@shadowob/connector 1.1.3-dev.251

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.
@@ -0,0 +1,176 @@
1
+ # Hermes Shadow/OpenClaw Buddy Platform Plugin
2
+
3
+ This is a first-pass Hermes gateway platform adapter for Shadow/OpenClaw Buddy. It is packaged as a user plugin directory named `shadowob`.
4
+
5
+ It focuses on the messaging path:
6
+
7
+ - Shadow channel/direct/thread inbound messages to Hermes `MessageEvent`
8
+ - Hermes outbound text replies to Shadow messages
9
+ - `threadId` and `replyToId` routing via Hermes metadata
10
+ - Socket.IO realtime receive with REST polling fallback
11
+ - Optional REST-only polling mode
12
+ - Startup catch-up window
13
+ - Typing/activity emit over Socket.IO
14
+ - Inbound attachment download into Hermes media/document cache
15
+ - Outbound image/document/video/audio upload through Shadow media API
16
+ - Message edit/delete support for Hermes streaming/fresh-final cleanup
17
+ - Reaction helpers exposed on the adapter class
18
+ - Agent heartbeat/online status after resolving the Buddy agent id from `/api/auth/me`
19
+ - Dynamic channel and policy discovery through `/api/agents/:id/config`
20
+ - Optional slash command registration and slash-command prompt handling through `SHADOW_SLASH_COMMANDS_JSON`
21
+ - Interactive component sends via Shadow message metadata and interactive response forwarding to Hermes
22
+ - Cron/send_message standalone delivery through `SHADOW_HOME_CHANNEL`
23
+
24
+ It deliberately does not implement the whole Shadow product surface. Workspace, commerce, wallet, cloud sandbox, marketplace, OAuth and dashboard stats should be added as Hermes tools or an MCP server, not as platform-adapter logic.
25
+
26
+ ## Install
27
+
28
+ Unzip this package into your Hermes plugins directory:
29
+
30
+ ```bash
31
+ mkdir -p ~/.hermes/plugins
32
+ unzip hermes-shadowob-plugin.zip -d ~/.hermes/plugins
33
+ ```
34
+
35
+ You should end up with:
36
+
37
+ ```text
38
+ ~/.hermes/plugins/shadowob/
39
+ __init__.py
40
+ adapter.py
41
+ shadow_sdk.py
42
+ plugin.yaml
43
+ requirements.txt
44
+ ```
45
+
46
+ Install plugin dependencies in the Python environment where Hermes runs:
47
+
48
+ ```bash
49
+ pip install -r ~/.hermes/plugins/shadowob/requirements.txt
50
+ ```
51
+
52
+ Enable the plugin if your Hermes build gates user plugins through `plugins.enabled`:
53
+
54
+ ```bash
55
+ hermes plugins enable shadowob
56
+ ```
57
+
58
+ Then configure environment variables or put equivalent values in `~/.hermes/config.yaml`.
59
+
60
+ ## Environment variables
61
+
62
+ Required:
63
+
64
+ ```bash
65
+ export SHADOW_BASE_URL="https://your-shadow.example.com"
66
+ export SHADOW_TOKEN="shadow_access_token"
67
+ ```
68
+
69
+ The plugin resolves the Buddy agent id and channel policy dynamically from Shadow. Static channel ids are not required.
70
+
71
+ ```bash
72
+ export SHADOW_HEARTBEAT_INTERVAL_SECONDS=30
73
+
74
+ # Optional slash commands registered at startup
75
+ export SHADOW_SLASH_COMMANDS_JSON='[{"name":"audit","description":"Run an audit"}]'
76
+ ```
77
+
78
+ Common optional settings:
79
+
80
+ ```bash
81
+ export SHADOW_ALLOWED_USERS="user_id_or_username_1,user_id_or_username_2"
82
+ export SHADOW_ALLOW_ALL_USERS=false
83
+ export SHADOW_BOT_USER_ID="bot_user_id" # optional; otherwise /api/auth/me is called
84
+ export SHADOW_BOT_USERNAME="bot_username" # optional; used by mention-only filter
85
+ export SHADOW_MENTION_ONLY=false # group/channel messages require @bot when true
86
+ export SHADOW_REPLY_TO_BOTS=false # loop guard
87
+ export SHADOW_REST_ONLY=false # true disables Socket.IO and uses polling
88
+ export SHADOW_POLL_INTERVAL_SECONDS=3
89
+ export SHADOW_CATCHUP_MINUTES=0 # set >0 to process recent messages on startup
90
+ export SHADOW_DOWNLOAD_MEDIA=true
91
+
92
+ # Advanced compatibility overrides; normally leave these unset so Shadow policy drives routing.
93
+ export SHADOW_CHANNEL_IDS="channel_id_1,channel_id_2"
94
+ export SHADOW_HOME_CHANNEL="channel_id_1"
95
+ export SHADOW_AGENT_ID="agent_id_1"
96
+ export SHADOW_SERVER_IDS="server_id_or_slug_1,server_id_or_slug_2"
97
+ export SHADOW_AUTO_DISCOVER_CHANNELS=true
98
+ ```
99
+
100
+ ## Example Hermes config.yaml fragment
101
+
102
+ ```yaml
103
+ plugins:
104
+ enabled:
105
+ - shadowob
106
+
107
+ platforms:
108
+ shadowob:
109
+ enabled: true
110
+ token: "${SHADOW_TOKEN}"
111
+ extra:
112
+ base_url: "${SHADOW_BASE_URL}"
113
+ slash_commands:
114
+ - name: "audit"
115
+ description: "Run an audit"
116
+ mention_only: false
117
+ rest_only: false
118
+ catchup_minutes: 0
119
+ download_media: true
120
+ ```
121
+
122
+ ## Metadata routing for outbound sends
123
+
124
+ The adapter accepts these Hermes send metadata keys:
125
+
126
+ ```python
127
+ metadata={
128
+ "thread_id": "shadow_thread_id", # or threadId / shadow_thread_id
129
+ "reply_to_message_id": "message_id", # or replyToId / reply_to / shadow_reply_to_id
130
+ "shadow_metadata": {...}, # forwarded as Shadow message metadata
131
+ }
132
+ ```
133
+
134
+ For thread replies, Hermes generally supplies `source.thread_id` through its normal gateway dispatch path. For custom tool calls, pass the keys above.
135
+
136
+ ## Files
137
+
138
+ - `adapter.py`: Hermes `BasePlatformAdapter` implementation and plugin `register(ctx)` entrypoint.
139
+ - `shadow_sdk.py`: small async REST + Socket.IO client matching the subset of Shadow TS SDK used by the adapter.
140
+ - `plugin.yaml` / `PLUGIN.yaml`: plugin manifest and configuration prompts.
141
+ - `requirements.txt`: runtime dependencies.
142
+ - `tests/`: offline unit tests for small parsing helpers.
143
+
144
+ ## v0.2.0 checks and fixes
145
+
146
+ This iteration fixes issues found during static review against the uploaded Shadow project and the current Hermes plugin contract:
147
+
148
+ - Corrected `pytest` import path handling so offline tests run from the plugin directory and from an extracted zip.
149
+ - Registered both Shadow event naming variants: current server broadcasts `message:updated` / `message:deleted`, while shared constants also define `message:update` / `message:delete`.
150
+ - Fixed REST polling shutdown condition so the polling loop stops when the adapter is disconnected.
151
+ - Fixed `env_enablement_fn` to return a flat seed dict, because Hermes merges all non-`home_channel` keys directly into `PlatformConfig.extra`.
152
+ - Changed env auto-enable and connector setup to require only Shadow endpoint/token; Buddy id and channel policy are now resolved dynamically from Shadow.
153
+ - Added dynamic handling for `channel:member-added` and `channel:member-removed` events.
154
+ - Added dynamic handling for `server:joined` and `agent:policy-changed` events.
155
+ - Updated standalone media delivery to support local paths, `MEDIA:` refs, relative paths, Shadow private URLs and remote URLs through the SDK helper.
156
+
157
+ ## Known limits in this first version
158
+
159
+ - Shadow interactive cards and commerce cards can be forwarded as `shadow_metadata` in outbound messages, but there is no LLM-facing Hermes tool schema in this package yet.
160
+ - Slash commands can be registered from JSON and routed into Hermes context; automatic discovery from Hermes skills/packs is not implemented yet.
161
+ - Buddy-chain rules are still simplified compared with `packages/openclaw-shadowob/src/monitor/preflight.ts`.
162
+ - REST polling uses recent message timestamps and an in-memory de-duplication set. It is not a persistent watermark store.
163
+ - External edits/deletes from Shadow are observed but not converted into Hermes conversation turns.
164
+
165
+ ## Suggested next step
166
+
167
+ Add a separate Shadow tools plugin or MCP server for:
168
+
169
+ - `shadow_send_interactive`
170
+ - `shadow_send_commerce_card`
171
+ - `shadow_react_message`
172
+ - `shadow_edit_message`
173
+ - `shadow_delete_message`
174
+ - workspace/cloud/wallet/marketplace operations
175
+
176
+ Keeping these as tools avoids turning the platform adapter into business logic.
@@ -0,0 +1,8 @@
1
+ """Shadow/OpenClaw Buddy Hermes plugin."""
2
+
3
+ try:
4
+ from .adapter import register
5
+ except Exception: # pragma: no cover - pytest may import this directory as a loose module.
6
+ from adapter import register # type: ignore
7
+
8
+ __all__ = ["register"]