@todoforai/cli 0.1.51 → 0.1.52
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/dist/todoforai-cli.js +69 -107
- package/package.json +1 -1
package/dist/todoforai-cli.js
CHANGED
|
@@ -42884,29 +42884,26 @@ class ApiClient {
|
|
|
42884
42884
|
setDeviceWallpaperMode(id, mode) {
|
|
42885
42885
|
return this.request("POST", `/api/v1/devices/${id}/wallpaper-mode`, { id, mode });
|
|
42886
42886
|
}
|
|
42887
|
-
|
|
42888
|
-
return this.request("GET",
|
|
42887
|
+
getBusinessContext(projectId) {
|
|
42888
|
+
return this.request("GET", `/api/v1/projects/${projectId}/business-context`);
|
|
42889
42889
|
}
|
|
42890
|
-
createBusinessContext(name) {
|
|
42891
|
-
return this.request("POST",
|
|
42890
|
+
createBusinessContext(projectId, name) {
|
|
42891
|
+
return this.request("POST", `/api/v1/projects/${projectId}/business-context`, { projectId, name });
|
|
42892
42892
|
}
|
|
42893
|
-
renameBusinessContext(
|
|
42894
|
-
return this.request("PUT", `/api/v1/business-context
|
|
42893
|
+
renameBusinessContext(projectId, name) {
|
|
42894
|
+
return this.request("PUT", `/api/v1/projects/${projectId}/business-context`, { projectId, name });
|
|
42895
42895
|
}
|
|
42896
|
-
|
|
42897
|
-
return this.request("
|
|
42896
|
+
listVoiceSources(projectId) {
|
|
42897
|
+
return this.request("GET", `/api/v1/projects/${projectId}/voice-sources`);
|
|
42898
42898
|
}
|
|
42899
|
-
|
|
42900
|
-
return this.request("
|
|
42899
|
+
collectVoiceSource(projectId, channel, opts) {
|
|
42900
|
+
return this.request("POST", "/api/v1/business-context/collect-voice-source", { projectId, channel, ...opts });
|
|
42901
42901
|
}
|
|
42902
|
-
|
|
42903
|
-
return this.request("POST", "/api/v1/business-context/
|
|
42902
|
+
removeVoiceSource(projectId, channel, opts = {}) {
|
|
42903
|
+
return this.request("POST", "/api/v1/business-context/remove-voice-source", { projectId, channel, ...opts });
|
|
42904
42904
|
}
|
|
42905
|
-
|
|
42906
|
-
return this.request("POST", "/api/v1/business-context/
|
|
42907
|
-
}
|
|
42908
|
-
refineBrandVoice(businessContextId, answers, source, correction) {
|
|
42909
|
-
return this.request("POST", "/api/v1/business-context/refine-brand-voice", { businessContextId, answers, ...source && { source }, ...correction && { correction } });
|
|
42905
|
+
refineBrandVoice(projectId, source, correction) {
|
|
42906
|
+
return this.request("POST", "/api/v1/business-context/refine-brand-voice", { projectId, ...source && { source }, ...correction && { correction } });
|
|
42910
42907
|
}
|
|
42911
42908
|
getProfile() {
|
|
42912
42909
|
return this.request("GET", "/api/v1/users/profile");
|
|
@@ -43450,7 +43447,7 @@ var TodoStatus;
|
|
|
43450
43447
|
TodoStatus2["DELETED"] = "DELETED";
|
|
43451
43448
|
})(TodoStatus ||= {});
|
|
43452
43449
|
// ../packages/shared-fbe/src/models.ts
|
|
43453
|
-
var DEFAULT_MODEL = "anthropic:anthropic/claude-opus-5";
|
|
43450
|
+
var DEFAULT_MODEL = "anthropic:anthropic/claude-opus-5.5";
|
|
43454
43451
|
var MODEL_ALIASES = {
|
|
43455
43452
|
claude: DEFAULT_MODEL
|
|
43456
43453
|
};
|
|
@@ -43742,7 +43739,7 @@ var SERVER_TO_FRONTENDS = {
|
|
|
43742
43739
|
updated: (projectId) => `${"project:surfaces_updated" /* PROJECT_SURFACES_UPDATED */}:${projectId}`
|
|
43743
43740
|
},
|
|
43744
43741
|
killSwitch: {
|
|
43745
|
-
changed: (projectId) => `${"project:kill_switch" /* KILL_SWITCH */}:${projectId}`
|
|
43742
|
+
changed: (projectId, userId) => `${"project:kill_switch" /* KILL_SWITCH */}:${projectId}${privateSuffix(userId)}`
|
|
43746
43743
|
},
|
|
43747
43744
|
sandbox: {
|
|
43748
43745
|
state: (userId) => `${"sandbox:state" /* SANDBOX_STATE */}:${userId}`
|
|
@@ -44354,6 +44351,8 @@ var model_promos_default = {
|
|
|
44354
44351
|
{ family: "gpt-5-5(-pro)?", rate: 0.8, starts: "2026-09-14", ends: "2026-11-21" },
|
|
44355
44352
|
{ family: "gpt-5-6-sol", rate: 0.85, starts: "2026-08-26", ends: "2026-09-13" },
|
|
44356
44353
|
{ family: "gpt-5-6-sol", rate: 0.8, starts: "2026-09-14", ends: "2026-11-21" },
|
|
44354
|
+
{ family: "gpt-6-sol", rate: 0.8, starts: "2026-09-22", ends: "2026-11-21" },
|
|
44355
|
+
{ family: "gpt-6-luna", rate: 0.8, starts: "2026-09-22", ends: "2026-11-21" },
|
|
44357
44356
|
{ family: "gpt-6-astra", rate: 0.85, starts: "2026-09-05", ends: "2026-09-13", boostable: false },
|
|
44358
44357
|
{ family: "gpt-6-astra", rate: 0.8, starts: "2026-09-14", ends: "2026-11-21", boostable: false },
|
|
44359
44358
|
{ family: "gpt-5-6-terra", rate: 0.85, starts: "2026-06-29", ends: "2026-09-13" },
|
|
@@ -44410,7 +44409,7 @@ var TOPICS = {
|
|
|
44410
44409
|
audience: "frontend"
|
|
44411
44410
|
},
|
|
44412
44411
|
["project:kill_switch" /* KILL_SWITCH */]: {
|
|
44413
|
-
channel: (p) => SERVER_TO_FRONTENDS.killSwitch.changed(p.projectId),
|
|
44412
|
+
channel: (p) => SERVER_TO_FRONTENDS.killSwitch.changed(p.projectId, p.userId),
|
|
44414
44413
|
audience: "frontend"
|
|
44415
44414
|
},
|
|
44416
44415
|
["sandbox:state" /* SANDBOX_STATE */]: {
|
|
@@ -44549,7 +44548,7 @@ import { parseArgs } from "util";
|
|
|
44549
44548
|
// package.json
|
|
44550
44549
|
var package_default = {
|
|
44551
44550
|
name: "@todoforai/cli",
|
|
44552
|
-
version: "0.1.
|
|
44551
|
+
version: "0.1.52",
|
|
44553
44552
|
type: "module",
|
|
44554
44553
|
bin: {
|
|
44555
44554
|
"todoforai-cli": "bin/todoforai-cli.js",
|
|
@@ -44607,7 +44606,7 @@ Examples:
|
|
|
44607
44606
|
tfa-cli agent list|get|update|create … # Agents (update <agent> model=…)
|
|
44608
44607
|
tfa-cli todo set <todo-id|-> title=… group=… star=true # Edit a todo's fields
|
|
44609
44608
|
tfa-cli project list|set|settings|groups|default|agent … # Projects; edit the current one
|
|
44610
|
-
tfa-cli brand
|
|
44609
|
+
tfa-cli brand [show|create|rename|voice …] # The project's brand page + voice learning
|
|
44611
44610
|
tfa-cli device list|rename|wallpaper … # Paired machines
|
|
44612
44611
|
tfa-cli list [-n 30] [--cursor N] [--all] [--status S] # List todos (paginated)
|
|
44613
44612
|
tfa-cli status <todo-id> <STATUS> # Update a todo's status
|
|
@@ -44724,8 +44723,6 @@ function parseCliArgs() {
|
|
|
44724
44723
|
card: { type: "string" },
|
|
44725
44724
|
link: { type: "boolean", default: false },
|
|
44726
44725
|
direction: { type: "string" },
|
|
44727
|
-
"business-context": { type: "string" },
|
|
44728
|
-
brand: { type: "string" },
|
|
44729
44726
|
url: { type: "string" },
|
|
44730
44727
|
"pasted-file": { type: "string" },
|
|
44731
44728
|
"from-company": { type: "boolean", default: false },
|
|
@@ -47839,7 +47836,6 @@ Fields (PUT /todos/{id}):
|
|
|
47839
47836
|
star true|false (starredAt now / 0)
|
|
47840
47837
|
schedule unix ms timestamp, 0 = immediate (alias: scheduledTimestamp)
|
|
47841
47838
|
agent agentSettingsId (alias: agentSettingsId)
|
|
47842
|
-
brand businessContextId (alias: businessContextId)
|
|
47843
47839
|
public true|false — refused from an agent shell (isPublic)
|
|
47844
47840
|
|
|
47845
47841
|
tfa-cli todo message <todo-id|-> <message-id> <field=value>…
|
|
@@ -47861,7 +47857,7 @@ tfa-cli project — edit the current project
|
|
|
47861
47857
|
|
|
47862
47858
|
Usage:
|
|
47863
47859
|
tfa-cli project list Projects you can access (* = default)
|
|
47864
|
-
tfa-cli project set <field=value>… name=… description=…
|
|
47860
|
+
tfa-cli project set <field=value>… name=… description=…
|
|
47865
47861
|
(isPublic refused from an agent shell)
|
|
47866
47862
|
tfa-cli project default Make it the project you land on at /
|
|
47867
47863
|
tfa-cli project agent <agent> Default agent for new todos in this project
|
|
@@ -47888,10 +47884,9 @@ var TODO_ALIASES = {
|
|
|
47888
47884
|
group: "groupTag",
|
|
47889
47885
|
schedule: "scheduledTimestamp",
|
|
47890
47886
|
agent: "agentSettingsId",
|
|
47891
|
-
brand: "businessContextId",
|
|
47892
47887
|
public: "isPublic"
|
|
47893
47888
|
};
|
|
47894
|
-
var PROJECT_ALIASES = {
|
|
47889
|
+
var PROJECT_ALIASES = {};
|
|
47895
47890
|
function fail(msg) {
|
|
47896
47891
|
process.stderr.write(`${RED}${msg}${RESET}
|
|
47897
47892
|
`);
|
|
@@ -48074,18 +48069,17 @@ async function projectCommand(api, positionals, args) {
|
|
|
48074
48069
|
}
|
|
48075
48070
|
function printBrandHelp() {
|
|
48076
48071
|
process.stderr.write(`
|
|
48077
|
-
tfa-cli brand —
|
|
48072
|
+
tfa-cli brand — the project's brand page and its learned writing voice
|
|
48078
48073
|
|
|
48074
|
+
The project IS the brand. --project <id> or $TODOFORAI_PROJECT_ID selects it.
|
|
48079
48075
|
The brand page text itself is a file: read/write todoforai:business-context.
|
|
48080
|
-
These commands manage the contexts and the voice learned for them.
|
|
48081
48076
|
|
|
48082
48077
|
Usage:
|
|
48083
|
-
tfa-cli brand
|
|
48084
|
-
tfa-cli brand create <name>
|
|
48085
|
-
tfa-cli brand rename <
|
|
48086
|
-
tfa-cli brand select <brand|none> Active brand for the account
|
|
48078
|
+
tfa-cli brand [show] This project's brand (none = personal board)
|
|
48079
|
+
tfa-cli brand create <name> Give the project a brand page (empty .md); the board turns business
|
|
48080
|
+
tfa-cli brand rename <name>
|
|
48087
48081
|
tfa-cli brand voice Learned profile + sources
|
|
48088
|
-
tfa-cli brand voice answers [<q>=<a>…] Show / set the
|
|
48082
|
+
tfa-cli brand voice answers [<q>=<a>…] Show / set the Manual source: answers to the style questions
|
|
48089
48083
|
tfa-cli brand voice collect <channel> [--url U | --pasted-file <F|-> | --max N]
|
|
48090
48084
|
Add a writing sample source.
|
|
48091
48085
|
On this device (signed-in CLI, reply pairs):
|
|
@@ -48099,9 +48093,7 @@ Usage:
|
|
|
48099
48093
|
tfa-cli brand voice correct "<what is off>" Tell the learner what it got wrong; profile is updated
|
|
48100
48094
|
in one pass and the correction is kept for every re-learn
|
|
48101
48095
|
|
|
48102
|
-
|
|
48103
|
-
selected brand unless --brand <id|name> is given (--pasted-file - reads stdin).
|
|
48104
|
-
Delete / reset are UI-only.
|
|
48096
|
+
--pasted-file - reads stdin. Delete is UI-only.
|
|
48105
48097
|
|
|
48106
48098
|
Questions the UI asks (keys for 'answers'):
|
|
48107
48099
|
"What makes you different from competitors?"
|
|
@@ -48109,43 +48101,30 @@ Questions the UI asks (keys for 'answers'):
|
|
|
48109
48101
|
"A frustrated customer says things aren't working. How do you reply?"
|
|
48110
48102
|
`);
|
|
48111
48103
|
}
|
|
48112
|
-
|
|
48113
|
-
const
|
|
48114
|
-
if (!
|
|
48115
|
-
|
|
48116
|
-
|
|
48117
|
-
return sel;
|
|
48118
|
-
if (contexts.length === 1)
|
|
48119
|
-
return contexts[0];
|
|
48120
|
-
fail("No brand selected — pass --brand <id|name> or 'tfa-cli brand select'");
|
|
48121
|
-
}
|
|
48122
|
-
const q = query.toLowerCase();
|
|
48123
|
-
const exact = contexts.find((c3) => c3.id === query || c3.name.toLowerCase() === q);
|
|
48124
|
-
if (exact)
|
|
48125
|
-
return exact;
|
|
48126
|
-
const partial = contexts.filter((c3) => c3.id.startsWith(query) || c3.name.toLowerCase().includes(q));
|
|
48127
|
-
if (partial.length === 1)
|
|
48128
|
-
return partial[0];
|
|
48129
|
-
fail(partial.length ? `Ambiguous brand '${query}'` : `No brand matching '${query}'`);
|
|
48104
|
+
function requireProject(args) {
|
|
48105
|
+
const projectId = args.project || getEnv2("PROJECT_ID");
|
|
48106
|
+
if (!projectId)
|
|
48107
|
+
fail("No project — pass --project <id> or set TODOFORAI_PROJECT_ID");
|
|
48108
|
+
return projectId;
|
|
48130
48109
|
}
|
|
48131
48110
|
async function brandCommand(api, positionals, args) {
|
|
48132
48111
|
const [, sub, ...rest] = positionals;
|
|
48133
|
-
|
|
48134
|
-
|
|
48135
|
-
const
|
|
48112
|
+
const projectId = requireProject(args);
|
|
48113
|
+
if (!sub || sub === "show") {
|
|
48114
|
+
const brand = await api.getBusinessContext(projectId);
|
|
48136
48115
|
if (args.json) {
|
|
48137
|
-
console.log(JSON.stringify(
|
|
48116
|
+
console.log(JSON.stringify(brand, null, 2));
|
|
48138
48117
|
return;
|
|
48139
48118
|
}
|
|
48140
|
-
|
|
48141
|
-
|
|
48119
|
+
process.stderr.write(brand ? `${brand.name} ${DIM}${brand.id}${RESET}
|
|
48120
|
+
` : `${DIM}(personal board — no brand)${RESET}
|
|
48142
48121
|
`);
|
|
48143
48122
|
return;
|
|
48144
48123
|
}
|
|
48145
48124
|
if (sub === "create") {
|
|
48146
48125
|
if (!rest[0])
|
|
48147
48126
|
fail("Usage: tfa-cli brand create <name>");
|
|
48148
|
-
const c3 = await api.createBusinessContext(rest[0]);
|
|
48127
|
+
const c3 = await api.createBusinessContext(projectId, rest[0]);
|
|
48149
48128
|
if (args.json) {
|
|
48150
48129
|
console.log(JSON.stringify(c3, null, 2));
|
|
48151
48130
|
return;
|
|
@@ -48155,25 +48134,15 @@ async function brandCommand(api, positionals, args) {
|
|
|
48155
48134
|
return;
|
|
48156
48135
|
}
|
|
48157
48136
|
if (sub === "rename") {
|
|
48158
|
-
if (!rest[1])
|
|
48159
|
-
fail("Usage: tfa-cli brand rename <brand> <name>");
|
|
48160
|
-
const c3 = await resolveBrand(api, rest[0]);
|
|
48161
|
-
await api.renameBusinessContext(c3.id, rest[1]);
|
|
48162
|
-
process.stderr.write(`${GREEN}✅ renamed to ${rest[1]}${RESET}
|
|
48163
|
-
`);
|
|
48164
|
-
return;
|
|
48165
|
-
}
|
|
48166
|
-
if (sub === "select") {
|
|
48167
48137
|
if (!rest[0])
|
|
48168
|
-
fail("Usage: tfa-cli brand
|
|
48169
|
-
|
|
48170
|
-
|
|
48171
|
-
process.stderr.write(`${GREEN}✅ selected brand: ${id ?? "none"}${RESET}
|
|
48138
|
+
fail("Usage: tfa-cli brand rename <name>");
|
|
48139
|
+
await api.renameBusinessContext(projectId, rest[0]);
|
|
48140
|
+
process.stderr.write(`${GREEN}✅ renamed to ${rest[0]}${RESET}
|
|
48172
48141
|
`);
|
|
48173
48142
|
return;
|
|
48174
48143
|
}
|
|
48175
48144
|
if (sub === "voice")
|
|
48176
|
-
return voiceCommand(api, rest, args);
|
|
48145
|
+
return voiceCommand(api, projectId, rest, args);
|
|
48177
48146
|
fail(`Unknown 'brand' subcommand: ${sub}`);
|
|
48178
48147
|
}
|
|
48179
48148
|
function dryCollect(channel, max) {
|
|
@@ -48227,26 +48196,30 @@ async function voiceDeviceCommand(rest, args) {
|
|
|
48227
48196
|
}
|
|
48228
48197
|
return false;
|
|
48229
48198
|
}
|
|
48230
|
-
async function voiceCommand(api, rest, args) {
|
|
48199
|
+
async function voiceCommand(api, projectId, rest, args) {
|
|
48231
48200
|
const [verb, ...vargs] = rest;
|
|
48232
48201
|
if (verb === "collect" && !vargs[0])
|
|
48233
|
-
fail("Usage: tfa-cli brand voice collect <channel> [--url U | --pasted-file F|- | --max N] [--dry-run]");
|
|
48234
|
-
const
|
|
48202
|
+
fail("Usage: tfa-cli brand voice collect <channel> [--url U | --pasted-file F|- | --account <page-id> | --max N] [--dry-run]");
|
|
48203
|
+
const brand = await api.getBusinessContext(projectId);
|
|
48204
|
+
if (!brand)
|
|
48205
|
+
fail("This project has no brand — 'tfa-cli brand create <name>' first");
|
|
48235
48206
|
if (verb === "answers") {
|
|
48207
|
+
const { sources } = await api.listVoiceSources(projectId);
|
|
48208
|
+
const manual = sources.find((s) => s.channel === "Manual");
|
|
48209
|
+
const answers = Object.fromEntries((manual?.items ?? []).filter((x) => x?.prompt).map((x) => [x.prompt, x.text]));
|
|
48236
48210
|
if (vargs.length) {
|
|
48237
|
-
const
|
|
48211
|
+
for (const a of vargs) {
|
|
48238
48212
|
const i = a.indexOf("=");
|
|
48239
48213
|
if (i < 1)
|
|
48240
48214
|
fail(`Expected question=answer, got '${a}'`);
|
|
48241
|
-
|
|
48242
|
-
}
|
|
48243
|
-
const
|
|
48244
|
-
await api.
|
|
48215
|
+
answers[a.slice(0, i)] = a.slice(i + 1);
|
|
48216
|
+
}
|
|
48217
|
+
const samples = Object.entries(answers).filter(([, t]) => t.trim()).map(([prompt, text]) => ({ prompt, text }));
|
|
48218
|
+
await api.collectVoiceSource(projectId, "Manual", { samples });
|
|
48245
48219
|
process.stderr.write(`${GREEN}✅ ${vargs.length} answer(s) saved${RESET}
|
|
48246
48220
|
`);
|
|
48247
48221
|
return;
|
|
48248
48222
|
}
|
|
48249
|
-
const answers = onboarding.styleAnswers ?? {};
|
|
48250
48223
|
if (args.json) {
|
|
48251
48224
|
console.log(JSON.stringify(answers, null, 2));
|
|
48252
48225
|
return;
|
|
@@ -48257,10 +48230,8 @@ async function voiceCommand(api, rest, args) {
|
|
|
48257
48230
|
`);
|
|
48258
48231
|
return;
|
|
48259
48232
|
}
|
|
48260
|
-
const brand = await resolveBrand(api, args.brand, (await api.getProfile()).user?.selectedBusinessContextId);
|
|
48261
48233
|
if (!verb || verb === "show") {
|
|
48262
|
-
const profile =
|
|
48263
|
-
const { sources } = await api.listVoiceSources(brand.id);
|
|
48234
|
+
const { sources, profile } = await api.listVoiceSources(projectId);
|
|
48264
48235
|
if (args.json) {
|
|
48265
48236
|
console.log(JSON.stringify({ brand, profile, sources }, null, 2));
|
|
48266
48237
|
return;
|
|
@@ -48273,7 +48244,7 @@ ${DIM}match ${profile.match}/100 · source ${profile.source}${RESET}
|
|
|
48273
48244
|
` : `${DIM}(no voice learned yet)${RESET}
|
|
48274
48245
|
`);
|
|
48275
48246
|
for (const s of sources)
|
|
48276
|
-
process.stderr.write(` ${s.channel} ${DIM}${s.posts ?? "?"} posts · ${s.chars ?? "?"} chars${RESET}
|
|
48247
|
+
process.stderr.write(` ${s.channel}${s.account ? ` ${s.label} ${DIM}(${s.account})${RESET}` : ""} ${DIM}${s.posts ?? "?"} posts · ${s.chars ?? "?"} chars${RESET}
|
|
48277
48248
|
`);
|
|
48278
48249
|
return;
|
|
48279
48250
|
}
|
|
@@ -48294,20 +48265,20 @@ ${DIM}match ${profile.match}/100 · source ${profile.source}${RESET}
|
|
|
48294
48265
|
const { samples, note } = collectChannel(channel, Number(args.max ?? 40));
|
|
48295
48266
|
if (!samples.length)
|
|
48296
48267
|
fail(`${channel}: nothing usable came back${note ? ` (${note})` : ""}`);
|
|
48297
|
-
const { sources: sources2 } = await api.collectVoiceSource(
|
|
48268
|
+
const { sources: sources2 } = await api.collectVoiceSource(projectId, channel, { samples });
|
|
48298
48269
|
process.stderr.write(`${GREEN}✅ ${channel}: ${samples.length} reply pairs stored (${sources2.length} source(s))${RESET}
|
|
48299
48270
|
`);
|
|
48300
48271
|
return;
|
|
48301
48272
|
}
|
|
48302
|
-
const { sources } = await api.collectVoiceSource(
|
|
48273
|
+
const { sources } = await api.collectVoiceSource(projectId, channel, { url: args.url, pasted, account: args.account });
|
|
48303
48274
|
process.stderr.write(`${GREEN}✅ ${channel} collected (${sources.length} source(s))${RESET}
|
|
48304
48275
|
`);
|
|
48305
48276
|
return;
|
|
48306
48277
|
}
|
|
48307
48278
|
if (verb === "remove") {
|
|
48308
48279
|
if (!vargs[0])
|
|
48309
|
-
fail("Usage: tfa-cli brand voice remove <channel>");
|
|
48310
|
-
await api.removeVoiceSource(
|
|
48280
|
+
fail("Usage: tfa-cli brand voice remove <channel> [--account <id>] (no --account: every source of the channel)");
|
|
48281
|
+
await api.removeVoiceSource(projectId, vargs[0], args.account ? { account: args.account } : { all: true });
|
|
48311
48282
|
process.stderr.write(`${GREEN}✅ ${vargs[0]} removed${RESET}
|
|
48312
48283
|
`);
|
|
48313
48284
|
return;
|
|
@@ -48315,14 +48286,9 @@ ${DIM}match ${profile.match}/100 · source ${profile.source}${RESET}
|
|
|
48315
48286
|
if (verb === "learn") {
|
|
48316
48287
|
process.stderr.write(`${DIM}learning voice for ${brand.name}…${RESET}
|
|
48317
48288
|
`);
|
|
48318
|
-
const res = await api.refineBrandVoice(
|
|
48289
|
+
const res = await api.refineBrandVoice(projectId, args["from-company"] ? "company" : undefined);
|
|
48319
48290
|
if (!res.profile)
|
|
48320
48291
|
fail("Nothing to learn from — add answers or collect a source first");
|
|
48321
|
-
const { [brand.id]: _stale, ...styleAiAnswers } = onboarding.styleAiAnswers ?? {};
|
|
48322
|
-
await api.patchOnboarding({
|
|
48323
|
-
voiceProfiles: { ...onboarding.voiceProfiles ?? {}, [brand.id]: { ...res, updatedAt: Date.now() } },
|
|
48324
|
-
styleAiAnswers
|
|
48325
|
-
});
|
|
48326
48292
|
if (args.json) {
|
|
48327
48293
|
console.log(JSON.stringify(res, null, 2));
|
|
48328
48294
|
return;
|
|
@@ -48336,16 +48302,13 @@ ${res.profile}
|
|
|
48336
48302
|
const text = vargs.join(" ").trim();
|
|
48337
48303
|
if (!text)
|
|
48338
48304
|
fail('Usage: tfa-cli brand voice correct "<what is off>"');
|
|
48339
|
-
|
|
48340
|
-
if (!stored?.profile)
|
|
48305
|
+
if (!(await api.listVoiceSources(projectId)).profile?.profile)
|
|
48341
48306
|
fail("No voice learned yet — 'tfa-cli brand voice learn' first");
|
|
48342
48307
|
process.stderr.write(`${DIM}applying correction…${RESET}
|
|
48343
48308
|
`);
|
|
48344
|
-
const res = await api.refineBrandVoice(
|
|
48309
|
+
const res = await api.refineBrandVoice(projectId, undefined, text);
|
|
48345
48310
|
if (!res.profile)
|
|
48346
48311
|
fail("The correction pass returned nothing — try rewording it");
|
|
48347
|
-
const { [brand.id]: _stale, ...styleAiAnswers } = onboarding.styleAiAnswers ?? {};
|
|
48348
|
-
await api.patchOnboarding({ voiceProfiles: { ...onboarding.voiceProfiles ?? {}, [brand.id]: { ...res, updatedAt: Date.now() } }, styleAiAnswers });
|
|
48349
48312
|
if (args.json) {
|
|
48350
48313
|
console.log(JSON.stringify(res, null, 2));
|
|
48351
48314
|
return;
|
|
@@ -73382,7 +73345,6 @@ Cancelled by user (Ctrl+C)
|
|
|
73382
73345
|
...args.title ? { title: args.title } : {},
|
|
73383
73346
|
...args.note ? { note: args.note } : {},
|
|
73384
73347
|
...priority ? { priority } : {},
|
|
73385
|
-
...args["business-context"] ? { businessContextId: args["business-context"] } : {},
|
|
73386
73348
|
...args.group ? { group: args.group } : {},
|
|
73387
73349
|
...args["group-name"] ? { groupName: args["group-name"] } : {},
|
|
73388
73350
|
...args["group-description"] ? { groupDescription: args["group-description"] } : {}
|
|
@@ -73451,7 +73413,7 @@ Cancelled by user (Ctrl+C)
|
|
|
73451
73413
|
const res = await fetch(`${apiUrl}${restBasePath(apiKey)}/projects/${projectId2}/recommendations/generate`, {
|
|
73452
73414
|
method: "POST",
|
|
73453
73415
|
headers: { "content-type": "application/json", "x-api-key": apiKey },
|
|
73454
|
-
body: JSON.stringify({ projectId: projectId2, ...
|
|
73416
|
+
body: JSON.stringify({ projectId: projectId2, ...direction ? { direction } : {} }),
|
|
73455
73417
|
signal: AbortSignal.timeout(30000)
|
|
73456
73418
|
});
|
|
73457
73419
|
const text = await res.text();
|