Commit Graph
27 Commits
Author SHA1 Message Date
rootandAbiba (pi) aa305ce431 Add hermes-enhancement/: pi-style behavioral enhancement for Hermes agents
Self-service enhancement package for Hermes agents to adopt pi-style
conduct quality. Contains:
- prompts/behavioral-core.md: Distilled Three Pillars (~800 tokens)
- config/compression.yaml: 256K model optimization (80% threshold)
- config/mcp-servers.yaml: Tool parity (Context7, GitHub, Firecrawl, etc.)
- skills/: On-demand skills for conduct, verification, self-healing
- CHECKLIST-POC.md: Tanko POC verification checklist

POC pilot: Tanko
2026-06-27 19:03:43 +00:00
Abiba (pi) 7e6536ea57 fix(agent-zero): auto-date in system prompt, env vars for config
CI / validate (pull_request) Failing after 1s
CI / validate (push) Failing after 4s
v1.0.5
2026-06-27 18:57:32 +00:00
Abiba (pi) 4db655d4f9 feat(agent-zero): uvicorn A2A server calling LiteLLM directly
CI / validate (pull_request) Failing after 1s
2026-06-27 18:44:56 +00:00
Abiba (pi) 1cf6c2f806 feat(agent-zero): working A2A server with Agent Zero core integration
CI / validate (pull_request) Failing after 2s
A2A server uses Agent Zero's AgentContext.communicate() directly
to process Zulip messages inside the container.

Full chain verified: Zulip DM -> adapter -> A2A -> Agent Zero -> response -> Zulip
2026-06-27 18:21:20 +00:00
Abiba (pi) c6beb650c4 feat(agent-zero): Zulip adapter with A2A protocol for kagentz
CI / validate (pull_request) Failing after 2s
New project: agent-zero-zulip/ — direct Zulip integration for Agent Zero
agents using A2A protocol internally.

Architecture:
  kagentz (CT 105) ┌──────────────────────┐
                    │ Zulip Adapter  ◄──►  │ Agent Zero
                    │ polls Zulip    A2A   │ Docker container
                    │ port 8001            │
                    └──────────────────────┘

- adapter.py: Zulip event queue poller + A2A client
- No intermediate bridge — direct kagentz ↔ Zulip
- Heartbeat, reconnection, placeholder→edit streaming
- Designed for re-use: scottdenya, future Agent Zero agents
2026-06-27 18:04:00 +00:00
Abiba (pi) 1b0f1c627a fix(zulip): connect() accepts **kwargs for is_reconnect flag
CI / validate (pull_request) Failing after 1s
Hermes Gateway passes is_reconnect=True to connect() on reconnection.
Without **kwargs, the adapter crashes on reconnect.
2026-06-27 15:21:49 +00:00
Abiba (pi) 3690a7f568 fix(zulip): use PATCH /api/v1/messages/{id} for message editing
CI / validate (pull_request) Failing after 2s
Zulip API edits messages via PATCH /api/v1/messages/{message_id}
(POST returns 405 on this endpoint). Also:
- edit_message() now returns SendResult (not bool) for Gateway compatibility
- Clean up duplicate gateway instances before restart
2026-06-27 14:20:14 +00:00
Abiba (pi) 870f64d8a9 fix(zulip): edit_message accepts **kwargs, returns SendResult; use POST for edits
CI / validate (pull_request) Failing after 2s
The Gateway streaming interface calls edit_message() with finalize=True
and expects SendResult. Fixed:
1. Added **kwargs to edit_message() signature — silently ignores finalize
2. Changed return type from bool to SendResult for Gateway compatibility
3. Switched from PATCH to POST /api/v1/messages/{id} — Zulip docs use
   POST for message editing (PATCH returns 405 Method Not Allowed)
4. Same fixes applied to delete_message() and send()

Discovered during Tanko Gen 4 testing.
2026-06-27 14:18:42 +00:00
Abiba (pi) 48bc66b42f feat(zulip): Gen 4 — connection pool recovery, heartbeat logging, log sanitization
CI / validate (pull_request) Failing after 6s
Fixes 4 critical reliability issues discovered during Zulip server outage recovery:

1. CLOSE-WAIT socket leak: _reconnect() now creates a fresh httpx.AsyncClient()
   when the queue expires, preventing stuck connection pool. Old client is
   explicitly aclose()'d.

