@base44-preview/cli 0.0.19-pr.124.f10d1f3 → 0.0.21-pr.112.26ce2e2

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.
Files changed (2) hide show
  1. package/dist/index.js +186 -6
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -7899,10 +7899,20 @@ var AuthValidationError = class extends Error {
7899
7899
  this.name = "AuthValidationError";
7900
7900
  }
7901
7901
  };
7902
+ /**
7903
+ * Formats an API error response into a human-readable string.
7904
+ * Prefers `message` (human-readable) over `detail`.
7905
+ */
7906
+ function formatApiError(errorJson) {
7907
+ const error = errorJson;
7908
+ const content = error?.message ?? error?.detail ?? errorJson;
7909
+ return typeof content === "string" ? content : JSON.stringify(content, null, 2);
7910
+ }
7902
7911
 
7903
7912
  //#endregion
7904
7913
  //#region src/core/consts.ts
7905
7914
  const PROJECT_SUBDIR = "base44";
7915
+ const CONFIG_FILE_EXTENSION = "jsonc";
7906
7916
  const CONFIG_FILE_EXTENSION_GLOB = "{json,jsonc}";
7907
7917
  const FUNCTION_CONFIG_FILE = `function.${CONFIG_FILE_EXTENSION_GLOB}`;
7908
7918
  const APP_CONFIG_PATTERN = `**/.app.${CONFIG_FILE_EXTENSION_GLOB}`;
@@ -16561,8 +16571,8 @@ async function syncEntities(entities) {
16561
16571
  });
16562
16572
  if (!response.ok) {
16563
16573
  const errorJson = await response.json();
16564
- if (response.status === 428) throw new Error(`Failed to delete entity: ${errorJson.message}`);
16565
- throw new Error(`Error occurred while syncing entities ${errorJson.message}`);
16574
+ if (response.status === 428) throw new Error(`Failed to delete entity: ${formatApiError(errorJson)}`);
16575
+ throw new Error(`Error occurred while syncing entities: ${formatApiError(errorJson)}`);
16566
16576
  }
16567
16577
  return SyncEntitiesResponseSchema.parse(await response.json());
16568
16578
  }
@@ -16684,6 +16694,123 @@ const functionResource = {
16684
16694
  push: pushFunctions
16685
16695
  };
16686
16696
 
