@w3osc/openclaw-conduit 1.0.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/dist/index.js ADDED
@@ -0,0 +1,123 @@
1
+ /**
2
+ * @w3os/openclaw-conduit — Conduit channel plugin for OpenClaw
3
+ *
4
+ * Registers Conduit as a native OpenClaw messaging channel, allowing the
5
+ * OpenClaw agent to receive messages from the Conduit AI chat UI and stream
6
+ * replies back in real time.
7
+ *
8
+ * Installation:
9
+ * openclaw plugins install @w3os/openclaw-conduit
10
+ *
11
+ * Config (add to ~/.openclaw/openclaw.json):
12
+ * {
13
+ * "channels": {
14
+ * "conduit": {
15
+ * "baseUrl": "http://your-conduit-host:3101",
16
+ * "apiKey": "sk-arb-...",
17
+ * "allowFrom": [], // leave empty to allow all
18
+ * "webhookSecret": "..." // optional; must match Conduit's webhook secret
19
+ * }
20
+ * }
21
+ * }
22
+ *
23
+ * Then restart the Gateway: openclaw gateway
24
+ *
25
+ * In Conduit (Settings → AI → OpenClaw Channel), enter:
26
+ * http://<your-openclaw-host>:18789/channels/conduit/inbound
27
+ */
28
+ import { defineChannelPluginEntry } from 'openclaw/plugin-sdk/channel-core';
29
+ import { conduitPlugin } from './src/channel.js';
30
+ import { parseInboundPayload, verifyWebhookSecret, handleConduitInbound } from './src/inbound.js';
31
+ export default defineChannelPluginEntry({
32
+ id: 'conduit',
33
+ name: 'Conduit',
34
+ description: 'Conduit personal communications hub — read messages, emails, and calendar.',
35
+ plugin: conduitPlugin,
36
+ registerCliMetadata(api) {
37
+ api.registerCli(({ program }) => {
38
+ program
39
+ .command('conduit')
40
+ .description('Conduit channel management');
41
+ }, {
42
+ descriptors: [
43
+ {
44
+ name: 'conduit',
45
+ description: 'Conduit channel management',
46
+ hasSubcommands: false,
47
+ },
48
+ ],
49
+ });
50
+ },
51
+ registerFull(api) {
52
+ // ── Inbound HTTP route ────────────────────────────────────────────────────
53
+ // Conduit POSTs AI chat messages here. We parse the payload, dispatch it
54
+ // into the OpenClaw agent session, and stream the reply back.
55
+ api.registerHttpRoute({
56
+ path: '/channels/conduit/inbound',
57
+ // 'plugin' auth = plugin-managed; we verify the webhook secret ourselves.
58
+ auth: 'plugin',
59
+ handler: async (req, res) => {
60
+ // Resolve the current account config to get the webhook secret and apiKey.
61
+ let account;
62
+ try {
63
+ const cfg = api.runtime.config.loadConfig();
64
+ account = conduitPlugin.config.resolveAccount(cfg, null);
65
+ }
66
+ catch (err) {
67
+ res.statusCode = 503;
68
+ res.setHeader('Content-Type', 'application/json');
69
+ res.end(JSON.stringify({ error: 'Channel not configured', detail: String(err) }));
70
+ return true;
71
+ }
72
+ // Verify the optional webhook secret.
73
+ const authHeader = req.headers['authorization'];
74
+ if (!verifyWebhookSecret(authHeader, account.webhookSecret)) {
75
+ res.statusCode = 401;
76
+ res.setHeader('Content-Type', 'application/json');
77
+ res.end(JSON.stringify({ error: 'Unauthorized' }));
78
+ return true;
79
+ }
80
+ // Parse the payload.
81
+ let payload;
82
+ try {
83
+ payload = parseInboundPayload(req.body);
84
+ }
85
+ catch (err) {
86
+ res.statusCode = 400;
87
+ res.setHeader('Content-Type', 'application/json');
88
+ res.end(JSON.stringify({ error: 'Bad request', detail: String(err) }));
89
+ return true;
90
+ }
91
+ // Acknowledge immediately — the agent reply is streamed back asynchronously.
92
+ res.statusCode = 202;
93
+ res.setHeader('Content-Type', 'application/json');
94
+ res.end(JSON.stringify({ accepted: true, sessionId: payload.sessionId }));
95
+ // Dispatch to the OpenClaw agent and stream the reply back to Conduit.
96
+ handleConduitInbound(payload, account.apiKey, async (p) => {
97
+ // Build the prompt, prepending an optional system prompt on first message.
98
+ const prompt = p.systemPrompt
99
+ ? `${p.systemPrompt}\n\n${p.content}`
100
+ : p.content;
101
+ const sessionKey = `conduit:${p.sessionId}`;
102
+ // Run the agent subagent and wait for completion.
103
+ const { runId } = await api.runtime.subagent.run({
104
+ sessionKey,
105
+ message: prompt,
106
+ });
107
+ const result = await api.runtime.subagent.waitForRun({ runId, timeoutMs: 120_000 });
108
+ if (result.status === 'error') {
109
+ throw new Error(`Agent run failed: ${result.error ?? 'unknown error'}`);
110
+ }
111
+ // Retrieve the last assistant message from the session.
112
+ const { messages } = await api.runtime.subagent.getSessionMessages({ sessionKey, limit: 1 });
113
+ const last = messages.find((m) => m.role === 'assistant');
114
+ return last?.content ?? '';
115
+ }).catch((err) => {
116
+ console.error('[conduit-plugin] Failed to handle inbound message:', err);
117
+ });
118
+ return true;
119
+ },
120
+ });
121
+ },
122
+ });
123
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Lightweight setup entry point for the Conduit channel plugin.
3
+ *
4
+ * OpenClaw loads this module instead of the full entry point when:
5
+ * - The channel is disabled or unconfigured
6
+ * - Onboarding/setup flows need channel metadata without activating
7
+ * the full runtime (HTTP routes, agent session wiring, etc.)
8
+ *
9
+ * See: https://docs.openclaw.ai/plugins/sdk-setup#setup-entry
10
+ */
11
+ import { defineSetupPluginEntry } from 'openclaw/plugin-sdk/channel-core';
12
+ import { conduitPlugin } from './src/channel.js';
13
+ export default defineSetupPluginEntry(conduitPlugin);
14
+ //# sourceMappingURL=setup-entry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup-entry.js","sourceRoot":"","sources":["../setup-entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,eAAe,sBAAsB,CAAC,aAAa,CAAC,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Conduit channel plugin definition.
3
+ *
4
+ * Uses `createChatChannelPlugin` from the OpenClaw plugin SDK to register
5
+ * Conduit as a native OpenClaw messaging channel. OpenClaw manages the
6
+ * agent session, tool calls, and reply dispatch; this plugin handles:
7
+ *
8
+ * - Config / account resolution from `openclaw.json`
9
+ * - Setup inspection (is the channel configured?)
10
+ * - DM security (allowlist who can receive Conduit messages)
11
+ * - Outbound: streaming reply chunks back to Conduit's stream endpoint
12
+ */
13
+ interface ResolvedAccount {
14
+ accountId: string | null;
15
+ baseUrl: string;
16
+ apiKey: string;
17
+ allowFrom: string[];
18
+ webhookSecret: string | undefined;
19
+ }
20
+ export declare const conduitPlugin: import("openclaw/plugin-sdk/channel-core").ChannelPlugin<ResolvedAccount, unknown, unknown>;
21
+ export {};
22
+ //# sourceMappingURL=channel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../../src/channel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAmBH,UAAU,eAAe;IACvB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;CACnC;AAiCD,eAAO,MAAM,aAAa,6FAsDxB,CAAC"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Conduit channel plugin definition.
3
+ *
4
+ * Uses `createChatChannelPlugin` from the OpenClaw plugin SDK to register
5
+ * Conduit as a native OpenClaw messaging channel. OpenClaw manages the
6
+ * agent session, tool calls, and reply dispatch; this plugin handles:
7
+ *
8
+ * - Config / account resolution from `openclaw.json`
9
+ * - Setup inspection (is the channel configured?)
10
+ * - DM security (allowlist who can receive Conduit messages)
11
+ * - Outbound: streaming reply chunks back to Conduit's stream endpoint
12
+ */
13
+ import { createChatChannelPlugin, createChannelPluginBase, } from 'openclaw/plugin-sdk/channel-core';
14
+ import { verifyConnection } from './client.js';
15
+ function getSection(cfg) {
16
+ return cfg['channels']?.['conduit'] ?? {};
17
+ }
18
+ function resolveAccount(cfg, accountId) {
19
+ const section = getSection(cfg);
20
+ if (!section.baseUrl)
21
+ throw new Error('conduit: channels.conduit.baseUrl is required');
22
+ if (!section.apiKey)
23
+ throw new Error('conduit: channels.conduit.apiKey is required');
24
+ return {
25
+ accountId: accountId ?? null,
26
+ baseUrl: section.baseUrl.replace(/\/$/, ''),
27
+ apiKey: section.apiKey,
28
+ allowFrom: section.allowFrom ?? [],
29
+ webhookSecret: section.webhookSecret,
30
+ };
31
+ }
32
+ function inspectAccount(cfg, _accountId) {
33
+ const section = getSection(cfg);
34
+ const hasUrl = Boolean(section.baseUrl);
35
+ const hasKey = Boolean(section.apiKey);
36
+ return {
37
+ enabled: hasUrl && hasKey,
38
+ configured: hasUrl && hasKey,
39
+ baseUrlStatus: hasUrl ? 'set' : 'missing',
40
+ apiKeyStatus: hasKey ? 'set' : 'missing',
41
+ };
42
+ }
43
+ // ── Channel plugin ────────────────────────────────────────────────────────────
44
+ const conduitBase = createChannelPluginBase({
45
+ id: 'conduit',
46
+ capabilities: {
47
+ chatTypes: ['direct'],
48
+ },
49
+ // ── Setup wizard adapter (config write path) ──────────────────────────────
50
+ // Conduit only needs `applyAccountConfig` — the wizard stores the baseUrl,
51
+ // apiKey, allowFrom, and webhookSecret under `channels.conduit`.
52
+ setup: {
53
+ applyAccountConfig({ cfg, input }) {
54
+ const next = { ...cfg };
55
+ const channels = { ...(next['channels'] ?? {}) };
56
+ channels['conduit'] = {
57
+ ...(channels['conduit'] ?? {}),
58
+ ...input,
59
+ };
60
+ next['channels'] = channels;
61
+ return next;
62
+ },
63
+ },
64
+ config: {
65
+ listAccountIds: () => ['default'],
66
+ resolveAccount,
67
+ inspectAccount,
68
+ isConfigured: async (account) => {
69
+ const result = await verifyConnection({ baseUrl: account.baseUrl, apiKey: account.apiKey });
70
+ return result.ok;
71
+ },
72
+ },
73
+ });
74
+ export const conduitPlugin = createChatChannelPlugin({
75
+ base: conduitBase,
76
+ // DM security — who can receive messages from this channel.
77
+ security: {
78
+ dm: {
79
+ channelKey: 'conduit',
80
+ resolvePolicy: (account) => account.allowFrom.length > 0 ? 'allowlist' : 'allow_all',
81
+ resolveAllowFrom: (account) => account.allowFrom,
82
+ defaultPolicy: 'allow_all',
83
+ },
84
+ },
85
+ // No pairing needed — Conduit authenticates via API key, not user DM pairing.
86
+ pairing: undefined,
87
+ // Replies are top-level (no threading model in the Conduit AI chat UI).
88
+ threading: { topLevelReplyToMode: 'reply' },
89
+ // Outbound: send text replies back to Conduit via the streaming endpoint.
90
+ // The actual stream URL and messageId bookkeeping are handled in inbound.ts;
91
+ // this adapter is used when OpenClaw proactively sends a message (rare for
92
+ // Conduit, but required by the channel contract).
93
+ outbound: {
94
+ base: { deliveryMode: 'direct' },
95
+ attachedResults: {
96
+ channel: 'conduit',
97
+ sendText: async (params) => {
98
+ // `params.to` holds the streamUrl injected by the inbound handler via
99
+ // the session conversation id. We re-use the streaming helper with
100
+ // a single done:true chunk for proactive sends where no ongoing
101
+ // stream context exists.
102
+ const [streamUrl, apiKey] = params.to.split('|APIKEY|');
103
+ if (!streamUrl || !apiKey) {
104
+ throw new Error('conduit outbound: malformed target — expected "streamUrl|APIKEY|apiKey"');
105
+ }
106
+ const { streamReplyToConduit } = await import('./client.js');
107
+ await streamReplyToConduit(streamUrl, apiKey, params.text);
108
+ return { messageId: `arb-${Date.now()}` };
109
+ },
110
+ },
111
+ },
112
+ });
113
+ //# sourceMappingURL=channel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel.js","sourceRoot":"","sources":["../../src/channel.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Conduit API client used by the OpenClaw channel plugin.
3
+ *
4
+ * Responsibilities:
5
+ * - Verify the Conduit server is reachable and the API key is valid.
6
+ * - Stream reply token chunks back to Conduit's session stream endpoint.
7
+ */
8
+ export interface ConduitClientConfig {
9
+ baseUrl: string;
10
+ apiKey: string;
11
+ }
12
+ export interface StreamChunk {
13
+ delta?: string;
14
+ done: boolean;
15
+ messageId?: string;
16
+ toolCalls?: Array<{
17
+ name: string;
18
+ input: unknown;
19
+ output?: unknown;
20
+ }>;
21
+ }
22
+ export interface StreamChunkResponse {
23
+ success: boolean;
24
+ messageId: string;
25
+ }
26
+ /**
27
+ * POST a single token chunk to Conduit's session stream endpoint.
28
+ *
29
+ * On the first chunk, omit `messageId` — Conduit returns one.
30
+ * Pass the returned `messageId` on all subsequent chunks.
31
+ * Send `{ done: true }` as the final chunk.
32
+ */
33
+ export declare function postStreamChunk(streamUrl: string, apiKey: string, chunk: StreamChunk): Promise<StreamChunkResponse>;
34
+ /**
35
+ * Send the full agent reply to Conduit as a stream of chunks.
36
+ *
37
+ * Splits `text` into ~200-character chunks so the Conduit UI renders
38
+ * streaming output progressively. A final `{ done: true }` chunk closes
39
+ * the stream.
40
+ */
41
+ export declare function streamReplyToConduit(streamUrl: string, apiKey: string, text: string): Promise<void>;
42
+ /**
43
+ * Verify that Conduit is reachable and the API key is valid.
44
+ * Returns `{ ok: true }` on success, `{ ok: false, error }` on failure.
45
+ */
46
+ export declare function verifyConnection(config: ConduitClientConfig): Promise<{
47
+ ok: boolean;
48
+ error?: string;
49
+ }>;
50
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CACvE;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,WAAW,GACjB,OAAO,CAAC,mBAAmB,CAAC,CAgB9B;AAED;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACxC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CAqBf;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAW5G"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Conduit API client used by the OpenClaw channel plugin.
3
+ *
4
+ * Responsibilities:
5
+ * - Verify the Conduit server is reachable and the API key is valid.
6
+ * - Stream reply token chunks back to Conduit's session stream endpoint.
7
+ */
8
+ /**
9
+ * POST a single token chunk to Conduit's session stream endpoint.
10
+ *
11
+ * On the first chunk, omit `messageId` — Conduit returns one.
12
+ * Pass the returned `messageId` on all subsequent chunks.
13
+ * Send `{ done: true }` as the final chunk.
14
+ */
15
+ export async function postStreamChunk(streamUrl, apiKey, chunk) {
16
+ const res = await fetch(streamUrl, {
17
+ method: 'POST',
18
+ headers: {
19
+ 'Content-Type': 'application/json',
20
+ 'X-API-Key': apiKey,
21
+ },
22
+ body: JSON.stringify(chunk),
23
+ signal: AbortSignal.timeout(15_000),
24
+ });
25
+ if (!res.ok) {
26
+ throw new Error(`Conduit stream endpoint returned ${res.status}: ${await res.text()}`);
27
+ }
28
+ return res.json();
29
+ }
30
+ /**
31
+ * Send the full agent reply to Conduit as a stream of chunks.
32
+ *
33
+ * Splits `text` into ~200-character chunks so the Conduit UI renders
34
+ * streaming output progressively. A final `{ done: true }` chunk closes
35
+ * the stream.
36
+ */
37
+ export async function streamReplyToConduit(streamUrl, apiKey, text) {
38
+ const CHUNK_SIZE = 200;
39
+ let messageId;
40
+ // Split into chunks; keep at least one iteration for empty/done responses.
41
+ const chunks = [];
42
+ for (let i = 0; i < text.length; i += CHUNK_SIZE) {
43
+ chunks.push(text.slice(i, i + CHUNK_SIZE));
44
+ }
45
+ if (chunks.length === 0)
46
+ chunks.push('');
47
+ for (let i = 0; i < chunks.length; i++) {
48
+ const isLast = i === chunks.length - 1;
49
+ const body = {
50
+ delta: chunks[i],
51
+ done: isLast,
52
+ ...(messageId ? { messageId } : {}),
53
+ };
54
+ const result = await postStreamChunk(streamUrl, apiKey, body);
55
+ if (!messageId)
56
+ messageId = result.messageId;
57
+ }
58
+ }
59
+ /**
60
+ * Verify that Conduit is reachable and the API key is valid.
61
+ * Returns `{ ok: true }` on success, `{ ok: false, error }` on failure.
62
+ */
63
+ export async function verifyConnection(config) {
64
+ try {
65
+ const res = await fetch(`${config.baseUrl}/api/connections`, {
66
+ headers: { 'X-API-Key': config.apiKey },
67
+ signal: AbortSignal.timeout(10_000),
68
+ });
69
+ if (res.ok)
70
+ return { ok: true };
71
+ return { ok: false, error: `Conduit returned ${res.status}` };
72
+ }
73
+ catch (err) {
74
+ return { ok: false, error: err instanceof Error ? err.message : String(err) };
75
+ }
76
+ }
77
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Inbound webhook handler for the Conduit OpenClaw channel plugin.
3
+ *
4
+ * Conduit POSTs a payload here whenever a user sends a message in the
5
+ * Conduit AI chat UI. This module parses that payload, dispatches it into
6
+ * the OpenClaw agent session, and returns the agent's reply by streaming
7
+ * chunks back to Conduit's session stream endpoint.
8
+ *
9
+ * Payload shape (from packages/server/src/api/ai.ts):
10
+ * {
11
+ * sessionId: string, // Conduit AI session UUID
12
+ * messageId: string, // Conduit message UUID
13
+ * role: "user",
14
+ * content: string, // User's message text
15
+ * conduitBaseUrl: string, // e.g. http://localhost:3101
16
+ * streamUrl: string, // e.g. http://localhost:3101/api/ai/sessions/<id>/stream
17
+ * systemPrompt?: string, // Injected on first message of each session
18
+ * }
19
+ */
20
+ export interface ConduitInboundPayload {
21
+ sessionId: string;
22
+ messageId: string;
23
+ role: 'user';
24
+ content: string;
25
+ conduitBaseUrl: string;
26
+ streamUrl: string;
27
+ systemPrompt?: string;
28
+ }
29
+ export interface DispatchFn {
30
+ (payload: ConduitInboundPayload): Promise<string>;
31
+ }
32
+ /**
33
+ * Validate and parse the raw request body as a ConduitInboundPayload.
34
+ * Throws if required fields are missing.
35
+ */
36
+ export declare function parseInboundPayload(body: unknown): ConduitInboundPayload;
37
+ /**
38
+ * Verify the inbound request's Authorization header against the configured
39
+ * webhook secret. Returns true if verification passes or no secret is set.
40
+ */
41
+ export declare function verifyWebhookSecret(authHeader: string | undefined, expectedSecret: string | undefined): boolean;
42
+ /**
43
+ * Handle one inbound Conduit message:
44
+ * 1. Dispatch it to the OpenClaw agent via `dispatch`.
45
+ * 2. Stream the agent's reply back to Conduit.
46
+ *
47
+ * `dispatch` is injected from the channel entry point and calls the
48
+ * OpenClaw agent runtime to produce a reply string.
49
+ */
50
+ export declare function handleConduitInbound(payload: ConduitInboundPayload, apiKey: string, dispatch: DispatchFn): Promise<void>;
51
+ //# sourceMappingURL=inbound.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inbound.d.ts","sourceRoot":"","sources":["../../src/inbound.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,UAAU;IACzB,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACnD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,OAAO,GAAG,qBAAqB,CAsBxE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,cAAc,EAAE,MAAM,GAAG,SAAS,GACjC,OAAO,CAWT;AAED;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,qBAAqB,EAC9B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,UAAU,GACnB,OAAO,CAAC,IAAI,CAAC,CAUf"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Inbound webhook handler for the Conduit OpenClaw channel plugin.
3
+ *
4
+ * Conduit POSTs a payload here whenever a user sends a message in the
5
+ * Conduit AI chat UI. This module parses that payload, dispatches it into
6
+ * the OpenClaw agent session, and returns the agent's reply by streaming
7
+ * chunks back to Conduit's session stream endpoint.
8
+ *
9
+ * Payload shape (from packages/server/src/api/ai.ts):
10
+ * {
11
+ * sessionId: string, // Conduit AI session UUID
12
+ * messageId: string, // Conduit message UUID
13
+ * role: "user",
14
+ * content: string, // User's message text
15
+ * conduitBaseUrl: string, // e.g. http://localhost:3101
16
+ * streamUrl: string, // e.g. http://localhost:3101/api/ai/sessions/<id>/stream
17
+ * systemPrompt?: string, // Injected on first message of each session
18
+ * }
19
+ */
20
+ import { streamReplyToConduit } from './client.js';
21
+ /**
22
+ * Validate and parse the raw request body as a ConduitInboundPayload.
23
+ * Throws if required fields are missing.
24
+ */
25
+ export function parseInboundPayload(body) {
26
+ if (typeof body !== 'object' || body === null) {
27
+ throw new Error('Request body must be a JSON object');
28
+ }
29
+ const b = body;
30
+ const required = ['sessionId', 'messageId', 'role', 'content', 'conduitBaseUrl', 'streamUrl'];
31
+ for (const field of required) {
32
+ if (typeof b[field] !== 'string' || !b[field].length) {
33
+ throw new Error(`Missing or invalid field: ${field}`);
34
+ }
35
+ }
36
+ return {
37
+ sessionId: b['sessionId'],
38
+ messageId: b['messageId'],
39
+ role: 'user',
40
+ content: b['content'],
41
+ conduitBaseUrl: b['conduitBaseUrl'],
42
+ streamUrl: b['streamUrl'],
43
+ systemPrompt: typeof b['systemPrompt'] === 'string' ? b['systemPrompt'] : undefined,
44
+ };
45
+ }
46
+ /**
47
+ * Verify the inbound request's Authorization header against the configured
48
+ * webhook secret. Returns true if verification passes or no secret is set.
49
+ */
50
+ export function verifyWebhookSecret(authHeader, expectedSecret) {
51
+ if (!expectedSecret)
52
+ return true;
53
+ if (!authHeader)
54
+ return false;
55
+ const token = authHeader.startsWith('Bearer ') ? authHeader.slice(7) : authHeader;
56
+ // Constant-time comparison to prevent timing attacks.
57
+ if (token.length !== expectedSecret.length)
58
+ return false;
59
+ let mismatch = 0;
60
+ for (let i = 0; i < token.length; i++) {
61
+ mismatch |= token.charCodeAt(i) ^ expectedSecret.charCodeAt(i);
62
+ }
63
+ return mismatch === 0;
64
+ }
65
+ /**
66
+ * Handle one inbound Conduit message:
67
+ * 1. Dispatch it to the OpenClaw agent via `dispatch`.
68
+ * 2. Stream the agent's reply back to Conduit.
69
+ *
70
+ * `dispatch` is injected from the channel entry point and calls the
71
+ * OpenClaw agent runtime to produce a reply string.
72
+ */
73
+ export async function handleConduitInbound(payload, apiKey, dispatch) {
74
+ let replyText;
75
+ try {
76
+ replyText = await dispatch(payload);
77
+ }
78
+ catch (err) {
79
+ replyText = `Error generating response: ${err instanceof Error ? err.message : String(err)}`;
80
+ }
81
+ await streamReplyToConduit(payload.streamUrl, apiKey, replyText);
82
+ }
83
+ //# sourceMappingURL=inbound.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inbound.js","sourceRoot":"","sources":["../../src/inbound.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAgBnD;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAa;IAC/C,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;IACD,MAAM,CAAC,GAAG,IAA+B,CAAC;IAE1C,MAAM,QAAQ,GAAG,CAAC,WAAW,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,gBAAgB,EAAE,WAAW,CAAU,CAAC;IACvG,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;QAC7B,IAAI,OAAO,CAAC,CAAC,KAAK,CAAC,KAAK,QAAQ,IAAI,CAAE,CAAC,CAAC,KAAK,CAAY,CAAC,MAAM,EAAE,CAAC;YACjE,MAAM,IAAI,KAAK,CAAC,6BAA6B,KAAK,EAAE,CAAC,CAAC;QACxD,CAAC;IACH,CAAC;IAED,OAAO;QACL,SAAS,EAAO,CAAC,CAAC,WAAW,CAAW;QACxC,SAAS,EAAO,CAAC,CAAC,WAAW,CAAW;QACxC,IAAI,EAAY,MAAM;QACtB,OAAO,EAAS,CAAC,CAAC,SAAS,CAAW;QACtC,cAAc,EAAE,CAAC,CAAC,gBAAgB,CAAW;QAC7C,SAAS,EAAO,CAAC,CAAC,WAAW,CAAW;QACxC,YAAY,EAAI,OAAO,CAAC,CAAC,cAAc,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,SAAS;KACtF,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CACjC,UAA8B,EAC9B,cAAkC;IAElC,IAAI,CAAC,cAAc;QAAE,OAAO,IAAI,CAAC;IACjC,IAAI,CAAC,UAAU;QAAE,OAAO,KAAK,CAAC;IAC9B,MAAM,KAAK,GAAG,UAAU,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;IAClF,sDAAsD;IACtD,IAAI,KAAK,CAAC,MAAM,KAAK,cAAc,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IACzD,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,QAAQ,IAAI,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IACjE,CAAC;IACD,OAAO,QAAQ,KAAK,CAAC,CAAC;AACxB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,OAA8B,EAC9B,MAAc,EACd,QAAoB;IAEpB,IAAI,SAAiB,CAAC;IAEtB,IAAI,CAAC;QACH,SAAS,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,SAAS,GAAG,8BAA8B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;IAC/F,CAAC;IAED,MAAM,oBAAoB,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;AACnE,CAAC"}
@@ -0,0 +1,37 @@
1
+ {
2
+ "id": "conduit",
3
+ "kind": "channel",
4
+ "channels": ["conduit"],
5
+ "name": "Conduit",
6
+ "description": "Conduit personal communications hub — read messages, emails, and calendar; queue outbound sends for approval.",
7
+ "configSchema": {
8
+ "type": "object",
9
+ "additionalProperties": false,
10
+ "properties": {
11
+ "conduit": {
12
+ "type": "object",
13
+ "additionalProperties": false,
14
+ "required": ["baseUrl", "apiKey"],
15
+ "properties": {
16
+ "baseUrl": {
17
+ "type": "string",
18
+ "description": "Base URL of your Conduit server, e.g. http://localhost:3101"
19
+ },
20
+ "apiKey": {
21
+ "type": "string",
22
+ "description": "Conduit API key (sk-arb-...). Generate one in Settings → Permissions."
23
+ },
24
+ "allowFrom": {
25
+ "type": "array",
26
+ "items": { "type": "string" },
27
+ "description": "Allowlist of OpenClaw user identifiers permitted to receive Conduit messages. Leave empty to allow all."
28
+ },
29
+ "webhookSecret": {
30
+ "type": "string",
31
+ "description": "Optional secret Conduit sends as Authorization: Bearer <secret> on each inbound message for request verification."
32
+ }
33
+ }
34
+ }
35
+ }
36
+ }
37
+ }
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@w3osc/openclaw-conduit",
3
+ "version": "1.0.0",
4
+ "description": "OpenClaw channel plugin that connects Conduit as a native messaging channel",
5
+ "type": "module",
6
+ "exports": {
7
+ ".": "./dist/index.js",
8
+ "./setup": "./dist/setup-entry.js"
9
+ },
10
+ "main": "./dist/index.js",
11
+ "files": [
12
+ "dist",
13
+ "openclaw.plugin.json"
14
+ ],
15
+ "scripts": {
16
+ "build": "tsc",
17
+ "dev": "tsc --watch",
18
+ "lint": "tsc --noEmit",
19
+ "prepublishOnly": "npm run build"
20
+ },
21
+ "openclaw": {
22
+ "extensions": ["./dist/index.js"],
23
+ "setupEntry": "./dist/setup-entry.js",
24
+ "channel": {
25
+ "id": "conduit",
26
+ "label": "Conduit",
27
+ "blurb": "Connect OpenClaw to Conduit — a self-hosted personal communications hub."
28
+ },
29
+ "compat": {
30
+ "pluginApi": ">=2026.3.24-beta.2",
31
+ "minGatewayVersion": "2026.3.24-beta.2"
32
+ }
33
+ },
34
+ "keywords": ["openclaw", "conduit", "channel", "plugin"],
35
+ "license": "MIT",
36
+ "devDependencies": {
37
+ "openclaw": "latest",
38
+ "typescript": "^6.0.2",
39
+ "@types/node": "^22.10.0"
40
+ },
41
+ "peerDependencies": {
42
+ "openclaw": ">=2026.3.24-beta.2"
43
+ }
44
+ }