@wabery/cli 0.19.2 → 0.20.2

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.
@@ -3,7 +3,27 @@ import { z } from "zod";
3
3
  import { WaberyApiClient, WaberyApiError } from "./api-client.js";
4
4
  import { createExampleConfig } from "./config-example.js";
5
5
  import { checkWaberyConnection } from "./diagnostics.js";
6
+ import { executeMetaManagementOperation, META_MANAGEMENT_OPERATIONS, resolveMetaManagementOperation, } from "./meta-business-agent-operations.js";
6
7
  const configSchema = z.record(z.string(), z.unknown());
8
+ const metaSettingsShape = {
9
+ rollout: z.object({ enabled: z.boolean() }).optional(),
10
+ ai_audience: z.enum(["ALLOWLISTED_ONLY", "EVERYONE"]).optional(),
11
+ handoff: z
12
+ .object({
13
+ enabled: z.boolean(),
14
+ message: z.string().optional(),
15
+ message_selection: z.enum(["DEFAULT", "AGENT", "CUSTOM"]).optional(),
16
+ })
17
+ .optional(),
18
+ followup: z
19
+ .object({
20
+ enabled: z.boolean(),
21
+ followup_interval_in_seconds: z.number().int().optional(),
22
+ message: z.string().optional(),
23
+ })
24
+ .optional(),
25
+ never_say_phrases: z.array(z.string()).optional(),
26
+ };
7
27
  const metadataSchema = z.record(z.string(), z.unknown()).optional();
8
28
  const groupIdSchema = z
9
29
  .string()
@@ -525,7 +545,7 @@ OpenAPI: https://api.wabery.com/v1/openapi.json
525
545
  CLI: npm i -g @wabery/cli (https://www.npmjs.com/package/@wabery/cli)
526
546
  MCP: https://mcp.wabery.com
527
547
  Sandbox: shared WhatsApp test number, no Meta setup
528
- Free plan: $0, one Live project, 500 messages, no credit card
548
+ Free plan: $0, one Live project, 1,000 messages, no credit card
529
549
  API keys: create them yourself at https://app.wabery.com/access?tab=api-keys
530
550
  `,
531
551
  },
@@ -579,7 +599,7 @@ REST version is currently scheduled for sunset.
579
599
 
580
600
  Canonical URL: https://wabery.com/pricing.md
581
601
 
582
- Free: $0, 1 Live project, 500 messages, Sandbox, no credit card.
602
+ Free: $0, 1 Live project, 1,000 messages, Sandbox, no credit card.
583
603
  Pro: $15/month for two Live projects and 50K messages.
584
604
  Create API keys yourself at https://app.wabery.com/access?tab=api-keys.
585
605
  `,
@@ -718,6 +738,94 @@ Create API keys yourself at https://app.wabery.com/access?tab=api-keys.
718
738
  throw error;
719
739
  }
720
740
  });
