code-context-control 2.143.0__tar.gz → 2.145.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.143.0 → code_context_control-2.145.0}/PKG-INFO +2 -1
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/c3.py +131 -12
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/commands/parser.py +21 -6
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hook_pretool_enforce.py +1 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hub_server.py +32 -24
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hub_ui/components/hub_credentials.js +32 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/server.py +7 -21
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/tools/credentials.py +25 -8
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/ui/components/credentials.js +1 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/code_context_control.egg-info/PKG-INFO +2 -1
- {code_context_control-2.143.0 → code_context_control-2.145.0}/code_context_control.egg-info/SOURCES.txt +2 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/code_context_control.egg-info/requires.txt +1 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/services/mobile_api.py +7 -15
- {code_context_control-2.143.0 → code_context_control-2.145.0}/pyproject.toml +2 -1
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/access_guard.py +2 -1
- code_context_control-2.145.0/services/credential_backup.py +333 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/credential_store.py +92 -25
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/override_policy.py +3 -1
- code_context_control-2.145.0/tests/test_credential_backup.py +245 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_credential_store.py +33 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_credentials_routes.py +19 -1
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_credentials_tool.py +16 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_creds_cli_smoke.py +20 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_hub_credentials_routes_write.py +14 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_mobile_security_api.py +12 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/LICENSE +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/README.md +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/__init__.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/_hook_utils.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/_shell_writes.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/commands/__init__.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/commands/common.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/docs.html +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/edits.html +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/guide/access.html +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/guide/bitbucket.html +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/guide/credentials.html +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/guide/getting-started.html +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/guide/index.html +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/guide/masking.html +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/guide/oracle.html +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/guide/shared.css +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/guide/tools.html +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/guide/workflow.html +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hook_access_guard.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hook_agent_model.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hook_artifact.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hook_auto_snapshot.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hook_c3_signal.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hook_c3read.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hook_codex_lifecycle.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hook_dispatch.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hook_edit_ledger.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hook_edit_unlock.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hook_filter.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hook_ghost_files.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hook_prompt_recall.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hook_read.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hook_session_end.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hook_session_open.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hook_session_stats.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hook_terse_advisor.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hub_ui/app.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hub_ui/components/add_project.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hub_ui/components/config_editor.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hub_ui/components/drill_artifacts.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hub_ui/components/drill_health.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hub_ui/components/drill_panel.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hub_ui/components/drill_subprojects.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hub_ui/components/drill_tasks.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hub_ui/components/drill_views.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hub_ui/components/global_search.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hub_ui/components/hub_access.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hub_ui/components/hub_ci.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hub_ui/components/hub_cred_audit.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hub_ui/components/hub_enforcement.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hub_ui/components/hub_locks.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hub_ui/components/hub_sessions.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hub_ui/components/hub_tokens.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hub_ui/components/mcp_manager.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hub_ui/components/modals.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hub_ui/components/project_card.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hub_ui/components/project_tree.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hub_ui/components/session_drawer.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hub_ui/components/settings_modal.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hub_ui/components/sidebar.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hub_ui/components/summary_bar.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hub_ui/components/task_board.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hub_ui/components/toasts.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hub_ui/components/topbar.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hub_ui/state.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/hub_ui.html +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/mcp_proxy.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/mcp_server.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/progress.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/tools/__init__.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/tools/_grants.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/tools/_helpers.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/tools/agent.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/tools/artifacts.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/tools/bitbucket.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/tools/ci.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/tools/compress.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/tools/delegate.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/tools/edit.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/tools/edit_verify.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/tools/edits.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/tools/federate.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/tools/filter.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/tools/impact.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/tools/jira.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/tools/locks.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/tools/memory.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/tools/override.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/tools/project.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/tools/read.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/tools/search.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/tools/session.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/tools/shell.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/tools/shell_job.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/tools/shell_nudge.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/tools/shell_parsers.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/tools/shell_render.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/tools/status.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/tools/tasks.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/tools/validate.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/ui/api.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/ui/app.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/ui/components/access.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/ui/components/bitbucket.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/ui/components/chat.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/ui/components/dashboard.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/ui/components/edits.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/ui/components/enforcement.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/ui/components/instructions.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/ui/components/jira.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/ui/components/memory.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/ui/components/sessions.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/ui/components/settings.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/ui/components/sidebar.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/ui/components/tasks.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/ui/icons.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/ui/pm_shared.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/ui/shared.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/ui/theme.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/ui.html +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/ui_legacy.html +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/cli/ui_nano.html +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/code_context_control.egg-info/dependency_links.txt +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/code_context_control.egg-info/entry_points.txt +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/code_context_control.egg-info/top_level.txt +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/core/__init__.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/core/codex_patch.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/core/config.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/core/grok_payload.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/core/hook_command.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/core/host.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/core/ide.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/core/mcp_toml.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/core/web_security.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/__init__.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/config.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/listeners.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/mcp_oracle.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/oracle_server.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/oracle_ui.html +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/services/__init__.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/services/activity_reporter.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/services/api_auth.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/services/c3_bridge.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/services/chat_engine.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/services/chat_poll.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/services/chat_store.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/services/client_tokens.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/services/cross_memory.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/services/discovery_audit.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/services/federated_graph.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/services/health_checker.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/services/insight_engine.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/services/local_session.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/services/memory_reader.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/services/memory_writer.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/services/project_scanner.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/services/review_agent.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/services/tool_executor.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/services/tool_registry.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/ui/activity.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/ui/agents.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/ui/app.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/ui/busy.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/ui/chat/conversations.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/ui/chat/input.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/ui/chat/markdown.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/ui/chat/send.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/ui/chat/stream_renderer.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/ui/chat/toolbar.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/ui/core.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/ui/crossgraph.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/ui/header.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/ui/insights.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/ui/projects.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/ui/qrcode.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/ui/settings.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/ui/suggestions.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/oracle/ui/theme_tabs.js +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/__init__.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/access_telemetry.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/activity_log.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/agent_base.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/agent_downshift.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/agent_locks.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/agents.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/agents_workflow.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/artifact_defs.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/artifact_store.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/atomic_json.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/auto_memory.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/background_service.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/bench/__init__.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/bench/delegate_eval.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/bench/delegate_write_eval.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/bench/external/__init__.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/bench/external/aider_polyglot.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/bench/external/swe_bench.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/bench/map_eval.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/bench/search_eval.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/bench/shell_eval.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/benchmark_dashboard.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/bitbucket_client.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/bitbucket_credentials.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/ci_act.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/ci_cache.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/ci_expr.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/ci_failures.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/ci_github.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/ci_impact.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/ci_intel.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/ci_runner.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/ci_workflow.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/circuit_breaker.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/claude_md.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/codex_integration.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/codex_transcript.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/compressor.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/context_snapshot.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/conversation_store.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/cred_audit.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/cred_telemetry.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/delegate_agents.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/delegate_hints.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/delegate_write.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/dir_map.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/doc_index.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/e2e_benchmark.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/e2e_evaluator.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/e2e_tasks.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/edit_ledger.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/embedding_index.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/enforcement_policy.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/error_reporting.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/file_map.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/file_memory.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/git_context.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/grok_integration.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/grok_transcript.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/host_sessions.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/hub_service.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/index_store.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/indexer.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/jira_client.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/jira_cloud.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/jira_credentials.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/jira_data_center.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/jira_links.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/lexical_index.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/mask_activation.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/mask_mirror.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/mask_presets.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/memory.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/memory_consolidator.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/memory_distiller.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/memory_graph.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/memory_grounder.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/memory_queue.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/memory_scorer.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/metrics.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/notifications.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/ollama_bridge.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/ollama_client.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/ollama_credentials.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/oracle_service.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/output_filter.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/override_costs.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/override_grants.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/override_requests.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/override_wake.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/parser.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/project_manager.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/project_runtime.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/protocol.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/proxy_state.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/repo_map.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/repo_shape.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/reranker.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/retention.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/retrieval.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/retrieval_broker.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/router.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/runtime.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/scanner.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/session_benchmark.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/session_catalog.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/session_live.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/session_manager.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/session_preloader.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/shell_jobs.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/shell_output.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/subprojects.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/task_store.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/telemetry.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/terminal_launch.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/text_index.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/time_tracker.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/tool_classifier.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/transcript_index.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/validation_cache.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/vector_store.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/watcher.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/services/win_subprocess.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/setup.cfg +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_access_builtin_optout.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_access_guard.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_access_guard_meta.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_access_guard_shell_project.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_access_guard_surfaces.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_access_guard_wiring.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_activity_log_find_last.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_activity_reporter.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_agent_locks.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_aider_polyglot.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_antigravity_transition.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_artifact_store.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_artifact_tool.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_atomic_json.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_background_service.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_bitbucket_cli_smoke.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_bitbucket_client.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_bitbucket_config_fallback.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_bitbucket_credentials.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_bitbucket_tool.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_builtin_modes.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_c3_bridge_project_artifacts.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_c3_shell.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_chat_poll.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_ci_act.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_ci_cache.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_ci_dag_ownership.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_ci_expr.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_ci_impact.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_ci_intel.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_ci_runner.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_ci_workflow.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_circuit_breaker.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_claude_md_merge.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_claude_md_updater.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_cli_smoke.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_codex_mcp_transport.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_codex_native.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_compressor_large_file.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_confirm_guard.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_confirm_guard_wiring.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_cooccurrence_bounds.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_cred_audit.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_cred_telemetry.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_credential_login_kind.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_credential_ui_parity.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_delegate_adoption_d4.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_delegate_auto.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_delegate_cascade.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_delegate_claude_d1.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_delegate_eval.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_delegate_grok.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_delegate_host_d2.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_delegate_scout_d3.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_delegate_telemetry_d0.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_delegate_thinking_cap.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_delegate_tuning.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_delegate_version_probe.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_delegate_write.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_delegate_write_eval.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_dir_map_c3.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_e2e_benchmark.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_edit_ledger_deadline.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_edit_ledger_hook.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_edit_locking.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_edit_normalization.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_edit_verify.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_embedding_index_deadlock.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_enforcement_flip.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_enforcement_policy.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_enforcement_routes.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_env_parser.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_failed_calls_do_not_unlock.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_federated_graph.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_file_map_c1.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_filter_backoff.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_ghost_files.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_ghost_generation.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_git_branch_awareness.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_grok_native.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_hook_access_guard.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_hook_codex_compat.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_hook_dispatch.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_hook_grok_compat.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_hook_pretool_enforce.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_hook_prompt_recall.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_hook_session_end.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_hook_smoke.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_hook_state.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_hook_utf8_stdio.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_hub_access_routes.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_hub_credentials_route.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_hub_enforcement_routes.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_hub_hook_migration.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_hub_inspect_api.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_hub_locks_routes.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_hub_oracle_service_routes.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_hub_override_policy_routes.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_hub_override_routes.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_hub_rules_routes.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_hub_server_smoke.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_hub_sessions_routes.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_hub_subproject_links.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_ide_workflow_adaptation.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_index_cap_not_hardcoded.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_init_clear_preserves_user_content.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_init_scan.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_install_mcp_entrypoint.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_jira_cli_smoke.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_jira_client.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_jira_config_fallback.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_jira_credentials.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_jira_links.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_jira_routes.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_jira_tool.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_large_files_c4.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_lazy_store_init.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_map_eval.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_map_telemetry_c0.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_mask_guard.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_mask_routes.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_mask_surfaces.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_mcp_host_guard.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_mcp_memory_timeout.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_mcp_server_smoke.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_mcp_toml.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_memory_distiller.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_memory_graph_api.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_memory_queue.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_memory_system.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_mobile_api.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_mobile_clients.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_mobile_extras.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_mobile_jobs_ci.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_mobile_override_costs.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_mobile_override_routes.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_no_stale_model_pins.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_notification_dedup.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_notification_discipline.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_notification_kinds.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_ollama_credentials.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_oracle_api_auth.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_oracle_apikey_api.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_oracle_c3_bridge.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_oracle_chat_engine.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_oracle_chat_store.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_oracle_discovery_api.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_oracle_discovery_audit.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_oracle_health_probe.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_oracle_local_auth.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_oracle_loopback.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_oracle_ollama_bridge.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_oracle_scanner_cache.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_oracle_security_fixes.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_oracle_session_bootstrap.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_oracle_subproject_awareness.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_oracle_ui_bundle.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_output_filter.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_override_costs.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_override_grants.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_override_grants_mcp.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_override_requests.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_override_wake.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_permissions.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_pm_api.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_project_manager.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_project_manager_merge.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_project_tool.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_read_coercion.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_read_edit_parity.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_read_outside_root.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_related_facts.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_repo_map.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_repo_shape.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_response_boilerplate.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_retention.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_review_digest.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_search_eval.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_search_p1.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_search_p2.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_search_p2b.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_search_p3.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_search_p4.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_search_p5.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_service_durability.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_session_benchmark.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_session_budget.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_session_catalog.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_session_live.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_session_tool.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_shell_budget_s1.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_shell_creds.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_shell_eval.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_shell_jobs_s3.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_shell_nudge_s4.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_shell_output.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_shell_parsers_s2.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_shell_robustness.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_shell_telemetry_s0.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_shell_write_ledger.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_shell_writes.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_subproject_clear_scope.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_subproject_depth_consumers.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_subproject_exclusion.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_subproject_federation.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_subproject_linkage_api.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_subprojects.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_swe_bench.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_task_store.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_task_tool.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_time_tracker.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_token_telemetry.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_token_tracking.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_tool_registry.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_ui_jsx_syntax.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_upgrade_and_version.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_validate.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_vault_write_guard.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_version_sync.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_watcher_pruning.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_web_security.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tests/test_windows_reliability.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tui/__init__.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tui/backend.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tui/main.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tui/screens/__init__.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tui/screens/benchmark_view.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tui/screens/claudemd_view.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tui/screens/compress_view.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tui/screens/index_view.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tui/screens/init_view.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tui/screens/mcp_view.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tui/screens/optimize_view.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tui/screens/pipe_view.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tui/screens/projects_view.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tui/screens/search_view.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tui/screens/session_view.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tui/screens/stats.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.0}/tui/screens/ui_view.py +0 -0
- {code_context_control-2.143.0 → code_context_control-2.145.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.145.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
|
|
@@ -44,6 +44,7 @@ Requires-Dist: rich>=13.0.0
|
|
|
44
44
|
Requires-Dist: click>=8.0.0
|
|
45
45
|
Requires-Dist: pyyaml>=6.0.0
|
|
46
46
|
Requires-Dist: keyring>=24.0
|
|
47
|
+
Requires-Dist: cryptography>=41.0
|
|
47
48
|
Provides-Extra: vector
|
|
48
49
|
Requires-Dist: scikit-learn>=1.3.0; extra == "vector"
|
|
49
50
|
Requires-Dist: numpy>=1.24.0; extra == "vector"
|
|
@@ -91,7 +91,7 @@ console = Console() if HAS_RICH else None
|
|
|
91
91
|
# Config
|
|
92
92
|
CONFIG_DIR = ".c3"
|
|
93
93
|
CONFIG_FILE = ".c3/config.json"
|
|
94
|
-
__version__ = "2.
|
|
94
|
+
__version__ = "2.145.0"
|
|
95
95
|
|
|
96
96
|
# The PreToolUse matcher for native subagent calls (installer and hub migration).
|
|
97
97
|
AGENT_MATCHER = "Agent|Task"
|
|
@@ -6371,7 +6371,7 @@ def cmd_creds(args):
|
|
|
6371
6371
|
"""Credential vault management (global + per-project scopes)."""
|
|
6372
6372
|
sub = getattr(args, "creds_cmd", None)
|
|
6373
6373
|
if not sub:
|
|
6374
|
-
print("Usage: c3 creds {set,get,list,rm,import,usage,audit} [args]")
|
|
6374
|
+
print("Usage: c3 creds {set,get,list,rm,import,usage,audit,backup} [args]")
|
|
6375
6375
|
return
|
|
6376
6376
|
|
|
6377
6377
|
project_path = getattr(args, "project_path", ".") or "."
|
|
@@ -6390,6 +6390,8 @@ def cmd_creds(args):
|
|
|
6390
6390
|
_creds_cmd_usage(args, project_path)
|
|
6391
6391
|
elif sub == "audit":
|
|
6392
6392
|
_creds_cmd_audit(args, project_path)
|
|
6393
|
+
elif sub == "backup":
|
|
6394
|
+
_creds_cmd_backup(args, project_path)
|
|
6393
6395
|
else:
|
|
6394
6396
|
print(f"Unknown creds subcommand: {sub}")
|
|
6395
6397
|
|
|
@@ -6398,11 +6400,12 @@ def _creds_scope(args) -> str:
|
|
|
6398
6400
|
return "global" if getattr(args, "use_global", False) else "project"
|
|
6399
6401
|
|
|
6400
6402
|
|
|
6401
|
-
def _creds_entry_line(name: str, entry: dict) -> str:
|
|
6403
|
+
def _creds_entry_line(name: str, entry: dict, missing: bool = False) -> str:
|
|
6402
6404
|
flags = [f for f in ("inject", "agent_readable") if entry.get(f)]
|
|
6405
|
+
size = "VALUE MISSING" if missing else f"len={entry.get('value_len', '?')}"
|
|
6403
6406
|
parts = [
|
|
6404
6407
|
f"{name:<24} {entry.get('scope', '?'):<8} {entry.get('type', 'token'):<10}"
|
|
6405
|
-
f"
|
|
6408
|
+
f" {size}",
|
|
6406
6409
|
]
|
|
6407
6410
|
display = entry.get("display") or {}
|
|
6408
6411
|
if display:
|
|
@@ -6465,13 +6468,15 @@ def _creds_cmd_set(args, project_path: str) -> None:
|
|
|
6465
6468
|
|
|
6466
6469
|
from services import credential_store as cred_store
|
|
6467
6470
|
|
|
6468
|
-
ctype = getattr(args, "ctype",
|
|
6471
|
+
ctype = getattr(args, "ctype", None)
|
|
6472
|
+
prompt_type = ctype or cred_store.get_entry(
|
|
6473
|
+
args.name, project_path=project_path).get("type", "token")
|
|
6469
6474
|
value = getattr(args, "value", "") or ""
|
|
6470
6475
|
if getattr(args, "stdin", False):
|
|
6471
6476
|
value = sys.stdin.read().rstrip("\n")
|
|
6472
6477
|
if not value:
|
|
6473
|
-
if
|
|
6474
|
-
value = _creds_prompt_structured(args.name,
|
|
6478
|
+
if prompt_type in cred_store.STRUCTURED_TYPES:
|
|
6479
|
+
value = _creds_prompt_structured(args.name, prompt_type)
|
|
6475
6480
|
if value == "{}":
|
|
6476
6481
|
print("Cancelled -- no fields entered.")
|
|
6477
6482
|
return
|
|
@@ -6485,11 +6490,11 @@ def _creds_cmd_set(args, project_path: str) -> None:
|
|
|
6485
6490
|
entry = cred_store.set_credential(
|
|
6486
6491
|
args.name, value,
|
|
6487
6492
|
scope=scope, project_path=project_path,
|
|
6488
|
-
description=getattr(args, "desc",
|
|
6493
|
+
description=getattr(args, "desc", None),
|
|
6489
6494
|
ctype=ctype,
|
|
6490
|
-
env_var=getattr(args, "env_var",
|
|
6491
|
-
agent_readable=
|
|
6492
|
-
inject=
|
|
6495
|
+
env_var=getattr(args, "env_var", None),
|
|
6496
|
+
agent_readable=getattr(args, "agent_readable", None),
|
|
6497
|
+
inject=getattr(args, "inject", None),
|
|
6493
6498
|
)
|
|
6494
6499
|
except (cred_store.CredentialError, RuntimeError) as exc:
|
|
6495
6500
|
print(f"[error] {exc}")
|
|
@@ -6499,6 +6504,111 @@ def _creds_cmd_set(args, project_path: str) -> None:
|
|
|
6499
6504
|
if entry["agent_readable"]:
|
|
6500
6505
|
print("[warn] agent_readable=true -- the agent can read this value "
|
|
6501
6506
|
"into its context and transcripts.")
|
|
6507
|
+
_creds_print_backup_note(entry.get("backup", ""))
|
|
6508
|
+
|
|
6509
|
+
|
|
6510
|
+
def _creds_print_backup_note(backup: str) -> None:
|
|
6511
|
+
if backup == "off":
|
|
6512
|
+
print("[note] no vault backup: this value exists only in the OS keychain. "
|
|
6513
|
+
"`c3 creds backup init` keeps a copy that survives a keychain wipe.")
|
|
6514
|
+
elif backup.startswith("failed"):
|
|
6515
|
+
print(f"[warn] the vault backup was not updated ({backup}); "
|
|
6516
|
+
"run `c3 creds backup sync`.")
|
|
6517
|
+
|
|
6518
|
+
|
|
6519
|
+
def _creds_known_projects(project_path: str) -> list:
|
|
6520
|
+
"""The current project plus every project the hub knows about."""
|
|
6521
|
+
from services.project_manager import ProjectManager
|
|
6522
|
+
paths = [str(Path(project_path).resolve())]
|
|
6523
|
+
paths += [str(p.get("path")) for p in ProjectManager().list_projects()
|
|
6524
|
+
if p.get("path")]
|
|
6525
|
+
return paths
|
|
6526
|
+
|
|
6527
|
+
|
|
6528
|
+
def _creds_read_passphrase(prompt: str, *, confirm: bool = False) -> str:
|
|
6529
|
+
import getpass
|
|
6530
|
+
first = getpass.getpass(prompt)
|
|
6531
|
+
if confirm and getpass.getpass("Repeat it: ") != first:
|
|
6532
|
+
print("[error] the passphrases did not match -- nothing changed.")
|
|
6533
|
+
return ""
|
|
6534
|
+
return first
|
|
6535
|
+
|
|
6536
|
+
|
|
6537
|
+
def _creds_cmd_backup(args, project_path: str) -> None:
|
|
6538
|
+
from services import credential_backup as backup
|
|
6539
|
+
|
|
6540
|
+
action = args.backup_cmd
|
|
6541
|
+
if action in ("init", "restore", "passphrase") and not sys.stdin.isatty():
|
|
6542
|
+
print("[error] run this in your own terminal: the passphrase is read from "
|
|
6543
|
+
"the keyboard, never from a pipe or an argument.")
|
|
6544
|
+
return
|
|
6545
|
+
try:
|
|
6546
|
+
if action == "init":
|
|
6547
|
+
print("Choose a passphrase for the vault backup. Without it the backup "
|
|
6548
|
+
"cannot be opened -- keep it in your password manager.")
|
|
6549
|
+
passphrase = _creds_read_passphrase(
|
|
6550
|
+
f"New passphrase (min {backup.MIN_PASSPHRASE} chars): ", confirm=True)
|
|
6551
|
+
if not passphrase:
|
|
6552
|
+
return
|
|
6553
|
+
backup.init(passphrase)
|
|
6554
|
+
done = backup.sync(_creds_known_projects(project_path))
|
|
6555
|
+
print(f"[OK] Vault backup on: {backup.backup_path()} -- "
|
|
6556
|
+
f"{done['saved']} value(s) copied. Every value you set from now "
|
|
6557
|
+
"on is copied automatically.")
|
|
6558
|
+
if done["missing"]:
|
|
6559
|
+
print(f" no value to copy (re-enter these): {', '.join(done['missing'])}")
|
|
6560
|
+
elif action == "sync":
|
|
6561
|
+
done = backup.sync(_creds_known_projects(project_path))
|
|
6562
|
+
print(f"[OK] {done['saved']} value(s) copied to the vault backup.")
|
|
6563
|
+
for label, names in (("no value to copy", done["missing"]),
|
|
6564
|
+
("failed", done["failed"])):
|
|
6565
|
+
if names:
|
|
6566
|
+
print(f" {label}: {', '.join(names)}")
|
|
6567
|
+
elif action == "status":
|
|
6568
|
+
st = backup.status(_creds_known_projects(project_path))
|
|
6569
|
+
if st["enabled"]:
|
|
6570
|
+
print(f"Vault backup: on ({st['path']}, created {st['created']}) -- "
|
|
6571
|
+
f"{st['backed_up']} value(s) held.")
|
|
6572
|
+
else:
|
|
6573
|
+
print("Vault backup: off -- values live only in the OS keychain. "
|
|
6574
|
+
"Turn it on with `c3 creds backup init`.")
|
|
6575
|
+
for label, key in (("restorable (`c3 creds backup restore`)", "restorable"),
|
|
6576
|
+
("lost, no copy (re-enter with `c3 creds set`)", "lost"),
|
|
6577
|
+
("not backed up yet (`c3 creds backup sync`)", "not_backed_up")):
|
|
6578
|
+
if st[key] and (st["enabled"] or key == "lost"):
|
|
6579
|
+
print(f" {label}: {', '.join(st[key])}")
|
|
6580
|
+
elif action == "restore":
|
|
6581
|
+
passphrase = _creds_read_passphrase("Backup passphrase: ")
|
|
6582
|
+
only = [n.strip() for n in (args.only or "").split(",") if n.strip()]
|
|
6583
|
+
out = backup.restore(passphrase, only=only or None)
|
|
6584
|
+
print(f"[OK] Restored {len(out['restored'])} value(s)"
|
|
6585
|
+
+ (f": {', '.join(out['restored'])}" if out["restored"] else "."))
|
|
6586
|
+
for label, key in (("still in the keychain, left alone", "present"),
|
|
6587
|
+
("entry or project gone, skipped", "orphaned"),
|
|
6588
|
+
("failed", "failed")):
|
|
6589
|
+
if out[key]:
|
|
6590
|
+
print(f" {label}: {', '.join(out[key])}")
|
|
6591
|
+
if out["restored"]:
|
|
6592
|
+
_creds_log_restore(out["restored"])
|
|
6593
|
+
else: # passphrase
|
|
6594
|
+
old = _creds_read_passphrase("Current passphrase: ")
|
|
6595
|
+
new = _creds_read_passphrase(
|
|
6596
|
+
f"New passphrase (min {backup.MIN_PASSPHRASE} chars): ", confirm=True)
|
|
6597
|
+
if old and new:
|
|
6598
|
+
backup.change_passphrase(old, new)
|
|
6599
|
+
print("[OK] Backup passphrase changed.")
|
|
6600
|
+
except backup.BackupError as exc:
|
|
6601
|
+
print(f"[error] {exc}")
|
|
6602
|
+
|
|
6603
|
+
|
|
6604
|
+
def _creds_log_restore(names: list) -> None:
|
|
6605
|
+
"""Names only, to the global activity log that `c3 creds audit` reads."""
|
|
6606
|
+
from services import credential_store as cred_store
|
|
6607
|
+
from services.activity_log import ActivityLog
|
|
6608
|
+
home = cred_store.global_base()
|
|
6609
|
+
if home is not None:
|
|
6610
|
+
ActivityLog(str(home)).log("cred_action", {
|
|
6611
|
+
"kind": "creds", "action": "restore", "names": names, "via": "cli"})
|
|
6502
6612
|
|
|
6503
6613
|
|
|
6504
6614
|
def _creds_count_show(refs, project_path: str) -> None:
|
|
@@ -6575,8 +6685,17 @@ def _creds_cmd_list(args, project_path: str) -> None:
|
|
|
6575
6685
|
"(add --global for all projects).")
|
|
6576
6686
|
return
|
|
6577
6687
|
print(f"{len(entries)} credential(s) — project scope shadows global:")
|
|
6688
|
+
missing = 0
|
|
6578
6689
|
for name, entry in entries.items():
|
|
6579
|
-
|
|
6690
|
+
gone = not cred_store.is_resolvable(
|
|
6691
|
+
name, project_path=project_path, scope=entry["scope"])
|
|
6692
|
+
missing += gone
|
|
6693
|
+
print(" " + _creds_entry_line(name, entry, gone))
|
|
6694
|
+
if missing:
|
|
6695
|
+
print(f"\n{missing} entr{'y has' if missing == 1 else 'ies have'} no stored "
|
|
6696
|
+
"value (the OS keychain no longer holds it). Re-enter with "
|
|
6697
|
+
"`c3 creds set NAME` (add --global for global entries); the "
|
|
6698
|
+
"entry keeps its env var, description and flags.")
|
|
6580
6699
|
|
|
6581
6700
|
|
|
6582
6701
|
def _creds_cmd_rm(args, project_path: str) -> None:
|
|
@@ -520,16 +520,21 @@ def build_parser(version: str, parse_cli_ide_arg):
|
|
|
520
520
|
cr_set.add_argument("name", help="Entry name (env-var safe: [A-Za-z_][A-Za-z0-9_]*)")
|
|
521
521
|
cr_set.add_argument("--value", default="", help="Secret value (prompted via getpass if omitted — preferred). Structured types take a JSON object of fields")
|
|
522
522
|
cr_set.add_argument("--stdin", action="store_true", help="Read the value from stdin (piped/multiline values)")
|
|
523
|
+
# Every metadata option defaults to None = keep what an existing entry
|
|
524
|
+
# has, so re-entering a value does not reset its settings.
|
|
523
525
|
cr_set.add_argument("--type", dest="ctype",
|
|
524
526
|
choices=["token", "env", "multiline",
|
|
525
527
|
"address", "identity", "card", "login"],
|
|
526
|
-
default=
|
|
527
|
-
help="Entry type;
|
|
528
|
+
default=None,
|
|
529
|
+
help="Entry type (default: keep the entry's type; token for a new one); "
|
|
530
|
+
"address/identity/card/login are structured "
|
|
528
531
|
"(field payload, inject-only, never revealable to the agent)")
|
|
529
|
-
cr_set.add_argument("--desc", default=
|
|
530
|
-
cr_set.add_argument("--env-var", default=
|
|
531
|
-
cr_set.add_argument("--agent-readable", action=
|
|
532
|
-
|
|
532
|
+
cr_set.add_argument("--desc", default=None, help="Human description shown in list/UI (default: keep)")
|
|
533
|
+
cr_set.add_argument("--env-var", default=None, help="Env var name used at injection (default: keep; entry name for a new one)")
|
|
534
|
+
cr_set.add_argument("--agent-readable", action=argparse.BooleanOptionalAction, default=None,
|
|
535
|
+
help="Allow the agent to reveal the decoded value into its context (default: keep; injection-only for a new one)")
|
|
536
|
+
cr_set.add_argument("--inject", action=argparse.BooleanOptionalAction, default=None,
|
|
537
|
+
help="Auto-inject into every c3_shell run (default: keep; off for a new one)")
|
|
533
538
|
cr_set.add_argument("--global", dest="use_global", action="store_true", help="Store in the global scope (~/.c3) so every C3 project can use it")
|
|
534
539
|
# --path (not a trailing positional): a second positional after options
|
|
535
540
|
# breaks argparse on py<3.12 ("unrecognized arguments").
|
|
@@ -578,6 +583,16 @@ def build_parser(version: str, parse_cli_ide_arg):
|
|
|
578
583
|
cr_audit.add_argument("--json", dest="as_json", action="store_true", help="Emit raw JSON")
|
|
579
584
|
cr_audit.add_argument("--path", dest="project_path", default=".", help="Project directory (default: current)")
|
|
580
585
|
|
|
586
|
+
cr_backup = creds_subs.add_parser(
|
|
587
|
+
"backup", help="Passphrase-locked copy of every value that survives an OS keychain wipe")
|
|
588
|
+
cr_backup.add_argument(
|
|
589
|
+
"backup_cmd", choices=["init", "status", "sync", "restore", "passphrase"],
|
|
590
|
+
help="init: turn it on (asks for a passphrase) · status · sync: copy every live "
|
|
591
|
+
"value now · restore: put lost values back (asks for the passphrase) · "
|
|
592
|
+
"passphrase: change it")
|
|
593
|
+
cr_backup.add_argument("--only", default="", help="restore: comma-separated names (default: all lost values)")
|
|
594
|
+
cr_backup.add_argument("--path", dest="project_path", default=".", help="Project directory (default: current)")
|
|
595
|
+
|
|
581
596
|
# ── Agent Locks (docs/agent-locks.md) ───────────────────────────────
|
|
582
597
|
# force-release is human-only: it bumps the fencing counter so a holder
|
|
583
598
|
# that comes back is stale by construction. Agents get c3_locks instead,
|
|
@@ -125,6 +125,7 @@ _WRITE_CLASS_ALWAYS = frozenset({"Edit", "Write", "MultiEdit"})
|
|
|
125
125
|
# Mirrors services.credential_store.VAULT_PROTECTED_FILES (parity-tested);
|
|
126
126
|
# duplicated because hooks must stay import-light.
|
|
127
127
|
_VAULT_FILES = frozenset({"config.json", "secrets.enc", "cred_state.json",
|
|
128
|
+
"vault_backup.json",
|
|
128
129
|
"cred_usage.jsonl", "cred_usage.jsonl.1"})
|
|
129
130
|
|
|
130
131
|
# Redirect messages per native tool
|
|
@@ -2016,7 +2016,8 @@ def api_projects_config_get():
|
|
|
2016
2016
|
# returned by any hub route (no reveal exists here). `credentials` stays out of
|
|
2017
2017
|
# _CONFIG_WRITE_SECTIONS — these dedicated routes are the only hub write path.
|
|
2018
2018
|
|
|
2019
|
-
def _cred_entry_public(name, entry, *, usage=None, shadows_global=None
|
|
2019
|
+
def _cred_entry_public(name, entry, *, usage=None, shadows_global=None,
|
|
2020
|
+
value_ok=None):
|
|
2020
2021
|
"""Explicit allowlist serializer — structurally cannot emit a value.
|
|
2021
2022
|
|
|
2022
2023
|
Delegates to credential_store.public_entry so the hub, the per-project UI
|
|
@@ -2024,7 +2025,8 @@ def _cred_entry_public(name, entry, *, usage=None, shadows_global=None):
|
|
|
2024
2025
|
is exactly the drift the write-only wire contract cannot survive."""
|
|
2025
2026
|
from services import credential_store as cred_store
|
|
2026
2027
|
return cred_store.public_entry(
|
|
2027
|
-
name, entry, usage=usage, shadows_global=shadows_global
|
|
2028
|
+
name, entry, usage=usage, shadows_global=shadows_global,
|
|
2029
|
+
value_ok=value_ok)
|
|
2028
2030
|
|
|
2029
2031
|
|
|
2030
2032
|
def _resolve_cred_target(path: str, scope: str, *, mutation: bool):
|
|
@@ -2141,7 +2143,9 @@ def api_projects_credentials():
|
|
|
2141
2143
|
entries.append(_cred_entry_public(
|
|
2142
2144
|
name, entry, usage=usage,
|
|
2143
2145
|
shadows_global=(entry.get("scope") == "project"
|
|
2144
|
-
and name in global_names)
|
|
2146
|
+
and name in global_names),
|
|
2147
|
+
value_ok=cred_store.is_resolvable(
|
|
2148
|
+
name, project_path=str(resolved), scope=entry["scope"])))
|
|
2145
2149
|
return jsonify({"path": str(resolved), "entries": entries})
|
|
2146
2150
|
|
|
2147
2151
|
|
|
@@ -2162,29 +2166,15 @@ def api_projects_credentials_set():
|
|
|
2162
2166
|
value = data.get("value")
|
|
2163
2167
|
# Structured kinds submit a field OBJECT; the store takes JSON text.
|
|
2164
2168
|
value = json.dumps(value) if isinstance(value, dict) else str(value or "")
|
|
2165
|
-
|
|
2169
|
+
meta = cred_store.payload_meta(data)
|
|
2166
2170
|
try:
|
|
2167
2171
|
if value:
|
|
2168
2172
|
entry = cred_store.set_credential(
|
|
2169
|
-
name, value, scope=scope, project_path=store_path,
|
|
2170
|
-
|
|
2171
|
-
env_var=str(data.get("env_var") or ""),
|
|
2172
|
-
agent_readable=bool(data.get("agent_readable")),
|
|
2173
|
-
inject=bool(data.get("inject")))
|
|
2173
|
+
name, value, scope=scope, project_path=store_path,
|
|
2174
|
+
ctype=meta.pop("type", None), **meta)
|
|
2174
2175
|
else:
|
|
2175
|
-
# Metadata-only update: touch ONLY the keys present in the payload
|
|
2176
|
-
# so a single-field toggle can't clobber the others.
|
|
2177
|
-
fields = {}
|
|
2178
|
-
for key in ("description", "env_var"):
|
|
2179
|
-
if key in data:
|
|
2180
|
-
fields[key] = str(data[key] or "")
|
|
2181
|
-
for key in ("agent_readable", "inject"):
|
|
2182
|
-
if key in data:
|
|
2183
|
-
fields[key] = bool(data[key])
|
|
2184
|
-
if "type" in data or "ctype" in data:
|
|
2185
|
-
fields["type"] = ctype
|
|
2186
2176
|
entry = cred_store.update_metadata(
|
|
2187
|
-
name, scope=scope, project_path=store_path, **
|
|
2177
|
+
name, scope=scope, project_path=store_path, **meta)
|
|
2188
2178
|
except cred_store.CredentialError as exc:
|
|
2189
2179
|
return jsonify({"error": str(exc)}), 400
|
|
2190
2180
|
except RuntimeError as exc:
|
|
@@ -2443,7 +2433,9 @@ def api_hub_credentials_overview():
|
|
|
2443
2433
|
continue
|
|
2444
2434
|
row["entries"].append(_cred_entry_public(
|
|
2445
2435
|
name, entry, usage=usage,
|
|
2446
|
-
shadows_global=name in global_entries
|
|
2436
|
+
shadows_global=name in global_entries,
|
|
2437
|
+
value_ok=cred_store.is_resolvable(
|
|
2438
|
+
name, project_path=ppath, scope="project")))
|
|
2447
2439
|
if name in shadowed_in:
|
|
2448
2440
|
shadowed_in[name].append(
|
|
2449
2441
|
{"name": row["name"], "path": ppath})
|
|
@@ -2452,11 +2444,27 @@ def api_hub_credentials_overview():
|
|
|
2452
2444
|
projects_out.append(row)
|
|
2453
2445
|
global_usage = cred_store.read_usage_state(str(home)) if home else {}
|
|
2454
2446
|
global_out = [
|
|
2455
|
-
{**_cred_entry_public(
|
|
2447
|
+
{**_cred_entry_public(
|
|
2448
|
+
name, entry, usage=global_usage,
|
|
2449
|
+
value_ok=cred_store.is_resolvable(
|
|
2450
|
+
name, project_path=str(home), scope="global")),
|
|
2456
2451
|
"shadowed_in": shadowed_in.get(name, [])}
|
|
2457
2452
|
for name, entry in global_entries.items()
|
|
2458
2453
|
]
|
|
2459
|
-
return jsonify({"global": {"entries": global_out}, "projects": projects_out
|
|
2454
|
+
return jsonify({"global": {"entries": global_out}, "projects": projects_out,
|
|
2455
|
+
"backup": _cred_backup_summary(
|
|
2456
|
+
[row["path"] for row in projects_out if row["initialized"]])})
|
|
2457
|
+
|
|
2458
|
+
|
|
2459
|
+
def _cred_backup_summary(project_paths) -> dict:
|
|
2460
|
+
"""Backup state as counts for the Hub banner; a broken file reports its error."""
|
|
2461
|
+
from services import credential_backup
|
|
2462
|
+
try:
|
|
2463
|
+
st = credential_backup.status(project_paths)
|
|
2464
|
+
except credential_backup.BackupError as exc:
|
|
2465
|
+
return {"enabled": True, "error": str(exc), "restorable": 0, "lost": 0}
|
|
2466
|
+
return {"enabled": st["enabled"], "restorable": len(st["restorable"]),
|
|
2467
|
+
"lost": len(st["lost"]), "not_backed_up": len(st["not_backed_up"])}
|
|
2460
2468
|
|
|
2461
2469
|
|
|
2462
2470
|
#: Bulk actions may only ever REDUCE what a credential is exposed to.
|
|
@@ -1197,6 +1197,11 @@ function CredRow({ entry, striped, owner, onOpen, onMenu, check,
|
|
|
1197
1197
|
<div style={{ display: 'flex', alignItems: 'center', flexWrap: 'wrap', gap: 7 }}>
|
|
1198
1198
|
<span className="mono" style={{ fontWeight: 600, color: T.text, fontSize: 12.5 }}>{entry.name}</span>
|
|
1199
1199
|
<Badge color={entry.scope === 'global' ? T.accent : T.blue}>{entry.scope}</Badge>
|
|
1200
|
+
{!!entry.value_missing && (
|
|
1201
|
+
<span title="Registered, but the OS keychain no longer holds its value — injecting it fails. Replace the secret to restore it.">
|
|
1202
|
+
<Badge color={T.error}>value missing</Badge>
|
|
1203
|
+
</span>
|
|
1204
|
+
)}
|
|
1200
1205
|
{!!entry.shadows_global && (
|
|
1201
1206
|
<span title="This project's value wins over the global entry of the same name">
|
|
1202
1207
|
<Badge color={T.warn}>overrides global</Badge>
|
|
@@ -2074,6 +2079,7 @@ function CredSearchResults({ groups, total, selected, setSelected, onOpen, onMen
|
|
|
2074
2079
|
minWidth: 150, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
|
|
2075
2080
|
}}>{def.projectName}</span>
|
|
2076
2081
|
<Badge color={e.scope === 'global' ? T.accent : T.blue}>{e.scope}</Badge>
|
|
2082
|
+
{!!e.value_missing && <Badge color={T.error}>value missing</Badge>}
|
|
2077
2083
|
{!!e.shadows_global && <Badge color={T.warn}>overrides global</Badge>}
|
|
2078
2084
|
<span className="mono" style={{ fontSize: 11, color: T.textDim }}>
|
|
2079
2085
|
{e.type || 'token'} · ••••{e.value_len}
|
|
@@ -2287,6 +2293,18 @@ function HubCredentials({ projects, onOpenDrill }) {
|
|
|
2287
2293
|
const totalProjEntries = ((ov || {}).projects || []).reduce((n, r) => n + (r.entries || []).length, 0);
|
|
2288
2294
|
const globalCount = ((((ov || {}).global) || {}).entries || []).length;
|
|
2289
2295
|
|
|
2296
|
+
// Restore and init read a passphrase from the keyboard, so they stay
|
|
2297
|
+
// terminal commands; the Hub only says which one is needed.
|
|
2298
|
+
const bk = (ov || {}).backup;
|
|
2299
|
+
const backupNote = !bk ? null
|
|
2300
|
+
: bk.restorable > 0 ? { tone: T.error, cmd: 'c3 creds backup restore',
|
|
2301
|
+
text: `${bk.restorable} credential${bk.restorable === 1 ? '' : 's'} lost ${bk.restorable === 1 ? 'its value' : 'their values'} in the OS keychain and can be restored from the vault backup.` }
|
|
2302
|
+
: bk.lost > 0 ? { tone: T.error, cmd: '',
|
|
2303
|
+
text: `${bk.lost} credential${bk.lost === 1 ? ' has' : 's have'} no stored value and no backup copy — replace each secret marked "value missing".` }
|
|
2304
|
+
: !bk.enabled ? { tone: T.warn, cmd: 'c3 creds backup init',
|
|
2305
|
+
text: 'No vault backup: values live only in the OS keychain, which Windows can empty on a restart.' }
|
|
2306
|
+
: null;
|
|
2307
|
+
|
|
2290
2308
|
return (
|
|
2291
2309
|
<div className="fade-up" style={{ maxWidth: 1100 }}>
|
|
2292
2310
|
<div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 10 }}>
|
|
@@ -2308,6 +2326,20 @@ function HubCredentials({ projects, onOpenDrill }) {
|
|
|
2308
2326
|
}}><I name="refresh" size={12} /> Refresh</button>
|
|
2309
2327
|
</div>
|
|
2310
2328
|
|
|
2329
|
+
{backupNote && (
|
|
2330
|
+
<div style={{
|
|
2331
|
+
display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap',
|
|
2332
|
+
marginBottom: 10, padding: '8px 12px', fontSize: 12, color: T.text,
|
|
2333
|
+
border: `1px solid ${T.border}`, borderLeft: `3px solid ${backupNote.tone}`,
|
|
2334
|
+
borderRadius: 6, background: T.surfaceAlt,
|
|
2335
|
+
}}>
|
|
2336
|
+
<span>{backupNote.text}</span>
|
|
2337
|
+
{backupNote.cmd && (
|
|
2338
|
+
<span>In a terminal: <span className="mono" style={{ color: backupNote.tone }}>{backupNote.cmd}</span></span>
|
|
2339
|
+
)}
|
|
2340
|
+
</div>
|
|
2341
|
+
)}
|
|
2342
|
+
|
|
2311
2343
|
{/* Cross-project search — always visible, above the sub-tabs */}
|
|
2312
2344
|
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 8, flexWrap: 'wrap' }}>
|
|
2313
2345
|
<div style={{
|
|
@@ -2766,7 +2766,10 @@ def api_credentials_list():
|
|
|
2766
2766
|
usage = cred_store.read_usage_state(pp)
|
|
2767
2767
|
out = []
|
|
2768
2768
|
for name, entry in cred_store.list_entries(pp).items():
|
|
2769
|
-
out.append(cred_store.public_entry(
|
|
2769
|
+
out.append(cred_store.public_entry(
|
|
2770
|
+
name, entry, usage=usage,
|
|
2771
|
+
value_ok=cred_store.is_resolvable(
|
|
2772
|
+
name, project_path=pp, scope=entry["scope"])))
|
|
2770
2773
|
return jsonify({"entries": out})
|
|
2771
2774
|
|
|
2772
2775
|
|
|
@@ -2781,32 +2784,15 @@ def api_credentials_set():
|
|
|
2781
2784
|
value = data.get("value")
|
|
2782
2785
|
# Structured kinds submit a field OBJECT; the store takes JSON text.
|
|
2783
2786
|
value = json.dumps(value) if isinstance(value, dict) else str(value or "")
|
|
2784
|
-
|
|
2785
|
-
meta = {
|
|
2786
|
-
"description": str(data.get("description") or ""),
|
|
2787
|
-
"env_var": str(data.get("env_var") or ""),
|
|
2788
|
-
"agent_readable": bool(data.get("agent_readable")),
|
|
2789
|
-
"inject": bool(data.get("inject")),
|
|
2790
|
-
}
|
|
2787
|
+
meta = cred_store.payload_meta(data)
|
|
2791
2788
|
try:
|
|
2792
2789
|
if value:
|
|
2793
2790
|
entry = cred_store.set_credential(
|
|
2794
2791
|
name, value, scope=scope, project_path=str(PROJECT_PATH),
|
|
2795
|
-
ctype=
|
|
2792
|
+
ctype=meta.pop("type", None), **meta)
|
|
2796
2793
|
else:
|
|
2797
|
-
# Metadata-only update: touch ONLY the keys present in the payload
|
|
2798
|
-
# so a single-field toggle can't clobber the others.
|
|
2799
|
-
fields = {}
|
|
2800
|
-
for key in ("description", "env_var"):
|
|
2801
|
-
if key in data:
|
|
2802
|
-
fields[key] = str(data[key] or "")
|
|
2803
|
-
for key in ("agent_readable", "inject"):
|
|
2804
|
-
if key in data:
|
|
2805
|
-
fields[key] = bool(data[key])
|
|
2806
|
-
if "type" in data or "ctype" in data:
|
|
2807
|
-
fields["type"] = ctype
|
|
2808
2794
|
entry = cred_store.update_metadata(
|
|
2809
|
-
name, scope=scope, project_path=str(PROJECT_PATH), **
|
|
2795
|
+
name, scope=scope, project_path=str(PROJECT_PATH), **meta)
|
|
2810
2796
|
except cred_store.CredentialError as exc:
|
|
2811
2797
|
return jsonify({"error": str(exc)}), 400
|
|
2812
2798
|
except RuntimeError as exc:
|
|
@@ -64,7 +64,8 @@ def _log_access(svc, action: str, name: str, scope: str, response: str) -> None:
|
|
|
64
64
|
pass
|
|
65
65
|
|
|
66
66
|
|
|
67
|
-
def _format_entry_line(name: str, entry: dict, usage: dict
|
|
67
|
+
def _format_entry_line(name: str, entry: dict, usage: dict,
|
|
68
|
+
missing: bool = False) -> str:
|
|
68
69
|
flags = []
|
|
69
70
|
if entry.get("inject"):
|
|
70
71
|
flags.append("inject")
|
|
@@ -73,7 +74,7 @@ def _format_entry_line(name: str, entry: dict, usage: dict) -> str:
|
|
|
73
74
|
last_used = (usage.get(name) or {}).get("last_used", "")
|
|
74
75
|
parts = [
|
|
75
76
|
f"{name} [{entry.get('scope', '?')}/{entry.get('type', 'token')}]",
|
|
76
|
-
f"len={entry.get('value_len', '?')}",
|
|
77
|
+
"VALUE MISSING" if missing else f"len={entry.get('value_len', '?')}",
|
|
77
78
|
]
|
|
78
79
|
display = entry.get("display") or {}
|
|
79
80
|
if display:
|
|
@@ -97,8 +98,22 @@ def _act_list(project_path: str) -> str:
|
|
|
97
98
|
"The user manages them via the Credentials UI tab or `c3 creds set`."
|
|
98
99
|
)
|
|
99
100
|
usage = cs.read_usage_state(project_path)
|
|
101
|
+
missing = {n for n, e in entries.items() if not cs.is_resolvable(
|
|
102
|
+
n, project_path=project_path, scope=e["scope"])}
|
|
100
103
|
lines = [f"[creds] {len(entries)} entries (project scope shadows global):"]
|
|
101
|
-
lines += [_format_entry_line(n, e, usage
|
|
104
|
+
lines += [_format_entry_line(n, e, usage, n in missing)
|
|
105
|
+
for n, e in entries.items()]
|
|
106
|
+
if missing:
|
|
107
|
+
from services import credential_backup
|
|
108
|
+
way_back = ("The user restores them in a terminal with `c3 creds backup "
|
|
109
|
+
"restore` (it asks for the backup passphrase)"
|
|
110
|
+
if credential_backup.is_enabled() else
|
|
111
|
+
"No vault backup is configured; the user re-enters them "
|
|
112
|
+
"(Credentials UI or `c3 creds set`)")
|
|
113
|
+
lines.append(
|
|
114
|
+
f"[creds:value-missing] {len(missing)} registered entries have no "
|
|
115
|
+
"stored value (the OS keychain no longer holds it); injecting them "
|
|
116
|
+
f"fails. {way_back}.")
|
|
102
117
|
lines.append(_USAGE_FOOTER)
|
|
103
118
|
return "\n".join(lines)
|
|
104
119
|
|
|
@@ -384,15 +399,17 @@ def handle_credentials(action: str, svc, finalize, **kwargs) -> str:
|
|
|
384
399
|
"(Credentials UI or `c3 creds set --agent-readable`)."
|
|
385
400
|
)
|
|
386
401
|
else:
|
|
402
|
+
# Empty/false arguments mean "not given": the entry keeps
|
|
403
|
+
# its current settings rather than resetting to defaults.
|
|
387
404
|
entry = cs.set_credential(
|
|
388
405
|
name, value,
|
|
389
406
|
scope=scope,
|
|
390
407
|
project_path=project_path,
|
|
391
|
-
description=kwargs.get("description") or
|
|
392
|
-
ctype=kwargs.get("ctype") or
|
|
393
|
-
env_var=kwargs.get("env_var") or
|
|
394
|
-
agent_readable=want_readable,
|
|
395
|
-
inject=
|
|
408
|
+
description=kwargs.get("description") or None,
|
|
409
|
+
ctype=kwargs.get("ctype") or None,
|
|
410
|
+
env_var=kwargs.get("env_var") or None,
|
|
411
|
+
agent_readable=True if want_readable else None,
|
|
412
|
+
inject=True if kwargs.get("inject") else None,
|
|
396
413
|
)
|
|
397
414
|
resp = (
|
|
398
415
|
f"[creds:set] {name} (scope={scope}, "
|
{code_context_control-2.143.0 → code_context_control-2.145.0}/cli/ui/components/credentials.js
RENAMED
|
@@ -753,6 +753,7 @@ const CredentialsPanel = () => {
|
|
|
753
753
|
{entry.name}
|
|
754
754
|
</span>
|
|
755
755
|
<Badge color={entry.scope === "global" ? T.accent : T.blue}>{entry.scope}</Badge>
|
|
756
|
+
{!!entry.value_missing && <Badge color={T.error}>value missing</Badge>}
|
|
756
757
|
<Badge color={T.textMuted}>{entry.type || "token"}</Badge>
|
|
757
758
|
{CREDS_STRUCTURED[entry.type] ? (
|
|
758
759
|
<span className="mono" style={{ color: T.text }}>
|
{code_context_control-2.143.0 → code_context_control-2.145.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.145.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
|
|
@@ -44,6 +44,7 @@ Requires-Dist: rich>=13.0.0
|
|
|
44
44
|
Requires-Dist: click>=8.0.0
|
|
45
45
|
Requires-Dist: pyyaml>=6.0.0
|
|
46
46
|
Requires-Dist: keyring>=24.0
|
|
47
|
+
Requires-Dist: cryptography>=41.0
|
|
47
48
|
Provides-Extra: vector
|
|
48
49
|
Requires-Dist: scikit-learn>=1.3.0; extra == "vector"
|
|
49
50
|
Requires-Dist: numpy>=1.24.0; extra == "vector"
|
|
@@ -226,6 +226,7 @@ services/context_snapshot.py
|
|
|
226
226
|
services/conversation_store.py
|
|
227
227
|
services/cred_audit.py
|
|
228
228
|
services/cred_telemetry.py
|
|
229
|
+
services/credential_backup.py
|
|
229
230
|
services/credential_store.py
|
|
230
231
|
services/delegate_agents.py
|
|
231
232
|
services/delegate_hints.py
|
|
@@ -362,6 +363,7 @@ tests/test_confirm_guard_wiring.py
|
|
|
362
363
|
tests/test_cooccurrence_bounds.py
|
|
363
364
|
tests/test_cred_audit.py
|
|
364
365
|
tests/test_cred_telemetry.py
|
|
366
|
+
tests/test_credential_backup.py
|
|
365
367
|
tests/test_credential_login_kind.py
|
|
366
368
|
tests/test_credential_store.py
|
|
367
369
|
tests/test_credential_ui_parity.py
|
|
@@ -1571,26 +1571,18 @@ def mobile_credentials_set():
|
|
|
1571
1571
|
"needs_confirmation": True, "confirm_with": name,
|
|
1572
1572
|
}), 400
|
|
1573
1573
|
|
|
1574
|
+
meta = cred_store.payload_meta(data)
|
|
1574
1575
|
try:
|
|
1575
1576
|
if value:
|
|
1577
|
+
# ctype stays explicit here: "keep the existing type" would let a
|
|
1578
|
+
# phone write field JSON into a structured entry.
|
|
1579
|
+
meta.pop("type", None)
|
|
1576
1580
|
entry = cred_store.set_credential(
|
|
1577
|
-
name, value, scope=scope, project_path=store_path,
|
|
1578
|
-
|
|
1579
|
-
env_var=str(data.get("env_var") or ""),
|
|
1580
|
-
agent_readable=wants_readable,
|
|
1581
|
-
inject=bool(data.get("inject")))
|
|
1581
|
+
name, value, scope=scope, project_path=store_path,
|
|
1582
|
+
ctype=ctype, **meta)
|
|
1582
1583
|
else:
|
|
1583
|
-
fields = {}
|
|
1584
|
-
for key in ("description", "env_var"):
|
|
1585
|
-
if key in data:
|
|
1586
|
-
fields[key] = str(data[key] or "")
|
|
1587
|
-
for key in ("agent_readable", "inject"):
|
|
1588
|
-
if key in data:
|
|
1589
|
-
fields[key] = bool(data[key])
|
|
1590
|
-
if "type" in data or "ctype" in data:
|
|
1591
|
-
fields["type"] = ctype
|
|
1592
1584
|
entry = cred_store.update_metadata(
|
|
1593
|
-
name, scope=scope, project_path=store_path, **
|
|
1585
|
+
name, scope=scope, project_path=store_path, **meta)
|
|
1594
1586
|
except cred_store.CredentialError as exc:
|
|
1595
1587
|
return jsonify({"error": str(exc)}), 400
|
|
1596
1588
|
except (ValueError, RuntimeError) as exc:
|