ltcai 3.6.0 → 4.0.1

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 (238) hide show
  1. package/README.md +39 -31
  2. package/docs/CHANGELOG.md +64 -0
  3. package/docs/REALTIME_COLLABORATION.md +3 -3
  4. package/docs/V3_FRONTEND.md +9 -8
  5. package/docs/V4_BRAIN_ARCHITECTURE.md +322 -0
  6. package/docs/V4_DIGITAL_BRAIN_RECOVERY.md +552 -0
  7. package/docs/V4_IMPLEMENTATION_PLAN.md +470 -0
  8. package/docs/kg-schema.md +51 -53
  9. package/docs/spec-vs-impl.md +10 -10
  10. package/kg_schema.py +2 -520
  11. package/knowledge_graph.py +37 -4629
  12. package/knowledge_graph_api.py +11 -127
  13. package/latticeai/__init__.py +1 -1
  14. package/latticeai/api/admin.py +16 -17
  15. package/latticeai/api/agents.py +20 -7
  16. package/latticeai/api/auth.py +46 -15
  17. package/latticeai/api/chat.py +112 -76
  18. package/latticeai/api/health.py +1 -1
  19. package/latticeai/api/hooks.py +1 -1
  20. package/latticeai/api/invitations.py +100 -0
  21. package/latticeai/api/knowledge_graph.py +139 -0
  22. package/latticeai/api/local_files.py +1 -1
  23. package/latticeai/api/mcp.py +23 -11
  24. package/latticeai/api/memory.py +1 -1
  25. package/latticeai/api/models.py +1 -1
  26. package/latticeai/api/network.py +81 -0
  27. package/latticeai/api/plugins.py +3 -6
  28. package/latticeai/api/realtime.py +5 -8
  29. package/latticeai/api/search.py +26 -2
  30. package/latticeai/api/security_dashboard.py +2 -3
  31. package/latticeai/api/setup.py +2 -2
  32. package/latticeai/api/static_routes.py +11 -16
  33. package/latticeai/api/tools.py +3 -0
  34. package/latticeai/api/ui_redirects.py +26 -0
  35. package/latticeai/api/workflow_designer.py +85 -6
  36. package/latticeai/api/workspace.py +93 -57
  37. package/latticeai/app_factory.py +1781 -0
  38. package/latticeai/brain/__init__.py +18 -0
  39. package/latticeai/brain/_kg_common.py +1123 -0
  40. package/latticeai/brain/context.py +213 -0
  41. package/latticeai/brain/conversations.py +236 -0
  42. package/latticeai/brain/discovery.py +1455 -0
  43. package/latticeai/brain/documents.py +218 -0
  44. package/latticeai/brain/identity.py +175 -0
  45. package/latticeai/brain/ingest.py +644 -0
  46. package/latticeai/brain/memory.py +102 -0
  47. package/latticeai/brain/network.py +205 -0
  48. package/latticeai/brain/projection.py +561 -0
  49. package/latticeai/brain/provenance.py +401 -0
  50. package/latticeai/brain/retrieval.py +1316 -0
  51. package/latticeai/brain/schema.py +640 -0
  52. package/latticeai/brain/store.py +216 -0
  53. package/latticeai/brain/write_master.py +225 -0
  54. package/latticeai/core/agent.py +31 -7
  55. package/latticeai/core/audit.py +0 -7
  56. package/latticeai/core/config.py +1 -1
  57. package/latticeai/core/context_builder.py +1 -2
  58. package/latticeai/core/enterprise.py +1 -1
  59. package/latticeai/core/graph_curator.py +2 -2
  60. package/latticeai/core/invitations.py +131 -0
  61. package/latticeai/core/marketplace.py +1 -1
  62. package/latticeai/core/mcp_registry.py +791 -0
  63. package/latticeai/core/model_compat.py +1 -1
  64. package/latticeai/core/model_resolution.py +0 -1
  65. package/latticeai/core/multi_agent.py +238 -4
  66. package/latticeai/core/policy.py +54 -0
  67. package/latticeai/core/realtime.py +65 -44
  68. package/latticeai/core/security.py +1 -1
  69. package/latticeai/core/sessions.py +66 -10
  70. package/latticeai/core/users.py +147 -0
  71. package/latticeai/core/workflow_engine.py +114 -2
  72. package/latticeai/core/workspace_os.py +477 -29
  73. package/latticeai/models/__init__.py +7 -0
  74. package/latticeai/models/router.py +779 -0
  75. package/latticeai/server_app.py +29 -1536
  76. package/latticeai/services/agent_runtime.py +243 -4
  77. package/latticeai/services/app_context.py +75 -14
  78. package/latticeai/services/ingestion.py +47 -0
  79. package/latticeai/services/kg_portability.py +33 -3
  80. package/latticeai/services/memory_service.py +39 -11
  81. package/latticeai/services/model_runtime.py +2 -5
  82. package/latticeai/services/platform_runtime.py +100 -23
  83. package/latticeai/services/run_executor.py +328 -0
  84. package/latticeai/services/search_service.py +17 -8
  85. package/latticeai/services/tool_dispatch.py +12 -2
  86. package/latticeai/services/triggers.py +241 -0
  87. package/latticeai/services/upload_service.py +37 -12
  88. package/latticeai/services/workspace_service.py +55 -16
  89. package/llm_router.py +29 -772
  90. package/ltcai_cli.py +1 -2
  91. package/mcp_registry.py +25 -788
  92. package/p_reinforce.py +124 -14
  93. package/package.json +10 -20
  94. package/scripts/bump_version.py +99 -0
  95. package/scripts/generate_diagrams.py +0 -1
  96. package/scripts/lint_v3.mjs +105 -18
  97. package/scripts/validate_release_artifacts.py +0 -1
  98. package/scripts/wheel_smoke.py +142 -0
  99. package/server.py +11 -7
  100. package/setup_wizard.py +1142 -0
  101. package/static/sw.js +81 -52
  102. package/static/v3/asset-manifest.json +33 -25
  103. package/static/v3/css/{lattice.base.e4cdd05d.css → lattice.base.49deefb5.css} +1 -1
  104. package/static/v3/css/lattice.base.css +1 -1
  105. package/static/v3/css/{lattice.components.9b49d614.css → lattice.components.cde18231.css} +1 -1
  106. package/static/v3/css/lattice.components.css +1 -1
  107. package/static/v3/css/{lattice.shell.8fcc9d33.css → lattice.shell.29d36d85.css} +1 -1
  108. package/static/v3/css/lattice.shell.css +1 -1
  109. package/static/v3/css/{lattice.tokens.e7018963.css → lattice.tokens.304cbc40.css} +3 -0
  110. package/static/v3/css/lattice.tokens.css +3 -0
  111. package/static/v3/css/{lattice.views.22f69117.css → lattice.views.0a18b6c5.css} +2 -2
  112. package/static/v3/css/lattice.views.css +2 -2
  113. package/static/v3/index.html +3 -4
  114. package/static/v3/js/{app.c541f955.js → app.c5c80c46.js} +1 -1
  115. package/static/v3/js/core/{api.33d6320e.js → api.ba0fbf14.js} +58 -1
  116. package/static/v3/js/core/api.js +57 -0
  117. package/static/v3/js/core/i18n.880e1fec.js +575 -0
  118. package/static/v3/js/core/i18n.js +575 -0
  119. package/static/v3/js/core/routes.37522821.js +101 -0
  120. package/static/v3/js/core/routes.js +71 -63
  121. package/static/v3/js/core/{shell.8c163e0e.js → shell.e3f6bbfa.js} +68 -39
  122. package/static/v3/js/core/shell.js +66 -37
  123. package/static/v3/js/core/{store.34ebd5e6.js → store.7b2aa044.js} +11 -1
  124. package/static/v3/js/core/store.js +11 -1
  125. package/static/v3/js/views/account.eff40715.js +143 -0
  126. package/static/v3/js/views/account.js +143 -0
  127. package/static/v3/js/views/activity.0d271ef9.js +67 -0
  128. package/static/v3/js/views/activity.js +67 -0
  129. package/static/v3/js/views/{admin-users.03bac88c.js → admin-users.f7ac7b43.js} +4 -6
  130. package/static/v3/js/views/admin-users.js +4 -6
  131. package/static/v3/js/views/{agents.014d0b74.js → agents.17c5288d.js} +35 -12
  132. package/static/v3/js/views/agents.js +35 -12
  133. package/static/v3/js/views/{chat.e6dd7dd0.js → chat.e250e2cc.js} +23 -0
  134. package/static/v3/js/views/chat.js +23 -0
  135. package/static/v3/js/views/graph-canvas.17c15d65.js +509 -0
  136. package/static/v3/js/views/graph-canvas.js +509 -0
  137. package/static/v3/js/views/{hybrid-search.b22b97e0.js → hybrid-search.2fb63ed9.js} +1 -2
  138. package/static/v3/js/views/hybrid-search.js +1 -2
  139. package/static/v3/js/views/{knowledge-graph.a96040a5.js → knowledge-graph.4d09c537.js} +60 -44
  140. package/static/v3/js/views/knowledge-graph.js +60 -44
  141. package/static/v3/js/views/network.52a4f181.js +97 -0
  142. package/static/v3/js/views/network.js +97 -0
  143. package/static/v3/js/views/{planning.9ac3e313.js → planning.4876fd77.js} +26 -5
  144. package/static/v3/js/views/planning.js +26 -5
  145. package/static/v3/js/views/runs.b63b2afa.js +144 -0
  146. package/static/v3/js/views/runs.js +144 -0
  147. package/static/v3/js/views/{settings.8631fa5e.js → settings.b7140634.js} +7 -8
  148. package/static/v3/js/views/settings.js +7 -8
  149. package/static/v3/js/views/snapshots.6f5db095.js +135 -0
  150. package/static/v3/js/views/snapshots.js +135 -0
  151. package/static/v3/js/views/{workflows.26c57290.js → workflows.7752225a.js} +87 -2
  152. package/static/v3/js/views/workflows.js +87 -2
  153. package/static/v3/js/views/workspace-admin.c466029b.js +156 -0
  154. package/static/v3/js/views/workspace-admin.js +156 -0
  155. package/static/vendor/chart.umd.min.js +20 -0
  156. package/static/vendor/fonts/inter-latin-300-normal.woff2 +0 -0
  157. package/static/vendor/fonts/inter-latin-400-normal.woff2 +0 -0
  158. package/static/vendor/fonts/inter-latin-500-normal.woff2 +0 -0
  159. package/static/vendor/fonts/inter-latin-600-normal.woff2 +0 -0
  160. package/static/vendor/fonts/inter-latin-700-normal.woff2 +0 -0
  161. package/static/vendor/fonts/inter-latin-800-normal.woff2 +0 -0
  162. package/static/vendor/fonts/inter.css +44 -0
  163. package/static/vendor/icons/tabler-icons.min.css +4 -0
  164. package/static/vendor/icons/tabler-icons.woff2 +0 -0
  165. package/static/vendor/marked.min.js +69 -0
  166. package/telegram_bot.py +1 -2
  167. package/tools/commands.py +4 -2
  168. package/tools/computer.py +1 -1
  169. package/tools/documents.py +1 -3
  170. package/tools/filesystem.py +0 -4
  171. package/tools/knowledge.py +1 -3
  172. package/tools/network.py +1 -3
  173. package/codex_telegram_bot.py +0 -195
  174. package/docs/assets/v3.4.0/agent-run.png +0 -0
  175. package/docs/assets/v3.4.0/agents.png +0 -0
  176. package/docs/assets/v3.4.0/before/chat-before.png +0 -0
  177. package/docs/assets/v3.4.0/before/files-before.png +0 -0
  178. package/docs/assets/v3.4.0/chat.png +0 -0
  179. package/docs/assets/v3.4.0/connect-folder.png +0 -0
  180. package/docs/assets/v3.4.0/files.png +0 -0
  181. package/docs/assets/v3.4.0/home.png +0 -0
  182. package/docs/assets/v3.4.0/hooks-dispatch.png +0 -0
  183. package/docs/assets/v3.4.0/knowledge-graph.png +0 -0
  184. package/docs/assets/v3.4.0/local-agent.png +0 -0
  185. package/docs/assets/v3.4.0/memory.png +0 -0
  186. package/docs/assets/v3.4.0/settings.png +0 -0
  187. package/docs/assets/v3.4.0/vision-input.png +0 -0
  188. package/docs/assets/v3.4.0/workflows.png +0 -0
  189. package/docs/assets/v3.4.1/e2e_runtime_log.txt +0 -42
  190. package/docs/assets/v3.4.1/hooks-dispatch.png +0 -0
  191. package/docs/assets/v3.4.1/local-agent.png +0 -0
  192. package/docs/images/admin-dashboard.png +0 -0
  193. package/docs/images/architecture.png +0 -0
  194. package/docs/images/enterprise.png +0 -0
  195. package/docs/images/graph.png +0 -0
  196. package/docs/images/hero.gif +0 -0
  197. package/docs/images/knowledge-graph.png +0 -0
  198. package/docs/images/lattice-ai-demo.gif +0 -0
  199. package/docs/images/lattice-ai-hero.png +0 -0
  200. package/docs/images/logo.svg +0 -33
  201. package/docs/images/mobile-responsive.png +0 -0
  202. package/docs/images/model-recommendation.png +0 -0
  203. package/docs/images/onboarding.png +0 -0
  204. package/docs/images/organization.png +0 -0
  205. package/docs/images/pipeline.png +0 -0
  206. package/docs/images/screenshot-admin.png +0 -0
  207. package/docs/images/screenshot-chat.png +0 -0
  208. package/docs/images/screenshot-graph.png +0 -0
  209. package/docs/images/skills.png +0 -0
  210. package/docs/images/workspace-dark.png +0 -0
  211. package/docs/images/workspace-light.png +0 -0
  212. package/docs/images/workspace.png +0 -0
  213. package/requirements.txt +0 -16
  214. package/static/account.html +0 -115
  215. package/static/activity.html +0 -73
  216. package/static/admin.html +0 -488
  217. package/static/agents.html +0 -139
  218. package/static/chat.html +0 -844
  219. package/static/css/reference/account.css +0 -439
  220. package/static/css/reference/admin.css +0 -610
  221. package/static/css/reference/base.css +0 -1661
  222. package/static/css/reference/chat.css +0 -4623
  223. package/static/css/reference/graph.css +0 -1016
  224. package/static/css/responsive.css +0 -861
  225. package/static/graph.html +0 -124
  226. package/static/platform.css +0 -104
  227. package/static/plugins.html +0 -136
  228. package/static/scripts/account.js +0 -238
  229. package/static/scripts/admin.js +0 -1614
  230. package/static/scripts/chat.js +0 -5081
  231. package/static/scripts/graph.js +0 -1804
  232. package/static/scripts/platform.js +0 -64
  233. package/static/scripts/ux.js +0 -167
  234. package/static/scripts/workspace.js +0 -948
  235. package/static/v3/js/core/routes.2ce3815a.js +0 -93
  236. package/static/workflows.html +0 -146
  237. package/static/workspace.css +0 -1121
  238. package/static/workspace.html +0 -357