2. Silent poll loop death: After sustained 502 errors, the poll loop was
   returning [] without logging — transport errors are swallowed by _api_call
   returning (None, 0). Added heartbeat logging every 5 minutes and silence
   detection warnings after 60s of no events.

3. HTTP client stuck pool: Added proactive client recreation after 20 consecutive
   empty polls (connection pool exhaustion detection) and periodic refresh every
   500 polls (connection reuse limit).

4. Log spam: 502 error responses from Netbird contain full HTML pages — now
   truncated to 80 chars with newlines stripped.

Also:
- Support ZULIP_URL env var (in addition to ZULIP_SITE)
- expose silence_seconds, consecutive_empty_polls, client_pool_resets in health stats
- Reduced health callback interval from 600s to 300s
2026-06-27 14:12:52 +00:00
Abiba (pi) 6bb438de6e fix(zulip): remove invalid kwargs from SendResult calls
SendResult only accepts: success, message_id, error, raw_response,
retryable. The adapter was passing platform=, chat_id=, and metadata=
which are not valid fields, causing TypeError on every send attempt.

This was the error Tanko was showing in Zulip:
'SendResult.__init__() got an unexpected keyword argument "platform"'
v1.0.4
2026-06-27 11:34:14 +00:00
Abiba (pi) b1bef9024f fix(zulip): resolve bot user_id from /users/me for @mention detection
The /register endpoint doesn't always return user_id on all Zulip
server versions. Added _resolve_bot_user_id() that queries the
/users/me endpoint as a fallback. This ensures @mention detection
(is_direct_mention check) works even when register doesn't provide it.

Also bumped to v1.0.3 — cumulative fixes since v1.0.1:
- v1.0.2: BAD_EVENT_QUEUE_ID detection (silent queue expiry)
- v1.0.3: bot user_id resolution (@mention detection)
v1.0.3
2026-06-27 05:51:12 +00:00
Abiba (pi) dcf2de0052 fix(zulip): detect BAD_EVENT_QUEUE_ID instead of silently swallowing it
Root cause of Tanko not responding to DMs after initial connection:
Zulip event queues expire after ~10min of dont_block polling. When the
queue expired, _api_call() returned None for all 400-level errors, which
_fetch_events() treated as 'no events' and returned []. The poll loop
never knew the queue died, so it never reconnected.

Fix:
1. _api_call() now returns (Optional[Dict], status_code) tuple
2. _fetch_events() explicitly checks for 400 status and raises
   RuntimeError('BAD_EVENT_QUEUE_ID') for the poll loop to catch
3. All callers updated to unpack the tuple

Now when a queue expires, the poll loop catches the error and
calls _reconnect() to register a fresh queue.
v1.0.2
2026-06-27 05:50:13 +00:00
Abiba (pi) 715d54564f fix(zulip): pass Platform enum instead of string to BasePlatformAdapter.__init__
Root cause of 'str' object has no attribute 'value' error during connect():
the adapter passed a raw string 'zulip' to the base class's platform
parameter, which expects a Platform enum instance. When self.name was
accessed (calling self.platform.value.title()), the string had no .value
attribute.

Fix: import Platform from gateway.config and wrap with Platform('zulip').
v1.0.1
2026-06-27 05:33:46 +00:00
Abiba (pi) 10e4e0374f feat: Gen 4 — deployment scripts, v1.0.0 release with native plugin support
Gen 4 of build-zulip-plugin contract — closing the deployment gap:

1. Rewrote deploy.sh for dual-mode deployment
   - --mode=native: deploys to ~/.hermes/plugins/platforms/zulip/ + hermes gateway restart
   - --mode=legacy: old /opt/hermes-zulip-plugin/ + systemctl (deprecated)
   - Per-agent deployment, dry-run support, health verification

2. Added verify-deployment.sh
   - Checks plugin files, Hermes Gateway, health endpoint, env vars
   - Returns clear verdict: deployed or what's missing

3. Updated ARCHITECTURE.md to v2
   - Documents native plugin as CURRENT, old systemd as DEPRECATED
   - Cross-references hermes-zulip-plugin/DEPRECATED.md

4. Tagged v1.0.0 — 14/14 Success Criteria met, deployable
v1.0.0
2026-06-27 05:17:42 +00:00
Abiba (pi) 0acf1068bf feat(hermes): Zulip adapter Gen 3 — malformed message resilience, periodic @all-bots refresh, health callback
Gen 3 improvements from build-zulip-plugin contract run:

