@igoruehara/canvas-flow 0.1.12 → 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 +15 -0
- package/bin/canvas-flow.js +113 -3
- package/package.json +1 -1
- package/public/assets/index-BUVXJRGV.js +767 -0
- package/public/assets/{index-PCQkqMUe.css → index-D-m2588h.css} +1 -1
- package/public/index.html +2 -2
- package/server/provider-config/provider-config-controller.d.ts +35 -0
- package/server/provider-config/provider-config-controller.js +15 -0
- package/server/provider-config/provider-config-controller.js.map +1 -1
- package/server/provider-config/provider-config-service.d.ts +54 -0
- package/server/provider-config/provider-config-service.js +251 -11
- package/server/provider-config/provider-config-service.js.map +1 -1
- package/server/queue/sqs-transition-service.js +6 -0
- package/server/queue/sqs-transition-service.js.map +1 -1
- package/server/rag/rag-service.d.ts +4 -2
- package/server/rag/rag-service.js +44 -25
- package/server/rag/rag-service.js.map +1 -1
- package/server/runner/runner-controller.d.ts +8 -0
- package/server/runner/runner-service.d.ts +20 -0
- package/server/runner/runner-service.js +295 -13
- package/server/runner/runner-service.js.map +1 -1
- package/templates/config.example.json +11 -0
- package/templates/config.production.example.json +11 -0
- package/public/assets/index-CAYKh0bn.js +0 -767
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
|
package/bin/canvas-flow.js
CHANGED
|
@@ -19,6 +19,62 @@ 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
|
+
};
|
|
28
|
+
|
|
29
|
+
const STARTUP_BANNER = [
|
|
30
|
+
' ______ ________ ',
|
|
31
|
+
' / ____/___ _____ _ ______ ______/ ____/ /___ _ __ ',
|
|
32
|
+
" / / / __ '/ __ \\ | / / __ '/ ___/ /_ / / __ \\ | /| / / ",
|
|
33
|
+
'/ /___/ /_/ / / / / |/ / /_/ (__ ) __/ / / /_/ / |/ |/ / ',
|
|
34
|
+
'\\____/\\__,_/_/ /_/|___/\\__,_/____/_/ /_/\\____/|__/|__/ ',
|
|
35
|
+
].join('\n');
|
|
36
|
+
|
|
37
|
+
function envFlagEnabled(name) {
|
|
38
|
+
return ['1', 'true', 'yes', 'sim', 'on'].includes(String(process.env[name] || '').trim().toLowerCase());
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function shouldUseAnsiColor() {
|
|
42
|
+
if (process.env.NO_COLOR) return false;
|
|
43
|
+
return Boolean(process.stdout.isTTY || process.env.FORCE_COLOR);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function colorAnsi(text, code) {
|
|
47
|
+
return shouldUseAnsiColor() ? `\x1b[${code}m${text}\x1b[0m` : text;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function shouldPrintStartupBanner(flags = {}) {
|
|
51
|
+
if (flags.banner === false || envFlagEnabled('CANVAS_FLOW_NO_BANNER')) return false;
|
|
52
|
+
if (process.env.CI && !envFlagEnabled('CANVAS_FLOW_BANNER')) return false;
|
|
53
|
+
return Boolean(process.stdout.isTTY || envFlagEnabled('CANVAS_FLOW_BANNER'));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function boxLine(text, width = 74) {
|
|
57
|
+
const safeText = String(text || '').slice(0, width - 4);
|
|
58
|
+
return `| ${safeText.padEnd(width - 4, ' ')} |`;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function printStartupBanner(flags = {}) {
|
|
62
|
+
if (!shouldPrintStartupBanner(flags)) return;
|
|
63
|
+
|
|
64
|
+
const border = '+'.padEnd(75, '-') + '+';
|
|
65
|
+
const box = [
|
|
66
|
+
border,
|
|
67
|
+
boxLine('Canvas Flow standalone runtime'),
|
|
68
|
+
boxLine('Tip: use --with-docker for local Mongo, or --full for Mongo + Milvus.'),
|
|
69
|
+
boxLine('Docs: https://igoruehara.github.io/canvas-flow/'),
|
|
70
|
+
border,
|
|
71
|
+
].join('\n');
|
|
72
|
+
|
|
73
|
+
console.log('');
|
|
74
|
+
console.log(colorAnsi(STARTUP_BANNER.trimEnd(), '95'));
|
|
75
|
+
console.log(colorAnsi(box, '36'));
|
|
76
|
+
console.log('');
|
|
77
|
+
}
|
|
22
78
|
|
|
23
79
|
function printHelp() {
|
|
24
80
|
console.log(`
|
|
@@ -44,6 +100,7 @@ Options:
|
|
|
44
100
|
--public-url <url> Override server.publicUrl
|
|
45
101
|
--open Open the browser after starting
|
|
46
102
|
--no-open Do not open the browser
|
|
103
|
+
--no-banner Do not print the startup banner
|
|
47
104
|
--with-docker Start local Docker infrastructure before Canvas Flow
|
|
48
105
|
--full Include Milvus, MinIO and etcd with Docker infrastructure
|
|
49
106
|
--show Show config content with "init" or "config"
|
|
@@ -267,6 +324,7 @@ function baseConfig() {
|
|
|
267
324
|
whatsapp: {
|
|
268
325
|
provider: 'meta',
|
|
269
326
|
deliveryMode: 'provider',
|
|
327
|
+
onboardingMode: 'manual',
|
|
270
328
|
autoReply: true,
|
|
271
329
|
verifyToken: '',
|
|
272
330
|
accessToken: '',
|
|
@@ -274,6 +332,16 @@ function baseConfig() {
|
|
|
274
332
|
wabaId: '',
|
|
275
333
|
phoneNumberId: '',
|
|
276
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,
|
|
277
345
|
blipContractId: '',
|
|
278
346
|
blipAuthorizationKey: '',
|
|
279
347
|
sinchProjectId: '',
|
|
@@ -350,6 +418,19 @@ function mergeConfig(defaults, overrides) {
|
|
|
350
418
|
return output;
|
|
351
419
|
}
|
|
352
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
|
+
|
|
353
434
|
function writeJson(filePath, value) {
|
|
354
435
|
fs.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`, 'utf8');
|
|
355
436
|
}
|
|
@@ -388,6 +469,9 @@ function loadConfig(configPath) {
|
|
|
388
469
|
|
|
389
470
|
const config = mergeConfig(baseConfig(), parsed);
|
|
390
471
|
let changed = false;
|
|
472
|
+
if (applyWhatsappCoexistenceDefaults(config)) {
|
|
473
|
+
changed = true;
|
|
474
|
+
}
|
|
391
475
|
if (!config.auth.apiToken) {
|
|
392
476
|
config.auth.apiToken = randomSecret('cf_master_');
|
|
393
477
|
changed = true;
|
|
@@ -478,6 +562,17 @@ function isLoopbackUrl(value) {
|
|
|
478
562
|
}
|
|
479
563
|
}
|
|
480
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
|
+
|
|
481
576
|
function applyEnvironment(config, paths, flags) {
|
|
482
577
|
const port = Number(flags.port || config.server.port || 3333);
|
|
483
578
|
const publicUrl = String(flags['public-url'] || config.server.publicUrl || `http://localhost:${port}`).replace(/\/$/, '');
|
|
@@ -486,7 +581,7 @@ function applyEnvironment(config, paths, flags) {
|
|
|
486
581
|
const claude = config.providers.claude || {};
|
|
487
582
|
const grok = config.providers.grok || {};
|
|
488
583
|
const bedrock = config.providers.bedrock || {};
|
|
489
|
-
const azureOpenAI = config.providers.azureOpenAI || {};
|
|
584
|
+
const azureOpenAI = config.providers.azureOpenAI || config.providers.azureOpenai || {};
|
|
490
585
|
const milvus = config.providers.milvus || {};
|
|
491
586
|
const azureBlob = config.providers.azureBlob || {};
|
|
492
587
|
const azureSearch = config.providers.azureSearch || {};
|
|
@@ -502,6 +597,9 @@ function applyEnvironment(config, paths, flags) {
|
|
|
502
597
|
const httpBatch = config.httpBatch || {};
|
|
503
598
|
const agentOps = config.agentOps || {};
|
|
504
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;
|
|
505
603
|
|
|
506
604
|
setEnv('CANVAS_FLOW_HOME', paths.homeDir);
|
|
507
605
|
setEnv('CANVAS_FLOW_CONFIG_FILE', paths.configPath);
|
|
@@ -562,7 +660,7 @@ function applyEnvironment(config, paths, flags) {
|
|
|
562
660
|
setEnv('CANVAS_FLOW_MAX_STEP_VISITS', config.runtime.maxStepVisits || 10);
|
|
563
661
|
setEnv('CANVAS_FLOW_PROVIDER_CACHE_MS', config.runtime.providerCacheMs || 10000);
|
|
564
662
|
|
|
565
|
-
setEnv('OPENAI_PROVIDER',
|
|
663
|
+
setEnv('OPENAI_PROVIDER', openaiProvider);
|
|
566
664
|
setEnv('LLM_PROVIDER', openai.llmProvider);
|
|
567
665
|
setEnv('OPENAI_API_KEY', openai.apiKey);
|
|
568
666
|
setEnv('OPENAI_CHAT_MODEL', openai.chatModel);
|
|
@@ -593,7 +691,7 @@ function applyEnvironment(config, paths, flags) {
|
|
|
593
691
|
setEnv('BEDROCK_CHAT_MODEL', bedrock.chatModel || 'anthropic.claude-sonnet-4-6');
|
|
594
692
|
setEnv('BEDROCK_MODEL', bedrock.chatModel || 'anthropic.claude-sonnet-4-6');
|
|
595
693
|
|
|
596
|
-
setBoolEnv('AZURE_OPENAI_ENABLED',
|
|
694
|
+
setBoolEnv('AZURE_OPENAI_ENABLED', azureOpenAIEnabled);
|
|
597
695
|
setEnv('AZURE_OPENAI_API_KEY', azureOpenAI.apiKey);
|
|
598
696
|
setEnv('AZURE_OPENAI_ENDPOINT', azureOpenAI.endpoint || azureOpenAI.apiBasePath);
|
|
599
697
|
setEnv('AZURE_OPENAI_API_BASE_PATH', azureOpenAI.apiBasePath || azureOpenAI.endpoint);
|
|
@@ -650,6 +748,7 @@ function applyEnvironment(config, paths, flags) {
|
|
|
650
748
|
|
|
651
749
|
setEnv('WHATSAPP_PROVIDER', whatsapp.provider || 'meta');
|
|
652
750
|
setEnv('WHATSAPP_DELIVERY_MODE', whatsapp.deliveryMode || 'provider');
|
|
751
|
+
setEnv('WHATSAPP_ONBOARDING_MODE', whatsapp.onboardingMode || 'manual');
|
|
653
752
|
setBoolEnv('WHATSAPP_AUTO_REPLY', whatsapp.autoReply !== false);
|
|
654
753
|
setEnv('WHATSAPP_VERIFY_TOKEN', whatsapp.verifyToken);
|
|
655
754
|
setEnv('WHATSAPP_ACCESS_TOKEN', whatsapp.accessToken);
|
|
@@ -657,6 +756,16 @@ function applyEnvironment(config, paths, flags) {
|
|
|
657
756
|
setEnv('WHATSAPP_WABA_ID', whatsapp.wabaId || whatsapp.businessAccountId);
|
|
658
757
|
setEnv('WHATSAPP_PHONE_NUMBER_ID', whatsapp.phoneNumberId);
|
|
659
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);
|
|
660
769
|
setEnv('BLIP_CONTRACT_ID', whatsapp.blipContractId);
|
|
661
770
|
setEnv('BLIP_AUTHORIZATION_KEY', whatsapp.blipAuthorizationKey);
|
|
662
771
|
setEnv('SINCH_PROJECT_ID', whatsapp.sinchProjectId);
|
|
@@ -1266,6 +1375,7 @@ async function waitForMongo(config, flags, paths, progress) {
|
|
|
1266
1375
|
}
|
|
1267
1376
|
|
|
1268
1377
|
async function start(flags) {
|
|
1378
|
+
printStartupBanner(flags);
|
|
1269
1379
|
const progress = createStartupProgress();
|
|
1270
1380
|
let startupStatus;
|
|
1271
1381
|
try {
|
package/package.json
CHANGED