package/static/sw.js CHANGED
@@ -1,71 +1,100 @@
1
- // Lattice AI Service Worker — enables PWA install on Android/iOS
2
- // Strategy: network-first for API, cache-first for static assets.
3
- const CACHE = "ltcai-v310";
4
- const STATIC = [
5
- "/",
1
+ // Lattice Service Worker — PWA install + offline shell for the /app SPA.
2
+ // Strategy: precache the v3 bundle from its asset manifest (hashed files),
3
+ // cache-first for static assets, network-only for everything dynamic.
4
+ const CACHE = "lattice-v4";
5
+ const MANIFEST_URL = "/static/v3/asset-manifest.json";
6
+
7
+ // Non-manifest assets the shell needs offline.
8
+ const SHELL = [
6
9
  "/app",
7
- "/workspace",
8
- "/static/v3/asset-manifest.json",
9
- "/static/css/tokens.css",
10
- "/static/css/reference/base.css",
11
- "/static/css/reference/chat.css",
12
- "/static/css/responsive.css",
13
- "/static/workspace.css",
14
- "/static/scripts/chat.js",
15
- "/static/scripts/admin.js",
16
- "/static/scripts/graph.js",
17
- "/static/scripts/workspace.js",
18
- "/static/scripts/account.js",
10
+ MANIFEST_URL,
19
11
  "/manifest.json",
20
12
  "/icons/icon-192.png",
21
13
  "/icons/icon-512.png",
22
14
  "/icons/apple-touch-icon.png",
15
+ "/static/vendor/fonts/inter.css",
16
+ "/static/vendor/fonts/inter-latin-400-normal.woff2",
17
+ "/static/vendor/fonts/inter-latin-500-normal.woff2",
18
+ "/static/vendor/fonts/inter-latin-600-normal.woff2",
19
+ "/static/vendor/fonts/inter-latin-700-normal.woff2",
20
+ "/static/vendor/fonts/inter-latin-800-normal.woff2",
21
+ "/static/vendor/icons/tabler-icons.min.css",
22
+ "/static/vendor/icons/tabler-icons.woff2",
23
23
  ];
24
24
 
25
- self.addEventListener("install", e => {
26
- e.waitUntil(
27
- caches.open(CACHE).then(c => c.addAll(STATIC)).then(() => self.skipWaiting())
28
- );
25
+ async function precache() {
26
+ const cache = await caches.open(CACHE);
27
+ let manifestPaths = [];
28
+ try {
29
+ const res = await fetch(MANIFEST_URL, { cache: "no-cache" });
30
+ const manifest = await res.json();
31
+ const entry = manifest.entrypoints || {};
32
+ manifestPaths = [entry.app, ...(entry.styles || []), ...Object.values(manifest.assets || {})]
33
+ .filter(Boolean);
34
+ } catch (err) {
35
+ // Offline install: shell precache below still applies.
36
+ }
37
+ const unique = [...new Set([...SHELL, ...manifestPaths])];
38
+ await Promise.all(unique.map(async (path) => {
39
+ try {
40
+ const res = await fetch(path, { cache: "no-cache" });
41
+ if (res.ok) await cache.put(path, res);
42
+ } catch (err) {
43
+ // Missing one asset must not abort install; it just isn't offline-ready.
44
+ }
45
+ }));
46
+ }
47
+
48
+ self.addEventListener("install", (e) => {
49
+ e.waitUntil(precache().then(() => self.skipWaiting()));
29
50
  });
30
51
 
31
- self.addEventListener("activate", e => {
52
+ self.addEventListener("activate", (e) => {
32
53
  e.waitUntil(
33
- caches.keys().then(keys =>
34
- Promise.all(keys.filter(k => k !== CACHE).map(k => caches.delete(k)))
35
- ).then(() => clients.claim())
54
+ caches.keys()
55
+ .then((keys) => Promise.all(keys.filter((k) => k !== CACHE).map((k) => caches.delete(k))))
56
+ .then(() => clients.claim())
36
57
  );
37
58
  });
38
59
 
39
- self.addEventListener("fetch", e => {
60
+ self.addEventListener("fetch", (e) => {
40
61
  const url = new URL(e.request.url);
62
+ if (e.request.method !== "GET" || url.origin !== self.location.origin) return;
41
63
 
42
- // API calls → always network (never cache)
43
- if (url.pathname.startsWith("/chat") ||
44
- url.pathname.startsWith("/agent") ||
45
- url.pathname.startsWith("/models") ||
46
- url.pathname.startsWith("/admin/") ||
47
- url.pathname.startsWith("/auth/") ||
48
- url.pathname.startsWith("/account/") ||
49
- url.pathname.startsWith("/vpc/") ||
50
- url.pathname.startsWith("/health") ||
51
- url.pathname.startsWith("/runtime_features") ||
52
- url.pathname.startsWith("/local") ||
53
- url.pathname.startsWith("/tools") ||
54
- url.pathname.startsWith("/knowledge") ||
55
- url.pathname.startsWith("/workspace/") ||
56
- url.pathname.startsWith("/history")) {
57
- e.respondWith(fetch(e.request));
64
+ const isStatic =
65
+ url.pathname.startsWith("/static/") ||
66
+ url.pathname.startsWith("/icons/") ||
67
+ url.pathname === "/manifest.json";
68
+
69
+ if (isStatic) {
70
+ // Hashed filenames make cache-first safe; unhashed files revalidate.
71
+ e.respondWith(
72
+ caches.match(e.request).then((hit) =>
73
+ hit ||
74
+ fetch(e.request).then((res) => {
75
+ const clone = res.clone();
76
+ if (res.ok) caches.open(CACHE).then((c) => c.put(e.request, clone));
77
+ return res;
78
+ })
79
+ )
80
+ );
58
81
  return;
59
82
  }
60
83
 
61
- // Static HTML network-first, fall back to cache
62
- e.respondWith(
63
- fetch(e.request)
64
- .then(res => {
65
- const clone = res.clone();
66
- caches.open(CACHE).then(c => c.put(e.request, clone));
67
- return res;
68
- })
69
- .catch(() => caches.match(e.request))
70
- );
84
+ if (url.pathname === "/app" || url.pathname.startsWith("/app/")) {
85
+ // SPA shell: network-first so updates land, cache fallback for offline.
86
+ e.respondWith(
87
+ fetch(e.request)
88
+ .then((res) => {
89
+ const clone = res.clone();
90
+ if (res.ok) caches.open(CACHE).then((c) => c.put("/app", clone));
91
+ return res;
92
+ })
93
+ .catch(() => caches.match("/app"))
94
+ );
95
+ return;
96
+ }
97
+
98
+ // Everything else (APIs, auth, realtime) is dynamic: network only —
99
+ // serving stale API responses would fabricate state.
71
100
  });
@@ -1,55 +1,63 @@
1
1
  {
2
- "version": "3.6.0",
2
+ "version": "4.0.1",
3
3
  "generated_at": "deterministic",
4
4
  "entrypoints": {
5
- "app": "/static/v3/js/app.c541f955.js",
5
+ "app": "/static/v3/js/app.c5c80c46.js",
6
6
  "styles": [
7
7
  "/static/css/tokens.3ba22e37.css",
8
- "/static/v3/css/lattice.tokens.e7018963.css",
9
- "/static/v3/css/lattice.base.e4cdd05d.css",
10
- "/static/v3/css/lattice.components.9b49d614.css",
11
- "/static/v3/css/lattice.shell.8fcc9d33.css",
12
- "/static/v3/css/lattice.views.22f69117.css"
8
+ "/static/v3/css/lattice.tokens.304cbc40.css",
9
+ "/static/v3/css/lattice.base.49deefb5.css",
10
+ "/static/v3/css/lattice.components.cde18231.css",
11
+ "/static/v3/css/lattice.shell.29d36d85.css",
12
+ "/static/v3/css/lattice.views.0a18b6c5.css"
13
13
  ]
14
14
  },
15
15
  "assets": {
16
16
  "static/css/tokens.css": "/static/css/tokens.3ba22e37.css",
17
- "static/v3/css/lattice.tokens.css": "/static/v3/css/lattice.tokens.e7018963.css",
18
- "static/v3/css/lattice.base.css": "/static/v3/css/lattice.base.e4cdd05d.css",
19
- "static/v3/css/lattice.components.css": "/static/v3/css/lattice.components.9b49d614.css",
20
- "static/v3/css/lattice.shell.css": "/static/v3/css/lattice.shell.8fcc9d33.css",
21
- "static/v3/css/lattice.views.css": "/static/v3/css/lattice.views.22f69117.css",
22
- "static/v3/js/app.js": "/static/v3/js/app.c541f955.js",
23
- "static/v3/js/core/api.js": "/static/v3/js/core/api.33d6320e.js",
17
+ "static/v3/css/lattice.tokens.css": "/static/v3/css/lattice.tokens.304cbc40.css",
18
+ "static/v3/css/lattice.base.css": "/static/v3/css/lattice.base.49deefb5.css",
19
+ "static/v3/css/lattice.components.css": "/static/v3/css/lattice.components.cde18231.css",
20
+ "static/v3/css/lattice.shell.css": "/static/v3/css/lattice.shell.29d36d85.css",
21
+ "static/v3/css/lattice.views.css": "/static/v3/css/lattice.views.0a18b6c5.css",
22
+ "static/v3/js/app.js": "/static/v3/js/app.c5c80c46.js",
23
+ "static/v3/js/core/api.js": "/static/v3/js/core/api.ba0fbf14.js",
24
24
  "static/v3/js/core/components.js": "/static/v3/js/core/components.f25b3b93.js",
25
25
  "static/v3/js/core/dom.js": "/static/v3/js/core/dom.a2773eb0.js",
26
+ "static/v3/js/core/i18n.js": "/static/v3/js/core/i18n.880e1fec.js",
26
27
  "static/v3/js/core/router.js": "/static/v3/js/core/router.584570f2.js",
27
- "static/v3/js/core/routes.js": "/static/v3/js/core/routes.2ce3815a.js",
28
- "static/v3/js/core/shell.js": "/static/v3/js/core/shell.8c163e0e.js",
29
- "static/v3/js/core/store.js": "/static/v3/js/core/store.34ebd5e6.js",
28
+ "static/v3/js/core/routes.js": "/static/v3/js/core/routes.37522821.js",
29
+ "static/v3/js/core/shell.js": "/static/v3/js/core/shell.e3f6bbfa.js",
30
+ "static/v3/js/core/store.js": "/static/v3/js/core/store.7b2aa044.js",
31
+ "static/v3/js/views/account.js": "/static/v3/js/views/account.eff40715.js",
32
+ "static/v3/js/views/activity.js": "/static/v3/js/views/activity.0d271ef9.js",
30
33
  "static/v3/js/views/admin-audit.js": "/static/v3/js/views/admin-audit.660a1fb1.js",
31
34
  "static/v3/js/views/admin-permissions.js": "/static/v3/js/views/admin-permissions.a7ae5f09.js",
32
35
  "static/v3/js/views/admin-policies.js": "/static/v3/js/views/admin-policies.3658fd86.js",
33
36
  "static/v3/js/views/admin-private-vpc.js": "/static/v3/js/views/admin-private-vpc.7d342d36.js",
34
37
  "static/v3/js/views/admin-security.js": "/static/v3/js/views/admin-security.07c66b72.js",
35
- "static/v3/js/views/admin-users.js": "/static/v3/js/views/admin-users.03bac88c.js",
36
- "static/v3/js/views/agents.js": "/static/v3/js/views/agents.014d0b74.js",
37
- "static/v3/js/views/chat.js": "/static/v3/js/views/chat.e6dd7dd0.js",
38
+ "static/v3/js/views/admin-users.js": "/static/v3/js/views/admin-users.f7ac7b43.js",
39
+ "static/v3/js/views/agents.js": "/static/v3/js/views/agents.17c5288d.js",
40
+ "static/v3/js/views/chat.js": "/static/v3/js/views/chat.e250e2cc.js",
38
41
  "static/v3/js/views/files.js": "/static/v3/js/views/files.adad14c1.js",
42
+ "static/v3/js/views/graph-canvas.js": "/static/v3/js/views/graph-canvas.17c15d65.js",
39
43
  "static/v3/js/views/home.js": "/static/v3/js/views/home.24f8b8ae.js",
40
44
  "static/v3/js/views/hooks.js": "/static/v3/js/views/hooks.37895880.js",
41
- "static/v3/js/views/hybrid-search.js": "/static/v3/js/views/hybrid-search.b22b97e0.js",
42
- "static/v3/js/views/knowledge-graph.js": "/static/v3/js/views/knowledge-graph.a96040a5.js",
45
+ "static/v3/js/views/hybrid-search.js": "/static/v3/js/views/hybrid-search.2fb63ed9.js",
46
+ "static/v3/js/views/knowledge-graph.js": "/static/v3/js/views/knowledge-graph.4d09c537.js",
43
47
  "static/v3/js/views/marketplace.js": "/static/v3/js/views/marketplace.ab0583d4.js",
44
48
  "static/v3/js/views/mcp.js": "/static/v3/js/views/mcp.99b5c6a7.js",
45
49
  "static/v3/js/views/memory.js": "/static/v3/js/views/memory.4ebdf474.js",
46
50
  "static/v3/js/views/models.js": "/static/v3/js/views/models.a1ffa147.js",
47
51
  "static/v3/js/views/my-computer.js": "/static/v3/js/views/my-computer.d9d9ae1c.js",
52
+ "static/v3/js/views/network.js": "/static/v3/js/views/network.52a4f181.js",
48
53
  "static/v3/js/views/pipeline.js": "/static/v3/js/views/pipeline.c522f1ce.js",
49
- "static/v3/js/views/planning.js": "/static/v3/js/views/planning.9ac3e313.js",
50
- "static/v3/js/views/settings.js": "/static/v3/js/views/settings.8631fa5e.js",
54
+ "static/v3/js/views/planning.js": "/static/v3/js/views/planning.4876fd77.js",
55
+ "static/v3/js/views/runs.js": "/static/v3/js/views/runs.b63b2afa.js",
56
+ "static/v3/js/views/settings.js": "/static/v3/js/views/settings.b7140634.js",
51
57
  "static/v3/js/views/skills.js": "/static/v3/js/views/skills.c6c2f965.js",
58
+ "static/v3/js/views/snapshots.js": "/static/v3/js/views/snapshots.6f5db095.js",
52
59
  "static/v3/js/views/tools.js": "/static/v3/js/views/tools.e4f11276.js",
53
- "static/v3/js/views/workflows.js": "/static/v3/js/views/workflows.26c57290.js"
60
+ "static/v3/js/views/workflows.js": "/static/v3/js/views/workflows.7752225a.js",
61
+ "static/v3/js/views/workspace-admin.js": "/static/v3/js/views/workspace-admin.c466029b.js"
54
62
  }
55
63
  }
@@ -111,7 +111,7 @@ code, pre, kbd, samp { font-family: var(--lt3-font-mono); }
111
111
  z-index: var(--lt3-z-toast);
112
112
  padding: var(--lt3-space-2) var(--lt3-space-4);
113
113
  background: var(--accent);
114
- color: #fff;
114
+ color: var(--lt3-on-accent);
115
115
  border-radius: var(--lt3-radius-sm);
116
116
  transform: translateY(-200%);
117
117
  transition: transform var(--lt3-dur-2) var(--lt3-ease);
@@ -111,7 +111,7 @@ code, pre, kbd, samp { font-family: var(--lt3-font-mono); }
111
111
  z-index: var(--lt3-z-toast);
112
112
  padding: var(--lt3-space-2) var(--lt3-space-4);
113
113
  background: var(--accent);
114
- color: #fff;
114
+ color: var(--lt3-on-accent);
115
115
  border-radius: var(--lt3-radius-sm);
116
116
  transform: translateY(-200%);
117
117
  transition: transform var(--lt3-dur-2) var(--lt3-ease);
@@ -87,7 +87,7 @@
87
87
  .lt3-btn[disabled] { opacity: 0.5; pointer-events: none; }
88
88
  .lt3-btn .ti { font-size: 1.05rem; }
89
89
 
90
- .lt3-btn--primary { background: var(--accent); color: #fff; box-shadow: var(--lt3-elev-1); }
90
+ .lt3-btn--primary { background: var(--accent); color: var(--lt3-on-accent); box-shadow: var(--lt3-elev-1); }
91
91
  .lt3-btn--primary:hover { background: var(--accent-deep); }
92
92
  .lt3-btn--ghost { background: var(--surface-2); border-color: var(--border); color: var(--text); }
93
93
  .lt3-btn--ghost:hover { border-color: var(--border-strong); background: var(--surface-3); }
@@ -87,7 +87,7 @@
87
87
  .lt3-btn[disabled] { opacity: 0.5; pointer-events: none; }
88
88
  .lt3-btn .ti { font-size: 1.05rem; }
89
89
 
90
- .lt3-btn--primary { background: var(--accent); color: #fff; box-shadow: var(--lt3-elev-1); }
90
+ .lt3-btn--primary { background: var(--accent); color: var(--lt3-on-accent); box-shadow: var(--lt3-elev-1); }
91
91
  .lt3-btn--primary:hover { background: var(--accent-deep); }
92
92
  .lt3-btn--ghost { background: var(--surface-2); border-color: var(--border); color: var(--text); }
93
93
  .lt3-btn--ghost:hover { border-color: var(--border-strong); background: var(--surface-3); }
@@ -36,7 +36,7 @@
36
36
  width: 34px; height: 34px; flex: none;
37
37
  border-radius: var(--lt3-radius-md);
38
38
  background: var(--text);
39
- color: #fff;
39
+ color: var(--lt3-on-accent);
40
40
  box-shadow: var(--lt3-elev-1);
41
41
  }
42
42
  .lt3-rail__logo svg { width: 22px; height: 22px; }
@@ -36,7 +36,7 @@
36
36
  width: 34px; height: 34px; flex: none;
37
37
  border-radius: var(--lt3-radius-md);
38
38
  background: var(--text);
39
- color: #fff;
39
+ color: var(--lt3-on-accent);
40
40
  box-shadow: var(--lt3-elev-1);
41
41
  }
42
42
  .lt3-rail__logo svg { width: 22px; height: 22px; }
@@ -98,6 +98,9 @@
98
98
  --lt3-pillar-graph: var(--accent); /* blue — relational structure */
99
99
  --lt3-pillar-vector: var(--accent-2); /* teal — embeddings field */
100
100
  --lt3-pillar-hybrid: var(--accent-pink); /* magenta — fusion of both */
101
+
102
+ /* Text rendered on saturated accent fills (both themes keep accents dark-safe). */
103
+ --lt3-on-accent: #ffffff;
101
104
  --lt3-pillar-graph-soft: color-mix(in srgb, var(--lt3-pillar-graph) 14%, transparent);
102
105
  --lt3-pillar-vector-soft: color-mix(in srgb, var(--lt3-pillar-vector) 16%, transparent);
103
106
  --lt3-pillar-hybrid-soft: color-mix(in srgb, var(--lt3-pillar-hybrid) 16%, transparent);
@@ -98,6 +98,9 @@
98
98
  --lt3-pillar-graph: var(--accent); /* blue — relational structure */
99
99
  --lt3-pillar-vector: var(--accent-2); /* teal — embeddings field */
100
100
  --lt3-pillar-hybrid: var(--accent-pink); /* magenta — fusion of both */
101
+
102
+ /* Text rendered on saturated accent fills (both themes keep accents dark-safe). */
103
+ --lt3-on-accent: #ffffff;
101
104
  --lt3-pillar-graph-soft: color-mix(in srgb, var(--lt3-pillar-graph) 14%, transparent);
102
105
  --lt3-pillar-vector-soft: color-mix(in srgb, var(--lt3-pillar-vector) 16%, transparent);
103
106
  --lt3-pillar-hybrid-soft: color-mix(in srgb, var(--lt3-pillar-hybrid) 16%, transparent);
@@ -222,12 +222,12 @@
222
222
  .lt3-msg--user { align-self: flex-end; flex-direction: row-reverse; max-width: 90%; }
223
223
  .lt3-msg--ai { align-self: flex-start; max-width: 100%; }
224
224
  .lt3-msg__avatar { width: 32px; height: 32px; flex: none; border-radius: var(--lt3-radius-sm); display: grid; place-items: center; }
225
- .lt3-msg--ai .lt3-msg__avatar { background: linear-gradient(135deg, var(--lt3-pillar-graph), var(--lt3-pillar-vector)); color: #fff; }
225
+ .lt3-msg--ai .lt3-msg__avatar { background: linear-gradient(135deg, var(--lt3-pillar-graph), var(--lt3-pillar-vector)); color: var(--lt3-on-accent); }
226
226
  .lt3-msg--user .lt3-msg__avatar { background: var(--surface-3); color: var(--muted); }
227
227
  .lt3-msg__body { min-width: 0; display: flex; flex-direction: column; gap: var(--lt3-space-2); }
228
228
  .lt3-msg__bubble { padding: var(--lt3-space-3) var(--lt3-space-4); border-radius: var(--lt3-radius-md); font-size: var(--lt3-text-md); line-height: var(--lt3-leading-normal); white-space: pre-wrap; overflow-wrap: anywhere; }
229
229
  .lt3-msg--ai .lt3-msg__bubble { background: var(--surface); border: 1px solid var(--border); }
230
- .lt3-msg--user .lt3-msg__bubble { background: var(--accent); color: #fff; }
230
+ .lt3-msg--user .lt3-msg__bubble { background: var(--accent); color: var(--lt3-on-accent); }
231
231
  .lt3-msg__cites { display: flex; flex-wrap: wrap; gap: var(--lt3-space-2); }
232
232
  .lt3-typing { display: inline-flex; gap: 4px; align-items: center; padding: var(--lt3-space-1) 0; }
233
233
  .lt3-typing i { width: 6px; height: 6px; border-radius: 99px; background: var(--faint); animation: lt3-bounce 1s var(--lt3-ease) infinite; }
@@ -222,12 +222,12 @@
222
222
  .lt3-msg--user { align-self: flex-end; flex-direction: row-reverse; max-width: 90%; }
223
223
  .lt3-msg--ai { align-self: flex-start; max-width: 100%; }
224
224
  .lt3-msg__avatar { width: 32px; height: 32px; flex: none; border-radius: var(--lt3-radius-sm); display: grid; place-items: center; }
225
- .lt3-msg--ai .lt3-msg__avatar { background: linear-gradient(135deg, var(--lt3-pillar-graph), var(--lt3-pillar-vector)); color: #fff; }
225
+ .lt3-msg--ai .lt3-msg__avatar { background: linear-gradient(135deg, var(--lt3-pillar-graph), var(--lt3-pillar-vector)); color: var(--lt3-on-accent); }
226
226
  .lt3-msg--user .lt3-msg__avatar { background: var(--surface-3); color: var(--muted); }
227
227
  .lt3-msg__body { min-width: 0; display: flex; flex-direction: column; gap: var(--lt3-space-2); }
228
228
  .lt3-msg__bubble { padding: var(--lt3-space-3) var(--lt3-space-4); border-radius: var(--lt3-radius-md); font-size: var(--lt3-text-md); line-height: var(--lt3-leading-normal); white-space: pre-wrap; overflow-wrap: anywhere; }
229
229
  .lt3-msg--ai .lt3-msg__bubble { background: var(--surface); border: 1px solid var(--border); }
230
- .lt3-msg--user .lt3-msg__bubble { background: var(--accent); color: #fff; }
230
+ .lt3-msg--user .lt3-msg__bubble { background: var(--accent); color: var(--lt3-on-accent); }
231
231
  .lt3-msg__cites { display: flex; flex-wrap: wrap; gap: var(--lt3-space-2); }
232
232
  .lt3-typing { display: inline-flex; gap: 4px; align-items: center; padding: var(--lt3-space-1) 0; }
233
233
  .lt3-typing i { width: 6px; height: 6px; border-radius: 99px; background: var(--faint); animation: lt3-bounce 1s var(--lt3-ease) infinite; }
@@ -18,10 +18,9 @@
18
18
 
19
19
  <link rel="manifest" href="/manifest.json">
20
20
  <link rel="icon" type="image/png" sizes="32x32" href="/icons/favicon-32.png">
21
- <link rel="preconnect" href="https://fonts.googleapis.com">
22
- <link rel="preconnect" href="https://cdn.jsdelivr.net">
23
- <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap">
24
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@tabler/icons-webfont@latest/tabler-icons.min.css">
21
+ <!-- Fonts and icons are vendored locally: no CDN calls from shipped pages. -->
22
+ <link rel="stylesheet" href="/static/vendor/fonts/inter.css">
23
+ <link rel="stylesheet" href="/static/vendor/icons/tabler-icons.min.css">
25
24
 
26
25
  <script>
27
26
  window.__LT_ASSET_SOURCES__ = {
@@ -3,7 +3,7 @@
3
3
  * Boots the shell. Views are lazy-loaded by the router (see core/routes.js).
4
4
  * ========================================================================== */
5
5
 
6
- import { boot } from "./core/shell.8c163e0e.js";
6
+ import { boot } from "./core/shell.e3f6bbfa.js";
7
7
 
8
8
  const root = document.getElementById("app");
9
9
  if (root) boot(root);
@@ -11,7 +11,7 @@
11
11
  * "unavailable" → endpoint missing/down; no fake payload
12
12
  * ========================================================================== */
13
13
 
14
- import { store } from "./store.34ebd5e6.js";
14
+ import { store } from "./store.7b2aa044.js";
15
15
 
16
16
  const TIMEOUT_MS = 8000;
17
17
  const EMPTY_INDEX_STATUS = { generated_at: null, pipelines: {}, sources: [] };
@@ -279,6 +279,53 @@ export const api = {
279
279
 
280
280
  /* ── Organization workspaces (real backend: /workspace/orgs) ────────── */
281
281
  createOrg(name) { return raw("/workspace/orgs", { method: "POST", body: { name } }); },
282
+ workspaceRegistry() { return withFallback("/workspace/registry", {}, { workspaces: [], roles: [], permissions: {} }); },
283
+ activateWorkspace(workspace_id) { return raw("/workspace/activate", { method: "POST", body: { workspace_id } }); },
284
+ workspaceDetail(workspace_id) { return raw(`/workspace/orgs/${encodeURIComponent(workspace_id)}`); },
285
+ updateWorkspace(workspace_id, body) { return raw(`/workspace/orgs/${encodeURIComponent(workspace_id)}`, { method: "PATCH", body }); },
286
+ archiveWorkspace(workspace_id) { return raw(`/workspace/orgs/${encodeURIComponent(workspace_id)}/archive`, { method: "POST", body: {} }); },
287
+ addWorkspaceMember(workspace_id, user_id, role) {
288
+ return raw(`/workspace/orgs/${encodeURIComponent(workspace_id)}/members`, { method: "POST", body: { user_id, role } });
289
+ },
290
+ updateWorkspaceMember(workspace_id, user_id, role) {
291
+ return raw(`/workspace/orgs/${encodeURIComponent(workspace_id)}/members/${encodeURIComponent(user_id)}`, { method: "PATCH", body: { role } });
292
+ },
293
+ removeWorkspaceMember(workspace_id, user_id) {
294
+ return raw(`/workspace/orgs/${encodeURIComponent(workspace_id)}/members/${encodeURIComponent(user_id)}`, { method: "DELETE" });
295
+ },
296
+ invitations() { return withFallback("/invitations", {}, { invitations: [] }); },
297
+ createInvitation(body) { return raw("/invitations", { method: "POST", body }); },
298
+ acceptInvitation(token) { return raw(`/invitations/${encodeURIComponent(token)}/accept`, { method: "POST", body: {} }); },
299
+
300
+ /* ── Account / token-native auth ───────────────────────────────────── */
301
+ profile() { return raw("/account/profile"); },
302
+ login(email, password) { return raw("/login", { method: "POST", body: { email, password } }); },
303
+ register(body) { return raw("/register", { method: "POST", body }); },
304
+ logout() { return raw("/logout", { method: "POST", body: {} }); },
305
+ updateProfile(body) { return raw("/account/profile", { method: "PATCH", body }); },
306
+ changePassword(current_password, new_password) {
307
+ return raw("/account/change-password", { method: "POST", body: { current_password, new_password } });
308
+ },
309
+ ssoConfig() { return withFallback("/auth/sso/config", {}, { enabled: false, providers: [] }); },
310
+
311
+ /* ── Snapshots, Time Machine, realtime ─────────────────────────────── */
312
+ snapshots() { return withFallback("/workspace/snapshots", {}, { snapshots: [] }); },
313
+ createSnapshot(name) { return raw("/workspace/snapshots", { method: "POST", body: { name } }); },
314
+ compareSnapshots(before_id, after_id) { return raw("/workspace/snapshots/compare", { method: "POST", body: { before_id, after_id } }); },
315
+ snapshotExport(snapshot_id) { return raw(`/workspace/snapshots/${encodeURIComponent(snapshot_id)}/export`, { method: "POST", body: {} }); },
316
+ snapshotRestore(snapshot_id) { return raw(`/workspace/snapshots/${encodeURIComponent(snapshot_id)}/restore`, { method: "POST", body: {} }); },
317
+ timeMachine(limit = 100) { return withFallback(`/workspace/time-machine?limit=${encodeURIComponent(limit)}`, {}, { events: [] }); },
318
+ realtimeFeed(limit = 50) { return withFallback(`/realtime/feed?limit=${encodeURIComponent(limit)}`, {}, { events: [], stats: {} }); },
319
+ presence() { return withFallback("/realtime/presence", {}, { presence: [], stats: {} }); },
320
+
321
+ /* ── Approval + Brain Network surfaces ─────────────────────────────── */
322
+ permissionsPending() { return withFallback("/permissions/pending", {}, { pending: {}, count: 0 }); },
323
+ denyPermission(token) { return raw(`/permissions/deny/${encodeURIComponent(token)}`, { method: "POST" }); },
324
+ networkIdentity() { return withFallback("/network/identity", {}, {}); },
325
+ networkPeers() { return withFallback("/network/peers", {}, { peers: [] }); },
326
+ pairPeer(body) { return raw("/network/peers", { method: "POST", body }); },
327
+ unpairPeer(peer_id) { return raw(`/network/peers/${encodeURIComponent(peer_id)}`, { method: "DELETE" }); },
328
+ pushPeer(peer_id, workspace_id) { return raw(`/network/push/${encodeURIComponent(peer_id)}`, { method: "POST", body: { workspace_id } }); },
282
329
 
283
330
  /* ── Chat (real backend: SSE /chat + /history/*) ────────────────────── */
284
331
 
@@ -402,9 +449,15 @@ export const api = {
402
449
  // Workflow Agents (Part 5)
403
450
  workflowDefinitions() { return withFallback("/workflows/api/definitions", {}, { workflows: [] }); },
404
451
  createWorkflow(body) { return raw("/workflows/api/definitions", { method: "POST", body }); },
452
+ updateWorkflow(id, body) { return raw(`/workflows/api/definitions/${encodeURIComponent(id)}`, { method: "PATCH", body }); },
405
453
  runWorkflow(id, body = {}) { return raw(`/workflows/api/definitions/${encodeURIComponent(id)}/run`, { method: "POST", body }); },
406
454
  workflowRuns() { return withFallback("/workflows/api/runs", {}, { runs: [] }); },
407
455
  workflowReplay(runId) { return raw(`/workflows/api/runs/${encodeURIComponent(runId)}/replay`); },
456
+ stopWorkflowRun(runId) { return raw(`/workflows/api/runs/${encodeURIComponent(runId)}/stop`, { method: "POST" }); },
457
+ resumeWorkflowRun(runId, approved = true) {
458
+ return raw(`/workflows/api/runs/${encodeURIComponent(runId)}/resume`, { method: "POST", body: { approved } });
459
+ },
460
+ workflowTriggers() { return withFallback("/workflows/api/triggers", {}, { running: false, armed: [] }); },
408
461
 
409
462
  // Long-Term Memory + Memory Manager (Parts 7, 8)
410
463
  memoryManager() { return withFallback("/api/memory/manager", {}, { sources: [], tiers: [], usage: {} }); },
@@ -532,6 +585,10 @@ export const api = {
532
585
  return withFallback(`/api/knowledge-graph/provenance${qs}`, {}, { items: [], count: 0 });
533
586
  },
534
587
 
588
+ kgProvenanceCoverage() {
589
+ return withFallback("/knowledge-graph/provenance/coverage", {}, { total_nodes: 0, nodes_with_provenance: 0, coverage_ratio: 0 });
590
+ },
591
+
535
592
  /** POST /api/knowledge-graph/export — logical JSON export of the whole graph. */
536
593
  graphExport() { return raw("/api/knowledge-graph/export", { method: "POST", body: {} }); },
537
594
 
@@ -279,6 +279,53 @@ export const api = {
279
279
 
280
280
  /* ── Organization workspaces (real backend: /workspace/orgs) ────────── */
281
281
  createOrg(name) { return raw("/workspace/orgs", { method: "POST", body: { name } }); },
282
+ workspaceRegistry() { return withFallback("/workspace/registry", {}, { workspaces: [], roles: [], permissions: {} }); },
283
+ activateWorkspace(workspace_id) { return raw("/workspace/activate", { method: "POST", body: { workspace_id } }); },
284
+ workspaceDetail(workspace_id) { return raw(`/workspace/orgs/${encodeURIComponent(workspace_id)}`); },
285
+ updateWorkspace(workspace_id, body) { return raw(`/workspace/orgs/${encodeURIComponent(workspace_id)}`, { method: "PATCH", body }); },
286
+ archiveWorkspace(workspace_id) { return raw(`/workspace/orgs/${encodeURIComponent(workspace_id)}/archive`, { method: "POST", body: {} }); },
287
+ addWorkspaceMember(workspace_id, user_id, role) {
288
+ return raw(`/workspace/orgs/${encodeURIComponent(workspace_id)}/members`, { method: "POST", body: { user_id, role } });
289
+ },
290
+ updateWorkspaceMember(workspace_id, user_id, role) {
291
+ return raw(`/workspace/orgs/${encodeURIComponent(workspace_id)}/members/${encodeURIComponent(user_id)}`, { method: "PATCH", body: { role } });
292
+ },
293
+ removeWorkspaceMember(workspace_id, user_id) {
294
+ return raw(`/workspace/orgs/${encodeURIComponent(workspace_id)}/members/${encodeURIComponent(user_id)}`, { method: "DELETE" });
295
+ },
296
+ invitations() { return withFallback("/invitations", {}, { invitations: [] }); },
297
+ createInvitation(body) { return raw("/invitations", { method: "POST", body }); },
298
+ acceptInvitation(token) { return raw(`/invitations/${encodeURIComponent(token)}/accept`, { method: "POST", body: {} }); },
299
+
300
+ /* ── Account / token-native auth ───────────────────────────────────── */
301
+ profile() { return raw("/account/profile"); },
302
+ login(email, password) { return raw("/login", { method: "POST", body: { email, password } }); },
303
+ register(body) { return raw("/register", { method: "POST", body }); },
304
+ logout() { return raw("/logout", { method: "POST", body: {} }); },
305
+ updateProfile(body) { return raw("/account/profile", { method: "PATCH", body }); },
306
+ changePassword(current_password, new_password) {
307
+ return raw("/account/change-password", { method: "POST", body: { current_password, new_password } });
308
+ },
309
+ ssoConfig() { return withFallback("/auth/sso/config", {}, { enabled: false, providers: [] }); },
310
+
311
+ /* ── Snapshots, Time Machine, realtime ─────────────────────────────── */
312
+ snapshots() { return withFallback("/workspace/snapshots", {}, { snapshots: [] }); },
313
+ createSnapshot(name) { return raw("/workspace/snapshots", { method: "POST", body: { name } }); },
314
+ compareSnapshots(before_id, after_id) { return raw("/workspace/snapshots/compare", { method: "POST", body: { before_id, after_id } }); },
315
+ snapshotExport(snapshot_id) { return raw(`/workspace/snapshots/${encodeURIComponent(snapshot_id)}/export`, { method: "POST", body: {} }); },
316
+ snapshotRestore(snapshot_id) { return raw(`/workspace/snapshots/${encodeURIComponent(snapshot_id)}/restore`, { method: "POST", body: {} }); },
317
+ timeMachine(limit = 100) { return withFallback(`/workspace/time-machine?limit=${encodeURIComponent(limit)}`, {}, { events: [] }); },
318
+ realtimeFeed(limit = 50) { return withFallback(`/realtime/feed?limit=${encodeURIComponent(limit)}`, {}, { events: [], stats: {} }); },
319
+ presence() { return withFallback("/realtime/presence", {}, { presence: [], stats: {} }); },
320
+
321
+ /* ── Approval + Brain Network surfaces ─────────────────────────────── */
322
+ permissionsPending() { return withFallback("/permissions/pending", {}, { pending: {}, count: 0 }); },
323
+ denyPermission(token) { return raw(`/permissions/deny/${encodeURIComponent(token)}`, { method: "POST" }); },
324
+ networkIdentity() { return withFallback("/network/identity", {}, {}); },
325
+ networkPeers() { return withFallback("/network/peers", {}, { peers: [] }); },
326
+ pairPeer(body) { return raw("/network/peers", { method: "POST", body }); },
327
+ unpairPeer(peer_id) { return raw(`/network/peers/${encodeURIComponent(peer_id)}`, { method: "DELETE" }); },
328
+ pushPeer(peer_id, workspace_id) { return raw(`/network/push/${encodeURIComponent(peer_id)}`, { method: "POST", body: { workspace_id } }); },
282
329
 
283
330
  /* ── Chat (real backend: SSE /chat + /history/*) ────────────────────── */
284
331
 
@@ -402,9 +449,15 @@ export const api = {
402
449
  // Workflow Agents (Part 5)
403
450
  workflowDefinitions() { return withFallback("/workflows/api/definitions", {}, { workflows: [] }); },
404
451
  createWorkflow(body) { return raw("/workflows/api/definitions", { method: "POST", body }); },
452
+ updateWorkflow(id, body) { return raw(`/workflows/api/definitions/${encodeURIComponent(id)}`, { method: "PATCH", body }); },
405
453
  runWorkflow(id, body = {}) { return raw(`/workflows/api/definitions/${encodeURIComponent(id)}/run`, { method: "POST", body }); },
406
454
  workflowRuns() { return withFallback("/workflows/api/runs", {}, { runs: [] }); },
407
455
  workflowReplay(runId) { return raw(`/workflows/api/runs/${encodeURIComponent(runId)}/replay`); },
456
+ stopWorkflowRun(runId) { return raw(`/workflows/api/runs/${encodeURIComponent(runId)}/stop`, { method: "POST" }); },
457
+ resumeWorkflowRun(runId, approved = true) {
458
+ return raw(`/workflows/api/runs/${encodeURIComponent(runId)}/resume`, { method: "POST", body: { approved } });
459
+ },
460
+ workflowTriggers() { return withFallback("/workflows/api/triggers", {}, { running: false, armed: [] }); },
408
461
 
409
462
  // Long-Term Memory + Memory Manager (Parts 7, 8)
410
463
  memoryManager() { return withFallback("/api/memory/manager", {}, { sources: [], tiers: [], usage: {} }); },
@@ -532,6 +585,10 @@ export const api = {
532
585
  return withFallback(`/api/knowledge-graph/provenance${qs}`, {}, { items: [], count: 0 });
533
586
  },
534
587
 
588
+ kgProvenanceCoverage() {
589
+ return withFallback("/knowledge-graph/provenance/coverage", {}, { total_nodes: 0, nodes_with_provenance: 0, coverage_ratio: 0 });
590
+ },
591
+
535
592
  /** POST /api/knowledge-graph/export — logical JSON export of the whole graph. */
536
593
  graphExport() { return raw("/api/knowledge-graph/export", { method: "POST", body: {} }); },
537
594