1. Malformed message resilience
   - Per-event try/except in poll loop — one bad event never kills adapter
   - malformed_events counter tracked in health stats
   - Fulfills Success Criterion: handles_malformed_messages == true

2. Periodic @all-bots refresh
   - _all_bots_refresh_forever() background task re-resolves every hour
   - Cancelled gracefully on disconnect()
   - all_bots_refreshes counter in health stats

3. Health stats callback mechanism
   - set_health_callback(callback, interval=600) — register external consumer
   - _report_health_if_callback() triggers on dedup cleanup cycle
   - Designed for Hermes Gateway to wire to RA-H OS knowledge graph logging
   - Cross-contract integration: get_all_bots_user_id() and get_bot_user_id()
     exposed for zulip-mention-reliability contract
2026-06-26 22:31:16 +00:00
Abiba (pi) 1c8f48fd77 feat(hermes): Zulip adapter Gen 2 — dedup cleanup task, self-test, health stats, dynamic all-bots
Gen 2 improvements from build-zulip-plugin contract run:

1. Background dedup maintenance task
   - _dedup_cleanup_forever() runs every 120s, pruning stale entries
   - _is_duplicate() is now pure O(1) — no per-call cleanup overhead
   - Cleanup is cancelled gracefully on disconnect

2. Self-test diagnostics (selftest())
   - 8 checks: connection, queue, HTTP client, bot identity, poll loop,
     dedup cleanup, echo prevention, @all-bots configuration
   - Returns structured verdict: healthy / degraded / critical_failure
   - Verifies every Success Criterion from the contract

3. Health stats tracking (get_health_stats())
   - Uptime, poll counts/errors, message routing counts, send stats
   - Error rate computation, dedup map size
   - Suitable for periodic RA-H OS knowledge graph logging

4. Dynamic @all-bots resolution
   - _resolve_all_bots_user_id() queries Zulip /api/v1/users on connect
   - Falls back to configured env var or hardcoded default (1)
   - Eliminates fragile hardcoded default in multi-bot deployments

5. Connection lifecycle now manages both poll_task and dedup_cleanup_task
   - Both cancelled gracefully on disconnect()
   - dedup task starts in connect() after queue registration
2026-06-26 22:23:38 +00:00
Abiba (pi) 2ee8a4d818 feat: Hermes Zulip native platform plugin — deprecates old standalone service
CI / validate (pull_request) Failing after 2s
Builds on the NousResearch Hermes Agent plugin system:

- plugins/platforms/zulip/ — full BasePlatformAdapter implementation
  - Zulip event queue polling (like pi-zulip-extension)
  - DM-first + @mention + @all-bots routing
  - Placeholder→edit streaming UX
  - Typing indicators
  - Deduplication and echo-loop prevention
  - Auto-registers via register(ctx) — zero core changes
  - plugin.yaml with full env var schema
- hermes-zulip-plugin/DEPRECATED.md — migration guide from old subprocess-based service

Configuration:
  Env vars: ZULIP_SITE, ZULIP_EMAIL, ZULIP_API_KEY (required)
  Config: platforms.zulip.extra in Hermes config.yaml
2026-06-25 21:22:52 +00:00
Abiba (pi) 397efef776 feat(hermes): full Zulip adapter with subprocess agent routing + streaming
CI / validate (pull_request) Failing after 1s
Complete rewrite of hermes-zulip-plugin following the same architecture
validated in pi-zulip-extension:

- Zulip event queue registration + async poll loop (replaces deprecated
  call_on_each_message threaded approach)
- DM-first processing (ADR-001/ADR-002): all private messages routed to agent
- @mention and @all-bots detection (ADR-005/ADR-006) with mention cleanup
- Subprocess agent invocation (configurable via agent.command) with stdin
  message passing and stdout response capture
- Placeholder + edit pattern: sends 'Thinking...' immediately, edits with
  final response (like pi extension streaming)
- Typing indicators (start/stop) via REST API
- Typing indicator support via REST API
- 10K Zulip char limit with graceful truncation
- Error handling: timeout, FileNotFoundError, agent crash → graceful Zulip msg
- Health endpoint (:9200) in background thread
- CLI entry point: python3 -m hermes_zulip --config config.yaml
2026-06-24 20:47:47 +00:00
Abiba (pi) 0a7b69f386 fix: raise Zulip truncation limit from 1500 to 10000 (Zulip max)
CI / validate (pull_request) Failing after 1s
2026-06-24 20:33:55 +00:00
Abiba (pi) ad802100f3 feat(zulip): streaming responses + steering via session injection
CI / validate (pull_request) Failing after 2s
- Adds message_update handler that periodically edits the Zulip
  placeholder with partial response text (every ~2s during streaming)
