ltcai 8.9.0 → 9.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 (208) hide show
  1. package/README.md +81 -58
  2. package/auto_setup.py +7 -904
  3. package/desktop/electron/README.md +9 -0
  4. package/desktop/electron/main.cjs +5 -3
  5. package/docs/CHANGELOG.md +221 -238
  6. package/docs/COMMUNITY_AND_PLUGINS.md +3 -2
  7. package/docs/DEVELOPMENT.md +53 -14
  8. package/docs/LEGACY_COMPATIBILITY.md +4 -4
  9. package/docs/ONBOARDING.md +10 -2
  10. package/docs/OPERATIONS.md +8 -4
  11. package/docs/PRODUCT_DIRECTION_REVIEW.md +4 -0
  12. package/docs/ROADMAP_RECOMMENDATIONS.md +61 -36
  13. package/docs/TRUST_MODEL.md +5 -2
  14. package/docs/WHY_LATTICE.md +15 -10
  15. package/docs/WORKFLOW_DESIGNER.md +22 -0
  16. package/docs/kg-schema.md +13 -2
  17. package/docs/mcp-tools.md +17 -6
  18. package/docs/privacy.md +19 -3
  19. package/docs/public-deploy.md +32 -3
  20. package/docs/security-model.md +46 -11
  21. package/lattice_brain/__init__.py +1 -1
  22. package/lattice_brain/archive.py +4 -14
  23. package/lattice_brain/context.py +66 -9
  24. package/lattice_brain/embeddings.py +38 -2
  25. package/lattice_brain/graph/_kg_common.py +27 -462
  26. package/lattice_brain/graph/_kg_constants.py +243 -0
  27. package/lattice_brain/graph/_kg_fsutil.py +293 -0
  28. package/lattice_brain/graph/discovery.py +0 -948
  29. package/lattice_brain/graph/discovery_index.py +1126 -0
  30. package/lattice_brain/graph/documents.py +44 -9
  31. package/lattice_brain/graph/ingest.py +47 -20
  32. package/lattice_brain/graph/provenance.py +13 -6
  33. package/lattice_brain/graph/retrieval.py +141 -610
  34. package/lattice_brain/graph/retrieval_docgen.py +243 -0
  35. package/lattice_brain/graph/retrieval_vector.py +460 -0
  36. package/lattice_brain/graph/store.py +6 -0
  37. package/lattice_brain/ingestion.py +69 -4
  38. package/lattice_brain/portability.py +29 -23
  39. package/lattice_brain/quality.py +98 -4
  40. package/lattice_brain/runtime/agent_runtime.py +169 -7
  41. package/lattice_brain/runtime/hooks.py +30 -13
  42. package/lattice_brain/runtime/multi_agent.py +27 -8
  43. package/lattice_brain/runtime/statuses.py +10 -0
  44. package/lattice_brain/utils.py +46 -0
  45. package/lattice_brain/workflow.py +1 -5
  46. package/latticeai/__init__.py +1 -1
  47. package/latticeai/api/admin.py +1 -1
  48. package/latticeai/api/agent_registry.py +10 -8
  49. package/latticeai/api/agents.py +22 -3
  50. package/latticeai/api/auth.py +78 -16
  51. package/latticeai/api/browser.py +303 -34
  52. package/latticeai/api/chat.py +355 -952
  53. package/latticeai/api/chat_agent_http.py +356 -0
  54. package/latticeai/api/chat_contracts.py +54 -0
  55. package/latticeai/api/chat_documents.py +256 -0
  56. package/latticeai/api/chat_helpers.py +250 -0
  57. package/latticeai/api/chat_history.py +99 -0
  58. package/latticeai/api/chat_intents.py +302 -0
  59. package/latticeai/api/chat_stream.py +115 -0
  60. package/latticeai/api/computer_use.py +211 -40
  61. package/latticeai/api/health.py +9 -3
  62. package/latticeai/api/hooks.py +17 -6
  63. package/latticeai/api/knowledge_graph.py +78 -14
  64. package/latticeai/api/local_files.py +7 -2
  65. package/latticeai/api/marketplace.py +11 -0
  66. package/latticeai/api/mcp.py +102 -23
  67. package/latticeai/api/models.py +72 -33
  68. package/latticeai/api/network.py +5 -5
  69. package/latticeai/api/permissions.py +70 -29
  70. package/latticeai/api/plugins.py +21 -7
  71. package/latticeai/api/portability.py +5 -5
  72. package/latticeai/api/realtime.py +33 -5
  73. package/latticeai/api/setup.py +2 -2
  74. package/latticeai/api/static_routes.py +123 -24
  75. package/latticeai/api/tools.py +97 -14
  76. package/latticeai/api/workflow_designer.py +37 -0
  77. package/latticeai/api/workspace.py +2 -1
  78. package/latticeai/app_factory.py +185 -405
  79. package/latticeai/core/agent.py +19 -9
  80. package/latticeai/core/agent_registry.py +1 -5
  81. package/latticeai/core/config.py +23 -3
  82. package/latticeai/core/context_builder.py +21 -3
  83. package/latticeai/core/invitations.py +1 -4
  84. package/latticeai/core/io_utils.py +45 -0
  85. package/latticeai/core/legacy_compatibility.py +24 -3
  86. package/latticeai/core/local_embeddings.py +2 -4
  87. package/latticeai/core/marketplace.py +33 -2
  88. package/latticeai/core/mcp_catalog.py +450 -0
  89. package/latticeai/core/mcp_registry.py +2 -441
  90. package/latticeai/core/plugins.py +15 -0
  91. package/latticeai/core/policy.py +1 -1
  92. package/latticeai/core/realtime.py +38 -15
  93. package/latticeai/core/sessions.py +7 -2
  94. package/latticeai/core/timeutil.py +10 -0
  95. package/latticeai/core/tool_registry.py +90 -18
  96. package/latticeai/core/users.py +5 -14
  97. package/latticeai/core/workspace_graph_trace.py +31 -5
  98. package/latticeai/core/workspace_memory.py +3 -1
  99. package/latticeai/core/workspace_os.py +18 -7
  100. package/latticeai/core/workspace_os_utils.py +2 -21
  101. package/latticeai/core/workspace_permissions.py +2 -1
  102. package/latticeai/core/workspace_plugins.py +1 -1
  103. package/latticeai/core/workspace_runs.py +14 -5
  104. package/latticeai/core/workspace_skills.py +1 -1
  105. package/latticeai/core/workspace_snapshots.py +2 -1
  106. package/latticeai/core/workspace_timeline.py +2 -1
  107. package/latticeai/integrations/telegram_bot.py +96 -40
  108. package/latticeai/models/model_providers.py +111 -0
  109. package/latticeai/models/router.py +189 -173
  110. package/latticeai/runtime/access_runtime.py +62 -4
  111. package/latticeai/runtime/audit_runtime.py +27 -16
  112. package/latticeai/runtime/automation_runtime.py +22 -7
  113. package/latticeai/runtime/brain_runtime.py +19 -7
  114. package/latticeai/runtime/chat_wiring.py +2 -0
  115. package/latticeai/runtime/config_runtime.py +58 -26
  116. package/latticeai/runtime/context_runtime.py +16 -4
  117. package/latticeai/runtime/history_runtime.py +163 -0
  118. package/latticeai/runtime/hooks_runtime.py +1 -1
  119. package/latticeai/runtime/model_wiring.py +33 -5
  120. package/latticeai/runtime/namespace_runtime.py +163 -0
  121. package/latticeai/runtime/network_config_runtime.py +56 -0
  122. package/latticeai/runtime/platform_runtime_wiring.py +4 -3
  123. package/latticeai/runtime/review_wiring.py +1 -1
  124. package/latticeai/runtime/router_registration.py +34 -1
  125. package/latticeai/runtime/security_runtime.py +110 -13
  126. package/latticeai/runtime/sso_config_runtime.py +128 -0
  127. package/latticeai/runtime/stages.py +27 -0
  128. package/latticeai/runtime/user_key_runtime.py +106 -0
  129. package/latticeai/server_app.py +5 -1
  130. package/latticeai/services/architecture_readiness.py +74 -5
  131. package/latticeai/services/brain_automation.py +3 -26
  132. package/latticeai/services/chat_service.py +205 -15
  133. package/latticeai/services/local_knowledge.py +423 -0
  134. package/latticeai/services/memory_service.py +268 -21
  135. package/latticeai/services/model_engines.py +48 -33
  136. package/latticeai/services/model_errors.py +17 -0
  137. package/latticeai/services/model_loading.py +28 -25
  138. package/latticeai/services/model_runtime.py +228 -162
  139. package/latticeai/services/p_reinforce.py +22 -3
  140. package/latticeai/services/platform_runtime.py +92 -24
  141. package/latticeai/services/product_readiness.py +19 -17
  142. package/latticeai/services/review_queue.py +76 -11
  143. package/latticeai/services/router_context.py +1 -0
  144. package/latticeai/services/run_executor.py +25 -9
  145. package/latticeai/services/search_service.py +203 -28
  146. package/latticeai/services/setup_detection.py +80 -0
  147. package/latticeai/services/tool_dispatch.py +28 -5
  148. package/latticeai/services/triggers.py +53 -4
  149. package/latticeai/services/upload_service.py +13 -2
  150. package/latticeai/setup/__init__.py +25 -0
  151. package/latticeai/setup/auto_setup.py +857 -0
  152. package/latticeai/setup/wizard.py +1264 -0
  153. package/latticeai/tools/__init__.py +278 -0
  154. package/{tools → latticeai/tools}/commands.py +67 -7
  155. package/{tools → latticeai/tools}/computer.py +1 -1
  156. package/{tools → latticeai/tools}/documents.py +1 -1
  157. package/{tools → latticeai/tools}/filesystem.py +3 -3
  158. package/latticeai/tools/knowledge.py +178 -0
  159. package/{tools → latticeai/tools}/local_files.py +7 -1
  160. package/{tools → latticeai/tools}/network.py +0 -1
  161. package/local_knowledge_api.py +4 -342
  162. package/package.json +22 -2
  163. package/scripts/brain_quality_eval.py +3 -1
  164. package/scripts/bump_version.py +3 -0
  165. package/scripts/capture_release_evidence.mjs +180 -0
  166. package/scripts/check_current_release_docs.mjs +142 -0
  167. package/scripts/check_i18n_literals.mjs +107 -31
  168. package/scripts/check_openapi_drift.mjs +56 -0
  169. package/scripts/export_openapi.py +67 -7
  170. package/scripts/i18n_literal_allowlist.json +22 -24
  171. package/scripts/run_integration_tests.mjs +72 -10
  172. package/scripts/validate_release_artifacts.py +49 -7
  173. package/scripts/wheel_smoke.py +5 -0
  174. package/setup_wizard.py +3 -1304
  175. package/src-tauri/Cargo.lock +1 -1
  176. package/src-tauri/Cargo.toml +1 -1
  177. package/src-tauri/tauri.conf.json +1 -1
  178. package/static/app/asset-manifest.json +11 -11
  179. package/static/app/assets/Act-Bzz0bUyW.js +1 -0
  180. package/static/app/assets/Brain-Dj2J20YA.js +321 -0
  181. package/static/app/assets/Capture-CqlEl1Ga.js +1 -0
  182. package/static/app/assets/Library-B03FP1Yx.js +1 -0
  183. package/static/app/assets/System-80lHW0Ux.js +1 -0
  184. package/static/app/assets/index-BiMofBTM.js +17 -0
  185. package/static/app/assets/index-Bmx9rzTc.css +2 -0
  186. package/static/app/assets/primitives-Q1A96_7v.js +1 -0
  187. package/static/app/assets/textarea-D13RtnTo.js +1 -0
  188. package/static/app/index.html +2 -2
  189. package/static/css/tokens.css +4 -2
  190. package/static/sw.js +1 -1
  191. package/tools/__init__.py +21 -269
  192. package/docs/CODE_REVIEW_2026-07-06.md +0 -764
  193. package/latticeai/runtime/app_context_runtime.py +0 -13
  194. package/latticeai/runtime/sso_runtime.py +0 -52
  195. package/latticeai/runtime/tail_wiring.py +0 -21
  196. package/scripts/com.pts.claudecode.discord.plist +0 -31
  197. package/scripts/pts-claudecode-discord-bridge.mjs +0 -207
  198. package/scripts/start-pts-claudecode-discord.sh +0 -51
  199. package/static/app/assets/Act-fZokUnC0.js +0 -1
  200. package/static/app/assets/Brain-DtyuWubr.js +0 -321
  201. package/static/app/assets/Capture-D5KV3Cu7.js +0 -1
  202. package/static/app/assets/Library-C9kyFkSt.js +0 -1
  203. package/static/app/assets/System-VbChmX7r.js +0 -1
  204. package/static/app/assets/index-DCh5AoXt.css +0 -2
  205. package/static/app/assets/index-DPdcPoF0.js +0 -17
  206. package/static/app/assets/primitives-DFeanEV6.js +0 -1
  207. package/static/app/assets/textarea-CD8UNKIy.js +0 -1
  208. package/tools/knowledge.py +0 -95
