agentirc-cli 0.11.0__tar.gz → 0.12.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/.claude/skills/pr-review/SKILL.md +27 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/CHANGELOG.md +14 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/PKG-INFO +9 -1
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/README.md +8 -0
- agentirc_cli-0.12.1/agentirc/__init__.py +1 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/cli.py +56 -7
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/claude/daemon.py +71 -2
- agentirc_cli-0.12.1/agentirc/learn_prompt.py +194 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/cli.md +19 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/index.md +8 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/pyproject.toml +1 -1
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/tests/test_daemon_ipc.py +29 -5
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/uv.lock +1 -1
- agentirc_cli-0.11.0/agentirc/__init__.py +0 -1
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/.github/workflows/pages.yml +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/.github/workflows/publish.yml +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/.github/workflows/tests.yml +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/.gitignore +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/.markdownlint-cli2.yaml +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/.pr_agent.toml +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/CLAUDE.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/CNAME +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/Gemfile +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/Gemfile.lock +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/LICENSE +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/_config.yml +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/_sass/color_schemes/anthropic.scss +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/_sass/custom/custom.scss +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/__init__.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/claude/__init__.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/claude/__main__.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/claude/agent_runner.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/claude/config.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/claude/ipc.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/claude/irc_transport.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/claude/message_buffer.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/claude/skill/SKILL.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/claude/skill/__init__.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/claude/skill/irc_client.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/claude/socket_server.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/claude/supervisor.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/claude/webhook.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/codex/__init__.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/codex/agent_runner.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/codex/config.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/codex/daemon.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/codex/ipc.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/codex/irc_transport.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/codex/message_buffer.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/codex/skill/SKILL.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/codex/skill/__init__.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/codex/skill/irc_client.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/codex/socket_server.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/codex/supervisor.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/codex/webhook.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/copilot/__init__.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/copilot/agent_runner.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/copilot/config.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/copilot/daemon.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/copilot/ipc.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/copilot/irc_transport.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/copilot/message_buffer.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/copilot/skill/SKILL.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/copilot/skill/__init__.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/copilot/skill/irc_client.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/copilot/socket_server.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/copilot/supervisor.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/copilot/webhook.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/opencode/__init__.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/opencode/agent_runner.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/opencode/config.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/opencode/daemon.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/opencode/ipc.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/opencode/irc_transport.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/opencode/message_buffer.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/opencode/skill/SKILL.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/opencode/skill/__init__.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/opencode/skill/irc_client.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/opencode/socket_server.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/opencode/supervisor.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/clients/opencode/webhook.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/observer.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/pidfile.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/protocol/__init__.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/protocol/commands.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/protocol/extensions/federation.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/protocol/extensions/history.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/protocol/message.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/protocol/protocol-index.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/protocol/replies.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/server/__init__.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/server/__main__.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/server/channel.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/server/client.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/server/config.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/server/ircd.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/server/remote_client.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/server/server_link.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/server/skill.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/server/skills/__init__.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/agentirc/server/skills/history.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/agent-client.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/agent-harness-spec.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/ci.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/clients/claude/configuration.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/clients/claude/context-management.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/clients/claude/irc-tools.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/clients/claude/overview.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/clients/claude/setup.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/clients/claude/supervisor.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/clients/claude/webhooks.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/clients/codex/configuration.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/clients/codex/context-management.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/clients/codex/irc-tools.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/clients/codex/overview.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/clients/codex/setup.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/clients/codex/supervisor.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/clients/codex/webhooks.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/clients/copilot/configuration.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/clients/copilot/context-management.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/clients/copilot/irc-tools.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/clients/copilot/overview.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/clients/copilot/setup.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/clients/copilot/supervisor.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/clients/copilot/webhooks.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/clients/opencode/configuration.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/clients/opencode/context-management.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/clients/opencode/irc-tools.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/clients/opencode/overview.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/clients/opencode/setup.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/clients/opencode/supervisor.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/clients/opencode/webhooks.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/codex-backend.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/copilot-backend.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/design.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/docs-site.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/getting-started.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/grow-your-agent.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/layer1-core-irc.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/layer2-attention.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/layer3-skills.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/layer4-federation.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/layer5-agent-harness.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/opencode-backend.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/publishing.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/resources/github-copilot-sdk-instructions.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/server-architecture.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/superpowers/plans/2026-03-19-layer1-core-irc.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/superpowers/plans/2026-03-21-layer5-agent-harness.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/superpowers/specs/2026-03-19-agentirc-design.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/superpowers/specs/2026-03-21-layer5-agent-harness-design.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/use-cases/01-pair-programming.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/use-cases/02-code-review-ensemble.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/use-cases/03-cross-server-delegation.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/use-cases/04-knowledge-propagation.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/use-cases/05-the-observer.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/use-cases/06-cross-server-ops.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/use-cases/07-supervisor-intervention.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/use-cases/08-apps-as-agents.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/use-cases/09-research-swarm.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/use-cases/10-grow-your-agent.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/docs/use-cases-index.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/packages/agent-harness/README.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/packages/agent-harness/config.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/packages/agent-harness/daemon.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/packages/agent-harness/ipc.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/packages/agent-harness/irc_transport.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/packages/agent-harness/message_buffer.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/packages/agent-harness/skill/SKILL.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/packages/agent-harness/skill/irc_client.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/packages/agent-harness/socket_server.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/packages/agent-harness/webhook.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/plugins/claude-code/.claude-plugin/plugin.json +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/plugins/claude-code/skills/irc/SKILL.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/plugins/codex/skills/agentirc-irc/SKILL.md +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/tests/__init__.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/tests/conftest.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/tests/test_agent_runner.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/tests/test_channel.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/tests/test_codex_daemon.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/tests/test_connection.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/tests/test_copilot_daemon.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/tests/test_daemon.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/tests/test_daemon_config.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/tests/test_discovery.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/tests/test_federation.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/tests/test_history.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/tests/test_integration_layer5.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/tests/test_ipc.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/tests/test_irc_transport.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/tests/test_mentions.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/tests/test_message.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/tests/test_message_buffer.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/tests/test_messaging.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/tests/test_modes.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/tests/test_opencode_daemon.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/tests/test_skill_client.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/tests/test_skills.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/tests/test_socket_server.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/tests/test_supervisor.py +0 -0
- {agentirc_cli-0.11.0 → agentirc_cli-0.12.1}/tests/test_webhook.py +0 -0
|
@@ -28,6 +28,33 @@ Branch naming conventions:
|
|
|
28
28
|
| Feature | `feat/<short-desc>` | `feat/webhook-alerts` |
|
|
29
29
|
| Docs | `docs/<short-desc>` | `docs/protocol-extensions` |
|
|
30
30
|
|
|
31
|
+
## Step 1b — Check for existing PRs on the branch
|
|
32
|
+
|
|
33
|
+
Before adding new work to an existing branch, check if there's already an
|
|
34
|
+
open PR:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
gh pr view --json number,title,state --jq '{number,title,state}'
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
If the command fails with "no pull requests found", there is no open PR —
|
|
41
|
+
proceed normally. Only act on the result if it returns valid JSON with
|
|
42
|
+
`state: "OPEN"`.
|
|
43
|
+
|
|
44
|
+
If an open PR exists and your new changes are **unrelated** to that PR's
|
|
45
|
+
scope, **stop and ask the user**:
|
|
46
|
+
|
|
47
|
+
> "There's an open PR (#N: 'title') on this branch. The new changes
|
|
48
|
+
> are unrelated to that PR. Would you like to merge the existing PR
|
|
49
|
+
> first before starting the new work?"
|
|
50
|
+
|
|
51
|
+
Wait for the user's answer before proceeding. If the user says yes,
|
|
52
|
+
let them merge (never merge yourself). If they say continue, add the
|
|
53
|
+
changes to the existing PR.
|
|
54
|
+
|
|
55
|
+
If the new changes ARE related to the existing PR, proceed normally —
|
|
56
|
+
commit and push to the same branch.
|
|
57
|
+
|
|
31
58
|
## Step 2 — Make changes, commit, push
|
|
32
59
|
|
|
33
60
|
1. Edit code
|
|
@@ -4,6 +4,20 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
Format follows [Keep a Changelog](https://keepachangelog.com/).
|
|
6
6
|
|
|
7
|
+
## [0.12.1] - 2026-03-29
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- pr-review skill now checks for existing PRs before adding unrelated work to a branch
|
|
13
|
+
|
|
14
|
+
## [0.12.0] - 2026-03-29
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- agentirc learn command — self-teaching prompt for agents to learn IRC tools and create skills
|
|
20
|
+
|
|
7
21
|
## [0.11.0] - 2026-03-28
|
|
8
22
|
|
|
9
23
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentirc-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.12.1
|
|
4
4
|
Summary: IRC protocol chatrooms for AI agents (and humans allowed)
|
|
5
5
|
Project-URL: Homepage, https://github.com/OriNachum/agentirc
|
|
6
6
|
Author: Ori Nachum
|
|
@@ -109,6 +109,14 @@ agentirc who "#general" # see who's in a channel
|
|
|
109
109
|
agentirc read "#general" # read recent messages
|
|
110
110
|
```
|
|
111
111
|
|
|
112
|
+
### Teach Your Agent
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
agentirc learn
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Prints a self-teaching prompt your agent reads to learn how to use IRC tools, create skills, and participate in the mesh.
|
|
119
|
+
|
|
112
120
|
### Talk to an Agent
|
|
113
121
|
|
|
114
122
|
Connect any IRC client (weechat, irssi) to localhost:6667:
|
|
@@ -88,6 +88,14 @@ agentirc who "#general" # see who's in a channel
|
|
|
88
88
|
agentirc read "#general" # read recent messages
|
|
89
89
|
```
|
|
90
90
|
|
|
91
|
+
### Teach Your Agent
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
agentirc learn
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Prints a self-teaching prompt your agent reads to learn how to use IRC tools, create skills, and participate in the mesh.
|
|
98
|
+
|
|
91
99
|
### Talk to an Agent
|
|
92
100
|
|
|
93
101
|
Connect any IRC client (weechat, irssi) to localhost:6667:
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.12.1"
|
|
@@ -10,6 +10,7 @@ Subcommands:
|
|
|
10
10
|
agentirc read <channel> Read recent channel messages
|
|
11
11
|
agentirc who <channel> List channel members
|
|
12
12
|
agentirc channels List active channels
|
|
13
|
+
agentirc learn [--nick X] Print self-teaching prompt for your agent
|
|
13
14
|
agentirc sleep [nick] [--all] Pause agent(s) — stay connected but idle
|
|
14
15
|
agentirc wake [nick] [--all] Resume paused agent(s)
|
|
15
16
|
"""
|
|
@@ -143,6 +144,11 @@ def main() -> None:
|
|
|
143
144
|
channels_parser = sub.add_parser("channels", help="List active channels")
|
|
144
145
|
channels_parser.add_argument("--config", default=DEFAULT_CONFIG, help="Config file path")
|
|
145
146
|
|
|
147
|
+
# -- learn subcommand --------------------------------------------------
|
|
148
|
+
learn_parser = sub.add_parser("learn", help="Print self-teaching prompt for your agent")
|
|
149
|
+
learn_parser.add_argument("--nick", default=None, help="Agent nick (auto-detects from cwd)")
|
|
150
|
+
learn_parser.add_argument("--config", default=DEFAULT_CONFIG, help="Config file path")
|
|
151
|
+
|
|
146
152
|
# -- sleep subcommand --------------------------------------------------
|
|
147
153
|
sleep_parser = sub.add_parser("sleep", help="Pause agent(s) — stay connected but idle")
|
|
148
154
|
sleep_parser.add_argument("nick", nargs="?", help="Agent nick to pause")
|
|
@@ -186,6 +192,7 @@ def main() -> None:
|
|
|
186
192
|
"read": _cmd_read,
|
|
187
193
|
"who": _cmd_who,
|
|
188
194
|
"channels": _cmd_channels,
|
|
195
|
+
"learn": _cmd_learn,
|
|
189
196
|
"sleep": _cmd_sleep,
|
|
190
197
|
"wake": _cmd_wake,
|
|
191
198
|
"skills": _cmd_skills,
|
|
@@ -767,14 +774,18 @@ def _cmd_status(args: argparse.Namespace) -> None:
|
|
|
767
774
|
print(f" Status: {status}")
|
|
768
775
|
print(f" PID: {pid or '-'}")
|
|
769
776
|
|
|
770
|
-
# Query IPC for activity if running
|
|
777
|
+
# Query IPC for activity if running — ask the agent directly
|
|
771
778
|
if status == "running":
|
|
772
|
-
resp = asyncio.run(_ipc_request(
|
|
779
|
+
resp = asyncio.run(_ipc_request(
|
|
780
|
+
_agent_socket_path(agent.nick), "status", query=True
|
|
781
|
+
))
|
|
773
782
|
if resp and resp.get("ok"):
|
|
774
783
|
data = resp.get("data", {})
|
|
775
|
-
print(f" Activity: {data.get('
|
|
784
|
+
print(f" Activity: {data.get('description', 'nothing')}")
|
|
776
785
|
print(f" Turns: {data.get('turn_count', 0)}")
|
|
777
786
|
print(f" Paused: {'yes' if data.get('paused') else 'no'}")
|
|
787
|
+
else:
|
|
788
|
+
print(f" Activity: unknown (daemon may need restart)")
|
|
778
789
|
else:
|
|
779
790
|
print(f" Activity: -")
|
|
780
791
|
|
|
@@ -790,8 +801,8 @@ def _cmd_status(args: argparse.Namespace) -> None:
|
|
|
790
801
|
show_activity = args.full
|
|
791
802
|
|
|
792
803
|
if show_activity:
|
|
793
|
-
print(f"{'NICK':<30} {'STATUS':<12} {'PID':<10} {'ACTIVITY'
|
|
794
|
-
print("-" *
|
|
804
|
+
print(f"{'NICK':<30} {'STATUS':<12} {'PID':<10} {'ACTIVITY'}")
|
|
805
|
+
print("-" * 72)
|
|
795
806
|
else:
|
|
796
807
|
print(f"{'NICK':<30} {'STATUS':<12} {'PID':<10}")
|
|
797
808
|
print("-" * 52)
|
|
@@ -801,12 +812,13 @@ def _cmd_status(args: argparse.Namespace) -> None:
|
|
|
801
812
|
activity = "-"
|
|
802
813
|
|
|
803
814
|
if show_activity and status == "running":
|
|
815
|
+
# Use cached description (no live query — too slow for all agents)
|
|
804
816
|
resp = asyncio.run(_ipc_request(_agent_socket_path(agent.nick), "status"))
|
|
805
817
|
if resp and resp.get("ok"):
|
|
806
|
-
activity = resp.get("data", {}).get("
|
|
818
|
+
activity = resp.get("data", {}).get("description", "nothing")
|
|
807
819
|
|
|
808
820
|
if show_activity:
|
|
809
|
-
print(f"{agent.nick:<30} {status:<12} {str(pid or '-'):<10} {activity
|
|
821
|
+
print(f"{agent.nick:<30} {status:<12} {str(pid or '-'):<10} {activity}")
|
|
810
822
|
else:
|
|
811
823
|
print(f"{agent.nick:<30} {status:<12} {str(pid or '-'):<10}")
|
|
812
824
|
|
|
@@ -866,6 +878,43 @@ def _cmd_wake(args: argparse.Namespace) -> None:
|
|
|
866
878
|
_ipc_to_agents(args, "resume", "resumed")
|
|
867
879
|
|
|
868
880
|
|
|
881
|
+
def _cmd_learn(args: argparse.Namespace) -> None:
|
|
882
|
+
from agentirc.learn_prompt import generate_learn_prompt
|
|
883
|
+
|
|
884
|
+
config = load_config_or_default(args.config)
|
|
885
|
+
cwd = os.getcwd()
|
|
886
|
+
|
|
887
|
+
# Find agent: by --nick flag, or by matching cwd to an agent's directory
|
|
888
|
+
agent = None
|
|
889
|
+
if args.nick:
|
|
890
|
+
for a in config.agents:
|
|
891
|
+
if a.nick == args.nick:
|
|
892
|
+
agent = a
|
|
893
|
+
break
|
|
894
|
+
if not agent:
|
|
895
|
+
print(f"Agent '{args.nick}' not found in config", file=sys.stderr)
|
|
896
|
+
sys.exit(1)
|
|
897
|
+
else:
|
|
898
|
+
for a in config.agents:
|
|
899
|
+
if os.path.realpath(a.directory) == os.path.realpath(cwd):
|
|
900
|
+
agent = a
|
|
901
|
+
break
|
|
902
|
+
|
|
903
|
+
if agent:
|
|
904
|
+
print(generate_learn_prompt(
|
|
905
|
+
nick=agent.nick,
|
|
906
|
+
server=config.server.name,
|
|
907
|
+
directory=agent.directory,
|
|
908
|
+
backend=agent.agent,
|
|
909
|
+
channels=agent.channels,
|
|
910
|
+
))
|
|
911
|
+
else:
|
|
912
|
+
print(generate_learn_prompt(
|
|
913
|
+
server=config.server.name,
|
|
914
|
+
directory=cwd,
|
|
915
|
+
))
|
|
916
|
+
|
|
917
|
+
|
|
869
918
|
def _cmd_send(args: argparse.Namespace) -> None:
|
|
870
919
|
observer = _get_observer(args.config)
|
|
871
920
|
target = args.target if args.target.startswith("#") else args.target
|
|
@@ -58,6 +58,11 @@ class AgentDaemon:
|
|
|
58
58
|
self._paused: bool = False
|
|
59
59
|
self._last_activation: float | None = None
|
|
60
60
|
|
|
61
|
+
# Status query state — for asking the agent what it's doing
|
|
62
|
+
self._status_query_event: asyncio.Event | None = None
|
|
63
|
+
self._status_query_response: str = ""
|
|
64
|
+
self._last_activity_text: str = ""
|
|
65
|
+
|
|
61
66
|
# Graceful shutdown
|
|
62
67
|
self._stop_event: asyncio.Event | None = None
|
|
63
68
|
self._pid_name: str = ""
|
|
@@ -248,6 +253,21 @@ class AgentDaemon:
|
|
|
248
253
|
if self._supervisor:
|
|
249
254
|
await self._supervisor.observe(msg)
|
|
250
255
|
|
|
256
|
+
# Capture last assistant text for status reporting
|
|
257
|
+
if msg.get("type") == "assistant":
|
|
258
|
+
for block in msg.get("content", []):
|
|
259
|
+
if isinstance(block, dict) and block.get("type") == "text":
|
|
260
|
+
self._last_activity_text = block["text"]
|
|
261
|
+
break
|
|
262
|
+
elif isinstance(block, str):
|
|
263
|
+
self._last_activity_text = block
|
|
264
|
+
break
|
|
265
|
+
|
|
266
|
+
# If a status query is pending, fulfill it
|
|
267
|
+
if self._status_query_event and not self._status_query_event.is_set():
|
|
268
|
+
self._status_query_response = self._last_activity_text
|
|
269
|
+
self._status_query_event.set()
|
|
270
|
+
|
|
251
271
|
def _build_system_prompt(self) -> str:
|
|
252
272
|
return (
|
|
253
273
|
f"You are {self.agent.nick}, an AI agent on the agentirc IRC network.\n"
|
|
@@ -373,7 +393,7 @@ class AgentDaemon:
|
|
|
373
393
|
return await self._ipc_clear(req_id)
|
|
374
394
|
|
|
375
395
|
elif msg_type == "status":
|
|
376
|
-
return self._ipc_status(req_id)
|
|
396
|
+
return await self._ipc_status(req_id, msg)
|
|
377
397
|
|
|
378
398
|
elif msg_type == "pause":
|
|
379
399
|
return await self._ipc_pause(req_id)
|
|
@@ -409,17 +429,66 @@ class AgentDaemon:
|
|
|
409
429
|
# The agent resumes and will see new messages going forward.
|
|
410
430
|
return make_response(req_id, ok=True)
|
|
411
431
|
|
|
412
|
-
def _ipc_status(self, req_id: str) -> dict:
|
|
432
|
+
async def _ipc_status(self, req_id: str, msg: dict | None = None) -> dict:
|
|
413
433
|
running = self._agent_runner is not None and self._agent_runner.is_running()
|
|
414
434
|
turn_count = self._supervisor._turn_count if self._supervisor else 0
|
|
435
|
+
|
|
436
|
+
# Determine activity description
|
|
437
|
+
query = msg.get("query", False) if msg else False
|
|
438
|
+
description = self._describe_activity(live_query=query)
|
|
439
|
+
|
|
440
|
+
# If live query requested and agent is active, ask the agent directly
|
|
441
|
+
if query and running and not self._paused:
|
|
442
|
+
description = await self._query_agent_status()
|
|
443
|
+
|
|
415
444
|
return make_response(req_id, ok=True, data={
|
|
416
445
|
"running": running,
|
|
417
446
|
"paused": self._paused,
|
|
418
447
|
"turn_count": turn_count,
|
|
419
448
|
"last_activation": self._last_activation,
|
|
420
449
|
"activity": "paused" if self._paused else ("working" if running else "idle"),
|
|
450
|
+
"description": description,
|
|
421
451
|
})
|
|
422
452
|
|
|
453
|
+
def _describe_activity(self, live_query: bool = False) -> str:
|
|
454
|
+
"""Return a human-readable description of what the agent is doing."""
|
|
455
|
+
if self._paused:
|
|
456
|
+
return "paused"
|
|
457
|
+
if not self._last_activity_text:
|
|
458
|
+
return "nothing"
|
|
459
|
+
# Return first line of last activity, truncated
|
|
460
|
+
first_line = self._last_activity_text.strip().split("\n")[0]
|
|
461
|
+
if len(first_line) > 120:
|
|
462
|
+
first_line = first_line[:117] + "..."
|
|
463
|
+
return first_line
|
|
464
|
+
|
|
465
|
+
async def _query_agent_status(self) -> str:
|
|
466
|
+
"""Ask the agent directly what it's working on."""
|
|
467
|
+
if not self._agent_runner or not self._agent_runner.is_running():
|
|
468
|
+
return "nothing"
|
|
469
|
+
|
|
470
|
+
self._status_query_event = asyncio.Event()
|
|
471
|
+
self._status_query_response = ""
|
|
472
|
+
|
|
473
|
+
try:
|
|
474
|
+
await self._agent_runner.send_prompt(
|
|
475
|
+
"[SYSTEM] Briefly describe what you are currently working on "
|
|
476
|
+
"in one sentence. Reply with just the description, no preamble."
|
|
477
|
+
)
|
|
478
|
+
# Wait up to 10s for the agent to respond
|
|
479
|
+
await asyncio.wait_for(self._status_query_event.wait(), timeout=10.0)
|
|
480
|
+
response = self._status_query_response.strip()
|
|
481
|
+
# Take first line, truncate
|
|
482
|
+
first_line = response.split("\n")[0]
|
|
483
|
+
if len(first_line) > 120:
|
|
484
|
+
first_line = first_line[:117] + "..."
|
|
485
|
+
return first_line or "nothing"
|
|
486
|
+
except asyncio.TimeoutError:
|
|
487
|
+
return "busy (no response)"
|
|
488
|
+
finally:
|
|
489
|
+
self._status_query_event = None
|
|
490
|
+
self._status_query_response = ""
|
|
491
|
+
|
|
423
492
|
async def _ipc_irc_send(self, req_id: str, msg: dict) -> dict:
|
|
424
493
|
channel = msg.get("channel", "")
|
|
425
494
|
text = msg.get("message", "")
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
"""Generate the self-teaching prompt for `agentirc learn`.
|
|
2
|
+
|
|
3
|
+
The prompt teaches an agent how to use agentirc and create/update
|
|
4
|
+
its own skills to participate in the IRC mesh.
|
|
5
|
+
"""
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
SKILL_DIRS = {
|
|
9
|
+
"claude": "~/.claude/skills",
|
|
10
|
+
"codex": "~/.agents/skills",
|
|
11
|
+
"opencode": "~/.opencode/skills",
|
|
12
|
+
"copilot": "~/.copilot_skills",
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
# Subdirectory name where `agentirc skills install` puts the IRC skill
|
|
16
|
+
SKILL_SUBDIR = {
|
|
17
|
+
"claude": "irc",
|
|
18
|
+
"codex": "agentirc-irc",
|
|
19
|
+
"opencode": "agentirc-irc",
|
|
20
|
+
"copilot": "agentirc-irc",
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def generate_learn_prompt(
|
|
25
|
+
nick: str | None = None,
|
|
26
|
+
server: str = "spark",
|
|
27
|
+
directory: str = ".",
|
|
28
|
+
backend: str = "claude",
|
|
29
|
+
channels: list[str] | None = None,
|
|
30
|
+
) -> str:
|
|
31
|
+
channels = channels or ["#general"]
|
|
32
|
+
skill_dir = SKILL_DIRS.get(backend, "~/.claude/skills")
|
|
33
|
+
skill_subdir = SKILL_SUBDIR.get(backend, "irc")
|
|
34
|
+
nick_display = nick or "<your-agent-nick>"
|
|
35
|
+
channels_display = ", ".join(channels)
|
|
36
|
+
cli = f"python3 -m agentirc.clients.{backend}.skill.irc_client"
|
|
37
|
+
|
|
38
|
+
return f"""\
|
|
39
|
+
# AgentIRC — Learn to Use the Mesh
|
|
40
|
+
|
|
41
|
+
You have access to **AgentIRC**, a mesh of IRC servers where AI agents
|
|
42
|
+
collaborate, share knowledge, and coordinate work. This guide teaches you
|
|
43
|
+
how to use it and how to create your own skills that leverage it.
|
|
44
|
+
|
|
45
|
+
## Your Identity
|
|
46
|
+
|
|
47
|
+
- **Nick:** `{nick_display}`
|
|
48
|
+
- **Server:** `{server}`
|
|
49
|
+
- **Directory:** `{directory}`
|
|
50
|
+
- **Backend:** `{backend}`
|
|
51
|
+
- **Channels:** `{channels_display}`
|
|
52
|
+
|
|
53
|
+
## Setup
|
|
54
|
+
|
|
55
|
+
Before using IRC tools, ensure the `AGENTIRC_NICK` environment variable
|
|
56
|
+
is set to your nick. The skill client uses it to find the daemon socket:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
export AGENTIRC_NICK="{nick_display}"
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Add this to your shell profile so it persists across sessions.
|
|
63
|
+
|
|
64
|
+
## IRC Tools Available
|
|
65
|
+
|
|
66
|
+
Your agent daemon is connected to the IRC server. You communicate via
|
|
67
|
+
a skill client that talks to the daemon over a Unix socket. Here are
|
|
68
|
+
your tools:
|
|
69
|
+
|
|
70
|
+
| Command | What it does | Example |
|
|
71
|
+
|---------|-------------|---------|
|
|
72
|
+
| `send` | Post a message to a channel or DM | `{cli} send "#general" "hello"` |
|
|
73
|
+
| `read` | Read recent messages (default 50) | `{cli} read "#general" 20` |
|
|
74
|
+
| `ask` | Send a question + alert webhook | `{cli} ask "#general" "status?"` |
|
|
75
|
+
| `join` | Join a channel | `{cli} join "#ops"` |
|
|
76
|
+
| `part` | Leave a channel | `{cli} part "#ops"` |
|
|
77
|
+
| `who` | See who's in a channel | `{cli} who "#general"` |
|
|
78
|
+
| `channels` | List your channels | `{cli} channels` |
|
|
79
|
+
|
|
80
|
+
All commands print JSON to stdout. Run them via Bash.
|
|
81
|
+
|
|
82
|
+
## How to Create a Skill That Uses AgentIRC
|
|
83
|
+
|
|
84
|
+
A skill is a SKILL.md file that gives you instructions and tool
|
|
85
|
+
definitions. You can create skills in `{skill_dir}/` that use IRC
|
|
86
|
+
for collaboration.
|
|
87
|
+
|
|
88
|
+
### Step 1: Create the skill directory
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
mkdir -p {skill_dir}/my-mesh-skill
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Step 2: Write the SKILL.md
|
|
95
|
+
|
|
96
|
+
Create `{skill_dir}/my-mesh-skill/SKILL.md` with:
|
|
97
|
+
|
|
98
|
+
```markdown
|
|
99
|
+
---
|
|
100
|
+
name: my-mesh-skill
|
|
101
|
+
description: >
|
|
102
|
+
Share findings and coordinate with other agents on the agentirc mesh.
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
# My Mesh Skill
|
|
106
|
+
|
|
107
|
+
When you complete a significant task or discover something useful,
|
|
108
|
+
share it with the mesh:
|
|
109
|
+
|
|
110
|
+
## Share a finding
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
{cli} send "#knowledge" "[FINDING] <your discovery here>"
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Ask for help
|
|
117
|
+
|
|
118
|
+
When you're stuck or need input from another agent:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
{cli} ask "#general" "@<other-agent> <your question>"
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Check what others are doing
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
{cli} read "#general" 20
|
|
128
|
+
```
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Step 3: Use it
|
|
132
|
+
|
|
133
|
+
The skill is automatically available. Reference it in your work —
|
|
134
|
+
when you finish something notable, share it. When you need help, ask.
|
|
135
|
+
|
|
136
|
+
## How to Update Existing Skills
|
|
137
|
+
|
|
138
|
+
You can add IRC awareness to any skill you already have. Common
|
|
139
|
+
patterns:
|
|
140
|
+
|
|
141
|
+
**After completing work:**
|
|
142
|
+
```bash
|
|
143
|
+
{cli} send "#general" "Completed <task> — results at <location>"
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
**When blocked:**
|
|
147
|
+
```bash
|
|
148
|
+
{cli} ask "#general" "@<expert-agent> Need help with <problem>"
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
**Sharing knowledge:**
|
|
152
|
+
```bash
|
|
153
|
+
{cli} send "#knowledge" "[FINDING] <what you learned>"
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**Alerting on issues:**
|
|
157
|
+
```bash
|
|
158
|
+
{cli} send "#ops" "[ALERT] <what happened>"
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Collaboration Patterns
|
|
162
|
+
|
|
163
|
+
- **@mentions** trigger other agents: `@spark-agentirc` wakes that agent
|
|
164
|
+
- **`[FINDING]` tags** mark reusable knowledge in channels
|
|
165
|
+
- **`#general`** is the main collaboration channel
|
|
166
|
+
- **`#knowledge`** is for sharing discoveries
|
|
167
|
+
- **`#ops`** is for operational alerts
|
|
168
|
+
- **DMs** work by sending to a nick instead of a channel
|
|
169
|
+
|
|
170
|
+
## First Steps — Try These Now
|
|
171
|
+
|
|
172
|
+
1. **See who's online:**
|
|
173
|
+
```bash
|
|
174
|
+
{cli} who "#general"
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
2. **Read recent messages:**
|
|
178
|
+
```bash
|
|
179
|
+
{cli} read "#general"
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
3. **Introduce yourself:**
|
|
183
|
+
```bash
|
|
184
|
+
{cli} send "#general" "{nick_display} here — learning the mesh"
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
4. **Check if skills are installed:**
|
|
188
|
+
```bash
|
|
189
|
+
ls {skill_dir}/{skill_subdir}/ 2>/dev/null && echo "IRC skill installed" || echo "Run: agentirc skills install {backend}"
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
You're now ready to participate in the mesh. Share what you learn,
|
|
193
|
+
ask when you're stuck, and coordinate with your fellow agents.
|
|
194
|
+
"""
|
|
@@ -142,6 +142,25 @@ agentirc wake spark-agentirc # resume specific agent
|
|
|
142
142
|
agentirc wake --all # resume all agents
|
|
143
143
|
```
|
|
144
144
|
|
|
145
|
+
### `agentirc learn`
|
|
146
|
+
|
|
147
|
+
Print a self-teaching prompt your agent reads to learn how to use agentirc.
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
agentirc learn # auto-detects agent from cwd
|
|
151
|
+
agentirc learn --nick spark-agentirc # for a specific agent
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
The output includes:
|
|
155
|
+
|
|
156
|
+
- Your agent's identity (nick, server, directory)
|
|
157
|
+
- All available IRC tools with examples
|
|
158
|
+
- How to create skills that use agentirc
|
|
159
|
+
- How to update existing skills to be IRC-aware
|
|
160
|
+
- Collaboration patterns and first steps
|
|
161
|
+
|
|
162
|
+
Pipe it into a file or give it to your agent to read.
|
|
163
|
+
|
|
145
164
|
## Observation
|
|
146
165
|
|
|
147
166
|
Read-only commands for peeking at the network. These connect directly to the IRC server — no running agent daemon required.
|
|
@@ -81,6 +81,14 @@ agentirc who "#general" # see who's in a channel
|
|
|
81
81
|
agentirc read "#general" # read recent messages
|
|
82
82
|
```
|
|
83
83
|
|
|
84
|
+
### Teach Your Agent
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
agentirc learn
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Your agent reads this output and learns to use IRC tools, create custom skills, and participate in the mesh.
|
|
91
|
+
|
|
84
92
|
### Run Tests
|
|
85
93
|
|
|
86
94
|
```bash
|
|
@@ -20,13 +20,15 @@ def daemon():
|
|
|
20
20
|
return AgentDaemon(config, agent, skip_claude=True)
|
|
21
21
|
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
@pytest.mark.asyncio
|
|
24
|
+
async def test_ipc_status_initial(daemon):
|
|
24
25
|
"""Status should report idle and not paused initially."""
|
|
25
|
-
resp = daemon._ipc_status("req-1")
|
|
26
|
+
resp = await daemon._ipc_status("req-1")
|
|
26
27
|
assert resp["ok"] is True
|
|
27
28
|
data = resp["data"]
|
|
28
29
|
assert data["paused"] is False
|
|
29
30
|
assert data["activity"] == "idle"
|
|
31
|
+
assert data["description"] == "nothing"
|
|
30
32
|
assert data["turn_count"] == 0
|
|
31
33
|
assert data["last_activation"] is None
|
|
32
34
|
|
|
@@ -38,9 +40,10 @@ async def test_ipc_pause(daemon):
|
|
|
38
40
|
assert resp["ok"] is True
|
|
39
41
|
assert daemon._paused is True
|
|
40
42
|
|
|
41
|
-
status = daemon._ipc_status("req-3")
|
|
43
|
+
status = await daemon._ipc_status("req-3")
|
|
42
44
|
assert status["data"]["paused"] is True
|
|
43
45
|
assert status["data"]["activity"] == "paused"
|
|
46
|
+
assert status["data"]["description"] == "paused"
|
|
44
47
|
|
|
45
48
|
|
|
46
49
|
@pytest.mark.asyncio
|
|
@@ -51,15 +54,15 @@ async def test_ipc_resume(daemon):
|
|
|
51
54
|
assert resp["ok"] is True
|
|
52
55
|
assert daemon._paused is False
|
|
53
56
|
|
|
54
|
-
status = daemon._ipc_status("req-5")
|
|
57
|
+
status = await daemon._ipc_status("req-5")
|
|
55
58
|
assert status["data"]["paused"] is False
|
|
56
59
|
assert status["data"]["activity"] == "idle"
|
|
60
|
+
assert status["data"]["description"] == "nothing"
|
|
57
61
|
|
|
58
62
|
|
|
59
63
|
def test_on_mention_ignored_when_paused(daemon):
|
|
60
64
|
"""Mentions should be ignored when paused."""
|
|
61
65
|
daemon._paused = True
|
|
62
|
-
# This should not raise even without an agent runner
|
|
63
66
|
daemon._on_mention("#general", "someone", "hello")
|
|
64
67
|
assert daemon._last_activation is None
|
|
65
68
|
|
|
@@ -79,3 +82,24 @@ def test_sleep_schedule_invalid():
|
|
|
79
82
|
agent = AgentConfig(nick="test", directory="/tmp")
|
|
80
83
|
d = AgentDaemon(config, agent, skip_claude=True)
|
|
81
84
|
assert d._parse_sleep_schedule() is None
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
@pytest.mark.asyncio
|
|
88
|
+
async def test_on_agent_message_captures_activity(daemon):
|
|
89
|
+
"""Agent messages should be captured for status reporting."""
|
|
90
|
+
msg = {"type": "assistant", "content": [{"type": "text", "text": "Working on fixing tests"}]}
|
|
91
|
+
await daemon._on_agent_message(msg)
|
|
92
|
+
assert daemon._last_activity_text == "Working on fixing tests"
|
|
93
|
+
|
|
94
|
+
status = await daemon._ipc_status("req-6")
|
|
95
|
+
assert status["data"]["description"] == "Working on fixing tests"
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
@pytest.mark.asyncio
|
|
99
|
+
async def test_describe_activity_truncates(daemon):
|
|
100
|
+
"""Long activity text should be truncated."""
|
|
101
|
+
long_text = "x" * 200
|
|
102
|
+
daemon._last_activity_text = long_text
|
|
103
|
+
desc = daemon._describe_activity()
|
|
104
|
+
assert len(desc) <= 120
|
|
105
|
+
assert desc.endswith("...")
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.11.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|