@fml-inc/fml 0.0.25 → 0.0.27
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/.claude-plugin/plugin.json +1 -0
- package/README.md +101 -0
- package/dist/chunk-2CRFCFE4.js +11 -0
- package/dist/chunk-2CRFCFE4.js.map +1 -0
- package/dist/{chunk-WXDGVKXK.js → chunk-ND2YSPQ6.js} +138 -4
- package/dist/chunk-ND2YSPQ6.js.map +1 -0
- package/dist/chunk-NLFKYSN7.js +640 -0
- package/dist/chunk-NLFKYSN7.js.map +1 -0
- package/dist/chunk-UALBZA5X.js +123 -0
- package/dist/chunk-UALBZA5X.js.map +1 -0
- package/dist/chunk-YIWT7BWN.js +33 -0
- package/dist/chunk-YIWT7BWN.js.map +1 -0
- package/dist/{chunk-EL2WSQBR.js → chunk-ZA4RG25C.js} +6 -33
- package/dist/chunk-ZA4RG25C.js.map +1 -0
- package/dist/cli.js +1929 -77
- package/dist/cli.js.map +1 -1
- package/dist/{daemon-J4WSZXVY.js → daemon-2YGD43RJ.js} +3 -2
- package/dist/daemon-utils-LIG6K2MK.js +17 -0
- package/dist/daemon-utils-LIG6K2MK.js.map +1 -0
- package/dist/doctor-YV6KQEGW.js +2019 -0
- package/dist/doctor-YV6KQEGW.js.map +1 -0
- package/dist/esm-GTDP7OMQ-EP6UYLQG.js +14442 -0
- package/dist/esm-GTDP7OMQ-EP6UYLQG.js.map +1 -0
- package/dist/mcp/server.js +6 -3
- package/dist/mcp/server.js.map +1 -1
- package/dist/postinstall.js +0 -65
- package/dist/postinstall.js.map +1 -1
- package/package.json +4 -4
- package/dist/chunk-EL2WSQBR.js.map +0 -1
- package/dist/chunk-WXDGVKXK.js.map +0 -1
- /package/dist/{daemon-J4WSZXVY.js.map → daemon-2YGD43RJ.js.map} +0 -0
package/dist/mcp/server.js
CHANGED
|
@@ -3,7 +3,8 @@ import {
|
|
|
3
3
|
createApiClient,
|
|
4
4
|
ensureNativeModules,
|
|
5
5
|
getAuthenticatedClient
|
|
6
|
-
} from "../chunk-
|
|
6
|
+
} from "../chunk-ND2YSPQ6.js";
|
|
7
|
+
import "../chunk-UALBZA5X.js";
|
|
7
8
|
import {
|
|
8
9
|
AUTH_STORE_PATH,
|
|
9
10
|
Sentry,
|
|
@@ -14,11 +15,13 @@ import {
|
|
|
14
15
|
} from "../chunk-FS55W24B.js";
|
|
15
16
|
import {
|
|
16
17
|
parsePanopticonRunning
|
|
17
|
-
} from "../chunk-
|
|
18
|
+
} from "../chunk-YIWT7BWN.js";
|
|
19
|
+
import "../chunk-ZA4RG25C.js";
|
|
18
20
|
import {
|
|
19
21
|
FML_DATA_DIR,
|
|
20
22
|
FML_LOG_DIR
|
|
21
23
|
} from "../chunk-4YEAQJPF.js";
|
|
24
|
+
import "../chunk-2CRFCFE4.js";
|
|
22
25
|
import "../chunk-PZ5AY32C.js";
|
|
23
26
|
|
|
24
27
|
// src/mcp/server.ts
|
|
@@ -473,7 +476,7 @@ async function main() {
|
|
|
473
476
|
await server.connect(transport);
|
|
474
477
|
if (!parsePanopticonRunning()) {
|
|
475
478
|
try {
|
|
476
|
-
const { handleStart } = await import("../daemon-
|
|
479
|
+
const { handleStart } = await import("../daemon-2YGD43RJ.js");
|
|
477
480
|
await handleStart();
|
|
478
481
|
} catch {
|
|
479
482
|
console.error(
|
package/dist/mcp/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/mcp/server.ts","../../src/mcp/tools.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { ensureNativeModules } from \"../native-check.js\";\nensureNativeModules();\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { registerTools } from \"./tools.js\";\nimport { getValidToken, readTokens } from \"../auth/token-store.js\";\nimport { AUTH_STORE_PATH } from \"../config.js\";\nimport { initSentry, Sentry } from \"../sentry.js\";\nimport { parsePanopticonRunning } from \"../commands/daemon.js\";\nimport { FML_DATA_DIR, FML_LOG_DIR } from \"../dirs.js\";\n\nconst LOG_PATH = path.join(FML_LOG_DIR, \"mcp.log\");\n\nconst server = new McpServer({\n name: \"fml\",\n version: \"0.1.0\",\n});\n\nregisterTools(server);\n\nasync function main() {\n await initSentry();\n\n // Redirect stderr to log file (stdout is reserved for MCP JSON-RPC protocol)\n if (!fs.existsSync(FML_LOG_DIR)) {\n fs.mkdirSync(FML_LOG_DIR, { recursive: true });\n }\n const logFd = fs.openSync(LOG_PATH, \"a\");\n const logStream = fs.createWriteStream(\"\", { fd: logFd });\n process.stderr.write = logStream.write.bind(\n logStream,\n ) as typeof process.stderr.write;\n\n // Check auth state and surface setup prompts\n const tokens = readTokens();\n const tokenValid = tokens ? await getValidToken() : null;\n\n if (!tokens) {\n try {\n const files = fs.readdirSync(FML_DATA_DIR).join(\", \") || \"(empty)\";\n console.error(\n `[fml] No auth file at ${AUTH_STORE_PATH}. Dir contents: ${files}`,\n );\n } catch {\n console.error(\n `[fml] No auth file at ${AUTH_STORE_PATH}. Dir not readable.`,\n );\n }\n server.resource(\"setup\", \"fml://setup\", async () => ({\n contents: [\n {\n uri: \"fml://setup\",\n text: \"FML plugin is not authenticated. Run `fml login` in your terminal to sign in, then restart Claude Code.\",\n },\n ],\n }));\n console.error(\"[fml] Not authenticated — run `fml login`\");\n } else if (!tokenValid) {\n console.error(\"[fml] Token expired — run `fml login` to re-authenticate\");\n }\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n\n // Ensure panopticon is running (includes sync, which handles config snapshots)\n if (!parsePanopticonRunning()) {\n try {\n const { handleStart } = await import(\"../commands/daemon.js\");\n await handleStart();\n } catch {\n console.error(\n \"[fml] Warning: could not start panopticon. Run `fml start` manually\",\n );\n }\n }\n}\n\nmain().catch((err) => {\n Sentry.captureException(err);\n console.error(\"FML MCP server error:\", err);\n process.exit(1);\n});\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport {\n getSelectedOrg,\n getValidToken,\n readTokens,\n} from \"../auth/token-store.js\";\nimport { createApiClient, getAuthenticatedClient } from \"../convex-client.js\";\nimport { Sentry } from \"../sentry.js\";\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction textResult(data: unknown) {\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(data, null, 2) }],\n };\n}\n\nfunction errorResult(message: string) {\n return {\n content: [{ type: \"text\" as const, text: message }],\n isError: true,\n };\n}\n\nconst PANOPTICON_HINT =\n \"\\n\\nFor local data, use the panopticon MCP tools instead (e.g. panopticon__sessions, panopticon__costs, panopticon__search, panopticon__timeline).\";\n\nasync function toolHandler(toolName: string, args: Record<string, unknown>) {\n try {\n const api = await getAuthenticatedClient();\n if (!api) {\n return errorResult(\n \"Not authenticated. Run `fml login` to sign in, then restart Claude Code.\" +\n PANOPTICON_HINT,\n );\n }\n const result = await api.callBackend(toolName, args);\n if (!result.ok) {\n return errorResult((result.error ?? \"Unknown error\") + PANOPTICON_HINT);\n }\n return textResult(result.result);\n } catch (err) {\n Sentry.captureException(err);\n const msg = err instanceof Error ? err.message : String(err);\n return errorResult(`Unexpected error: ${msg}` + PANOPTICON_HINT);\n }\n}\n\n// ─── Registration ─────────────────────────────────────────────────────────────\n\nexport function registerTools(server: McpServer): void {\n server.tool(\n \"whoami\",\n \"Show current authenticated user and available organizations\",\n {},\n async () => {\n const tokens = readTokens();\n const token = tokens ? await getValidToken() : null;\n let orgs = null;\n if (token) {\n try {\n orgs = await createApiClient(token).queryOrgs();\n } catch {}\n }\n return textResult({\n authenticated: !!tokens,\n user: tokens?.user ?? null,\n orgs,\n });\n },\n );\n\n // ── Messages ───────────────────────────────────────────────────────────────\n\n server.tool(\n \"fml_list_messages\",\n \"List messages from a conversation within a time range. Requires a conversationId from the FML web app.\",\n {\n startTime: z\n .number()\n .optional()\n .describe(\n \"Start time in milliseconds (inclusive). Omit to start from beginning.\",\n ),\n endTime: z\n .number()\n .optional()\n .describe(\n \"End time in milliseconds (inclusive). Omit to include up to most recent.\",\n ),\n limit: z\n .number()\n .optional()\n .describe(\n \"Maximum number of messages to return per page (default: 20)\",\n ),\n cursor: z\n .string()\n .optional()\n .describe(\"Pagination cursor from previous result to get next page\"),\n },\n async (args) => toolHandler(\"list-messages\", args),\n );\n\n server.tool(\n \"fml_list_messages_with_context\",\n \"Get messages around a specific message to see the context. Takes a message ID and returns messages before and after it.\",\n {\n messageId: z\n .string()\n .describe(\"The ID of the target message to get context around\"),\n before: z\n .number()\n .optional()\n .describe(\n \"Number of messages to retrieve before the target (default: 5)\",\n ),\n after: z\n .number()\n .optional()\n .describe(\n \"Number of messages to retrieve after the target (default: 5)\",\n ),\n },\n async (args) => toolHandler(\"list-messages-with-context\", args),\n );\n\n // ── Slack ──────────────────────────────────────────────────────────────────\n\n server.tool(\n \"fml_get_slack_channel_history\",\n \"Fetch recent message history from a Slack channel. Requires Slack integration to be connected.\",\n {\n channelId: z\n .string()\n .optional()\n .describe(\n \"Slack channel ID (e.g. C0123ABC). If omitted, uses the channel from the current Slack-sourced conversation.\",\n ),\n limit: z\n .number()\n .optional()\n .describe(\"Number of messages to fetch (default 20, max 50)\"),\n },\n async (args) => toolHandler(\"get-slack-channel-history\", args),\n );\n\n server.tool(\n \"fml_get_slack_message\",\n \"Fetch a specific Slack message by timestamp or permalink. Requires Slack integration to be connected.\",\n {\n permalink: z\n .string()\n .optional()\n .describe(\n \"Slack message permalink. If provided, channelId and messageTs are ignored.\",\n ),\n channelId: z\n .string()\n .optional()\n .describe(\n \"Slack channel ID (e.g. C0123ABC). Required if permalink not provided.\",\n ),\n messageTs: z\n .string()\n .optional()\n .describe(\n \"Message timestamp (e.g. 1234567890.123456). Required if permalink not provided.\",\n ),\n includeThreadContext: z\n .boolean()\n .optional()\n .describe(\n \"If true, fetches thread replies along with the message (default false)\",\n ),\n },\n async (args) => toolHandler(\"get-slack-message\", args),\n );\n\n // ── Skills ─────────────────────────────────────────────────────────────────\n\n server.tool(\n \"fml_list_skills\",\n \"List all available FML skills. Skills provide detailed knowledge about FML features.\",\n {},\n async () => toolHandler(\"list-skills\", {}),\n );\n\n server.tool(\n \"fml_load_skill\",\n \"Load a skill prompt by ID. Skills provide detailed knowledge about FML features.\",\n {\n skillId: z\n .string()\n .describe(\"The skill ID to load (e.g., 'fml-help', 'fml-navigation')\"),\n },\n async (args) => toolHandler(\"load-skill\", args),\n );\n\n // ── Analysis ───────────────────────────────────────────────────────────────\n\n server.tool(\n \"fml_search_analysis\",\n \"Search analysis results. USE FOR: finding analyses by topic, type, or status. RETURNS: full analysis content.\",\n {\n query: z\n .string()\n .optional()\n .describe(\"Text search across analysis type and content\"),\n promptKey: z\n .string()\n .optional()\n .describe(\"Exact filter by analysis type (e.g., 'analyze-codebase')\"),\n status: z\n .enum([\"complete\", \"running\", \"created\", \"failed\"])\n .optional()\n .describe(\"Filter by status\"),\n limit: z\n .number()\n .optional()\n .describe(\"Maximum number of results to return (default 20)\"),\n },\n async (args) => toolHandler(\"search-analysis\", args),\n );\n\n server.tool(\n \"fml_run_analysis_workflow\",\n \"Run comprehensive codebase analysis workflows. Available prompts: deep_security_auditor, deep_architecture_auditor, deep_code_quality_auditor, deep_performance_auditor, deep_ux_auditor, deep_dependencies_auditor, deep_cost_auditor, deep_ai_architecture_integration, deep_ai_security.\",\n {\n selectedPromptKeys: z\n .array(\n z.enum([\n \"deep_security_auditor\",\n \"deep_architecture_auditor\",\n \"deep_code_quality_auditor\",\n \"deep_performance_auditor\",\n \"deep_ux_auditor\",\n \"deep_dependencies_auditor\",\n \"deep_cost_auditor\",\n \"deep_ai_architecture_integration\",\n \"deep_ai_security\",\n ]),\n )\n .optional()\n .describe(\n \"Array of specific analysis prompts to run. If not provided, runs default set.\",\n ),\n },\n async (args) => toolHandler(\"run-analysis-workflow\", args),\n );\n\n // ── Integrations ───────────────────────────────────────────────────────────\n\n server.tool(\n \"fml_list_integrations\",\n \"List integrations for this project — both connected and available. Use to check what integrations are active.\",\n {},\n async () => toolHandler(\"list-integrations\", {}),\n );\n\n // Integration query tools\n const integrationTools: Array<{\n name: string;\n mastraId: string;\n description: string;\n endpointHelp: string;\n }> = [\n {\n name: \"fml_query_sentry\",\n mastraId: \"integration-sentry\",\n description:\n \"Look up production errors, exceptions, and crash data from Sentry. Common endpoints: 'organizations/{orgSlug}/issues/' (GET), 'issues/{issue_id}/' (GET). {orgSlug} is auto-substituted.\",\n endpointHelp:\n \"Sentry REST API endpoint. {orgSlug} is auto-substituted. e.g. 'organizations/{orgSlug}/issues/'\",\n },\n {\n name: \"fml_query_slack\",\n mastraId: \"integration-slack\",\n description:\n \"Send messages and read channel/user info from Slack. Use channel IDs not names. Common endpoints: 'conversations.list' (GET), 'chat.postMessage' (POST).\",\n endpointHelp:\n \"Slack API method, e.g. 'conversations.list', 'chat.postMessage'\",\n },\n {\n name: \"fml_query_github\",\n mastraId: \"integration-github\",\n description:\n \"Query repository activity from GitHub — PRs, commits, issues, code. {owner} and {repo} are auto-substituted. Common endpoints: 'repos/{owner}/{repo}/pulls' (GET).\",\n endpointHelp: \"GitHub REST API path. e.g. 'repos/{owner}/{repo}/pulls'\",\n },\n {\n name: \"fml_query_linear\",\n mastraId: \"integration-linear\",\n description:\n \"Query and manage Linear issues and projects via GraphQL. Endpoint is always 'graphql', method POST.\",\n endpointHelp:\n \"Linear GraphQL endpoint — always use 'graphql' with method POST and {query, variables} in body\",\n },\n {\n name: \"fml_query_notion\",\n mastraId: \"integration-notion\",\n description:\n \"Search pages, query databases, read and write content in Notion. Common endpoints: 'search' (POST), 'databases/{id}/query' (POST).\",\n endpointHelp:\n \"Notion REST API endpoint, e.g. 'search', 'databases/{database_id}/query'\",\n },\n {\n name: \"fml_query_freshdesk\",\n mastraId: \"integration-freshdesk\",\n description:\n \"Query and manage customer support tickets in Freshdesk. Common endpoints: 'tickets' (GET), 'tickets/{id}' (GET).\",\n endpointHelp:\n \"Freshdesk REST API v2 endpoint, e.g. 'tickets', 'tickets/{id}'\",\n },\n ];\n\n for (const tool of integrationTools) {\n server.tool(\n tool.name,\n tool.description,\n {\n endpoint: z.string().describe(tool.endpointHelp),\n method: z\n .enum([\"GET\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\"])\n .optional()\n .describe(\"HTTP method. Defaults to GET.\"),\n body: z\n .record(z.string(), z.unknown())\n .optional()\n .describe(\"Request body as a JSON object (for POST/PUT/PATCH)\"),\n projectId: z\n .string()\n .optional()\n .describe(\n \"Optional project ID to scope this query. Required for GitHub (needs repo context).\",\n ),\n },\n async (args) => toolHandler(tool.mastraId, args),\n );\n }\n\n // ── Engineering Activity ───────────────────────────────────────────────────\n\n server.tool(\n \"get_engineering_activity\",\n \"Get agent activity summary (Claude Code, Codex, Gemini CLI, Mastra). SCOPES: 'org' (default), 'project', or 'user' (by githubUsername).\",\n {\n timeRange: z\n .enum([\"1h\", \"6h\", \"24h\", \"7d\", \"30d\"])\n .optional()\n .describe(\"Preset time range. Default '7d'.\"),\n since: z\n .string()\n .optional()\n .describe(\"ISO 8601 start timestamp. Overrides timeRange.\"),\n until: z.string().optional().describe(\"ISO 8601 end timestamp.\"),\n target: z\n .enum([\"claude\", \"codex\", \"gemini\", \"mastra\"])\n .optional()\n .describe(\"Filter by agent type. Omit for all.\"),\n scope: z\n .enum([\"org\", \"project\", \"user\"])\n .optional()\n .describe(\"Query scope. 'org' (default), 'project', or 'user'.\"),\n githubUsername: z\n .string()\n .optional()\n .describe(\"Required when scope is 'user'. GitHub username.\"),\n },\n async (args) => toolHandler(\"get-engineering-activity\", args),\n );\n\n server.tool(\n \"list_engineering_sessions\",\n \"List agent sessions (Claude Code, Codex, Gemini CLI, Mastra). Each session includes first prompt preview and event counts.\",\n {\n scope: z\n .enum([\"org\", \"project\"])\n .optional()\n .describe(\"Query scope. Default 'org'.\"),\n target: z\n .enum([\"claude\", \"codex\", \"gemini\", \"mastra\"])\n .optional()\n .describe(\"Filter by agent type. Omit for all.\"),\n githubUsername: z\n .string()\n .optional()\n .describe(\"Filter to sessions by this GitHub username.\"),\n timeRange: z.enum([\"1h\", \"6h\", \"24h\", \"7d\", \"30d\"]).optional(),\n since: z.string().optional().describe(\"ISO 8601 start timestamp.\"),\n until: z.string().optional().describe(\"ISO 8601 end timestamp.\"),\n limit: z\n .number()\n .optional()\n .describe(\"Max sessions to return (default 20, max 50).\"),\n },\n async (args) => toolHandler(\"list-engineering-sessions\", args),\n );\n\n server.tool(\n \"get_session_timeline\",\n 'Get chronological timeline for a coding agent session. Returns messages and/or hook events interleaved by timestamp. Use source=\"hooks\" to see permission requests, tool approvals, etc. REQUIRES: sessionId from list_engineering_sessions.',\n {\n sessionId: z.string().describe(\"The session ID to get details for.\"),\n includeSystemMessages: z\n .boolean()\n .optional()\n .describe(\"Include system messages (default false).\"),\n source: z\n .enum([\"messages\", \"hooks\", \"all\"])\n .optional()\n .describe(\n 'Filter by source: \"messages\" (scanner messages only), \"hooks\" (hook events only), \"all\" (both interleaved). Default \"all\".',\n ),\n eventType: z\n .string()\n .optional()\n .describe(\n 'Filter hook events by type (e.g. \"PermissionRequest\", \"PreToolUse\", \"Stop\"). Only applies when source includes hooks.',\n ),\n limit: z\n .number()\n .optional()\n .describe(\"Max entries to return (default 50, max 200).\"),\n offset: z\n .number()\n .optional()\n .describe(\"Skip first N entries for pagination.\"),\n },\n async (args) => toolHandler(\"get-session-timeline\", args),\n );\n\n server.tool(\n \"get_session_turns\",\n \"Get per-turn token accounting for a coding agent session. USE FOR: understanding cost per turn, model used at each step, cache hit analysis. REQUIRES: sessionId from list_engineering_sessions.\",\n {\n sessionId: z.string().describe(\"The session ID to get turns for.\"),\n limit: z\n .number()\n .optional()\n .describe(\"Max turns to return (default 50, max 200).\"),\n offset: z\n .number()\n .optional()\n .describe(\"Skip first N turns for pagination.\"),\n },\n async (args) => toolHandler(\"get-session-turns\", args),\n );\n\n server.tool(\n \"get_ai_spending\",\n \"Get AI spending and token usage data. Groups by 'session' (default), 'model', or 'day'.\",\n {\n timeRange: z\n .enum([\"1h\", \"6h\", \"24h\", \"7d\", \"30d\"])\n .optional()\n .describe(\"Default '7d'.\"),\n since: z.string().optional().describe(\"ISO 8601 start timestamp.\"),\n until: z.string().optional().describe(\"ISO 8601 end timestamp.\"),\n groupBy: z\n .enum([\"session\", \"model\", \"day\"])\n .optional()\n .describe(\"How to group results.\"),\n target: z\n .enum([\"claude\", \"codex\", \"gemini\", \"mastra\"])\n .optional()\n .describe(\"Filter by agent type. Omit for all.\"),\n },\n async (args) => toolHandler(\"get-ai-spending\", args),\n );\n\n server.tool(\n \"search_engineering_sessions\",\n \"Search across agent sessions by text. Searches prompts, tool names, and event payloads.\",\n {\n query: z.string().describe(\"Text to search for. Case-insensitive.\"),\n timeRange: z.enum([\"1h\", \"6h\", \"24h\", \"7d\", \"30d\"]).optional(),\n since: z.string().optional(),\n until: z.string().optional(),\n target: z\n .enum([\"claude\", \"codex\", \"gemini\", \"mastra\"])\n .optional()\n .describe(\"Filter by agent type. Omit for all.\"),\n limit: z.number().optional().describe(\"Max results (default 20).\"),\n },\n async (args) => toolHandler(\"search-engineering-sessions\", args),\n );\n\n // ── Config Snapshots ────────────────────────────────────────────────────\n\n server.tool(\n \"list_user_configs\",\n \"List user-level configuration snapshots (CLAUDE.md, settings, etc.) across the org. Shows who has configs and when they were last updated.\",\n {},\n async () => {\n try {\n const orgSlug = getSelectedOrg();\n if (!orgSlug) return errorResult(\"No org selected. Run `fml login`.\");\n const api = await getAuthenticatedClient();\n if (!api) return errorResult(\"Not authenticated. Run `fml login`.\");\n const result = await api.listUserConfigSnapshots(orgSlug);\n return textResult(result);\n } catch (err) {\n Sentry.captureException(err);\n return errorResult(\n `Error: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n },\n );\n\n server.tool(\n \"get_user_config\",\n \"Get detailed user configuration for a specific GitHub user — their CLAUDE.md, settings.json, MCP servers, etc.\",\n {\n githubUsername: z.string().describe(\"GitHub username to look up.\"),\n },\n async (args) => {\n try {\n const orgSlug = getSelectedOrg();\n if (!orgSlug) return errorResult(\"No org selected. Run `fml login`.\");\n const api = await getAuthenticatedClient();\n if (!api) return errorResult(\"Not authenticated. Run `fml login`.\");\n const result = await api.getUserConfigDetail(\n orgSlug,\n args.githubUsername,\n );\n if (!result)\n return errorResult(`No config found for ${args.githubUsername}.`);\n return textResult(result);\n } catch (err) {\n Sentry.captureException(err);\n return errorResult(\n `Error: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n },\n );\n\n server.tool(\n \"list_repo_configs\",\n \"List repository-level configuration snapshots (CLAUDE.md, .mcp.json, etc.) across the org. Optionally filter by repository.\",\n {\n repository: z\n .string()\n .optional()\n .describe(\"Filter by repository full name (e.g. 'org/repo').\"),\n },\n async (args) => {\n try {\n const orgSlug = getSelectedOrg();\n if (!orgSlug) return errorResult(\"No org selected. Run `fml login`.\");\n const api = await getAuthenticatedClient();\n if (!api) return errorResult(\"Not authenticated. Run `fml login`.\");\n const result = await api.listRepoConfigSnapshots(\n orgSlug,\n args.repository,\n );\n return textResult(result);\n } catch (err) {\n Sentry.captureException(err);\n return errorResult(\n `Error: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n },\n );\n\n server.tool(\n \"get_repo_config\",\n \"Get detailed repository configuration — CLAUDE.md files, .mcp.json, and other agent config found in a specific repo.\",\n {\n repository: z\n .string()\n .describe(\"Repository full name (e.g. 'org/repo').\"),\n },\n async (args) => {\n try {\n const orgSlug = getSelectedOrg();\n if (!orgSlug) return errorResult(\"No org selected. Run `fml login`.\");\n const api = await getAuthenticatedClient();\n if (!api) return errorResult(\"Not authenticated. Run `fml login`.\");\n const result = await api.getRepoConfigDetail(orgSlug, args.repository);\n if (!result)\n return errorResult(`No config found for ${args.repository}.`);\n return textResult(result);\n } catch (err) {\n Sentry.captureException(err);\n return errorResult(\n `Error: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n },\n );\n}\n"],"mappings":"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","names":["server"]}
|
|
1
|
+
{"version":3,"sources":["../../src/mcp/server.ts","../../src/mcp/tools.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { ensureNativeModules } from \"../native-check.js\";\nensureNativeModules();\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { registerTools } from \"./tools.js\";\nimport { getValidToken, readTokens } from \"../auth/token-store.js\";\nimport { AUTH_STORE_PATH } from \"../config.js\";\nimport { initSentry, Sentry } from \"../sentry.js\";\nimport { parsePanopticonRunning } from \"../commands/daemon.js\";\nimport { FML_DATA_DIR, FML_LOG_DIR } from \"../dirs.js\";\n\nconst LOG_PATH = path.join(FML_LOG_DIR, \"mcp.log\");\n\nconst server = new McpServer({\n name: \"fml\",\n version: \"0.1.0\",\n});\n\nregisterTools(server);\n\nasync function main() {\n await initSentry();\n\n // Redirect stderr to log file (stdout is reserved for MCP JSON-RPC protocol)\n if (!fs.existsSync(FML_LOG_DIR)) {\n fs.mkdirSync(FML_LOG_DIR, { recursive: true });\n }\n const logFd = fs.openSync(LOG_PATH, \"a\");\n const logStream = fs.createWriteStream(\"\", { fd: logFd });\n process.stderr.write = logStream.write.bind(\n logStream,\n ) as typeof process.stderr.write;\n\n // Check auth state and surface setup prompts\n const tokens = readTokens();\n const tokenValid = tokens ? await getValidToken() : null;\n\n if (!tokens) {\n try {\n const files = fs.readdirSync(FML_DATA_DIR).join(\", \") || \"(empty)\";\n console.error(\n `[fml] No auth file at ${AUTH_STORE_PATH}. Dir contents: ${files}`,\n );\n } catch {\n console.error(\n `[fml] No auth file at ${AUTH_STORE_PATH}. Dir not readable.`,\n );\n }\n server.resource(\"setup\", \"fml://setup\", async () => ({\n contents: [\n {\n uri: \"fml://setup\",\n text: \"FML plugin is not authenticated. Run `fml login` in your terminal to sign in, then restart Claude Code.\",\n },\n ],\n }));\n console.error(\"[fml] Not authenticated — run `fml login`\");\n } else if (!tokenValid) {\n console.error(\"[fml] Token expired — run `fml login` to re-authenticate\");\n }\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n\n // Ensure panopticon is running (includes sync, which handles config snapshots)\n if (!parsePanopticonRunning()) {\n try {\n const { handleStart } = await import(\"../commands/daemon.js\");\n await handleStart();\n } catch {\n console.error(\n \"[fml] Warning: could not start panopticon. Run `fml start` manually\",\n );\n }\n }\n}\n\nmain().catch((err) => {\n Sentry.captureException(err);\n console.error(\"FML MCP server error:\", err);\n process.exit(1);\n});\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport {\n getSelectedOrg,\n getValidToken,\n readTokens,\n} from \"../auth/token-store.js\";\nimport { createApiClient, getAuthenticatedClient } from \"../convex-client.js\";\nimport { Sentry } from \"../sentry.js\";\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction textResult(data: unknown) {\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(data, null, 2) }],\n };\n}\n\nfunction errorResult(message: string) {\n return {\n content: [{ type: \"text\" as const, text: message }],\n isError: true,\n };\n}\n\nconst PANOPTICON_HINT =\n \"\\n\\nFor local data, use the panopticon MCP tools instead (e.g. panopticon__sessions, panopticon__costs, panopticon__search, panopticon__timeline).\";\n\nasync function toolHandler(toolName: string, args: Record<string, unknown>) {\n try {\n const api = await getAuthenticatedClient();\n if (!api) {\n return errorResult(\n \"Not authenticated. Run `fml login` to sign in, then restart Claude Code.\" +\n PANOPTICON_HINT,\n );\n }\n const result = await api.callBackend(toolName, args);\n if (!result.ok) {\n return errorResult((result.error ?? \"Unknown error\") + PANOPTICON_HINT);\n }\n return textResult(result.result);\n } catch (err) {\n Sentry.captureException(err);\n const msg = err instanceof Error ? err.message : String(err);\n return errorResult(`Unexpected error: ${msg}` + PANOPTICON_HINT);\n }\n}\n\n// ─── Registration ─────────────────────────────────────────────────────────────\n\nexport function registerTools(server: McpServer): void {\n server.tool(\n \"whoami\",\n \"Show current authenticated user and available organizations\",\n {},\n async () => {\n const tokens = readTokens();\n const token = tokens ? await getValidToken() : null;\n let orgs = null;\n if (token) {\n try {\n orgs = await createApiClient(token).queryOrgs();\n } catch {}\n }\n return textResult({\n authenticated: !!tokens,\n user: tokens?.user ?? null,\n orgs,\n });\n },\n );\n\n // ── Messages ───────────────────────────────────────────────────────────────\n\n server.tool(\n \"fml_list_messages\",\n \"List messages from a conversation within a time range. Requires a conversationId from the FML web app.\",\n {\n startTime: z\n .number()\n .optional()\n .describe(\n \"Start time in milliseconds (inclusive). Omit to start from beginning.\",\n ),\n endTime: z\n .number()\n .optional()\n .describe(\n \"End time in milliseconds (inclusive). Omit to include up to most recent.\",\n ),\n limit: z\n .number()\n .optional()\n .describe(\n \"Maximum number of messages to return per page (default: 20)\",\n ),\n cursor: z\n .string()\n .optional()\n .describe(\"Pagination cursor from previous result to get next page\"),\n },\n async (args) => toolHandler(\"list-messages\", args),\n );\n\n server.tool(\n \"fml_list_messages_with_context\",\n \"Get messages around a specific message to see the context. Takes a message ID and returns messages before and after it.\",\n {\n messageId: z\n .string()\n .describe(\"The ID of the target message to get context around\"),\n before: z\n .number()\n .optional()\n .describe(\n \"Number of messages to retrieve before the target (default: 5)\",\n ),\n after: z\n .number()\n .optional()\n .describe(\n \"Number of messages to retrieve after the target (default: 5)\",\n ),\n },\n async (args) => toolHandler(\"list-messages-with-context\", args),\n );\n\n // ── Slack ──────────────────────────────────────────────────────────────────\n\n server.tool(\n \"fml_get_slack_channel_history\",\n \"Fetch recent message history from a Slack channel. Requires Slack integration to be connected.\",\n {\n channelId: z\n .string()\n .optional()\n .describe(\n \"Slack channel ID (e.g. C0123ABC). If omitted, uses the channel from the current Slack-sourced conversation.\",\n ),\n limit: z\n .number()\n .optional()\n .describe(\"Number of messages to fetch (default 20, max 50)\"),\n },\n async (args) => toolHandler(\"get-slack-channel-history\", args),\n );\n\n server.tool(\n \"fml_get_slack_message\",\n \"Fetch a specific Slack message by timestamp or permalink. Requires Slack integration to be connected.\",\n {\n permalink: z\n .string()\n .optional()\n .describe(\n \"Slack message permalink. If provided, channelId and messageTs are ignored.\",\n ),\n channelId: z\n .string()\n .optional()\n .describe(\n \"Slack channel ID (e.g. C0123ABC). Required if permalink not provided.\",\n ),\n messageTs: z\n .string()\n .optional()\n .describe(\n \"Message timestamp (e.g. 1234567890.123456). Required if permalink not provided.\",\n ),\n includeThreadContext: z\n .boolean()\n .optional()\n .describe(\n \"If true, fetches thread replies along with the message (default false)\",\n ),\n },\n async (args) => toolHandler(\"get-slack-message\", args),\n );\n\n // ── Skills ─────────────────────────────────────────────────────────────────\n\n server.tool(\n \"fml_list_skills\",\n \"List all available FML skills. Skills provide detailed knowledge about FML features.\",\n {},\n async () => toolHandler(\"list-skills\", {}),\n );\n\n server.tool(\n \"fml_load_skill\",\n \"Load a skill prompt by ID. Skills provide detailed knowledge about FML features.\",\n {\n skillId: z\n .string()\n .describe(\"The skill ID to load (e.g., 'fml-help', 'fml-navigation')\"),\n },\n async (args) => toolHandler(\"load-skill\", args),\n );\n\n // ── Analysis ───────────────────────────────────────────────────────────────\n\n server.tool(\n \"fml_search_analysis\",\n \"Search analysis results. USE FOR: finding analyses by topic, type, or status. RETURNS: full analysis content.\",\n {\n query: z\n .string()\n .optional()\n .describe(\"Text search across analysis type and content\"),\n promptKey: z\n .string()\n .optional()\n .describe(\"Exact filter by analysis type (e.g., 'analyze-codebase')\"),\n status: z\n .enum([\"complete\", \"running\", \"created\", \"failed\"])\n .optional()\n .describe(\"Filter by status\"),\n limit: z\n .number()\n .optional()\n .describe(\"Maximum number of results to return (default 20)\"),\n },\n async (args) => toolHandler(\"search-analysis\", args),\n );\n\n server.tool(\n \"fml_run_analysis_workflow\",\n \"Run comprehensive codebase analysis workflows. Available prompts: deep_security_auditor, deep_architecture_auditor, deep_code_quality_auditor, deep_performance_auditor, deep_ux_auditor, deep_dependencies_auditor, deep_cost_auditor, deep_ai_architecture_integration, deep_ai_security.\",\n {\n selectedPromptKeys: z\n .array(\n z.enum([\n \"deep_security_auditor\",\n \"deep_architecture_auditor\",\n \"deep_code_quality_auditor\",\n \"deep_performance_auditor\",\n \"deep_ux_auditor\",\n \"deep_dependencies_auditor\",\n \"deep_cost_auditor\",\n \"deep_ai_architecture_integration\",\n \"deep_ai_security\",\n ]),\n )\n .optional()\n .describe(\n \"Array of specific analysis prompts to run. If not provided, runs default set.\",\n ),\n },\n async (args) => toolHandler(\"run-analysis-workflow\", args),\n );\n\n // ── Integrations ───────────────────────────────────────────────────────────\n\n server.tool(\n \"fml_list_integrations\",\n \"List integrations for this project — both connected and available. Use to check what integrations are active.\",\n {},\n async () => toolHandler(\"list-integrations\", {}),\n );\n\n // Integration query tools\n const integrationTools: Array<{\n name: string;\n mastraId: string;\n description: string;\n endpointHelp: string;\n }> = [\n {\n name: \"fml_query_sentry\",\n mastraId: \"integration-sentry\",\n description:\n \"Look up production errors, exceptions, and crash data from Sentry. Common endpoints: 'organizations/{orgSlug}/issues/' (GET), 'issues/{issue_id}/' (GET). {orgSlug} is auto-substituted.\",\n endpointHelp:\n \"Sentry REST API endpoint. {orgSlug} is auto-substituted. e.g. 'organizations/{orgSlug}/issues/'\",\n },\n {\n name: \"fml_query_slack\",\n mastraId: \"integration-slack\",\n description:\n \"Send messages and read channel/user info from Slack. Use channel IDs not names. Common endpoints: 'conversations.list' (GET), 'chat.postMessage' (POST).\",\n endpointHelp:\n \"Slack API method, e.g. 'conversations.list', 'chat.postMessage'\",\n },\n {\n name: \"fml_query_github\",\n mastraId: \"integration-github\",\n description:\n \"Query repository activity from GitHub — PRs, commits, issues, code. {owner} and {repo} are auto-substituted. Common endpoints: 'repos/{owner}/{repo}/pulls' (GET).\",\n endpointHelp: \"GitHub REST API path. e.g. 'repos/{owner}/{repo}/pulls'\",\n },\n {\n name: \"fml_query_linear\",\n mastraId: \"integration-linear\",\n description:\n \"Query and manage Linear issues and projects via GraphQL. Endpoint is always 'graphql', method POST.\",\n endpointHelp:\n \"Linear GraphQL endpoint — always use 'graphql' with method POST and {query, variables} in body\",\n },\n {\n name: \"fml_query_notion\",\n mastraId: \"integration-notion\",\n description:\n \"Search pages, query databases, read and write content in Notion. Common endpoints: 'search' (POST), 'databases/{id}/query' (POST).\",\n endpointHelp:\n \"Notion REST API endpoint, e.g. 'search', 'databases/{database_id}/query'\",\n },\n {\n name: \"fml_query_freshdesk\",\n mastraId: \"integration-freshdesk\",\n description:\n \"Query and manage customer support tickets in Freshdesk. Common endpoints: 'tickets' (GET), 'tickets/{id}' (GET).\",\n endpointHelp:\n \"Freshdesk REST API v2 endpoint, e.g. 'tickets', 'tickets/{id}'\",\n },\n ];\n\n for (const tool of integrationTools) {\n server.tool(\n tool.name,\n tool.description,\n {\n endpoint: z.string().describe(tool.endpointHelp),\n method: z\n .enum([\"GET\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\"])\n .optional()\n .describe(\"HTTP method. Defaults to GET.\"),\n body: z\n .record(z.string(), z.unknown())\n .optional()\n .describe(\"Request body as a JSON object (for POST/PUT/PATCH)\"),\n projectId: z\n .string()\n .optional()\n .describe(\n \"Optional project ID to scope this query. Required for GitHub (needs repo context).\",\n ),\n },\n async (args) => toolHandler(tool.mastraId, args),\n );\n }\n\n // ── Engineering Activity ───────────────────────────────────────────────────\n\n server.tool(\n \"get_engineering_activity\",\n \"Get agent activity summary (Claude Code, Codex, Gemini CLI, Mastra). SCOPES: 'org' (default), 'project', or 'user' (by githubUsername).\",\n {\n timeRange: z\n .enum([\"1h\", \"6h\", \"24h\", \"7d\", \"30d\"])\n .optional()\n .describe(\"Preset time range. Default '7d'.\"),\n since: z\n .string()\n .optional()\n .describe(\"ISO 8601 start timestamp. Overrides timeRange.\"),\n until: z.string().optional().describe(\"ISO 8601 end timestamp.\"),\n target: z\n .enum([\"claude\", \"codex\", \"gemini\", \"mastra\"])\n .optional()\n .describe(\"Filter by agent type. Omit for all.\"),\n scope: z\n .enum([\"org\", \"project\", \"user\"])\n .optional()\n .describe(\"Query scope. 'org' (default), 'project', or 'user'.\"),\n githubUsername: z\n .string()\n .optional()\n .describe(\"Required when scope is 'user'. GitHub username.\"),\n },\n async (args) => toolHandler(\"get-engineering-activity\", args),\n );\n\n server.tool(\n \"list_engineering_sessions\",\n \"List agent sessions (Claude Code, Codex, Gemini CLI, Mastra). Each session includes first prompt preview and event counts.\",\n {\n scope: z\n .enum([\"org\", \"project\"])\n .optional()\n .describe(\"Query scope. Default 'org'.\"),\n target: z\n .enum([\"claude\", \"codex\", \"gemini\", \"mastra\"])\n .optional()\n .describe(\"Filter by agent type. Omit for all.\"),\n githubUsername: z\n .string()\n .optional()\n .describe(\"Filter to sessions by this GitHub username.\"),\n timeRange: z.enum([\"1h\", \"6h\", \"24h\", \"7d\", \"30d\"]).optional(),\n since: z.string().optional().describe(\"ISO 8601 start timestamp.\"),\n until: z.string().optional().describe(\"ISO 8601 end timestamp.\"),\n limit: z\n .number()\n .optional()\n .describe(\"Max sessions to return (default 20, max 50).\"),\n },\n async (args) => toolHandler(\"list-engineering-sessions\", args),\n );\n\n server.tool(\n \"get_session_timeline\",\n 'Get chronological timeline for a coding agent session. Returns messages and/or hook events interleaved by timestamp. Use source=\"hooks\" to see permission requests, tool approvals, etc. REQUIRES: sessionId from list_engineering_sessions.',\n {\n sessionId: z.string().describe(\"The session ID to get details for.\"),\n includeSystemMessages: z\n .boolean()\n .optional()\n .describe(\"Include system messages (default false).\"),\n source: z\n .enum([\"messages\", \"hooks\", \"all\"])\n .optional()\n .describe(\n 'Filter by source: \"messages\" (scanner messages only), \"hooks\" (hook events only), \"all\" (both interleaved). Default \"all\".',\n ),\n eventType: z\n .string()\n .optional()\n .describe(\n 'Filter hook events by type (e.g. \"PermissionRequest\", \"PreToolUse\", \"Stop\"). Only applies when source includes hooks.',\n ),\n limit: z\n .number()\n .optional()\n .describe(\"Max entries to return (default 50, max 200).\"),\n offset: z\n .number()\n .optional()\n .describe(\"Skip first N entries for pagination.\"),\n },\n async (args) => toolHandler(\"get-session-timeline\", args),\n );\n\n server.tool(\n \"get_session_turns\",\n \"Get per-turn token accounting for a coding agent session. USE FOR: understanding cost per turn, model used at each step, cache hit analysis. REQUIRES: sessionId from list_engineering_sessions.\",\n {\n sessionId: z.string().describe(\"The session ID to get turns for.\"),\n limit: z\n .number()\n .optional()\n .describe(\"Max turns to return (default 50, max 200).\"),\n offset: z\n .number()\n .optional()\n .describe(\"Skip first N turns for pagination.\"),\n },\n async (args) => toolHandler(\"get-session-turns\", args),\n );\n\n server.tool(\n \"get_ai_spending\",\n \"Get AI spending and token usage data. Groups by 'session' (default), 'model', or 'day'.\",\n {\n timeRange: z\n .enum([\"1h\", \"6h\", \"24h\", \"7d\", \"30d\"])\n .optional()\n .describe(\"Default '7d'.\"),\n since: z.string().optional().describe(\"ISO 8601 start timestamp.\"),\n until: z.string().optional().describe(\"ISO 8601 end timestamp.\"),\n groupBy: z\n .enum([\"session\", \"model\", \"day\"])\n .optional()\n .describe(\"How to group results.\"),\n target: z\n .enum([\"claude\", \"codex\", \"gemini\", \"mastra\"])\n .optional()\n .describe(\"Filter by agent type. Omit for all.\"),\n },\n async (args) => toolHandler(\"get-ai-spending\", args),\n );\n\n server.tool(\n \"search_engineering_sessions\",\n \"Search across agent sessions by text. Searches prompts, tool names, and event payloads.\",\n {\n query: z.string().describe(\"Text to search for. Case-insensitive.\"),\n timeRange: z.enum([\"1h\", \"6h\", \"24h\", \"7d\", \"30d\"]).optional(),\n since: z.string().optional(),\n until: z.string().optional(),\n target: z\n .enum([\"claude\", \"codex\", \"gemini\", \"mastra\"])\n .optional()\n .describe(\"Filter by agent type. Omit for all.\"),\n limit: z.number().optional().describe(\"Max results (default 20).\"),\n },\n async (args) => toolHandler(\"search-engineering-sessions\", args),\n );\n\n // ── Config Snapshots ────────────────────────────────────────────────────\n\n server.tool(\n \"list_user_configs\",\n \"List user-level configuration snapshots (CLAUDE.md, settings, etc.) across the org. Shows who has configs and when they were last updated.\",\n {},\n async () => {\n try {\n const orgSlug = getSelectedOrg();\n if (!orgSlug) return errorResult(\"No org selected. Run `fml login`.\");\n const api = await getAuthenticatedClient();\n if (!api) return errorResult(\"Not authenticated. Run `fml login`.\");\n const result = await api.listUserConfigSnapshots(orgSlug);\n return textResult(result);\n } catch (err) {\n Sentry.captureException(err);\n return errorResult(\n `Error: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n },\n );\n\n server.tool(\n \"get_user_config\",\n \"Get detailed user configuration for a specific GitHub user — their CLAUDE.md, settings.json, MCP servers, etc.\",\n {\n githubUsername: z.string().describe(\"GitHub username to look up.\"),\n },\n async (args) => {\n try {\n const orgSlug = getSelectedOrg();\n if (!orgSlug) return errorResult(\"No org selected. Run `fml login`.\");\n const api = await getAuthenticatedClient();\n if (!api) return errorResult(\"Not authenticated. Run `fml login`.\");\n const result = await api.getUserConfigDetail(\n orgSlug,\n args.githubUsername,\n );\n if (!result)\n return errorResult(`No config found for ${args.githubUsername}.`);\n return textResult(result);\n } catch (err) {\n Sentry.captureException(err);\n return errorResult(\n `Error: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n },\n );\n\n server.tool(\n \"list_repo_configs\",\n \"List repository-level configuration snapshots (CLAUDE.md, .mcp.json, etc.) across the org. Optionally filter by repository.\",\n {\n repository: z\n .string()\n .optional()\n .describe(\"Filter by repository full name (e.g. 'org/repo').\"),\n },\n async (args) => {\n try {\n const orgSlug = getSelectedOrg();\n if (!orgSlug) return errorResult(\"No org selected. Run `fml login`.\");\n const api = await getAuthenticatedClient();\n if (!api) return errorResult(\"Not authenticated. Run `fml login`.\");\n const result = await api.listRepoConfigSnapshots(\n orgSlug,\n args.repository,\n );\n return textResult(result);\n } catch (err) {\n Sentry.captureException(err);\n return errorResult(\n `Error: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n },\n );\n\n server.tool(\n \"get_repo_config\",\n \"Get detailed repository configuration — CLAUDE.md files, .mcp.json, and other agent config found in a specific repo.\",\n {\n repository: z\n .string()\n .describe(\"Repository full name (e.g. 'org/repo').\"),\n },\n async (args) => {\n try {\n const orgSlug = getSelectedOrg();\n if (!orgSlug) return errorResult(\"No org selected. Run `fml login`.\");\n const api = await getAuthenticatedClient();\n if (!api) return errorResult(\"Not authenticated. Run `fml login`.\");\n const result = await api.getRepoConfigDetail(orgSlug, args.repository);\n if (!result)\n return errorResult(`No config found for ${args.repository}.`);\n return textResult(result);\n } catch (err) {\n Sentry.captureException(err);\n return errorResult(\n `Error: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n },\n );\n}\n"],"mappings":"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","names":["server"]}
|
package/dist/postinstall.js
CHANGED
|
@@ -5,71 +5,6 @@ import { execFileSync } from "child_process";
|
|
|
5
5
|
import { dirname, join } from "path";
|
|
6
6
|
import { fileURLToPath } from "url";
|
|
7
7
|
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
|
-
function bootstrapPanopticon() {
|
|
9
|
-
const npmEnv = { ...process.env };
|
|
10
|
-
delete npmEnv.npm_config_registry;
|
|
11
|
-
let globalVersion = null;
|
|
12
|
-
try {
|
|
13
|
-
const json = execFileSync(
|
|
14
|
-
"npm",
|
|
15
|
-
["ls", "-g", "@fml-inc/panopticon", "--json", "--depth=0"],
|
|
16
|
-
{ encoding: "utf-8", timeout: 15e3, stdio: "pipe", env: npmEnv }
|
|
17
|
-
);
|
|
18
|
-
const parsed = JSON.parse(json);
|
|
19
|
-
globalVersion = parsed?.dependencies?.["@fml-inc/panopticon"]?.version ?? null;
|
|
20
|
-
} catch {
|
|
21
|
-
}
|
|
22
|
-
if (!globalVersion) {
|
|
23
|
-
console.log("[postinstall] Installing @fml-inc/panopticon globally...");
|
|
24
|
-
try {
|
|
25
|
-
execFileSync("npm", ["install", "-g", "@fml-inc/panopticon@latest"], {
|
|
26
|
-
encoding: "utf-8",
|
|
27
|
-
timeout: 12e4,
|
|
28
|
-
stdio: "pipe",
|
|
29
|
-
env: npmEnv
|
|
30
|
-
});
|
|
31
|
-
console.log("[postinstall] Installed @fml-inc/panopticon");
|
|
32
|
-
} catch (err) {
|
|
33
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
34
|
-
console.error(`[postinstall] Failed to install panopticon: ${msg}`);
|
|
35
|
-
console.error(
|
|
36
|
-
"[postinstall] Install manually: npm install -g @fml-inc/panopticon@latest"
|
|
37
|
-
);
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
} else {
|
|
41
|
-
let isOutdated = false;
|
|
42
|
-
try {
|
|
43
|
-
execFileSync("npm", ["outdated", "-g", "@fml-inc/panopticon"], {
|
|
44
|
-
encoding: "utf-8",
|
|
45
|
-
timeout: 3e4,
|
|
46
|
-
stdio: "pipe",
|
|
47
|
-
env: npmEnv
|
|
48
|
-
});
|
|
49
|
-
} catch (err) {
|
|
50
|
-
const e = err;
|
|
51
|
-
if (e.status === 1) isOutdated = true;
|
|
52
|
-
}
|
|
53
|
-
if (isOutdated) {
|
|
54
|
-
console.log("[postinstall] Updating @fml-inc/panopticon...");
|
|
55
|
-
try {
|
|
56
|
-
execFileSync("npm", ["install", "-g", "@fml-inc/panopticon@latest"], {
|
|
57
|
-
encoding: "utf-8",
|
|
58
|
-
timeout: 12e4,
|
|
59
|
-
stdio: "pipe",
|
|
60
|
-
env: npmEnv
|
|
61
|
-
});
|
|
62
|
-
console.log("[postinstall] Updated @fml-inc/panopticon");
|
|
63
|
-
} catch {
|
|
64
|
-
}
|
|
65
|
-
} else {
|
|
66
|
-
console.log(
|
|
67
|
-
`[postinstall] @fml-inc/panopticon@${globalVersion} (up to date)`
|
|
68
|
-
);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
bootstrapPanopticon();
|
|
73
8
|
var fmlBin = join(__dirname, "..", "bin", "fml");
|
|
74
9
|
try {
|
|
75
10
|
execFileSync("node", [fmlBin, "install"], {
|
package/dist/postinstall.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/postinstall.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * Lightweight postinstall
|
|
1
|
+
{"version":3,"sources":["../src/postinstall.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * Lightweight postinstall — runs `fml install` to set up fml-specific\n * config (directories, marketplace, plugin cache, sync target).\n *\n * Panopticon setup is handled by @fml-inc/panopticon's own postinstall\n * which npm runs automatically as a dependency.\n */\nimport { execFileSync } from \"node:child_process\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst fmlBin = join(__dirname, \"..\", \"bin\", \"fml\");\n\ntry {\n execFileSync(\"node\", [fmlBin, \"install\"], {\n stdio: \"inherit\",\n timeout: 120_000,\n });\n} catch {\n // fml install failed — not fatal for postinstall\n}\n"],"mappings":";;;AAQA,SAAS,oBAAoB;AAC7B,SAAS,SAAS,YAAY;AAC9B,SAAS,qBAAqB;AAE9B,IAAM,YAAY,QAAQ,cAAc,YAAY,GAAG,CAAC;AACxD,IAAM,SAAS,KAAK,WAAW,MAAM,OAAO,KAAK;AAEjD,IAAI;AACF,eAAa,QAAQ,CAAC,QAAQ,SAAS,GAAG;AAAA,IACxC,OAAO;AAAA,IACP,SAAS;AAAA,EACX,CAAC;AACH,QAAQ;AAER;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fml-inc/fml",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.27",
|
|
4
4
|
"description": "FML agent tools for Claude Code",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"type": "module",
|
|
@@ -25,17 +25,16 @@
|
|
|
25
25
|
".claude-plugin/"
|
|
26
26
|
],
|
|
27
27
|
"scripts": {
|
|
28
|
-
"build": "tsup",
|
|
28
|
+
"build": "node scripts/generate-plugin-manifest.js && tsup",
|
|
29
29
|
"dev": "tsup --watch",
|
|
30
30
|
"prepack": "node scripts/generate-plugin-manifest.js",
|
|
31
31
|
"pack:local": "pnpm build && pnpm pack",
|
|
32
|
-
"postinstall": "node ./dist/postinstall.js && claude plugin
|
|
32
|
+
"postinstall": "[ ! -d dist ] || (node ./dist/postinstall.js && (claude plugin install fml@local-plugins 2>/dev/null || claude plugin update fml@local-plugins || echo 'warn: claude CLI not found, run claude plugin install fml@local-plugins manually'))",
|
|
33
33
|
"type-check": "tsc --noEmit",
|
|
34
34
|
"test": "vitest run",
|
|
35
35
|
"test:watch": "vitest"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@fml-inc/panopticon": "^0.1.4",
|
|
39
38
|
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
40
39
|
"better-sqlite3": "^11.0.0",
|
|
41
40
|
"commander": "^13.1.0",
|
|
@@ -55,6 +54,7 @@
|
|
|
55
54
|
]
|
|
56
55
|
},
|
|
57
56
|
"devDependencies": {
|
|
57
|
+
"@fml-inc/panopticon": "^0.2.2",
|
|
58
58
|
"@sentry/core": "^10.43.0",
|
|
59
59
|
"@types/better-sqlite3": "^7.6.0",
|
|
60
60
|
"@types/node": "^22.0.0",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/daemon-utils.ts","../src/commands/daemon.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { execFileSync } from \"node:child_process\";\nimport { FML_DATA_DIR, FML_LOG_DIR } from \"./dirs.js\";\n\nexport const SYNC_PID_FILE = path.join(FML_DATA_DIR, \"sync.pid\");\nexport const SYNC_LOG_FILE = path.join(FML_LOG_DIR, \"sync.log\");\n\nexport function isDaemonRunning(pidFile: string): {\n running: boolean;\n pid: number | null;\n} {\n if (!fs.existsSync(pidFile)) return { running: false, pid: null };\n const pid = parseInt(fs.readFileSync(pidFile, \"utf-8\").trim(), 10);\n try {\n process.kill(pid, 0);\n return { running: true, pid };\n } catch {\n return { running: false, pid };\n }\n}\n\n/** Resolve the panopticon CLI binary from PATH or the bundled dependency. */\nexport function resolvePanopticonBin(): string | null {\n // Try to find panopticon in PATH\n try {\n const result = execFileSync(\"which\", [\"panopticon\"], {\n encoding: \"utf-8\",\n timeout: 5_000,\n }).trim();\n if (result) return result;\n } catch {}\n\n // Fall back to the bundled dependency\n try {\n const resolved = import.meta.resolve(\"@fml-inc/panopticon/setup\");\n const pkgDir = path.resolve(new URL(resolved).pathname, \"../..\");\n const bin = path.join(pkgDir, \"bin\", \"panopticon\");\n if (fs.existsSync(bin)) return bin;\n } catch {}\n\n return null;\n}\n\n/** Run a panopticon CLI command and return stdout. */\nexport function panopticonExec(...args: string[]): {\n ok: boolean;\n stdout: string;\n};\nexport function panopticonExec(\n ...argsAndOpts: [...string[], { timeout?: number }]\n): { ok: boolean; stdout: string };\nexport function panopticonExec(\n ...argsAndOpts: Array<string | { timeout?: number }>\n): {\n ok: boolean;\n stdout: string;\n} {\n let timeout = 10_000;\n const args: string[] = [];\n for (const a of argsAndOpts) {\n if (typeof a === \"string\") args.push(a);\n else timeout = a.timeout ?? timeout;\n }\n const bin = resolvePanopticonBin();\n if (!bin) return { ok: false, stdout: \"panopticon binary not found\" };\n try {\n const stdout = execFileSync(\"node\", [bin, ...args], {\n encoding: \"utf-8\",\n timeout,\n });\n return { ok: true, stdout };\n } catch (err: unknown) {\n const e = err as { stdout?: string; stderr?: string; status?: number };\n return { ok: false, stdout: (e.stdout ?? \"\") + (e.stderr ?? \"\") };\n }\n}\n","import {\n isDaemonRunning,\n panopticonExec,\n SYNC_PID_FILE,\n} from \"../daemon-utils.js\";\n\n// ── Status helpers (used by doctor, status) ─────────────────────────────────\n\nexport function parsePanopticonRunning(): boolean {\n const result = panopticonExec(\"status\");\n const serverLine = result.stdout\n .split(\"\\n\")\n .find((l) => l.startsWith(\"Server:\"));\n return result.ok && /running/i.test(serverLine ?? \"\");\n}\n\nexport function isSyncRunning(): { running: boolean; pid: number | null } {\n return isDaemonRunning(SYNC_PID_FILE);\n}\n\n// ── Start / Stop (used by CLI, install, MCP) ────────────────────────────────\n\nexport async function handleStart(): Promise<void> {\n const startResult = panopticonExec(\"start\");\n console.log(\n startResult.stdout.trim() ||\n (startResult.ok ? \"Panopticon started\" : \"Failed to start panopticon\"),\n );\n}\n\nexport function handleStop(): void {\n const stopResult = panopticonExec(\"stop\");\n console.log(stopResult.stdout.trim() || \"Panopticon stopped\");\n}\n"],"mappings":";;;;;;AAAA,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,SAAS,oBAAoB;AAGtB,IAAM,gBAAgB,KAAK,KAAK,cAAc,UAAU;AACxD,IAAM,gBAAgB,KAAK,KAAK,aAAa,UAAU;AAEvD,SAAS,gBAAgB,SAG9B;AACA,MAAI,CAAC,GAAG,WAAW,OAAO,EAAG,QAAO,EAAE,SAAS,OAAO,KAAK,KAAK;AAChE,QAAM,MAAM,SAAS,GAAG,aAAa,SAAS,OAAO,EAAE,KAAK,GAAG,EAAE;AACjE,MAAI;AACF,YAAQ,KAAK,KAAK,CAAC;AACnB,WAAO,EAAE,SAAS,MAAM,IAAI;AAAA,EAC9B,QAAQ;AACN,WAAO,EAAE,SAAS,OAAO,IAAI;AAAA,EAC/B;AACF;AAGO,SAAS,uBAAsC;AAEpD,MAAI;AACF,UAAM,SAAS,aAAa,SAAS,CAAC,YAAY,GAAG;AAAA,MACnD,UAAU;AAAA,MACV,SAAS;AAAA,IACX,CAAC,EAAE,KAAK;AACR,QAAI,OAAQ,QAAO;AAAA,EACrB,QAAQ;AAAA,EAAC;AAGT,MAAI;AACF,UAAM,WAAW,YAAY,QAAQ,2BAA2B;AAChE,UAAM,SAAS,KAAK,QAAQ,IAAI,IAAI,QAAQ,EAAE,UAAU,OAAO;AAC/D,UAAM,MAAM,KAAK,KAAK,QAAQ,OAAO,YAAY;AACjD,QAAI,GAAG,WAAW,GAAG,EAAG,QAAO;AAAA,EACjC,QAAQ;AAAA,EAAC;AAET,SAAO;AACT;AAUO,SAAS,kBACX,aAIH;AACA,MAAI,UAAU;AACd,QAAM,OAAiB,CAAC;AACxB,aAAW,KAAK,aAAa;AAC3B,QAAI,OAAO,MAAM,SAAU,MAAK,KAAK,CAAC;AAAA,QACjC,WAAU,EAAE,WAAW;AAAA,EAC9B;AACA,QAAM,MAAM,qBAAqB;AACjC,MAAI,CAAC,IAAK,QAAO,EAAE,IAAI,OAAO,QAAQ,8BAA8B;AACpE,MAAI;AACF,UAAM,SAAS,aAAa,QAAQ,CAAC,KAAK,GAAG,IAAI,GAAG;AAAA,MAClD,UAAU;AAAA,MACV;AAAA,IACF,CAAC;AACD,WAAO,EAAE,IAAI,MAAM,OAAO;AAAA,EAC5B,SAAS,KAAc;AACrB,UAAM,IAAI;AACV,WAAO,EAAE,IAAI,OAAO,SAAS,EAAE,UAAU,OAAO,EAAE,UAAU,IAAI;AAAA,EAClE;AACF;;;ACpEO,SAAS,yBAAkC;AAChD,QAAM,SAAS,eAAe,QAAQ;AACtC,QAAM,aAAa,OAAO,OACvB,MAAM,IAAI,EACV,KAAK,CAAC,MAAM,EAAE,WAAW,SAAS,CAAC;AACtC,SAAO,OAAO,MAAM,WAAW,KAAK,cAAc,EAAE;AACtD;AAEO,SAAS,gBAA0D;AACxE,SAAO,gBAAgB,aAAa;AACtC;AAIA,eAAsB,cAA6B;AACjD,QAAM,cAAc,eAAe,OAAO;AAC1C,UAAQ;AAAA,IACN,YAAY,OAAO,KAAK,MACrB,YAAY,KAAK,uBAAuB;AAAA,EAC7C;AACF;AAEO,SAAS,aAAmB;AACjC,QAAM,aAAa,eAAe,MAAM;AACxC,UAAQ,IAAI,WAAW,OAAO,KAAK,KAAK,oBAAoB;AAC9D;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/native-check.ts","../src/convex-client.ts"],"sourcesContent":["import { createRequire } from \"node:module\";\nimport { execSync } from \"node:child_process\";\nimport { rmSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\n/**\n * Verify that better-sqlite3's native addon matches the running Node version.\n * If mismatched (e.g. user upgraded Node), attempt an automatic rebuild.\n * Call this before any code that imports better-sqlite3.\n */\nexport function ensureNativeModules(): void {\n const require = createRequire(import.meta.url);\n try {\n require(\"better-sqlite3\");\n } catch (err) {\n const msg = err instanceof Error ? err.message : \"\";\n if (!msg.includes(\"NODE_MODULE_VERSION\")) {\n throw err;\n }\n\n console.error(\n \"[fml] better-sqlite3 was compiled for a different Node.js version, rebuilding...\",\n );\n\n const pkgRoot = join(dirname(fileURLToPath(import.meta.url)), \"..\");\n\n // Remove stale build directory to avoid EEXIST errors from node-gyp\n const sqlitePath = dirname(require.resolve(\"better-sqlite3/package.json\"));\n rmSync(join(sqlitePath, \"build\"), { recursive: true, force: true });\n\n try {\n execSync(\"npm rebuild better-sqlite3\", {\n cwd: pkgRoot,\n stdio: \"inherit\",\n timeout: 60_000,\n });\n console.error(\"[fml] Rebuild complete.\");\n } catch {\n console.error(\n \"[fml] Automatic rebuild failed. Please run manually:\\n\" +\n ` cd ${pkgRoot} && rm -rf node_modules/better-sqlite3/build && npm rebuild better-sqlite3`,\n );\n process.exit(1);\n }\n }\n}\n","import type { FunctionReference } from \"convex/server\";\nimport { resolveRepoFromCwd } from \"@fml-inc/panopticon/repo\";\nimport { getSelectedOrg, getValidToken } from \"./auth/token-store.js\";\nimport { CONVEX_URL } from \"./config.js\";\nimport type {\n RepoConfigSnapshotDetail,\n RepoConfigSnapshotSummary,\n ResolvedRepo,\n UserConfigSnapshotDetail,\n UserConfigSnapshotSummary,\n} from \"./types.js\";\n\n// ── Shared plumbing ─────────────────────────────────────────────────────────\n\nexport interface ToolResult {\n ok: boolean;\n result?: unknown;\n error?: string;\n}\n\nexport interface OrgInfo {\n _id: string;\n name: string;\n slug?: string;\n repos?: Array<{\n _id: string;\n fullName: string;\n owner: string;\n name: string;\n private: boolean;\n }>;\n}\n\nfunction ref<T extends \"query\" | \"mutation\" | \"action\">(\n path: string,\n): FunctionReference<T> {\n return path as unknown as FunctionReference<T>;\n}\n\n// ── API client factory ──────────────────────────────────────────────────────\n\nexport function createApiClient(token: string) {\n const isServiceToken = token.startsWith(\"fml_st_\");\n\n let clientPromise: Promise<{\n query: <T>(\n ref: FunctionReference<\"query\">,\n args: Record<string, unknown>,\n ) => Promise<T>;\n mutation: <T>(\n ref: FunctionReference<\"mutation\">,\n args: Record<string, unknown>,\n ) => Promise<T>;\n action: <T>(\n ref: FunctionReference<\"action\">,\n args: Record<string, unknown>,\n ) => Promise<T>;\n }> | null = null;\n\n function getClient() {\n if (!clientPromise) {\n clientPromise = import(\"convex/browser\").then(({ ConvexHttpClient }) => {\n const client = new ConvexHttpClient(CONVEX_URL);\n client.setAuth(token);\n return client;\n });\n }\n return clientPromise;\n }\n\n /**\n * Derive the Convex site URL (HTTP actions) from the cloud URL.\n * Convex uses paired domains: *.convex.cloud for client APIs,\n * *.convex.site for HTTP actions. This is a stable Convex convention.\n */\n function getSiteUrl(): string {\n return CONVEX_URL.replace(\".convex.cloud\", \".convex.site\").replace(\n /\\/$/,\n \"\",\n );\n }\n\n return {\n // ── Orgs ──────────────────────────────────────────────────────────────\n\n async queryOrgs(): Promise<OrgInfo[]> {\n if (isServiceToken) {\n // Service tokens can't call Convex actions directly — org is embedded in the token\n return [];\n }\n const client = await getClient();\n return await client.query(ref(\"user/plugin:getMyOrgsAndRepos\"), {});\n },\n\n // ── Tool gateway ─────────────────────────────────────────────────────\n\n async callBackend(\n toolName: string,\n args: Record<string, unknown>,\n opts?: { org?: string },\n ): Promise<ToolResult> {\n try {\n if (isServiceToken) {\n // Service token path: POST to HTTP endpoint (Convex can't validate non-JWT tokens)\n const res = await fetch(`${getSiteUrl()}/api/tools/execute`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify({ toolName, args }),\n });\n const text = await res.text();\n let data: ToolResult;\n try {\n data = JSON.parse(text) as ToolResult;\n } catch {\n return {\n ok: false,\n error: `HTTP ${res.status}: ${text.slice(0, 200)}`,\n };\n }\n if (!res.ok && !data.error) {\n return { ok: false, error: `HTTP ${res.status}` };\n }\n return data;\n }\n\n // JWT path: standard Convex action\n const client = await getClient();\n const actionArgs: Record<string, unknown> = { toolName, args };\n // Explicit org > stored org selection > repo-based inference\n const org = opts?.org ?? getSelectedOrg();\n if (org) actionArgs.org = org;\n const repo = resolveRepoFromCwd(process.cwd());\n if (repo) actionArgs.repo = repo.repo;\n\n const result = await client.action(\n ref<\"action\">(\"user/tool_gateway:executeTool\"),\n actionArgs,\n );\n return { ok: true, result };\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n if (msg.includes(\"Unauthorized\") || msg.includes(\"not authenticated\")) {\n return {\n ok: false,\n error:\n \"Authentication expired. Run `fml login` to sign in again, then restart Claude Code.\",\n };\n }\n return { ok: false, error: msg };\n }\n },\n\n // ── Repo resolution ──────────────────────────────────────────────────\n\n async resolveRepo(\n orgSlug: string,\n repoFullName: string,\n ): Promise<ResolvedRepo | null> {\n const client = await getClient();\n return await client.query(ref(\"user/cli:resolveRepo\"), {\n orgSlug,\n repoFullName,\n });\n },\n\n // ── Config snapshots ─────────────────────────────────────────────────\n\n async listUserConfigSnapshots(\n orgSlug: string,\n ): Promise<UserConfigSnapshotSummary[]> {\n const client = await getClient();\n const result = await client.query<UserConfigSnapshotSummary[] | null>(\n ref(\"user/config_snapshots:listUserSnapshots\"),\n { orgSlug },\n );\n return result ?? [];\n },\n\n async getUserConfigDetail(\n orgSlug: string,\n githubUsername: string,\n ): Promise<UserConfigSnapshotDetail | null> {\n const client = await getClient();\n return await client.query(ref(\"user/config_snapshots:getUserDetail\"), {\n orgSlug,\n githubUsername,\n });\n },\n\n async listRepoConfigSnapshots(\n orgSlug: string,\n repository?: string,\n ): Promise<RepoConfigSnapshotSummary[]> {\n const client = await getClient();\n const result = await client.query<RepoConfigSnapshotSummary[] | null>(\n ref(\"user/config_snapshots:listRepoSnapshots\"),\n { orgSlug, repository },\n );\n return result ?? [];\n },\n\n async getRepoConfigDetail(\n orgSlug: string,\n repository: string,\n ): Promise<RepoConfigSnapshotDetail | null> {\n const client = await getClient();\n return await client.query(ref(\"user/config_snapshots:getRepoDetail\"), {\n orgSlug,\n repository,\n });\n },\n };\n}\n\n// ── Convenience: auto-authenticated client ──────────────────────────────────\n\n/**\n * Create an API client using the stored auth token.\n * Returns null if not authenticated.\n */\nexport async function getAuthenticatedClient() {\n const token = await getValidToken();\n if (!token) return null;\n return createApiClient(token);\n}\n"],"mappings":"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","names":["require"]}
|
|
File without changes
|