ltcai 11.5.2 → 11.7.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 (443) hide show
  1. package/README.md +93 -148
  2. package/bin/ltcai.js +234 -24
  3. package/docs/CHANGELOG.md +119 -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 +54 -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-BPcVAbOL.js} +1 -1
  96. package/static/app/assets/AdminConsole-Bw1ATQL0.js +1 -0
  97. package/static/app/assets/{Brain-3VCSHFcn.js → Brain-CT92Kos0.js} +2 -2
  98. package/static/app/assets/{BrainHome-Qm8eaztx.js → BrainHome-CFBkt1K_.js} +1 -1
  99. package/static/app/assets/{BrainSignals-DS9BtKOW.js → BrainSignals-ReLWF2H8.js} +1 -1
  100. package/static/app/assets/Capture-BsTokYkk.js +1 -0
  101. package/static/app/assets/{Chronicle-BGvuAchH.js → Chronicle-B6f0T9id.js} +1 -1
  102. package/static/app/assets/{CommandPalette-Bqhm0Urn.js → CommandPalette-CuvjTv1u.js} +1 -1
  103. package/static/app/assets/{Library-BV6NnF0a.js → Library-BGJbG9Hd.js} +1 -1
  104. package/static/app/assets/{LivingBrain-GzenJchP.js → LivingBrain-DGYK_Jsa.js} +1 -1
  105. package/static/app/assets/{ProductFlow-DEP6-vML.js → ProductFlow-DXBC6brE.js} +1 -1
  106. package/static/app/assets/{ReviewCard-CNZ7XjWG.js → ReviewCard-HXRle3qq.js} +2 -2
  107. package/static/app/assets/System-CMHSO9qM.js +1 -0
  108. package/static/app/assets/arrow-left-BfmkskWx.js +1 -0
  109. package/static/app/assets/{bot-B_K1Tdmw.js → bot-Cn8bWRuq.js} +1 -1
  110. package/static/app/assets/{brain-DWyaV1L1.js → brain-CQJberbE.js} +1 -1
  111. package/static/app/assets/{button-aTn4s84A.js → button-Ct9f2_oT.js} +1 -1
  112. package/static/app/assets/circle-check-DruOxB-4.js +1 -0
  113. package/static/app/assets/{circle-pause-xKgeGXkT.js → circle-pause-CmzC_apg.js} +1 -1
  114. package/static/app/assets/{circle-play-DkT6tYPX.js → circle-play-D8mW2aQ7.js} +1 -1
  115. package/static/app/assets/{cpu-85xYObUC.js → cpu-DZcdd0PZ.js} +1 -1
  116. package/static/app/assets/{download-B5Fm7YXo.js → download-bv1KEPGQ.js} +1 -1
  117. package/static/app/assets/{folder-open-kk2Xa52u.js → folder-open-d-Pip5gr.js} +1 -1
  118. package/static/app/assets/{hard-drive-DkA3zBW_.js → hard-drive-D20iavUb.js} +1 -1
  119. package/static/app/assets/index-D9x-kSNy.css +2 -0
  120. package/static/app/assets/{index-BMPdTmlY.js → index-Do83hDzJ.js} +3 -3
  121. package/static/app/assets/{input-B0nRf2jO.js → input-BLXVNmj1.js} +1 -1
  122. package/static/app/assets/{link-2-Dwb4gnTc.js → link-2-BPJOFlAy.js} +1 -1
  123. package/static/app/assets/{permissionCopy-CQDUBrOZ.js → permissionCopy-ChdJd493.js} +1 -1
  124. package/static/app/assets/primitives-Cv5tbZBY.js +1 -0
  125. package/static/app/assets/search-CT9aho2j.js +1 -0
  126. package/static/app/assets/{share-2-BsrxFglO.js → share-2-YNX_NtMU.js} +1 -1
  127. package/static/app/assets/{shield-alert-5BStfp2_.js → shield-alert-DuQ3zrVL.js} +1 -1
  128. package/static/app/assets/{textarea-Cg8IUA-k.js → textarea-DqwLnli4.js} +1 -1
  129. package/static/app/assets/{useFocusTrap-CYKvE46M.js → useFocusTrap-ZVI98jaW.js} +1 -1
  130. package/static/app/assets/{useMutation-CSn9t1op.js → useMutation-CVC4qv_D.js} +1 -1
  131. package/static/app/assets/{useQuery-CY2OI2uy.js → useQuery-C7BeG4HU.js} +1 -1
  132. package/static/app/assets/{utils-Ddol2RWD.js → utils-CiFtIdZq.js} +1 -1
  133. package/static/app/assets/{workspace-BqDwOz_p.js → workspace-DQz9vIId.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/AdminConsole-cf4npybT.js +0 -1
  437. package/static/app/assets/Capture-DiQ219jW.js +0 -1
  438. package/static/app/assets/System-CieofHQa.js +0 -1
  439. package/static/app/assets/arrow-left-kfsrk0mv.js +0 -1
  440. package/static/app/assets/circle-check-qqLug9nU.js +0 -1
  441. package/static/app/assets/index-DxmOfNRi.css +0 -2
  442. package/static/app/assets/primitives-SNp0LRJz.js +0 -1
  443. package/static/app/assets/search-BcHqkjoy.js +0 -1
@@ -1,158 +0,0 @@
1
- """Enterprise PoC surfaces (admin policies, audit export, SIEM stub, org settings).
2
-
3
- This module is **structure only** — it prepares concrete, discoverable shapes for
4
- Enterprise governance features while keeping the open-source Community edition
5
- fully functional and ungated. Every capability here is consulted through
6
- :data:`latticeai.core.enterprise.capability_registry`; in the Community build
7
- each is reported ``enabled=False`` and the Community behaviour (local audit
8
- export, the four base roles, single-tenant local storage) is always available.
9
-
10
- Nothing in this module restricts a Community feature. It answers "what *would*
11
- an Enterprise provider light up, and is it active?" so the admin UI can show an
12
- honest edition/capability matrix and a SIEM export *preview envelope* without
13
- shipping any Enterprise implementation.
14
- """
15
-
16
- from __future__ import annotations
17
-
18
- from typing import Any, Dict, List, Optional
19
-
20
- from latticeai.core.enterprise import (
21
- EnterpriseCapability,
22
- capability_registry,
23
- )
24
-
25
- COMMUNITY_NOTICE = (
26
- "Community edition: this is an Enterprise extension point and is not "
27
- "enforced. Local-first behaviour is always available. See "
28
- "docs/ENTERPRISE.md and docs/EDITION_STRATEGY.md."
29
- )
30
-
31
-
32
- def _cap(capability: EnterpriseCapability) -> bool:
33
- return capability_registry.is_capability_enabled(capability)
34
-
35
-
36
- def admin_policies() -> Dict[str, Any]:
37
- """Admin policy-pack status + the effective (open) Community policy."""
38
- enabled = _cap(EnterpriseCapability.ADMIN_POLICY_PACKS)
39
- return {
40
- "capability": EnterpriseCapability.ADMIN_POLICY_PACKS.value,
41
- "enabled": enabled,
42
- "enforced": enabled,
43
- "effective_policy": {
44
- # Community defaults — descriptive, not enforced by a policy engine.
45
- "base_roles": ["owner", "admin", "member", "viewer"],
46
- "local_file_access": "approval-token gated (per path/user/action)",
47
- "package_install": "admin-only with audit trail",
48
- "network_binding": "127.0.0.1 by default",
49
- "managed_policy_packs": [] if not enabled else "provided-by-enterprise",
50
- },
51
- "note": COMMUNITY_NOTICE,
52
- }
53
-
54
-
55
- def audit_export_descriptor() -> Dict[str, Any]:
56
- """What audit export is available locally vs. via Enterprise SIEM streaming."""
57
- siem_enabled = _cap(EnterpriseCapability.SIEM_EXPORT)
58
- retention_enabled = _cap(EnterpriseCapability.COMPLIANCE_RETENTION)
59
- return {
60
- "local_export": {
61
- "available": True,
62
- "endpoint": "/admin/security/export",
63
- "formats": ["json", "csv", "xlsx", "txt", "pdf"],
64
- "note": "Community local audit export is always available to admins.",
65
- },
66
- "siem_streaming": {
67
- "capability": EnterpriseCapability.SIEM_EXPORT.value,
68
- "enabled": siem_enabled,
69
- "note": COMMUNITY_NOTICE,
70
- },
71
- "compliance_retention": {
72
- "capability": EnterpriseCapability.COMPLIANCE_RETENTION.value,
73
- "enabled": retention_enabled,
74
- "note": COMMUNITY_NOTICE,
75
- },
76
- }
77
-
78
-
79
- def siem_export_stub(events: Optional[List[Dict[str, Any]]] = None) -> Dict[str, Any]:
80
- """A preview of the envelope an Enterprise SIEM exporter would emit.
81
-
82
- In the Community build this is a *stub*: it returns the envelope *shape*
83
- (so integrators can see the contract) but ``streamed=False`` and no events
84
- are actually pushed to an external SIEM.
85
- """
86
- enabled = _cap(EnterpriseCapability.SIEM_EXPORT)
87
- sample = events or [
88
- {
89
- "id": "evt_sample",
90
- "type": "audit_event",
91
- "timestamp": "1970-01-01T00:00:00Z",
92
- "actor": "admin@example.com",
93
- "action": "model_load",
94
- "severity": "informational",
95
- }
96
- ]
97
- envelope = {
98
- "format": "ltcai.siem.v1",
99
- "encoding": "ndjson",
100
- "vendor": "LatticeAI",
101
- "product": "Workspace OS",
102
- "records": [
103
- {
104
- "ts": e.get("timestamp"),
105
- "actor": e.get("actor"),
106
- "act": e.get("action"),
107
- "sev": e.get("severity", "informational"),
108
- "kind": e.get("type"),
109
- "id": e.get("id"),
110
- }
111
- for e in sample
112
- ],
113
- }
114
- return {
115
- "capability": EnterpriseCapability.SIEM_EXPORT.value,
116
- "enabled": enabled,
117
- "streamed": False if not enabled else True,
118
- "destination": None if not enabled else "configured-by-enterprise",
119
- "preview_envelope": envelope,
120
- "note": COMMUNITY_NOTICE,
121
- }
122
-
123
-
124
- def organization_settings() -> Dict[str, Any]:
125
- """Org-scale governance capabilities and their (Community=off) state."""
126
- governance_caps = [
127
- EnterpriseCapability.TENANT_ISOLATION,
128
- EnterpriseCapability.RBAC_ABAC_ADVANCED,
129
- EnterpriseCapability.SCIM,
130
- EnterpriseCapability.IDP_PROVISIONING,
131
- EnterpriseCapability.SSO_ADVANCED,
132
- EnterpriseCapability.DLP_POLICY,
133
- EnterpriseCapability.EDISCOVERY,
134
- EnterpriseCapability.PRIVATE_VPC,
135
- EnterpriseCapability.AIR_GAPPED_DEPLOYMENT,
136
- ]
137
- return {
138
- "community_baseline": {
139
- "workspaces": ["personal", "organization"],
140
- "roles": ["owner", "admin", "member", "viewer"],
141
- "data_isolation": "single-tenant local storage (~/.ltcai)",
142
- },
143
- "governance_capabilities": {
144
- cap.value: _cap(cap) for cap in governance_caps
145
- },
146
- "note": COMMUNITY_NOTICE,
147
- }
148
-
149
-
150
- def poc_overview() -> Dict[str, Any]:
151
- """Combined Enterprise PoC surface for the admin dashboard."""
152
- return {
153
- "edition": capability_registry.describe(),
154
- "admin_policies": admin_policies(),
155
- "audit_export": audit_export_descriptor(),
156
- "siem_export": siem_export_stub(),
157
- "organization_settings": organization_settings(),
158
- }
@@ -1,115 +0,0 @@
1
- """Model-agnostic file content generation pipeline.
2
-
3
- Small local models (gemma/qwen/llama 7B class) asked to "generate an HTML
4
- file" commonly wrap the payload in chat noise: leading commentary ("Sure!
5
- Here is your page:"), Markdown fences, ``<think>`` reasoning blocks,
6
- trailing explanations, or an incomplete document. The previous direct-write
7
- path saved that reply nearly verbatim, so weak models produced broken files.
8
-
9
- This package makes the file-creation flow robust regardless of which LLM is
10
- loaded, by treating the model as an untrusted content source:
11
-
12
- 1. Prompt — extension-aware instructions anchored with the exact first
13
- line the reply must start with (small models follow examples, not rules).
14
- → :mod:`.prompting`
15
- 2. Extract — strip reasoning blocks and conversational framing, pick the
16
- best fenced block, slice known document boundaries. → :mod:`.extraction`
17
- 3. Validate — per-extension structural checks (HTML document shape, JSON
18
- parses, CSS has rule blocks, refusal/chat detection). → :mod:`.validation`
19
- 4. Retry — one corrective attempt that tells the model what was wrong.
20
- → :mod:`.orchestration`
21
- 5. Repair — deterministic scaffolds guarantee the user still gets a valid
22
- file even when the model never produces usable output. → :mod:`.repair`
23
-
24
- Alongside the five steps: :mod:`.sanitize` is the single write-side door every
25
- entry point runs untrusted content through, :mod:`.inference` guesses a
26
- filename or a whole project manifest when the user named neither, and
27
- :mod:`.bundles` checks that a multi-file project's links hold together.
28
-
29
- The pipeline is pure (no I/O, no FastAPI); the chat layer injects an async
30
- ``generate(context) -> str`` callable.
31
-
32
- Split into these submodules in v11.3.0 with no behaviour change. Every name
33
- the single module exposed still resolves from ``latticeai.core.file_generation``.
34
-
35
- Stubbing note: a name rebound *here* changes only this module's binding — the
36
- submodule that calls it holds its own. A test standing in for one of the
37
- regex/helper seams patches the submodule that reads it (for example
38
- ``latticeai.core.file_generation.inference._PKG_NAME_RE``).
39
- """
40
-
41
- from __future__ import annotations
42
-
43
- # The single module bound this for its own use, which made it part of the
44
- # surface callers could reach. Re-exported in the redundant-alias form so it
45
- # reads as deliberate rather than as a leftover import.
46
- from latticeai.core.quiet import quiet as quiet
47
-
48
- from .bundles import _EXTERNAL_REF_PREFIXES as _EXTERNAL_REF_PREFIXES
49
- from .bundles import _HTML_LOCAL_REF_RE as _HTML_LOCAL_REF_RE
50
- from .bundles import _local_bundle_refs as _local_bundle_refs
51
- from .bundles import repair_bundle_references as repair_bundle_references
52
- from .bundles import validate_project_bundle as validate_project_bundle
53
- from .extraction import _CHAT_LINE_RE as _CHAT_LINE_RE
54
- from .extraction import _EXT_FENCE_LANGS as _EXT_FENCE_LANGS
55
- from .extraction import _FENCE_RE as _FENCE_RE
56
- from .extraction import _THINK_BLOCK_RE as _THINK_BLOCK_RE
57
- from .extraction import _THINK_OPEN_RE as _THINK_OPEN_RE
58
- from .extraction import _ext as _ext
59
- from .extraction import _slice_html_document as _slice_html_document
60
- from .extraction import _slice_json_document as _slice_json_document
61
- from .extraction import _strip_chat_lines as _strip_chat_lines
62
- from .extraction import extract_file_content as extract_file_content
63
- from .inference import _CREATE_VERB_RE as _CREATE_VERB_RE
64
- from .inference import _CSS_HINT_RE as _CSS_HINT_RE
65
- from .inference import _EXPLICIT_FILENAME_RE as _EXPLICIT_FILENAME_RE
66
- from .inference import _HTML_HINT_RE as _HTML_HINT_RE
67
- from .inference import _JS_HINT_RE as _JS_HINT_RE
68
- from .inference import _PACKAGE_HINT_RE as _PACKAGE_HINT_RE
69
- from .inference import _PKG_NAME_RE as _PKG_NAME_RE
70
- from .inference import _PROJECT_NAME_RE as _PROJECT_NAME_RE
71
- from .inference import _PYTHON_HINT_RE as _PYTHON_HINT_RE
72
- from .inference import _REACT_HINT_RE as _REACT_HINT_RE
73
- from .inference import _TYPE_KEYWORDS as _TYPE_KEYWORDS
74
- from .inference import _VITE_HINT_RE as _VITE_HINT_RE
75
- from .inference import _python_package_manifest as _python_package_manifest
76
- from .inference import _react_manifest as _react_manifest
77
- from .inference import infer_file_target as infer_file_target
78
- from .inference import infer_project_manifest as infer_project_manifest
79
- from .orchestration import _salvage_score as _salvage_score
80
- from .orchestration import generate_file_content as generate_file_content
81
- from .prompting import _BUNDLE_HTML_MODULE_RULE as _BUNDLE_HTML_MODULE_RULE
82
- from .prompting import _BUNDLE_HTML_RULE as _BUNDLE_HTML_RULE
83
- from .prompting import _FIRST_LINE_HINTS as _FIRST_LINE_HINTS
84
- from .prompting import _TYPE_RULES as _TYPE_RULES
85
- from .prompting import _bundle_html_rule as _bundle_html_rule
86
- from .prompting import build_file_generation_context as build_file_generation_context
87
- from .repair import _repair_html as _repair_html
88
- from .repair import repair_file_content as repair_file_content
89
- from .sanitize import PREVIEWABLE_EXTENSIONS as PREVIEWABLE_EXTENSIONS
90
- from .sanitize import sanitize_write_content as sanitize_write_content
91
- from .validation import _BRACED_CODE_EXTENSIONS as _BRACED_CODE_EXTENSIONS
92
- from .validation import _COMMENTARY_RE as _COMMENTARY_RE
93
- from .validation import _COMPONENT_EXTENSIONS as _COMPONENT_EXTENSIONS
94
- from .validation import _REFUSAL_RE as _REFUSAL_RE
95
- from .validation import _check_balanced_delimiters as _check_balanced_delimiters
96
- from .validation import _check_component_blocks as _check_component_blocks
97
- from .validation import _looks_like_commentary as _looks_like_commentary
98
- from .validation import _strip_code_literals as _strip_code_literals
99
- from .validation import looks_like_refusal as looks_like_refusal
100
- from .validation import validate_file_content as validate_file_content
101
-
102
- __all__ = [
103
- "PREVIEWABLE_EXTENSIONS",
104
- "build_file_generation_context",
105
- "extract_file_content",
106
- "generate_file_content",
107
- "infer_file_target",
108
- "infer_project_manifest",
109
- "looks_like_refusal",
110
- "repair_bundle_references",
111
- "repair_file_content",
112
- "sanitize_write_content",
113
- "validate_file_content",
114
- "validate_project_bundle",
115
- ]
@@ -1,76 +0,0 @@
1
- """Bundle-level checks: does this set of files hold together?
2
-
3
- A multi-file project is only as valid as its links. These helpers find the
4
- local references an HTML document makes, repoint the ones a weak model got
5
- almost right, and report every file that is invalid or dangling.
6
- """
7
-
8
- from __future__ import annotations
9
-
10
- import re
11
- from typing import Any, Dict, List, Tuple
12
-
13
- from .extraction import _ext
14
- from .validation import validate_file_content
15
-
16
- _HTML_LOCAL_REF_RE = re.compile(
17
- r"(?:href|src)\s*=\s*[\"']([^\"'#?]+)[\"']", re.IGNORECASE
18
- )
19
- _EXTERNAL_REF_PREFIXES = ("http://", "https://", "//", "data:", "mailto:", "tel:", "javascript:")
20
-
21
-
22
- def _local_bundle_refs(html: str) -> List[str]:
23
- """File references inside an HTML document that must exist in the bundle."""
24
- refs: List[str] = []
25
- for ref in _HTML_LOCAL_REF_RE.findall(html or ""):
26
- candidate = ref.strip()
27
- if not candidate or candidate.startswith(_EXTERNAL_REF_PREFIXES):
28
- continue
29
- if "." not in candidate.rsplit("/", 1)[-1]:
30
- continue # anchors / routes, not files
31
- refs.append(candidate)
32
- return refs
33
-
34
-
35
- def repair_bundle_references(files: Dict[str, str]) -> Tuple[Dict[str, str], List[str]]:
36
- """Deterministically point dangling HTML refs at real bundle files.
37
-
38
- A weak model asked for ``style.css`` sometimes links ``styles.css``. When
39
- a referenced file is missing but the bundle contains exactly one file of
40
- the same extension, the reference is rewritten. Returns ``(files, fixes)``.
41
- """
42
- names = {p.rsplit("/", 1)[-1] for p in files}
43
- fixes: List[str] = []
44
- repaired = dict(files)
45
- for path, content in files.items():
46
- if _ext(path) not in (".html", ".htm"):
47
- continue
48
- updated = content
49
- for ref in _local_bundle_refs(content):
50
- base = ref.rsplit("/", 1)[-1]
51
- if base in names:
52
- continue
53
- same_ext = [n for n in names if _ext(n) == _ext(base)]
54
- if len(same_ext) == 1:
55
- updated = updated.replace(ref, same_ext[0])
56
- fixes.append(f"{path}: '{ref}' -> '{same_ext[0]}'")
57
- if updated != content:
58
- repaired[path] = updated
59
- return repaired, fixes
60
-
61
-
62
- def validate_project_bundle(files: Dict[str, str]) -> Dict[str, Any]:
63
- """Bundle-level verification: every file valid, every HTML ref resolvable."""
64
- issues: List[str] = []
65
- per_file: Dict[str, Dict[str, Any]] = {}
66
- names = {p.rsplit("/", 1)[-1] for p in files}
67
- for path, content in files.items():
68
- ok, reason = validate_file_content(content, path)
69
- per_file[path] = {"valid": ok, "reason": reason}
70
- if not ok:
71
- issues.append(f"{path}: {reason}")
72
- if _ext(path) in (".html", ".htm"):
73
- for ref in _local_bundle_refs(content):
74
- if ref.rsplit("/", 1)[-1] not in names:
75
- issues.append(f"{path}: references missing file '{ref}'")
76
- return {"ok": not issues, "issues": issues, "files": per_file}
@@ -1,154 +0,0 @@
1
- """Recover the intended file payload from an arbitrary model reply.
2
-
3
- Step 2 of the pipeline described in the package docstring: strip reasoning
4
- blocks and conversational framing, pick the best fenced block, and slice known
5
- document boundaries. Pure string work — nothing here decides whether the result
6
- is *good*, only what the model most plausibly meant to hand over.
7
- """
8
-
9
- from __future__ import annotations
10
-
11
- import json
12
- import re
13
- from typing import Dict, List, Optional, Tuple
14
-
15
- from latticeai.core.quiet import quiet
16
-
17
- _THINK_BLOCK_RE = re.compile(
18
- r"<(think|thinking|reasoning|reflection)>.*?</\1>",
19
- re.DOTALL | re.IGNORECASE,
20
- )
21
- # Unclosed think block (model hit the token limit mid-reasoning).
22
- _THINK_OPEN_RE = re.compile(r"<(think|thinking|reasoning)>.*\Z", re.DOTALL | re.IGNORECASE)
23
-
24
- _FENCE_RE = re.compile(r"```([\w.+-]*)[ \t]*\n(.*?)```", re.DOTALL)
25
-
26
- # Conversational lines that small models prepend/append around the payload.
27
- _CHAT_LINE_RE = re.compile(
28
- r"^\s*("
29
- r"(sure|of course|certainly|okay|ok|alright|great|absolutely)\b[^\n]*"
30
- r"|here('s| is| are)\b[^\n]*"
31
- r"|i('ve| have) (created|written|generated|made)\b[^\n]*"
32
- r"|(below|following) is\b[^\n]*"
33
- r"|let me know\b[^\n]*"
34
- r"|hope (this|that) helps[^\n]*"
35
- r"|feel free\b[^\n]*"
36
- r"|물론(입니다|이죠|이에요)?[!., ]*[^\n]*"
37
- r"|네[,!. ][^\n]*"
38
- r"|알겠습니다[^\n]*"
39
- r"|다음은[^\n]*(입니다|합니다)[:.]?[^\n]*"
40
- r"|아래는?[^\n]*(입니다|내용)[^\n]*"
41
- r"|(요청하신|원하시는)[^\n]*(입니다|만들었습니다|작성했습니다)[^\n]*"
42
- r"|(파일|내용|코드)[을를]?\s*(생성|작성|만들)[^\n]*"
43
- r"|도움이 (필요하|되)[^\n]*"
44
- r"|추가로[^\n]*(말씀|요청)[^\n]*"
45
- r")\s*$",
46
- re.IGNORECASE,
47
- )
48
-
49
-
50
- # Language tags that identify a fenced block as the payload for an extension.
51
- _EXT_FENCE_LANGS: Dict[str, Tuple[str, ...]] = {
52
- ".html": ("html", "htm", "xhtml"),
53
- ".htm": ("html", "htm", "xhtml"),
54
- ".css": ("css",),
55
- ".js": ("js", "javascript"),
56
- ".jsx": ("jsx", "javascript"),
57
- ".ts": ("ts", "typescript"),
58
- ".tsx": ("tsx", "typescript"),
59
- ".py": ("py", "python"),
60
- ".json": ("json",),
61
- ".yaml": ("yaml", "yml"),
62
- ".yml": ("yaml", "yml"),
63
- ".toml": ("toml",),
64
- ".md": ("md", "markdown"),
65
- ".markdown": ("md", "markdown"),
66
- ".sql": ("sql",),
67
- ".sh": ("sh", "bash", "shell", "zsh"),
68
- ".xml": ("xml", "svg"),
69
- ".csv": ("csv",),
70
- ".txt": ("txt", "text", "plaintext"),
71
- ".vue": ("vue", "html"),
72
- ".svelte": ("svelte", "html"),
73
- }
74
-
75
-
76
- def _ext(path: str) -> str:
77
- dot = path.rfind(".")
78
- return path[dot:].lower() if dot >= 0 else ""
79
-
80
-
81
- def _strip_chat_lines(text: str) -> str:
82
- """Drop leading/trailing conversational lines around the payload."""
83
- lines = text.split("\n")
84
- start, end = 0, len(lines)
85
- while start < end and (not lines[start].strip() or _CHAT_LINE_RE.match(lines[start])):
86
- start += 1
87
- while end > start and (not lines[end - 1].strip() or _CHAT_LINE_RE.match(lines[end - 1])):
88
- end -= 1
89
- stripped = "\n".join(lines[start:end]).strip()
90
- return stripped if stripped else text.strip()
91
-
92
-
93
- def extract_file_content(raw: str, target_path: str) -> str:
94
- """Recover the intended file payload from an arbitrary model reply."""
95
- text = (raw or "").strip()
96
- if not text:
97
- return ""
98
- text = _THINK_BLOCK_RE.sub("", text)
99
- text = _THINK_OPEN_RE.sub("", text).strip()
100
-
101
- ext = _ext(target_path)
102
- fences = _FENCE_RE.findall(text + ("\n```" if text.count("```") % 2 else ""))
103
- if fences:
104
- wanted = _EXT_FENCE_LANGS.get(ext, ())
105
- matching = [body for lang, body in fences if lang.lower() in wanted]
106
- candidates = matching if matching else [body for _, body in fences]
107
- # The payload is the largest block; short blocks are usually usage
108
- # snippets ("run it with: python app.py").
109
- content = max(candidates, key=len).strip()
110
- else:
111
- content = _strip_chat_lines(text)
112
-
113
- if ext in (".html", ".htm"):
114
- content = _slice_html_document(content)
115
- elif ext == ".json":
116
- sliced = _slice_json_document(content)
117
- if sliced is not None:
118
- content = sliced
119
- return content.strip()
120
-
121
-
122
- def _slice_html_document(content: str) -> str:
123
- """Cut a complete HTML document out of surrounding prose when present."""
124
- lower = content.lower()
125
- start = lower.find("<!doctype")
126
- if start < 0:
127
- start = lower.find("<html")
128
- if start > 0:
129
- content = content[start:]
130
- lower = lower[start:]
131
- end = lower.rfind("</html>")
132
- if end >= 0:
133
- content = content[: end + len("</html>")]
134
- return content
135
-
136
-
137
- def _slice_json_document(content: str) -> Optional[str]:
138
- """Return the largest parseable JSON value inside ``content``, if any."""
139
- candidates: List[str] = [content]
140
- for opener, closer in (("{", "}"), ("[", "]")):
141
- start = content.find(opener)
142
- end = content.rfind(closer)
143
- if start >= 0 and end > start:
144
- candidates.append(content[start : end + 1])
145
- best: Optional[str] = None
146
- for candidate in candidates:
147
- try:
148
- json.loads(candidate)
149
- except (ValueError, TypeError):
150
- quiet()
151
- continue
152
- if best is None or len(candidate) > len(best):
153
- best = candidate
154
- return best