@flowapt/flowiq-cli 0.12.3 → 0.12.4
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 +6 -0
- package/TEAM-GUIDE.md +3 -0
- package/package.json +1 -1
- package/src/commands/report.js +42 -0
- package/src/index.js +19 -1
package/README.md
CHANGED
|
@@ -1310,6 +1310,12 @@ flowiq report deck build <org_id> 2026-08 --refresh # metrics only; statu
|
|
|
1310
1310
|
flowiq report deck narrate <org_id> 2026-08 # copy only (hand edits are kept)
|
|
1311
1311
|
flowiq report deck narrate <org_id> 2026-08 --only changes,action_points # rewrite just these copy fields, keep the rest as written
|
|
1312
1312
|
flowiq report deck check <org_id> 2026-08 # fact-check the copy as shown (hand edits too) against the figures; rewrites nothing
|
|
1313
|
+
flowiq report deck dismiss <org_id> 2026-08 honest_read --note "stands" # keep a flagged sentence as written (recorded)
|
|
1314
|
+
flowiq report deck edit <org_id> 2026-08 honest_read --text "…" # hand-edit one copy field (--clear restores the generated text)
|
|
1315
|
+
flowiq report config <org_id> # the org's report settings
|
|
1316
|
+
flowiq report config <org_id> --set deck.org_type='"non_store"' --set deck.outcome='{"source":"handover","label_singular":"request","label_plural":"requests"}'
|
|
1317
|
+
# settings: deck.org_type, deck.outcome (handover | ticket_status | keyword | tag | link_click), deck.entry_points (in-store QR / ad pre-fills),
|
|
1318
|
+
# deck.agent_display_name, deck.client_display_name, deck.go_live_month, report.email.recipients
|
|
1313
1319
|
flowiq report deck inputs <org_id> 2026-08 --file inputs.json # the super-admin input form
|
|
1314
1320
|
flowiq report deck approve <org_id> 2026-08 # refused until every required input is present
|
|
1315
1321
|
flowiq report deck send <org_id> 2026-08 --test-to me@flowapt.com # one test copy, status untouched
|
package/TEAM-GUIDE.md
CHANGED
|
@@ -275,6 +275,9 @@ several.
|
|
|
275
275
|
| See whether a client deck can be approved, and what is still missing | `flowiq report deck status <org_id> 2026-08` |
|
|
276
276
|
| Rewrite one part of a deck's copy without touching the rest (e.g. the changes column and action points) | `flowiq report deck narrate <org_id> 2026-08 --only changes,suggested_updates,action_points` |
|
|
277
277
|
| Check a deck's wording against its figures before it goes out (e.g. a heading that says a group "leads" when it does not) | `flowiq report deck check <org_id> 2026-08` — lists each unsupported statement with a fix; rewrites nothing |
|
|
278
|
+
| A fact-check flag is wrong and the sentence should stay | `flowiq report deck dismiss <org_id> 2026-08 <field> --note "why"` (or Inputs → Fact check → Keep as written) |
|
|
279
|
+
| Change the wording of one part of a deck from the terminal | `flowiq report deck edit <org_id> 2026-08 <field> --text "…"` (`--clear` puts the generated text back) |
|
|
280
|
+
| See or change a client's report settings (in-person "win", till QR codes, recipients, names) | `flowiq report config <org_id>` to see; `--set deck.outcome='{…}'`, `--set deck.entry_points='[…]'`, `--set report.email.recipients='["a@b.co"]'` to change |
|
|
278
281
|
| Send yourself a test copy of a client deck (PDF from flowiq@flowapt.com) | `flowiq report deck send <org_id> 2026-08 --test-to you@flowapt.com` — status untouched |
|
|
279
282
|
| Take a tile, pill or card off a client deck (and its PDF) for one month | On `/reporting/deck` open **Inputs** (the rail beside the slides) → Show or hide; or `flowiq report deck inputs <org_id> 2026-08 --file inputs.json` with `{ "hidden": { "tile:tail": true } }` |
|
|
280
283
|
| Approve a client deck / send it to the client | `flowiq report deck approve <org_id> 2026-08` then `… send … --client` (or let the 09:00 SAST schedule send it on the 5th) |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flowapt/flowiq-cli",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.4",
|
|
4
4
|
"description": "Command-line tool for FlowIQ staff: round-trip agent prompts, questionnaires, fine-tuning, pin-board tasks, webhooks, templates, agent-updates, chat exports, and live agent testing without ever touching service-role credentials.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
package/src/commands/report.js
CHANGED
|
@@ -95,6 +95,48 @@ function printClaims(issues) {
|
|
|
95
95
|
for (const i of issues) console.log(` ${i.path}: "${i.quote}" (${i.why}) → ${i.fix}`);
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
+
export async function config(orgId, opts) {
|
|
99
|
+
if (!orgId) { console.error("Give the organization id."); process.exit(1); }
|
|
100
|
+
const pairs = opts.set ?? [];
|
|
101
|
+
let r;
|
|
102
|
+
try {
|
|
103
|
+
if (!pairs.length) r = await http.get("report", { organization_id: orgId, config: 1 });
|
|
104
|
+
else {
|
|
105
|
+
const set = {};
|
|
106
|
+
for (const p of pairs) {
|
|
107
|
+
const i = p.indexOf("=");
|
|
108
|
+
if (i < 1) { console.error(`--set needs path=value (got "${p}")`); process.exit(1); }
|
|
109
|
+
const raw = p.slice(i + 1);
|
|
110
|
+
let v; try { v = JSON.parse(raw); } catch { v = raw; }
|
|
111
|
+
set[p.slice(0, i)] = v;
|
|
112
|
+
}
|
|
113
|
+
if (opts.dryRun) { console.log(JSON.stringify({ would_set: set }, null, 2)); return; }
|
|
114
|
+
r = await http.post("report", { organization_id: orgId, action: "config_set", set });
|
|
115
|
+
}
|
|
116
|
+
} catch (e) { console.error(`Config failed: ${e.message}`); process.exit(1); }
|
|
117
|
+
if (opts.json) { console.log(JSON.stringify(r, null, 2)); return; }
|
|
118
|
+
if (r.before) for (const [k, v] of Object.entries(r.after)) console.log(`${k}: ${JSON.stringify(r.before[k])} → ${JSON.stringify(v)}`);
|
|
119
|
+
else for (const [k, v] of Object.entries(r.config)) console.log(`${k}: ${JSON.stringify(v)}`);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export async function dismiss(orgId, month, path, opts) {
|
|
123
|
+
requireArgs(orgId, month);
|
|
124
|
+
const r = await post("dismiss_claim", orgId, month, { path, ...(opts.quote ? { quote: opts.quote } : {}), ...(opts.note ? { note: opts.note } : {}) }, "Dismiss");
|
|
125
|
+
if (opts.json) { console.log(JSON.stringify(r, null, 2)); return; }
|
|
126
|
+
console.log(`Kept as written: ${r.dismissed} fact-check flag${r.dismissed === 1 ? "" : "s"} on ${path}`);
|
|
127
|
+
if (r.status) console.log(` status: ${r.status}${r.missing?.length ? ` · needed: ${r.missing.join(" · ")}` : ""}`);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export async function edit(orgId, month, path, opts) {
|
|
131
|
+
requireArgs(orgId, month);
|
|
132
|
+
const text = opts.clear ? "" : opts.text;
|
|
133
|
+
if (typeof text !== "string") { console.error("Give --text \"…\" (or --clear to put the generated wording back)."); process.exit(1); }
|
|
134
|
+
const r = await post("save_override", orgId, month, { path, text }, "Edit");
|
|
135
|
+
if (opts.json) { console.log(JSON.stringify(r, null, 2)); return; }
|
|
136
|
+
console.log(r.cleared ? `Generated wording restored on ${path}` : `Saved your wording on ${path}`);
|
|
137
|
+
if (r.status) console.log(` status: ${r.status}${r.missing?.length ? ` · needed: ${r.missing.join(" · ")}` : ""}`);
|
|
138
|
+
}
|
|
139
|
+
|
|
98
140
|
export async function generate(orgId, month, opts) {
|
|
99
141
|
requireArgs(orgId, month);
|
|
100
142
|
const r = await post("generate", orgId, month, { refresh: !!opts.refresh, force: !!opts.force }, "Generate");
|
package/src/index.js
CHANGED
|
@@ -365,7 +365,7 @@ export function run(argv) {
|
|
|
365
365
|
.action((orgId, opts) => hoursCmd.packageClear(orgId, opts));
|
|
366
366
|
|
|
367
367
|
// report deck — the monthly client deck (build / copy / approve / send)
|
|
368
|
-
const report = program.command("report").description("Client reporting: the monthly
|
|
368
|
+
const report = program.command("report").description("Client reporting: the monthly client deck (a cover and five slides) and its settings");
|
|
369
369
|
const deck = report.command("deck").description("The monthly client deck for one org and month (/reporting/deck)");
|
|
370
370
|
deck.command("status <organization_id> <month>")
|
|
371
371
|
.description("What exists for the month, the workflow status and what still blocks approval")
|
|
@@ -385,6 +385,24 @@ export function run(argv) {
|
|
|
385
385
|
.description("Fact-check the copy as the slides show it (hand edits included) against the month's figures; rewrites nothing")
|
|
386
386
|
.option("--json", "raw JSON output")
|
|
387
387
|
.action((orgId, month, opts) => reportCmd.check(orgId, month, opts));
|
|
388
|
+
report.command("config <organization_id>")
|
|
389
|
+
.description("Show or change an org's report settings: deck.org_type, deck.outcome, deck.entry_points, deck.agent_display_name, deck.client_display_name, deck.go_live_month, report.email.recipients")
|
|
390
|
+
.option("--set <path=json>", "a setting to change, JSON value (repeatable), e.g. --set deck.org_type='\"non_store\"'", (v, acc) => [...acc, v], [])
|
|
391
|
+
.option("--dry-run", "print what would be set")
|
|
392
|
+
.option("--json", "raw JSON output")
|
|
393
|
+
.action((orgId, opts) => reportCmd.config(orgId, opts));
|
|
394
|
+
deck.command("dismiss <organization_id> <month> <path>")
|
|
395
|
+
.description("Keep a sentence as written: drop the fact-check flag(s) on one copy field (who and when are recorded)")
|
|
396
|
+
.option("--quote <words>", "only the flag quoting these words (default: every open flag on the field)")
|
|
397
|
+
.option("--note <text>", "why it stands")
|
|
398
|
+
.option("--json", "raw JSON output")
|
|
399
|
+
.action((orgId, month, path, opts) => reportCmd.dismiss(orgId, month, path, opts));
|
|
400
|
+
deck.command("edit <organization_id> <month> <path>")
|
|
401
|
+
.description("Hand-edit one copy field (e.g. honest_read, plan.agent_upgrades); shows on the slide as an edit with your name")
|
|
402
|
+
.option("--text <text>", "the new wording")
|
|
403
|
+
.option("--clear", "put the generated wording back")
|
|
404
|
+
.option("--json", "raw JSON output")
|
|
405
|
+
.action((orgId, month, path, opts) => reportCmd.edit(orgId, month, path, opts));
|
|
388
406
|
deck.command("generate <organization_id> <month>")
|
|
389
407
|
.description("Build the metrics (if missing, or --refresh) and write the copy")
|
|
390
408
|
.option("--refresh", "rebuild the metrics first")
|