From 34fb5ca9c64d937d972710c3f3d0814eed01b66b Mon Sep 17 00:00:00 2001 From: Justin Massa Date: Mon, 12 Jan 2026 09:16:25 -0600 Subject: [PATCH] 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 --- src/googlechat/accounts.ts | 17 ++++++++--- src/googlechat/monitor.ts | 13 +++++---- src/googlechat/run-webhook.ts | 44 +++++++++++++++++++---------- src/googlechat/send.ts | 12 ++++---- src/googlechat/types.ts | 6 +--- src/googlechat/webhook-server.ts | 24 ++++++++++++---- src/providers/plugins/googlechat.ts | 19 +++++++------ src/providers/registry.ts | 3 +- 8 files changed, 90 insertions(+), 48 deletions(-) diff --git a/src/googlechat/accounts.ts b/src/googlechat/accounts.ts index 4a848515a..08ea7ffa6 100644 --- a/src/googlechat/accounts.ts +++ b/src/googlechat/accounts.ts @@ -16,7 +16,9 @@ export type ResolvedGoogleChatAccount = { }; function listConfiguredAccountIds(cfg: ClawdbotConfig): string[] { - const googlechat = (cfg as { googlechat?: { accounts?: Record } }).googlechat; + const googlechat = ( + cfg as { googlechat?: { accounts?: Record } } + ).googlechat; const accounts = googlechat?.accounts; if (!accounts || typeof accounts !== "object") return []; return Object.keys(accounts).filter(Boolean); @@ -38,7 +40,11 @@ function resolveAccountConfig( cfg: ClawdbotConfig, accountId: string, ): GoogleChatAccountConfig | undefined { - const googlechat = (cfg as { googlechat?: { accounts?: Record } }).googlechat; + const googlechat = ( + cfg as { + googlechat?: { accounts?: Record }; + } + ).googlechat; const accounts = googlechat?.accounts; if (!accounts || typeof accounts !== "object") return undefined; return accounts[accountId]; @@ -48,7 +54,9 @@ function mergeGoogleChatAccountConfig( cfg: ClawdbotConfig, accountId: string, ): 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 account = resolveAccountConfig(cfg, accountId) ?? {}; return { ...base, ...account }; @@ -58,7 +66,8 @@ export function resolveGoogleChatAccount(params: { cfg: ClawdbotConfig; accountId?: string | null; }): 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 resolve = (accountId: string) => { diff --git a/src/googlechat/monitor.ts b/src/googlechat/monitor.ts index e6b5109c3..769305510 100644 --- a/src/googlechat/monitor.ts +++ b/src/googlechat/monitor.ts @@ -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 { RuntimeEnv } from "../runtime.js"; import type { ResolvedGoogleChatAccount } from "./accounts.js"; -import type { GoogleChatEvent, GoogleChatMessage } from "./types.js"; +import type { GoogleChatEvent } from "./types.js"; export type GoogleChatMonitorOptions = { account: ResolvedGoogleChatAccount; @@ -86,8 +86,8 @@ function checkMessagePolicy( ): boolean { const policy = message.chat.type === "dm" - ? account.config.dmPolicy ?? "pairing" - : account.config.spacePolicy ?? "disabled"; + ? (account.config.dmPolicy ?? "pairing") + : (account.config.spacePolicy ?? "disabled"); switch (policy) { case "disabled": @@ -157,7 +157,10 @@ export async function monitorGoogleChatProvider( }; const errorHandler = (error: Error) => { - console.error(`[googlechat:${account.accountId}] Subscription error:`, error); + console.error( + `[googlechat:${account.accountId}] Subscription error:`, + error, + ); }; subscription.on("message", messageHandler); diff --git a/src/googlechat/run-webhook.ts b/src/googlechat/run-webhook.ts index 84a3adbb1..899bac8a7 100644 --- a/src/googlechat/run-webhook.ts +++ b/src/googlechat/run-webhook.ts @@ -1,6 +1,6 @@ #!/usr/bin/env npx tsx +import { execSync } from "node:child_process"; import express, { type Request, type Response } from "express"; -import { execSync } from "child_process"; const PORT = 18792; const app = express(); @@ -21,7 +21,11 @@ app.post("/webhook/googlechat", async (req: Request, res: Response) => { const isAddedToSpace = !!chat.addedToSpacePayload; 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}`); if (isAddedToSpace) { @@ -55,21 +59,27 @@ app.post("/webhook/googlechat", async (req: Request, res: Response) => { const escapedText = text.replace(/'/g, "'\\''"); const sessionId = `googlechat:${spaceId}`; 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) - encoding: 'utf-8', + timeout: 25000, // 25 second timeout (Google Chat times out at ~30s) + encoding: "utf-8", maxBuffer: 1024 * 1024, - } + }, ); - responseText = result.trim() || "I processed your message but have no response."; - console.log(`[googlechat] AI Response: ${responseText.slice(0, 100)}...`); - } catch (err: any) { - console.error(`[googlechat] CLI error:`, err.message); - if (err.killed) { - responseText = "Sorry, the request timed out. Please try a simpler question."; + responseText = + result.trim() || "I processed your message but have no response."; + console.log( + `[googlechat] AI Response: ${responseText.slice(0, 100)}...`, + ); + } 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 { - 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, () => { console.log(`[googlechat] Webhook server running on port ${PORT}`); - console.log(`[googlechat] Local: http://localhost:${PORT}/webhook/googlechat`); - console.log(`[googlechat] Use ngrok URL + /webhook/googlechat for Google Chat config`); + console.log( + `[googlechat] Local: http://localhost:${PORT}/webhook/googlechat`, + ); + console.log( + `[googlechat] Use ngrok URL + /webhook/googlechat for Google Chat config`, + ); }); diff --git a/src/googlechat/send.ts b/src/googlechat/send.ts index 11df59036..4f62cf089 100644 --- a/src/googlechat/send.ts +++ b/src/googlechat/send.ts @@ -1,9 +1,11 @@ -import { google, type chat_v1 } from "googleapis"; +import { type chat_v1, google } from "googleapis"; import type { ResolvedGoogleChatAccount } from "./accounts.js"; -let chatClients: Map = new Map(); +const chatClients: Map = new Map(); -async function getChatClient(account: ResolvedGoogleChatAccount): Promise { +async function getChatClient( + account: ResolvedGoogleChatAccount, +): Promise { const cacheKey = `${account.accountId}:${account.credentialsPath ?? "default"}`; const cached = chatClients.get(cacheKey); if (cached) return cached; @@ -127,8 +129,8 @@ export async function sendGoogleChatMedia( }, }; - if (options.caption) { - card.card!.sections![0].widgets!.unshift({ + if (options.caption && card.card?.sections?.[0]?.widgets) { + card.card.sections[0].widgets.unshift({ textParagraph: { text: options.caption }, }); } diff --git a/src/googlechat/types.ts b/src/googlechat/types.ts index 73a2ac14d..330b55c3f 100644 --- a/src/googlechat/types.ts +++ b/src/googlechat/types.ts @@ -59,11 +59,7 @@ export type GoogleChatMessage = { }; export type GoogleChatEvent = { - type: - | "MESSAGE" - | "ADDED_TO_SPACE" - | "REMOVED_FROM_SPACE" - | "CARD_CLICKED"; + type: "MESSAGE" | "ADDED_TO_SPACE" | "REMOVED_FROM_SPACE" | "CARD_CLICKED"; eventTime: string; message?: GoogleChatMessage; user?: { diff --git a/src/googlechat/webhook-server.ts b/src/googlechat/webhook-server.ts index 6113e374e..7a2c6cb73 100644 --- a/src/googlechat/webhook-server.ts +++ b/src/googlechat/webhook-server.ts @@ -83,7 +83,11 @@ function normalizeMessage( export async function startGoogleChatWebhookServer( options: GoogleChatWebhookOptions, -): Promise<{ server: ReturnType; port: number; stop: () => void }> { +): Promise<{ + server: ReturnType; + port: number; + stop: () => void; +}> { const { account, port = 18792 } = options; const app = express(); @@ -91,7 +95,11 @@ export async function startGoogleChatWebhookServer( // Health check endpoint 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 @@ -99,7 +107,9 @@ export async function startGoogleChatWebhookServer( try { 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 if (event.type === "ADDED_TO_SPACE") { @@ -142,8 +152,12 @@ export async function startGoogleChatWebhookServer( // Start server const server = app.listen(port, () => { - console.log(`[googlechat:${account.accountId}] Webhook server listening on port ${port}`); - console.log(`[googlechat:${account.accountId}] Webhook URL: http://localhost:${port}/webhook/googlechat`); + console.log( + `[googlechat:${account.accountId}] Webhook server listening on port ${port}`, + ); + console.log( + `[googlechat:${account.accountId}] Webhook URL: http://localhost:${port}/webhook/googlechat`, + ); }); const stop = () => { diff --git a/src/providers/plugins/googlechat.ts b/src/providers/plugins/googlechat.ts index 8f7a4efec..82192ad47 100644 --- a/src/providers/plugins/googlechat.ts +++ b/src/providers/plugins/googlechat.ts @@ -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 { listGoogleChatAccountIds, type ResolvedGoogleChatAccount, @@ -13,6 +10,7 @@ import { sendGoogleChatMedia, sendGoogleChatText, } from "../../googlechat/send.js"; +import { DEFAULT_ACCOUNT_ID } from "../../routing/session-key.js"; import { getChatProviderMeta } from "../registry.js"; import { deleteAccountFromConfigSection, @@ -57,7 +55,12 @@ export const googlechatPlugin: ProviderPlugin = { cfg, sectionKey: "googlechat", accountId, - clearBaseFields: ["projectId", "subscriptionName", "credentialsPath", "name"], + clearBaseFields: [ + "projectId", + "subscriptionName", + "credentialsPath", + "name", + ], }), isConfigured: (account) => Boolean(account.projectId?.trim() && account.subscriptionName?.trim()), @@ -78,7 +81,9 @@ export const googlechatPlugin: ProviderPlugin = { }, security: { resolveDmPolicy: ({ cfg, accountId, account }) => { - const googlechat = (cfg as { googlechat?: { accounts?: Record } }).googlechat; + const googlechat = ( + cfg as { googlechat?: { accounts?: Record } } + ).googlechat; const resolvedAccountId = accountId ?? account.accountId ?? DEFAULT_ACCOUNT_ID; const useAccountPath = Boolean(googlechat?.accounts?.[resolvedAccountId]); @@ -107,9 +112,7 @@ export const googlechatPlugin: ProviderPlugin = { if (!trimmed) { return { ok: false, - error: new Error( - "Delivering to Google Chat requires --to ", - ), + error: new Error("Delivering to Google Chat requires --to "), }; } return { ok: true, to: trimmed }; diff --git a/src/providers/registry.ts b/src/providers/registry.ts index a0c27f4d4..ff5de70b2 100644 --- a/src/providers/registry.ts +++ b/src/providers/registry.ts @@ -101,7 +101,8 @@ const CHAT_PROVIDER_META: Record = { selectionLabel: "Google Chat (Pub/Sub)", docsPath: "/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.", }, };