ltcai 11.5.1 → 11.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +92 -117
- package/bin/ltcai.js +234 -24
- package/docs/CHANGELOG.md +129 -0
- package/docs/COMMUNITY_AND_PLUGINS.md +1 -1
- package/docs/DEVELOPMENT.md +8 -6
- package/docs/ENTERPRISE.md +2 -1
- package/docs/HYBRID_CLOUD_KG_STREAMING.md +8 -4
- 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/architecture.md +4 -4
- package/docs/kg-schema.md +1 -1
- package/docs/v11.5.2_TIGHT_SHIP_PLAN.md +144 -0
- 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 -597
- package/latticeai/__init__.py +1 -1
- package/latticeai/api/agent_worker_seam.py +7 -80
- package/latticeai/api/health.py +26 -20
- package/latticeai/api/local_files.py +25 -608
- package/latticeai/api/models.py +12 -87
- package/latticeai/api/search.py +17 -231
- 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/cli/runtime.py +7 -3
- package/latticeai/core/agent_permission.py +16 -91
- package/latticeai/core/config.py +47 -3
- package/latticeai/core/csrf.py +28 -2
- package/latticeai/core/embedding_providers/__init__.py +3 -5
- package/latticeai/core/embedding_providers/base.py +1 -1
- package/latticeai/core/embedding_providers/text.py +1 -1
- package/latticeai/core/http_origin.py +146 -0
- package/latticeai/core/io_utils.py +2 -11
- package/latticeai/core/messages.py +94 -531
- package/latticeai/core/model_compat.py +2 -8
- package/latticeai/core/module_probe.py +37 -0
- package/latticeai/core/security.py +13 -0
- package/latticeai/core/sessions.py +3 -2
- package/latticeai/core/sse.py +25 -0
- package/latticeai/core/users.py +0 -9
- package/latticeai/models/router/documents.py +0 -35
- package/latticeai/models/router/registry.py +0 -4
- package/latticeai/runtime/access_runtime.py +16 -18
- 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 +101 -389
- package/latticeai/runtime/build_phases/foundation.py +82 -392
- package/latticeai/runtime/build_phases/web.py +91 -406
- 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 +14 -143
- package/latticeai/runtime/security_runtime.py +10 -103
- package/latticeai/services/architecture_readiness.py +82 -43
- package/latticeai/services/model_capability_registry.py +0 -15
- package/latticeai/services/model_catalog.py +0 -7
- package/latticeai/services/model_loading.py +3 -2
- package/latticeai/services/model_runtime/__init__.py +2 -68
- package/latticeai/services/model_runtime/engines.py +27 -128
- package/latticeai/services/model_runtime/loading.py +2 -2
- 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 -390
- 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 +3 -6
- 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 +19 -6
- package/scripts/check_current_release_docs.mjs +7 -4
- package/scripts/check_legacy_debt.mjs +1 -1
- 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 +31 -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 +223 -43
- package/src-tauri/src/main.rs +27 -17
- package/src-tauri/src/topology.rs +58 -88
- package/src-tauri/tauri.conf.json +2 -3
- package/static/app/asset-manifest.json +41 -41
- package/static/app/assets/{Act-Drs_jd-O.js → Act-CToZnOHz.js} +1 -1
- package/static/app/assets/{AdminConsole-BqNx5oF6.js → AdminConsole-D5kbrBu8.js} +1 -1
- package/static/app/assets/{Brain-C7bdNmz-.js → Brain-C6zCdv4S.js} +1 -1
- package/static/app/assets/{BrainHome-DcTnINcI.js → BrainHome-D4n3EDUt.js} +1 -1
- package/static/app/assets/{BrainSignals-Df1MRIPD.js → BrainSignals-CzeZ-vQ9.js} +1 -1
- package/static/app/assets/{Capture-Dgsxvnbx.js → Capture-DPcyTczq.js} +1 -1
- package/static/app/assets/{Chronicle-BrkTxJK1.js → Chronicle-D3Nx-oWS.js} +1 -1
- package/static/app/assets/{CommandPalette-DDziw7Oj.js → CommandPalette-DPPvpp28.js} +1 -1
- package/static/app/assets/{Library-CYxeuraA.js → Library-Co2qTu3I.js} +1 -1
- package/static/app/assets/{LivingBrain-CNp6mvCm.js → LivingBrain-Bsmzwy8_.js} +1 -1
- package/static/app/assets/{ProductFlow-BVsowu3Z.js → ProductFlow-CBLdmesT.js} +1 -1
- package/static/app/assets/{ReviewCard-D1LbOfJS.js → ReviewCard-CfR6DLs7.js} +1 -1
- package/static/app/assets/{System-DcRAq7wj.js → System-Ce-P2YL6.js} +1 -1
- package/static/app/assets/arrow-left-DD5jFGHV.js +1 -0
- package/static/app/assets/{bot-BK2xQ9mN.js → bot-C5-XIww2.js} +1 -1
- package/static/app/assets/{brain-BZNztFBb.js → brain-CFRJUvdX.js} +1 -1
- package/static/app/assets/{button-CjueubVZ.js → button-DI1KcQP-.js} +1 -1
- package/static/app/assets/circle-check-CY20XMCh.js +1 -0
- package/static/app/assets/{circle-pause-HRjSmpyY.js → circle-pause-C8HHyood.js} +1 -1
- package/static/app/assets/{circle-play-CMcKDVwu.js → circle-play-Cufc235E.js} +1 -1
- package/static/app/assets/{cpu-B_MyTfYr.js → cpu-DW2_JVsv.js} +1 -1
- package/static/app/assets/{download-CTy0EByV.js → download-gbdKTBb8.js} +1 -1
- package/static/app/assets/{folder-open-DF6bLhTg.js → folder-open-C9ydyX33.js} +1 -1
- package/static/app/assets/{hard-drive-CpWHG77C.js → hard-drive-BxNMzBM3.js} +1 -1
- package/static/app/assets/index-BovSWRmQ.css +2 -0
- package/static/app/assets/{index-Dd6abJHX.js → index-q9XyDY7A.js} +3 -3
- package/static/app/assets/{input-bVgIRN3s.js → input-GLD94Y_K.js} +1 -1
- package/static/app/assets/{link-2-bg6CG5Vk.js → link-2-B4Y0gz1S.js} +1 -1
- package/static/app/assets/{permissionCopy-DFTf1HDZ.js → permissionCopy-CxrV0fvU.js} +1 -1
- package/static/app/assets/{primitives-D7D-sQ3T.js → primitives-2ANdAsu2.js} +1 -1
- package/static/app/assets/search-DTxtjQ07.js +1 -0
- package/static/app/assets/{share-2-BLzo7U4L.js → share-2-DxArfiuI.js} +1 -1
- package/static/app/assets/{shield-alert-BmngqnsJ.js → shield-alert-CgftuFFs.js} +1 -1
- package/static/app/assets/{textarea-DOSlAQQ3.js → textarea-BHVBAoCr.js} +1 -1
- package/static/app/assets/{useFocusTrap-pZhgeee4.js → useFocusTrap-Dzq2j_OG.js} +1 -1
- package/static/app/assets/{useMutation-BMDwNk4I.js → useMutation-BcqfMLNq.js} +1 -1
- package/static/app/assets/{useQuery-CSjKttRo.js → useQuery-DBzLKCOv.js} +1 -1
- package/static/app/assets/{utils-D3u_yv7B.js → utils-B-Aah1bO.js} +1 -1
- package/static/app/assets/{workspace-H3bMjYXC.js → workspace-B6fFhoko.js} +1 -1
- package/static/app/index.html +4 -4
- package/static/sw.js +1 -1
- package/desktop/electron/README.md +0 -9
- package/desktop/electron/main.cjs +0 -58
- package/desktop/electron/preload.cjs +0 -5
- 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 -546
- 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 -170
- package/lattice_brain/graph/vector_index/brute_force.py +0 -114
- package/lattice_brain/graph/vector_index/hnsw.py +0 -293
- package/lattice_brain/graph/vector_index/jobs.py +0 -287
- package/lattice_brain/graph/vector_index/quantized.py +0 -151
- 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 -383
- package/lattice_brain/memory.py +0 -102
- 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 -714
- package/lattice_brain/quality.py +0 -592
- 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 -244
- 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 -360
- 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 -901
- package/latticeai/api/chat_contracts.py +0 -73
- package/latticeai/api/chat_documents.py +0 -276
- package/latticeai/api/chat_helpers.py +0 -463
- 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 -485
- 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 -410
- 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 -351
- 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 -157
- 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/graph_curator.py +0 -11
- package/latticeai/core/hooks.py +0 -11
- package/latticeai/core/invitations.py +0 -131
- package/latticeai/core/legacy_compatibility.py +0 -243
- package/latticeai/core/local_embeddings.py +0 -104
- 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/multi_agent.py +0 -11
- 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 -423
- package/latticeai/core/run_store.py +0 -252
- package/latticeai/core/timezones.py +0 -80
- package/latticeai/core/workflow_engine.py +0 -11
- package/latticeai/core/workspace_computer_memory.py +0 -84
- package/latticeai/core/workspace_graph_trace.py +0 -161
- 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 -988
- 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 -69
- 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 -118
- package/latticeai/core/workspace_runs.py +0 -732
- package/latticeai/core/workspace_skills.py +0 -114
- 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 -163
- 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 -128
- package/latticeai/runtime/network_config_runtime.py +0 -56
- package/latticeai/runtime/permission_mode_wiring.py +0 -119
- 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 -689
- 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 -264
- 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 -505
- package/latticeai/services/chat_service.py +0 -243
- package/latticeai/services/chronicle.py +0 -557
- 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 -255
- 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 -178
- package/latticeai/services/ingestion.py +0 -11
- package/latticeai/services/interop_bridges.py +0 -978
- package/latticeai/services/kg_portability.py +0 -11
- 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/model_recommendation.py +0 -224
- package/latticeai/services/model_runtime/cloud.py +0 -87
- package/latticeai/services/multimodal_streaming.py +0 -129
- package/latticeai/services/network_boundary_service.py +0 -154
- 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 -170
- 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 -81
- package/latticeai/services/triggers.py +0 -378
- package/latticeai/services/upload_service.py +0 -185
- package/latticeai/services/workspace_service.py +0 -171
- package/latticeai/setup/__init__.py +0 -25
- package/latticeai/setup/auto_setup.py +0 -857
- package/latticeai/setup/demo_corpus.py +0 -98
- package/latticeai/setup/wizard/__init__.py +0 -126
- package/latticeai/setup/wizard/catalog.py +0 -172
- package/latticeai/setup/wizard/detect.py +0 -323
- package/latticeai/setup/wizard/install.py +0 -348
- package/latticeai/setup/wizard/paths.py +0 -168
- 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 -907
- package/scripts/generate_rust_parity_fixtures.py +0 -1000
- package/scripts/measure_brain_home_fill.mjs +0 -141
- package/scripts/migrate_brain_storage.py +0 -57
- package/scripts/parity_fixture_corpus_docgen.py +0 -341
- package/scripts/profile_kg.py +0 -355
- package/server.py +0 -30
- package/static/app/assets/arrow-left-BHYmOTWU.js +0 -1
- package/static/app/assets/circle-check-CLeWJr67.js +0 -1
- package/static/app/assets/index-DxmOfNRi.css +0 -2
- package/static/app/assets/search-BgSVX6NG.js +0 -1
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
[](https://github.com/TaeSooPark-PTS/LatticeAI/actions/workflows/ci.yml)
|
|
12
12
|
[](LICENSE)
|
|
13
13
|
|
|
14
|
-

|
|
15
15
|
|
|
16
16
|
Chat, files, folders, notes, and web pages all flow into one durable knowledge
|
|
17
17
|
graph on your computer. Any model — local MLX or cloud — can speak with that
|
|
@@ -24,10 +24,10 @@ memory. Nothing leaves your machine without explicit consent.
|
|
|
24
24
|
|
|
25
25
|
| | |
|
|
26
26
|
| --- | --- |
|
|
27
|
-
| **See your Brain's story in time** — a growth curve, an activity heatmap, and each day's story, rewindable to any past moment  | **Chat with a Brain that remembers** — every conversation grows durable, source-linked memory  |
|
|
28
|
+
| **See how knowledge connects** — a real relationship graph, not a file list  | **Capture anything** — files, whole folders, notes, screenshots, web pages  |
|
|
29
|
+
| **Automate with review** — agent changes become proposals you approve first  | **Pick a model in one click** — recommended local models for your hardware  |
|
|
30
|
+
| **Watch a file become memory** — three named steps, not a pipeline diagram  | **Say how much it may do alone** — one dial in plain words; dangerous actions stay blocked either way  |
|
|
31
31
|
|
|
32
32
|
## Why Lattice AI
|
|
33
33
|
|
|
@@ -58,72 +58,81 @@ First-run flow — wake the Brain, pick the owner, load a recommended model:
|
|
|
58
58
|
|
|
59
59
|
| | | |
|
|
60
60
|
| --- | --- | --- |
|
|
61
|
-
|  |  |  |
|
|
62
62
|
|
|
63
63
|
Screenshot index and capture notes:
|
|
64
|
-
[output/release/v11.
|
|
64
|
+
[output/release/v11.6.0/SCREENSHOT_INDEX.md](output/release/v11.6.0/SCREENSHOT_INDEX.md)
|
|
65
65
|
|
|
66
66
|
## Current Release
|
|
67
67
|
|
|
68
|
-
The current release is **11.
|
|
69
|
-
|
|
70
|
-
The
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
- `
|
|
68
|
+
The current release is **11.6.0 — One Door**:
|
|
69
|
+
|
|
70
|
+
The product now has one front door, and it is Rust. `lattice-host` serves
|
|
71
|
+
**420 operations across 41 route families** at the paths they always had,
|
|
72
|
+
and the Python package is no longer a web application at all — it is a
|
|
73
|
+
pure-compute **AI worker** with **28 routes**: LLM inference and streaming,
|
|
74
|
+
embedding, extraction, parsing, four document renderers, speech-to-text,
|
|
75
|
+
multimodal description, the model and engine catalog, `sysinfo`, and
|
|
76
|
+
`/health`. Nine crates hold the product; the door forwards exactly the 28
|
|
77
|
+
and answers `404 {"detail":"Not Found"}` for anything else, from a
|
|
78
|
+
committed allowlist that a drift gate regenerates and compares.
|
|
79
|
+
|
|
80
|
+
- **Every write is native.** The knowledge-graph write engine moved into
|
|
81
|
+
`lattice-core`: ingest, curation, provenance, taxonomy and the vector
|
|
82
|
+
queue. It is held to Python's bytes by a **32-step row-parity battery**
|
|
83
|
+
that dumps every table after every step with zero tolerated differences,
|
|
84
|
+
and by a schema comparison over all **67 objects** in `sqlite_master`
|
|
85
|
+
(indexes and FTS shadow tables included). Seventeen graph tables changed
|
|
86
|
+
owner from the worker to Rust, and the single-writer invariant is now a
|
|
87
|
+
test rather than a convention.
|
|
88
|
+
- **The surface is replayed, not re-described.** **1,487 recorded HTTP
|
|
89
|
+
cases** across twelve committed fixture files — captured from the real
|
|
90
|
+
Python app while it still served them — are replayed against the native
|
|
91
|
+
routes, status line and body compared. The retrieval, chunking, agent
|
|
92
|
+
kernel and agent-loop golden families are unchanged and still green.
|
|
93
|
+
- **298 Python files and 73,617 lines were deleted.** What remains is 127
|
|
94
|
+
files and about 20,900 lines, all of it compute, at **100.00% statement
|
|
95
|
+
and branch coverage** with `fail_under=100` and no new pragmas.
|
|
96
|
+
- **What the port found.** The Python oracle's own bugs are documented
|
|
97
|
+
rather than smoothed over: four graph-write divergences (a `kgv2_*` view
|
|
98
|
+
that updates `type` on conflict where `nodes` does not; two writers that
|
|
99
|
+
serialise without `sort_keys`; a hash computed from CPython's default
|
|
100
|
+
JSON separators), a documented redaction rule that never fired, and a
|
|
101
|
+
change-proposal kind whitelist that could never approve a folder
|
|
102
|
+
reorganization. Three known-wrong behaviours were ported **as they are**
|
|
103
|
+
so the surface does not change under users mid-release — they are listed
|
|
104
|
+
in [RELEASE_NOTES_v11.6.0.md](RELEASE_NOTES_v11.6.0.md).
|
|
105
|
+
- **What was removed, and why.** The **Telegram bridge** is gone: it lived
|
|
106
|
+
in the platform code that became the worker, and a bridge with no product
|
|
107
|
+
server to bridge to is not a feature. **SSO/OIDC login and callback
|
|
108
|
+
flows** are gone with it — the configuration surface remains, and
|
|
109
|
+
password login is native. Both are consequences of the worker boundary,
|
|
110
|
+
not decisions taken on their own merits.
|
|
111
|
+
|
|
112
|
+
Full disclosure of gaps, ported bugs and removed surfaces:
|
|
113
|
+
[RELEASE_NOTES_v11.6.0.md](RELEASE_NOTES_v11.6.0.md)
|
|
114
|
+
|
|
115
|
+
Expected artifacts for 11.6.0 release must use exact filenames:
|
|
116
|
+
|
|
117
|
+
- `dist/ltcai-11.6.0-py3-none-any.whl`
|
|
118
|
+
- `dist/ltcai-11.6.0.tar.gz`
|
|
119
|
+
- `ltcai-11.6.0.tgz`
|
|
120
|
+
- `dist/ltcai-11.6.0.vsix`
|
|
121
|
+
- `src-tauri/target/release/bundle/dmg/Lattice AI_11.6.0_aarch64.dmg`
|
|
118
122
|
|
|
119
123
|
Do not use wildcard artifact uploads. Package registry publishing remains owner-run.
|
|
120
124
|
|
|
125
|
+
Release notes: [RELEASE.md](RELEASE.md) · Full history: [docs/CHANGELOG.md](docs/CHANGELOG.md)
|
|
126
|
+
|
|
121
127
|
## Architecture At A Glance
|
|
122
128
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
129
|
+
One Rust server on localhost is the source of truth: `lattice-host` answers
|
|
130
|
+
every product route, owns every write to the Brain, and supervises a Python
|
|
131
|
+
**AI worker** it reaches over loopback for the things a model does — inference,
|
|
132
|
+
embedding, extraction, parsing, rendering, speech-to-text. The React/Vite
|
|
133
|
+
frontend and the Tauri desktop shell sit on top of that one door. Local-first
|
|
134
|
+
by default — cloud model calls, downloads, Brain Network, and update checks are
|
|
135
|
+
opt-in.
|
|
127
136
|
|
|
128
137
|
See [ARCHITECTURE.md](ARCHITECTURE.md) for details and
|
|
129
138
|
[docs/DEVELOPMENT.md](docs/DEVELOPMENT.md) for the developer workflow
|
|
@@ -133,22 +142,37 @@ See [ARCHITECTURE.md](ARCHITECTURE.md) for details and
|
|
|
133
142
|
## Known Limitations
|
|
134
143
|
|
|
135
144
|
- External package registries are owner-published and can lag behind GitHub.
|
|
136
|
-
-
|
|
137
|
-
|
|
138
|
-
- Docker, model downloads, cloud model calls,
|
|
139
|
-
|
|
145
|
+
- SQLite is the live local Brain store. The optional PostgreSQL/pgvector
|
|
146
|
+
migration tooling is not part of the 11.6.0 worker.
|
|
147
|
+
- Docker, model downloads, cloud model calls, Brain Network, and update checks
|
|
148
|
+
require explicit user action.
|
|
149
|
+
- **The Telegram bridge was removed in 11.6.0** — it lived in the platform code
|
|
150
|
+
that became the AI worker. **SSO/OIDC login and callback flows were removed
|
|
151
|
+
with it**; the configuration surface remains and password login is native.
|
|
140
152
|
- Conversation does not fabricate answers when no model is loaded. Agent and
|
|
141
153
|
workflow simulation without a loaded LLM is deterministic and LLM-free (it
|
|
142
154
|
does not call a model) — labeled as such, never presented as autonomous
|
|
143
155
|
model success.
|
|
144
|
-
-
|
|
145
|
-
|
|
146
|
-
|
|
156
|
+
- `POST /worker/render/pdf` ships working out of the box: `reportlab` is a
|
|
157
|
+
required dependency as of 11.6.0 (it used to be an undeclared lazy import
|
|
158
|
+
that raised a 500; `ltcai[pdf]` remains as an empty alias for older
|
|
159
|
+
install instructions).
|
|
160
|
+
- Known gaps carried openly into this release — upload extraction enrichment is
|
|
161
|
+
UTF-8-text only, supplied vectors cover the primary ingest node, and the
|
|
162
|
+
pointer-control tools still execute in the worker — are listed with their
|
|
163
|
+
reasons in [RELEASE_NOTES_v11.6.0.md](RELEASE_NOTES_v11.6.0.md).
|
|
147
164
|
|
|
148
165
|
## Release History
|
|
149
166
|
|
|
167
|
+
Public history starts at 11.0.0. 11.6.0 rebuilt the product server in Rust and
|
|
168
|
+
reduced the Python package to an AI worker, so a 10.x or 9.x install is a
|
|
169
|
+
different program; `SECURITY.md` supports only 11.x, and this table states the
|
|
170
|
+
same boundary. Earlier notes stay in the tree as `RELEASE_NOTES_v*.md` files.
|
|
171
|
+
|
|
150
172
|
| Version | Theme |
|
|
151
173
|
| --- | --- |
|
|
174
|
+
| 11.6.0 | One Door |
|
|
175
|
+
| 11.5.2 | Tight Ship |
|
|
152
176
|
| 11.5.1 | Rust Full Loop |
|
|
153
177
|
| 11.5.0 | Rust Complete |
|
|
154
178
|
| 11.4.0 | Rust Foundation |
|
|
@@ -157,54 +181,5 @@ See [ARCHITECTURE.md](ARCHITECTURE.md) for details and
|
|
|
157
181
|
| 11.1.0 | Product Intelligence |
|
|
158
182
|
| 11.0.1 | Both Branches |
|
|
159
183
|
| 11.0.0 | Full Measure |
|
|
160
|
-
| 10.10.0 | Quiet Station |
|
|
161
|
-
| 10.9.0 | Never Blocks |
|
|
162
|
-
| 10.8.0 | Within Reach |
|
|
163
|
-
| 10.7.0 | Plain Surface |
|
|
164
|
-
| 10.6.4 | Loud Limits |
|
|
165
|
-
| 10.6.3 | Loud Limits |
|
|
166
|
-
| 10.6.2 | Ask First |
|
|
167
|
-
| 10.6.1 | First Things |
|
|
168
|
-
| 10.6.0 | Promoted Panels |
|
|
169
|
-
| 10.5.0 | Everyday Words |
|
|
170
|
-
| 10.4.0 | Named Ground |
|
|
171
|
-
| 10.3.0 | Measured Ground |
|
|
172
|
-
| 10.2.0 | Load-Bearing Fixes |
|
|
173
|
-
| 10.1.1 | Reachable Boundary |
|
|
174
|
-
| 10.1.0 | Hybrid Brain |
|
|
175
|
-
| 10.0.1 | One Source of Truth |
|
|
176
|
-
| 10.0.0 | Plain Language |
|
|
177
|
-
| 9.9.9 | Lean Shell |
|
|
178
|
-
| 9.9.8 | Autonomy Dial |
|
|
179
|
-
| 9.9.7 | No Gaps Left |
|
|
180
|
-
| 9.9.6 | Same Brain Everywhere |
|
|
181
|
-
| 9.9.5 | Closed Gaps |
|
|
182
|
-
| 9.9.4 | Durable Loops |
|
|
183
|
-
| 9.9.3 | Closed Loops |
|
|
184
|
-
| 9.9.2 | Artifact Trust |
|
|
185
|
-
| 9.9.1 | Clean Foundations |
|
|
186
|
-
| 9.9.0 | Fail-Closed Trust |
|
|
187
|
-
| 9.8.0 | Honest Knowledge Pipeline |
|
|
188
|
-
| 9.7.0 | Proactive Hybrid Brain |
|
|
189
|
-
| 9.6.0 | Trusted Agent Loop |
|
|
190
|
-
| 9.5.0 | Command Center |
|
|
191
|
-
| 9.4.0 | Question-Driven Everyday Automation |
|
|
192
|
-
| 9.3.0 | Proactive Brain Intelligence |
|
|
193
|
-
| 9.2.0 | Model-Agnostic File Generation |
|
|
194
|
-
| 9.1.0 | Code Review Completion & Fail-Closed Runtime |
|
|
195
|
-
| 9.0.0 | Code Review Closure & Runtime Cleanup |
|
|
196
184
|
|
|
197
185
|
Per-release details: [RELEASE_NOTES.md](RELEASE_NOTES.md)
|
|
198
|
-
|
|
199
|
-
## Documentation
|
|
200
|
-
|
|
201
|
-
- [docs/WHY_LATTICE.md](docs/WHY_LATTICE.md) — product philosophy
|
|
202
|
-
- [docs/TRUST_MODEL.md](docs/TRUST_MODEL.md) — local-first trust model
|
|
203
|
-
- [PRIVACY.md](PRIVACY.md) — privacy and external communication policy
|
|
204
|
-
- [FEATURE_STATUS.md](FEATURE_STATUS.md) — feature status and limitations
|
|
205
|
-
- [SECURITY.md](SECURITY.md) — security posture
|
|
206
|
-
- [RELEASE.md](RELEASE.md) — release guide and notes
|
|
207
|
-
|
|
208
|
-
## License
|
|
209
|
-
|
|
210
|
-
MIT. See [LICENSE](LICENSE).
|
package/bin/ltcai.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
const { spawn } = require("node:child_process");
|
|
4
|
-
const { spawnSync } = require("node:child_process");
|
|
3
|
+
const { spawn, spawnSync } = require("node:child_process");
|
|
5
4
|
const fs = require("node:fs");
|
|
6
5
|
const os = require("node:os");
|
|
7
6
|
const path = require("node:path");
|
|
@@ -11,6 +10,34 @@ const managedVenv = process.env.LTCAI_NPM_VENV || path.join(os.homedir(), ".ltca
|
|
|
11
10
|
const managedPython = process.platform === "win32"
|
|
12
11
|
? path.join(managedVenv, "Scripts", "python.exe")
|
|
13
12
|
: path.join(managedVenv, "bin", "python");
|
|
13
|
+
const hostName = process.platform === "win32" ? "lattice-host.exe" : "lattice-host";
|
|
14
|
+
const WORKER_MODULE = "latticeai.worker_app";
|
|
15
|
+
// Mirrors rust/lattice-host/src/supervisor/command.rs::WORKER_FACTORY — the
|
|
16
|
+
// supervisor appends `--host`/`--port` itself, so this is the whole of what a
|
|
17
|
+
// launcher can name.
|
|
18
|
+
const WORKER_FACTORY = `-m uvicorn ${WORKER_MODULE}:create_worker_app --factory`;
|
|
19
|
+
|
|
20
|
+
const USAGE = `\
|
|
21
|
+
ltcai — Lattice AI front door (lattice-host)
|
|
22
|
+
|
|
23
|
+
USAGE:
|
|
24
|
+
ltcai [OPTIONS]
|
|
25
|
+
ltcai doctor
|
|
26
|
+
|
|
27
|
+
OPTIONS:
|
|
28
|
+
--host <HOST> Bind hint (sets LATTICEAI_HOST). lattice-host listens on 127.0.0.1
|
|
29
|
+
--port <PORT> Gateway port (default: LATTICEAI_PORT, then 4825)
|
|
30
|
+
--worker-port <PORT> Pin the worker port instead of scanning
|
|
31
|
+
--no-spawn Do not start a worker; front an existing one
|
|
32
|
+
--no-jobs Mount /host/jobs but never run the timer
|
|
33
|
+
-h, --help Print this help
|
|
34
|
+
-V, --version Print the version
|
|
35
|
+
|
|
36
|
+
lattice-host is the only front door. It supervises the Python AI worker
|
|
37
|
+
(\`python ${WORKER_FACTORY}\`, with the port it chose).
|
|
38
|
+
LATTICEAI_* environment variables are passed through. Pin the host binary with
|
|
39
|
+
LATTICEAI_HOST_BIN or LTCAI_HOST, and the worker interpreter with LTCAI_PYTHON.
|
|
40
|
+
`;
|
|
14
41
|
|
|
15
42
|
function loadDotEnv(file) {
|
|
16
43
|
if (!fs.existsSync(file)) return;
|
|
@@ -61,7 +88,7 @@ function ensureManagedPython() {
|
|
|
61
88
|
if (!canImport(managedPython, "fastapi")) {
|
|
62
89
|
const requirements = path.join(root, "requirements.txt");
|
|
63
90
|
if (!fs.existsSync(requirements)) {
|
|
64
|
-
console.error(`[LTCAI] Missing ${requirements}. The npm package is incomplete and cannot start the Python
|
|
91
|
+
console.error(`[LTCAI] Missing ${requirements}. The npm package is incomplete and cannot start the Python worker.`);
|
|
65
92
|
process.exit(1);
|
|
66
93
|
}
|
|
67
94
|
console.log("[LTCAI] Installing Python dependencies. This can take a few minutes on first run.");
|
|
@@ -72,34 +99,217 @@ function ensureManagedPython() {
|
|
|
72
99
|
return managedPython;
|
|
73
100
|
}
|
|
74
101
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
102
|
+
function pythonCandidates(includeManaged) {
|
|
103
|
+
return [
|
|
104
|
+
process.env.LTCAI_PYTHON,
|
|
105
|
+
includeManaged ? ensureManagedPython() : managedPython,
|
|
106
|
+
path.join(root, ".venv", "bin", "python"),
|
|
107
|
+
path.join(root, "venv", "bin", "python"),
|
|
108
|
+
process.platform === "win32" ? path.join(root, ".venv", "Scripts", "python.exe") : null,
|
|
109
|
+
process.env.PYTHON,
|
|
110
|
+
"python3",
|
|
111
|
+
"python",
|
|
112
|
+
].filter(Boolean);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function resolveWorkerPython(bootstrap) {
|
|
116
|
+
for (const python of pythonCandidates(bootstrap)) {
|
|
117
|
+
if (canImport(python, WORKER_MODULE)) return python;
|
|
118
|
+
}
|
|
119
|
+
return pythonCandidates(bootstrap)[0] || "python3";
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function whichHost() {
|
|
123
|
+
const tool = process.platform === "win32" ? "where" : "which";
|
|
124
|
+
const result = spawnSync(tool, ["lattice-host"], { encoding: "utf8" });
|
|
125
|
+
if (result.status !== 0) return null;
|
|
126
|
+
const found = String(result.stdout || "").split(/\r?\n/).map((line) => line.trim()).find(Boolean);
|
|
127
|
+
return found && fs.existsSync(found) ? found : null;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function existingHostBinary() {
|
|
131
|
+
const pinned = process.env.LATTICEAI_HOST_BIN || process.env.LTCAI_HOST;
|
|
132
|
+
if (pinned && fs.existsSync(pinned)) return pinned;
|
|
133
|
+
const candidates = [
|
|
134
|
+
path.join(root, "rust", "target", "release", hostName),
|
|
135
|
+
path.join(root, "rust", "target", "debug", hostName),
|
|
136
|
+
path.join(root, "src-tauri", "target", "release", hostName),
|
|
137
|
+
path.join(root, "src-tauri", "target", "debug", hostName),
|
|
138
|
+
];
|
|
139
|
+
for (const candidate of candidates) {
|
|
140
|
+
if (fs.existsSync(candidate)) return candidate;
|
|
141
|
+
}
|
|
142
|
+
return whichHost();
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function ensureHostBinary() {
|
|
146
|
+
const existing = existingHostBinary();
|
|
147
|
+
if (existing) return existing;
|
|
148
|
+
if (process.env.LTCAI_SKIP_HOST_BUILD === "1") {
|
|
149
|
+
console.error("[LTCAI] lattice-host binary not found and LTCAI_SKIP_HOST_BUILD=1.");
|
|
150
|
+
process.exit(1);
|
|
151
|
+
}
|
|
152
|
+
const manifest = path.join(root, "rust", "Cargo.toml");
|
|
153
|
+
if (!fs.existsSync(manifest)) {
|
|
154
|
+
console.error("[LTCAI] lattice-host binary not found and rust/ workspace is missing.");
|
|
155
|
+
process.exit(1);
|
|
156
|
+
}
|
|
157
|
+
console.log("[LTCAI] Building lattice-host (cargo build -p lattice-host)...");
|
|
158
|
+
if (!runSync("cargo", ["build", "-p", "lattice-host"], { cwd: path.join(root, "rust") })) {
|
|
159
|
+
console.error("[LTCAI] cargo build -p lattice-host failed.");
|
|
160
|
+
process.exit(1);
|
|
161
|
+
}
|
|
162
|
+
const built = path.join(root, "rust", "target", "debug", hostName);
|
|
163
|
+
if (!fs.existsSync(built)) {
|
|
164
|
+
console.error(`[LTCAI] build succeeded but ${built} is missing.`);
|
|
90
165
|
process.exit(1);
|
|
91
166
|
}
|
|
167
|
+
return built;
|
|
168
|
+
}
|
|
92
169
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
170
|
+
function parseArgs(argv) {
|
|
171
|
+
const parsed = {
|
|
172
|
+
help: false,
|
|
173
|
+
version: false,
|
|
174
|
+
doctor: false,
|
|
175
|
+
host: null,
|
|
176
|
+
port: null,
|
|
177
|
+
hostArgs: [],
|
|
178
|
+
};
|
|
179
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
180
|
+
const arg = argv[i];
|
|
181
|
+
if (arg === "doctor") {
|
|
182
|
+
parsed.doctor = true;
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
if (arg === "-h" || arg === "--help") {
|
|
186
|
+
parsed.help = true;
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
if (arg === "-V" || arg === "--version") {
|
|
190
|
+
parsed.version = true;
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
if (arg === "--host" || arg.startsWith("--host=")) {
|
|
194
|
+
parsed.host = arg === "--host" ? argv[++i] : arg.slice("--host=".length);
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
if (arg === "--port" || arg.startsWith("--port=")) {
|
|
198
|
+
parsed.port = arg === "--port" ? argv[++i] : arg.slice("--port=".length);
|
|
199
|
+
if (parsed.port) parsed.hostArgs.push("--port", parsed.port);
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
if (arg === "--reload" || arg === "--tunnel") {
|
|
203
|
+
console.error(`[LTCAI] ${arg} is not supported on the lattice-host front door.`);
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
parsed.hostArgs.push(arg);
|
|
207
|
+
}
|
|
208
|
+
return parsed;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* The interpreter, as an absolute path.
|
|
213
|
+
*
|
|
214
|
+
* `lattice-host` spawns the worker with `PATH` prefixed by
|
|
215
|
+
* `/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin`
|
|
216
|
+
* (supervisor/worker_env.rs — GUI processes inherit a minimal PATH), so a bare
|
|
217
|
+
* `python3` is looked up against a different PATH than the one this launcher
|
|
218
|
+
* validated it on and can land on an interpreter with none of the deps.
|
|
219
|
+
* `sys.executable` is what keeps it the same interpreter on both sides.
|
|
220
|
+
*/
|
|
221
|
+
function absoluteInterpreter(python) {
|
|
222
|
+
const probe = spawnSync(python, ["-c", "import sys; print(sys.executable)"], { encoding: "utf8" });
|
|
223
|
+
const resolved = probe.status === 0 ? String(probe.stdout || "").trim() : "";
|
|
224
|
+
return resolved && fs.existsSync(resolved) ? resolved : python;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Tell the supervisor *which interpreter*, and let it build the command.
|
|
229
|
+
*
|
|
230
|
+
* This used to pin `LATTICEAI_DESKTOP_BACKEND_CMD = "<python> -m
|
|
231
|
+
* latticeai.worker_app"`, and that command serves nothing: `worker_app` exports
|
|
232
|
+
* `main()` but has no `if __name__ == "__main__"` guard, so the module form
|
|
233
|
+
* imports and exits 0 without binding a port — the supervisor restarts it,
|
|
234
|
+
* forever, and the front door answers 502 on every proxied route.
|
|
235
|
+
*
|
|
236
|
+
* The fix is not to pin the uvicorn string instead. `LATTICEAI_DESKTOP_BACKEND_CMD`
|
|
237
|
+
* is the supervisor's rule 1, whose args are passed **verbatim**; `--host` and
|
|
238
|
+
* `--port` are appended only by the module rules (`command.rs::module_args`),
|
|
239
|
+
* and the worker port is chosen at runtime by a free-port scan. A statically
|
|
240
|
+
* pinned `-m uvicorn … --factory` would therefore bind uvicorn's default 8000
|
|
241
|
+
* while the supervisor health-probes the port it actually picked.
|
|
242
|
+
*
|
|
243
|
+
* So pin the input the launcher genuinely knows — the interpreter — and let
|
|
244
|
+
* rule 2 produce its own canonical command (`command.rs::WORKER_FACTORY`):
|
|
245
|
+
* `<python> -m uvicorn latticeai.worker_app:create_worker_app --factory --host
|
|
246
|
+
* 127.0.0.1 --port <chosen>`. An explicit `LATTICEAI_DESKTOP_BACKEND_CMD` from
|
|
247
|
+
* the caller still wins, untouched.
|
|
248
|
+
*/
|
|
249
|
+
function pinWorkerInterpreter() {
|
|
250
|
+
if (process.env.LATTICEAI_DESKTOP_BACKEND_CMD) return;
|
|
251
|
+
process.env.LTCAI_PYTHON = absoluteInterpreter(resolveWorkerPython(true));
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function doctor() {
|
|
255
|
+
let ok = true;
|
|
256
|
+
const host = existingHostBinary();
|
|
257
|
+
if (host) {
|
|
258
|
+
console.log(`[OK] lattice-host: ${host}`);
|
|
259
|
+
} else {
|
|
260
|
+
console.log("[MISS] lattice-host: not built (run without doctor to cargo-build it)");
|
|
261
|
+
ok = false;
|
|
262
|
+
}
|
|
263
|
+
const python = absoluteInterpreter(resolveWorkerPython(false));
|
|
264
|
+
if (canImport(python, WORKER_MODULE)) {
|
|
265
|
+
console.log(`[OK] worker: ${python} ${WORKER_FACTORY}`);
|
|
266
|
+
} else {
|
|
267
|
+
console.log(`[MISS] worker: cannot import ${WORKER_MODULE} (${python})`);
|
|
268
|
+
ok = false;
|
|
269
|
+
}
|
|
270
|
+
process.exit(ok ? 0 : 1);
|
|
271
|
+
}
|
|
97
272
|
|
|
98
|
-
|
|
273
|
+
function launchHost(bin, args) {
|
|
274
|
+
const child = spawn(bin, args, { cwd: root, stdio: "inherit" });
|
|
275
|
+
child.on("error", (err) => {
|
|
276
|
+
console.error(`[LTCAI] failed to launch lattice-host (${bin}): ${err.message}`);
|
|
277
|
+
process.exit(1);
|
|
278
|
+
});
|
|
99
279
|
child.on("exit", (code, signal) => {
|
|
100
280
|
if (signal) process.kill(process.pid, signal);
|
|
101
281
|
process.exit(code ?? 0);
|
|
102
282
|
});
|
|
103
283
|
}
|
|
104
284
|
|
|
105
|
-
|
|
285
|
+
const parsed = parseArgs(process.argv.slice(2));
|
|
286
|
+
|
|
287
|
+
if (parsed.help) {
|
|
288
|
+
process.stdout.write(USAGE);
|
|
289
|
+
const host = existingHostBinary();
|
|
290
|
+
if (host) {
|
|
291
|
+
process.stdout.write("\n");
|
|
292
|
+
spawnSync(host, ["--help"], { stdio: "inherit" });
|
|
293
|
+
}
|
|
294
|
+
process.exit(0);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
if (parsed.version) {
|
|
298
|
+
const host = existingHostBinary();
|
|
299
|
+
if (host) {
|
|
300
|
+
spawnSync(host, ["--version"], { stdio: "inherit" });
|
|
301
|
+
} else {
|
|
302
|
+
console.log("ltcai (lattice-host front door)");
|
|
303
|
+
}
|
|
304
|
+
process.exit(0);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
if (parsed.doctor) {
|
|
308
|
+
doctor();
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
if (parsed.host) process.env.LATTICEAI_HOST = parsed.host;
|
|
312
|
+
if (parsed.port) process.env.LATTICEAI_PORT = parsed.port;
|
|
313
|
+
|
|
314
|
+
pinWorkerInterpreter();
|
|
315
|
+
launchHost(ensureHostBinary(), parsed.hostArgs);
|