@todoforai/cli 0.1.52 → 0.1.54
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 +34 -35
- package/package.json +1 -1
package/dist/todoforai-cli.js
CHANGED
|
@@ -42875,6 +42875,9 @@ class ApiClient {
|
|
|
42875
42875
|
setDefaultProject(projectId) {
|
|
42876
42876
|
return this.request("POST", "/api/v1/users/default-project", { projectId });
|
|
42877
42877
|
}
|
|
42878
|
+
updateProjectSettings(projectId, settings) {
|
|
42879
|
+
return this.request("PUT", `/api/v1/settings/projects/${projectId}`, { projectId, settings });
|
|
42880
|
+
}
|
|
42878
42881
|
setProjectDefaultAgent(projectId, agentSettingsId) {
|
|
42879
42882
|
return this.request("POST", "/api/v1/users/project-agent-mapping", { projectId, agentSettingsId });
|
|
42880
42883
|
}
|
|
@@ -43809,6 +43812,17 @@ var SERVER_TO_FRONTENDS = {
|
|
|
43809
43812
|
function_call_request: (userId) => `${"FUNCTION_CALL_REQUEST_AGENT" /* FUNCTION_CALL_REQUEST_AGENT */}:frontend:${userId}`
|
|
43810
43813
|
}
|
|
43811
43814
|
};
|
|
43815
|
+
// ../packages/shared-fbe/src/REST_types.ts
|
|
43816
|
+
var MANUAL_CHANNEL = "Manual";
|
|
43817
|
+
function manualAnswersOf(sources) {
|
|
43818
|
+
const manual = sources?.find((s) => s.channel === MANUAL_CHANNEL);
|
|
43819
|
+
const out = {};
|
|
43820
|
+
for (const x of manual?.items ?? [])
|
|
43821
|
+
if (typeof x !== "string" && x.prompt)
|
|
43822
|
+
out[x.prompt] = x.text;
|
|
43823
|
+
return out;
|
|
43824
|
+
}
|
|
43825
|
+
var manualSamples = (answers) => Object.entries(answers).filter(([, a]) => a.trim()).map(([prompt, text]) => ({ prompt, text: text.trim() }));
|
|
43812
43826
|
// ../packages/shared-fbe/src/templateBody.ts
|
|
43813
43827
|
var USER_HEADINGS = new Set([
|
|
43814
43828
|
"your task",
|
|
@@ -44266,7 +44280,6 @@ Exactly ONE \`api_recommend_template\` call per proposal: it carries both what t
|
|
|
44266
44280
|
It runs in-process and needs no machine or shell. Never shell out to \`todoregistry-cli\` or \`todoforai-cli\` for this.
|
|
44267
44281
|
|
|
44268
44282
|
3. Propose only todos you genuinely believe fit this business, highest priority first. There is no quota: a weak card costs the user more than no card, so if you can't find good ones, propose fewer or none and say why. Favour the trivial, high-probability moves for this company, the strategic directions its owner would nod at instantly, alongside any cleverer bets. Then reply with a one-line summary per proposal grouped by workstream, and tell the user they're waiting on the board for review (or, if you proposed none, what you'd need to make a confident recommendation).`,
|
|
44269
|
-
mcpConfigs: {},
|
|
44270
44283
|
edgesMcpConfigs: {},
|
|
44271
44284
|
permissions: {
|
|
44272
44285
|
allow: [
|
|
@@ -44289,7 +44302,6 @@ var JARVIS_AGENT = {
|
|
|
44289
44302
|
ownerId: "SYSTEM",
|
|
44290
44303
|
systemMessage: "",
|
|
44291
44304
|
model: "",
|
|
44292
|
-
mcpConfigs: {},
|
|
44293
44305
|
edgesMcpConfigs: {},
|
|
44294
44306
|
createdAt: 0,
|
|
44295
44307
|
updatedAt: 0
|
|
@@ -44299,7 +44311,6 @@ var ONBOARDING_AGENT = {
|
|
|
44299
44311
|
name: "Setup",
|
|
44300
44312
|
ownerId: "SYSTEM",
|
|
44301
44313
|
systemMessage: "Workspace setup — this todo is a guided stepper and never runs an agent.",
|
|
44302
|
-
mcpConfigs: {},
|
|
44303
44314
|
edgesMcpConfigs: {},
|
|
44304
44315
|
createdAt: 0,
|
|
44305
44316
|
updatedAt: 0
|
|
@@ -44548,7 +44559,7 @@ import { parseArgs } from "util";
|
|
|
44548
44559
|
// package.json
|
|
44549
44560
|
var package_default = {
|
|
44550
44561
|
name: "@todoforai/cli",
|
|
44551
|
-
version: "0.1.
|
|
44562
|
+
version: "0.1.54",
|
|
44552
44563
|
type: "module",
|
|
44553
44564
|
bin: {
|
|
44554
44565
|
"todoforai-cli": "bin/todoforai-cli.js",
|
|
@@ -47434,8 +47445,7 @@ Examples:
|
|
|
47434
47445
|
tfa-cli agent update <agent> sysmsg="You are a terse video editor."
|
|
47435
47446
|
tfa-cli agent create name=Reviewer model=claude sysmsg="Review diffs only."
|
|
47436
47447
|
|
|
47437
|
-
From an agent shell (dst_ token) permissions,
|
|
47438
|
-
devicesConfig and delete are refused by the backend.
|
|
47448
|
+
From an agent shell (dst_ token) permissions, edgesMcpConfigs, devicesConfig and delete are refused by the backend.
|
|
47439
47449
|
`);
|
|
47440
47450
|
}
|
|
47441
47451
|
var FIELD_ALIASES = {
|
|
@@ -47853,7 +47863,7 @@ function printProjectHelp() {
|
|
|
47853
47863
|
process.stderr.write(`
|
|
47854
47864
|
tfa-cli project — edit the current project
|
|
47855
47865
|
|
|
47856
|
-
--project <id
|
|
47866
|
+
--project <id>, $TODOFORAI_PROJECT_ID, or the configured default selects the project.
|
|
47857
47867
|
|
|
47858
47868
|
Usage:
|
|
47859
47869
|
tfa-cli project list Projects you can access (* = default)
|
|
@@ -47886,7 +47896,7 @@ var TODO_ALIASES = {
|
|
|
47886
47896
|
agent: "agentSettingsId",
|
|
47887
47897
|
public: "isPublic"
|
|
47888
47898
|
};
|
|
47889
|
-
var
|
|
47899
|
+
var NO_PROJECT = "No project — pass --project <id> or set TODOFORAI_PROJECT_ID";
|
|
47890
47900
|
function fail(msg) {
|
|
47891
47901
|
process.stderr.write(`${RED}${msg}${RESET}
|
|
47892
47902
|
`);
|
|
@@ -47937,9 +47947,8 @@ async function todoCommand(api, positionals, args) {
|
|
|
47937
47947
|
process.stderr.write(`${GREEN}✅ ${todoId} updated: ${Object.keys(updates).join(", ")}${RESET}
|
|
47938
47948
|
`);
|
|
47939
47949
|
}
|
|
47940
|
-
async function projectCommand(api, positionals, args) {
|
|
47950
|
+
async function projectCommand(api, positionals, args, projectId) {
|
|
47941
47951
|
const [, sub, ...rest] = positionals;
|
|
47942
|
-
const projectId = args.project || getEnv2("PROJECT_ID");
|
|
47943
47952
|
if (!sub) {
|
|
47944
47953
|
printProjectHelp();
|
|
47945
47954
|
process.exit(0);
|
|
@@ -47958,11 +47967,11 @@ async function projectCommand(api, positionals, args) {
|
|
|
47958
47967
|
return;
|
|
47959
47968
|
}
|
|
47960
47969
|
if (!projectId)
|
|
47961
|
-
fail(
|
|
47970
|
+
fail(NO_PROJECT);
|
|
47962
47971
|
if (sub === "set") {
|
|
47963
47972
|
if (!rest.length)
|
|
47964
47973
|
fail("Usage: tfa-cli project set <field=value>…");
|
|
47965
|
-
const updates = parseAssignments2(rest
|
|
47974
|
+
const updates = parseAssignments2(rest);
|
|
47966
47975
|
await api.updateProject(projectId, updates);
|
|
47967
47976
|
process.stderr.write(`${GREEN}✅ project updated: ${Object.keys(updates).join(", ")}${RESET}
|
|
47968
47977
|
`);
|
|
@@ -48071,7 +48080,7 @@ function printBrandHelp() {
|
|
|
48071
48080
|
process.stderr.write(`
|
|
48072
48081
|
tfa-cli brand — the project's brand page and its learned writing voice
|
|
48073
48082
|
|
|
48074
|
-
The project IS the brand. --project <id
|
|
48083
|
+
The project IS the brand. --project <id>, $TODOFORAI_PROJECT_ID, or the configured default selects it.
|
|
48075
48084
|
The brand page text itself is a file: read/write todoforai:business-context.
|
|
48076
48085
|
|
|
48077
48086
|
Usage:
|
|
@@ -48101,15 +48110,9 @@ Questions the UI asks (keys for 'answers'):
|
|
|
48101
48110
|
"A frustrated customer says things aren't working. How do you reply?"
|
|
48102
48111
|
`);
|
|
48103
48112
|
}
|
|
48104
|
-
function
|
|
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;
|
|
48109
|
-
}
|
|
48110
|
-
async function brandCommand(api, positionals, args) {
|
|
48113
|
+
async function brandCommand(api, positionals, args, scoped) {
|
|
48111
48114
|
const [, sub, ...rest] = positionals;
|
|
48112
|
-
const projectId =
|
|
48115
|
+
const projectId = scoped || fail(NO_PROJECT);
|
|
48113
48116
|
if (!sub || sub === "show") {
|
|
48114
48117
|
const brand = await api.getBusinessContext(projectId);
|
|
48115
48118
|
if (args.json) {
|
|
@@ -48200,13 +48203,8 @@ async function voiceCommand(api, projectId, rest, args) {
|
|
|
48200
48203
|
const [verb, ...vargs] = rest;
|
|
48201
48204
|
if (verb === "collect" && !vargs[0])
|
|
48202
48205
|
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");
|
|
48206
48206
|
if (verb === "answers") {
|
|
48207
|
-
const
|
|
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]));
|
|
48207
|
+
const answers = manualAnswersOf((await api.listVoiceSources(projectId)).sources);
|
|
48210
48208
|
if (vargs.length) {
|
|
48211
48209
|
for (const a of vargs) {
|
|
48212
48210
|
const i = a.indexOf("=");
|
|
@@ -48214,8 +48212,7 @@ async function voiceCommand(api, projectId, rest, args) {
|
|
|
48214
48212
|
fail(`Expected question=answer, got '${a}'`);
|
|
48215
48213
|
answers[a.slice(0, i)] = a.slice(i + 1);
|
|
48216
48214
|
}
|
|
48217
|
-
|
|
48218
|
-
await api.collectVoiceSource(projectId, "Manual", { samples });
|
|
48215
|
+
await api.collectVoiceSource(projectId, MANUAL_CHANNEL, { samples: manualSamples(answers) });
|
|
48219
48216
|
process.stderr.write(`${GREEN}✅ ${vargs.length} answer(s) saved${RESET}
|
|
48220
48217
|
`);
|
|
48221
48218
|
return;
|
|
@@ -48231,12 +48228,13 @@ async function voiceCommand(api, projectId, rest, args) {
|
|
|
48231
48228
|
return;
|
|
48232
48229
|
}
|
|
48233
48230
|
if (!verb || verb === "show") {
|
|
48234
|
-
const { sources, profile } = await api.listVoiceSources(projectId);
|
|
48231
|
+
const [{ sources, profile }, brand] = await Promise.all([api.listVoiceSources(projectId), api.getBusinessContext(projectId)]);
|
|
48235
48232
|
if (args.json) {
|
|
48236
48233
|
console.log(JSON.stringify({ brand, profile, sources }, null, 2));
|
|
48237
48234
|
return;
|
|
48238
48235
|
}
|
|
48239
|
-
|
|
48236
|
+
if (brand)
|
|
48237
|
+
process.stderr.write(`${brand.name} ${DIM}${brand.id}${RESET}
|
|
48240
48238
|
`);
|
|
48241
48239
|
process.stderr.write(profile ? `
|
|
48242
48240
|
${profile.profile}
|
|
@@ -48284,11 +48282,11 @@ ${DIM}match ${profile.match}/100 · source ${profile.source}${RESET}
|
|
|
48284
48282
|
return;
|
|
48285
48283
|
}
|
|
48286
48284
|
if (verb === "learn") {
|
|
48287
|
-
process.stderr.write(`${DIM}learning voice
|
|
48285
|
+
process.stderr.write(`${DIM}learning voice…${RESET}
|
|
48288
48286
|
`);
|
|
48289
48287
|
const res = await api.refineBrandVoice(projectId, args["from-company"] ? "company" : undefined);
|
|
48290
48288
|
if (!res.profile)
|
|
48291
|
-
fail("Nothing to learn from — add answers
|
|
48289
|
+
fail(args["from-company"] ? "No brand page to learn from — 'tfa-cli brand create <name>' and fill it first" : "Nothing to learn from — add answers, collect a source, or fill the brand page first");
|
|
48292
48290
|
if (args.json) {
|
|
48293
48291
|
console.log(JSON.stringify(res, null, 2));
|
|
48294
48292
|
return;
|
|
@@ -73166,12 +73164,13 @@ Cancelled by user (Ctrl+C)
|
|
|
73166
73164
|
await todoCommand(api2, positionals, args);
|
|
73167
73165
|
return;
|
|
73168
73166
|
}
|
|
73167
|
+
const scopedProject = args.project || getEnv("PROJECT_ID") || cfgScope.data.default_project_id || undefined;
|
|
73169
73168
|
if (positionals[0] === "project") {
|
|
73170
|
-
await projectCommand(api2, positionals, args);
|
|
73169
|
+
await projectCommand(api2, positionals, args, scopedProject);
|
|
73171
73170
|
return;
|
|
73172
73171
|
}
|
|
73173
73172
|
if (positionals[0] === "brand") {
|
|
73174
|
-
await brandCommand(api2, positionals, args);
|
|
73173
|
+
await brandCommand(api2, positionals, args, scopedProject);
|
|
73175
73174
|
return;
|
|
73176
73175
|
}
|
|
73177
73176
|
if (positionals[0] === "device") {
|