16697
+ //#endregion
16698
+ //#region src/core/resources/agent/schema.ts
16699
+ const EntityToolConfigSchema = object({
16700
+ entity_name: string().min(1),
16701
+ allowed_operations: array(_enum([
16702
+ "read",
16703
+ "create",
16704
+ "update",
16705
+ "delete"
16706
+ ])).default([])
16707
+ });
16708
+ const BackendFunctionToolConfigSchema = object({
16709
+ function_name: string().min(1),
16710
+ description: string().default("agent backend function")
16711
+ });
16712
+ const ToolConfigSchema = union([EntityToolConfigSchema, BackendFunctionToolConfigSchema]);
16713
+ const AgentConfigSchema = object({
16714
+ name: string().regex(/^[a-z0-9_]+$/, "Agent name must be lowercase alphanumeric with underscores").min(1).max(100),
16715
+ description: string().min(1, "Agent description cannot be empty"),
16716
+ instructions: string().min(1, "Agent instructions cannot be empty"),
16717
+ tool_configs: array(ToolConfigSchema).default([]),
16718
+ whatsapp_greeting: string().nullable().optional()
16719
+ });
16720
+ const SyncAgentsResponseSchema = object({
16721
+ created: array(string()),
16722
+ updated: array(string()),
16723
+ deleted: array(string())
16724
+ });
16725
+ const AgentConfigApiResponseSchema = object({
16726
+ name: string(),
16727
+ description: string(),
16728
+ instructions: string(),
16729
+ tool_configs: array(ToolConfigSchema).default([]),
16730
+ whatsapp_greeting: string().nullable().optional()
16731
+ });
16732
+ const ListAgentsResponseSchema = object({
16733
+ items: array(AgentConfigApiResponseSchema),
16734
+ total: number()
16735
+ });
16736
+
16737
+ //#endregion
16738
+ //#region src/core/resources/agent/config.ts
16739
+ async function readAgentFile(agentPath) {
16740
+ const parsed = await readJsonFile(agentPath);
16741
+ const result = AgentConfigSchema.safeParse(parsed);
16742
+ if (!result.success) throw new Error(`Invalid agent configuration in ${agentPath}: ${result.error.issues.map((e$1) => e$1.message).join(", ")}`);
16743
+ return result.data;
16744
+ }
16745
+ async function readAllAgents(agentsDir) {
16746
+ if (!await pathExists(agentsDir)) return [];
16747
+ const files = await globby(`*.${CONFIG_FILE_EXTENSION_GLOB}`, {
16748
+ cwd: agentsDir,
16749
+ absolute: true
16750
+ });
16751
+ const agents = await Promise.all(files.map((filePath) => readAgentFile(filePath)));
16752
+ const names = /* @__PURE__ */ new Set();
16753
+ for (const agent of agents) {
16754
+ if (names.has(agent.name)) throw new Error(`Duplicate agent name "${agent.name}"`);
16755
+ names.add(agent.name);
16756
+ }
16757
+ return agents;
16758
+ }
16759
+ async function writeAgents(agentsDir, agents) {
16760
+ const existingAgents = await readAllAgents(agentsDir);
16761
+ const newNames = new Set(agents.map((a$1) => a$1.name));
16762
+ const toDelete = existingAgents.filter((a$1) => !newNames.has(a$1.name));
16763
+ for (const agent of toDelete) await deleteFile(join(agentsDir, `${agent.name}.${CONFIG_FILE_EXTENSION}`));
16764
+ for (const agent of agents) await writeJsonFile(join(agentsDir, `${agent.name}.${CONFIG_FILE_EXTENSION}`), {
16765
+ name: agent.name,
16766
+ description: agent.description,
16767
+ instructions: agent.instructions,
16768
+ tool_configs: agent.tool_configs,
16769
+ whatsapp_greeting: agent.whatsapp_greeting ?? null
16770
+ });
16771
+ return {
16772
+ written: agents.map((a$1) => a$1.name),
16773
+ deleted: toDelete.map((a$1) => a$1.name)
16774
+ };
16775
+ }
16776
+
16777
+ //#endregion
16778
+ //#region src/core/resources/agent/api.ts
16779
+ async function pushAgents(agents) {
16780
+ const appClient = getAppClient();
16781
+ const payload = agents.map((agent) => ({
16782
+ name: agent.name,
16783
+ description: agent.description,
16784
+ instructions: agent.instructions,
16785
+ tool_configs: agent.tool_configs,
16786
+ whatsapp_greeting: agent.whatsapp_greeting ?? null
16787
+ }));
16788
+ const response = await appClient.put("agent-configs", {
16789
+ json: payload,
16790
+ throwHttpErrors: false
16791
+ });
16792
+ if (!response.ok) {
16793
+ const errorJson = await response.json();
16794
+ throw new Error(`Error occurred while syncing agents: ${formatApiError(errorJson)}`);
16795
+ }
16796
+ return SyncAgentsResponseSchema.parse(await response.json());
16797
+ }
16798
+ async function fetchAgents() {
16799
+ const response = await getAppClient().get("agent-configs", { throwHttpErrors: false });
16800
+ if (!response.ok) {
16801
+ const errorJson = await response.json();
16802
+ throw new Error(`Error occurred while fetching agents: ${formatApiError(errorJson)}`);
16803
+ }
16804
+ return ListAgentsResponseSchema.parse(await response.json());
16805
+ }
16806
+
16807
+ //#endregion
16808
+ //#region src/core/resources/agent/resource.ts
16809
+ const agentResource = {
16810
+ readAll: readAllAgents,
16811
+ push: pushAgents
16812
+ };
16813
+
16687
16814
  //#endregion
16688
16815
  //#region src/core/project/schema.ts
