@alfe.ai/openclaw-google 0.0.16 → 0.0.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/plugin.cjs +22 -3
- package/dist/plugin.d.cts +11 -0
- package/dist/plugin.d.cts.map +1 -1
- package/dist/plugin.d.ts +11 -0
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +22 -3
- package/dist/plugin.js.map +1 -1
- package/package.json +1 -1
package/dist/plugin.cjs
CHANGED
|
@@ -102,7 +102,7 @@ function runGwsCommand(args, configDir) {
|
|
|
102
102
|
resolve({
|
|
103
103
|
stdout,
|
|
104
104
|
stderr,
|
|
105
|
-
exitCode: error?.code
|
|
105
|
+
exitCode: typeof error?.code === "number" ? error.code : error ? 1 : 0
|
|
106
106
|
});
|
|
107
107
|
});
|
|
108
108
|
});
|
|
@@ -183,7 +183,11 @@ const plugin = {
|
|
|
183
183
|
const log = api.logger;
|
|
184
184
|
for (const tool of googleTools) api.registerTool(tool);
|
|
185
185
|
log.info(`Registered ${googleTools.length.toString()} Google tools: ${googleTools.map((t) => t.name).join(", ")}`);
|
|
186
|
-
|
|
186
|
+
const startGoogleService = () => {
|
|
187
|
+
if (globalThis.__googlePluginActivated === true) {
|
|
188
|
+
log.debug("Google plugin already activated — skipping duplicate");
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
187
191
|
globalThis.__googlePluginActivated = true;
|
|
188
192
|
log.info("Alfe Google Workspace plugin activating...");
|
|
189
193
|
try {
|
|
@@ -202,7 +206,22 @@ const plugin = {
|
|
|
202
206
|
log.warn("Google tools will fail — no API config available");
|
|
203
207
|
}
|
|
204
208
|
log.info("Alfe Google Workspace plugin activated");
|
|
205
|
-
}
|
|
209
|
+
};
|
|
210
|
+
const stopGoogleService = () => {
|
|
211
|
+
globalThis.__googlePluginActivated = false;
|
|
212
|
+
client = null;
|
|
213
|
+
cachedAccounts = [];
|
|
214
|
+
log.info("Alfe Google Workspace plugin stopped");
|
|
215
|
+
};
|
|
216
|
+
if (api.registerService) api.registerService({
|
|
217
|
+
id: "alfe-google-workspace",
|
|
218
|
+
start: () => {
|
|
219
|
+
startGoogleService();
|
|
220
|
+
},
|
|
221
|
+
stop: () => {
|
|
222
|
+
stopGoogleService();
|
|
223
|
+
}
|
|
224
|
+
});
|
|
206
225
|
},
|
|
207
226
|
deactivate(api) {
|
|
208
227
|
globalThis.__googlePluginActivated = false;
|
package/dist/plugin.d.cts
CHANGED
|
@@ -8,11 +8,22 @@ interface Logger {
|
|
|
8
8
|
error(msg: string, ...args: unknown[]): void;
|
|
9
9
|
debug(msg: string, ...args: unknown[]): void;
|
|
10
10
|
}
|
|
11
|
+
interface PluginServiceContext {
|
|
12
|
+
config?: Record<string, unknown>;
|
|
13
|
+
workspaceDir?: string;
|
|
14
|
+
stateDir?: string;
|
|
15
|
+
logger?: Logger;
|
|
16
|
+
}
|
|
11
17
|
interface OpenClawPluginApi {
|
|
12
18
|
logger: Logger;
|
|
13
19
|
registrationMode?: "full" | "setup-only" | "setup-runtime" | "cli-metadata";
|
|
14
20
|
registerTool(tool: ToolDef): void;
|
|
15
21
|
registerGatewayMethod(name: string, handler: (...args: unknown[]) => Promise<unknown>): void;
|
|
22
|
+
registerService?(service: {
|
|
23
|
+
id: string;
|
|
24
|
+
start: (ctx: PluginServiceContext) => void | Promise<void>;
|
|
25
|
+
stop?: (ctx: PluginServiceContext) => void | Promise<void>;
|
|
26
|
+
}): void;
|
|
16
27
|
on(event: string, handler: (...args: unknown[]) => void | Promise<void>, options?: {
|
|
17
28
|
priority?: number;
|
|
18
29
|
}): void;
|
package/dist/plugin.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.cts","names":[],"sources":["../src/plugin.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"plugin.d.cts","names":[],"sources":["../src/plugin.ts"],"mappings":";;;;UAqBU,MAAA,CAeA;MAEW,CAAA,GAAA,EAAA,MAAA,EAAA,GAAA,IAAA,EAAA,OAAA,EAAA,CAAA,EAAA,IAAA;MACkD,CAAA,GAAA,EAAA,MAAA,EAAA,GAAA,IAAA,EAAA,OAAA,EAAA,CAAA,EAAA,IAAA;OAGtD,CAAA,GAAA,EAAA,MAAA,EAAA,GAAA,IAAA,EAAA,OAAA,EAAA,CAAA,EAAA,IAAA;OAAgC,CAAA,GAAA,EAAA,MAAA,EAAA,GAAA,IAAA,EAAA,OAAA,EAAA,CAAA,EAAA,IAAA;;UAdvC,oBAAA,CAeuC;QAEW,CAAA,EAhBjD,MAgBiD,CAAA,MAAA,EAAA,OAAA,CAAA;EAAO,YAAA,CAAA,EAAA,MAAA;EAKzD,QAAA,CAAA,EAAO,MAAA;EAAA,MAAA,CAAA,EAlBN,MAkBM;;UAfP,iBAAA,CAoB8B;QAA4B,EAnB1D,MAmB0D;EAAO,gBAAA,CAAA,EAAA,MAAA,GAAA,YAAA,GAAA,eAAA,GAAA,cAAA;EAwNrE,YA+DL,CAAA,IAAA,EAxSoB,OAwSpB,CAAA,EAAA,IAAA;EAAA,qBAAA,CAAA,IAAA,EAAA,MAAA,EAAA,OAAA,EAAA,CAAA,GAAA,IAAA,EAAA,OAAA,EAAA,EAAA,GAvSsE,OAuStE,CAAA,OAAA,CAAA,CAAA,EAAA,IAAA;iBAzDe,EAAA,OAAA,EAAA;IAmDE,EAAA,EAAA,MAAA;IAAiB,KAAA,EAAA,CAAA,GAAA,EA9RlB,oBA8RkB,EAAA,GAAA,IAAA,GA9Rc,OA8Rd,CAAA,IAAA,CAAA;iBA7RlB,gCAAgC;;4DAEW;;;;UAKlD,OAAA;;;;cAII;wCAC0B,4BAA4B;;;;;;;;cAwN9D;;;;;gBAMU;kBAmDE"}
|
package/dist/plugin.d.ts
CHANGED
|
@@ -8,11 +8,22 @@ interface Logger {
|
|
|
8
8
|
error(msg: string, ...args: unknown[]): void;
|
|
9
9
|
debug(msg: string, ...args: unknown[]): void;
|
|
10
10
|
}
|
|
11
|
+
interface PluginServiceContext {
|
|
12
|
+
config?: Record<string, unknown>;
|
|
13
|
+
workspaceDir?: string;
|
|
14
|
+
stateDir?: string;
|
|
15
|
+
logger?: Logger;
|
|
16
|
+
}
|
|
11
17
|
interface OpenClawPluginApi {
|
|
12
18
|
logger: Logger;
|
|
13
19
|
registrationMode?: "full" | "setup-only" | "setup-runtime" | "cli-metadata";
|
|
14
20
|
registerTool(tool: ToolDef): void;
|
|
15
21
|
registerGatewayMethod(name: string, handler: (...args: unknown[]) => Promise<unknown>): void;
|
|
22
|
+
registerService?(service: {
|
|
23
|
+
id: string;
|
|
24
|
+
start: (ctx: PluginServiceContext) => void | Promise<void>;
|
|
25
|
+
stop?: (ctx: PluginServiceContext) => void | Promise<void>;
|
|
26
|
+
}): void;
|
|
16
27
|
on(event: string, handler: (...args: unknown[]) => void | Promise<void>, options?: {
|
|
17
28
|
priority?: number;
|
|
18
29
|
}): void;
|
package/dist/plugin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","names":[],"sources":["../src/plugin.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","names":[],"sources":["../src/plugin.ts"],"mappings":";;;;UAqBU,MAAA,CAeA;MAEW,CAAA,GAAA,EAAA,MAAA,EAAA,GAAA,IAAA,EAAA,OAAA,EAAA,CAAA,EAAA,IAAA;MACkD,CAAA,GAAA,EAAA,MAAA,EAAA,GAAA,IAAA,EAAA,OAAA,EAAA,CAAA,EAAA,IAAA;OAGtD,CAAA,GAAA,EAAA,MAAA,EAAA,GAAA,IAAA,EAAA,OAAA,EAAA,CAAA,EAAA,IAAA;OAAgC,CAAA,GAAA,EAAA,MAAA,EAAA,GAAA,IAAA,EAAA,OAAA,EAAA,CAAA,EAAA,IAAA;;UAdvC,oBAAA,CAeuC;QAEW,CAAA,EAhBjD,MAgBiD,CAAA,MAAA,EAAA,OAAA,CAAA;EAAO,YAAA,CAAA,EAAA,MAAA;EAKzD,QAAA,CAAA,EAAO,MAAA;EAAA,MAAA,CAAA,EAlBN,MAkBM;;UAfP,iBAAA,CAoB8B;QAA4B,EAnB1D,MAmB0D;EAAO,gBAAA,CAAA,EAAA,MAAA,GAAA,YAAA,GAAA,eAAA,GAAA,cAAA;EAwNrE,YA+DL,CAAA,IAAA,EAxSoB,OAwSpB,CAAA,EAAA,IAAA;EAAA,qBAAA,CAAA,IAAA,EAAA,MAAA,EAAA,OAAA,EAAA,CAAA,GAAA,IAAA,EAAA,OAAA,EAAA,EAAA,GAvSsE,OAuStE,CAAA,OAAA,CAAA,CAAA,EAAA,IAAA;iBAzDe,EAAA,OAAA,EAAA;IAmDE,EAAA,EAAA,MAAA;IAAiB,KAAA,EAAA,CAAA,GAAA,EA9RlB,oBA8RkB,EAAA,GAAA,IAAA,GA9Rc,OA8Rd,CAAA,IAAA,CAAA;iBA7RlB,gCAAgC;;4DAEW;;;;UAKlD,OAAA;;;;cAII;wCAC0B,4BAA4B;;;;;;;;cAwN9D;;;;;gBAMU;kBAmDE"}
|
package/dist/plugin.js
CHANGED
|
@@ -103,7 +103,7 @@ function runGwsCommand(args, configDir) {
|
|
|
103
103
|
resolve({
|
|
104
104
|
stdout,
|
|
105
105
|
stderr,
|
|
106
|
-
exitCode: error?.code
|
|
106
|
+
exitCode: typeof error?.code === "number" ? error.code : error ? 1 : 0
|
|
107
107
|
});
|
|
108
108
|
});
|
|
109
109
|
});
|
|
@@ -184,7 +184,11 @@ const plugin = {
|
|
|
184
184
|
const log = api.logger;
|
|
185
185
|
for (const tool of googleTools) api.registerTool(tool);
|
|
186
186
|
log.info(`Registered ${googleTools.length.toString()} Google tools: ${googleTools.map((t) => t.name).join(", ")}`);
|
|
187
|
-
|
|
187
|
+
const startGoogleService = () => {
|
|
188
|
+
if (globalThis.__googlePluginActivated === true) {
|
|
189
|
+
log.debug("Google plugin already activated — skipping duplicate");
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
188
192
|
globalThis.__googlePluginActivated = true;
|
|
189
193
|
log.info("Alfe Google Workspace plugin activating...");
|
|
190
194
|
try {
|
|
@@ -203,7 +207,22 @@ const plugin = {
|
|
|
203
207
|
log.warn("Google tools will fail — no API config available");
|
|
204
208
|
}
|
|
205
209
|
log.info("Alfe Google Workspace plugin activated");
|
|
206
|
-
}
|
|
210
|
+
};
|
|
211
|
+
const stopGoogleService = () => {
|
|
212
|
+
globalThis.__googlePluginActivated = false;
|
|
213
|
+
client = null;
|
|
214
|
+
cachedAccounts = [];
|
|
215
|
+
log.info("Alfe Google Workspace plugin stopped");
|
|
216
|
+
};
|
|
217
|
+
if (api.registerService) api.registerService({
|
|
218
|
+
id: "alfe-google-workspace",
|
|
219
|
+
start: () => {
|
|
220
|
+
startGoogleService();
|
|
221
|
+
},
|
|
222
|
+
stop: () => {
|
|
223
|
+
stopGoogleService();
|
|
224
|
+
}
|
|
225
|
+
});
|
|
207
226
|
},
|
|
208
227
|
deactivate(api) {
|
|
209
228
|
globalThis.__googlePluginActivated = false;
|
package/dist/plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","names":[],"sources":["../src/plugin.ts"],"sourcesContent":["/**\n * @alfe/openclaw-google — OpenClaw native plugin\n *\n * Registers Google Workspace account management tools with OpenClaw.\n * Provides multi-account awareness so the agent can:\n * - List connected Google accounts\n * - Run gws CLI commands targeting a specific account\n * - Set the default account\n * - Disconnect an account\n */\n\nimport { Type, type TSchema } from \"@sinclair/typebox\";\nimport { resolveConfig } from \"@alfe.ai/config\";\nimport { AgentApiClient } from \"@alfe.ai/agent-api-client\";\nimport { execFile } from \"node:child_process\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { createRequire } from 'node:module';\nconst require = createRequire(import.meta.url);\nconst pkg = require('../package.json') as { version: string };\n\ninterface Logger {\n info(msg: string, ...args: unknown[]): void;\n warn(msg: string, ...args: unknown[]): void;\n error(msg: string, ...args: unknown[]): void;\n debug(msg: string, ...args: unknown[]): void;\n}\n\ninterface OpenClawPluginApi {\n logger: Logger;\n registrationMode?: \"full\" | \"setup-only\" | \"setup-runtime\" | \"cli-metadata\";\n registerTool(tool: ToolDef): void;\n registerGatewayMethod(name: string, handler: (...args: unknown[]) => Promise<unknown>): void;\n on(event: string, handler: (...args: unknown[]) => void | Promise<void>, options?: { priority?: number }): void;\n}\n\n// ── Tool types ───────────────────────────────────────────────\n\ninterface ToolDef {\n name: string;\n description: string;\n label: string;\n parameters: TSchema;\n execute: (toolCallId: string, params: Record<string, unknown>) => Promise<{\n content: { type: \"text\"; text: string }[];\n details: unknown;\n }>;\n}\n\nfunction ok(data: unknown) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify(data) }], details: data };\n}\n\nfunction errResult(message: string) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }], details: { error: message } };\n}\n\nfunction defineTool(def: {\n name: string;\n description: string;\n parameters: TSchema;\n handler: (params: Record<string, unknown>) => Promise<unknown>;\n}): ToolDef {\n return {\n name: def.name,\n description: def.description,\n label: def.name,\n parameters: def.parameters,\n execute: async (_toolCallId: string, params: Record<string, unknown>) => {\n try {\n const result = await def.handler(params);\n return ok(result);\n } catch (e: unknown) {\n return errResult(e instanceof Error ? e.message : \"Unknown error\");\n }\n },\n };\n}\n\n// ── Account config dir resolution ───────────────────────────\n\ninterface GoogleAccountInfo {\n email: string;\n isDefault: boolean;\n displayName?: string;\n configDir: string;\n}\n\nfunction sanitizeEmail(email: string): string {\n return email.replace(/@/g, \"-\").replace(/\\./g, \"-\");\n}\n\nfunction resolveConfigDir(email: string, isDefault: boolean): string {\n const dirName = isDefault ? \"gws\" : `gws-${sanitizeEmail(email)}`;\n return join(homedir(), \".config\", dirName);\n}\n\n// ── State ───────────────────────────────────────────────────\n\nlet client: AgentApiClient | null = null;\nlet cachedAccounts: GoogleAccountInfo[] = [];\n\nfunction getClient(): AgentApiClient {\n if (!client) throw new Error(\"Google plugin not initialized — no API client\");\n return client;\n}\n\nasync function refreshAccountCache(): Promise<GoogleAccountInfo[]> {\n const creds = await getClient().getGoogleCredentials();\n const accounts = creds.accounts ?? [{\n email: creds.email,\n isDefault: true,\n displayName: undefined,\n }];\n\n cachedAccounts = accounts.map((a, i) => ({\n email: a.email,\n isDefault: i === 0 ? true : a.isDefault,\n displayName: a.displayName,\n configDir: resolveConfigDir(a.email, i === 0 ? true : a.isDefault),\n }));\n\n return cachedAccounts;\n}\n\nfunction findAccount(email?: string): GoogleAccountInfo {\n if (!email) {\n const def = cachedAccounts.find((a) => a.isDefault);\n if (!def) {\n if (cachedAccounts.length === 0) throw new Error(\"No Google accounts connected\");\n return cachedAccounts[0];\n }\n return def;\n }\n\n const account = cachedAccounts.find((a) => a.email === email);\n if (!account) {\n throw new Error(\n `Google account \"${email}\" not found. Available: ${cachedAccounts.map((a) => a.email).join(\", \")}`,\n );\n }\n return account;\n}\n\n// ── gws command execution ───────────────────────────────────\n\nfunction runGwsCommand(args: string[], configDir: string): Promise<{ stdout: string; stderr: string; exitCode: number }> {\n return new Promise((resolve) => {\n const env = { ...process.env, GOOGLE_WORKSPACE_CLI_CONFIG_DIR: configDir };\n execFile(\"gws\", args, { env, timeout: 60_000, maxBuffer: 10 * 1024 * 1024 }, (error, stdout, stderr) => {\n resolve({\n stdout,\n stderr,\n exitCode: error?.code ?? (error ? 1 : 0),\n });\n });\n });\n}\n\n// ── Tool definitions ─────────────────────────────────────────\n\nconst googleTools: ToolDef[] = [\n defineTool({\n name: \"google_list_accounts\",\n description:\n \"List all connected Google Workspace accounts. Shows email, display name, \" +\n \"whether it's the default account, and the gws CLI config directory path. \" +\n \"Use this to resolve which account to target (e.g., 'Kevin\\\\'s emails' → kevin@alfe.ai).\",\n parameters: Type.Object({}),\n handler: async () => {\n const accounts = await refreshAccountCache();\n return {\n accounts: accounts.map((a) => ({\n email: a.email,\n displayName: a.displayName,\n isDefault: a.isDefault,\n configDir: a.configDir,\n })),\n count: accounts.length,\n };\n },\n }),\n\n defineTool({\n name: \"google_run_command\",\n description:\n \"Run a gws (Google Workspace CLI) command targeting a specific account. \" +\n \"Automatically sets GOOGLE_WORKSPACE_CLI_CONFIG_DIR for the target account. \" +\n \"If no email is specified, uses the default account. \" +\n \"Example: google_run_command({ command: 'gmail list', email: 'kevin@alfe.ai' })\",\n parameters: Type.Object({\n command: Type.String({\n description: \"The gws CLI command and arguments (e.g., 'gmail list', 'calendar agenda', 'drive list')\",\n }),\n email: Type.Optional(\n Type.String({\n description: \"Email of the Google account to use. Omit to use the default account.\",\n }),\n ),\n }),\n handler: async (params) => {\n const { command, email } = params as { command: string; email?: string };\n const account = findAccount(email);\n\n const args = command.split(/\\s+/).filter(Boolean);\n if (args.length === 0) throw new Error(\"Command cannot be empty\");\n\n const result = await runGwsCommand(args, account.configDir);\n\n return {\n account: account.email,\n command: `gws ${command}`,\n ...result,\n };\n },\n }),\n\n defineTool({\n name: \"google_set_default_account\",\n description:\n \"Set a specific Google account as the default. The default account is \" +\n \"used when no email is specified in google_run_command.\",\n parameters: Type.Object({\n email: Type.String({ description: \"Email of the Google account to set as default\" }),\n }),\n handler: async (params) => {\n const { email } = params as { email: string };\n const result = await getClient().setDefaultGoogleAccount(email);\n await refreshAccountCache();\n return {\n message: `${email} is now the default Google account`,\n accounts: result.accounts,\n };\n },\n }),\n\n defineTool({\n name: \"google_disconnect_account\",\n description:\n \"Disconnect a specific Google account from this agent. \" +\n \"Revokes the OAuth token and removes the account. \" +\n \"If this was the default account, the next account is promoted.\",\n parameters: Type.Object({\n email: Type.String({ description: \"Email of the Google account to disconnect\" }),\n }),\n handler: async (params) => {\n const { email } = params as { email: string };\n const result = await getClient().disconnectGoogleAccount(email);\n await refreshAccountCache();\n return {\n message: `${email} has been disconnected`,\n remainingAccounts: result.accounts,\n };\n },\n }),\n];\n\n// ── Plugin definition ────────────────────────────────────────\n\nconst plugin = {\n id: \"@alfe.ai/openclaw-google\",\n name: \"Alfe Google Workspace Plugin\",\n description: \"Multi-account Google Workspace management — list accounts, run gws commands, manage defaults\",\n version: pkg.version,\n\n activate(api: OpenClawPluginApi) {\n const log = api.logger;\n\n\n for (const tool of googleTools) {\n api.registerTool(tool);\n }\n log.info(`Registered ${googleTools.length.toString()} Google tools: ${googleTools.map((t) => t.name).join(\", \")}`);\n\n if (!(globalThis as Record<string, unknown>).__googlePluginActivated) {\n (globalThis as Record<string, unknown>).__googlePluginActivated = true;\n log.info(\"Alfe Google Workspace plugin activating...\");\n\n try {\n const config = resolveConfig();\n client = new AgentApiClient({ apiKey: config.apiKey, apiUrl: config.apiUrl });\n\n refreshAccountCache()\n .then((accounts) => {\n log.info(`Cached ${accounts.length.toString()} Google account(s): ${accounts.map((a) => a.email).join(\", \")}`);\n })\n .catch((err: unknown) => {\n log.warn(`Failed to pre-cache Google accounts: ${err instanceof Error ? err.message : \"unknown\"}`);\n });\n } catch (err: unknown) {\n log.error(`Failed to resolve config: ${err instanceof Error ? err.message : \"unknown\"}`);\n log.warn(\"Google tools will fail — no API config available\");\n }\n\n log.info(\"Alfe Google Workspace plugin activated\");\n }\n },\n\n deactivate(api: OpenClawPluginApi) {\n (globalThis as Record<string, unknown>).__googlePluginActivated = false;\n client = null;\n cachedAccounts = [];\n api.logger.info(\"Alfe Google Workspace plugin deactivated\");\n },\n};\n\nexport default plugin;\n"],"mappings":";;;;;;;;;;;;;;;;;;AAmBA,MAAM,MADU,cAAc,OAAO,KAAK,IAAI,CAC1B,kBAAkB;AA8BtC,SAAS,GAAG,MAAe;AACzB,QAAO;EAAE,SAAS,CAAC;GAAE,MAAM;GAAiB,MAAM,KAAK,UAAU,KAAK;GAAE,CAAC;EAAE,SAAS;EAAM;;AAG5F,SAAS,UAAU,SAAiB;AAClC,QAAO;EAAE,SAAS,CAAC;GAAE,MAAM;GAAiB,MAAM,KAAK,UAAU,EAAE,OAAO,SAAS,CAAC;GAAE,CAAC;EAAE,SAAS,EAAE,OAAO,SAAS;EAAE;;AAGxH,SAAS,WAAW,KAKR;AACV,QAAO;EACL,MAAM,IAAI;EACV,aAAa,IAAI;EACjB,OAAO,IAAI;EACX,YAAY,IAAI;EAChB,SAAS,OAAO,aAAqB,WAAoC;AACvE,OAAI;AAEF,WAAO,GADQ,MAAM,IAAI,QAAQ,OAAO,CACvB;YACV,GAAY;AACnB,WAAO,UAAU,aAAa,QAAQ,EAAE,UAAU,gBAAgB;;;EAGvE;;AAYH,SAAS,cAAc,OAAuB;AAC5C,QAAO,MAAM,QAAQ,MAAM,IAAI,CAAC,QAAQ,OAAO,IAAI;;AAGrD,SAAS,iBAAiB,OAAe,WAA4B;CACnE,MAAM,UAAU,YAAY,QAAQ,OAAO,cAAc,MAAM;AAC/D,QAAO,KAAK,SAAS,EAAE,WAAW,QAAQ;;AAK5C,IAAI,SAAgC;AACpC,IAAI,iBAAsC,EAAE;AAE5C,SAAS,YAA4B;AACnC,KAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,gDAAgD;AAC7E,QAAO;;AAGT,eAAe,sBAAoD;CACjE,MAAM,QAAQ,MAAM,WAAW,CAAC,sBAAsB;AAOtD,mBANiB,MAAM,YAAY,CAAC;EAClC,OAAO,MAAM;EACb,WAAW;EACX,aAAa,KAAA;EACd,CAAC,EAEwB,KAAK,GAAG,OAAO;EACvC,OAAO,EAAE;EACT,WAAW,MAAM,IAAI,OAAO,EAAE;EAC9B,aAAa,EAAE;EACf,WAAW,iBAAiB,EAAE,OAAO,MAAM,IAAI,OAAO,EAAE,UAAU;EACnE,EAAE;AAEH,QAAO;;AAGT,SAAS,YAAY,OAAmC;AACtD,KAAI,CAAC,OAAO;EACV,MAAM,MAAM,eAAe,MAAM,MAAM,EAAE,UAAU;AACnD,MAAI,CAAC,KAAK;AACR,OAAI,eAAe,WAAW,EAAG,OAAM,IAAI,MAAM,+BAA+B;AAChF,UAAO,eAAe;;AAExB,SAAO;;CAGT,MAAM,UAAU,eAAe,MAAM,MAAM,EAAE,UAAU,MAAM;AAC7D,KAAI,CAAC,QACH,OAAM,IAAI,MACR,mBAAmB,MAAM,0BAA0B,eAAe,KAAK,MAAM,EAAE,MAAM,CAAC,KAAK,KAAK,GACjG;AAEH,QAAO;;AAKT,SAAS,cAAc,MAAgB,WAAkF;AACvH,QAAO,IAAI,SAAS,YAAY;AAE9B,WAAS,OAAO,MAAM;GAAE,KADZ;IAAE,GAAG,QAAQ;IAAK,iCAAiC;IAAW;GAC7C,SAAS;GAAQ,WAAW,KAAK,OAAO;GAAM,GAAG,OAAO,QAAQ,WAAW;AACtG,WAAQ;IACN;IACA;IACA,UAAU,OAAO,SAAS,QAAQ,IAAI;IACvC,CAAC;IACF;GACF;;AAKJ,MAAM,cAAyB;CAC7B,WAAW;EACT,MAAM;EACN,aACE;EAGF,YAAY,KAAK,OAAO,EAAE,CAAC;EAC3B,SAAS,YAAY;GACnB,MAAM,WAAW,MAAM,qBAAqB;AAC5C,UAAO;IACL,UAAU,SAAS,KAAK,OAAO;KAC7B,OAAO,EAAE;KACT,aAAa,EAAE;KACf,WAAW,EAAE;KACb,WAAW,EAAE;KACd,EAAE;IACH,OAAO,SAAS;IACjB;;EAEJ,CAAC;CAEF,WAAW;EACT,MAAM;EACN,aACE;EAIF,YAAY,KAAK,OAAO;GACtB,SAAS,KAAK,OAAO,EACnB,aAAa,2FACd,CAAC;GACF,OAAO,KAAK,SACV,KAAK,OAAO,EACV,aAAa,wEACd,CAAC,CACH;GACF,CAAC;EACF,SAAS,OAAO,WAAW;GACzB,MAAM,EAAE,SAAS,UAAU;GAC3B,MAAM,UAAU,YAAY,MAAM;GAElC,MAAM,OAAO,QAAQ,MAAM,MAAM,CAAC,OAAO,QAAQ;AACjD,OAAI,KAAK,WAAW,EAAG,OAAM,IAAI,MAAM,0BAA0B;GAEjE,MAAM,SAAS,MAAM,cAAc,MAAM,QAAQ,UAAU;AAE3D,UAAO;IACL,SAAS,QAAQ;IACjB,SAAS,OAAO;IAChB,GAAG;IACJ;;EAEJ,CAAC;CAEF,WAAW;EACT,MAAM;EACN,aACE;EAEF,YAAY,KAAK,OAAO,EACtB,OAAO,KAAK,OAAO,EAAE,aAAa,iDAAiD,CAAC,EACrF,CAAC;EACF,SAAS,OAAO,WAAW;GACzB,MAAM,EAAE,UAAU;GAClB,MAAM,SAAS,MAAM,WAAW,CAAC,wBAAwB,MAAM;AAC/D,SAAM,qBAAqB;AAC3B,UAAO;IACL,SAAS,GAAG,MAAM;IAClB,UAAU,OAAO;IAClB;;EAEJ,CAAC;CAEF,WAAW;EACT,MAAM;EACN,aACE;EAGF,YAAY,KAAK,OAAO,EACtB,OAAO,KAAK,OAAO,EAAE,aAAa,6CAA6C,CAAC,EACjF,CAAC;EACF,SAAS,OAAO,WAAW;GACzB,MAAM,EAAE,UAAU;GAClB,MAAM,SAAS,MAAM,WAAW,CAAC,wBAAwB,MAAM;AAC/D,SAAM,qBAAqB;AAC3B,UAAO;IACL,SAAS,GAAG,MAAM;IAClB,mBAAmB,OAAO;IAC3B;;EAEJ,CAAC;CACH;AAID,MAAM,SAAS;CACb,IAAI;CACJ,MAAM;CACN,aAAa;CACb,SAAS,IAAI;CAEb,SAAS,KAAwB;EAC/B,MAAM,MAAM,IAAI;AAGhB,OAAK,MAAM,QAAQ,YACjB,KAAI,aAAa,KAAK;AAExB,MAAI,KAAK,cAAc,YAAY,OAAO,UAAU,CAAC,iBAAiB,YAAY,KAAK,MAAM,EAAE,KAAK,CAAC,KAAK,KAAK,GAAG;AAElH,MAAI,CAAE,WAAuC,yBAAyB;AACnE,cAAuC,0BAA0B;AAClE,OAAI,KAAK,6CAA6C;AAEtD,OAAI;IACF,MAAM,SAAS,eAAe;AAC9B,aAAS,IAAI,eAAe;KAAE,QAAQ,OAAO;KAAQ,QAAQ,OAAO;KAAQ,CAAC;AAE7E,yBAAqB,CAClB,MAAM,aAAa;AAClB,SAAI,KAAK,UAAU,SAAS,OAAO,UAAU,CAAC,sBAAsB,SAAS,KAAK,MAAM,EAAE,MAAM,CAAC,KAAK,KAAK,GAAG;MAC9G,CACD,OAAO,QAAiB;AACvB,SAAI,KAAK,wCAAwC,eAAe,QAAQ,IAAI,UAAU,YAAY;MAClG;YACG,KAAc;AACrB,QAAI,MAAM,6BAA6B,eAAe,QAAQ,IAAI,UAAU,YAAY;AACxF,QAAI,KAAK,mDAAmD;;AAG9D,OAAI,KAAK,yCAAyC;;;CAItD,WAAW,KAAwB;AAChC,aAAuC,0BAA0B;AAClE,WAAS;AACT,mBAAiB,EAAE;AACnB,MAAI,OAAO,KAAK,2CAA2C;;CAE9D"}
|
|
1
|
+
{"version":3,"file":"plugin.js","names":[],"sources":["../src/plugin.ts"],"sourcesContent":["/**\n * @alfe/openclaw-google — OpenClaw native plugin\n *\n * Registers Google Workspace account management tools with OpenClaw.\n * Provides multi-account awareness so the agent can:\n * - List connected Google accounts\n * - Run gws CLI commands targeting a specific account\n * - Set the default account\n * - Disconnect an account\n */\n\nimport { Type, type TSchema } from \"@sinclair/typebox\";\nimport { resolveConfig } from \"@alfe.ai/config\";\nimport { AgentApiClient } from \"@alfe.ai/agent-api-client\";\nimport { execFile } from \"node:child_process\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { createRequire } from 'node:module';\nconst require = createRequire(import.meta.url);\nconst pkg = require('../package.json') as { version: string };\n\ninterface Logger {\n info(msg: string, ...args: unknown[]): void;\n warn(msg: string, ...args: unknown[]): void;\n error(msg: string, ...args: unknown[]): void;\n debug(msg: string, ...args: unknown[]): void;\n}\n\ninterface PluginServiceContext {\n config?: Record<string, unknown>;\n workspaceDir?: string;\n stateDir?: string;\n logger?: Logger;\n}\n\ninterface OpenClawPluginApi {\n logger: Logger;\n registrationMode?: \"full\" | \"setup-only\" | \"setup-runtime\" | \"cli-metadata\";\n registerTool(tool: ToolDef): void;\n registerGatewayMethod(name: string, handler: (...args: unknown[]) => Promise<unknown>): void;\n registerService?(service: {\n id: string;\n start: (ctx: PluginServiceContext) => void | Promise<void>;\n stop?: (ctx: PluginServiceContext) => void | Promise<void>;\n }): void;\n on(event: string, handler: (...args: unknown[]) => void | Promise<void>, options?: { priority?: number }): void;\n}\n\n// ── Tool types ───────────────────────────────────────────────\n\ninterface ToolDef {\n name: string;\n description: string;\n label: string;\n parameters: TSchema;\n execute: (toolCallId: string, params: Record<string, unknown>) => Promise<{\n content: { type: \"text\"; text: string }[];\n details: unknown;\n }>;\n}\n\nfunction ok(data: unknown) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify(data) }], details: data };\n}\n\nfunction errResult(message: string) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }], details: { error: message } };\n}\n\nfunction defineTool(def: {\n name: string;\n description: string;\n parameters: TSchema;\n handler: (params: Record<string, unknown>) => Promise<unknown>;\n}): ToolDef {\n return {\n name: def.name,\n description: def.description,\n label: def.name,\n parameters: def.parameters,\n execute: async (_toolCallId: string, params: Record<string, unknown>) => {\n try {\n const result = await def.handler(params);\n return ok(result);\n } catch (e: unknown) {\n return errResult(e instanceof Error ? e.message : \"Unknown error\");\n }\n },\n };\n}\n\n// ── Account config dir resolution ───────────────────────────\n\ninterface GoogleAccountInfo {\n email: string;\n isDefault: boolean;\n displayName?: string;\n configDir: string;\n}\n\nfunction sanitizeEmail(email: string): string {\n return email.replace(/@/g, \"-\").replace(/\\./g, \"-\");\n}\n\nfunction resolveConfigDir(email: string, isDefault: boolean): string {\n const dirName = isDefault ? \"gws\" : `gws-${sanitizeEmail(email)}`;\n return join(homedir(), \".config\", dirName);\n}\n\n// ── State ───────────────────────────────────────────────────\n\nlet client: AgentApiClient | null = null;\nlet cachedAccounts: GoogleAccountInfo[] = [];\n\nfunction getClient(): AgentApiClient {\n if (!client) throw new Error(\"Google plugin not initialized — no API client\");\n return client;\n}\n\nasync function refreshAccountCache(): Promise<GoogleAccountInfo[]> {\n const creds = await getClient().getGoogleCredentials();\n const accounts = creds.accounts ?? [{\n email: creds.email,\n isDefault: true,\n displayName: undefined,\n }];\n\n cachedAccounts = accounts.map((a, i) => ({\n email: a.email,\n isDefault: i === 0 ? true : a.isDefault,\n displayName: a.displayName,\n configDir: resolveConfigDir(a.email, i === 0 ? true : a.isDefault),\n }));\n\n return cachedAccounts;\n}\n\nfunction findAccount(email?: string): GoogleAccountInfo {\n if (!email) {\n const def = cachedAccounts.find((a) => a.isDefault);\n if (!def) {\n if (cachedAccounts.length === 0) throw new Error(\"No Google accounts connected\");\n return cachedAccounts[0];\n }\n return def;\n }\n\n const account = cachedAccounts.find((a) => a.email === email);\n if (!account) {\n throw new Error(\n `Google account \"${email}\" not found. Available: ${cachedAccounts.map((a) => a.email).join(\", \")}`,\n );\n }\n return account;\n}\n\n// ── gws command execution ───────────────────────────────────\n\nfunction runGwsCommand(args: string[], configDir: string): Promise<{ stdout: string; stderr: string; exitCode: number }> {\n return new Promise((resolve) => {\n const env = { ...process.env, GOOGLE_WORKSPACE_CLI_CONFIG_DIR: configDir };\n execFile(\"gws\", args, { env, timeout: 60_000, maxBuffer: 10 * 1024 * 1024 }, (error, stdout, stderr) => {\n resolve({\n stdout,\n stderr,\n exitCode: typeof error?.code === 'number' ? error.code : error ? 1 : 0,\n });\n });\n });\n}\n\n// ── Tool definitions ─────────────────────────────────────────\n\nconst googleTools: ToolDef[] = [\n defineTool({\n name: \"google_list_accounts\",\n description:\n \"List all connected Google Workspace accounts. Shows email, display name, \" +\n \"whether it's the default account, and the gws CLI config directory path. \" +\n \"Use this to resolve which account to target (e.g., 'Kevin\\\\'s emails' → kevin@alfe.ai).\",\n parameters: Type.Object({}),\n handler: async () => {\n const accounts = await refreshAccountCache();\n return {\n accounts: accounts.map((a) => ({\n email: a.email,\n displayName: a.displayName,\n isDefault: a.isDefault,\n configDir: a.configDir,\n })),\n count: accounts.length,\n };\n },\n }),\n\n defineTool({\n name: \"google_run_command\",\n description:\n \"Run a gws (Google Workspace CLI) command targeting a specific account. \" +\n \"Automatically sets GOOGLE_WORKSPACE_CLI_CONFIG_DIR for the target account. \" +\n \"If no email is specified, uses the default account. \" +\n \"Example: google_run_command({ command: 'gmail list', email: 'kevin@alfe.ai' })\",\n parameters: Type.Object({\n command: Type.String({\n description: \"The gws CLI command and arguments (e.g., 'gmail list', 'calendar agenda', 'drive list')\",\n }),\n email: Type.Optional(\n Type.String({\n description: \"Email of the Google account to use. Omit to use the default account.\",\n }),\n ),\n }),\n handler: async (params) => {\n const { command, email } = params as { command: string; email?: string };\n const account = findAccount(email);\n\n const args = command.split(/\\s+/).filter(Boolean);\n if (args.length === 0) throw new Error(\"Command cannot be empty\");\n\n const result = await runGwsCommand(args, account.configDir);\n\n return {\n account: account.email,\n command: `gws ${command}`,\n ...result,\n };\n },\n }),\n\n defineTool({\n name: \"google_set_default_account\",\n description:\n \"Set a specific Google account as the default. The default account is \" +\n \"used when no email is specified in google_run_command.\",\n parameters: Type.Object({\n email: Type.String({ description: \"Email of the Google account to set as default\" }),\n }),\n handler: async (params) => {\n const { email } = params as { email: string };\n const result = await getClient().setDefaultGoogleAccount(email);\n await refreshAccountCache();\n return {\n message: `${email} is now the default Google account`,\n accounts: result.accounts,\n };\n },\n }),\n\n defineTool({\n name: \"google_disconnect_account\",\n description:\n \"Disconnect a specific Google account from this agent. \" +\n \"Revokes the OAuth token and removes the account. \" +\n \"If this was the default account, the next account is promoted.\",\n parameters: Type.Object({\n email: Type.String({ description: \"Email of the Google account to disconnect\" }),\n }),\n handler: async (params) => {\n const { email } = params as { email: string };\n const result = await getClient().disconnectGoogleAccount(email);\n await refreshAccountCache();\n return {\n message: `${email} has been disconnected`,\n remainingAccounts: result.accounts,\n };\n },\n }),\n];\n\n// ── Plugin definition ────────────────────────────────────────\n\nconst plugin = {\n id: \"@alfe.ai/openclaw-google\",\n name: \"Alfe Google Workspace Plugin\",\n description: \"Multi-account Google Workspace management — list accounts, run gws commands, manage defaults\",\n version: pkg.version,\n\n activate(api: OpenClawPluginApi) {\n const log = api.logger;\n\n for (const tool of googleTools) {\n api.registerTool(tool);\n }\n log.info(`Registered ${googleTools.length.toString()} Google tools: ${googleTools.map((t) => t.name).join(\", \")}`);\n\n const startGoogleService = () => {\n if ((globalThis as Record<string, unknown>).__googlePluginActivated === true) {\n log.debug(\"Google plugin already activated — skipping duplicate\");\n return;\n }\n (globalThis as Record<string, unknown>).__googlePluginActivated = true;\n log.info(\"Alfe Google Workspace plugin activating...\");\n\n try {\n const config = resolveConfig();\n client = new AgentApiClient({ apiKey: config.apiKey, apiUrl: config.apiUrl });\n\n refreshAccountCache()\n .then((accounts) => {\n log.info(`Cached ${accounts.length.toString()} Google account(s): ${accounts.map((a) => a.email).join(\", \")}`);\n })\n .catch((err: unknown) => {\n log.warn(`Failed to pre-cache Google accounts: ${err instanceof Error ? err.message : \"unknown\"}`);\n });\n } catch (err: unknown) {\n log.error(`Failed to resolve config: ${err instanceof Error ? err.message : \"unknown\"}`);\n log.warn(\"Google tools will fail — no API config available\");\n }\n\n log.info(\"Alfe Google Workspace plugin activated\");\n };\n\n const stopGoogleService = () => {\n (globalThis as Record<string, unknown>).__googlePluginActivated = false;\n client = null;\n cachedAccounts = [];\n log.info(\"Alfe Google Workspace plugin stopped\");\n };\n\n if (api.registerService) {\n api.registerService({\n id: \"alfe-google-workspace\",\n start: () => { startGoogleService(); },\n stop: () => { stopGoogleService(); },\n });\n }\n },\n\n deactivate(api: OpenClawPluginApi) {\n (globalThis as Record<string, unknown>).__googlePluginActivated = false;\n client = null;\n cachedAccounts = [];\n api.logger.info(\"Alfe Google Workspace plugin deactivated\");\n },\n};\n\nexport default plugin;\n"],"mappings":"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"}
|