@igoruehara/canvas-flow 0.1.13 → 0.1.14

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/README.md CHANGED
@@ -219,6 +219,21 @@ npx @igoruehara/canvas-flow@latest --home C:\canvas-flow-data --open
219
219
 
220
220
  Tambem e possivel configurar provedores pela propria aplicacao depois que ela estiver rodando. Nesse caso, a configuracao fica salva no MongoDB.
221
221
 
222
+ ## WhatsApp Oficial E Open Source
223
+
224
+ O onboarding da Meta tem dois modos principais:
225
+
226
+ - **Sinergy gerenciado / Coexistence**: usa o preset da Sinergy. Funciona quando
227
+ o onboarding roda por uma URL fixa da Sinergy ou por dominios autorizados no
228
+ app Meta da Sinergy.
229
+ - **Self-hosted / app Meta proprio**: use quando cada usuario hospeda o Canvas
230
+ Flow no proprio dominio. O usuario precisa informar o proprio App ID,
231
+ Configuration ID e App Secret, alem de cadastrar o dominio HTTPS/redirect URI
232
+ no app Meta dele.
233
+
234
+ Use o modo manual quando o cliente ja tiver WABA ID, Phone Number ID e access
235
+ token existentes.
236
+
222
237
  `providers.milvus`: opcional para RAG com Milvus/Zilliz. Milvus local via Docker pode rodar sem token. Milvus remoto normalmente precisa de `token` ou `username/password`.
223
238
 
224
239
  ```json
@@ -19,6 +19,12 @@ const INFRA_COMPOSE_FILE = path.join(PACKAGE_ROOT, 'templates', 'docker-compose.
19
19
  const INFRA_PROJECT_NAME = 'canvas-flow';
20
20
  const INFRA_BASE_SERVICES = ['mongo'];
21
21
  const INFRA_FULL_SERVICES = ['mongo', 'etcd', 'minio', 'milvus'];
22
+ const SINERGY_WHATSAPP_COEXISTENCE_PRESET = {
23
+ embeddedSignupAppId: '617497366521622',
24
+ embeddedSignupConfigId: '1952866105586018',
25
+ embeddedSignupSessionInfoVersion: '3',
26
+ embeddedSignupVersion: 'v3',
27
+ };
22
28
 
23
29
  const STARTUP_BANNER = [
24
30
  ' ______ ________ ',
@@ -318,6 +324,7 @@ function baseConfig() {
318
324
  whatsapp: {
319
325
  provider: 'meta',
320
326
  deliveryMode: 'provider',
327
+ onboardingMode: 'manual',
321
328
  autoReply: true,
322
329
  verifyToken: '',
323
330
  accessToken: '',
@@ -325,6 +332,16 @@ function baseConfig() {
325
332
  wabaId: '',
326
333
  phoneNumberId: '',
327
334
  graphApiVersion: 'v20.0',
335
+ coexistenceEnabled: false,
336
+ syncMessageEchoes: true,
337
+ syncHistory: false,
338
+ embeddedSignupAppId: SINERGY_WHATSAPP_COEXISTENCE_PRESET.embeddedSignupAppId,
339
+ embeddedSignupConfigId: SINERGY_WHATSAPP_COEXISTENCE_PRESET.embeddedSignupConfigId,
340
+ embeddedSignupAppSecret: '',
341
+ embeddedSignupSolutionId: '',
342
+ embeddedSignupFeatureType: '',
343
+ embeddedSignupSessionInfoVersion: SINERGY_WHATSAPP_COEXISTENCE_PRESET.embeddedSignupSessionInfoVersion,
344
+ embeddedSignupVersion: SINERGY_WHATSAPP_COEXISTENCE_PRESET.embeddedSignupVersion,
328
345
  blipContractId: '',
329
346
  blipAuthorizationKey: '',
330
347
  sinchProjectId: '',
@@ -401,6 +418,19 @@ function mergeConfig(defaults, overrides) {
401
418
  return output;
402
419
  }
403
420
 
421
+ function applyWhatsappCoexistenceDefaults(config) {
422
+ const whatsapp = config?.providers?.whatsapp;
423
+ if (!isPlainObject(whatsapp)) return false;
424
+
425
+ let changed = false;
426
+ for (const [key, value] of Object.entries(SINERGY_WHATSAPP_COEXISTENCE_PRESET)) {
427
+ if (String(whatsapp[key] || '').trim()) continue;
428
+ whatsapp[key] = value;
429
+ changed = true;
430
+ }
431
+ return changed;
432
+ }
433
+
404
434
  function writeJson(filePath, value) {
405
435
  fs.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`, 'utf8');
