ltcai 11.5.2 → 11.6.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 (439) hide show
  1. package/README.md +91 -148
  2. package/bin/ltcai.js +234 -24
  3. package/docs/CHANGELOG.md +75 -0
  4. package/docs/COMMUNITY_AND_PLUGINS.md +1 -1
  5. package/docs/DEVELOPMENT.md +8 -6
  6. package/docs/ENTERPRISE.md +2 -1
  7. package/docs/MULTI_AGENT_RUNTIME.md +12 -5
  8. package/docs/ONBOARDING.md +1 -1
  9. package/docs/OPERATIONS.md +6 -3
  10. package/docs/REALTIME_COLLABORATION.md +1 -1
  11. package/docs/TRUST_MODEL.md +1 -1
  12. package/docs/WHY_LATTICE.md +1 -1
  13. package/docs/WORKFLOW_DESIGNER.md +3 -2
  14. package/docs/kg-schema.md +1 -1
  15. package/docs/v11.6.0_ONE_DOOR_PLAN.md +170 -0
  16. package/lattice_brain/__init__.py +42 -79
  17. package/lattice_brain/graph/__init__.py +9 -24
  18. package/lattice_brain/graph/_kg_common/__init__.py +13 -24
  19. package/lattice_brain/ingestion/__init__.py +19 -58
  20. package/lattice_brain/ingestion/pipeline.py +20 -398
  21. package/lattice_brain/multimodal/__init__.py +7 -18
  22. package/lattice_brain/multimodal/images.py +6 -264
  23. package/lattice_brain/multimodal/video.py +8 -247
  24. package/lattice_brain/runtime/__init__.py +8 -79
  25. package/lattice_brain/runtime/hooks.py +22 -584
  26. package/latticeai/__init__.py +1 -1
  27. package/latticeai/api/agent_worker_seam.py +7 -80
  28. package/latticeai/api/health.py +6 -20
  29. package/latticeai/api/local_files.py +16 -613
  30. package/latticeai/api/models.py +12 -87
  31. package/latticeai/api/search.py +17 -255
  32. package/latticeai/api/tools.py +69 -750
  33. package/latticeai/api/voice_capture.py +8 -70
  34. package/latticeai/api/worker_compute.py +842 -0
  35. package/latticeai/api/worker_seams.py +216 -0
  36. package/latticeai/app_factory.py +23 -232
  37. package/latticeai/cli/entrypoint.py +36 -249
  38. package/latticeai/core/agent_permission.py +16 -91
  39. package/latticeai/core/messages.py +89 -531
  40. package/latticeai/runtime/access_runtime.py +0 -14
  41. package/latticeai/runtime/bootstrap.py +10 -21
  42. package/latticeai/runtime/brain_runtime.py +35 -43
  43. package/latticeai/runtime/build_phases/__init__.py +21 -37
  44. package/latticeai/runtime/build_phases/features.py +99 -389
  45. package/latticeai/runtime/build_phases/foundation.py +82 -392
  46. package/latticeai/runtime/build_phases/web.py +91 -408
  47. package/latticeai/runtime/build_phases/worker_profile.py +244 -0
  48. package/latticeai/runtime/lifespan_runtime.py +7 -16
  49. package/latticeai/runtime/platform_services_runtime.py +1 -15
  50. package/latticeai/runtime/runtime_context.py +13 -130
  51. package/latticeai/runtime/security_runtime.py +10 -103
  52. package/latticeai/services/architecture_readiness.py +82 -43
  53. package/latticeai/services/model_runtime/__init__.py +2 -11
  54. package/latticeai/services/model_runtime/service.py +4 -28
  55. package/latticeai/services/p_reinforce.py +10 -261
  56. package/latticeai/services/product_readiness.py +31 -38
  57. package/latticeai/services/search_service.py +37 -795
  58. package/latticeai/services/tool_dispatch.py +30 -386
  59. package/latticeai/services/voice_capture.py +13 -107
  60. package/latticeai/tools/__init__.py +22 -49
  61. package/latticeai/tools/commands.py +0 -163
  62. package/latticeai/tools/computer.py +0 -39
  63. package/latticeai/tools/documents.py +1 -134
  64. package/latticeai/tools/filesystem.py +1 -247
  65. package/latticeai/tools/knowledge.py +1 -52
  66. package/latticeai/tools/local_files.py +0 -20
  67. package/latticeai/worker_app.py +75 -0
  68. package/package.json +2 -3
  69. package/requirements.txt +0 -5
  70. package/scripts/agent_eval.py +16 -28
  71. package/scripts/brain_quality_eval.py +20 -183
  72. package/scripts/bump_version.py +5 -5
  73. package/scripts/check_current_release_docs.mjs +7 -4
  74. package/scripts/check_openapi_drift.mjs +10 -0
  75. package/scripts/check_server_i18n.mjs +2 -18
  76. package/scripts/compose_openapi.py +377 -0
  77. package/scripts/export_openapi.py +32 -4
  78. package/scripts/gen_messages_catalog_fixture.py +302 -0
  79. package/scripts/gen_openapi_fragments.py +365 -0
  80. package/scripts/gen_redact_fixture.py +196 -0
  81. package/scripts/gen_worker_allowlist_fixture.py +115 -0
  82. package/scripts/generate_agent_parity_fixtures.py +33 -14
  83. package/scripts/openapi_route_families.json +2161 -0
  84. package/scripts/release_screen_claims.json +21 -0
  85. package/scripts/run_integration_tests.mjs +134 -29
  86. package/scripts/run_sidecar_e2e.mjs +104 -11
  87. package/scripts/wheel_smoke.py +32 -22
  88. package/src-tauri/Cargo.lock +375 -9
  89. package/src-tauri/Cargo.toml +1 -1
  90. package/src-tauri/src/backend.rs +151 -45
  91. package/src-tauri/src/main.rs +18 -18
  92. package/src-tauri/src/topology.rs +58 -88
  93. package/src-tauri/tauri.conf.json +1 -2
  94. package/static/app/asset-manifest.json +41 -41
  95. package/static/app/assets/{Act-DcQizkl1.js → Act-CToZnOHz.js} +1 -1
  96. package/static/app/assets/{AdminConsole-cf4npybT.js → AdminConsole-D5kbrBu8.js} +1 -1
  97. package/static/app/assets/{Brain-3VCSHFcn.js → Brain-C6zCdv4S.js} +1 -1
  98. package/static/app/assets/{BrainHome-Qm8eaztx.js → BrainHome-D4n3EDUt.js} +1 -1
  99. package/static/app/assets/{BrainSignals-DS9BtKOW.js → BrainSignals-CzeZ-vQ9.js} +1 -1
  100. package/static/app/assets/{Capture-DiQ219jW.js → Capture-DPcyTczq.js} +1 -1
  101. package/static/app/assets/{Chronicle-BGvuAchH.js → Chronicle-D3Nx-oWS.js} +1 -1
  102. package/static/app/assets/{CommandPalette-Bqhm0Urn.js → CommandPalette-DPPvpp28.js} +1 -1
  103. package/static/app/assets/{Library-BV6NnF0a.js → Library-Co2qTu3I.js} +1 -1
  104. package/static/app/assets/{LivingBrain-GzenJchP.js → LivingBrain-Bsmzwy8_.js} +1 -1
  105. package/static/app/assets/{ProductFlow-DEP6-vML.js → ProductFlow-CBLdmesT.js} +1 -1
  106. package/static/app/assets/{ReviewCard-CNZ7XjWG.js → ReviewCard-CfR6DLs7.js} +1 -1
  107. package/static/app/assets/{System-CieofHQa.js → System-Ce-P2YL6.js} +1 -1
  108. package/static/app/assets/arrow-left-DD5jFGHV.js +1 -0
  109. package/static/app/assets/{bot-B_K1Tdmw.js → bot-C5-XIww2.js} +1 -1
  110. package/static/app/assets/{brain-DWyaV1L1.js → brain-CFRJUvdX.js} +1 -1
  111. package/static/app/assets/{button-aTn4s84A.js → button-DI1KcQP-.js} +1 -1
  112. package/static/app/assets/circle-check-CY20XMCh.js +1 -0
  113. package/static/app/assets/{circle-pause-xKgeGXkT.js → circle-pause-C8HHyood.js} +1 -1
  114. package/static/app/assets/{circle-play-DkT6tYPX.js → circle-play-Cufc235E.js} +1 -1
  115. package/static/app/assets/{cpu-85xYObUC.js → cpu-DW2_JVsv.js} +1 -1
  116. package/static/app/assets/{download-B5Fm7YXo.js → download-gbdKTBb8.js} +1 -1
  117. package/static/app/assets/{folder-open-kk2Xa52u.js → folder-open-C9ydyX33.js} +1 -1
  118. package/static/app/assets/{hard-drive-DkA3zBW_.js → hard-drive-BxNMzBM3.js} +1 -1
  119. package/static/app/assets/index-BovSWRmQ.css +2 -0
  120. package/static/app/assets/{index-BMPdTmlY.js → index-q9XyDY7A.js} +3 -3
  121. package/static/app/assets/{input-B0nRf2jO.js → input-GLD94Y_K.js} +1 -1
  122. package/static/app/assets/{link-2-Dwb4gnTc.js → link-2-B4Y0gz1S.js} +1 -1
  123. package/static/app/assets/{permissionCopy-CQDUBrOZ.js → permissionCopy-CxrV0fvU.js} +1 -1
  124. package/static/app/assets/{primitives-SNp0LRJz.js → primitives-2ANdAsu2.js} +1 -1
  125. package/static/app/assets/search-DTxtjQ07.js +1 -0
  126. package/static/app/assets/{share-2-BsrxFglO.js → share-2-DxArfiuI.js} +1 -1
  127. package/static/app/assets/{shield-alert-5BStfp2_.js → shield-alert-CgftuFFs.js} +1 -1
  128. package/static/app/assets/{textarea-Cg8IUA-k.js → textarea-BHVBAoCr.js} +1 -1
  129. package/static/app/assets/{useFocusTrap-CYKvE46M.js → useFocusTrap-Dzq2j_OG.js} +1 -1
  130. package/static/app/assets/{useMutation-CSn9t1op.js → useMutation-BcqfMLNq.js} +1 -1
  131. package/static/app/assets/{useQuery-CY2OI2uy.js → useQuery-DBzLKCOv.js} +1 -1
  132. package/static/app/assets/{utils-Ddol2RWD.js → utils-B-Aah1bO.js} +1 -1
  133. package/static/app/assets/{workspace-BqDwOz_p.js → workspace-B6fFhoko.js} +1 -1
  134. package/static/app/index.html +4 -4
  135. package/static/sw.js +1 -1
  136. package/lattice_brain/archive.py +0 -522
  137. package/lattice_brain/context.py +0 -325
  138. package/lattice_brain/conversations.py +0 -382
  139. package/lattice_brain/core.py +0 -82
  140. package/lattice_brain/graph/_kg_contract.py +0 -249
  141. package/lattice_brain/graph/curator.py +0 -676
  142. package/lattice_brain/graph/discovery.py +0 -595
  143. package/lattice_brain/graph/discovery_index/__init__.py +0 -35
  144. package/lattice_brain/graph/discovery_index/cleanup.py +0 -182
  145. package/lattice_brain/graph/discovery_index/extract.py +0 -137
  146. package/lattice_brain/graph/discovery_index/scan.py +0 -411
  147. package/lattice_brain/graph/discovery_index/upsert.py +0 -495
  148. package/lattice_brain/graph/documents.py +0 -380
  149. package/lattice_brain/graph/fusion.py +0 -395
  150. package/lattice_brain/graph/identity.py +0 -175
  151. package/lattice_brain/graph/image_vectors.py +0 -230
  152. package/lattice_brain/graph/ingest.py +0 -829
  153. package/lattice_brain/graph/network.py +0 -205
  154. package/lattice_brain/graph/proactive.py +0 -724
  155. package/lattice_brain/graph/projection/__init__.py +0 -42
  156. package/lattice_brain/graph/projection/curation.py +0 -500
  157. package/lattice_brain/graph/projection/v2_schema.py +0 -518
  158. package/lattice_brain/graph/provenance.py +0 -524
  159. package/lattice_brain/graph/rerank.py +0 -163
  160. package/lattice_brain/graph/retrieval/__init__.py +0 -54
  161. package/lattice_brain/graph/retrieval/context.py +0 -197
  162. package/lattice_brain/graph/retrieval/graph_view.py +0 -319
  163. package/lattice_brain/graph/retrieval/hybrid.py +0 -488
  164. package/lattice_brain/graph/retrieval/maintenance.py +0 -121
  165. package/lattice_brain/graph/retrieval/signals.py +0 -95
  166. package/lattice_brain/graph/retrieval_docgen.py +0 -253
  167. package/lattice_brain/graph/retrieval_policy.py +0 -180
  168. package/lattice_brain/graph/retrieval_reads.py +0 -769
  169. package/lattice_brain/graph/retrieval_vector/__init__.py +0 -42
  170. package/lattice_brain/graph/retrieval_vector/fingerprint.py +0 -97
  171. package/lattice_brain/graph/retrieval_vector/indexing.py +0 -347
  172. package/lattice_brain/graph/retrieval_vector/search.py +0 -560
  173. package/lattice_brain/graph/retrieval_vector/status.py +0 -374
  174. package/lattice_brain/graph/schema.py +0 -792
  175. package/lattice_brain/graph/store.py +0 -268
  176. package/lattice_brain/graph/vector_index/__init__.py +0 -85
  177. package/lattice_brain/graph/vector_index/base.py +0 -167
  178. package/lattice_brain/graph/vector_index/brute_force.py +0 -110
  179. package/lattice_brain/graph/vector_index/hnsw.py +0 -290
  180. package/lattice_brain/graph/vector_index/jobs.py +0 -287
  181. package/lattice_brain/graph/vector_index/quantized.py +0 -148
  182. package/lattice_brain/graph/vector_index/selector.py +0 -161
  183. package/lattice_brain/graph/write_master.py +0 -308
  184. package/lattice_brain/ingestion/_contract.py +0 -90
  185. package/lattice_brain/ingestion/folder_scan.py +0 -57
  186. package/lattice_brain/ingestion/folders.py +0 -258
  187. package/lattice_brain/ingestion/jobs_api.py +0 -107
  188. package/lattice_brain/ingestion/routing.py +0 -295
  189. package/lattice_brain/ingestion_jobs.py +0 -380
  190. package/lattice_brain/memory.py +0 -75
  191. package/lattice_brain/portability/__init__.py +0 -90
  192. package/lattice_brain/portability/_contract.py +0 -42
  193. package/lattice_brain/portability/backups.py +0 -338
  194. package/lattice_brain/portability/bundles.py +0 -136
  195. package/lattice_brain/portability/constants.py +0 -93
  196. package/lattice_brain/portability/fsops.py +0 -138
  197. package/lattice_brain/portability/service.py +0 -41
  198. package/lattice_brain/portability/sharing.py +0 -710
  199. package/lattice_brain/quality.py +0 -543
  200. package/lattice_brain/retrieval_benchmark_fixtures.py +0 -92
  201. package/lattice_brain/runtime/agent_runtime.py +0 -859
  202. package/lattice_brain/runtime/contracts.py +0 -460
  203. package/lattice_brain/runtime/multi_agent.py +0 -942
  204. package/lattice_brain/runtime/statuses.py +0 -10
  205. package/lattice_brain/sealed_box.py +0 -240
  206. package/lattice_brain/self_model.py +0 -675
  207. package/lattice_brain/sensitivity.py +0 -94
  208. package/lattice_brain/storage/__init__.py +0 -22
  209. package/lattice_brain/storage/base.py +0 -100
  210. package/lattice_brain/storage/docker.py +0 -105
  211. package/lattice_brain/storage/factory.py +0 -31
  212. package/lattice_brain/storage/migration.py +0 -191
  213. package/lattice_brain/storage/postgres.py +0 -123
  214. package/lattice_brain/storage/sqlite.py +0 -143
  215. package/lattice_brain/synthesis.py +0 -824
  216. package/lattice_brain/workflow.py +0 -497
  217. package/latticeai/api/admin.py +0 -471
  218. package/latticeai/api/agent_registry.py +0 -105
  219. package/latticeai/api/agents.py +0 -228
  220. package/latticeai/api/auth.py +0 -383
  221. package/latticeai/api/automation_intelligence.py +0 -401
  222. package/latticeai/api/brain_intelligence.py +0 -199
  223. package/latticeai/api/browser.py +0 -493
  224. package/latticeai/api/change_proposals.py +0 -89
  225. package/latticeai/api/chat.py +0 -572
  226. package/latticeai/api/chat_agent_http.py +0 -892
  227. package/latticeai/api/chat_contracts.py +0 -73
  228. package/latticeai/api/chat_documents.py +0 -276
  229. package/latticeai/api/chat_helpers.py +0 -460
  230. package/latticeai/api/chat_history.py +0 -101
  231. package/latticeai/api/chat_hybrid.py +0 -113
  232. package/latticeai/api/chat_intents.py +0 -646
  233. package/latticeai/api/chat_stream.py +0 -216
  234. package/latticeai/api/chronicle.py +0 -63
  235. package/latticeai/api/command_center.py +0 -51
  236. package/latticeai/api/computer_use.py +0 -474
  237. package/latticeai/api/evidence_actions.py +0 -48
  238. package/latticeai/api/features.py +0 -70
  239. package/latticeai/api/funnel_metrics.py +0 -31
  240. package/latticeai/api/garden.py +0 -34
  241. package/latticeai/api/hooks.py +0 -165
  242. package/latticeai/api/index_jobs.py +0 -145
  243. package/latticeai/api/invitations.py +0 -100
  244. package/latticeai/api/knowledge_graph.py +0 -536
  245. package/latticeai/api/marketplace.py +0 -105
  246. package/latticeai/api/mcp.py +0 -482
  247. package/latticeai/api/memory.py +0 -270
  248. package/latticeai/api/network.py +0 -81
  249. package/latticeai/api/network_boundary.py +0 -225
  250. package/latticeai/api/permission_mode.py +0 -61
  251. package/latticeai/api/permissions.py +0 -436
  252. package/latticeai/api/plugins.py +0 -126
  253. package/latticeai/api/portability.py +0 -391
  254. package/latticeai/api/project_sessions.py +0 -114
  255. package/latticeai/api/realtime.py +0 -118
  256. package/latticeai/api/review_queue.py +0 -364
  257. package/latticeai/api/security_dashboard.py +0 -604
  258. package/latticeai/api/setup.py +0 -319
  259. package/latticeai/api/static_routes.py +0 -354
  260. package/latticeai/api/ui_redirects.py +0 -26
  261. package/latticeai/api/workflow_designer.py +0 -394
  262. package/latticeai/api/workspace.py +0 -856
  263. package/latticeai/api/workspace_scope.py +0 -125
  264. package/latticeai/core/agent/__init__.py +0 -93
  265. package/latticeai/core/agent/_contract.py +0 -79
  266. package/latticeai/core/agent/context.py +0 -57
  267. package/latticeai/core/agent/deps.py +0 -125
  268. package/latticeai/core/agent/execution.py +0 -622
  269. package/latticeai/core/agent/planning.py +0 -145
  270. package/latticeai/core/agent/recovery.py +0 -157
  271. package/latticeai/core/agent/runtime.py +0 -210
  272. package/latticeai/core/agent/verification.py +0 -231
  273. package/latticeai/core/agent_eval.py +0 -739
  274. package/latticeai/core/agent_helpers.py +0 -493
  275. package/latticeai/core/agent_profiles.py +0 -110
  276. package/latticeai/core/agent_prompts.py +0 -171
  277. package/latticeai/core/agent_registry.py +0 -232
  278. package/latticeai/core/agent_state.py +0 -41
  279. package/latticeai/core/agent_trace.py +0 -104
  280. package/latticeai/core/artifact_ledger.py +0 -109
  281. package/latticeai/core/audit.py +0 -260
  282. package/latticeai/core/builtin_hooks.py +0 -105
  283. package/latticeai/core/context_builder.py +0 -394
  284. package/latticeai/core/document_generator.py +0 -103
  285. package/latticeai/core/enterprise.py +0 -154
  286. package/latticeai/core/enterprise_admin.py +0 -158
  287. package/latticeai/core/file_generation/__init__.py +0 -115
  288. package/latticeai/core/file_generation/bundles.py +0 -76
  289. package/latticeai/core/file_generation/extraction.py +0 -154
  290. package/latticeai/core/file_generation/inference.py +0 -235
  291. package/latticeai/core/file_generation/orchestration.py +0 -152
  292. package/latticeai/core/file_generation/prompting.py +0 -117
  293. package/latticeai/core/file_generation/repair.py +0 -114
  294. package/latticeai/core/file_generation/sanitize.py +0 -61
  295. package/latticeai/core/file_generation/validation.py +0 -201
  296. package/latticeai/core/invitations.py +0 -132
  297. package/latticeai/core/legacy_compatibility.py +0 -243
  298. package/latticeai/core/logging_safety.py +0 -46
  299. package/latticeai/core/marketplace.py +0 -293
  300. package/latticeai/core/mcp_catalog.py +0 -452
  301. package/latticeai/core/mcp_registry.py +0 -506
  302. package/latticeai/core/network_boundary.py +0 -168
  303. package/latticeai/core/oidc.py +0 -208
  304. package/latticeai/core/plugins.py +0 -432
  305. package/latticeai/core/product_hardening.py +0 -218
  306. package/latticeai/core/project_sessions.py +0 -337
  307. package/latticeai/core/realtime.py +0 -238
  308. package/latticeai/core/run_explain.py +0 -426
  309. package/latticeai/core/run_store.py +0 -252
  310. package/latticeai/core/timezones.py +0 -80
  311. package/latticeai/core/workspace_computer_memory.py +0 -84
  312. package/latticeai/core/workspace_graph_trace.py +0 -155
  313. package/latticeai/core/workspace_indexing.py +0 -102
  314. package/latticeai/core/workspace_memory.py +0 -77
  315. package/latticeai/core/workspace_onboarding.py +0 -104
  316. package/latticeai/core/workspace_os.py +0 -978
  317. package/latticeai/core/workspace_os_constants.py +0 -126
  318. package/latticeai/core/workspace_os_state.py +0 -180
  319. package/latticeai/core/workspace_os_utils.py +0 -103
  320. package/latticeai/core/workspace_permissions.py +0 -101
  321. package/latticeai/core/workspace_plugins.py +0 -97
  322. package/latticeai/core/workspace_relationships.py +0 -99
  323. package/latticeai/core/workspace_reorganization.py +0 -335
  324. package/latticeai/core/workspace_review_items.py +0 -112
  325. package/latticeai/core/workspace_runs.py +0 -726
  326. package/latticeai/core/workspace_skills.py +0 -109
  327. package/latticeai/core/workspace_snapshots.py +0 -198
  328. package/latticeai/core/workspace_timeline.py +0 -110
  329. package/latticeai/integrations/__init__.py +0 -0
  330. package/latticeai/integrations/telegram_bot/__init__.py +0 -123
  331. package/latticeai/integrations/telegram_bot/__main__.py +0 -17
  332. package/latticeai/integrations/telegram_bot/config.py +0 -86
  333. package/latticeai/integrations/telegram_bot/dispatch.py +0 -311
  334. package/latticeai/integrations/telegram_bot/flows.py +0 -478
  335. package/latticeai/integrations/telegram_bot/helpers.py +0 -322
  336. package/latticeai/integrations/telegram_bot/screens.py +0 -394
  337. package/latticeai/runtime/audit_runtime.py +0 -76
  338. package/latticeai/runtime/automation_runtime.py +0 -81
  339. package/latticeai/runtime/chat_wiring.py +0 -141
  340. package/latticeai/runtime/context_runtime.py +0 -66
  341. package/latticeai/runtime/feature_toggle_wiring.py +0 -157
  342. package/latticeai/runtime/history_runtime.py +0 -163
  343. package/latticeai/runtime/history_writer.py +0 -138
  344. package/latticeai/runtime/hooks_runtime.py +0 -77
  345. package/latticeai/runtime/model_wiring.py +0 -68
  346. package/latticeai/runtime/namespace_runtime.py +0 -163
  347. package/latticeai/runtime/network_boundary_wiring.py +0 -117
  348. package/latticeai/runtime/network_config_runtime.py +0 -56
  349. package/latticeai/runtime/permission_mode_wiring.py +0 -112
  350. package/latticeai/runtime/persistence_runtime.py +0 -159
  351. package/latticeai/runtime/platform_runtime_wiring.py +0 -89
  352. package/latticeai/runtime/review_wiring.py +0 -42
  353. package/latticeai/runtime/router_registration.py +0 -693
  354. package/latticeai/runtime/service_singletons.py +0 -55
  355. package/latticeai/runtime/sso_config_runtime.py +0 -128
  356. package/latticeai/runtime/user_key_runtime.py +0 -106
  357. package/latticeai/runtime/web_runtime.py +0 -92
  358. package/latticeai/server_app.py +0 -51
  359. package/latticeai/services/app_context.py +0 -130
  360. package/latticeai/services/automation_execution.py +0 -266
  361. package/latticeai/services/automation_intelligence.py +0 -614
  362. package/latticeai/services/brain_automation.py +0 -191
  363. package/latticeai/services/brain_intelligence/__init__.py +0 -58
  364. package/latticeai/services/brain_intelligence/_contract.py +0 -71
  365. package/latticeai/services/brain_intelligence/consistency.py +0 -193
  366. package/latticeai/services/brain_intelligence/constants.py +0 -47
  367. package/latticeai/services/brain_intelligence/digest.py +0 -258
  368. package/latticeai/services/brain_intelligence/health.py +0 -331
  369. package/latticeai/services/brain_intelligence/proposals.py +0 -259
  370. package/latticeai/services/brain_intelligence/sampling.py +0 -84
  371. package/latticeai/services/brain_intelligence/service.py +0 -48
  372. package/latticeai/services/change_proposals.py +0 -471
  373. package/latticeai/services/chat_service.py +0 -243
  374. package/latticeai/services/chronicle.py +0 -555
  375. package/latticeai/services/cloud_egress_audit.py +0 -85
  376. package/latticeai/services/cloud_extraction.py +0 -129
  377. package/latticeai/services/cloud_streaming.py +0 -268
  378. package/latticeai/services/cloud_token_guard.py +0 -84
  379. package/latticeai/services/command_center.py +0 -548
  380. package/latticeai/services/evidence_actions.py +0 -258
  381. package/latticeai/services/feature_toggles.py +0 -502
  382. package/latticeai/services/folder_watch.py +0 -520
  383. package/latticeai/services/funnel_metrics.py +0 -307
  384. package/latticeai/services/hybrid_chat.py +0 -316
  385. package/latticeai/services/hybrid_context.py +0 -228
  386. package/latticeai/services/hybrid_policy.py +0 -129
  387. package/latticeai/services/interop_bridges.py +0 -978
  388. package/latticeai/services/local_knowledge.py +0 -465
  389. package/latticeai/services/memory_service/__init__.py +0 -52
  390. package/latticeai/services/memory_service/_contract.py +0 -100
  391. package/latticeai/services/memory_service/brief.py +0 -431
  392. package/latticeai/services/memory_service/constants.py +0 -57
  393. package/latticeai/services/memory_service/maintenance.py +0 -138
  394. package/latticeai/services/memory_service/manager.py +0 -186
  395. package/latticeai/services/memory_service/proof.py +0 -136
  396. package/latticeai/services/memory_service/recall.py +0 -225
  397. package/latticeai/services/memory_service/service.py +0 -48
  398. package/latticeai/services/memory_service/stores.py +0 -110
  399. package/latticeai/services/mode_store.py +0 -132
  400. package/latticeai/services/model_recommendation.py +0 -224
  401. package/latticeai/services/model_runtime/cloud.py +0 -87
  402. package/latticeai/services/network_boundary_service.py +0 -117
  403. package/latticeai/services/obsidian_bridge.py +0 -609
  404. package/latticeai/services/openai_compatible_adapter.py +0 -101
  405. package/latticeai/services/permission_mode_service.py +0 -122
  406. package/latticeai/services/platform_runtime.py +0 -366
  407. package/latticeai/services/review_queue.py +0 -380
  408. package/latticeai/services/router_context.py +0 -59
  409. package/latticeai/services/run_executor.py +0 -387
  410. package/latticeai/services/self_model_service.py +0 -171
  411. package/latticeai/services/setup_detection.py +0 -147
  412. package/latticeai/services/triggers.py +0 -378
  413. package/latticeai/services/upload_service.py +0 -172
  414. package/latticeai/services/workspace_service.py +0 -165
  415. package/latticeai/setup/__init__.py +0 -25
  416. package/latticeai/setup/auto_setup.py +0 -846
  417. package/latticeai/setup/demo_corpus.py +0 -98
  418. package/latticeai/setup/wizard/__init__.py +0 -126
  419. package/latticeai/setup/wizard/catalog.py +0 -175
  420. package/latticeai/setup/wizard/detect.py +0 -302
  421. package/latticeai/setup/wizard/install.py +0 -348
  422. package/latticeai/setup/wizard/paths.py +0 -165
  423. package/latticeai/setup/wizard/plans.py +0 -74
  424. package/latticeai/setup/wizard/recommend.py +0 -320
  425. package/scripts/bench_agent_smoke.py +0 -409
  426. package/scripts/bench_models.py +0 -540
  427. package/scripts/bench_vector_index.py +0 -295
  428. package/scripts/funnel_soft_gate.py +0 -192
  429. package/scripts/generate_agent_loop_fixtures.py +0 -994
  430. package/scripts/generate_rust_parity_fixtures.py +0 -908
  431. package/scripts/migrate_brain_storage.py +0 -57
  432. package/scripts/parity_fixture_corpus_context.py +0 -162
  433. package/scripts/parity_fixture_corpus_docgen.py +0 -341
  434. package/scripts/profile_kg.py +0 -355
  435. package/server.py +0 -30
  436. package/static/app/assets/arrow-left-kfsrk0mv.js +0 -1
  437. package/static/app/assets/circle-check-qqLug9nU.js +0 -1
  438. package/static/app/assets/index-DxmOfNRi.css +0 -2
  439. package/static/app/assets/search-BcHqkjoy.js +0 -1
