@wolpertingerlabs/drawlatch 1.0.0-alpha.4 → 1.0.0-alpha.5
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/connections/{anthropic.json → ai/anthropic.json} +2 -0
- package/dist/connections/{devin.json → ai/devin.json} +2 -0
- package/dist/connections/{google-ai.json → ai/google-ai.json} +2 -0
- package/dist/connections/{openai.json → ai/openai.json} +2 -0
- package/dist/connections/{openrouter.json → ai/openrouter.json} +2 -0
- package/dist/connections/{github.json → developer-tools/github.json} +2 -0
- package/dist/connections/{hex.json → developer-tools/hex.json} +2 -0
- package/dist/connections/{linear.json → developer-tools/linear.json} +2 -0
- package/dist/connections/{lichess.json → gaming/lichess.json} +2 -0
- package/dist/connections/{discord-bot.json → messaging/discord-bot.json} +2 -0
- package/dist/connections/{discord-oauth.json → messaging/discord-oauth.json} +2 -0
- package/dist/connections/{slack.json → messaging/slack.json} +2 -0
- package/dist/connections/{telegram.json → messaging/telegram.json} +2 -0
- package/dist/connections/{google.json → productivity/google.json} +2 -0
- package/dist/connections/{notion.json → productivity/notion.json} +2 -0
- package/dist/connections/{stripe.json → productivity/stripe.json} +2 -0
- package/dist/connections/{trello.json → productivity/trello.json} +2 -0
- package/dist/connections/{bluesky.json → social-media/bluesky.json} +2 -0
- package/dist/connections/{mastodon.json → social-media/mastodon.json} +2 -0
- package/dist/connections/{reddit.json → social-media/reddit.json} +2 -0
- package/dist/connections/{twitch.json → social-media/twitch.json} +2 -0
- package/dist/connections/{x.json → social-media/x.json} +2 -0
- package/dist/remote/server.js +4 -0
- package/dist/shared/config.d.ts +15 -0
- package/dist/shared/config.js +2 -0
- package/dist/shared/connections.d.ts +12 -5
- package/dist/shared/connections.js +52 -14
- package/package.json +1 -1
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "Anthropic API",
|
|
3
|
+
"stability": "beta",
|
|
4
|
+
"category": "ai",
|
|
3
5
|
"description": "Anthropic Claude API — messages, models, and more. Auth is handled automatically via the ANTHROPIC_API_KEY environment variable. Uses x-api-key header (not Bearer token). The anthropic-version header is set to 2023-06-01.",
|
|
4
6
|
"docsUrl": "https://docs.anthropic.com/en/api",
|
|
5
7
|
"headers": {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "Devin API",
|
|
3
|
+
"stability": "dev",
|
|
4
|
+
"category": "ai",
|
|
3
5
|
"description": "Devin AI API — sessions, knowledge, and machine management. Auth is handled automatically via the DEVIN_API_KEY environment variable.",
|
|
4
6
|
"docsUrl": "https://docs.devin.ai/api-reference/overview",
|
|
5
7
|
"headers": {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "Google AI (Gemini) API",
|
|
3
|
+
"stability": "stable",
|
|
4
|
+
"category": "ai",
|
|
3
5
|
"description": "Google AI Gemini API — chat completions, embeddings, image generation, token counting, and more. Auth is handled automatically via the GOOGLE_AI_API_KEY environment variable. Uses x-goog-api-key header (not Bearer token). This is separate from the 'google' connection which covers Google Workspace APIs (Sheets, Drive, etc.).",
|
|
4
6
|
"docsUrl": "https://ai.google.dev/api",
|
|
5
7
|
"headers": {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "OpenAI API",
|
|
3
|
+
"stability": "beta",
|
|
4
|
+
"category": "ai",
|
|
3
5
|
"description": "OpenAI API — chat completions, embeddings, images, audio, files, fine-tuning, and more. Auth is handled automatically via the OPENAI_API_KEY environment variable.",
|
|
4
6
|
"docsUrl": "https://platform.openai.com/docs/api-reference",
|
|
5
7
|
"openApiUrl": "https://raw.githubusercontent.com/openai/openai-openapi/master/openapi.yaml",
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "OpenRouter API",
|
|
3
|
+
"stability": "stable",
|
|
4
|
+
"category": "ai",
|
|
3
5
|
"description": "OpenRouter unified LLM API — chat completions, models, generation stats, and more. Auth is handled automatically via the OPENROUTER_API_KEY environment variable.",
|
|
4
6
|
"docsUrl": "https://openrouter.ai/docs/api-reference",
|
|
5
7
|
"openApiUrl": "https://openrouter.ai/openapi.json",
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "GitHub API",
|
|
3
|
+
"stability": "beta",
|
|
4
|
+
"category": "developer-tools",
|
|
3
5
|
"description": "GitHub REST API — repositories, issues, pull requests, users, organizations, and more. Auth is handled automatically via the GITHUB_TOKEN environment variable. Includes a webhook ingestor for real-time events (push, pull_request, issues, etc.) — set GITHUB_WEBHOOK_SECRET and use poll_events to retrieve them.",
|
|
4
6
|
"docsUrl": "https://docs.github.com/en/rest",
|
|
5
7
|
"openApiUrl": "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.json",
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "Hex API",
|
|
3
|
+
"stability": "dev",
|
|
4
|
+
"category": "developer-tools",
|
|
3
5
|
"description": "Hex API — projects, runs, users, groups, collections, and data connections. Auth is handled automatically via the HEX_TOKEN environment variable.",
|
|
4
6
|
"docsUrl": "https://learn.hex.tech/docs/api/api-overview",
|
|
5
7
|
"headers": {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "Linear API",
|
|
3
|
+
"stability": "beta",
|
|
4
|
+
"category": "developer-tools",
|
|
3
5
|
"description": "Linear GraphQL API — issues, projects, teams, cycles, and more. Auth is handled automatically via the LINEAR_API_KEY environment variable. All requests are GraphQL queries sent as POST to https://api.linear.app/graphql. Includes a poll ingestor that periodically fetches recently updated issues — use poll_events to retrieve them.",
|
|
4
6
|
"docsUrl": "https://developers.linear.app/docs/graphql/working-with-the-graphql-api",
|
|
5
7
|
"headers": {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "Lichess API",
|
|
3
|
+
"stability": "stable",
|
|
4
|
+
"category": "gaming",
|
|
3
5
|
"description": "Lichess Opening Explorer, Cloud Evaluation, and authenticated API — query master and rated game statistics by opening move sequence, get cached Stockfish engine evaluations by FEN position, and access authenticated endpoints (account info, game history, player-specific opening analysis, etc.). Set LICHESS_API_TOKEN to a personal access token for authenticated routes; public endpoints (Opening Explorer, Cloud Eval) work without it.",
|
|
4
6
|
"docsUrl": "https://lichess.org/api",
|
|
5
7
|
"headers": {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "Discord Bot API",
|
|
3
|
+
"stability": "stable",
|
|
4
|
+
"category": "messaging",
|
|
3
5
|
"description": "Discord Bot API (v10) — guilds, channels, messages, users, roles, and more. Auth is handled automatically via the DISCORD_BOT_TOKEN environment variable. Uses the 'Bot' authorization prefix. For OAuth2 user-scoped access, use the 'discord-oauth' connection instead. Includes a Gateway ingestor for real-time events (messages, reactions, etc.) — use poll_events to retrieve them.",
|
|
4
6
|
"docsUrl": "https://discord.com/developers/docs/intro",
|
|
5
7
|
"openApiUrl": "https://raw.githubusercontent.com/discord/discord-api-spec/main/specs/openapi.json",
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "Discord OAuth2 API",
|
|
3
|
+
"stability": "dev",
|
|
4
|
+
"category": "messaging",
|
|
3
5
|
"description": "Discord OAuth2 API (v10) — user identity, guilds, connections, and other user-scoped data. Auth is handled automatically via the DISCORD_OAUTH_TOKEN environment variable (OAuth2 Bearer access token). Access is limited to the scopes the user authorized. For full bot access, use the 'discord-bot' connection instead.",
|
|
4
6
|
"docsUrl": "https://discord.com/developers/docs/topics/oauth2",
|
|
5
7
|
"openApiUrl": "https://raw.githubusercontent.com/discord/discord-api-spec/main/specs/openapi.json",
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "Slack API",
|
|
3
|
+
"stability": "stable",
|
|
4
|
+
"category": "messaging",
|
|
3
5
|
"description": "Slack Web API — messages, channels, users, reactions, files, and more. Auth is handled automatically via the SLACK_BOT_TOKEN environment variable. Real-time events via Socket Mode require SLACK_APP_TOKEN.",
|
|
4
6
|
"docsUrl": "https://docs.slack.dev/apis/web-api",
|
|
5
7
|
"openApiUrl": "https://raw.githubusercontent.com/slackapi/slack-api-specs/master/web-api/slack_web_openapi_v2.json",
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "Telegram Bot API",
|
|
3
|
+
"stability": "beta",
|
|
4
|
+
"category": "messaging",
|
|
3
5
|
"description": "Telegram Bot API — messages, chats, users, inline queries, payments, and more. Auth uses a bot token embedded in the URL path — include /bot${TELEGRAM_BOT_TOKEN}/ in your request URLs. The placeholder is resolved automatically from the route's secrets. Create a bot via @BotFather on Telegram to obtain a token. Includes a poll ingestor that fetches new updates via getUpdates — use poll_events to retrieve them.",
|
|
4
6
|
"docsUrl": "https://core.telegram.org/bots/api",
|
|
5
7
|
"headers": {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "Google APIs",
|
|
3
|
+
"stability": "dev",
|
|
4
|
+
"category": "productivity",
|
|
3
5
|
"description": "Google APIs — Sheets, Docs, Drive, Calendar, Gmail, and more. Auth is handled automatically via the GOOGLE_API_TOKEN environment variable (OAuth2 access token or service account token). Multiple Google API domains are allowlisted.",
|
|
4
6
|
"docsUrl": "https://developers.google.com/apis-explorer",
|
|
5
7
|
"headers": {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "Notion API",
|
|
3
|
+
"stability": "beta",
|
|
4
|
+
"category": "productivity",
|
|
3
5
|
"description": "Notion API — pages, databases, blocks, users, search, and more. Auth is handled automatically via the NOTION_API_KEY environment variable (internal integration token). The Notion-Version header is set to 2022-06-28. Includes a poll ingestor that periodically searches for recently edited pages — use poll_events to retrieve them.",
|
|
4
6
|
"docsUrl": "https://developers.notion.com/reference",
|
|
5
7
|
"headers": {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "Stripe API",
|
|
3
|
+
"stability": "beta",
|
|
4
|
+
"category": "productivity",
|
|
3
5
|
"description": "Stripe payments API — customers, charges, payment intents, subscriptions, invoices, and more. Auth is handled automatically via the STRIPE_SECRET_KEY environment variable. Includes a webhook ingestor for real-time events (payment_intent.succeeded, invoice.paid, etc.) — set STRIPE_WEBHOOK_SECRET and use poll_events to retrieve them. Note: Stripe uses application/x-www-form-urlencoded for request bodies, not JSON.",
|
|
4
6
|
"docsUrl": "https://docs.stripe.com/api",
|
|
5
7
|
"openApiUrl": "https://raw.githubusercontent.com/stripe/openapi/master/openapi/spec3.json",
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "Trello API",
|
|
3
|
+
"stability": "stable",
|
|
4
|
+
"category": "productivity",
|
|
3
5
|
"description": "Trello boards, lists, and cards API. Authentication uses query parameters — include ?key=${TRELLO_API_KEY}&token=${TRELLO_TOKEN} in your request URLs. The placeholders are resolved automatically from the route's secrets. Includes a webhook ingestor for real-time events (card updates, list changes, board activity, etc.) — set TRELLO_API_SECRET and TRELLO_CALLBACK_URL, then use poll_events to retrieve them.",
|
|
4
6
|
"docsUrl": "https://developer.atlassian.com/cloud/trello/rest/",
|
|
5
7
|
"headers": {},
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "Bluesky API (AT Protocol)",
|
|
3
|
+
"stability": "beta",
|
|
4
|
+
"category": "social-media",
|
|
3
5
|
"description": "Bluesky API via the AT Protocol — posts, feeds, profiles, notifications, social graph, and more. Auth is handled automatically via the BLUESKY_ACCESS_TOKEN environment variable (JWT Bearer token). Obtain a token by POSTing to com.atproto.server.createSession with your handle and an App Password. Tokens expire after ~2 hours — rotate externally using the refresh token. Both bsky.social (authenticated PDS) and public.api.bsky.app (public read-only API) are allowlisted. For self-hosted PDS instances, override with a custom connector. Includes a poll ingestor that fetches notifications — use poll_events to retrieve them.",
|
|
4
6
|
"docsUrl": "https://docs.bsky.app/",
|
|
5
7
|
"headers": {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "Mastodon API",
|
|
3
|
+
"stability": "beta",
|
|
4
|
+
"category": "social-media",
|
|
3
5
|
"description": "Mastodon API — statuses (toots), timelines, notifications, accounts, search, and more. Auth is handled automatically via the MASTODON_ACCESS_TOKEN environment variable (OAuth2 Bearer token from your instance's Development settings). This template targets mastodon.social — for other instances, override with a custom connector using the same auth pattern but different allowedEndpoints. Includes a poll ingestor that fetches the home timeline — use poll_events to retrieve them.",
|
|
4
6
|
"docsUrl": "https://docs.joinmastodon.org/api/",
|
|
5
7
|
"headers": {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "Reddit API",
|
|
3
|
+
"stability": "beta",
|
|
4
|
+
"category": "social-media",
|
|
3
5
|
"description": "Reddit API — subreddits, posts, comments, users, search, and more. Auth is handled automatically via the REDDIT_ACCESS_TOKEN environment variable (OAuth2 Bearer token). A User-Agent header is required by Reddit and set via REDDIT_USER_AGENT. Obtain an OAuth2 token by registering a 'script' app at https://www.reddit.com/prefs/apps and using the client credentials grant. Tokens expire after 1 hour — rotate externally. Includes a poll ingestor that fetches new posts from a configurable subreddit — set REDDIT_SUBREDDIT and use poll_events to retrieve them.",
|
|
4
6
|
"docsUrl": "https://www.reddit.com/dev/api/",
|
|
5
7
|
"headers": {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "Twitch API",
|
|
3
|
+
"stability": "beta",
|
|
4
|
+
"category": "social-media",
|
|
3
5
|
"description": "Twitch Helix API — streams, users, channels, clips, videos, chat, and more. Auth requires both a Bearer token and Client-Id header, handled automatically via TWITCH_ACCESS_TOKEN and TWITCH_CLIENT_ID environment variables. Register an application at https://dev.twitch.tv/console/apps to obtain credentials. Includes a poll ingestor that fetches followed live streams — set TWITCH_USER_ID and use poll_events to retrieve them.",
|
|
4
6
|
"docsUrl": "https://dev.twitch.tv/docs/api/reference/",
|
|
5
7
|
"headers": {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "X (Twitter) API",
|
|
3
|
+
"stability": "beta",
|
|
4
|
+
"category": "social-media",
|
|
3
5
|
"description": "X (formerly Twitter) API v2 — tweets, users, spaces, lists, and more. Auth is handled automatically via the X_BEARER_TOKEN environment variable (App-only Bearer token from the X Developer Portal). Both api.x.com and api.twitter.com domains are allowlisted. Includes a poll ingestor that searches recent tweets matching a configurable query — set X_SEARCH_QUERY and use poll_events to retrieve them.",
|
|
4
6
|
"docsUrl": "https://developer.x.com/en/docs/x-api",
|
|
5
7
|
"headers": {
|
package/dist/remote/server.js
CHANGED
|
@@ -253,6 +253,10 @@ const toolHandlers = {
|
|
|
253
253
|
info.docsUrl = route.docsUrl;
|
|
254
254
|
if (route.openApiUrl)
|
|
255
255
|
info.openApiUrl = route.openApiUrl;
|
|
256
|
+
if (route.stability)
|
|
257
|
+
info.stability = route.stability;
|
|
258
|
+
if (route.category)
|
|
259
|
+
info.category = route.category;
|
|
256
260
|
info.allowedEndpoints = route.allowedEndpoints;
|
|
257
261
|
info.secretNames = Object.keys(route.secrets);
|
|
258
262
|
info.autoHeaders = Object.keys(route.headers);
|
package/dist/shared/config.d.ts
CHANGED
|
@@ -30,6 +30,9 @@ export declare function getLocalKeysDir(): string;
|
|
|
30
30
|
export declare function getRemoteKeysDir(): string;
|
|
31
31
|
export declare function getPeerKeysDir(): string;
|
|
32
32
|
export declare function getEnvFilePath(): string;
|
|
33
|
+
/** Category grouping for built-in connection templates.
|
|
34
|
+
* Matches the subdirectory name under src/connections/. */
|
|
35
|
+
export type ConnectionCategory = 'ai' | 'developer-tools' | 'gaming' | 'messaging' | 'productivity' | 'social-media';
|
|
33
36
|
/** MCP proxy (local) configuration */
|
|
34
37
|
export interface ProxyConfig {
|
|
35
38
|
/** Remote server URL */
|
|
@@ -64,6 +67,14 @@ export interface Route {
|
|
|
64
67
|
/** URL to an OpenAPI / Swagger spec (JSON or YAML) for this route's API.
|
|
65
68
|
* Optional — provides more structured, agent-friendly documentation. */
|
|
66
69
|
openApiUrl?: string;
|
|
70
|
+
/** Stability level of this connection: "stable", "beta", or "dev".
|
|
71
|
+
* Defaults to "dev" if omitted. Helps agents and UIs communicate
|
|
72
|
+
* whether a connection is production-ready, in testing, or experimental. */
|
|
73
|
+
stability?: 'stable' | 'beta' | 'dev';
|
|
74
|
+
/** Category grouping for this connection template (e.g., "ai", "messaging").
|
|
75
|
+
* Matches the subdirectory under src/connections/. Only present on built-in
|
|
76
|
+
* connection templates; custom connectors may omit it. */
|
|
77
|
+
category?: ConnectionCategory;
|
|
67
78
|
/** Headers to inject automatically into outgoing requests for this route.
|
|
68
79
|
* These MUST NOT conflict with client-provided headers (request is rejected on conflict).
|
|
69
80
|
* Values may contain ${VAR} placeholders resolved against this route's secrets. */
|
|
@@ -106,6 +117,10 @@ export interface ResolvedRoute {
|
|
|
106
117
|
docsUrl?: string;
|
|
107
118
|
/** URL to an OpenAPI / Swagger spec for this route's API (carried from config) */
|
|
108
119
|
openApiUrl?: string;
|
|
120
|
+
/** Stability level (carried from config) */
|
|
121
|
+
stability?: 'stable' | 'beta' | 'dev';
|
|
122
|
+
/** Category grouping (carried from config) */
|
|
123
|
+
category?: ConnectionCategory;
|
|
109
124
|
headers: Record<string, string>;
|
|
110
125
|
secrets: Record<string, string>;
|
|
111
126
|
allowedEndpoints: string[];
|
package/dist/shared/config.js
CHANGED
|
@@ -263,6 +263,8 @@ export function resolveRoutes(routes, envOverrides) {
|
|
|
263
263
|
...(route.description !== undefined && { description: route.description }),
|
|
264
264
|
...(route.docsUrl !== undefined && { docsUrl: route.docsUrl }),
|
|
265
265
|
...(route.openApiUrl !== undefined && { openApiUrl: route.openApiUrl }),
|
|
266
|
+
...(route.stability !== undefined && { stability: route.stability }),
|
|
267
|
+
...(route.category !== undefined && { category: route.category }),
|
|
266
268
|
headers: resolvedHeaders,
|
|
267
269
|
secrets: resolvedSecrets,
|
|
268
270
|
allowedEndpoints: route.allowedEndpoints,
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
* Connection template loading.
|
|
3
3
|
*
|
|
4
4
|
* Connections are pre-built Route templates (JSON files) that ship with
|
|
5
|
-
* the package in the connections/ directory
|
|
6
|
-
*
|
|
5
|
+
* the package in the connections/ directory, organized into category
|
|
6
|
+
* subdirectories (ai/, messaging/, social-media/, etc.).
|
|
7
7
|
*
|
|
8
8
|
* At runtime, templates are loaded from disk relative to this module's
|
|
9
9
|
* location, so they work from both src/ (dev via tsx) and dist/ (production).
|
|
10
10
|
*/
|
|
11
|
-
import type { Route } from './config.js';
|
|
11
|
+
import type { Route, ConnectionCategory } from './config.js';
|
|
12
12
|
/** Metadata about a built-in connection template — used by UIs to render
|
|
13
13
|
* connection cards, form fields, and badges without parsing raw JSON. */
|
|
14
14
|
export interface ConnectionTemplateInfo {
|
|
@@ -22,6 +22,10 @@ export interface ConnectionTemplateInfo {
|
|
|
22
22
|
docsUrl?: string;
|
|
23
23
|
/** URL to an OpenAPI / Swagger spec. */
|
|
24
24
|
openApiUrl?: string;
|
|
25
|
+
/** Stability level: "stable", "beta", or "dev". */
|
|
26
|
+
stability: 'stable' | 'beta' | 'dev';
|
|
27
|
+
/** Category grouping (e.g., "ai", "messaging", "social-media"). */
|
|
28
|
+
category: ConnectionCategory;
|
|
25
29
|
/** Secret names referenced in route headers — these are auto-injected
|
|
26
30
|
* into every request, so they must always be configured. */
|
|
27
31
|
requiredSecrets: string[];
|
|
@@ -44,6 +48,8 @@ export interface ConnectionTemplateInfo {
|
|
|
44
48
|
/** Allowlisted URL patterns (glob). */
|
|
45
49
|
allowedEndpoints: string[];
|
|
46
50
|
}
|
|
51
|
+
/** Invalidate the cached index. Exported for testing only. */
|
|
52
|
+
export declare function _resetConnectionIndex(): void;
|
|
47
53
|
/**
|
|
48
54
|
* Load a single connection template by name.
|
|
49
55
|
*
|
|
@@ -56,8 +62,9 @@ export declare function loadConnection(name: string): Route;
|
|
|
56
62
|
/**
|
|
57
63
|
* List all available connection template names.
|
|
58
64
|
*
|
|
59
|
-
* Scans the connections directory
|
|
60
|
-
* basenames (without extension), sorted
|
|
65
|
+
* Scans the connections directory (including category subdirectories) for
|
|
66
|
+
* .json files and returns their basenames (without extension), sorted
|
|
67
|
+
* alphabetically.
|
|
61
68
|
*/
|
|
62
69
|
export declare function listAvailableConnections(): string[];
|
|
63
70
|
/**
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Connection template loading.
|
|
3
3
|
*
|
|
4
4
|
* Connections are pre-built Route templates (JSON files) that ship with
|
|
5
|
-
* the package in the connections/ directory
|
|
6
|
-
*
|
|
5
|
+
* the package in the connections/ directory, organized into category
|
|
6
|
+
* subdirectories (ai/, messaging/, social-media/, etc.).
|
|
7
7
|
*
|
|
8
8
|
* At runtime, templates are loaded from disk relative to this module's
|
|
9
9
|
* location, so they work from both src/ (dev via tsx) and dist/ (production).
|
|
@@ -13,6 +13,46 @@ import path from 'node:path';
|
|
|
13
13
|
import { fileURLToPath } from 'node:url';
|
|
14
14
|
/** Directory containing connection template JSON files. */
|
|
15
15
|
const CONNECTIONS_DIR = path.join(path.dirname(fileURLToPath(import.meta.url)), '..', 'connections');
|
|
16
|
+
// ── Lazy-cached alias→filepath index ──────────────────────────────────────
|
|
17
|
+
/** Cached alias → absolute filepath index. Built lazily on first access.
|
|
18
|
+
* Supports both flat files (connections/foo.json) and category
|
|
19
|
+
* subdirectories (connections/ai/anthropic.json). */
|
|
20
|
+
let connectionIndex = null;
|
|
21
|
+
/** Build the alias→filepath index by scanning CONNECTIONS_DIR.
|
|
22
|
+
* Files at the top level and files in one level of subdirectories are
|
|
23
|
+
* both indexed. The alias is always the filename without .json. */
|
|
24
|
+
function getConnectionIndex() {
|
|
25
|
+
if (connectionIndex)
|
|
26
|
+
return connectionIndex;
|
|
27
|
+
connectionIndex = new Map();
|
|
28
|
+
if (!fs.existsSync(CONNECTIONS_DIR))
|
|
29
|
+
return connectionIndex;
|
|
30
|
+
const entries = fs.readdirSync(CONNECTIONS_DIR, { withFileTypes: true });
|
|
31
|
+
for (const entry of entries) {
|
|
32
|
+
if (entry.isFile() && entry.name.endsWith('.json')) {
|
|
33
|
+
// Top-level JSON file (backward compat)
|
|
34
|
+
const alias = entry.name.replace(/\.json$/, '');
|
|
35
|
+
connectionIndex.set(alias, path.join(CONNECTIONS_DIR, entry.name));
|
|
36
|
+
}
|
|
37
|
+
else if (entry.isDirectory()) {
|
|
38
|
+
// Category subdirectory — scan one level deep
|
|
39
|
+
const subdir = path.join(CONNECTIONS_DIR, entry.name);
|
|
40
|
+
const subEntries = fs.readdirSync(subdir, 'utf-8');
|
|
41
|
+
for (const subFile of subEntries) {
|
|
42
|
+
if (subFile.endsWith('.json')) {
|
|
43
|
+
const alias = subFile.replace(/\.json$/, '');
|
|
44
|
+
connectionIndex.set(alias, path.join(subdir, subFile));
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return connectionIndex;
|
|
50
|
+
}
|
|
51
|
+
/** Invalidate the cached index. Exported for testing only. */
|
|
52
|
+
export function _resetConnectionIndex() {
|
|
53
|
+
connectionIndex = null;
|
|
54
|
+
}
|
|
55
|
+
// ── Public API ────────────────────────────────────────────────────────────
|
|
16
56
|
/**
|
|
17
57
|
* Load a single connection template by name.
|
|
18
58
|
*
|
|
@@ -22,8 +62,9 @@ const CONNECTIONS_DIR = path.join(path.dirname(fileURLToPath(import.meta.url)),
|
|
|
22
62
|
* @throws If the template file does not exist or contains invalid JSON.
|
|
23
63
|
*/
|
|
24
64
|
export function loadConnection(name) {
|
|
25
|
-
const
|
|
26
|
-
|
|
65
|
+
const index = getConnectionIndex();
|
|
66
|
+
const filePath = index.get(name);
|
|
67
|
+
if (!filePath) {
|
|
27
68
|
const available = listAvailableConnections();
|
|
28
69
|
throw new Error(`Unknown connection "${name}". Available connections: ${available.join(', ') || '(none)'}`);
|
|
29
70
|
}
|
|
@@ -33,18 +74,13 @@ export function loadConnection(name) {
|
|
|
33
74
|
/**
|
|
34
75
|
* List all available connection template names.
|
|
35
76
|
*
|
|
36
|
-
* Scans the connections directory
|
|
37
|
-
* basenames (without extension), sorted
|
|
77
|
+
* Scans the connections directory (including category subdirectories) for
|
|
78
|
+
* .json files and returns their basenames (without extension), sorted
|
|
79
|
+
* alphabetically.
|
|
38
80
|
*/
|
|
39
81
|
export function listAvailableConnections() {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
return fs
|
|
44
|
-
.readdirSync(CONNECTIONS_DIR, 'utf-8')
|
|
45
|
-
.filter((f) => f.endsWith('.json'))
|
|
46
|
-
.map((f) => f.replace(/\.json$/, ''))
|
|
47
|
-
.sort();
|
|
82
|
+
const index = getConnectionIndex();
|
|
83
|
+
return [...index.keys()].sort();
|
|
48
84
|
}
|
|
49
85
|
// ── Template introspection ────────────────────────────────────────────────
|
|
50
86
|
/** Extract ${VAR} placeholder names from a string. */
|
|
@@ -92,6 +128,8 @@ export function listConnectionTemplates() {
|
|
|
92
128
|
...(route.description !== undefined && { description: route.description }),
|
|
93
129
|
...(route.docsUrl !== undefined && { docsUrl: route.docsUrl }),
|
|
94
130
|
...(route.openApiUrl !== undefined && { openApiUrl: route.openApiUrl }),
|
|
131
|
+
stability: route.stability ?? 'dev',
|
|
132
|
+
category: route.category,
|
|
95
133
|
requiredSecrets,
|
|
96
134
|
optionalSecrets,
|
|
97
135
|
hasIngestor: route.ingestor !== undefined,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wolpertingerlabs/drawlatch",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.5",
|
|
4
4
|
"description": "Encrypted MCP proxy with mutual authentication. Local MCP server forwards requests through an encrypted channel to a remote secrets-holding server.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/mcp/server.js",
|