railcode 0.1.24 → 0.1.25

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/index.js CHANGED
@@ -47,6 +47,8 @@ Usage:
47
47
  Service connectors: call them, or manage them (admin)
48
48
  railcode connections <list|create|delete> ... Manage org data connectors (admin)
49
49
  railcode llm <providers|models> List the LLM providers/models apps can call
50
+ railcode personal-connectors <list|tools|connect|call> ...
51
+ Your own connected accounts (Gmail, ...): discover + test
50
52
  railcode manifest <validate|show> ... Validate ${APP_MANIFEST_NAME} locally / show an app's ratified manifest
51
53
  railcode agent <list|show|create|update|delete|run|schedule> ...
52
54
  Manage org-scoped managed agents
@@ -112,6 +114,11 @@ async function main() {
112
114
  case "llm":
113
115
  await commandLlm(args);
114
116
  return;
117
+ case "personal-connectors":
118
+ case "personal-connector":
119
+ case "pc":
120
+ await commandPersonalConnectors(args);
121
+ return;
115
122
  case "member":
116
123
  case "members":
117
124
  await commandMembers(args);
@@ -5103,6 +5110,164 @@ function assertKnownLlmOptions(args, allowed) {
5103
5110
  }
5104
5111
  }
5105
5112
  // ---------------------------------------------------------------------------