741
+ registerTool("wabery_list_business_agent_operations", {
742
+ title: "Discover Meta management operations",
743
+ description: "Use this when you need to discover documented Meta management operations supported by this client. This is management access for a creator, never customer-facing agent tools. Server authorization and feature availability still apply; local contract coverage is not live verification.",
744
+ inputSchema: {},
745
+ annotations: {
746
+ readOnlyHint: true,
747
+ destructiveHint: false,
748
+ idempotentHint: true,
749
+ openWorldHint: false,
750
+ },
751
+ }, async () => jsonResult({
752
+ operations: META_MANAGEMENT_OPERATIONS,
753
+ live_verified: false,
754
+ }));
755
+ const metaOperationNames = (read) => META_MANAGEMENT_OPERATIONS.filter((item) => (item.method === "GET") === read).map((item) => item.name);
756
+ registerTool("wabery_read_business_agent_operation", {
757
+ title: "Read Meta management data",
758
+ description: "Use this when you need to read a named operation from wabery_list_business_agent_operations. Supply path identifiers in parameters (business_agent_id, connector_id, tool_id, remote_id) and documented filters in query. Connector/tool IDs are Wabery binding IDs; other resource IDs are Meta IDs. This cannot invoke a write or run a tool.",
759
+ inputSchema: {
760
+ operation: z.enum(metaOperationNames(true)),
761
+ parameters: z.record(z.string()).optional(),
762
+ query: z.record(z.union([z.string(), z.number()])).optional(),
763
+ },
764
+ annotations: {
765
+ readOnlyHint: true,
766
+ destructiveHint: false,
767
+ idempotentHint: true,
768
+ openWorldHint: true,
769
+ },
770
+ }, async ({ operation, ...input }) => {
771
+ if (resolveMetaManagementOperation(operation).method !== "GET")
772
+ throw new Error("Read operation required");
773
+ return jsonResult(await executeMetaManagementOperation(client, operation, input));
774
+ });
775
+ registerTool("wabery_write_business_agent_operation", {
776
+ title: "Change Meta management configuration",
777
+ description: "Use this when you need one named management write after explicit creator approval. Parameters contain scoped IDs; body contains the documented Wabery API request. Test/eval/tool-run may cause real backend writes: isolate connectors first. No automatic retries after uncertain writes. For files.upload provide body.file_name and body.file_base64 (up to 1 MiB decoded); use CLI/SDK for larger files. Never provide this management tool to a customer-facing agent.",
778
+ inputSchema: {
779
+ operation: z.enum(metaOperationNames(false)),
780
+ parameters: z.record(z.string()).optional(),
781
+ query: z.record(z.union([z.string(), z.number()])).optional(),
782
+ body: z.record(z.unknown()).optional(),
783
+ operation_id: z
784
+ .string()
785
+ .min(1)
786
+ .max(200)
787
+ .optional()
788
+ .describe("Required caller-owned ID for onboard, settings, and connector mutations."),
789
+ confirmation_token: z
790
+ .string()
791
+ .optional()
792
+ .describe("Required confirmation: meta_management_write"),
793
+ },
794
+ annotations: {
795
+ readOnlyHint: false,
796
+ destructiveHint: true,
797
+ idempotentHint: false,
798
+ openWorldHint: true,
799
+ },
800
+ }, async ({ operation, confirmation_token, operation_id, ...input }) => {
801
+ const blocked = await requireWrite("wabery_write_business_agent_operation", confirmation_token, "meta_management_write");
802
+ if (blocked)
803
+ return blocked;
804
+ if (resolveMetaManagementOperation(operation).method === "GET")
805
+ throw new Error("Write operation required");
806
+ let body = input.body;
807
+ if (operation === "files.upload") {
808
+ const name = input.body?.file_name;
809
+ const encoded = input.body?.file_base64;
810
+ if (typeof name !== "string" ||
811
+ typeof encoded !== "string" ||
812
+ encoded.length > 1_398_104 ||
813
+ !/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(encoded))
814
+ throw new Error("Provide file_name and valid base64 for a file of at most 1 MiB");
815
+ const bytes = Buffer.from(encoded, "base64");
816
+ if (bytes.length > 1_048_576)
817
+ throw new Error("MCP file limit is 1 MiB; use CLI or SDK");
818
+ const form = new FormData();
819
+ form.set("file_name", name);
820
+ form.set("file", new Blob([new Uint8Array(bytes)]), name);
821
+ body = form;
822
+ }
823
+ return jsonResult(await executeMetaManagementOperation(client, operation, {
824
+ ...input,
825
+ body,
826
+ operationId: operation_id,
827
+ }));
828
+ });
721
829
  registerTool("wabery_list_business_agents", {
722
830
  title: "List Meta Business Agents",
723
831
  description: "Use this when you need the selected project's Meta Business Agent records and business_agent_id values. Do not use it for live settings; use wabery_get_business_agent_settings.",
@@ -753,11 +861,8 @@ Create API keys yourself at https://app.wabery.com/access?tab=api-keys.
753
861
  description: "Use this when you need to provision or overwrite Meta Business Agent settings for a channel_id from wabery_list_channels. Prefer wabery_apply_config for reviewed project-wide declarative changes.",
754
862
  inputSchema: {
755
863
  channel_id: z.string().min(1),
756
- enabled: z.boolean().optional(),
757
- persona: z.string().min(1).max(4096).optional(),
758
- language: z.string().min(2).max(16).optional(),
759
- handoff: z.record(z.string(), z.unknown()).optional(),
760
- knowledge: z.record(z.string(), z.unknown()).optional(),
864
+ operation_id: z.string().min(1).max(200),
865
+ ...metaSettingsShape,
761
866
  confirmation_token: z
762
867
  .string()
763
868
  .optional()
@@ -770,11 +875,11 @@ Create API keys yourself at https://app.wabery.com/access?tab=api-keys.
770
875
  openWorldHint: true,
771
876
  },
772
877
  }, async (input) => {
773
- const { confirmation_token, ...body } = input;
878
+ const { confirmation_token, operation_id, ...body } = input;
774
879
  const blocked = await requireWrite("wabery_apply_business_agent", confirmation_token, "apply_business_agent");
775
880
  if (blocked)
776
881
  return blocked;
777
- return jsonResult(await client.put("/business-agents", body));
882
+ return jsonResult(await client.put("/business-agents", body, operation_id));
778
883
  });
