ltcai 9.0.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 (187) hide show
  1. package/README.md +80 -46
  2. package/auto_setup.py +7 -853
  3. package/desktop/electron/README.md +9 -0
  4. package/desktop/electron/main.cjs +5 -3
  5. package/docs/CHANGELOG.md +146 -2
  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/TRUST_MODEL.md +5 -2
  13. package/docs/WHY_LATTICE.md +15 -10
  14. package/docs/WORKFLOW_DESIGNER.md +22 -0
  15. package/docs/kg-schema.md +13 -2
  16. package/docs/mcp-tools.md +17 -6
  17. package/docs/privacy.md +19 -3
  18. package/docs/public-deploy.md +32 -3
  19. package/docs/security-model.md +46 -11
  20. package/lattice_brain/__init__.py +1 -1
  21. package/lattice_brain/archive.py +1 -6
  22. package/lattice_brain/context.py +66 -9
  23. package/lattice_brain/graph/_kg_fsutil.py +1 -5
  24. package/lattice_brain/graph/discovery_index.py +174 -20
  25. package/lattice_brain/graph/documents.py +44 -9
  26. package/lattice_brain/graph/ingest.py +47 -20
  27. package/lattice_brain/graph/provenance.py +13 -6
  28. package/lattice_brain/graph/retrieval.py +140 -39
  29. package/lattice_brain/graph/retrieval_docgen.py +37 -4
  30. package/lattice_brain/ingestion.py +4 -7
  31. package/lattice_brain/portability.py +28 -14
  32. package/lattice_brain/runtime/agent_runtime.py +5 -9
  33. package/lattice_brain/runtime/hooks.py +30 -13
  34. package/lattice_brain/runtime/multi_agent.py +27 -8
  35. package/lattice_brain/runtime/statuses.py +10 -0
  36. package/lattice_brain/utils.py +20 -2
  37. package/lattice_brain/workflow.py +1 -5
  38. package/latticeai/__init__.py +1 -1
  39. package/latticeai/api/admin.py +1 -1
  40. package/latticeai/api/agent_registry.py +10 -8
  41. package/latticeai/api/agents.py +22 -3
  42. package/latticeai/api/auth.py +78 -16
  43. package/latticeai/api/browser.py +303 -34
  44. package/latticeai/api/chat.py +320 -850
  45. package/latticeai/api/chat_agent_http.py +356 -0
  46. package/latticeai/api/chat_contracts.py +54 -0
  47. package/latticeai/api/chat_documents.py +256 -0
  48. package/latticeai/api/chat_helpers.py +24 -1
  49. package/latticeai/api/chat_history.py +99 -0
  50. package/latticeai/api/chat_intents.py +302 -0
  51. package/latticeai/api/chat_stream.py +115 -0
  52. package/latticeai/api/computer_use.py +62 -9
  53. package/latticeai/api/health.py +9 -3
  54. package/latticeai/api/hooks.py +17 -6
  55. package/latticeai/api/knowledge_graph.py +78 -14
  56. package/latticeai/api/local_files.py +7 -2
  57. package/latticeai/api/mcp.py +102 -23
  58. package/latticeai/api/models.py +72 -33
  59. package/latticeai/api/network.py +5 -5
  60. package/latticeai/api/permissions.py +67 -26
  61. package/latticeai/api/plugins.py +21 -7
  62. package/latticeai/api/portability.py +5 -5
  63. package/latticeai/api/realtime.py +33 -5
  64. package/latticeai/api/setup.py +2 -2
  65. package/latticeai/api/static_routes.py +123 -24
  66. package/latticeai/api/tools.py +96 -14
  67. package/latticeai/api/workflow_designer.py +37 -0
  68. package/latticeai/api/workspace.py +2 -1
  69. package/latticeai/app_factory.py +110 -52
  70. package/latticeai/core/agent.py +19 -9
  71. package/latticeai/core/agent_registry.py +1 -5
  72. package/latticeai/core/config.py +23 -3
  73. package/latticeai/core/context_builder.py +21 -3
  74. package/latticeai/core/invitations.py +1 -4
  75. package/latticeai/core/io_utils.py +9 -1
  76. package/latticeai/core/legacy_compatibility.py +24 -3
  77. package/latticeai/core/marketplace.py +1 -1
  78. package/latticeai/core/plugins.py +15 -0
  79. package/latticeai/core/policy.py +1 -1
  80. package/latticeai/core/realtime.py +38 -15
  81. package/latticeai/core/sessions.py +7 -2
  82. package/latticeai/core/timeutil.py +10 -0
  83. package/latticeai/core/tool_registry.py +90 -18
  84. package/latticeai/core/users.py +1 -5
  85. package/latticeai/core/workspace_graph_trace.py +31 -5
  86. package/latticeai/core/workspace_memory.py +3 -1
  87. package/latticeai/core/workspace_os.py +18 -7
  88. package/latticeai/core/workspace_os_utils.py +0 -5
  89. package/latticeai/core/workspace_permissions.py +2 -1
  90. package/latticeai/core/workspace_plugins.py +1 -1
  91. package/latticeai/core/workspace_runs.py +14 -5
  92. package/latticeai/core/workspace_skills.py +1 -1
  93. package/latticeai/core/workspace_snapshots.py +2 -1
  94. package/latticeai/core/workspace_timeline.py +2 -1
  95. package/latticeai/integrations/telegram_bot.py +94 -43
  96. package/latticeai/models/router.py +130 -36
  97. package/latticeai/runtime/access_runtime.py +62 -4
  98. package/latticeai/runtime/automation_runtime.py +13 -7
  99. package/latticeai/runtime/brain_runtime.py +19 -7
  100. package/latticeai/runtime/chat_wiring.py +2 -0
  101. package/latticeai/runtime/config_runtime.py +58 -26
  102. package/latticeai/runtime/context_runtime.py +16 -4
  103. package/latticeai/runtime/hooks_runtime.py +1 -1
  104. package/latticeai/runtime/model_wiring.py +33 -5
  105. package/latticeai/runtime/namespace_runtime.py +62 -72
  106. package/latticeai/runtime/platform_runtime_wiring.py +4 -3
  107. package/latticeai/runtime/review_wiring.py +1 -1
  108. package/latticeai/runtime/router_registration.py +34 -1
  109. package/latticeai/runtime/security_runtime.py +110 -13
  110. package/latticeai/runtime/stages.py +27 -0
  111. package/latticeai/server_app.py +5 -1
  112. package/latticeai/services/architecture_readiness.py +74 -5
  113. package/latticeai/services/brain_automation.py +3 -26
  114. package/latticeai/services/chat_service.py +205 -15
  115. package/latticeai/services/local_knowledge.py +423 -0
  116. package/latticeai/services/memory_service.py +55 -21
  117. package/latticeai/services/model_engines.py +48 -33
  118. package/latticeai/services/model_errors.py +17 -0
  119. package/latticeai/services/model_loading.py +28 -25
  120. package/latticeai/services/model_runtime.py +228 -162
  121. package/latticeai/services/p_reinforce.py +22 -3
  122. package/latticeai/services/platform_runtime.py +83 -23
  123. package/latticeai/services/product_readiness.py +19 -17
  124. package/latticeai/services/review_queue.py +12 -0
  125. package/latticeai/services/router_context.py +1 -0
  126. package/latticeai/services/run_executor.py +4 -9
  127. package/latticeai/services/search_service.py +203 -28
  128. package/latticeai/services/tool_dispatch.py +28 -5
  129. package/latticeai/services/triggers.py +53 -4
  130. package/latticeai/services/upload_service.py +13 -2
  131. package/latticeai/setup/__init__.py +25 -0
  132. package/latticeai/setup/auto_setup.py +857 -0
  133. package/latticeai/setup/wizard.py +1264 -0
  134. package/latticeai/tools/__init__.py +278 -0
  135. package/{tools → latticeai/tools}/commands.py +67 -7
  136. package/{tools → latticeai/tools}/computer.py +1 -1
  137. package/{tools → latticeai/tools}/documents.py +1 -1
  138. package/{tools → latticeai/tools}/filesystem.py +3 -3
  139. package/latticeai/tools/knowledge.py +178 -0
  140. package/{tools → latticeai/tools}/local_files.py +1 -1
  141. package/{tools → latticeai/tools}/network.py +0 -1
  142. package/local_knowledge_api.py +4 -342
  143. package/package.json +22 -2
  144. package/scripts/brain_quality_eval.py +3 -1
  145. package/scripts/bump_version.py +3 -0
  146. package/scripts/capture_release_evidence.mjs +180 -0
  147. package/scripts/check_current_release_docs.mjs +142 -0
  148. package/scripts/check_i18n_literals.mjs +107 -31
  149. package/scripts/check_openapi_drift.mjs +56 -0
  150. package/scripts/export_openapi.py +67 -7
  151. package/scripts/i18n_literal_allowlist.json +22 -24
  152. package/scripts/run_integration_tests.mjs +72 -10
  153. package/scripts/validate_release_artifacts.py +49 -7
  154. package/scripts/wheel_smoke.py +5 -0
  155. package/setup_wizard.py +3 -1260
  156. package/src-tauri/Cargo.lock +1 -1
  157. package/src-tauri/Cargo.toml +1 -1
  158. package/src-tauri/tauri.conf.json +1 -1
  159. package/static/app/asset-manifest.json +11 -11
  160. package/static/app/assets/Act-Bzz0bUyW.js +1 -0
  161. package/static/app/assets/Brain-Dj2J20YA.js +321 -0
  162. package/static/app/assets/Capture-CqlEl1Ga.js +1 -0
  163. package/static/app/assets/Library-B03FP1Yx.js +1 -0
  164. package/static/app/assets/System-80lHW0Ux.js +1 -0
  165. package/static/app/assets/index-BiMofBTM.js +17 -0
  166. package/static/app/assets/index-Bmx9rzTc.css +2 -0
  167. package/static/app/assets/primitives-Q1A96_7v.js +1 -0
  168. package/static/app/assets/textarea-D13RtnTo.js +1 -0
  169. package/static/app/index.html +2 -2
  170. package/static/sw.js +1 -1
  171. package/tools/__init__.py +21 -269
  172. package/docs/CODE_REVIEW_2026-07-06.md +0 -764
  173. package/latticeai/runtime/app_context_runtime.py +0 -13
  174. package/latticeai/runtime/tail_wiring.py +0 -21
  175. package/scripts/com.pts.claudecode.discord.plist +0 -31
  176. package/scripts/pts-claudecode-discord-bridge.mjs +0 -207
  177. package/scripts/start-pts-claudecode-discord.sh +0 -51
  178. package/static/app/assets/Act-21lIXx2E.js +0 -1
  179. package/static/app/assets/Brain-BqUd5UJJ.js +0 -321
  180. package/static/app/assets/Capture-BA7Z2Q1u.js +0 -1
  181. package/static/app/assets/Library-bFMtyni3.js +0 -1
  182. package/static/app/assets/System-K6krGCqn.js +0 -1
  183. package/static/app/assets/index-C4R3ws30.js +0 -17
  184. package/static/app/assets/index-ChSeOB02.css +0 -2
  185. package/static/app/assets/primitives-sQU3it5I.js +0 -1
  186. package/static/app/assets/textarea-DK3Fd_lR.js +0 -1
  187. 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-C4R3ws30.js"></script>
12
- <link rel="stylesheet" crossorigin href="/static/app/assets/index-ChSeOB02.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>
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-v900";
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