@@ -1,394 +0,0 @@
1
- """The command screens — one Lattice-server read (or upload) rendered for a phone.
2
-
3
- Everything reachable from the main menu that answers a question about the
4
- running system rather than driving a conversation: server status, loaded
5
- models, Knowledge Graph counts, a screenshot, chat history, the web-UI link,
6
- the MCP tool list, and document upload into the graph.
7
-
8
- Each screen follows the same shape: an optimistic chat action, one call through
9
- :func:`~latticeai.integrations.telegram_bot.config._server_client`, and a plain
10
- Korean rendering of exactly what came back — an unreachable server produces an
11
- empty payload, never an invented one.
12
-
13
- Stubbing note: these functions read ``_server_client``, ``_mac_ram_used_gb``,
14
- ``send_photo``, ``send_message`` and ``download_telegram_file`` as *this*
15
- module's globals, so a test standing in for any of them patches this module.
16
- ``get_web_url``/``get_graph_url`` are read here but resolve
17
- ``PUBLIC_WEB_URL``/``get_lan_ip``/``SERVER_PORT`` inside ``helpers``.
18
- """
19
-
20
- import asyncio
21
- import os
22
- import tempfile
23
- from pathlib import Path
24
-
25
- from latticeai.core.logging_safety import safe_log_text
26
- from latticeai.core.quiet import quiet
27
-
28
- from .config import (
29
- API_URL,
30
- BASE_URL,
31
- GRAPH_STATS_URL,
32
- HISTORY_URL,
33
- MCP_TOOLS_URL,
34
- MODELS_URL,
35
- STATUS_URL,
36
- UPLOAD_DOC_URL,
37
- _server_client,
38
- logger,
39
- )
40
- from .helpers import (
41
- download_telegram_file,
42
- get_graph_url,
43
- get_web_url,
44
- send_chat_action,
45
- send_message,
46
- send_photo,
47
- )
48
-
49
- # ── Main menu ─────────────────────────────────────────────────────────────────
50
-
51
- MAIN_MENU = {
52
- "inline_keyboard": [
53
- [
54
- {"text": "📊 서버 상태", "callback_data": "cmd:status"},
55
- {"text": "🧠 현재 모델", "callback_data": "cmd:model"},
56
- ],
57
- [
58
- {"text": "🕸 Knowledge Graph", "callback_data": "cmd:graph"},
59
- {"text": "📸 스크린샷", "callback_data": "cmd:screenshot"},
60
- ],
61
- [
62
- {"text": "📜 최근 대화 5건", "callback_data": "cmd:history"},
63
- {"text": "🗑 기록 정리", "callback_data": "cmd:clear"},
64
- ],
65
- [
66
- {"text": "🔗 웹 UI 열기", "callback_data": "cmd:web"},
67
- {"text": "🔌 MCP 도구 목록", "callback_data": "cmd:mcp"},
68
- ],
69
- [
70
- {"text": "🗂 변경 제안 검토", "callback_data": "cmd:review"},
71
- ],
72
- ]
73
- }
74
-
75
- async def show_menu(client, chat_id):
76
- await send_message(client, chat_id, "📱 Lattice AI 원격 제어 메뉴입니다.", reply_markup=MAIN_MENU)
77
-
78
- # ── Server status ─────────────────────────────────────────────────────────────
79
-
80
- async def _mac_ram_used_gb() -> str:
81
- try:
82
- vm_proc = await asyncio.create_subprocess_exec(
83
- "vm_stat", stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.DEVNULL
84
- )
85
- vm_out, _ = await vm_proc.communicate()
86
- lines = vm_out.decode().splitlines()
87
-
88
- # Parse page size from header line: "Mach Virtual Memory Statistics: (page size of 16384 bytes)"
89
- page_size = 4096
90
- if lines:
91
- import re
92
- m = re.search(r"page size of (\d+) bytes", lines[0])
93
- if m:
94
- page_size = int(m.group(1))
95
-
96
- stats = {}
97
- for line in lines[1:]:
98
- if ":" in line:
99
- k, _, v = line.partition(":")
100
- try:
101
- stats[k.strip()] = int(v.strip().rstrip(".")) * page_size
102
- except ValueError:
103
- quiet()
104
-
105
- used = stats.get("Pages active", 0) + stats.get("Pages wired down", 0)
106
-
107
- mem_proc = await asyncio.create_subprocess_exec(
108
- "sysctl", "-n", "hw.memsize", stdout=asyncio.subprocess.PIPE
109
- )
110
- mem_out, _ = await mem_proc.communicate()
111
- total = int(mem_out.strip())
112
- return f"{used/1e9:.1f} GB / {total/1e9:.0f} GB"
113
- except Exception:
114
- return "N/A"
115
-
116
- async def show_status(client, chat_id):
117
- await send_chat_action(client, chat_id, "typing")
118
- try:
119
- async with _server_client() as lc:
120
- res = await lc.get(STATUS_URL, timeout=5.0)
121
- data = res.json() if res.status_code == 200 else {}
122
- except Exception:
123
- data = {}
124
-
125
- ram = await _mac_ram_used_gb()
126
- model = data.get("loaded_model") or "없음"
127
- mode = data.get("mode") or "unknown"
128
- state = "🟢 온라인" if data.get("status") == "online" else "🔴 오프라인"
129
-
130
- text = (
131
- f"📊 Lattice AI 서버 상태\n"
132
- f"상태: {state}\n"
133
- f"모드: {mode}\n"
134
- f"모델: {model}\n"
135
- f"RAM: {ram}"
136
- )
137
- await send_message(client, chat_id, text)
138
-
139
- # ── Model info & unload ───────────────────────────────────────────────────────
140
-
141
- async def show_model_info(client, chat_id):
142
- await send_chat_action(client, chat_id, "typing")
143
- try:
144
- async with _server_client() as lc:
145
- res = await lc.get(MODELS_URL, timeout=5.0)
146
- data = res.json() if res.status_code == 200 else {}
147
- except Exception:
148
- data = {}
149
-
150
- current = data.get("current") or "없음"
151
- loaded = data.get("loaded") or []
152
- loaded_str = "\n".join(f" - {m}" for m in loaded) if loaded else " 없음"
153
- text = f"🧠 현재 모델: {current}\n\n로드된 모델:\n{loaded_str}"
154
-
155
- markup = None
156
- if loaded:
157
- markup = {
158
- "inline_keyboard": [
159
- [{"text": f"🗑 {m} 언로드", "callback_data": f"model:unload:{m}"}]
160
- for m in loaded
161
- ] + [[{"text": "↩ 메뉴로", "callback_data": "cmd:menu"}]]
162
- }
163
- await send_message(client, chat_id, text, reply_markup=markup)
164
-
165
- def _unload_all_report(results: list[tuple[str, int]]) -> str:
166
- """Report an unload-all run from the statuses the server actually returned."""
167
- failed = [(mid, code) for mid, code in results if code != 200]
168
- if not failed:
169
- return "✅ 모든 모델 언로드 완료. RAM이 해제되었습니다."
170
- detail = ", ".join(f"{mid} ({code})" for mid, code in failed)
171
- return (
172
- f"일부 모델 언로드 실패: {detail}\n"
173
- f"성공 {len(results) - len(failed)}개 / 실패 {len(failed)}개"
174
- )
175
-
176
- async def do_unload_model(client, chat_id, model_id: str = ""):
177
- await send_chat_action(client, chat_id, "typing")
178
- try:
179
- results: list[tuple[str, int]] | None = None
180
- async with _server_client() as lc:
181
- if model_id:
182
- res = await lc.delete(f"{BASE_URL}/models/unload/{model_id}", timeout=15.0)
183
- else:
184
- # Unload all: keep every delete's real status. Discarding them
185
- # for a synthesized 200 reported "모든 모델 언로드 완료" even
186
- # when a model refused to unload.
187
- res = await lc.get(MODELS_URL, timeout=5.0)
188
- if res.status_code == 200:
189
- results = []
190
- for mid in res.json().get("loaded") or []:
191
- deleted = await lc.delete(f"{BASE_URL}/models/unload/{mid}", timeout=15.0)
192
- results.append((mid, deleted.status_code))
193
- if results is not None:
194
- await send_message(client, chat_id, _unload_all_report(results))
195
- elif res.status_code == 200:
196
- await send_message(client, chat_id, f"✅ {model_id} 언로드 완료. RAM이 해제되었습니다.")
197
- else:
198
- await send_message(client, chat_id, f"언로드 실패 ({res.status_code})")
199
- except Exception as e:
200
- await send_message(client, chat_id, f"언로드 오류: {e}")
201
-
202
- # ── Knowledge Graph stats ─────────────────────────────────────────────────────
203
-
204
- async def show_graph_stats(client, chat_id):
205
- await send_chat_action(client, chat_id, "typing")
206
- try:
207
- async with _server_client() as lc:
208
- res = await lc.get(GRAPH_STATS_URL, timeout=5.0)
209
- data = res.json() if res.status_code == 200 else {}
210
- except Exception:
211
- data = {}
212
-
213
- nodes = data.get("nodes") or {}
214
- edges = data.get("edges") or {}
215
- total_nodes = sum(nodes.values())
216
- total_edges = sum(edges.values())
217
-
218
- node_lines = "\n".join(f" {t}: {c}" for t, c in sorted(nodes.items(), key=lambda x: -x[1])) or " 없음"
219
- edge_lines = "\n".join(f" {t}: {c}" for t, c in sorted(edges.items(), key=lambda x: -x[1])[:8]) or " 없음"
220
-
221
- text = (
222
- f"🕸 Knowledge Graph 통계\n\n"
223
- f"노드 총 {total_nodes}개:\n{node_lines}\n\n"
224
- f"엣지 총 {total_edges}개:\n{edge_lines}\n\n"
225
- f"그래프 보기: {get_graph_url()}"
226
- )
227
- markup = {
228
- "inline_keyboard": [[
229
- {"text": "🔗 그래프 열기", "url": get_graph_url()},
230
- {"text": "↩ 메뉴로", "callback_data": "cmd:menu"},
231
- ]]
232
- }
233
- await send_message(client, chat_id, text, reply_markup=markup)
234
-
235
- # ── Screenshot ────────────────────────────────────────────────────────────────
236
-
237
- async def take_screenshot(client, chat_id):
238
- await send_chat_action(client, chat_id, "upload_photo")
239
- # mkstemp, not mktemp: mktemp only predicts an unused name, leaving a
240
- # window in which anything can create that path first. mkstemp creates
241
- # the file atomically with 0600.
242
- _fd, _name = tempfile.mkstemp(suffix=".jpg")
243
- os.close(_fd)
244
- tmp = Path(_name)
245
- try:
246
- proc = await asyncio.create_subprocess_exec(
247
- "screencapture", "-x", str(tmp),
248
- stdout=asyncio.subprocess.DEVNULL,
249
- stderr=asyncio.subprocess.DEVNULL,
250
- )
251
- await asyncio.wait_for(proc.communicate(), timeout=10.0)
252
- if tmp.exists() and tmp.stat().st_size > 0:
253
- await send_photo(client, chat_id, tmp, caption="현재 화면입니다.")
254
- else:
255
- await send_message(client, chat_id, "스크린샷 파일이 생성되지 않았습니다. screencapture가 설치되어 있는지 확인하세요.")
256
- except asyncio.TimeoutError:
257
- await send_message(client, chat_id, "스크린샷 시간 초과")
258
- except FileNotFoundError:
259
- await send_message(client, chat_id, "screencapture 명령이 없습니다. macOS에서만 동작합니다.")
260
- except Exception as e:
261
- await send_message(client, chat_id, f"스크린샷 오류: {e}")
262
- finally:
263
- try:
264
- tmp.unlink(missing_ok=True)
265
- except Exception:
266
- quiet()
267
-
268
- # ── History ───────────────────────────────────────────────────────────────────
269
-
270
- async def show_history_summary(client, chat_id, n: int = 5):
271
- await send_chat_action(client, chat_id, "typing")
272
- try:
273
- async with _server_client() as lc:
274
- res = await lc.get(HISTORY_URL, timeout=10.0)
275
- items = res.json() if res.status_code == 200 else []
276
- except Exception:
277
- items = []
278
-
279
- if not items:
280
- await send_message(client, chat_id, "저장된 대화 기록이 없습니다.")
281
- return
282
-
283
- recent = [i for i in items if i.get("role") == "user"][-n:]
284
- lines = [f"📜 최근 사용자 메시지 {len(recent)}건\n"]
285
- for item in recent:
286
- ts = str(item.get("timestamp", ""))[:16]
287
- src = item.get("source", "web")
288
- content = str(item.get("content", ""))[:120].replace("\n", " ")
289
- lines.append(f"[{ts}] ({src}) {content}")
290
- await send_message(client, chat_id, "\n".join(lines))
291
-
292
- async def clear_server_history(client, chat_id, keep_last=0):
293
- try:
294
- async with _server_client() as lc:
295
- res = await lc.delete(HISTORY_URL, params={"keep_last": keep_last}, timeout=10.0)
296
- data = res.json() if res.headers.get("content-type", "").startswith("application/json") else {}
297
- if res.status_code == 200:
298
- await send_message(client, chat_id, f"대화 기록을 정리했습니다. 삭제 {data.get('removed', 0)}개, 유지 {data.get('kept', 0)}개.")
299
- else:
300
- await send_message(client, chat_id, f"대화 기록 정리 실패: {res.status_code}")
301
- except Exception as e:
302
- await send_message(client, chat_id, f"대화 기록 정리 오류: {e}")
303
-
304
- # ── Web UI link ───────────────────────────────────────────────────────────────
305
-
306
- async def send_web_link(client, chat_id):
307
- web_url = get_web_url()
308
- text = (
309
- "웹 UI 링크입니다.\n"
310
- f"{web_url}\n\n"
311
- "핸드폰이 Mac과 같은 Wi-Fi에 있어야 바로 열립니다. "
312
- "외부망에서 쓰려면 LATTICEAI_PUBLIC_URL에 터널 주소를 설정하세요."
313
- )
314
- payload = {
315
- "chat_id": chat_id,
316
- "text": text,
317
- "reply_markup": {
318
- "inline_keyboard": [[
319
- {"text": "Lattice AI Web 열기", "url": web_url},
320
- {"text": "Knowledge Graph", "url": get_graph_url()},
321
- ]]
322
- },
323
- }
324
- try:
325
- # The Telegram client, like every other helper here. Sending this on the
326
- # server client shipped the local bearer capability to api.telegram.org
327
- # and failed outright whenever that token was unset.
328
- await client.post(f"{API_URL}/sendMessage", json=payload)
329
- except Exception as e:
330
- logger.error("웹 링크 전송 실패: %s", safe_log_text(e))
331
-
332
- # ── MCP tools ─────────────────────────────────────────────────────────────────
333
-
334
- async def send_mcp_tools(client, chat_id):
335
- try:
336
- async with _server_client() as lc:
337
- res = await lc.get(MCP_TOOLS_URL, timeout=10.0)
338
- if res.status_code != 200:
339
- await send_message(client, chat_id, f"MCP 도구 목록을 가져오지 못했습니다: {res.status_code}")
340
- return
341
- data = res.json()
342
- names = [tool["name"] for tool in data.get("tools", [])]
343
- await send_message(client, chat_id, "사용 가능한 MCP 도구:\n" + ("\n".join(f"- {n}" for n in names) or "없음"))
344
- except Exception as e:
345
- await send_message(client, chat_id, f"MCP 도구 조회 실패: {e}")
346
-
347
- # ── Document upload → knowledge graph ────────────────────────────────────────
348
-
349
- async def process_document_file(client, chat_id, file_id: str, filename: str, caption: str = ""):
350
- await send_chat_action(client, chat_id, "upload_document")
351
- raw = await download_telegram_file(client, file_id)
352
- if not raw:
353
- await send_message(client, chat_id, "파일 다운로드 실패")
354
- return
355
-
356
- suffix = Path(filename).suffix.lower()
357
- allowed = {".pdf", ".docx", ".xlsx", ".pptx", ".txt", ".md", ".csv"}
358
- if suffix not in allowed:
359
- await send_message(client, chat_id,
360
- f"지원하지 않는 파일 형식입니다({suffix}). "
361
- f"지원 형식: {', '.join(sorted(allowed))}")
362
- return
363
-
364
- _fd, _name = tempfile.mkstemp(suffix=suffix) # see take_screenshot
365
- os.close(_fd)
366
- tmp = Path(_name)
367
- try:
368
- tmp.write_bytes(raw)
369
- async with _server_client() as lc:
370
- res = await lc.post(
371
- UPLOAD_DOC_URL,
372
- files={"file": (filename, raw)},
373
- timeout=60.0,
374
- )
375
- if res.status_code == 200:
376
- data = res.json()
377
- chars = data.get("chars") or len(raw)
378
- preview = str(data.get("preview") or "")[:300]
379
- kg = data.get("knowledge_graph") or {}
380
- node_id = kg.get("node_id", "")
381
- text = (
382
- f"✅ {filename} 수집 완료\n"
383
- f"크기: {len(raw) // 1024} KB | 문자: {chars}\n"
384
- f"노드: {node_id}\n"
385
- f"\n미리보기:\n{preview}"
386
- )
387
- await send_message(client, chat_id, text)
388
- else:
389
- err = res.json().get("detail") if res.headers.get("content-type", "").startswith("application/json") else res.text
390
- await send_message(client, chat_id, f"업로드 실패 ({res.status_code}): {err}")
391
- except Exception as e:
392
- await send_message(client, chat_id, f"문서 처리 오류: {e}")
393
- finally:
394
- tmp.unlink(missing_ok=True)
@@ -1,76 +0,0 @@
1
- """Audit log wiring extracted from app_factory _build for smaller closure.
2
-
3
- Returns dict of get_audit_log / append_audit_event for legacy namespace.
4
- """
5
- from __future__ import annotations
6
-
7
- import json
8
- from pathlib import Path
9
- from typing import Any, Callable, Dict, List, Optional
10
-
11
- from latticeai.core import timezones
12
- from latticeai.core.quiet import quiet
13
-
14
-
15
- def build_audit_runtime(
16
- *,
17
- audit_file: Path,
18
- logging: Any,
19
- redact_fn: Optional[Callable[[str], str]] = None,
20
- ) -> Dict[str, Any]:
21
- _audit_lock: Any = __import__("threading").Lock()
22
- audit_jsonl = audit_file.with_suffix(audit_file.suffix + ".jsonl")
23
-
24
- def _read_audit() -> List[Dict[str, Any]]:
25
- events: List[Dict[str, Any]] = []
26
- if not audit_file.exists():
27
- data = []
28
- else:
29
- try:
30
- data = json.loads(audit_file.read_text(encoding="utf-8"))
31
- except Exception:
32
- data = []
33
- if isinstance(data, list):
34
- events.extend(item for item in data if isinstance(item, dict))
35
- if audit_jsonl.exists():
36
- try:
37
- for line in audit_jsonl.read_text(encoding="utf-8").splitlines():
38
- if not line.strip():
39
- continue
40
- item = json.loads(line)
41
- if isinstance(item, dict):
42
- events.append(item)
43
- except Exception:
44
- quiet()
45
- return events[-5000:]
46
-
47
- def _append(event_type: str, **payload: Any) -> None:
48
- entry = {"event_type": event_type, "timestamp": timezones.now_iso()}
49
- if payload:
50
- entry.update(payload)
51
- if redact_fn:
52
- try:
53
- for k in ("content", "content_preview", "message"):
54
- if k in entry and isinstance(entry[k], str):
55
- entry[k] = redact_fn(entry[k])
56
- except Exception:
57
- quiet()
58
- with _audit_lock:
59
- audit_file.parent.mkdir(parents=True, exist_ok=True)
60
- with audit_jsonl.open("a", encoding="utf-8") as fh:
61
- fh.write(json.dumps(entry, ensure_ascii=False, default=str))
62
- fh.write("\n")
63
-
64
- def get_audit_log() -> List[Dict[str, Any]]:
65
- return _read_audit()
66
-
67
- def append_audit_event(event_type: str, **payload: Any) -> None:
68
- try:
69
- _append(event_type, **payload)
70
- except Exception as e:
71
- logging.warning("audit append failed: %s", e)
72
-
73
- return {
74
- "get_audit_log": get_audit_log,
75
- "append_audit_event": append_audit_event,
76
- }
@@ -1,81 +0,0 @@
1
- """Automation runtime assembly for review, trigger, agent, and run execution.
2
-
3
- This module keeps the automation object graph behind one construction seam.
4
- Router registration remains in ``app_factory`` so route order stays unchanged.
5
- """
6
-
7
- from __future__ import annotations
8
-
9
- from typing import Any, Callable, Dict, Optional
10
-
11
-
12
- def build_automation_runtime(
13
- *,
14
- store: Any,
15
- platform: Any,
16
- data_dir: Any,
17
- workspace_graph: Callable[..., Any],
18
- append_audit_event: Callable[..., Any],
19
- hooks: Any,
20
- tz_name: Optional[str] = None,
21
- ) -> Dict[str, Any]:
22
- """Construct automation services and attach the run executor boundary."""
23
-
24
- from lattice_brain.runtime.agent_runtime import AgentRuntime
25
- from latticeai.services.review_queue import ReviewQueueService
26
- from latticeai.services.run_executor import RunExecutor
27
- from latticeai.services.triggers import TriggerService
28
-
29
- review_queue = ReviewQueueService(store=store)
30
-
31
- def _run_triggered_workflow(workflow_id: str, inputs: Dict[str, Any]) -> Dict[str, Any]:
32
- trigger = (inputs or {}).get("__trigger__") or {}
33
- return platform.run_workflow_by_id(
34
- workflow_id,
35
- trigger.get("user_email"),
36
- trigger.get("workspace_id"),
37
- with_agent=True,
38
- inputs=inputs,
39
- )
40
-
41
- trigger_service = TriggerService(
42
- store=store,
43
- run_workflow=_run_triggered_workflow,
44
- data_dir=data_dir,
45
- review_sink=review_queue,
46
- tz_name=tz_name,
47
- )
48
-
49
- def _memory_ingest(**kwargs):
50
- try:
51
- # Delegate to store's upsert (enriches memories + KG automatically via internal graph.ingest_event)
52
- return store.upsert_memory(**kwargs)
53
- except Exception:
54
- return None
55
-
56
- agent_runtime = AgentRuntime(
57
- store=store,
58
- orchestrator_factory=platform.build_orchestrator,
59
- workspace_graph=workspace_graph,
60
- append_audit_event=append_audit_event,
61
- hooks=hooks,
62
- memory_ingest=_memory_ingest,
63
- review_sink=review_queue,
64
- )
65
- run_executor = RunExecutor(
66
- store=store,
67
- agent_runtime=agent_runtime,
68
- build_workflow_runners=platform.build_workflow_runners,
69
- workspace_graph=workspace_graph,
70
- append_audit_event=append_audit_event,
71
- hooks=hooks,
72
- review_sink=review_queue,
73
- )
74
- agent_runtime.attach_executor(run_executor)
75
-
76
- return {
77
- "REVIEW_QUEUE": review_queue,
78
- "TRIGGER_SERVICE": trigger_service,
79
- "AGENT_RUNTIME": agent_runtime,
80
- "RUN_EXECUTOR": run_executor,
81
- }
@@ -1,141 +0,0 @@
1
- """Chat and interaction wiring seam for ``latticeai.app_factory``."""
2
-
3
- from __future__ import annotations
4
-
5
- from typing import Any, Optional
6
-
7
- from latticeai.runtime.permission_mode_wiring import (
8
- bind_dispatch_permission_mode,
9
- resolve_active_permission_mode,
10
- )
11
- from latticeai.services.router_context import (
12
- InteractionRouterContext,
13
- ToolRouterContext,
14
- )
15
-
16
-
17
- def build_chat_agent_runtime_from_context(
18
- *,
19
- build_agent_runtime: Any,
20
- model_router: Any,
21
- execute_tool: Any,
22
- recent_chat_context: Any,
23
- clear_history: Any,
24
- knowledge_save: Any,
25
- audit: Any,
26
- hooks: Any,
27
- brain_memory: Any,
28
- self_model_summary: Any = None,
29
- ) -> Any:
30
- # Ensure dispatch + agent share the same autonomy dial before the runtime
31
- # is constructed (process-wide service; data_dir refined later at router mount).
32
- bind_dispatch_permission_mode()
33
- return build_agent_runtime(
34
- model_router=model_router,
35
- execute_tool=execute_tool,
36
- recent_chat_context=recent_chat_context,
37
- clear_history=clear_history,
38
- knowledge_save=knowledge_save,
39
- audit=audit,
40
- hooks=hooks,
41
- brain_memory=brain_memory,
42
- permission_mode=resolve_active_permission_mode,
43
- # v11.2.0: a scoped resolver, not a snapshot — the profile a run sees is
44
- # the one the Brain holds when the run starts, per user and workspace.
45
- self_model_summary=self_model_summary,
46
- )
47
-
48
-
49
- def build_interaction_contexts(
50
- *,
51
- config: Any,
52
- ingestion_pipeline: Any,
53
- data_dir: Any,
54
- static_dir: Any,
55
- model_router: Any,
56
- require_user: Any,
57
- require_admin: Any,
58
- get_current_user: Any,
59
- clear_history: Any,
60
- append_audit_event: Any,
61
- enforce_rate_limit: Any,
62
- bytes_match_extension: Any,
63
- classify_sensitive_message: Any,
64
- save_to_history: Any,
65
- enable_graph: bool,
66
- knowledge_graph: Any,
67
- require_graph: Any,
68
- local_kg_watcher: Any,
69
- load_mcp_installs: Any,
70
- recommend_mcps: Any,
71
- install_mcp: Any,
72
- mcp_public_item: Any,
73
- hooks: Any,
74
- workspace_service: Any,
75
- chat_context: Any,
76
- search_service: Any,
77
- allowed_workspaces_for: Any,
78
- embedding_info: Any,
79
- agent_registry: Any,
80
- memory_service: Any,
81
- platform: Any,
82
- active_model_getter: Any = None,
83
- brain_intelligence: Any = None,
84
- ) -> tuple[ToolRouterContext, InteractionRouterContext]:
85
- tool_router_context = ToolRouterContext(
86
- config=config,
87
- ingestion_pipeline=ingestion_pipeline,
88
- data_dir=data_dir,
89
- static_dir=static_dir,
90
- model_router=model_router,
91
- require_user=require_user,
92
- require_admin=require_admin,
93
- get_current_user=get_current_user,
94
- clear_history=clear_history,
95
- append_audit_event=append_audit_event,
96
- enforce_rate_limit=enforce_rate_limit,
97
- bytes_match_extension=bytes_match_extension,
98
- classify_sensitive_message=classify_sensitive_message,
99
- save_to_history=save_to_history,
100
- enable_graph=enable_graph,
101
- knowledge_graph=knowledge_graph,
102
- require_graph=require_graph,
103
- local_kg_watcher=local_kg_watcher,
104
- load_mcp_installs=load_mcp_installs,
105
- recommend_mcps=recommend_mcps,
106
- install_mcp=install_mcp,
107
- mcp_public_item=mcp_public_item,
108
- hooks=hooks,
109
- workspace_service=workspace_service,
110
- allowed_workspaces_for=allowed_workspaces_for,
111
- )
112
- interaction_router_context = InteractionRouterContext(
113
- chat_context=chat_context,
114
- search_service=search_service,
115
- allowed_workspaces_for=allowed_workspaces_for,
116
- require_user=require_user,
117
- embedding_info=embedding_info,
118
- tool_context=tool_router_context,
119
- hooks=hooks,
120
- agent_registry=agent_registry,
121
- memory_service=memory_service,
122
- platform=platform,
123
- active_model_getter=active_model_getter,
124
- brain_intelligence=brain_intelligence,
125
- )
126
- return tool_router_context, interaction_router_context
127
-
128
-
129
- def maybe_build_telegram_chat_mirror(
130
- *,
131
- enable_telegram: bool,
132
- spawn: Any,
133
- ) -> Optional[Any]:
134
- if not enable_telegram:
135
- return None
136
-
137
- def telegram_chat_mirror(role: str, text: str, source: Optional[str] = None) -> None:
138
- from latticeai.integrations.telegram_bot import broadcast_web_chat
139
- spawn(broadcast_web_chat(role, text), name="telegram_broadcast")
140
-
141
- return telegram_chat_mirror