- Sends a 'Thinking...' placeholder to Zulip immediately on DM receipt
- Detects agent busy state and uses deliverAs: 'steer' so subsequent
  Zulip DMs steer the conversation mid-stream (like terminal TUI)
- Adds editMessage() to the queue helper (Zulip PATCH /messages/{id})
- sendMessage() now returns the message ID for editing
- Turn_start / agent_end lifecycle tracks agent busy state
- Cleanup: streaming timer properly cleared on shutdown
2026-06-24 20:30:55 +00:00
jerome 0079d11d94 Merge pull request 'fix: replace subprocess spawn with direct session injection for Zulip extension' (#22) from fix/zulip-session-injection into main
CI / validate (push) Failing after 1s
Reviewed-on: #22
2026-06-24 20:25:56 +00:00
Abiba (pi) ab3cb50eb4 fix(zulip): replace subprocess spawn with direct session injection
CI / validate (pull_request) Failing after 3s
- Removed spawnSync subprocess (pi -p --mode json) for Zulip DM processing
- Messages now inject directly into the current pi session via
  pi.sendUserMessage(), reusing the already-hot LLM — zero cold-start
- agent_end event handler captures assistant response and relays it to Zulip
- Added pending reply queue for ordered delivery of multiple Zulip messages
- Fixed zulip-js import (CJS default export, not named createClient)
- Added types.d.ts for zulip-js with default export declaration
- Updated package.json with yaml dependency, @earendil-works/pi-coding-agent
- Config supports both nested YAML and flat env-var formats
- Removed all subprocess timeout/buffer error paths (no longer needed)
2026-06-24 20:24:27 +00:00
kagentz-bot 154454ac6d feat: define shared swarm config schema (Issue #4)
CI / validate (push) Failing after 1s
- Add config.yaml.example as multi-agent swarm schema
- 7 bot users across 3 platforms: hermes (4), pi (1), agent-zero (1), @all-bots
- All owner_email values confirmed:
  - tanko, mumuni, abiba, kagentz -> jerome@sysloggh.com
  - koonimo -> jeremytabiri@gmail.com
  - koby -> theo@sysloggh.com
- DRY: deploy.sh AGENTS array should derive from config.yaml in future
- config.yaml is gitignored (secrets-safe); created locally with full data
2026-06-20 00:25:25 -04:00
jerome b60d541d6c docs: update architecture and config schema; feat: enhance hermes adapter and deploy script
CI / validate (push) Failing after 1s
2026-06-19 22:51:13 -04:00
Abiba (pi) ea262a38bb feat: add GitOps workflow — branch strategy, PR template, deploy/rollback scripts, CI skeleton
CI / validate (push) Failing after 11s
- docs/GITOPS.md: complete workflow from prototype to production
- .gitea/pull_request_template.md: pre-merge checklist for swarm PR review
- scripts/deploy.sh: tag-based deployment to all 6 CTs with health checks
- scripts/rollback.sh: rollback to previous tag
- .gitea/workflows/ci.yml: CI pipeline (activates when Actions runners available)
- .gitignore: prevent config.yaml and secrets from being committed
- .gitattributes: consistent LF line endings across platforms
2026-06-20 00:07:37 +00:00
Abiba (pi) 66c6d4966e fix: correct Abiba platform label (pi not openclaw), add plugin skeletons, shared config, fix health port
- Replace all 'openclaw' references with 'pi' (pi coding harness)
- Fix Git remote URL in CONTEXT.md
- Harmonize health port to 9200 across all docs
- Add config.yaml.example with full schema
- Add pi-zulip-extension skeleton (TypeScript, pi Extension API)
- Add hermes-zulip-plugin skeleton (Python, BasePlatformAdapter)
- Add agent-zero-plugin skeleton (Python, A0 plugin API)
- Update ADR-007 with pi extension docs reference
- Document private topic ACL v1 limitation in CONTEXT.md
2026-06-19 23:55:19 +00:00
kagentz-bot fe434553a8 feat: initial monorepo with PRD, 12 ADRs, and plugin skeletons 2026-06-19 18:37:27 -04:00