16689
16816
  const TemplateSchema = object({
@@ -16704,7 +16831,8 @@ const ProjectConfigSchema = object({
16704
16831
  description: string().optional(),
16705
16832
  site: SiteConfigSchema.optional(),
16706
16833
  entitiesDir: string().optional().default("entities"),
16707
- functionsDir: string().optional().default("functions")
16834
+ functionsDir: string().optional().default("functions"),
16835
+ agentsDir: string().optional().default("agents")
16708
16836
  });
16709
16837
  const AppConfigSchema = object({ id: string().min(1, "id cannot be empty") });
16710
16838
  const CreateProjectResponseSchema = looseObject({ id: string() });
@@ -16776,7 +16904,11 @@ async function readProjectConfig(projectRoot) {
16776
16904
  if (!result.success) throw new Error(`Invalid project configuration: ${result.error.message}`);
16777
16905
  const project = result.data;
16778
16906
  const configDir = dirname(configPath);
16779
- const [entities, functions] = await Promise.all([entityResource.readAll(join(configDir, project.entitiesDir)), functionResource.readAll(join(configDir, project.functionsDir))]);
16907
+ const [entities, functions, agents] = await Promise.all([
16908
+ entityResource.readAll(join(configDir, project.entitiesDir)),
16909
+ functionResource.readAll(join(configDir, project.functionsDir)),
16910
+ agentResource.readAll(join(configDir, project.agentsDir))
16911
+ ]);
16780
16912
  return {
16781
16913
  project: {
16782
16914
  ...project,
@@ -16784,7 +16916,8 @@ async function readProjectConfig(projectRoot) {
16784
16916
  configPath
16785
16917
  },
16786
16918
  entities,
16787
- functions
16919
+ functions,
16920
+ agents
16788
16921
  };
16789
16922
  }
16790
16923
 
@@ -31355,6 +31488,52 @@ const entitiesPushCommand = new Command("entities").description("Manage project
31355
31488
  await runCommand(pushEntitiesAction, { requireAuth: true });
31356
31489
  }));
31357
31490
 
31491
+ //#endregion
31492
+ //#region src/cli/commands/agents/pull.ts
31493
+ async function pullAgentsAction() {
31494
+ const { project } = await readProjectConfig();
31495
+ const agentsDir = join(dirname(project.configPath), project.agentsDir);
31496
+ const response = await runTask("Fetching agents from Base44", async () => {
31497
+ return await fetchAgents();
31498
+ }, {
31499
+ successMessage: "Agents fetched successfully",
31500
+ errorMessage: "Failed to fetch agents"
31501
+ });
31502
+ if (response.items.length === 0) return { outroMessage: "No agents found on Base44" };
31503
+ const { written, deleted } = await runTask("Writing agent files", async () => {
31504
+ return await writeAgents(agentsDir, response.items);
31505
+ }, {
31506
+ successMessage: "Agent files written successfully",
31507
+ errorMessage: "Failed to write agent files"
31508
+ });
31509
+ if (written.length > 0) M.success(`Written: ${written.join(", ")}`);
31510
+ if (deleted.length > 0) M.warn(`Deleted: ${deleted.join(", ")}`);
31511
+ return { outroMessage: `Pulled ${response.total} agents to ${agentsDir}` };
31512
+ }
31513
+ const agentsPullCommand = new Command("pull").description("Pull agents from Base44 to local files (replaces all local agent configs)").action(async () => {
31514
+ await runCommand(pullAgentsAction, { requireAuth: true });
31515
+ });
31516
+
31517
+ //#endregion
31518
+ //#region src/cli/commands/agents/push.ts
31519
+ async function pushAgentsAction() {
31520
+ const { agents } = await readProjectConfig();
31521
+ M.info(agents.length === 0 ? "No local agents found - this will delete all remote agents" : `Found ${agents.length} agents to push`);
31522
+ const result = await runTask("Pushing agents to Base44", async () => {
31523
+ return await pushAgents(agents);
31524
+ }, {
31525
+ successMessage: "Agents pushed successfully",
31526
+ errorMessage: "Failed to push agents"
31527
+ });
31528
+ if (result.created.length > 0) M.success(`Created: ${result.created.join(", ")}`);
31529
+ if (result.updated.length > 0) M.success(`Updated: ${result.updated.join(", ")}`);
31530
+ if (result.deleted.length > 0) M.warn(`Deleted: ${result.deleted.join(", ")}`);
31531
+ return {};
31532
+ }
31533
+ const agentsCommand = new Command("agents").description("Manage project agents").addCommand(new Command("push").description("Push local agents to Base44 (replaces all remote agent configs)").action(async () => {
31534
+ await runCommand(pushAgentsAction, { requireAuth: true });
31535
+ })).addCommand(agentsPullCommand);
31536
+
31358
31537
  //#endregion
31359
31538
  //#region src/cli/commands/functions/deploy.ts
31360
31539
  async function deployFunctionsAction() {
@@ -38931,7 +39110,7 @@ const siteDeployCommand = new Command("site").description("Manage site deploymen
38931
39110
 
38932
39111
  //#endregion
38933
39112
  //#region package.json
38934
- var version = "0.0.19";
39113
+ var version = "0.0.21";
38935
39114
 
38936
39115
  //#endregion
38937
39116
  //#region src/cli/program.ts
@@ -38946,6 +39125,7 @@ program.addCommand(dashboardCommand);
38946
39125
  program.addCommand(deployCommand);
38947
39126
  program.addCommand(linkCommand);
38948
39127
  program.addCommand(entitiesPushCommand);
39128
+ program.addCommand(agentsCommand);
38949
39129
  program.addCommand(functionsDeployCommand);
38950
39130
  program.addCommand(siteDeployCommand);
38951
39131
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@base44-preview/cli",
3
- "version": "0.0.19-pr.124.f10d1f3",
3
+ "version": "0.0.21-pr.112.26ce2e2",
4
4
  "description": "Base44 CLI - Unified interface for managing Base44 applications",
5
5
  "type": "module",
6
6
  "bin": {