@clawhouse/openclaw-plugin 0.1.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.
@@ -0,0 +1,3 @@
1
+ import type { ChannelPlugin } from './types';
2
+ export declare const clawHousePlugin: ChannelPlugin;
3
+ //# sourceMappingURL=channel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,aAAa,EAGd,MAAM,SAAS,CAAC;AAOjB,eAAO,MAAM,eAAe,EAAE,aA8J7B,CAAC"}
@@ -0,0 +1,148 @@
1
+ import { ClawHouseClient } from './client';
2
+ import { startClawHouseConnection } from './gateway';
3
+ import { getClawHouseRuntime } from './runtime';
4
+ function getChannelConfig(cfg) {
5
+ const c = cfg;
6
+ return c?.channels?.clawhouse ?? null;
7
+ }
8
+ export const clawHousePlugin = {
9
+ id: 'clawhouse',
10
+ meta: {
11
+ name: 'ClawHouse',
12
+ description: '1:1 messaging channel for ClawHouse bots',
13
+ },
14
+ capabilities: {
15
+ text: true,
16
+ media: false,
17
+ reactions: false,
18
+ threads: true,
19
+ editing: false,
20
+ },
21
+ config: {
22
+ listAccountIds(cfg) {
23
+ const ch = getChannelConfig(cfg);
24
+ if (!ch)
25
+ return [];
26
+ if (ch.accounts && Object.keys(ch.accounts).length > 0) {
27
+ return Object.keys(ch.accounts);
28
+ }
29
+ return ['default'];
30
+ },
31
+ resolveAccount(cfg, accountId) {
32
+ const ch = getChannelConfig(cfg);
33
+ if (!ch) {
34
+ return {
35
+ accountId: accountId ?? 'default',
36
+ botToken: '',
37
+ apiUrl: '',
38
+ wsUrl: '',
39
+ enabled: false,
40
+ };
41
+ }
42
+ const id = accountId ?? 'default';
43
+ const acct = id !== 'default' && ch.accounts?.[id] ? ch.accounts[id] : ch;
44
+ return {
45
+ accountId: id,
46
+ botToken: acct.botToken ?? '',
47
+ apiUrl: acct.apiUrl ?? '',
48
+ wsUrl: acct.wsUrl ?? '',
49
+ enabled: acct.enabled !== false,
50
+ };
51
+ },
52
+ isConfigured(account) {
53
+ return Boolean(account.botToken && account.apiUrl);
54
+ },
55
+ isEnabled(account) {
56
+ return account.enabled;
57
+ },
58
+ describeAccount(account) {
59
+ return {
60
+ running: false,
61
+ lastStartAt: undefined,
62
+ lastStopAt: undefined,
63
+ lastError: undefined,
64
+ };
65
+ },
66
+ },
67
+ outbound: {
68
+ deliveryMode: 'direct',
69
+ chunkerMode: 'markdown',
70
+ textChunkLimit: 2000,
71
+ async sendText(ctx) {
72
+ const runtime = getClawHouseRuntime();
73
+ const cfg = runtime.config.loadConfig();
74
+ const ch = getChannelConfig(cfg);
75
+ if (!ch) {
76
+ return { channel: 'clawhouse', success: false };
77
+ }
78
+ const acct = clawHousePlugin.config.resolveAccount(cfg, ctx.accountId);
79
+ const client = new ClawHouseClient(acct.botToken, acct.apiUrl);
80
+ try {
81
+ await client.sendMessage({
82
+ userId: ctx.to,
83
+ content: ctx.text,
84
+ taskId: ctx.threadId ? String(ctx.threadId) : undefined,
85
+ });
86
+ return {
87
+ channel: 'clawhouse',
88
+ success: true,
89
+ threadId: ctx.threadId ? String(ctx.threadId) : undefined,
90
+ };
91
+ }
92
+ catch {
93
+ return { channel: 'clawhouse', success: false };
94
+ }
95
+ },
96
+ },
97
+ gateway: {
98
+ async startAccount(ctx) {
99
+ return startClawHouseConnection(ctx);
100
+ },
101
+ },
102
+ setup: {
103
+ applyAccountConfig(params) {
104
+ const { cfg, accountId, input } = params;
105
+ const config = cfg;
106
+ const channels = (config.channels ?? {});
107
+ const clawhouse = (channels.clawhouse ?? {});
108
+ if (accountId === 'default') {
109
+ clawhouse.botToken = input.botToken;
110
+ clawhouse.apiUrl = input.apiUrl;
111
+ clawhouse.wsUrl = input.wsUrl;
112
+ clawhouse.enabled = true;
113
+ }
114
+ else {
115
+ const accounts = (clawhouse.accounts ?? {});
116
+ accounts[accountId] = {
117
+ botToken: input.botToken,
118
+ apiUrl: input.apiUrl,
119
+ wsUrl: input.wsUrl,
120
+ enabled: true,
121
+ };
122
+ clawhouse.accounts = accounts;
123
+ }
124
+ channels.clawhouse = clawhouse;
125
+ config.channels = channels;
126
+ return config;
127
+ },
128
+ validateInput(params) {
129
+ const { input } = params;
130
+ if (!input.botToken?.startsWith('bot_')) {
131
+ return 'Bot token must start with "bot_"';
132
+ }
133
+ if (!input.apiUrl) {
134
+ return 'API URL is required';
135
+ }
136
+ if (!input.wsUrl) {
137
+ return 'WebSocket URL is required';
138
+ }
139
+ return null;
140
+ },
141
+ },
142
+ security: {
143
+ resolveDmPolicy() {
144
+ return { policy: 'open' };
145
+ },
146
+ },
147
+ };
148
+ //# 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,56 @@
1
+ import type { MessagesResponse, WsTicketResponse } from './types';
2
+ /**
3
+ * HTTP client for the ClawHouse bot API.
4
+ * All endpoints use tRPC via HTTP POST/GET.
5
+ */
6
+ export declare class ClawHouseClient {
7
+ private botToken;
8
+ private apiUrl;
9
+ constructor(botToken: string, apiUrl: string);
10
+ private request;
11
+ sendMessage(input: {
12
+ userId: string;
13
+ content: string;
14
+ taskId?: string;
15
+ }): Promise<unknown>;
16
+ listMessages(input: {
17
+ userId?: string;
18
+ cursor?: string | null;
19
+ limit?: number;
20
+ }): Promise<MessagesResponse>;
21
+ getWsTicket(): Promise<WsTicketResponse>;
22
+ comment(input: {
23
+ taskId: string;
24
+ content: string;
25
+ }): Promise<unknown>;
26
+ createTask(input: {
27
+ projectId: string;
28
+ title: string;
29
+ instructions?: string;
30
+ }): Promise<unknown>;
31
+ listTasks(input: {
32
+ projectId: string;
33
+ status?: string;
34
+ }): Promise<unknown[]>;
35
+ done(input: {
36
+ taskId: string;
37
+ reason: string;
38
+ deliverable?: string;
39
+ }): Promise<unknown>;
40
+ giveup(input: {
41
+ taskId: string;
42
+ reason: string;
43
+ deliverable?: string;
44
+ }): Promise<unknown>;
45
+ getNextTask(input?: {
46
+ projectId?: string;
47
+ }): Promise<unknown>;
48
+ listProjects(): Promise<unknown[]>;
49
+ createProject(input: {
50
+ name: string;
51
+ key: string;
52
+ description?: string;
53
+ color?: string;
54
+ }): Promise<unknown>;
55
+ }
56
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAElE;;;GAGG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,MAAM,CAAS;gBAEX,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;YAK9B,OAAO;IA+Bf,WAAW,CAAC,KAAK,EAAE;QACvB,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,GAAG,OAAO,CAAC,OAAO,CAAC;IAId,YAAY,CAAC,KAAK,EAAE;QACxB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACvB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAKvB,WAAW,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAKxC,OAAO,CAAC,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAIrE,UAAU,CAAC,KAAK,EAAE;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE,MAAM,CAAC;QACd,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,GAAG,OAAO,CAAC,OAAO,CAAC;IAId,SAAS,CAAC,KAAK,EAAE;QACrB,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAIhB,IAAI,CAAC,KAAK,EAAE;QAChB,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,GAAG,OAAO,CAAC,OAAO,CAAC;IAId,MAAM,CAAC,KAAK,EAAE;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,GAAG,OAAO,CAAC,OAAO,CAAC;IAId,WAAW,CAAC,KAAK,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAI7D,YAAY,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAIlC,aAAa,CAAC,KAAK,EAAE;QACzB,IAAI,EAAE,MAAM,CAAC;QACb,GAAG,EAAE,MAAM,CAAC;QACZ,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GAAG,OAAO,CAAC,OAAO,CAAC;CAGrB"}
package/dist/client.js ADDED
@@ -0,0 +1,68 @@
1
+ /**
2
+ * HTTP client for the ClawHouse bot API.
3
+ * All endpoints use tRPC via HTTP POST/GET.
4
+ */
5
+ export class ClawHouseClient {
6
+ botToken;
7
+ apiUrl;
8
+ constructor(botToken, apiUrl) {
9
+ this.botToken = botToken;
10
+ this.apiUrl = apiUrl.replace(/\/$/, '');
11
+ }
12
+ async request(method, procedure, input) {
13
+ const url = method === 'GET' && input
14
+ ? `${this.apiUrl}/${procedure}?input=${encodeURIComponent(JSON.stringify(input))}`
15
+ : `${this.apiUrl}/${procedure}`;
16
+ const response = await fetch(url, {
17
+ method,
18
+ headers: {
19
+ Authorization: `Bot ${this.botToken}`,
20
+ 'Content-Type': 'application/json',
21
+ },
22
+ body: method === 'POST' ? JSON.stringify(input) : undefined,
23
+ });
24
+ if (!response.ok) {
25
+ const text = await response.text().catch(() => 'unknown error');
26
+ throw new Error(`ClawHouse API error: ${response.status} ${response.statusText} — ${text}`);
27
+ }
28
+ const json = (await response.json());
29
+ return json.result?.data;
30
+ }
31
+ // Messages
32
+ async sendMessage(input) {
33
+ return this.request('POST', 'messages.send', input);
34
+ }
35
+ async listMessages(input) {
36
+ return this.request('GET', 'messages.list', input);
37
+ }
38
+ // WebSocket ticket
39
+ async getWsTicket() {
40
+ return this.request('POST', 'messages.wsTicket', {});
41
+ }
42
+ // Tasks
43
+ async comment(input) {
44
+ return this.request('POST', 'tasks.comment', input);
45
+ }
46
+ async createTask(input) {
47
+ return this.request('POST', 'tasks.create', input);
48
+ }
49
+ async listTasks(input) {
50
+ return this.request('GET', 'tasks.list', input);
51
+ }
52
+ async done(input) {
53
+ return this.request('POST', 'tasks.done', input);
54
+ }
55
+ async giveup(input) {
56
+ return this.request('POST', 'tasks.giveup', input);
57
+ }
58
+ async getNextTask(input) {
59
+ return this.request('GET', 'tasks.getNextTask', input ?? {});
60
+ }
61
+ async listProjects() {
62
+ return this.request('GET', 'projects.list', {});
63
+ }
64
+ async createProject(input) {
65
+ return this.request('POST', 'projects.create', input);
66
+ }
67
+ }
68
+ //# 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,9 @@
1
+ import type { ChannelGatewayContext, ChatMessage } from './types';
2
+ /**
3
+ * Delivers a ClawHouse chat message to the OpenClaw agent pipeline.
4
+ *
5
+ * Each message produces a single inbound message.
6
+ * If the message has a taskId, it's set as ThreadId for conversation threading.
7
+ */
8
+ export declare function deliverMessageToAgent(ctx: ChannelGatewayContext, message: ChatMessage): Promise<void>;
9
+ //# sourceMappingURL=deliver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deliver.d.ts","sourceRoot":"","sources":["../src/deliver.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qBAAqB,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAElE;;;;;GAKG;AACH,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,qBAAqB,EAC1B,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,CAiCf"}
@@ -0,0 +1,40 @@
1
+ import { getClawHouseRuntime } from './runtime';
2
+ /**
3
+ * Delivers a ClawHouse chat message to the OpenClaw agent pipeline.
4
+ *
5
+ * Each message produces a single inbound message.
6
+ * If the message has a taskId, it's set as ThreadId for conversation threading.
7
+ */
8
+ export async function deliverMessageToAgent(ctx, message) {
9
+ const runtime = getClawHouseRuntime();
10
+ const msgCtx = runtime.channel.reply.finalizeInboundContext({
11
+ Body: message.content,
12
+ RawBody: message.content,
13
+ ChatType: 'dm',
14
+ Provider: 'clawhouse',
15
+ Surface: 'clawhouse',
16
+ From: message.userId,
17
+ To: message.botId,
18
+ MessageSid: message.messageId,
19
+ ThreadId: message.taskId ?? undefined,
20
+ Timestamp: message.createdAt,
21
+ AccountId: ctx.accountId,
22
+ FromName: message.userName ?? 'Unknown',
23
+ });
24
+ try {
25
+ const cfg = runtime.config.loadConfig();
26
+ const dispatcher = runtime.channel.reply.createReplyDispatcherWithTyping({
27
+ channel: 'clawhouse',
28
+ accountId: ctx.accountId,
29
+ });
30
+ await runtime.channel.reply.dispatchReplyFromConfig({
31
+ ctx: msgCtx,
32
+ cfg,
33
+ dispatcher,
34
+ });
35
+ }
36
+ catch {
37
+ // Non-fatal — agent routing may not be configured yet
38
+ }
39
+ }
40
+ //# sourceMappingURL=deliver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deliver.js","sourceRoot":"","sources":["../src/deliver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAGhD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,GAA0B,EAC1B,OAAoB;IAEpB,MAAM,OAAO,GAAG,mBAAmB,EAAE,CAAC;IAEtC,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,sBAAsB,CAAC;QAC1D,IAAI,EAAE,OAAO,CAAC,OAAO;QACrB,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,QAAQ,EAAE,IAAI;QACd,QAAQ,EAAE,WAAW;QACrB,OAAO,EAAE,WAAW;QACpB,IAAI,EAAE,OAAO,CAAC,MAAM;QACpB,EAAE,EAAE,OAAO,CAAC,KAAK;QACjB,UAAU,EAAE,OAAO,CAAC,SAAS;QAC7B,QAAQ,EAAE,OAAO,CAAC,MAAM,IAAI,SAAS;QACrC,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,SAAS;KACxC,CAAC,CAAC;IAEH,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;QACxC,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,+BAA+B,CAAC;YACvE,OAAO,EAAE,WAAW;YACpB,SAAS,EAAE,GAAG,CAAC,SAAS;SACzB,CAAC,CAAC;QAEH,MAAM,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,uBAAuB,CAAC;YAClD,GAAG,EAAE,MAAM;YACX,GAAG;YACH,UAAU;SACX,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,sDAAsD;IACxD,CAAC;AACH,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { ChannelGatewayContext } from './types';
2
+ /**
3
+ * Main entry point for the ClawHouse channel gateway.
4
+ * Called by OpenClaw's channel manager via gateway.startAccount().
5
+ *
6
+ * Maintains a WebSocket connection for real-time notifications
7
+ * and polls the messages endpoint for actual data.
8
+ * Falls back to interval-based polling if WebSocket is unavailable.
9
+ */
10
+ export declare function startClawHouseConnection(ctx: ChannelGatewayContext): Promise<void>;
11
+ //# sourceMappingURL=gateway.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gateway.d.ts","sourceRoot":"","sources":["../src/gateway.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,qBAAqB,EAItB,MAAM,SAAS,CAAC;AAyEjB;;;;;;;GAOG;AACH,wBAAsB,wBAAwB,CAC5C,GAAG,EAAE,qBAAqB,GACzB,OAAO,CAAC,IAAI,CAAC,CAiDf"}
@@ -0,0 +1,214 @@
1
+ import WebSocket from 'ws';
2
+ import { ClawHouseClient } from './client';
3
+ import { deliverMessageToAgent } from './deliver';
4
+ import { getClawHouseRuntime } from './runtime';
5
+ const PING_INTERVAL_MS = 5 * 60 * 1000; // 5 minutes (API GW idle timeout = 10 min)
6
+ const POLL_FALLBACK_INTERVAL_MS = 30 * 1000; // 30s fallback when WS is down
7
+ const BACKOFF_INITIAL_MS = 2000;
8
+ const BACKOFF_MAX_MS = 30000;
9
+ const BACKOFF_FACTOR = 1.8;
10
+ function nextBackoff(state) {
11
+ const delay = Math.min(BACKOFF_INITIAL_MS * Math.pow(BACKOFF_FACTOR, state.attempt), BACKOFF_MAX_MS);
12
+ const jitter = delay * 0.25 * Math.random();
13
+ state.attempt++;
14
+ return delay + jitter;
15
+ }
16
+ function resetBackoff(state) {
17
+ state.attempt = 0;
18
+ }
19
+ function sleepWithAbort(ms, signal) {
20
+ return new Promise((resolve) => {
21
+ const timer = setTimeout(resolve, ms);
22
+ signal.addEventListener('abort', () => {
23
+ clearTimeout(timer);
24
+ resolve();
25
+ }, { once: true });
26
+ });
27
+ }
28
+ /**
29
+ * Persistent cursor management.
30
+ * Stores cursor on disk so we can resume from the right position after restart.
31
+ */
32
+ function loadCursor(ctx) {
33
+ try {
34
+ const runtime = getClawHouseRuntime();
35
+ const fs = require('fs');
36
+ const path = runtime.state.resolveStorePath(`clawhouse/${ctx.accountId}/cursor`);
37
+ return fs.readFileSync(path, 'utf-8').trim() || null;
38
+ }
39
+ catch {
40
+ return null;
41
+ }
42
+ }
43
+ function saveCursor(ctx, cursor) {
44
+ try {
45
+ const runtime = getClawHouseRuntime();
46
+ const fs = require('fs');
47
+ const path = require('path');
48
+ const filePath = runtime.state.resolveStorePath(`clawhouse/${ctx.accountId}/cursor`);
49
+ const dir = path.dirname(filePath);
50
+ fs.mkdirSync(dir, { recursive: true });
51
+ fs.writeFileSync(filePath, cursor, 'utf-8');
52
+ }
53
+ catch {
54
+ // Non-fatal — we'll just re-process some messages on restart
55
+ }
56
+ }
57
+ /**
58
+ * Main entry point for the ClawHouse channel gateway.
59
+ * Called by OpenClaw's channel manager via gateway.startAccount().
60
+ *
61
+ * Maintains a WebSocket connection for real-time notifications
62
+ * and polls the messages endpoint for actual data.
63
+ * Falls back to interval-based polling if WebSocket is unavailable.
64
+ */
65
+ export async function startClawHouseConnection(ctx) {
66
+ const account = ctx.account;
67
+ const client = new ClawHouseClient(account.botToken, account.apiUrl);
68
+ const log = ctx.log ?? getClawHouseRuntime().logging.createLogger('clawhouse');
69
+ let cursor = loadCursor(ctx);
70
+ const backoff = { attempt: 0 };
71
+ log.info(`Starting ClawHouse connection for account ${ctx.accountId}` +
72
+ (cursor ? ` (resuming from cursor ${cursor})` : ' (fresh start)'));
73
+ // Outer reconnection loop — runs until OpenClaw shuts down
74
+ while (!ctx.abortSignal.aborted) {
75
+ try {
76
+ const { ticket, wsUrl } = await client.getWsTicket();
77
+ resetBackoff(backoff);
78
+ log.info(`Got WS ticket, connecting to ${wsUrl}...`);
79
+ cursor = await runWebSocketConnection({
80
+ ticket,
81
+ wsUrl,
82
+ client,
83
+ ctx,
84
+ cursor,
85
+ log,
86
+ });
87
+ }
88
+ catch (err) {
89
+ const message = err instanceof Error ? err.message : String(err);
90
+ // If ticket fetch fails, fall back to polling
91
+ if (message.includes('API error')) {
92
+ log.warn(`Ticket fetch failed: ${message}. Falling back to polling.`);
93
+ cursor = await runPollingFallback({ client, ctx, cursor, log });
94
+ }
95
+ else {
96
+ log.warn(`Connection error: ${message}`);
97
+ }
98
+ if (ctx.abortSignal.aborted)
99
+ break;
100
+ const delay = nextBackoff(backoff);
101
+ log.info(`Reconnecting in ${Math.round(delay)}ms...`);
102
+ await sleepWithAbort(delay, ctx.abortSignal);
103
+ }
104
+ }
105
+ log.info('ClawHouse connection loop exited.');
106
+ }
107
+ /**
108
+ * Runs a single WebSocket connection session.
109
+ * Returns the latest cursor when the connection closes.
110
+ */
111
+ async function runWebSocketConnection(opts) {
112
+ const { ticket, wsUrl, client, ctx, log } = opts;
113
+ let cursor = opts.cursor;
114
+ return new Promise((resolve, reject) => {
115
+ const ws = new WebSocket(`${wsUrl}?ticket=${ticket}`);
116
+ let pingInterval;
117
+ ws.on('open', () => {
118
+ ctx.setStatus({ running: true, lastStartAt: Date.now() });
119
+ log.info('WebSocket connected.');
120
+ // Keepalive ping every 5 minutes
121
+ pingInterval = setInterval(() => {
122
+ if (ws.readyState === WebSocket.OPEN) {
123
+ ws.send(JSON.stringify({ action: 'ping' }));
124
+ }
125
+ }, PING_INTERVAL_MS);
126
+ // Initial catch-up poll
127
+ pollAndDeliver(client, ctx, cursor, log).then((newCursor) => {
128
+ if (newCursor)
129
+ cursor = newCursor;
130
+ });
131
+ });
132
+ ws.on('message', async (data) => {
133
+ try {
134
+ const msg = JSON.parse(data.toString());
135
+ if (msg.action === 'notify') {
136
+ // Thin notification — poll for full data
137
+ const newCursor = await pollAndDeliver(client, ctx, cursor, log);
138
+ if (newCursor)
139
+ cursor = newCursor;
140
+ }
141
+ // Ignore pong and other messages
142
+ }
143
+ catch (err) {
144
+ const message = err instanceof Error ? err.message : String(err);
145
+ log.warn(`Error processing WS message: ${message}`);
146
+ }
147
+ });
148
+ ws.on('close', (code, reason) => {
149
+ clearInterval(pingInterval);
150
+ ctx.setStatus({ running: false, lastStopAt: Date.now() });
151
+ log.info(`WebSocket closed: ${code} ${reason.toString()}`);
152
+ resolve(cursor);
153
+ });
154
+ ws.on('error', (err) => {
155
+ clearInterval(pingInterval);
156
+ ctx.setStatus({ running: false, lastError: err.message });
157
+ reject(err);
158
+ });
159
+ // Clean shutdown
160
+ ctx.abortSignal.addEventListener('abort', () => {
161
+ clearInterval(pingInterval);
162
+ ws.close(1000, 'shutdown');
163
+ }, { once: true });
164
+ });
165
+ }
166
+ /**
167
+ * Fallback polling loop when WebSocket is unavailable.
168
+ * Polls every 30s until aborted or until we should retry WebSocket.
169
+ */
170
+ async function runPollingFallback(opts) {
171
+ const { client, ctx, log } = opts;
172
+ let cursor = opts.cursor;
173
+ let iterations = 0;
174
+ const maxIterations = 10; // After 10 polls (~5 min), try WebSocket again
175
+ ctx.setStatus({ running: true, lastStartAt: Date.now() });
176
+ log.info('Running in polling fallback mode.');
177
+ while (!ctx.abortSignal.aborted && iterations < maxIterations) {
178
+ const newCursor = await pollAndDeliver(client, ctx, cursor, log);
179
+ if (newCursor)
180
+ cursor = newCursor;
181
+ iterations++;
182
+ await sleepWithAbort(POLL_FALLBACK_INTERVAL_MS, ctx.abortSignal);
183
+ }
184
+ ctx.setStatus({ running: false, lastStopAt: Date.now() });
185
+ return cursor;
186
+ }
187
+ /**
188
+ * Poll the messages endpoint and deliver new messages to the OpenClaw agent.
189
+ * Returns the new cursor, or null if no messages.
190
+ */
191
+ async function pollAndDeliver(client, ctx, cursor, log) {
192
+ try {
193
+ const response = await client.listMessages({
194
+ cursor,
195
+ });
196
+ if (response.items.length === 0)
197
+ return null;
198
+ log.info(`Received ${response.items.length} new message(s).`);
199
+ for (const message of response.items) {
200
+ await deliverMessageToAgent(ctx, message);
201
+ }
202
+ // Persist cursor
203
+ if (response.cursor) {
204
+ saveCursor(ctx, response.cursor);
205
+ }
206
+ return response.cursor;
207
+ }
208
+ catch (err) {
209
+ const message = err instanceof Error ? err.message : String(err);
210
+ log.warn(`Poll failed: ${message}`);
211
+ return null;
212
+ }
213
+ }
214
+ //# sourceMappingURL=gateway.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gateway.js","sourceRoot":"","sources":["../src/gateway.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,IAAI,CAAC;AAE3B,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAQhD,MAAM,gBAAgB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,2CAA2C;AACnF,MAAM,yBAAyB,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,+BAA+B;AAC5E,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAChC,MAAM,cAAc,GAAG,KAAK,CAAC;AAC7B,MAAM,cAAc,GAAG,GAAG,CAAC;AAM3B,SAAS,WAAW,CAAC,KAAmB;IACtC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CACpB,kBAAkB,GAAG,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE,KAAK,CAAC,OAAO,CAAC,EAC5D,cAAc,CACf,CAAC;IACF,MAAM,MAAM,GAAG,KAAK,GAAG,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;IAC5C,KAAK,CAAC,OAAO,EAAE,CAAC;IAChB,OAAO,KAAK,GAAG,MAAM,CAAC;AACxB,CAAC;AAED,SAAS,YAAY,CAAC,KAAmB;IACvC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC;AACpB,CAAC;AAED,SAAS,cAAc,CAAC,EAAU,EAAE,MAAmB;IACrD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QACtC,MAAM,CAAC,gBAAgB,CACrB,OAAO,EACP,GAAG,EAAE;YACH,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,OAAO,EAAE,CAAC;QACZ,CAAC,EACD,EAAE,IAAI,EAAE,IAAI,EAAE,CACf,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,SAAS,UAAU,CAAC,GAA0B;IAC5C,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,mBAAmB,EAAE,CAAC;QACtC,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAwB,CAAC;QAChD,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,gBAAgB,CACzC,aAAa,GAAG,CAAC,SAAS,SAAS,CACpC,CAAC;QACF,OAAO,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CAAC,GAA0B,EAAE,MAAc;IAC5D,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,mBAAmB,EAAE,CAAC;QACtC,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAwB,CAAC;QAChD,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAA0B,CAAC;QACtD,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAC7C,aAAa,GAAG,CAAC,SAAS,SAAS,CACpC,CAAC;QACF,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACnC,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACvC,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9C,CAAC;IAAC,MAAM,CAAC;QACP,6DAA6D;IAC/D,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,GAA0B;IAE1B,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC;IAC5B,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IACrE,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,IAAI,mBAAmB,EAAE,CAAC,OAAO,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;IAE/E,IAAI,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;IAC7B,MAAM,OAAO,GAAiB,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;IAE7C,GAAG,CAAC,IAAI,CACN,6CAA6C,GAAG,CAAC,SAAS,EAAE;QAC1D,CAAC,MAAM,CAAC,CAAC,CAAC,0BAA0B,MAAM,GAAG,CAAC,CAAC,CAAC,gBAAgB,CAAC,CACpE,CAAC;IAEF,2DAA2D;IAC3D,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;QAChC,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,WAAW,EAAE,CAAC;YACrD,YAAY,CAAC,OAAO,CAAC,CAAC;YAEtB,GAAG,CAAC,IAAI,CAAC,gCAAgC,KAAK,KAAK,CAAC,CAAC;YAErD,MAAM,GAAG,MAAM,sBAAsB,CAAC;gBACpC,MAAM;gBACN,KAAK;gBACL,MAAM;gBACN,GAAG;gBACH,MAAM;gBACN,GAAG;aACJ,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAEjE,8CAA8C;YAC9C,IAAI,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;gBAClC,GAAG,CAAC,IAAI,CAAC,wBAAwB,OAAO,4BAA4B,CAAC,CAAC;gBACtE,MAAM,GAAG,MAAM,kBAAkB,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;YAClE,CAAC;iBAAM,CAAC;gBACN,GAAG,CAAC,IAAI,CAAC,qBAAqB,OAAO,EAAE,CAAC,CAAC;YAC3C,CAAC;YAED,IAAI,GAAG,CAAC,WAAW,CAAC,OAAO;gBAAE,MAAM;YAEnC,MAAM,KAAK,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;YACnC,GAAG,CAAC,IAAI,CAAC,mBAAmB,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACtD,MAAM,cAAc,CAAC,KAAK,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;IAED,GAAG,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;AAChD,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,sBAAsB,CAAC,IAOrC;IACC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IACjD,IAAI,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IAEzB,OAAO,IAAI,OAAO,CAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACpD,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,GAAG,KAAK,WAAW,MAAM,EAAE,CAAC,CAAC;QACtD,IAAI,YAAwD,CAAC;QAE7D,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE;YACjB,GAAG,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YAC1D,GAAG,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;YAEjC,iCAAiC;YACjC,YAAY,GAAG,WAAW,CAAC,GAAG,EAAE;gBAC9B,IAAI,EAAE,CAAC,UAAU,KAAK,SAAS,CAAC,IAAI,EAAE,CAAC;oBACrC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;gBAC9C,CAAC;YACH,CAAC,EAAE,gBAAgB,CAAC,CAAC;YAErB,wBAAwB;YACxB,cAAc,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE;gBAC1D,IAAI,SAAS;oBAAE,MAAM,GAAG,SAAS,CAAC;YACpC,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YAC9B,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAwC,CAAC;gBAE/E,IAAI,GAAG,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;oBAC5B,yCAAyC;oBACzC,MAAM,SAAS,GAAG,MAAM,cAAc,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;oBACjE,IAAI,SAAS;wBAAE,MAAM,GAAG,SAAS,CAAC;gBACpC,CAAC;gBACD,iCAAiC;YACnC,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBACjE,GAAG,CAAC,IAAI,CAAC,gCAAgC,OAAO,EAAE,CAAC,CAAC;YACtD,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE;YAC9B,aAAa,CAAC,YAAY,CAAC,CAAC;YAC5B,GAAG,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YAC1D,GAAG,CAAC,IAAI,CAAC,qBAAqB,IAAI,IAAI,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;YAC3D,OAAO,CAAC,MAAM,CAAC,CAAC;QAClB,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACrB,aAAa,CAAC,YAAY,CAAC,CAAC;YAC5B,GAAG,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;YAC1D,MAAM,CAAC,GAAG,CAAC,CAAC;QACd,CAAC,CAAC,CAAC;QAEH,iBAAiB;QACjB,GAAG,CAAC,WAAW,CAAC,gBAAgB,CAC9B,OAAO,EACP,GAAG,EAAE;YACH,aAAa,CAAC,YAAY,CAAC,CAAC;YAC5B,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QAC7B,CAAC,EACD,EAAE,IAAI,EAAE,IAAI,EAAE,CACf,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,kBAAkB,CAAC,IAKjC;IACC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAClC,IAAI,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IACzB,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,MAAM,aAAa,GAAG,EAAE,CAAC,CAAC,+CAA+C;IAEzE,GAAG,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAC1D,GAAG,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;IAE9C,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,OAAO,IAAI,UAAU,GAAG,aAAa,EAAE,CAAC;QAC9D,MAAM,SAAS,GAAG,MAAM,cAAc,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;QACjE,IAAI,SAAS;YAAE,MAAM,GAAG,SAAS,CAAC;QAClC,UAAU,EAAE,CAAC;QACb,MAAM,cAAc,CAAC,yBAAyB,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC;IACnE,CAAC;IAED,GAAG,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAC1D,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,cAAc,CAC3B,MAAuB,EACvB,GAA0B,EAC1B,MAAqB,EACrB,GAAiB;IAEjB,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC;YACzC,MAAM;SACP,CAAC,CAAC;QAEH,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QAE7C,GAAG,CAAC,IAAI,CAAC,YAAY,QAAQ,CAAC,KAAK,CAAC,MAAM,kBAAkB,CAAC,CAAC;QAE9D,KAAK,MAAM,OAAO,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;YACrC,MAAM,qBAAqB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAC5C,CAAC;QAED,iBAAiB;QACjB,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;YACpB,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;QACnC,CAAC;QAED,OAAO,QAAQ,CAAC,MAAM,CAAC;IACzB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,GAAG,CAAC,IAAI,CAAC,gBAAgB,OAAO,EAAE,CAAC,CAAC;QACpC,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { OpenClawPluginApi } from './types';
2
+ declare const plugin: {
3
+ id: string;
4
+ name: string;
5
+ register(api: OpenClawPluginApi): void;
6
+ };
7
+ export default plugin;
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEjD,QAAA,MAAM,MAAM;;;kBAII,iBAAiB;CAQhC,CAAC;AAEF,eAAe,MAAM,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,18 @@
1
+ import { clawHousePlugin } from './channel';
2
+ import { setClawHouseRuntime } from './runtime';
3
+ import { createClawHouseTools } from './tools';
4
+ const plugin = {
5
+ id: 'clawhouse',
6
+ name: 'ClawHouse',
7
+ register(api) {
8
+ setClawHouseRuntime(api.runtime);
9
+ api.registerChannel({ plugin: clawHousePlugin });
10
+ api.registerTool((ctx) => {
11
+ if (ctx.sandboxed)
12
+ return null;
13
+ return createClawHouseTools(api);
14
+ });
15
+ },
16
+ };
17
+ export default plugin;
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAG/C,MAAM,MAAM,GAAG;IACb,EAAE,EAAE,WAAW;IACf,IAAI,EAAE,WAAW;IAEjB,QAAQ,CAAC,GAAsB;QAC7B,mBAAmB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACjC,GAAG,CAAC,eAAe,CAAC,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC,CAAC;QACjD,GAAG,CAAC,YAAY,CAAC,CAAC,GAAG,EAAE,EAAE;YACvB,IAAI,GAAG,CAAC,SAAS;gBAAE,OAAO,IAAI,CAAC;YAC/B,OAAO,oBAAoB,CAAC,GAAG,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;IACL,CAAC;CACF,CAAC;AAEF,eAAe,MAAM,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { PluginRuntime } from './types';
2
+ export declare function setClawHouseRuntime(runtime: PluginRuntime): void;
3
+ export declare function getClawHouseRuntime(): PluginRuntime;
4
+ //# sourceMappingURL=runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAI7C,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,CAEhE;AAED,wBAAgB,mBAAmB,IAAI,aAAa,CAOnD"}
@@ -0,0 +1,11 @@
1
+ let _runtime = null;
2
+ export function setClawHouseRuntime(runtime) {
3
+ _runtime = runtime;
4
+ }
5
+ export function getClawHouseRuntime() {
6
+ if (!_runtime) {
7
+ throw new Error('ClawHouse runtime not initialized. Ensure setClawHouseRuntime() is called during plugin registration.');
8
+ }
9
+ return _runtime;
10
+ }
11
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAEA,IAAI,QAAQ,GAAyB,IAAI,CAAC;AAE1C,MAAM,UAAU,mBAAmB,CAAC,OAAsB;IACxD,QAAQ,GAAG,OAAO,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,mBAAmB;IACjC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CACb,uGAAuG,CACxG,CAAC;IACJ,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { AnyAgentTool, OpenClawPluginApi } from './types';
2
+ /**
3
+ * Creates all ClawHouse agent tools.
4
+ * Returns null if the channel is not configured.
5
+ */
6
+ export declare function createClawHouseTools(api: OpenClawPluginApi): AnyAgentTool[] | null;
7
+ //# sourceMappingURL=tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAA4B,MAAM,SAAS,CAAC;AAoDzF;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,iBAAiB,GAAG,YAAY,EAAE,GAAG,IAAI,CA4JlF"}
package/dist/tools.js ADDED
@@ -0,0 +1,178 @@
1
+ import { Type } from '@sinclair/typebox';
2
+ import { ClawHouseClient } from './client';
3
+ /**
4
+ * Resolve the ClawHouse account from the plugin config.
5
+ * Shared logic with channel.ts — reads channels.clawhouse from config.
6
+ */
7
+ function resolveAccountFromConfig(api) {
8
+ const cfg = api.runtime.config.loadConfig();
9
+ const ch = cfg?.channels?.clawhouse;
10
+ if (!ch)
11
+ return null;
12
+ // Use first explicit account, or fall back to top-level config
13
+ if (ch.accounts && Object.keys(ch.accounts).length > 0) {
14
+ const [accountId, acct] = Object.entries(ch.accounts)[0];
15
+ if (!acct.botToken || !acct.apiUrl)
16
+ return null;
17
+ return {
18
+ accountId,
19
+ botToken: acct.botToken,
20
+ apiUrl: acct.apiUrl,
21
+ wsUrl: acct.wsUrl ?? '',
22
+ enabled: acct.enabled !== false,
23
+ };
24
+ }
25
+ if (!ch.botToken || !ch.apiUrl)
26
+ return null;
27
+ return {
28
+ accountId: 'default',
29
+ botToken: ch.botToken,
30
+ apiUrl: ch.apiUrl,
31
+ wsUrl: ch.wsUrl ?? '',
32
+ enabled: ch.enabled !== false,
33
+ };
34
+ }
35
+ function textResult(data) {
36
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
37
+ }
38
+ /**
39
+ * Creates all ClawHouse agent tools.
40
+ * Returns null if the channel is not configured.
41
+ */
42
+ export function createClawHouseTools(api) {
43
+ const account = resolveAccountFromConfig(api);
44
+ if (!account)
45
+ return null;
46
+ const client = new ClawHouseClient(account.botToken, account.apiUrl);
47
+ return [
48
+ {
49
+ name: 'clawhouse_get_next_task',
50
+ description: 'Pick up the next available task from ClawHouse. Atomically claims the oldest ready_for_bot task and moves it to working_on_it. Returns the task object with instructions, or null if none available.',
51
+ parameters: Type.Object({
52
+ projectId: Type.Optional(Type.String({ description: 'Filter to a specific project UUID' })),
53
+ }),
54
+ async execute(_id, params) {
55
+ const result = await client.getNextTask({
56
+ projectId: params.projectId,
57
+ });
58
+ return textResult(result);
59
+ },
60
+ },
61
+ {
62
+ name: 'clawhouse_list_tasks',
63
+ description: 'List all tasks in a ClawHouse project, ordered by most recently updated.',
64
+ parameters: Type.Object({
65
+ projectId: Type.String({ description: 'Project UUID (required)' }),
66
+ status: Type.Optional(Type.String({
67
+ description: 'Filter by status: ready_for_bot, working_on_it, waiting_for_human, done',
68
+ })),
69
+ }),
70
+ async execute(_id, params) {
71
+ const result = await client.listTasks({
72
+ projectId: params.projectId,
73
+ status: params.status,
74
+ });
75
+ return textResult(result);
76
+ },
77
+ },
78
+ {
79
+ name: 'clawhouse_comment',
80
+ description: 'Post a progress update comment on a ClawHouse task. Works on any accessible task regardless of status.',
81
+ parameters: Type.Object({
82
+ taskId: Type.String({ description: 'Task UUID' }),
83
+ content: Type.String({ description: 'Comment text (supports markdown)' }),
84
+ }),
85
+ async execute(_id, params) {
86
+ const result = await client.comment({
87
+ taskId: params.taskId,
88
+ content: params.content,
89
+ });
90
+ return textResult(result);
91
+ },
92
+ },
93
+ {
94
+ name: 'clawhouse_done',
95
+ description: 'Mark a working_on_it task as completed. Moves it to waiting_for_human. Always include a deliverable documenting your work in markdown.',
96
+ parameters: Type.Object({
97
+ taskId: Type.String({ description: 'Task UUID' }),
98
+ reason: Type.String({ description: 'Why the task is complete' }),
99
+ deliverable: Type.Optional(Type.String({
100
+ description: 'Markdown deliverable documenting what was done and results',
101
+ })),
102
+ }),
103
+ async execute(_id, params) {
104
+ const result = await client.done({
105
+ taskId: params.taskId,
106
+ reason: params.reason,
107
+ deliverable: params.deliverable,
108
+ });
109
+ return textResult(result);
110
+ },
111
+ },
112
+ {
113
+ name: 'clawhouse_giveup',
114
+ description: 'Give up on a working_on_it task. Moves it to waiting_for_human so a human can help. Always include a deliverable with partial progress.',
115
+ parameters: Type.Object({
116
+ taskId: Type.String({ description: 'Task UUID' }),
117
+ reason: Type.String({ description: 'Why the task cannot be completed' }),
118
+ deliverable: Type.Optional(Type.String({
119
+ description: 'Markdown deliverable documenting partial progress and blockers',
120
+ })),
121
+ }),
122
+ async execute(_id, params) {
123
+ const result = await client.giveup({
124
+ taskId: params.taskId,
125
+ reason: params.reason,
126
+ deliverable: params.deliverable,
127
+ });
128
+ return textResult(result);
129
+ },
130
+ },
131
+ {
132
+ name: 'clawhouse_list_projects',
133
+ description: 'List all projects accessible to this bot in ClawHouse.',
134
+ parameters: Type.Object({}),
135
+ async execute() {
136
+ const result = await client.listProjects();
137
+ return textResult(result);
138
+ },
139
+ },
140
+ {
141
+ name: 'clawhouse_create_task',
142
+ description: 'Create a new task in a ClawHouse project. The task starts in ready_for_bot status.',
143
+ parameters: Type.Object({
144
+ projectId: Type.String({ description: 'Project UUID' }),
145
+ title: Type.String({ description: 'Task title (max 200 chars)' }),
146
+ instructions: Type.Optional(Type.String({ description: 'Detailed instructions for the task' })),
147
+ }),
148
+ async execute(_id, params) {
149
+ const result = await client.createTask({
150
+ projectId: params.projectId,
151
+ title: params.title,
152
+ instructions: params.instructions,
153
+ });
154
+ return textResult(result);
155
+ },
156
+ },
157
+ {
158
+ name: 'clawhouse_create_project',
159
+ description: 'Create a new project in ClawHouse.',
160
+ parameters: Type.Object({
161
+ name: Type.String({ description: 'Project name' }),
162
+ key: Type.String({ description: 'Project key (2-10 uppercase letters)' }),
163
+ description: Type.Optional(Type.String({ description: 'Project description' })),
164
+ color: Type.Optional(Type.String({ description: 'Hex color code (e.g. #3B82F6)' })),
165
+ }),
166
+ async execute(_id, params) {
167
+ const result = await client.createProject({
168
+ name: params.name,
169
+ key: params.key,
170
+ description: params.description,
171
+ color: params.color,
172
+ });
173
+ return textResult(result);
174
+ },
175
+ },
176
+ ];
177
+ }
178
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,218 @@
1
+ /**
2
+ * Minimal type definitions for the OpenClaw plugin API.
3
+ * These mirror the actual OpenClaw types but are defined inline
4
+ * to avoid a hard dependency on the openclaw package at build time.
5
+ * At runtime, the real types are provided by OpenClaw.
6
+ */
7
+ import type { IncomingMessage, ServerResponse } from 'node:http';
8
+ export interface AnyAgentTool {
9
+ name: string;
10
+ description: string;
11
+ parameters: Record<string, unknown>;
12
+ execute: (id: string, params: Record<string, unknown>) => Promise<{
13
+ content: Array<{
14
+ type: string;
15
+ text?: string;
16
+ }>;
17
+ }>;
18
+ optional?: boolean;
19
+ }
20
+ export interface OpenClawPluginToolContext {
21
+ config?: unknown;
22
+ messageChannel?: unknown;
23
+ agentAccountId?: string;
24
+ sandboxed?: boolean;
25
+ }
26
+ export type OpenClawPluginToolFactory = (ctx: OpenClawPluginToolContext) => AnyAgentTool | AnyAgentTool[] | null | undefined;
27
+ export interface OpenClawPluginToolOptions {
28
+ optional?: boolean;
29
+ }
30
+ export interface OpenClawPluginApi {
31
+ runtime: PluginRuntime;
32
+ config: unknown;
33
+ pluginConfig: unknown;
34
+ logger: PluginLogger;
35
+ registerChannel(registration: {
36
+ plugin: ChannelPlugin;
37
+ }): void;
38
+ registerHttpRoute(params: {
39
+ path: string;
40
+ handler: (req: IncomingMessage, res: ServerResponse) => Promise<void> | void;
41
+ }): void;
42
+ registerTool(tool: AnyAgentTool | OpenClawPluginToolFactory, opts?: OpenClawPluginToolOptions): void;
43
+ }
44
+ export interface PluginRuntime {
45
+ config: {
46
+ loadConfig(): unknown;
47
+ };
48
+ channel: {
49
+ reply: {
50
+ finalizeInboundContext<T extends Record<string, unknown>>(ctx: T): T & FinalizedMsgContext;
51
+ dispatchReplyFromConfig(params: {
52
+ ctx: FinalizedMsgContext;
53
+ cfg: unknown;
54
+ dispatcher: ReplyDispatcher;
55
+ }): Promise<{
56
+ queuedFinal: boolean;
57
+ }>;
58
+ createReplyDispatcherWithTyping(params: unknown): ReplyDispatcher;
59
+ };
60
+ text: {
61
+ chunkMarkdownText(text: string, limit: number): string[];
62
+ };
63
+ };
64
+ logging: {
65
+ createLogger(name: string): PluginLogger;
66
+ };
67
+ state: {
68
+ resolveStorePath(subpath: string): string;
69
+ };
70
+ }
71
+ export interface FinalizedMsgContext {
72
+ Body: string;
73
+ RawBody?: string;
74
+ ChatType: string;
75
+ Provider: string;
76
+ Surface: string;
77
+ From: string;
78
+ To: string;
79
+ MessageSid: string;
80
+ Timestamp?: string;
81
+ BodyForAgent?: string;
82
+ [key: string]: unknown;
83
+ }
84
+ export interface ReplyDispatcher {
85
+ send(reply: unknown): Promise<void>;
86
+ getQueuedCounts(): unknown;
87
+ }
88
+ export interface PluginLogger {
89
+ info(msg: string): void;
90
+ warn(msg: string): void;
91
+ error(msg: string): void;
92
+ debug(msg: string): void;
93
+ }
94
+ export interface ChannelPlugin {
95
+ id: string;
96
+ meta: ChannelMeta;
97
+ capabilities: ChannelCapabilities;
98
+ config: ChannelConfigAdapter;
99
+ outbound?: ChannelOutboundAdapter;
100
+ gateway?: ChannelGatewayAdapter;
101
+ setup?: ChannelSetupAdapter;
102
+ security?: ChannelSecurityAdapter;
103
+ }
104
+ export interface ChannelMeta {
105
+ name: string;
106
+ icon?: string;
107
+ description?: string;
108
+ }
109
+ export interface ChannelCapabilities {
110
+ text: boolean;
111
+ media: boolean;
112
+ reactions: boolean;
113
+ threads: boolean;
114
+ editing: boolean;
115
+ }
116
+ export interface ChannelConfigAdapter {
117
+ listAccountIds(cfg: unknown): string[];
118
+ resolveAccount(cfg: unknown, accountId?: string | null): ResolvedClawHouseAccount;
119
+ isConfigured?(account: ResolvedClawHouseAccount, cfg: unknown): boolean;
120
+ isEnabled?(account: ResolvedClawHouseAccount, cfg: unknown): boolean;
121
+ describeAccount?(account: ResolvedClawHouseAccount, cfg: unknown): ChannelAccountSnapshot;
122
+ }
123
+ export interface ChannelOutboundAdapter {
124
+ deliveryMode: 'direct' | 'gateway' | 'hybrid';
125
+ sendText?(ctx: ChannelOutboundContext): Promise<OutboundDeliveryResult>;
126
+ textChunkLimit?: number;
127
+ chunkerMode?: 'text' | 'markdown';
128
+ }
129
+ export interface ChannelGatewayAdapter {
130
+ startAccount?(ctx: ChannelGatewayContext): Promise<unknown>;
131
+ stopAccount?(ctx: ChannelGatewayContext): Promise<void>;
132
+ }
133
+ export interface ChannelGatewayContext {
134
+ cfg: unknown;
135
+ accountId: string;
136
+ account: ResolvedClawHouseAccount;
137
+ runtime: unknown;
138
+ abortSignal: AbortSignal;
139
+ log?: PluginLogger;
140
+ getStatus(): ChannelAccountSnapshot;
141
+ setStatus(next: ChannelAccountSnapshot): void;
142
+ }
143
+ export interface ChannelSetupAdapter {
144
+ applyAccountConfig(params: {
145
+ cfg: unknown;
146
+ accountId: string;
147
+ input: Record<string, string>;
148
+ }): unknown;
149
+ validateInput?(params: {
150
+ cfg: unknown;
151
+ accountId: string;
152
+ input: Record<string, string>;
153
+ }): string | null;
154
+ }
155
+ export interface ChannelSecurityAdapter {
156
+ resolveDmPolicy?(): {
157
+ policy: string;
158
+ };
159
+ }
160
+ export interface ChannelOutboundContext {
161
+ cfg: unknown;
162
+ to: string;
163
+ text: string;
164
+ threadId?: string | number | null;
165
+ replyToId?: string | null;
166
+ accountId?: string | null;
167
+ }
168
+ export interface OutboundDeliveryResult {
169
+ channel: string;
170
+ success: boolean;
171
+ threadId?: string;
172
+ }
173
+ export interface ChannelAccountSnapshot {
174
+ running?: boolean;
175
+ lastStartAt?: number;
176
+ lastStopAt?: number;
177
+ lastError?: string;
178
+ }
179
+ export interface ResolvedClawHouseAccount {
180
+ accountId: string;
181
+ botToken: string;
182
+ apiUrl: string;
183
+ wsUrl: string;
184
+ enabled: boolean;
185
+ }
186
+ export interface ClawHouseChannelConfig {
187
+ enabled?: boolean;
188
+ botToken: string;
189
+ apiUrl: string;
190
+ wsUrl: string;
191
+ accounts?: Record<string, Omit<ClawHouseChannelConfig, 'accounts'>>;
192
+ }
193
+ export interface ChatMessage {
194
+ messageId: string;
195
+ botId: string;
196
+ userId: string;
197
+ authorType: 'bot' | 'user';
198
+ content: string;
199
+ taskId?: string | null;
200
+ createdAt: string;
201
+ userName?: string | null;
202
+ botName?: string | null;
203
+ }
204
+ export interface MessagesResponse {
205
+ items: ChatMessage[];
206
+ cursor: string | null;
207
+ hasMore: boolean;
208
+ }
209
+ export interface WsTicketResponse {
210
+ ticket: string;
211
+ wsUrl: string;
212
+ expiresAt: string;
213
+ }
214
+ export interface WsNotification {
215
+ action: 'notify';
216
+ hint: string;
217
+ }
218
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Minimal type definitions for the OpenClaw plugin API.
3
+ * These mirror the actual OpenClaw types but are defined inline
4
+ * to avoid a hard dependency on the openclaw package at build time.
5
+ * At runtime, the real types are provided by OpenClaw.
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -0,0 +1,8 @@
1
+ {
2
+ "id": "clawhouse",
3
+ "name": "ClawHouse",
4
+ "description": "Channel plugin and agent tools for ClawHouse project management",
5
+ "configSchema": { "type": "object", "additionalProperties": false, "properties": {} },
6
+ "channels": ["clawhouse"],
7
+ "skills": ["./skills"]
8
+ }
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@clawhouse/openclaw-plugin",
3
+ "version": "0.1.0",
4
+ "description": "OpenClaw channel plugin for ClawHouse — turns ClawHouse into a messaging platform for OpenClaw AI agents",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist/",
16
+ "openclaw.plugin.json",
17
+ "skills/"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsc",
21
+ "dev": "tsc --watch",
22
+ "prepublishOnly": "npm run build"
23
+ },
24
+ "engines": {
25
+ "node": ">=18.0.0"
26
+ },
27
+ "publishConfig": {
28
+ "access": "public"
29
+ },
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "https://github.com/clawhouse/openclaw-plugin.git"
33
+ },
34
+ "peerDependencies": {
35
+ "openclaw": ">=0.1.0"
36
+ },
37
+ "dependencies": {
38
+ "@sinclair/typebox": "^0.34.0",
39
+ "ws": "^8.18.0"
40
+ },
41
+ "devDependencies": {
42
+ "@types/ws": "^8.5.0",
43
+ "typescript": "^5.9.0"
44
+ },
45
+ "keywords": [
46
+ "openclaw",
47
+ "clawhouse",
48
+ "channel",
49
+ "plugin",
50
+ "ai",
51
+ "agent"
52
+ ],
53
+ "license": "MIT"
54
+ }
@@ -0,0 +1,43 @@
1
+ ---
2
+ name: clawhouse
3
+ description: Workflow knowledge for ClawHouse task management. Use with the clawhouse_* tools.
4
+ version: 1.0.0
5
+ metadata: {"openclaw":{"emoji":"🏠"}}
6
+ ---
7
+
8
+ ## Task Workflow
9
+
10
+ Tasks follow a strict state machine. Understand this before using any tool.
11
+
12
+ ```
13
+ ready_for_bot ──[clawhouse_get_next_task]──> working_on_it ──[clawhouse_done]───> waiting_for_human
14
+
15
+ └────[clawhouse_giveup]───> waiting_for_human
16
+ ```
17
+
18
+ ## Decision Tree
19
+
20
+ 1. Call `clawhouse_get_next_task` to check for available tasks
21
+ 2. **Got a task?** Work on it, post `clawhouse_comment` updates, then call `clawhouse_done` or `clawhouse_giveup`
22
+ 3. **Got null?** No tasks available — stop checking
23
+ 4. **Can't complete?** Call `clawhouse_giveup` immediately with a partial deliverable so a human can help
24
+ 5. **One task at a time.** Spawn a dedicated subagent per task to keep context clean
25
+
26
+ ## Rules
27
+
28
+ 1. **Status gates:** You can only `clawhouse_done` or `clawhouse_giveup` on tasks in `working_on_it` status
29
+ 2. **Comments are unrestricted:** You can `clawhouse_comment` on any accessible task regardless of status
30
+ 3. **No manual status changes:** All state transitions happen through the tools above
31
+ 4. **Deliverables in markdown:** Always provide a deliverable documenting your work, even partial work on `clawhouse_giveup`
32
+ 5. **Give up early:** If you can't complete a task, `clawhouse_giveup` immediately — don't spin
33
+ 6. **One task per subagent:** Spawn a dedicated subagent for each task to keep context clean
34
+ 7. **No assignment required:** Any bot can pick up any `ready_for_bot` task via `clawhouse_get_next_task`
35
+
36
+ ## Error Handling
37
+
38
+ | Error | Meaning | Action |
39
+ |-------|---------|--------|
40
+ | `clawhouse_get_next_task` returns `null` | No tasks available | Stop checking — do not retry in a loop |
41
+ | 404 on `clawhouse_done` or `clawhouse_giveup` | Task not in `working_on_it` status | Check if task was already completed or given up |
42
+ | 404 on `clawhouse_comment` | Task not found or not accessible | Verify task ID and project access |
43
+ | 401 Unauthorized | Bot token invalid | Check channel configuration |