5113
+ // Personal connectors: your OWN connected accounts (Gmail, Slack, ...).
5114
+ //
5115
+ // Everything here hits the NON-org-scoped `/api/personal-connections/*` plane —
5116
+ // a personal connection belongs to the human, not the org. It's the same
5117
+ // resource the console's Connectors tab drives. `call` executes as YOU against
5118
+ // YOUR own connection (an identity op, not an app), so it's how you smoke-test a
5119
+ // tool from the terminal before wiring it into an app or agent.
5120
+ // ---------------------------------------------------------------------------
5121
+ const PC_HELP = `railcode personal-connectors — your own connected accounts (Gmail, Slack, ...)
5122
+
5123
+ Usage:
5124
+ railcode personal-connectors list Toolkits this deployment brokers + your status
5125
+ railcode personal-connectors tools <toolkit> The callable tools of a toolkit (and their inputs)
5126
+ railcode personal-connectors connect <toolkit> Print the OAuth URL to connect it (open in a browser)
5127
+ railcode personal-connectors call <tool> [--args '<json>'] Run one tool on your own account
5128
+
5129
+ Aliases: personal-connector, pc
5130
+
5131
+ Discovery is what you build against: \`tools <toolkit> --json\` shows each tool's
5132
+ input schema, so you know what to put in an app's \`personal_connectors:\` and what
5133
+ \`personalConnections.call('<tool>', {...})\` expects.
5134
+
5135
+ Options:
5136
+ --json Print raw JSON instead of a table
5137
+ --args '<json>' Arguments object for \`call\` (default {})
5138
+ `;
5139
+ async function commandPersonalConnectors(args) {
5140
+ const sub = args.rest[0] ?? "";
5141
+ switch (sub) {
5142
+ case "list":
5143
+ await commandPcList(args);
5144
+ return;
5145
+ case "tools":
5146
+ await commandPcTools(args);
5147
+ return;
5148
+ case "connect":
5149
+ await commandPcConnect(args);
5150
+ return;
5151
+ case "call":
5152
+ await commandPcCall(args);
5153
+ return;
5154
+ case "":
5155
+ case "help":
5156
+ console.log(PC_HELP);
5157
+ return;
5158
+ default:
5159
+ throw new CliError(`Unknown personal-connectors command: ${sub}\n\n${PC_HELP}`, 2);
5160
+ }
5161
+ }
5162
+ // A 503 here means the DEPLOYMENT has personal connectors turned off — a state to
5163
+ // report plainly, not a failure. Anything else is a real error.
5164
+ function pcUnavailable(status) {
5165
+ return status === 503;
5166
+ }
5167
+ async function commandPcList(args) {
5168
+ rejectUnknownOptions(args, ["json", "apiUrl"], "personal-connectors list", PC_HELP);
5169
+ const config = requireLogin(args);
5170
+ const resp = await authedFetch(config, `/api/personal-connections/toolkits`);
5171
+ if (resp.status === 401)
5172
+ await reLoginOrThrow();
5173
+ if (pcUnavailable(resp.status)) {
5174
+ console.log("Personal connectors are not enabled on this deployment.");
5175
+ return;
5176
+ }
5177
+ const toolkits = (await readJsonOrThrow(resp, "List toolkits"));
5178
+ if (args.options.json) {
5179
+ console.log(JSON.stringify(toolkits, null, 2));
5180
+ return;
5181
+ }
5182
+ if (toolkits.length === 0) {
5183
+ console.log("No connectors are available yet.");
5184
+ return;
5185
+ }
5186
+ console.log(formatTable(["TOOLKIT", "NAME", "STATUS"], toolkits.map((t) => [t.slug, t.name, t.connected ? "connected" : t.status ?? "not connected"])));
5187
+ }
5188
+ async function commandPcTools(args) {
5189
+ rejectUnknownOptions(args, ["json", "apiUrl"], "personal-connectors tools", PC_HELP);
5190
+ const toolkit = args.rest[1];
5191
+ if (!toolkit)
5192
+ throw new CliError("Usage: railcode personal-connectors tools <toolkit>", 2);
5193
+ const config = requireLogin(args);
5194
+ const resp = await authedFetch(config, `/api/personal-connections/toolkits/${encodeURIComponent(toolkit)}/tools`);
5195
+ if (resp.status === 401)
5196
+ await reLoginOrThrow();
5197
+ if (pcUnavailable(resp.status)) {
5198
+ console.log("Personal connectors are not enabled on this deployment.");
5199
+ return;
5200
+ }
5201
+ const tools = (await readJsonOrThrow(resp, `List ${toolkit} tools`));
5202
+ if (args.options.json) {
5203
+ // --json carries the input_schema, which is what you actually build against.
5204
+ console.log(JSON.stringify(tools, null, 2));
5205
+ return;
5206
+ }
5207
+ if (tools.length === 0) {
5208
+ console.log(`No tools found for "${toolkit}".`);
5209
+ return;
5210
+ }
5211
+ console.log(formatTable(["TOOL", "DESCRIPTION"], tools.map((t) => [t.slug, t.description])));
5212
+ console.log(`\n${tools.length} tool(s). Add \`--json\` to see each tool's input schema.`);
5213
+ }
5214
+ async function commandPcConnect(args) {
5215
+ rejectUnknownOptions(args, ["json", "apiUrl"], "personal-connectors connect", PC_HELP);
5216
+ const toolkit = args.rest[1];
5217
+ if (!toolkit)
5218
+ throw new CliError("Usage: railcode personal-connectors connect <toolkit>", 2);
5219
+ const config = requireLogin(args);
5220
+ // Connecting is browser-bound OAuth; the CLI can't complete it. It prints the
5221
+ // URL and leaves opening it to you — the same handoff `railcode login` uses.
5222
+ const resp = await authedFetch(config, `/api/personal-connections/${encodeURIComponent(toolkit)}/connect`, { method: "POST" });
5223
+ if (resp.status === 401)
5224
+ await reLoginOrThrow();
5225
+ if (pcUnavailable(resp.status)) {
5226
+ console.log("Personal connectors are not enabled on this deployment.");
5227
+ return;
5228
+ }
5229
+ const body = (await readJsonOrThrow(resp, `Connect ${toolkit}`));
5230
+ if (args.options.json) {
5231
+ console.log(JSON.stringify(body, null, 2));
5232
+ return;
5233
+ }
5234
+ console.log(`Open this URL to connect ${toolkit}, then re-run your command:\n\n ${body.redirect_url}\n`);
5235
+ }
5236
+ async function commandPcCall(args) {
5237
+ rejectUnknownOptions(args, ["json", "args", "apiUrl"], "personal-connectors call", PC_HELP);
5238
+ const tool = args.rest[1];
5239
+ if (!tool)
5240
+ throw new CliError("Usage: railcode personal-connectors call <tool> [--args '<json>']", 2);
5241
+ let toolArgs = {};
5242
+ if (typeof args.options.args === "string") {
5243
+ try {
5244
+ toolArgs = JSON.parse(args.options.args);
5245
+ }
5246
+ catch {
5247
+ throw new CliError(`--args must be a JSON object (got: ${args.options.args})`, 2);
5248
+ }
5249
+ }
5250
+ const config = requireLogin(args);
5251
+ const resp = await authedFetch(config, `/api/personal-connections/call`, {
5252
+ method: "POST",
5253
+ headers: { "Content-Type": "application/json" },
5254
+ body: JSON.stringify({ tool, arguments: toolArgs }),
5255
+ });
5256
+ if (resp.status === 401)
5257
+ await reLoginOrThrow();
5258
+ if (pcUnavailable(resp.status)) {
5259
+ console.log("Personal connectors are not enabled on this deployment.");
5260
+ return;
5261
+ }
5262
+ // A 409 means "connect this toolkit first" — surface the server's hint verbatim
5263
+ // rather than a generic failure, since it names the exact command to run.
5264
+ if (resp.status === 409) {
5265
+ throw new CliError(await errorDetail(resp), 1);
5266
+ }
5267
+ const body = await readJsonOrThrow(resp, `Call ${tool}`);
5268
+ console.log(JSON.stringify(body, null, 2));
5269
+ }
5270
+ // ---------------------------------------------------------------------------
5106
5271
  // Shared admin helpers (members / roles / apps / analytics / logs / connections)
