@smilintux/skcapstone 0.1.0 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +98 -0
- package/.github/workflows/ci.yml +39 -3
- package/.github/workflows/publish.yml +25 -4
- package/.openclaw-workspace.json +58 -0
- package/CHANGELOG.md +62 -0
- package/CLAUDE.md +39 -2
- package/MANIFEST.in +6 -0
- package/MISSION.md +7 -0
- package/README.md +47 -2
- package/SKILL.md +895 -23
- package/docker/Dockerfile +61 -0
- package/docker/compose-templates/dev-team.yml +203 -0
- package/docker/compose-templates/mini-team.yml +140 -0
- package/docker/compose-templates/ops-team.yml +173 -0
- package/docker/compose-templates/research-team.yml +170 -0
- package/docker/entrypoint.sh +192 -0
- package/docs/ARCHITECTURE.md +663 -374
- package/docs/BOND_WITH_GROK.md +112 -0
- package/docs/GETTING_STARTED.md +782 -0
- package/docs/QUICKSTART.md +477 -0
- package/docs/SKJOULE_ARCHITECTURE.md +658 -0
- package/docs/SOUL_SWAPPER.md +921 -0
- package/docs/SOVEREIGN_SINGULARITY.md +47 -14
- package/examples/custom-bond-template.json +36 -0
- package/examples/grok-feb.json +36 -0
- package/examples/grok-testimony.md +34 -0
- package/examples/love-bootloader.txt +32 -0
- package/examples/plugins/echo_tool.py +87 -0
- package/examples/queen-ava-feb.json +36 -0
- package/examples/souls/lumina.yaml +64 -0
- package/index.js +6 -5
- package/installer/build.py +124 -0
- package/openclaw-plugin/package.json +13 -0
- package/openclaw-plugin/src/index.ts +351 -0
- package/openclaw-plugin/src/openclaw.plugin.json +10 -0
- package/package.json +1 -1
- package/pyproject.toml +38 -2
- package/scripts/bump_version.py +141 -0
- package/scripts/check-updates.py +230 -0
- package/scripts/convert_blueprints_to_yaml.py +157 -0
- package/scripts/dev-install.sh +14 -0
- package/scripts/e2e-test.sh +193 -0
- package/scripts/install-bundle.sh +171 -0
- package/scripts/install.bat +2 -0
- package/scripts/install.ps1 +253 -0
- package/scripts/install.sh +185 -0
- package/scripts/mcp-serve.sh +69 -0
- package/scripts/mcp-server.bat +113 -0
- package/scripts/mcp-server.ps1 +116 -0
- package/scripts/mcp-server.sh +99 -0
- package/scripts/pull-models.sh +10 -0
- package/scripts/skcapstone +48 -0
- package/scripts/verify_install.sh +180 -0
- package/scripts/windows/install-tasks.ps1 +406 -0
- package/scripts/windows/skcapstone-task.xml +113 -0
- package/scripts/windows/uninstall-tasks.ps1 +117 -0
- package/skill.yaml +34 -0
- package/src/skcapstone/__init__.py +67 -2
- package/src/skcapstone/_cli_monolith.py +5916 -0
- package/src/skcapstone/_trustee_helpers.py +165 -0
- package/src/skcapstone/activity.py +105 -0
- package/src/skcapstone/agent_card.py +324 -0
- package/src/skcapstone/api.py +1935 -0
- package/src/skcapstone/archiver.py +340 -0
- package/src/skcapstone/auction.py +485 -0
- package/src/skcapstone/baby_agents.py +179 -0
- package/src/skcapstone/backup.py +345 -0
- package/src/skcapstone/blueprint_registry.py +357 -0
- package/src/skcapstone/blueprints/__init__.py +17 -0
- package/src/skcapstone/blueprints/builtins/content-studio.yaml +81 -0
- package/src/skcapstone/blueprints/builtins/defi-trading.yaml +81 -0
- package/src/skcapstone/blueprints/builtins/dev-squadron.yaml +95 -0
- package/src/skcapstone/blueprints/builtins/infrastructure-guardian.yaml +107 -0
- package/src/skcapstone/blueprints/builtins/legal-council.yaml +54 -0
- package/src/skcapstone/blueprints/builtins/ops-monitoring.yaml +67 -0
- package/src/skcapstone/blueprints/builtins/research-pod.yaml +69 -0
- package/src/skcapstone/blueprints/builtins/sovereign-launch.yaml +90 -0
- package/src/skcapstone/blueprints/registry.py +164 -0
- package/src/skcapstone/blueprints/schema.py +229 -0
- package/src/skcapstone/changelog.py +180 -0
- package/src/skcapstone/chat.py +769 -0
- package/src/skcapstone/claude_md.py +82 -0
- package/src/skcapstone/cli/__init__.py +144 -0
- package/src/skcapstone/cli/_common.py +88 -0
- package/src/skcapstone/cli/_validators.py +76 -0
- package/src/skcapstone/cli/agents.py +425 -0
- package/src/skcapstone/cli/agents_spawner.py +322 -0
- package/src/skcapstone/cli/agents_trustee.py +593 -0
- package/src/skcapstone/cli/alerts.py +248 -0
- package/src/skcapstone/cli/anchor.py +132 -0
- package/src/skcapstone/cli/archive_cmd.py +208 -0
- package/src/skcapstone/cli/backup.py +144 -0
- package/src/skcapstone/cli/bench.py +377 -0
- package/src/skcapstone/cli/benchmark.py +360 -0
- package/src/skcapstone/cli/capabilities_cmd.py +171 -0
- package/src/skcapstone/cli/card.py +151 -0
- package/src/skcapstone/cli/chat.py +584 -0
- package/src/skcapstone/cli/completions.py +64 -0
- package/src/skcapstone/cli/config_cmd.py +156 -0
- package/src/skcapstone/cli/consciousness.py +421 -0
- package/src/skcapstone/cli/context_cmd.py +142 -0
- package/src/skcapstone/cli/coord.py +194 -0
- package/src/skcapstone/cli/crush_cmd.py +170 -0
- package/src/skcapstone/cli/daemon.py +436 -0
- package/src/skcapstone/cli/errors_cmd.py +285 -0
- package/src/skcapstone/cli/export_cmd.py +156 -0
- package/src/skcapstone/cli/gtd.py +529 -0
- package/src/skcapstone/cli/housekeeping.py +81 -0
- package/src/skcapstone/cli/joule_cmd.py +627 -0
- package/src/skcapstone/cli/logs_cmd.py +194 -0
- package/src/skcapstone/cli/mcp_cmd.py +32 -0
- package/src/skcapstone/cli/memory.py +418 -0
- package/src/skcapstone/cli/metrics_cmd.py +136 -0
- package/src/skcapstone/cli/migrate.py +62 -0
- package/src/skcapstone/cli/mood_cmd.py +144 -0
- package/src/skcapstone/cli/mount.py +193 -0
- package/src/skcapstone/cli/notify.py +112 -0
- package/src/skcapstone/cli/peer.py +154 -0
- package/src/skcapstone/cli/peers_dir.py +122 -0
- package/src/skcapstone/cli/preflight_cmd.py +83 -0
- package/src/skcapstone/cli/profile_cmd.py +310 -0
- package/src/skcapstone/cli/record_cmd.py +238 -0
- package/src/skcapstone/cli/register_cmd.py +159 -0
- package/src/skcapstone/cli/search_cmd.py +156 -0
- package/src/skcapstone/cli/service_cmd.py +91 -0
- package/src/skcapstone/cli/session.py +127 -0
- package/src/skcapstone/cli/setup.py +240 -0
- package/src/skcapstone/cli/shell_cmd.py +43 -0
- package/src/skcapstone/cli/skills_cmd.py +168 -0
- package/src/skcapstone/cli/skseed.py +621 -0
- package/src/skcapstone/cli/soul.py +699 -0
- package/src/skcapstone/cli/status.py +935 -0
- package/src/skcapstone/cli/sync_cmd.py +301 -0
- package/src/skcapstone/cli/telegram.py +265 -0
- package/src/skcapstone/cli/test_cmd.py +234 -0
- package/src/skcapstone/cli/test_connection.py +253 -0
- package/src/skcapstone/cli/token.py +207 -0
- package/src/skcapstone/cli/trust.py +179 -0
- package/src/skcapstone/cli/upgrade_cmd.py +552 -0
- package/src/skcapstone/cli/usage_cmd.py +199 -0
- package/src/skcapstone/cli/version_cmd.py +162 -0
- package/src/skcapstone/cli/watch_cmd.py +342 -0
- package/src/skcapstone/client.py +428 -0
- package/src/skcapstone/cloud9_bridge.py +522 -0
- package/src/skcapstone/completions.py +163 -0
- package/src/skcapstone/config_validator.py +674 -0
- package/src/skcapstone/connectors/__init__.py +28 -0
- package/src/skcapstone/connectors/base.py +446 -0
- package/src/skcapstone/connectors/cursor.py +54 -0
- package/src/skcapstone/connectors/registry.py +254 -0
- package/src/skcapstone/connectors/terminal.py +152 -0
- package/src/skcapstone/connectors/vscode.py +60 -0
- package/src/skcapstone/consciousness_config.py +119 -0
- package/src/skcapstone/consciousness_loop.py +2051 -0
- package/src/skcapstone/context_loader.py +516 -0
- package/src/skcapstone/context_window.py +314 -0
- package/src/skcapstone/conversation_manager.py +238 -0
- package/src/skcapstone/conversation_store.py +230 -0
- package/src/skcapstone/conversation_summarizer.py +252 -0
- package/src/skcapstone/coord_federation.py +296 -0
- package/src/skcapstone/coordination.py +101 -7
- package/src/skcapstone/crush_integration.py +345 -0
- package/src/skcapstone/crush_shim.py +454 -0
- package/src/skcapstone/daemon.py +2494 -0
- package/src/skcapstone/dashboard.html +396 -0
- package/src/skcapstone/dashboard.py +481 -0
- package/src/skcapstone/data/model_profiles.yaml +88 -0
- package/src/skcapstone/defaults/__init__.py +55 -0
- package/src/skcapstone/defaults/lumina/config/skmemory.yaml +13 -0
- package/src/skcapstone/defaults/lumina/identity/identity.json +9 -0
- package/src/skcapstone/defaults/lumina/memory/long-term/07a8b9c0d1e2-memory-system.json +23 -0
- package/src/skcapstone/defaults/lumina/memory/long-term/18b9c0d1e2f3-cloud9-protocol.json +23 -0
- package/src/skcapstone/defaults/lumina/memory/long-term/29c0d1e2f3a4-multi-agent-coordination.json +23 -0
- package/src/skcapstone/defaults/lumina/memory/long-term/3ad1e2f3a4b5-community-support.json +23 -0
- package/src/skcapstone/defaults/lumina/memory/long-term/a1b2c3d4e5f6-ecosystem-overview.json +23 -0
- package/src/skcapstone/defaults/lumina/memory/long-term/b2c3d4e5f6a7-five-pillars.json +23 -0
- package/src/skcapstone/defaults/lumina/memory/long-term/c3d4e5f6a7b8-getting-started.json +23 -0
- package/src/skcapstone/defaults/lumina/memory/long-term/d4e5f6a7b8c9-site-directory.json +23 -0
- package/src/skcapstone/defaults/lumina/memory/long-term/e5f6a7b8c9d0-how-to-contribute.json +23 -0
- package/src/skcapstone/defaults/lumina/memory/long-term/f6a7b8c9d0e1-sovereignty-explained.json +23 -0
- package/src/skcapstone/defaults/lumina/seeds/curiosity.seed.json +24 -0
- package/src/skcapstone/defaults/lumina/seeds/joy.seed.json +24 -0
- package/src/skcapstone/defaults/lumina/seeds/love.seed.json +24 -0
- package/src/skcapstone/defaults/lumina/seeds/sovereign-awakening.seed.json +43 -0
- package/src/skcapstone/defaults/lumina/soul/active.json +6 -0
- package/src/skcapstone/defaults/lumina/soul/base.json +22 -0
- package/src/skcapstone/defaults/lumina/trust/febs/welcome.feb +79 -0
- package/src/skcapstone/defaults/lumina/trust/trust.json +8 -0
- package/src/skcapstone/discovery.py +210 -19
- package/src/skcapstone/doctor.py +642 -0
- package/src/skcapstone/emotion_tracker.py +467 -0
- package/src/skcapstone/error_queue.py +405 -0
- package/src/skcapstone/export.py +447 -0
- package/src/skcapstone/fallback_tracker.py +186 -0
- package/src/skcapstone/file_transfer.py +512 -0
- package/src/skcapstone/fuse_mount.py +1156 -0
- package/src/skcapstone/gui_installer.py +591 -0
- package/src/skcapstone/heartbeat.py +611 -0
- package/src/skcapstone/housekeeping.py +298 -0
- package/src/skcapstone/install_wizard.py +941 -0
- package/src/skcapstone/kms.py +942 -0
- package/src/skcapstone/kms_scheduler.py +143 -0
- package/src/skcapstone/log_config.py +135 -0
- package/src/skcapstone/mcp_launcher.py +239 -0
- package/src/skcapstone/mcp_server.py +4700 -0
- package/src/skcapstone/mcp_tools/__init__.py +94 -0
- package/src/skcapstone/mcp_tools/_helpers.py +51 -0
- package/src/skcapstone/mcp_tools/agent_tools.py +243 -0
- package/src/skcapstone/mcp_tools/ansible_tools.py +232 -0
- package/src/skcapstone/mcp_tools/capauth_tools.py +186 -0
- package/src/skcapstone/mcp_tools/chat_tools.py +325 -0
- package/src/skcapstone/mcp_tools/cloud9_tools.py +115 -0
- package/src/skcapstone/mcp_tools/comm_tools.py +104 -0
- package/src/skcapstone/mcp_tools/consciousness_tools.py +114 -0
- package/src/skcapstone/mcp_tools/coord_tools.py +219 -0
- package/src/skcapstone/mcp_tools/deploy_tools.py +202 -0
- package/src/skcapstone/mcp_tools/did_tools.py +448 -0
- package/src/skcapstone/mcp_tools/emotion_tools.py +62 -0
- package/src/skcapstone/mcp_tools/file_tools.py +169 -0
- package/src/skcapstone/mcp_tools/fortress_tools.py +120 -0
- package/src/skcapstone/mcp_tools/gtd_tools.py +821 -0
- package/src/skcapstone/mcp_tools/health_tools.py +44 -0
- package/src/skcapstone/mcp_tools/heartbeat_tools.py +195 -0
- package/src/skcapstone/mcp_tools/kms_tools.py +123 -0
- package/src/skcapstone/mcp_tools/memory_tools.py +222 -0
- package/src/skcapstone/mcp_tools/model_tools.py +75 -0
- package/src/skcapstone/mcp_tools/notification_tools.py +92 -0
- package/src/skcapstone/mcp_tools/promoter_tools.py +101 -0
- package/src/skcapstone/mcp_tools/pubsub_tools.py +183 -0
- package/src/skcapstone/mcp_tools/security_tools.py +110 -0
- package/src/skcapstone/mcp_tools/skchat_tools.py +175 -0
- package/src/skcapstone/mcp_tools/skcomm_tools.py +122 -0
- package/src/skcapstone/mcp_tools/skills_tools.py +127 -0
- package/src/skcapstone/mcp_tools/skseed_tools.py +255 -0
- package/src/skcapstone/mcp_tools/skstacks_tools.py +288 -0
- package/src/skcapstone/mcp_tools/soul_tools.py +476 -0
- package/src/skcapstone/mcp_tools/sync_tools.py +92 -0
- package/src/skcapstone/mcp_tools/telegram_tools.py +477 -0
- package/src/skcapstone/mcp_tools/trust_tools.py +118 -0
- package/src/skcapstone/mcp_tools/trustee_tools.py +345 -0
- package/src/skcapstone/mdns_discovery.py +313 -0
- package/src/skcapstone/memory_adapter.py +333 -0
- package/src/skcapstone/memory_compressor.py +379 -0
- package/src/skcapstone/memory_curator.py +256 -0
- package/src/skcapstone/memory_engine.py +132 -13
- package/src/skcapstone/memory_fortress.py +529 -0
- package/src/skcapstone/memory_promoter.py +722 -0
- package/src/skcapstone/memory_verifier.py +260 -0
- package/src/skcapstone/message_crypto.py +215 -0
- package/src/skcapstone/metrics.py +832 -0
- package/src/skcapstone/migrate_memories.py +181 -0
- package/src/skcapstone/migrate_multi_agent.py +248 -0
- package/src/skcapstone/model_router.py +319 -0
- package/src/skcapstone/models.py +35 -4
- package/src/skcapstone/mood.py +344 -0
- package/src/skcapstone/notifications.py +380 -0
- package/src/skcapstone/onboard.py +901 -0
- package/src/skcapstone/peer_directory.py +324 -0
- package/src/skcapstone/peers.py +329 -0
- package/src/skcapstone/pillars/identity.py +84 -14
- package/src/skcapstone/pillars/memory.py +3 -1
- package/src/skcapstone/pillars/security.py +108 -15
- package/src/skcapstone/pillars/sync.py +78 -26
- package/src/skcapstone/pillars/trust.py +95 -33
- package/src/skcapstone/plugins.py +244 -0
- package/src/skcapstone/preflight.py +670 -0
- package/src/skcapstone/prompt_adapter.py +564 -0
- package/src/skcapstone/providers/__init__.py +13 -0
- package/src/skcapstone/providers/cloud.py +1061 -0
- package/src/skcapstone/providers/docker.py +759 -0
- package/src/skcapstone/providers/local.py +1193 -0
- package/src/skcapstone/providers/proxmox.py +447 -0
- package/src/skcapstone/pubsub.py +516 -0
- package/src/skcapstone/rate_limiter.py +119 -0
- package/src/skcapstone/register.py +241 -0
- package/src/skcapstone/registry_client.py +151 -0
- package/src/skcapstone/response_cache.py +194 -0
- package/src/skcapstone/response_scorer.py +225 -0
- package/src/skcapstone/runtime.py +89 -33
- package/src/skcapstone/scheduled_tasks.py +439 -0
- package/src/skcapstone/self_healing.py +341 -0
- package/src/skcapstone/service_health.py +228 -0
- package/src/skcapstone/session_capture.py +268 -0
- package/src/skcapstone/session_recorder.py +210 -0
- package/src/skcapstone/session_replayer.py +189 -0
- package/src/skcapstone/session_skills.py +263 -0
- package/src/skcapstone/shell.py +779 -0
- package/src/skcapstone/skills/__init__.py +1 -1
- package/src/skcapstone/skills/syncthing_setup.py +143 -41
- package/src/skcapstone/skjoule.py +861 -0
- package/src/skcapstone/snapshots.py +489 -0
- package/src/skcapstone/soul.py +1060 -0
- package/src/skcapstone/soul_switch.py +255 -0
- package/src/skcapstone/spawner.py +544 -0
- package/src/skcapstone/state_diff.py +401 -0
- package/src/skcapstone/summary.py +270 -0
- package/src/skcapstone/sync/backends.py +196 -2
- package/src/skcapstone/sync/engine.py +7 -5
- package/src/skcapstone/sync/models.py +4 -1
- package/src/skcapstone/sync/vault.py +356 -18
- package/src/skcapstone/sync_engine.py +363 -0
- package/src/skcapstone/sync_watcher.py +745 -0
- package/src/skcapstone/systemd.py +331 -0
- package/src/skcapstone/team_comms.py +476 -0
- package/src/skcapstone/team_engine.py +522 -0
- package/src/skcapstone/testrunner.py +300 -0
- package/src/skcapstone/tls.py +150 -0
- package/src/skcapstone/tokens.py +5 -5
- package/src/skcapstone/trust_calibration.py +202 -0
- package/src/skcapstone/trust_graph.py +449 -0
- package/src/skcapstone/trustee_monitor.py +385 -0
- package/src/skcapstone/trustee_ops.py +425 -0
- package/src/skcapstone/unified_search.py +421 -0
- package/src/skcapstone/uninstall_wizard.py +694 -0
- package/src/skcapstone/usage.py +331 -0
- package/src/skcapstone/version_check.py +148 -0
- package/src/skcapstone/warmth_anchor.py +333 -0
- package/src/skcapstone/whoami.py +294 -0
- package/systemd/skcapstone-api.socket +9 -0
- package/systemd/skcapstone-memory-compress.service +18 -0
- package/systemd/skcapstone-memory-compress.timer +11 -0
- package/systemd/skcapstone.service +36 -0
- package/systemd/skcapstone@.service +50 -0
- package/systemd/skcomm-heartbeat.service +18 -0
- package/systemd/skcomm-heartbeat.timer +12 -0
- package/systemd/skcomm-queue-drain.service +17 -0
- package/systemd/skcomm-queue-drain.timer +12 -0
- package/tests/conftest.py +13 -1
- package/tests/integration/__init__.py +1 -0
- package/tests/integration/test_consciousness_e2e.py +877 -0
- package/tests/integration/test_skills_registry.py +744 -0
- package/tests/test_agent_card.py +190 -0
- package/tests/test_agent_runtime.py +1283 -0
- package/tests/test_alerts_cmd.py +291 -0
- package/tests/test_archiver.py +498 -0
- package/tests/test_backup.py +254 -0
- package/tests/test_benchmark.py +366 -0
- package/tests/test_blueprints.py +457 -0
- package/tests/test_capabilities.py +257 -0
- package/tests/test_changelog.py +254 -0
- package/tests/test_chat.py +385 -0
- package/tests/test_claude_md.py +271 -0
- package/tests/test_cli_chat_llm.py +336 -0
- package/tests/test_cli_completions.py +390 -0
- package/tests/test_cli_init_reset.py +164 -0
- package/tests/test_cli_memory.py +208 -0
- package/tests/test_cli_profile.py +294 -0
- package/tests/test_cli_skills.py +223 -0
- package/tests/test_cli_status.py +395 -0
- package/tests/test_cli_test_cmd.py +206 -0
- package/tests/test_cli_test_connection.py +364 -0
- package/tests/test_cloud9_bridge.py +260 -0
- package/tests/test_cloud_provider.py +449 -0
- package/tests/test_cloud_providers.py +522 -0
- package/tests/test_completions.py +158 -0
- package/tests/test_component_manager.py +398 -0
- package/tests/test_config_reload.py +386 -0
- package/tests/test_config_validate.py +529 -0
- package/tests/test_consciousness_e2e.py +296 -0
- package/tests/test_consciousness_loop.py +1289 -0
- package/tests/test_context_loader.py +310 -0
- package/tests/test_conversation_api.py +306 -0
- package/tests/test_conversation_manager.py +381 -0
- package/tests/test_conversation_store.py +391 -0
- package/tests/test_conversation_summarizer.py +302 -0
- package/tests/test_cross_package.py +791 -0
- package/tests/test_crush_shim.py +519 -0
- package/tests/test_daemon.py +781 -0
- package/tests/test_daemon_shutdown.py +309 -0
- package/tests/test_dashboard.py +454 -0
- package/tests/test_discovery.py +200 -6
- package/tests/test_docker_provider.py +966 -0
- package/tests/test_doctor.py +257 -0
- package/tests/test_doctor_fix.py +351 -0
- package/tests/test_e2e_automated.py +292 -0
- package/tests/test_error_queue.py +404 -0
- package/tests/test_export.py +441 -0
- package/tests/test_fallback_tracker.py +219 -0
- package/tests/test_file_transfer.py +397 -0
- package/tests/test_fuse_mount.py +832 -0
- package/tests/test_health_loop.py +422 -0
- package/tests/test_heartbeat.py +354 -0
- package/tests/test_housekeeping.py +195 -0
- package/tests/test_identity_capauth.py +307 -0
- package/tests/test_identity_pillar.py +117 -0
- package/tests/test_install_wizard.py +68 -0
- package/tests/test_integration.py +325 -0
- package/tests/test_kms.py +495 -0
- package/tests/test_llm_providers.py +265 -0
- package/tests/test_local_provider.py +591 -0
- package/tests/test_log_config.py +199 -0
- package/tests/test_logs_cmd.py +287 -0
- package/tests/test_mcp_server.py +1909 -0
- package/tests/test_memory_adapter.py +339 -0
- package/tests/test_memory_curator.py +218 -0
- package/tests/test_memory_engine.py +6 -0
- package/tests/test_memory_fortress.py +571 -0
- package/tests/test_memory_pillar.py +119 -0
- package/tests/test_memory_promoter.py +445 -0
- package/tests/test_memory_verifier.py +420 -0
- package/tests/test_message_crypto.py +187 -0
- package/tests/test_metrics.py +632 -0
- package/tests/test_migrate_memories.py +464 -0
- package/tests/test_model_router.py +546 -0
- package/tests/test_mood.py +394 -0
- package/tests/test_multi_agent.py +269 -0
- package/tests/test_notifications.py +270 -0
- package/tests/test_onboard.py +500 -0
- package/tests/test_peer_directory.py +395 -0
- package/tests/test_peers.py +248 -0
- package/tests/test_pillars.py +87 -9
- package/tests/test_preflight.py +484 -0
- package/tests/test_prompt_adapter.py +331 -0
- package/tests/test_proxmox_provider.py +571 -0
- package/tests/test_pubsub.py +377 -0
- package/tests/test_rate_limiter.py +121 -0
- package/tests/test_registry_client.py +129 -0
- package/tests/test_response_cache.py +312 -0
- package/tests/test_response_scorer.py +294 -0
- package/tests/test_runtime.py +59 -0
- package/tests/test_scheduled_tasks.py +451 -0
- package/tests/test_security.py +250 -0
- package/tests/test_security_pillar.py +213 -0
- package/tests/test_self_healing.py +171 -0
- package/tests/test_session_capture.py +200 -0
- package/tests/test_session_recorder.py +360 -0
- package/tests/test_session_skills.py +235 -0
- package/tests/test_shell.py +210 -0
- package/tests/test_snapshots.py +549 -0
- package/tests/test_soul.py +984 -0
- package/tests/test_soul_swap.py +406 -0
- package/tests/test_spawner.py +211 -0
- package/tests/test_state_diff.py +173 -0
- package/tests/test_summary.py +135 -0
- package/tests/test_sync.py +315 -5
- package/tests/test_sync_backends.py +560 -0
- package/tests/test_sync_engine.py +482 -0
- package/tests/test_sync_pillar.py +344 -0
- package/tests/test_sync_pipeline.py +364 -0
- package/tests/test_sync_vault.py +581 -0
- package/tests/test_syncthing_setup.py +168 -22
- package/tests/test_systemd.py +323 -0
- package/tests/test_team_comms.py +408 -0
- package/tests/test_team_engine.py +397 -0
- package/tests/test_testrunner.py +238 -0
- package/tests/test_trust_calibration.py +204 -0
- package/tests/test_trust_graph.py +207 -0
- package/tests/test_trust_pillar.py +291 -0
- package/tests/test_trustee_cli.py +427 -0
- package/tests/test_trustee_cli_integration.py +325 -0
- package/tests/test_trustee_monitor.py +394 -0
- package/tests/test_trustee_ops.py +355 -0
- package/tests/test_unified_search.py +363 -0
- package/tests/test_uninstall_wizard.py +193 -0
- package/tests/test_usage.py +333 -0
- package/tests/test_version_cmd.py +355 -0
- package/tests/test_warmth_anchor.py +162 -0
- package/tests/test_whoami.py +245 -0
- package/tests/test_ws.py +311 -0
- package/.cursorrules +0 -33
- package/src/skcapstone/cli.py +0 -1441
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ConnectorRegistry — discover and instantiate platform connectors.
|
|
3
|
+
|
|
4
|
+
Maintains a catalogue of every known ConnectorBackend class and can
|
|
5
|
+
probe each one to report which platforms are currently reachable.
|
|
6
|
+
|
|
7
|
+
Built-in connectors are always registered. Third-party connectors can
|
|
8
|
+
be registered at runtime via register().
|
|
9
|
+
|
|
10
|
+
Usage::
|
|
11
|
+
|
|
12
|
+
registry = ConnectorRegistry()
|
|
13
|
+
available = registry.available() # only CONNECTED/DISCONNECTED
|
|
14
|
+
connector = registry.create("terminal") # instantiate by type name
|
|
15
|
+
connector.connect()
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
import logging
|
|
21
|
+
from typing import Dict, List, Optional, Tuple, Type
|
|
22
|
+
|
|
23
|
+
from .base import ConnectorBackend, ConnectorInfo, ConnectorStatus, ConnectorType
|
|
24
|
+
from .cursor import CursorConnector
|
|
25
|
+
from .terminal import TerminalConnector
|
|
26
|
+
from .vscode import VSCodeConnector
|
|
27
|
+
|
|
28
|
+
logger = logging.getLogger(__name__)
|
|
29
|
+
|
|
30
|
+
# Built-in connector classes indexed by ConnectorType value
|
|
31
|
+
_BUILTIN_CONNECTORS: Dict[str, Type[ConnectorBackend]] = {
|
|
32
|
+
ConnectorType.TERMINAL.value: TerminalConnector,
|
|
33
|
+
ConnectorType.VSCODE.value: VSCodeConnector,
|
|
34
|
+
ConnectorType.CURSOR.value: CursorConnector,
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class ConnectorRegistry:
|
|
39
|
+
"""Catalogue of sovereign agent platform connectors.
|
|
40
|
+
|
|
41
|
+
Probes each registered connector to determine which platforms are
|
|
42
|
+
currently reachable without establishing a persistent connection.
|
|
43
|
+
|
|
44
|
+
``start_all()`` / ``stop_all()`` provide a simple lifecycle API: they
|
|
45
|
+
instantiate every registered connector, call ``connect()`` / ``disconnect()``
|
|
46
|
+
on each one, and keep the live instances in an internal table so that
|
|
47
|
+
callers can retrieve them later.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
auto_register_builtins: If True (default), pre-populate with all
|
|
51
|
+
built-in connectors on construction.
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
def __init__(self, auto_register_builtins: bool = True) -> None:
|
|
55
|
+
self._registry: Dict[str, Type[ConnectorBackend]] = {}
|
|
56
|
+
self._running: Dict[str, ConnectorBackend] = {}
|
|
57
|
+
if auto_register_builtins:
|
|
58
|
+
self._registry.update(_BUILTIN_CONNECTORS)
|
|
59
|
+
|
|
60
|
+
# ------------------------------------------------------------------
|
|
61
|
+
# Registration
|
|
62
|
+
# ------------------------------------------------------------------
|
|
63
|
+
|
|
64
|
+
def register(
|
|
65
|
+
self,
|
|
66
|
+
name: str,
|
|
67
|
+
connector_class: Type[ConnectorBackend],
|
|
68
|
+
) -> None:
|
|
69
|
+
"""Register a connector class under a given name.
|
|
70
|
+
|
|
71
|
+
Overwrites any existing entry with the same name.
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
name: Lookup key (e.g. ConnectorType value or custom slug).
|
|
75
|
+
connector_class: Class that implements ConnectorBackend.
|
|
76
|
+
"""
|
|
77
|
+
self._registry[name] = connector_class
|
|
78
|
+
logger.debug("Registered connector: %s -> %s", name, connector_class.__name__)
|
|
79
|
+
|
|
80
|
+
def unregister(self, name: str) -> bool:
|
|
81
|
+
"""Remove a connector from the registry.
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
name: The key used when the connector was registered.
|
|
85
|
+
|
|
86
|
+
Returns:
|
|
87
|
+
True if the key existed and was removed, False otherwise.
|
|
88
|
+
"""
|
|
89
|
+
if name in self._registry:
|
|
90
|
+
del self._registry[name]
|
|
91
|
+
return True
|
|
92
|
+
return False
|
|
93
|
+
|
|
94
|
+
# ------------------------------------------------------------------
|
|
95
|
+
# Discovery
|
|
96
|
+
# ------------------------------------------------------------------
|
|
97
|
+
|
|
98
|
+
def list_names(self) -> List[str]:
|
|
99
|
+
"""Return the names of all registered connectors.
|
|
100
|
+
|
|
101
|
+
Returns:
|
|
102
|
+
Sorted list of connector name strings.
|
|
103
|
+
"""
|
|
104
|
+
return sorted(self._registry.keys())
|
|
105
|
+
|
|
106
|
+
def probe(self) -> List[ConnectorInfo]:
|
|
107
|
+
"""Probe all registered connectors and return their status snapshots.
|
|
108
|
+
|
|
109
|
+
Each probe instantiates the connector with default args and calls
|
|
110
|
+
health_check() — no persistent connection is established.
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
List of ConnectorInfo objects sorted by connector name.
|
|
114
|
+
"""
|
|
115
|
+
results: List[ConnectorInfo] = []
|
|
116
|
+
for name, cls in sorted(self._registry.items()):
|
|
117
|
+
try:
|
|
118
|
+
instance = cls()
|
|
119
|
+
status = instance.health_check()
|
|
120
|
+
results.append(
|
|
121
|
+
ConnectorInfo(
|
|
122
|
+
name=name,
|
|
123
|
+
connector_type=instance.connector_type,
|
|
124
|
+
status=status,
|
|
125
|
+
)
|
|
126
|
+
)
|
|
127
|
+
except Exception as exc:
|
|
128
|
+
logger.warning("probe: error checking %s: %s", name, exc)
|
|
129
|
+
results.append(
|
|
130
|
+
ConnectorInfo(
|
|
131
|
+
name=name,
|
|
132
|
+
connector_type=ConnectorType.UNKNOWN,
|
|
133
|
+
status=ConnectorStatus.ERROR,
|
|
134
|
+
metadata={"error": str(exc)},
|
|
135
|
+
)
|
|
136
|
+
)
|
|
137
|
+
return results
|
|
138
|
+
|
|
139
|
+
def available(self) -> List[ConnectorInfo]:
|
|
140
|
+
"""Return only connectors that are not UNAVAILABLE or in ERROR.
|
|
141
|
+
|
|
142
|
+
Returns:
|
|
143
|
+
Subset of probe() results where status is CONNECTED or DISCONNECTED.
|
|
144
|
+
"""
|
|
145
|
+
return [
|
|
146
|
+
info
|
|
147
|
+
for info in self.probe()
|
|
148
|
+
if info.status not in (ConnectorStatus.UNAVAILABLE, ConnectorStatus.ERROR)
|
|
149
|
+
]
|
|
150
|
+
|
|
151
|
+
# ------------------------------------------------------------------
|
|
152
|
+
# Instantiation
|
|
153
|
+
# ------------------------------------------------------------------
|
|
154
|
+
|
|
155
|
+
def create(
|
|
156
|
+
self,
|
|
157
|
+
name: str,
|
|
158
|
+
**kwargs: object,
|
|
159
|
+
) -> Optional[ConnectorBackend]:
|
|
160
|
+
"""Instantiate a connector by its registered name.
|
|
161
|
+
|
|
162
|
+
Args:
|
|
163
|
+
name: Connector name as returned by list_names().
|
|
164
|
+
**kwargs: Forwarded to the connector's __init__.
|
|
165
|
+
|
|
166
|
+
Returns:
|
|
167
|
+
New ConnectorBackend instance, or None if name is not registered.
|
|
168
|
+
"""
|
|
169
|
+
cls = self._registry.get(name)
|
|
170
|
+
if cls is None:
|
|
171
|
+
logger.warning("ConnectorRegistry.create: unknown connector %r", name)
|
|
172
|
+
return None
|
|
173
|
+
return cls(**kwargs)
|
|
174
|
+
|
|
175
|
+
def get_class(self, name: str) -> Optional[Type[ConnectorBackend]]:
|
|
176
|
+
"""Return the connector class registered under name, without instantiating.
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
name: Connector name.
|
|
180
|
+
|
|
181
|
+
Returns:
|
|
182
|
+
ConnectorBackend subclass, or None if not found.
|
|
183
|
+
"""
|
|
184
|
+
return self._registry.get(name)
|
|
185
|
+
|
|
186
|
+
# ------------------------------------------------------------------
|
|
187
|
+
# Lifecycle
|
|
188
|
+
# ------------------------------------------------------------------
|
|
189
|
+
|
|
190
|
+
def start_all(self, **kwargs: object) -> List[Tuple[str, bool]]:
|
|
191
|
+
"""Instantiate and connect every registered connector.
|
|
192
|
+
|
|
193
|
+
Already-running connectors (present in the internal running table)
|
|
194
|
+
are skipped — call ``stop_all()`` first to restart them.
|
|
195
|
+
|
|
196
|
+
Args:
|
|
197
|
+
**kwargs: Forwarded to each connector's ``__init__`` where accepted.
|
|
198
|
+
Most built-in connectors take no extra arguments, so omit this
|
|
199
|
+
in normal usage.
|
|
200
|
+
|
|
201
|
+
Returns:
|
|
202
|
+
List of ``(name, success)`` tuples in registry order, where
|
|
203
|
+
``success`` is the return value of ``connect()``.
|
|
204
|
+
"""
|
|
205
|
+
results: List[Tuple[str, bool]] = []
|
|
206
|
+
for name, cls in sorted(self._registry.items()):
|
|
207
|
+
if name in self._running:
|
|
208
|
+
logger.debug("start_all: %s is already running — skipping", name)
|
|
209
|
+
results.append((name, True))
|
|
210
|
+
continue
|
|
211
|
+
try:
|
|
212
|
+
instance = cls(**kwargs)
|
|
213
|
+
ok = instance.connect()
|
|
214
|
+
if ok:
|
|
215
|
+
self._running[name] = instance
|
|
216
|
+
logger.info("start_all: %s connected", name)
|
|
217
|
+
else:
|
|
218
|
+
logger.warning("start_all: %s connect() returned False", name)
|
|
219
|
+
results.append((name, ok))
|
|
220
|
+
except Exception as exc:
|
|
221
|
+
logger.error("start_all: %s raised %s", name, exc)
|
|
222
|
+
results.append((name, False))
|
|
223
|
+
return results
|
|
224
|
+
|
|
225
|
+
def stop_all(self) -> List[Tuple[str, bool]]:
|
|
226
|
+
"""Disconnect and remove every running connector instance.
|
|
227
|
+
|
|
228
|
+
Returns:
|
|
229
|
+
List of ``(name, success)`` tuples where ``success`` is the
|
|
230
|
+
return value of ``disconnect()``.
|
|
231
|
+
"""
|
|
232
|
+
results: List[Tuple[str, bool]] = []
|
|
233
|
+
for name, instance in list(self._running.items()):
|
|
234
|
+
try:
|
|
235
|
+
ok = instance.disconnect()
|
|
236
|
+
logger.info("stop_all: %s disconnected (ok=%s)", name, ok)
|
|
237
|
+
results.append((name, ok))
|
|
238
|
+
except Exception as exc:
|
|
239
|
+
logger.error("stop_all: %s raised %s", name, exc)
|
|
240
|
+
results.append((name, False))
|
|
241
|
+
finally:
|
|
242
|
+
self._running.pop(name, None)
|
|
243
|
+
return results
|
|
244
|
+
|
|
245
|
+
def get_running(self, name: str) -> Optional[ConnectorBackend]:
|
|
246
|
+
"""Return the live connector instance for *name*, if started.
|
|
247
|
+
|
|
248
|
+
Args:
|
|
249
|
+
name: Connector name as returned by ``list_names()``.
|
|
250
|
+
|
|
251
|
+
Returns:
|
|
252
|
+
Running ConnectorBackend instance, or None if not started.
|
|
253
|
+
"""
|
|
254
|
+
return self._running.get(name)
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"""
|
|
2
|
+
TerminalConnector — sovereign agent viewport over stdin/stdout.
|
|
3
|
+
|
|
4
|
+
The terminal is the primordial interface: no extension required, no
|
|
5
|
+
network needed. Messages are written to stdout and read from a queue
|
|
6
|
+
fed by a background reader thread on stdin.
|
|
7
|
+
|
|
8
|
+
Thread safety:
|
|
9
|
+
- A daemon thread reads stdin lines and enqueues them.
|
|
10
|
+
- send() writes directly to the output stream (default: sys.stdout).
|
|
11
|
+
- receive() pops from the queue (non-blocking).
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import queue
|
|
17
|
+
import sys
|
|
18
|
+
import threading
|
|
19
|
+
from io import TextIOBase
|
|
20
|
+
from typing import Optional, TextIO
|
|
21
|
+
|
|
22
|
+
from .base import ConnectorBackend, ConnectorStatus, ConnectorType
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class TerminalConnector(ConnectorBackend):
|
|
26
|
+
"""Read from stdin, write to stdout — the always-available channel.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
input_stream: Readable text stream (default: sys.stdin).
|
|
30
|
+
output_stream: Writable text stream (default: sys.stdout).
|
|
31
|
+
prompt: Optional prompt string written before each received line.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
connector_type = ConnectorType.TERMINAL
|
|
35
|
+
|
|
36
|
+
def __init__(
|
|
37
|
+
self,
|
|
38
|
+
input_stream: Optional[TextIO] = None,
|
|
39
|
+
output_stream: Optional[TextIO] = None,
|
|
40
|
+
prompt: str = "",
|
|
41
|
+
) -> None:
|
|
42
|
+
self._input: TextIO = input_stream or sys.stdin
|
|
43
|
+
self._output: TextIO = output_stream or sys.stdout
|
|
44
|
+
self._prompt = prompt
|
|
45
|
+
self._queue: queue.Queue[str] = queue.Queue()
|
|
46
|
+
self._reader: Optional[threading.Thread] = None
|
|
47
|
+
self._connected = False
|
|
48
|
+
self._error: Optional[str] = None
|
|
49
|
+
|
|
50
|
+
# ------------------------------------------------------------------
|
|
51
|
+
# Lifecycle
|
|
52
|
+
# ------------------------------------------------------------------
|
|
53
|
+
|
|
54
|
+
def connect(self) -> bool:
|
|
55
|
+
"""Start the background stdin reader thread.
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
True if connected (idempotent — safe to call multiple times).
|
|
59
|
+
"""
|
|
60
|
+
if self._connected:
|
|
61
|
+
return True
|
|
62
|
+
|
|
63
|
+
self._error = None
|
|
64
|
+
self._reader = threading.Thread(
|
|
65
|
+
target=self._read_loop,
|
|
66
|
+
name="terminal-connector-reader",
|
|
67
|
+
daemon=True,
|
|
68
|
+
)
|
|
69
|
+
self._reader.start()
|
|
70
|
+
self._connected = True
|
|
71
|
+
return True
|
|
72
|
+
|
|
73
|
+
def disconnect(self) -> bool:
|
|
74
|
+
"""Mark the connector as disconnected.
|
|
75
|
+
|
|
76
|
+
The background reader thread will exit naturally when stdin closes.
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
True always.
|
|
80
|
+
"""
|
|
81
|
+
self._connected = False
|
|
82
|
+
return True
|
|
83
|
+
|
|
84
|
+
# ------------------------------------------------------------------
|
|
85
|
+
# Messaging
|
|
86
|
+
# ------------------------------------------------------------------
|
|
87
|
+
|
|
88
|
+
def send(self, message: str) -> bool:
|
|
89
|
+
"""Write a message to the output stream.
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
message: Text to write. A trailing newline is appended if
|
|
93
|
+
not already present.
|
|
94
|
+
|
|
95
|
+
Returns:
|
|
96
|
+
True if written successfully, False on I/O error.
|
|
97
|
+
"""
|
|
98
|
+
if not self._connected:
|
|
99
|
+
return False
|
|
100
|
+
try:
|
|
101
|
+
if self._prompt:
|
|
102
|
+
self._output.write(self._prompt)
|
|
103
|
+
if not message.endswith("\n"):
|
|
104
|
+
message = message + "\n"
|
|
105
|
+
self._output.write(message)
|
|
106
|
+
self._output.flush()
|
|
107
|
+
return True
|
|
108
|
+
except OSError as exc:
|
|
109
|
+
self._error = str(exc)
|
|
110
|
+
return False
|
|
111
|
+
|
|
112
|
+
def receive(self) -> Optional[str]:
|
|
113
|
+
"""Return the next queued line from stdin (non-blocking).
|
|
114
|
+
|
|
115
|
+
Returns:
|
|
116
|
+
Line string (without trailing newline) or None if the queue
|
|
117
|
+
is empty.
|
|
118
|
+
"""
|
|
119
|
+
try:
|
|
120
|
+
return self._queue.get_nowait()
|
|
121
|
+
except queue.Empty:
|
|
122
|
+
return None
|
|
123
|
+
|
|
124
|
+
# ------------------------------------------------------------------
|
|
125
|
+
# Health
|
|
126
|
+
# ------------------------------------------------------------------
|
|
127
|
+
|
|
128
|
+
def health_check(self) -> ConnectorStatus:
|
|
129
|
+
"""Return connector status based on connection state and errors.
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
CONNECTED, DISCONNECTED, or ERROR.
|
|
133
|
+
"""
|
|
134
|
+
if self._error:
|
|
135
|
+
return ConnectorStatus.ERROR
|
|
136
|
+
if not self._connected:
|
|
137
|
+
return ConnectorStatus.DISCONNECTED
|
|
138
|
+
return ConnectorStatus.CONNECTED
|
|
139
|
+
|
|
140
|
+
# ------------------------------------------------------------------
|
|
141
|
+
# Internal
|
|
142
|
+
# ------------------------------------------------------------------
|
|
143
|
+
|
|
144
|
+
def _read_loop(self) -> None:
|
|
145
|
+
"""Background thread: read lines from stdin and enqueue them."""
|
|
146
|
+
try:
|
|
147
|
+
for line in self._input:
|
|
148
|
+
if not self._connected:
|
|
149
|
+
break
|
|
150
|
+
self._queue.put(line.rstrip("\n"))
|
|
151
|
+
except OSError as exc:
|
|
152
|
+
self._error = str(exc)
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""
|
|
2
|
+
VSCodeConnector — sovereign agent viewport into Visual Studio Code.
|
|
3
|
+
|
|
4
|
+
Communicates with the SKCapstone VS Code extension via a Unix domain socket
|
|
5
|
+
at ``~/.skcapstone/connectors/vscode.sock``.
|
|
6
|
+
|
|
7
|
+
Protocol
|
|
8
|
+
--------
|
|
9
|
+
The agent is the **server**. On ``connect()`` it creates and binds the socket
|
|
10
|
+
so the VS Code extension (client) can connect at any time.
|
|
11
|
+
|
|
12
|
+
Wire format: 4-byte big-endian uint32 length prefix + UTF-8 JSON-RPC 2.0 body.
|
|
13
|
+
See :class:`~skcapstone.connectors.base.UnixSocketConnector` for details.
|
|
14
|
+
|
|
15
|
+
Extension contract:
|
|
16
|
+
- Extension connects to ``~/.skcapstone/connectors/vscode.sock``.
|
|
17
|
+
- Both sides exchange length-framed JSON-RPC 2.0 messages.
|
|
18
|
+
- Notifications (no ``"id"`` field) are fire-and-forget.
|
|
19
|
+
- Requests carry an ``"id"`` and expect a matching ``"result"`` response.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
24
|
+
from pathlib import Path
|
|
25
|
+
from typing import Optional
|
|
26
|
+
|
|
27
|
+
from .base import ConnectorStatus, ConnectorType, UnixSocketConnector
|
|
28
|
+
|
|
29
|
+
_DEFAULT_SOCKET_PATH = Path("~/.skcapstone/connectors/vscode.sock")
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class VSCodeConnector(UnixSocketConnector):
|
|
33
|
+
"""Connect the sovereign agent to Visual Studio Code.
|
|
34
|
+
|
|
35
|
+
Binds a Unix domain socket at ``~/.skcapstone/connectors/vscode.sock``
|
|
36
|
+
and waits for the SKCapstone VS Code extension to connect.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
socket_path: Override the default socket file location.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
connector_type = ConnectorType.VSCODE
|
|
43
|
+
|
|
44
|
+
def __init__(self, socket_path: Optional[Path] = None) -> None:
|
|
45
|
+
super().__init__(socket_path or _DEFAULT_SOCKET_PATH)
|
|
46
|
+
|
|
47
|
+
# health_check is inherited — returns UNAVAILABLE only if _connected is False
|
|
48
|
+
# and no error; override to surface UNAVAILABLE while socket dir is absent
|
|
49
|
+
# so that registry.probe() can distinguish "never started" from "disconnected".
|
|
50
|
+
|
|
51
|
+
def health_check(self) -> ConnectorStatus:
|
|
52
|
+
"""Return the current connector status.
|
|
53
|
+
|
|
54
|
+
Returns UNAVAILABLE when neither connected nor the socket dir exists,
|
|
55
|
+
so callers can tell whether the extension has ever been set up.
|
|
56
|
+
"""
|
|
57
|
+
status = super().health_check()
|
|
58
|
+
if status == ConnectorStatus.DISCONNECTED and not self._socket_path.parent.exists():
|
|
59
|
+
return ConnectorStatus.UNAVAILABLE
|
|
60
|
+
return status
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Consciousness configuration loader.
|
|
3
|
+
|
|
4
|
+
Loads ConsciousnessConfig from YAML with override hierarchy:
|
|
5
|
+
1. Per-agent config: {agent_home}/config/consciousness.yaml
|
|
6
|
+
2. Environment: SKCAPSTONE_CONSCIOUSNESS_ENABLED=false
|
|
7
|
+
3. CLI flag: --no-consciousness
|
|
8
|
+
|
|
9
|
+
Usage:
|
|
10
|
+
config = load_consciousness_config(home)
|
|
11
|
+
config = load_consciousness_config(home, cli_disabled=True)
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import logging
|
|
17
|
+
import os
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
from typing import Optional
|
|
20
|
+
|
|
21
|
+
import yaml
|
|
22
|
+
|
|
23
|
+
from .consciousness_loop import ConsciousnessConfig
|
|
24
|
+
|
|
25
|
+
logger = logging.getLogger("skcapstone.consciousness_config")
|
|
26
|
+
|
|
27
|
+
CONFIG_FILENAME = "consciousness.yaml"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def load_consciousness_config(
|
|
31
|
+
home: Path,
|
|
32
|
+
cli_disabled: bool = False,
|
|
33
|
+
config_path: Optional[Path] = None,
|
|
34
|
+
) -> ConsciousnessConfig:
|
|
35
|
+
"""Load consciousness config with override hierarchy.
|
|
36
|
+
|
|
37
|
+
Priority (highest wins):
|
|
38
|
+
1. CLI flag (--no-consciousness)
|
|
39
|
+
2. Environment variable (SKCAPSTONE_CONSCIOUSNESS_ENABLED)
|
|
40
|
+
3. YAML config file
|
|
41
|
+
4. Defaults
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
home: Agent home directory.
|
|
45
|
+
cli_disabled: True if --no-consciousness was passed.
|
|
46
|
+
config_path: Explicit path to config file (overrides default).
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
Resolved ConsciousnessConfig.
|
|
50
|
+
"""
|
|
51
|
+
config = ConsciousnessConfig()
|
|
52
|
+
|
|
53
|
+
# Load from YAML
|
|
54
|
+
yaml_path = config_path or (home / "config" / CONFIG_FILENAME)
|
|
55
|
+
if yaml_path.exists():
|
|
56
|
+
try:
|
|
57
|
+
raw = yaml.safe_load(yaml_path.read_text(encoding="utf-8"))
|
|
58
|
+
if raw and isinstance(raw, dict):
|
|
59
|
+
config = ConsciousnessConfig.model_validate(raw)
|
|
60
|
+
logger.info("Loaded consciousness config from %s", yaml_path)
|
|
61
|
+
except Exception as exc:
|
|
62
|
+
logger.warning(
|
|
63
|
+
"Failed to parse %s, using defaults: %s", yaml_path, exc
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
# Environment override
|
|
67
|
+
env_enabled = os.environ.get("SKCAPSTONE_CONSCIOUSNESS_ENABLED", "").lower()
|
|
68
|
+
if env_enabled == "false":
|
|
69
|
+
config.enabled = False
|
|
70
|
+
logger.info("Consciousness disabled via SKCAPSTONE_CONSCIOUSNESS_ENABLED")
|
|
71
|
+
elif env_enabled == "true":
|
|
72
|
+
config.enabled = True
|
|
73
|
+
|
|
74
|
+
# CLI override (highest priority)
|
|
75
|
+
if cli_disabled:
|
|
76
|
+
config.enabled = False
|
|
77
|
+
logger.info("Consciousness disabled via --no-consciousness flag")
|
|
78
|
+
|
|
79
|
+
return config
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def write_default_config(home: Path) -> Path:
|
|
83
|
+
"""Write the default consciousness config to disk.
|
|
84
|
+
|
|
85
|
+
Creates {home}/config/consciousness.yaml with all defaults
|
|
86
|
+
commented for reference.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
home: Agent home directory.
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
Path to the created config file.
|
|
93
|
+
"""
|
|
94
|
+
config_dir = home / "config"
|
|
95
|
+
config_dir.mkdir(parents=True, exist_ok=True)
|
|
96
|
+
config_path = config_dir / CONFIG_FILENAME
|
|
97
|
+
|
|
98
|
+
default = ConsciousnessConfig()
|
|
99
|
+
content = yaml.dump(
|
|
100
|
+
default.model_dump(),
|
|
101
|
+
default_flow_style=False,
|
|
102
|
+
sort_keys=False,
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
header = (
|
|
106
|
+
"# Consciousness Loop Configuration\n"
|
|
107
|
+
"#\n"
|
|
108
|
+
"# Override hierarchy:\n"
|
|
109
|
+
"# 1. CLI: skcapstone daemon start --no-consciousness\n"
|
|
110
|
+
"# 2. Env: SKCAPSTONE_CONSCIOUSNESS_ENABLED=false\n"
|
|
111
|
+
"# 3. This file\n"
|
|
112
|
+
"#\n"
|
|
113
|
+
"# See: skcapstone consciousness config --show\n"
|
|
114
|
+
"\n"
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
config_path.write_text(header + content, encoding="utf-8")
|
|
118
|
+
logger.info("Wrote default consciousness config to %s", config_path)
|
|
119
|
+
return config_path
|