chore(googlechat): fix lint and formatting issues
- Add node: protocol to imports - Remove unused imports - Fix any type to unknown with proper typing - Fix non-null assertions with optional chaining - Change let to const where appropriate - Apply formatting and import organization Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
6208f7da36
commit
34fb5ca9c6
@ -16,7 +16,9 @@ export type ResolvedGoogleChatAccount = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function listConfiguredAccountIds(cfg: ClawdbotConfig): string[] {
|
function listConfiguredAccountIds(cfg: ClawdbotConfig): string[] {
|
||||||
const googlechat = (cfg as { googlechat?: { accounts?: Record<string, unknown> } }).googlechat;
|
const googlechat = (
|
||||||
|
cfg as { googlechat?: { accounts?: Record<string, unknown> } }
|
||||||
|
).googlechat;
|
||||||
const accounts = googlechat?.accounts;
|
const accounts = googlechat?.accounts;
|
||||||
if (!accounts || typeof accounts !== "object") return [];
|
if (!accounts || typeof accounts !== "object") return [];
|
||||||
return Object.keys(accounts).filter(Boolean);
|
return Object.keys(accounts).filter(Boolean);
|
||||||
@ -38,7 +40,11 @@ function resolveAccountConfig(
|
|||||||
cfg: ClawdbotConfig,
|
cfg: ClawdbotConfig,
|
||||||
accountId: string,
|
accountId: string,
|
||||||
): GoogleChatAccountConfig | undefined {
|
): GoogleChatAccountConfig | undefined {
|
||||||
const googlechat = (cfg as { googlechat?: { accounts?: Record<string, GoogleChatAccountConfig> } }).googlechat;
|
const googlechat = (
|
||||||
|
cfg as {
|
||||||
|
googlechat?: { accounts?: Record<string, GoogleChatAccountConfig> };
|
||||||
|
}
|
||||||
|
).googlechat;
|
||||||
const accounts = googlechat?.accounts;
|
const accounts = googlechat?.accounts;
|
||||||
if (!accounts || typeof accounts !== "object") return undefined;
|
if (!accounts || typeof accounts !== "object") return undefined;
|
||||||
return accounts[accountId];
|
return accounts[accountId];
|
||||||
@ -48,7 +54,9 @@ function mergeGoogleChatAccountConfig(
|
|||||||
cfg: ClawdbotConfig,
|
cfg: ClawdbotConfig,
|
||||||
accountId: string,
|
accountId: string,
|
||||||
): GoogleChatAccountConfig {
|
): GoogleChatAccountConfig {
|
||||||
const googlechat = (cfg as { googlechat?: GoogleChatAccountConfig & { accounts?: unknown } }).googlechat ?? {};
|
const googlechat =
|
||||||
|
(cfg as { googlechat?: GoogleChatAccountConfig & { accounts?: unknown } })
|
||||||
|
.googlechat ?? {};
|
||||||
const { accounts: _ignored, ...base } = googlechat;
|
const { accounts: _ignored, ...base } = googlechat;
|
||||||
const account = resolveAccountConfig(cfg, accountId) ?? {};
|
const account = resolveAccountConfig(cfg, accountId) ?? {};
|
||||||
return { ...base, ...account };
|
return { ...base, ...account };
|
||||||
@ -58,7 +66,8 @@ export function resolveGoogleChatAccount(params: {
|
|||||||
cfg: ClawdbotConfig;
|
cfg: ClawdbotConfig;
|
||||||
accountId?: string | null;
|
accountId?: string | null;
|
||||||
}): ResolvedGoogleChatAccount {
|
}): ResolvedGoogleChatAccount {
|
||||||
const googlechat = (params.cfg as { googlechat?: { enabled?: boolean } }).googlechat;
|
const googlechat = (params.cfg as { googlechat?: { enabled?: boolean } })
|
||||||
|
.googlechat;
|
||||||
const baseEnabled = googlechat?.enabled !== false;
|
const baseEnabled = googlechat?.enabled !== false;
|
||||||
|
|
||||||
const resolve = (accountId: string) => {
|
const resolve = (accountId: string) => {
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import { PubSub, type Message } from "@google-cloud/pubsub";
|
import { type Message, PubSub } from "@google-cloud/pubsub";
|
||||||
import type { ClawdbotConfig } from "../config/config.js";
|
import type { ClawdbotConfig } from "../config/config.js";
|
||||||
import type { RuntimeEnv } from "../runtime.js";
|
import type { RuntimeEnv } from "../runtime.js";
|
||||||
import type { ResolvedGoogleChatAccount } from "./accounts.js";
|
import type { ResolvedGoogleChatAccount } from "./accounts.js";
|
||||||
import type { GoogleChatEvent, GoogleChatMessage } from "./types.js";
|
import type { GoogleChatEvent } from "./types.js";
|
||||||
|
|
||||||
export type GoogleChatMonitorOptions = {
|
export type GoogleChatMonitorOptions = {
|
||||||
account: ResolvedGoogleChatAccount;
|
account: ResolvedGoogleChatAccount;
|
||||||
@ -86,8 +86,8 @@ function checkMessagePolicy(
|
|||||||
): boolean {
|
): boolean {
|
||||||
const policy =
|
const policy =
|
||||||
message.chat.type === "dm"
|
message.chat.type === "dm"
|
||||||
? account.config.dmPolicy ?? "pairing"
|
? (account.config.dmPolicy ?? "pairing")
|
||||||
: account.config.spacePolicy ?? "disabled";
|
: (account.config.spacePolicy ?? "disabled");
|
||||||
|
|
||||||
switch (policy) {
|
switch (policy) {
|
||||||
case "disabled":
|
case "disabled":
|
||||||
@ -157,7 +157,10 @@ export async function monitorGoogleChatProvider(
|
|||||||
};
|
};
|
||||||
|
|
||||||
const errorHandler = (error: Error) => {
|
const errorHandler = (error: Error) => {
|
||||||
console.error(`[googlechat:${account.accountId}] Subscription error:`, error);
|
console.error(
|
||||||
|
`[googlechat:${account.accountId}] Subscription error:`,
|
||||||
|
error,
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
subscription.on("message", messageHandler);
|
subscription.on("message", messageHandler);
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env npx tsx
|
#!/usr/bin/env npx tsx
|
||||||
|
import { execSync } from "node:child_process";
|
||||||
import express, { type Request, type Response } from "express";
|
import express, { type Request, type Response } from "express";
|
||||||
import { execSync } from "child_process";
|
|
||||||
|
|
||||||
const PORT = 18792;
|
const PORT = 18792;
|
||||||
const app = express();
|
const app = express();
|
||||||
@ -21,7 +21,11 @@ app.post("/webhook/googlechat", async (req: Request, res: Response) => {
|
|||||||
const isAddedToSpace = !!chat.addedToSpacePayload;
|
const isAddedToSpace = !!chat.addedToSpacePayload;
|
||||||
const isMessage = !!chat.messagePayload;
|
const isMessage = !!chat.messagePayload;
|
||||||
|
|
||||||
const eventType = isAddedToSpace ? "ADDED_TO_SPACE" : isMessage ? "MESSAGE" : "UNKNOWN";
|
const eventType = isAddedToSpace
|
||||||
|
? "ADDED_TO_SPACE"
|
||||||
|
: isMessage
|
||||||
|
? "MESSAGE"
|
||||||
|
: "UNKNOWN";
|
||||||
console.log(`[googlechat] Received event: ${eventType}`);
|
console.log(`[googlechat] Received event: ${eventType}`);
|
||||||
|
|
||||||
if (isAddedToSpace) {
|
if (isAddedToSpace) {
|
||||||
@ -55,21 +59,27 @@ app.post("/webhook/googlechat", async (req: Request, res: Response) => {
|
|||||||
const escapedText = text.replace(/'/g, "'\\''");
|
const escapedText = text.replace(/'/g, "'\\''");
|
||||||
const sessionId = `googlechat:${spaceId}`;
|
const sessionId = `googlechat:${spaceId}`;
|
||||||
const result = execSync(
|
const result = execSync(
|
||||||
`clawdbot agent --message '${escapedText}' --session-id '${sessionId}' --local 2>&1`,
|
`clawdbot agent --message '${escapedText}' --session-id '${sessionId}' --local`,
|
||||||
{
|
{
|
||||||
timeout: 25000, // 25 second timeout (Google Chat times out at ~30s)
|
timeout: 25000, // 25 second timeout (Google Chat times out at ~30s)
|
||||||
encoding: 'utf-8',
|
encoding: "utf-8",
|
||||||
maxBuffer: 1024 * 1024,
|
maxBuffer: 1024 * 1024,
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
responseText = result.trim() || "I processed your message but have no response.";
|
responseText =
|
||||||
console.log(`[googlechat] AI Response: ${responseText.slice(0, 100)}...`);
|
result.trim() || "I processed your message but have no response.";
|
||||||
} catch (err: any) {
|
console.log(
|
||||||
console.error(`[googlechat] CLI error:`, err.message);
|
`[googlechat] AI Response: ${responseText.slice(0, 100)}...`,
|
||||||
if (err.killed) {
|
);
|
||||||
responseText = "Sorry, the request timed out. Please try a simpler question.";
|
} catch (err: unknown) {
|
||||||
|
const error = err as { message?: string; killed?: boolean };
|
||||||
|
console.error(`[googlechat] CLI error:`, error.message);
|
||||||
|
if (error.killed) {
|
||||||
|
responseText =
|
||||||
|
"Sorry, the request timed out. Please try a simpler question.";
|
||||||
} else {
|
} else {
|
||||||
responseText = "Sorry, I encountered an error processing your message.";
|
responseText =
|
||||||
|
"Sorry, I encountered an error processing your message.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,6 +106,10 @@ app.post("/webhook/googlechat", async (req: Request, res: Response) => {
|
|||||||
|
|
||||||
app.listen(PORT, () => {
|
app.listen(PORT, () => {
|
||||||
console.log(`[googlechat] Webhook server running on port ${PORT}`);
|
console.log(`[googlechat] Webhook server running on port ${PORT}`);
|
||||||
console.log(`[googlechat] Local: http://localhost:${PORT}/webhook/googlechat`);
|
console.log(
|
||||||
console.log(`[googlechat] Use ngrok URL + /webhook/googlechat for Google Chat config`);
|
`[googlechat] Local: http://localhost:${PORT}/webhook/googlechat`,
|
||||||
|
);
|
||||||
|
console.log(
|
||||||
|
`[googlechat] Use ngrok URL + /webhook/googlechat for Google Chat config`,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
import { google, type chat_v1 } from "googleapis";
|
import { type chat_v1, google } from "googleapis";
|
||||||
import type { ResolvedGoogleChatAccount } from "./accounts.js";
|
import type { ResolvedGoogleChatAccount } from "./accounts.js";
|
||||||
|
|
||||||
let chatClients: Map<string, chat_v1.Chat> = new Map();
|
const chatClients: Map<string, chat_v1.Chat> = new Map();
|
||||||
|
|
||||||
async function getChatClient(account: ResolvedGoogleChatAccount): Promise<chat_v1.Chat> {
|
async function getChatClient(
|
||||||
|
account: ResolvedGoogleChatAccount,
|
||||||
|
): Promise<chat_v1.Chat> {
|
||||||
const cacheKey = `${account.accountId}:${account.credentialsPath ?? "default"}`;
|
const cacheKey = `${account.accountId}:${account.credentialsPath ?? "default"}`;
|
||||||
const cached = chatClients.get(cacheKey);
|
const cached = chatClients.get(cacheKey);
|
||||||
if (cached) return cached;
|
if (cached) return cached;
|
||||||
@ -127,8 +129,8 @@ export async function sendGoogleChatMedia(
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
if (options.caption) {
|
if (options.caption && card.card?.sections?.[0]?.widgets) {
|
||||||
card.card!.sections![0].widgets!.unshift({
|
card.card.sections[0].widgets.unshift({
|
||||||
textParagraph: { text: options.caption },
|
textParagraph: { text: options.caption },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -59,11 +59,7 @@ export type GoogleChatMessage = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type GoogleChatEvent = {
|
export type GoogleChatEvent = {
|
||||||
type:
|
type: "MESSAGE" | "ADDED_TO_SPACE" | "REMOVED_FROM_SPACE" | "CARD_CLICKED";
|
||||||
| "MESSAGE"
|
|
||||||
| "ADDED_TO_SPACE"
|
|
||||||
| "REMOVED_FROM_SPACE"
|
|
||||||
| "CARD_CLICKED";
|
|
||||||
eventTime: string;
|
eventTime: string;
|
||||||
message?: GoogleChatMessage;
|
message?: GoogleChatMessage;
|
||||||
user?: {
|
user?: {
|
||||||
|
|||||||
@ -83,7 +83,11 @@ function normalizeMessage(
|
|||||||
|
|
||||||
export async function startGoogleChatWebhookServer(
|
export async function startGoogleChatWebhookServer(
|
||||||
options: GoogleChatWebhookOptions,
|
options: GoogleChatWebhookOptions,
|
||||||
): Promise<{ server: ReturnType<typeof express>; port: number; stop: () => void }> {
|
): Promise<{
|
||||||
|
server: ReturnType<typeof express>;
|
||||||
|
port: number;
|
||||||
|
stop: () => void;
|
||||||
|
}> {
|
||||||
const { account, port = 18792 } = options;
|
const { account, port = 18792 } = options;
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
@ -91,7 +95,11 @@ export async function startGoogleChatWebhookServer(
|
|||||||
|
|
||||||
// Health check endpoint
|
// Health check endpoint
|
||||||
app.get("/health", (_req: Request, res: Response) => {
|
app.get("/health", (_req: Request, res: Response) => {
|
||||||
res.json({ ok: true, provider: "googlechat", accountId: account.accountId });
|
res.json({
|
||||||
|
ok: true,
|
||||||
|
provider: "googlechat",
|
||||||
|
accountId: account.accountId,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Google Chat webhook endpoint
|
// Google Chat webhook endpoint
|
||||||
@ -99,7 +107,9 @@ export async function startGoogleChatWebhookServer(
|
|||||||
try {
|
try {
|
||||||
const event = req.body as GoogleChatEvent;
|
const event = req.body as GoogleChatEvent;
|
||||||
|
|
||||||
console.log(`[googlechat:${account.accountId}] Received event: ${event.type}`);
|
console.log(
|
||||||
|
`[googlechat:${account.accountId}] Received event: ${event.type}`,
|
||||||
|
);
|
||||||
|
|
||||||
// Handle different event types
|
// Handle different event types
|
||||||
if (event.type === "ADDED_TO_SPACE") {
|
if (event.type === "ADDED_TO_SPACE") {
|
||||||
@ -142,8 +152,12 @@ export async function startGoogleChatWebhookServer(
|
|||||||
|
|
||||||
// Start server
|
// Start server
|
||||||
const server = app.listen(port, () => {
|
const server = app.listen(port, () => {
|
||||||
console.log(`[googlechat:${account.accountId}] Webhook server listening on port ${port}`);
|
console.log(
|
||||||
console.log(`[googlechat:${account.accountId}] Webhook URL: http://localhost:${port}/webhook/googlechat`);
|
`[googlechat:${account.accountId}] Webhook server listening on port ${port}`,
|
||||||
|
);
|
||||||
|
console.log(
|
||||||
|
`[googlechat:${account.accountId}] Webhook URL: http://localhost:${port}/webhook/googlechat`,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const stop = () => {
|
const stop = () => {
|
||||||
|
|||||||
@ -1,6 +1,3 @@
|
|||||||
import { chunkMarkdownText } from "../../auto-reply/chunk.js";
|
|
||||||
import type { ClawdbotConfig } from "../../config/config.js";
|
|
||||||
import { DEFAULT_ACCOUNT_ID } from "../../routing/session-key.js";
|
|
||||||
import {
|
import {
|
||||||
listGoogleChatAccountIds,
|
listGoogleChatAccountIds,
|
||||||
type ResolvedGoogleChatAccount,
|
type ResolvedGoogleChatAccount,
|
||||||
@ -13,6 +10,7 @@ import {
|
|||||||
sendGoogleChatMedia,
|
sendGoogleChatMedia,
|
||||||
sendGoogleChatText,
|
sendGoogleChatText,
|
||||||
} from "../../googlechat/send.js";
|
} from "../../googlechat/send.js";
|
||||||
|
import { DEFAULT_ACCOUNT_ID } from "../../routing/session-key.js";
|
||||||
import { getChatProviderMeta } from "../registry.js";
|
import { getChatProviderMeta } from "../registry.js";
|
||||||
import {
|
import {
|
||||||
deleteAccountFromConfigSection,
|
deleteAccountFromConfigSection,
|
||||||
@ -57,7 +55,12 @@ export const googlechatPlugin: ProviderPlugin<ResolvedGoogleChatAccount> = {
|
|||||||
cfg,
|
cfg,
|
||||||
sectionKey: "googlechat",
|
sectionKey: "googlechat",
|
||||||
accountId,
|
accountId,
|
||||||
clearBaseFields: ["projectId", "subscriptionName", "credentialsPath", "name"],
|
clearBaseFields: [
|
||||||
|
"projectId",
|
||||||
|
"subscriptionName",
|
||||||
|
"credentialsPath",
|
||||||
|
"name",
|
||||||
|
],
|
||||||
}),
|
}),
|
||||||
isConfigured: (account) =>
|
isConfigured: (account) =>
|
||||||
Boolean(account.projectId?.trim() && account.subscriptionName?.trim()),
|
Boolean(account.projectId?.trim() && account.subscriptionName?.trim()),
|
||||||
@ -78,7 +81,9 @@ export const googlechatPlugin: ProviderPlugin<ResolvedGoogleChatAccount> = {
|
|||||||
},
|
},
|
||||||
security: {
|
security: {
|
||||||
resolveDmPolicy: ({ cfg, accountId, account }) => {
|
resolveDmPolicy: ({ cfg, accountId, account }) => {
|
||||||
const googlechat = (cfg as { googlechat?: { accounts?: Record<string, unknown> } }).googlechat;
|
const googlechat = (
|
||||||
|
cfg as { googlechat?: { accounts?: Record<string, unknown> } }
|
||||||
|
).googlechat;
|
||||||
const resolvedAccountId =
|
const resolvedAccountId =
|
||||||
accountId ?? account.accountId ?? DEFAULT_ACCOUNT_ID;
|
accountId ?? account.accountId ?? DEFAULT_ACCOUNT_ID;
|
||||||
const useAccountPath = Boolean(googlechat?.accounts?.[resolvedAccountId]);
|
const useAccountPath = Boolean(googlechat?.accounts?.[resolvedAccountId]);
|
||||||
@ -107,9 +112,7 @@ export const googlechatPlugin: ProviderPlugin<ResolvedGoogleChatAccount> = {
|
|||||||
if (!trimmed) {
|
if (!trimmed) {
|
||||||
return {
|
return {
|
||||||
ok: false,
|
ok: false,
|
||||||
error: new Error(
|
error: new Error("Delivering to Google Chat requires --to <spaceId>"),
|
||||||
"Delivering to Google Chat requires --to <spaceId>",
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return { ok: true, to: trimmed };
|
return { ok: true, to: trimmed };
|
||||||
|
|||||||
@ -101,7 +101,8 @@ const CHAT_PROVIDER_META: Record<ChatProviderId, ChatProviderMeta> = {
|
|||||||
selectionLabel: "Google Chat (Pub/Sub)",
|
selectionLabel: "Google Chat (Pub/Sub)",
|
||||||
docsPath: "/googlechat",
|
docsPath: "/googlechat",
|
||||||
docsLabel: "googlechat",
|
docsLabel: "googlechat",
|
||||||
blurb: "Google Workspace only; uses Pub/Sub for firewall-friendly operation.",
|
blurb:
|
||||||
|
"Google Workspace only; uses Pub/Sub for firewall-friendly operation.",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user