@flowapt/flowiq-cli 0.9.7 → 0.9.9

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/src/index.js CHANGED
@@ -96,6 +96,7 @@ export function run(argv) {
96
96
  prompts.command("pull <organization_id>")
97
97
  .description("Fetch an agent's prompt_sections into a local JSON file (default: active agent)")
98
98
  .option("--agent <id>", "target a specific agent instead of the org's active one")
99
+ .option("--out <file>", "write the JSON here instead of .flowiq/prompts/<slug>.json")
99
100
  .action((orgId, opts) => promptsCmd.pull(orgId, opts));
100
101
  prompts.command("history <organization_id>")
101
102
  .description("Every recorded prompt push (who / when / size) — the version list for `restore`")
@@ -381,8 +382,10 @@ export function run(argv) {
381
382
  .requiredOption("--request-file <path>", "JSON file with template_request (+ optional template_data/media_header/cards_media)")
382
383
  .action((orgId, opts) => templatesCmd.create(orgId, opts));
383
384
  templates.command("status <organization_id>")
384
- .description("List the org's template rows (name + status) to poll Meta approval")
385
+ .description("Template status: FlowIQ's record by default, or straight from Meta with --live (incl. rejection reasons)")
385
386
  .option("--name <substr>", "filter by template name substring")
387
+ .option("--live", "read Meta directly (one cheap call with --name; no snapshot file written)")
388
+ .option("--watch", "with --live: re-check every 15 s until every match is decided (max 15 min)")
386
389
  .action((orgId, opts) => templatesCmd.status(orgId, opts));
387
390
  templates.command("show <organization_id> <name>")
388
391
  .description("Render ONE template row in full — including a DRAFT, which `pull` cannot see (drafts never reach Meta)")
@@ -514,12 +517,27 @@ export function run(argv) {
514
517
  .option("--model <model>", "settings.model (e.g. gpt-6-luna, the house default)")
515
518
  .option("--reasoning-effort <level>", "settings.reasoning_effort — low|medium|high|xhigh|max (\"\" clears it; max = GPT-6 and Claude only); pairs with reasoning models (e.g. gpt-6-luna + high, gpt-6-luna + high, claude-sonnet-5 + medium)")
516
519
  .option("--rename <name>", "rename the agent")
517
- .option("--tool <flag=bool>", "toggle a tool flag (repeatable): woo_order_build/woo_tip_field/woo_order_note_field/view_cart_tool/restock_tool/block_tool_status/postal_code_tool_status/shopify_products_web_chat/ticket_tool_status/product_lookup/email_request_tool/collapse_product_variants", agentConfigCmd.collectTool, [])
520
+ .option("--tool <flag=bool>", "toggle a tool flag (repeatable): woo_order_build/woo_tip_field/woo_order_note_field/view_cart_tool/restock_tool/block_tool_status/postal_code_tool_status/shopify_products_web_chat/ticket_tool_status/product_lookup/email_request_tool/collapse_product_variants/silent_option", agentConfigCmd.collectTool, [])
518
521
  .option("--discount [bool]", "agent.discount.enabled (true if bare)")
519
522
  .option("--test-contact-number <number>", "settings.test_contact_number — the contact `flowiq test` uses (use a FAKE number; \"\" clears it → synthetic fallback)")
520
523
  .option("--test-contact-name <name>", "settings.test_contact_name — display name for the test contact (\"\" clears it)")
521
524
  .option("--disable-base-tool <name>", "hide a disableable built-in tool from this agent (repeatable)", agentConfigCmd.collectToolName, [])
522
525
  .option("--enable-base-tool <name>", "restore a previously disabled built-in tool (repeatable)", agentConfigCmd.collectToolName, [])
526
+ .option("--tool-instruction <tool=text>", "settings.tool_instructions: text APPENDED to that tool's description (repeatable; text or @file; \"tool=\" removes it)", agentConfigCmd.collectTool, [])
527
+ .option("--shorten-links <channel=on|off|default>", "per-channel link shortening (repeatable): whatsapp/web/messenger/instagram/tiktok/email/call; default = on for whatsapp only", agentConfigCmd.collectTool, [])
528
+ .option("--email-from-name <name>", "settings.email_from_name: the From display name on agent emails (\"\" clears)")
529
+ .option("--email-signature-name <name>", "settings.email_signature_name: name printed in the email signature (\"\" clears → agent name)")
530
+ .option("--email-signature-title <title>", "settings.email_signature_title: title line under the signature name (\"\" clears)")
531
+ .option("--email-request-to <addresses>", "settings.email_request.to: comma-separated recipients for email_request_to_team (\"\" clears)")
532
+ .option("--email-request-subject-prefix <text>", "settings.email_request.subject_prefix (\"\" clears)")
533
+ .option("--send-success-rule <when=text>", "send_message_success_instructions rule, one per condition: media/image/video/document/audio/text/always (repeatable; text or @file; \"when=\" removes it)", agentConfigCmd.collectTool, [])
534
+ .option("--send-success [bool]", "send_message_success_instructions.enabled (true if bare)")
535
+ .option("--after-escalation <text>", "human_notify.success_instructions: the NEXT STEP appended to the handover tool's reply (text or @file; \"\" clears)")
536
+ .option("--knowledge <pairs>", "knowledge_config: enabled=true,match_count=8,min_similarity=0.3 (\"default\" clears a key)")
537
+ .option("--human-notify <json>", "merge keys into human_notify (JSON or @file.json; null deletes a key; unknown keys refused)")
538
+ .option("--order-notify <json>", "merge keys into order_notify (JSON or @file.json; null deletes a key; unknown keys refused)")
539
+ .option("--full", "show long values in full (show mode and the before/after diff)")
540
+ .option("--json", "show mode: print the raw response as JSON")
523
541
  .action((orgId, opts) => agentConfigCmd.config(orgId, opts));
524
542
 
525
543
  // agent-updates (pending client change-requests + chat context; pull + resolve)
@@ -563,11 +581,11 @@ export function run(argv) {
563
581
  .description("List local agent-updates snapshots")
564
582
  .action(() => agentUpdatesCmd.list());
565
583
  au.command("resolve <update_id>")
566
- .description("Flip a client-raised ticket to resolved/declined + write the client-facing note (the client reads \"FlowIQ: <note>\")")
584
+ .description("Flip a client-raised ticket to resolved/declined (or back to in_progress) + write the client-facing note (the client reads \"FlowIQ: <note>\")")
567
585
  .option("--note <text>", "client-facing note (required when resolving)")
568
586
  .option("--internal <text>", "staff-only note (never shown to the client)")
569
587
  .option("--image <url>", "client-facing response image URL")
570
- .option("--status <status>", "resolved (default) | declined", "resolved")
588
+ .option("--status <status>", "resolved (default) | declined | in_progress (open, fix not yet proven; note optional)", "resolved")
571
589
  .option("--yes", "skip the interactive confirm gate (the --note requirement still applies)")
572
590
  .action((updateId, opts) => agentUpdatesCmd.resolve(updateId, opts));
573
591
 
@@ -646,7 +664,9 @@ export function run(argv) {
646
664
  .description("Maintainers: planned | in_progress | done | declined | duplicate. Closing emails everyone who reported or hit it")
647
665
  .requiredOption("--to <status>", "open | planned | in_progress | done | declined | duplicate")
648
666
  .option("--note <text>", "what shipped / why not (required for done + declined; the people who asked read it)")
649
- .option("--version <x.y.z>", "the CLI version the fix shipped in (done)")
667
+ // Not --version: the root program owns that flag, so it printed the CLI version
668
+ // and exited before anything was sent (found closing 27 requests, 1 Oct 2026).
669
+ .option("--fixed-in <x.y.z>", "the CLI version the fix shipped in (done)")
650
670
  .option("--of <number>", "with --to duplicate: the request this one duplicates (hits move across)")
651
671
  .option("--no-notify", "close without emailing the people who asked")
652
672
  .option("--json", "print the raw response")
@@ -662,9 +682,10 @@ export function run(argv) {
662
682
  .option("--agent <id>", "scope to one agent")
663
683
  .option("--target <id>", "scope to one target (task id, tool name, tag, broadcast id)")
664
684
  .option("--user <substr>", "filter by staff email (substring)")
665
- .option("--since <date>", "YYYY-MM-DD or ISO")
666
- .option("--until <date>", "YYYY-MM-DD or ISO")
667
- .option("--limit <n>", "max entries (default 50, max 200)")
685
+ .option("--since <when>", "YYYY-MM-DD (SAST day start), ISO, or a window: 14d / 12h / 2w")
686
+ .option("--until <when>", "YYYY-MM-DD, ISO, or a window: 14d / 12h / 2w")
687
+ .option("--before <created_at>", "page back: only entries older than this (the listing prints the value to use)")
688
+ .option("--limit <n>", "max entries (default 50, max 200; above 200 is clamped and the total is shown)")
668
689
  .option("--json", "raw JSON")
669
690
  .action((orgId, opts) => auditCmd.list(orgId, opts));
670
691
  audit.command("show <audit_id>")
@@ -695,11 +716,13 @@ export function run(argv) {
695
716
  .option("--image <url>", "attach a publicly-fetchable image URL (text is the caption)")
696
717
  .option("--timeout <ms>", "per-turn HTTP timeout (default 120000)")
697
718
  .option("--json", "print raw JSON instead of the transcript")
719
+ .option("--force", "go ahead even though the test contact had real (non-web) messages in the last 6 h")
698
720
  .action((orgId, message, opts) => testCmd.send(orgId, message, opts));
699
721
  test.command("scenario <organization_id> <file>")
700
722
  .description("Run a scenario pack (JSON: {scenarios:[{id,title,turns:[{text,expect?,expectNot?}]}]})")
701
723
  .option("--agent <id>", "test a specific agent")
702
724
  .option("--no-clear-between", "do NOT clear between scenarios (one long thread)")
725
+ .option("--force", "go ahead even though the test contact had real (non-web) messages in the last 6 h")
703
726
  .option("--sender <name>", "senderName")
704
727
  .option("--timeout <ms>", "per-turn HTTP timeout (default 120000)")
705
728
  .option("--json", "print raw JSON results")
@@ -708,6 +731,7 @@ export function run(argv) {
708
731
  .description("Run the bundled generic smoke pack")
709
732
  .option("--agent <id>", "test a specific agent")
710
733
  .option("--no-clear-between", "do NOT clear between scenarios")
734
+ .option("--force", "go ahead even though the test contact had real (non-web) messages in the last 6 h")
711
735
  .option("--sender <name>", "senderName")
712
736
  .option("--timeout <ms>", "per-turn HTTP timeout")
713
737
  .option("--json", "print raw JSON results")
@@ -715,6 +739,7 @@ export function run(argv) {
715
739
  test.command("clear <organization_id>")
716
740
  .description("Clear the test conversation (hide history via memory_cutoff)")
717
741
  .option("--agent <id>", "target a specific agent's test contact")
742
+ .option("--force", "go ahead even though the test contact had real (non-web) messages in the last 6 h")
718
743
  .action((orgId, opts) => testCmd.clear(orgId, opts));
719
744
  test.command("stress <organization_id> [pack]")
720
745
  .description("Run an adversarial pack in parallel, one isolated contact per scenario (phase 2)")
@@ -870,10 +895,11 @@ export function run(argv) {
870
895
  .option("--limit <n>", "how many to show (default 25, max 200)")
871
896
  .option("--template <substr>", "filter: template_name contains this (case-insensitive)")
872
897
  .option("--since <date>", "filter: created on/after this date, e.g. 2026-07-01")
898
+ .option("--min-recipients <n>", "filter: only sends to at least N recipients (2 hides welcomes and cart reminders)")
873
899
  .option("--json", "raw JSON")
874
900
  .action((orgId, opts) => broadcastCmd.listRemote(orgId, opts));
875
901
  broadcast.command("status <organization_id> <broadcast_id>")
876
- .description("Live delivery counts (read/delivered/sent/failed) for a broadcast by its broadcastId — e.g. from a --python fire-and-forget send")
902
+ .description("Live delivery counts (read/delivered/sent/failed) for a broadcast by its broadcastId, plus what it sent (slot values, button code and the link's destination)")
877
903
  .option("--failures", "also list each FAILED recipient + the Meta error reason (makes a python send auditable)")
878
904
  .option("--limit <n>", "with --failures: how many failed rows to print", "40")
879
905
  .option("--json", "raw JSON")
@@ -951,6 +977,7 @@ export function run(argv) {
951
977
  .option("--content <value>", "utm_content, the per-link tag (e.g. ViewMore); defaults to the campaign")
952
978
  .option("--date <value>", "send date for the campaign tag when it is not today: 9Sep | 2026-09-24 | 24/9/2026")
953
979
  .option("--raw-campaign", "use --campaign exactly as typed, bypassing the Date_Campaign normalisation")
980
+ .option("--new-campaign", "confirm the tag is a NEW campaign even though a differently spelled one with the same name already runs")
954
981
  .option("--domain <host>", "short domain: chatcart.io (default) | linklnk.io | yapi.store")
955
982
  .option("--commit", "actually mint the links (omit = dry-run preview)")
956
983
  .option("--json", "raw JSON output")