code-context-control 2.63.2__tar.gz → 2.64.0__tar.gz
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.
- {code_context_control-2.63.2 → code_context_control-2.64.0}/PKG-INFO +1 -1
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/c3.py +80 -4
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/commands/parser.py +8 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hook_access_guard.py +23 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_server.py +0 -6
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/settings_modal.js +0 -6
- {code_context_control-2.63.2 → code_context_control-2.64.0}/code_context_control.egg-info/PKG-INFO +1 -1
- {code_context_control-2.63.2 → code_context_control-2.64.0}/code_context_control.egg-info/SOURCES.txt +5 -1
- {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/config.py +3 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/oracle_server.py +141 -11
- code_context_control-2.64.0/oracle/services/chat_store.py +245 -0
- code_context_control-2.64.0/oracle/services/discovery_audit.py +164 -0
- code_context_control-2.64.0/oracle/services/local_session.py +149 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/pyproject.toml +1 -1
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/access_guard.py +11 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/claude_md.py +97 -16
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/e2e_benchmark.py +40 -6
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/jira_data_center.py +119 -9
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_e2e_benchmark.py +46 -2
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_federated_graph.py +6 -3
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_hook_access_guard.py +66 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_hub_server_smoke.py +7 -4
- code_context_control-2.64.0/tests/test_ide_workflow_adaptation.py +121 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_jira_client.py +78 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_oracle_apikey_api.py +6 -3
- code_context_control-2.64.0/tests/test_oracle_chat_store.py +176 -0
- code_context_control-2.64.0/tests/test_oracle_discovery_audit.py +194 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_oracle_local_auth.py +31 -11
- code_context_control-2.64.0/tests/test_oracle_session_bootstrap.py +160 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_oracle_ui_bundle.py +4 -2
- code_context_control-2.63.2/cli/hub.html +0 -3889
- code_context_control-2.63.2/oracle/services/chat_store.py +0 -155
- code_context_control-2.63.2/oracle/services/local_session.py +0 -54
- {code_context_control-2.63.2 → code_context_control-2.64.0}/LICENSE +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/README.md +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/__init__.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/_hook_utils.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/commands/__init__.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/commands/common.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/docs.html +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/edits.html +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/guide/access.html +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/guide/bitbucket.html +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/guide/credentials.html +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/guide/getting-started.html +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/guide/index.html +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/guide/masking.html +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/guide/oracle.html +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/guide/shared.css +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/guide/tools.html +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/guide/workflow.html +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hook_artifact.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hook_auto_snapshot.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hook_c3_signal.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hook_c3read.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hook_dispatch.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hook_edit_ledger.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hook_edit_unlock.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hook_filter.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hook_ghost_files.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hook_pretool_enforce.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hook_prompt_recall.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hook_read.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hook_session_stats.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hook_terse_advisor.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/app.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/add_project.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/config_editor.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/drill_artifacts.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/drill_health.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/drill_panel.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/drill_subprojects.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/drill_tasks.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/drill_views.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/global_search.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/hub_credentials.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/mcp_manager.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/modals.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/project_card.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/project_tree.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/session_drawer.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/sidebar.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/summary_bar.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/task_board.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/toasts.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/topbar.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/state.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui.html +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/mcp_proxy.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/mcp_server.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/progress.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/server.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/__init__.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/_helpers.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/agent.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/artifacts.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/bitbucket.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/compress.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/credentials.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/delegate.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/edit.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/edits.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/federate.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/filter.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/impact.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/jira.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/memory.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/project.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/read.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/search.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/session.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/shell.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/status.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/tasks.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/validate.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui/api.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui/app.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui/components/access.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui/components/bitbucket.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui/components/chat.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui/components/credentials.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui/components/dashboard.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui/components/edits.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui/components/instructions.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui/components/jira.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui/components/memory.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui/components/sessions.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui/components/settings.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui/components/sidebar.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui/components/tasks.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui/icons.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui/pm_shared.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui/shared.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui/theme.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui.html +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui_legacy.html +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui_nano.html +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/code_context_control.egg-info/dependency_links.txt +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/code_context_control.egg-info/entry_points.txt +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/code_context_control.egg-info/requires.txt +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/code_context_control.egg-info/top_level.txt +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/core/__init__.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/core/config.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/core/ide.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/core/mcp_toml.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/core/web_security.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/__init__.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/mcp_oracle.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/oracle_ui.html +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/services/__init__.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/services/activity_reporter.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/services/api_auth.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/services/c3_bridge.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/services/chat_engine.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/services/cross_memory.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/services/federated_graph.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/services/health_checker.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/services/insight_engine.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/services/memory_reader.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/services/memory_writer.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/services/project_scanner.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/services/review_agent.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/services/tool_executor.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/services/tool_registry.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/ui/activity.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/ui/agents.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/ui/app.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/ui/busy.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/ui/chat/conversations.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/ui/chat/input.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/ui/chat/markdown.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/ui/chat/send.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/ui/chat/stream_renderer.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/ui/chat/toolbar.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/ui/core.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/ui/crossgraph.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/ui/header.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/ui/insights.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/ui/projects.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/ui/settings.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/ui/suggestions.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/ui/theme_tabs.js +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/__init__.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/activity_log.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/agent_base.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/agents.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/artifact_defs.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/artifact_store.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/auto_memory.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/bench/__init__.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/bench/external/__init__.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/bench/external/aider_polyglot.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/bench/external/swe_bench.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/benchmark_dashboard.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/bitbucket_client.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/bitbucket_credentials.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/circuit_breaker.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/compressor.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/context_snapshot.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/conversation_store.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/credential_store.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/doc_index.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/e2e_evaluator.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/e2e_tasks.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/edit_ledger.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/embedding_index.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/error_reporting.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/file_memory.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/git_context.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/hub_service.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/indexer.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/jira_client.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/jira_cloud.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/jira_credentials.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/jira_links.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/mask_activation.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/mask_mirror.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/mask_presets.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/memory.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/memory_consolidator.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/memory_distiller.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/memory_graph.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/memory_grounder.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/memory_queue.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/memory_scorer.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/metrics.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/notifications.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/ollama_bridge.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/ollama_client.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/ollama_credentials.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/output_filter.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/parser.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/project_manager.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/project_runtime.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/protocol.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/proxy_state.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/repo_map.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/retention.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/retrieval_broker.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/router.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/runtime.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/scanner.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/session_benchmark.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/session_manager.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/session_preloader.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/subprojects.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/task_store.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/telemetry.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/text_index.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/time_tracker.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/tool_classifier.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/transcript_index.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/validation_cache.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/vector_store.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/watcher.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/services/win_subprocess.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/setup.cfg +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_access_guard.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_access_guard_meta.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_access_guard_shell_project.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_access_guard_surfaces.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_access_guard_wiring.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_activity_reporter.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_aider_polyglot.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_antigravity_transition.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_artifact_store.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_artifact_tool.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_bitbucket_cli_smoke.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_bitbucket_client.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_bitbucket_config_fallback.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_bitbucket_credentials.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_bitbucket_tool.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_c3_bridge_project_artifacts.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_c3_shell.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_circuit_breaker.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_claude_md_merge.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_cli_smoke.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_compressor_large_file.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_credential_store.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_credentials_routes.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_credentials_tool.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_creds_cli_smoke.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_delegate_cascade.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_edit_ledger_hook.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_edit_normalization.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_enforcement_flip.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_filter_backoff.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_ghost_files.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_ghost_generation.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_git_branch_awareness.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_hook_dispatch.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_hook_pretool_enforce.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_hook_prompt_recall.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_hook_smoke.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_hook_state.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_hook_utf8_stdio.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_hub_credentials_route.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_hub_credentials_routes_write.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_hub_inspect_api.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_hub_subproject_links.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_init_scan.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_install_mcp_entrypoint.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_jira_cli_smoke.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_jira_config_fallback.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_jira_credentials.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_jira_links.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_jira_routes.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_jira_tool.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_lazy_store_init.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_mask_guard.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_mask_routes.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_mask_surfaces.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_mcp_host_guard.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_mcp_memory_timeout.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_mcp_server_smoke.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_mcp_toml.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_memory_distiller.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_memory_graph_api.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_memory_queue.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_memory_system.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_no_stale_model_pins.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_notification_dedup.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_notification_discipline.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_ollama_credentials.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_oracle_api_auth.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_oracle_c3_bridge.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_oracle_chat_engine.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_oracle_discovery_api.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_oracle_ollama_bridge.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_oracle_scanner_cache.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_oracle_security_fixes.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_oracle_subproject_awareness.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_output_filter.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_permissions.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_pm_api.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_project_manager.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_project_manager_merge.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_project_tool.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_read_coercion.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_read_edit_parity.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_related_facts.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_repo_map.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_response_boilerplate.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_retention.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_review_digest.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_service_durability.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_session_benchmark.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_session_budget.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_shell_creds.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_shell_robustness.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_subproject_exclusion.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_subproject_federation.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_subprojects.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_swe_bench.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_task_store.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_task_tool.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_time_tracker.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_token_telemetry.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_tool_registry.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_upgrade_and_version.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_validate.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_vault_write_guard.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_version_sync.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_web_security.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_windows_reliability.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tui/__init__.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tui/backend.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tui/main.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tui/screens/__init__.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tui/screens/benchmark_view.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tui/screens/claudemd_view.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tui/screens/compress_view.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tui/screens/index_view.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tui/screens/init_view.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tui/screens/mcp_view.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tui/screens/optimize_view.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tui/screens/pipe_view.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tui/screens/projects_view.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tui/screens/search_view.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tui/screens/session_view.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tui/screens/stats.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tui/screens/ui_view.py +0 -0
- {code_context_control-2.63.2 → code_context_control-2.64.0}/tui/theme.tcss +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code-context-control
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.64.0
|
|
4
4
|
Summary: Local MCP code-intelligence for AI coding tools: surgical search/read/edit, agent-config version history, path-level access + masking guards, and a multi-project hub.
|
|
5
5
|
Author-email: Dimitri Tselenchuk <dtselenc@gmail.com>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -92,7 +92,7 @@ console = Console() if HAS_RICH else None
|
|
|
92
92
|
# Config
|
|
93
93
|
CONFIG_DIR = ".c3"
|
|
94
94
|
CONFIG_FILE = ".c3/config.json"
|
|
95
|
-
__version__ = "2.
|
|
95
|
+
__version__ = "2.64.0"
|
|
96
96
|
|
|
97
97
|
|
|
98
98
|
def _compress_file_cli(compressor, path, mode="smart", **kw):
|
|
@@ -4046,14 +4046,22 @@ def cmd_pipe(args):
|
|
|
4046
4046
|
|
|
4047
4047
|
|
|
4048
4048
|
from services.claude_md import C3_COMPACT_WORKFLOW as _SHARED_C3_COMPACT_WORKFLOW
|
|
4049
|
+
from services.claude_md import VSCODE_SESSION_INIT as _VSCODE_SESSION_INIT
|
|
4050
|
+
from services.claude_md import adapt_workflow_for_ide as _adapt_workflow_for_ide
|
|
4049
4051
|
|
|
4050
4052
|
_C3_COMPACT_WORKFLOW = _SHARED_C3_COMPACT_WORKFLOW
|
|
4051
4053
|
|
|
4052
4054
|
_CLAUDE_MD_CONTENT = _C3_COMPACT_WORKFLOW
|
|
4053
4055
|
|
|
4054
|
-
|
|
4056
|
+
# Copilot and Codex run without PreToolUse hooks and without /clear, so both
|
|
4057
|
+
# docs get the hookless restatement of the mandate (see PROFILES in core/ide.py).
|
|
4058
|
+
_C3_HOOKLESS_WORKFLOW = _adapt_workflow_for_ide(
|
|
4059
|
+
_C3_COMPACT_WORKFLOW, supports_hooks=False, supports_clear=False
|
|
4060
|
+
)
|
|
4061
|
+
|
|
4062
|
+
_COPILOT_INSTRUCTIONS_CONTENT = _VSCODE_SESSION_INIT + "\n\n" + _C3_HOOKLESS_WORKFLOW
|
|
4055
4063
|
|
|
4056
|
-
_AGENTS_MD_CONTENT =
|
|
4064
|
+
_AGENTS_MD_CONTENT = _C3_HOOKLESS_WORKFLOW + """
|
|
4057
4065
|
|
|
4058
4066
|
## IDE Configuration (Codex)
|
|
4059
4067
|
This project uses project-scoped MCP servers. Ensure your `.codex/config.toml` includes:
|
|
@@ -5989,6 +5997,10 @@ def _access_cmd_list(args, project_path: str) -> None:
|
|
|
5989
5997
|
if sec.get("corrupt"):
|
|
5990
5998
|
print(" [warn] access section invalid — scope fails closed "
|
|
5991
5999
|
"(deny-all); fix config.json 'access' by hand")
|
|
6000
|
+
if scope == "builtin":
|
|
6001
|
+
print(" spelling rules (deny by how a path is written, no glob):")
|
|
6002
|
+
for name, why in access_guard.SYNTHETIC_RULES:
|
|
6003
|
+
print(f" {name:<18} {why}")
|
|
5992
6004
|
print()
|
|
5993
6005
|
from services import mask_activation
|
|
5994
6006
|
summary = mask_activation.summary_line(project_path)
|
|
@@ -6404,6 +6416,66 @@ def _jira_cmd_set_default(args, project_path: str) -> None:
|
|
|
6404
6416
|
print(f"[OK] Default Jira project: {args.project}")
|
|
6405
6417
|
|
|
6406
6418
|
|
|
6419
|
+
def _oracle_open(args):
|
|
6420
|
+
"""Mint a single-use sign-in URL for a running Oracle dashboard (#31).
|
|
6421
|
+
|
|
6422
|
+
Plain ``GET /`` no longer issues the session cookie, so a dashboard opened
|
|
6423
|
+
by hand is read-only until a bootstrap code is redeemed. Reading the
|
|
6424
|
+
owner-only key file is what proves we are the same OS user as the server.
|
|
6425
|
+
"""
|
|
6426
|
+
import json as _json
|
|
6427
|
+
import urllib.error
|
|
6428
|
+
import urllib.request
|
|
6429
|
+
import webbrowser
|
|
6430
|
+
|
|
6431
|
+
from oracle.config import ORACLE_DIR, load_config
|
|
6432
|
+
from oracle.services import local_session
|
|
6433
|
+
|
|
6434
|
+
cfg = load_config()
|
|
6435
|
+
host = cfg.get("bind_host", "127.0.0.1")
|
|
6436
|
+
disp_host = "127.0.0.1" if host in ("0.0.0.0", "") else host
|
|
6437
|
+
port = getattr(args, "port", None) or cfg.get("port", 3331)
|
|
6438
|
+
base = f"http://{disp_host}:{port}"
|
|
6439
|
+
|
|
6440
|
+
key = local_session.read_bootstrap_key(ORACLE_DIR)
|
|
6441
|
+
if not key:
|
|
6442
|
+
print(f"[oracle:open] no bootstrap key at "
|
|
6443
|
+
f"{ORACLE_DIR / local_session.BOOTSTRAP_KEY_FILENAME}")
|
|
6444
|
+
print(" The key is written when the server starts. Is Oracle running?")
|
|
6445
|
+
print(" Start it with: c3 oracle serve")
|
|
6446
|
+
return
|
|
6447
|
+
|
|
6448
|
+
req = urllib.request.Request(
|
|
6449
|
+
f"{base}/api/session/bootstrap",
|
|
6450
|
+
data=_json.dumps({"key": key}).encode("utf-8"),
|
|
6451
|
+
headers={"Content-Type": "application/json"},
|
|
6452
|
+
method="POST",
|
|
6453
|
+
)
|
|
6454
|
+
try:
|
|
6455
|
+
with urllib.request.urlopen(req, timeout=10) as resp:
|
|
6456
|
+
payload = _json.loads(resp.read().decode("utf-8"))
|
|
6457
|
+
except urllib.error.HTTPError as e:
|
|
6458
|
+
detail = e.read().decode("utf-8", "replace")[:200]
|
|
6459
|
+
print(f"[oracle:open] server refused the request ({e.code}): {detail}")
|
|
6460
|
+
if e.code == 401:
|
|
6461
|
+
print(" The key on disk is stale — restart the server to rewrite it.")
|
|
6462
|
+
return
|
|
6463
|
+
except OSError as e:
|
|
6464
|
+
print(f"[oracle:open] could not reach {base}: {e}")
|
|
6465
|
+
print(" Start it with: c3 oracle serve")
|
|
6466
|
+
return
|
|
6467
|
+
|
|
6468
|
+
url = payload.get("url", "")
|
|
6469
|
+
if not url:
|
|
6470
|
+
print("[oracle:open] server returned no URL")
|
|
6471
|
+
return
|
|
6472
|
+
ttl = payload.get("expires_in", local_session.CODE_TTL_SECONDS)
|
|
6473
|
+
print(f"[oracle:open] single-use sign-in link (valid {ttl}s, one use):")
|
|
6474
|
+
print(f" {url}")
|
|
6475
|
+
if not getattr(args, "no_browser", False):
|
|
6476
|
+
webbrowser.open(url)
|
|
6477
|
+
|
|
6478
|
+
|
|
6407
6479
|
def cmd_oracle(args):
|
|
6408
6480
|
"""Oracle dashboard server + Discovery API key management."""
|
|
6409
6481
|
sub = getattr(args, "oracle_cmd", None)
|
|
@@ -6414,8 +6486,12 @@ def cmd_oracle(args):
|
|
|
6414
6486
|
run_oracle(port=getattr(args, "port", None),
|
|
6415
6487
|
open_browser=not getattr(args, "no_browser", False))
|
|
6416
6488
|
return
|
|
6489
|
+
if sub == "open":
|
|
6490
|
+
_oracle_open(args)
|
|
6491
|
+
return
|
|
6417
6492
|
if sub != "api":
|
|
6418
|
-
print("Usage: c3 oracle {serve,api} — serve: launch the dashboard; "
|
|
6493
|
+
print("Usage: c3 oracle {serve,open,api} — serve: launch the dashboard; "
|
|
6494
|
+
"open: sign in to a running dashboard; "
|
|
6419
6495
|
"api {info,key,rotate,clear}: manage the Discovery key")
|
|
6420
6496
|
return
|
|
6421
6497
|
|
|
@@ -540,6 +540,14 @@ def build_parser(version: str, parse_cli_ide_arg):
|
|
|
540
540
|
help="Server port (default: config 'port', 3331)")
|
|
541
541
|
or_serve.add_argument("--no-browser", action="store_true",
|
|
542
542
|
help="Don't open the browser")
|
|
543
|
+
or_open = or_subs.add_parser(
|
|
544
|
+
"open",
|
|
545
|
+
help="Sign in to a running dashboard via a single-use URL",
|
|
546
|
+
)
|
|
547
|
+
or_open.add_argument("--port", type=int, default=None,
|
|
548
|
+
help="Server port (default: config 'port', 3331)")
|
|
549
|
+
or_open.add_argument("--no-browser", action="store_true",
|
|
550
|
+
help="Print the URL without opening a browser")
|
|
543
551
|
or_api = or_subs.add_parser(
|
|
544
552
|
"api",
|
|
545
553
|
help="Show connection info / manage the Discovery API key",
|
|
@@ -31,6 +31,23 @@ _SHELL_TOOLS = {"Bash"} # normalize_tool_name folds run_shell_command in
|
|
|
31
31
|
_TOKEN_SPLIT = re.compile(r"\s+")
|
|
32
32
|
_MAX_TOKENS = 200
|
|
33
33
|
|
|
34
|
+
# A colon in a shell token overwhelmingly means "URL scheme" or "IPv6", not
|
|
35
|
+
# "NTFS alternate data stream". The ADS check stays strict for real path
|
|
36
|
+
# arguments (_WRITE_TOOLS/_READ_TOOLS); here it only produced false denies on
|
|
37
|
+
# commit messages, curl, and gh (#50).
|
|
38
|
+
_SCHEME_RE = re.compile(r"^[a-z][a-z0-9+.\-]*://", re.IGNORECASE)
|
|
39
|
+
# IPv6 literal or CIDR: >=2 colons, hex groups only, optional [] and /prefix.
|
|
40
|
+
# 'C:/x/f.txt:stream' has one colon and non-hex parts, so it never matches.
|
|
41
|
+
_IPV6_RE = re.compile(
|
|
42
|
+
r"^\[?[0-9a-f]{0,4}(?::[0-9a-f]{0,4}){2,}\]?(?:/\d{1,3})?$",
|
|
43
|
+
re.IGNORECASE,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _is_network_token(tok: str) -> bool:
|
|
48
|
+
"""True for URLs and IPv6 literals/CIDRs — never for an ADS spelling."""
|
|
49
|
+
return bool(_SCHEME_RE.match(tok) or _IPV6_RE.match(tok))
|
|
50
|
+
|
|
34
51
|
|
|
35
52
|
def _deny(reason: str) -> dict:
|
|
36
53
|
return {
|
|
@@ -57,6 +74,10 @@ def _scan_shell(cmd: str, base: str):
|
|
|
57
74
|
Confident = the token resolves to an EXISTING path that a ``deny`` rule
|
|
58
75
|
covers (existence-gating keeps regex/pattern arguments like '\\.env'
|
|
59
76
|
from false-denying), or the evaluator flags the spelling itself.
|
|
77
|
+
|
|
78
|
+
URLs and IPv6 literals are skipped outright: they trip the ADS spelling
|
|
79
|
+
check, which is exempt from existence-gating, so a token naming nothing
|
|
80
|
+
on disk would otherwise hard-deny (#50).
|
|
60
81
|
"""
|
|
61
82
|
for raw in _TOKEN_SPLIT.split(cmd)[:_MAX_TOKENS]:
|
|
62
83
|
tok = raw.strip("\"'`;,()")
|
|
@@ -64,6 +85,8 @@ def _scan_shell(cmd: str, base: str):
|
|
|
64
85
|
continue
|
|
65
86
|
if "/" not in tok and "\\" not in tok and not tok.startswith("."):
|
|
66
87
|
continue
|
|
88
|
+
if _is_network_token(tok):
|
|
89
|
+
continue
|
|
67
90
|
if re.match(r"^/[a-z]/", tok): # MSYS /c/foo → C:/foo
|
|
68
91
|
tok = f"{tok[1]}:{tok[2:]}"
|
|
69
92
|
denial = ag.check(tok, "read", base)
|
|
@@ -379,12 +379,6 @@ def index():
|
|
|
379
379
|
return Response(_hub_html_cache, mimetype="text/html")
|
|
380
380
|
|
|
381
381
|
|
|
382
|
-
@app.route("/legacy")
|
|
383
|
-
def index_legacy():
|
|
384
|
-
"""Frozen pre-2.44 hub UI — escape hatch for one release, then removed."""
|
|
385
|
-
return send_from_directory(str(Path(__file__).parent), "hub.html")
|
|
386
|
-
|
|
387
|
-
|
|
388
382
|
@app.route("/guide/")
|
|
389
383
|
@app.route("/guide/<path:filename>")
|
|
390
384
|
def serve_guide(filename="index.html"):
|
{code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/settings_modal.js
RENAMED
|
@@ -187,12 +187,6 @@ function SettingsModal({ onClose, onChanged }) {
|
|
|
187
187
|
</div>
|
|
188
188
|
)}
|
|
189
189
|
|
|
190
|
-
<div style={{ marginTop: 18, paddingTop: 12, borderTop: `1px solid ${T.border}` }}>
|
|
191
|
-
<a href="/legacy" style={{ fontSize: 11, color: T.textMuted, textDecoration: 'none' }}>
|
|
192
|
-
Legacy UI (pre-2.44)
|
|
193
|
-
</a>
|
|
194
|
-
</div>
|
|
195
|
-
|
|
196
190
|
{confirmAction === 'stop' && (
|
|
197
191
|
<ConfirmDialog title="Stop Hub"
|
|
198
192
|
message="The page will become unreachable until the hub is restarted (c3 hub)."
|
{code_context_control-2.63.2 → code_context_control-2.64.0}/code_context_control.egg-info/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code-context-control
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.64.0
|
|
4
4
|
Summary: Local MCP code-intelligence for AI coding tools: surgical search/read/edit, agent-config version history, path-level access + masking guards, and a multi-project hub.
|
|
5
5
|
Author-email: Dimitri Tselenchuk <dtselenc@gmail.com>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -21,7 +21,6 @@ cli/hook_prompt_recall.py
|
|
|
21
21
|
cli/hook_read.py
|
|
22
22
|
cli/hook_session_stats.py
|
|
23
23
|
cli/hook_terse_advisor.py
|
|
24
|
-
cli/hub.html
|
|
25
24
|
cli/hub_server.py
|
|
26
25
|
cli/hub_ui.html
|
|
27
26
|
cli/mcp_proxy.py
|
|
@@ -132,6 +131,7 @@ oracle/services/c3_bridge.py
|
|
|
132
131
|
oracle/services/chat_engine.py
|
|
133
132
|
oracle/services/chat_store.py
|
|
134
133
|
oracle/services/cross_memory.py
|
|
134
|
+
oracle/services/discovery_audit.py
|
|
135
135
|
oracle/services/federated_graph.py
|
|
136
136
|
oracle/services/health_checker.py
|
|
137
137
|
oracle/services/insight_engine.py
|
|
@@ -285,6 +285,7 @@ tests/test_hub_credentials_routes_write.py
|
|
|
285
285
|
tests/test_hub_inspect_api.py
|
|
286
286
|
tests/test_hub_server_smoke.py
|
|
287
287
|
tests/test_hub_subproject_links.py
|
|
288
|
+
tests/test_ide_workflow_adaptation.py
|
|
288
289
|
tests/test_init_scan.py
|
|
289
290
|
tests/test_install_mcp_entrypoint.py
|
|
290
291
|
tests/test_jira_cli_smoke.py
|
|
@@ -314,11 +315,14 @@ tests/test_oracle_api_auth.py
|
|
|
314
315
|
tests/test_oracle_apikey_api.py
|
|
315
316
|
tests/test_oracle_c3_bridge.py
|
|
316
317
|
tests/test_oracle_chat_engine.py
|
|
318
|
+
tests/test_oracle_chat_store.py
|
|
317
319
|
tests/test_oracle_discovery_api.py
|
|
320
|
+
tests/test_oracle_discovery_audit.py
|
|
318
321
|
tests/test_oracle_local_auth.py
|
|
319
322
|
tests/test_oracle_ollama_bridge.py
|
|
320
323
|
tests/test_oracle_scanner_cache.py
|
|
321
324
|
tests/test_oracle_security_fixes.py
|
|
325
|
+
tests/test_oracle_session_bootstrap.py
|
|
322
326
|
tests/test_oracle_subproject_awareness.py
|
|
323
327
|
tests/test_oracle_ui_bundle.py
|
|
324
328
|
tests/test_output_filter.py
|
|
@@ -14,6 +14,9 @@ DEFAULTS = {
|
|
|
14
14
|
"api_enabled": True, # expose /api/discovery/* REST surface
|
|
15
15
|
"api_require_auth": True, # require Bearer token on /api/discovery/*
|
|
16
16
|
"api_max_tier": "action", # cap exposed tools: "read" | "action"
|
|
17
|
+
"api_rate_limit_per_min": 60, # per-caller tool-call budget; 0 disables
|
|
18
|
+
"api_rate_burst": 0, # bucket size; 0 = quarter-minute of budget
|
|
19
|
+
"api_audit_enabled": True, # JSONL audit line per discovery tool call
|
|
17
20
|
"mcp_enabled": True, # start FastMCP HTTP/SSE discovery server
|
|
18
21
|
"mcp_port": 3332, # discovery MCP transport port (loopback)
|
|
19
22
|
"ollama_base_url": "https://ollama.com",
|
|
@@ -6,6 +6,7 @@ import logging
|
|
|
6
6
|
import socket
|
|
7
7
|
import sys
|
|
8
8
|
import threading
|
|
9
|
+
import time
|
|
9
10
|
import urllib.request
|
|
10
11
|
import webbrowser
|
|
11
12
|
from pathlib import Path
|
|
@@ -15,7 +16,7 @@ _PROJECT_ROOT = Path(__file__).resolve().parent.parent
|
|
|
15
16
|
if str(_PROJECT_ROOT) not in sys.path:
|
|
16
17
|
sys.path.insert(0, str(_PROJECT_ROOT))
|
|
17
18
|
|
|
18
|
-
from flask import Flask, Response, jsonify, request # noqa: E402
|
|
19
|
+
from flask import Flask, Response, jsonify, redirect, request, url_for # noqa: E402
|
|
19
20
|
|
|
20
21
|
from oracle.config import ORACLE_DIR, load_config, save_config # noqa: E402
|
|
21
22
|
from oracle.mcp_oracle import mcp_url, start_mcp_thread # noqa: E402
|
|
@@ -143,6 +144,42 @@ _install_web_guard(
|
|
|
143
144
|
)
|
|
144
145
|
|
|
145
146
|
|
|
147
|
+
# ── Discovery API rate limit + audit (#33) ────────────────
|
|
148
|
+
from oracle.services import discovery_audit # noqa: E402
|
|
149
|
+
|
|
150
|
+
# Only tool-executing routes are throttled; /tools, /openapi.json and
|
|
151
|
+
# /mcp-info are cheap reads.
|
|
152
|
+
_RATE_LIMITED_PATHS = {"/api/discovery/call", "/api/discovery/call/stream"}
|
|
153
|
+
|
|
154
|
+
_limiter: discovery_audit.RateLimiter | None = None
|
|
155
|
+
_limiter_key: tuple[int, int] | None = None
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def _rate_limiter() -> discovery_audit.RateLimiter:
|
|
159
|
+
"""Rebuild the bucket only when the configured budget actually changes,
|
|
160
|
+
so a config reload does not silently reset every caller's usage."""
|
|
161
|
+
global _limiter, _limiter_key
|
|
162
|
+
key = (int(_cfg.get("api_rate_limit_per_min", 60) or 0),
|
|
163
|
+
int(_cfg.get("api_rate_burst", 0) or 0))
|
|
164
|
+
if _limiter is None or key != _limiter_key:
|
|
165
|
+
_limiter = discovery_audit.RateLimiter(per_minute=key[0], burst=key[1])
|
|
166
|
+
_limiter_key = key
|
|
167
|
+
return _limiter
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def _audit_call(name: str, args: dict, started: float, status: str) -> None:
|
|
171
|
+
if not _cfg.get("api_audit_enabled", True):
|
|
172
|
+
return
|
|
173
|
+
token = extract_bearer(request.headers.get("Authorization"))
|
|
174
|
+
discovery_audit.record(
|
|
175
|
+
name,
|
|
176
|
+
caller=discovery_audit.caller_id(token, request.remote_addr),
|
|
177
|
+
args=args,
|
|
178
|
+
duration_ms=(time.monotonic() - started) * 1000.0,
|
|
179
|
+
status=status,
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
|
|
146
183
|
# ── Discovery API auth guard ──────────────────────────────
|
|
147
184
|
@app.before_request
|
|
148
185
|
def _discovery_auth_guard():
|
|
@@ -154,10 +191,28 @@ def _discovery_auth_guard():
|
|
|
154
191
|
return None # allow CORS preflight
|
|
155
192
|
if not _cfg.get("api_enabled", True):
|
|
156
193
|
return jsonify({"error": "discovery API disabled"}), 404
|
|
194
|
+
token = extract_bearer(request.headers.get("Authorization"))
|
|
157
195
|
if _cfg.get("api_require_auth", True):
|
|
158
|
-
token = extract_bearer(request.headers.get("Authorization"))
|
|
159
196
|
if not verify_api_key(token):
|
|
160
197
|
return jsonify({"error": "unauthorized"}), 401
|
|
198
|
+
|
|
199
|
+
# Throttle the endpoints that actually execute tools. Listing tools, the
|
|
200
|
+
# OpenAPI doc, and mcp-info are cheap and read-only, so they stay open —
|
|
201
|
+
# a limiter that blocks discovery of the API is just a worse error message.
|
|
202
|
+
if request.path.rstrip("/") in _RATE_LIMITED_PATHS or \
|
|
203
|
+
request.path.startswith("/api/discovery/tools/"):
|
|
204
|
+
limiter = _rate_limiter()
|
|
205
|
+
allowed, retry_after = limiter.check(
|
|
206
|
+
discovery_audit.caller_id(token, request.remote_addr)
|
|
207
|
+
)
|
|
208
|
+
if not allowed:
|
|
209
|
+
resp = jsonify({
|
|
210
|
+
"error": "rate limited",
|
|
211
|
+
"detail": f"exceeded {limiter.per_minute} tool calls/min",
|
|
212
|
+
"retry_after": round(retry_after, 2),
|
|
213
|
+
})
|
|
214
|
+
resp.headers["Retry-After"] = str(max(1, int(retry_after + 0.999)))
|
|
215
|
+
return resp, 429
|
|
161
216
|
return None
|
|
162
217
|
|
|
163
218
|
|
|
@@ -178,6 +233,10 @@ def _local_write_guard():
|
|
|
178
233
|
return None
|
|
179
234
|
if request.method in ("GET", "HEAD", "OPTIONS"):
|
|
180
235
|
return None
|
|
236
|
+
# The bootstrap mint is how a browser ACQUIRES the cookie, so it cannot
|
|
237
|
+
# require one. It runs its own loopback + bootstrap-key/Bearer check.
|
|
238
|
+
if path == "/api/session/bootstrap":
|
|
239
|
+
return None
|
|
181
240
|
if verify_api_key(extract_bearer(request.headers.get("Authorization"))):
|
|
182
241
|
return None
|
|
183
242
|
if local_session.verify(request.cookies.get(local_session.COOKIE_NAME)):
|
|
@@ -237,14 +296,48 @@ _oracle_html_cache: str | None = None
|
|
|
237
296
|
@app.route("/")
|
|
238
297
|
def index():
|
|
239
298
|
global _oracle_html_cache
|
|
299
|
+
# A single-use bootstrap code is the ONLY way to obtain the session
|
|
300
|
+
# cookie (#31). Redeeming it redirects to a clean "/" so the code does
|
|
301
|
+
# not linger in the address bar, browser history, or a Referer header.
|
|
302
|
+
code = request.args.get(local_session.BOOTSTRAP_PARAM)
|
|
303
|
+
if code:
|
|
304
|
+
if local_session.is_loopback(request.remote_addr) and \
|
|
305
|
+
local_session.consume_code(code):
|
|
306
|
+
resp = redirect(url_for("index"))
|
|
307
|
+
local_session.attach_cookie(resp)
|
|
308
|
+
return resp
|
|
309
|
+
return redirect(url_for("index", stale="1"))
|
|
310
|
+
|
|
240
311
|
if _oracle_html_cache is None:
|
|
241
312
|
_oracle_html_cache = _build_oracle_html()
|
|
242
|
-
|
|
243
|
-
#
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
313
|
+
# No cookie here by design: plain GET / is readable by any local process,
|
|
314
|
+
# including one running as a different OS user.
|
|
315
|
+
return Response(_oracle_html_cache, mimetype="text/html")
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
@app.route("/api/session/bootstrap", methods=["POST"])
|
|
319
|
+
def api_session_bootstrap():
|
|
320
|
+
"""Mint a single-use bootstrap URL. Used by ``c3 oracle open``.
|
|
321
|
+
|
|
322
|
+
Authorized by the on-disk bootstrap key (owner-only) or the Discovery
|
|
323
|
+
Bearer token — both prove same-OS-user access, which is the boundary
|
|
324
|
+
this feature enforces.
|
|
325
|
+
"""
|
|
326
|
+
if not local_session.is_loopback(request.remote_addr):
|
|
327
|
+
return jsonify({"error": "loopback only"}), 403
|
|
328
|
+
data = request.get_json(silent=True) or {}
|
|
329
|
+
presented = (data.get("key") or "").strip() or \
|
|
330
|
+
request.headers.get("X-C3-Bootstrap-Key", "")
|
|
331
|
+
authorized = local_session.verify_bootstrap_key(presented) or \
|
|
332
|
+
verify_api_key(extract_bearer(request.headers.get("Authorization")))
|
|
333
|
+
if not authorized:
|
|
334
|
+
return jsonify({"error": "unauthorized"}), 401
|
|
335
|
+
code = local_session.mint_code()
|
|
336
|
+
base = request.host_url.rstrip("/")
|
|
337
|
+
return jsonify({
|
|
338
|
+
"url": f"{base}/?{local_session.BOOTSTRAP_PARAM}={code}",
|
|
339
|
+
"expires_in": local_session.CODE_TTL_SECONDS,
|
|
340
|
+
})
|
|
248
341
|
|
|
249
342
|
|
|
250
343
|
# ── Health ────────────────────────────────────────────────
|
|
@@ -778,7 +871,15 @@ def api_discovery_call():
|
|
|
778
871
|
args = data.get("args") or {}
|
|
779
872
|
if not isinstance(args, dict):
|
|
780
873
|
return jsonify({"error": "'args' must be an object"}), 400
|
|
781
|
-
|
|
874
|
+
started = time.monotonic()
|
|
875
|
+
try:
|
|
876
|
+
result = _tool_registry.call_tool(name, args)
|
|
877
|
+
except Exception:
|
|
878
|
+
_audit_call(name, args, started, "error")
|
|
879
|
+
raise
|
|
880
|
+
_audit_call(name, args, started,
|
|
881
|
+
"error" if isinstance(result, dict) and result.get("error") else "ok")
|
|
882
|
+
return jsonify(result)
|
|
782
883
|
|
|
783
884
|
|
|
784
885
|
@app.route("/api/discovery/tools/<name>", methods=["POST"])
|
|
@@ -789,7 +890,25 @@ def api_discovery_call_named(name):
|
|
|
789
890
|
args = request.get_json(silent=True) or {}
|
|
790
891
|
if not isinstance(args, dict):
|
|
791
892
|
return jsonify({"error": "request body must be a JSON object of arguments"}), 400
|
|
792
|
-
|
|
893
|
+
started = time.monotonic()
|
|
894
|
+
try:
|
|
895
|
+
result = _tool_registry.call_tool(name, args)
|
|
896
|
+
except Exception:
|
|
897
|
+
_audit_call(name, args, started, "error")
|
|
898
|
+
raise
|
|
899
|
+
_audit_call(name, args, started,
|
|
900
|
+
"error" if isinstance(result, dict) and result.get("error") else "ok")
|
|
901
|
+
return jsonify(result)
|
|
902
|
+
|
|
903
|
+
|
|
904
|
+
@app.route("/api/activity/discovery", methods=["GET"])
|
|
905
|
+
def api_activity_discovery():
|
|
906
|
+
"""Recent Discovery tool calls for the Activity tab (args are hashed)."""
|
|
907
|
+
try:
|
|
908
|
+
limit = max(1, min(500, int(request.args.get("limit", 100))))
|
|
909
|
+
except (TypeError, ValueError):
|
|
910
|
+
limit = 100
|
|
911
|
+
return jsonify({"calls": discovery_audit.read_recent(limit)})
|
|
793
912
|
|
|
794
913
|
|
|
795
914
|
@app.route("/api/discovery/call/stream", methods=["POST"])
|
|
@@ -1019,6 +1138,12 @@ def run_oracle(port: int = None, open_browser: bool = None):
|
|
|
1019
1138
|
url = f"http://localhost:{actual_port}"
|
|
1020
1139
|
print(f"Oracle Memory Agent → {url} (model: {cfg.get('model', 'gemma4:31b-cloud')})")
|
|
1021
1140
|
|
|
1141
|
+
# Publish the bootstrap key so a same-user `c3 oracle open` can mint a
|
|
1142
|
+
# sign-in link. Loading the URL above shows the dashboard read-only (#31).
|
|
1143
|
+
local_session.write_bootstrap_key(ORACLE_DIR)
|
|
1144
|
+
print(f"Sign in with: c3 oracle open"
|
|
1145
|
+
f"{'' if actual_port == 3331 else f' --port {actual_port}'}")
|
|
1146
|
+
|
|
1022
1147
|
# Start review agent if enabled
|
|
1023
1148
|
if cfg.get("review_enabled", True) and _agent:
|
|
1024
1149
|
_agent.start()
|
|
@@ -1045,7 +1170,12 @@ def run_oracle(port: int = None, open_browser: bool = None):
|
|
|
1045
1170
|
logging.getLogger("oracle").warning("MCP server not started: %s", e)
|
|
1046
1171
|
|
|
1047
1172
|
if open_browser:
|
|
1048
|
-
|
|
1173
|
+
# Auto-open lands signed in: the server mints its own code rather
|
|
1174
|
+
# than making the common case require a second command. This grants
|
|
1175
|
+
# nothing extra — the server already holds the secret, and it opens
|
|
1176
|
+
# the default browser as the same OS user that launched it.
|
|
1177
|
+
signed_in = f"{url}/?{local_session.BOOTSTRAP_PARAM}={local_session.mint_code()}"
|
|
1178
|
+
threading.Timer(0.8, lambda: webbrowser.open(signed_in)).start()
|
|
1049
1179
|
|
|
1050
1180
|
app.run(host=cfg.get("bind_host", "127.0.0.1"), port=actual_port, debug=False, use_reloader=False)
|
|
1051
1181
|
|