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.
- package/README.md +93 -148
- package/bin/ltcai.js +234 -24
- package/docs/CHANGELOG.md +119 -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 +54 -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-BPcVAbOL.js} +1 -1
- package/static/app/assets/AdminConsole-Bw1ATQL0.js +1 -0
- package/static/app/assets/{Brain-3VCSHFcn.js → Brain-CT92Kos0.js} +2 -2
- package/static/app/assets/{BrainHome-Qm8eaztx.js → BrainHome-CFBkt1K_.js} +1 -1
- package/static/app/assets/{BrainSignals-DS9BtKOW.js → BrainSignals-ReLWF2H8.js} +1 -1
- package/static/app/assets/Capture-BsTokYkk.js +1 -0
- package/static/app/assets/{Chronicle-BGvuAchH.js → Chronicle-B6f0T9id.js} +1 -1
- package/static/app/assets/{CommandPalette-Bqhm0Urn.js → CommandPalette-CuvjTv1u.js} +1 -1
- package/static/app/assets/{Library-BV6NnF0a.js → Library-BGJbG9Hd.js} +1 -1
- package/static/app/assets/{LivingBrain-GzenJchP.js → LivingBrain-DGYK_Jsa.js} +1 -1
- package/static/app/assets/{ProductFlow-DEP6-vML.js → ProductFlow-DXBC6brE.js} +1 -1
- package/static/app/assets/{ReviewCard-CNZ7XjWG.js → ReviewCard-HXRle3qq.js} +2 -2
- package/static/app/assets/System-CMHSO9qM.js +1 -0
- package/static/app/assets/arrow-left-BfmkskWx.js +1 -0
- package/static/app/assets/{bot-B_K1Tdmw.js → bot-Cn8bWRuq.js} +1 -1
- package/static/app/assets/{brain-DWyaV1L1.js → brain-CQJberbE.js} +1 -1
- package/static/app/assets/{button-aTn4s84A.js → button-Ct9f2_oT.js} +1 -1
- package/static/app/assets/circle-check-DruOxB-4.js +1 -0
- package/static/app/assets/{circle-pause-xKgeGXkT.js → circle-pause-CmzC_apg.js} +1 -1
- package/static/app/assets/{circle-play-DkT6tYPX.js → circle-play-D8mW2aQ7.js} +1 -1
- package/static/app/assets/{cpu-85xYObUC.js → cpu-DZcdd0PZ.js} +1 -1
- package/static/app/assets/{download-B5Fm7YXo.js → download-bv1KEPGQ.js} +1 -1
- package/static/app/assets/{folder-open-kk2Xa52u.js → folder-open-d-Pip5gr.js} +1 -1
- package/static/app/assets/{hard-drive-DkA3zBW_.js → hard-drive-D20iavUb.js} +1 -1
- package/static/app/assets/index-D9x-kSNy.css +2 -0
- package/static/app/assets/{index-BMPdTmlY.js → index-Do83hDzJ.js} +3 -3
- package/static/app/assets/{input-B0nRf2jO.js → input-BLXVNmj1.js} +1 -1
- package/static/app/assets/{link-2-Dwb4gnTc.js → link-2-BPJOFlAy.js} +1 -1
- package/static/app/assets/{permissionCopy-CQDUBrOZ.js → permissionCopy-ChdJd493.js} +1 -1
- package/static/app/assets/primitives-Cv5tbZBY.js +1 -0
- package/static/app/assets/search-CT9aho2j.js +1 -0
- package/static/app/assets/{share-2-BsrxFglO.js → share-2-YNX_NtMU.js} +1 -1
- package/static/app/assets/{shield-alert-5BStfp2_.js → shield-alert-DuQ3zrVL.js} +1 -1
- package/static/app/assets/{textarea-Cg8IUA-k.js → textarea-DqwLnli4.js} +1 -1
- package/static/app/assets/{useFocusTrap-CYKvE46M.js → useFocusTrap-ZVI98jaW.js} +1 -1
- package/static/app/assets/{useMutation-CSn9t1op.js → useMutation-CVC4qv_D.js} +1 -1
- package/static/app/assets/{useQuery-CY2OI2uy.js → useQuery-C7BeG4HU.js} +1 -1
- package/static/app/assets/{utils-Ddol2RWD.js → utils-CiFtIdZq.js} +1 -1
- package/static/app/assets/{workspace-BqDwOz_p.js → workspace-DQz9vIId.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/AdminConsole-cf4npybT.js +0 -1
- package/static/app/assets/Capture-DiQ219jW.js +0 -1
- package/static/app/assets/System-CieofHQa.js +0 -1
- 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/primitives-SNp0LRJz.js +0 -1
- package/static/app/assets/search-BcHqkjoy.js +0 -1
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
"""Phases 5-
|
|
1
|
+
"""Phases 5-6 of the AI-Worker build: domain singletons and the web shell.
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
``phase_domain`` runs before ``phase_web`` because the lifespan and the model
|
|
4
|
+
runtime service are both wired against the router it builds.
|
|
5
|
+
|
|
6
|
+
WP-P1 removed the product half of both phases: the chat service, the garden,
|
|
7
|
+
the telegram mirror, the typed ``AppContext``, the auth/admin/security/static
|
|
8
|
+
routers and the workspace mount all went to ``lattice-host``. What is left is
|
|
9
|
+
the LLM router (the thing this process exists to run), the tool-dispatch
|
|
10
|
+
whitelist, and the FastAPI object with the two middlewares a proxied browser
|
|
11
|
+
write still passes through.
|
|
8
12
|
|
|
9
13
|
Every heavy import lives *inside* a phase, never at module scope.
|
|
10
14
|
"""
|
|
@@ -12,25 +16,22 @@ Every heavy import lives *inside* a phase, never at module scope.
|
|
|
12
16
|
from __future__ import annotations
|
|
13
17
|
|
|
14
18
|
import logging
|
|
15
|
-
from typing import
|
|
19
|
+
from typing import List
|
|
16
20
|
|
|
17
21
|
from latticeai.runtime.runtime_context import RuntimeContext
|
|
18
22
|
|
|
19
23
|
|
|
20
24
|
# ── phase 5: domain singletons (must precede the web app) ────────────────────
|
|
21
25
|
def phase_domain(ctx: RuntimeContext) -> None:
|
|
22
|
-
"""The model router
|
|
26
|
+
"""The model router and the tool-dispatch policy.
|
|
23
27
|
|
|
24
|
-
Separated from
|
|
25
|
-
|
|
26
|
-
service are all wired against it.
|
|
28
|
+
Separated from ``phase_web`` because the lifespan hooks and the model
|
|
29
|
+
runtime service are both wired against the router.
|
|
27
30
|
"""
|
|
28
31
|
ctx.enter("domain")
|
|
29
32
|
|
|
30
33
|
from lattice_brain.graph.runtime import set_llm_router
|
|
31
34
|
from latticeai.models.router import LLMRouter
|
|
32
|
-
from latticeai.services.chat_service import ChatService
|
|
33
|
-
from latticeai.services.p_reinforce import PReinforceGardener
|
|
34
35
|
from latticeai.services.tool_dispatch import configure_tool_dispatch
|
|
35
36
|
|
|
36
37
|
model_router = LLMRouter()
|
|
@@ -38,290 +39,13 @@ def phase_domain(ctx: RuntimeContext) -> None:
|
|
|
38
39
|
configure_tool_dispatch(load_users=ctx.load_users, get_user_role=ctx.get_user_role)
|
|
39
40
|
ctx.set(model_router=model_router)
|
|
40
41
|
|
|
41
|
-
# v4 garden absorption: the vault is the user-owned markdown mirror and the
|
|
42
|
-
# brain is authoritative. Existing notes import idempotently (content-hash
|
|
43
|
-
# dedup), and garden context queries the brain rather than rescanning.
|
|
44
|
-
gardener = PReinforceGardener(
|
|
45
|
-
ingestion_pipeline=ctx.INGESTION_PIPELINE if ctx.ENABLE_GRAPH else None,
|
|
46
|
-
knowledge_graph=ctx.KNOWLEDGE_GRAPH,
|
|
47
|
-
)
|
|
48
|
-
if ctx.ENABLE_GRAPH:
|
|
49
|
-
try:
|
|
50
|
-
garden_import = gardener.import_vault()
|
|
51
|
-
if garden_import.get("failed"):
|
|
52
|
-
logging.warning(
|
|
53
|
-
"garden vault import: %s notes failed to ingest",
|
|
54
|
-
garden_import["failed"],
|
|
55
|
-
)
|
|
56
|
-
except Exception as exc:
|
|
57
|
-
logging.warning("garden vault import skipped: %s", exc)
|
|
58
|
-
ctx.set(gardener=gardener)
|
|
59
|
-
|
|
60
|
-
# The chat service owns persistence and trace behaviour once its user-key
|
|
61
|
-
# dependencies exist.
|
|
62
|
-
ctx.set(
|
|
63
|
-
CHAT_SERVICE=ChatService(
|
|
64
|
-
store=ctx.WORKSPACE_OS,
|
|
65
|
-
get_history=ctx.get_history,
|
|
66
|
-
save_to_history=ctx.save_to_history,
|
|
67
|
-
get_history_user=ctx.get_history_user,
|
|
68
|
-
)
|
|
69
|
-
)
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
def self_model_port(workspace_graph: Any) -> Any:
|
|
73
|
-
"""The agent loop's Self-Model port (v11.2.0).
|
|
74
|
-
|
|
75
|
-
11.1.0 built ``executor_prompt_for(self_model_summary=…)`` and had nothing
|
|
76
|
-
to pass it; this is what the composition root passes. ``summary_for_prompt``
|
|
77
|
-
never raises and answers ``""`` for a Brain that knows nothing about its
|
|
78
|
-
owner — which produces exactly the pre-11.2.0 prompt bytes.
|
|
79
|
-
|
|
80
|
-
A module-level factory rather than a closure inside ``phase_services``
|
|
81
|
-
because a port that cannot be called on its own cannot be tested on its own.
|
|
82
|
-
"""
|
|
83
|
-
|
|
84
|
-
def _summary(*, user_email: Any = None, workspace_id: Any = None) -> str:
|
|
85
|
-
from lattice_brain.self_model import summary_for_prompt
|
|
86
|
-
|
|
87
|
-
graph = workspace_graph()
|
|
88
|
-
if graph is None:
|
|
89
|
-
return ""
|
|
90
|
-
return summary_for_prompt(graph, workspace_id=workspace_id)
|
|
91
|
-
|
|
92
|
-
return _summary
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
# ── phase 6b: retrieval, agent runtime, and the typed AppContext ─────────────
|
|
96
|
-
def phase_services(ctx: RuntimeContext) -> None:
|
|
97
|
-
"""Retrieval/context assembly, the chat agent runtime, and the AppContext.
|
|
98
|
-
|
|
99
|
-
Runs after ``phase_web`` because the AppContext carries handles the web
|
|
100
|
-
phase produces (``ui_file_response``, ``local_sysinfo``, ``graph_stats``)
|
|
101
|
-
and the telegram mirror needs the lifespan's ``_spawn``.
|
|
102
|
-
"""
|
|
103
|
-
ctx.enter("services")
|
|
104
|
-
|
|
105
|
-
from latticeai.api.chat import build_recent_chat_context
|
|
106
|
-
from latticeai.core.enterprise import capability_registry
|
|
107
|
-
from latticeai.core.mcp_registry import (
|
|
108
|
-
SKILLS_DIR,
|
|
109
|
-
_fetch_skills_marketplace,
|
|
110
|
-
install_skill,
|
|
111
|
-
)
|
|
112
|
-
from latticeai.core.workspace_os import remove_skill_directory
|
|
113
|
-
from latticeai.runtime.chat_wiring import (
|
|
114
|
-
build_chat_agent_runtime_from_context,
|
|
115
|
-
maybe_build_telegram_chat_mirror,
|
|
116
|
-
)
|
|
117
|
-
from latticeai.runtime.context_runtime import build_context_runtime
|
|
118
|
-
from latticeai.services.app_context import AppContext
|
|
119
|
-
from latticeai.services.tool_dispatch import build_agent_runtime
|
|
120
|
-
from latticeai.setup.wizard import get_recommendations, scan_environment
|
|
121
|
-
from latticeai.tools import execute_tool, knowledge_save
|
|
122
|
-
|
|
123
|
-
gardener = ctx.gardener
|
|
124
|
-
model_router = ctx.model_router
|
|
125
|
-
|
|
126
|
-
def _workspace_settings_payload() -> Dict:
|
|
127
|
-
return {
|
|
128
|
-
"mode": ctx.APP_MODE,
|
|
129
|
-
"host": ctx.DEFAULT_HOST,
|
|
130
|
-
"port": ctx.DEFAULT_PORT,
|
|
131
|
-
"require_auth": ctx.REQUIRE_AUTH,
|
|
132
|
-
"enable_graph": ctx.ENABLE_GRAPH,
|
|
133
|
-
"allow_local_models": ctx.ALLOW_LOCAL_MODELS,
|
|
134
|
-
"static_dir": str(ctx.STATIC_DIR),
|
|
135
|
-
"data_dir": str(ctx.DATA_DIR),
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
def _workspace_models_payload() -> Dict:
|
|
139
|
-
return {
|
|
140
|
-
"current_model": ctx.model_router.current_model_id,
|
|
141
|
-
"loaded_models": ctx.model_router.loaded_model_ids,
|
|
142
|
-
"public_model": ctx.PUBLIC_MODEL,
|
|
143
|
-
"local_model": ctx.LOCAL_MODEL,
|
|
144
|
-
"local_draft_model": ctx.LOCAL_DRAFT_MODEL,
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
def _embedding_info() -> dict:
|
|
148
|
-
from latticeai.core.embedding_providers import (
|
|
149
|
-
PROVIDER_TYPES,
|
|
150
|
-
embedding_provider_profiles,
|
|
151
|
-
)
|
|
152
|
-
|
|
153
|
-
info = ctx.EMBEDDER.as_dict()
|
|
154
|
-
info["available_providers"] = list(PROVIDER_TYPES)
|
|
155
|
-
info["profile"] = ctx.CONFIG.embedding_profile or ""
|
|
156
|
-
info["profiles"] = embedding_provider_profiles()
|
|
157
|
-
return info
|
|
158
|
-
|
|
159
|
-
def _allowed_workspaces_for(user: Any) -> Any:
|
|
160
|
-
# No-auth local mode is single-user: no scoping. With auth, reads are
|
|
161
|
-
# scoped to the caller's memberships (legacy-global rows need an
|
|
162
|
-
# explicit maintenance-only opt-in).
|
|
163
|
-
if not ctx.REQUIRE_AUTH or not user:
|
|
164
|
-
return None
|
|
165
|
-
return ctx.PLATFORM.allowed_scopes(user)
|
|
166
|
-
|
|
167
|
-
def _recent_chat_context(
|
|
168
|
-
limit: int = 10,
|
|
169
|
-
include_image_missing_replies: bool = True,
|
|
170
|
-
user_email: Optional[str] = None,
|
|
171
|
-
conversation_id: Optional[str] = None,
|
|
172
|
-
workspace_id: Optional[str] = None,
|
|
173
|
-
) -> str:
|
|
174
|
-
return build_recent_chat_context(
|
|
175
|
-
get_history=ctx.get_history,
|
|
176
|
-
limit=limit,
|
|
177
|
-
include_image_missing_replies=include_image_missing_replies,
|
|
178
|
-
user_email=user_email,
|
|
179
|
-
conversation_id=conversation_id,
|
|
180
|
-
workspace_id=workspace_id,
|
|
181
|
-
)
|
|
182
|
-
|
|
183
|
-
ctx.set(
|
|
184
|
-
_workspace_settings_payload=_workspace_settings_payload,
|
|
185
|
-
_workspace_models_payload=_workspace_models_payload,
|
|
186
|
-
_embedding_info=_embedding_info,
|
|
187
|
-
_allowed_workspaces_for=_allowed_workspaces_for,
|
|
188
|
-
_recent_chat_context=_recent_chat_context,
|
|
189
|
-
)
|
|
190
|
-
|
|
191
|
-
context_runtime = build_context_runtime(
|
|
192
|
-
graph_store=ctx._workspace_graph(),
|
|
193
|
-
ingestion_pipeline=ctx.INGESTION_PIPELINE,
|
|
194
|
-
memory_service=ctx.MEMORY_SERVICE,
|
|
195
|
-
gardener=gardener,
|
|
196
|
-
require_auth=ctx.REQUIRE_AUTH,
|
|
197
|
-
allowed_scopes_for_user=lambda user_email: ctx.PLATFORM.allowed_scopes(
|
|
198
|
-
user_email
|
|
199
|
-
),
|
|
200
|
-
)
|
|
201
|
-
ctx.adopt(
|
|
202
|
-
context_runtime,
|
|
203
|
-
"SEARCH_SERVICE",
|
|
204
|
-
"BRAIN_MEMORY",
|
|
205
|
-
"CONTEXT_ASSEMBLER",
|
|
206
|
-
"ARTIFACT_LEDGER",
|
|
207
|
-
"_scoped_hybrid_search",
|
|
208
|
-
)
|
|
209
|
-
|
|
210
|
-
# Telegram chat mirror: registered only when ENABLE_TELEGRAM is truthy, so
|
|
211
|
-
# latticeai.api.chat never imports the 45KB telegram module.
|
|
212
|
-
ctx.set(
|
|
213
|
-
on_chat_message=maybe_build_telegram_chat_mirror(
|
|
214
|
-
enable_telegram=ctx.ENABLE_TELEGRAM,
|
|
215
|
-
spawn=ctx._spawn,
|
|
216
|
-
)
|
|
217
|
-
)
|
|
218
|
-
|
|
219
|
-
ctx.set(
|
|
220
|
-
CHAT_AGENT_RUNTIME=build_chat_agent_runtime_from_context(
|
|
221
|
-
build_agent_runtime=build_agent_runtime,
|
|
222
|
-
model_router=model_router,
|
|
223
|
-
execute_tool=execute_tool,
|
|
224
|
-
recent_chat_context=_recent_chat_context,
|
|
225
|
-
clear_history=ctx.clear_history,
|
|
226
|
-
knowledge_save=knowledge_save,
|
|
227
|
-
audit=ctx.append_audit_event,
|
|
228
|
-
hooks=ctx.HOOKS_REGISTRY,
|
|
229
|
-
brain_memory=ctx.BRAIN_MEMORY,
|
|
230
|
-
self_model_summary=self_model_port(
|
|
231
|
-
lambda: ctx.KNOWLEDGE_GRAPH if ctx.ENABLE_GRAPH else None
|
|
232
|
-
),
|
|
233
|
-
)
|
|
234
|
-
)
|
|
235
|
-
|
|
236
|
-
# One typed context object replaces the historical 25-30-kwarg wiring.
|
|
237
|
-
ctx.set(
|
|
238
|
-
app_context=AppContext(
|
|
239
|
-
config=ctx.CONFIG,
|
|
240
|
-
data_dir=ctx.DATA_DIR,
|
|
241
|
-
static_dir=ctx.STATIC_DIR,
|
|
242
|
-
base_dir=ctx.BASE_DIR,
|
|
243
|
-
skills_dir=SKILLS_DIR,
|
|
244
|
-
model_router=model_router,
|
|
245
|
-
workspace_store=ctx.WORKSPACE_OS,
|
|
246
|
-
workspace_service=ctx.WORKSPACE_SERVICE,
|
|
247
|
-
knowledge_graph=ctx.KNOWLEDGE_GRAPH,
|
|
248
|
-
local_kg_watcher=ctx.LOCAL_KG_WATCHER,
|
|
249
|
-
chat_service=ctx.CHAT_SERVICE,
|
|
250
|
-
context_assembler=ctx.CONTEXT_ASSEMBLER,
|
|
251
|
-
artifact_ledger=ctx.ARTIFACT_LEDGER,
|
|
252
|
-
brain_memory=ctx.BRAIN_MEMORY,
|
|
253
|
-
ingestion_pipeline=ctx.INGESTION_PIPELINE if ctx.ENABLE_GRAPH else None,
|
|
254
|
-
chat_agent_runtime=ctx.CHAT_AGENT_RUNTIME,
|
|
255
|
-
gardener=gardener,
|
|
256
|
-
hooks=ctx.HOOKS_REGISTRY,
|
|
257
|
-
realtime_bus=ctx.REALTIME_BUS,
|
|
258
|
-
capability_registry=capability_registry,
|
|
259
|
-
require_user=ctx.require_user,
|
|
260
|
-
require_admin=ctx.require_admin,
|
|
261
|
-
get_current_user=ctx.get_current_user,
|
|
262
|
-
load_users=ctx.load_users,
|
|
263
|
-
get_user_role=ctx.get_user_role,
|
|
264
|
-
enforce_rate_limit=ctx.enforce_rate_limit,
|
|
265
|
-
allowed_workspaces_for=ctx._history_allowed_workspaces_for,
|
|
266
|
-
append_audit_event=ctx.append_audit_event,
|
|
267
|
-
get_audit_log=ctx.get_audit_log,
|
|
268
|
-
get_history=ctx.get_history,
|
|
269
|
-
get_history_user=ctx.get_history_user,
|
|
270
|
-
save_to_history=ctx.save_to_history,
|
|
271
|
-
clear_history=ctx.clear_history,
|
|
272
|
-
clear_conversation=ctx.clear_conversation,
|
|
273
|
-
group_history_conversations=ctx.group_history_conversations,
|
|
274
|
-
get_conversation_messages=ctx.get_conversation_messages,
|
|
275
|
-
conversation_title=ctx.conversation_title,
|
|
276
|
-
enable_graph=ctx.ENABLE_GRAPH,
|
|
277
|
-
require_graph=ctx._require_graph,
|
|
278
|
-
workspace_graph=ctx._workspace_graph,
|
|
279
|
-
graph_stats=ctx._graph_stats_safe,
|
|
280
|
-
# Provider, not a value: REVIEW_QUEUE lands two phases later.
|
|
281
|
-
review_queue=lambda: ctx.REVIEW_QUEUE,
|
|
282
|
-
workspace_models=_workspace_models_payload,
|
|
283
|
-
workspace_settings=_workspace_settings_payload,
|
|
284
|
-
scan_environment=scan_environment,
|
|
285
|
-
local_sysinfo=ctx.local_sysinfo,
|
|
286
|
-
get_recommendations=get_recommendations,
|
|
287
|
-
fetch_skills_marketplace=_fetch_skills_marketplace,
|
|
288
|
-
install_skill=install_skill,
|
|
289
|
-
remove_skill_directory=remove_skill_directory,
|
|
290
|
-
redact_secret_text=ctx.redact_secret_text,
|
|
291
|
-
ui_file_response=ctx.ui_file_response,
|
|
292
|
-
public_model=ctx.PUBLIC_MODEL,
|
|
293
|
-
local_model=ctx.LOCAL_MODEL or "",
|
|
294
|
-
on_chat_message=ctx.on_chat_message,
|
|
295
|
-
funnel_metrics=ctx.FUNNEL_METRICS,
|
|
296
|
-
)
|
|
297
|
-
)
|
|
298
|
-
ctx.app.state.context = ctx.app_context
|
|
299
|
-
|
|
300
42
|
|
|
301
|
-
# ── phase 6: web
|
|
43
|
+
# ── phase 6: the web shell ───────────────────────────────────────────────────
|
|
302
44
|
def phase_web(ctx: RuntimeContext) -> None:
|
|
303
|
-
"""Lifespan, the FastAPI
|
|
45
|
+
"""Lifespan, the FastAPI application object, the model runtime service."""
|
|
304
46
|
ctx.enter("web")
|
|
305
47
|
|
|
306
|
-
from latticeai.api.admin import create_admin_router
|
|
307
|
-
from latticeai.api.auth import create_auth_router
|
|
308
|
-
from latticeai.api.invitations import create_invitations_router
|
|
309
|
-
from latticeai.api.security_dashboard import (
|
|
310
|
-
create_security_router as _create_security_router,
|
|
311
|
-
)
|
|
312
|
-
from latticeai.api.static_routes import create_static_routes_router
|
|
313
|
-
from latticeai.core.config import default_sso_redirect_uri
|
|
314
|
-
from latticeai.core.policy import policy_matrix
|
|
315
|
-
from latticeai.core.product_hardening import build_product_hardening_status
|
|
316
|
-
from latticeai.core.security import hash_password
|
|
317
|
-
from latticeai.core.users import ensure_user_identity
|
|
318
48
|
from latticeai.runtime.lifespan_runtime import build_lifespan_runtime
|
|
319
|
-
from latticeai.runtime.model_wiring import configure_model_runtime_from_context
|
|
320
|
-
from latticeai.runtime.router_registration import (
|
|
321
|
-
build_auth_admin_security_router_bundle,
|
|
322
|
-
build_static_routes_bundle,
|
|
323
|
-
)
|
|
324
|
-
from latticeai.runtime.web_runtime import build_web_runtime
|
|
325
49
|
from latticeai.services.model_runtime import (
|
|
326
50
|
LOCAL_SERVER_PROCESSES,
|
|
327
51
|
build_model_runtime,
|
|
@@ -330,7 +54,6 @@ def phase_web(ctx: RuntimeContext) -> None:
|
|
|
330
54
|
|
|
331
55
|
lifespan_runtime = build_lifespan_runtime(
|
|
332
56
|
app_mode=ctx.APP_MODE,
|
|
333
|
-
enable_telegram=ctx.ENABLE_TELEGRAM,
|
|
334
57
|
autoload_models=ctx.AUTOLOAD_MODELS,
|
|
335
58
|
is_public_mode=ctx.IS_PUBLIC_MODE,
|
|
336
59
|
public_model=ctx.PUBLIC_MODEL,
|
|
@@ -339,36 +62,22 @@ def phase_web(ctx: RuntimeContext) -> None:
|
|
|
339
62
|
local_draft_model=ctx.LOCAL_DRAFT_MODEL,
|
|
340
63
|
model_idle_unload_seconds=ctx.MODEL_IDLE_UNLOAD_SECONDS,
|
|
341
64
|
model_router=ctx.model_router,
|
|
342
|
-
local_kg_watcher=ctx.LOCAL_KG_WATCHER,
|
|
343
65
|
local_server_processes=LOCAL_SERVER_PROCESSES,
|
|
344
66
|
logger=logging,
|
|
345
67
|
)
|
|
346
68
|
ctx.adopt(lifespan_runtime, "_spawn", "lifespan")
|
|
347
69
|
|
|
348
|
-
|
|
349
|
-
app_mode=ctx.APP_MODE,
|
|
350
|
-
app_version=ctx.APP_VERSION,
|
|
351
|
-
lifespan=ctx.lifespan,
|
|
352
|
-
default_host=ctx.DEFAULT_HOST,
|
|
353
|
-
default_port=ctx.DEFAULT_PORT,
|
|
354
|
-
cors_extra_origins=ctx.CORS_EXTRA_ORIGINS,
|
|
355
|
-
cors_allow_network=ctx.CORS_ALLOW_NETWORK,
|
|
356
|
-
static_dir=ctx.STATIC_DIR,
|
|
357
|
-
csrf_trusted_origins=ctx.CSRF_TRUSTED_ORIGINS,
|
|
358
|
-
)
|
|
359
|
-
ctx.adopt(web_runtime, "app")
|
|
70
|
+
ctx.set(app=build_worker_app_shell(ctx))
|
|
360
71
|
ensure_agent_root()
|
|
361
72
|
|
|
362
73
|
ctx.set(
|
|
363
|
-
model_runtime_service=
|
|
364
|
-
build_model_runtime=build_model_runtime,
|
|
74
|
+
model_runtime_service=build_model_runtime(
|
|
365
75
|
router=ctx.model_router,
|
|
366
76
|
APP_MODE=ctx.APP_MODE,
|
|
367
77
|
DEFAULT_HOST=ctx.DEFAULT_HOST,
|
|
368
78
|
DEFAULT_PORT=ctx.DEFAULT_PORT,
|
|
369
79
|
DATA_DIR=ctx.DATA_DIR,
|
|
370
80
|
BASE_DIR=ctx.BASE_DIR,
|
|
371
|
-
ENABLE_TELEGRAM=ctx.ENABLE_TELEGRAM,
|
|
372
81
|
ENABLE_GRAPH=ctx.ENABLE_GRAPH,
|
|
373
82
|
AUTOLOAD_MODELS=ctx.AUTOLOAD_MODELS,
|
|
374
83
|
MODEL_IDLE_UNLOAD_SECONDS=ctx.MODEL_IDLE_UNLOAD_SECONDS,
|
|
@@ -376,7 +85,6 @@ def phase_web(ctx: RuntimeContext) -> None:
|
|
|
376
85
|
MODEL_DOWNLOAD_TIMEOUT=ctx.MODEL_DOWNLOAD_TIMEOUT,
|
|
377
86
|
ALLOW_LOCAL_MODELS=ctx.ALLOW_LOCAL_MODELS,
|
|
378
87
|
REQUIRE_AUTH=ctx.REQUIRE_AUTH,
|
|
379
|
-
INVITE_GATE_ENABLED=ctx.INVITE_GATE_ENABLED,
|
|
380
88
|
ALLOW_PLAINTEXT_API_KEYS=ctx.ALLOW_PLAINTEXT_API_KEYS,
|
|
381
89
|
CORS_ALLOW_NETWORK=ctx.CORS_ALLOW_NETWORK,
|
|
382
90
|
PUBLIC_MODEL=ctx.PUBLIC_MODEL,
|
|
@@ -384,111 +92,86 @@ def phase_web(ctx: RuntimeContext) -> None:
|
|
|
384
92
|
IS_PUBLIC_MODE=ctx.IS_PUBLIC_MODE,
|
|
385
93
|
keyring=ctx.keyring,
|
|
386
94
|
get_current_user=ctx.get_current_user,
|
|
387
|
-
get_user_api_key=ctx.get_user_api_key,
|
|
388
95
|
)
|
|
389
96
|
)
|
|
390
97
|
|
|
391
|
-
static_routes_bundle = build_static_routes_bundle(
|
|
392
|
-
create_static_routes_router=create_static_routes_router,
|
|
393
|
-
static_dir=ctx.STATIC_DIR,
|
|
394
|
-
invite_gate_enabled=ctx.INVITE_GATE_ENABLED,
|
|
395
|
-
invite_code=ctx.INVITE_CODE,
|
|
396
|
-
invite_cookie_secret=ctx.INVITE_COOKIE_SECRET,
|
|
397
|
-
secure_cookies=ctx.SECURE_COOKIES,
|
|
398
|
-
app_mode=ctx.APP_MODE,
|
|
399
|
-
model_router=ctx.model_router,
|
|
400
|
-
require_user=ctx.require_user,
|
|
401
|
-
)
|
|
402
|
-
ctx.adopt(
|
|
403
|
-
static_routes_bundle,
|
|
404
|
-
"STATIC_ROUTES",
|
|
405
|
-
"ui_file_response",
|
|
406
|
-
"local_sysinfo",
|
|
407
|
-
"invite_authorized",
|
|
408
|
-
)
|
|
409
98
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
verify_and_migrate_password=ctx.verify_and_migrate_password,
|
|
417
|
-
create_session=ctx.create_session,
|
|
418
|
-
get_session_email=ctx.get_session_email,
|
|
419
|
-
invalidate_session=ctx.invalidate_session,
|
|
420
|
-
extract_bearer_token=ctx._extract_bearer_token,
|
|
421
|
-
get_user_role=ctx.get_user_role,
|
|
422
|
-
require_user=ctx.require_user,
|
|
423
|
-
check_ip_rate_limit=ctx._check_rate_limit,
|
|
424
|
-
client_ip=ctx._client_ip,
|
|
425
|
-
get_sso_settings=ctx.get_sso_settings,
|
|
426
|
-
get_sso_discovery=ctx._get_sso_discovery,
|
|
427
|
-
public_sso_config=ctx.public_sso_config,
|
|
428
|
-
open_registration=ctx.OPEN_REGISTRATION,
|
|
429
|
-
session_ttl=ctx._SESSION_TTL,
|
|
430
|
-
require_auth=ctx.REQUIRE_AUTH,
|
|
431
|
-
secure_cookies=ctx.SECURE_COOKIES,
|
|
432
|
-
invite_authorized=ctx.invite_authorized,
|
|
433
|
-
ensure_identity=ensure_user_identity,
|
|
434
|
-
create_admin_router=create_admin_router,
|
|
435
|
-
require_admin=ctx.require_admin,
|
|
436
|
-
get_history=ctx.get_history,
|
|
437
|
-
get_audit_log=ctx.get_audit_log,
|
|
438
|
-
audit_file=ctx.AUDIT_FILE,
|
|
439
|
-
public_user=ctx.public_user,
|
|
440
|
-
load_vpc_config=ctx.load_vpc_config,
|
|
441
|
-
save_vpc_config=ctx.save_vpc_config,
|
|
442
|
-
build_admin_audit_report=ctx.build_admin_audit_report,
|
|
443
|
-
build_sensitivity_report=ctx.build_sensitivity_report,
|
|
444
|
-
append_audit_event=ctx.append_audit_event,
|
|
445
|
-
save_sso_config=ctx.save_sso_config,
|
|
446
|
-
knowledge_graph=ctx.KNOWLEDGE_GRAPH,
|
|
447
|
-
enable_graph=ctx.ENABLE_GRAPH,
|
|
448
|
-
logger=logging,
|
|
449
|
-
invite_code=ctx.INVITE_CODE,
|
|
450
|
-
invite_gate_enabled=ctx.INVITE_GATE_ENABLED,
|
|
451
|
-
default_port=ctx.DEFAULT_PORT,
|
|
452
|
-
policy_matrix=policy_matrix,
|
|
453
|
-
build_product_hardening_status=build_product_hardening_status,
|
|
454
|
-
config=ctx.CONFIG,
|
|
455
|
-
kg_portability=ctx.KG_PORTABILITY,
|
|
456
|
-
device_identity=ctx.DEVICE_IDENTITY,
|
|
457
|
-
create_invitations_router=create_invitations_router,
|
|
458
|
-
invitation_store=ctx.INVITATION_STORE,
|
|
459
|
-
workspace_service=ctx.WORKSPACE_SERVICE,
|
|
460
|
-
user_id_for_email=ctx.user_id_for_email,
|
|
461
|
-
create_security_router=_create_security_router,
|
|
462
|
-
classify_sensitive_message=ctx.classify_sensitive_message,
|
|
463
|
-
)
|
|
464
|
-
ctx.adopt(
|
|
465
|
-
foundation_router_bundle,
|
|
466
|
-
"auth_router",
|
|
467
|
-
"admin_router",
|
|
468
|
-
"invitations_router",
|
|
469
|
-
"security_router",
|
|
470
|
-
"_graph_stats_safe",
|
|
471
|
-
"_product_hardening_status",
|
|
472
|
-
"_security_audit_events_safe",
|
|
473
|
-
"_security_list_uploaded_files",
|
|
474
|
-
)
|
|
99
|
+
def build_worker_app_shell(ctx: RuntimeContext):
|
|
100
|
+
"""The FastAPI object plus the two middlewares a proxied write still meets.
|
|
101
|
+
|
|
102
|
+
Moved here from ``runtime/web_runtime.py`` (deleted with the router
|
|
103
|
+
registration it existed beside). The static mounts went with it: a worker
|
|
104
|
+
serves no UI, and the worker profile dropped those mounts anyway.
|
|
475
105
|
|
|
106
|
+
Both middlewares are load-bearing on a worker, which is not obvious:
|
|
476
107
|
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
108
|
+
* **CORS** stays outside the CSRF guard so a rejected request still comes
|
|
109
|
+
back with the headers a browser needs to surface the 403 rather than an
|
|
110
|
+
opaque network error.
|
|
111
|
+
* **The CSRF origin guard** is what makes ``LATTICEAI_CSRF_TRUSTED_ORIGINS``
|
|
112
|
+
load-bearing for the gateway (v11.6.0 gateway integration §3): a proxied
|
|
113
|
+
browser write — ``POST /models/load``, ``POST /engines/pull-model``,
|
|
114
|
+
``POST /tools/read_document`` — arrives carrying the browser's session
|
|
115
|
+
cookie *and* ``Origin: …:{gateway port}``, and without the host's
|
|
116
|
+
injected trust list this guard would answer 403.
|
|
117
|
+
"""
|
|
118
|
+
from fastapi import FastAPI
|
|
480
119
|
|
|
481
|
-
from latticeai.
|
|
482
|
-
from latticeai.
|
|
120
|
+
from latticeai.core.csrf import CSRFOriginGuardMiddleware, CSRFOriginPolicy
|
|
121
|
+
from latticeai.core.security import host_is_loopback
|
|
483
122
|
|
|
484
|
-
|
|
485
|
-
ctx.
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
admin_router=ctx.admin_router,
|
|
489
|
-
invitations_router=ctx.invitations_router,
|
|
490
|
-
security_router=ctx.security_router,
|
|
491
|
-
create_workspace_router=create_workspace_router,
|
|
492
|
-
context=ctx.app_context,
|
|
123
|
+
app = FastAPI(
|
|
124
|
+
title=f"Lattice AI Server ({ctx.APP_MODE})",
|
|
125
|
+
version=ctx.APP_VERSION,
|
|
126
|
+
lifespan=ctx.lifespan,
|
|
493
127
|
)
|
|
494
128
|
|
|
129
|
+
cors_allowed_origins = [
|
|
130
|
+
f"http://localhost:{ctx.DEFAULT_PORT}",
|
|
131
|
+
f"http://127.0.0.1:{ctx.DEFAULT_PORT}",
|
|
132
|
+
*ctx.CORS_EXTRA_ORIGINS,
|
|
133
|
+
]
|
|
134
|
+
if ctx.CORS_ALLOW_NETWORK:
|
|
135
|
+
cors_allowed_origins = cors_allowed_origins + [
|
|
136
|
+
f"http://{ctx.DEFAULT_HOST}:{ctx.DEFAULT_PORT}",
|
|
137
|
+
f"https://{ctx.DEFAULT_HOST}:{ctx.DEFAULT_PORT}",
|
|
138
|
+
]
|
|
139
|
+
|
|
140
|
+
# An origin that CORS already lets send *credentialed* cross-origin
|
|
141
|
+
# requests is, by that decision, trusted with the session cookie; listing
|
|
142
|
+
# it again here would be a second place to forget. The explicit
|
|
143
|
+
# LATTICEAI_CSRF_TRUSTED_ORIGINS entries are for the reverse-proxy case —
|
|
144
|
+
# and, since v11.6.0, for the gateway that fronts this worker.
|
|
145
|
+
csrf_allowed_origins: List[str] = [
|
|
146
|
+
*cors_allowed_origins,
|
|
147
|
+
*ctx.CSRF_TRUSTED_ORIGINS,
|
|
148
|
+
]
|
|
149
|
+
csrf_policy = CSRFOriginPolicy(
|
|
150
|
+
trusted_origins=csrf_allowed_origins,
|
|
151
|
+
server_host=ctx.DEFAULT_HOST,
|
|
152
|
+
server_port=ctx.DEFAULT_PORT,
|
|
153
|
+
bind_is_loopback=host_is_loopback(ctx.DEFAULT_HOST),
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
# Registration order is stack order in reverse: the LAST middleware added
|
|
157
|
+
# is the OUTERMOST.
|
|
158
|
+
app.add_middleware(CSRFOriginGuardMiddleware, policy=csrf_policy)
|
|
159
|
+
_add_cors(app, cors_allowed_origins)
|
|
160
|
+
|
|
161
|
+
ctx.set(
|
|
162
|
+
CORS_ALLOWED_ORIGINS=cors_allowed_origins,
|
|
163
|
+
CSRF_ALLOWED_ORIGINS=csrf_allowed_origins,
|
|
164
|
+
)
|
|
165
|
+
return app
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def _add_cors(app, origins: List[str]) -> None:
|
|
169
|
+
from fastapi.middleware.cors import CORSMiddleware
|
|
170
|
+
|
|
171
|
+
app.add_middleware(
|
|
172
|
+
CORSMiddleware,
|
|
173
|
+
allow_origins=origins,
|
|
174
|
+
allow_methods=["*"],
|
|
175
|
+
allow_headers=["*"],
|
|
176
|
+
allow_credentials=True,
|
|
177
|
+
)
|