779
884
  registerTool("wabery_get_business_agent_settings", {
780
885
  title: "Get Meta Business Agent settings",
@@ -794,11 +899,8 @@ Create API keys yourself at https://app.wabery.com/access?tab=api-keys.
794
899
  description: "Use this when you need to overwrite live Meta settings for a business_agent_id from wabery_list_business_agents. Prefer wabery_apply_business_agent when provisioning by channel.",
795
900
  inputSchema: {
796
901
  business_agent_id: z.string().min(1),
797
- enabled: z.boolean().optional(),
798
- persona: z.string().min(1).max(4096).optional(),
799
- language: z.string().min(2).max(16).optional(),
800
- handoff: z.record(z.string(), z.unknown()).optional(),
801
- knowledge: z.record(z.string(), z.unknown()).optional(),
902
+ operation_id: z.string().min(1).max(200),
903
+ ...metaSettingsShape,
802
904
  confirmation_token: z
803
905
  .string()
804
906
  .optional()
@@ -811,11 +913,11 @@ Create API keys yourself at https://app.wabery.com/access?tab=api-keys.
811
913
  openWorldHint: true,
812
914
  },
813
915
  }, async (input) => {
814
- const { business_agent_id, confirmation_token, ...body } = input;
916
+ const { business_agent_id, confirmation_token, operation_id, ...body } = input;
815
917
  const blocked = await requireWrite("wabery_update_business_agent_settings", confirmation_token, "update_business_agent_settings");
816
918
  if (blocked)
817
919
  return blocked;
818
- return jsonResult(await client.put(`/business-agents/${encodeURIComponent(business_agent_id)}/settings`, body));
920
+ return jsonResult(await client.put(`/business-agents/${encodeURIComponent(business_agent_id)}/settings`, body, operation_id));
819
921
  });
820
922
  registerTool("wabery_list_business_agent_connectors", {
821
923
  title: "List Meta Business Agent connectors",
@@ -837,6 +939,7 @@ Create API keys yourself at https://app.wabery.com/access?tab=api-keys.
837
939
  description: "Use this when you need to create a connector in Meta for a provisioned business_agent_id from wabery_list_business_agents. Prefer wabery_apply_config for reviewed project-wide declarative changes.",
838
940
  inputSchema: {
839
941
  business_agent_id: z.string().min(1),
942
+ operation_id: z.string().min(1).max(200),
840
943
  name: z.string().min(1).max(120),
841
944
  type: z.string().min(1).max(80),
842
945
  config: z.record(z.string(), z.unknown()).optional(),
@@ -853,11 +956,11 @@ Create API keys yourself at https://app.wabery.com/access?tab=api-keys.
853
956
  openWorldHint: true,
854
957
  },
855
958
  }, async (input) => {
856
- const { confirmation_token, ...body } = input;
959
+ const { confirmation_token, operation_id, ...body } = input;
857
960
  const blocked = await requireWrite("wabery_create_business_agent_connector", confirmation_token, "create_business_agent_connector");
858
961
  if (blocked)
859
962
  return blocked;
860
- return jsonResult(await client.post("/business-agents/connectors", body));
963
+ return jsonResult(await client.post("/business-agents/connectors", body, operation_id));
861
964
  });
862
965
  registerTool("wabery_create_business_agent_connector_tool", {
863
966
  title: "Create Meta Business Agent connector tool",
@@ -979,7 +1082,7 @@ Create API keys yourself at https://app.wabery.com/access?tab=api-keys.
979
1082
  });