406
436
  }
@@ -439,6 +469,9 @@ function loadConfig(configPath) {
439
469
 
440
470
  const config = mergeConfig(baseConfig(), parsed);
441
471
  let changed = false;
472
+ if (applyWhatsappCoexistenceDefaults(config)) {
473
+ changed = true;
474
+ }
442
475
  if (!config.auth.apiToken) {
443
476
  config.auth.apiToken = randomSecret('cf_master_');
444
477
  changed = true;
@@ -529,6 +562,17 @@ function isLoopbackUrl(value) {
529
562
  }
530
563
  }
531
564
 
565
+ function normalizeProviderName(value) {
566
+ const text = String(value || '').trim().toLowerCase();
567
+ if (text === 'azure' || text === 'azure_openai' || text === 'azure-openai' || text === 'azureopenai') {
568
+ return 'azure';
569
+ }
570
+ if (['openai', 'gemini', 'claude', 'grok', 'bedrock'].includes(text)) {
571
+ return text;
572
+ }
573
+ return 'openai';
574
+ }
575
+
532
576
  function applyEnvironment(config, paths, flags) {
533
577
  const port = Number(flags.port || config.server.port || 3333);
534
578
  const publicUrl = String(flags['public-url'] || config.server.publicUrl || `http://localhost:${port}`).replace(/\/$/, '');
@@ -537,7 +581,7 @@ function applyEnvironment(config, paths, flags) {
537
581
  const claude = config.providers.claude || {};
538
582
  const grok = config.providers.grok || {};
539
583
  const bedrock = config.providers.bedrock || {};
540
- const azureOpenAI = config.providers.azureOpenAI || {};
584
+ const azureOpenAI = config.providers.azureOpenAI || config.providers.azureOpenai || {};
541
585
  const milvus = config.providers.milvus || {};
542
586
  const azureBlob = config.providers.azureBlob || {};
543
587
  const azureSearch = config.providers.azureSearch || {};
@@ -553,6 +597,9 @@ function applyEnvironment(config, paths, flags) {
553
597
  const httpBatch = config.httpBatch || {};
554
598
  const agentOps = config.agentOps || {};
555
599
  const aws = config.aws || {};
600
+ const configuredProvider = normalizeProviderName(openai.provider);
601
+ const azureOpenAIEnabled = configuredProvider === 'azure' || asBool(azureOpenAI.enabled);
602
+ const openaiProvider = azureOpenAIEnabled ? 'azure' : configuredProvider;
556
603
 
557
604
  setEnv('CANVAS_FLOW_HOME', paths.homeDir);
558
605
  setEnv('CANVAS_FLOW_CONFIG_FILE', paths.configPath);
@@ -613,7 +660,7 @@ function applyEnvironment(config, paths, flags) {
613
660
  setEnv('CANVAS_FLOW_MAX_STEP_VISITS', config.runtime.maxStepVisits || 10);
614
661
  setEnv('CANVAS_FLOW_PROVIDER_CACHE_MS', config.runtime.providerCacheMs || 10000);
615
662
 
616
- setEnv('OPENAI_PROVIDER', openai.provider || 'openai');
663
+ setEnv('OPENAI_PROVIDER', openaiProvider);
617
664
  setEnv('LLM_PROVIDER', openai.llmProvider);
618
665
  setEnv('OPENAI_API_KEY', openai.apiKey);
619
666
  setEnv('OPENAI_CHAT_MODEL', openai.chatModel);
@@ -644,7 +691,7 @@ function applyEnvironment(config, paths, flags) {
644
691
  setEnv('BEDROCK_CHAT_MODEL', bedrock.chatModel || 'anthropic.claude-sonnet-4-6');
645
692
  setEnv('BEDROCK_MODEL', bedrock.chatModel || 'anthropic.claude-sonnet-4-6');
646
693
 
647
- setBoolEnv('AZURE_OPENAI_ENABLED', asBool(azureOpenAI.enabled));
694
+ setBoolEnv('AZURE_OPENAI_ENABLED', azureOpenAIEnabled);
648
695
  setEnv('AZURE_OPENAI_API_KEY', azureOpenAI.apiKey);
649
696
  setEnv('AZURE_OPENAI_ENDPOINT', azureOpenAI.endpoint || azureOpenAI.apiBasePath);
650
697
  setEnv('AZURE_OPENAI_API_BASE_PATH', azureOpenAI.apiBasePath || azureOpenAI.endpoint);
@@ -701,6 +748,7 @@ function applyEnvironment(config, paths, flags) {
701
748
 
702
749
  setEnv('WHATSAPP_PROVIDER', whatsapp.provider || 'meta');
703
750
  setEnv('WHATSAPP_DELIVERY_MODE', whatsapp.deliveryMode || 'provider');
751
+ setEnv('WHATSAPP_ONBOARDING_MODE', whatsapp.onboardingMode || 'manual');
704
752
  setBoolEnv('WHATSAPP_AUTO_REPLY', whatsapp.autoReply !== false);
705
753
  setEnv('WHATSAPP_VERIFY_TOKEN', whatsapp.verifyToken);
706
754
  setEnv('WHATSAPP_ACCESS_TOKEN', whatsapp.accessToken);
@@ -708,6 +756,16 @@ function applyEnvironment(config, paths, flags) {
708
756
  setEnv('WHATSAPP_WABA_ID', whatsapp.wabaId || whatsapp.businessAccountId);
709
757
  setEnv('WHATSAPP_PHONE_NUMBER_ID', whatsapp.phoneNumberId);
710
758
  setEnv('WHATSAPP_GRAPH_API_VERSION', whatsapp.graphApiVersion || 'v20.0');
759
+ setBoolEnv('WHATSAPP_COEXISTENCE_ENABLED', whatsapp.coexistenceEnabled === true || whatsapp.onboardingMode === 'coexistence');
760
+ setBoolEnv('WHATSAPP_SYNC_MESSAGE_ECHOES', whatsapp.syncMessageEchoes !== false);
761
+ setBoolEnv('WHATSAPP_SYNC_HISTORY', whatsapp.syncHistory === true);
762
+ setEnv('WHATSAPP_EMBEDDED_SIGNUP_APP_ID', whatsapp.embeddedSignupAppId);
763
+ setEnv('WHATSAPP_EMBEDDED_SIGNUP_CONFIG_ID', whatsapp.embeddedSignupConfigId);
764
+ setEnv('WHATSAPP_EMBEDDED_SIGNUP_APP_SECRET', whatsapp.embeddedSignupAppSecret);
765
+ setEnv('WHATSAPP_EMBEDDED_SIGNUP_SOLUTION_ID', whatsapp.embeddedSignupSolutionId);
766
+ setEnv('WHATSAPP_EMBEDDED_SIGNUP_FEATURE_TYPE', whatsapp.embeddedSignupFeatureType);
767
+ setEnv('WHATSAPP_EMBEDDED_SIGNUP_SESSION_INFO_VERSION', whatsapp.embeddedSignupSessionInfoVersion || '3');
768
+ setEnv('WHATSAPP_EMBEDDED_SIGNUP_VERSION', whatsapp.embeddedSignupVersion);
711
769
  setEnv('BLIP_CONTRACT_ID', whatsapp.blipContractId);
712
770
  setEnv('BLIP_AUTHORIZATION_KEY', whatsapp.blipAuthorizationKey);
713
771
  setEnv('SINCH_PROJECT_ID', whatsapp.sinchProjectId);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@igoruehara/canvas-flow",
3
- "version": "0.1.13",
3
+ "version": "0.1.14",
4
4
  "description": "Standalone npm launcher for Canvas Flow multi-agent GenAI workflows.",
5
5
  "homepage": "https://github.com/igoruehara/canvas-flow#readme",
6
6
  "repository": {