@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.
- package/LICENSE +661 -0
- package/README.md +157 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +477 -0
- package/dist/index.cjs +293 -0
- package/dist/index.d.cts +35 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.js +267 -0
- package/hermes-shadowob-plugin/README.md +176 -0
- package/hermes-shadowob-plugin/__init__.py +8 -0
- package/hermes-shadowob-plugin/adapter.py +1572 -0
- package/hermes-shadowob-plugin/plugin.yaml +84 -0
- package/hermes-shadowob-plugin/requirements.txt +2 -0
- package/hermes-shadowob-plugin/shadow_sdk.py +479 -0
- package/hermes-shadowob-plugin/tests/test_adapter_env.py +159 -0
- package/hermes-shadowob-plugin/tests/test_shadow_sdk_helpers.py +25 -0
- package/package.json +57 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
createConnectorPlan: () => createConnectorPlan,
|
|
24
|
+
createConnectorPlans: () => createConnectorPlans
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(index_exports);
|
|
27
|
+
var DEFAULT_SERVER_URL = "https://shadowob.com";
|
|
28
|
+
var DEFAULT_WORK_DIR = ".";
|
|
29
|
+
var DEFAULT_PROJECT_NAME = "shadow-buddy";
|
|
30
|
+
var DEFAULT_CC_AGENT = "codex";
|
|
31
|
+
var shellQuote = (value) => {
|
|
32
|
+
if (!value) return "''";
|
|
33
|
+
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
34
|
+
};
|
|
35
|
+
var normalizeServerUrl = (value) => {
|
|
36
|
+
const trimmed = value.trim() || DEFAULT_SERVER_URL;
|
|
37
|
+
return trimmed.endsWith("/api") ? trimmed.slice(0, -4) : trimmed.replace(/\/$/, "");
|
|
38
|
+
};
|
|
39
|
+
var tokenOrPlaceholder = (token) => token.trim() || "<BUDDY_TOKEN>";
|
|
40
|
+
function buildOpenClawPlan(input) {
|
|
41
|
+
const token = tokenOrPlaceholder(input.token);
|
|
42
|
+
const serverUrl = normalizeServerUrl(input.serverUrl);
|
|
43
|
+
const jsonConfig = JSON.stringify(
|
|
44
|
+
{
|
|
45
|
+
channels: {
|
|
46
|
+
shadowob: {
|
|
47
|
+
token,
|
|
48
|
+
serverUrl
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
null,
|
|
53
|
+
2
|
|
54
|
+
);
|
|
55
|
+
const commands = [
|
|
56
|
+
{
|
|
57
|
+
label: "Install plugin",
|
|
58
|
+
command: "openclaw plugins install @shadowob/openclaw-shadowob"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
label: "Set Buddy token",
|
|
62
|
+
command: `openclaw config set channels.shadowob.token ${shellQuote(token)}`
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
label: "Set Shadow server URL",
|
|
66
|
+
command: `openclaw config set channels.shadowob.serverUrl ${shellQuote(serverUrl)}`
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
label: "Restart gateway",
|
|
70
|
+
command: "openclaw gateway restart"
|
|
71
|
+
}
|
|
72
|
+
];
|
|
73
|
+
const quickCommand = commands.map((item) => item.command).join(" && ");
|
|
74
|
+
const connectCommand = [
|
|
75
|
+
"npx @shadowob/connector@latest connect",
|
|
76
|
+
"--target openclaw",
|
|
77
|
+
`--server-url ${shellQuote(serverUrl)}`,
|
|
78
|
+
`--token ${shellQuote(token)}`
|
|
79
|
+
].join(" ");
|
|
80
|
+
return {
|
|
81
|
+
target: "openclaw",
|
|
82
|
+
title: "OpenClaw",
|
|
83
|
+
summary: "Install the Shadow channel plugin and bind this Buddy token to OpenClaw.",
|
|
84
|
+
connectCommand,
|
|
85
|
+
quickCommand,
|
|
86
|
+
commands,
|
|
87
|
+
configBlocks: [{ label: "openclaw.json", language: "json", content: jsonConfig }],
|
|
88
|
+
aiPrompt: [
|
|
89
|
+
"Configure this Shadow Buddy in OpenClaw.",
|
|
90
|
+
"",
|
|
91
|
+
`Shadow server URL: ${serverUrl}`,
|
|
92
|
+
`Buddy token: ${token}`,
|
|
93
|
+
"",
|
|
94
|
+
"Run these steps in order:",
|
|
95
|
+
...commands.map((item, index) => `${index + 1}. ${item.command}`),
|
|
96
|
+
"",
|
|
97
|
+
"Confirm each step and then verify the gateway is running."
|
|
98
|
+
].join("\n"),
|
|
99
|
+
docsUrl: "/product/index.html",
|
|
100
|
+
capabilities: [
|
|
101
|
+
"channelMessages",
|
|
102
|
+
"dms",
|
|
103
|
+
"threads",
|
|
104
|
+
"mentions",
|
|
105
|
+
"attachments",
|
|
106
|
+
"images",
|
|
107
|
+
"interactive",
|
|
108
|
+
"slashCommands",
|
|
109
|
+
"onlineStatus",
|
|
110
|
+
"typing",
|
|
111
|
+
"activityStatus",
|
|
112
|
+
"reactions",
|
|
113
|
+
"editDelete"
|
|
114
|
+
]
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
function buildHermesPlan(input) {
|
|
118
|
+
const token = tokenOrPlaceholder(input.token);
|
|
119
|
+
const serverUrl = normalizeServerUrl(input.serverUrl);
|
|
120
|
+
const envBlock = [
|
|
121
|
+
`SHADOW_BASE_URL=${shellQuote(serverUrl)}`,
|
|
122
|
+
`SHADOW_TOKEN=${shellQuote(token)}`,
|
|
123
|
+
"SHADOW_ALLOW_ALL_USERS=true",
|
|
124
|
+
"SHADOW_HEARTBEAT_INTERVAL_SECONDS=30",
|
|
125
|
+
`SHADOW_SLASH_COMMANDS_JSON=${shellQuote("[]")}`
|
|
126
|
+
].join("\n");
|
|
127
|
+
const yamlConfig = [
|
|
128
|
+
"plugins:",
|
|
129
|
+
" enabled:",
|
|
130
|
+
" - shadowob",
|
|
131
|
+
"",
|
|
132
|
+
"platforms:",
|
|
133
|
+
" shadowob:",
|
|
134
|
+
" enabled: true",
|
|
135
|
+
` token: "${token}"`,
|
|
136
|
+
" extra:",
|
|
137
|
+
` base_url: "${serverUrl}"`,
|
|
138
|
+
" mention_only: false",
|
|
139
|
+
" rest_only: false",
|
|
140
|
+
" catchup_minutes: 0",
|
|
141
|
+
" download_media: true",
|
|
142
|
+
" slash_commands: []"
|
|
143
|
+
].join("\n");
|
|
144
|
+
const commands = [
|
|
145
|
+
{
|
|
146
|
+
label: "Copy plugin directory",
|
|
147
|
+
command: "mkdir -p ~/.hermes/plugins && cp -R ./packages/connector/hermes-shadowob-plugin ~/.hermes/plugins/shadowob"
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
label: "Install plugin dependencies",
|
|
151
|
+
command: "python -m pip install -r ~/.hermes/plugins/shadowob/requirements.txt"
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
label: "Enable plugin",
|
|
155
|
+
command: "hermes plugins enable shadowob"
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
label: "Start gateway",
|
|
159
|
+
command: "hermes gateway"
|
|
160
|
+
}
|
|
161
|
+
];
|
|
162
|
+
const connectCommand = [
|
|
163
|
+
"npx @shadowob/connector@latest connect",
|
|
164
|
+
"--target hermes",
|
|
165
|
+
`--server-url ${shellQuote(serverUrl)}`,
|
|
166
|
+
`--token ${shellQuote(token)}`
|
|
167
|
+
].join(" ");
|
|
168
|
+
return {
|
|
169
|
+
target: "hermes",
|
|
170
|
+
title: "Hermes Agent",
|
|
171
|
+
summary: "Install the ShadowOB Hermes platform plugin and run Hermes gateway for this Buddy.",
|
|
172
|
+
connectCommand,
|
|
173
|
+
quickCommand: commands.map((item) => item.command).join(" && "),
|
|
174
|
+
commands,
|
|
175
|
+
configBlocks: [
|
|
176
|
+
{ label: "~/.hermes/.env", language: "bash", content: envBlock },
|
|
177
|
+
{ label: "~/.hermes/config.yaml", language: "yaml", content: yamlConfig }
|
|
178
|
+
],
|
|
179
|
+
aiPrompt: [
|
|
180
|
+
"Configure this Shadow Buddy in Hermes Agent.",
|
|
181
|
+
"",
|
|
182
|
+
`Shadow server URL: ${serverUrl}`,
|
|
183
|
+
`Buddy token: ${token}`,
|
|
184
|
+
"",
|
|
185
|
+
"Install the bundled ShadowOB platform plugin, write the environment values above, enable the plugin, then run hermes gateway. The plugin resolves the Buddy agent id and channel policy from Shadow at runtime."
|
|
186
|
+
].join("\n"),
|
|
187
|
+
docsUrl: "https://hermes-agent.nousresearch.com/docs/user-guide/messaging",
|
|
188
|
+
capabilities: [
|
|
189
|
+
"channelMessages",
|
|
190
|
+
"dms",
|
|
191
|
+
"threads",
|
|
192
|
+
"attachments",
|
|
193
|
+
"images",
|
|
194
|
+
"interactive",
|
|
195
|
+
"slashCommands",
|
|
196
|
+
"onlineStatus",
|
|
197
|
+
"typing",
|
|
198
|
+
"activityStatus",
|
|
199
|
+
"cronDelivery"
|
|
200
|
+
]
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
function buildCcConnectPlan(input) {
|
|
204
|
+
const token = tokenOrPlaceholder(input.token);
|
|
205
|
+
const serverUrl = normalizeServerUrl(input.serverUrl);
|
|
206
|
+
const projectName = input.projectName?.trim() || DEFAULT_PROJECT_NAME;
|
|
207
|
+
const workDir = input.workDir?.trim() || DEFAULT_WORK_DIR;
|
|
208
|
+
const agentType = input.agentType?.trim() || DEFAULT_CC_AGENT;
|
|
209
|
+
const tomlConfig = [
|
|
210
|
+
'language = "zh"',
|
|
211
|
+
"",
|
|
212
|
+
"[[projects]]",
|
|
213
|
+
`name = "${projectName}"`,
|
|
214
|
+
`work_dir = "${workDir}"`,
|
|
215
|
+
`agent_type = "${agentType}"`,
|
|
216
|
+
"",
|
|
217
|
+
"[[projects.platforms]]",
|
|
218
|
+
'type = "shadowob"',
|
|
219
|
+
"",
|
|
220
|
+
"[projects.platforms.options]",
|
|
221
|
+
`token = "${token}"`,
|
|
222
|
+
`server_url = "${serverUrl}"`,
|
|
223
|
+
'allow_from = "*"',
|
|
224
|
+
"listen_dms = true",
|
|
225
|
+
"share_session_in_channel = false",
|
|
226
|
+
'progress_style = "compact"'
|
|
227
|
+
].join("\n");
|
|
228
|
+
const commands = [
|
|
229
|
+
{ label: "Install cc-connect", command: "npm install -g cc-connect" },
|
|
230
|
+
{ label: "Create config directory", command: "mkdir -p ~/.cc-connect" },
|
|
231
|
+
{
|
|
232
|
+
label: "Edit config",
|
|
233
|
+
command: "$EDITOR ~/.cc-connect/config.toml"
|
|
234
|
+
},
|
|
235
|
+
{ label: "Start cc-connect", command: "cc-connect" }
|
|
236
|
+
];
|
|
237
|
+
const connectCommand = [
|
|
238
|
+
"npx @shadowob/connector@latest connect",
|
|
239
|
+
"--target cc-connect",
|
|
240
|
+
`--server-url ${shellQuote(serverUrl)}`,
|
|
241
|
+
`--token ${shellQuote(token)}`,
|
|
242
|
+
`--work-dir ${shellQuote(workDir)}`,
|
|
243
|
+
`--project-name ${shellQuote(projectName)}`,
|
|
244
|
+
`--agent-type ${shellQuote(agentType)}`
|
|
245
|
+
].join(" ");
|
|
246
|
+
return {
|
|
247
|
+
target: "cc-connect",
|
|
248
|
+
title: "cc-connect",
|
|
249
|
+
summary: "Use cc-connect ShadowOB Socket.IO platform support with this Buddy token.",
|
|
250
|
+
connectCommand,
|
|
251
|
+
quickCommand: commands.map((item) => item.command).join(" && "),
|
|
252
|
+
commands,
|
|
253
|
+
configBlocks: [{ label: "~/.cc-connect/config.toml", language: "toml", content: tomlConfig }],
|
|
254
|
+
aiPrompt: [
|
|
255
|
+
"Configure this Shadow Buddy in cc-connect.",
|
|
256
|
+
"",
|
|
257
|
+
`Shadow server URL: ${serverUrl}`,
|
|
258
|
+
`Buddy token: ${token}`,
|
|
259
|
+
`Project work_dir: ${workDir}`,
|
|
260
|
+
`Agent type: ${agentType}`,
|
|
261
|
+
"",
|
|
262
|
+
"Install cc-connect, add the TOML platform block, and start cc-connect."
|
|
263
|
+
].join("\n"),
|
|
264
|
+
docsUrl: "https://github.com/buggyblues/cc-connect/blob/main/docs/shadowob.md",
|
|
265
|
+
capabilities: [
|
|
266
|
+
"channelMessages",
|
|
267
|
+
"dms",
|
|
268
|
+
"attachments",
|
|
269
|
+
"images",
|
|
270
|
+
"interactive",
|
|
271
|
+
"slashCommands",
|
|
272
|
+
"typing",
|
|
273
|
+
"streamingPreviews",
|
|
274
|
+
"forms"
|
|
275
|
+
]
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
function createConnectorPlan(input) {
|
|
279
|
+
if (input.target === "openclaw") return buildOpenClawPlan(input);
|
|
280
|
+
if (input.target === "hermes") return buildHermesPlan(input);
|
|
281
|
+
if (input.target === "cc-connect") return buildCcConnectPlan(input);
|
|
282
|
+
throw new Error(`Unsupported connector target: ${String(input.target)}`);
|
|
283
|
+
}
|
|
284
|
+
function createConnectorPlans(input) {
|
|
285
|
+
return ["openclaw", "hermes", "cc-connect"].map(
|
|
286
|
+
(target) => createConnectorPlan({ ...input, target })
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
290
|
+
0 && (module.exports = {
|
|
291
|
+
createConnectorPlan,
|
|
292
|
+
createConnectorPlans
|
|
293
|
+
});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
type ShadowConnectorTarget = 'openclaw' | 'hermes' | 'cc-connect';
|
|
2
|
+
interface ShadowConnectorInput {
|
|
3
|
+
target: ShadowConnectorTarget;
|
|
4
|
+
serverUrl: string;
|
|
5
|
+
token: string;
|
|
6
|
+
hermesHome?: string;
|
|
7
|
+
workDir?: string;
|
|
8
|
+
projectName?: string;
|
|
9
|
+
agentType?: 'codex' | 'claudecode' | 'opencode' | 'gemini' | 'cursor' | string;
|
|
10
|
+
}
|
|
11
|
+
interface ConnectorCommand {
|
|
12
|
+
label: string;
|
|
13
|
+
command: string;
|
|
14
|
+
}
|
|
15
|
+
interface ConnectorConfigBlock {
|
|
16
|
+
label: string;
|
|
17
|
+
language: 'bash' | 'json' | 'toml' | 'yaml' | 'text';
|
|
18
|
+
content: string;
|
|
19
|
+
}
|
|
20
|
+
interface ConnectorPlan {
|
|
21
|
+
target: ShadowConnectorTarget;
|
|
22
|
+
title: string;
|
|
23
|
+
summary: string;
|
|
24
|
+
connectCommand: string;
|
|
25
|
+
quickCommand: string;
|
|
26
|
+
commands: ConnectorCommand[];
|
|
27
|
+
configBlocks: ConnectorConfigBlock[];
|
|
28
|
+
aiPrompt: string;
|
|
29
|
+
docsUrl: string;
|
|
30
|
+
capabilities: string[];
|
|
31
|
+
}
|
|
32
|
+
declare function createConnectorPlan(input: ShadowConnectorInput): ConnectorPlan;
|
|
33
|
+
declare function createConnectorPlans(input: Omit<ShadowConnectorInput, 'target'>): ConnectorPlan[];
|
|
34
|
+
|
|
35
|
+
export { type ConnectorCommand, type ConnectorConfigBlock, type ConnectorPlan, type ShadowConnectorInput, type ShadowConnectorTarget, createConnectorPlan, createConnectorPlans };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
type ShadowConnectorTarget = 'openclaw' | 'hermes' | 'cc-connect';
|
|
2
|
+
interface ShadowConnectorInput {
|
|
3
|
+
target: ShadowConnectorTarget;
|
|
4
|
+
serverUrl: string;
|
|
5
|
+
token: string;
|
|
6
|
+
hermesHome?: string;
|
|
7
|
+
workDir?: string;
|
|
8
|
+
projectName?: string;
|
|
9
|
+
agentType?: 'codex' | 'claudecode' | 'opencode' | 'gemini' | 'cursor' | string;
|
|
10
|
+
}
|
|
11
|
+
interface ConnectorCommand {
|
|
12
|
+
label: string;
|
|
13
|
+
command: string;
|
|
14
|
+
}
|
|
15
|
+
interface ConnectorConfigBlock {
|
|
16
|
+
label: string;
|
|
17
|
+
language: 'bash' | 'json' | 'toml' | 'yaml' | 'text';
|
|
18
|
+
content: string;
|
|
19
|
+
}
|
|
20
|
+
interface ConnectorPlan {
|
|
21
|
+
target: ShadowConnectorTarget;
|
|
22
|
+
title: string;
|
|
23
|
+
summary: string;
|
|
24
|
+
connectCommand: string;
|
|
25
|
+
quickCommand: string;
|
|
26
|
+
commands: ConnectorCommand[];
|
|
27
|
+
configBlocks: ConnectorConfigBlock[];
|
|
28
|
+
aiPrompt: string;
|
|
29
|
+
docsUrl: string;
|
|
30
|
+
capabilities: string[];
|
|
31
|
+
}
|
|
32
|
+
declare function createConnectorPlan(input: ShadowConnectorInput): ConnectorPlan;
|
|
33
|
+
declare function createConnectorPlans(input: Omit<ShadowConnectorInput, 'target'>): ConnectorPlan[];
|
|
34
|
+
|
|
35
|
+
export { type ConnectorCommand, type ConnectorConfigBlock, type ConnectorPlan, type ShadowConnectorInput, type ShadowConnectorTarget, createConnectorPlan, createConnectorPlans };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
var DEFAULT_SERVER_URL = "https://shadowob.com";
|
|
3
|
+
var DEFAULT_WORK_DIR = ".";
|
|
4
|
+
var DEFAULT_PROJECT_NAME = "shadow-buddy";
|
|
5
|
+
var DEFAULT_CC_AGENT = "codex";
|
|
6
|
+
var shellQuote = (value) => {
|
|
7
|
+
if (!value) return "''";
|
|
8
|
+
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
9
|
+
};
|
|
10
|
+
var normalizeServerUrl = (value) => {
|
|
11
|
+
const trimmed = value.trim() || DEFAULT_SERVER_URL;
|
|
12
|
+
return trimmed.endsWith("/api") ? trimmed.slice(0, -4) : trimmed.replace(/\/$/, "");
|
|
13
|
+
};
|
|
14
|
+
var tokenOrPlaceholder = (token) => token.trim() || "<BUDDY_TOKEN>";
|
|
15
|
+
function buildOpenClawPlan(input) {
|
|
16
|
+
const token = tokenOrPlaceholder(input.token);
|
|
17
|
+
const serverUrl = normalizeServerUrl(input.serverUrl);
|
|
18
|
+
const jsonConfig = JSON.stringify(
|
|
19
|
+
{
|
|
20
|
+
channels: {
|
|
21
|
+
shadowob: {
|
|
22
|
+
token,
|
|
23
|
+
serverUrl
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
null,
|
|
28
|
+
2
|
|
29
|
+
);
|
|
30
|
+
const commands = [
|
|
31
|
+
{
|
|
32
|
+
label: "Install plugin",
|
|
33
|
+
command: "openclaw plugins install @shadowob/openclaw-shadowob"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
label: "Set Buddy token",
|
|
37
|
+
command: `openclaw config set channels.shadowob.token ${shellQuote(token)}`
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
label: "Set Shadow server URL",
|
|
41
|
+
command: `openclaw config set channels.shadowob.serverUrl ${shellQuote(serverUrl)}`
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
label: "Restart gateway",
|
|
45
|
+
command: "openclaw gateway restart"
|
|
46
|
+
}
|
|
47
|
+
];
|
|
48
|
+
const quickCommand = commands.map((item) => item.command).join(" && ");
|
|
49
|
+
const connectCommand = [
|
|
50
|
+
"npx @shadowob/connector@latest connect",
|
|
51
|
+
"--target openclaw",
|
|
52
|
+
`--server-url ${shellQuote(serverUrl)}`,
|
|
53
|
+
`--token ${shellQuote(token)}`
|
|
54
|
+
].join(" ");
|
|
55
|
+
return {
|
|
56
|
+
target: "openclaw",
|
|
57
|
+
title: "OpenClaw",
|
|
58
|
+
summary: "Install the Shadow channel plugin and bind this Buddy token to OpenClaw.",
|
|
59
|
+
connectCommand,
|
|
60
|
+
quickCommand,
|
|
61
|
+
commands,
|
|
62
|
+
configBlocks: [{ label: "openclaw.json", language: "json", content: jsonConfig }],
|
|
63
|
+
aiPrompt: [
|
|
64
|
+
"Configure this Shadow Buddy in OpenClaw.",
|
|
65
|
+
"",
|
|
66
|
+
`Shadow server URL: ${serverUrl}`,
|
|
67
|
+
`Buddy token: ${token}`,
|
|
68
|
+
"",
|
|
69
|
+
"Run these steps in order:",
|
|
70
|
+
...commands.map((item, index) => `${index + 1}. ${item.command}`),
|
|
71
|
+
"",
|
|
72
|
+
"Confirm each step and then verify the gateway is running."
|
|
73
|
+
].join("\n"),
|
|
74
|
+
docsUrl: "/product/index.html",
|
|
75
|
+
capabilities: [
|
|
76
|
+
"channelMessages",
|
|
77
|
+
"dms",
|
|
78
|
+
"threads",
|
|
79
|
+
"mentions",
|
|
80
|
+
"attachments",
|
|
81
|
+
"images",
|
|
82
|
+
"interactive",
|
|
83
|
+
"slashCommands",
|
|
84
|
+
"onlineStatus",
|
|
85
|
+
"typing",
|
|
86
|
+
"activityStatus",
|
|
87
|
+
"reactions",
|
|
88
|
+
"editDelete"
|
|
89
|
+
]
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function buildHermesPlan(input) {
|
|
93
|
+
const token = tokenOrPlaceholder(input.token);
|
|
94
|
+
const serverUrl = normalizeServerUrl(input.serverUrl);
|
|
95
|
+
const envBlock = [
|
|
96
|
+
`SHADOW_BASE_URL=${shellQuote(serverUrl)}`,
|
|
97
|
+
`SHADOW_TOKEN=${shellQuote(token)}`,
|
|
98
|
+
"SHADOW_ALLOW_ALL_USERS=true",
|
|
99
|
+
"SHADOW_HEARTBEAT_INTERVAL_SECONDS=30",
|
|
100
|
+
`SHADOW_SLASH_COMMANDS_JSON=${shellQuote("[]")}`
|
|
101
|
+
].join("\n");
|
|
102
|
+
const yamlConfig = [
|
|
103
|
+
"plugins:",
|
|
104
|
+
" enabled:",
|
|
105
|
+
" - shadowob",
|
|
106
|
+
"",
|
|
107
|
+
"platforms:",
|
|
108
|
+
" shadowob:",
|
|
109
|
+
" enabled: true",
|
|
110
|
+
` token: "${token}"`,
|
|
111
|
+
" extra:",
|
|
112
|
+
` base_url: "${serverUrl}"`,
|
|
113
|
+
" mention_only: false",
|
|
114
|
+
" rest_only: false",
|
|
115
|
+
" catchup_minutes: 0",
|
|
116
|
+
" download_media: true",
|
|
117
|
+
" slash_commands: []"
|
|
118
|
+
].join("\n");
|
|
119
|
+
const commands = [
|
|
120
|
+
{
|
|
121
|
+
label: "Copy plugin directory",
|
|
122
|
+
command: "mkdir -p ~/.hermes/plugins && cp -R ./packages/connector/hermes-shadowob-plugin ~/.hermes/plugins/shadowob"
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
label: "Install plugin dependencies",
|
|
126
|
+
command: "python -m pip install -r ~/.hermes/plugins/shadowob/requirements.txt"
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
label: "Enable plugin",
|
|
130
|
+
command: "hermes plugins enable shadowob"
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
label: "Start gateway",
|
|
134
|
+
command: "hermes gateway"
|
|
135
|
+
}
|
|
136
|
+
];
|
|
137
|
+
const connectCommand = [
|
|
138
|
+
"npx @shadowob/connector@latest connect",
|
|
139
|
+
"--target hermes",
|
|
140
|
+
`--server-url ${shellQuote(serverUrl)}`,
|
|
141
|
+
`--token ${shellQuote(token)}`
|
|
142
|
+
].join(" ");
|
|
143
|
+
return {
|
|
144
|
+
target: "hermes",
|
|
145
|
+
title: "Hermes Agent",
|
|
146
|
+
summary: "Install the ShadowOB Hermes platform plugin and run Hermes gateway for this Buddy.",
|
|
147
|
+
connectCommand,
|
|
148
|
+
quickCommand: commands.map((item) => item.command).join(" && "),
|
|
149
|
+
commands,
|
|
150
|
+
configBlocks: [
|
|
151
|
+
{ label: "~/.hermes/.env", language: "bash", content: envBlock },
|
|
152
|
+
{ label: "~/.hermes/config.yaml", language: "yaml", content: yamlConfig }
|
|
153
|
+
],
|
|
154
|
+
aiPrompt: [
|
|
155
|
+
"Configure this Shadow Buddy in Hermes Agent.",
|
|
156
|
+
"",
|
|
157
|
+
`Shadow server URL: ${serverUrl}`,
|
|
158
|
+
`Buddy token: ${token}`,
|
|
159
|
+
"",
|
|
160
|
+
"Install the bundled ShadowOB platform plugin, write the environment values above, enable the plugin, then run hermes gateway. The plugin resolves the Buddy agent id and channel policy from Shadow at runtime."
|
|
161
|
+
].join("\n"),
|
|
162
|
+
docsUrl: "https://hermes-agent.nousresearch.com/docs/user-guide/messaging",
|
|
163
|
+
capabilities: [
|
|
164
|
+
"channelMessages",
|
|
165
|
+
"dms",
|
|
166
|
+
"threads",
|
|
167
|
+
"attachments",
|
|
168
|
+
"images",
|
|
169
|
+
"interactive",
|
|
170
|
+
"slashCommands",
|
|
171
|
+
"onlineStatus",
|
|
172
|
+
"typing",
|
|
173
|
+
"activityStatus",
|
|
174
|
+
"cronDelivery"
|
|
175
|
+
]
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
function buildCcConnectPlan(input) {
|
|
179
|
+
const token = tokenOrPlaceholder(input.token);
|
|
180
|
+
const serverUrl = normalizeServerUrl(input.serverUrl);
|
|
181
|
+
const projectName = input.projectName?.trim() || DEFAULT_PROJECT_NAME;
|
|
182
|
+
const workDir = input.workDir?.trim() || DEFAULT_WORK_DIR;
|
|
183
|
+
const agentType = input.agentType?.trim() || DEFAULT_CC_AGENT;
|
|
184
|
+
const tomlConfig = [
|
|
185
|
+
'language = "zh"',
|
|
186
|
+
"",
|
|
187
|
+
"[[projects]]",
|
|
188
|
+
`name = "${projectName}"`,
|
|
189
|
+
`work_dir = "${workDir}"`,
|
|
190
|
+
`agent_type = "${agentType}"`,
|
|
191
|
+
"",
|
|
192
|
+
"[[projects.platforms]]",
|
|
193
|
+
'type = "shadowob"',
|
|
194
|
+
"",
|
|
195
|
+
"[projects.platforms.options]",
|
|
196
|
+
`token = "${token}"`,
|
|
197
|
+
`server_url = "${serverUrl}"`,
|
|
198
|
+
'allow_from = "*"',
|
|
199
|
+
"listen_dms = true",
|
|
200
|
+
"share_session_in_channel = false",
|
|
201
|
+
'progress_style = "compact"'
|
|
202
|
+
].join("\n");
|
|
203
|
+
const commands = [
|
|
204
|
+
{ label: "Install cc-connect", command: "npm install -g cc-connect" },
|
|
205
|
+
{ label: "Create config directory", command: "mkdir -p ~/.cc-connect" },
|
|
206
|
+
{
|
|
207
|
+
label: "Edit config",
|
|
208
|
+
command: "$EDITOR ~/.cc-connect/config.toml"
|
|
209
|
+
},
|
|
210
|
+
{ label: "Start cc-connect", command: "cc-connect" }
|
|
211
|
+
];
|
|
212
|
+
const connectCommand = [
|
|
213
|
+
"npx @shadowob/connector@latest connect",
|
|
214
|
+
"--target cc-connect",
|
|
215
|
+
`--server-url ${shellQuote(serverUrl)}`,
|
|
216
|
+
`--token ${shellQuote(token)}`,
|
|
217
|
+
`--work-dir ${shellQuote(workDir)}`,
|
|
218
|
+
`--project-name ${shellQuote(projectName)}`,
|
|
219
|
+
`--agent-type ${shellQuote(agentType)}`
|
|
220
|
+
].join(" ");
|
|
221
|
+
return {
|
|
222
|
+
target: "cc-connect",
|
|
223
|
+
title: "cc-connect",
|
|
224
|
+
summary: "Use cc-connect ShadowOB Socket.IO platform support with this Buddy token.",
|
|
225
|
+
connectCommand,
|
|
226
|
+
quickCommand: commands.map((item) => item.command).join(" && "),
|
|
227
|
+
commands,
|
|
228
|
+
configBlocks: [{ label: "~/.cc-connect/config.toml", language: "toml", content: tomlConfig }],
|
|
229
|
+
aiPrompt: [
|
|
230
|
+
"Configure this Shadow Buddy in cc-connect.",
|
|
231
|
+
"",
|
|
232
|
+
`Shadow server URL: ${serverUrl}`,
|
|
233
|
+
`Buddy token: ${token}`,
|
|
234
|
+
`Project work_dir: ${workDir}`,
|
|
235
|
+
`Agent type: ${agentType}`,
|
|
236
|
+
"",
|
|
237
|
+
"Install cc-connect, add the TOML platform block, and start cc-connect."
|
|
238
|
+
].join("\n"),
|
|
239
|
+
docsUrl: "https://github.com/buggyblues/cc-connect/blob/main/docs/shadowob.md",
|
|
240
|
+
capabilities: [
|
|
241
|
+
"channelMessages",
|
|
242
|
+
"dms",
|
|
243
|
+
"attachments",
|
|
244
|
+
"images",
|
|
245
|
+
"interactive",
|
|
246
|
+
"slashCommands",
|
|
247
|
+
"typing",
|
|
248
|
+
"streamingPreviews",
|
|
249
|
+
"forms"
|
|
250
|
+
]
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
function createConnectorPlan(input) {
|
|
254
|
+
if (input.target === "openclaw") return buildOpenClawPlan(input);
|
|
255
|
+
if (input.target === "hermes") return buildHermesPlan(input);
|
|
256
|
+
if (input.target === "cc-connect") return buildCcConnectPlan(input);
|
|
257
|
+
throw new Error(`Unsupported connector target: ${String(input.target)}`);
|
|
258
|
+
}
|
|
259
|
+
function createConnectorPlans(input) {
|
|
260
|
+
return ["openclaw", "hermes", "cc-connect"].map(
|
|
261
|
+
(target) => createConnectorPlan({ ...input, target })
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
export {
|
|
265
|
+
createConnectorPlan,
|
|
266
|
+
createConnectorPlans
|
|
267
|
+
};
|