@chorus-aidlc/chorus-openclaw-plugin 0.4.0 → 0.5.0
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/README.md +208 -278
- package/dist/commands.d.ts +5 -0
- package/dist/commands.d.ts.map +1 -0
- package/dist/commands.js +147 -0
- package/dist/commands.js.map +1 -0
- package/dist/config.d.ts +38 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +57 -0
- package/dist/config.js.map +1 -0
- package/dist/event-router.d.ts +55 -0
- package/dist/event-router.d.ts.map +1 -0
- package/dist/event-router.js +157 -0
- package/dist/event-router.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +108 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-client.d.ts +37 -0
- package/dist/mcp-client.d.ts.map +1 -0
- package/dist/mcp-client.js +137 -0
- package/dist/mcp-client.js.map +1 -0
- package/dist/mcp-registration.d.ts +25 -0
- package/dist/mcp-registration.d.ts.map +1 -0
- package/dist/mcp-registration.js +93 -0
- package/dist/mcp-registration.js.map +1 -0
- package/dist/sse-listener.d.ts +37 -0
- package/dist/sse-listener.d.ts.map +1 -0
- package/dist/sse-listener.js +152 -0
- package/dist/sse-listener.js.map +1 -0
- package/dist/wake.d.ts +67 -0
- package/dist/wake.d.ts.map +1 -0
- package/dist/wake.js +234 -0
- package/dist/wake.js.map +1 -0
- package/openclaw.plugin.json +13 -12
- package/package.json +23 -5
- package/skills/brainstorm/SKILL.md +163 -0
- package/skills/chorus/SKILL.md +113 -96
- package/skills/develop/SKILL.md +195 -51
- package/skills/idea/SKILL.md +136 -149
- package/skills/openspec-aware/SKILL.md +425 -0
- package/skills/proposal/SKILL.md +155 -157
- package/skills/proposal-reviewer/SKILL.md +117 -0
- package/skills/quick-dev/SKILL.md +31 -7
- package/skills/review/SKILL.md +105 -33
- package/skills/task-reviewer/SKILL.md +113 -0
- package/skills/yolo/SKILL.md +498 -0
- package/src/commands.ts +138 -71
- package/src/config.ts +23 -10
- package/src/event-router.ts +46 -54
- package/src/index.ts +56 -83
- package/src/mcp-client.ts +17 -0
- package/src/mcp-registration.ts +142 -0
- package/src/openclaw-sdk.d.ts +95 -0
- package/src/wake.ts +310 -0
- package/src/tools/admin-tools.ts +0 -126
- package/src/tools/common-tools.ts +0 -575
- package/src/tools/dev-tools.ts +0 -105
- package/src/tools/pm-tools.ts +0 -411
package/src/index.ts
CHANGED
|
@@ -1,107 +1,89 @@
|
|
|
1
|
-
|
|
2
|
-
type OpenClawPluginApi
|
|
1
|
+
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
|
2
|
+
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry";
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { resolveConfig, validateConfigWithWarnings } from "./config.js";
|
|
5
|
+
import { ensureChorusMcpServer } from "./mcp-registration.js";
|
|
5
6
|
import { ChorusMcpClient } from "./mcp-client.js";
|
|
6
7
|
import { ChorusSseListener } from "./sse-listener.js";
|
|
7
8
|
import { ChorusEventRouter } from "./event-router.js";
|
|
8
|
-
import {
|
|
9
|
-
import { registerDevTools } from "./tools/dev-tools.js";
|
|
10
|
-
import { registerCommonTools } from "./tools/common-tools.js";
|
|
11
|
-
import { registerAdminTools } from "./tools/admin-tools.js";
|
|
9
|
+
import { createWake } from "./wake.js";
|
|
12
10
|
import { registerChorusCommands } from "./commands.js";
|
|
13
11
|
|
|
14
12
|
/**
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
13
|
+
* JSON-Schema config contract for the Chorus plugin.
|
|
14
|
+
*
|
|
15
|
+
* This mirrors the canonical `configSchema` in `openclaw.plugin.json`
|
|
16
|
+
* (the manifest is validated by the host BEFORE this code loads). Keep the two
|
|
17
|
+
* in sync: same property set, same `additionalProperties: false`.
|
|
18
18
|
*/
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
});
|
|
34
|
-
if (!res.ok) {
|
|
35
|
-
logger.warn(`Wake agent failed: HTTP ${res.status}`);
|
|
36
|
-
} else {
|
|
37
|
-
logger.info(`Agent woken: ${text.slice(0, 80)}...`);
|
|
38
|
-
}
|
|
39
|
-
} catch (err) {
|
|
40
|
-
logger.warn(`Wake agent error: ${err}`);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
19
|
+
const CHORUS_JSON_SCHEMA = {
|
|
20
|
+
type: "object",
|
|
21
|
+
additionalProperties: false,
|
|
22
|
+
properties: {
|
|
23
|
+
chorusUrl: {
|
|
24
|
+
type: "string",
|
|
25
|
+
description: "Chorus server URL (e.g. https://chorus.example.com)",
|
|
26
|
+
},
|
|
27
|
+
apiKey: {
|
|
28
|
+
type: "string",
|
|
29
|
+
description: "Chorus API Key (cho_ prefix)",
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
} as const;
|
|
43
33
|
|
|
44
|
-
|
|
34
|
+
export default definePluginEntry({
|
|
45
35
|
id: "chorus-openclaw-plugin",
|
|
46
36
|
name: "Chorus",
|
|
47
37
|
description:
|
|
48
|
-
"Chorus AI-DLC collaboration platform — SSE real-time events
|
|
49
|
-
configSchema:
|
|
38
|
+
"Chorus AI-DLC collaboration platform — native MCP + SSE real-time events",
|
|
39
|
+
configSchema: {
|
|
40
|
+
jsonSchema: CHORUS_JSON_SCHEMA,
|
|
41
|
+
uiHints: { apiKey: { sensitive: true } },
|
|
42
|
+
},
|
|
50
43
|
|
|
51
44
|
register(api: OpenClawPluginApi) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
projectUuids: rawConfig.projectUuids ?? [],
|
|
57
|
-
autoStart: rawConfig.autoStart ?? true,
|
|
58
|
-
};
|
|
59
|
-
const logger = api.logger;
|
|
45
|
+
// 1. Discovery-mode guard: heavy runtime wiring (MCP connect, SSE socket,
|
|
46
|
+
// config mutation) must run ONLY in "full" registration mode. In
|
|
47
|
+
// discovery / cli-metadata / setup-* modes we declare nothing heavy.
|
|
48
|
+
if (api.registrationMode !== "full") return;
|
|
60
49
|
|
|
50
|
+
// 2. Resolve + validate config from the host-validated pluginConfig bag.
|
|
51
|
+
const config = resolveConfig(api.pluginConfig);
|
|
52
|
+
const logger = api.logger;
|
|
61
53
|
if (!validateConfigWithWarnings(config, logger)) {
|
|
62
54
|
return;
|
|
63
55
|
}
|
|
64
56
|
|
|
65
|
-
// After validateConfigWithWarnings, chorusUrl and apiKey are
|
|
57
|
+
// After validateConfigWithWarnings, chorusUrl and apiKey are present.
|
|
66
58
|
const chorusUrl = config.chorusUrl!;
|
|
67
59
|
const apiKey = config.apiKey!;
|
|
68
60
|
|
|
69
|
-
|
|
70
|
-
const gatewayPort = api.config?.gateway?.port ?? 18789;
|
|
71
|
-
const gatewayUrl = `http://127.0.0.1:${gatewayPort}`;
|
|
72
|
-
const hooksToken = api.config?.hooks?.token ?? "";
|
|
61
|
+
logger.info(`Chorus plugin initializing — ${chorusUrl}`);
|
|
73
62
|
|
|
74
|
-
|
|
75
|
-
|
|
63
|
+
// 3. Ensure the Chorus MCP server is registered with OpenClaw so the agent
|
|
64
|
+
// gains native chorus__* tools (fire-and-log; real impl in sibling task).
|
|
65
|
+
void ensureChorusMcpServer(api, config).catch((err) =>
|
|
66
|
+
logger.error(`MCP registration failed: ${err}`),
|
|
76
67
|
);
|
|
77
68
|
|
|
78
|
-
//
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
apiKey,
|
|
82
|
-
logger,
|
|
83
|
-
});
|
|
69
|
+
// 4. Slim MCP client for the plugin's own synchronous calls (checkin,
|
|
70
|
+
// assignments, notifications back-fill).
|
|
71
|
+
const mcpClient = new ChorusMcpClient({ chorusUrl, apiKey, logger });
|
|
84
72
|
|
|
85
|
-
//
|
|
73
|
+
// 5. Event router. Wakes the agent in-process by running an embedded agent
|
|
74
|
+
// turn via `api.runtime.agent.runEmbeddedAgent` (see wake.ts). `createWake`
|
|
75
|
+
// resolves the main agent session + configured model on each wake and
|
|
76
|
+
// gracefully DROPS (logs + returns) when it cannot run — it never throws,
|
|
77
|
+
// so the SSE service stays alive even on a host that exposes no session.
|
|
86
78
|
const eventRouter = new ChorusEventRouter({
|
|
87
79
|
mcpClient,
|
|
88
|
-
config,
|
|
89
80
|
logger,
|
|
90
|
-
|
|
91
|
-
// Use /hooks/wake to enqueue a system event + trigger immediate heartbeat
|
|
92
|
-
if (hooksToken) {
|
|
93
|
-
wakeAgent(gatewayUrl, hooksToken, message, logger);
|
|
94
|
-
} else {
|
|
95
|
-
logger.warn(
|
|
96
|
-
`[Chorus] Cannot wake agent — gateway.auth.token not configured. Event: ${message.slice(0, 100)}`
|
|
97
|
-
);
|
|
98
|
-
}
|
|
99
|
-
},
|
|
81
|
+
wake: createWake(api, logger),
|
|
100
82
|
});
|
|
101
83
|
|
|
102
|
-
//
|
|
84
|
+
// 6. Background SSE service. The SSE socket opens only inside start(), which
|
|
85
|
+
// the host calls in full mode — keeping the heavy socket gated.
|
|
103
86
|
let sseListener: ChorusSseListener | null = null;
|
|
104
|
-
|
|
105
87
|
api.registerService({
|
|
106
88
|
id: "chorus-sse",
|
|
107
89
|
async start() {
|
|
@@ -111,7 +93,6 @@ const plugin = {
|
|
|
111
93
|
logger,
|
|
112
94
|
onEvent: (event) => eventRouter.dispatch(event),
|
|
113
95
|
onReconnect: async () => {
|
|
114
|
-
// Back-fill missed notifications after reconnect
|
|
115
96
|
try {
|
|
116
97
|
const result = (await mcpClient.callTool("chorus_get_notifications", {
|
|
117
98
|
status: "unread",
|
|
@@ -134,15 +115,7 @@ const plugin = {
|
|
|
134
115
|
},
|
|
135
116
|
});
|
|
136
117
|
|
|
137
|
-
//
|
|
138
|
-
registerPmTools(api, mcpClient);
|
|
139
|
-
registerDevTools(api, mcpClient);
|
|
140
|
-
registerCommonTools(api, mcpClient);
|
|
141
|
-
registerAdminTools(api, mcpClient);
|
|
142
|
-
|
|
143
|
-
// --- Commands ---
|
|
118
|
+
// 7. /chorus command (status | tasks | ideas | skills).
|
|
144
119
|
registerChorusCommands(api, mcpClient, () => sseListener?.status ?? "disconnected");
|
|
145
120
|
},
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
export default plugin;
|
|
121
|
+
});
|
package/src/mcp-client.ts
CHANGED
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin-INTERNAL MCP client.
|
|
3
|
+
*
|
|
4
|
+
* This is NOT how the agent gets Chorus tools — those are exposed natively by
|
|
5
|
+
* OpenClaw connecting to the `mcp.servers.chorus` entry written by
|
|
6
|
+
* `ensureChorusMcpServer` (see mcp-registration.ts). The plugin no longer
|
|
7
|
+
* hand-wraps any Chorus tool with `api.registerTool`.
|
|
8
|
+
*
|
|
9
|
+
* This client exists only for the plugin's OWN synchronous calls into Chorus:
|
|
10
|
+
* - `/chorus` command: chorus_checkin, chorus_get_my_assignments,
|
|
11
|
+
* chorus_get_available_ideas (see commands.ts)
|
|
12
|
+
* - SSE reconnect back-fill: chorus_get_notifications (see index.ts)
|
|
13
|
+
*
|
|
14
|
+
* No agent-facing tool depends on it. Keep it a generic StreamableHTTP
|
|
15
|
+
* `callTool` client (lazy connect + 404 reconnect); do not grow it into a tool
|
|
16
|
+
* surface.
|
|
17
|
+
*/
|
|
1
18
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
2
19
|
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
3
20
|
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry";
|
|
2
|
+
import type { ChorusPluginConfig } from "./config.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Shape of the `mcp.servers.chorus` entry we write into OpenClaw config.
|
|
6
|
+
*
|
|
7
|
+
* Mirrors the relevant subset of OpenClaw's `McpServerConfig`
|
|
8
|
+
* (`../openclaw/src/config/types.mcp.ts:12`): a remote streamable-http MCP
|
|
9
|
+
* server reachable at `<chorusUrl>/api/mcp` with a Bearer auth header.
|
|
10
|
+
*/
|
|
11
|
+
interface ChorusMcpServerEntry {
|
|
12
|
+
url: string;
|
|
13
|
+
transport: "streamable-http";
|
|
14
|
+
headers: { Authorization: string };
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Build the desired `mcp.servers.chorus` entry for the current config.
|
|
19
|
+
*/
|
|
20
|
+
function buildDesiredEntry(chorusUrl: string, apiKey: string): ChorusMcpServerEntry {
|
|
21
|
+
return {
|
|
22
|
+
url: new URL("/api/mcp", chorusUrl).toString(),
|
|
23
|
+
transport: "streamable-http",
|
|
24
|
+
headers: { Authorization: `Bearer ${apiKey}` },
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Shallow-equal the fields that define the desired entry. We only compare the
|
|
30
|
+
* three load-bearing fields (url, transport, Authorization header) so an
|
|
31
|
+
* operator-added extra field — e.g. `connectionTimeoutMs` — does not force a
|
|
32
|
+
* rewrite-and-reload on every activation.
|
|
33
|
+
*/
|
|
34
|
+
function entryMatches(existing: unknown, desired: ChorusMcpServerEntry): boolean {
|
|
35
|
+
if (!existing || typeof existing !== "object") return false;
|
|
36
|
+
const e = existing as {
|
|
37
|
+
url?: unknown;
|
|
38
|
+
transport?: unknown;
|
|
39
|
+
headers?: { Authorization?: unknown } | undefined;
|
|
40
|
+
};
|
|
41
|
+
return (
|
|
42
|
+
e.url === desired.url &&
|
|
43
|
+
e.transport === desired.transport &&
|
|
44
|
+
e.headers?.Authorization === desired.headers.Authorization
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Ensure the Chorus MCP server is registered with OpenClaw so the agent gains
|
|
50
|
+
* the native `chorus__*` tools.
|
|
51
|
+
*
|
|
52
|
+
* Writes (idempotently) an `mcp.servers.chorus` entry into the OpenClaw config
|
|
53
|
+
* via `api.runtime.config.mutateConfigFile` — a remote streamable-http MCP
|
|
54
|
+
* server with Bearer auth. OpenClaw then connects to the remote Chorus MCP
|
|
55
|
+
* server on (re)load and auto-exposes its tools under the `chorus__` prefix; we
|
|
56
|
+
* never re-declare those tools with `api.registerTool`.
|
|
57
|
+
*
|
|
58
|
+
* Behavior:
|
|
59
|
+
* - Missing `chorusUrl`/`apiKey`: do NOT write; warn naming the missing field(s).
|
|
60
|
+
* - Existing entry already equals the desired entry: return without writing
|
|
61
|
+
* (idempotent — no config reload triggered).
|
|
62
|
+
* - Otherwise: `mutateConfigFile({ afterWrite: { mode: "auto" }, mutate })`,
|
|
63
|
+
* mutating the draft in place (OpenClaw's `mutate` callback receives a
|
|
64
|
+
* structuredClone draft and persists the in-place mutation).
|
|
65
|
+
* - Any rejection from `mutateConfigFile` (or the runtime API being absent) is
|
|
66
|
+
* logged at error level and swallowed — registration failure must never crash
|
|
67
|
+
* the gateway, so the SSE service and `/chorus` command still register.
|
|
68
|
+
*/
|
|
69
|
+
export async function ensureChorusMcpServer(
|
|
70
|
+
api: OpenClawPluginApi,
|
|
71
|
+
cfg: ChorusPluginConfig,
|
|
72
|
+
): Promise<void> {
|
|
73
|
+
const logger = api.logger;
|
|
74
|
+
|
|
75
|
+
// 1. Required-config guard: do not write a half-formed entry.
|
|
76
|
+
const missing: string[] = [];
|
|
77
|
+
if (!cfg.chorusUrl) missing.push("chorusUrl");
|
|
78
|
+
if (!cfg.apiKey) missing.push("apiKey");
|
|
79
|
+
if (missing.length > 0) {
|
|
80
|
+
logger.warn(
|
|
81
|
+
`[Chorus] Skipping MCP server registration — missing required config: ${missing.join(", ")}`,
|
|
82
|
+
);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const desired = buildDesiredEntry(cfg.chorusUrl!, cfg.apiKey!);
|
|
87
|
+
|
|
88
|
+
try {
|
|
89
|
+
// `api.runtime` is permissively typed via the SDK shim; narrow to the
|
|
90
|
+
// config surface we use (current() + mutateConfigFile). At runtime the host
|
|
91
|
+
// provides the real `PluginRuntimeCore.config` API
|
|
92
|
+
// (../openclaw/src/plugins/runtime/types-core.ts:145).
|
|
93
|
+
const runtimeConfig = (
|
|
94
|
+
api.runtime as
|
|
95
|
+
| {
|
|
96
|
+
config?: {
|
|
97
|
+
current?: () => { mcp?: { servers?: Record<string, unknown> } } | undefined;
|
|
98
|
+
mutateConfigFile?: (params: {
|
|
99
|
+
afterWrite: { mode: "auto" };
|
|
100
|
+
mutate: (draft: {
|
|
101
|
+
mcp?: { servers?: Record<string, unknown> };
|
|
102
|
+
}) => void;
|
|
103
|
+
}) => Promise<unknown>;
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
| undefined
|
|
107
|
+
)?.config;
|
|
108
|
+
|
|
109
|
+
if (!runtimeConfig?.mutateConfigFile) {
|
|
110
|
+
logger.error(
|
|
111
|
+
"[Chorus] MCP server registration failed — runtime.config.mutateConfigFile is unavailable on this host",
|
|
112
|
+
);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// 2. Idempotency: skip the write (and the reload it triggers) when the
|
|
117
|
+
// existing entry already matches.
|
|
118
|
+
const existing = runtimeConfig.current?.()?.mcp?.servers?.chorus;
|
|
119
|
+
if (entryMatches(existing, desired)) {
|
|
120
|
+
logger.info("[Chorus] MCP server entry already up to date — no config change");
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// 3. Write the entry, mutating the draft in place.
|
|
125
|
+
await runtimeConfig.mutateConfigFile({
|
|
126
|
+
afterWrite: { mode: "auto" },
|
|
127
|
+
mutate: (draft) => {
|
|
128
|
+
const mcp = (draft.mcp ??= {});
|
|
129
|
+
const servers = (mcp.servers ??= {});
|
|
130
|
+
servers.chorus = desired;
|
|
131
|
+
},
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
logger.info(`[Chorus] Registered MCP server entry — ${desired.url}`);
|
|
135
|
+
} catch (err) {
|
|
136
|
+
// 4. Never crash the gateway: log at error level and continue so the SSE
|
|
137
|
+
// service and /chorus command still register.
|
|
138
|
+
logger.error(
|
|
139
|
+
`[Chorus] MCP server registration failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ambient module shim for the OpenClaw 2026.5.x Plugin SDK.
|
|
3
|
+
*
|
|
4
|
+
* WHY THIS EXISTS:
|
|
5
|
+
* The plugin's runtime entry imports `definePluginEntry` from the subpath
|
|
6
|
+
* `openclaw/plugin-sdk/plugin-entry`. That subpath export only exists in the
|
|
7
|
+
* OpenClaw 2026.5.30 Plugin SDK. The `openclaw` package currently resolvable in
|
|
8
|
+
* this workspace's node_modules is an older build (2026.3.x) that does NOT
|
|
9
|
+
* export `./plugin-sdk/plugin-entry`, so `tsc` cannot resolve the import from
|
|
10
|
+
* the real package and would fail type-checking.
|
|
11
|
+
*
|
|
12
|
+
* Rather than bundle/install the full 2026.5.30 OpenClaw package just to satisfy
|
|
13
|
+
* `tsc --noEmit`, we declare a minimal ambient module with a permissive
|
|
14
|
+
* signature. At install/runtime the real host provides the actual SDK
|
|
15
|
+
* (the package.json `peerDependencies.openclaw` floor + the
|
|
16
|
+
* `openclaw.compat.pluginApi >=2026.5.30` gate enforce the version contract);
|
|
17
|
+
* this declaration is purely a compile-time bridge.
|
|
18
|
+
*
|
|
19
|
+
* The signature mirrors `definePluginEntry` from
|
|
20
|
+
* `../openclaw/src/plugin-sdk/plugin-entry.ts` (verified against OpenClaw
|
|
21
|
+
* 2026.5.30). `api` is typed `unknown`-ish via a permissive shape so the entry
|
|
22
|
+
* file stays readable without pulling in the full `OpenClawPluginApi` type
|
|
23
|
+
* graph. When the workspace upgrades to an `openclaw` build that exports
|
|
24
|
+
* `plugin-sdk/plugin-entry`, delete this shim and rely on the real types.
|
|
25
|
+
*/
|
|
26
|
+
declare module "openclaw/plugin-sdk/plugin-entry" {
|
|
27
|
+
/** Public registration modes surfaced to plugin `register(api)` calls. */
|
|
28
|
+
export type PluginRegistrationMode =
|
|
29
|
+
| "full"
|
|
30
|
+
| "discovery"
|
|
31
|
+
| "tool-discovery"
|
|
32
|
+
| "setup-only"
|
|
33
|
+
| "setup-runtime"
|
|
34
|
+
| "cli-metadata";
|
|
35
|
+
|
|
36
|
+
/** JSON-Schema / parser config contract accepted by plugin entries. */
|
|
37
|
+
export type OpenClawPluginConfigSchema = {
|
|
38
|
+
safeParse?: (value: unknown) => unknown;
|
|
39
|
+
parse?: (value: unknown) => unknown;
|
|
40
|
+
validate?: (value: unknown) => unknown;
|
|
41
|
+
uiHints?: Record<string, unknown>;
|
|
42
|
+
jsonSchema?: Record<string, unknown>;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Permissive subset of `OpenClawPluginApi` used by this plugin's entry.
|
|
47
|
+
*
|
|
48
|
+
* Only the members this plugin touches are typed; the index signature keeps
|
|
49
|
+
* the rest of the (large) host API accessible without importing it.
|
|
50
|
+
*/
|
|
51
|
+
export type OpenClawPluginApi = {
|
|
52
|
+
registrationMode: PluginRegistrationMode;
|
|
53
|
+
pluginConfig?: Record<string, unknown>;
|
|
54
|
+
config?: Record<string, unknown> & {
|
|
55
|
+
gateway?: { port?: number };
|
|
56
|
+
hooks?: { token?: string };
|
|
57
|
+
};
|
|
58
|
+
logger: {
|
|
59
|
+
debug?: (message: string) => void;
|
|
60
|
+
info: (message: string) => void;
|
|
61
|
+
warn: (message: string) => void;
|
|
62
|
+
error: (message: string) => void;
|
|
63
|
+
};
|
|
64
|
+
registerService: (service: {
|
|
65
|
+
id: string;
|
|
66
|
+
start: (...args: unknown[]) => void | Promise<void>;
|
|
67
|
+
stop?: (...args: unknown[]) => void | Promise<void>;
|
|
68
|
+
}) => void;
|
|
69
|
+
registerCommand: (command: unknown) => void;
|
|
70
|
+
registerTool: (tool: unknown, opts?: unknown) => void;
|
|
71
|
+
runtime?: unknown;
|
|
72
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
73
|
+
[key: string]: any;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export type DefinePluginEntryOptions = {
|
|
77
|
+
id: string;
|
|
78
|
+
name: string;
|
|
79
|
+
description: string;
|
|
80
|
+
configSchema?: OpenClawPluginConfigSchema | (() => OpenClawPluginConfigSchema);
|
|
81
|
+
register: (api: OpenClawPluginApi) => void;
|
|
82
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
83
|
+
[key: string]: any;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export type DefinedPluginEntry = {
|
|
87
|
+
id: string;
|
|
88
|
+
name: string;
|
|
89
|
+
description: string;
|
|
90
|
+
configSchema: OpenClawPluginConfigSchema;
|
|
91
|
+
register: (api: OpenClawPluginApi) => void;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
export function definePluginEntry(options: DefinePluginEntryOptions): DefinedPluginEntry;
|
|
95
|
+
}
|