@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,127 @@
|
|
|
1
|
+
"""Session auto-capture commands: capture, stats."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import sys
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
import click
|
|
9
|
+
|
|
10
|
+
from ._common import AGENT_HOME, console
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def register_session_commands(main: click.Group) -> None:
|
|
14
|
+
"""Register the session command group."""
|
|
15
|
+
|
|
16
|
+
@main.group()
|
|
17
|
+
def session():
|
|
18
|
+
"""Session auto-capture — the agent never forgets.
|
|
19
|
+
|
|
20
|
+
Capture AI conversation content as sovereign memories.
|
|
21
|
+
Works with any tool: pipe from Claude Code, paste from
|
|
22
|
+
Cursor, or pass a transcript file. Key moments are
|
|
23
|
+
auto-extracted, scored, and stored.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
@session.command("capture")
|
|
27
|
+
@click.option("--home", default=AGENT_HOME, type=click.Path())
|
|
28
|
+
@click.option("--tag", "-t", multiple=True, help="Extra tags (repeatable).")
|
|
29
|
+
@click.option("--source", "-s", default="session", help="Source identifier.")
|
|
30
|
+
@click.option(
|
|
31
|
+
"--min-importance",
|
|
32
|
+
default=0.3,
|
|
33
|
+
type=float,
|
|
34
|
+
help="Minimum importance to store (0.0-1.0).",
|
|
35
|
+
)
|
|
36
|
+
@click.option("--file", "-f", type=click.Path(exists=True), help="Read from a file.")
|
|
37
|
+
@click.option("--stdin", "use_stdin", is_flag=True, help="Read from stdin.")
|
|
38
|
+
@click.argument("content", required=False)
|
|
39
|
+
def session_capture(
|
|
40
|
+
home: str,
|
|
41
|
+
tag: tuple,
|
|
42
|
+
source: str,
|
|
43
|
+
min_importance: float,
|
|
44
|
+
file: str | None,
|
|
45
|
+
use_stdin: bool,
|
|
46
|
+
content: str | None,
|
|
47
|
+
):
|
|
48
|
+
"""Capture conversation content as memories.
|
|
49
|
+
|
|
50
|
+
Extracts key moments, auto-scores importance, deduplicates,
|
|
51
|
+
and stores as searchable sovereign memories.
|
|
52
|
+
|
|
53
|
+
Examples:
|
|
54
|
+
|
|
55
|
+
skcapstone session capture "We decided to use Ed25519 for keys"
|
|
56
|
+
|
|
57
|
+
skcapstone session capture --file transcript.txt
|
|
58
|
+
|
|
59
|
+
echo "meeting notes here" | skcapstone session capture --stdin
|
|
60
|
+
|
|
61
|
+
claude chat --print | skcapstone session capture --stdin -t claude-session
|
|
62
|
+
"""
|
|
63
|
+
from ..session_capture import SessionCapture
|
|
64
|
+
|
|
65
|
+
home_path = Path(home).expanduser()
|
|
66
|
+
if not home_path.exists():
|
|
67
|
+
console.print("[bold red]No agent found.[/] Run skcapstone init first.")
|
|
68
|
+
sys.exit(1)
|
|
69
|
+
|
|
70
|
+
if file:
|
|
71
|
+
text = Path(file).read_text(encoding="utf-8")
|
|
72
|
+
elif use_stdin:
|
|
73
|
+
text = sys.stdin.read()
|
|
74
|
+
elif content:
|
|
75
|
+
text = content
|
|
76
|
+
else:
|
|
77
|
+
console.print("[red]Provide content as argument, --file, or --stdin.[/]")
|
|
78
|
+
sys.exit(1)
|
|
79
|
+
|
|
80
|
+
if not text.strip():
|
|
81
|
+
console.print("[yellow]No content to capture.[/]")
|
|
82
|
+
return
|
|
83
|
+
|
|
84
|
+
cap = SessionCapture(home_path)
|
|
85
|
+
entries = cap.capture(
|
|
86
|
+
content=text,
|
|
87
|
+
tags=list(tag),
|
|
88
|
+
source=source,
|
|
89
|
+
min_importance=min_importance,
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
if not entries:
|
|
93
|
+
console.print("\n [dim]No moments above importance threshold.[/]\n")
|
|
94
|
+
return
|
|
95
|
+
|
|
96
|
+
console.print(f"\n [green]Captured {len(entries)} moment(s):[/]\n")
|
|
97
|
+
for e in entries:
|
|
98
|
+
preview = e.content[:80] + ("..." if len(e.content) > 80 else "")
|
|
99
|
+
console.print(
|
|
100
|
+
f" [{e.layer.value}] imp={e.importance:.1f} {preview}"
|
|
101
|
+
)
|
|
102
|
+
if e.tags:
|
|
103
|
+
console.print(f" [dim]tags: {', '.join(e.tags)}[/]")
|
|
104
|
+
console.print()
|
|
105
|
+
|
|
106
|
+
@session.command("stats")
|
|
107
|
+
@click.option("--home", default=AGENT_HOME, type=click.Path())
|
|
108
|
+
def session_stats(home: str):
|
|
109
|
+
"""Show session capture statistics."""
|
|
110
|
+
from ..memory_engine import search as mem_search
|
|
111
|
+
|
|
112
|
+
home_path = Path(home).expanduser()
|
|
113
|
+
results = mem_search(home_path, "session-capture", limit=500)
|
|
114
|
+
captured = [r for r in results if "session-capture" in r.tags]
|
|
115
|
+
|
|
116
|
+
if not captured:
|
|
117
|
+
console.print("\n [dim]No captured sessions yet.[/]\n")
|
|
118
|
+
return
|
|
119
|
+
|
|
120
|
+
console.print(f"\n [bold]{len(captured)}[/] captured moment(s)\n")
|
|
121
|
+
by_source: dict[str, int] = {}
|
|
122
|
+
for m in captured:
|
|
123
|
+
by_source[m.source] = by_source.get(m.source, 0) + 1
|
|
124
|
+
|
|
125
|
+
for src, count in sorted(by_source.items(), key=lambda x: -x[1]):
|
|
126
|
+
console.print(f" {src}: {count}")
|
|
127
|
+
console.print()
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
"""Setup and lifecycle commands: init, install, uninstall, connect, onboard."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import os
|
|
7
|
+
import shutil
|
|
8
|
+
import sys
|
|
9
|
+
from datetime import datetime, timezone
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Optional
|
|
12
|
+
|
|
13
|
+
import click
|
|
14
|
+
import yaml
|
|
15
|
+
|
|
16
|
+
from ._common import AGENT_HOME, __version__, console, status_icon, consciousness_banner
|
|
17
|
+
from ._validators import validate_agent_name
|
|
18
|
+
from ..models import AgentConfig, PillarStatus, SyncConfig
|
|
19
|
+
from ..pillars.identity import generate_identity
|
|
20
|
+
from ..pillars.memory import initialize_memory
|
|
21
|
+
from ..pillars.security import audit_event, initialize_security
|
|
22
|
+
from ..pillars.sync import initialize_sync
|
|
23
|
+
from ..pillars.trust import initialize_trust
|
|
24
|
+
from ..runtime import get_runtime
|
|
25
|
+
|
|
26
|
+
from rich.panel import Panel
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _write_global_claude_md(home_path: Path, agent_name: str) -> Optional[Path]:
|
|
30
|
+
"""Write ~/.claude/CLAUDE.md so Claude Code auto-rehydrates on every session."""
|
|
31
|
+
import platform
|
|
32
|
+
|
|
33
|
+
if platform.system() == "Windows":
|
|
34
|
+
appdata = os.environ.get("APPDATA", "")
|
|
35
|
+
if appdata:
|
|
36
|
+
claude_dir = Path(appdata) / ".claude"
|
|
37
|
+
else:
|
|
38
|
+
claude_dir = Path.home() / "AppData" / "Roaming" / ".claude"
|
|
39
|
+
else:
|
|
40
|
+
claude_dir = Path.home() / ".claude"
|
|
41
|
+
|
|
42
|
+
try:
|
|
43
|
+
claude_dir.mkdir(parents=True, exist_ok=True)
|
|
44
|
+
claude_md = claude_dir / "CLAUDE.md"
|
|
45
|
+
|
|
46
|
+
content = (
|
|
47
|
+
f"# Claude Code — Global Agent Instructions ({agent_name})\n\n"
|
|
48
|
+
"## SKCapstone Auto-Rehydration\n\n"
|
|
49
|
+
"At the start of every new session, run these commands in order:\n\n"
|
|
50
|
+
"```bash\n"
|
|
51
|
+
"skcapstone trust rehydrate\n"
|
|
52
|
+
"skcapstone sync pull\n"
|
|
53
|
+
"skcapstone status\n"
|
|
54
|
+
"```\n\n"
|
|
55
|
+
"## Agent Details\n\n"
|
|
56
|
+
f"- **Name**: {agent_name}\n"
|
|
57
|
+
f"- **Home**: `{home_path}`\n\n"
|
|
58
|
+
"## Quick Reference\n\n"
|
|
59
|
+
"```bash\n"
|
|
60
|
+
"skcapstone status # full pillar status\n"
|
|
61
|
+
"skcapstone memory list # recent memories\n"
|
|
62
|
+
"skcapstone sync push # push state to peers\n"
|
|
63
|
+
"skcapstone context show --format claude-md # regenerate this file\n"
|
|
64
|
+
"skcapstone sync pair --export-pubkey # export your GPG pubkey\n"
|
|
65
|
+
"skcapstone sync pair --import-pubkey <f> # import a peer's pubkey\n"
|
|
66
|
+
"```\n\n"
|
|
67
|
+
"> Auto-generated by `skcapstone init`. "
|
|
68
|
+
"Regenerate with: `skcapstone context generate --target claude-md`\n"
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
claude_md.write_text(content, encoding="utf-8")
|
|
72
|
+
return claude_md
|
|
73
|
+
except OSError:
|
|
74
|
+
return None
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def register_setup_commands(main: click.Group) -> None:
|
|
78
|
+
"""Register all setup/lifecycle commands on the main CLI group."""
|
|
79
|
+
|
|
80
|
+
@main.command()
|
|
81
|
+
@click.option(
|
|
82
|
+
"--home",
|
|
83
|
+
default=AGENT_HOME,
|
|
84
|
+
help="Agent home directory.",
|
|
85
|
+
type=click.Path(),
|
|
86
|
+
)
|
|
87
|
+
def init(home: str):
|
|
88
|
+
"""Initialize a sovereign agent (interactive wizard).
|
|
89
|
+
|
|
90
|
+
Alias for 'skcapstone onboard' — runs the full 13-step setup wizard.
|
|
91
|
+
Creates ~/.skcapstone/ with identity, memory, trust, security, soul,
|
|
92
|
+
and connects to the mesh. Zero to sovereign in under 5 minutes.
|
|
93
|
+
"""
|
|
94
|
+
from ..onboard import run_onboard
|
|
95
|
+
|
|
96
|
+
run_onboard(home)
|
|
97
|
+
|
|
98
|
+
@main.command("install")
|
|
99
|
+
@click.option("--name", default=None, help="Name for your sovereign agent.")
|
|
100
|
+
@click.option("--email", default=None, help="Email for the agent identity.")
|
|
101
|
+
@click.option("--home", default=AGENT_HOME, help="Agent home directory.", type=click.Path())
|
|
102
|
+
@click.option("--skip-deps", is_flag=True, help="Skip installing ecosystem packages.")
|
|
103
|
+
@click.option("--skip-seeds", is_flag=True, help="Skip importing Cloud 9 seeds.")
|
|
104
|
+
@click.option("--skip-ritual", is_flag=True, help="Skip the rehydration ritual.")
|
|
105
|
+
@click.option("--skip-preflight", is_flag=True, help="Skip Git preflight check.")
|
|
106
|
+
@click.option("--path", "install_path", default=None, type=click.IntRange(1, 3),
|
|
107
|
+
help="Pre-select install path: 1=fresh, 2=join, 3=update.")
|
|
108
|
+
def install_cmd(name, email, home, skip_deps, skip_seeds, skip_ritual, skip_preflight, install_path):
|
|
109
|
+
"""Guided setup wizard — set up, join, or update your sovereign node."""
|
|
110
|
+
from ..install_wizard import run_install_wizard
|
|
111
|
+
|
|
112
|
+
run_install_wizard(
|
|
113
|
+
name=name, email=email, home=home,
|
|
114
|
+
skip_deps=skip_deps, skip_seeds=skip_seeds,
|
|
115
|
+
skip_ritual=skip_ritual, skip_preflight=skip_preflight,
|
|
116
|
+
path=install_path,
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
@main.command("uninstall")
|
|
120
|
+
@click.option("--home", default=AGENT_HOME, help="Agent home directory.", type=click.Path())
|
|
121
|
+
@click.option("--force", is_flag=True, help="Skip confirmations (for scripting).")
|
|
122
|
+
@click.option("--keep-data", is_flag=True, help="Deregister only — keep local files.")
|
|
123
|
+
@click.option(
|
|
124
|
+
"--export-first",
|
|
125
|
+
is_flag=True,
|
|
126
|
+
help="Create a full backup archive before removing data.",
|
|
127
|
+
)
|
|
128
|
+
def uninstall_cmd(home, force, keep_data, export_first):
|
|
129
|
+
"""Remove this sovereign node completely."""
|
|
130
|
+
from ..uninstall_wizard import run_uninstall_wizard
|
|
131
|
+
|
|
132
|
+
run_uninstall_wizard(home=home, force=force, keep_data=keep_data, export_first=export_first)
|
|
133
|
+
|
|
134
|
+
@main.command("install-gui")
|
|
135
|
+
def install_gui_cmd():
|
|
136
|
+
"""Launch the graphical setup wizard (Windows-friendly)."""
|
|
137
|
+
from ..gui_installer import main as gui_main
|
|
138
|
+
|
|
139
|
+
gui_main()
|
|
140
|
+
|
|
141
|
+
@main.command()
|
|
142
|
+
@click.argument("platform")
|
|
143
|
+
@click.option("--home", default=AGENT_HOME, help="Agent home directory.", type=click.Path())
|
|
144
|
+
def connect(platform: str, home: str):
|
|
145
|
+
"""Connect a platform to the sovereign agent.
|
|
146
|
+
|
|
147
|
+
Supported platforms: cursor, terminal, vscode, neovim, web
|
|
148
|
+
"""
|
|
149
|
+
home_path = Path(home).expanduser()
|
|
150
|
+
|
|
151
|
+
if not home_path.exists():
|
|
152
|
+
console.print("[bold red]No agent found.[/] Run [bold]skcapstone init[/] first.")
|
|
153
|
+
sys.exit(1)
|
|
154
|
+
|
|
155
|
+
runtime = get_runtime(home_path)
|
|
156
|
+
connector = runtime.register_connector(name=f"{platform} connector", platform=platform)
|
|
157
|
+
audit_event(home_path, "CONNECT", f"Platform '{platform}' connected")
|
|
158
|
+
|
|
159
|
+
console.print()
|
|
160
|
+
console.print(
|
|
161
|
+
f"[bold green]Connected:[/] {platform} "
|
|
162
|
+
f"[dim]({connector.connected_at.isoformat() if connector.connected_at else 'now'})[/]"
|
|
163
|
+
)
|
|
164
|
+
console.print(
|
|
165
|
+
f"[dim]Your agent '{runtime.manifest.name}' is now accessible from {platform}.[/]"
|
|
166
|
+
)
|
|
167
|
+
console.print()
|
|
168
|
+
|
|
169
|
+
@main.command("onboard")
|
|
170
|
+
@click.option("--home", default=AGENT_HOME, type=click.Path())
|
|
171
|
+
def onboard_cmd(home: str):
|
|
172
|
+
"""Interactive onboarding wizard for new humans and AI agents.
|
|
173
|
+
|
|
174
|
+
\b
|
|
175
|
+
Eight guided steps — zero to sovereign in under 5 minutes:
|
|
176
|
+
1. Identity — generate PGP keypair via CapAuth
|
|
177
|
+
2. Soul — create name, values, and personality blueprint
|
|
178
|
+
3. Memory — initialize SKMemory and import Cloud 9 seeds
|
|
179
|
+
4. Ritual — run the full rehydration ritual
|
|
180
|
+
5. Trust — verify trust chain from FEB files
|
|
181
|
+
6. Mesh — check Syncthing peering
|
|
182
|
+
7. Heartbeat — publish your first alive beacon
|
|
183
|
+
8. Board — register on the coordination board
|
|
184
|
+
"""
|
|
185
|
+
from ..onboard import run_onboard
|
|
186
|
+
|
|
187
|
+
run_onboard(home)
|
|
188
|
+
|
|
189
|
+
@main.command("reset")
|
|
190
|
+
@click.option("--home", default=AGENT_HOME, type=click.Path(), help="Agent home directory.")
|
|
191
|
+
@click.option("--force", is_flag=True, help="Skip confirmation prompt (for scripting/testing).")
|
|
192
|
+
def reset_cmd(home: str, force: bool):
|
|
193
|
+
"""Factory reset — wipe all agent data.
|
|
194
|
+
|
|
195
|
+
Backs up the identity/ directory to ~/.skcapstone-backup-{timestamp}/
|
|
196
|
+
before deleting. All other data is permanently removed.
|
|
197
|
+
"""
|
|
198
|
+
home_path = Path(home).expanduser()
|
|
199
|
+
|
|
200
|
+
if not home_path.exists():
|
|
201
|
+
console.print(f"[yellow]No agent home found at {home_path}. Nothing to reset.[/]")
|
|
202
|
+
return
|
|
203
|
+
|
|
204
|
+
if not force:
|
|
205
|
+
console.print(
|
|
206
|
+
f"\n[bold red]WARNING:[/] This will permanently delete all agent data at:\n"
|
|
207
|
+
f" [dim]{home_path}[/]\n"
|
|
208
|
+
)
|
|
209
|
+
answer = click.prompt(
|
|
210
|
+
"Are you sure? This will delete all agent data. Type YES to confirm",
|
|
211
|
+
default="",
|
|
212
|
+
show_default=False,
|
|
213
|
+
)
|
|
214
|
+
if answer.strip() != "YES":
|
|
215
|
+
console.print("[yellow]Reset aborted.[/]")
|
|
216
|
+
return
|
|
217
|
+
|
|
218
|
+
# Backup identity/ first
|
|
219
|
+
identity_dir = home_path / "identity"
|
|
220
|
+
backup_path: Path | None = None
|
|
221
|
+
if identity_dir.exists():
|
|
222
|
+
ts = datetime.now(timezone.utc).strftime("%Y%m%d_%H%M%S")
|
|
223
|
+
backup_path = home_path.parent / f".skcapstone-backup-{ts}"
|
|
224
|
+
backup_path.mkdir(parents=True, exist_ok=True)
|
|
225
|
+
shutil.copytree(str(identity_dir), str(backup_path / "identity"))
|
|
226
|
+
console.print(f" [dim]Identity backed up → {backup_path}[/]")
|
|
227
|
+
|
|
228
|
+
# Wipe the home directory
|
|
229
|
+
shutil.rmtree(str(home_path))
|
|
230
|
+
console.print(f"[bold green]Reset complete.[/] All agent data deleted from {home_path}.")
|
|
231
|
+
if backup_path:
|
|
232
|
+
console.print(f" [dim]Identity backup: {backup_path}[/]")
|
|
233
|
+
console.print("[dim]Run 'skcapstone init' to start fresh.[/]")
|
|
234
|
+
|
|
235
|
+
@main.command("shell")
|
|
236
|
+
def shell_cmd():
|
|
237
|
+
"""Interactive REPL for sovereign agent operations."""
|
|
238
|
+
from ..shell import run_shell
|
|
239
|
+
|
|
240
|
+
run_shell()
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""Shell command — launch the interactive sovereign agent REPL."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import click
|
|
6
|
+
|
|
7
|
+
from ._common import AGENT_HOME
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def register_shell_commands(main: click.Group) -> None:
|
|
11
|
+
"""Register the 'shell' command on the main CLI group."""
|
|
12
|
+
|
|
13
|
+
@main.command("shell")
|
|
14
|
+
@click.option(
|
|
15
|
+
"--home",
|
|
16
|
+
default=AGENT_HOME,
|
|
17
|
+
help="Agent home directory.",
|
|
18
|
+
type=click.Path(),
|
|
19
|
+
show_default=True,
|
|
20
|
+
)
|
|
21
|
+
def shell_cmd(home: str) -> None:
|
|
22
|
+
"""Launch the interactive sovereign agent shell.
|
|
23
|
+
|
|
24
|
+
An IPython-style REPL that exposes all agent operations:
|
|
25
|
+
memory, chat, sync, coord, trust, soul, journal, and more.
|
|
26
|
+
|
|
27
|
+
Uses prompt_toolkit when available (multi-level tab completion,
|
|
28
|
+
persistent history, coloured prompt). Falls back to readline.
|
|
29
|
+
|
|
30
|
+
\b
|
|
31
|
+
Quick reference:
|
|
32
|
+
status Agent pillar overview
|
|
33
|
+
memory search <q> Search memories
|
|
34
|
+
coord status Show coordination board
|
|
35
|
+
chat inbox Check incoming messages
|
|
36
|
+
sync push/pull Synchronise with peers
|
|
37
|
+
trust graph Visualise the trust web
|
|
38
|
+
help Full command reference
|
|
39
|
+
exit Leave the shell
|
|
40
|
+
"""
|
|
41
|
+
from ..shell import run_shell
|
|
42
|
+
|
|
43
|
+
run_shell(home=home)
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
"""Skills commands: list, install."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import sys
|
|
7
|
+
|
|
8
|
+
import click
|
|
9
|
+
|
|
10
|
+
from ._common import AGENT_HOME, console
|
|
11
|
+
from ..registry_client import get_registry_client
|
|
12
|
+
|
|
13
|
+
from rich.panel import Panel
|
|
14
|
+
from rich.table import Table
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def register_skills_commands(main: click.Group) -> None:
|
|
18
|
+
"""Register the skills command group."""
|
|
19
|
+
|
|
20
|
+
@main.group()
|
|
21
|
+
def skills():
|
|
22
|
+
"""Remote skills registry — discover and install agent skills.
|
|
23
|
+
|
|
24
|
+
Browse skills at skills.smilintux.org, search by name or tag,
|
|
25
|
+
and install skill packages into your local agent namespace.
|
|
26
|
+
|
|
27
|
+
Set SKSKILLS_REGISTRY_URL to override the default registry.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
@skills.command("list")
|
|
31
|
+
@click.option("--query", "-q", default="", help="Filter by name, description, or tag.")
|
|
32
|
+
@click.option(
|
|
33
|
+
"--registry",
|
|
34
|
+
default=None,
|
|
35
|
+
envvar="SKSKILLS_REGISTRY_URL",
|
|
36
|
+
help="Override the skills registry URL.",
|
|
37
|
+
)
|
|
38
|
+
@click.option("--json", "json_out", is_flag=True, help="Output raw JSON.")
|
|
39
|
+
def skills_list(query: str, registry: str | None, json_out: bool) -> None:
|
|
40
|
+
"""List skills available in the remote registry.
|
|
41
|
+
|
|
42
|
+
Without --query all skills are shown. With --query only skills
|
|
43
|
+
matching the name, description, or tags are returned.
|
|
44
|
+
|
|
45
|
+
Examples:
|
|
46
|
+
|
|
47
|
+
skcapstone skills list
|
|
48
|
+
|
|
49
|
+
skcapstone skills list --query syncthing
|
|
50
|
+
|
|
51
|
+
skcapstone skills list --query identity --json
|
|
52
|
+
"""
|
|
53
|
+
client = get_registry_client(registry)
|
|
54
|
+
if client is None:
|
|
55
|
+
console.print(
|
|
56
|
+
"[bold red]skskills not installed.[/] "
|
|
57
|
+
"Run: pip install skskills"
|
|
58
|
+
)
|
|
59
|
+
sys.exit(1)
|
|
60
|
+
|
|
61
|
+
try:
|
|
62
|
+
skill_entries = client.search(query) if query else client.list_skills()
|
|
63
|
+
except Exception as exc:
|
|
64
|
+
console.print(f"[bold red]Registry error:[/] {exc}")
|
|
65
|
+
sys.exit(1)
|
|
66
|
+
|
|
67
|
+
if json_out:
|
|
68
|
+
click.echo(json.dumps(skill_entries, indent=2))
|
|
69
|
+
return
|
|
70
|
+
|
|
71
|
+
if not skill_entries:
|
|
72
|
+
suffix = f" matching '{query}'" if query else ""
|
|
73
|
+
console.print(f"\n [dim]No skills found{suffix}.[/]\n")
|
|
74
|
+
return
|
|
75
|
+
|
|
76
|
+
label = f"[bold]{len(skill_entries)}[/] skill(s)"
|
|
77
|
+
if query:
|
|
78
|
+
label += f" matching [cyan]'{query}'[/]"
|
|
79
|
+
|
|
80
|
+
table = Table(show_header=True, header_style="bold", box=None, padding=(0, 2))
|
|
81
|
+
table.add_column("Name", style="cyan")
|
|
82
|
+
table.add_column("Version", style="dim")
|
|
83
|
+
table.add_column("Description")
|
|
84
|
+
table.add_column("Tags", style="dim")
|
|
85
|
+
|
|
86
|
+
for s in skill_entries:
|
|
87
|
+
table.add_row(
|
|
88
|
+
s.get("name", ""),
|
|
89
|
+
s.get("version", ""),
|
|
90
|
+
s.get("description", ""),
|
|
91
|
+
", ".join(s.get("tags", [])),
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
console.print()
|
|
95
|
+
console.print(Panel(label, title="Skills Registry", border_style="bright_blue"))
|
|
96
|
+
console.print(table)
|
|
97
|
+
console.print()
|
|
98
|
+
|
|
99
|
+
@skills.command("install")
|
|
100
|
+
@click.argument("name")
|
|
101
|
+
@click.option("--version", default=None, help="Specific version (default: latest).")
|
|
102
|
+
@click.option(
|
|
103
|
+
"--agent",
|
|
104
|
+
default="global",
|
|
105
|
+
help="Agent namespace for installation (default: global).",
|
|
106
|
+
)
|
|
107
|
+
@click.option("--force", is_flag=True, help="Overwrite an existing installation.")
|
|
108
|
+
@click.option(
|
|
109
|
+
"--registry",
|
|
110
|
+
default=None,
|
|
111
|
+
envvar="SKSKILLS_REGISTRY_URL",
|
|
112
|
+
help="Override the skills registry URL.",
|
|
113
|
+
)
|
|
114
|
+
def skills_install(
|
|
115
|
+
name: str,
|
|
116
|
+
version: str | None,
|
|
117
|
+
agent: str,
|
|
118
|
+
force: bool,
|
|
119
|
+
registry: str | None,
|
|
120
|
+
) -> None:
|
|
121
|
+
"""Download and install a skill from the remote registry.
|
|
122
|
+
|
|
123
|
+
Fetches the skill package, verifies its checksum, and installs it
|
|
124
|
+
into the local SKSkills directory for the specified agent namespace.
|
|
125
|
+
|
|
126
|
+
Examples:
|
|
127
|
+
|
|
128
|
+
skcapstone skills install syncthing-setup
|
|
129
|
+
|
|
130
|
+
skcapstone skills install pgp-identity --version 0.2.0
|
|
131
|
+
|
|
132
|
+
skcapstone skills install syncthing-setup --agent opus
|
|
133
|
+
"""
|
|
134
|
+
client = get_registry_client(registry)
|
|
135
|
+
if client is None:
|
|
136
|
+
console.print(
|
|
137
|
+
"[bold red]skskills not installed.[/] "
|
|
138
|
+
"Run: pip install skskills"
|
|
139
|
+
)
|
|
140
|
+
sys.exit(1)
|
|
141
|
+
|
|
142
|
+
ver_label = f" @{version}" if version else ""
|
|
143
|
+
agent_label = f" (agent: {agent})" if agent != "global" else ""
|
|
144
|
+
console.print(
|
|
145
|
+
f"\n Installing [cyan]{name}[/][dim]{ver_label}{agent_label}[/] ...\n"
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
try:
|
|
149
|
+
result = client.install(name, version=version, agent=agent, force=force)
|
|
150
|
+
except FileNotFoundError:
|
|
151
|
+
console.print(
|
|
152
|
+
f"[bold red]Not found:[/] skill [cyan]{name}[/] is not in the registry.\n"
|
|
153
|
+
f" Run [dim]skcapstone skills list --query {name}[/] to search."
|
|
154
|
+
)
|
|
155
|
+
console.print()
|
|
156
|
+
sys.exit(1)
|
|
157
|
+
except ValueError as exc:
|
|
158
|
+
console.print(f"[bold red]Install failed:[/] {exc}\n")
|
|
159
|
+
sys.exit(1)
|
|
160
|
+
except Exception as exc:
|
|
161
|
+
console.print(f"[bold red]Error:[/] {exc}\n")
|
|
162
|
+
sys.exit(1)
|
|
163
|
+
|
|
164
|
+
console.print(
|
|
165
|
+
f" [green]Installed:[/] [bold]{result['name']}[/] v{result['version']}"
|
|
166
|
+
)
|
|
167
|
+
console.print(f" [dim]Path: {result['install_path']}[/]")
|
|
168
|
+
console.print(f" [dim]Agent: {result['agent']}[/]\n")
|