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
package/src-tauri/src/backend.rs
CHANGED
|
@@ -14,6 +14,11 @@
|
|
|
14
14
|
//! navigates to the gateway, and the worker is told to trust that origin so
|
|
15
15
|
//! cookie-authenticated writes still work through the proxy hop.
|
|
16
16
|
//!
|
|
17
|
+
//! 11.6.0 One Door: the Python-direct topologies are gone. The shell always
|
|
18
|
+
//! boots or attaches through lattice-host. The window health-gates on
|
|
19
|
+
//! `GET {origin}/health` — the **host** surface at the same origin the window
|
|
20
|
+
//! loads, not a bare worker port.
|
|
21
|
+
//!
|
|
17
22
|
//! Which arrangement is chosen lives in [`crate::topology`]; what this module
|
|
18
23
|
//! adds is the running of it, and the five IPC contracts on top (unchanged in
|
|
19
24
|
//! name, type and meaning — the new status fields are additive).
|
|
@@ -26,10 +31,18 @@ use lattice_host::supervisor::{
|
|
|
26
31
|
wait_for_health, HostProbe, Supervisor, SupervisorConfig, SupervisorError, SystemProbe,
|
|
27
32
|
WorkerStatus,
|
|
28
33
|
};
|
|
34
|
+
|
|
29
35
|
use serde::Serialize;
|
|
30
36
|
|
|
31
37
|
use crate::topology::{self, Plan, Topology};
|
|
32
38
|
|
|
39
|
+
/// The module the host supervises. I6's launch string is
|
|
40
|
+
/// `uvicorn latticeai.worker_app:create_worker_app --factory`; the module form
|
|
41
|
+
/// reads `LATTICEAI_PORT` from the supervisor, so we do not have to know the
|
|
42
|
+
/// internal port at pin time.
|
|
43
|
+
const WORKER_MODULE: &str = "latticeai.worker_app";
|
|
44
|
+
const BACKEND_CMD_ENV: &str = "LATTICEAI_DESKTOP_BACKEND_CMD";
|
|
45
|
+
|
|
33
46
|
/// The desktop shell's view of the worker.
|
|
34
47
|
///
|
|
35
48
|
/// The first six fields are the contract `latticeApi.desktopBackendStatus`
|
|
@@ -54,14 +67,14 @@ pub struct BackendStatus {
|
|
|
54
67
|
pub healthy: bool,
|
|
55
68
|
/// The chosen port — authoritative, not the configured preference.
|
|
56
69
|
pub port: u16,
|
|
57
|
-
/// `false` when the shell only fronts a
|
|
70
|
+
/// `false` when the shell only fronts a host it did not start.
|
|
58
71
|
pub supervised: bool,
|
|
59
72
|
/// How many times the supervisor restarted the worker after a crash.
|
|
60
73
|
pub restarts: u32,
|
|
61
74
|
/// Seconds since the current worker process started.
|
|
62
75
|
pub uptime_seconds: Option<u64>,
|
|
63
|
-
/// Which arrangement this shell is running: `gateway
|
|
64
|
-
///
|
|
76
|
+
/// Which arrangement this shell is running: `gateway` or `external`
|
|
77
|
+
/// (11.5.0, additive; `direct`/`disabled` retired in 11.6.0).
|
|
65
78
|
pub topology: String,
|
|
66
79
|
/// Where the worker itself answers. Equal to `origin` unless a gateway is
|
|
67
80
|
/// in front of it (11.5.0, additive).
|
|
@@ -94,14 +107,71 @@ pub struct DesktopBackend {
|
|
|
94
107
|
jobs: Option<Arc<lattice_jobs::Scheduler>>,
|
|
95
108
|
/// Why the front door is not there, when it could not be bound.
|
|
96
109
|
///
|
|
97
|
-
/// `None` means "nothing went wrong" — including in the
|
|
98
|
-
///
|
|
110
|
+
/// `None` means "nothing went wrong" — including in the topology that
|
|
111
|
+
/// attaches to someone else's host, where this process serves no gateway.
|
|
99
112
|
gateway_error: Mutex<Option<String>>,
|
|
100
113
|
}
|
|
101
114
|
|
|
115
|
+
/// True when the packaged Resources tree already carries a worker.
|
|
116
|
+
///
|
|
117
|
+
/// Leave `LATTICEAI_DESKTOP_BACKEND_CMD` unset in that case so the supervisor
|
|
118
|
+
/// can point `PYTHONPATH` at the tree (its bundled-tree rule). Integrator
|
|
119
|
+
/// must flip `WORKER_MODULE` from `latticeai.cli.entrypoint` to
|
|
120
|
+
/// `latticeai.worker_app`.
|
|
121
|
+
fn bundled_worker_present(probe: &dyn HostProbe) -> bool {
|
|
122
|
+
let Some(resources) = probe.resource_dir() else {
|
|
123
|
+
return false;
|
|
124
|
+
};
|
|
125
|
+
for root in [resources.join("_up_"), resources] {
|
|
126
|
+
if probe.is_file(&root.join("latticeai").join("worker_app.py"))
|
|
127
|
+
|| probe.is_file(&root.join("latticeai").join("cli").join("entrypoint.py"))
|
|
128
|
+
{
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
false
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/// Command that pins the supervisor onto the worker, or `None` when an
|
|
136
|
+
/// existing override / bundled tree should win.
|
|
137
|
+
///
|
|
138
|
+
/// `bin/ltcai.js` is now the **host** front door. If the supervisor still
|
|
139
|
+
/// treats `ltcai` on `PATH` as a worker (lattice-host rule 2), it would spawn
|
|
140
|
+
/// another host and recurse. Pinning `python -m latticeai.worker_app` closes
|
|
141
|
+
/// that hatch in the unpackaged shell. A caller that already set
|
|
142
|
+
/// `LATTICEAI_DESKTOP_BACKEND_CMD` is left alone.
|
|
143
|
+
fn worker_launch_command(probe: &dyn HostProbe) -> Option<String> {
|
|
144
|
+
if probe
|
|
145
|
+
.env_var(BACKEND_CMD_ENV)
|
|
146
|
+
.filter(|value| !value.trim().is_empty())
|
|
147
|
+
.is_some()
|
|
148
|
+
{
|
|
149
|
+
return None;
|
|
150
|
+
}
|
|
151
|
+
if bundled_worker_present(probe) {
|
|
152
|
+
return None;
|
|
153
|
+
}
|
|
154
|
+
let candidates = lattice_host::supervisor::command::python_candidates(probe);
|
|
155
|
+
let python = candidates
|
|
156
|
+
.iter()
|
|
157
|
+
.find(|program| probe.module_importable(program, WORKER_MODULE))
|
|
158
|
+
.cloned()
|
|
159
|
+
.or_else(|| candidates.first().cloned())
|
|
160
|
+
.unwrap_or_else(|| "python3".into());
|
|
161
|
+
Some(format!("{python} -m {WORKER_MODULE}"))
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/// Pin the worker launch on the real process environment, once.
|
|
165
|
+
fn pin_worker_launch_if_needed(probe: &dyn HostProbe) {
|
|
166
|
+
if let Some(command) = worker_launch_command(probe) {
|
|
167
|
+
std::env::set_var(BACKEND_CMD_ENV, command);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
102
171
|
impl DesktopBackend {
|
|
103
172
|
/// Resolve against the real machine.
|
|
104
173
|
pub fn resolve() -> Result<Self, SupervisorError> {
|
|
174
|
+
pin_worker_launch_if_needed(&SystemProbe);
|
|
105
175
|
Self::with_probe(Arc::new(SystemProbe))
|
|
106
176
|
}
|
|
107
177
|
|
|
@@ -180,7 +250,8 @@ impl DesktopBackend {
|
|
|
180
250
|
///
|
|
181
251
|
/// A failure here is logged rather than fatal — the window still opens, and
|
|
182
252
|
/// the browser's own "cannot connect" plus this line is a better failure
|
|
183
|
-
/// than a shell that exits.
|
|
253
|
+
/// than a shell that exits. Attach to a running host with
|
|
254
|
+
/// `LATTICEAI_DESKTOP_BACKEND_ORIGIN` if this process cannot bind.
|
|
184
255
|
async fn start_gateway(&self) {
|
|
185
256
|
let Some(port) = self.plan.gateway_port else {
|
|
186
257
|
return;
|
|
@@ -194,7 +265,8 @@ impl DesktopBackend {
|
|
|
194
265
|
Err(err) => {
|
|
195
266
|
let message = format!(
|
|
196
267
|
"the gateway could not bind {addr}: {err} — \
|
|
197
|
-
set
|
|
268
|
+
set LATTICEAI_PORT to a free port, or \
|
|
269
|
+
LATTICEAI_DESKTOP_BACKEND_ORIGIN to an already-running lattice-host"
|
|
198
270
|
);
|
|
199
271
|
eprintln!("lattice-ai-desktop: {message}");
|
|
200
272
|
// Recorded, not only logged: `plan.origin` names the port that
|
|
@@ -258,18 +330,12 @@ impl DesktopBackend {
|
|
|
258
330
|
.agent_root()
|
|
259
331
|
}
|
|
260
332
|
|
|
261
|
-
/// Wait for `GET {origin}/health
|
|
262
|
-
/// worker has not started serving yet.
|
|
333
|
+
/// Wait for `GET {origin}/health` on the **host** origin the window loads.
|
|
263
334
|
///
|
|
264
335
|
/// Replaces the old TCP-connect probe, which proved only that *something*
|
|
265
|
-
/// had bound the port.
|
|
266
|
-
///
|
|
267
|
-
/// open reach a healthy worker? With the kill switch on there is nothing to
|
|
268
|
-
/// wait for and this returns immediately.
|
|
336
|
+
/// had bound the port. After One Door this is never a bare worker port:
|
|
337
|
+
/// `plan.origin` is the in-process gateway or the attached lattice-host.
|
|
269
338
|
pub async fn wait_until_serving(&self) -> bool {
|
|
270
|
-
if self.plan.disabled {
|
|
271
|
-
return false;
|
|
272
|
-
}
|
|
273
339
|
wait_for_health(
|
|
274
340
|
&self.supervisor.client(),
|
|
275
341
|
&self.plan.origin,
|
|
@@ -349,8 +415,8 @@ impl DesktopBackend {
|
|
|
349
415
|
}
|
|
350
416
|
if !self.supervised() {
|
|
351
417
|
return format!(
|
|
352
|
-
"external
|
|
353
|
-
self.plan.
|
|
418
|
+
"external lattice-host at {} (not started here)",
|
|
419
|
+
self.plan.origin
|
|
354
420
|
);
|
|
355
421
|
}
|
|
356
422
|
match &status.last_error {
|
|
@@ -384,16 +450,18 @@ mod tests {
|
|
|
384
450
|
}
|
|
385
451
|
|
|
386
452
|
#[test]
|
|
387
|
-
fn
|
|
453
|
+
fn a_retired_direct_flag_still_fronts_the_gateway() {
|
|
388
454
|
let shell = backend(
|
|
389
455
|
StaticProbe::new()
|
|
390
456
|
.with_env(DIRECT_ENV, "1")
|
|
391
457
|
.with_env(PORT_ENV, "41841"),
|
|
392
458
|
);
|
|
393
|
-
assert_eq!(shell.topology(), Topology::
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
459
|
+
assert_eq!(shell.topology(), Topology::Gateway);
|
|
460
|
+
assert_ne!(shell.plan.worker_origin, shell.plan.origin);
|
|
461
|
+
assert!(
|
|
462
|
+
shell.jobs.is_some(),
|
|
463
|
+
"gateway topology still mounts /host/jobs"
|
|
464
|
+
);
|
|
397
465
|
}
|
|
398
466
|
|
|
399
467
|
#[test]
|
|
@@ -403,28 +471,33 @@ mod tests {
|
|
|
403
471
|
assert_eq!(shell.app_url(), "http://127.0.0.1:9100/app");
|
|
404
472
|
assert!(!shell.supervised());
|
|
405
473
|
assert_eq!(shell.topology(), Topology::External);
|
|
474
|
+
assert!(
|
|
475
|
+
shell.jobs.is_none(),
|
|
476
|
+
"an attached host is not ours to schedule"
|
|
477
|
+
);
|
|
406
478
|
}
|
|
407
479
|
|
|
408
480
|
#[test]
|
|
409
|
-
fn
|
|
410
|
-
let shell = backend(
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
481
|
+
fn a_retired_kill_switch_still_fronts_the_gateway() {
|
|
482
|
+
let shell = backend(
|
|
483
|
+
StaticProbe::new()
|
|
484
|
+
.with_env(NO_BACKEND_ENV, "1")
|
|
485
|
+
.with_env(PORT_ENV, "41845"),
|
|
486
|
+
);
|
|
487
|
+
assert!(shell.supervised());
|
|
488
|
+
assert_eq!(shell.topology(), Topology::Gateway);
|
|
489
|
+
assert_eq!(shell.origin(), "http://127.0.0.1:41845");
|
|
414
490
|
}
|
|
415
491
|
|
|
416
492
|
#[test]
|
|
417
|
-
fn
|
|
493
|
+
fn an_explicit_origin_outranks_the_retired_kill_switch() {
|
|
418
494
|
let shell = backend(
|
|
419
495
|
StaticProbe::new()
|
|
420
496
|
.with_env(NO_BACKEND_ENV, "1")
|
|
421
497
|
.with_env(ORIGIN_ENV, "http://127.0.0.1:9100"),
|
|
422
498
|
);
|
|
423
499
|
assert!(!shell.supervised(), "still nothing is spawned");
|
|
424
|
-
|
|
425
|
-
!shell.plan.disabled,
|
|
426
|
-
"a worker was named, so the shell waits"
|
|
427
|
-
);
|
|
500
|
+
assert_eq!(shell.topology(), Topology::External);
|
|
428
501
|
}
|
|
429
502
|
|
|
430
503
|
#[test]
|
|
@@ -437,19 +510,19 @@ mod tests {
|
|
|
437
510
|
shell.command_text(&status),
|
|
438
511
|
"unavailable: worker unavailable"
|
|
439
512
|
);
|
|
440
|
-
status.command = Some("/usr/bin/python3 -m latticeai.
|
|
513
|
+
status.command = Some("/usr/bin/python3 -m latticeai.worker_app".into());
|
|
441
514
|
assert_eq!(
|
|
442
515
|
shell.command_text(&status),
|
|
443
|
-
"/usr/bin/python3 -m latticeai.
|
|
516
|
+
"/usr/bin/python3 -m latticeai.worker_app"
|
|
444
517
|
);
|
|
445
518
|
}
|
|
446
519
|
|
|
447
520
|
#[test]
|
|
448
|
-
fn
|
|
521
|
+
fn an_external_host_is_named_by_its_own_origin() {
|
|
449
522
|
let shell = backend(StaticProbe::new().with_env(ORIGIN_ENV, "http://127.0.0.1:9100"));
|
|
450
523
|
assert_eq!(
|
|
451
524
|
shell.command_text(&WorkerStatus::idle(9100, false)),
|
|
452
|
-
"external
|
|
525
|
+
"external lattice-host at http://127.0.0.1:9100 (not started here)"
|
|
453
526
|
);
|
|
454
527
|
}
|
|
455
528
|
|
|
@@ -470,18 +543,18 @@ mod tests {
|
|
|
470
543
|
}
|
|
471
544
|
|
|
472
545
|
#[test]
|
|
473
|
-
fn
|
|
474
|
-
let shell = backend(StaticProbe::new().with_env(
|
|
475
|
-
let value =
|
|
476
|
-
|
|
477
|
-
assert_eq!(value["topology"], "
|
|
546
|
+
fn an_external_shell_reports_no_local_gateway_origin() {
|
|
547
|
+
let shell = backend(StaticProbe::new().with_env(ORIGIN_ENV, "http://127.0.0.1:9100"));
|
|
548
|
+
let value = serde_json::to_value(shell.render(&WorkerStatus::idle(9100, false)))
|
|
549
|
+
.expect("serialise");
|
|
550
|
+
assert_eq!(value["topology"], "external");
|
|
478
551
|
assert!(value["gateway_origin"].is_null());
|
|
479
552
|
assert_eq!(value["worker_origin"], value["origin"]);
|
|
480
553
|
}
|
|
481
554
|
|
|
482
555
|
#[test]
|
|
483
556
|
fn stopping_a_gateway_that_never_started_is_a_no_op() {
|
|
484
|
-
let shell = backend(StaticProbe::new().with_env(
|
|
557
|
+
let shell = backend(StaticProbe::new().with_env(ORIGIN_ENV, "http://127.0.0.1:9100"));
|
|
485
558
|
shell.stop_gateway();
|
|
486
559
|
shell.stop_gateway();
|
|
487
560
|
}
|
|
@@ -492,7 +565,7 @@ mod tests {
|
|
|
492
565
|
fn a_healthy_shell_names_no_gateway_error() {
|
|
493
566
|
for probe in [
|
|
494
567
|
StaticProbe::new().with_env(PORT_ENV, "41844"),
|
|
495
|
-
StaticProbe::new().with_env(
|
|
568
|
+
StaticProbe::new().with_env(ORIGIN_ENV, "http://127.0.0.1:9100"),
|
|
496
569
|
] {
|
|
497
570
|
let shell = backend(probe);
|
|
498
571
|
assert_eq!(shell.gateway_error(), None);
|
|
@@ -518,9 +591,13 @@ mod tests {
|
|
|
518
591
|
let reason = shell.gateway_error().expect("the failure is recorded");
|
|
519
592
|
assert!(reason.contains("could not bind"), "{reason}");
|
|
520
593
|
assert!(
|
|
521
|
-
reason.contains("
|
|
594
|
+
reason.contains("LATTICEAI_DESKTOP_BACKEND_ORIGIN"),
|
|
522
595
|
"the way out is named: {reason}"
|
|
523
596
|
);
|
|
597
|
+
assert!(
|
|
598
|
+
!reason.contains("LATTICEAI_DESKTOP_DIRECT"),
|
|
599
|
+
"the retired hatch must not be offered: {reason}"
|
|
600
|
+
);
|
|
524
601
|
assert!(
|
|
525
602
|
shell.app_url().contains(&port.to_string()),
|
|
526
603
|
"app_url still names the port nothing bound — which is why boot must \
|
|
@@ -531,4 +608,33 @@ mod tests {
|
|
|
531
608
|
assert_eq!(value["gateway_error"], reason);
|
|
532
609
|
drop(occupied);
|
|
533
610
|
}
|
|
611
|
+
|
|
612
|
+
#[test]
|
|
613
|
+
fn an_existing_backend_cmd_is_left_alone() {
|
|
614
|
+
let probe = StaticProbe::new().with_env(BACKEND_CMD_ENV, "custom-worker --flag");
|
|
615
|
+
assert_eq!(worker_launch_command(&probe), None);
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
#[test]
|
|
619
|
+
fn a_bundled_tree_is_left_to_the_supervisor() {
|
|
620
|
+
let probe = StaticProbe::new()
|
|
621
|
+
.with_resource_dir("/app/Resources")
|
|
622
|
+
.with_file("/app/Resources/latticeai/worker_app.py");
|
|
623
|
+
assert_eq!(worker_launch_command(&probe), None);
|
|
624
|
+
let legacy = StaticProbe::new()
|
|
625
|
+
.with_resource_dir("/app/Resources")
|
|
626
|
+
.with_file("/app/Resources/_up_/latticeai/cli/entrypoint.py");
|
|
627
|
+
assert_eq!(worker_launch_command(&legacy), None);
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
#[test]
|
|
631
|
+
fn an_unpackaged_shell_pins_the_worker_module() {
|
|
632
|
+
let probe = StaticProbe::new().with_importable("/opt/homebrew/bin/python3");
|
|
633
|
+
let command = worker_launch_command(&probe).expect("pin");
|
|
634
|
+
assert!(command.ends_with("-m latticeai.worker_app"), "{command}");
|
|
635
|
+
assert!(
|
|
636
|
+
!command.contains("latticeai.cli.entrypoint"),
|
|
637
|
+
"the product server is gone: {command}"
|
|
638
|
+
);
|
|
639
|
+
}
|
|
534
640
|
}
|
package/src-tauri/src/main.rs
CHANGED
|
@@ -9,13 +9,14 @@
|
|
|
9
9
|
//! stops the worker.
|
|
10
10
|
//!
|
|
11
11
|
//! Since 11.5.0 the shell also *serves* that front door: the gateway runs
|
|
12
|
-
//! in-process on the public port and the worker sits behind it
|
|
13
|
-
//!
|
|
12
|
+
//! in-process on the public port and the worker sits behind it. 11.6.0 One
|
|
13
|
+
//! Door drops the Python-direct escape hatches — see [`topology`].
|
|
14
14
|
//!
|
|
15
15
|
//! The five command names and their response shapes are unchanged — the
|
|
16
16
|
//! frontend (`frontend/src/api/base.ts`, `frontend/src/api/client.ts`) invokes
|
|
17
|
-
//!
|
|
18
|
-
//! in 11.5.0 are
|
|
17
|
+
//! `backend_origin`, `backend_status` and `select_folder` by name and reads
|
|
18
|
+
//! `backend_status` as a plain record. The fields added in 11.5.0 are
|
|
19
|
+
//! additive; nothing was renamed or removed.
|
|
19
20
|
|
|
20
21
|
mod backend;
|
|
21
22
|
mod folder;
|
|
@@ -60,11 +61,12 @@ fn select_folder() -> Option<String> {
|
|
|
60
61
|
folder::select_folder()
|
|
61
62
|
}
|
|
62
63
|
|
|
63
|
-
/// Bring the
|
|
64
|
+
/// Bring the host up, then point the webview at `{origin}/app`.
|
|
64
65
|
///
|
|
65
|
-
/// The navigation waits on the
|
|
66
|
-
///
|
|
67
|
-
/// `/app` before the
|
|
66
|
+
/// The navigation waits on the **host's** `GET /health` at the same origin the
|
|
67
|
+
/// window loads — never a bare Python worker. A bound socket only proves
|
|
68
|
+
/// something is listening, and landing on `/app` before the host answers is
|
|
69
|
+
/// what used to show a blank window.
|
|
68
70
|
fn boot(app: &tauri::App) {
|
|
69
71
|
let Some(window) = app.get_webview_window("main") else {
|
|
70
72
|
return;
|
|
@@ -75,13 +77,7 @@ fn boot(app: &tauri::App) {
|
|
|
75
77
|
|
|
76
78
|
let shell = Arc::clone(&app.state::<Arc<DesktopBackend>>());
|
|
77
79
|
tauri::async_runtime::spawn(async move {
|
|
78
|
-
|
|
79
|
-
if !status.healthy && !shell.supervised() {
|
|
80
|
-
// A supervised worker already had its health gate inside `start`;
|
|
81
|
-
// an adopted one (LATTICEAI_DESKTOP_BACKEND_ORIGIN) still needs it.
|
|
82
|
-
// Waiting in both places would double the worst case.
|
|
83
|
-
shell.wait_until_serving().await;
|
|
84
|
-
}
|
|
80
|
+
shell.start().await;
|
|
85
81
|
// One reason not to navigate, and it is not "the worker is slow": if
|
|
86
82
|
// this shell was supposed to serve the front door and could not bind
|
|
87
83
|
// it, `app_url` names a port nothing will ever listen on, and sending
|
|
@@ -92,9 +88,13 @@ fn boot(app: &tauri::App) {
|
|
|
92
88
|
eprintln!("lattice-ai-desktop: staying on the bundled shell — {reason}");
|
|
93
89
|
return;
|
|
94
90
|
}
|
|
95
|
-
//
|
|
96
|
-
//
|
|
97
|
-
//
|
|
91
|
+
// Host /health at the origin the window is about to load. An attached
|
|
92
|
+
// host (LATTICEAI_DESKTOP_BACKEND_ORIGIN) never ran start_gateway, so
|
|
93
|
+
// this is also the first time we wait for it.
|
|
94
|
+
shell.wait_until_serving().await;
|
|
95
|
+
// Navigate either way: a window showing the browser's own "cannot
|
|
96
|
+
// connect" is more use than a window showing nothing while a host that
|
|
97
|
+
// will never arrive is waited for.
|
|
98
98
|
if let Ok(url) = tauri::Url::parse(&shell.app_url()) {
|
|
99
99
|
let _ = window.navigate(url);
|
|
100
100
|
}
|