ltcai 11.5.2 → 11.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +93 -148
- package/bin/ltcai.js +234 -24
- package/docs/CHANGELOG.md +119 -0
- package/docs/COMMUNITY_AND_PLUGINS.md +1 -1
- package/docs/DEVELOPMENT.md +8 -6
- package/docs/ENTERPRISE.md +2 -1
- package/docs/MULTI_AGENT_RUNTIME.md +12 -5
- package/docs/ONBOARDING.md +1 -1
- package/docs/OPERATIONS.md +6 -3
- package/docs/REALTIME_COLLABORATION.md +1 -1
- package/docs/TRUST_MODEL.md +1 -1
- package/docs/WHY_LATTICE.md +1 -1
- package/docs/WORKFLOW_DESIGNER.md +3 -2
- package/docs/kg-schema.md +1 -1
- package/docs/v11.6.0_ONE_DOOR_PLAN.md +170 -0
- package/lattice_brain/__init__.py +42 -79
- package/lattice_brain/graph/__init__.py +9 -24
- package/lattice_brain/graph/_kg_common/__init__.py +13 -24
- package/lattice_brain/ingestion/__init__.py +19 -58
- package/lattice_brain/ingestion/pipeline.py +20 -398
- package/lattice_brain/multimodal/__init__.py +7 -18
- package/lattice_brain/multimodal/images.py +6 -264
- package/lattice_brain/multimodal/video.py +8 -247
- package/lattice_brain/runtime/__init__.py +8 -79
- package/lattice_brain/runtime/hooks.py +22 -584
- package/latticeai/__init__.py +1 -1
- package/latticeai/api/agent_worker_seam.py +7 -80
- package/latticeai/api/health.py +6 -20
- package/latticeai/api/local_files.py +16 -613
- package/latticeai/api/models.py +12 -87
- package/latticeai/api/search.py +17 -255
- package/latticeai/api/tools.py +69 -750
- package/latticeai/api/voice_capture.py +8 -70
- package/latticeai/api/worker_compute.py +842 -0
- package/latticeai/api/worker_seams.py +216 -0
- package/latticeai/app_factory.py +23 -232
- package/latticeai/cli/entrypoint.py +36 -249
- package/latticeai/core/agent_permission.py +16 -91
- package/latticeai/core/messages.py +89 -531
- package/latticeai/runtime/access_runtime.py +0 -14
- package/latticeai/runtime/bootstrap.py +10 -21
- package/latticeai/runtime/brain_runtime.py +35 -43
- package/latticeai/runtime/build_phases/__init__.py +21 -37
- package/latticeai/runtime/build_phases/features.py +99 -389
- package/latticeai/runtime/build_phases/foundation.py +82 -392
- package/latticeai/runtime/build_phases/web.py +91 -408
- package/latticeai/runtime/build_phases/worker_profile.py +244 -0
- package/latticeai/runtime/lifespan_runtime.py +7 -16
- package/latticeai/runtime/platform_services_runtime.py +1 -15
- package/latticeai/runtime/runtime_context.py +13 -130
- package/latticeai/runtime/security_runtime.py +10 -103
- package/latticeai/services/architecture_readiness.py +82 -43
- package/latticeai/services/model_runtime/__init__.py +2 -11
- package/latticeai/services/model_runtime/service.py +4 -28
- package/latticeai/services/p_reinforce.py +10 -261
- package/latticeai/services/product_readiness.py +31 -38
- package/latticeai/services/search_service.py +37 -795
- package/latticeai/services/tool_dispatch.py +30 -386
- package/latticeai/services/voice_capture.py +13 -107
- package/latticeai/tools/__init__.py +22 -49
- package/latticeai/tools/commands.py +0 -163
- package/latticeai/tools/computer.py +0 -39
- package/latticeai/tools/documents.py +1 -134
- package/latticeai/tools/filesystem.py +1 -247
- package/latticeai/tools/knowledge.py +1 -52
- package/latticeai/tools/local_files.py +0 -20
- package/latticeai/worker_app.py +75 -0
- package/package.json +2 -3
- package/requirements.txt +0 -5
- package/scripts/agent_eval.py +16 -28
- package/scripts/brain_quality_eval.py +20 -183
- package/scripts/bump_version.py +5 -5
- package/scripts/check_current_release_docs.mjs +7 -4
- package/scripts/check_openapi_drift.mjs +10 -0
- package/scripts/check_server_i18n.mjs +2 -18
- package/scripts/compose_openapi.py +377 -0
- package/scripts/export_openapi.py +32 -4
- package/scripts/gen_messages_catalog_fixture.py +302 -0
- package/scripts/gen_openapi_fragments.py +365 -0
- package/scripts/gen_redact_fixture.py +196 -0
- package/scripts/gen_worker_allowlist_fixture.py +115 -0
- package/scripts/generate_agent_parity_fixtures.py +33 -14
- package/scripts/openapi_route_families.json +2161 -0
- package/scripts/release_screen_claims.json +54 -0
- package/scripts/run_integration_tests.mjs +134 -29
- package/scripts/run_sidecar_e2e.mjs +104 -11
- package/scripts/wheel_smoke.py +32 -22
- package/src-tauri/Cargo.lock +375 -9
- package/src-tauri/Cargo.toml +1 -1
- package/src-tauri/src/backend.rs +151 -45
- package/src-tauri/src/main.rs +18 -18
- package/src-tauri/src/topology.rs +58 -88
- package/src-tauri/tauri.conf.json +1 -2
- package/static/app/asset-manifest.json +41 -41
- package/static/app/assets/{Act-DcQizkl1.js → Act-BPcVAbOL.js} +1 -1
- package/static/app/assets/AdminConsole-Bw1ATQL0.js +1 -0
- package/static/app/assets/{Brain-3VCSHFcn.js → Brain-CT92Kos0.js} +2 -2
- package/static/app/assets/{BrainHome-Qm8eaztx.js → BrainHome-CFBkt1K_.js} +1 -1
- package/static/app/assets/{BrainSignals-DS9BtKOW.js → BrainSignals-ReLWF2H8.js} +1 -1
- package/static/app/assets/Capture-BsTokYkk.js +1 -0
- package/static/app/assets/{Chronicle-BGvuAchH.js → Chronicle-B6f0T9id.js} +1 -1
- package/static/app/assets/{CommandPalette-Bqhm0Urn.js → CommandPalette-CuvjTv1u.js} +1 -1
- package/static/app/assets/{Library-BV6NnF0a.js → Library-BGJbG9Hd.js} +1 -1
- package/static/app/assets/{LivingBrain-GzenJchP.js → LivingBrain-DGYK_Jsa.js} +1 -1
- package/static/app/assets/{ProductFlow-DEP6-vML.js → ProductFlow-DXBC6brE.js} +1 -1
- package/static/app/assets/{ReviewCard-CNZ7XjWG.js → ReviewCard-HXRle3qq.js} +2 -2
- package/static/app/assets/System-CMHSO9qM.js +1 -0
- package/static/app/assets/arrow-left-BfmkskWx.js +1 -0
- package/static/app/assets/{bot-B_K1Tdmw.js → bot-Cn8bWRuq.js} +1 -1
- package/static/app/assets/{brain-DWyaV1L1.js → brain-CQJberbE.js} +1 -1
- package/static/app/assets/{button-aTn4s84A.js → button-Ct9f2_oT.js} +1 -1
- package/static/app/assets/circle-check-DruOxB-4.js +1 -0
- package/static/app/assets/{circle-pause-xKgeGXkT.js → circle-pause-CmzC_apg.js} +1 -1
- package/static/app/assets/{circle-play-DkT6tYPX.js → circle-play-D8mW2aQ7.js} +1 -1
- package/static/app/assets/{cpu-85xYObUC.js → cpu-DZcdd0PZ.js} +1 -1
- package/static/app/assets/{download-B5Fm7YXo.js → download-bv1KEPGQ.js} +1 -1
- package/static/app/assets/{folder-open-kk2Xa52u.js → folder-open-d-Pip5gr.js} +1 -1
- package/static/app/assets/{hard-drive-DkA3zBW_.js → hard-drive-D20iavUb.js} +1 -1
- package/static/app/assets/index-D9x-kSNy.css +2 -0
- package/static/app/assets/{index-BMPdTmlY.js → index-Do83hDzJ.js} +3 -3
- package/static/app/assets/{input-B0nRf2jO.js → input-BLXVNmj1.js} +1 -1
- package/static/app/assets/{link-2-Dwb4gnTc.js → link-2-BPJOFlAy.js} +1 -1
- package/static/app/assets/{permissionCopy-CQDUBrOZ.js → permissionCopy-ChdJd493.js} +1 -1
- package/static/app/assets/primitives-Cv5tbZBY.js +1 -0
- package/static/app/assets/search-CT9aho2j.js +1 -0
- package/static/app/assets/{share-2-BsrxFglO.js → share-2-YNX_NtMU.js} +1 -1
- package/static/app/assets/{shield-alert-5BStfp2_.js → shield-alert-DuQ3zrVL.js} +1 -1
- package/static/app/assets/{textarea-Cg8IUA-k.js → textarea-DqwLnli4.js} +1 -1
- package/static/app/assets/{useFocusTrap-CYKvE46M.js → useFocusTrap-ZVI98jaW.js} +1 -1
- package/static/app/assets/{useMutation-CSn9t1op.js → useMutation-CVC4qv_D.js} +1 -1
- package/static/app/assets/{useQuery-CY2OI2uy.js → useQuery-C7BeG4HU.js} +1 -1
- package/static/app/assets/{utils-Ddol2RWD.js → utils-CiFtIdZq.js} +1 -1
- package/static/app/assets/{workspace-BqDwOz_p.js → workspace-DQz9vIId.js} +1 -1
- package/static/app/index.html +4 -4
- package/static/sw.js +1 -1
- package/lattice_brain/archive.py +0 -522
- package/lattice_brain/context.py +0 -325
- package/lattice_brain/conversations.py +0 -382
- package/lattice_brain/core.py +0 -82
- package/lattice_brain/graph/_kg_contract.py +0 -249
- package/lattice_brain/graph/curator.py +0 -676
- package/lattice_brain/graph/discovery.py +0 -595
- package/lattice_brain/graph/discovery_index/__init__.py +0 -35
- package/lattice_brain/graph/discovery_index/cleanup.py +0 -182
- package/lattice_brain/graph/discovery_index/extract.py +0 -137
- package/lattice_brain/graph/discovery_index/scan.py +0 -411
- package/lattice_brain/graph/discovery_index/upsert.py +0 -495
- package/lattice_brain/graph/documents.py +0 -380
- package/lattice_brain/graph/fusion.py +0 -395
- package/lattice_brain/graph/identity.py +0 -175
- package/lattice_brain/graph/image_vectors.py +0 -230
- package/lattice_brain/graph/ingest.py +0 -829
- package/lattice_brain/graph/network.py +0 -205
- package/lattice_brain/graph/proactive.py +0 -724
- package/lattice_brain/graph/projection/__init__.py +0 -42
- package/lattice_brain/graph/projection/curation.py +0 -500
- package/lattice_brain/graph/projection/v2_schema.py +0 -518
- package/lattice_brain/graph/provenance.py +0 -524
- package/lattice_brain/graph/rerank.py +0 -163
- package/lattice_brain/graph/retrieval/__init__.py +0 -54
- package/lattice_brain/graph/retrieval/context.py +0 -197
- package/lattice_brain/graph/retrieval/graph_view.py +0 -319
- package/lattice_brain/graph/retrieval/hybrid.py +0 -488
- package/lattice_brain/graph/retrieval/maintenance.py +0 -121
- package/lattice_brain/graph/retrieval/signals.py +0 -95
- package/lattice_brain/graph/retrieval_docgen.py +0 -253
- package/lattice_brain/graph/retrieval_policy.py +0 -180
- package/lattice_brain/graph/retrieval_reads.py +0 -769
- package/lattice_brain/graph/retrieval_vector/__init__.py +0 -42
- package/lattice_brain/graph/retrieval_vector/fingerprint.py +0 -97
- package/lattice_brain/graph/retrieval_vector/indexing.py +0 -347
- package/lattice_brain/graph/retrieval_vector/search.py +0 -560
- package/lattice_brain/graph/retrieval_vector/status.py +0 -374
- package/lattice_brain/graph/schema.py +0 -792
- package/lattice_brain/graph/store.py +0 -268
- package/lattice_brain/graph/vector_index/__init__.py +0 -85
- package/lattice_brain/graph/vector_index/base.py +0 -167
- package/lattice_brain/graph/vector_index/brute_force.py +0 -110
- package/lattice_brain/graph/vector_index/hnsw.py +0 -290
- package/lattice_brain/graph/vector_index/jobs.py +0 -287
- package/lattice_brain/graph/vector_index/quantized.py +0 -148
- package/lattice_brain/graph/vector_index/selector.py +0 -161
- package/lattice_brain/graph/write_master.py +0 -308
- package/lattice_brain/ingestion/_contract.py +0 -90
- package/lattice_brain/ingestion/folder_scan.py +0 -57
- package/lattice_brain/ingestion/folders.py +0 -258
- package/lattice_brain/ingestion/jobs_api.py +0 -107
- package/lattice_brain/ingestion/routing.py +0 -295
- package/lattice_brain/ingestion_jobs.py +0 -380
- package/lattice_brain/memory.py +0 -75
- package/lattice_brain/portability/__init__.py +0 -90
- package/lattice_brain/portability/_contract.py +0 -42
- package/lattice_brain/portability/backups.py +0 -338
- package/lattice_brain/portability/bundles.py +0 -136
- package/lattice_brain/portability/constants.py +0 -93
- package/lattice_brain/portability/fsops.py +0 -138
- package/lattice_brain/portability/service.py +0 -41
- package/lattice_brain/portability/sharing.py +0 -710
- package/lattice_brain/quality.py +0 -543
- package/lattice_brain/retrieval_benchmark_fixtures.py +0 -92
- package/lattice_brain/runtime/agent_runtime.py +0 -859
- package/lattice_brain/runtime/contracts.py +0 -460
- package/lattice_brain/runtime/multi_agent.py +0 -942
- package/lattice_brain/runtime/statuses.py +0 -10
- package/lattice_brain/sealed_box.py +0 -240
- package/lattice_brain/self_model.py +0 -675
- package/lattice_brain/sensitivity.py +0 -94
- package/lattice_brain/storage/__init__.py +0 -22
- package/lattice_brain/storage/base.py +0 -100
- package/lattice_brain/storage/docker.py +0 -105
- package/lattice_brain/storage/factory.py +0 -31
- package/lattice_brain/storage/migration.py +0 -191
- package/lattice_brain/storage/postgres.py +0 -123
- package/lattice_brain/storage/sqlite.py +0 -143
- package/lattice_brain/synthesis.py +0 -824
- package/lattice_brain/workflow.py +0 -497
- package/latticeai/api/admin.py +0 -471
- package/latticeai/api/agent_registry.py +0 -105
- package/latticeai/api/agents.py +0 -228
- package/latticeai/api/auth.py +0 -383
- package/latticeai/api/automation_intelligence.py +0 -401
- package/latticeai/api/brain_intelligence.py +0 -199
- package/latticeai/api/browser.py +0 -493
- package/latticeai/api/change_proposals.py +0 -89
- package/latticeai/api/chat.py +0 -572
- package/latticeai/api/chat_agent_http.py +0 -892
- package/latticeai/api/chat_contracts.py +0 -73
- package/latticeai/api/chat_documents.py +0 -276
- package/latticeai/api/chat_helpers.py +0 -460
- package/latticeai/api/chat_history.py +0 -101
- package/latticeai/api/chat_hybrid.py +0 -113
- package/latticeai/api/chat_intents.py +0 -646
- package/latticeai/api/chat_stream.py +0 -216
- package/latticeai/api/chronicle.py +0 -63
- package/latticeai/api/command_center.py +0 -51
- package/latticeai/api/computer_use.py +0 -474
- package/latticeai/api/evidence_actions.py +0 -48
- package/latticeai/api/features.py +0 -70
- package/latticeai/api/funnel_metrics.py +0 -31
- package/latticeai/api/garden.py +0 -34
- package/latticeai/api/hooks.py +0 -165
- package/latticeai/api/index_jobs.py +0 -145
- package/latticeai/api/invitations.py +0 -100
- package/latticeai/api/knowledge_graph.py +0 -536
- package/latticeai/api/marketplace.py +0 -105
- package/latticeai/api/mcp.py +0 -482
- package/latticeai/api/memory.py +0 -270
- package/latticeai/api/network.py +0 -81
- package/latticeai/api/network_boundary.py +0 -225
- package/latticeai/api/permission_mode.py +0 -61
- package/latticeai/api/permissions.py +0 -436
- package/latticeai/api/plugins.py +0 -126
- package/latticeai/api/portability.py +0 -391
- package/latticeai/api/project_sessions.py +0 -114
- package/latticeai/api/realtime.py +0 -118
- package/latticeai/api/review_queue.py +0 -364
- package/latticeai/api/security_dashboard.py +0 -604
- package/latticeai/api/setup.py +0 -319
- package/latticeai/api/static_routes.py +0 -354
- package/latticeai/api/ui_redirects.py +0 -26
- package/latticeai/api/workflow_designer.py +0 -394
- package/latticeai/api/workspace.py +0 -856
- package/latticeai/api/workspace_scope.py +0 -125
- package/latticeai/core/agent/__init__.py +0 -93
- package/latticeai/core/agent/_contract.py +0 -79
- package/latticeai/core/agent/context.py +0 -57
- package/latticeai/core/agent/deps.py +0 -125
- package/latticeai/core/agent/execution.py +0 -622
- package/latticeai/core/agent/planning.py +0 -145
- package/latticeai/core/agent/recovery.py +0 -157
- package/latticeai/core/agent/runtime.py +0 -210
- package/latticeai/core/agent/verification.py +0 -231
- package/latticeai/core/agent_eval.py +0 -739
- package/latticeai/core/agent_helpers.py +0 -493
- package/latticeai/core/agent_profiles.py +0 -110
- package/latticeai/core/agent_prompts.py +0 -171
- package/latticeai/core/agent_registry.py +0 -232
- package/latticeai/core/agent_state.py +0 -41
- package/latticeai/core/agent_trace.py +0 -104
- package/latticeai/core/artifact_ledger.py +0 -109
- package/latticeai/core/audit.py +0 -260
- package/latticeai/core/builtin_hooks.py +0 -105
- package/latticeai/core/context_builder.py +0 -394
- package/latticeai/core/document_generator.py +0 -103
- package/latticeai/core/enterprise.py +0 -154
- package/latticeai/core/enterprise_admin.py +0 -158
- package/latticeai/core/file_generation/__init__.py +0 -115
- package/latticeai/core/file_generation/bundles.py +0 -76
- package/latticeai/core/file_generation/extraction.py +0 -154
- package/latticeai/core/file_generation/inference.py +0 -235
- package/latticeai/core/file_generation/orchestration.py +0 -152
- package/latticeai/core/file_generation/prompting.py +0 -117
- package/latticeai/core/file_generation/repair.py +0 -114
- package/latticeai/core/file_generation/sanitize.py +0 -61
- package/latticeai/core/file_generation/validation.py +0 -201
- package/latticeai/core/invitations.py +0 -132
- package/latticeai/core/legacy_compatibility.py +0 -243
- package/latticeai/core/logging_safety.py +0 -46
- package/latticeai/core/marketplace.py +0 -293
- package/latticeai/core/mcp_catalog.py +0 -452
- package/latticeai/core/mcp_registry.py +0 -506
- package/latticeai/core/network_boundary.py +0 -168
- package/latticeai/core/oidc.py +0 -208
- package/latticeai/core/plugins.py +0 -432
- package/latticeai/core/product_hardening.py +0 -218
- package/latticeai/core/project_sessions.py +0 -337
- package/latticeai/core/realtime.py +0 -238
- package/latticeai/core/run_explain.py +0 -426
- package/latticeai/core/run_store.py +0 -252
- package/latticeai/core/timezones.py +0 -80
- package/latticeai/core/workspace_computer_memory.py +0 -84
- package/latticeai/core/workspace_graph_trace.py +0 -155
- package/latticeai/core/workspace_indexing.py +0 -102
- package/latticeai/core/workspace_memory.py +0 -77
- package/latticeai/core/workspace_onboarding.py +0 -104
- package/latticeai/core/workspace_os.py +0 -978
- package/latticeai/core/workspace_os_constants.py +0 -126
- package/latticeai/core/workspace_os_state.py +0 -180
- package/latticeai/core/workspace_os_utils.py +0 -103
- package/latticeai/core/workspace_permissions.py +0 -101
- package/latticeai/core/workspace_plugins.py +0 -97
- package/latticeai/core/workspace_relationships.py +0 -99
- package/latticeai/core/workspace_reorganization.py +0 -335
- package/latticeai/core/workspace_review_items.py +0 -112
- package/latticeai/core/workspace_runs.py +0 -726
- package/latticeai/core/workspace_skills.py +0 -109
- package/latticeai/core/workspace_snapshots.py +0 -198
- package/latticeai/core/workspace_timeline.py +0 -110
- package/latticeai/integrations/__init__.py +0 -0
- package/latticeai/integrations/telegram_bot/__init__.py +0 -123
- package/latticeai/integrations/telegram_bot/__main__.py +0 -17
- package/latticeai/integrations/telegram_bot/config.py +0 -86
- package/latticeai/integrations/telegram_bot/dispatch.py +0 -311
- package/latticeai/integrations/telegram_bot/flows.py +0 -478
- package/latticeai/integrations/telegram_bot/helpers.py +0 -322
- package/latticeai/integrations/telegram_bot/screens.py +0 -394
- package/latticeai/runtime/audit_runtime.py +0 -76
- package/latticeai/runtime/automation_runtime.py +0 -81
- package/latticeai/runtime/chat_wiring.py +0 -141
- package/latticeai/runtime/context_runtime.py +0 -66
- package/latticeai/runtime/feature_toggle_wiring.py +0 -157
- package/latticeai/runtime/history_runtime.py +0 -163
- package/latticeai/runtime/history_writer.py +0 -138
- package/latticeai/runtime/hooks_runtime.py +0 -77
- package/latticeai/runtime/model_wiring.py +0 -68
- package/latticeai/runtime/namespace_runtime.py +0 -163
- package/latticeai/runtime/network_boundary_wiring.py +0 -117
- package/latticeai/runtime/network_config_runtime.py +0 -56
- package/latticeai/runtime/permission_mode_wiring.py +0 -112
- package/latticeai/runtime/persistence_runtime.py +0 -159
- package/latticeai/runtime/platform_runtime_wiring.py +0 -89
- package/latticeai/runtime/review_wiring.py +0 -42
- package/latticeai/runtime/router_registration.py +0 -693
- package/latticeai/runtime/service_singletons.py +0 -55
- package/latticeai/runtime/sso_config_runtime.py +0 -128
- package/latticeai/runtime/user_key_runtime.py +0 -106
- package/latticeai/runtime/web_runtime.py +0 -92
- package/latticeai/server_app.py +0 -51
- package/latticeai/services/app_context.py +0 -130
- package/latticeai/services/automation_execution.py +0 -266
- package/latticeai/services/automation_intelligence.py +0 -614
- package/latticeai/services/brain_automation.py +0 -191
- package/latticeai/services/brain_intelligence/__init__.py +0 -58
- package/latticeai/services/brain_intelligence/_contract.py +0 -71
- package/latticeai/services/brain_intelligence/consistency.py +0 -193
- package/latticeai/services/brain_intelligence/constants.py +0 -47
- package/latticeai/services/brain_intelligence/digest.py +0 -258
- package/latticeai/services/brain_intelligence/health.py +0 -331
- package/latticeai/services/brain_intelligence/proposals.py +0 -259
- package/latticeai/services/brain_intelligence/sampling.py +0 -84
- package/latticeai/services/brain_intelligence/service.py +0 -48
- package/latticeai/services/change_proposals.py +0 -471
- package/latticeai/services/chat_service.py +0 -243
- package/latticeai/services/chronicle.py +0 -555
- package/latticeai/services/cloud_egress_audit.py +0 -85
- package/latticeai/services/cloud_extraction.py +0 -129
- package/latticeai/services/cloud_streaming.py +0 -268
- package/latticeai/services/cloud_token_guard.py +0 -84
- package/latticeai/services/command_center.py +0 -548
- package/latticeai/services/evidence_actions.py +0 -258
- package/latticeai/services/feature_toggles.py +0 -502
- package/latticeai/services/folder_watch.py +0 -520
- package/latticeai/services/funnel_metrics.py +0 -307
- package/latticeai/services/hybrid_chat.py +0 -316
- package/latticeai/services/hybrid_context.py +0 -228
- package/latticeai/services/hybrid_policy.py +0 -129
- package/latticeai/services/interop_bridges.py +0 -978
- package/latticeai/services/local_knowledge.py +0 -465
- package/latticeai/services/memory_service/__init__.py +0 -52
- package/latticeai/services/memory_service/_contract.py +0 -100
- package/latticeai/services/memory_service/brief.py +0 -431
- package/latticeai/services/memory_service/constants.py +0 -57
- package/latticeai/services/memory_service/maintenance.py +0 -138
- package/latticeai/services/memory_service/manager.py +0 -186
- package/latticeai/services/memory_service/proof.py +0 -136
- package/latticeai/services/memory_service/recall.py +0 -225
- package/latticeai/services/memory_service/service.py +0 -48
- package/latticeai/services/memory_service/stores.py +0 -110
- package/latticeai/services/mode_store.py +0 -132
- package/latticeai/services/model_recommendation.py +0 -224
- package/latticeai/services/model_runtime/cloud.py +0 -87
- package/latticeai/services/network_boundary_service.py +0 -117
- package/latticeai/services/obsidian_bridge.py +0 -609
- package/latticeai/services/openai_compatible_adapter.py +0 -101
- package/latticeai/services/permission_mode_service.py +0 -122
- package/latticeai/services/platform_runtime.py +0 -366
- package/latticeai/services/review_queue.py +0 -380
- package/latticeai/services/router_context.py +0 -59
- package/latticeai/services/run_executor.py +0 -387
- package/latticeai/services/self_model_service.py +0 -171
- package/latticeai/services/setup_detection.py +0 -147
- package/latticeai/services/triggers.py +0 -378
- package/latticeai/services/upload_service.py +0 -172
- package/latticeai/services/workspace_service.py +0 -165
- package/latticeai/setup/__init__.py +0 -25
- package/latticeai/setup/auto_setup.py +0 -846
- package/latticeai/setup/demo_corpus.py +0 -98
- package/latticeai/setup/wizard/__init__.py +0 -126
- package/latticeai/setup/wizard/catalog.py +0 -175
- package/latticeai/setup/wizard/detect.py +0 -302
- package/latticeai/setup/wizard/install.py +0 -348
- package/latticeai/setup/wizard/paths.py +0 -165
- package/latticeai/setup/wizard/plans.py +0 -74
- package/latticeai/setup/wizard/recommend.py +0 -320
- package/scripts/bench_agent_smoke.py +0 -409
- package/scripts/bench_models.py +0 -540
- package/scripts/bench_vector_index.py +0 -295
- package/scripts/funnel_soft_gate.py +0 -192
- package/scripts/generate_agent_loop_fixtures.py +0 -994
- package/scripts/generate_rust_parity_fixtures.py +0 -908
- package/scripts/migrate_brain_storage.py +0 -57
- package/scripts/parity_fixture_corpus_context.py +0 -162
- package/scripts/parity_fixture_corpus_docgen.py +0 -341
- package/scripts/profile_kg.py +0 -355
- package/server.py +0 -30
- package/static/app/assets/AdminConsole-cf4npybT.js +0 -1
- package/static/app/assets/Capture-DiQ219jW.js +0 -1
- package/static/app/assets/System-CieofHQa.js +0 -1
- package/static/app/assets/arrow-left-kfsrk0mv.js +0 -1
- package/static/app/assets/circle-check-qqLug9nU.js +0 -1
- package/static/app/assets/index-DxmOfNRi.css +0 -2
- package/static/app/assets/primitives-SNp0LRJz.js +0 -1
- package/static/app/assets/search-BcHqkjoy.js +0 -1
|
@@ -1,281 +1,68 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""``LTCAI`` — start the AI-Worker this machine's Lattice host talks to.
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
import platform
|
|
8
|
-
import re
|
|
9
|
-
import shutil
|
|
10
|
-
import socket
|
|
11
|
-
import stat
|
|
12
|
-
import subprocess
|
|
13
|
-
import sys
|
|
14
|
-
import threading
|
|
15
|
-
import time
|
|
16
|
-
import urllib.request
|
|
17
|
-
from pathlib import Path
|
|
18
|
-
|
|
19
|
-
from latticeai.cli.runtime import (
|
|
20
|
-
_apply_extra_path,
|
|
21
|
-
_has_module,
|
|
22
|
-
_load_env_file,
|
|
23
|
-
)
|
|
24
|
-
from latticeai.core.quiet import quiet
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
def _local_ips() -> list[str]:
|
|
28
|
-
ips: list[str] = []
|
|
29
|
-
try:
|
|
30
|
-
hostname = socket.gethostname()
|
|
31
|
-
for info in socket.getaddrinfo(hostname, None):
|
|
32
|
-
addr = str(info[4][0])
|
|
33
|
-
if ":" not in addr and not addr.startswith("127."):
|
|
34
|
-
if addr not in ips:
|
|
35
|
-
ips.append(addr)
|
|
36
|
-
except Exception:
|
|
37
|
-
quiet()
|
|
38
|
-
if not ips:
|
|
39
|
-
try:
|
|
40
|
-
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
41
|
-
s.connect(("8.8.8.8", 80))
|
|
42
|
-
ips.append(s.getsockname()[0])
|
|
43
|
-
s.close()
|
|
44
|
-
except Exception:
|
|
45
|
-
quiet()
|
|
46
|
-
return ips
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
def _print_banner(host: str, port: int, tunnel_url: str | None = None) -> None:
|
|
50
|
-
local_url = f"http://localhost:{port}"
|
|
51
|
-
print()
|
|
52
|
-
print("=" * 56)
|
|
53
|
-
print(" Lattice AI is running")
|
|
54
|
-
print(f" Local: {local_url}")
|
|
55
|
-
if host == "0.0.0.0":
|
|
56
|
-
for ip in _local_ips():
|
|
57
|
-
print(f" Network: http://{ip}:{port}")
|
|
58
|
-
print()
|
|
59
|
-
print(" Other devices on the same Wi-Fi can open the")
|
|
60
|
-
print(" Network URL above in their browser.")
|
|
61
|
-
print(" On iPad/Android: browser menu → 'Add to Home Screen'")
|
|
62
|
-
if tunnel_url:
|
|
63
|
-
print()
|
|
64
|
-
print(f" Tunnel: {tunnel_url}")
|
|
65
|
-
print(" Anyone on the internet can access via the Tunnel URL.")
|
|
66
|
-
print("=" * 56)
|
|
67
|
-
print()
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
def doctor() -> int:
|
|
71
|
-
checks = [
|
|
72
|
-
("Python 3.11+", sys.version_info >= (3, 11), sys.version.split()[0], True),
|
|
73
|
-
("FastAPI", _has_module("fastapi"), "required server dependency", True),
|
|
74
|
-
("Uvicorn", _has_module("uvicorn"), "required server dependency", True),
|
|
75
|
-
("OpenAI SDK", _has_module("openai"), "required for cloud providers", False),
|
|
76
|
-
("MLX", _has_module("mlx"), "required for Apple Silicon multimodal models", False),
|
|
77
|
-
("MLX-VLM", _has_module("mlx_vlm"), "required for Gemma-4/VLM models", False),
|
|
78
|
-
("Ollama binary", shutil.which("ollama") is not None, "optional local-server engine", False),
|
|
79
|
-
]
|
|
80
|
-
data_dir = Path(os.getenv("LATTICEAI_DATA_DIR") or Path.home() / ".ltcai")
|
|
81
|
-
static_dir = Path(os.getenv("LATTICEAI_STATIC_DIR") or Path(__file__).resolve().parent / "static")
|
|
82
|
-
checks.extend([
|
|
83
|
-
("Data dir", data_dir.exists() or data_dir.parent.exists(), str(data_dir), True),
|
|
84
|
-
("Static UI", static_dir.exists(), str(static_dir), True),
|
|
85
|
-
])
|
|
86
|
-
|
|
87
|
-
ok = True
|
|
88
|
-
for label, passed, detail, required in checks:
|
|
89
|
-
icon = "OK" if passed else ("MISS" if required else "OPTIONAL")
|
|
90
|
-
print(f"[{icon}] {label}: {detail}")
|
|
91
|
-
ok = ok and (passed or not required)
|
|
92
|
-
|
|
93
|
-
cloud_keys = ["OPENAI_API_KEY", "OPENROUTER_API_KEY", "GROQ_API_KEY", "TOGETHER_API_KEY"]
|
|
94
|
-
configured = [key for key in cloud_keys if os.getenv(key)]
|
|
95
|
-
print(f"[INFO] Cloud keys configured: {', '.join(configured) if configured else 'none'}")
|
|
96
|
-
return 0 if ok else 1
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
# ── Cloudflare Tunnel ─────────────────────────────────────────────────────────
|
|
100
|
-
|
|
101
|
-
def _cloudflared_url() -> str:
|
|
102
|
-
system = sys.platform
|
|
103
|
-
machine = platform.machine().lower()
|
|
104
|
-
base = "https://github.com/cloudflare/cloudflared/releases/latest/download"
|
|
105
|
-
if system == "darwin":
|
|
106
|
-
arch = "arm64" if machine in ("arm64", "aarch64") else "amd64"
|
|
107
|
-
return f"{base}/cloudflared-darwin-{arch}"
|
|
108
|
-
if system == "win32":
|
|
109
|
-
return f"{base}/cloudflared-windows-amd64.exe"
|
|
110
|
-
arch = "arm64" if machine in ("arm64", "aarch64") else "amd64"
|
|
111
|
-
return f"{base}/cloudflared-linux-{arch}"
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
def _cloudflared_bin() -> Path:
|
|
115
|
-
suffix = ".exe" if sys.platform == "win32" else ""
|
|
116
|
-
return Path.home() / ".latticeai" / "bin" / f"cloudflared{suffix}"
|
|
3
|
+
This used to be the product's front door: it printed the LAN banner, ran a
|
|
4
|
+
``doctor`` dependency check, could open a Cloudflare tunnel, sent a Telegram
|
|
5
|
+
"server started" notification, and served ``server:app`` — the 464-route
|
|
6
|
+
FastAPI application.
|
|
117
7
|
|
|
8
|
+
v11.6.0 made ``lattice-host`` the product server (plan §설계 결정 1). The host
|
|
9
|
+
is what ``bin/ltcai.js`` starts, the host owns the banner and the network
|
|
10
|
+
posture, and the host is what *supervises this process*. So the entrypoint is
|
|
11
|
+
now one job: bind the worker profile on a loopback address and serve it.
|
|
118
12
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
dest.parent.mkdir(parents=True, exist_ok=True)
|
|
127
|
-
url = _cloudflared_url()
|
|
128
|
-
print(" cloudflared not found — downloading from GitHub...")
|
|
129
|
-
try:
|
|
130
|
-
urllib.request.urlretrieve(url, dest)
|
|
131
|
-
if sys.platform != "win32":
|
|
132
|
-
dest.chmod(dest.stat().st_mode | stat.S_IEXEC | stat.S_IXGRP | stat.S_IXOTH)
|
|
133
|
-
print(f" cloudflared installed at {dest}")
|
|
134
|
-
return str(dest)
|
|
135
|
-
except Exception as e:
|
|
136
|
-
print(f" cloudflared download failed: {e}")
|
|
137
|
-
print(" Install manually: https://developers.cloudflare.com/cloudflared/install")
|
|
138
|
-
return ""
|
|
13
|
+
Everything removed went somewhere real rather than away — the banner and the
|
|
14
|
+
reachability report to the host's own startup, ``doctor`` to ``GET /health``'s
|
|
15
|
+
access block (which the supervisor already polls), the tunnel to the network
|
|
16
|
+
boundary controls, the Telegram bridge to the bot's own process. What is left
|
|
17
|
+
would be a `uvicorn` invocation if it were not for the two lines above it: the
|
|
18
|
+
``.env`` file and ``LATTICEAI_EXTRA_PATH``, which a desktop bundle depends on
|
|
19
|
+
being applied *before* configuration is read.
|
|
139
20
|
|
|
21
|
+
The host normally launches the ASGI factory directly::
|
|
140
22
|
|
|
141
|
-
|
|
142
|
-
try:
|
|
143
|
-
data = urllib.parse.urlencode({"chat_id": chat_id, "text": text}).encode()
|
|
144
|
-
req = urllib.request.Request(
|
|
145
|
-
f"https://api.telegram.org/bot{token}/sendMessage",
|
|
146
|
-
data=data,
|
|
147
|
-
)
|
|
148
|
-
urllib.request.urlopen(req, timeout=10)
|
|
149
|
-
except Exception:
|
|
150
|
-
quiet()
|
|
23
|
+
python -m uvicorn latticeai.worker_app:create_worker_app --factory --host 127.0.0.1 --port N
|
|
151
24
|
|
|
25
|
+
and this command is the equivalent for a person debugging a worker by hand.
|
|
26
|
+
"""
|
|
152
27
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
bin_path = _ensure_cloudflared()
|
|
156
|
-
if not bin_path:
|
|
157
|
-
return None
|
|
158
|
-
|
|
159
|
-
log_path = Path.home() / ".latticeai" / "tunnel.log"
|
|
160
|
-
log_path.parent.mkdir(parents=True, exist_ok=True)
|
|
161
|
-
|
|
162
|
-
# Detached on purpose: the tunnel outlives this helper; the log file is
|
|
163
|
-
# the observable surface.
|
|
164
|
-
subprocess.Popen(
|
|
165
|
-
[bin_path, "tunnel", "--url", f"http://localhost:{port}"],
|
|
166
|
-
stdout=open(log_path, "w"),
|
|
167
|
-
stderr=subprocess.STDOUT,
|
|
168
|
-
)
|
|
169
|
-
|
|
170
|
-
# Wait for the public URL (up to 30s)
|
|
171
|
-
pattern = re.compile(r"https://[a-z0-9-]+\.trycloudflare\.com")
|
|
172
|
-
deadline = time.time() + 30
|
|
173
|
-
url: str | None = None
|
|
174
|
-
while time.time() < deadline:
|
|
175
|
-
time.sleep(0.5)
|
|
176
|
-
try:
|
|
177
|
-
text = log_path.read_text(errors="replace")
|
|
178
|
-
m = pattern.search(text)
|
|
179
|
-
if m:
|
|
180
|
-
url = m.group(0)
|
|
181
|
-
break
|
|
182
|
-
except Exception:
|
|
183
|
-
quiet()
|
|
184
|
-
|
|
185
|
-
if not url:
|
|
186
|
-
return None
|
|
187
|
-
|
|
188
|
-
# Telegram notification if configured
|
|
189
|
-
token = os.getenv("LATTICEAI_TELEGRAM_BOT_TOKEN", "")
|
|
190
|
-
chat_id = os.getenv("LATTICEAI_TELEGRAM_CHAT_ID", "")
|
|
191
|
-
if token and chat_id:
|
|
192
|
-
msg = (
|
|
193
|
-
f"✅ Lattice AI 시작됨\n\n"
|
|
194
|
-
f"🌐 외부 URL: {url}\n"
|
|
195
|
-
f"🏠 로컬: http://localhost:{port}"
|
|
196
|
-
)
|
|
197
|
-
threading.Thread(target=_send_telegram, args=(token, chat_id, msg), daemon=True).start()
|
|
28
|
+
from __future__ import annotations
|
|
198
29
|
|
|
199
|
-
|
|
30
|
+
import argparse
|
|
31
|
+
import os
|
|
32
|
+
from pathlib import Path
|
|
200
33
|
|
|
34
|
+
from latticeai.cli.runtime import _apply_extra_path, _load_env_file
|
|
201
35
|
|
|
202
|
-
# ─────────────────────────────────────────────────────────────────────────────
|
|
203
36
|
|
|
204
37
|
def main() -> None:
|
|
205
38
|
app_dir = Path(__file__).resolve().parent
|
|
206
39
|
_load_env_file(app_dir / ".env")
|
|
207
40
|
_apply_extra_path()
|
|
208
41
|
|
|
209
|
-
parser = argparse.ArgumentParser(
|
|
210
|
-
|
|
211
|
-
|
|
42
|
+
parser = argparse.ArgumentParser(
|
|
43
|
+
prog="LTCAI",
|
|
44
|
+
description="Run the Lattice AI compute worker (the product server is lattice-host).",
|
|
45
|
+
)
|
|
212
46
|
parser.add_argument("--host", default=os.getenv("LATTICEAI_HOST") or "127.0.0.1")
|
|
213
47
|
parser.add_argument("--port", type=int, default=int(os.getenv("LATTICEAI_PORT") or "4825"))
|
|
214
|
-
parser.add_argument("--reload", action="store_true", help="Enable uvicorn reload for local development.")
|
|
215
48
|
parser.add_argument(
|
|
216
|
-
"--
|
|
217
|
-
action="store_true",
|
|
218
|
-
help="Open a public Cloudflare tunnel so anyone can access this server from the internet.",
|
|
49
|
+
"--reload", action="store_true", help="Enable uvicorn reload for local development."
|
|
219
50
|
)
|
|
220
51
|
args = parser.parse_args()
|
|
221
52
|
|
|
222
|
-
if args.command == "doctor":
|
|
223
|
-
raise SystemExit(doctor())
|
|
224
|
-
|
|
225
53
|
os.chdir(app_dir)
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
"true",
|
|
230
|
-
"yes",
|
|
231
|
-
):
|
|
232
|
-
print(
|
|
233
|
-
" LATTICEAI_TUNNEL is ignored during default local startup; "
|
|
234
|
-
"restart with --tunnel to expose this server."
|
|
235
|
-
)
|
|
236
|
-
|
|
237
|
-
# --tunnel forces 0.0.0.0 so cloudflared can reach the server
|
|
238
|
-
if args.tunnel and args.host == "127.0.0.1":
|
|
239
|
-
args.host = "0.0.0.0"
|
|
240
|
-
os.environ.setdefault("LATTICEAI_HOST", "0.0.0.0")
|
|
241
|
-
os.environ.setdefault("LATTICEAI_CORS_ALLOW_NETWORK", "true")
|
|
242
|
-
os.environ.setdefault("LATTICEAI_REQUIRE_AUTH", "true")
|
|
243
|
-
|
|
244
|
-
# Keep the app config in sync with CLI flags. ``Config.from_env`` is the
|
|
245
|
-
# source of truth for /mode, /health.features, SSO defaults, and routers.
|
|
54
|
+
# ``Config.from_env`` is the source of truth for the address the worker
|
|
55
|
+
# binds and reports on ``/health``; the flags are written back so a
|
|
56
|
+
# command-line override and the configuration cannot disagree.
|
|
246
57
|
os.environ["LATTICEAI_HOST"] = str(args.host)
|
|
247
58
|
os.environ["LATTICEAI_PORT"] = str(args.port)
|
|
248
59
|
|
|
249
|
-
tunnel_url: str | None = None
|
|
250
|
-
if args.tunnel:
|
|
251
|
-
print()
|
|
252
|
-
print(" Starting Cloudflare tunnel...")
|
|
253
|
-
tunnel_url = _start_tunnel(args.port)
|
|
254
|
-
if not tunnel_url:
|
|
255
|
-
print(" ⚠️ Tunnel URL not obtained — server will start without tunnel.")
|
|
256
|
-
|
|
257
|
-
_print_banner(args.host, args.port, tunnel_url)
|
|
258
|
-
|
|
259
|
-
# Telegram startup notification (local start, tunnel handled separately inside _start_tunnel)
|
|
260
|
-
if not args.tunnel:
|
|
261
|
-
_tg_enabled = os.getenv("LATTICEAI_ENABLE_TELEGRAM", "").strip().lower() in ("1", "true", "yes", "on")
|
|
262
|
-
_tg_token = os.getenv("LATTICEAI_TELEGRAM_BOT_TOKEN", "")
|
|
263
|
-
_tg_chat = os.getenv("LATTICEAI_TELEGRAM_CHAT_ID", "")
|
|
264
|
-
if _tg_enabled and _tg_token and _tg_chat:
|
|
265
|
-
_local_msg = (
|
|
266
|
-
f"✅ Lattice AI 시작됨\n\n"
|
|
267
|
-
f"🏠 로컬: http://localhost:{args.port}"
|
|
268
|
-
)
|
|
269
|
-
threading.Thread(
|
|
270
|
-
target=_send_telegram,
|
|
271
|
-
args=(_tg_token, _tg_chat, _local_msg),
|
|
272
|
-
daemon=True,
|
|
273
|
-
).start()
|
|
274
|
-
|
|
275
60
|
import uvicorn
|
|
276
61
|
|
|
62
|
+
print(f"🧠 Lattice AI worker on http://{args.host}:{args.port}")
|
|
277
63
|
uvicorn.run(
|
|
278
|
-
"
|
|
64
|
+
"latticeai.worker_app:create_worker_app",
|
|
65
|
+
factory=True,
|
|
279
66
|
host=args.host,
|
|
280
67
|
port=args.port,
|
|
281
68
|
reload=args.reload,
|
|
@@ -1,71 +1,31 @@
|
|
|
1
|
-
"""Agent-loop permission-mode gates (v9.9.8).
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
"""Agent-loop permission-mode gates (v9.9.8) — the two the parity fixtures pin.
|
|
2
|
+
|
|
3
|
+
These were the Python loop's mode tables, called by ``SingleAgentRuntime`` and
|
|
4
|
+
``build_agent_runtime``. Orchestration moved to ``lattice-agent`` in v11.6.0 and
|
|
5
|
+
the Python loop is gone, so **nothing in the worker imports this module**.
|
|
6
|
+
|
|
7
|
+
It survives for one reason, stated so it is not read as a leftover:
|
|
8
|
+
``scripts/generate_agent_parity_fixtures.py`` produces the committed goldens
|
|
9
|
+
``rust/fixtures`` holds for the Rust loop's permission gates, and it derives
|
|
10
|
+
them from :func:`block_reason_for_tool` and :func:`non_auto_plan_steps` here.
|
|
11
|
+
Deleting these two would leave the Rust side asserting against fixtures no
|
|
12
|
+
Python could regenerate — the fixtures would still pass, and would stop meaning
|
|
13
|
+
anything. The rest of the module (``call_mode_source``, ``resolve_deps_mode``,
|
|
14
|
+
``approval_requirements_for``) went with the loop that called it.
|
|
6
15
|
"""
|
|
7
16
|
|
|
8
17
|
from __future__ import annotations
|
|
9
18
|
|
|
10
|
-
from typing import Any,
|
|
19
|
+
from typing import Any, List, Mapping, Optional, Sequence
|
|
11
20
|
|
|
12
21
|
from latticeai.core.permission_mode import (
|
|
13
|
-
DEFAULT_MODE,
|
|
14
22
|
PermissionMode,
|
|
15
23
|
effective_auto_approve,
|
|
16
24
|
is_circuit_breaker,
|
|
17
25
|
normalize_mode,
|
|
18
|
-
plan_requires_approval,
|
|
19
26
|
)
|
|
20
27
|
|
|
21
28
|
|
|
22
|
-
def call_mode_source(
|
|
23
|
-
raw: Any,
|
|
24
|
-
*,
|
|
25
|
-
user_email: Optional[str] = None,
|
|
26
|
-
workspace_id: Optional[str] = None,
|
|
27
|
-
) -> Any:
|
|
28
|
-
"""Resolve a mode source that may be a value, or a callable that either
|
|
29
|
-
accepts ``user_email``/``workspace_id`` scope kwargs or takes no arguments.
|
|
30
|
-
|
|
31
|
-
Scoped resolution is what makes per-user and per-workspace overrides real:
|
|
32
|
-
an unscoped call always collapses to the process-wide default.
|
|
33
|
-
"""
|
|
34
|
-
if not callable(raw):
|
|
35
|
-
return raw
|
|
36
|
-
try:
|
|
37
|
-
return raw(user_email=user_email, workspace_id=workspace_id)
|
|
38
|
-
except TypeError:
|
|
39
|
-
# Legacy zero-arg resolver (or a static callable) — fall back.
|
|
40
|
-
try:
|
|
41
|
-
return raw()
|
|
42
|
-
except Exception:
|
|
43
|
-
return DEFAULT_MODE
|
|
44
|
-
except Exception:
|
|
45
|
-
return DEFAULT_MODE
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
def resolve_deps_mode(
|
|
49
|
-
deps: Any,
|
|
50
|
-
ctx: Any = None,
|
|
51
|
-
*,
|
|
52
|
-
user_email: Optional[str] = None,
|
|
53
|
-
workspace_id: Optional[str] = None,
|
|
54
|
-
) -> PermissionMode:
|
|
55
|
-
"""Mode for this run: explicit context stamp wins, else the scoped resolver
|
|
56
|
-
on ``deps``, else strict."""
|
|
57
|
-
if ctx is not None:
|
|
58
|
-
override = getattr(ctx, "permission_mode", None)
|
|
59
|
-
if override is not None:
|
|
60
|
-
return normalize_mode(override)
|
|
61
|
-
raw = call_mode_source(
|
|
62
|
-
getattr(deps, "permission_mode", None),
|
|
63
|
-
user_email=user_email,
|
|
64
|
-
workspace_id=workspace_id,
|
|
65
|
-
)
|
|
66
|
-
return normalize_mode(raw if raw is not None else DEFAULT_MODE)
|
|
67
|
-
|
|
68
|
-
|
|
69
29
|
def non_auto_plan_steps(
|
|
70
30
|
mode: PermissionMode | str,
|
|
71
31
|
steps: Sequence[Mapping[str, Any]],
|
|
@@ -94,38 +54,6 @@ def non_auto_plan_steps(
|
|
|
94
54
|
return non_auto
|
|
95
55
|
|
|
96
56
|
|
|
97
|
-
def approval_requirements_for(
|
|
98
|
-
mode: PermissionMode | str,
|
|
99
|
-
plan: Mapping[str, Any],
|
|
100
|
-
tool_governance: Mapping[str, Mapping[str, Any]],
|
|
101
|
-
*,
|
|
102
|
-
governed_tools: Optional[Any] = None,
|
|
103
|
-
) -> Dict[str, Any]:
|
|
104
|
-
steps = plan.get("steps") or []
|
|
105
|
-
non_auto = non_auto_plan_steps(
|
|
106
|
-
mode, steps, tool_governance, governed_tools=governed_tools,
|
|
107
|
-
)
|
|
108
|
-
requires = plan_requires_approval(
|
|
109
|
-
mode,
|
|
110
|
-
non_auto_steps=non_auto,
|
|
111
|
-
plan_flag=bool(plan.get("requires_approval", False)),
|
|
112
|
-
)
|
|
113
|
-
lines = [
|
|
114
|
-
f"{index}. {step.get('description') or step.get('action') or '?'}"
|
|
115
|
-
for index, step in enumerate(steps, start=1)
|
|
116
|
-
if isinstance(step, dict)
|
|
117
|
-
]
|
|
118
|
-
summary = str(plan.get("goal") or "").strip()
|
|
119
|
-
if lines:
|
|
120
|
-
summary = (summary + "\n" if summary else "") + "\n".join(lines)
|
|
121
|
-
return {
|
|
122
|
-
"requires_approval": requires,
|
|
123
|
-
"non_auto_steps": non_auto,
|
|
124
|
-
"plan_summary": summary,
|
|
125
|
-
"permission_mode": normalize_mode(mode).value,
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
|
|
129
57
|
def block_reason_for_tool(
|
|
130
58
|
mode: PermissionMode | str,
|
|
131
59
|
name: str,
|
|
@@ -152,9 +80,6 @@ def block_reason_for_tool(
|
|
|
152
80
|
|
|
153
81
|
|
|
154
82
|
__all__ = [
|
|
155
|
-
"call_mode_source",
|
|
156
|
-
"resolve_deps_mode",
|
|
157
|
-
"non_auto_plan_steps",
|
|
158
|
-
"approval_requirements_for",
|
|
159
83
|
"block_reason_for_tool",
|
|
84
|
+
"non_auto_plan_steps",
|
|
160
85
|
]
|