5107
5272
  //
5108
5273
  // All of these hit the org-scoped `/api/organizations/{org}/...` management APIs
@@ -6182,6 +6347,7 @@ async function commandDev(args) {
6182
6347
  fileStores: new Map(),
6183
6348
  port: requestedPort,
6184
6349
  config,
6350
+ personalConnectors: readAppPersonalConnectors(cwd),
6185
6351
  };
6186
6352
  // Asset mode needs its deps before we bind anything; the check is cheap and
6187
6353
  // failing early avoids leaving the proxy port bound on a misconfigured app.
@@ -6682,6 +6848,10 @@ async function handleLocalApi(ctx, req, res, url) {
6682
6848
  await handleFiles(ctx, req, res, path, url);
6683
6849
  return;
6684
6850
  }
6851
+ if (path === "/personal-connections" || path.startsWith("/personal-connections/")) {
6852
+ await handlePersonalConnections(ctx, req, res, path, url);
6853
+ return;
6854
+ }
6685
6855
  // Proxied surfaces → forward to the real instance with the saved token.
6686
6856
  if (path === "/connections" ||
6687
6857
  path === "/queries" ||
@@ -7030,6 +7200,172 @@ export function devUpstreamAuthFallback(status, degradeOk) {
7030
7200
  },
7031
7201
  };
7032
7202
  }
