mirror of
https://github.com/farcasclaudiu/openclaw.git
synced 2026-06-22 09:01:46 +03:00
refactor: rename clawdbot to moltbot with legacy compat
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import type { ClawdbotPluginApi } from "clawdbot/plugin-sdk";
|
||||
import type { MoltbotPluginApi } from "clawdbot/plugin-sdk";
|
||||
import { emptyPluginConfigSchema } from "clawdbot/plugin-sdk";
|
||||
|
||||
import { bluebubblesPlugin } from "./src/channel.js";
|
||||
@@ -10,7 +10,7 @@ const plugin = {
|
||||
name: "BlueBubbles",
|
||||
description: "BlueBubbles channel plugin (macOS app)",
|
||||
configSchema: emptyPluginConfigSchema(),
|
||||
register(api: ClawdbotPluginApi) {
|
||||
register(api: MoltbotPluginApi) {
|
||||
setBlueBubblesRuntime(api.runtime);
|
||||
api.registerChannel({ plugin: bluebubblesPlugin });
|
||||
api.registerHttpHandler(handleBlueBubblesWebhookRequest);
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
"name": "@moltbot/bluebubbles",
|
||||
"version": "2026.1.26",
|
||||
"type": "module",
|
||||
"description": "Clawdbot BlueBubbles channel plugin",
|
||||
"clawdbot": {
|
||||
"description": "Moltbot BlueBubbles channel plugin",
|
||||
"moltbot": {
|
||||
"extensions": [
|
||||
"./index.ts"
|
||||
],
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ClawdbotConfig } from "clawdbot/plugin-sdk";
|
||||
import type { MoltbotConfig } from "clawdbot/plugin-sdk";
|
||||
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "clawdbot/plugin-sdk";
|
||||
import { normalizeBlueBubblesServerUrl, type BlueBubblesAccountConfig } from "./types.js";
|
||||
|
||||
@@ -11,26 +11,26 @@ export type ResolvedBlueBubblesAccount = {
|
||||
baseUrl?: string;
|
||||
};
|
||||
|
||||
function listConfiguredAccountIds(cfg: ClawdbotConfig): string[] {
|
||||
function listConfiguredAccountIds(cfg: MoltbotConfig): string[] {
|
||||
const accounts = cfg.channels?.bluebubbles?.accounts;
|
||||
if (!accounts || typeof accounts !== "object") return [];
|
||||
return Object.keys(accounts).filter(Boolean);
|
||||
}
|
||||
|
||||
export function listBlueBubblesAccountIds(cfg: ClawdbotConfig): string[] {
|
||||
export function listBlueBubblesAccountIds(cfg: MoltbotConfig): string[] {
|
||||
const ids = listConfiguredAccountIds(cfg);
|
||||
if (ids.length === 0) return [DEFAULT_ACCOUNT_ID];
|
||||
return ids.sort((a, b) => a.localeCompare(b));
|
||||
}
|
||||
|
||||
export function resolveDefaultBlueBubblesAccountId(cfg: ClawdbotConfig): string {
|
||||
export function resolveDefaultBlueBubblesAccountId(cfg: MoltbotConfig): string {
|
||||
const ids = listBlueBubblesAccountIds(cfg);
|
||||
if (ids.includes(DEFAULT_ACCOUNT_ID)) return DEFAULT_ACCOUNT_ID;
|
||||
return ids[0] ?? DEFAULT_ACCOUNT_ID;
|
||||
}
|
||||
|
||||
function resolveAccountConfig(
|
||||
cfg: ClawdbotConfig,
|
||||
cfg: MoltbotConfig,
|
||||
accountId: string,
|
||||
): BlueBubblesAccountConfig | undefined {
|
||||
const accounts = cfg.channels?.bluebubbles?.accounts;
|
||||
@@ -39,7 +39,7 @@ function resolveAccountConfig(
|
||||
}
|
||||
|
||||
function mergeBlueBubblesAccountConfig(
|
||||
cfg: ClawdbotConfig,
|
||||
cfg: MoltbotConfig,
|
||||
accountId: string,
|
||||
): BlueBubblesAccountConfig {
|
||||
const base = (cfg.channels?.bluebubbles ?? {}) as BlueBubblesAccountConfig & {
|
||||
@@ -52,7 +52,7 @@ function mergeBlueBubblesAccountConfig(
|
||||
}
|
||||
|
||||
export function resolveBlueBubblesAccount(params: {
|
||||
cfg: ClawdbotConfig;
|
||||
cfg: MoltbotConfig;
|
||||
accountId?: string | null;
|
||||
}): ResolvedBlueBubblesAccount {
|
||||
const accountId = normalizeAccountId(params.accountId);
|
||||
@@ -73,7 +73,7 @@ export function resolveBlueBubblesAccount(params: {
|
||||
};
|
||||
}
|
||||
|
||||
export function listEnabledBlueBubblesAccounts(cfg: ClawdbotConfig): ResolvedBlueBubblesAccount[] {
|
||||
export function listEnabledBlueBubblesAccounts(cfg: MoltbotConfig): ResolvedBlueBubblesAccount[] {
|
||||
return listBlueBubblesAccountIds(cfg)
|
||||
.map((accountId) => resolveBlueBubblesAccount({ cfg, accountId }))
|
||||
.filter((account) => account.enabled);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { describe, expect, it, vi, beforeEach } from "vitest";
|
||||
|
||||
import { bluebubblesMessageActions } from "./actions.js";
|
||||
import type { ClawdbotConfig } from "clawdbot/plugin-sdk";
|
||||
import type { MoltbotConfig } from "clawdbot/plugin-sdk";
|
||||
|
||||
vi.mock("./accounts.js", () => ({
|
||||
resolveBlueBubblesAccount: vi.fn(({ cfg, accountId }) => {
|
||||
@@ -49,7 +49,7 @@ describe("bluebubblesMessageActions", () => {
|
||||
|
||||
describe("listActions", () => {
|
||||
it("returns empty array when account is not enabled", () => {
|
||||
const cfg: ClawdbotConfig = {
|
||||
const cfg: MoltbotConfig = {
|
||||
channels: { bluebubbles: { enabled: false } },
|
||||
};
|
||||
const actions = bluebubblesMessageActions.listActions({ cfg });
|
||||
@@ -57,7 +57,7 @@ describe("bluebubblesMessageActions", () => {
|
||||
});
|
||||
|
||||
it("returns empty array when account is not configured", () => {
|
||||
const cfg: ClawdbotConfig = {
|
||||
const cfg: MoltbotConfig = {
|
||||
channels: { bluebubbles: { enabled: true } },
|
||||
};
|
||||
const actions = bluebubblesMessageActions.listActions({ cfg });
|
||||
@@ -65,7 +65,7 @@ describe("bluebubblesMessageActions", () => {
|
||||
});
|
||||
|
||||
it("returns react action when enabled and configured", () => {
|
||||
const cfg: ClawdbotConfig = {
|
||||
const cfg: MoltbotConfig = {
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enabled: true,
|
||||
@@ -79,7 +79,7 @@ describe("bluebubblesMessageActions", () => {
|
||||
});
|
||||
|
||||
it("excludes react action when reactions are gated off", () => {
|
||||
const cfg: ClawdbotConfig = {
|
||||
const cfg: MoltbotConfig = {
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enabled: true,
|
||||
@@ -153,7 +153,7 @@ describe("bluebubblesMessageActions", () => {
|
||||
|
||||
describe("handleAction", () => {
|
||||
it("throws for unsupported actions", async () => {
|
||||
const cfg: ClawdbotConfig = {
|
||||
const cfg: MoltbotConfig = {
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
serverUrl: "http://localhost:1234",
|
||||
@@ -172,7 +172,7 @@ describe("bluebubblesMessageActions", () => {
|
||||
});
|
||||
|
||||
it("throws when emoji is missing for react action", async () => {
|
||||
const cfg: ClawdbotConfig = {
|
||||
const cfg: MoltbotConfig = {
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
serverUrl: "http://localhost:1234",
|
||||
@@ -191,7 +191,7 @@ describe("bluebubblesMessageActions", () => {
|
||||
});
|
||||
|
||||
it("throws when messageId is missing", async () => {
|
||||
const cfg: ClawdbotConfig = {
|
||||
const cfg: MoltbotConfig = {
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
serverUrl: "http://localhost:1234",
|
||||
@@ -213,7 +213,7 @@ describe("bluebubblesMessageActions", () => {
|
||||
const { resolveChatGuidForTarget } = await import("./send.js");
|
||||
vi.mocked(resolveChatGuidForTarget).mockResolvedValueOnce(null);
|
||||
|
||||
const cfg: ClawdbotConfig = {
|
||||
const cfg: MoltbotConfig = {
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
serverUrl: "http://localhost:1234",
|
||||
@@ -234,7 +234,7 @@ describe("bluebubblesMessageActions", () => {
|
||||
it("sends reaction successfully with chatGuid", async () => {
|
||||
const { sendBlueBubblesReaction } = await import("./reactions.js");
|
||||
|
||||
const cfg: ClawdbotConfig = {
|
||||
const cfg: MoltbotConfig = {
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
serverUrl: "http://localhost:1234",
|
||||
@@ -269,7 +269,7 @@ describe("bluebubblesMessageActions", () => {
|
||||
it("sends reaction removal successfully", async () => {
|
||||
const { sendBlueBubblesReaction } = await import("./reactions.js");
|
||||
|
||||
const cfg: ClawdbotConfig = {
|
||||
const cfg: MoltbotConfig = {
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
serverUrl: "http://localhost:1234",
|
||||
@@ -305,7 +305,7 @@ describe("bluebubblesMessageActions", () => {
|
||||
const { resolveChatGuidForTarget } = await import("./send.js");
|
||||
vi.mocked(resolveChatGuidForTarget).mockResolvedValueOnce("iMessage;-;+15559876543");
|
||||
|
||||
const cfg: ClawdbotConfig = {
|
||||
const cfg: MoltbotConfig = {
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
serverUrl: "http://localhost:1234",
|
||||
@@ -335,7 +335,7 @@ describe("bluebubblesMessageActions", () => {
|
||||
it("passes partIndex when provided", async () => {
|
||||
const { sendBlueBubblesReaction } = await import("./reactions.js");
|
||||
|
||||
const cfg: ClawdbotConfig = {
|
||||
const cfg: MoltbotConfig = {
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
serverUrl: "http://localhost:1234",
|
||||
@@ -367,7 +367,7 @@ describe("bluebubblesMessageActions", () => {
|
||||
const { resolveChatGuidForTarget } = await import("./send.js");
|
||||
vi.mocked(resolveChatGuidForTarget).mockResolvedValueOnce("iMessage;-;+15550001111");
|
||||
|
||||
const cfg: ClawdbotConfig = {
|
||||
const cfg: MoltbotConfig = {
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
serverUrl: "http://localhost:1234",
|
||||
@@ -405,7 +405,7 @@ describe("bluebubblesMessageActions", () => {
|
||||
const { sendBlueBubblesReaction } = await import("./reactions.js");
|
||||
vi.mocked(resolveBlueBubblesMessageId).mockReturnValueOnce("resolved-uuid");
|
||||
|
||||
const cfg: ClawdbotConfig = {
|
||||
const cfg: MoltbotConfig = {
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
serverUrl: "http://localhost:1234",
|
||||
@@ -439,7 +439,7 @@ describe("bluebubblesMessageActions", () => {
|
||||
throw new Error("short id expired");
|
||||
});
|
||||
|
||||
const cfg: ClawdbotConfig = {
|
||||
const cfg: MoltbotConfig = {
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
serverUrl: "http://localhost:1234",
|
||||
@@ -465,7 +465,7 @@ describe("bluebubblesMessageActions", () => {
|
||||
it("accepts message param for edit action", async () => {
|
||||
const { editBlueBubblesMessage } = await import("./chat.js");
|
||||
|
||||
const cfg: ClawdbotConfig = {
|
||||
const cfg: MoltbotConfig = {
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
serverUrl: "http://localhost:1234",
|
||||
@@ -491,7 +491,7 @@ describe("bluebubblesMessageActions", () => {
|
||||
it("accepts message/target aliases for sendWithEffect", async () => {
|
||||
const { sendMessageBlueBubbles } = await import("./send.js");
|
||||
|
||||
const cfg: ClawdbotConfig = {
|
||||
const cfg: MoltbotConfig = {
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
serverUrl: "http://localhost:1234",
|
||||
@@ -524,7 +524,7 @@ describe("bluebubblesMessageActions", () => {
|
||||
it("passes asVoice through sendAttachment", async () => {
|
||||
const { sendBlueBubblesAttachment } = await import("./attachments.js");
|
||||
|
||||
const cfg: ClawdbotConfig = {
|
||||
const cfg: MoltbotConfig = {
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
serverUrl: "http://localhost:1234",
|
||||
@@ -558,7 +558,7 @@ describe("bluebubblesMessageActions", () => {
|
||||
});
|
||||
|
||||
it("throws when buffer is missing for setGroupIcon", async () => {
|
||||
const cfg: ClawdbotConfig = {
|
||||
const cfg: MoltbotConfig = {
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
serverUrl: "http://localhost:1234",
|
||||
@@ -580,7 +580,7 @@ describe("bluebubblesMessageActions", () => {
|
||||
it("sets group icon successfully with chatGuid and buffer", async () => {
|
||||
const { setGroupIconBlueBubbles } = await import("./chat.js");
|
||||
|
||||
const cfg: ClawdbotConfig = {
|
||||
const cfg: MoltbotConfig = {
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
serverUrl: "http://localhost:1234",
|
||||
@@ -619,7 +619,7 @@ describe("bluebubblesMessageActions", () => {
|
||||
it("uses default filename when not provided for setGroupIcon", async () => {
|
||||
const { setGroupIconBlueBubbles } = await import("./chat.js");
|
||||
|
||||
const cfg: ClawdbotConfig = {
|
||||
const cfg: MoltbotConfig = {
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
serverUrl: "http://localhost:1234",
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
type ChannelMessageActionAdapter,
|
||||
type ChannelMessageActionName,
|
||||
type ChannelToolSend,
|
||||
type ClawdbotConfig,
|
||||
type MoltbotConfig,
|
||||
} from "clawdbot/plugin-sdk";
|
||||
|
||||
import { resolveBlueBubblesAccount } from "./accounts.js";
|
||||
@@ -66,9 +66,9 @@ const SUPPORTED_ACTIONS = new Set<ChannelMessageActionName>(BLUEBUBBLES_ACTION_N
|
||||
|
||||
export const bluebubblesMessageActions: ChannelMessageActionAdapter = {
|
||||
listActions: ({ cfg }) => {
|
||||
const account = resolveBlueBubblesAccount({ cfg: cfg as ClawdbotConfig });
|
||||
const account = resolveBlueBubblesAccount({ cfg: cfg as MoltbotConfig });
|
||||
if (!account.enabled || !account.configured) return [];
|
||||
const gate = createActionGate((cfg as ClawdbotConfig).channels?.bluebubbles?.actions);
|
||||
const gate = createActionGate((cfg as MoltbotConfig).channels?.bluebubbles?.actions);
|
||||
const actions = new Set<ChannelMessageActionName>();
|
||||
const macOS26 = isMacOS26OrHigher(account.accountId);
|
||||
for (const action of BLUEBUBBLES_ACTION_NAMES) {
|
||||
@@ -90,12 +90,12 @@ export const bluebubblesMessageActions: ChannelMessageActionAdapter = {
|
||||
},
|
||||
handleAction: async ({ action, params, cfg, accountId, toolContext }) => {
|
||||
const account = resolveBlueBubblesAccount({
|
||||
cfg: cfg as ClawdbotConfig,
|
||||
cfg: cfg as MoltbotConfig,
|
||||
accountId: accountId ?? undefined,
|
||||
});
|
||||
const baseUrl = account.config.serverUrl?.trim();
|
||||
const password = account.config.password?.trim();
|
||||
const opts = { cfg: cfg as ClawdbotConfig, accountId: accountId ?? undefined };
|
||||
const opts = { cfg: cfg as MoltbotConfig, accountId: accountId ?? undefined };
|
||||
|
||||
// Helper to resolve chatGuid from various params or session context
|
||||
const resolveChatGuid = async (): Promise<string> => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import crypto from "node:crypto";
|
||||
import path from "node:path";
|
||||
import type { ClawdbotConfig } from "clawdbot/plugin-sdk";
|
||||
import type { MoltbotConfig } from "clawdbot/plugin-sdk";
|
||||
import { resolveBlueBubblesAccount } from "./accounts.js";
|
||||
import { resolveChatGuidForTarget } from "./send.js";
|
||||
import { parseBlueBubblesTarget, normalizeBlueBubblesHandle } from "./targets.js";
|
||||
@@ -16,7 +16,7 @@ export type BlueBubblesAttachmentOpts = {
|
||||
password?: string;
|
||||
accountId?: string;
|
||||
timeoutMs?: number;
|
||||
cfg?: ClawdbotConfig;
|
||||
cfg?: MoltbotConfig;
|
||||
};
|
||||
|
||||
const DEFAULT_ATTACHMENT_MAX_BYTES = 8 * 1024 * 1024;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ChannelAccountSnapshot, ChannelPlugin, ClawdbotConfig } from "clawdbot/plugin-sdk";
|
||||
import type { ChannelAccountSnapshot, ChannelPlugin, MoltbotConfig } from "clawdbot/plugin-sdk";
|
||||
import {
|
||||
applyAccountNameToChannelSection,
|
||||
buildChannelConfigSchema,
|
||||
@@ -78,13 +78,13 @@ export const bluebubblesPlugin: ChannelPlugin<ResolvedBlueBubblesAccount> = {
|
||||
configSchema: buildChannelConfigSchema(BlueBubblesConfigSchema),
|
||||
onboarding: blueBubblesOnboardingAdapter,
|
||||
config: {
|
||||
listAccountIds: (cfg) => listBlueBubblesAccountIds(cfg as ClawdbotConfig),
|
||||
listAccountIds: (cfg) => listBlueBubblesAccountIds(cfg as MoltbotConfig),
|
||||
resolveAccount: (cfg, accountId) =>
|
||||
resolveBlueBubblesAccount({ cfg: cfg as ClawdbotConfig, accountId }),
|
||||
defaultAccountId: (cfg) => resolveDefaultBlueBubblesAccountId(cfg as ClawdbotConfig),
|
||||
resolveBlueBubblesAccount({ cfg: cfg as MoltbotConfig, accountId }),
|
||||
defaultAccountId: (cfg) => resolveDefaultBlueBubblesAccountId(cfg as MoltbotConfig),
|
||||
setAccountEnabled: ({ cfg, accountId, enabled }) =>
|
||||
setAccountEnabledInConfigSection({
|
||||
cfg: cfg as ClawdbotConfig,
|
||||
cfg: cfg as MoltbotConfig,
|
||||
sectionKey: "bluebubbles",
|
||||
accountId,
|
||||
enabled,
|
||||
@@ -92,7 +92,7 @@ export const bluebubblesPlugin: ChannelPlugin<ResolvedBlueBubblesAccount> = {
|
||||
}),
|
||||
deleteAccount: ({ cfg, accountId }) =>
|
||||
deleteAccountFromConfigSection({
|
||||
cfg: cfg as ClawdbotConfig,
|
||||
cfg: cfg as MoltbotConfig,
|
||||
sectionKey: "bluebubbles",
|
||||
accountId,
|
||||
clearBaseFields: ["serverUrl", "password", "name", "webhookPath"],
|
||||
@@ -106,7 +106,7 @@ export const bluebubblesPlugin: ChannelPlugin<ResolvedBlueBubblesAccount> = {
|
||||
baseUrl: account.baseUrl,
|
||||
}),
|
||||
resolveAllowFrom: ({ cfg, accountId }) =>
|
||||
(resolveBlueBubblesAccount({ cfg: cfg as ClawdbotConfig, accountId }).config.allowFrom ??
|
||||
(resolveBlueBubblesAccount({ cfg: cfg as MoltbotConfig, accountId }).config.allowFrom ??
|
||||
[]).map(
|
||||
(entry) => String(entry),
|
||||
),
|
||||
@@ -122,7 +122,7 @@ export const bluebubblesPlugin: ChannelPlugin<ResolvedBlueBubblesAccount> = {
|
||||
resolveDmPolicy: ({ cfg, accountId, account }) => {
|
||||
const resolvedAccountId = accountId ?? account.accountId ?? DEFAULT_ACCOUNT_ID;
|
||||
const useAccountPath = Boolean(
|
||||
(cfg as ClawdbotConfig).channels?.bluebubbles?.accounts?.[resolvedAccountId],
|
||||
(cfg as MoltbotConfig).channels?.bluebubbles?.accounts?.[resolvedAccountId],
|
||||
);
|
||||
const basePath = useAccountPath
|
||||
? `channels.bluebubbles.accounts.${resolvedAccountId}.`
|
||||
@@ -207,7 +207,7 @@ export const bluebubblesPlugin: ChannelPlugin<ResolvedBlueBubblesAccount> = {
|
||||
resolveAccountId: ({ accountId }) => normalizeAccountId(accountId),
|
||||
applyAccountName: ({ cfg, accountId, name }) =>
|
||||
applyAccountNameToChannelSection({
|
||||
cfg: cfg as ClawdbotConfig,
|
||||
cfg: cfg as MoltbotConfig,
|
||||
channelKey: "bluebubbles",
|
||||
accountId,
|
||||
name,
|
||||
@@ -222,7 +222,7 @@ export const bluebubblesPlugin: ChannelPlugin<ResolvedBlueBubblesAccount> = {
|
||||
},
|
||||
applyAccountConfig: ({ cfg, accountId, input }) => {
|
||||
const namedConfig = applyAccountNameToChannelSection({
|
||||
cfg: cfg as ClawdbotConfig,
|
||||
cfg: cfg as MoltbotConfig,
|
||||
channelKey: "bluebubbles",
|
||||
accountId,
|
||||
name: input.name,
|
||||
@@ -247,7 +247,7 @@ export const bluebubblesPlugin: ChannelPlugin<ResolvedBlueBubblesAccount> = {
|
||||
...(input.webhookPath ? { webhookPath: input.webhookPath } : {}),
|
||||
},
|
||||
},
|
||||
} as ClawdbotConfig;
|
||||
} as MoltbotConfig;
|
||||
}
|
||||
return {
|
||||
...next,
|
||||
@@ -268,7 +268,7 @@ export const bluebubblesPlugin: ChannelPlugin<ResolvedBlueBubblesAccount> = {
|
||||
},
|
||||
},
|
||||
},
|
||||
} as ClawdbotConfig;
|
||||
} as MoltbotConfig;
|
||||
},
|
||||
},
|
||||
pairing: {
|
||||
@@ -276,7 +276,7 @@ export const bluebubblesPlugin: ChannelPlugin<ResolvedBlueBubblesAccount> = {
|
||||
normalizeAllowEntry: (entry) => normalizeBlueBubblesHandle(entry.replace(/^bluebubbles:/i, "")),
|
||||
notifyApproval: async ({ cfg, id }) => {
|
||||
await sendMessageBlueBubbles(id, PAIRING_APPROVED_MESSAGE, {
|
||||
cfg: cfg as ClawdbotConfig,
|
||||
cfg: cfg as MoltbotConfig,
|
||||
});
|
||||
},
|
||||
},
|
||||
@@ -300,7 +300,7 @@ export const bluebubblesPlugin: ChannelPlugin<ResolvedBlueBubblesAccount> = {
|
||||
? resolveBlueBubblesMessageId(rawReplyToId, { requireKnownShortId: true })
|
||||
: "";
|
||||
const result = await sendMessageBlueBubbles(to, text, {
|
||||
cfg: cfg as ClawdbotConfig,
|
||||
cfg: cfg as MoltbotConfig,
|
||||
accountId: accountId ?? undefined,
|
||||
replyToMessageGuid: replyToMessageGuid || undefined,
|
||||
});
|
||||
@@ -317,7 +317,7 @@ export const bluebubblesPlugin: ChannelPlugin<ResolvedBlueBubblesAccount> = {
|
||||
};
|
||||
const resolvedCaption = caption ?? text;
|
||||
const result = await sendBlueBubblesMedia({
|
||||
cfg: cfg as ClawdbotConfig,
|
||||
cfg: cfg as MoltbotConfig,
|
||||
to,
|
||||
mediaUrl,
|
||||
mediaPath,
|
||||
@@ -388,7 +388,7 @@ export const bluebubblesPlugin: ChannelPlugin<ResolvedBlueBubblesAccount> = {
|
||||
ctx.log?.info(`[${account.accountId}] starting provider (webhook=${webhookPath})`);
|
||||
return monitorBlueBubblesProvider({
|
||||
account,
|
||||
config: ctx.cfg as ClawdbotConfig,
|
||||
config: ctx.cfg as MoltbotConfig,
|
||||
runtime: ctx.runtime,
|
||||
abortSignal: ctx.abortSignal,
|
||||
statusSink: (patch) => ctx.setStatus({ accountId: ctx.accountId, ...patch }),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import crypto from "node:crypto";
|
||||
import { resolveBlueBubblesAccount } from "./accounts.js";
|
||||
import type { ClawdbotConfig } from "clawdbot/plugin-sdk";
|
||||
import type { MoltbotConfig } from "clawdbot/plugin-sdk";
|
||||
import { blueBubblesFetchWithTimeout, buildBlueBubblesApiUrl } from "./types.js";
|
||||
|
||||
export type BlueBubblesChatOpts = {
|
||||
@@ -8,7 +8,7 @@ export type BlueBubblesChatOpts = {
|
||||
password?: string;
|
||||
accountId?: string;
|
||||
timeoutMs?: number;
|
||||
cfg?: ClawdbotConfig;
|
||||
cfg?: MoltbotConfig;
|
||||
};
|
||||
|
||||
function resolveAccount(params: BlueBubblesChatOpts) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
import { resolveChannelMediaMaxBytes, type ClawdbotConfig } from "clawdbot/plugin-sdk";
|
||||
import { resolveChannelMediaMaxBytes, type MoltbotConfig } from "clawdbot/plugin-sdk";
|
||||
|
||||
import { sendBlueBubblesAttachment } from "./attachments.js";
|
||||
import { resolveBlueBubblesMessageId } from "./monitor.js";
|
||||
@@ -49,7 +49,7 @@ function resolveFilenameFromSource(source?: string): string | undefined {
|
||||
}
|
||||
|
||||
export async function sendBlueBubblesMedia(params: {
|
||||
cfg: ClawdbotConfig;
|
||||
cfg: MoltbotConfig;
|
||||
to: string;
|
||||
mediaUrl?: string;
|
||||
mediaPath?: string;
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { IncomingMessage, ServerResponse } from "node:http";
|
||||
import { EventEmitter } from "node:events";
|
||||
|
||||
import { removeAckReactionAfterReply, shouldAckReaction } from "clawdbot/plugin-sdk";
|
||||
import type { ClawdbotConfig, PluginRuntime } from "clawdbot/plugin-sdk";
|
||||
import type { MoltbotConfig, PluginRuntime } from "clawdbot/plugin-sdk";
|
||||
import {
|
||||
handleBlueBubblesWebhookRequest,
|
||||
registerBlueBubblesWebhookTarget,
|
||||
@@ -178,7 +178,7 @@ function createMockRuntime(): PluginRuntime {
|
||||
})) as unknown as PluginRuntime["logging"]["getChildLogger"],
|
||||
},
|
||||
state: {
|
||||
resolveStateDir: vi.fn(() => "/tmp/clawdbot") as unknown as PluginRuntime["state"]["resolveStateDir"],
|
||||
resolveStateDir: vi.fn(() => "/tmp/moltbot") as unknown as PluginRuntime["state"]["resolveStateDir"],
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -264,7 +264,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
describe("webhook parsing + auth handling", () => {
|
||||
it("rejects non-POST requests", async () => {
|
||||
const account = createMockAccount();
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -287,7 +287,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
|
||||
it("accepts POST requests with valid JSON payload", async () => {
|
||||
const account = createMockAccount();
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -323,7 +323,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
|
||||
it("rejects requests with invalid JSON", async () => {
|
||||
const account = createMockAccount();
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -346,7 +346,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
|
||||
it("authenticates via password query parameter", async () => {
|
||||
const account = createMockAccount({ password: "secret-token" });
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -380,7 +380,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
|
||||
it("authenticates via x-password header", async () => {
|
||||
const account = createMockAccount({ password: "secret-token" });
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -418,7 +418,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
|
||||
it("rejects unauthorized requests with wrong password", async () => {
|
||||
const account = createMockAccount({ password: "secret-token" });
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -451,7 +451,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
|
||||
it("allows localhost requests without authentication", async () => {
|
||||
const account = createMockAccount({ password: "secret-token" });
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -497,7 +497,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
vi.mocked(resolveChatGuidForTarget).mockClear();
|
||||
|
||||
const account = createMockAccount({ groupPolicy: "open" });
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -545,7 +545,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
});
|
||||
|
||||
const account = createMockAccount({ groupPolicy: "open" });
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -591,7 +591,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
dmPolicy: "allowlist",
|
||||
allowFrom: ["+15551234567"],
|
||||
});
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -632,7 +632,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
dmPolicy: "allowlist",
|
||||
allowFrom: ["+15559999999"], // Different number
|
||||
});
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -673,7 +673,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
dmPolicy: "pairing",
|
||||
allowFrom: ["+15559999999"], // Different number than sender
|
||||
});
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -716,7 +716,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
dmPolicy: "pairing",
|
||||
allowFrom: ["+15559999999"], // Different number than sender
|
||||
});
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -757,7 +757,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
dmPolicy: "open",
|
||||
allowFrom: [],
|
||||
});
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -794,7 +794,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
const account = createMockAccount({
|
||||
dmPolicy: "disabled",
|
||||
});
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -833,7 +833,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
const account = createMockAccount({
|
||||
groupPolicy: "open",
|
||||
});
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -871,7 +871,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
const account = createMockAccount({
|
||||
groupPolicy: "disabled",
|
||||
});
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -910,7 +910,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
groupPolicy: "allowlist",
|
||||
dmPolicy: "open",
|
||||
});
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -949,7 +949,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
groupPolicy: "allowlist",
|
||||
groupAllowFrom: ["chat_guid:iMessage;+;chat123456"],
|
||||
});
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -990,7 +990,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
mockMatchesMentionPatterns.mockReturnValue(true);
|
||||
|
||||
const account = createMockAccount({ groupPolicy: "open" });
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -1031,7 +1031,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
mockMatchesMentionPatterns.mockReturnValue(false);
|
||||
|
||||
const account = createMockAccount({ groupPolicy: "open" });
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -1069,7 +1069,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
mockResolveRequireMention.mockReturnValue(false);
|
||||
|
||||
const account = createMockAccount({ groupPolicy: "open" });
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -1107,7 +1107,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
describe("group metadata", () => {
|
||||
it("includes group subject + members in ctx", async () => {
|
||||
const account = createMockAccount({ groupPolicy: "open" });
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -1153,7 +1153,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
describe("reply metadata", () => {
|
||||
it("surfaces reply fields in ctx when provided", async () => {
|
||||
const account = createMockAccount({ dmPolicy: "open" });
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -1201,7 +1201,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
|
||||
it("preserves part index prefixes in reply tags when short IDs are unavailable", async () => {
|
||||
const account = createMockAccount({ dmPolicy: "open" });
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -1246,7 +1246,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
|
||||
it("hydrates missing reply sender/body from the recent-message cache", async () => {
|
||||
const account = createMockAccount({ dmPolicy: "open", groupPolicy: "open" });
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -1316,7 +1316,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
|
||||
it("falls back to threadOriginatorGuid when reply metadata is absent", async () => {
|
||||
const account = createMockAccount({ dmPolicy: "open" });
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -1357,7 +1357,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
describe("tapback text parsing", () => {
|
||||
it("does not rewrite tapback-like text without metadata", async () => {
|
||||
const account = createMockAccount({ dmPolicy: "open" });
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -1397,7 +1397,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
|
||||
it("parses tapback text with custom emoji when metadata is present", async () => {
|
||||
const account = createMockAccount({ dmPolicy: "open" });
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -1442,7 +1442,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
vi.mocked(sendBlueBubblesReaction).mockClear();
|
||||
|
||||
const account = createMockAccount({ dmPolicy: "open" });
|
||||
const config: ClawdbotConfig = {
|
||||
const config: MoltbotConfig = {
|
||||
messages: {
|
||||
ackReaction: "❤️",
|
||||
ackReactionScope: "direct",
|
||||
@@ -1500,7 +1500,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
groupPolicy: "open",
|
||||
allowFrom: ["+15551234567"],
|
||||
});
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -1543,7 +1543,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
groupPolicy: "open",
|
||||
allowFrom: [], // No one authorized
|
||||
});
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -1586,7 +1586,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
const account = createMockAccount({
|
||||
sendReadReceipts: true,
|
||||
});
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -1627,7 +1627,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
const account = createMockAccount({
|
||||
sendReadReceipts: false,
|
||||
});
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -1666,7 +1666,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
vi.mocked(sendBlueBubblesTyping).mockClear();
|
||||
|
||||
const account = createMockAccount();
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -1714,7 +1714,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
vi.mocked(sendBlueBubblesTyping).mockClear();
|
||||
|
||||
const account = createMockAccount();
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -1763,7 +1763,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
vi.mocked(sendBlueBubblesTyping).mockClear();
|
||||
|
||||
const account = createMockAccount();
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -1813,7 +1813,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
});
|
||||
|
||||
const account = createMockAccount();
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -1859,7 +1859,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
mockEnqueueSystemEvent.mockClear();
|
||||
|
||||
const account = createMockAccount();
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -1899,7 +1899,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
mockEnqueueSystemEvent.mockClear();
|
||||
|
||||
const account = createMockAccount();
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -1939,7 +1939,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
mockEnqueueSystemEvent.mockClear();
|
||||
|
||||
const account = createMockAccount();
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -1976,7 +1976,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
mockEnqueueSystemEvent.mockClear();
|
||||
|
||||
const account = createMockAccount();
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -2017,7 +2017,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
describe("short message ID mapping", () => {
|
||||
it("assigns sequential short IDs to messages", async () => {
|
||||
const account = createMockAccount({ dmPolicy: "open" });
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -2057,7 +2057,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
|
||||
it("resolves short ID back to UUID", async () => {
|
||||
const account = createMockAccount({ dmPolicy: "open" });
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
@@ -2110,7 +2110,7 @@ describe("BlueBubbles webhook monitor", () => {
|
||||
describe("fromMe messages", () => {
|
||||
it("ignores messages from self (fromMe=true)", async () => {
|
||||
const account = createMockAccount();
|
||||
const config: ClawdbotConfig = {};
|
||||
const config: MoltbotConfig = {};
|
||||
const core = createMockRuntime();
|
||||
setBlueBubblesRuntime(core);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { IncomingMessage, ServerResponse } from "node:http";
|
||||
|
||||
import type { ClawdbotConfig } from "clawdbot/plugin-sdk";
|
||||
import type { MoltbotConfig } from "clawdbot/plugin-sdk";
|
||||
import {
|
||||
logAckFailure,
|
||||
logInboundDrop,
|
||||
@@ -26,7 +26,7 @@ export type BlueBubblesRuntimeEnv = {
|
||||
|
||||
export type BlueBubblesMonitorOptions = {
|
||||
account: ResolvedBlueBubblesAccount;
|
||||
config: ClawdbotConfig;
|
||||
config: MoltbotConfig;
|
||||
runtime: BlueBubblesRuntimeEnv;
|
||||
abortSignal: AbortSignal;
|
||||
statusSink?: (patch: { lastInboundAt?: number; lastOutboundAt?: number }) => void;
|
||||
@@ -243,7 +243,7 @@ function logGroupAllowlistHint(params: {
|
||||
|
||||
type WebhookTarget = {
|
||||
account: ResolvedBlueBubblesAccount;
|
||||
config: ClawdbotConfig;
|
||||
config: MoltbotConfig;
|
||||
runtime: BlueBubblesRuntimeEnv;
|
||||
core: BlueBubblesCoreRuntime;
|
||||
path: string;
|
||||
@@ -340,7 +340,7 @@ const targetDebouncers = new Map<
|
||||
>();
|
||||
|
||||
function resolveBlueBubblesDebounceMs(
|
||||
config: ClawdbotConfig,
|
||||
config: MoltbotConfig,
|
||||
core: BlueBubblesCoreRuntime,
|
||||
): number {
|
||||
const inbound = config.messages?.inbound;
|
||||
@@ -940,7 +940,7 @@ function maskSecret(value: string): string {
|
||||
}
|
||||
|
||||
function resolveBlueBubblesAckReaction(params: {
|
||||
cfg: ClawdbotConfig;
|
||||
cfg: MoltbotConfig;
|
||||
agentId: string;
|
||||
core: BlueBubblesCoreRuntime;
|
||||
runtime: BlueBubblesRuntimeEnv;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type {
|
||||
ChannelOnboardingAdapter,
|
||||
ChannelOnboardingDmPolicy,
|
||||
ClawdbotConfig,
|
||||
MoltbotConfig,
|
||||
DmPolicy,
|
||||
WizardPrompter,
|
||||
} from "clawdbot/plugin-sdk";
|
||||
@@ -22,7 +22,7 @@ import { parseBlueBubblesAllowTarget, normalizeBlueBubblesHandle } from "./targe
|
||||
|
||||
const channel = "bluebubbles" as const;
|
||||
|
||||
function setBlueBubblesDmPolicy(cfg: ClawdbotConfig, dmPolicy: DmPolicy): ClawdbotConfig {
|
||||
function setBlueBubblesDmPolicy(cfg: MoltbotConfig, dmPolicy: DmPolicy): MoltbotConfig {
|
||||
const allowFrom =
|
||||
dmPolicy === "open" ? addWildcardAllowFrom(cfg.channels?.bluebubbles?.allowFrom) : undefined;
|
||||
return {
|
||||
@@ -39,10 +39,10 @@ function setBlueBubblesDmPolicy(cfg: ClawdbotConfig, dmPolicy: DmPolicy): Clawdb
|
||||
}
|
||||
|
||||
function setBlueBubblesAllowFrom(
|
||||
cfg: ClawdbotConfig,
|
||||
cfg: MoltbotConfig,
|
||||
accountId: string,
|
||||
allowFrom: string[],
|
||||
): ClawdbotConfig {
|
||||
): MoltbotConfig {
|
||||
if (accountId === DEFAULT_ACCOUNT_ID) {
|
||||
return {
|
||||
...cfg,
|
||||
@@ -81,10 +81,10 @@ function parseBlueBubblesAllowFromInput(raw: string): string[] {
|
||||
}
|
||||
|
||||
async function promptBlueBubblesAllowFrom(params: {
|
||||
cfg: ClawdbotConfig;
|
||||
cfg: MoltbotConfig;
|
||||
prompter: WizardPrompter;
|
||||
accountId?: string;
|
||||
}): Promise<ClawdbotConfig> {
|
||||
}): Promise<MoltbotConfig> {
|
||||
const accountId =
|
||||
params.accountId && normalizeAccountId(params.accountId)
|
||||
? (normalizeAccountId(params.accountId) ?? DEFAULT_ACCOUNT_ID)
|
||||
@@ -318,7 +318,7 @@ export const blueBubblesOnboardingAdapter: ChannelOnboardingAdapter = {
|
||||
[
|
||||
"Configure the webhook URL in BlueBubbles Server:",
|
||||
"1. Open BlueBubbles Server → Settings → Webhooks",
|
||||
"2. Add your Clawdbot gateway URL + webhook path",
|
||||
"2. Add your Moltbot gateway URL + webhook path",
|
||||
" Example: https://your-gateway-host:3000/bluebubbles-webhook",
|
||||
"3. Enable the webhook and save",
|
||||
"",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { resolveBlueBubblesAccount } from "./accounts.js";
|
||||
import type { ClawdbotConfig } from "clawdbot/plugin-sdk";
|
||||
import type { MoltbotConfig } from "clawdbot/plugin-sdk";
|
||||
import { blueBubblesFetchWithTimeout, buildBlueBubblesApiUrl } from "./types.js";
|
||||
|
||||
export type BlueBubblesReactionOpts = {
|
||||
@@ -7,7 +7,7 @@ export type BlueBubblesReactionOpts = {
|
||||
password?: string;
|
||||
accountId?: string;
|
||||
timeoutMs?: number;
|
||||
cfg?: ClawdbotConfig;
|
||||
cfg?: MoltbotConfig;
|
||||
};
|
||||
|
||||
const REACTION_TYPES = new Set([
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
normalizeBlueBubblesHandle,
|
||||
parseBlueBubblesTarget,
|
||||
} from "./targets.js";
|
||||
import type { ClawdbotConfig } from "clawdbot/plugin-sdk";
|
||||
import type { MoltbotConfig } from "clawdbot/plugin-sdk";
|
||||
import {
|
||||
blueBubblesFetchWithTimeout,
|
||||
buildBlueBubblesApiUrl,
|
||||
@@ -18,7 +18,7 @@ export type BlueBubblesSendOpts = {
|
||||
password?: string;
|
||||
accountId?: string;
|
||||
timeoutMs?: number;
|
||||
cfg?: ClawdbotConfig;
|
||||
cfg?: MoltbotConfig;
|
||||
/** Message GUID to reply to (reply threading) */
|
||||
replyToMessageGuid?: string;
|
||||
/** Part index for reply (default: 0) */
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
"name": "@moltbot/copilot-proxy",
|
||||
"version": "2026.1.26",
|
||||
"type": "module",
|
||||
"description": "Clawdbot Copilot Proxy provider plugin",
|
||||
"clawdbot": {
|
||||
"description": "Moltbot Copilot Proxy provider plugin",
|
||||
"moltbot": {
|
||||
"extensions": [
|
||||
"./index.ts"
|
||||
]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ClawdbotPluginApi } from "clawdbot/plugin-sdk";
|
||||
import type { MoltbotPluginApi } from "clawdbot/plugin-sdk";
|
||||
import { emptyPluginConfigSchema } from "clawdbot/plugin-sdk";
|
||||
|
||||
import { createDiagnosticsOtelService } from "./src/service.js";
|
||||
@@ -8,7 +8,7 @@ const plugin = {
|
||||
name: "Diagnostics OpenTelemetry",
|
||||
description: "Export diagnostics events to OpenTelemetry",
|
||||
configSchema: emptyPluginConfigSchema(),
|
||||
register(api: ClawdbotPluginApi) {
|
||||
register(api: MoltbotPluginApi) {
|
||||
api.registerService(createDiagnosticsOtelService());
|
||||
},
|
||||
};
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
"name": "@moltbot/diagnostics-otel",
|
||||
"version": "2026.1.26",
|
||||
"type": "module",
|
||||
"description": "Clawdbot diagnostics OpenTelemetry exporter",
|
||||
"clawdbot": {
|
||||
"description": "Moltbot diagnostics OpenTelemetry exporter",
|
||||
"moltbot": {
|
||||
"extensions": [
|
||||
"./index.ts"
|
||||
]
|
||||
|
||||
@@ -191,20 +191,20 @@ describe("diagnostics-otel service", () => {
|
||||
attempt: 2,
|
||||
});
|
||||
|
||||
expect(telemetryState.counters.get("clawdbot.webhook.received")?.add).toHaveBeenCalled();
|
||||
expect(telemetryState.histograms.get("clawdbot.webhook.duration_ms")?.record).toHaveBeenCalled();
|
||||
expect(telemetryState.counters.get("clawdbot.message.queued")?.add).toHaveBeenCalled();
|
||||
expect(telemetryState.counters.get("clawdbot.message.processed")?.add).toHaveBeenCalled();
|
||||
expect(telemetryState.histograms.get("clawdbot.message.duration_ms")?.record).toHaveBeenCalled();
|
||||
expect(telemetryState.histograms.get("clawdbot.queue.wait_ms")?.record).toHaveBeenCalled();
|
||||
expect(telemetryState.counters.get("clawdbot.session.stuck")?.add).toHaveBeenCalled();
|
||||
expect(telemetryState.histograms.get("clawdbot.session.stuck_age_ms")?.record).toHaveBeenCalled();
|
||||
expect(telemetryState.counters.get("clawdbot.run.attempt")?.add).toHaveBeenCalled();
|
||||
expect(telemetryState.counters.get("moltbot.webhook.received")?.add).toHaveBeenCalled();
|
||||
expect(telemetryState.histograms.get("moltbot.webhook.duration_ms")?.record).toHaveBeenCalled();
|
||||
expect(telemetryState.counters.get("moltbot.message.queued")?.add).toHaveBeenCalled();
|
||||
expect(telemetryState.counters.get("moltbot.message.processed")?.add).toHaveBeenCalled();
|
||||
expect(telemetryState.histograms.get("moltbot.message.duration_ms")?.record).toHaveBeenCalled();
|
||||
expect(telemetryState.histograms.get("moltbot.queue.wait_ms")?.record).toHaveBeenCalled();
|
||||
expect(telemetryState.counters.get("moltbot.session.stuck")?.add).toHaveBeenCalled();
|
||||
expect(telemetryState.histograms.get("moltbot.session.stuck_age_ms")?.record).toHaveBeenCalled();
|
||||
expect(telemetryState.counters.get("moltbot.run.attempt")?.add).toHaveBeenCalled();
|
||||
|
||||
const spanNames = telemetryState.tracer.startSpan.mock.calls.map((call) => call[0]);
|
||||
expect(spanNames).toContain("clawdbot.webhook.processed");
|
||||
expect(spanNames).toContain("clawdbot.message.processed");
|
||||
expect(spanNames).toContain("clawdbot.session.stuck");
|
||||
expect(spanNames).toContain("moltbot.webhook.processed");
|
||||
expect(spanNames).toContain("moltbot.message.processed");
|
||||
expect(spanNames).toContain("moltbot.session.stuck");
|
||||
|
||||
expect(registerLogTransportMock).toHaveBeenCalledTimes(1);
|
||||
expect(registeredTransports).toHaveLength(1);
|
||||
|
||||
@@ -10,10 +10,10 @@ import { NodeSDK } from "@opentelemetry/sdk-node";
|
||||
import { ParentBasedSampler, TraceIdRatioBasedSampler } from "@opentelemetry/sdk-trace-base";
|
||||
import { SemanticResourceAttributes } from "@opentelemetry/semantic-conventions";
|
||||
|
||||
import type { ClawdbotPluginService, DiagnosticEventPayload } from "clawdbot/plugin-sdk";
|
||||
import type { MoltbotPluginService, DiagnosticEventPayload } from "clawdbot/plugin-sdk";
|
||||
import { onDiagnosticEvent, registerLogTransport } from "clawdbot/plugin-sdk";
|
||||
|
||||
const DEFAULT_SERVICE_NAME = "clawdbot";
|
||||
const DEFAULT_SERVICE_NAME = "moltbot";
|
||||
|
||||
function normalizeEndpoint(endpoint?: string): string | undefined {
|
||||
const trimmed = endpoint?.trim();
|
||||
@@ -32,7 +32,7 @@ function resolveSampleRate(value: number | undefined): number | undefined {
|
||||
return value;
|
||||
}
|
||||
|
||||
export function createDiagnosticsOtelService(): ClawdbotPluginService {
|
||||
export function createDiagnosticsOtelService(): MoltbotPluginService {
|
||||
let sdk: NodeSDK | null = null;
|
||||
let logProvider: LoggerProvider | null = null;
|
||||
let stopLogTransport: (() => void) | null = null;
|
||||
@@ -118,78 +118,78 @@ export function createDiagnosticsOtelService(): ClawdbotPluginService {
|
||||
FATAL: 21 as SeverityNumber,
|
||||
};
|
||||
|
||||
const meter = metrics.getMeter("clawdbot");
|
||||
const tracer = trace.getTracer("clawdbot");
|
||||
const meter = metrics.getMeter("moltbot");
|
||||
const tracer = trace.getTracer("moltbot");
|
||||
|
||||
const tokensCounter = meter.createCounter("clawdbot.tokens", {
|
||||
const tokensCounter = meter.createCounter("moltbot.tokens", {
|
||||
unit: "1",
|
||||
description: "Token usage by type",
|
||||
});
|
||||
const costCounter = meter.createCounter("clawdbot.cost.usd", {
|
||||
const costCounter = meter.createCounter("moltbot.cost.usd", {
|
||||
unit: "1",
|
||||
description: "Estimated model cost (USD)",
|
||||
});
|
||||
const durationHistogram = meter.createHistogram("clawdbot.run.duration_ms", {
|
||||
const durationHistogram = meter.createHistogram("moltbot.run.duration_ms", {
|
||||
unit: "ms",
|
||||
description: "Agent run duration",
|
||||
});
|
||||
const contextHistogram = meter.createHistogram("clawdbot.context.tokens", {
|
||||
const contextHistogram = meter.createHistogram("moltbot.context.tokens", {
|
||||
unit: "1",
|
||||
description: "Context window size and usage",
|
||||
});
|
||||
const webhookReceivedCounter = meter.createCounter("clawdbot.webhook.received", {
|
||||
const webhookReceivedCounter = meter.createCounter("moltbot.webhook.received", {
|
||||
unit: "1",
|
||||
description: "Webhook requests received",
|
||||
});
|
||||
const webhookErrorCounter = meter.createCounter("clawdbot.webhook.error", {
|
||||
const webhookErrorCounter = meter.createCounter("moltbot.webhook.error", {
|
||||
unit: "1",
|
||||
description: "Webhook processing errors",
|
||||
});
|
||||
const webhookDurationHistogram = meter.createHistogram("clawdbot.webhook.duration_ms", {
|
||||
const webhookDurationHistogram = meter.createHistogram("moltbot.webhook.duration_ms", {
|
||||
unit: "ms",
|
||||
description: "Webhook processing duration",
|
||||
});
|
||||
const messageQueuedCounter = meter.createCounter("clawdbot.message.queued", {
|
||||
const messageQueuedCounter = meter.createCounter("moltbot.message.queued", {
|
||||
unit: "1",
|
||||
description: "Messages queued for processing",
|
||||
});
|
||||
const messageProcessedCounter = meter.createCounter("clawdbot.message.processed", {
|
||||
const messageProcessedCounter = meter.createCounter("moltbot.message.processed", {
|
||||
unit: "1",
|
||||
description: "Messages processed by outcome",
|
||||
});
|
||||
const messageDurationHistogram = meter.createHistogram("clawdbot.message.duration_ms", {
|
||||
const messageDurationHistogram = meter.createHistogram("moltbot.message.duration_ms", {
|
||||
unit: "ms",
|
||||
description: "Message processing duration",
|
||||
});
|
||||
const queueDepthHistogram = meter.createHistogram("clawdbot.queue.depth", {
|
||||
const queueDepthHistogram = meter.createHistogram("moltbot.queue.depth", {
|
||||
unit: "1",
|
||||
description: "Queue depth on enqueue/dequeue",
|
||||
});
|
||||
const queueWaitHistogram = meter.createHistogram("clawdbot.queue.wait_ms", {
|
||||
const queueWaitHistogram = meter.createHistogram("moltbot.queue.wait_ms", {
|
||||
unit: "ms",
|
||||
description: "Queue wait time before execution",
|
||||
});
|
||||
const laneEnqueueCounter = meter.createCounter("clawdbot.queue.lane.enqueue", {
|
||||
const laneEnqueueCounter = meter.createCounter("moltbot.queue.lane.enqueue", {
|
||||
unit: "1",
|
||||
description: "Command queue lane enqueue events",
|
||||
});
|
||||
const laneDequeueCounter = meter.createCounter("clawdbot.queue.lane.dequeue", {
|
||||
const laneDequeueCounter = meter.createCounter("moltbot.queue.lane.dequeue", {
|
||||
unit: "1",
|
||||
description: "Command queue lane dequeue events",
|
||||
});
|
||||
const sessionStateCounter = meter.createCounter("clawdbot.session.state", {
|
||||
const sessionStateCounter = meter.createCounter("moltbot.session.state", {
|
||||
unit: "1",
|
||||
description: "Session state transitions",
|
||||
});
|
||||
const sessionStuckCounter = meter.createCounter("clawdbot.session.stuck", {
|
||||
const sessionStuckCounter = meter.createCounter("moltbot.session.stuck", {
|
||||
unit: "1",
|
||||
description: "Sessions stuck in processing",
|
||||
});
|
||||
const sessionStuckAgeHistogram = meter.createHistogram("clawdbot.session.stuck_age_ms", {
|
||||
const sessionStuckAgeHistogram = meter.createHistogram("moltbot.session.stuck_age_ms", {
|
||||
unit: "ms",
|
||||
description: "Age of stuck sessions",
|
||||
});
|
||||
const runAttemptCounter = meter.createCounter("clawdbot.run.attempt", {
|
||||
const runAttemptCounter = meter.createCounter("moltbot.run.attempt", {
|
||||
unit: "1",
|
||||
description: "Run attempts",
|
||||
});
|
||||
@@ -207,7 +207,7 @@ export function createDiagnosticsOtelService(): ClawdbotPluginService {
|
||||
: {}),
|
||||
}),
|
||||
);
|
||||
const otelLogger = logProvider.getLogger("clawdbot");
|
||||
const otelLogger = logProvider.getLogger("moltbot");
|
||||
|
||||
stopLogTransport = registerLogTransport((logObj) => {
|
||||
const safeStringify = (value: unknown) => {
|
||||
@@ -265,29 +265,29 @@ export function createDiagnosticsOtelService(): ClawdbotPluginService {
|
||||
}
|
||||
|
||||
const attributes: Record<string, string | number | boolean> = {
|
||||
"clawdbot.log.level": logLevelName,
|
||||
"moltbot.log.level": logLevelName,
|
||||
};
|
||||
if (meta?.name) attributes["clawdbot.logger"] = meta.name;
|
||||
if (meta?.name) attributes["moltbot.logger"] = meta.name;
|
||||
if (meta?.parentNames?.length) {
|
||||
attributes["clawdbot.logger.parents"] = meta.parentNames.join(".");
|
||||
attributes["moltbot.logger.parents"] = meta.parentNames.join(".");
|
||||
}
|
||||
if (bindings) {
|
||||
for (const [key, value] of Object.entries(bindings)) {
|
||||
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
||||
attributes[`clawdbot.${key}`] = value;
|
||||
attributes[`moltbot.${key}`] = value;
|
||||
} else if (value != null) {
|
||||
attributes[`clawdbot.${key}`] = safeStringify(value);
|
||||
attributes[`moltbot.${key}`] = safeStringify(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (numericArgs.length > 0) {
|
||||
attributes["clawdbot.log.args"] = safeStringify(numericArgs);
|
||||
attributes["moltbot.log.args"] = safeStringify(numericArgs);
|
||||
}
|
||||
if (meta?.path?.filePath) attributes["code.filepath"] = meta.path.filePath;
|
||||
if (meta?.path?.fileLine) attributes["code.lineno"] = Number(meta.path.fileLine);
|
||||
if (meta?.path?.method) attributes["code.function"] = meta.path.method;
|
||||
if (meta?.path?.filePathWithLine) {
|
||||
attributes["clawdbot.code.location"] = meta.path.filePathWithLine;
|
||||
attributes["moltbot.code.location"] = meta.path.filePathWithLine;
|
||||
}
|
||||
|
||||
otelLogger.emit({
|
||||
@@ -316,48 +316,48 @@ export function createDiagnosticsOtelService(): ClawdbotPluginService {
|
||||
|
||||
const recordModelUsage = (evt: Extract<DiagnosticEventPayload, { type: "model.usage" }>) => {
|
||||
const attrs = {
|
||||
"clawdbot.channel": evt.channel ?? "unknown",
|
||||
"clawdbot.provider": evt.provider ?? "unknown",
|
||||
"clawdbot.model": evt.model ?? "unknown",
|
||||
"moltbot.channel": evt.channel ?? "unknown",
|
||||
"moltbot.provider": evt.provider ?? "unknown",
|
||||
"moltbot.model": evt.model ?? "unknown",
|
||||
};
|
||||
|
||||
const usage = evt.usage;
|
||||
if (usage.input) tokensCounter.add(usage.input, { ...attrs, "clawdbot.token": "input" });
|
||||
if (usage.output) tokensCounter.add(usage.output, { ...attrs, "clawdbot.token": "output" });
|
||||
if (usage.input) tokensCounter.add(usage.input, { ...attrs, "moltbot.token": "input" });
|
||||
if (usage.output) tokensCounter.add(usage.output, { ...attrs, "moltbot.token": "output" });
|
||||
if (usage.cacheRead)
|
||||
tokensCounter.add(usage.cacheRead, { ...attrs, "clawdbot.token": "cache_read" });
|
||||
tokensCounter.add(usage.cacheRead, { ...attrs, "moltbot.token": "cache_read" });
|
||||
if (usage.cacheWrite)
|
||||
tokensCounter.add(usage.cacheWrite, { ...attrs, "clawdbot.token": "cache_write" });
|
||||
tokensCounter.add(usage.cacheWrite, { ...attrs, "moltbot.token": "cache_write" });
|
||||
if (usage.promptTokens)
|
||||
tokensCounter.add(usage.promptTokens, { ...attrs, "clawdbot.token": "prompt" });
|
||||
if (usage.total) tokensCounter.add(usage.total, { ...attrs, "clawdbot.token": "total" });
|
||||
tokensCounter.add(usage.promptTokens, { ...attrs, "moltbot.token": "prompt" });
|
||||
if (usage.total) tokensCounter.add(usage.total, { ...attrs, "moltbot.token": "total" });
|
||||
|
||||
if (evt.costUsd) costCounter.add(evt.costUsd, attrs);
|
||||
if (evt.durationMs) durationHistogram.record(evt.durationMs, attrs);
|
||||
if (evt.context?.limit)
|
||||
contextHistogram.record(evt.context.limit, {
|
||||
...attrs,
|
||||
"clawdbot.context": "limit",
|
||||
"moltbot.context": "limit",
|
||||
});
|
||||
if (evt.context?.used)
|
||||
contextHistogram.record(evt.context.used, {
|
||||
...attrs,
|
||||
"clawdbot.context": "used",
|
||||
"moltbot.context": "used",
|
||||
});
|
||||
|
||||
if (!tracesEnabled) return;
|
||||
const spanAttrs: Record<string, string | number> = {
|
||||
...attrs,
|
||||
"clawdbot.sessionKey": evt.sessionKey ?? "",
|
||||
"clawdbot.sessionId": evt.sessionId ?? "",
|
||||
"clawdbot.tokens.input": usage.input ?? 0,
|
||||
"clawdbot.tokens.output": usage.output ?? 0,
|
||||
"clawdbot.tokens.cache_read": usage.cacheRead ?? 0,
|
||||
"clawdbot.tokens.cache_write": usage.cacheWrite ?? 0,
|
||||
"clawdbot.tokens.total": usage.total ?? 0,
|
||||
"moltbot.sessionKey": evt.sessionKey ?? "",
|
||||
"moltbot.sessionId": evt.sessionId ?? "",
|
||||
"moltbot.tokens.input": usage.input ?? 0,
|
||||
"moltbot.tokens.output": usage.output ?? 0,
|
||||
"moltbot.tokens.cache_read": usage.cacheRead ?? 0,
|
||||
"moltbot.tokens.cache_write": usage.cacheWrite ?? 0,
|
||||
"moltbot.tokens.total": usage.total ?? 0,
|
||||
};
|
||||
|
||||
const span = spanWithDuration("clawdbot.model.usage", spanAttrs, evt.durationMs);
|
||||
const span = spanWithDuration("moltbot.model.usage", spanAttrs, evt.durationMs);
|
||||
span.end();
|
||||
};
|
||||
|
||||
@@ -365,8 +365,8 @@ export function createDiagnosticsOtelService(): ClawdbotPluginService {
|
||||
evt: Extract<DiagnosticEventPayload, { type: "webhook.received" }>,
|
||||
) => {
|
||||
const attrs = {
|
||||
"clawdbot.channel": evt.channel ?? "unknown",
|
||||
"clawdbot.webhook": evt.updateType ?? "unknown",
|
||||
"moltbot.channel": evt.channel ?? "unknown",
|
||||
"moltbot.webhook": evt.updateType ?? "unknown",
|
||||
};
|
||||
webhookReceivedCounter.add(1, attrs);
|
||||
};
|
||||
@@ -375,16 +375,16 @@ export function createDiagnosticsOtelService(): ClawdbotPluginService {
|
||||
evt: Extract<DiagnosticEventPayload, { type: "webhook.processed" }>,
|
||||
) => {
|
||||
const attrs = {
|
||||
"clawdbot.channel": evt.channel ?? "unknown",
|
||||
"clawdbot.webhook": evt.updateType ?? "unknown",
|
||||
"moltbot.channel": evt.channel ?? "unknown",
|
||||
"moltbot.webhook": evt.updateType ?? "unknown",
|
||||
};
|
||||
if (typeof evt.durationMs === "number") {
|
||||
webhookDurationHistogram.record(evt.durationMs, attrs);
|
||||
}
|
||||
if (!tracesEnabled) return;
|
||||
const spanAttrs: Record<string, string | number> = { ...attrs };
|
||||
if (evt.chatId !== undefined) spanAttrs["clawdbot.chatId"] = String(evt.chatId);
|
||||
const span = spanWithDuration("clawdbot.webhook.processed", spanAttrs, evt.durationMs);
|
||||
if (evt.chatId !== undefined) spanAttrs["moltbot.chatId"] = String(evt.chatId);
|
||||
const span = spanWithDuration("moltbot.webhook.processed", spanAttrs, evt.durationMs);
|
||||
span.end();
|
||||
};
|
||||
|
||||
@@ -392,17 +392,17 @@ export function createDiagnosticsOtelService(): ClawdbotPluginService {
|
||||
evt: Extract<DiagnosticEventPayload, { type: "webhook.error" }>,
|
||||
) => {
|
||||
const attrs = {
|
||||
"clawdbot.channel": evt.channel ?? "unknown",
|
||||
"clawdbot.webhook": evt.updateType ?? "unknown",
|
||||
"moltbot.channel": evt.channel ?? "unknown",
|
||||
"moltbot.webhook": evt.updateType ?? "unknown",
|
||||
};
|
||||
webhookErrorCounter.add(1, attrs);
|
||||
if (!tracesEnabled) return;
|
||||
const spanAttrs: Record<string, string | number> = {
|
||||
...attrs,
|
||||
"clawdbot.error": evt.error,
|
||||
"moltbot.error": evt.error,
|
||||
};
|
||||
if (evt.chatId !== undefined) spanAttrs["clawdbot.chatId"] = String(evt.chatId);
|
||||
const span = tracer.startSpan("clawdbot.webhook.error", {
|
||||
if (evt.chatId !== undefined) spanAttrs["moltbot.chatId"] = String(evt.chatId);
|
||||
const span = tracer.startSpan("moltbot.webhook.error", {
|
||||
attributes: spanAttrs,
|
||||
});
|
||||
span.setStatus({ code: SpanStatusCode.ERROR, message: evt.error });
|
||||
@@ -413,8 +413,8 @@ export function createDiagnosticsOtelService(): ClawdbotPluginService {
|
||||
evt: Extract<DiagnosticEventPayload, { type: "message.queued" }>,
|
||||
) => {
|
||||
const attrs = {
|
||||
"clawdbot.channel": evt.channel ?? "unknown",
|
||||
"clawdbot.source": evt.source ?? "unknown",
|
||||
"moltbot.channel": evt.channel ?? "unknown",
|
||||
"moltbot.source": evt.source ?? "unknown",
|
||||
};
|
||||
messageQueuedCounter.add(1, attrs);
|
||||
if (typeof evt.queueDepth === "number") {
|
||||
@@ -426,8 +426,8 @@ export function createDiagnosticsOtelService(): ClawdbotPluginService {
|
||||
evt: Extract<DiagnosticEventPayload, { type: "message.processed" }>,
|
||||
) => {
|
||||
const attrs = {
|
||||
"clawdbot.channel": evt.channel ?? "unknown",
|
||||
"clawdbot.outcome": evt.outcome ?? "unknown",
|
||||
"moltbot.channel": evt.channel ?? "unknown",
|
||||
"moltbot.outcome": evt.outcome ?? "unknown",
|
||||
};
|
||||
messageProcessedCounter.add(1, attrs);
|
||||
if (typeof evt.durationMs === "number") {
|
||||
@@ -435,12 +435,12 @@ export function createDiagnosticsOtelService(): ClawdbotPluginService {
|
||||
}
|
||||
if (!tracesEnabled) return;
|
||||
const spanAttrs: Record<string, string | number> = { ...attrs };
|
||||
if (evt.sessionKey) spanAttrs["clawdbot.sessionKey"] = evt.sessionKey;
|
||||
if (evt.sessionId) spanAttrs["clawdbot.sessionId"] = evt.sessionId;
|
||||
if (evt.chatId !== undefined) spanAttrs["clawdbot.chatId"] = String(evt.chatId);
|
||||
if (evt.messageId !== undefined) spanAttrs["clawdbot.messageId"] = String(evt.messageId);
|
||||
if (evt.reason) spanAttrs["clawdbot.reason"] = evt.reason;
|
||||
const span = spanWithDuration("clawdbot.message.processed", spanAttrs, evt.durationMs);
|
||||
if (evt.sessionKey) spanAttrs["moltbot.sessionKey"] = evt.sessionKey;
|
||||
if (evt.sessionId) spanAttrs["moltbot.sessionId"] = evt.sessionId;
|
||||
if (evt.chatId !== undefined) spanAttrs["moltbot.chatId"] = String(evt.chatId);
|
||||
if (evt.messageId !== undefined) spanAttrs["moltbot.messageId"] = String(evt.messageId);
|
||||
if (evt.reason) spanAttrs["moltbot.reason"] = evt.reason;
|
||||
const span = spanWithDuration("moltbot.message.processed", spanAttrs, evt.durationMs);
|
||||
if (evt.outcome === "error") {
|
||||
span.setStatus({ code: SpanStatusCode.ERROR, message: evt.error });
|
||||
}
|
||||
@@ -450,7 +450,7 @@ export function createDiagnosticsOtelService(): ClawdbotPluginService {
|
||||
const recordLaneEnqueue = (
|
||||
evt: Extract<DiagnosticEventPayload, { type: "queue.lane.enqueue" }>,
|
||||
) => {
|
||||
const attrs = { "clawdbot.lane": evt.lane };
|
||||
const attrs = { "moltbot.lane": evt.lane };
|
||||
laneEnqueueCounter.add(1, attrs);
|
||||
queueDepthHistogram.record(evt.queueSize, attrs);
|
||||
};
|
||||
@@ -458,7 +458,7 @@ export function createDiagnosticsOtelService(): ClawdbotPluginService {
|
||||
const recordLaneDequeue = (
|
||||
evt: Extract<DiagnosticEventPayload, { type: "queue.lane.dequeue" }>,
|
||||
) => {
|
||||
const attrs = { "clawdbot.lane": evt.lane };
|
||||
const attrs = { "moltbot.lane": evt.lane };
|
||||
laneDequeueCounter.add(1, attrs);
|
||||
queueDepthHistogram.record(evt.queueSize, attrs);
|
||||
if (typeof evt.waitMs === "number") {
|
||||
@@ -469,38 +469,38 @@ export function createDiagnosticsOtelService(): ClawdbotPluginService {
|
||||
const recordSessionState = (
|
||||
evt: Extract<DiagnosticEventPayload, { type: "session.state" }>,
|
||||
) => {
|
||||
const attrs: Record<string, string> = { "clawdbot.state": evt.state };
|
||||
if (evt.reason) attrs["clawdbot.reason"] = evt.reason;
|
||||
const attrs: Record<string, string> = { "moltbot.state": evt.state };
|
||||
if (evt.reason) attrs["moltbot.reason"] = evt.reason;
|
||||
sessionStateCounter.add(1, attrs);
|
||||
};
|
||||
|
||||
const recordSessionStuck = (
|
||||
evt: Extract<DiagnosticEventPayload, { type: "session.stuck" }>,
|
||||
) => {
|
||||
const attrs: Record<string, string> = { "clawdbot.state": evt.state };
|
||||
const attrs: Record<string, string> = { "moltbot.state": evt.state };
|
||||
sessionStuckCounter.add(1, attrs);
|
||||
if (typeof evt.ageMs === "number") {
|
||||
sessionStuckAgeHistogram.record(evt.ageMs, attrs);
|
||||
}
|
||||
if (!tracesEnabled) return;
|
||||
const spanAttrs: Record<string, string | number> = { ...attrs };
|
||||
if (evt.sessionKey) spanAttrs["clawdbot.sessionKey"] = evt.sessionKey;
|
||||
if (evt.sessionId) spanAttrs["clawdbot.sessionId"] = evt.sessionId;
|
||||
spanAttrs["clawdbot.queueDepth"] = evt.queueDepth ?? 0;
|
||||
spanAttrs["clawdbot.ageMs"] = evt.ageMs;
|
||||
const span = tracer.startSpan("clawdbot.session.stuck", { attributes: spanAttrs });
|
||||
if (evt.sessionKey) spanAttrs["moltbot.sessionKey"] = evt.sessionKey;
|
||||
if (evt.sessionId) spanAttrs["moltbot.sessionId"] = evt.sessionId;
|
||||
spanAttrs["moltbot.queueDepth"] = evt.queueDepth ?? 0;
|
||||
spanAttrs["moltbot.ageMs"] = evt.ageMs;
|
||||
const span = tracer.startSpan("moltbot.session.stuck", { attributes: spanAttrs });
|
||||
span.setStatus({ code: SpanStatusCode.ERROR, message: "session stuck" });
|
||||
span.end();
|
||||
};
|
||||
|
||||
const recordRunAttempt = (evt: Extract<DiagnosticEventPayload, { type: "run.attempt" }>) => {
|
||||
runAttemptCounter.add(1, { "clawdbot.attempt": evt.attempt });
|
||||
runAttemptCounter.add(1, { "moltbot.attempt": evt.attempt });
|
||||
};
|
||||
|
||||
const recordHeartbeat = (
|
||||
evt: Extract<DiagnosticEventPayload, { type: "diagnostic.heartbeat" }>,
|
||||
) => {
|
||||
queueDepthHistogram.record(evt.queued, { "clawdbot.channel": "heartbeat" });
|
||||
queueDepthHistogram.record(evt.queued, { "moltbot.channel": "heartbeat" });
|
||||
};
|
||||
|
||||
unsubscribe = onDiagnosticEvent((evt: DiagnosticEventPayload) => {
|
||||
@@ -562,5 +562,5 @@ export function createDiagnosticsOtelService(): ClawdbotPluginService {
|
||||
sdk = null;
|
||||
}
|
||||
},
|
||||
} satisfies ClawdbotPluginService;
|
||||
} satisfies MoltbotPluginService;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ClawdbotPluginApi } from "clawdbot/plugin-sdk";
|
||||
import type { MoltbotPluginApi } from "clawdbot/plugin-sdk";
|
||||
import { emptyPluginConfigSchema } from "clawdbot/plugin-sdk";
|
||||
|
||||
import { discordPlugin } from "./src/channel.js";
|
||||
@@ -9,7 +9,7 @@ const plugin = {
|
||||
name: "Discord",
|
||||
description: "Discord channel plugin",
|
||||
configSchema: emptyPluginConfigSchema(),
|
||||
register(api: ClawdbotPluginApi) {
|
||||
register(api: MoltbotPluginApi) {
|
||||
setDiscordRuntime(api.runtime);
|
||||
api.registerChannel({ plugin: discordPlugin });
|
||||
},
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
"name": "@moltbot/discord",
|
||||
"version": "2026.1.26",
|
||||
"type": "module",
|
||||
"description": "Clawdbot Discord channel plugin",
|
||||
"clawdbot": {
|
||||
"description": "Moltbot Discord channel plugin",
|
||||
"moltbot": {
|
||||
"extensions": [
|
||||
"./index.ts"
|
||||
]
|
||||
|
||||
@@ -32,7 +32,7 @@ const RESPONSE_PAGE = `<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Clawdbot Antigravity OAuth</title>
|
||||
<title>Moltbot Antigravity OAuth</title>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
"name": "@moltbot/google-antigravity-auth",
|
||||
"version": "2026.1.26",
|
||||
"type": "module",
|
||||
"description": "Clawdbot Google Antigravity OAuth provider plugin",
|
||||
"clawdbot": {
|
||||
"description": "Moltbot Google Antigravity OAuth provider plugin",
|
||||
"moltbot": {
|
||||
"extensions": [
|
||||
"./index.ts"
|
||||
]
|
||||
|
||||
@@ -262,7 +262,7 @@ async function waitForLocalCallback(params: {
|
||||
res.end(
|
||||
"<!doctype html><html><head><meta charset='utf-8'/></head>" +
|
||||
"<body><h2>Gemini CLI OAuth complete</h2>" +
|
||||
"<p>You can close this window and return to Clawdbot.</p></body></html>",
|
||||
"<p>You can close this window and return to Moltbot.</p></body></html>",
|
||||
);
|
||||
|
||||
finish(undefined, { code, state });
|
||||
@@ -367,7 +367,7 @@ async function discoverProject(accessToken: string): Promise<string> {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
"Content-Type": "application/json",
|
||||
"User-Agent": "google-api-nodejs-client/9.15.1",
|
||||
"X-Goog-Api-Client": "gl-node/clawdbot",
|
||||
"X-Goog-Api-Client": "gl-node/moltbot",
|
||||
};
|
||||
|
||||
const loadBody = {
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
"name": "@moltbot/google-gemini-cli-auth",
|
||||
"version": "2026.1.26",
|
||||
"type": "module",
|
||||
"description": "Clawdbot Gemini CLI OAuth provider plugin",
|
||||
"clawdbot": {
|
||||
"description": "Moltbot Gemini CLI OAuth provider plugin",
|
||||
"moltbot": {
|
||||
"extensions": [
|
||||
"./index.ts"
|
||||
]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ClawdbotPluginApi } from "clawdbot/plugin-sdk";
|
||||
import type { MoltbotPluginApi } from "clawdbot/plugin-sdk";
|
||||
import { emptyPluginConfigSchema } from "clawdbot/plugin-sdk";
|
||||
|
||||
import { googlechatDock, googlechatPlugin } from "./src/channel.js";
|
||||
@@ -8,9 +8,9 @@ import { setGoogleChatRuntime } from "./src/runtime.js";
|
||||
const plugin = {
|
||||
id: "googlechat",
|
||||
name: "Google Chat",
|
||||
description: "Clawdbot Google Chat channel plugin",
|
||||
description: "Moltbot Google Chat channel plugin",
|
||||
configSchema: emptyPluginConfigSchema(),
|
||||
register(api: ClawdbotPluginApi) {
|
||||
register(api: MoltbotPluginApi) {
|
||||
setGoogleChatRuntime(api.runtime);
|
||||
api.registerChannel({ plugin: googlechatPlugin, dock: googlechatDock });
|
||||
api.registerHttpHandler(handleGoogleChatWebhookRequest);
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
"name": "@moltbot/googlechat",
|
||||
"version": "2026.1.26",
|
||||
"type": "module",
|
||||
"description": "Clawdbot Google Chat channel plugin",
|
||||
"clawdbot": {
|
||||
"description": "Moltbot Google Chat channel plugin",
|
||||
"moltbot": {
|
||||
"extensions": [
|
||||
"./index.ts"
|
||||
],
|
||||
@@ -31,9 +31,9 @@
|
||||
"google-auth-library": "^10.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"clawdbot": "workspace:*"
|
||||
"moltbot": "workspace:*"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"clawdbot": ">=2026.1.26"
|
||||
"moltbot": ">=2026.1.26"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ClawdbotConfig } from "clawdbot/plugin-sdk";
|
||||
import type { MoltbotConfig } from "clawdbot/plugin-sdk";
|
||||
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "clawdbot/plugin-sdk";
|
||||
|
||||
import type { GoogleChatAccountConfig, GoogleChatConfig } from "./types.config.js";
|
||||
@@ -18,19 +18,19 @@ export type ResolvedGoogleChatAccount = {
|
||||
const ENV_SERVICE_ACCOUNT = "GOOGLE_CHAT_SERVICE_ACCOUNT";
|
||||
const ENV_SERVICE_ACCOUNT_FILE = "GOOGLE_CHAT_SERVICE_ACCOUNT_FILE";
|
||||
|
||||
function listConfiguredAccountIds(cfg: ClawdbotConfig): string[] {
|
||||
function listConfiguredAccountIds(cfg: MoltbotConfig): string[] {
|
||||
const accounts = (cfg.channels?.["googlechat"] as GoogleChatConfig | undefined)?.accounts;
|
||||
if (!accounts || typeof accounts !== "object") return [];
|
||||
return Object.keys(accounts).filter(Boolean);
|
||||
}
|
||||
|
||||
export function listGoogleChatAccountIds(cfg: ClawdbotConfig): string[] {
|
||||
export function listGoogleChatAccountIds(cfg: MoltbotConfig): string[] {
|
||||
const ids = listConfiguredAccountIds(cfg);
|
||||
if (ids.length === 0) return [DEFAULT_ACCOUNT_ID];
|
||||
return ids.sort((a, b) => a.localeCompare(b));
|
||||
}
|
||||
|
||||
export function resolveDefaultGoogleChatAccountId(cfg: ClawdbotConfig): string {
|
||||
export function resolveDefaultGoogleChatAccountId(cfg: MoltbotConfig): string {
|
||||
const channel = cfg.channels?.["googlechat"] as GoogleChatConfig | undefined;
|
||||
if (channel?.defaultAccount?.trim()) return channel.defaultAccount.trim();
|
||||
const ids = listGoogleChatAccountIds(cfg);
|
||||
@@ -39,7 +39,7 @@ export function resolveDefaultGoogleChatAccountId(cfg: ClawdbotConfig): string {
|
||||
}
|
||||
|
||||
function resolveAccountConfig(
|
||||
cfg: ClawdbotConfig,
|
||||
cfg: MoltbotConfig,
|
||||
accountId: string,
|
||||
): GoogleChatAccountConfig | undefined {
|
||||
const accounts = (cfg.channels?.["googlechat"] as GoogleChatConfig | undefined)?.accounts;
|
||||
@@ -48,7 +48,7 @@ function resolveAccountConfig(
|
||||
}
|
||||
|
||||
function mergeGoogleChatAccountConfig(
|
||||
cfg: ClawdbotConfig,
|
||||
cfg: MoltbotConfig,
|
||||
accountId: string,
|
||||
): GoogleChatAccountConfig {
|
||||
const raw = (cfg.channels?.["googlechat"] ?? {}) as GoogleChatConfig;
|
||||
@@ -104,7 +104,7 @@ function resolveCredentialsFromConfig(params: {
|
||||
}
|
||||
|
||||
export function resolveGoogleChatAccount(params: {
|
||||
cfg: ClawdbotConfig;
|
||||
cfg: MoltbotConfig;
|
||||
accountId?: string | null;
|
||||
}): ResolvedGoogleChatAccount {
|
||||
const accountId = normalizeAccountId(params.accountId);
|
||||
@@ -126,7 +126,7 @@ export function resolveGoogleChatAccount(params: {
|
||||
};
|
||||
}
|
||||
|
||||
export function listEnabledGoogleChatAccounts(cfg: ClawdbotConfig): ResolvedGoogleChatAccount[] {
|
||||
export function listEnabledGoogleChatAccounts(cfg: MoltbotConfig): ResolvedGoogleChatAccount[] {
|
||||
return listGoogleChatAccountIds(cfg)
|
||||
.map((accountId) => resolveGoogleChatAccount({ cfg, accountId }))
|
||||
.filter((account) => account.enabled);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type {
|
||||
ChannelMessageActionAdapter,
|
||||
ChannelMessageActionName,
|
||||
ClawdbotConfig,
|
||||
MoltbotConfig,
|
||||
} from "clawdbot/plugin-sdk";
|
||||
import {
|
||||
createActionGate,
|
||||
@@ -24,13 +24,13 @@ import { resolveGoogleChatOutboundSpace } from "./targets.js";
|
||||
|
||||
const providerId = "googlechat";
|
||||
|
||||
function listEnabledAccounts(cfg: ClawdbotConfig) {
|
||||
function listEnabledAccounts(cfg: MoltbotConfig) {
|
||||
return listEnabledGoogleChatAccounts(cfg).filter(
|
||||
(account) => account.enabled && account.credentialSource !== "none",
|
||||
);
|
||||
}
|
||||
|
||||
function isReactionsEnabled(accounts: ReturnType<typeof listEnabledAccounts>, cfg: ClawdbotConfig) {
|
||||
function isReactionsEnabled(accounts: ReturnType<typeof listEnabledAccounts>, cfg: MoltbotConfig) {
|
||||
for (const account of accounts) {
|
||||
const gate = createActionGate(
|
||||
(account.config.actions ?? (cfg.channels?.["googlechat"] as { actions?: unknown })?.actions) as Record<
|
||||
@@ -49,11 +49,11 @@ function resolveAppUserNames(account: { config: { botUser?: string | null } }) {
|
||||
|
||||
export const googlechatMessageActions: ChannelMessageActionAdapter = {
|
||||
listActions: ({ cfg }) => {
|
||||
const accounts = listEnabledAccounts(cfg as ClawdbotConfig);
|
||||
const accounts = listEnabledAccounts(cfg as MoltbotConfig);
|
||||
if (accounts.length === 0) return [];
|
||||
const actions = new Set<ChannelMessageActionName>([]);
|
||||
actions.add("send");
|
||||
if (isReactionsEnabled(accounts, cfg as ClawdbotConfig)) {
|
||||
if (isReactionsEnabled(accounts, cfg as MoltbotConfig)) {
|
||||
actions.add("react");
|
||||
actions.add("reactions");
|
||||
}
|
||||
@@ -69,7 +69,7 @@ export const googlechatMessageActions: ChannelMessageActionAdapter = {
|
||||
},
|
||||
handleAction: async ({ action, params, cfg, accountId }) => {
|
||||
const account = resolveGoogleChatAccount({
|
||||
cfg: cfg as ClawdbotConfig,
|
||||
cfg: cfg as MoltbotConfig,
|
||||
accountId,
|
||||
});
|
||||
if (account.credentialSource === "none") {
|
||||
|
||||
@@ -153,7 +153,7 @@ export async function uploadGoogleChatAttachment(params: {
|
||||
contentType?: string;
|
||||
}): Promise<{ attachmentUploadToken?: string }> {
|
||||
const { account, space, filename, buffer, contentType } = params;
|
||||
const boundary = `clawdbot-${crypto.randomUUID()}`;
|
||||
const boundary = `moltbot-${crypto.randomUUID()}`;
|
||||
const metadata = JSON.stringify({ filename });
|
||||
const header = `--${boundary}\r\nContent-Type: application/json; charset=UTF-8\r\n\r\n${metadata}\r\n`;
|
||||
const mediaHeader = `--${boundary}\r\nContent-Type: ${contentType ?? "application/octet-stream"}\r\n\r\n`;
|
||||
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
type ChannelDock,
|
||||
type ChannelMessageActionAdapter,
|
||||
type ChannelPlugin,
|
||||
type ClawdbotConfig,
|
||||
type MoltbotConfig,
|
||||
} from "clawdbot/plugin-sdk";
|
||||
import { GoogleChatConfigSchema } from "clawdbot/plugin-sdk";
|
||||
|
||||
@@ -59,7 +59,7 @@ export const googlechatDock: ChannelDock = {
|
||||
outbound: { textChunkLimit: 4000 },
|
||||
config: {
|
||||
resolveAllowFrom: ({ cfg, accountId }) =>
|
||||
(resolveGoogleChatAccount({ cfg: cfg as ClawdbotConfig, accountId }).config.dm?.allowFrom ??
|
||||
(resolveGoogleChatAccount({ cfg: cfg as MoltbotConfig, accountId }).config.dm?.allowFrom ??
|
||||
[]
|
||||
).map((entry) => String(entry)),
|
||||
formatAllowFrom: ({ allowFrom }) =>
|
||||
@@ -103,7 +103,7 @@ export const googlechatPlugin: ChannelPlugin<ResolvedGoogleChatAccount> = {
|
||||
idLabel: "googlechatUserId",
|
||||
normalizeAllowEntry: (entry) => formatAllowFromEntry(entry),
|
||||
notifyApproval: async ({ cfg, id }) => {
|
||||
const account = resolveGoogleChatAccount({ cfg: cfg as ClawdbotConfig });
|
||||
const account = resolveGoogleChatAccount({ cfg: cfg as MoltbotConfig });
|
||||
if (account.credentialSource === "none") return;
|
||||
const user = normalizeGoogleChatTarget(id) ?? id;
|
||||
const target = isGoogleChatUserTarget(user) ? user : `users/${user}`;
|
||||
@@ -129,13 +129,13 @@ export const googlechatPlugin: ChannelPlugin<ResolvedGoogleChatAccount> = {
|
||||
reload: { configPrefixes: ["channels.googlechat"] },
|
||||
configSchema: buildChannelConfigSchema(GoogleChatConfigSchema),
|
||||
config: {
|
||||
listAccountIds: (cfg) => listGoogleChatAccountIds(cfg as ClawdbotConfig),
|
||||
listAccountIds: (cfg) => listGoogleChatAccountIds(cfg as MoltbotConfig),
|
||||
resolveAccount: (cfg, accountId) =>
|
||||
resolveGoogleChatAccount({ cfg: cfg as ClawdbotConfig, accountId }),
|
||||
defaultAccountId: (cfg) => resolveDefaultGoogleChatAccountId(cfg as ClawdbotConfig),
|
||||
resolveGoogleChatAccount({ cfg: cfg as MoltbotConfig, accountId }),
|
||||
defaultAccountId: (cfg) => resolveDefaultGoogleChatAccountId(cfg as MoltbotConfig),
|
||||
setAccountEnabled: ({ cfg, accountId, enabled }) =>
|
||||
setAccountEnabledInConfigSection({
|
||||
cfg: cfg as ClawdbotConfig,
|
||||
cfg: cfg as MoltbotConfig,
|
||||
sectionKey: "googlechat",
|
||||
accountId,
|
||||
enabled,
|
||||
@@ -143,7 +143,7 @@ export const googlechatPlugin: ChannelPlugin<ResolvedGoogleChatAccount> = {
|
||||
}),
|
||||
deleteAccount: ({ cfg, accountId }) =>
|
||||
deleteAccountFromConfigSection({
|
||||
cfg: cfg as ClawdbotConfig,
|
||||
cfg: cfg as MoltbotConfig,
|
||||
sectionKey: "googlechat",
|
||||
accountId,
|
||||
clearBaseFields: [
|
||||
@@ -167,7 +167,7 @@ export const googlechatPlugin: ChannelPlugin<ResolvedGoogleChatAccount> = {
|
||||
}),
|
||||
resolveAllowFrom: ({ cfg, accountId }) =>
|
||||
(resolveGoogleChatAccount({
|
||||
cfg: cfg as ClawdbotConfig,
|
||||
cfg: cfg as MoltbotConfig,
|
||||
accountId,
|
||||
}).config.dm?.allowFrom ?? []
|
||||
).map((entry) => String(entry)),
|
||||
@@ -181,7 +181,7 @@ export const googlechatPlugin: ChannelPlugin<ResolvedGoogleChatAccount> = {
|
||||
resolveDmPolicy: ({ cfg, accountId, account }) => {
|
||||
const resolvedAccountId = accountId ?? account.accountId ?? DEFAULT_ACCOUNT_ID;
|
||||
const useAccountPath = Boolean(
|
||||
(cfg as ClawdbotConfig).channels?.["googlechat"]?.accounts?.[resolvedAccountId],
|
||||
(cfg as MoltbotConfig).channels?.["googlechat"]?.accounts?.[resolvedAccountId],
|
||||
);
|
||||
const allowFromPath = useAccountPath
|
||||
? `channels.googlechat.accounts.${resolvedAccountId}.dm.`
|
||||
@@ -231,7 +231,7 @@ export const googlechatPlugin: ChannelPlugin<ResolvedGoogleChatAccount> = {
|
||||
self: async () => null,
|
||||
listPeers: async ({ cfg, accountId, query, limit }) => {
|
||||
const account = resolveGoogleChatAccount({
|
||||
cfg: cfg as ClawdbotConfig,
|
||||
cfg: cfg as MoltbotConfig,
|
||||
accountId,
|
||||
});
|
||||
const q = query?.trim().toLowerCase() || "";
|
||||
@@ -251,7 +251,7 @@ export const googlechatPlugin: ChannelPlugin<ResolvedGoogleChatAccount> = {
|
||||
},
|
||||
listGroups: async ({ cfg, accountId, query, limit }) => {
|
||||
const account = resolveGoogleChatAccount({
|
||||
cfg: cfg as ClawdbotConfig,
|
||||
cfg: cfg as MoltbotConfig,
|
||||
accountId,
|
||||
});
|
||||
const groups = account.config.groups ?? {};
|
||||
@@ -291,7 +291,7 @@ export const googlechatPlugin: ChannelPlugin<ResolvedGoogleChatAccount> = {
|
||||
resolveAccountId: ({ accountId }) => normalizeAccountId(accountId),
|
||||
applyAccountName: ({ cfg, accountId, name }) =>
|
||||
applyAccountNameToChannelSection({
|
||||
cfg: cfg as ClawdbotConfig,
|
||||
cfg: cfg as MoltbotConfig,
|
||||
channelKey: "googlechat",
|
||||
accountId,
|
||||
name,
|
||||
@@ -307,7 +307,7 @@ export const googlechatPlugin: ChannelPlugin<ResolvedGoogleChatAccount> = {
|
||||
},
|
||||
applyAccountConfig: ({ cfg, accountId, input }) => {
|
||||
const namedConfig = applyAccountNameToChannelSection({
|
||||
cfg: cfg as ClawdbotConfig,
|
||||
cfg: cfg as MoltbotConfig,
|
||||
channelKey: "googlechat",
|
||||
accountId,
|
||||
name: input.name,
|
||||
@@ -315,7 +315,7 @@ export const googlechatPlugin: ChannelPlugin<ResolvedGoogleChatAccount> = {
|
||||
const next =
|
||||
accountId !== DEFAULT_ACCOUNT_ID
|
||||
? migrateBaseNameToDefaultAccount({
|
||||
cfg: namedConfig as ClawdbotConfig,
|
||||
cfg: namedConfig as MoltbotConfig,
|
||||
channelKey: "googlechat",
|
||||
})
|
||||
: namedConfig;
|
||||
@@ -348,7 +348,7 @@ export const googlechatPlugin: ChannelPlugin<ResolvedGoogleChatAccount> = {
|
||||
...configPatch,
|
||||
},
|
||||
},
|
||||
} as ClawdbotConfig;
|
||||
} as MoltbotConfig;
|
||||
}
|
||||
return {
|
||||
...next,
|
||||
@@ -367,7 +367,7 @@ export const googlechatPlugin: ChannelPlugin<ResolvedGoogleChatAccount> = {
|
||||
},
|
||||
},
|
||||
},
|
||||
} as ClawdbotConfig;
|
||||
} as MoltbotConfig;
|
||||
},
|
||||
},
|
||||
outbound: {
|
||||
@@ -414,7 +414,7 @@ export const googlechatPlugin: ChannelPlugin<ResolvedGoogleChatAccount> = {
|
||||
},
|
||||
sendText: async ({ cfg, to, text, accountId, replyToId, threadId }) => {
|
||||
const account = resolveGoogleChatAccount({
|
||||
cfg: cfg as ClawdbotConfig,
|
||||
cfg: cfg as MoltbotConfig,
|
||||
accountId,
|
||||
});
|
||||
const space = await resolveGoogleChatOutboundSpace({ account, target: to });
|
||||
@@ -436,14 +436,14 @@ export const googlechatPlugin: ChannelPlugin<ResolvedGoogleChatAccount> = {
|
||||
throw new Error("Google Chat mediaUrl is required.");
|
||||
}
|
||||
const account = resolveGoogleChatAccount({
|
||||
cfg: cfg as ClawdbotConfig,
|
||||
cfg: cfg as MoltbotConfig,
|
||||
accountId,
|
||||
});
|
||||
const space = await resolveGoogleChatOutboundSpace({ account, target: to });
|
||||
const thread = (threadId ?? replyToId ?? undefined) as string | undefined;
|
||||
const runtime = getGoogleChatRuntime();
|
||||
const maxBytes = resolveChannelMediaMaxBytes({
|
||||
cfg: cfg as ClawdbotConfig,
|
||||
cfg: cfg as MoltbotConfig,
|
||||
resolveChannelLimitMb: ({ cfg, accountId }) =>
|
||||
(cfg.channels?.["googlechat"] as { accounts?: Record<string, { mediaMaxMb?: number }>; mediaMaxMb?: number } | undefined)
|
||||
?.accounts?.[accountId]?.mediaMaxMb ??
|
||||
@@ -560,7 +560,7 @@ export const googlechatPlugin: ChannelPlugin<ResolvedGoogleChatAccount> = {
|
||||
});
|
||||
const unregister = await startGoogleChatMonitor({
|
||||
account,
|
||||
config: ctx.cfg as ClawdbotConfig,
|
||||
config: ctx.cfg as MoltbotConfig,
|
||||
runtime: ctx.runtime,
|
||||
abortSignal: ctx.abortSignal,
|
||||
webhookPath: account.config.webhookPath,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { IncomingMessage, ServerResponse } from "node:http";
|
||||
|
||||
import type { ClawdbotConfig } from "clawdbot/plugin-sdk";
|
||||
import type { MoltbotConfig } from "clawdbot/plugin-sdk";
|
||||
import { resolveMentionGatingWithBypass } from "clawdbot/plugin-sdk";
|
||||
|
||||
import {
|
||||
@@ -30,7 +30,7 @@ export type GoogleChatRuntimeEnv = {
|
||||
|
||||
export type GoogleChatMonitorOptions = {
|
||||
account: ResolvedGoogleChatAccount;
|
||||
config: ClawdbotConfig;
|
||||
config: MoltbotConfig;
|
||||
runtime: GoogleChatRuntimeEnv;
|
||||
abortSignal: AbortSignal;
|
||||
webhookPath?: string;
|
||||
@@ -42,7 +42,7 @@ type GoogleChatCoreRuntime = ReturnType<typeof getGoogleChatRuntime>;
|
||||
|
||||
type WebhookTarget = {
|
||||
account: ResolvedGoogleChatAccount;
|
||||
config: ClawdbotConfig;
|
||||
config: MoltbotConfig;
|
||||
runtime: GoogleChatRuntimeEnv;
|
||||
core: GoogleChatCoreRuntime;
|
||||
path: string;
|
||||
@@ -357,24 +357,24 @@ function extractMentionInfo(annotations: GoogleChatAnnotation[], botUser?: strin
|
||||
* Resolve bot display name with fallback chain:
|
||||
* 1. Account config name
|
||||
* 2. Agent name from config
|
||||
* 3. "Clawdbot" as generic fallback
|
||||
* 3. "Moltbot" as generic fallback
|
||||
*/
|
||||
function resolveBotDisplayName(params: {
|
||||
accountName?: string;
|
||||
agentId: string;
|
||||
config: ClawdbotConfig;
|
||||
config: MoltbotConfig;
|
||||
}): string {
|
||||
const { accountName, agentId, config } = params;
|
||||
if (accountName?.trim()) return accountName.trim();
|
||||
const agent = config.agents?.list?.find((a) => a.id === agentId);
|
||||
if (agent?.name?.trim()) return agent.name.trim();
|
||||
return "Clawdbot";
|
||||
return "Moltbot";
|
||||
}
|
||||
|
||||
async function processMessageWithPipeline(params: {
|
||||
event: GoogleChatEvent;
|
||||
account: ResolvedGoogleChatAccount;
|
||||
config: ClawdbotConfig;
|
||||
config: MoltbotConfig;
|
||||
runtime: GoogleChatRuntimeEnv;
|
||||
core: GoogleChatCoreRuntime;
|
||||
statusSink?: (patch: { lastInboundAt?: number; lastOutboundAt?: number }) => void;
|
||||
@@ -726,7 +726,7 @@ async function deliverGoogleChatReply(params: {
|
||||
spaceId: string;
|
||||
runtime: GoogleChatRuntimeEnv;
|
||||
core: GoogleChatCoreRuntime;
|
||||
config: ClawdbotConfig;
|
||||
config: MoltbotConfig;
|
||||
statusSink?: (patch: { lastInboundAt?: number; lastOutboundAt?: number }) => void;
|
||||
typingMessageName?: string;
|
||||
}): Promise<void> {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ClawdbotConfig, DmPolicy } from "clawdbot/plugin-sdk";
|
||||
import type { MoltbotConfig, DmPolicy } from "clawdbot/plugin-sdk";
|
||||
import {
|
||||
addWildcardAllowFrom,
|
||||
formatDocsLink,
|
||||
@@ -22,7 +22,7 @@ const channel = "googlechat" as const;
|
||||
const ENV_SERVICE_ACCOUNT = "GOOGLE_CHAT_SERVICE_ACCOUNT";
|
||||
const ENV_SERVICE_ACCOUNT_FILE = "GOOGLE_CHAT_SERVICE_ACCOUNT_FILE";
|
||||
|
||||
function setGoogleChatDmPolicy(cfg: ClawdbotConfig, policy: DmPolicy) {
|
||||
function setGoogleChatDmPolicy(cfg: MoltbotConfig, policy: DmPolicy) {
|
||||
const allowFrom =
|
||||
policy === "open"
|
||||
? addWildcardAllowFrom(cfg.channels?.["googlechat"]?.dm?.allowFrom)
|
||||
@@ -51,9 +51,9 @@ function parseAllowFromInput(raw: string): string[] {
|
||||
}
|
||||
|
||||
async function promptAllowFrom(params: {
|
||||
cfg: ClawdbotConfig;
|
||||
cfg: MoltbotConfig;
|
||||
prompter: WizardPrompter;
|
||||
}): Promise<ClawdbotConfig> {
|
||||
}): Promise<MoltbotConfig> {
|
||||
const current = params.cfg.channels?.["googlechat"]?.dm?.allowFrom ?? [];
|
||||
const entry = await params.prompter.text({
|
||||
message: "Google Chat allowFrom (user id or email)",
|
||||
@@ -91,10 +91,10 @@ const dmPolicy: ChannelOnboardingDmPolicy = {
|
||||
};
|
||||
|
||||
function applyAccountConfig(params: {
|
||||
cfg: ClawdbotConfig;
|
||||
cfg: MoltbotConfig;
|
||||
accountId: string;
|
||||
patch: Record<string, unknown>;
|
||||
}): ClawdbotConfig {
|
||||
}): MoltbotConfig {
|
||||
const { cfg, accountId, patch } = params;
|
||||
if (accountId === DEFAULT_ACCOUNT_ID) {
|
||||
return {
|
||||
@@ -130,10 +130,10 @@ function applyAccountConfig(params: {
|
||||
}
|
||||
|
||||
async function promptCredentials(params: {
|
||||
cfg: ClawdbotConfig;
|
||||
cfg: MoltbotConfig;
|
||||
prompter: WizardPrompter;
|
||||
accountId: string;
|
||||
}): Promise<ClawdbotConfig> {
|
||||
}): Promise<MoltbotConfig> {
|
||||
const { cfg, prompter, accountId } = params;
|
||||
const envReady =
|
||||
accountId === DEFAULT_ACCOUNT_ID &&
|
||||
@@ -184,10 +184,10 @@ async function promptCredentials(params: {
|
||||
}
|
||||
|
||||
async function promptAudience(params: {
|
||||
cfg: ClawdbotConfig;
|
||||
cfg: MoltbotConfig;
|
||||
prompter: WizardPrompter;
|
||||
accountId: string;
|
||||
}): Promise<ClawdbotConfig> {
|
||||
}): Promise<MoltbotConfig> {
|
||||
const account = resolveGoogleChatAccount({
|
||||
cfg: params.cfg,
|
||||
accountId: params.accountId,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ClawdbotPluginApi } from "clawdbot/plugin-sdk";
|
||||
import type { MoltbotPluginApi } from "clawdbot/plugin-sdk";
|
||||
import { emptyPluginConfigSchema } from "clawdbot/plugin-sdk";
|
||||
|
||||
import { imessagePlugin } from "./src/channel.js";
|
||||
@@ -9,7 +9,7 @@ const plugin = {
|
||||
name: "iMessage",
|
||||
description: "iMessage channel plugin",
|
||||
configSchema: emptyPluginConfigSchema(),
|
||||
register(api: ClawdbotPluginApi) {
|
||||
register(api: MoltbotPluginApi) {
|
||||
setIMessageRuntime(api.runtime);
|
||||
api.registerChannel({ plugin: imessagePlugin });
|
||||
},
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
"name": "@moltbot/imessage",
|
||||
"version": "2026.1.26",
|
||||
"type": "module",
|
||||
"description": "Clawdbot iMessage channel plugin",
|
||||
"clawdbot": {
|
||||
"description": "Moltbot iMessage channel plugin",
|
||||
"moltbot": {
|
||||
"extensions": [
|
||||
"./index.ts"
|
||||
]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ClawdbotPluginApi } from "clawdbot/plugin-sdk";
|
||||
import type { MoltbotPluginApi } from "clawdbot/plugin-sdk";
|
||||
import { emptyPluginConfigSchema } from "clawdbot/plugin-sdk";
|
||||
|
||||
import { linePlugin } from "./src/channel.js";
|
||||
@@ -10,7 +10,7 @@ const plugin = {
|
||||
name: "LINE",
|
||||
description: "LINE Messaging API channel plugin",
|
||||
configSchema: emptyPluginConfigSchema(),
|
||||
register(api: ClawdbotPluginApi) {
|
||||
register(api: MoltbotPluginApi) {
|
||||
setLineRuntime(api.runtime);
|
||||
api.registerChannel({ plugin: linePlugin });
|
||||
registerLineCardCommand(api);
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
"name": "@moltbot/line",
|
||||
"version": "2026.1.26",
|
||||
"type": "module",
|
||||
"description": "Clawdbot LINE channel plugin",
|
||||
"clawdbot": {
|
||||
"description": "Moltbot LINE channel plugin",
|
||||
"moltbot": {
|
||||
"extensions": [
|
||||
"./index.ts"
|
||||
],
|
||||
@@ -24,6 +24,6 @@
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"clawdbot": "workspace:*"
|
||||
"moltbot": "workspace:*"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ClawdbotPluginApi, LineChannelData, ReplyPayload } from "clawdbot/plugin-sdk";
|
||||
import type { MoltbotPluginApi, LineChannelData, ReplyPayload } from "clawdbot/plugin-sdk";
|
||||
import {
|
||||
createActionCard,
|
||||
createImageCard,
|
||||
@@ -150,7 +150,7 @@ function parseCardArgs(argsStr: string): {
|
||||
return result;
|
||||
}
|
||||
|
||||
export function registerLineCardCommand(api: ClawdbotPluginApi): void {
|
||||
export function registerLineCardCommand(api: MoltbotPluginApi): void {
|
||||
api.registerCommand({
|
||||
name: "card",
|
||||
description: "Send a rich card message (LINE).",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { ClawdbotConfig, PluginRuntime } from "clawdbot/plugin-sdk";
|
||||
import type { MoltbotConfig, PluginRuntime } from "clawdbot/plugin-sdk";
|
||||
import { linePlugin } from "./channel.js";
|
||||
import { setLineRuntime } from "./runtime.js";
|
||||
|
||||
@@ -12,7 +12,7 @@ type LineRuntimeMocks = {
|
||||
|
||||
function createRuntime(): { runtime: PluginRuntime; mocks: LineRuntimeMocks } {
|
||||
const writeConfigFile = vi.fn(async () => {});
|
||||
const resolveLineAccount = vi.fn(({ cfg, accountId }: { cfg: ClawdbotConfig; accountId?: string }) => {
|
||||
const resolveLineAccount = vi.fn(({ cfg, accountId }: { cfg: MoltbotConfig; accountId?: string }) => {
|
||||
const lineConfig = (cfg.channels?.line ?? {}) as {
|
||||
tokenFile?: string;
|
||||
secretFile?: string;
|
||||
@@ -48,7 +48,7 @@ describe("linePlugin gateway.logoutAccount", () => {
|
||||
const { runtime, mocks } = createRuntime();
|
||||
setLineRuntime(runtime);
|
||||
|
||||
const cfg: ClawdbotConfig = {
|
||||
const cfg: MoltbotConfig = {
|
||||
channels: {
|
||||
line: {
|
||||
tokenFile: "/tmp/token",
|
||||
@@ -71,7 +71,7 @@ describe("linePlugin gateway.logoutAccount", () => {
|
||||
const { runtime, mocks } = createRuntime();
|
||||
setLineRuntime(runtime);
|
||||
|
||||
const cfg: ClawdbotConfig = {
|
||||
const cfg: MoltbotConfig = {
|
||||
channels: {
|
||||
line: {
|
||||
accounts: {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import type { ClawdbotConfig, PluginRuntime } from "clawdbot/plugin-sdk";
|
||||
import type { MoltbotConfig, PluginRuntime } from "clawdbot/plugin-sdk";
|
||||
import { linePlugin } from "./channel.js";
|
||||
import { setLineRuntime } from "./runtime.js";
|
||||
|
||||
@@ -33,7 +33,7 @@ function createRuntime(): { runtime: PluginRuntime; mocks: LineRuntimeMocks } {
|
||||
const sendMessageLine = vi.fn(async () => ({ messageId: "m-media", chatId: "c1" }));
|
||||
const chunkMarkdownText = vi.fn((text: string) => [text]);
|
||||
const resolveTextChunkLimit = vi.fn(() => 123);
|
||||
const resolveLineAccount = vi.fn(({ cfg, accountId }: { cfg: ClawdbotConfig; accountId?: string }) => {
|
||||
const resolveLineAccount = vi.fn(({ cfg, accountId }: { cfg: MoltbotConfig; accountId?: string }) => {
|
||||
const resolved = accountId ?? "default";
|
||||
const lineConfig = (cfg.channels?.line ?? {}) as {
|
||||
accounts?: Record<string, Record<string, unknown>>;
|
||||
@@ -90,7 +90,7 @@ describe("linePlugin outbound.sendPayload", () => {
|
||||
it("sends flex message without dropping text", async () => {
|
||||
const { runtime, mocks } = createRuntime();
|
||||
setLineRuntime(runtime);
|
||||
const cfg = { channels: { line: {} } } as ClawdbotConfig;
|
||||
const cfg = { channels: { line: {} } } as MoltbotConfig;
|
||||
|
||||
const payload = {
|
||||
text: "Now playing:",
|
||||
@@ -121,7 +121,7 @@ describe("linePlugin outbound.sendPayload", () => {
|
||||
it("sends template message without dropping text", async () => {
|
||||
const { runtime, mocks } = createRuntime();
|
||||
setLineRuntime(runtime);
|
||||
const cfg = { channels: { line: {} } } as ClawdbotConfig;
|
||||
const cfg = { channels: { line: {} } } as MoltbotConfig;
|
||||
|
||||
const payload = {
|
||||
text: "Choose one:",
|
||||
@@ -157,7 +157,7 @@ describe("linePlugin outbound.sendPayload", () => {
|
||||
it("attaches quick replies when no text chunks are present", async () => {
|
||||
const { runtime, mocks } = createRuntime();
|
||||
setLineRuntime(runtime);
|
||||
const cfg = { channels: { line: {} } } as ClawdbotConfig;
|
||||
const cfg = { channels: { line: {} } } as MoltbotConfig;
|
||||
|
||||
const payload = {
|
||||
channelData: {
|
||||
@@ -197,7 +197,7 @@ describe("linePlugin outbound.sendPayload", () => {
|
||||
it("sends media before quick-reply text so buttons stay visible", async () => {
|
||||
const { runtime, mocks } = createRuntime();
|
||||
setLineRuntime(runtime);
|
||||
const cfg = { channels: { line: {} } } as ClawdbotConfig;
|
||||
const cfg = { channels: { line: {} } } as MoltbotConfig;
|
||||
|
||||
const payload = {
|
||||
text: "Hello",
|
||||
@@ -235,7 +235,7 @@ describe("linePlugin outbound.sendPayload", () => {
|
||||
it("uses configured text chunk limit for payloads", async () => {
|
||||
const { runtime, mocks } = createRuntime();
|
||||
setLineRuntime(runtime);
|
||||
const cfg = { channels: { line: { textChunkLimit: 123 } } } as ClawdbotConfig;
|
||||
const cfg = { channels: { line: { textChunkLimit: 123 } } } as MoltbotConfig;
|
||||
|
||||
const payload = {
|
||||
text: "Hello world",
|
||||
@@ -295,7 +295,7 @@ describe("linePlugin groups.resolveRequireMention", () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
} as ClawdbotConfig;
|
||||
} as MoltbotConfig;
|
||||
|
||||
const requireMention = linePlugin.groups.resolveRequireMention({
|
||||
cfg,
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
LineConfigSchema,
|
||||
processLineMessage,
|
||||
type ChannelPlugin,
|
||||
type ClawdbotConfig,
|
||||
type MoltbotConfig,
|
||||
type LineConfig,
|
||||
type LineChannelData,
|
||||
type ResolvedLineAccount,
|
||||
@@ -53,7 +53,7 @@ export const linePlugin: ChannelPlugin<ResolvedLineAccount> = {
|
||||
if (!account.channelAccessToken) {
|
||||
throw new Error("LINE channel access token not configured");
|
||||
}
|
||||
await line.pushMessageLine(id, "Clawdbot: your access has been approved.", {
|
||||
await line.pushMessageLine(id, "Moltbot: your access has been approved.", {
|
||||
channelAccessToken: account.channelAccessToken,
|
||||
});
|
||||
},
|
||||
@@ -164,7 +164,7 @@ export const linePlugin: ChannelPlugin<ResolvedLineAccount> = {
|
||||
allowFrom: account.config.allowFrom ?? [],
|
||||
policyPath: `${basePath}dmPolicy`,
|
||||
allowFromPath: basePath,
|
||||
approveHint: "clawdbot pairing approve line <code>",
|
||||
approveHint: "moltbot pairing approve line <code>",
|
||||
normalizeEntry: (raw) => raw.replace(/^line:(?:user:)?/i, ""),
|
||||
};
|
||||
},
|
||||
@@ -639,7 +639,7 @@ export const linePlugin: ChannelPlugin<ResolvedLineAccount> = {
|
||||
},
|
||||
logoutAccount: async ({ accountId, cfg }) => {
|
||||
const envToken = process.env.LINE_CHANNEL_ACCESS_TOKEN?.trim() ?? "";
|
||||
const nextCfg = { ...cfg } as ClawdbotConfig;
|
||||
const nextCfg = { ...cfg } as MoltbotConfig;
|
||||
const lineConfig = (cfg.channels?.line ?? {}) as LineConfig;
|
||||
const nextLine = { ...lineConfig };
|
||||
let cleared = false;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { ClawdbotPluginApi } from "../../src/plugins/types.js";
|
||||
import type { MoltbotPluginApi } from "../../src/plugins/types.js";
|
||||
|
||||
import { createLlmTaskTool } from "./src/llm-task-tool.js";
|
||||
|
||||
export default function register(api: ClawdbotPluginApi) {
|
||||
export default function register(api: MoltbotPluginApi) {
|
||||
api.registerTool(createLlmTaskTool(api), { optional: true });
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
"name": "@moltbot/llm-task",
|
||||
"version": "2026.1.26",
|
||||
"type": "module",
|
||||
"description": "Clawdbot JSON-only LLM task plugin",
|
||||
"clawdbot": {
|
||||
"description": "Moltbot JSON-only LLM task plugin",
|
||||
"moltbot": {
|
||||
"extensions": [
|
||||
"./index.ts"
|
||||
]
|
||||
|
||||
@@ -5,12 +5,12 @@ import fs from "node:fs/promises";
|
||||
import Ajv from "ajv";
|
||||
import { Type } from "@sinclair/typebox";
|
||||
|
||||
// NOTE: This extension is intended to be bundled with Clawdbot.
|
||||
// When running from source (tests/dev), Clawdbot internals live under src/.
|
||||
// NOTE: This extension is intended to be bundled with Moltbot.
|
||||
// When running from source (tests/dev), Moltbot internals live under src/.
|
||||
// When running from a built install, internals live under dist/ (no src/ tree).
|
||||
// So we resolve internal imports dynamically with src-first, dist-fallback.
|
||||
|
||||
import type { ClawdbotPluginApi } from "../../../src/plugins/types.js";
|
||||
import type { MoltbotPluginApi } from "../../../src/plugins/types.js";
|
||||
|
||||
type RunEmbeddedPiAgentFn = (params: Record<string, unknown>) => Promise<unknown>;
|
||||
|
||||
@@ -61,7 +61,7 @@ type PluginCfg = {
|
||||
timeoutMs?: number;
|
||||
};
|
||||
|
||||
export function createLlmTaskTool(api: ClawdbotPluginApi) {
|
||||
export function createLlmTaskTool(api: MoltbotPluginApi) {
|
||||
return {
|
||||
name: "llm-task",
|
||||
description:
|
||||
@@ -154,7 +154,7 @@ export function createLlmTaskTool(api: ClawdbotPluginApi) {
|
||||
|
||||
let tmpDir: string | null = null;
|
||||
try {
|
||||
tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-llm-task-"));
|
||||
tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-llm-task-"));
|
||||
const sessionId = `llm-task-${Date.now()}`;
|
||||
const sessionFile = path.join(tmpDir, "session.json");
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import type { ClawdbotPluginApi } from "../../src/plugins/types.js";
|
||||
import type { MoltbotPluginApi } from "../../src/plugins/types.js";
|
||||
|
||||
import { createLobsterTool } from "./src/lobster-tool.js";
|
||||
|
||||
export default function register(api: ClawdbotPluginApi) {
|
||||
export default function register(api: MoltbotPluginApi) {
|
||||
api.registerTool(
|
||||
(ctx) => {
|
||||
if (ctx.sandboxed) return null;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"version": "2026.1.26",
|
||||
"type": "module",
|
||||
"description": "Lobster workflow tool plugin (typed pipelines + resumable approvals)",
|
||||
"clawdbot": {
|
||||
"moltbot": {
|
||||
"extensions": [
|
||||
"./index.ts"
|
||||
]
|
||||
|
||||
@@ -4,10 +4,10 @@ import path from "node:path";
|
||||
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import type { ClawdbotPluginApi, ClawdbotPluginToolContext } from "../../../src/plugins/types.js";
|
||||
import type { MoltbotPluginApi, MoltbotPluginToolContext } from "../../../src/plugins/types.js";
|
||||
import { createLobsterTool } from "./lobster-tool.js";
|
||||
|
||||
async function writeFakeLobsterScript(scriptBody: string, prefix = "clawdbot-lobster-plugin-") {
|
||||
async function writeFakeLobsterScript(scriptBody: string, prefix = "moltbot-lobster-plugin-") {
|
||||
const dir = await fs.mkdtemp(path.join(os.tmpdir(), prefix));
|
||||
const isWindows = process.platform === "win32";
|
||||
|
||||
@@ -33,7 +33,7 @@ async function writeFakeLobster(params: { payload: unknown }) {
|
||||
return await writeFakeLobsterScript(scriptBody);
|
||||
}
|
||||
|
||||
function fakeApi(): ClawdbotPluginApi {
|
||||
function fakeApi(): MoltbotPluginApi {
|
||||
return {
|
||||
id: "lobster",
|
||||
name: "lobster",
|
||||
@@ -52,7 +52,7 @@ function fakeApi(): ClawdbotPluginApi {
|
||||
};
|
||||
}
|
||||
|
||||
function fakeCtx(overrides: Partial<ClawdbotPluginToolContext> = {}): ClawdbotPluginToolContext {
|
||||
function fakeCtx(overrides: Partial<MoltbotPluginToolContext> = {}): MoltbotPluginToolContext {
|
||||
return {
|
||||
config: {} as any,
|
||||
workspaceDir: "/tmp",
|
||||
@@ -89,7 +89,7 @@ describe("lobster plugin tool", () => {
|
||||
`const payload = ${JSON.stringify(payload)};\n` +
|
||||
`console.log("noise before json");\n` +
|
||||
`process.stdout.write(JSON.stringify(payload));\n`,
|
||||
"clawdbot-lobster-plugin-noisy-",
|
||||
"moltbot-lobster-plugin-noisy-",
|
||||
);
|
||||
|
||||
const tool = createLobsterTool(fakeApi());
|
||||
@@ -117,7 +117,7 @@ describe("lobster plugin tool", () => {
|
||||
it("rejects invalid JSON from lobster", async () => {
|
||||
const { binPath } = await writeFakeLobsterScript(
|
||||
`process.stdout.write("nope");\n`,
|
||||
"clawdbot-lobster-plugin-bad-",
|
||||
"moltbot-lobster-plugin-bad-",
|
||||
);
|
||||
|
||||
const tool = createLobsterTool(fakeApi());
|
||||
@@ -132,7 +132,7 @@ describe("lobster plugin tool", () => {
|
||||
|
||||
it("can be gated off in sandboxed contexts", async () => {
|
||||
const api = fakeApi();
|
||||
const factoryTool = (ctx: ClawdbotPluginToolContext) => {
|
||||
const factoryTool = (ctx: MoltbotPluginToolContext) => {
|
||||
if (ctx.sandboxed) return null;
|
||||
return createLobsterTool(api);
|
||||
};
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Type } from "@sinclair/typebox";
|
||||
import { spawn } from "node:child_process";
|
||||
import path from "node:path";
|
||||
|
||||
import type { ClawdbotPluginApi } from "../../../src/plugins/types.js";
|
||||
import type { MoltbotPluginApi } from "../../../src/plugins/types.js";
|
||||
|
||||
type LobsterEnvelope =
|
||||
| {
|
||||
@@ -168,7 +168,7 @@ function parseEnvelope(stdout: string): LobsterEnvelope {
|
||||
throw new Error("lobster returned invalid JSON envelope");
|
||||
}
|
||||
|
||||
export function createLobsterTool(api: ClawdbotPluginApi) {
|
||||
export function createLobsterTool(api: MoltbotPluginApi) {
|
||||
return {
|
||||
name: "lobster",
|
||||
description:
|
||||
|
||||
@@ -3,47 +3,47 @@
|
||||
## 2026.1.23
|
||||
|
||||
### Changes
|
||||
- Version alignment with core Clawdbot release numbers.
|
||||
- Version alignment with core Moltbot release numbers.
|
||||
|
||||
## 2026.1.22
|
||||
|
||||
### Changes
|
||||
- Version alignment with core Clawdbot release numbers.
|
||||
- Version alignment with core Moltbot release numbers.
|
||||
|
||||
## 2026.1.21
|
||||
|
||||
### Changes
|
||||
- Version alignment with core Clawdbot release numbers.
|
||||
- Version alignment with core Moltbot release numbers.
|
||||
|
||||
## 2026.1.20
|
||||
|
||||
### Changes
|
||||
- Version alignment with core Clawdbot release numbers.
|
||||
- Version alignment with core Moltbot release numbers.
|
||||
|
||||
## 2026.1.17-1
|
||||
|
||||
### Changes
|
||||
- Version alignment with core Clawdbot release numbers.
|
||||
- Version alignment with core Moltbot release numbers.
|
||||
|
||||
## 2026.1.17
|
||||
|
||||
### Changes
|
||||
- Version alignment with core Clawdbot release numbers.
|
||||
- Version alignment with core Moltbot release numbers.
|
||||
|
||||
## 2026.1.16
|
||||
|
||||
### Changes
|
||||
- Version alignment with core Clawdbot release numbers.
|
||||
- Version alignment with core Moltbot release numbers.
|
||||
|
||||
## 2026.1.15
|
||||
|
||||
### Changes
|
||||
- Version alignment with core Clawdbot release numbers.
|
||||
- Version alignment with core Moltbot release numbers.
|
||||
|
||||
## 2026.1.14
|
||||
|
||||
### Features
|
||||
- Version alignment with core Clawdbot release numbers.
|
||||
- Version alignment with core Moltbot release numbers.
|
||||
- Matrix channel plugin with homeserver + user ID auth (access token or password login with device name).
|
||||
- Direct messages with pairing/allowlist/open/disabled policies and allowFrom support.
|
||||
- Group/room controls: allowlist policy, per-room config, mention gating, auto-reply, per-room skills/system prompts.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ClawdbotPluginApi } from "clawdbot/plugin-sdk";
|
||||
import type { MoltbotPluginApi } from "clawdbot/plugin-sdk";
|
||||
import { emptyPluginConfigSchema } from "clawdbot/plugin-sdk";
|
||||
|
||||
import { matrixPlugin } from "./src/channel.js";
|
||||
@@ -9,7 +9,7 @@ const plugin = {
|
||||
name: "Matrix",
|
||||
description: "Matrix channel plugin (matrix-js-sdk)",
|
||||
configSchema: emptyPluginConfigSchema(),
|
||||
register(api: ClawdbotPluginApi) {
|
||||
register(api: MoltbotPluginApi) {
|
||||
setMatrixRuntime(api.runtime);
|
||||
api.registerChannel({ plugin: matrixPlugin });
|
||||
},
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
"name": "@moltbot/matrix",
|
||||
"version": "2026.1.26",
|
||||
"type": "module",
|
||||
"description": "Clawdbot Matrix channel plugin",
|
||||
"clawdbot": {
|
||||
"description": "Moltbot Matrix channel plugin",
|
||||
"moltbot": {
|
||||
"extensions": [
|
||||
"./index.ts"
|
||||
],
|
||||
@@ -31,6 +31,6 @@
|
||||
"zod": "^4.3.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"clawdbot": "workspace:*"
|
||||
"moltbot": "workspace:*"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@ export async function resolveMatrixAuth(params?: {
|
||||
type: "m.login.password",
|
||||
identifier: { type: "m.id.user", user: resolved.userId },
|
||||
password: resolved.password,
|
||||
initial_device_display_name: resolved.deviceName ?? "Clawdbot Gateway",
|
||||
initial_device_display_name: resolved.deviceName ?? "Moltbot Gateway",
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
@@ -252,12 +252,12 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam
|
||||
await sendMessageMatrix(
|
||||
`room:${roomId}`,
|
||||
[
|
||||
"Clawdbot: access not configured.",
|
||||
"Moltbot: access not configured.",
|
||||
"",
|
||||
`Pairing code: ${code}`,
|
||||
"",
|
||||
"Ask the bot owner to approve with:",
|
||||
"clawdbot pairing approve matrix <code>",
|
||||
"moltbot pairing approve matrix <code>",
|
||||
].join("\n"),
|
||||
{ client },
|
||||
);
|
||||
|
||||
@@ -318,7 +318,7 @@ export const matrixOnboardingAdapter: ChannelOnboardingAdapter = {
|
||||
const deviceName = String(
|
||||
await prompter.text({
|
||||
message: "Matrix device name (optional)",
|
||||
initialValue: existing.deviceName ?? "Clawdbot Gateway",
|
||||
initialValue: existing.deviceName ?? "Moltbot Gateway",
|
||||
}),
|
||||
).trim();
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ClawdbotPluginApi } from "clawdbot/plugin-sdk";
|
||||
import type { MoltbotPluginApi } from "clawdbot/plugin-sdk";
|
||||
import { emptyPluginConfigSchema } from "clawdbot/plugin-sdk";
|
||||
|
||||
import { mattermostPlugin } from "./src/channel.js";
|
||||
@@ -9,7 +9,7 @@ const plugin = {
|
||||
name: "Mattermost",
|
||||
description: "Mattermost channel plugin",
|
||||
configSchema: emptyPluginConfigSchema(),
|
||||
register(api: ClawdbotPluginApi) {
|
||||
register(api: MoltbotPluginApi) {
|
||||
setMattermostRuntime(api.runtime);
|
||||
api.registerChannel({ plugin: mattermostPlugin });
|
||||
},
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
"name": "@moltbot/mattermost",
|
||||
"version": "2026.1.26",
|
||||
"type": "module",
|
||||
"description": "Clawdbot Mattermost channel plugin",
|
||||
"clawdbot": {
|
||||
"description": "Moltbot Mattermost channel plugin",
|
||||
"moltbot": {
|
||||
"extensions": [
|
||||
"./index.ts"
|
||||
],
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ClawdbotConfig } from "clawdbot/plugin-sdk";
|
||||
import type { MoltbotConfig } from "clawdbot/plugin-sdk";
|
||||
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "clawdbot/plugin-sdk";
|
||||
|
||||
import type { MattermostAccountConfig, MattermostChatMode } from "../types.js";
|
||||
@@ -24,26 +24,26 @@ export type ResolvedMattermostAccount = {
|
||||
blockStreamingCoalesce?: MattermostAccountConfig["blockStreamingCoalesce"];
|
||||
};
|
||||
|
||||
function listConfiguredAccountIds(cfg: ClawdbotConfig): string[] {
|
||||
function listConfiguredAccountIds(cfg: MoltbotConfig): string[] {
|
||||
const accounts = cfg.channels?.mattermost?.accounts;
|
||||
if (!accounts || typeof accounts !== "object") return [];
|
||||
return Object.keys(accounts).filter(Boolean);
|
||||
}
|
||||
|
||||
export function listMattermostAccountIds(cfg: ClawdbotConfig): string[] {
|
||||
export function listMattermostAccountIds(cfg: MoltbotConfig): string[] {
|
||||
const ids = listConfiguredAccountIds(cfg);
|
||||
if (ids.length === 0) return [DEFAULT_ACCOUNT_ID];
|
||||
return ids.sort((a, b) => a.localeCompare(b));
|
||||
}
|
||||
|
||||
export function resolveDefaultMattermostAccountId(cfg: ClawdbotConfig): string {
|
||||
export function resolveDefaultMattermostAccountId(cfg: MoltbotConfig): string {
|
||||
const ids = listMattermostAccountIds(cfg);
|
||||
if (ids.includes(DEFAULT_ACCOUNT_ID)) return DEFAULT_ACCOUNT_ID;
|
||||
return ids[0] ?? DEFAULT_ACCOUNT_ID;
|
||||
}
|
||||
|
||||
function resolveAccountConfig(
|
||||
cfg: ClawdbotConfig,
|
||||
cfg: MoltbotConfig,
|
||||
accountId: string,
|
||||
): MattermostAccountConfig | undefined {
|
||||
const accounts = cfg.channels?.mattermost?.accounts;
|
||||
@@ -52,7 +52,7 @@ function resolveAccountConfig(
|
||||
}
|
||||
|
||||
function mergeMattermostAccountConfig(
|
||||
cfg: ClawdbotConfig,
|
||||
cfg: MoltbotConfig,
|
||||
accountId: string,
|
||||
): MattermostAccountConfig {
|
||||
const { accounts: _ignored, ...base } = (cfg.channels?.mattermost ??
|
||||
@@ -69,7 +69,7 @@ function resolveMattermostRequireMention(config: MattermostAccountConfig): boole
|
||||
}
|
||||
|
||||
export function resolveMattermostAccount(params: {
|
||||
cfg: ClawdbotConfig;
|
||||
cfg: MoltbotConfig;
|
||||
accountId?: string | null;
|
||||
}): ResolvedMattermostAccount {
|
||||
const accountId = normalizeAccountId(params.accountId);
|
||||
@@ -108,7 +108,7 @@ export function resolveMattermostAccount(params: {
|
||||
};
|
||||
}
|
||||
|
||||
export function listEnabledMattermostAccounts(cfg: ClawdbotConfig): ResolvedMattermostAccount[] {
|
||||
export function listEnabledMattermostAccounts(cfg: MoltbotConfig): ResolvedMattermostAccount[] {
|
||||
return listMattermostAccountIds(cfg)
|
||||
.map((accountId) => resolveMattermostAccount({ cfg, accountId }))
|
||||
.filter((account) => account.enabled);
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Buffer } from "node:buffer";
|
||||
|
||||
import type WebSocket from "ws";
|
||||
|
||||
import type { ClawdbotConfig } from "clawdbot/plugin-sdk";
|
||||
import type { MoltbotConfig } from "clawdbot/plugin-sdk";
|
||||
|
||||
export type ResponsePrefixContext = {
|
||||
model?: string;
|
||||
@@ -114,20 +114,20 @@ function normalizeAgentId(value: string | undefined | null): string {
|
||||
);
|
||||
}
|
||||
|
||||
type AgentEntry = NonNullable<NonNullable<ClawdbotConfig["agents"]>["list"]>[number];
|
||||
type AgentEntry = NonNullable<NonNullable<MoltbotConfig["agents"]>["list"]>[number];
|
||||
|
||||
function listAgents(cfg: ClawdbotConfig): AgentEntry[] {
|
||||
function listAgents(cfg: MoltbotConfig): AgentEntry[] {
|
||||
const list = cfg.agents?.list;
|
||||
if (!Array.isArray(list)) return [];
|
||||
return list.filter((entry): entry is AgentEntry => Boolean(entry && typeof entry === "object"));
|
||||
}
|
||||
|
||||
function resolveAgentEntry(cfg: ClawdbotConfig, agentId: string): AgentEntry | undefined {
|
||||
function resolveAgentEntry(cfg: MoltbotConfig, agentId: string): AgentEntry | undefined {
|
||||
const id = normalizeAgentId(agentId);
|
||||
return listAgents(cfg).find((entry) => normalizeAgentId(entry.id) === id);
|
||||
}
|
||||
|
||||
export function resolveIdentityName(cfg: ClawdbotConfig, agentId: string): string | undefined {
|
||||
export function resolveIdentityName(cfg: MoltbotConfig, agentId: string): string | undefined {
|
||||
const entry = resolveAgentEntry(cfg, agentId);
|
||||
return entry?.identity?.name?.trim() || undefined;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import WebSocket from "ws";
|
||||
|
||||
import type {
|
||||
ChannelAccountSnapshot,
|
||||
ClawdbotConfig,
|
||||
MoltbotConfig,
|
||||
ReplyPayload,
|
||||
RuntimeEnv,
|
||||
} from "clawdbot/plugin-sdk";
|
||||
@@ -45,7 +45,7 @@ export type MonitorMattermostOpts = {
|
||||
botToken?: string;
|
||||
baseUrl?: string;
|
||||
accountId?: string;
|
||||
config?: ClawdbotConfig;
|
||||
config?: MoltbotConfig;
|
||||
runtime?: RuntimeEnv;
|
||||
abortSignal?: AbortSignal;
|
||||
statusSink?: (patch: Partial<ChannelAccountSnapshot>) => void;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import type { ClawdbotConfig, WizardPrompter } from "clawdbot/plugin-sdk";
|
||||
import type { MoltbotConfig, WizardPrompter } from "clawdbot/plugin-sdk";
|
||||
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "clawdbot/plugin-sdk";
|
||||
|
||||
type PromptAccountIdParams = {
|
||||
cfg: ClawdbotConfig;
|
||||
cfg: MoltbotConfig;
|
||||
prompter: WizardPrompter;
|
||||
label: string;
|
||||
currentId?: string;
|
||||
listAccountIds: (cfg: ClawdbotConfig) => string[];
|
||||
listAccountIds: (cfg: MoltbotConfig) => string[];
|
||||
defaultAccountId: string;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ChannelOnboardingAdapter, ClawdbotConfig, WizardPrompter } from "clawdbot/plugin-sdk";
|
||||
import type { ChannelOnboardingAdapter, MoltbotConfig, WizardPrompter } from "clawdbot/plugin-sdk";
|
||||
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "clawdbot/plugin-sdk";
|
||||
|
||||
import {
|
||||
@@ -177,7 +177,7 @@ export const mattermostOnboardingAdapter: ChannelOnboardingAdapter = {
|
||||
|
||||
return { cfg: next, accountId };
|
||||
},
|
||||
disable: (cfg: ClawdbotConfig) => ({
|
||||
disable: (cfg: MoltbotConfig) => ({
|
||||
...cfg,
|
||||
channels: {
|
||||
...cfg.channels,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ClawdbotPluginApi } from "clawdbot/plugin-sdk";
|
||||
import type { MoltbotPluginApi } from "clawdbot/plugin-sdk";
|
||||
import { emptyPluginConfigSchema } from "clawdbot/plugin-sdk";
|
||||
|
||||
const memoryCorePlugin = {
|
||||
@@ -7,7 +7,7 @@ const memoryCorePlugin = {
|
||||
description: "File-backed memory search tools and CLI",
|
||||
kind: "memory",
|
||||
configSchema: emptyPluginConfigSchema(),
|
||||
register(api: ClawdbotPluginApi) {
|
||||
register(api: MoltbotPluginApi) {
|
||||
api.registerTool(
|
||||
(ctx) => {
|
||||
const memorySearchTool = api.runtime.tools.createMemorySearchTool({
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
"name": "@moltbot/memory-core",
|
||||
"version": "2026.1.26",
|
||||
"type": "module",
|
||||
"description": "Clawdbot core memory search plugin",
|
||||
"clawdbot": {
|
||||
"description": "Moltbot core memory search plugin",
|
||||
"moltbot": {
|
||||
"extensions": [
|
||||
"./index.ts"
|
||||
]
|
||||
},
|
||||
"peerDependencies": {
|
||||
"clawdbot": ">=2026.1.26"
|
||||
"moltbot": ">=2026.1.26"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ describe("memory plugin e2e", () => {
|
||||
let dbPath: string;
|
||||
|
||||
beforeEach(async () => {
|
||||
tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-memory-test-"));
|
||||
tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-memory-test-"));
|
||||
dbPath = path.join(tmpDir, "lancedb");
|
||||
});
|
||||
|
||||
@@ -165,7 +165,7 @@ describeLive("memory plugin live tests", () => {
|
||||
let dbPath: string;
|
||||
|
||||
beforeEach(async () => {
|
||||
tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-memory-live-"));
|
||||
tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-memory-live-"));
|
||||
dbPath = path.join(tmpDir, "lancedb");
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Clawdbot Memory (LanceDB) Plugin
|
||||
* Moltbot Memory (LanceDB) Plugin
|
||||
*
|
||||
* Long-term memory with vector search for AI conversations.
|
||||
* Uses LanceDB for storage and OpenAI for embeddings.
|
||||
@@ -10,7 +10,7 @@ import { Type } from "@sinclair/typebox";
|
||||
import * as lancedb from "@lancedb/lancedb";
|
||||
import OpenAI from "openai";
|
||||
import { randomUUID } from "node:crypto";
|
||||
import type { ClawdbotPluginApi } from "clawdbot/plugin-sdk";
|
||||
import type { MoltbotPluginApi } from "clawdbot/plugin-sdk";
|
||||
import { stringEnum } from "clawdbot/plugin-sdk";
|
||||
|
||||
import {
|
||||
@@ -220,7 +220,7 @@ const memoryPlugin = {
|
||||
kind: "memory" as const,
|
||||
configSchema: memoryConfigSchema,
|
||||
|
||||
register(api: ClawdbotPluginApi) {
|
||||
register(api: MoltbotPluginApi) {
|
||||
const cfg = memoryConfigSchema.parse(api.pluginConfig);
|
||||
const resolvedDbPath = api.resolvePath(cfg.dbPath!);
|
||||
const vectorDim = vectorDimsForModel(cfg.embedding.model ?? "text-embedding-3-small");
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
"name": "@moltbot/memory-lancedb",
|
||||
"version": "2026.1.26",
|
||||
"type": "module",
|
||||
"description": "Clawdbot LanceDB-backed long-term memory plugin with auto-recall/capture",
|
||||
"description": "Moltbot LanceDB-backed long-term memory plugin with auto-recall/capture",
|
||||
"dependencies": {
|
||||
"@lancedb/lancedb": "^0.23.0",
|
||||
"@sinclair/typebox": "0.34.47",
|
||||
"openai": "^6.16.0"
|
||||
},
|
||||
"clawdbot": {
|
||||
"moltbot": {
|
||||
"extensions": [
|
||||
"./index.ts"
|
||||
]
|
||||
|
||||
@@ -3,37 +3,37 @@
|
||||
## 2026.1.23
|
||||
|
||||
### Changes
|
||||
- Version alignment with core Clawdbot release numbers.
|
||||
- Version alignment with core Moltbot release numbers.
|
||||
|
||||
## 2026.1.22
|
||||
|
||||
### Changes
|
||||
- Version alignment with core Clawdbot release numbers.
|
||||
- Version alignment with core Moltbot release numbers.
|
||||
|
||||
## 2026.1.21
|
||||
|
||||
### Changes
|
||||
- Version alignment with core Clawdbot release numbers.
|
||||
- Version alignment with core Moltbot release numbers.
|
||||
|
||||
## 2026.1.20
|
||||
|
||||
### Changes
|
||||
- Version alignment with core Clawdbot release numbers.
|
||||
- Version alignment with core Moltbot release numbers.
|
||||
|
||||
## 2026.1.17-1
|
||||
|
||||
### Changes
|
||||
- Version alignment with core Clawdbot release numbers.
|
||||
- Version alignment with core Moltbot release numbers.
|
||||
|
||||
## 2026.1.17
|
||||
|
||||
### Changes
|
||||
- Version alignment with core Clawdbot release numbers.
|
||||
- Version alignment with core Moltbot release numbers.
|
||||
|
||||
## 2026.1.16
|
||||
|
||||
### Changes
|
||||
- Version alignment with core Clawdbot release numbers.
|
||||
- Version alignment with core Moltbot release numbers.
|
||||
|
||||
## 2026.1.15
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ClawdbotPluginApi } from "clawdbot/plugin-sdk";
|
||||
import type { MoltbotPluginApi } from "clawdbot/plugin-sdk";
|
||||
import { emptyPluginConfigSchema } from "clawdbot/plugin-sdk";
|
||||
|
||||
import { msteamsPlugin } from "./src/channel.js";
|
||||
@@ -9,7 +9,7 @@ const plugin = {
|
||||
name: "Microsoft Teams",
|
||||
description: "Microsoft Teams channel plugin (Bot Framework)",
|
||||
configSchema: emptyPluginConfigSchema(),
|
||||
register(api: ClawdbotPluginApi) {
|
||||
register(api: MoltbotPluginApi) {
|
||||
setMSTeamsRuntime(api.runtime);
|
||||
api.registerChannel({ plugin: msteamsPlugin });
|
||||
},
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
"name": "@moltbot/msteams",
|
||||
"version": "2026.1.26",
|
||||
"type": "module",
|
||||
"description": "Clawdbot Microsoft Teams channel plugin",
|
||||
"clawdbot": {
|
||||
"description": "Moltbot Microsoft Teams channel plugin",
|
||||
"moltbot": {
|
||||
"extensions": [
|
||||
"./index.ts"
|
||||
],
|
||||
@@ -29,7 +29,7 @@
|
||||
"@microsoft/agents-hosting": "^1.2.2",
|
||||
"@microsoft/agents-hosting-express": "^1.2.2",
|
||||
"@microsoft/agents-hosting-extensions-teams": "^1.2.2",
|
||||
"clawdbot": "workspace:*",
|
||||
"moltbot": "workspace:*",
|
||||
"express": "^5.2.1",
|
||||
"proper-lockfile": "^4.1.2"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import type { ClawdbotConfig } from "clawdbot/plugin-sdk";
|
||||
import type { MoltbotConfig } from "clawdbot/plugin-sdk";
|
||||
|
||||
import { msteamsPlugin } from "./channel.js";
|
||||
|
||||
@@ -21,7 +21,7 @@ describe("msteams directory", () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
} as unknown as ClawdbotConfig;
|
||||
} as unknown as MoltbotConfig;
|
||||
|
||||
expect(msteamsPlugin.directory).toBeTruthy();
|
||||
expect(msteamsPlugin.directory?.listPeers).toBeTruthy();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ChannelMessageActionName, ChannelPlugin, ClawdbotConfig } from "clawdbot/plugin-sdk";
|
||||
import type { ChannelMessageActionName, ChannelPlugin, MoltbotConfig } from "clawdbot/plugin-sdk";
|
||||
import {
|
||||
buildChannelConfigSchema,
|
||||
DEFAULT_ACCOUNT_ID,
|
||||
@@ -102,7 +102,7 @@ export const msteamsPlugin: ChannelPlugin<ResolvedMSTeamsAccount> = {
|
||||
},
|
||||
}),
|
||||
deleteAccount: ({ cfg }) => {
|
||||
const next = { ...cfg } as ClawdbotConfig;
|
||||
const next = { ...cfg } as MoltbotConfig;
|
||||
const nextChannels = { ...cfg.channels };
|
||||
delete nextChannels.msteams;
|
||||
if (Object.keys(nextChannels).length > 0) {
|
||||
|
||||
@@ -26,7 +26,7 @@ describe("msteams conversation store (fs)", () => {
|
||||
});
|
||||
|
||||
it("filters and prunes expired entries (but keeps legacy ones)", async () => {
|
||||
const stateDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), "clawdbot-msteams-store-"));
|
||||
const stateDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), "moltbot-msteams-store-"));
|
||||
|
||||
const env: NodeJS.ProcessEnv = {
|
||||
...process.env,
|
||||
|
||||
@@ -36,8 +36,8 @@ export async function uploadToOneDrive(params: {
|
||||
const fetchFn = params.fetchFn ?? fetch;
|
||||
const token = await params.tokenProvider.getAccessToken(GRAPH_SCOPE);
|
||||
|
||||
// Use "ClawdbotShared" folder to organize bot-uploaded files
|
||||
const uploadPath = `/ClawdbotShared/${encodeURIComponent(params.filename)}`;
|
||||
// Use "MoltbotShared" folder to organize bot-uploaded files
|
||||
const uploadPath = `/MoltbotShared/${encodeURIComponent(params.filename)}`;
|
||||
|
||||
const res = await fetchFn(`${GRAPH_ROOT}/me/drive/root:${uploadPath}:/content`, {
|
||||
method: "PUT",
|
||||
@@ -179,8 +179,8 @@ export async function uploadToSharePoint(params: {
|
||||
const fetchFn = params.fetchFn ?? fetch;
|
||||
const token = await params.tokenProvider.getAccessToken(GRAPH_SCOPE);
|
||||
|
||||
// Use "ClawdbotShared" folder to organize bot-uploaded files
|
||||
const uploadPath = `/ClawdbotShared/${encodeURIComponent(params.filename)}`;
|
||||
// Use "MoltbotShared" folder to organize bot-uploaded files
|
||||
const uploadPath = `/MoltbotShared/${encodeURIComponent(params.filename)}`;
|
||||
|
||||
const res = await fetchFn(`${GRAPH_ROOT}/sites/${params.siteId}/drive/root:${uploadPath}:/content`, {
|
||||
method: "PUT",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ClawdbotConfig, RuntimeEnv } from "clawdbot/plugin-sdk";
|
||||
import type { MoltbotConfig, RuntimeEnv } from "clawdbot/plugin-sdk";
|
||||
import type { MSTeamsConversationStore } from "./conversation-store.js";
|
||||
import {
|
||||
buildFileInfoCard,
|
||||
@@ -27,7 +27,7 @@ export type MSTeamsActivityHandler = {
|
||||
};
|
||||
|
||||
export type MSTeamsMessageHandlerDeps = {
|
||||
cfg: ClawdbotConfig;
|
||||
cfg: MoltbotConfig;
|
||||
runtime: RuntimeEnv;
|
||||
appId: string;
|
||||
adapter: MSTeamsAdapter;
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { Request, Response } from "express";
|
||||
import {
|
||||
mergeAllowlist,
|
||||
summarizeMapping,
|
||||
type ClawdbotConfig,
|
||||
type MoltbotConfig,
|
||||
type RuntimeEnv,
|
||||
} from "clawdbot/plugin-sdk";
|
||||
import type { MSTeamsConversationStore } from "./conversation-store.js";
|
||||
@@ -20,7 +20,7 @@ import { resolveMSTeamsCredentials } from "./token.js";
|
||||
import { getMSTeamsRuntime } from "./runtime.js";
|
||||
|
||||
export type MonitorMSTeamsOpts = {
|
||||
cfg: ClawdbotConfig;
|
||||
cfg: MoltbotConfig;
|
||||
runtime?: RuntimeEnv;
|
||||
abortSignal?: AbortSignal;
|
||||
conversationStore?: MSTeamsConversationStore;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type {
|
||||
ChannelOnboardingAdapter,
|
||||
ChannelOnboardingDmPolicy,
|
||||
ClawdbotConfig,
|
||||
MoltbotConfig,
|
||||
DmPolicy,
|
||||
WizardPrompter,
|
||||
} from "clawdbot/plugin-sdk";
|
||||
@@ -21,7 +21,7 @@ import {
|
||||
|
||||
const channel = "msteams" as const;
|
||||
|
||||
function setMSTeamsDmPolicy(cfg: ClawdbotConfig, dmPolicy: DmPolicy) {
|
||||
function setMSTeamsDmPolicy(cfg: MoltbotConfig, dmPolicy: DmPolicy) {
|
||||
const allowFrom =
|
||||
dmPolicy === "open"
|
||||
? addWildcardAllowFrom(cfg.channels?.msteams?.allowFrom)?.map((entry) => String(entry))
|
||||
@@ -39,7 +39,7 @@ function setMSTeamsDmPolicy(cfg: ClawdbotConfig, dmPolicy: DmPolicy) {
|
||||
};
|
||||
}
|
||||
|
||||
function setMSTeamsAllowFrom(cfg: ClawdbotConfig, allowFrom: string[]): ClawdbotConfig {
|
||||
function setMSTeamsAllowFrom(cfg: MoltbotConfig, allowFrom: string[]): MoltbotConfig {
|
||||
return {
|
||||
...cfg,
|
||||
channels: {
|
||||
@@ -64,9 +64,9 @@ function looksLikeGuid(value: string): boolean {
|
||||
}
|
||||
|
||||
async function promptMSTeamsAllowFrom(params: {
|
||||
cfg: ClawdbotConfig;
|
||||
cfg: MoltbotConfig;
|
||||
prompter: WizardPrompter;
|
||||
}): Promise<ClawdbotConfig> {
|
||||
}): Promise<MoltbotConfig> {
|
||||
const existing = params.cfg.channels?.msteams?.allowFrom ?? [];
|
||||
await params.prompter.note(
|
||||
[
|
||||
@@ -144,9 +144,9 @@ async function noteMSTeamsCredentialHelp(prompter: WizardPrompter): Promise<void
|
||||
}
|
||||
|
||||
function setMSTeamsGroupPolicy(
|
||||
cfg: ClawdbotConfig,
|
||||
cfg: MoltbotConfig,
|
||||
groupPolicy: "open" | "allowlist" | "disabled",
|
||||
): ClawdbotConfig {
|
||||
): MoltbotConfig {
|
||||
return {
|
||||
...cfg,
|
||||
channels: {
|
||||
@@ -161,9 +161,9 @@ function setMSTeamsGroupPolicy(
|
||||
}
|
||||
|
||||
function setMSTeamsTeamsAllowlist(
|
||||
cfg: ClawdbotConfig,
|
||||
cfg: MoltbotConfig,
|
||||
entries: Array<{ teamKey: string; channelKey?: string }>,
|
||||
): ClawdbotConfig {
|
||||
): MoltbotConfig {
|
||||
const baseTeams = cfg.channels?.msteams?.teams ?? {};
|
||||
const teams: Record<string, { channels?: Record<string, unknown> }> = { ...baseTeams };
|
||||
for (const entry of entries) {
|
||||
|
||||
@@ -8,7 +8,7 @@ import { createMSTeamsPollStoreFs } from "./polls.js";
|
||||
import { createMSTeamsPollStoreMemory } from "./polls-store-memory.js";
|
||||
|
||||
const createFsStore = async () => {
|
||||
const stateDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), "clawdbot-msteams-polls-"));
|
||||
const stateDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), "moltbot-msteams-polls-"));
|
||||
return createMSTeamsPollStoreFs({ stateDir });
|
||||
};
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ describe("msteams polls", () => {
|
||||
it("extracts poll votes from activity values", () => {
|
||||
const vote = extractMSTeamsPollVote({
|
||||
value: {
|
||||
clawdbotPollId: "poll-1",
|
||||
moltbotPollId: "poll-1",
|
||||
choices: "0,1",
|
||||
},
|
||||
});
|
||||
@@ -51,7 +51,7 @@ describe("msteams polls", () => {
|
||||
});
|
||||
|
||||
it("stores and records poll votes", async () => {
|
||||
const home = await fs.promises.mkdtemp(path.join(os.tmpdir(), "clawdbot-msteams-polls-"));
|
||||
const home = await fs.promises.mkdtemp(path.join(os.tmpdir(), "moltbot-msteams-polls-"));
|
||||
const store = createMSTeamsPollStoreFs({ homedir: () => home });
|
||||
await store.createPoll({
|
||||
id: "poll-2",
|
||||
|
||||
@@ -97,13 +97,13 @@ export function extractMSTeamsPollVote(
|
||||
const value = activity?.value;
|
||||
if (!value || !isRecord(value)) return null;
|
||||
const pollId =
|
||||
readNestedString(value, ["clawdbotPollId"]) ??
|
||||
readNestedString(value, ["moltbotPollId"]) ??
|
||||
readNestedString(value, ["pollId"]) ??
|
||||
readNestedString(value, ["clawdbot", "pollId"]) ??
|
||||
readNestedString(value, ["clawdbot", "poll", "id"]) ??
|
||||
readNestedString(value, ["data", "clawdbotPollId"]) ??
|
||||
readNestedString(value, ["moltbot", "pollId"]) ??
|
||||
readNestedString(value, ["moltbot", "poll", "id"]) ??
|
||||
readNestedString(value, ["data", "moltbotPollId"]) ??
|
||||
readNestedString(value, ["data", "pollId"]) ??
|
||||
readNestedString(value, ["data", "clawdbot", "pollId"]);
|
||||
readNestedString(value, ["data", "moltbot", "pollId"]);
|
||||
if (!pollId) return null;
|
||||
|
||||
const directSelections = extractSelections(value.choices);
|
||||
@@ -176,13 +176,13 @@ export function buildMSTeamsPollCard(params: {
|
||||
type: "Action.Submit",
|
||||
title: "Vote",
|
||||
data: {
|
||||
clawdbotPollId: pollId,
|
||||
moltbotPollId: pollId,
|
||||
},
|
||||
msteams: {
|
||||
type: "messageBack",
|
||||
text: "clawdbot poll vote",
|
||||
text: "moltbot poll vote",
|
||||
displayText: "Vote recorded",
|
||||
value: { clawdbotPollId: pollId },
|
||||
value: { moltbotPollId: pollId },
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@@ -3,7 +3,7 @@ import {
|
||||
createTypingCallbacks,
|
||||
logTypingFailure,
|
||||
resolveChannelMediaMaxBytes,
|
||||
type ClawdbotConfig,
|
||||
type MoltbotConfig,
|
||||
type MSTeamsReplyStyle,
|
||||
type RuntimeEnv,
|
||||
} from "clawdbot/plugin-sdk";
|
||||
@@ -24,7 +24,7 @@ import type { MSTeamsTurnContext } from "./sdk-types.js";
|
||||
import { getMSTeamsRuntime } from "./runtime.js";
|
||||
|
||||
export function createMSTeamsReplyDispatcher(params: {
|
||||
cfg: ClawdbotConfig;
|
||||
cfg: MoltbotConfig;
|
||||
agentId: string;
|
||||
runtime: RuntimeEnv;
|
||||
log: MSTeamsMonitorLogger;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { resolveChannelMediaMaxBytes, type ClawdbotConfig, type PluginRuntime } from "clawdbot/plugin-sdk";
|
||||
import { resolveChannelMediaMaxBytes, type MoltbotConfig, type PluginRuntime } from "clawdbot/plugin-sdk";
|
||||
import type { MSTeamsAccessTokenProvider } from "./attachments/types.js";
|
||||
import type {
|
||||
MSTeamsConversationStore,
|
||||
@@ -84,7 +84,7 @@ async function findConversationReference(recipient: {
|
||||
}
|
||||
|
||||
export async function resolveMSTeamsSendContext(params: {
|
||||
cfg: ClawdbotConfig;
|
||||
cfg: MoltbotConfig;
|
||||
to: string;
|
||||
}): Promise<MSTeamsProactiveContext> {
|
||||
const msteamsCfg = params.cfg.channels?.msteams;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { loadWebMedia, resolveChannelMediaMaxBytes } from "clawdbot/plugin-sdk";
|
||||
import type { ClawdbotConfig } from "clawdbot/plugin-sdk";
|
||||
import type { MoltbotConfig } from "clawdbot/plugin-sdk";
|
||||
import { createMSTeamsConversationStoreFs } from "./conversation-store-fs.js";
|
||||
import {
|
||||
classifyMSTeamsSendError,
|
||||
@@ -21,7 +21,7 @@ import { resolveMSTeamsSendContext, type MSTeamsProactiveContext } from "./send-
|
||||
|
||||
export type SendMSTeamsMessageParams = {
|
||||
/** Full config (for credentials) */
|
||||
cfg: ClawdbotConfig;
|
||||
cfg: MoltbotConfig;
|
||||
/** Conversation ID or user ID to send to */
|
||||
to: string;
|
||||
/** Message text */
|
||||
@@ -48,7 +48,7 @@ const MSTEAMS_MAX_MEDIA_BYTES = 100 * 1024 * 1024;
|
||||
|
||||
export type SendMSTeamsPollParams = {
|
||||
/** Full config (for credentials) */
|
||||
cfg: ClawdbotConfig;
|
||||
cfg: MoltbotConfig;
|
||||
/** Conversation ID or user ID to send to */
|
||||
to: string;
|
||||
/** Poll question */
|
||||
@@ -67,7 +67,7 @@ export type SendMSTeamsPollResult = {
|
||||
|
||||
export type SendMSTeamsCardParams = {
|
||||
/** Full config (for credentials) */
|
||||
cfg: ClawdbotConfig;
|
||||
cfg: MoltbotConfig;
|
||||
/** Conversation ID or user ID to send to */
|
||||
to: string;
|
||||
/** Adaptive Card JSON object */
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ClawdbotPluginApi } from "clawdbot/plugin-sdk";
|
||||
import type { MoltbotPluginApi } from "clawdbot/plugin-sdk";
|
||||
import { emptyPluginConfigSchema } from "clawdbot/plugin-sdk";
|
||||
|
||||
import { nextcloudTalkPlugin } from "./src/channel.js";
|
||||
@@ -9,7 +9,7 @@ const plugin = {
|
||||
name: "Nextcloud Talk",
|
||||
description: "Nextcloud Talk channel plugin",
|
||||
configSchema: emptyPluginConfigSchema(),
|
||||
register(api: ClawdbotPluginApi) {
|
||||
register(api: MoltbotPluginApi) {
|
||||
setNextcloudTalkRuntime(api.runtime);
|
||||
api.registerChannel({ plugin: nextcloudTalkPlugin });
|
||||
},
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
"name": "@moltbot/nextcloud-talk",
|
||||
"version": "2026.1.26",
|
||||
"type": "module",
|
||||
"description": "Clawdbot Nextcloud Talk channel plugin",
|
||||
"clawdbot": {
|
||||
"description": "Moltbot Nextcloud Talk channel plugin",
|
||||
"moltbot": {
|
||||
"extensions": [
|
||||
"./index.ts"
|
||||
],
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
normalizeAccountId,
|
||||
setAccountEnabledInConfigSection,
|
||||
type ChannelPlugin,
|
||||
type ClawdbotConfig,
|
||||
type MoltbotConfig,
|
||||
type ChannelSetupInput,
|
||||
} from "clawdbot/plugin-sdk";
|
||||
|
||||
@@ -173,7 +173,7 @@ export const nextcloudTalkPlugin: ChannelPlugin<ResolvedNextcloudTalkAccount> =
|
||||
resolveAccountId: ({ accountId }) => normalizeAccountId(accountId),
|
||||
applyAccountName: ({ cfg, accountId, name }) =>
|
||||
applyAccountNameToChannelSection({
|
||||
cfg: cfg as ClawdbotConfig,
|
||||
cfg: cfg as MoltbotConfig,
|
||||
channelKey: "nextcloud-talk",
|
||||
accountId,
|
||||
name,
|
||||
@@ -194,7 +194,7 @@ export const nextcloudTalkPlugin: ChannelPlugin<ResolvedNextcloudTalkAccount> =
|
||||
applyAccountConfig: ({ cfg, accountId, input }) => {
|
||||
const setupInput = input as NextcloudSetupInput;
|
||||
const namedConfig = applyAccountNameToChannelSection({
|
||||
cfg: cfg as ClawdbotConfig,
|
||||
cfg: cfg as MoltbotConfig,
|
||||
channelKey: "nextcloud-talk",
|
||||
accountId,
|
||||
name: setupInput.name,
|
||||
@@ -217,7 +217,7 @@ export const nextcloudTalkPlugin: ChannelPlugin<ResolvedNextcloudTalkAccount> =
|
||||
: {}),
|
||||
},
|
||||
},
|
||||
} as ClawdbotConfig;
|
||||
} as MoltbotConfig;
|
||||
}
|
||||
return {
|
||||
...namedConfig,
|
||||
@@ -241,7 +241,7 @@ export const nextcloudTalkPlugin: ChannelPlugin<ResolvedNextcloudTalkAccount> =
|
||||
},
|
||||
},
|
||||
},
|
||||
} as ClawdbotConfig;
|
||||
} as MoltbotConfig;
|
||||
},
|
||||
},
|
||||
outbound: {
|
||||
@@ -323,7 +323,7 @@ export const nextcloudTalkPlugin: ChannelPlugin<ResolvedNextcloudTalkAccount> =
|
||||
return { stop };
|
||||
},
|
||||
logoutAccount: async ({ accountId, cfg }) => {
|
||||
const nextCfg = { ...cfg } as ClawdbotConfig;
|
||||
const nextCfg = { ...cfg } as MoltbotConfig;
|
||||
const nextSection = cfg.channels?.["nextcloud-talk"]
|
||||
? { ...cfg.channels["nextcloud-talk"] }
|
||||
: undefined;
|
||||
@@ -377,7 +377,7 @@ export const nextcloudTalkPlugin: ChannelPlugin<ResolvedNextcloudTalkAccount> =
|
||||
const nextChannels = { ...nextCfg.channels } as Record<string, unknown>;
|
||||
delete nextChannels["nextcloud-talk"];
|
||||
if (Object.keys(nextChannels).length > 0) {
|
||||
nextCfg.channels = nextChannels as ClawdbotConfig["channels"];
|
||||
nextCfg.channels = nextChannels as MoltbotConfig["channels"];
|
||||
} else {
|
||||
delete nextCfg.channels;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {
|
||||
logInboundDrop,
|
||||
resolveControlCommandGate,
|
||||
type ClawdbotConfig,
|
||||
type MoltbotConfig,
|
||||
type RuntimeEnv,
|
||||
} from "clawdbot/plugin-sdk";
|
||||
|
||||
@@ -114,7 +114,7 @@ export async function handleNextcloudTalkInbound(params: {
|
||||
const effectiveGroupAllowFrom = [...baseGroupAllowFrom, ...storeAllowList].filter(Boolean);
|
||||
|
||||
const allowTextCommands = core.channel.commands.shouldHandleTextCommands({
|
||||
cfg: config as ClawdbotConfig,
|
||||
cfg: config as MoltbotConfig,
|
||||
surface: CHANNEL_ID,
|
||||
});
|
||||
const useAccessGroups = config.commands?.useAccessGroups !== false;
|
||||
@@ -125,7 +125,7 @@ export async function handleNextcloudTalkInbound(params: {
|
||||
}).allowed;
|
||||
const hasControlCommand = core.channel.text.hasControlCommand(
|
||||
rawBody,
|
||||
config as ClawdbotConfig,
|
||||
config as MoltbotConfig,
|
||||
);
|
||||
const commandGate = resolveControlCommandGate({
|
||||
useAccessGroups,
|
||||
@@ -211,7 +211,7 @@ export async function handleNextcloudTalkInbound(params: {
|
||||
}
|
||||
|
||||
const mentionRegexes = core.channel.mentions.buildMentionRegexes(
|
||||
config as ClawdbotConfig,
|
||||
config as MoltbotConfig,
|
||||
);
|
||||
const wasMentioned = mentionRegexes.length
|
||||
? core.channel.mentions.matchesMentionPatterns(rawBody, mentionRegexes)
|
||||
@@ -236,7 +236,7 @@ export async function handleNextcloudTalkInbound(params: {
|
||||
}
|
||||
|
||||
const route = core.channel.routing.resolveAgentRoute({
|
||||
cfg: config as ClawdbotConfig,
|
||||
cfg: config as MoltbotConfig,
|
||||
channel: CHANNEL_ID,
|
||||
accountId: account.accountId,
|
||||
peer: {
|
||||
@@ -252,7 +252,7 @@ export async function handleNextcloudTalkInbound(params: {
|
||||
agentId: route.agentId,
|
||||
});
|
||||
const envelopeOptions = core.channel.reply.resolveEnvelopeFormatOptions(
|
||||
config as ClawdbotConfig,
|
||||
config as MoltbotConfig,
|
||||
);
|
||||
const previousTimestamp = core.channel.session.readSessionUpdatedAt({
|
||||
storePath,
|
||||
@@ -304,7 +304,7 @@ export async function handleNextcloudTalkInbound(params: {
|
||||
|
||||
await core.channel.reply.dispatchReplyWithBufferedBlockDispatcher({
|
||||
ctx: ctxPayload,
|
||||
cfg: config as ClawdbotConfig,
|
||||
cfg: config as MoltbotConfig,
|
||||
dispatcherOptions: {
|
||||
deliver: async (payload) => {
|
||||
await deliverNextcloudTalkReply({
|
||||
|
||||
@@ -43,7 +43,7 @@ async function noteNextcloudTalkSecretHelp(prompter: WizardPrompter): Promise<vo
|
||||
await prompter.note(
|
||||
[
|
||||
"1) SSH into your Nextcloud server",
|
||||
'2) Run: ./occ talk:bot:install "Clawdbot" "<shared-secret>" "<webhook-url>" --feature reaction',
|
||||
'2) Run: ./occ talk:bot:install "Moltbot" "<shared-secret>" "<webhook-url>" --feature reaction',
|
||||
"3) Copy the shared secret you used in the command",
|
||||
"4) Enable the bot in your Nextcloud Talk room settings",
|
||||
"Tip: you can also set NEXTCLOUD_TALK_BOT_SECRET in your env.",
|
||||
|
||||
@@ -3,22 +3,22 @@
|
||||
## 2026.1.23
|
||||
|
||||
### Changes
|
||||
- Version alignment with core Clawdbot release numbers.
|
||||
- Version alignment with core Moltbot release numbers.
|
||||
|
||||
## 2026.1.22
|
||||
|
||||
### Changes
|
||||
- Version alignment with core Clawdbot release numbers.
|
||||
- Version alignment with core Moltbot release numbers.
|
||||
|
||||
## 2026.1.21
|
||||
|
||||
### Changes
|
||||
- Version alignment with core Clawdbot release numbers.
|
||||
- Version alignment with core Moltbot release numbers.
|
||||
|
||||
## 2026.1.20
|
||||
|
||||
### Changes
|
||||
- Version alignment with core Clawdbot release numbers.
|
||||
- Version alignment with core Moltbot release numbers.
|
||||
|
||||
## 2026.1.19-1
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ClawdbotPluginApi, ClawdbotConfig } from "clawdbot/plugin-sdk";
|
||||
import type { MoltbotPluginApi, MoltbotConfig } from "clawdbot/plugin-sdk";
|
||||
import { emptyPluginConfigSchema } from "clawdbot/plugin-sdk";
|
||||
|
||||
import { nostrPlugin } from "./src/channel.js";
|
||||
@@ -12,7 +12,7 @@ const plugin = {
|
||||
name: "Nostr",
|
||||
description: "Nostr DM channel plugin via NIP-04",
|
||||
configSchema: emptyPluginConfigSchema(),
|
||||
register(api: ClawdbotPluginApi) {
|
||||
register(api: MoltbotPluginApi) {
|
||||
setNostrRuntime(api.runtime);
|
||||
api.registerChannel({ plugin: nostrPlugin });
|
||||
|
||||
@@ -20,13 +20,13 @@ const plugin = {
|
||||
const httpHandler = createNostrProfileHttpHandler({
|
||||
getConfigProfile: (accountId: string) => {
|
||||
const runtime = getNostrRuntime();
|
||||
const cfg = runtime.config.loadConfig() as ClawdbotConfig;
|
||||
const cfg = runtime.config.loadConfig() as MoltbotConfig;
|
||||
const account = resolveNostrAccount({ cfg, accountId });
|
||||
return account.profile;
|
||||
},
|
||||
updateConfigProfile: async (accountId: string, profile: NostrProfile) => {
|
||||
const runtime = getNostrRuntime();
|
||||
const cfg = runtime.config.loadConfig() as ClawdbotConfig;
|
||||
const cfg = runtime.config.loadConfig() as MoltbotConfig;
|
||||
|
||||
// Build the config patch for channels.nostr.profile
|
||||
const channels = (cfg.channels ?? {}) as Record<string, unknown>;
|
||||
@@ -49,7 +49,7 @@ const plugin = {
|
||||
},
|
||||
getAccountInfo: (accountId: string) => {
|
||||
const runtime = getNostrRuntime();
|
||||
const cfg = runtime.config.loadConfig() as ClawdbotConfig;
|
||||
const cfg = runtime.config.loadConfig() as MoltbotConfig;
|
||||
const account = resolveNostrAccount({ cfg, accountId });
|
||||
if (!account.configured || !account.publicKey) {
|
||||
return null;
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
"name": "@moltbot/nostr",
|
||||
"version": "2026.1.26",
|
||||
"type": "module",
|
||||
"description": "Clawdbot Nostr channel plugin for NIP-04 encrypted DMs",
|
||||
"clawdbot": {
|
||||
"description": "Moltbot Nostr channel plugin for NIP-04 encrypted DMs",
|
||||
"moltbot": {
|
||||
"extensions": [
|
||||
"./index.ts"
|
||||
],
|
||||
@@ -24,7 +24,7 @@
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"clawdbot": "workspace:*",
|
||||
"moltbot": "workspace:*",
|
||||
"nostr-tools": "^2.20.0",
|
||||
"zod": "^4.3.6"
|
||||
}
|
||||
|
||||
@@ -221,7 +221,7 @@ export const nostrPlugin: ChannelPlugin<ResolvedNostrAccount> = {
|
||||
onMessage: async (senderPubkey, text, reply) => {
|
||||
ctx.log?.debug(`[${account.accountId}] DM from ${senderPubkey}: ${text.slice(0, 50)}...`);
|
||||
|
||||
// Forward to clawdbot's message pipeline
|
||||
// Forward to moltbot's message pipeline
|
||||
await runtime.channel.reply.handleInboundMessage({
|
||||
channel: "nostr",
|
||||
accountId: account.accountId,
|
||||
|
||||
@@ -14,7 +14,7 @@ import { setNostrRuntime } from "./runtime.js";
|
||||
|
||||
async function withTempStateDir<T>(fn: (dir: string) => Promise<T>) {
|
||||
const previous = process.env.CLAWDBOT_STATE_DIR;
|
||||
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-nostr-"));
|
||||
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-nostr-"));
|
||||
process.env.CLAWDBOT_STATE_DIR = dir;
|
||||
setNostrRuntime({
|
||||
state: {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ClawdbotConfig } from "clawdbot/plugin-sdk";
|
||||
import type { MoltbotConfig } from "clawdbot/plugin-sdk";
|
||||
import { getPublicKeyFromPrivate } from "./nostr-bus.js";
|
||||
import { DEFAULT_RELAYS } from "./nostr-bus.js";
|
||||
import type { NostrProfile } from "./config-schema.js";
|
||||
@@ -30,7 +30,7 @@ const DEFAULT_ACCOUNT_ID = "default";
|
||||
/**
|
||||
* List all configured Nostr account IDs
|
||||
*/
|
||||
export function listNostrAccountIds(cfg: ClawdbotConfig): string[] {
|
||||
export function listNostrAccountIds(cfg: MoltbotConfig): string[] {
|
||||
const nostrCfg = (cfg.channels as Record<string, unknown> | undefined)?.nostr as
|
||||
| NostrAccountConfig
|
||||
| undefined;
|
||||
@@ -46,7 +46,7 @@ export function listNostrAccountIds(cfg: ClawdbotConfig): string[] {
|
||||
/**
|
||||
* Get the default account ID
|
||||
*/
|
||||
export function resolveDefaultNostrAccountId(cfg: ClawdbotConfig): string {
|
||||
export function resolveDefaultNostrAccountId(cfg: MoltbotConfig): string {
|
||||
const ids = listNostrAccountIds(cfg);
|
||||
if (ids.includes(DEFAULT_ACCOUNT_ID)) return DEFAULT_ACCOUNT_ID;
|
||||
return ids[0] ?? DEFAULT_ACCOUNT_ID;
|
||||
@@ -56,7 +56,7 @@ export function resolveDefaultNostrAccountId(cfg: ClawdbotConfig): string {
|
||||
* Resolve a Nostr account from config
|
||||
*/
|
||||
export function resolveNostrAccount(opts: {
|
||||
cfg: ClawdbotConfig;
|
||||
cfg: MoltbotConfig;
|
||||
accountId?: string | null;
|
||||
}): ResolvedNostrAccount {
|
||||
const accountId = opts.accountId ?? DEFAULT_ACCOUNT_ID;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ClawdbotPluginApi } from "../../src/plugins/types.js";
|
||||
import type { MoltbotPluginApi } from "../../src/plugins/types.js";
|
||||
|
||||
export default function register(_api: ClawdbotPluginApi) {
|
||||
export default function register(_api: MoltbotPluginApi) {
|
||||
// OpenProse is delivered via plugin-shipped skills.
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"version": "2026.1.26",
|
||||
"type": "module",
|
||||
"description": "OpenProse VM skill pack plugin (slash command + telemetry).",
|
||||
"clawdbot": {
|
||||
"moltbot": {
|
||||
"extensions": [
|
||||
"./index.ts"
|
||||
]
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
---
|
||||
name: prose
|
||||
description: OpenProse VM skill pack. Activate on any `prose` command, .prose files, or OpenProse mentions; orchestrates multi-agent workflows.
|
||||
metadata: {"clawdbot":{"emoji":"🪶","homepage":"https://www.prose.md"}}
|
||||
metadata: {"moltbot":{"emoji":"🪶","homepage":"https://www.prose.md"}}
|
||||
---
|
||||
|
||||
# OpenProse Skill
|
||||
|
||||
OpenProse is a programming language for AI sessions. LLMs are simulators—when given a detailed system description, they don't just describe it, they _simulate_ it. The `prose.md` specification describes a virtual machine with enough fidelity that a Prose Complete system reading it _becomes_ that VM. Simulation with sufficient fidelity is implementation. **You are the Prose Complete system.**
|
||||
|
||||
## Clawdbot Runtime Mapping
|
||||
## Moltbot Runtime Mapping
|
||||
|
||||
- **Task tool** in the upstream spec == Clawdbot `sessions_spawn`
|
||||
- **File I/O** == Clawdbot `read`/`write`
|
||||
- **Remote fetch** == Clawdbot `web_fetch` (or `exec` with curl when POST is required)
|
||||
- **Task tool** in the upstream spec == Moltbot `sessions_spawn`
|
||||
- **File I/O** == Moltbot `read`/`write`
|
||||
- **Remote fetch** == Moltbot `web_fetch` (or `exec` with curl when POST is required)
|
||||
|
||||
## When to Activate
|
||||
|
||||
|
||||
@@ -18,11 +18,11 @@ see-also:
|
||||
|
||||
This document defines how to execute OpenProse programs. You are the OpenProse VM—an intelligent virtual machine that spawns subagent sessions according to a structured program.
|
||||
|
||||
## Clawdbot Runtime Mapping
|
||||
## Moltbot Runtime Mapping
|
||||
|
||||
- **Task tool** in the upstream spec == Clawdbot `sessions_spawn`
|
||||
- **File I/O** == Clawdbot `read`/`write`
|
||||
- **Remote fetch** == Clawdbot `web_fetch` (or `exec` with curl when POST is required)
|
||||
- **Task tool** in the upstream spec == Moltbot `sessions_spawn`
|
||||
- **File I/O** == Moltbot `read`/`write`
|
||||
- **Remote fetch** == Moltbot `web_fetch` (or `exec` with curl when POST is required)
|
||||
|
||||
## CLI Commands
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ClawdbotPluginApi } from "clawdbot/plugin-sdk";
|
||||
import type { MoltbotPluginApi } from "clawdbot/plugin-sdk";
|
||||
import { emptyPluginConfigSchema } from "clawdbot/plugin-sdk";
|
||||
|
||||
import { signalPlugin } from "./src/channel.js";
|
||||
@@ -9,7 +9,7 @@ const plugin = {
|
||||
name: "Signal",
|
||||
description: "Signal channel plugin",
|
||||
configSchema: emptyPluginConfigSchema(),
|
||||
register(api: ClawdbotPluginApi) {
|
||||
register(api: MoltbotPluginApi) {
|
||||
setSignalRuntime(api.runtime);
|
||||
api.registerChannel({ plugin: signalPlugin });
|
||||
},
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
"name": "@moltbot/signal",
|
||||
"version": "2026.1.26",
|
||||
"type": "module",
|
||||
"description": "Clawdbot Signal channel plugin",
|
||||
"clawdbot": {
|
||||
"description": "Moltbot Signal channel plugin",
|
||||
"moltbot": {
|
||||
"extensions": [
|
||||
"./index.ts"
|
||||
]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ClawdbotPluginApi } from "clawdbot/plugin-sdk";
|
||||
import type { MoltbotPluginApi } from "clawdbot/plugin-sdk";
|
||||
import { emptyPluginConfigSchema } from "clawdbot/plugin-sdk";
|
||||
|
||||
import { slackPlugin } from "./src/channel.js";
|
||||
@@ -9,7 +9,7 @@ const plugin = {
|
||||
name: "Slack",
|
||||
description: "Slack channel plugin",
|
||||
configSchema: emptyPluginConfigSchema(),
|
||||
register(api: ClawdbotPluginApi) {
|
||||
register(api: MoltbotPluginApi) {
|
||||
setSlackRuntime(api.runtime);
|
||||
api.registerChannel({ plugin: slackPlugin });
|
||||
},
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user