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.
- package/README.md +91 -148
- package/bin/ltcai.js +234 -24
- package/docs/CHANGELOG.md +75 -0
- package/docs/COMMUNITY_AND_PLUGINS.md +1 -1
- package/docs/DEVELOPMENT.md +8 -6
- package/docs/ENTERPRISE.md +2 -1
- package/docs/MULTI_AGENT_RUNTIME.md +12 -5
- package/docs/ONBOARDING.md +1 -1
- package/docs/OPERATIONS.md +6 -3
- package/docs/REALTIME_COLLABORATION.md +1 -1
- package/docs/TRUST_MODEL.md +1 -1
- package/docs/WHY_LATTICE.md +1 -1
- package/docs/WORKFLOW_DESIGNER.md +3 -2
- package/docs/kg-schema.md +1 -1
- package/docs/v11.6.0_ONE_DOOR_PLAN.md +170 -0
- package/lattice_brain/__init__.py +42 -79
- package/lattice_brain/graph/__init__.py +9 -24
- package/lattice_brain/graph/_kg_common/__init__.py +13 -24
- package/lattice_brain/ingestion/__init__.py +19 -58
- package/lattice_brain/ingestion/pipeline.py +20 -398
- package/lattice_brain/multimodal/__init__.py +7 -18
- package/lattice_brain/multimodal/images.py +6 -264
- package/lattice_brain/multimodal/video.py +8 -247
- package/lattice_brain/runtime/__init__.py +8 -79
- package/lattice_brain/runtime/hooks.py +22 -584
- package/latticeai/__init__.py +1 -1
- package/latticeai/api/agent_worker_seam.py +7 -80
- package/latticeai/api/health.py +6 -20
- package/latticeai/api/local_files.py +16 -613
- package/latticeai/api/models.py +12 -87
- package/latticeai/api/search.py +17 -255
- package/latticeai/api/tools.py +69 -750
- package/latticeai/api/voice_capture.py +8 -70
- package/latticeai/api/worker_compute.py +842 -0
- package/latticeai/api/worker_seams.py +216 -0
- package/latticeai/app_factory.py +23 -232
- package/latticeai/cli/entrypoint.py +36 -249
- package/latticeai/core/agent_permission.py +16 -91
- package/latticeai/core/messages.py +89 -531
- package/latticeai/runtime/access_runtime.py +0 -14
- package/latticeai/runtime/bootstrap.py +10 -21
- package/latticeai/runtime/brain_runtime.py +35 -43
- package/latticeai/runtime/build_phases/__init__.py +21 -37
- package/latticeai/runtime/build_phases/features.py +99 -389
- package/latticeai/runtime/build_phases/foundation.py +82 -392
- package/latticeai/runtime/build_phases/web.py +91 -408
- package/latticeai/runtime/build_phases/worker_profile.py +244 -0
- package/latticeai/runtime/lifespan_runtime.py +7 -16
- package/latticeai/runtime/platform_services_runtime.py +1 -15
- package/latticeai/runtime/runtime_context.py +13 -130
- package/latticeai/runtime/security_runtime.py +10 -103
- package/latticeai/services/architecture_readiness.py +82 -43
- package/latticeai/services/model_runtime/__init__.py +2 -11
- package/latticeai/services/model_runtime/service.py +4 -28
- package/latticeai/services/p_reinforce.py +10 -261
- package/latticeai/services/product_readiness.py +31 -38
- package/latticeai/services/search_service.py +37 -795
- package/latticeai/services/tool_dispatch.py +30 -386
- package/latticeai/services/voice_capture.py +13 -107
- package/latticeai/tools/__init__.py +22 -49
- package/latticeai/tools/commands.py +0 -163
- package/latticeai/tools/computer.py +0 -39
- package/latticeai/tools/documents.py +1 -134
- package/latticeai/tools/filesystem.py +1 -247
- package/latticeai/tools/knowledge.py +1 -52
- package/latticeai/tools/local_files.py +0 -20
- package/latticeai/worker_app.py +75 -0
- package/package.json +2 -3
- package/requirements.txt +0 -5
- package/scripts/agent_eval.py +16 -28
- package/scripts/brain_quality_eval.py +20 -183
- package/scripts/bump_version.py +5 -5
- package/scripts/check_current_release_docs.mjs +7 -4
- package/scripts/check_openapi_drift.mjs +10 -0
- package/scripts/check_server_i18n.mjs +2 -18
- package/scripts/compose_openapi.py +377 -0
- package/scripts/export_openapi.py +32 -4
- package/scripts/gen_messages_catalog_fixture.py +302 -0
- package/scripts/gen_openapi_fragments.py +365 -0
- package/scripts/gen_redact_fixture.py +196 -0
- package/scripts/gen_worker_allowlist_fixture.py +115 -0
- package/scripts/generate_agent_parity_fixtures.py +33 -14
- package/scripts/openapi_route_families.json +2161 -0
- package/scripts/release_screen_claims.json +21 -0
- package/scripts/run_integration_tests.mjs +134 -29
- package/scripts/run_sidecar_e2e.mjs +104 -11
- package/scripts/wheel_smoke.py +32 -22
- package/src-tauri/Cargo.lock +375 -9
- package/src-tauri/Cargo.toml +1 -1
- package/src-tauri/src/backend.rs +151 -45
- package/src-tauri/src/main.rs +18 -18
- package/src-tauri/src/topology.rs +58 -88
- package/src-tauri/tauri.conf.json +1 -2
- package/static/app/asset-manifest.json +41 -41
- package/static/app/assets/{Act-DcQizkl1.js → Act-CToZnOHz.js} +1 -1
- package/static/app/assets/{AdminConsole-cf4npybT.js → AdminConsole-D5kbrBu8.js} +1 -1
- package/static/app/assets/{Brain-3VCSHFcn.js → Brain-C6zCdv4S.js} +1 -1
- package/static/app/assets/{BrainHome-Qm8eaztx.js → BrainHome-D4n3EDUt.js} +1 -1
- package/static/app/assets/{BrainSignals-DS9BtKOW.js → BrainSignals-CzeZ-vQ9.js} +1 -1
- package/static/app/assets/{Capture-DiQ219jW.js → Capture-DPcyTczq.js} +1 -1
- package/static/app/assets/{Chronicle-BGvuAchH.js → Chronicle-D3Nx-oWS.js} +1 -1
- package/static/app/assets/{CommandPalette-Bqhm0Urn.js → CommandPalette-DPPvpp28.js} +1 -1
- package/static/app/assets/{Library-BV6NnF0a.js → Library-Co2qTu3I.js} +1 -1
- package/static/app/assets/{LivingBrain-GzenJchP.js → LivingBrain-Bsmzwy8_.js} +1 -1
- package/static/app/assets/{ProductFlow-DEP6-vML.js → ProductFlow-CBLdmesT.js} +1 -1
- package/static/app/assets/{ReviewCard-CNZ7XjWG.js → ReviewCard-CfR6DLs7.js} +1 -1
- package/static/app/assets/{System-CieofHQa.js → System-Ce-P2YL6.js} +1 -1
- package/static/app/assets/arrow-left-DD5jFGHV.js +1 -0
- package/static/app/assets/{bot-B_K1Tdmw.js → bot-C5-XIww2.js} +1 -1
- package/static/app/assets/{brain-DWyaV1L1.js → brain-CFRJUvdX.js} +1 -1
- package/static/app/assets/{button-aTn4s84A.js → button-DI1KcQP-.js} +1 -1
- package/static/app/assets/circle-check-CY20XMCh.js +1 -0
- package/static/app/assets/{circle-pause-xKgeGXkT.js → circle-pause-C8HHyood.js} +1 -1
- package/static/app/assets/{circle-play-DkT6tYPX.js → circle-play-Cufc235E.js} +1 -1
- package/static/app/assets/{cpu-85xYObUC.js → cpu-DW2_JVsv.js} +1 -1
- package/static/app/assets/{download-B5Fm7YXo.js → download-gbdKTBb8.js} +1 -1
- package/static/app/assets/{folder-open-kk2Xa52u.js → folder-open-C9ydyX33.js} +1 -1
- package/static/app/assets/{hard-drive-DkA3zBW_.js → hard-drive-BxNMzBM3.js} +1 -1
- package/static/app/assets/index-BovSWRmQ.css +2 -0
- package/static/app/assets/{index-BMPdTmlY.js → index-q9XyDY7A.js} +3 -3
- package/static/app/assets/{input-B0nRf2jO.js → input-GLD94Y_K.js} +1 -1
- package/static/app/assets/{link-2-Dwb4gnTc.js → link-2-B4Y0gz1S.js} +1 -1
- package/static/app/assets/{permissionCopy-CQDUBrOZ.js → permissionCopy-CxrV0fvU.js} +1 -1
- package/static/app/assets/{primitives-SNp0LRJz.js → primitives-2ANdAsu2.js} +1 -1
- package/static/app/assets/search-DTxtjQ07.js +1 -0
- package/static/app/assets/{share-2-BsrxFglO.js → share-2-DxArfiuI.js} +1 -1
- package/static/app/assets/{shield-alert-5BStfp2_.js → shield-alert-CgftuFFs.js} +1 -1
- package/static/app/assets/{textarea-Cg8IUA-k.js → textarea-BHVBAoCr.js} +1 -1
- package/static/app/assets/{useFocusTrap-CYKvE46M.js → useFocusTrap-Dzq2j_OG.js} +1 -1
- package/static/app/assets/{useMutation-CSn9t1op.js → useMutation-BcqfMLNq.js} +1 -1
- package/static/app/assets/{useQuery-CY2OI2uy.js → useQuery-DBzLKCOv.js} +1 -1
- package/static/app/assets/{utils-Ddol2RWD.js → utils-B-Aah1bO.js} +1 -1
- package/static/app/assets/{workspace-BqDwOz_p.js → workspace-B6fFhoko.js} +1 -1
- package/static/app/index.html +4 -4
- package/static/sw.js +1 -1
- package/lattice_brain/archive.py +0 -522
- package/lattice_brain/context.py +0 -325
- package/lattice_brain/conversations.py +0 -382
- package/lattice_brain/core.py +0 -82
- package/lattice_brain/graph/_kg_contract.py +0 -249
- package/lattice_brain/graph/curator.py +0 -676
- package/lattice_brain/graph/discovery.py +0 -595
- package/lattice_brain/graph/discovery_index/__init__.py +0 -35
- package/lattice_brain/graph/discovery_index/cleanup.py +0 -182
- package/lattice_brain/graph/discovery_index/extract.py +0 -137
- package/lattice_brain/graph/discovery_index/scan.py +0 -411
- package/lattice_brain/graph/discovery_index/upsert.py +0 -495
- package/lattice_brain/graph/documents.py +0 -380
- package/lattice_brain/graph/fusion.py +0 -395
- package/lattice_brain/graph/identity.py +0 -175
- package/lattice_brain/graph/image_vectors.py +0 -230
- package/lattice_brain/graph/ingest.py +0 -829
- package/lattice_brain/graph/network.py +0 -205
- package/lattice_brain/graph/proactive.py +0 -724
- package/lattice_brain/graph/projection/__init__.py +0 -42
- package/lattice_brain/graph/projection/curation.py +0 -500
- package/lattice_brain/graph/projection/v2_schema.py +0 -518
- package/lattice_brain/graph/provenance.py +0 -524
- package/lattice_brain/graph/rerank.py +0 -163
- package/lattice_brain/graph/retrieval/__init__.py +0 -54
- package/lattice_brain/graph/retrieval/context.py +0 -197
- package/lattice_brain/graph/retrieval/graph_view.py +0 -319
- package/lattice_brain/graph/retrieval/hybrid.py +0 -488
- package/lattice_brain/graph/retrieval/maintenance.py +0 -121
- package/lattice_brain/graph/retrieval/signals.py +0 -95
- package/lattice_brain/graph/retrieval_docgen.py +0 -253
- package/lattice_brain/graph/retrieval_policy.py +0 -180
- package/lattice_brain/graph/retrieval_reads.py +0 -769
- package/lattice_brain/graph/retrieval_vector/__init__.py +0 -42
- package/lattice_brain/graph/retrieval_vector/fingerprint.py +0 -97
- package/lattice_brain/graph/retrieval_vector/indexing.py +0 -347
- package/lattice_brain/graph/retrieval_vector/search.py +0 -560
- package/lattice_brain/graph/retrieval_vector/status.py +0 -374
- package/lattice_brain/graph/schema.py +0 -792
- package/lattice_brain/graph/store.py +0 -268
- package/lattice_brain/graph/vector_index/__init__.py +0 -85
- package/lattice_brain/graph/vector_index/base.py +0 -167
- package/lattice_brain/graph/vector_index/brute_force.py +0 -110
- package/lattice_brain/graph/vector_index/hnsw.py +0 -290
- package/lattice_brain/graph/vector_index/jobs.py +0 -287
- package/lattice_brain/graph/vector_index/quantized.py +0 -148
- package/lattice_brain/graph/vector_index/selector.py +0 -161
- package/lattice_brain/graph/write_master.py +0 -308
- package/lattice_brain/ingestion/_contract.py +0 -90
- package/lattice_brain/ingestion/folder_scan.py +0 -57
- package/lattice_brain/ingestion/folders.py +0 -258
- package/lattice_brain/ingestion/jobs_api.py +0 -107
- package/lattice_brain/ingestion/routing.py +0 -295
- package/lattice_brain/ingestion_jobs.py +0 -380
- package/lattice_brain/memory.py +0 -75
- package/lattice_brain/portability/__init__.py +0 -90
- package/lattice_brain/portability/_contract.py +0 -42
- package/lattice_brain/portability/backups.py +0 -338
- package/lattice_brain/portability/bundles.py +0 -136
- package/lattice_brain/portability/constants.py +0 -93
- package/lattice_brain/portability/fsops.py +0 -138
- package/lattice_brain/portability/service.py +0 -41
- package/lattice_brain/portability/sharing.py +0 -710
- package/lattice_brain/quality.py +0 -543
- package/lattice_brain/retrieval_benchmark_fixtures.py +0 -92
- package/lattice_brain/runtime/agent_runtime.py +0 -859
- package/lattice_brain/runtime/contracts.py +0 -460
- package/lattice_brain/runtime/multi_agent.py +0 -942
- package/lattice_brain/runtime/statuses.py +0 -10
- package/lattice_brain/sealed_box.py +0 -240
- package/lattice_brain/self_model.py +0 -675
- package/lattice_brain/sensitivity.py +0 -94
- package/lattice_brain/storage/__init__.py +0 -22
- package/lattice_brain/storage/base.py +0 -100
- package/lattice_brain/storage/docker.py +0 -105
- package/lattice_brain/storage/factory.py +0 -31
- package/lattice_brain/storage/migration.py +0 -191
- package/lattice_brain/storage/postgres.py +0 -123
- package/lattice_brain/storage/sqlite.py +0 -143
- package/lattice_brain/synthesis.py +0 -824
- package/lattice_brain/workflow.py +0 -497
- package/latticeai/api/admin.py +0 -471
- package/latticeai/api/agent_registry.py +0 -105
- package/latticeai/api/agents.py +0 -228
- package/latticeai/api/auth.py +0 -383
- package/latticeai/api/automation_intelligence.py +0 -401
- package/latticeai/api/brain_intelligence.py +0 -199
- package/latticeai/api/browser.py +0 -493
- package/latticeai/api/change_proposals.py +0 -89
- package/latticeai/api/chat.py +0 -572
- package/latticeai/api/chat_agent_http.py +0 -892
- package/latticeai/api/chat_contracts.py +0 -73
- package/latticeai/api/chat_documents.py +0 -276
- package/latticeai/api/chat_helpers.py +0 -460
- package/latticeai/api/chat_history.py +0 -101
- package/latticeai/api/chat_hybrid.py +0 -113
- package/latticeai/api/chat_intents.py +0 -646
- package/latticeai/api/chat_stream.py +0 -216
- package/latticeai/api/chronicle.py +0 -63
- package/latticeai/api/command_center.py +0 -51
- package/latticeai/api/computer_use.py +0 -474
- package/latticeai/api/evidence_actions.py +0 -48
- package/latticeai/api/features.py +0 -70
- package/latticeai/api/funnel_metrics.py +0 -31
- package/latticeai/api/garden.py +0 -34
- package/latticeai/api/hooks.py +0 -165
- package/latticeai/api/index_jobs.py +0 -145
- package/latticeai/api/invitations.py +0 -100
- package/latticeai/api/knowledge_graph.py +0 -536
- package/latticeai/api/marketplace.py +0 -105
- package/latticeai/api/mcp.py +0 -482
- package/latticeai/api/memory.py +0 -270
- package/latticeai/api/network.py +0 -81
- package/latticeai/api/network_boundary.py +0 -225
- package/latticeai/api/permission_mode.py +0 -61
- package/latticeai/api/permissions.py +0 -436
- package/latticeai/api/plugins.py +0 -126
- package/latticeai/api/portability.py +0 -391
- package/latticeai/api/project_sessions.py +0 -114
- package/latticeai/api/realtime.py +0 -118
- package/latticeai/api/review_queue.py +0 -364
- package/latticeai/api/security_dashboard.py +0 -604
- package/latticeai/api/setup.py +0 -319
- package/latticeai/api/static_routes.py +0 -354
- package/latticeai/api/ui_redirects.py +0 -26
- package/latticeai/api/workflow_designer.py +0 -394
- package/latticeai/api/workspace.py +0 -856
- package/latticeai/api/workspace_scope.py +0 -125
- package/latticeai/core/agent/__init__.py +0 -93
- package/latticeai/core/agent/_contract.py +0 -79
- package/latticeai/core/agent/context.py +0 -57
- package/latticeai/core/agent/deps.py +0 -125
- package/latticeai/core/agent/execution.py +0 -622
- package/latticeai/core/agent/planning.py +0 -145
- package/latticeai/core/agent/recovery.py +0 -157
- package/latticeai/core/agent/runtime.py +0 -210
- package/latticeai/core/agent/verification.py +0 -231
- package/latticeai/core/agent_eval.py +0 -739
- package/latticeai/core/agent_helpers.py +0 -493
- package/latticeai/core/agent_profiles.py +0 -110
- package/latticeai/core/agent_prompts.py +0 -171
- package/latticeai/core/agent_registry.py +0 -232
- package/latticeai/core/agent_state.py +0 -41
- package/latticeai/core/agent_trace.py +0 -104
- package/latticeai/core/artifact_ledger.py +0 -109
- package/latticeai/core/audit.py +0 -260
- package/latticeai/core/builtin_hooks.py +0 -105
- package/latticeai/core/context_builder.py +0 -394
- package/latticeai/core/document_generator.py +0 -103
- package/latticeai/core/enterprise.py +0 -154
- package/latticeai/core/enterprise_admin.py +0 -158
- package/latticeai/core/file_generation/__init__.py +0 -115
- package/latticeai/core/file_generation/bundles.py +0 -76
- package/latticeai/core/file_generation/extraction.py +0 -154
- package/latticeai/core/file_generation/inference.py +0 -235
- package/latticeai/core/file_generation/orchestration.py +0 -152
- package/latticeai/core/file_generation/prompting.py +0 -117
- package/latticeai/core/file_generation/repair.py +0 -114
- package/latticeai/core/file_generation/sanitize.py +0 -61
- package/latticeai/core/file_generation/validation.py +0 -201
- package/latticeai/core/invitations.py +0 -132
- package/latticeai/core/legacy_compatibility.py +0 -243
- package/latticeai/core/logging_safety.py +0 -46
- package/latticeai/core/marketplace.py +0 -293
- package/latticeai/core/mcp_catalog.py +0 -452
- package/latticeai/core/mcp_registry.py +0 -506
- package/latticeai/core/network_boundary.py +0 -168
- package/latticeai/core/oidc.py +0 -208
- package/latticeai/core/plugins.py +0 -432
- package/latticeai/core/product_hardening.py +0 -218
- package/latticeai/core/project_sessions.py +0 -337
- package/latticeai/core/realtime.py +0 -238
- package/latticeai/core/run_explain.py +0 -426
- package/latticeai/core/run_store.py +0 -252
- package/latticeai/core/timezones.py +0 -80
- package/latticeai/core/workspace_computer_memory.py +0 -84
- package/latticeai/core/workspace_graph_trace.py +0 -155
- package/latticeai/core/workspace_indexing.py +0 -102
- package/latticeai/core/workspace_memory.py +0 -77
- package/latticeai/core/workspace_onboarding.py +0 -104
- package/latticeai/core/workspace_os.py +0 -978
- package/latticeai/core/workspace_os_constants.py +0 -126
- package/latticeai/core/workspace_os_state.py +0 -180
- package/latticeai/core/workspace_os_utils.py +0 -103
- package/latticeai/core/workspace_permissions.py +0 -101
- package/latticeai/core/workspace_plugins.py +0 -97
- package/latticeai/core/workspace_relationships.py +0 -99
- package/latticeai/core/workspace_reorganization.py +0 -335
- package/latticeai/core/workspace_review_items.py +0 -112
- package/latticeai/core/workspace_runs.py +0 -726
- package/latticeai/core/workspace_skills.py +0 -109
- package/latticeai/core/workspace_snapshots.py +0 -198
- package/latticeai/core/workspace_timeline.py +0 -110
- package/latticeai/integrations/__init__.py +0 -0
- package/latticeai/integrations/telegram_bot/__init__.py +0 -123
- package/latticeai/integrations/telegram_bot/__main__.py +0 -17
- package/latticeai/integrations/telegram_bot/config.py +0 -86
- package/latticeai/integrations/telegram_bot/dispatch.py +0 -311
- package/latticeai/integrations/telegram_bot/flows.py +0 -478
- package/latticeai/integrations/telegram_bot/helpers.py +0 -322
- package/latticeai/integrations/telegram_bot/screens.py +0 -394
- package/latticeai/runtime/audit_runtime.py +0 -76
- package/latticeai/runtime/automation_runtime.py +0 -81
- package/latticeai/runtime/chat_wiring.py +0 -141
- package/latticeai/runtime/context_runtime.py +0 -66
- package/latticeai/runtime/feature_toggle_wiring.py +0 -157
- package/latticeai/runtime/history_runtime.py +0 -163
- package/latticeai/runtime/history_writer.py +0 -138
- package/latticeai/runtime/hooks_runtime.py +0 -77
- package/latticeai/runtime/model_wiring.py +0 -68
- package/latticeai/runtime/namespace_runtime.py +0 -163
- package/latticeai/runtime/network_boundary_wiring.py +0 -117
- package/latticeai/runtime/network_config_runtime.py +0 -56
- package/latticeai/runtime/permission_mode_wiring.py +0 -112
- package/latticeai/runtime/persistence_runtime.py +0 -159
- package/latticeai/runtime/platform_runtime_wiring.py +0 -89
- package/latticeai/runtime/review_wiring.py +0 -42
- package/latticeai/runtime/router_registration.py +0 -693
- package/latticeai/runtime/service_singletons.py +0 -55
- package/latticeai/runtime/sso_config_runtime.py +0 -128
- package/latticeai/runtime/user_key_runtime.py +0 -106
- package/latticeai/runtime/web_runtime.py +0 -92
- package/latticeai/server_app.py +0 -51
- package/latticeai/services/app_context.py +0 -130
- package/latticeai/services/automation_execution.py +0 -266
- package/latticeai/services/automation_intelligence.py +0 -614
- package/latticeai/services/brain_automation.py +0 -191
- package/latticeai/services/brain_intelligence/__init__.py +0 -58
- package/latticeai/services/brain_intelligence/_contract.py +0 -71
- package/latticeai/services/brain_intelligence/consistency.py +0 -193
- package/latticeai/services/brain_intelligence/constants.py +0 -47
- package/latticeai/services/brain_intelligence/digest.py +0 -258
- package/latticeai/services/brain_intelligence/health.py +0 -331
- package/latticeai/services/brain_intelligence/proposals.py +0 -259
- package/latticeai/services/brain_intelligence/sampling.py +0 -84
- package/latticeai/services/brain_intelligence/service.py +0 -48
- package/latticeai/services/change_proposals.py +0 -471
- package/latticeai/services/chat_service.py +0 -243
- package/latticeai/services/chronicle.py +0 -555
- package/latticeai/services/cloud_egress_audit.py +0 -85
- package/latticeai/services/cloud_extraction.py +0 -129
- package/latticeai/services/cloud_streaming.py +0 -268
- package/latticeai/services/cloud_token_guard.py +0 -84
- package/latticeai/services/command_center.py +0 -548
- package/latticeai/services/evidence_actions.py +0 -258
- package/latticeai/services/feature_toggles.py +0 -502
- package/latticeai/services/folder_watch.py +0 -520
- package/latticeai/services/funnel_metrics.py +0 -307
- package/latticeai/services/hybrid_chat.py +0 -316
- package/latticeai/services/hybrid_context.py +0 -228
- package/latticeai/services/hybrid_policy.py +0 -129
- package/latticeai/services/interop_bridges.py +0 -978
- package/latticeai/services/local_knowledge.py +0 -465
- package/latticeai/services/memory_service/__init__.py +0 -52
- package/latticeai/services/memory_service/_contract.py +0 -100
- package/latticeai/services/memory_service/brief.py +0 -431
- package/latticeai/services/memory_service/constants.py +0 -57
- package/latticeai/services/memory_service/maintenance.py +0 -138
- package/latticeai/services/memory_service/manager.py +0 -186
- package/latticeai/services/memory_service/proof.py +0 -136
- package/latticeai/services/memory_service/recall.py +0 -225
- package/latticeai/services/memory_service/service.py +0 -48
- package/latticeai/services/memory_service/stores.py +0 -110
- package/latticeai/services/mode_store.py +0 -132
- package/latticeai/services/model_recommendation.py +0 -224
- package/latticeai/services/model_runtime/cloud.py +0 -87
- package/latticeai/services/network_boundary_service.py +0 -117
- package/latticeai/services/obsidian_bridge.py +0 -609
- package/latticeai/services/openai_compatible_adapter.py +0 -101
- package/latticeai/services/permission_mode_service.py +0 -122
- package/latticeai/services/platform_runtime.py +0 -366
- package/latticeai/services/review_queue.py +0 -380
- package/latticeai/services/router_context.py +0 -59
- package/latticeai/services/run_executor.py +0 -387
- package/latticeai/services/self_model_service.py +0 -171
- package/latticeai/services/setup_detection.py +0 -147
- package/latticeai/services/triggers.py +0 -378
- package/latticeai/services/upload_service.py +0 -172
- package/latticeai/services/workspace_service.py +0 -165
- package/latticeai/setup/__init__.py +0 -25
- package/latticeai/setup/auto_setup.py +0 -846
- package/latticeai/setup/demo_corpus.py +0 -98
- package/latticeai/setup/wizard/__init__.py +0 -126
- package/latticeai/setup/wizard/catalog.py +0 -175
- package/latticeai/setup/wizard/detect.py +0 -302
- package/latticeai/setup/wizard/install.py +0 -348
- package/latticeai/setup/wizard/paths.py +0 -165
- package/latticeai/setup/wizard/plans.py +0 -74
- package/latticeai/setup/wizard/recommend.py +0 -320
- package/scripts/bench_agent_smoke.py +0 -409
- package/scripts/bench_models.py +0 -540
- package/scripts/bench_vector_index.py +0 -295
- package/scripts/funnel_soft_gate.py +0 -192
- package/scripts/generate_agent_loop_fixtures.py +0 -994
- package/scripts/generate_rust_parity_fixtures.py +0 -908
- package/scripts/migrate_brain_storage.py +0 -57
- package/scripts/parity_fixture_corpus_context.py +0 -162
- package/scripts/parity_fixture_corpus_docgen.py +0 -341
- package/scripts/profile_kg.py +0 -355
- package/server.py +0 -30
- package/static/app/assets/arrow-left-kfsrk0mv.js +0 -1
- package/static/app/assets/circle-check-qqLug9nU.js +0 -1
- package/static/app/assets/index-DxmOfNRi.css +0 -2
- package/static/app/assets/search-BcHqkjoy.js +0 -1
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
"""Explicit runtime exports for the legacy :mod:`server_app` facade.
|
|
2
|
-
|
|
3
|
-
The composition root must never export ``locals()``. Every compatibility name
|
|
4
|
-
is selected here and every typed assembly stage remains available through the
|
|
5
|
-
``RuntimeBundle`` without leaking construction scratch state.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
from __future__ import annotations
|
|
9
|
-
|
|
10
|
-
from dataclasses import dataclass
|
|
11
|
-
from typing import Any, Dict, Mapping
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
@dataclass(frozen=True)
|
|
15
|
-
class RuntimeBundle:
|
|
16
|
-
"""Typed application assembly result and its five explicit stages."""
|
|
17
|
-
|
|
18
|
-
app: Any
|
|
19
|
-
CONFIG: Any
|
|
20
|
-
KNOWLEDGE_GRAPH: Any
|
|
21
|
-
INGESTION_PIPELINE: Any
|
|
22
|
-
AGENT_RUNTIME: Any
|
|
23
|
-
HOOKS_REGISTRY: Any
|
|
24
|
-
REVIEW_QUEUE: Any
|
|
25
|
-
AGENT_REGISTRY: Any
|
|
26
|
-
model_router: Any
|
|
27
|
-
build_runtime: Any
|
|
28
|
-
get_shared_runtime: Any
|
|
29
|
-
create_app: Any
|
|
30
|
-
config_runtime: Any
|
|
31
|
-
security_runtime: Any
|
|
32
|
-
brain_runtime: Any
|
|
33
|
-
model_runtime: Any
|
|
34
|
-
router_bundle: Any
|
|
35
|
-
|
|
36
|
-
def as_legacy_dict(self) -> Dict[str, Any]:
|
|
37
|
-
return {
|
|
38
|
-
name: getattr(self, name)
|
|
39
|
-
for name in RUNTIME_BUNDLE_EXPORTS
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
@property
|
|
43
|
-
def stages(self) -> Dict[str, Any]:
|
|
44
|
-
return {
|
|
45
|
-
"config": self.config_runtime,
|
|
46
|
-
"security": self.security_runtime,
|
|
47
|
-
"brain": self.brain_runtime,
|
|
48
|
-
"models": self.model_runtime,
|
|
49
|
-
"routers": self.router_bundle,
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
RUNTIME_BUNDLE_EXPORTS = frozenset(
|
|
54
|
-
{
|
|
55
|
-
"app",
|
|
56
|
-
"CONFIG",
|
|
57
|
-
"KNOWLEDGE_GRAPH",
|
|
58
|
-
"INGESTION_PIPELINE",
|
|
59
|
-
"AGENT_RUNTIME",
|
|
60
|
-
"HOOKS_REGISTRY",
|
|
61
|
-
"REVIEW_QUEUE",
|
|
62
|
-
"AGENT_REGISTRY",
|
|
63
|
-
"model_router",
|
|
64
|
-
"build_runtime",
|
|
65
|
-
"get_shared_runtime",
|
|
66
|
-
"create_app",
|
|
67
|
-
}
|
|
68
|
-
)
|
|
69
|
-
|
|
70
|
-
LEGACY_UNDERSCORE_EXPORTS = {
|
|
71
|
-
"_LOCAL_WRITE_BLOCKED_PREFIXES",
|
|
72
|
-
"_RATE_LIMIT_ENABLED",
|
|
73
|
-
"_SESSION_TTL",
|
|
74
|
-
"_TOOL_CATALOG_BRIEF",
|
|
75
|
-
"_TOOL_GOVERNANCE_DEFAULT",
|
|
76
|
-
"_agent_risk",
|
|
77
|
-
"_allowed_workspaces_for",
|
|
78
|
-
"_build_admin_audit_report",
|
|
79
|
-
"_build_sensitivity_report",
|
|
80
|
-
"_bytes_match_extension",
|
|
81
|
-
"_check_ip_rate_limit",
|
|
82
|
-
"_check_rate_limit",
|
|
83
|
-
"_check_tool_role",
|
|
84
|
-
"_classify_sensitive_message",
|
|
85
|
-
"_client_ip",
|
|
86
|
-
"_create_security_router",
|
|
87
|
-
"_embedding_info",
|
|
88
|
-
"_fetch_skills_marketplace",
|
|
89
|
-
"_get_audit_log",
|
|
90
|
-
"_get_sso_discovery",
|
|
91
|
-
"_graph_stats_safe",
|
|
92
|
-
"_host_is_loopback",
|
|
93
|
-
"_list_compat_profiles",
|
|
94
|
-
"_llm_generate_sync",
|
|
95
|
-
"_product_hardening_status",
|
|
96
|
-
"_recent_chat_context",
|
|
97
|
-
"_redact_secret_text",
|
|
98
|
-
"_require_graph",
|
|
99
|
-
"_scoped_hybrid_search",
|
|
100
|
-
"_security_audit_events_safe",
|
|
101
|
-
"_security_list_uploaded_files",
|
|
102
|
-
"_spawn",
|
|
103
|
-
"_tool_response",
|
|
104
|
-
"_user_id_for_email",
|
|
105
|
-
"_workspace_graph",
|
|
106
|
-
"_workspace_models_payload",
|
|
107
|
-
"_workspace_scope_from_request",
|
|
108
|
-
"_workspace_settings_payload",
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
LEGACY_PUBLIC_EXPORTS = {
|
|
112
|
-
"ENGINE_MODEL_CATALOG",
|
|
113
|
-
"TOOL_GOVERNANCE",
|
|
114
|
-
"enforce_rate_limit",
|
|
115
|
-
"filter_lower_family_versions",
|
|
116
|
-
"hash_password",
|
|
117
|
-
"normalize_local_model_request",
|
|
118
|
-
"verify_password",
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
def build_runtime_namespace(
|
|
123
|
-
*, runtime_bundle: RuntimeBundle | Mapping[str, Any], legacy_exports: Mapping[str, Any]
|
|
124
|
-
) -> Dict[str, Any]:
|
|
125
|
-
"""Return only explicit compatibility exports and typed bundle handles."""
|
|
126
|
-
legacy_bundle = (
|
|
127
|
-
runtime_bundle.as_legacy_dict()
|
|
128
|
-
if isinstance(runtime_bundle, RuntimeBundle)
|
|
129
|
-
else dict(runtime_bundle)
|
|
130
|
-
)
|
|
131
|
-
exported: Dict[str, Any] = dict(legacy_bundle)
|
|
132
|
-
allowed = LEGACY_PUBLIC_EXPORTS | LEGACY_UNDERSCORE_EXPORTS
|
|
133
|
-
unexpected = set(legacy_exports) - allowed
|
|
134
|
-
if unexpected:
|
|
135
|
-
raise ValueError(f"unapproved runtime exports: {sorted(unexpected)}")
|
|
136
|
-
for name in sorted(allowed):
|
|
137
|
-
if name in exported:
|
|
138
|
-
continue
|
|
139
|
-
value = legacy_exports.get(name)
|
|
140
|
-
if value is None:
|
|
141
|
-
continue
|
|
142
|
-
exported[name] = value
|
|
143
|
-
exported["RUNTIME_BUNDLE"] = runtime_bundle
|
|
144
|
-
exported["_RUNTIME_BUNDLE"] = legacy_bundle
|
|
145
|
-
return exported
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
SERVER_APP_EXPORTS = frozenset(
|
|
149
|
-
RUNTIME_BUNDLE_EXPORTS
|
|
150
|
-
| LEGACY_PUBLIC_EXPORTS
|
|
151
|
-
| LEGACY_UNDERSCORE_EXPORTS
|
|
152
|
-
| {"RUNTIME_BUNDLE", "_RUNTIME_BUNDLE"}
|
|
153
|
-
)
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
__all__ = [
|
|
157
|
-
"LEGACY_UNDERSCORE_EXPORTS",
|
|
158
|
-
"LEGACY_PUBLIC_EXPORTS",
|
|
159
|
-
"RUNTIME_BUNDLE_EXPORTS",
|
|
160
|
-
"RuntimeBundle",
|
|
161
|
-
"SERVER_APP_EXPORTS",
|
|
162
|
-
"build_runtime_namespace",
|
|
163
|
-
]
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
"""Wire NetworkBoundaryMode + HybridPolicy into the running app (Phase 1–3)."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
import os
|
|
6
|
-
import threading
|
|
7
|
-
from pathlib import Path
|
|
8
|
-
from typing import Any, Callable, Optional
|
|
9
|
-
|
|
10
|
-
from latticeai.core.network_boundary import (
|
|
11
|
-
DEFAULT_NETWORK_MODE,
|
|
12
|
-
normalize_network_mode,
|
|
13
|
-
)
|
|
14
|
-
from latticeai.runtime.service_singletons import (
|
|
15
|
-
rebind_singleton,
|
|
16
|
-
singleton_data_dir,
|
|
17
|
-
)
|
|
18
|
-
from latticeai.services.hybrid_policy import HybridPolicyService
|
|
19
|
-
from latticeai.services.network_boundary_service import NetworkBoundaryService
|
|
20
|
-
|
|
21
|
-
_LOCK = threading.Lock()
|
|
22
|
-
_SHARED: Optional[NetworkBoundaryService] = None
|
|
23
|
-
_POLICY: Optional[HybridPolicyService] = None
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
def _env_default_mode() -> Any:
|
|
27
|
-
return normalize_network_mode(
|
|
28
|
-
os.environ.get("LATTICEAI_NETWORK_MODE", DEFAULT_NETWORK_MODE.value)
|
|
29
|
-
)
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
def get_network_boundary_service(
|
|
33
|
-
*,
|
|
34
|
-
data_dir: Optional[Path] = None,
|
|
35
|
-
audit: Optional[Callable[..., None]] = None,
|
|
36
|
-
) -> NetworkBoundaryService:
|
|
37
|
-
global _SHARED
|
|
38
|
-
with _LOCK:
|
|
39
|
-
if _SHARED is None:
|
|
40
|
-
_SHARED = NetworkBoundaryService(
|
|
41
|
-
data_dir=singleton_data_dir(data_dir),
|
|
42
|
-
default_mode=_env_default_mode(),
|
|
43
|
-
audit=audit,
|
|
44
|
-
)
|
|
45
|
-
return _SHARED
|
|
46
|
-
return rebind_singleton(_SHARED, data_dir=data_dir, audit=audit)
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
def get_hybrid_policy_service(
|
|
50
|
-
*,
|
|
51
|
-
data_dir: Optional[Path] = None,
|
|
52
|
-
audit: Optional[Callable[..., None]] = None,
|
|
53
|
-
) -> HybridPolicyService:
|
|
54
|
-
global _POLICY
|
|
55
|
-
with _LOCK:
|
|
56
|
-
if _POLICY is None:
|
|
57
|
-
_POLICY = HybridPolicyService(
|
|
58
|
-
data_dir=singleton_data_dir(data_dir),
|
|
59
|
-
audit=audit,
|
|
60
|
-
)
|
|
61
|
-
return _POLICY
|
|
62
|
-
return rebind_singleton(_POLICY, data_dir=data_dir, audit=audit)
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
def resolve_active_network_mode(
|
|
66
|
-
*,
|
|
67
|
-
user_email: Optional[str] = None,
|
|
68
|
-
workspace_id: Optional[str] = None,
|
|
69
|
-
) -> Any:
|
|
70
|
-
return get_network_boundary_service().resolve(
|
|
71
|
-
user_email=user_email, workspace_id=workspace_id,
|
|
72
|
-
)
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
def register_network_boundary_router(
|
|
76
|
-
app: Any,
|
|
77
|
-
*,
|
|
78
|
-
require_user: Callable[..., str],
|
|
79
|
-
data_dir: Optional[Path] = None,
|
|
80
|
-
append_audit_event: Optional[Callable[..., None]] = None,
|
|
81
|
-
knowledge_graph: Any = None,
|
|
82
|
-
) -> Any:
|
|
83
|
-
from latticeai.api.network_boundary import create_network_boundary_router
|
|
84
|
-
from latticeai.services.cloud_egress_audit import bind_egress_audit
|
|
85
|
-
|
|
86
|
-
svc = get_network_boundary_service(data_dir=data_dir, audit=append_audit_event)
|
|
87
|
-
policy = get_hybrid_policy_service(data_dir=data_dir, audit=append_audit_event)
|
|
88
|
-
# The dial's own changes were audited from 10.1.0; the sends were not.
|
|
89
|
-
# Bind the same sink so egress lands in the same log.
|
|
90
|
-
bind_egress_audit(append_audit_event)
|
|
91
|
-
# Skip if already mounted (re-entrant factory / tests). Flag on app.state
|
|
92
|
-
# rather than a route-path scan: fastapi >= 0.140 wraps an included router
|
|
93
|
-
# in an opaque entry whose flat ``path`` is None, so path introspection
|
|
94
|
-
# stopped seeing the mount and a re-entrant call duplicated the routes.
|
|
95
|
-
# This function is the only in-tree mount site for this router.
|
|
96
|
-
state = getattr(app, "state", None)
|
|
97
|
-
if state is not None and getattr(state, "_ltcai_network_boundary_mounted", False):
|
|
98
|
-
return svc
|
|
99
|
-
app.include_router(
|
|
100
|
-
create_network_boundary_router(
|
|
101
|
-
service=svc,
|
|
102
|
-
require_user=require_user,
|
|
103
|
-
knowledge_graph=knowledge_graph,
|
|
104
|
-
policy_service=policy,
|
|
105
|
-
)
|
|
106
|
-
)
|
|
107
|
-
if state is not None:
|
|
108
|
-
state._ltcai_network_boundary_mounted = True
|
|
109
|
-
return svc
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
__all__ = [
|
|
113
|
-
"get_network_boundary_service",
|
|
114
|
-
"get_hybrid_policy_service",
|
|
115
|
-
"resolve_active_network_mode",
|
|
116
|
-
"register_network_boundary_router",
|
|
117
|
-
]
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
"""VPC network-profile config seam extracted from the legacy app factory.
|
|
2
|
-
|
|
3
|
-
``DEFAULT_VPC_CONFIG`` and the load/save helpers used to live inline in
|
|
4
|
-
``app_factory._build``. Behaviour and exported names are preserved exactly for
|
|
5
|
-
the legacy ``server_app`` compatibility namespace; the only change is that they
|
|
6
|
-
now live behind a builder so the factory stays a wiring path.
|
|
7
|
-
"""
|
|
8
|
-
|
|
9
|
-
from __future__ import annotations
|
|
10
|
-
|
|
11
|
-
import json
|
|
12
|
-
import os
|
|
13
|
-
from datetime import datetime
|
|
14
|
-
from pathlib import Path
|
|
15
|
-
from typing import Any, Dict
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
def build_vpc_runtime(*, vpc_file: Path, logging: Any) -> Dict[str, Any]:
|
|
19
|
-
"""Return ``DEFAULT_VPC_CONFIG`` and the VPC load/save helpers."""
|
|
20
|
-
|
|
21
|
-
default_vpc_config: Dict[str, Any] = {
|
|
22
|
-
"provider": "AWS",
|
|
23
|
-
"region": "ap-northeast-2",
|
|
24
|
-
"cidr_block": "10.42.0.0/16",
|
|
25
|
-
"private_subnets": ["10.42.10.0/24", "10.42.20.0/24"],
|
|
26
|
-
"endpoint": "ltcai-private.local",
|
|
27
|
-
"vpn_status": "standby",
|
|
28
|
-
"peering_status": "not_configured",
|
|
29
|
-
"notes": "로컬 MLX 브릿지를 프라이빗 서브넷 또는 VPN 뒤에서 운영할 때 쓰는 네트워크 프로필입니다.",
|
|
30
|
-
"updated_at": None,
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
def load_vpc_config() -> Dict:
|
|
34
|
-
if not os.path.exists(vpc_file):
|
|
35
|
-
return default_vpc_config.copy()
|
|
36
|
-
try:
|
|
37
|
-
with open(vpc_file, "r", encoding="utf-8") as f:
|
|
38
|
-
stored = json.load(f)
|
|
39
|
-
return {**default_vpc_config, **stored}
|
|
40
|
-
except Exception as e:
|
|
41
|
-
logging.warning("load_vpc_config failed (using defaults): %s", e)
|
|
42
|
-
return default_vpc_config.copy()
|
|
43
|
-
|
|
44
|
-
def save_vpc_config(config: Dict) -> None:
|
|
45
|
-
config["updated_at"] = datetime.now().isoformat()
|
|
46
|
-
with open(vpc_file, "w", encoding="utf-8") as f:
|
|
47
|
-
json.dump(config, f, ensure_ascii=False, indent=2)
|
|
48
|
-
|
|
49
|
-
return {
|
|
50
|
-
"DEFAULT_VPC_CONFIG": default_vpc_config,
|
|
51
|
-
"load_vpc_config": load_vpc_config,
|
|
52
|
-
"save_vpc_config": save_vpc_config,
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
__all__ = ["build_vpc_runtime"]
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
"""Wire PermissionMode into the running app without a large app_factory rewrite.
|
|
2
|
-
|
|
3
|
-
Creates one process-wide :class:`PermissionModeService`, points
|
|
4
|
-
``ToolDispatchService.permission_mode`` at it, and registers the HTTP dial.
|
|
5
|
-
Called from ``register_review_and_brain_tail_routers`` (which already has
|
|
6
|
-
``data_dir``, ``require_user``, ``append_audit_event``) and from
|
|
7
|
-
``build_chat_agent_runtime_from_context`` so the agent loop sees the same dial.
|
|
8
|
-
"""
|
|
9
|
-
|
|
10
|
-
from __future__ import annotations
|
|
11
|
-
|
|
12
|
-
import os
|
|
13
|
-
import threading
|
|
14
|
-
from pathlib import Path
|
|
15
|
-
from typing import Any, Callable, Optional
|
|
16
|
-
|
|
17
|
-
from latticeai.core.permission_mode import DEFAULT_MODE, normalize_mode
|
|
18
|
-
from latticeai.runtime.service_singletons import (
|
|
19
|
-
rebind_singleton,
|
|
20
|
-
singleton_data_dir,
|
|
21
|
-
)
|
|
22
|
-
from latticeai.services.permission_mode_service import PermissionModeService
|
|
23
|
-
|
|
24
|
-
_LOCK = threading.Lock()
|
|
25
|
-
_SHARED: Optional[PermissionModeService] = None
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
def _env_default_mode() -> Any:
|
|
29
|
-
return normalize_mode(os.environ.get("LATTICEAI_PERMISSION_MODE", DEFAULT_MODE.value))
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
def get_permission_mode_service(
|
|
33
|
-
*,
|
|
34
|
-
data_dir: Optional[Path] = None,
|
|
35
|
-
audit: Optional[Callable[..., None]] = None,
|
|
36
|
-
) -> PermissionModeService:
|
|
37
|
-
"""Process-wide singleton.
|
|
38
|
-
|
|
39
|
-
An early lazy caller (a tool dispatch before routers are mounted) would
|
|
40
|
-
otherwise pin the service to the fallback ``data_dir`` with no audit sink.
|
|
41
|
-
Explicit arguments therefore *rebind* an already-created service instead of
|
|
42
|
-
being silently dropped, so the app's real data dir and audit log always win.
|
|
43
|
-
"""
|
|
44
|
-
global _SHARED
|
|
45
|
-
with _LOCK:
|
|
46
|
-
if _SHARED is None:
|
|
47
|
-
_SHARED = PermissionModeService(
|
|
48
|
-
data_dir=singleton_data_dir(data_dir),
|
|
49
|
-
default_mode=_env_default_mode(),
|
|
50
|
-
audit=audit,
|
|
51
|
-
)
|
|
52
|
-
return _SHARED
|
|
53
|
-
return rebind_singleton(_SHARED, data_dir=data_dir, audit=audit)
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
def resolve_active_permission_mode(
|
|
57
|
-
*,
|
|
58
|
-
user_email: Optional[str] = None,
|
|
59
|
-
workspace_id: Optional[str] = None,
|
|
60
|
-
) -> Any:
|
|
61
|
-
return get_permission_mode_service().resolve(
|
|
62
|
-
user_email=user_email, workspace_id=workspace_id,
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
def bind_dispatch_permission_mode(dispatch_service: Any = None) -> None:
|
|
67
|
-
"""Point tool dispatch at the shared mode resolver.
|
|
68
|
-
|
|
69
|
-
The bound callable accepts scope kwargs so per-user and per-workspace
|
|
70
|
-
overrides actually reach ``enforce_policy`` — an unscoped resolver would
|
|
71
|
-
always return the process-wide default and make the dial a no-op.
|
|
72
|
-
"""
|
|
73
|
-
from latticeai.services.tool_dispatch import DEFAULT_TOOL_DISPATCH_SERVICE
|
|
74
|
-
|
|
75
|
-
service = dispatch_service or DEFAULT_TOOL_DISPATCH_SERVICE
|
|
76
|
-
service.permission_mode = resolve_active_permission_mode
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
def register_permission_mode_router(
|
|
80
|
-
app: Any,
|
|
81
|
-
*,
|
|
82
|
-
require_user: Callable[..., str],
|
|
83
|
-
data_dir: Optional[Path] = None,
|
|
84
|
-
append_audit_event: Optional[Callable[..., None]] = None,
|
|
85
|
-
) -> Any:
|
|
86
|
-
"""Install GET/POST /api/permission-mode on ``app``. Idempotent by route path."""
|
|
87
|
-
from latticeai.api.permission_mode import create_permission_mode_router
|
|
88
|
-
|
|
89
|
-
svc = get_permission_mode_service(data_dir=data_dir, audit=append_audit_event)
|
|
90
|
-
bind_dispatch_permission_mode()
|
|
91
|
-
# Skip if already mounted (re-entrant factory / tests). The guard is a flag
|
|
92
|
-
# on app.state rather than a scan of route paths: fastapi >= 0.140 wraps an
|
|
93
|
-
# included router in an opaque entry whose flat ``path`` is None, so path
|
|
94
|
-
# introspection stopped seeing the mount and a re-entrant call duplicated
|
|
95
|
-
# the routes. This function is the only in-tree mount site for this router.
|
|
96
|
-
state = getattr(app, "state", None)
|
|
97
|
-
if state is not None and getattr(state, "_ltcai_permission_mode_mounted", False):
|
|
98
|
-
return svc
|
|
99
|
-
app.include_router(
|
|
100
|
-
create_permission_mode_router(service=svc, require_user=require_user)
|
|
101
|
-
)
|
|
102
|
-
if state is not None:
|
|
103
|
-
state._ltcai_permission_mode_mounted = True
|
|
104
|
-
return svc
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
__all__ = [
|
|
108
|
-
"get_permission_mode_service",
|
|
109
|
-
"resolve_active_permission_mode",
|
|
110
|
-
"bind_dispatch_permission_mode",
|
|
111
|
-
"register_permission_mode_router",
|
|
112
|
-
]
|
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
"""Persistence/service assembly seams for app startup.
|
|
2
|
-
|
|
3
|
-
This module owns the durable local stores and services that sit between the
|
|
4
|
-
Brain runtime and API routers. Imports stay inside the function so importing
|
|
5
|
-
``latticeai.app_factory`` remains side-effect free.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
from __future__ import annotations
|
|
9
|
-
|
|
10
|
-
from typing import Any, Callable, Dict, Optional
|
|
11
|
-
|
|
12
|
-
from latticeai.core.quiet import quiet
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
def build_persistence_runtime(
|
|
16
|
-
*,
|
|
17
|
-
data_dir: Any,
|
|
18
|
-
base_dir: Any,
|
|
19
|
-
enable_graph: bool,
|
|
20
|
-
knowledge_graph: Any,
|
|
21
|
-
hooks_registry: Any,
|
|
22
|
-
history_file: Any,
|
|
23
|
-
conversations: Any,
|
|
24
|
-
user_id_for_email: Callable[[Optional[str]], Optional[str]],
|
|
25
|
-
audit: Callable[[str, Dict[str, Any], Optional[str]], None],
|
|
26
|
-
) -> Dict[str, Any]:
|
|
27
|
-
"""Construct workspace, plugin, memory, ingestion, and portability services."""
|
|
28
|
-
|
|
29
|
-
import os
|
|
30
|
-
from pathlib import Path
|
|
31
|
-
|
|
32
|
-
from lattice_brain.graph.identity import DeviceIdentity
|
|
33
|
-
from lattice_brain.ingestion import IngestionPipeline
|
|
34
|
-
from lattice_brain.portability import KGPortabilityService
|
|
35
|
-
from latticeai.core.agent_registry import AgentRegistry
|
|
36
|
-
from latticeai.core.invitations import InvitationStore
|
|
37
|
-
from latticeai.core.marketplace import TemplateCatalog
|
|
38
|
-
from latticeai.core.plugins import PluginRegistry
|
|
39
|
-
from latticeai.core.realtime import RealtimeBus
|
|
40
|
-
from latticeai.core.workspace_os import WorkspaceOSStore
|
|
41
|
-
from latticeai.services.automation_intelligence import AutomationIntelligenceService
|
|
42
|
-
from latticeai.services.brain_intelligence import BrainIntelligenceService
|
|
43
|
-
from latticeai.services.funnel_metrics import FunnelMetricsService
|
|
44
|
-
from latticeai.services.memory_service import MemoryService
|
|
45
|
-
from latticeai.services.multimodal_ports import (
|
|
46
|
-
build_multimodal_ports,
|
|
47
|
-
multimodal_enabled,
|
|
48
|
-
)
|
|
49
|
-
from latticeai.services.workspace_service import WorkspaceService
|
|
50
|
-
|
|
51
|
-
realtime_bus = RealtimeBus()
|
|
52
|
-
workspace_os = WorkspaceOSStore(data_dir, event_sink=realtime_bus)
|
|
53
|
-
workspace_service = WorkspaceService(workspace_os, resolve_user_id=user_id_for_email)
|
|
54
|
-
invitation_store = InvitationStore(data_dir / "invitations.json")
|
|
55
|
-
|
|
56
|
-
plugins_dir = Path(os.getenv("LATTICEAI_PLUGINS_DIR") or (base_dir / "plugins"))
|
|
57
|
-
plugin_registry = PluginRegistry(plugins_dir, store=workspace_os)
|
|
58
|
-
template_catalog = TemplateCatalog()
|
|
59
|
-
agent_registry = AgentRegistry(data_dir / "agent_registry.json")
|
|
60
|
-
|
|
61
|
-
memory_service = MemoryService(
|
|
62
|
-
store=workspace_os,
|
|
63
|
-
data_dir=data_dir,
|
|
64
|
-
knowledge_graph=knowledge_graph,
|
|
65
|
-
enable_graph=enable_graph,
|
|
66
|
-
history_file=history_file,
|
|
67
|
-
conversation_store=conversations,
|
|
68
|
-
)
|
|
69
|
-
brain_intelligence = BrainIntelligenceService(
|
|
70
|
-
knowledge_graph=knowledge_graph,
|
|
71
|
-
memory_service=memory_service,
|
|
72
|
-
enable_graph=enable_graph,
|
|
73
|
-
)
|
|
74
|
-
automation_intelligence = AutomationIntelligenceService(
|
|
75
|
-
conversation_store=conversations,
|
|
76
|
-
knowledge_graph=knowledge_graph,
|
|
77
|
-
store=workspace_os,
|
|
78
|
-
enable_graph=enable_graph,
|
|
79
|
-
)
|
|
80
|
-
# UX funnel metrics (backlog #16): cheap JSON counters under the data dir.
|
|
81
|
-
# The ingestion pipeline's audit seam is wrapped so every successful
|
|
82
|
-
# ingest bumps the funnel (and starts the TTFV clock) without touching
|
|
83
|
-
# lattice_brain internals.
|
|
84
|
-
funnel_metrics = FunnelMetricsService(Path(data_dir) / "funnel_metrics.json")
|
|
85
|
-
|
|
86
|
-
def _funnel_audit(action, detail, user):
|
|
87
|
-
"""Best-effort sinks for a landed ingest, then the real audit.
|
|
88
|
-
|
|
89
|
-
Both sinks are isolated separately: one failing must not cost the
|
|
90
|
-
other, and neither may cost the ingest that is already persisted.
|
|
91
|
-
"""
|
|
92
|
-
if action == "kg_ingest":
|
|
93
|
-
try:
|
|
94
|
-
funnel_metrics.record_ingest(
|
|
95
|
-
duplicate=bool((detail or {}).get("duplicate"))
|
|
96
|
-
)
|
|
97
|
-
except Exception: # noqa: BLE001 — metrics must never break ingestion
|
|
98
|
-
quiet()
|
|
99
|
-
# v11.1.0: the same seam drives synthesis. The pipeline audits an
|
|
100
|
-
# ingest only after the graph write landed, so ``status: "ok"`` is
|
|
101
|
-
# a fact about this call site rather than a guess; ``duplicate``
|
|
102
|
-
# travels in the detail and is what keeps a re-import from pushing
|
|
103
|
-
# the Brain toward a pass it has nothing new to say in.
|
|
104
|
-
try:
|
|
105
|
-
brain_intelligence.note_ingest(
|
|
106
|
-
{"status": "ok", **(detail or {})}, user_email=user
|
|
107
|
-
)
|
|
108
|
-
except Exception: # noqa: BLE001 — synthesis must never break ingestion
|
|
109
|
-
quiet()
|
|
110
|
-
audit(action, detail, user)
|
|
111
|
-
|
|
112
|
-
# Multi-modal capture (v11.1.0): off unless the user turned it on, and
|
|
113
|
-
# even then only as capable as the models actually present. With nothing
|
|
114
|
-
# configured this resolves to an empty bundle without importing or loading
|
|
115
|
-
# anything.
|
|
116
|
-
multimodal_ports = build_multimodal_ports()
|
|
117
|
-
ingestion_pipeline = IngestionPipeline(
|
|
118
|
-
knowledge_graph,
|
|
119
|
-
hooks=hooks_registry,
|
|
120
|
-
enable_graph=enable_graph,
|
|
121
|
-
audit=_funnel_audit,
|
|
122
|
-
allow_multimodal=multimodal_enabled(),
|
|
123
|
-
multimodal=multimodal_ports,
|
|
124
|
-
)
|
|
125
|
-
# The local folder scanner reads images through the same ports, so a
|
|
126
|
-
# caption in the Evidence panel and a caption on a scanned screenshot come
|
|
127
|
-
# from one model or from none. A disabled/absent graph has nothing to
|
|
128
|
-
# attach them to, and a store that refuses new attributes is not a reason
|
|
129
|
-
# to fail startup.
|
|
130
|
-
try:
|
|
131
|
-
knowledge_graph.multimodal_ports = multimodal_ports
|
|
132
|
-
except AttributeError:
|
|
133
|
-
quiet()
|
|
134
|
-
device_identity = DeviceIdentity(data_dir)
|
|
135
|
-
kg_portability = KGPortabilityService(
|
|
136
|
-
knowledge_graph=knowledge_graph,
|
|
137
|
-
data_dir=data_dir,
|
|
138
|
-
enable_graph=enable_graph,
|
|
139
|
-
device_identity=device_identity,
|
|
140
|
-
)
|
|
141
|
-
|
|
142
|
-
return {
|
|
143
|
-
"REALTIME_BUS": realtime_bus,
|
|
144
|
-
"WORKSPACE_OS": workspace_os,
|
|
145
|
-
"WORKSPACE_SERVICE": workspace_service,
|
|
146
|
-
"INVITATION_STORE": invitation_store,
|
|
147
|
-
"PLUGINS_DIR": plugins_dir,
|
|
148
|
-
"PLUGIN_REGISTRY": plugin_registry,
|
|
149
|
-
"TEMPLATE_CATALOG": template_catalog,
|
|
150
|
-
"AGENT_REGISTRY": agent_registry,
|
|
151
|
-
"MEMORY_SERVICE": memory_service,
|
|
152
|
-
"BRAIN_INTELLIGENCE": brain_intelligence,
|
|
153
|
-
"AUTOMATION_INTELLIGENCE": automation_intelligence,
|
|
154
|
-
"INGESTION_PIPELINE": ingestion_pipeline,
|
|
155
|
-
"MULTIMODAL_PORTS": multimodal_ports,
|
|
156
|
-
"DEVICE_IDENTITY": device_identity,
|
|
157
|
-
"KG_PORTABILITY": kg_portability,
|
|
158
|
-
"FUNNEL_METRICS": funnel_metrics,
|
|
159
|
-
}
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
"""Platform and automation wiring for the application factory.
|
|
2
|
-
|
|
3
|
-
This module owns the cross-subsystem runtime assembly that used to live inline
|
|
4
|
-
inside ``app_factory._build``. Keeping it here reduces the app factory's global
|
|
5
|
-
surface without changing router order or the legacy exported runtime names.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
from __future__ import annotations
|
|
9
|
-
|
|
10
|
-
from typing import Any, Callable, Dict, Optional
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def build_platform_automation_runtime(
|
|
14
|
-
*,
|
|
15
|
-
model_router: Any,
|
|
16
|
-
workspace_store: Any,
|
|
17
|
-
workspace_service: Any,
|
|
18
|
-
plugin_registry: Any,
|
|
19
|
-
get_current_user: Callable[..., Any],
|
|
20
|
-
workspace_graph: Callable[[], Any],
|
|
21
|
-
workspace_scope_from_request: Callable[..., Any],
|
|
22
|
-
get_tool_permission: Callable[..., Any],
|
|
23
|
-
hooks: Any,
|
|
24
|
-
agent_registry: Any,
|
|
25
|
-
data_dir: Any,
|
|
26
|
-
append_audit_event: Callable[..., Any],
|
|
27
|
-
memory_service: Any = None,
|
|
28
|
-
tz_name: Optional[str] = None,
|
|
29
|
-
) -> Dict[str, Any]:
|
|
30
|
-
"""Build platform services, automation services, and hook bindings.
|
|
31
|
-
|
|
32
|
-
The returned names intentionally match the explicit composition-root
|
|
33
|
-
bindings consumed by the typed application stages.
|
|
34
|
-
"""
|
|
35
|
-
from latticeai.runtime.automation_runtime import build_automation_runtime
|
|
36
|
-
from latticeai.services.platform_runtime import PlatformRuntime
|
|
37
|
-
|
|
38
|
-
def _llm_generate_sync(
|
|
39
|
-
message: str,
|
|
40
|
-
context: str = "",
|
|
41
|
-
max_tokens: int = 1024,
|
|
42
|
-
temperature: float = 0.1,
|
|
43
|
-
) -> str:
|
|
44
|
-
# Synchronous model bridge for the orchestrator's role runner. Safe
|
|
45
|
-
# because the agents run endpoint executes start() in a worker thread
|
|
46
|
-
# (asyncio.to_thread), where no event loop is running.
|
|
47
|
-
import asyncio as _asyncio
|
|
48
|
-
|
|
49
|
-
return str(_asyncio.run(model_router.generate(
|
|
50
|
-
message,
|
|
51
|
-
context=context,
|
|
52
|
-
max_tokens=max_tokens,
|
|
53
|
-
temperature=temperature,
|
|
54
|
-
)))
|
|
55
|
-
|
|
56
|
-
platform = PlatformRuntime(
|
|
57
|
-
store=workspace_store,
|
|
58
|
-
workspace_service=workspace_service,
|
|
59
|
-
plugin_registry=plugin_registry,
|
|
60
|
-
get_current_user=get_current_user,
|
|
61
|
-
workspace_graph=workspace_graph,
|
|
62
|
-
workspace_scope_from_request=workspace_scope_from_request,
|
|
63
|
-
get_tool_permission=get_tool_permission,
|
|
64
|
-
hooks=hooks,
|
|
65
|
-
llm_generate=_llm_generate_sync,
|
|
66
|
-
llm_available=lambda: bool(getattr(model_router, "current_model_id", None)),
|
|
67
|
-
agent_registry=agent_registry,
|
|
68
|
-
memory_recall=memory_service.recall if memory_service is not None else None,
|
|
69
|
-
)
|
|
70
|
-
|
|
71
|
-
automation_runtime = build_automation_runtime(
|
|
72
|
-
store=workspace_store,
|
|
73
|
-
platform=platform,
|
|
74
|
-
data_dir=data_dir,
|
|
75
|
-
workspace_graph=workspace_graph,
|
|
76
|
-
append_audit_event=append_audit_event,
|
|
77
|
-
hooks=hooks,
|
|
78
|
-
tz_name=tz_name,
|
|
79
|
-
)
|
|
80
|
-
|
|
81
|
-
return {
|
|
82
|
-
"_llm_generate_sync": _llm_generate_sync,
|
|
83
|
-
"PLATFORM": platform,
|
|
84
|
-
"_automation_runtime": automation_runtime,
|
|
85
|
-
"REVIEW_QUEUE": automation_runtime["REVIEW_QUEUE"],
|
|
86
|
-
"TRIGGER_SERVICE": automation_runtime["TRIGGER_SERVICE"],
|
|
87
|
-
"AGENT_RUNTIME": automation_runtime["AGENT_RUNTIME"],
|
|
88
|
-
"RUN_EXECUTOR": automation_runtime["RUN_EXECUTOR"],
|
|
89
|
-
}
|