@@ -0,0 +1 @@
1
+ import{B as e,D as t,E as n,F as r,H as i,L as a,M as o,O as s,P as c,R as l,T as u,f as d,i as f,j as p,k as m,s as h,w as g,x as _}from"./index-BiMofBTM.js";var v=g(`circle-alert`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`line`,{x1:`12`,x2:`12`,y1:`8`,y2:`12`,key:`1pkeuh`}],[`line`,{x1:`12`,x2:`12.01`,y1:`16`,y2:`16`,key:`4dfq90`}]]),y=g(`lock-keyhole`,[[`circle`,{cx:`12`,cy:`16`,r:`1`,key:`1au0dj`}],[`rect`,{x:`3`,y:`10`,width:`18`,height:`12`,rx:`2`,key:`6s8ecr`}],[`path`,{d:`M7 10V7a5 5 0 0 1 10 0v3`,key:`1pqi11`}]]),b=i(e()),x=l(),S={default:`border-primary/25 bg-primary/12 text-primary`,success:`border-success/30 bg-success/12 text-success`,warning:`border-warning/30 bg-warning/12 text-warning`,muted:`border-border bg-muted/70 text-muted-foreground`,danger:`border-destructive/30 bg-destructive/12 text-destructive`};function C({className:e,variant:n=`default`,...r}){return(0,x.jsx)(`span`,{className:t(`inline-flex min-h-6 max-w-full items-center whitespace-nowrap rounded-md border px-2 py-0.5 text-xs font-semibold leading-none`,S[n],e),...r})}function w({className:e,...n}){return(0,x.jsx)(`section`,{className:t(`premium-surface rounded-lg text-card-foreground`,e),...n})}function T({className:e,...n}){return(0,x.jsx)(`div`,{className:t(`flex flex-col gap-1.5 p-5`,e),...n})}function E({className:e,...n}){return(0,x.jsx)(`h2`,{className:t(`text-base font-semibold tracking-normal`,e),...n})}function D({className:e,...n}){return(0,x.jsx)(`p`,{className:t(`text-sm leading-6 text-muted-foreground`,e),...n})}function O({className:e,...n}){return(0,x.jsx)(`div`,{className:t(`p-5 pt-0`,e),...n})}function k({result:e}){let t=c(e=>e.mode),n=c(e=>e.language);return e?e.source===`live`&&e.ok?(0,x.jsx)(C,{variant:`success`,children:t===`basic`?u(n,`ui.status.ready`):u(n,`ui.status.connected`)}):(0,x.jsx)(C,{variant:`warning`,children:t===`basic`?u(n,`ui.status.needsSetup`):u(n,`ui.status.unavailable`)}):(0,x.jsx)(C,{variant:`muted`,children:u(n,`ui.status.notLoaded`)})}function A({title:e,detail:t}){let n=c(e=>e.language);return(0,x.jsxs)(`div`,{className:`product-empty-state flex min-h-36 flex-col items-center justify-center gap-2 rounded-lg border border-dashed border-border bg-muted/24 p-6 text-center text-sm text-muted-foreground`,children:[(0,x.jsx)(`div`,{className:`grid h-10 w-10 place-items-center rounded-md border border-border bg-card`,children:(0,x.jsx)(h,{className:`h-5 w-5 text-primary`})}),(0,x.jsx)(`div`,{className:`text-base font-semibold text-foreground`,children:e||u(n,`ui.empty.title`)}),t?(0,x.jsx)(`div`,{className:`max-w-md leading-6`,children:t}):null]})}function j({title:e,description:n,result:r,children:i,className:a}){let o=c(e=>e.mode),s=c(e=>e.language);return(0,x.jsxs)(w,{className:t(`data-panel overflow-hidden`,a),children:[(0,x.jsxs)(T,{className:`flex-row items-start justify-between gap-3`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(E,{children:e}),n?(0,x.jsx)(D,{children:n}):null]}),o===`basic`?null:(0,x.jsx)(k,{result:r})]}),(0,x.jsx)(O,{children:r?.ok?i(r.data):(0,x.jsx)(A,{detail:o===`basic`?u(s,`ui.empty.basicDetail`):r?.error||u(s,`ui.empty.advancedDetail`)})})]})}function M({title:e}){let t=c(e=>e.language);return(0,x.jsxs)(w,{children:[(0,x.jsx)(T,{children:(0,x.jsx)(E,{children:e})}),(0,x.jsx)(O,{children:(0,x.jsxs)(`div`,{className:`flex items-center gap-2 text-sm text-muted-foreground`,children:[(0,x.jsx)(d,{className:`h-4 w-4 animate-spin`}),` `,u(t,`ui.loading`)]})})]})}function N({stats:e}){return(0,x.jsx)(`div`,{className:`data-stat-grid grid gap-3 sm:grid-cols-2 xl:grid-cols-4`,children:e.map(e=>(0,x.jsxs)(`div`,{className:`rounded-lg border border-border bg-background/55 p-4`,children:[(0,x.jsx)(`div`,{className:`text-xs uppercase text-muted-foreground`,children:e.label}),(0,x.jsx)(`div`,{className:`mt-2 text-2xl font-semibold leading-tight`,children:typeof e.value==`number`?s(e.value):String(e.value??`-`)}),e.hint?(0,x.jsx)(`div`,{className:`mt-2 text-xs leading-5 text-muted-foreground`,children:e.hint}):null]},e.label))})}function P(e){return e==null||e===``?`-`:typeof e==`number`?Number.isFinite(e)?s(e):`-`:typeof e==`boolean`?e?`Enabled`:`Disabled`:String(e)}var F=/(^id$|_id$|token|secret|passphrase|fingerprint|public_key|private_key|dsn|schema|endpoint|base_url|localhost|127\.0\.0\.1|stack|trace|raw|runtime|engine|module|port|host|api|internal)/i;function I(e){return F.test(e)}function L(e){let t=P(e);return t===`-`||t.includes(`/`)||t.includes(`@`)||/\.[a-z0-9]{2,5}$/i.test(t)?t:o(t.replace(/^agent:/i,``).replace(/^tool:/i,``))}function R(e){for(let t of[`documents`,`sources`,`items`,`agents`,`workflows`,`runs`,`events`,`permissions`,`models`,`peers`,`invitations`,`roles`,`policies`,`hooks`,`tools`,`templates`,`plugins`,`recent_events`]){let r=n(e[t]);if(r.length)return r}return[]}function z({value:e}){let t=c(e=>e.language);if(typeof e==`boolean`)return(0,x.jsx)(C,{variant:e?`success`:`muted`,children:u(t,e?`ui.value.enabled`:`ui.value.disabled`)});if(Array.isArray(e))return e.length?e.every(e=>e===null||[`string`,`number`,`boolean`].includes(typeof e))?(0,x.jsxs)(`span`,{className:`flex flex-wrap gap-1`,children:[e.slice(0,5).map((e,t)=>(0,x.jsx)(C,{variant:`muted`,children:P(e)},`${String(e)}-${t}`)),e.length>5?(0,x.jsxs)(C,{variant:`muted`,children:[`+`,e.length-5]}):null]}):(0,x.jsx)(`span`,{className:`text-muted-foreground`,children:u(t,`ui.value.records`,{count:s(e.length)})}):(0,x.jsx)(`span`,{className:`text-muted-foreground`,children:u(t,`ui.value.none`)});if(m(e)){let n=Object.keys(e);return n.length?(0,x.jsxs)(`span`,{className:`text-muted-foreground`,children:[n.slice(0,4).map(o).join(`, `),n.length>4?` +${n.length-4}`:``]}):(0,x.jsx)(`span`,{className:`text-muted-foreground`,children:u(t,`ui.value.noFields`)})}let n=P(e);return(0,x.jsx)(`span`,{className:`break-words`,children:n.length>96?p(n,96):n})}function B({data:e,limit:t=8}){let n=c(e=>e.mode),r=c(e=>e.language),i=Object.entries(e||{}).filter(([e])=>n!==`basic`||!I(e)).slice(0,t);return i.length?(0,x.jsx)(`div`,{className:`divide-y divide-border rounded-md border border-border`,children:i.map(([e,t])=>(0,x.jsxs)(`div`,{className:`grid grid-cols-[minmax(9rem,0.5fr)_1fr] gap-3 p-3 text-sm`,children:[(0,x.jsx)(`span`,{className:`font-medium text-muted-foreground`,children:o(e)}),(0,x.jsx)(`span`,{className:`min-w-0 break-words`,children:(0,x.jsx)(z,{value:t})})]},e))}):(0,x.jsx)(A,{title:u(r,`ui.noValues`)})}function V({value:e,titleKey:t=`title`,metaKey:n=`status`,limit:r=8}){let i=c(e=>e.mode),a=c(e=>e.language);return i===`basic`?(0,x.jsx)(H,{value:e,titleKey:t,metaKey:n,limit:r}):Array.isArray(e)?e.length?e.every(e=>m(e))?(0,x.jsx)(W,{items:e,titleKey:t,metaKey:n,limit:r}):(0,x.jsxs)(`div`,{className:`flex flex-wrap gap-1 rounded-md border border-border bg-background p-3`,children:[e.slice(0,r).map((e,t)=>(0,x.jsx)(C,{variant:`muted`,children:P(e)},`${String(e)}-${t}`)),e.length>r?(0,x.jsxs)(C,{variant:`muted`,children:[`+`,e.length-r]}):null]}):(0,x.jsx)(A,{detail:u(a,`ui.empty.listDetail`)}):m(e)?(0,x.jsx)(B,{data:e,limit:r}):(0,x.jsx)(`div`,{className:`rounded-md border border-border bg-background p-3 text-sm`,children:(0,x.jsx)(z,{value:e})})}function H({value:e,titleKey:t=`title`,metaKey:n=`status`,limit:r=6}){let i=c(e=>e.language);if(Array.isArray(e))return e.length?e.every(e=>m(e))?(0,x.jsx)(W,{items:e,titleKey:t,metaKey:n,limit:r}):(0,x.jsxs)(`div`,{className:`flex flex-wrap gap-1 rounded-md border border-border bg-background/55 p-3`,children:[e.slice(0,r).map((e,t)=>(0,x.jsx)(C,{variant:`muted`,children:L(e)},`${String(e)}-${t}`)),e.length>r?(0,x.jsxs)(C,{variant:`muted`,children:[`+`,e.length-r]}):null]}):(0,x.jsx)(A,{detail:u(i,`ui.empty.listDetail`)});if(m(e)){let i=R(e);return i.length?(0,x.jsx)(W,{items:i,titleKey:t,metaKey:n,limit:r}):(0,x.jsx)(B,{data:Object.fromEntries(Object.entries(e).filter(([e])=>!I(e)).map(([e,t])=>[e,Array.isArray(t)?`${s(t.length)} items`:m(t)?`available`:t])),limit:r})}return(0,x.jsx)(`div`,{className:`rounded-md border border-border bg-background/55 p-3 text-sm`,children:L(e)})}function U({result:e,successLabel:t}){let n=c(e=>e.mode),r=c(e=>e.language);return e?e.ok?(0,x.jsxs)(`div`,{className:`space-y-2 rounded-md border border-border bg-background p-3`,children:[(0,x.jsx)(C,{variant:`success`,children:t||u(r,`ui.requestCompleted`)}),n===`basic`?(0,x.jsx)(H,{value:e.data}):(0,x.jsx)(V,{value:e.data})]}):(0,x.jsx)(A,{title:u(r,`ui.requestUnavailable`),detail:e.error||(0,x.jsx)(z,{value:e.data})}):null}function W({items:e,titleKey:t=`title`,metaKey:r=`type`,limit:i=8}){let a=c(e=>e.mode),o=c(e=>e.language),s=n(e).slice(0,i);return s.length?(0,x.jsx)(`div`,{className:`entity-list grid gap-2`,children:s.map((e,n)=>(0,x.jsxs)(`div`,{className:`entity-list-row rounded-lg border border-border bg-background/55 p-3`,children:[(0,x.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-2`,children:[(0,x.jsx)(`div`,{className:`font-medium`,children:a===`basic`?L(e[t]||e.name||e.label||`Item ${n+1}`):String(e[t]||e.name||e.id||`Record ${n+1}`)}),(0,x.jsx)(C,{variant:`muted`,children:a===`basic`?L(e[r]||e.status||e.state||`ready`):String(e[r]||e.status||e.state||`record`)})]}),e.summary||e.description||e.path||e.id&&e[t]!==e.id?(0,x.jsx)(`p`,{className:`mt-1 text-sm text-muted-foreground`,children:String(e.summary||e.description||e.path||e.id)}):null,a!==`basic`&&e.id&&e[t]!==e.id?(0,x.jsx)(`div`,{className:`mt-1 text-xs text-muted-foreground`,children:p(e.id,48)}):null]},String(e.id||e.name||n)))}):(0,x.jsx)(A,{detail:u(o,`ui.empty.listDetail`)})}function G({title:e,detail:t,target:n=`advanced`}){let r=c(e=>e.setMode),i=c(e=>e.language);return(0,x.jsx)(w,{children:(0,x.jsxs)(O,{className:`flex flex-col items-start gap-3 p-6`,children:[(0,x.jsx)(`div`,{className:`grid h-10 w-10 place-items-center rounded-md border border-border bg-background/70`,children:(0,x.jsx)(y,{className:`h-5 w-5 text-primary`})}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`div`,{className:`text-lg font-semibold`,children:e||u(i,`ui.modeGate.title`)}),(0,x.jsx)(`p`,{className:`mt-1 max-w-2xl text-sm leading-6 text-muted-foreground`,children:t||u(i,`ui.modeGate.detail`)})]}),(0,x.jsx)(f,{onClick:()=>r(n),children:n===`admin`?u(i,`ui.modeGate.admin`):u(i,`ui.modeGate.advanced`)})]})})}function K({label:e,successLabel:n,action:i,onSuccess:o,invalidate:s,variant:l=`outline`,disabled:p}){let m=a(),h=c(e=>e.language),g=n||u(h,`ui.done`),[y,S]=b.useState(null),C=r({mutationFn:i,onSuccess:async e=>{S(e.ok?g:e.error||u(h,`ui.status.unavailable`)),e.ok&&(await o?.(e),s&&await Promise.all(s.map(e=>m.invalidateQueries({queryKey:[e]}))))}});return(0,x.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,x.jsxs)(f,{variant:l,disabled:p||C.isPending,onClick:()=>C.mutate(),children:[C.isPending?(0,x.jsx)(d,{className:`h-4 w-4 animate-spin`}):null,e]}),y?(0,x.jsxs)(`span`,{className:t(`inline-flex items-center gap-1 text-xs`,y===g?`text-success`:`text-warning`),children:[y===g?(0,x.jsx)(_,{className:`h-3.5 w-3.5`}):(0,x.jsx)(v,{className:`h-3.5 w-3.5`}),y]}):null]})}function q({tabs:e,value:n,onChange:r}){let i=b.useRef([]),a=(t,n)=>{let a=(t+n+e.length)%e.length;i.current[a]?.focus(),r(e[a].id)};return(0,x.jsx)(`div`,{className:`product-tabs inline-flex max-w-full flex-wrap gap-1 rounded-lg border border-border bg-muted/28 p-1`,role:`tablist`,children:e.map((o,s)=>(0,x.jsx)(`button`,{ref:e=>{i.current[s]=e},type:`button`,role:`tab`,"aria-selected":n===o.id,tabIndex:n===o.id?0:-1,onClick:()=>r(o.id),onKeyDown:t=>{t.key===`ArrowRight`||t.key===`ArrowDown`?(t.preventDefault(),a(s,1)):t.key===`ArrowLeft`||t.key===`ArrowUp`?(t.preventDefault(),a(s,-1)):t.key===`Home`?(t.preventDefault(),i.current[0]?.focus(),r(e[0].id)):t.key===`End`&&(t.preventDefault(),i.current[e.length-1]?.focus(),r(e[e.length-1].id))},className:t(`h-9 rounded-md px-3.5 text-sm font-semibold transition`,n===o.id?`bg-card text-foreground shadow-sm`:`text-muted-foreground hover:bg-card/60 hover:text-foreground`),children:o.label},o.id))})}export{E as _,B as a,U as c,q as d,z as f,T as g,D as h,W as i,N as l,O as m,j as n,M as o,w as p,A as r,G as s,K as t,V as u,C as v,v as y};
@@ -0,0 +1 @@
1
+ import{B as e,D as t,H as n,R as r}from"./index-BiMofBTM.js";var i=n(e()),a=r(),o=i.forwardRef(({className:e,...n},r)=>(0,a.jsx)(`textarea`,{ref:r,className:t(`min-h-28 w-full resize-y rounded-md border border-input bg-background/70 px-3 py-3 text-sm leading-6 outline-none transition placeholder:text-muted-foreground focus:border-ring focus:ring-2 focus:ring-ring/35 disabled:cursor-not-allowed disabled:opacity-50`,e),...n}));o.displayName=`Textarea`;export{o as t};
@@ -8,8 +8,8 @@
8
8
  <link rel="manifest" href="/manifest.json" />
9
9
  <link rel="icon" type="image/png" sizes="32x32" href="/icons/favicon-32.png" />
10
10
  <script src="/static/app/theme-boot.js"></script>
11
- <script type="module" crossorigin src="/static/app/assets/index-DPdcPoF0.js"></script>
12
- <link rel="stylesheet" crossorigin href="/static/app/assets/index-DCh5AoXt.css">
11
+ <script type="module" crossorigin src="/static/app/assets/index-BiMofBTM.js"></script>
12
+ <link rel="stylesheet" crossorigin href="/static/app/assets/index-Bmx9rzTc.css">
13
13
  </head>
14
14
  <body>
15
15
  <div id="root"></div>
@@ -1,7 +1,9 @@
1
1
  /* ============================================================================
2
- * Lattice AI — Design Tokens (Single Source of Truth) v3.3.1
2
+ * Lattice AI — Static-shell Design Tokens v3.3.1
3
3
  *
4
- * 이 파일이 색·면·테두리·그림자·포커스의 단일 출처다.
4
+ * 이 파일은 정적 서버 렌더링/legacy shell CSS의 색·면·테두리·그림자·포커스
5
+ * 출처다. React SPA(/app)는 frontend/src/styles/tokens.css의 HSL triple
6
+ * 토큰을 별도로 소비한다.
5
7
  * :root → 라이트 테마 값
6
8
  * :root[data-lt-theme="dark"] → 동일 토큰명의 다크 값
7
9
  * @media (prefers-color-scheme: dark) → 사용자가 명시 선택 안 했을 때 OS 추종
package/static/sw.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // Lattice Service Worker — PWA install + offline shell for the /app SPA.
2
2
  // Strategy: precache the Vite app bundle from its asset manifest,
3
3
  // cache-first for static assets, network-only for everything dynamic.
4
- const CACHE = "lattice-v890";
4
+ const CACHE = "lattice-v910";
5
5
  const MANIFEST_URL = "/static/app/asset-manifest.json";
6
6
 
7
7
  // Non-manifest assets the shell needs offline.
package/tools/__init__.py CHANGED
@@ -1,277 +1,29 @@
1
- """Safe local tools for Lattice AI agent mode.
1
+ """Compatibility alias for the physical :mod:`latticeai.tools` package.
2
2
 
3
- All filesystem operations are confined to LATTICEAI_AGENT_ROOT, defaulting to
4
- ./agent_workspace. Command execution runs without a shell and from inside that
5
- workspace.
6
-
7
- v3.5.0 splits the historical flat ``tools.py`` into focused submodules
8
- (computer, filesystem, documents, local_files, knowledge, network, commands)
9
- while keeping the exact import surface: this package re-exports every public name
10
- and ``execute_tool``/``DEFAULT_TOOL_REGISTRY``, so ``import tools`` and
11
- ``from tools import X`` behave identically to before. ``AGENT_ROOT`` and the path
12
- helpers live here as the single source of truth (tests monkeypatch
13
- ``tools.AGENT_ROOT``); submodules read it dynamically.
3
+ This shim replaces itself with the implementation module instead of copying
4
+ exports. Thus legacy and package imports share globals, registry instances,
5
+ submodules, and monkeypatches.
14
6
  """
15
7
 
16
- import base64
17
- import json
18
- import os
19
- import platform
20
- import re
21
- import shlex
22
- import socket
23
- import subprocess
24
- import tempfile
25
- from html.parser import HTMLParser
26
- from pathlib import Path
27
- from typing import Any, Callable, Dict, List, Optional
28
-
29
- from latticeai.core.tool_registry import ToolRegistry
30
- from p_reinforce import BRAIN_DIR, STRUCTURE
31
-
32
- _PLATFORM = platform.system() # "Darwin" | "Windows" | "Linux"
33
-
34
-
35
- # ── base: agent-root sandbox, shared constants, path helpers ──────────────────
36
- AGENT_ROOT = Path(os.getenv("LATTICEAI_AGENT_ROOT") or "agent_workspace").resolve()
37
- MAX_FILE_BYTES = 512_000
38
- MAX_COMMAND_SECONDS = 30
39
- MAX_BUILD_SECONDS = 180
40
- MAX_DEPLOY_SECONDS = 300
41
- MAX_COMMAND_OUTPUT = 12_000
42
-
43
- BLOCKED_COMMANDS = {
44
- "rm",
45
- "rmdir",
46
- "sudo",
47
- "su",
48
- "chmod",
49
- "chown",
50
- "curl",
51
- "wget",
52
- "ssh",
53
- "scp",
54
- "rsync",
55
- "dd",
56
- "mkfs",
57
- "diskutil",
58
- "launchctl",
59
- }
60
-
61
- ALLOWED_COMMANDS = {
62
- "pwd",
63
- "ls",
64
- "find",
65
- "cat",
66
- "sed",
67
- "head",
68
- "tail",
69
- "wc",
70
- "rg",
71
- "python",
72
- "python3",
73
- "node",
74
- "npm",
75
- "npx",
76
- "git",
77
- }
78
-
79
- BUILD_SCRIPT_NAMES = {"build", "compile", "typecheck", "test"}
80
- DEPLOY_SCRIPT_NAMES = {
81
- "deploy",
82
- "preview",
83
- "release",
84
- "package",
85
- "dist",
86
- "make",
87
- "build:installer",
88
- "build:pkg",
89
- "build:exe",
90
- "package:mac",
91
- "package:win",
92
- }
93
-
94
- ALLOWED_GIT_SUBCOMMANDS = {"status", "diff", "log", "show"}
95
-
96
- TEXT_EXTENSIONS = {
97
- ".css",
98
- ".csv",
99
- ".html",
100
- ".js",
101
- ".json",
102
- ".jsx",
103
- ".md",
104
- ".py",
105
- ".ts",
106
- ".tsx",
107
- ".txt",
108
- ".xml",
109
- ".yaml",
110
- ".yml",
111
- }
112
-
113
- DOCUMENT_OUTPUT_DIR = "generated_documents"
114
- PRESENTATION_OUTPUT_DIR = "generated_presentations"
115
- SPREADSHEET_OUTPUT_DIR = "generated_spreadsheets"
116
-
117
-
118
- class ToolError(ValueError):
119
- pass
120
-
121
-
122
- def ensure_agent_root() -> Path:
123
- AGENT_ROOT.mkdir(parents=True, exist_ok=True)
124
- return AGENT_ROOT
125
-
126
-
127
- def _resolve_path(path: str = "") -> Path:
128
- ensure_agent_root()
129
- if not path:
130
- return AGENT_ROOT
131
- candidate = (AGENT_ROOT / path).resolve()
132
- if candidate != AGENT_ROOT and AGENT_ROOT not in candidate.parents:
133
- raise ToolError("Path escapes the agent workspace.")
134
- return candidate
135
-
136
-
137
- def _relative(path: Path) -> str:
138
- return str(path.relative_to(AGENT_ROOT))
139
-
140
-
141
- # ── document / local / read constants (shared by submodules) ──────────────────
142
- PDF_OUTPUT_DIR = "generated_pdfs"
143
- LOCAL_MAX_FILE_BYTES = 2_000_000 # 2 MB cap for local reads
144
-
145
-
146
- # CJK-capable fonts (Korean + Chinese + Japanese)
147
- _CJK_FONT_CANDIDATES = [
148
- "/System/Library/Fonts/AppleSDGothicNeo.ttc", # Korean (macOS)
149
- "/System/Library/Fonts/STHeiti Light.ttc", # Chinese (macOS)
150
- "/System/Library/Fonts/PingFang.ttc", # Chinese (macOS)
151
- "/Library/Fonts/NanumGothic.ttf", # Korean
152
- "/usr/share/fonts/truetype/nanum/NanumGothic.ttf",
153
- ]
154
-
155
- _SUPPORTED_READ_EXTENSIONS = {".pdf", ".docx", ".xlsx", ".pptx", ".txt", ".md", ".csv"}
156
- DOCUMENT_MAX_READ_BYTES = 10_000_000 # 10 MB
157
-
158
-
159
- # ── focused tool submodules (re-exported flat for import compatibility) ───────
160
- from tools.computer import * # noqa: E402,F401,F403
161
- from tools.filesystem import * # noqa: E402,F401,F403
162
- from tools.documents import * # noqa: E402,F401,F403
163
- from tools.local_files import * # noqa: E402,F401,F403
164
- from tools.knowledge import * # noqa: E402,F401,F403
165
- from tools.network import * # noqa: E402,F401,F403
166
- from tools.commands import * # noqa: E402,F401,F403
167
-
168
-
169
- # ── tool registry: the single name → invocation source of truth ───────────────
170
- def _h_create_xlsx(args: Dict[str, Any]) -> Dict[str, Any]:
171
- rows = args.get("rows", [])
172
- if isinstance(rows, str):
173
- rows = json.loads(rows)
174
- return create_xlsx(rows, args.get("filename", "spreadsheet.xlsx"), args.get("sheet_name", "Sheet1"))
175
-
176
-
177
- def _h_create_pptx(args: Dict[str, Any]) -> Dict[str, Any]:
178
- slides = args.get("slides", [])
179
- if isinstance(slides, str):
180
- slides = json.loads(slides)
181
- return create_pptx(args.get("title", ""), slides, args.get("filename", "presentation.pptx"))
182
-
183
-
184
- # ── Tool registry: the single source of truth for name → invocation ───────────
185
- # Each entry binds the args dict to a tool function. ``execute_tool`` is a
186
- # lookup over this table — adding a tool means adding one entry here, not
187
- # editing an if/elif chain. server.py's governance map and catalog brief are
188
- # checked against ``registered_tools()`` so the three never silently drift.
189
- TOOL_HANDLERS: Dict[str, Callable[[Dict[str, Any]], Dict[str, Any]]] = {
190
- # filesystem
191
- "list_dir": lambda a: list_dir(a.get("path", ".")),
192
- "workspace_tree": lambda a: workspace_tree(a.get("path", "."), a.get("max_depth", 3)),
193
- "read_file": lambda a: read_file(a["path"], offset=a.get("offset", 0), limit=a.get("limit", 0), line_numbers=a.get("line_numbers", True)),
194
- "write_file": lambda a: write_file(a["path"], a.get("content", "")),
195
- "edit_file": lambda a: edit_file(a["path"], a["old_string"], a["new_string"], replace_all=bool(a.get("replace_all", False))),
196
- "grep": lambda a: grep(a["pattern"], path=a.get("path", "."), glob=a.get("glob"), max_results=a.get("max_results", 50), case_insensitive=bool(a.get("case_insensitive", False)), context_lines=a.get("context_lines", 0)),
197
- "search_files": lambda a: search_files(a["query"], a.get("path", "."), a.get("max_results", 20)),
198
- "inspect_html": lambda a: inspect_html(a["path"]),
199
- "preview_url": lambda a: preview_url(a.get("path", "index.html")),
200
- # planning
201
- "todo_read": lambda a: todo_read(),
202
- "todo_write": lambda a: todo_write(a.get("todos") or []),
203
- # documents
204
- "create_docx": lambda a: create_docx(a.get("title", ""), a.get("body", ""), a.get("filename", "document.docx")),
205
- "create_xlsx": _h_create_xlsx,
206
- "create_pptx": _h_create_pptx,
207
- "create_pdf": lambda a: create_pdf(a.get("title", ""), a.get("body", ""), a.get("filename", "document.pdf")),
208
- "create_web_project": lambda a: create_web_project(a.get("path", ""), a.get("framework", "react"), a.get("template", "vite")),
209
- # local filesystem
210
- "local_list": lambda a: local_list(a["path"]),
211
- "local_read": lambda a: local_read(a["path"]),
212
- "local_write": lambda a: local_write(a["path"], a.get("content", "")),
213
- "read_document": lambda a: read_document(a["path"]),
214
- "network_status": lambda a: network_status(),
215
- # computer use
216
- "computer_screenshot": lambda a: computer_screenshot(),
217
- "computer_open_app": lambda a: computer_open_app(a.get("app", "Google Chrome")),
218
- "computer_open_url": lambda a: computer_open_url(a["url"], a.get("app", "Google Chrome")),
219
- "computer_click": lambda a: computer_click(a.get("x", 0), a.get("y", 0), a.get("button", "left"), a.get("double", False)),
220
- "computer_type": lambda a: computer_type(a["text"], a.get("interval", 0.04)),
221
- "computer_key": lambda a: computer_key(a["key"]),
222
- "computer_scroll": lambda a: computer_scroll(a.get("x", 0), a.get("y", 0), a.get("direction", "down"), a.get("clicks", 3)),
223
- "computer_move": lambda a: computer_move(a.get("x", 0), a.get("y", 0)),
224
- "computer_drag": lambda a: computer_drag(a.get("x1", 0), a.get("y1", 0), a.get("x2", 0), a.get("y2", 0)),
225
- "computer_status": lambda a: computer_status(),
226
- "chrome_status": lambda a: desktop_bridge_status(),
227
- "computer_use_status": lambda a: desktop_bridge_status(),
228
- "vision_analyze": lambda a: vision_analyze(a.get("image_b64", ""), a.get("prompt", "Describe this image in detail. Be concise.")),
229
- # knowledge / obsidian
230
- "knowledge_save": lambda a: knowledge_save(a["content"], a.get("folder", "00_Raw"), a.get("title")),
231
- "knowledge_search": lambda a: knowledge_search(a["query"], a.get("max_results", 5)),
232
- "knowledge_tree": lambda a: knowledge_tree(),
233
- "obsidian_save": lambda a: obsidian_save(a["content"], a.get("folder", "00_Raw"), a.get("title")),
234
- "obsidian_search": lambda a: obsidian_search(a["query"], a.get("max_results", 5)),
235
- "obsidian_tree": lambda a: obsidian_tree(),
236
- # git (read-only)
237
- "git_status": lambda a: git_status(a.get("cwd")),
238
- "git_diff": lambda a: git_diff(a.get("path"), a.get("cwd")),
239
- "git_log": lambda a: git_log(a.get("max_count", 5), a.get("cwd")),
240
- "git_show": lambda a: git_show(a.get("revision", "HEAD"), a.get("cwd")),
241
- # exec
242
- "run_command": lambda a: run_command(a["command"], a.get("cwd")),
243
- "build_project": lambda a: build_project(a.get("cwd"), a.get("script", "build")),
244
- "deploy_project": lambda a: deploy_project(a.get("cwd"), a.get("script", "deploy")),
245
- }
246
-
247
-
248
- DEFAULT_TOOL_REGISTRY = ToolRegistry(TOOL_HANDLERS)
249
-
8
+ from __future__ import annotations
250
9
 
251
- def registered_tools() -> frozenset:
252
- """Names dispatchable through ``execute_tool`` — the seam other modules verify against."""
253
- return DEFAULT_TOOL_REGISTRY.registered_tools()
10
+ import importlib
11
+ import sys
254
12
 
255
13
 
256
- def execute_tool(action: str, args: Dict[str, Any]) -> Dict[str, Any]:
257
- return DEFAULT_TOOL_REGISTRY.execute(action, args, error_cls=ToolError)
14
+ _IMPLEMENTATION = importlib.import_module("latticeai.tools")
258
15
 
16
+ for _submodule in (
17
+ "commands",
18
+ "computer",
19
+ "documents",
20
+ "filesystem",
21
+ "knowledge",
22
+ "local_files",
23
+ "network",
24
+ ):
25
+ sys.modules[f"{__name__}.{_submodule}"] = importlib.import_module(
26
+ f"latticeai.tools.{_submodule}"
27
+ )
259
28
 
260
- __all__ = [
261
- "AGENT_ROOT", "ToolError", "ensure_agent_root",
262
- "list_dir", "workspace_tree", "read_file", "write_file", "edit_file", "grep",
263
- "search_files", "inspect_html", "preview_url", "create_web_project",
264
- "todo_read", "todo_write",
265
- "create_docx", "create_xlsx", "create_pptx", "create_pdf", "read_document",
266
- "local_list", "local_read", "local_write", "desktop_bridge_status",
267
- "knowledge_save", "knowledge_search", "knowledge_tree",
268
- "obsidian_save", "obsidian_search", "obsidian_tree",
269
- "network_status",
270
- "computer_screenshot", "computer_open_app", "computer_open_url",
271
- "computer_click", "computer_type", "computer_key", "computer_scroll",
272
- "computer_move", "computer_drag", "computer_status", "vision_analyze",
273
- "run_command", "build_project", "deploy_project",
274
- "git_status", "git_diff", "git_log", "git_show",
275
- "TOOL_HANDLERS", "DEFAULT_TOOL_REGISTRY", "registered_tools", "execute_tool",
276
- "BRAIN_DIR", "STRUCTURE",
277
- ]
29
+ sys.modules[__name__] = _IMPLEMENTATION