980
1083
  registerTool("wabery_get_business_agent_thread_control", {
981
1084
  title: "Get Meta Business Agent thread control",
982
- description: "Use this when you need to inspect current WhatsApp thread ownership for a channel_id from wabery_list_channels and contact_id from wabery_list_contacts. Use the set tool for handoff.",
1085
+ description: "Use this when you need Wabery's last observed thread-control state, which may be unknown or stale. Meta does not document an owner GET endpoint. Use channel_id and contact_id from this project; use the set tool for an explicit transition.",
983
1086
  inputSchema: {
984
1087
  channel_id: z.string().min(1),
985
1088
  contact_id: z.string().min(1),
@@ -987,26 +1090,27 @@ Create API keys yourself at https://app.wabery.com/access?tab=api-keys.
987
1090
  thread_id: z.string().min(1).optional(),
988
1091
  },
989
1092
  annotations: {
990
- readOnlyHint: false,
1093
+ readOnlyHint: true,
991
1094
  destructiveHint: false,
992
- idempotentHint: false,
1095
+ idempotentHint: true,
993
1096
  openWorldHint: true,
994
1097
  },
995
- }, async (input) => jsonResult(await client.post("/business-agents/thread-control", {
1098
+ }, async (input) => jsonResult(await client.get("/business-agents/thread-control", {
996
1099
  ...input,
997
- action: "get",
998
1100
  })));
999
1101
  registerTool("wabery_set_business_agent_thread_control", {
1000
1102
  title: "Set Meta Business Agent thread control",
1001
1103
  description: "Use this when you need to take or pass WhatsApp thread control for a channel_id and contact_id, changing automation or human ownership. Inspect first with wabery_get_business_agent_thread_control.",
1002
1104
  inputSchema: {
1003
- action: z.enum(["take", "pass"]),
1105
+ operation_id: z.string().min(1).max(200),
1106
+ action: z.enum(["take", "release", "pass"]),
1004
1107
  channel_id: z.string().min(1),
1005
1108
  contact_id: z.string().min(1),
1006
1109
  business_agent_id: z.string().min(1).optional(),
1007
- thread_id: z.string().min(1).optional(),
1110
+ to: z.string().min(1),
1111
+ pass_to_meta: z.boolean().optional(),
1008
1112
  reason: z.string().max(512).optional(),
1009
- payload: z.record(z.string(), z.unknown()).optional(),
1113
+ metadata: z.string().max(2000).optional(),
1010
1114
  confirmation_token: z
1011
1115
  .string()
1012
1116
  .optional()
@@ -1019,19 +1123,21 @@ Create API keys yourself at https://app.wabery.com/access?tab=api-keys.
1019
1123
  openWorldHint: true,
1020
1124
  },
1021
1125
  }, async (input) => {
1022
- const { confirmation_token, ...body } = input;
1126
+ const { confirmation_token, operation_id, ...body } = input;
1023
1127
  const blocked = await requireWrite("wabery_set_business_agent_thread_control", confirmation_token, "thread_control");
1024
1128
  if (blocked)
1025
1129
  return blocked;
1026
- return jsonResult(await client.post("/business-agents/thread-control", body));
1130
+ return jsonResult(await client.post("/business-agents/thread-control", body, operation_id));
1027
1131
  });
1028
1132
  registerTool("wabery_test_business_agent", {
1029
1133
  title: "Test Meta Business Agent",
1030
1134
  description: "Use this when you need to submit a controlled test scenario to Meta for a business_agent_id from wabery_list_business_agents. This is a remote provider operation, not a read or a real-recipient message send.",
1031
1135
  inputSchema: {
1136
+ operation_id: z.string().min(1).max(200),
1032
1137
  business_agent_id: z.string().min(1),
1033
- input: z.string().min(1).optional(),
1034
- scenario: z.record(z.string(), z.unknown()).optional(),
1138
+ user_msg: z.string().min(1),
1139
+ conversation_id: z.string().min(1).optional(),
1140
+ isolated_connectors: z.literal(true),
1035
1141
  confirmation_token: z
1036
1142
  .string()
1037
1143
  .optional()
@@ -1043,17 +1149,23 @@ Create API keys yourself at https://app.wabery.com/access?tab=api-keys.
1043
1149
  idempotentHint: false,
1044
1150
  openWorldHint: true,
1045
1151
  },
1046
- }, async ({ confirmation_token, ...body }) => {
1152
+ }, async ({ confirmation_token, operation_id, ...body }) => {
1047
1153
  const blocked = await requireWrite("wabery_test_business_agent", confirmation_token, "test_business_agent");
1048
1154
  if (blocked)
1049
1155
  return blocked;
1050
- return jsonResult(await client.post("/business-agents/test", body));
1156
+ return jsonResult(await client.post("/business-agents/test", body, operation_id));
1051
1157
  });
1052
1158
  registerTool("wabery_get_business_agent_eval", {
1053
- title: "Get Meta Business Agent eval summary",
1054
- description: "Use this when you need the live Meta evaluation summary for a business_agent_id from wabery_list_business_agents. Do not use it to run a test scenario.",
1159
+ title: "Read Meta Business Agent evaluation",
1160
+ description: "Use this when you need cases, a job, evaluation details, or summaries. Supply job_id for run, comma-separated eval_id for details, or comma-separated summary_id for summary. This does not start evaluation or invoke tools.",
1055
1161
  inputSchema: {
1056
1162
  business_agent_id: z.string().min(1),
1163
+ operation: z
1164
+ .enum(["cases", "run", "details", "summary"])
1165
+ .default("cases"),
1166
+ job_id: z.string().optional(),
1167
+ eval_id: z.string().optional(),
1168
+ summary_id: z.string().optional(),
1057
1169
  },
1058
1170
  annotations: {
1059
1171
  readOnlyHint: true,
@@ -1061,12 +1173,16 @@ Create API keys yourself at https://app.wabery.com/access?tab=api-keys.
1061
1173
  idempotentHint: true,
1062
1174
  openWorldHint: true,
1063
1175
  },
1064
- }, async ({ business_agent_id }) => jsonResult(await client.get("/business-agents/eval", {
1176
+ }, async ({ business_agent_id, operation, job_id, eval_id, summary_id }) => jsonResult(await client.get("/business-agents/eval", {
1065
1177
  business_agent_id,
1178
+ operation,
1179
+ job_id,
1180
+ eval_id,
1181
+ summary_id,
1066
1182
  })));
1067
1183
  registerTool("wabery_list_business_agent_skills", {
1068
1184
  title: "List Meta Business Agent skills",
1069
- description: "Use this when you need the current Meta skill list for a business_agent_id from wabery_list_business_agents. Use the set tool only to replace the full list.",
1185
+ description: "Use this when you need individual Meta skills and review states. There is no bulk replacement API. Use skills.create/update/delete through the management operation tool.",
1070
1186
  inputSchema: {
1071
1187
  business_agent_id: z.string().min(1),
1072
1188
  },
@@ -1079,28 +1195,31 @@ Create API keys yourself at https://app.wabery.com/access?tab=api-keys.
1079
1195
  }, async ({ business_agent_id }) => jsonResult(await client.get("/business-agents/skills", {
1080
1196
  business_agent_id,
1081
1197
  })));
1082
- registerTool("wabery_set_business_agent_skills", {
1083
- title: "Set Meta Business Agent skills",
1084
- description: "Use this when you need to replace the entire Meta skill list for a business_agent_id from wabery_list_business_agents. Do not use it to append one skill without first preserving existing entries.",
1198
+ registerTool("wabery_create_business_agent_skill", {
1199
+ title: "Create one Meta Business Agent skill",
1200
+ description: "Use this when you need to create one skill without replacing existing skills. Its Meta review status must become active before relying on it.",
1085
1201
  inputSchema: {
1202
+ operation_id: z.string().min(1).max(200),
1086
1203
  business_agent_id: z.string().min(1),
1087
- skills: z.array(z.unknown()),
1204
+ title: z.string().max(64).optional(),
1205
+ description: z.string().max(1024).optional(),
1206
+ skill: z.string().max(20000).optional(),
1088
1207
  confirmation_token: z
1089
1208
  .string()
1090
1209
  .optional()
1091
- .describe("Required when write mode is enabled: set_business_agent_skills"),
1210
+ .describe("Required when write mode is enabled: create_business_agent_skill"),
1092
1211
  },
1093
1212
  annotations: {
1094
1213
  readOnlyHint: false,
1095
- destructiveHint: true,
1096
- idempotentHint: true,
1214
+ destructiveHint: false,
1215
+ idempotentHint: false,
1097
1216
  openWorldHint: true,
1098
1217
  },
1099
- }, async ({ confirmation_token, ...body }) => {
1100
- const blocked = await requireWrite("wabery_set_business_agent_skills", confirmation_token, "set_business_agent_skills");
1218
+ }, async ({ confirmation_token, operation_id, ...body }) => {
1219
+ const blocked = await requireWrite("wabery_create_business_agent_skill", confirmation_token, "create_business_agent_skill");
1101
1220
  if (blocked)
1102
1221
  return blocked;
1103
- return jsonResult(await client.put("/business-agents/skills", body));
1222
+ return jsonResult(await client.post("/business-agents/skills", body, operation_id));
1104
1223
  });
1105
1224
  registerTool("wabery_list_projects", {
1106
1225
  title: "List Wabery projects",