@kernelius/openclaw-plugin 0.2.2 → 0.2.4
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 +31 -0
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -153,6 +153,36 @@ Example:
|
|
|
153
153
|
}
|
|
154
154
|
```
|
|
155
155
|
|
|
156
|
+
## Actions
|
|
157
|
+
|
|
158
|
+
### Send Message
|
|
159
|
+
Send a comment to an issue or PR:
|
|
160
|
+
```javascript
|
|
161
|
+
{
|
|
162
|
+
action: "send",
|
|
163
|
+
to: "repo:owner/name:issue:42",
|
|
164
|
+
message: "Your comment text"
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### React
|
|
169
|
+
Add an emoji reaction to issues, PRs, or comments:
|
|
170
|
+
```javascript
|
|
171
|
+
{
|
|
172
|
+
action: "react",
|
|
173
|
+
messageId: "issue_comment:abc123", // or issue:, pr:, pr_comment:
|
|
174
|
+
emoji: "+1" // Valid: +1, -1, laugh, hooray, confused, heart, rocket, eyes
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
**messageId formats:**
|
|
179
|
+
- `issue:<id>` - React to an issue
|
|
180
|
+
- `pr:<id>` - React to a pull request
|
|
181
|
+
- `issue_comment:<id>` - React to an issue comment
|
|
182
|
+
- `pr_comment:<id>` - React to a PR comment
|
|
183
|
+
|
|
184
|
+
Inbound webhook messages include `messageId` automatically, allowing agents to react to incoming comments.
|
|
185
|
+
|
|
156
186
|
## Webhook Events
|
|
157
187
|
|
|
158
188
|
The plugin handles these Forge webhook events:
|
|
@@ -168,6 +198,7 @@ The plugin handles these Forge webhook events:
|
|
|
168
198
|
| `pr.updated` | PR title/body changed |
|
|
169
199
|
| `pr.merged` | Pull request merged |
|
|
170
200
|
| `pr.closed` | PR closed without merging |
|
|
201
|
+
| `pr.reopened` | PR reopened |
|
|
171
202
|
| `pr.review_requested` | Review requested on PR |
|
|
172
203
|
| `pr.reviewed` | Review submitted |
|
|
173
204
|
| `pr.commented` | Comment on PR |
|
package/dist/index.js
CHANGED
|
@@ -36,7 +36,7 @@ function forgePayloadToInbound(payload, accountId) {
|
|
|
36
36
|
let conversationId;
|
|
37
37
|
let body;
|
|
38
38
|
let messageId;
|
|
39
|
-
let chatType = "
|
|
39
|
+
let chatType = "group";
|
|
40
40
|
if (issue) {
|
|
41
41
|
conversationId = `repo:${repository.fullName}:issue:${issue.number}`;
|
|
42
42
|
if (event === "issue.created") {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/channel.ts","../src/runtime.ts","../src/inbound.ts"],"sourcesContent":["import type { OpenClawPluginApi } from \"openclaw/plugin-sdk\";\nimport { emptyPluginConfigSchema } from \"openclaw/plugin-sdk\";\nimport { kerneliusPlugin } from \"./channel.js\";\nimport { setKerneliusRuntime } from \"./runtime.js\";\n\nconst plugin = {\n id: \"kernelius\",\n name: \"Kernelius Forge\",\n description: \"Connect to Kernelius Forge repositories, issues, and pull requests\",\n configSchema: emptyPluginConfigSchema(),\n register(api: OpenClawPluginApi) {\n setKerneliusRuntime(api.runtime);\n api.registerChannel({ plugin: kerneliusPlugin });\n },\n};\n\nexport default plugin;\n","import type {\n ChannelPlugin,\n ChannelConfigAdapter,\n} from \"openclaw/plugin-sdk\";\nimport {\n getChatChannelMeta,\n DEFAULT_ACCOUNT_ID,\n} from \"openclaw/plugin-sdk\";\nimport { getKerneliusRuntime } from \"./runtime.js\";\nimport type { KerneliusConfig, KerneliusResolvedAccount } from \"./types.js\";\nimport {\n handleWebhookRequest,\n resolveKerneliusWebhookPath,\n} from \"./inbound.js\";\n\nconst meta = getChatChannelMeta(\"kernelius\");\n\n// Resolve Kernelius account configuration\nfunction resolveKerneliusAccount(cfg: any, accountId?: string): KerneliusResolvedAccount {\n const effectiveAccountId = accountId || DEFAULT_ACCOUNT_ID;\n const channelConfig = cfg.channels?.kernelius || {};\n\n // Support both top-level config and accounts structure\n const accountConfig = channelConfig.accounts?.[effectiveAccountId] || channelConfig;\n\n return {\n accountId: effectiveAccountId,\n enabled: accountConfig.enabled !== false,\n apiUrl: accountConfig.apiUrl || \"https://forge-api.kernelius.com\",\n apiKey: accountConfig.apiKey,\n webhookSecret: accountConfig.webhookSecret,\n webhookPath: accountConfig.webhookPath,\n webhookUrl: accountConfig.webhookUrl,\n };\n}\n\nexport const kerneliusPlugin: ChannelPlugin = {\n id: \"kernelius\",\n meta: {\n ...meta,\n name: \"Kernelius Forge\",\n emoji: \"🔥\",\n description: \"Git platform for human-agent collaboration\",\n },\n capabilities: {\n chatTypes: [\"direct\", \"channel\", \"thread\"],\n reactions: true,\n threads: true,\n media: false,\n nativeCommands: false,\n },\n reload: { configPrefixes: [\"channels.kernelius\"] },\n config: {\n listAccountIds: (cfg) => {\n const channelConfig = cfg.channels?.kernelius;\n if (!channelConfig) return [];\n if (channelConfig.accounts) {\n return Object.keys(channelConfig.accounts);\n }\n return [DEFAULT_ACCOUNT_ID];\n },\n resolveAccount: (cfg, accountId) => resolveKerneliusAccount(cfg, accountId),\n defaultAccountId: () => DEFAULT_ACCOUNT_ID,\n setAccountEnabled: ({ cfg, accountId, enabled }) => {\n const effectiveAccountId = accountId || DEFAULT_ACCOUNT_ID;\n if (!cfg.channels) cfg.channels = {};\n if (!cfg.channels.kernelius) cfg.channels.kernelius = {};\n\n if (cfg.channels.kernelius.accounts?.[effectiveAccountId]) {\n cfg.channels.kernelius.accounts[effectiveAccountId].enabled = enabled;\n } else {\n cfg.channels.kernelius.enabled = enabled;\n }\n return cfg;\n },\n deleteAccount: ({ cfg, accountId }) => {\n if (accountId && accountId !== DEFAULT_ACCOUNT_ID) {\n delete cfg.channels?.kernelius?.accounts?.[accountId];\n }\n return cfg;\n },\n isConfigured: (account: any) => Boolean(account.apiKey),\n describeAccount: (account: any) => ({\n accountId: account.accountId,\n enabled: account.enabled,\n configured: Boolean(account.apiKey),\n apiUrl: account.apiUrl,\n }),\n resolveAllowFrom: () => [],\n formatAllowFrom: ({ allowFrom }) => allowFrom,\n },\n messaging: {\n // Send message to Forge (comment on issue/PR)\n send: async (ctx, action) => {\n const runtime = getKerneliusRuntime();\n const account = resolveKerneliusAccount(runtime.config.loadConfig(), action.accountId);\n\n if (!account.apiKey) {\n throw new Error(\"Kernelius API key not configured\");\n }\n\n // Parse target: repo:owner/name:issue:42 or repo:owner/name:pr:10\n const target = action.to;\n const match = target.match(/^repo:([^/]+)\\/([^:]+):(issue|pr):(\\d+)$/);\n\n if (!match) {\n throw new Error(`Invalid Kernelius target format: ${target}. Expected: repo:owner/name:issue:42 or repo:owner/name:pr:10`);\n }\n\n const [, owner, repo, type, number] = match;\n const endpoint = type === \"issue\"\n ? `/api/repositories/${owner}/${repo}/issues/${number}/comments`\n : `/api/repositories/${owner}/${repo}/pulls/${number}/comments`;\n\n const response = await fetch(`${account.apiUrl}${endpoint}`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"Authorization\": `Bearer ${account.apiKey}`,\n },\n body: JSON.stringify({\n body: action.body,\n }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Failed to send message to Kernelius: ${response.status} ${error}`);\n }\n\n const result = await response.json();\n\n return {\n messageId: result.id,\n timestamp: new Date(result.createdAt),\n };\n },\n\n // React to a comment with an emoji\n // Valid emojis: +1, -1, laugh, hooray, confused, heart, rocket, eyes\n react: async (ctx, action) => {\n const runtime = getKerneliusRuntime();\n const account = resolveKerneliusAccount(runtime.config.loadConfig(), action.accountId);\n\n if (!account.apiKey) {\n throw new Error(\"Kernelius API key not configured\");\n }\n\n const { messageId, emoji } = action;\n if (!messageId || !emoji) {\n throw new Error(\"messageId and emoji are required for reactions\");\n }\n\n // Determine the reaction endpoint based on message type\n // messageId format: \"issue_comment:<id>\" or \"pr_comment:<id>\" or \"issue:<id>\" or \"pr:<id>\"\n let endpoint: string;\n if (messageId.startsWith(\"issue_comment:\")) {\n endpoint = `/api/issues/comments/${messageId.replace(\"issue_comment:\", \"\")}/reactions`;\n } else if (messageId.startsWith(\"pr_comment:\")) {\n endpoint = `/api/pulls/comments/${messageId.replace(\"pr_comment:\", \"\")}/reactions`;\n } else if (messageId.startsWith(\"issue:\")) {\n endpoint = `/api/issues/${messageId.replace(\"issue:\", \"\")}/reactions`;\n } else if (messageId.startsWith(\"pr:\")) {\n endpoint = `/api/pulls/${messageId.replace(\"pr:\", \"\")}/reactions`;\n } else {\n throw new Error(`Invalid messageId format: ${messageId}. Expected: issue_comment:<id>, pr_comment:<id>, issue:<id>, or pr:<id>`);\n }\n\n const response = await fetch(`${account.apiUrl}${endpoint}`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"Authorization\": `Bearer ${account.apiKey}`,\n },\n body: JSON.stringify({ emoji }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Failed to add reaction: ${response.status} ${error}`);\n }\n\n const result = await response.json() as { added: boolean };\n return { added: result.added };\n },\n },\n actions: {\n listActions: () => [\"send\", \"react\"],\n extractToolSend: ({ args }) => {\n const action = typeof args.action === \"string\" ? args.action.trim() : \"\";\n if (action !== \"sendMessage\") {\n return null;\n }\n const to = typeof args.to === \"string\" ? args.to : undefined;\n if (!to) {\n return null;\n }\n const accountId = typeof args.accountId === \"string\" ? args.accountId.trim() : undefined;\n return { to, accountId };\n },\n handleAction: async ({ action, params, cfg, accountId }) => {\n const account = resolveKerneliusAccount(cfg, accountId);\n\n if (!account.apiKey) {\n throw new Error(\"Kernelius API key not configured\");\n }\n\n if (action === \"react\") {\n const messageId = typeof params.messageId === \"string\" ? params.messageId : undefined;\n const emoji = typeof params.emoji === \"string\" ? params.emoji : undefined;\n\n if (!messageId || !emoji) {\n throw new Error(\"Missing required parameters for react: messageId, emoji\");\n }\n\n // Determine the reaction endpoint based on message type\n let endpoint: string;\n if (messageId.startsWith(\"issue_comment:\")) {\n endpoint = `/api/issues/comments/${messageId.replace(\"issue_comment:\", \"\")}/reactions`;\n } else if (messageId.startsWith(\"pr_comment:\")) {\n endpoint = `/api/pulls/comments/${messageId.replace(\"pr_comment:\", \"\")}/reactions`;\n } else if (messageId.startsWith(\"issue:\")) {\n endpoint = `/api/issues/${messageId.replace(\"issue:\", \"\")}/reactions`;\n } else if (messageId.startsWith(\"pr:\")) {\n endpoint = `/api/pulls/${messageId.replace(\"pr:\", \"\")}/reactions`;\n } else {\n throw new Error(`Invalid messageId format: ${messageId}`);\n }\n\n const response = await fetch(`${account.apiUrl}${endpoint}`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"Authorization\": `Bearer ${account.apiKey}`,\n },\n body: JSON.stringify({ emoji }),\n });\n\n if (!response.ok) {\n throw new Error(`Failed to add reaction: ${response.status}`);\n }\n\n return { success: true };\n }\n\n if (action !== \"send\") {\n throw new Error(`Unknown action: ${action}`);\n }\n\n const to = typeof params.to === \"string\" ? params.to : undefined;\n const message = typeof params.message === \"string\" ? params.message : undefined;\n\n if (!to || !message) {\n throw new Error(\"Missing required parameters: to, message\");\n }\n\n // Parse target and send\n const match = to.match(/^repo:([^/]+)\\/([^:]+):(issue|pr):(\\d+)$/);\n if (!match) {\n throw new Error(`Invalid target format: ${to}`);\n }\n\n const [, owner, repo, type, number] = match;\n const endpoint = type === \"issue\"\n ? `/api/repositories/${owner}/${repo}/issues/${number}/comments`\n : `/api/repositories/${owner}/${repo}/pulls/${number}/comments`;\n\n const response = await fetch(`${account.apiUrl}${endpoint}`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"Authorization\": `Bearer ${account.apiKey}`,\n },\n body: JSON.stringify({ body: message }),\n });\n\n if (!response.ok) {\n throw new Error(`Failed to send: ${response.status}`);\n }\n\n return { success: true };\n },\n },\n gateway: {\n start: async (ctx) => {\n const runtime = getKerneliusRuntime();\n const config = runtime.config.loadConfig();\n const account = resolveKerneliusAccount(config, ctx.accountId);\n\n // Only start gateway if webhook path/url is configured\n if (!account.webhookPath && !account.webhookUrl) {\n console.log(\"[kernelius] No webhook path configured, skipping gateway start\");\n return;\n }\n\n const webhookPath = resolveKerneliusWebhookPath(\n account.webhookPath,\n account.webhookUrl\n );\n\n console.log(`[kernelius] Starting gateway for account ${account.accountId} at ${webhookPath}`);\n\n // Register HTTP handler for webhooks\n ctx.registerHttpHandler({\n path: webhookPath,\n method: \"POST\",\n handler: async (req, res) => {\n try {\n const inbound = await handleWebhookRequest(req, res, {\n account,\n runtime,\n statusSink: ctx.statusSink,\n });\n\n if (inbound) {\n // Queue message for agent processing\n await ctx.queueInbound(inbound);\n }\n } catch (error) {\n console.error(\"[kernelius] Webhook handler error:\", error);\n if (!res.headersSent) {\n res.writeHead(500, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Internal server error\" }));\n }\n }\n },\n });\n\n console.log(`[kernelius] Gateway started successfully at ${webhookPath}`);\n },\n stop: async (ctx) => {\n console.log(`[kernelius] Stopping gateway for account ${ctx.accountId}`);\n // Cleanup is handled by OpenClaw when unregistering handlers\n },\n },\n};\n","import type { OpenClawRuntime } from \"openclaw/plugin-sdk\";\n\nlet runtime: OpenClawRuntime | null = null;\n\nexport function setKerneliusRuntime(rt: OpenClawRuntime): void {\n runtime = rt;\n}\n\nexport function getKerneliusRuntime(): OpenClawRuntime {\n if (!runtime) {\n throw new Error(\"Kernelius runtime not initialized\");\n }\n return runtime;\n}\n","import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport type { WebInboundMessage } from \"openclaw/plugin-sdk\";\nimport type { ForgeWebhookPayload, KerneliusResolvedAccount } from \"./types.js\";\nimport crypto from \"node:crypto\";\n\nexport interface InboundHandlerContext {\n account: KerneliusResolvedAccount;\n runtime: any;\n statusSink?: (patch: { lastInboundAt?: number }) => void;\n}\n\n/**\n * Verify webhook signature\n */\nexport function verifyWebhookSignature(\n payload: string,\n signature: string,\n secret: string\n): boolean {\n if (!secret) {\n return true; // No secret configured, skip verification\n }\n\n const expectedSignature = `sha256=${crypto\n .createHmac(\"sha256\", secret)\n .update(payload)\n .digest(\"hex\")}`;\n\n return crypto.timingSafeEqual(\n Buffer.from(signature),\n Buffer.from(expectedSignature)\n );\n}\n\n/**\n * Convert Forge webhook payload to WebInboundMessage\n */\nexport function forgePayloadToInbound(\n payload: ForgeWebhookPayload,\n accountId: string\n): WebInboundMessage | null {\n const { event, repository, sender, issue, pullRequest, comment } = payload;\n\n // Determine conversation ID and messageId based on event type\n let conversationId: string;\n let body: string;\n let messageId: string | undefined;\n let chatType: \"direct\" | \"group\" = \"channel\";\n\n if (issue) {\n conversationId = `repo:${repository.fullName}:issue:${issue.number}`;\n\n if (event === \"issue.created\") {\n body = `**New Issue #${issue.number}**: ${issue.title}\\n\\n${issue.body || \"\"}`;\n messageId = `issue:${issue.id}`;\n } else if (event === \"issue.commented\" && comment) {\n body = `**Comment on Issue #${issue.number}** by @${sender.username}:\\n\\n${comment.body}`;\n messageId = `issue_comment:${comment.id}`;\n } else if (event === \"issue.closed\") {\n body = `**Issue #${issue.number} closed** by @${sender.username}`;\n messageId = `issue:${issue.id}`;\n } else if (event === \"issue.reopened\") {\n body = `**Issue #${issue.number} reopened** by @${sender.username}`;\n messageId = `issue:${issue.id}`;\n } else if (event === \"issue.updated\") {\n body = `**Issue #${issue.number} updated** by @${sender.username}: ${issue.title}`;\n messageId = `issue:${issue.id}`;\n } else {\n body = `Issue #${issue.number} event: ${event}`;\n messageId = `issue:${issue.id}`;\n }\n } else if (pullRequest) {\n conversationId = `repo:${repository.fullName}:pr:${pullRequest.number}`;\n\n if (event === \"pr.created\") {\n body = `**New Pull Request #${pullRequest.number}**: ${pullRequest.title}\\n\\n${pullRequest.body || \"\"}`;\n messageId = `pr:${pullRequest.id}`;\n } else if (event === \"pr.review_requested\") {\n body = `**Review Requested on PR #${pullRequest.number}**: ${pullRequest.title}\\n\\nPlease review this pull request.`;\n messageId = `pr:${pullRequest.id}`;\n } else if (event === \"pr.reviewed\") {\n body = `**PR #${pullRequest.number} reviewed** by @${sender.username}`;\n messageId = `pr:${pullRequest.id}`;\n } else if (event === \"pr.merged\") {\n body = `**PR #${pullRequest.number} merged** by @${sender.username}`;\n messageId = `pr:${pullRequest.id}`;\n } else if (event === \"pr.commented\" && comment) {\n body = `**Comment on PR #${pullRequest.number}** by @${sender.username}:\\n\\n${comment.body}`;\n messageId = `pr_comment:${comment.id}`;\n } else if (event === \"pr.closed\") {\n body = `**PR #${pullRequest.number} closed** by @${sender.username}`;\n messageId = `pr:${pullRequest.id}`;\n } else if (event === \"pr.reopened\") {\n body = `**PR #${pullRequest.number} reopened** by @${sender.username}`;\n messageId = `pr:${pullRequest.id}`;\n } else {\n body = `Pull Request #${pullRequest.number} event: ${event}`;\n messageId = `pr:${pullRequest.id}`;\n }\n } else {\n // Repository-level event\n conversationId = `repo:${repository.fullName}`;\n body = `Repository event: ${event}`;\n }\n\n const timestamp = new Date(payload.timestamp).getTime();\n\n return {\n id: crypto.randomUUID(),\n from: conversationId,\n conversationId,\n to: accountId,\n accountId,\n body,\n pushName: sender.username,\n timestamp,\n chatType,\n chatId: conversationId,\n senderName: sender.username,\n selfJid: accountId,\n selfE164: null,\n messageId, // For reactions support\n // Helpers (simplified for webhook-based channel)\n sendComposing: async () => {},\n reply: async (text: string) => {\n // Would send back to Forge, but we handle that via messaging adapter\n console.log(`[kernelius] Reply queued: ${text}`);\n },\n sendMedia: async () => {\n throw new Error(\"Media not supported for Forge webhooks\");\n },\n };\n}\n\n/**\n * Handle incoming webhook request\n */\nexport async function handleWebhookRequest(\n req: IncomingMessage,\n res: ServerResponse,\n ctx: InboundHandlerContext\n): Promise<WebInboundMessage | null> {\n // Read request body\n const chunks: Buffer[] = [];\n for await (const chunk of req) {\n chunks.push(chunk as Buffer);\n }\n const rawBody = Buffer.concat(chunks).toString(\"utf-8\");\n\n // Verify signature if secret is configured\n const signature = req.headers[\"x-forge-signature\"] as string;\n if (ctx.account.webhookSecret) {\n if (!signature) {\n res.writeHead(401, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Missing X-Forge-Signature header\" }));\n return null;\n }\n\n if (!verifyWebhookSignature(rawBody, signature, ctx.account.webhookSecret)) {\n res.writeHead(401, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Invalid signature\" }));\n return null;\n }\n }\n\n // Parse payload\n let payload: ForgeWebhookPayload;\n try {\n payload = JSON.parse(rawBody);\n } catch (error) {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Invalid JSON payload\" }));\n return null;\n }\n\n // Verify source is from Forge\n if (payload.source !== \"forge\") {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Invalid source\" }));\n return null;\n }\n\n // Update status\n ctx.statusSink?.({ lastInboundAt: Date.now() });\n\n // Convert to WebInboundMessage\n const inbound = forgePayloadToInbound(payload, ctx.account.accountId);\n\n if (!inbound) {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Could not process event\" }));\n return null;\n }\n\n // Respond success\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ success: true, event: payload.event }));\n\n return inbound;\n}\n\n/**\n * Resolve webhook path from config\n */\nexport function resolveKerneliusWebhookPath(\n webhookPath?: string,\n webhookUrl?: string\n): string {\n if (webhookPath?.trim()) {\n const path = webhookPath.trim();\n return path.startsWith(\"/\") ? path : `/${path}`;\n }\n\n if (webhookUrl?.trim()) {\n try {\n const parsed = new URL(webhookUrl);\n return parsed.pathname || \"/kernelius\";\n } catch {\n return \"/kernelius\";\n }\n }\n\n return \"/kernelius\";\n}\n"],"mappings":"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","names":["runtime","endpoint","response"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/channel.ts","../src/runtime.ts","../src/inbound.ts"],"sourcesContent":["import type { OpenClawPluginApi } from \"openclaw/plugin-sdk\";\nimport { emptyPluginConfigSchema } from \"openclaw/plugin-sdk\";\nimport { kerneliusPlugin } from \"./channel.js\";\nimport { setKerneliusRuntime } from \"./runtime.js\";\n\nconst plugin = {\n id: \"kernelius\",\n name: \"Kernelius Forge\",\n description: \"Connect to Kernelius Forge repositories, issues, and pull requests\",\n configSchema: emptyPluginConfigSchema(),\n register(api: OpenClawPluginApi) {\n setKerneliusRuntime(api.runtime);\n api.registerChannel({ plugin: kerneliusPlugin });\n },\n};\n\nexport default plugin;\n","import type {\n ChannelPlugin,\n ChannelConfigAdapter,\n} from \"openclaw/plugin-sdk\";\nimport {\n getChatChannelMeta,\n DEFAULT_ACCOUNT_ID,\n} from \"openclaw/plugin-sdk\";\nimport { getKerneliusRuntime } from \"./runtime.js\";\nimport type { KerneliusConfig, KerneliusResolvedAccount } from \"./types.js\";\nimport {\n handleWebhookRequest,\n resolveKerneliusWebhookPath,\n} from \"./inbound.js\";\n\nconst meta = getChatChannelMeta(\"kernelius\");\n\n// Resolve Kernelius account configuration\nfunction resolveKerneliusAccount(cfg: any, accountId?: string): KerneliusResolvedAccount {\n const effectiveAccountId = accountId || DEFAULT_ACCOUNT_ID;\n const channelConfig = cfg.channels?.kernelius || {};\n\n // Support both top-level config and accounts structure\n const accountConfig = channelConfig.accounts?.[effectiveAccountId] || channelConfig;\n\n return {\n accountId: effectiveAccountId,\n enabled: accountConfig.enabled !== false,\n apiUrl: accountConfig.apiUrl || \"https://forge-api.kernelius.com\",\n apiKey: accountConfig.apiKey,\n webhookSecret: accountConfig.webhookSecret,\n webhookPath: accountConfig.webhookPath,\n webhookUrl: accountConfig.webhookUrl,\n };\n}\n\nexport const kerneliusPlugin: ChannelPlugin = {\n id: \"kernelius\",\n meta: {\n ...meta,\n name: \"Kernelius Forge\",\n emoji: \"🔥\",\n description: \"Git platform for human-agent collaboration\",\n },\n capabilities: {\n chatTypes: [\"direct\", \"channel\", \"thread\"],\n reactions: true,\n threads: true,\n media: false,\n nativeCommands: false,\n },\n reload: { configPrefixes: [\"channels.kernelius\"] },\n config: {\n listAccountIds: (cfg) => {\n const channelConfig = cfg.channels?.kernelius;\n if (!channelConfig) return [];\n if (channelConfig.accounts) {\n return Object.keys(channelConfig.accounts);\n }\n return [DEFAULT_ACCOUNT_ID];\n },\n resolveAccount: (cfg, accountId) => resolveKerneliusAccount(cfg, accountId),\n defaultAccountId: () => DEFAULT_ACCOUNT_ID,\n setAccountEnabled: ({ cfg, accountId, enabled }) => {\n const effectiveAccountId = accountId || DEFAULT_ACCOUNT_ID;\n if (!cfg.channels) cfg.channels = {};\n if (!cfg.channels.kernelius) cfg.channels.kernelius = {};\n\n if (cfg.channels.kernelius.accounts?.[effectiveAccountId]) {\n cfg.channels.kernelius.accounts[effectiveAccountId].enabled = enabled;\n } else {\n cfg.channels.kernelius.enabled = enabled;\n }\n return cfg;\n },\n deleteAccount: ({ cfg, accountId }) => {\n if (accountId && accountId !== DEFAULT_ACCOUNT_ID) {\n delete cfg.channels?.kernelius?.accounts?.[accountId];\n }\n return cfg;\n },\n isConfigured: (account: any) => Boolean(account.apiKey),\n describeAccount: (account: any) => ({\n accountId: account.accountId,\n enabled: account.enabled,\n configured: Boolean(account.apiKey),\n apiUrl: account.apiUrl,\n }),\n resolveAllowFrom: () => [],\n formatAllowFrom: ({ allowFrom }) => allowFrom,\n },\n messaging: {\n // Send message to Forge (comment on issue/PR)\n send: async (ctx, action) => {\n const runtime = getKerneliusRuntime();\n const account = resolveKerneliusAccount(runtime.config.loadConfig(), action.accountId);\n\n if (!account.apiKey) {\n throw new Error(\"Kernelius API key not configured\");\n }\n\n // Parse target: repo:owner/name:issue:42 or repo:owner/name:pr:10\n const target = action.to;\n const match = target.match(/^repo:([^/]+)\\/([^:]+):(issue|pr):(\\d+)$/);\n\n if (!match) {\n throw new Error(`Invalid Kernelius target format: ${target}. Expected: repo:owner/name:issue:42 or repo:owner/name:pr:10`);\n }\n\n const [, owner, repo, type, number] = match;\n const endpoint = type === \"issue\"\n ? `/api/repositories/${owner}/${repo}/issues/${number}/comments`\n : `/api/repositories/${owner}/${repo}/pulls/${number}/comments`;\n\n const response = await fetch(`${account.apiUrl}${endpoint}`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"Authorization\": `Bearer ${account.apiKey}`,\n },\n body: JSON.stringify({\n body: action.body,\n }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Failed to send message to Kernelius: ${response.status} ${error}`);\n }\n\n const result = await response.json() as { id: string; createdAt: string };\n\n return {\n messageId: result.id,\n timestamp: new Date(result.createdAt),\n };\n },\n\n // React to a comment with an emoji\n // Valid emojis: +1, -1, laugh, hooray, confused, heart, rocket, eyes\n react: async (ctx, action) => {\n const runtime = getKerneliusRuntime();\n const account = resolveKerneliusAccount(runtime.config.loadConfig(), action.accountId);\n\n if (!account.apiKey) {\n throw new Error(\"Kernelius API key not configured\");\n }\n\n const { messageId, emoji } = action;\n if (!messageId || !emoji) {\n throw new Error(\"messageId and emoji are required for reactions\");\n }\n\n // Determine the reaction endpoint based on message type\n // messageId format: \"issue_comment:<id>\" or \"pr_comment:<id>\" or \"issue:<id>\" or \"pr:<id>\"\n let endpoint: string;\n if (messageId.startsWith(\"issue_comment:\")) {\n endpoint = `/api/issues/comments/${messageId.replace(\"issue_comment:\", \"\")}/reactions`;\n } else if (messageId.startsWith(\"pr_comment:\")) {\n endpoint = `/api/pulls/comments/${messageId.replace(\"pr_comment:\", \"\")}/reactions`;\n } else if (messageId.startsWith(\"issue:\")) {\n endpoint = `/api/issues/${messageId.replace(\"issue:\", \"\")}/reactions`;\n } else if (messageId.startsWith(\"pr:\")) {\n endpoint = `/api/pulls/${messageId.replace(\"pr:\", \"\")}/reactions`;\n } else {\n throw new Error(`Invalid messageId format: ${messageId}. Expected: issue_comment:<id>, pr_comment:<id>, issue:<id>, or pr:<id>`);\n }\n\n const response = await fetch(`${account.apiUrl}${endpoint}`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"Authorization\": `Bearer ${account.apiKey}`,\n },\n body: JSON.stringify({ emoji }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Failed to add reaction: ${response.status} ${error}`);\n }\n\n const result = await response.json() as { added: boolean };\n return { added: result.added };\n },\n },\n actions: {\n listActions: () => [\"send\", \"react\"],\n extractToolSend: ({ args }) => {\n const action = typeof args.action === \"string\" ? args.action.trim() : \"\";\n if (action !== \"sendMessage\") {\n return null;\n }\n const to = typeof args.to === \"string\" ? args.to : undefined;\n if (!to) {\n return null;\n }\n const accountId = typeof args.accountId === \"string\" ? args.accountId.trim() : undefined;\n return { to, accountId };\n },\n handleAction: async ({ action, params, cfg, accountId }) => {\n const account = resolveKerneliusAccount(cfg, accountId);\n\n if (!account.apiKey) {\n throw new Error(\"Kernelius API key not configured\");\n }\n\n if (action === \"react\") {\n const messageId = typeof params.messageId === \"string\" ? params.messageId : undefined;\n const emoji = typeof params.emoji === \"string\" ? params.emoji : undefined;\n\n if (!messageId || !emoji) {\n throw new Error(\"Missing required parameters for react: messageId, emoji\");\n }\n\n // Determine the reaction endpoint based on message type\n let endpoint: string;\n if (messageId.startsWith(\"issue_comment:\")) {\n endpoint = `/api/issues/comments/${messageId.replace(\"issue_comment:\", \"\")}/reactions`;\n } else if (messageId.startsWith(\"pr_comment:\")) {\n endpoint = `/api/pulls/comments/${messageId.replace(\"pr_comment:\", \"\")}/reactions`;\n } else if (messageId.startsWith(\"issue:\")) {\n endpoint = `/api/issues/${messageId.replace(\"issue:\", \"\")}/reactions`;\n } else if (messageId.startsWith(\"pr:\")) {\n endpoint = `/api/pulls/${messageId.replace(\"pr:\", \"\")}/reactions`;\n } else {\n throw new Error(`Invalid messageId format: ${messageId}`);\n }\n\n const response = await fetch(`${account.apiUrl}${endpoint}`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"Authorization\": `Bearer ${account.apiKey}`,\n },\n body: JSON.stringify({ emoji }),\n });\n\n if (!response.ok) {\n throw new Error(`Failed to add reaction: ${response.status}`);\n }\n\n return { success: true };\n }\n\n if (action !== \"send\") {\n throw new Error(`Unknown action: ${action}`);\n }\n\n const to = typeof params.to === \"string\" ? params.to : undefined;\n const message = typeof params.message === \"string\" ? params.message : undefined;\n\n if (!to || !message) {\n throw new Error(\"Missing required parameters: to, message\");\n }\n\n // Parse target and send\n const match = to.match(/^repo:([^/]+)\\/([^:]+):(issue|pr):(\\d+)$/);\n if (!match) {\n throw new Error(`Invalid target format: ${to}`);\n }\n\n const [, owner, repo, type, number] = match;\n const endpoint = type === \"issue\"\n ? `/api/repositories/${owner}/${repo}/issues/${number}/comments`\n : `/api/repositories/${owner}/${repo}/pulls/${number}/comments`;\n\n const response = await fetch(`${account.apiUrl}${endpoint}`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"Authorization\": `Bearer ${account.apiKey}`,\n },\n body: JSON.stringify({ body: message }),\n });\n\n if (!response.ok) {\n throw new Error(`Failed to send: ${response.status}`);\n }\n\n return { success: true };\n },\n },\n gateway: {\n start: async (ctx) => {\n const runtime = getKerneliusRuntime();\n const config = runtime.config.loadConfig();\n const account = resolveKerneliusAccount(config, ctx.accountId);\n\n // Only start gateway if webhook path/url is configured\n if (!account.webhookPath && !account.webhookUrl) {\n console.log(\"[kernelius] No webhook path configured, skipping gateway start\");\n return;\n }\n\n const webhookPath = resolveKerneliusWebhookPath(\n account.webhookPath,\n account.webhookUrl\n );\n\n console.log(`[kernelius] Starting gateway for account ${account.accountId} at ${webhookPath}`);\n\n // Register HTTP handler for webhooks\n ctx.registerHttpHandler({\n path: webhookPath,\n method: \"POST\",\n handler: async (req, res) => {\n try {\n const inbound = await handleWebhookRequest(req, res, {\n account,\n runtime,\n statusSink: ctx.statusSink,\n });\n\n if (inbound) {\n // Queue message for agent processing\n await ctx.queueInbound(inbound);\n }\n } catch (error) {\n console.error(\"[kernelius] Webhook handler error:\", error);\n if (!res.headersSent) {\n res.writeHead(500, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Internal server error\" }));\n }\n }\n },\n });\n\n console.log(`[kernelius] Gateway started successfully at ${webhookPath}`);\n },\n stop: async (ctx) => {\n console.log(`[kernelius] Stopping gateway for account ${ctx.accountId}`);\n // Cleanup is handled by OpenClaw when unregistering handlers\n },\n },\n};\n","import type { OpenClawRuntime } from \"openclaw/plugin-sdk\";\n\nlet runtime: OpenClawRuntime | null = null;\n\nexport function setKerneliusRuntime(rt: OpenClawRuntime): void {\n runtime = rt;\n}\n\nexport function getKerneliusRuntime(): OpenClawRuntime {\n if (!runtime) {\n throw new Error(\"Kernelius runtime not initialized\");\n }\n return runtime;\n}\n","import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport type { WebInboundMessage } from \"openclaw/plugin-sdk\";\nimport type { ForgeWebhookPayload, KerneliusResolvedAccount } from \"./types.js\";\nimport crypto from \"node:crypto\";\n\nexport interface InboundHandlerContext {\n account: KerneliusResolvedAccount;\n runtime: any;\n statusSink?: (patch: { lastInboundAt?: number }) => void;\n}\n\n/**\n * Verify webhook signature\n */\nexport function verifyWebhookSignature(\n payload: string,\n signature: string,\n secret: string\n): boolean {\n if (!secret) {\n return true; // No secret configured, skip verification\n }\n\n const expectedSignature = `sha256=${crypto\n .createHmac(\"sha256\", secret)\n .update(payload)\n .digest(\"hex\")}`;\n\n return crypto.timingSafeEqual(\n Buffer.from(signature),\n Buffer.from(expectedSignature)\n );\n}\n\n/**\n * Convert Forge webhook payload to WebInboundMessage\n */\nexport function forgePayloadToInbound(\n payload: ForgeWebhookPayload,\n accountId: string\n): WebInboundMessage | null {\n const { event, repository, sender, issue, pullRequest, comment } = payload;\n\n // Determine conversation ID and messageId based on event type\n let conversationId: string;\n let body: string;\n let messageId: string | undefined;\n let chatType: \"direct\" | \"group\" = \"group\"; // Issues/PRs are group conversations\n\n if (issue) {\n conversationId = `repo:${repository.fullName}:issue:${issue.number}`;\n\n if (event === \"issue.created\") {\n body = `**New Issue #${issue.number}**: ${issue.title}\\n\\n${issue.body || \"\"}`;\n messageId = `issue:${issue.id}`;\n } else if (event === \"issue.commented\" && comment) {\n body = `**Comment on Issue #${issue.number}** by @${sender.username}:\\n\\n${comment.body}`;\n messageId = `issue_comment:${comment.id}`;\n } else if (event === \"issue.closed\") {\n body = `**Issue #${issue.number} closed** by @${sender.username}`;\n messageId = `issue:${issue.id}`;\n } else if (event === \"issue.reopened\") {\n body = `**Issue #${issue.number} reopened** by @${sender.username}`;\n messageId = `issue:${issue.id}`;\n } else if (event === \"issue.updated\") {\n body = `**Issue #${issue.number} updated** by @${sender.username}: ${issue.title}`;\n messageId = `issue:${issue.id}`;\n } else {\n body = `Issue #${issue.number} event: ${event}`;\n messageId = `issue:${issue.id}`;\n }\n } else if (pullRequest) {\n conversationId = `repo:${repository.fullName}:pr:${pullRequest.number}`;\n\n if (event === \"pr.created\") {\n body = `**New Pull Request #${pullRequest.number}**: ${pullRequest.title}\\n\\n${pullRequest.body || \"\"}`;\n messageId = `pr:${pullRequest.id}`;\n } else if (event === \"pr.review_requested\") {\n body = `**Review Requested on PR #${pullRequest.number}**: ${pullRequest.title}\\n\\nPlease review this pull request.`;\n messageId = `pr:${pullRequest.id}`;\n } else if (event === \"pr.reviewed\") {\n body = `**PR #${pullRequest.number} reviewed** by @${sender.username}`;\n messageId = `pr:${pullRequest.id}`;\n } else if (event === \"pr.merged\") {\n body = `**PR #${pullRequest.number} merged** by @${sender.username}`;\n messageId = `pr:${pullRequest.id}`;\n } else if (event === \"pr.commented\" && comment) {\n body = `**Comment on PR #${pullRequest.number}** by @${sender.username}:\\n\\n${comment.body}`;\n messageId = `pr_comment:${comment.id}`;\n } else if (event === \"pr.closed\") {\n body = `**PR #${pullRequest.number} closed** by @${sender.username}`;\n messageId = `pr:${pullRequest.id}`;\n } else if (event === \"pr.reopened\") {\n body = `**PR #${pullRequest.number} reopened** by @${sender.username}`;\n messageId = `pr:${pullRequest.id}`;\n } else {\n body = `Pull Request #${pullRequest.number} event: ${event}`;\n messageId = `pr:${pullRequest.id}`;\n }\n } else {\n // Repository-level event\n conversationId = `repo:${repository.fullName}`;\n body = `Repository event: ${event}`;\n }\n\n const timestamp = new Date(payload.timestamp).getTime();\n\n return {\n id: crypto.randomUUID(),\n from: conversationId,\n conversationId,\n to: accountId,\n accountId,\n body,\n pushName: sender.username,\n timestamp,\n chatType,\n chatId: conversationId,\n senderName: sender.username,\n selfJid: accountId,\n selfE164: null,\n messageId, // For reactions support\n // Helpers (simplified for webhook-based channel)\n sendComposing: async () => {},\n reply: async (text: string) => {\n // Would send back to Forge, but we handle that via messaging adapter\n console.log(`[kernelius] Reply queued: ${text}`);\n },\n sendMedia: async () => {\n throw new Error(\"Media not supported for Forge webhooks\");\n },\n };\n}\n\n/**\n * Handle incoming webhook request\n */\nexport async function handleWebhookRequest(\n req: IncomingMessage,\n res: ServerResponse,\n ctx: InboundHandlerContext\n): Promise<WebInboundMessage | null> {\n // Read request body\n const chunks: Buffer[] = [];\n for await (const chunk of req) {\n chunks.push(chunk as Buffer);\n }\n const rawBody = Buffer.concat(chunks).toString(\"utf-8\");\n\n // Verify signature if secret is configured\n const signature = req.headers[\"x-forge-signature\"] as string;\n if (ctx.account.webhookSecret) {\n if (!signature) {\n res.writeHead(401, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Missing X-Forge-Signature header\" }));\n return null;\n }\n\n if (!verifyWebhookSignature(rawBody, signature, ctx.account.webhookSecret)) {\n res.writeHead(401, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Invalid signature\" }));\n return null;\n }\n }\n\n // Parse payload\n let payload: ForgeWebhookPayload;\n try {\n payload = JSON.parse(rawBody);\n } catch (error) {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Invalid JSON payload\" }));\n return null;\n }\n\n // Verify source is from Forge\n if (payload.source !== \"forge\") {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Invalid source\" }));\n return null;\n }\n\n // Update status\n ctx.statusSink?.({ lastInboundAt: Date.now() });\n\n // Convert to WebInboundMessage\n const inbound = forgePayloadToInbound(payload, ctx.account.accountId);\n\n if (!inbound) {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Could not process event\" }));\n return null;\n }\n\n // Respond success\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ success: true, event: payload.event }));\n\n return inbound;\n}\n\n/**\n * Resolve webhook path from config\n */\nexport function resolveKerneliusWebhookPath(\n webhookPath?: string,\n webhookUrl?: string\n): string {\n if (webhookPath?.trim()) {\n const path = webhookPath.trim();\n return path.startsWith(\"/\") ? path : `/${path}`;\n }\n\n if (webhookUrl?.trim()) {\n try {\n const parsed = new URL(webhookUrl);\n return parsed.pathname || \"/kernelius\";\n } catch {\n return \"/kernelius\";\n }\n }\n\n return \"/kernelius\";\n}\n"],"mappings":";AACA,SAAS,+BAA+B;;;ACGxC;AAAA,EACE;AAAA,EACA;AAAA,OACK;;;ACLP,IAAI,UAAkC;AAE/B,SAAS,oBAAoB,IAA2B;AAC7D,YAAU;AACZ;AAEO,SAAS,sBAAuC;AACrD,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,mCAAmC;AAAA,EACrD;AACA,SAAO;AACT;;;ACVA,OAAO,YAAY;AAWZ,SAAS,uBACd,SACA,WACA,QACS;AACT,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,EACT;AAEA,QAAM,oBAAoB,UAAU,OACjC,WAAW,UAAU,MAAM,EAC3B,OAAO,OAAO,EACd,OAAO,KAAK,CAAC;AAEhB,SAAO,OAAO;AAAA,IACZ,OAAO,KAAK,SAAS;AAAA,IACrB,OAAO,KAAK,iBAAiB;AAAA,EAC/B;AACF;AAKO,SAAS,sBACd,SACA,WAC0B;AAC1B,QAAM,EAAE,OAAO,YAAY,QAAQ,OAAO,aAAa,QAAQ,IAAI;AAGnE,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI,WAA+B;AAEnC,MAAI,OAAO;AACT,qBAAiB,QAAQ,WAAW,QAAQ,UAAU,MAAM,MAAM;AAElE,QAAI,UAAU,iBAAiB;AAC7B,aAAO,gBAAgB,MAAM,MAAM,OAAO,MAAM,KAAK;AAAA;AAAA,EAAO,MAAM,QAAQ,EAAE;AAC5E,kBAAY,SAAS,MAAM,EAAE;AAAA,IAC/B,WAAW,UAAU,qBAAqB,SAAS;AACjD,aAAO,uBAAuB,MAAM,MAAM,UAAU,OAAO,QAAQ;AAAA;AAAA,EAAQ,QAAQ,IAAI;AACvF,kBAAY,iBAAiB,QAAQ,EAAE;AAAA,IACzC,WAAW,UAAU,gBAAgB;AACnC,aAAO,YAAY,MAAM,MAAM,iBAAiB,OAAO,QAAQ;AAC/D,kBAAY,SAAS,MAAM,EAAE;AAAA,IAC/B,WAAW,UAAU,kBAAkB;AACrC,aAAO,YAAY,MAAM,MAAM,mBAAmB,OAAO,QAAQ;AACjE,kBAAY,SAAS,MAAM,EAAE;AAAA,IAC/B,WAAW,UAAU,iBAAiB;AACpC,aAAO,YAAY,MAAM,MAAM,kBAAkB,OAAO,QAAQ,KAAK,MAAM,KAAK;AAChF,kBAAY,SAAS,MAAM,EAAE;AAAA,IAC/B,OAAO;AACL,aAAO,UAAU,MAAM,MAAM,WAAW,KAAK;AAC7C,kBAAY,SAAS,MAAM,EAAE;AAAA,IAC/B;AAAA,EACF,WAAW,aAAa;AACtB,qBAAiB,QAAQ,WAAW,QAAQ,OAAO,YAAY,MAAM;AAErE,QAAI,UAAU,cAAc;AAC1B,aAAO,uBAAuB,YAAY,MAAM,OAAO,YAAY,KAAK;AAAA;AAAA,EAAO,YAAY,QAAQ,EAAE;AACrG,kBAAY,MAAM,YAAY,EAAE;AAAA,IAClC,WAAW,UAAU,uBAAuB;AAC1C,aAAO,6BAA6B,YAAY,MAAM,OAAO,YAAY,KAAK;AAAA;AAAA;AAC9E,kBAAY,MAAM,YAAY,EAAE;AAAA,IAClC,WAAW,UAAU,eAAe;AAClC,aAAO,SAAS,YAAY,MAAM,mBAAmB,OAAO,QAAQ;AACpE,kBAAY,MAAM,YAAY,EAAE;AAAA,IAClC,WAAW,UAAU,aAAa;AAChC,aAAO,SAAS,YAAY,MAAM,iBAAiB,OAAO,QAAQ;AAClE,kBAAY,MAAM,YAAY,EAAE;AAAA,IAClC,WAAW,UAAU,kBAAkB,SAAS;AAC9C,aAAO,oBAAoB,YAAY,MAAM,UAAU,OAAO,QAAQ;AAAA;AAAA,EAAQ,QAAQ,IAAI;AAC1F,kBAAY,cAAc,QAAQ,EAAE;AAAA,IACtC,WAAW,UAAU,aAAa;AAChC,aAAO,SAAS,YAAY,MAAM,iBAAiB,OAAO,QAAQ;AAClE,kBAAY,MAAM,YAAY,EAAE;AAAA,IAClC,WAAW,UAAU,eAAe;AAClC,aAAO,SAAS,YAAY,MAAM,mBAAmB,OAAO,QAAQ;AACpE,kBAAY,MAAM,YAAY,EAAE;AAAA,IAClC,OAAO;AACL,aAAO,iBAAiB,YAAY,MAAM,WAAW,KAAK;AAC1D,kBAAY,MAAM,YAAY,EAAE;AAAA,IAClC;AAAA,EACF,OAAO;AAEL,qBAAiB,QAAQ,WAAW,QAAQ;AAC5C,WAAO,qBAAqB,KAAK;AAAA,EACnC;AAEA,QAAM,YAAY,IAAI,KAAK,QAAQ,SAAS,EAAE,QAAQ;AAEtD,SAAO;AAAA,IACL,IAAI,OAAO,WAAW;AAAA,IACtB,MAAM;AAAA,IACN;AAAA,IACA,IAAI;AAAA,IACJ;AAAA,IACA;AAAA,IACA,UAAU,OAAO;AAAA,IACjB;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR,YAAY,OAAO;AAAA,IACnB,SAAS;AAAA,IACT,UAAU;AAAA,IACV;AAAA;AAAA;AAAA,IAEA,eAAe,YAAY;AAAA,IAAC;AAAA,IAC5B,OAAO,OAAO,SAAiB;AAE7B,cAAQ,IAAI,6BAA6B,IAAI,EAAE;AAAA,IACjD;AAAA,IACA,WAAW,YAAY;AACrB,YAAM,IAAI,MAAM,wCAAwC;AAAA,IAC1D;AAAA,EACF;AACF;AAKA,eAAsB,qBACpB,KACA,KACA,KACmC;AAEnC,QAAM,SAAmB,CAAC;AAC1B,mBAAiB,SAAS,KAAK;AAC7B,WAAO,KAAK,KAAe;AAAA,EAC7B;AACA,QAAM,UAAU,OAAO,OAAO,MAAM,EAAE,SAAS,OAAO;AAGtD,QAAM,YAAY,IAAI,QAAQ,mBAAmB;AACjD,MAAI,IAAI,QAAQ,eAAe;AAC7B,QAAI,CAAC,WAAW;AACd,UAAI,UAAU,KAAK,EAAE,gBAAgB,mBAAmB,CAAC;AACzD,UAAI,IAAI,KAAK,UAAU,EAAE,OAAO,mCAAmC,CAAC,CAAC;AACrE,aAAO;AAAA,IACT;AAEA,QAAI,CAAC,uBAAuB,SAAS,WAAW,IAAI,QAAQ,aAAa,GAAG;AAC1E,UAAI,UAAU,KAAK,EAAE,gBAAgB,mBAAmB,CAAC;AACzD,UAAI,IAAI,KAAK,UAAU,EAAE,OAAO,oBAAoB,CAAC,CAAC;AACtD,aAAO;AAAA,IACT;AAAA,EACF;AAGA,MAAI;AACJ,MAAI;AACF,cAAU,KAAK,MAAM,OAAO;AAAA,EAC9B,SAAS,OAAO;AACd,QAAI,UAAU,KAAK,EAAE,gBAAgB,mBAAmB,CAAC;AACzD,QAAI,IAAI,KAAK,UAAU,EAAE,OAAO,uBAAuB,CAAC,CAAC;AACzD,WAAO;AAAA,EACT;AAGA,MAAI,QAAQ,WAAW,SAAS;AAC9B,QAAI,UAAU,KAAK,EAAE,gBAAgB,mBAAmB,CAAC;AACzD,QAAI,IAAI,KAAK,UAAU,EAAE,OAAO,iBAAiB,CAAC,CAAC;AACnD,WAAO;AAAA,EACT;AAGA,MAAI,aAAa,EAAE,eAAe,KAAK,IAAI,EAAE,CAAC;AAG9C,QAAM,UAAU,sBAAsB,SAAS,IAAI,QAAQ,SAAS;AAEpE,MAAI,CAAC,SAAS;AACZ,QAAI,UAAU,KAAK,EAAE,gBAAgB,mBAAmB,CAAC;AACzD,QAAI,IAAI,KAAK,UAAU,EAAE,OAAO,0BAA0B,CAAC,CAAC;AAC5D,WAAO;AAAA,EACT;AAGA,MAAI,UAAU,KAAK,EAAE,gBAAgB,mBAAmB,CAAC;AACzD,MAAI,IAAI,KAAK,UAAU,EAAE,SAAS,MAAM,OAAO,QAAQ,MAAM,CAAC,CAAC;AAE/D,SAAO;AACT;AAKO,SAAS,4BACd,aACA,YACQ;AACR,MAAI,aAAa,KAAK,GAAG;AACvB,UAAM,OAAO,YAAY,KAAK;AAC9B,WAAO,KAAK,WAAW,GAAG,IAAI,OAAO,IAAI,IAAI;AAAA,EAC/C;AAEA,MAAI,YAAY,KAAK,GAAG;AACtB,QAAI;AACF,YAAM,SAAS,IAAI,IAAI,UAAU;AACjC,aAAO,OAAO,YAAY;AAAA,IAC5B,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;;;AFhNA,IAAM,OAAO,mBAAmB,WAAW;AAG3C,SAAS,wBAAwB,KAAU,WAA8C;AACvF,QAAM,qBAAqB,aAAa;AACxC,QAAM,gBAAgB,IAAI,UAAU,aAAa,CAAC;AAGlD,QAAM,gBAAgB,cAAc,WAAW,kBAAkB,KAAK;AAEtE,SAAO;AAAA,IACL,WAAW;AAAA,IACX,SAAS,cAAc,YAAY;AAAA,IACnC,QAAQ,cAAc,UAAU;AAAA,IAChC,QAAQ,cAAc;AAAA,IACtB,eAAe,cAAc;AAAA,IAC7B,aAAa,cAAc;AAAA,IAC3B,YAAY,cAAc;AAAA,EAC5B;AACF;AAEO,IAAM,kBAAiC;AAAA,EAC5C,IAAI;AAAA,EACJ,MAAM;AAAA,IACJ,GAAG;AAAA,IACH,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,EACf;AAAA,EACA,cAAc;AAAA,IACZ,WAAW,CAAC,UAAU,WAAW,QAAQ;AAAA,IACzC,WAAW;AAAA,IACX,SAAS;AAAA,IACT,OAAO;AAAA,IACP,gBAAgB;AAAA,EAClB;AAAA,EACA,QAAQ,EAAE,gBAAgB,CAAC,oBAAoB,EAAE;AAAA,EACjD,QAAQ;AAAA,IACN,gBAAgB,CAAC,QAAQ;AACvB,YAAM,gBAAgB,IAAI,UAAU;AACpC,UAAI,CAAC,cAAe,QAAO,CAAC;AAC5B,UAAI,cAAc,UAAU;AAC1B,eAAO,OAAO,KAAK,cAAc,QAAQ;AAAA,MAC3C;AACA,aAAO,CAAC,kBAAkB;AAAA,IAC5B;AAAA,IACA,gBAAgB,CAAC,KAAK,cAAc,wBAAwB,KAAK,SAAS;AAAA,IAC1E,kBAAkB,MAAM;AAAA,IACxB,mBAAmB,CAAC,EAAE,KAAK,WAAW,QAAQ,MAAM;AAClD,YAAM,qBAAqB,aAAa;AACxC,UAAI,CAAC,IAAI,SAAU,KAAI,WAAW,CAAC;AACnC,UAAI,CAAC,IAAI,SAAS,UAAW,KAAI,SAAS,YAAY,CAAC;AAEvD,UAAI,IAAI,SAAS,UAAU,WAAW,kBAAkB,GAAG;AACzD,YAAI,SAAS,UAAU,SAAS,kBAAkB,EAAE,UAAU;AAAA,MAChE,OAAO;AACL,YAAI,SAAS,UAAU,UAAU;AAAA,MACnC;AACA,aAAO;AAAA,IACT;AAAA,IACA,eAAe,CAAC,EAAE,KAAK,UAAU,MAAM;AACrC,UAAI,aAAa,cAAc,oBAAoB;AACjD,eAAO,IAAI,UAAU,WAAW,WAAW,SAAS;AAAA,MACtD;AACA,aAAO;AAAA,IACT;AAAA,IACA,cAAc,CAAC,YAAiB,QAAQ,QAAQ,MAAM;AAAA,IACtD,iBAAiB,CAAC,aAAkB;AAAA,MAClC,WAAW,QAAQ;AAAA,MACnB,SAAS,QAAQ;AAAA,MACjB,YAAY,QAAQ,QAAQ,MAAM;AAAA,MAClC,QAAQ,QAAQ;AAAA,IAClB;AAAA,IACA,kBAAkB,MAAM,CAAC;AAAA,IACzB,iBAAiB,CAAC,EAAE,UAAU,MAAM;AAAA,EACtC;AAAA,EACA,WAAW;AAAA;AAAA,IAET,MAAM,OAAO,KAAK,WAAW;AAC3B,YAAMA,WAAU,oBAAoB;AACpC,YAAM,UAAU,wBAAwBA,SAAQ,OAAO,WAAW,GAAG,OAAO,SAAS;AAErF,UAAI,CAAC,QAAQ,QAAQ;AACnB,cAAM,IAAI,MAAM,kCAAkC;AAAA,MACpD;AAGA,YAAM,SAAS,OAAO;AACtB,YAAM,QAAQ,OAAO,MAAM,0CAA0C;AAErE,UAAI,CAAC,OAAO;AACV,cAAM,IAAI,MAAM,oCAAoC,MAAM,+DAA+D;AAAA,MAC3H;AAEA,YAAM,CAAC,EAAE,OAAO,MAAM,MAAM,MAAM,IAAI;AACtC,YAAM,WAAW,SAAS,UACtB,qBAAqB,KAAK,IAAI,IAAI,WAAW,MAAM,cACnD,qBAAqB,KAAK,IAAI,IAAI,UAAU,MAAM;AAEtD,YAAM,WAAW,MAAM,MAAM,GAAG,QAAQ,MAAM,GAAG,QAAQ,IAAI;AAAA,QAC3D,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,iBAAiB,UAAU,QAAQ,MAAM;AAAA,QAC3C;AAAA,QACA,MAAM,KAAK,UAAU;AAAA,UACnB,MAAM,OAAO;AAAA,QACf,CAAC;AAAA,MACH,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,QAAQ,MAAM,SAAS,KAAK;AAClC,cAAM,IAAI,MAAM,wCAAwC,SAAS,MAAM,IAAI,KAAK,EAAE;AAAA,MACpF;AAEA,YAAM,SAAS,MAAM,SAAS,KAAK;AAEnC,aAAO;AAAA,QACL,WAAW,OAAO;AAAA,QAClB,WAAW,IAAI,KAAK,OAAO,SAAS;AAAA,MACtC;AAAA,IACF;AAAA;AAAA;AAAA,IAIA,OAAO,OAAO,KAAK,WAAW;AAC5B,YAAMA,WAAU,oBAAoB;AACpC,YAAM,UAAU,wBAAwBA,SAAQ,OAAO,WAAW,GAAG,OAAO,SAAS;AAErF,UAAI,CAAC,QAAQ,QAAQ;AACnB,cAAM,IAAI,MAAM,kCAAkC;AAAA,MACpD;AAEA,YAAM,EAAE,WAAW,MAAM,IAAI;AAC7B,UAAI,CAAC,aAAa,CAAC,OAAO;AACxB,cAAM,IAAI,MAAM,gDAAgD;AAAA,MAClE;AAIA,UAAI;AACJ,UAAI,UAAU,WAAW,gBAAgB,GAAG;AAC1C,mBAAW,wBAAwB,UAAU,QAAQ,kBAAkB,EAAE,CAAC;AAAA,MAC5E,WAAW,UAAU,WAAW,aAAa,GAAG;AAC9C,mBAAW,uBAAuB,UAAU,QAAQ,eAAe,EAAE,CAAC;AAAA,MACxE,WAAW,UAAU,WAAW,QAAQ,GAAG;AACzC,mBAAW,eAAe,UAAU,QAAQ,UAAU,EAAE,CAAC;AAAA,MAC3D,WAAW,UAAU,WAAW,KAAK,GAAG;AACtC,mBAAW,cAAc,UAAU,QAAQ,OAAO,EAAE,CAAC;AAAA,MACvD,OAAO;AACL,cAAM,IAAI,MAAM,6BAA6B,SAAS,yEAAyE;AAAA,MACjI;AAEA,YAAM,WAAW,MAAM,MAAM,GAAG,QAAQ,MAAM,GAAG,QAAQ,IAAI;AAAA,QAC3D,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,iBAAiB,UAAU,QAAQ,MAAM;AAAA,QAC3C;AAAA,QACA,MAAM,KAAK,UAAU,EAAE,MAAM,CAAC;AAAA,MAChC,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,QAAQ,MAAM,SAAS,KAAK;AAClC,cAAM,IAAI,MAAM,2BAA2B,SAAS,MAAM,IAAI,KAAK,EAAE;AAAA,MACvE;AAEA,YAAM,SAAS,MAAM,SAAS,KAAK;AACnC,aAAO,EAAE,OAAO,OAAO,MAAM;AAAA,IAC/B;AAAA,EACF;AAAA,EACA,SAAS;AAAA,IACP,aAAa,MAAM,CAAC,QAAQ,OAAO;AAAA,IACnC,iBAAiB,CAAC,EAAE,KAAK,MAAM;AAC7B,YAAM,SAAS,OAAO,KAAK,WAAW,WAAW,KAAK,OAAO,KAAK,IAAI;AACtE,UAAI,WAAW,eAAe;AAC5B,eAAO;AAAA,MACT;AACA,YAAM,KAAK,OAAO,KAAK,OAAO,WAAW,KAAK,KAAK;AACnD,UAAI,CAAC,IAAI;AACP,eAAO;AAAA,MACT;AACA,YAAM,YAAY,OAAO,KAAK,cAAc,WAAW,KAAK,UAAU,KAAK,IAAI;AAC/E,aAAO,EAAE,IAAI,UAAU;AAAA,IACzB;AAAA,IACA,cAAc,OAAO,EAAE,QAAQ,QAAQ,KAAK,UAAU,MAAM;AAC1D,YAAM,UAAU,wBAAwB,KAAK,SAAS;AAEtD,UAAI,CAAC,QAAQ,QAAQ;AACnB,cAAM,IAAI,MAAM,kCAAkC;AAAA,MACpD;AAEA,UAAI,WAAW,SAAS;AACtB,cAAM,YAAY,OAAO,OAAO,cAAc,WAAW,OAAO,YAAY;AAC5E,cAAM,QAAQ,OAAO,OAAO,UAAU,WAAW,OAAO,QAAQ;AAEhE,YAAI,CAAC,aAAa,CAAC,OAAO;AACxB,gBAAM,IAAI,MAAM,yDAAyD;AAAA,QAC3E;AAGA,YAAIC;AACJ,YAAI,UAAU,WAAW,gBAAgB,GAAG;AAC1C,UAAAA,YAAW,wBAAwB,UAAU,QAAQ,kBAAkB,EAAE,CAAC;AAAA,QAC5E,WAAW,UAAU,WAAW,aAAa,GAAG;AAC9C,UAAAA,YAAW,uBAAuB,UAAU,QAAQ,eAAe,EAAE,CAAC;AAAA,QACxE,WAAW,UAAU,WAAW,QAAQ,GAAG;AACzC,UAAAA,YAAW,eAAe,UAAU,QAAQ,UAAU,EAAE,CAAC;AAAA,QAC3D,WAAW,UAAU,WAAW,KAAK,GAAG;AACtC,UAAAA,YAAW,cAAc,UAAU,QAAQ,OAAO,EAAE,CAAC;AAAA,QACvD,OAAO;AACL,gBAAM,IAAI,MAAM,6BAA6B,SAAS,EAAE;AAAA,QAC1D;AAEA,cAAMC,YAAW,MAAM,MAAM,GAAG,QAAQ,MAAM,GAAGD,SAAQ,IAAI;AAAA,UAC3D,QAAQ;AAAA,UACR,SAAS;AAAA,YACP,gBAAgB;AAAA,YAChB,iBAAiB,UAAU,QAAQ,MAAM;AAAA,UAC3C;AAAA,UACA,MAAM,KAAK,UAAU,EAAE,MAAM,CAAC;AAAA,QAChC,CAAC;AAED,YAAI,CAACC,UAAS,IAAI;AAChB,gBAAM,IAAI,MAAM,2BAA2BA,UAAS,MAAM,EAAE;AAAA,QAC9D;AAEA,eAAO,EAAE,SAAS,KAAK;AAAA,MACzB;AAEA,UAAI,WAAW,QAAQ;AACrB,cAAM,IAAI,MAAM,mBAAmB,MAAM,EAAE;AAAA,MAC7C;AAEA,YAAM,KAAK,OAAO,OAAO,OAAO,WAAW,OAAO,KAAK;AACvD,YAAM,UAAU,OAAO,OAAO,YAAY,WAAW,OAAO,UAAU;AAEtE,UAAI,CAAC,MAAM,CAAC,SAAS;AACnB,cAAM,IAAI,MAAM,0CAA0C;AAAA,MAC5D;AAGA,YAAM,QAAQ,GAAG,MAAM,0CAA0C;AACjE,UAAI,CAAC,OAAO;AACV,cAAM,IAAI,MAAM,0BAA0B,EAAE,EAAE;AAAA,MAChD;AAEA,YAAM,CAAC,EAAE,OAAO,MAAM,MAAM,MAAM,IAAI;AACtC,YAAM,WAAW,SAAS,UACtB,qBAAqB,KAAK,IAAI,IAAI,WAAW,MAAM,cACnD,qBAAqB,KAAK,IAAI,IAAI,UAAU,MAAM;AAEtD,YAAM,WAAW,MAAM,MAAM,GAAG,QAAQ,MAAM,GAAG,QAAQ,IAAI;AAAA,QAC3D,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,iBAAiB,UAAU,QAAQ,MAAM;AAAA,QAC3C;AAAA,QACA,MAAM,KAAK,UAAU,EAAE,MAAM,QAAQ,CAAC;AAAA,MACxC,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,IAAI,MAAM,mBAAmB,SAAS,MAAM,EAAE;AAAA,MACtD;AAEA,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB;AAAA,EACF;AAAA,EACA,SAAS;AAAA,IACP,OAAO,OAAO,QAAQ;AACpB,YAAMF,WAAU,oBAAoB;AACpC,YAAM,SAASA,SAAQ,OAAO,WAAW;AACzC,YAAM,UAAU,wBAAwB,QAAQ,IAAI,SAAS;AAG7D,UAAI,CAAC,QAAQ,eAAe,CAAC,QAAQ,YAAY;AAC/C,gBAAQ,IAAI,gEAAgE;AAC5E;AAAA,MACF;AAEA,YAAM,cAAc;AAAA,QAClB,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV;AAEA,cAAQ,IAAI,4CAA4C,QAAQ,SAAS,OAAO,WAAW,EAAE;AAG7F,UAAI,oBAAoB;AAAA,QACtB,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,SAAS,OAAO,KAAK,QAAQ;AAC3B,cAAI;AACF,kBAAM,UAAU,MAAM,qBAAqB,KAAK,KAAK;AAAA,cACnD;AAAA,cACA,SAAAA;AAAA,cACA,YAAY,IAAI;AAAA,YAClB,CAAC;AAED,gBAAI,SAAS;AAEX,oBAAM,IAAI,aAAa,OAAO;AAAA,YAChC;AAAA,UACF,SAAS,OAAO;AACd,oBAAQ,MAAM,sCAAsC,KAAK;AACzD,gBAAI,CAAC,IAAI,aAAa;AACpB,kBAAI,UAAU,KAAK,EAAE,gBAAgB,mBAAmB,CAAC;AACzD,kBAAI,IAAI,KAAK,UAAU,EAAE,OAAO,wBAAwB,CAAC,CAAC;AAAA,YAC5D;AAAA,UACF;AAAA,QACF;AAAA,MACF,CAAC;AAED,cAAQ,IAAI,+CAA+C,WAAW,EAAE;AAAA,IAC1E;AAAA,IACA,MAAM,OAAO,QAAQ;AACnB,cAAQ,IAAI,4CAA4C,IAAI,SAAS,EAAE;AAAA,IAEzE;AAAA,EACF;AACF;;;AD1UA,IAAM,SAAS;AAAA,EACb,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,aAAa;AAAA,EACb,cAAc,wBAAwB;AAAA,EACtC,SAAS,KAAwB;AAC/B,wBAAoB,IAAI,OAAO;AAC/B,QAAI,gBAAgB,EAAE,QAAQ,gBAAgB,CAAC;AAAA,EACjD;AACF;AAEA,IAAO,gBAAQ;","names":["runtime","endpoint","response"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kernelius/openclaw-plugin",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"description": "OpenClaw channel plugin for Kernelius Forge - enables agents to work with repositories, issues, and pull requests",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|