@base44-preview/cli 0.0.31-pr.214.25a02b0 → 0.0.31-pr.214.27ce774

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/cli/index.js CHANGED
@@ -184888,7 +184888,7 @@ var ToolConfigSchema = exports_external.union([
184888
184888
  BackendFunctionToolConfigSchema
184889
184889
  ]);
184890
184890
  var AgentConfigSchema = exports_external.looseObject({
184891
- name: exports_external.string().regex(/^[a-z0-9_]+$/, "Agent name must be lowercase alphanumeric with underscores").min(1).max(100),
184891
+ name: exports_external.string().trim().min(1).max(100),
184892
184892
  description: exports_external.string().trim().min(1, "Description is required"),
184893
184893
  instructions: exports_external.string().trim().min(1, "Instructions are required"),
184894
184894
  tool_configs: exports_external.array(ToolConfigSchema).optional().default([]),
@@ -184944,6 +184944,9 @@ async function fetchAgents() {
184944
184944
  }
184945
184945
  // src/core/resources/agent/config.ts
184946
184946
  import { join as join3 } from "node:path";
184947
+ function toFileSlug(name2) {
184948
+ return name2.toLowerCase().replace(/[^a-z0-9_]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "");
184949
+ }
184947
184950
  async function readAgentFile(agentPath) {
184948
184951
  const parsed = await readJsonFile(agentPath);
184949
184952
  const result = AgentConfigSchema.safeParse(parsed);
@@ -184975,7 +184978,8 @@ async function writeAgents(agentsDir, remoteAgents) {
184975
184978
  const newNames = new Set(remoteAgents.map((a) => a.name));
184976
184979
  const toDelete = existingAgents.filter((a) => !newNames.has(a.name));
184977
184980
  for (const agent of toDelete) {
184978
- const files = await globby(`${agent.name}.${CONFIG_FILE_EXTENSION_GLOB}`, {
184981
+ const slug = toFileSlug(agent.name);
184982
+ const files = await globby(`${slug}.${CONFIG_FILE_EXTENSION_GLOB}`, {
184979
184983
  cwd: agentsDir,
184980
184984
  absolute: true
184981
184985
  });
@@ -184984,7 +184988,8 @@ async function writeAgents(agentsDir, remoteAgents) {
184984
184988
  }
184985
184989
  }
184986
184990
  for (const agent of remoteAgents) {
184987
- const filePath = join3(agentsDir, `${agent.name}.${CONFIG_FILE_EXTENSION}`);
184991
+ const slug = toFileSlug(agent.name);
184992
+ const filePath = join3(agentsDir, `${slug}.${CONFIG_FILE_EXTENSION}`);
184988
184993
  await writeJsonFile(filePath, agent);
184989
184994
  }
184990
184995
  const written = remoteAgents.map((a) => a.name);
@@ -185973,24 +185978,26 @@ async function createArchive(pathToArchive, targetArchivePath) {
185973
185978
  }
185974
185979
  // src/core/project/deploy.ts
185975
185980
  function hasResourcesToDeploy(projectData) {
185976
- const { project, entities, functions, agents } = projectData;
185981
+ const { project, entities, functions, agents, connectors } = projectData;
185977
185982
  const hasSite = Boolean(project.site?.outputDirectory);
185978
185983
  const hasEntities = entities.length > 0;
185979
185984
  const hasFunctions = functions.length > 0;
185980
185985
  const hasAgents = agents.length > 0;
185981
- return hasEntities || hasFunctions || hasAgents || hasSite;
185986
+ const hasConnectors = connectors.length > 0;
185987
+ return hasEntities || hasFunctions || hasAgents || hasConnectors || hasSite;
185982
185988
  }
185983
185989
  async function deployAll(projectData) {
185984
- const { project, entities, functions, agents } = projectData;
185990
+ const { project, entities, functions, agents, connectors } = projectData;
185985
185991
  await entityResource.push(entities);
185986
185992
  await functionResource.push(functions);
185987
185993
  await agentResource.push(agents);
185994
+ const { results: connectorResults } = await pushConnectors(connectors);
185988
185995
  if (project.site?.outputDirectory) {
185989
185996
  const outputDir = resolve(project.root, project.site.outputDirectory);
185990
185997
  const { appUrl } = await deploySite(outputDir);
185991
- return { appUrl };
185998
+ return { appUrl, connectorResults };
185992
185999
  }
185993
- return {};
186000
+ return { connectorResults };
185994
186001
  }
185995
186002
  // src/core/clients/base44-client.ts
185996
186003
  var retriedRequests = new WeakSet;
@@ -194368,14 +194375,94 @@ defineLazyProperty(apps, "safari", () => detectPlatformBinary({
194368
194375
  }));
194369
194376
  var open_default = open;
194370
194377
 
194371
- // src/cli/commands/connectors/push.ts
194372
- function isPendingOAuth(r2) {
194373
- return r2.action === "needs_oauth" && !!r2.redirectUrl && !!r2.connectionId;
194378
+ // src/cli/commands/connectors/oauth-prompt.ts
194379
+ var POLL_INTERVAL_MS = 2000;
194380
+ var POLL_TIMEOUT_MS = 2 * 60 * 1000;
194381
+ function filterPendingOAuth(results) {
194382
+ return results.filter((r2) => r2.action === "needs_oauth" && !!r2.redirectUrl && !!r2.connectionId);
194383
+ }
194384
+ async function runOAuthFlowWithSkip(connector2) {
194385
+ await open_default(connector2.redirectUrl);
194386
+ let finalStatus = "PENDING";
194387
+ let skipped = false;
194388
+ const s = Y2();
194389
+ const originalExit = process.exit;
194390
+ process.exit = () => {
194391
+ skipped = true;
194392
+ s.stop(`${connector2.type} skipped`);
194393
+ };
194394
+ s.start(`Waiting for ${connector2.type} authorization... (Esc to skip)`);
194395
+ try {
194396
+ await pWaitFor(async () => {
194397
+ if (skipped) {
194398
+ finalStatus = "SKIPPED";
194399
+ return true;
194400
+ }
194401
+ const response = await getOAuthStatus(connector2.type, connector2.connectionId);
194402
+ finalStatus = response.status;
194403
+ return response.status !== "PENDING";
194404
+ }, {
194405
+ interval: POLL_INTERVAL_MS,
194406
+ timeout: POLL_TIMEOUT_MS
194407
+ });
194408
+ } catch (err) {
194409
+ if (err instanceof TimeoutError2) {
194410
+ finalStatus = "PENDING";
194411
+ } else {
194412
+ throw err;
194413
+ }
194414
+ } finally {
194415
+ process.exit = originalExit;
194416
+ if (!skipped) {
194417
+ if (finalStatus === "ACTIVE") {
194418
+ s.stop(`${connector2.type} authorization complete`);
194419
+ } else if (finalStatus === "FAILED") {
194420
+ s.stop(`${connector2.type} authorization failed`);
194421
+ } else {
194422
+ s.stop(`${connector2.type} authorization timed out`);
194423
+ }
194424
+ }
194425
+ }
194426
+ return finalStatus;
194427
+ }
194428
+ async function promptOAuthFlows(pending, options) {
194429
+ const outcomes = new Map;
194430
+ if (pending.length === 0) {
194431
+ return outcomes;
194432
+ }
194433
+ M2.warn(`${pending.length} connector(s) require authorization in your browser:`);
194434
+ for (const connector2 of pending) {
194435
+ M2.info(` ${connector2.type}: ${theme.styles.dim(connector2.redirectUrl)}`);
194436
+ }
194437
+ if (options?.skipPrompt) {
194438
+ return outcomes;
194439
+ }
194440
+ const shouldAuth = await ye({
194441
+ message: "Open browser to authorize now?"
194442
+ });
194443
+ if (pD(shouldAuth) || !shouldAuth) {
194444
+ return outcomes;
194445
+ }
194446
+ for (const connector2 of pending) {
194447
+ try {
194448
+ M2.info(`
194449
+ Opening browser for ${connector2.type}...`);
194450
+ const status = await runOAuthFlowWithSkip(connector2);
194451
+ outcomes.set(connector2.type, status);
194452
+ } catch (err) {
194453
+ M2.error(`Failed to authorize ${connector2.type}: ${err instanceof Error ? err.message : String(err)}`);
194454
+ outcomes.set(connector2.type, "FAILED");
194455
+ }
194456
+ }
194457
+ return outcomes;
194374
194458
  }
194459
+
194460
+ // src/cli/commands/connectors/push.ts
194375
194461
  function printSummary(results, oauthOutcomes) {
194376
194462
  const synced = [];
194377
194463
  const added = [];
194378
194464
  const removed = [];
194465
+ const skipped = [];
194379
194466
  const failed = [];
194380
194467
  for (const r2 of results) {
194381
194468
  const oauthStatus = oauthOutcomes.get(r2.type);
@@ -194388,6 +194475,8 @@ function printSummary(results, oauthOutcomes) {
194388
194475
  } else if (r2.action === "needs_oauth") {
194389
194476
  if (oauthStatus === "ACTIVE") {
194390
194477
  added.push(r2.type);
194478
+ } else if (oauthStatus === "SKIPPED") {
194479
+ skipped.push(r2.type);
194391
194480
  } else if (oauthStatus === "PENDING") {
194392
194481
  failed.push({ type: r2.type, error: "authorization timed out" });
194393
194482
  } else if (oauthStatus === "FAILED") {
@@ -194397,7 +194486,6 @@ function printSummary(results, oauthOutcomes) {
194397
194486
  }
194398
194487
  }
194399
194488
  }
194400
- M2.info("");
194401
194489
  M2.info(theme.styles.bold("Summary:"));
194402
194490
  if (synced.length > 0) {
194403
194491
  M2.success(`Synced: ${synced.join(", ")}`);
@@ -194408,6 +194496,9 @@ function printSummary(results, oauthOutcomes) {
194408
194496
  if (removed.length > 0) {
194409
194497
  M2.info(theme.styles.dim(`Removed: ${removed.join(", ")}`));
194410
194498
  }
194499
+ if (skipped.length > 0) {
194500
+ M2.warn(`Skipped: ${skipped.join(", ")}`);
194501
+ }
194411
194502
  for (const r2 of failed) {
194412
194503
  M2.error(`Failed: ${r2.type}${r2.error ? ` - ${r2.error}` : ""}`);
194413
194504
  }
@@ -194423,59 +194514,14 @@ async function pushConnectorsAction() {
194423
194514
  const { results } = await runTask("Pushing connectors to Base44", async () => {
194424
194515
  return await pushConnectors(connectors);
194425
194516
  });
194426
- const oauthOutcomes = new Map;
194427
- const needsOAuth = results.filter(isPendingOAuth);
194517
+ const needsOAuth = filterPendingOAuth(results);
194428
194518
  let outroMessage = "Connectors pushed to Base44";
194429
- if (needsOAuth.length === 0) {
194430
- printSummary(results, oauthOutcomes);
194431
- return { outroMessage };
194432
- }
194433
- M2.warn(`${needsOAuth.length} connector(s) require authorization in your browser:`);
194434
- for (const connector2 of needsOAuth) {
194435
- M2.info(` '${connector2.type}': ${theme.styles.dim(connector2.redirectUrl)}`);
194436
- }
194437
- const pending = needsOAuth.map((c3) => c3.type).join(", ");
194438
- if (process.env.CI) {
194439
- outroMessage = `Skipped OAuth in CI. Pending: ${pending}. Run 'base44 connectors push' locally to authorize.`;
194440
- } else {
194441
- const shouldAuth = await ye({
194442
- message: "Open browser to authorize now?"
194443
- });
194444
- if (pD(shouldAuth) || !shouldAuth) {
194445
- outroMessage = `Authorization skipped. Pending: ${pending}. Run 'base44 connectors push' again to complete.`;
194446
- } else {
194447
- for (const connector2 of needsOAuth) {
194448
- try {
194449
- M2.info(`
194450
- Opening browser for '${connector2.type}'...`);
194451
- await open_default(connector2.redirectUrl);
194452
- let finalStatus = "PENDING";
194453
- await runTask(`Waiting for '${connector2.type}' authorization...`, async () => {
194454
- await pWaitFor(async () => {
194455
- const response = await getOAuthStatus(connector2.type, connector2.connectionId);
194456
- finalStatus = response.status;
194457
- return response.status !== "PENDING";
194458
- }, {
194459
- interval: 2000,
194460
- timeout: 2 * 60 * 1000
194461
- });
194462
- }, {
194463
- successMessage: `'${connector2.type}' authorization complete`,
194464
- errorMessage: `'${connector2.type}' authorization failed`
194465
- }).catch((err) => {
194466
- if (err instanceof TimeoutError2) {
194467
- finalStatus = "PENDING";
194468
- } else {
194469
- throw err;
194470
- }
194471
- });
194472
- oauthOutcomes.set(connector2.type, finalStatus);
194473
- } catch (err) {
194474
- M2.error(`Failed to authorize '${connector2.type}': ${err instanceof Error ? err.message : String(err)}`);
194475
- oauthOutcomes.set(connector2.type, "FAILED");
194476
- }
194477
- }
194478
- }
194519
+ const oauthOutcomes = await promptOAuthFlows(needsOAuth, {
194520
+ skipPrompt: !!process.env.CI
194521
+ });
194522
+ const allAuthorized = oauthOutcomes.size > 0 && [...oauthOutcomes.values()].every((s) => s === "ACTIVE");
194523
+ if (needsOAuth.length > 0 && !allAuthorized) {
194524
+ outroMessage = process.env.CI ? "Skipped OAuth in CI. Run 'base44 connectors push' locally or open the links above to authorize." : "Some connectors still require authorization. Run 'base44 connectors push' or open the links above to authorize.";
194479
194525
  }
194480
194526
  printSummary(results, oauthOutcomes);
194481
194527
  return { outroMessage };
@@ -194766,7 +194812,7 @@ async function deployAction(options) {
194766
194812
  outroMessage: "No resources found to deploy"
194767
194813
  };
194768
194814
  }
194769
- const { project: project2, entities, functions, agents } = projectData;
194815
+ const { project: project2, entities, functions, agents, connectors } = projectData;
194770
194816
  const summaryLines = [];
194771
194817
  if (entities.length > 0) {
194772
194818
  summaryLines.push(` - ${entities.length} ${entities.length === 1 ? "entity" : "entities"}`);
@@ -194777,6 +194823,9 @@ async function deployAction(options) {
194777
194823
  if (agents.length > 0) {
194778
194824
  summaryLines.push(` - ${agents.length} ${agents.length === 1 ? "agent" : "agents"}`);
194779
194825
  }
194826
+ if (connectors.length > 0) {
194827
+ summaryLines.push(` - ${connectors.length} ${connectors.length === 1 ? "connector" : "connectors"}`);
194828
+ }
194780
194829
  if (project2.site?.outputDirectory) {
194781
194830
  summaryLines.push(` - Site from ${project2.site.outputDirectory}`);
194782
194831
  }
@@ -194801,6 +194850,16 @@ ${summaryLines.join(`
194801
194850
  successMessage: theme.colors.base44Orange("Deployment completed"),
194802
194851
  errorMessage: "Deployment failed"
194803
194852
  });
194853
+ const needsOAuth = filterPendingOAuth(result.connectorResults ?? []);
194854
+ if (needsOAuth.length > 0) {
194855
+ const oauthOutcomes = await promptOAuthFlows(needsOAuth, {
194856
+ skipPrompt: options.yes || !!process.env.CI
194857
+ });
194858
+ const allAuthorized = oauthOutcomes.size > 0 && [...oauthOutcomes.values()].every((s) => s === "ACTIVE");
194859
+ if (!allAuthorized) {
194860
+ M2.info("Some connectors still require authorization. Run 'base44 connectors push' or open the links above in your browser.");
194861
+ }
194862
+ }
194804
194863
  M2.message(`${theme.styles.header("Dashboard")}: ${theme.colors.links(getDashboardUrl())}`);
194805
194864
  if (result.appUrl) {
194806
194865
  M2.message(`${theme.styles.header("App URL")}: ${theme.colors.links(result.appUrl)}`);
@@ -194808,7 +194867,7 @@ ${summaryLines.join(`
194808
194867
  return { outroMessage: "App deployed successfully" };
194809
194868
  }
194810
194869
  function getDeployCommand(context) {
194811
- return new Command("deploy").description("Deploy all project resources (entities, functions, agents, and site)").option("-y, --yes", "Skip confirmation prompt").action(async (options) => {
194870
+ return new Command("deploy").description("Deploy all project resources (entities, functions, agents, connectors, and site)").option("-y, --yes", "Skip confirmation prompt").action(async (options) => {
194812
194871
  await runCommand(() => deployAction(options), { requireAuth: true }, context);
194813
194872
  });
194814
194873
  }
@@ -199699,4 +199758,4 @@ export {
199699
199758
  CLIExitError
199700
199759
  };
199701
199760
 
199702
- //# debugId=3B15B2EE2CDAA1C064756E2164756E21
199761
+ //# debugId=F8EEF50D0741958B64756E2164756E21