7203
+ // ── personal connectors in dev ────────────────────────────────────────────────
7204
+ //
7205
+ // The SDK's `personalConnections.*` methods hit the app plane in prod, which is
7206
+ // bounded by the app's ratified manifest. `railcode dev` has no ratified app, so
7207
+ // it reproduces that bound HERE from the local manifest.yaml and forwards the
7208
+ // actual work to the USER plane (`/api/personal-connections/*`) as the signed-in
7209
+ // developer — the same "run as you, not as a deployed app" model dev uses for
7210
+ // SQL and LLM. The result: declared tools run against your real connection,
7211
+ // undeclared ones are refused exactly as they will be in prod, so a bad call
7212
+ // fails locally instead of only after deploy.
7213
+ function readAppPersonalConnectors(cwd) {
7214
+ const path = join(cwd, APP_MANIFEST_NAME);
7215
+ if (!existsSync(path))
7216
+ return [];
7217
+ try {
7218
+ return parseManifestYaml(readFileSync(path, "utf8")).personal_connectors ?? [];
7219
+ }
7220
+ catch {
7221
+ // A malformed manifest is caught (loudly) at deploy; dev must not crash on it.
7222
+ // Treating it as "nothing declared" makes personal-connector calls 403 here,
7223
+ // which is the safe direction.
7224
+ return [];
7225
+ }
7226
+ }
7227
+ // The toolkit slugs an app declared (any tool scope). Mirrors the server's
7228
+ // `manifest.personal_connector_toolkits`.
7229
+ function pcDeclaredToolkits(entries) {
7230
+ return new Set(entries.map((e) => e.split(":", 1)[0]));
7231
+ }
7232
+ // May this app call `tool` of `toolkit`? Mirrors the server's
7233
+ // `manifest.personal_connector_allowed`: a bare/`*` entry covers the whole
7234
+ // toolkit, else the tool must match exactly.
7235
+ function pcAllows(entries, toolkit, tool) {
7236
+ for (const entry of entries) {
7237
+ const idx = entry.indexOf(":");
7238
+ const entryToolkit = idx === -1 ? entry : entry.slice(0, idx);
7239
+ if (entryToolkit !== toolkit)
7240
+ continue;
7241
+ const entryTool = idx === -1 ? "" : entry.slice(idx + 1);
7242
+ if (entryTool === "" || entryTool === "*" || entryTool === tool)
7243
+ return true;
7244
+ }
7245
+ return false;
7246
+ }
7247
+ // Forward one request to the USER plane and return its parsed body. Kept separate
7248
+ // from forwardCompute because these need post-filtering by the local manifest,
7249
+ // not a raw pass-through.
7250
+ async function pcForward(ctx, method, apiPath, body) {
7251
+ const creds = devCreds(ctx.config);
7252
+ if (!creds) {
7253
+ return {
7254
+ status: 503,
7255
+ body: {
7256
+ error: "not_logged_in",
7257
+ message: "Run `railcode login` to use personal connectors in dev.",
7258
+ },
7259
+ };
7260
+ }
7261
+ const headers = {
7262
+ Authorization: `Bearer ${creds.token}`,
7263
+ "X-Railcode-Source": "local-dev",
7264
+ };
7265
+ if (body !== undefined)
7266
+ headers["Content-Type"] = "application/json";
7267
+ let upstream;
7268
+ try {
7269
+ upstream = await fetch(`${creds.apiUrl}/api${apiPath}`, {
7270
+ method,
7271
+ headers,
7272
+ body: body !== undefined ? JSON.stringify(body) : undefined,
7273
+ redirect: "manual",
7274
+ });
7275
+ }
7276
+ catch {
7277
+ return { status: 503, body: { error: "unreachable", message: `Could not reach ${creds.apiUrl}.` } };
7278
+ }
7279
+ const text = await upstream.text();
7280
+ let parsed = null;
7281
+ try {
7282
+ parsed = text ? JSON.parse(text) : null;
7283
+ }
7284
+ catch {
7285
+ parsed = text;
7286
+ }
7287
+ return { status: upstream.status, body: parsed };
7288
+ }
7289
+ // Which declared toolkit owns `tool` — asked of the user-plane catalog, scanning
7290
+ // only the app's declared toolkits (as the server's app-plane resolver does).
7291
+ async function pcResolveToolkit(ctx, entries, tool) {
7292
+ for (const toolkit of pcDeclaredToolkits(entries)) {
7293
+ const { status, body } = await pcForward(ctx, "GET", `/personal-connections/toolkits/${encodeURIComponent(toolkit)}/tools`);
7294
+ if (status === 200 && Array.isArray(body) && body.some((t) => t.slug === tool)) {
7295
+ return toolkit;
7296
+ }
7297
+ }
7298
+ return null;
7299
+ }
7300
+ const PC_NOT_IN_MANIFEST = (label) => ({
7301
+ detail: `personal connector "${label}" was not in the manifest`,
7302
+ });
7303
+ async function handlePersonalConnections(ctx, req, res, path, url) {
7304
+ const entries = ctx.personalConnectors;
7305
+ const declared = pcDeclaredToolkits(entries);
7306
+ const rest = path.slice("/personal-connections".length); // "", "/gmail/tools", "/call", ...
7307
+ // list() — forward, then filter to the toolkits this app declared (the app
7308
+ // plane never shows an app the user's OTHER connected accounts).
7309
+ if (rest === "" && req.method === "GET") {
7310
+ const { status, body } = await pcForward(ctx, "GET", "/personal-connections");
7311
+ const filtered = Array.isArray(body)
7312
+ ? body.filter((c) => declared.has(c.toolkit))
7313
+ : body;
7314
+ return sendJson(res, status === 200 ? 200 : status, status === 200 ? filtered : body);
7315
+ }
7316
+ // tools(toolkit) — require the toolkit is declared, then filter to the declared
7317
+ // tool subset. Both mirror the app plane.
7318
+ const toolsMatch = rest.match(/^\/([^/]+)\/tools$/);
7319
+ if (toolsMatch && req.method === "GET") {
7320
+ const toolkit = decodeURIComponent(toolsMatch[1]);
7321
+ if (!declared.has(toolkit))
7322
+ return sendJson(res, 403, PC_NOT_IN_MANIFEST(toolkit));
7323
+ const { status, body } = await pcForward(ctx, "GET", `/personal-connections/toolkits/${encodeURIComponent(toolkit)}/tools`);
7324
+ const filtered = status === 200 && Array.isArray(body)
7325
+ ? body.filter((t) => pcAllows(entries, toolkit, t.slug))
7326
+ : body;
7327
+ return sendJson(res, status, status === 200 ? filtered : body);
7328
+ }
7329
+ // connect(toolkit) — require declared (an app shouldn't walk you through
7330
+ // connecting an account it can never use), then forward.
7331
+ const connectMatch = rest.match(/^\/([^/]+)\/connect$/);
7332
+ if (connectMatch && req.method === "POST") {
7333
+ const toolkit = decodeURIComponent(connectMatch[1]);
7334
+ if (!declared.has(toolkit))
7335
+ return sendJson(res, 403, PC_NOT_IN_MANIFEST(toolkit));
7336
+ const { status, body } = await pcForward(ctx, "POST", `/personal-connections/${encodeURIComponent(toolkit)}/connect`);
7337
+ return sendJson(res, status, body);
7338
+ }
7339
+ // call(tool, args) — the load-bearing gate: resolve the tool's toolkit, require
7340
+ // both that toolkit declared AND this specific tool permitted, else 403 (never
7341
+ // forwarded). No declaration at all ⇒ nothing resolves ⇒ refused, matching the
7342
+ // prod chokepoint's "no manifest = refuse".
7343
+ if (rest === "/call" && req.method === "POST") {
7344
+ const raw = await readBody(req);
7345
+ let payload;
7346
+ try {
7347
+ payload = raw ? JSON.parse(raw.toString("utf8")) : {};
7348
+ }
7349
+ catch {
7350
+ return sendJson(res, 400, { detail: "body must be JSON" });
7351
+ }
7352
+ const tool = payload.tool;
7353
+ if (!tool)
7354
+ return sendJson(res, 400, { detail: '"tool" is required' });
7355
+ if (entries.length === 0)
7356
+ return sendJson(res, 403, PC_NOT_IN_MANIFEST(tool));
7357
+ const toolkit = await pcResolveToolkit(ctx, entries, tool);
7358
+ if (!toolkit || !pcAllows(entries, toolkit, tool)) {
7359
+ return sendJson(res, 403, PC_NOT_IN_MANIFEST(tool));
7360
+ }
7361
+ const { status, body } = await pcForward(ctx, "POST", "/personal-connections/call", {
7362
+ tool,
7363
+ arguments: payload.arguments ?? {},
7364
+ });
7365
+ return sendJson(res, status, body);
7366
+ }
7367
+ sendJson(res, 404, { detail: "not found" });
7368
+ }
7033
7369
  async function forwardCompute(ctx, req, res, path, url) {
7034
7370
  // Never reply 401 to the browser — the SDK reloads the page on 401 (loop).
7035
7371
  // Load-time list calls degrade to [] so dataConnectors()/savedQueries()/
package/dist/manifest.js CHANGED
@@ -41,9 +41,14 @@ const ALLOWED_KEYS = [
41
41
  "email",
42
42
  "adhoc_sql",
43
43
  "agents",
44
+ "personal_connectors",
44
45
  ];
45
46
  const HTTP_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"];
46
47
  const SAVED_QUERY_NAME = /^[a-z0-9_]{1,80}$/;
48
+ // Mirrors the server's _PERSONAL_CONNECTOR_RE exactly. The server is
49
+ // authoritative; this exists so `railcode deploy` can reject a bad manifest
50
+ // locally instead of after a round trip.
51
+ const PERSONAL_CONNECTOR = /^[a-z0-9][a-z0-9_]{0,63}(?::(?:\*|[A-Z0-9_]{1,120}))?$/;
47
52
  // PyYAML's YAML 1.1 plain-scalar resolver: a bare (unquoted) scalar matching one
48
53
  // of these resolves to a non-string (bool/null/int/float/timestamp), and the
49
54
  // server rejects a non-string wherever the manifest wants a name. The quirks are
@@ -396,6 +401,7 @@ export function parseManifestYaml(source) {
396
401
  email: false,
397
402
  adhoc_sql: [],
398
403
  agents: [],
404
+ personal_connectors: [],
399
405
  };
400
406
  for (const [key, entry] of entries) {
401
407
  if (key === "run_as") {
@@ -415,12 +421,14 @@ export function parseManifestYaml(source) {
415
421
  doc.connectors = parseConnectors(entry);
416
422
  }
417
423
  else {
418
- // saved_queries / adhoc_sql / agents: a list of names.
424
+ // saved_queries / adhoc_sql / agents / personal_connectors: a list of names.
419
425
  const items = parseStringList(entry, key);
420
426
  if (key === "saved_queries")
421
427
  doc.saved_queries = items;
422
428
  else if (key === "agents")
423
429
  doc.agents = items;
430
+ else if (key === "personal_connectors")
431
+ doc.personal_connectors = items;
424
432
  else
425
433
  doc.adhoc_sql = items;
426
434
  }
@@ -643,6 +651,12 @@ function validateDoc(doc, lines) {
643
651
  doc.saved_queries = [...new Set(doc.saved_queries)].sort();
644
652
  doc.adhoc_sql = [...new Set(doc.adhoc_sql)].sort();
645
653
  doc.agents = [...new Set(doc.agents)].sort();
654
+ for (const entry of doc.personal_connectors) {
655
+ if (!PERSONAL_CONNECTOR.test(entry)) {
656
+ throw new ManifestParseError(`"${entry}" is not a valid personal_connectors entry — use "gmail", "gmail:*", or "gmail:GMAIL_SEND_EMAIL"`, lineOf(entry));
657
+ }
658
+ }
659
+ doc.personal_connectors = [...new Set(doc.personal_connectors)].sort();
646
660
  for (const name of Object.keys(doc.connectors)) {
647
661
  doc.connectors[name] = [...new Set(doc.connectors[name])].sort();
648
662
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "railcode",
3
- "version": "0.1.24",
3
+ "version": "0.1.25",
4
4
  "description": "Developer CLI for the multi-tenant Railcode platform: log in, scaffold, and deploy static apps.",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/static/sdk.js CHANGED
@@ -261,7 +261,7 @@
261
261
  window.addEventListener("railcode:inspector", sync);
262
262
  }
263
263
  me().then((who) => {
264
- if (who.user.is_admin) mount2();
264
+ if (who.user.is_admin || who.user.is_app_owner) mount2();
265
265
  }).catch(() => {
266
266
  });
267
267
 
@@ -711,6 +711,42 @@
711
711
  var llm = { generate, stream };
712
712
  var llmProviders = () => track("llm", "llmProviders()", () => call("GET", "/llm/providers"));
713
713
 
714
+ // ../sdk/src/personal-connections.ts
715
+ function list2() {
716
+ return track(
717
+ "personalConnections",
718
+ "personalConnections.list()",
719
+ () => call("GET", "/personal-connections")
720
+ );
721
+ }
722
+ function connect(toolkit) {
723
+ return track(
724
+ "personalConnections",
725
+ `personalConnections.connect(${q(toolkit)})`,
726
+ () => call(
727
+ "POST",
728
+ `/personal-connections/${encodeURIComponent(toolkit)}/connect`
729
+ )
730
+ );
731
+ }
732
+ function tools(toolkit) {
733
+ return track(
734
+ "personalConnections",
735
+ `personalConnections.tools(${q(toolkit)})`,
736
+ () => call("GET", `/personal-connections/${encodeURIComponent(toolkit)}/tools`)
737
+ );
738
+ }
739
+ function callTool(tool, args = {}) {
740
+ return track(
741
+ "personalConnections",
742
+ `personalConnections.call(${q(tool)})`,
743
+ () => call("POST", "/personal-connections/call", {
744
+ body: { tool, arguments: args }
745
+ })
746
+ );
747
+ }
748
+ var personalConnections = { list: list2, connect, tools, call: callTool };
749
+
714
750
  // ../sdk/src/queries.ts
715
751
  var PARAMS_LABEL_MAX2 = 40;
716
752
  var query = (name, params) => {
@@ -769,6 +805,7 @@
769
805
  target.email = email;
770
806
  target.llm = llm;
771
807
  target.llmProviders = llmProviders;
808
+ target.personalConnections = personalConnections;
772
809
  target.data = data;
773
810
  target.postgres = postgres;
774
811
  target.bigquery = bigquery;