@todoforai/cli 0.1.47 → 0.1.48
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 +658 -6
- package/package.json +1 -1
package/dist/todoforai-cli.js
CHANGED
|
@@ -42860,6 +42860,75 @@ class ApiClient {
|
|
|
42860
42860
|
deleteTodo(todoId) {
|
|
42861
42861
|
return this.request("DELETE", `/api/v1/todos/${todoId}`);
|
|
42862
42862
|
}
|
|
42863
|
+
restoreTodo(todoId) {
|
|
42864
|
+
return this.request("POST", `/api/v1/todos/${todoId}/restore`, { todoId });
|
|
42865
|
+
}
|
|
42866
|
+
reorderAgentSettings(agentSettingsIds) {
|
|
42867
|
+
return this.request("PUT", "/api/v1/agents/reorder", { agentSettingsIds });
|
|
42868
|
+
}
|
|
42869
|
+
updateTodo(todoId, updates) {
|
|
42870
|
+
return this.request("PUT", `/api/v1/todos/${todoId}`, { todoId, ...updates });
|
|
42871
|
+
}
|
|
42872
|
+
updateScheduledMessage(todoId, messageId, agentSettingsId, updates) {
|
|
42873
|
+
return this.request("PATCH", `/api/v1/todos/${todoId}/messages/${messageId}`, { todoId, messageId, agentSettingsId, ...updates });
|
|
42874
|
+
}
|
|
42875
|
+
setDefaultProject(projectId) {
|
|
42876
|
+
return this.request("POST", "/api/v1/users/default-project", { projectId });
|
|
42877
|
+
}
|
|
42878
|
+
setProjectDefaultAgent(projectId, agentSettingsId) {
|
|
42879
|
+
return this.request("POST", "/api/v1/users/project-agent-mapping", { projectId, agentSettingsId });
|
|
42880
|
+
}
|
|
42881
|
+
renameDevice(id, name) {
|
|
42882
|
+
return this.request("PATCH", `/api/v1/devices/${id}/name`, { id, name });
|
|
42883
|
+
}
|
|
42884
|
+
setDeviceWallpaperMode(id, mode) {
|
|
42885
|
+
return this.request("POST", `/api/v1/devices/${id}/wallpaper-mode`, { id, mode });
|
|
42886
|
+
}
|
|
42887
|
+
listBusinessContexts() {
|
|
42888
|
+
return this.request("GET", "/api/v1/business-context");
|
|
42889
|
+
}
|
|
42890
|
+
createBusinessContext(name) {
|
|
42891
|
+
return this.request("POST", "/api/v1/business-context", { name });
|
|
42892
|
+
}
|
|
42893
|
+
renameBusinessContext(id, name) {
|
|
42894
|
+
return this.request("PUT", `/api/v1/business-context/${id}`, { id, name });
|
|
42895
|
+
}
|
|
42896
|
+
selectBusinessContext(contextId) {
|
|
42897
|
+
return this.request("POST", "/api/v1/business-context/select", { contextId });
|
|
42898
|
+
}
|
|
42899
|
+
listVoiceSources(businessContextId) {
|
|
42900
|
+
return this.request("GET", `/api/v1/business-context/voice-sources?id=${encodeURIComponent(businessContextId)}`);
|
|
42901
|
+
}
|
|
42902
|
+
collectVoiceSource(businessContextId, channel, opts) {
|
|
42903
|
+
return this.request("POST", "/api/v1/business-context/collect-voice-source", { businessContextId, channel, ...opts });
|
|
42904
|
+
}
|
|
42905
|
+
removeVoiceSource(businessContextId, channel) {
|
|
42906
|
+
return this.request("POST", "/api/v1/business-context/remove-voice-source", { businessContextId, channel });
|
|
42907
|
+
}
|
|
42908
|
+
refineBrandVoice(businessContextId, answers, source) {
|
|
42909
|
+
return this.request("POST", "/api/v1/business-context/refine-brand-voice", { businessContextId, answers, ...source && { source } });
|
|
42910
|
+
}
|
|
42911
|
+
getProfile() {
|
|
42912
|
+
return this.request("GET", "/api/v1/users/profile");
|
|
42913
|
+
}
|
|
42914
|
+
getOnboarding() {
|
|
42915
|
+
return this.request("GET", "/api/v1/onboarding");
|
|
42916
|
+
}
|
|
42917
|
+
patchOnboarding(patch) {
|
|
42918
|
+
return this.request("PUT", "/api/v1/onboarding", { patch });
|
|
42919
|
+
}
|
|
42920
|
+
updateProject(projectId, updates) {
|
|
42921
|
+
return this.request("PUT", `/api/v1/projects/${projectId}`, { projectId, ...updates });
|
|
42922
|
+
}
|
|
42923
|
+
listProjectGroups(projectId) {
|
|
42924
|
+
return this.request("GET", `/api/v1/projects/${projectId}/groups`);
|
|
42925
|
+
}
|
|
42926
|
+
upsertProjectGroup(projectId, slug, fields) {
|
|
42927
|
+
return this.request("PUT", `/api/v1/projects/${projectId}/groups/${encodeURIComponent(slug)}`, { projectId, slug, ...fields });
|
|
42928
|
+
}
|
|
42929
|
+
reorderProjectGroups(projectId, slugs) {
|
|
42930
|
+
return this.request("PUT", `/api/v1/projects/${projectId}/groups-order`, { projectId, slugs });
|
|
42931
|
+
}
|
|
42863
42932
|
listModels() {
|
|
42864
42933
|
return this.request("GET", "/api/v1/models");
|
|
42865
42934
|
}
|
|
@@ -43669,6 +43738,9 @@ var SERVER_TO_FRONTENDS = {
|
|
|
43669
43738
|
notification: {
|
|
43670
43739
|
changed: (userId) => `${"notification:changed" /* NOTIFICATION_CHANGED */}:${userId}`
|
|
43671
43740
|
},
|
|
43741
|
+
frontend: {
|
|
43742
|
+
presence: (userId) => `${"frontend:presence" /* FRONTEND_PRESENCE */}:${userId}`
|
|
43743
|
+
},
|
|
43672
43744
|
agent: {
|
|
43673
43745
|
status: (userId) => `${"agent:status" /* AGENT_STATUS */}:${userId}`,
|
|
43674
43746
|
mcpList: () => `${"agent:mcp_list" /* AGENT_MCP_LIST */}:ALL`
|
|
@@ -44334,6 +44406,10 @@ var TOPICS = {
|
|
|
44334
44406
|
channel: (p) => SERVER_TO_FRONTENDS.notification.changed(p.userId),
|
|
44335
44407
|
audience: "frontend"
|
|
44336
44408
|
},
|
|
44409
|
+
["frontend:presence" /* FRONTEND_PRESENCE */]: {
|
|
44410
|
+
channel: (p) => SERVER_TO_FRONTENDS.frontend.presence(p.userId),
|
|
44411
|
+
audience: "frontend"
|
|
44412
|
+
},
|
|
44337
44413
|
["NOTIFY" /* NOTIFY */]: {
|
|
44338
44414
|
channel: (p) => p.userId ? SERVER_TO_FRONTENDS.notify.user(p.userId) : SERVER_TO_FRONTENDS.todo.notify(p.todoId),
|
|
44339
44415
|
audience: "frontend"
|
|
@@ -44450,7 +44526,7 @@ import { parseArgs } from "util";
|
|
|
44450
44526
|
// package.json
|
|
44451
44527
|
var package_default = {
|
|
44452
44528
|
name: "@todoforai/cli",
|
|
44453
|
-
version: "0.1.
|
|
44529
|
+
version: "0.1.48",
|
|
44454
44530
|
type: "module",
|
|
44455
44531
|
bin: {
|
|
44456
44532
|
"todoforai-cli": "bin/todoforai-cli.js",
|
|
@@ -44507,7 +44583,11 @@ Usage:
|
|
|
44507
44583
|
tfa-cli acp # Agent Client Protocol server on stdio (Zed, JetBrains, …; see README)
|
|
44508
44584
|
tfa-cli --list-agents # List available agents and exit
|
|
44509
44585
|
tfa-cli --list-models [filter] # List models usable with --model and exit
|
|
44510
|
-
tfa-cli agent update <agent> model=<model> # Update agent settings (see 'agent --help')
|
|
44586
|
+
tfa-cli agent update <agent> model=<model> # Update agent settings (see 'agent --help'; also 'agent create')
|
|
44587
|
+
tfa-cli todo set <todo-id|-> title=… group=… star=true # Edit a todo's fields (see 'todo --help')
|
|
44588
|
+
tfa-cli project set|settings|groups|default|agent … # Edit the project, groups, defaults (see 'project --help')
|
|
44589
|
+
tfa-cli brand list|create|select|voice … # Brands (business contexts) + voice learning (see 'brand --help')
|
|
44590
|
+
tfa-cli device list|rename|wallpaper … # Paired machines (see 'device --help')
|
|
44511
44591
|
tfa-cli list [-n 30] [--cursor N] [--all] [--status S] # List todos (paginated); see 'list --help'
|
|
44512
44592
|
tfa-cli status <todo-id> <STATUS> # Update a todo's status (run 'status --help' for the full list)
|
|
44513
44593
|
tfa-cli delete <todo-id> # Permanently delete a todo
|
|
@@ -44614,6 +44694,10 @@ function parseCliArgs() {
|
|
|
44614
44694
|
link: { type: "boolean", default: false },
|
|
44615
44695
|
direction: { type: "string" },
|
|
44616
44696
|
"business-context": { type: "string" },
|
|
44697
|
+
brand: { type: "string" },
|
|
44698
|
+
url: { type: "string" },
|
|
44699
|
+
"pasted-file": { type: "string" },
|
|
44700
|
+
"from-company": { type: "boolean", default: false },
|
|
44617
44701
|
seed: { type: "string" },
|
|
44618
44702
|
emails: { type: "string" },
|
|
44619
44703
|
ttl: { type: "string" },
|
|
@@ -47290,6 +47374,9 @@ Usage:
|
|
|
47290
47374
|
tfa-cli agent list List agents (name, model, id, paths)
|
|
47291
47375
|
tfa-cli agent get <agent> Show a single agent's settings
|
|
47292
47376
|
tfa-cli agent update <agent> <field=value>… Update one or more settings
|
|
47377
|
+
tfa-cli agent create [<field=value>…] Create an agent (defaults, then apply fields)
|
|
47378
|
+
tfa-cli agent global [<field=value>…] Show / update the user's global agent defaults
|
|
47379
|
+
tfa-cli agent reorder <agent>… Set the sidebar order (names or ids)
|
|
47293
47380
|
tfa-cli agent delete <agent> Delete an agent configuration (asks to confirm)
|
|
47294
47381
|
|
|
47295
47382
|
<agent> is a name or id (unique partial name also works).
|
|
@@ -47306,6 +47393,10 @@ Examples:
|
|
|
47306
47393
|
tfa-cli agent update <agent> model=claude
|
|
47307
47394
|
tfa-cli agent update <agent> model=anthropic:anthropic/claude-opus-5 temperature=0.5
|
|
47308
47395
|
tfa-cli agent update <agent> sysmsg="You are a terse video editor."
|
|
47396
|
+
tfa-cli agent create name=Reviewer model=claude sysmsg="Review diffs only."
|
|
47397
|
+
|
|
47398
|
+
From an agent shell (dst_ token) permissions, mcpConfigs, edgesMcpConfigs,
|
|
47399
|
+
devicesConfig and delete are refused by the backend.
|
|
47309
47400
|
`);
|
|
47310
47401
|
}
|
|
47311
47402
|
var FIELD_ALIASES = {
|
|
@@ -47314,7 +47405,7 @@ var FIELD_ALIASES = {
|
|
|
47314
47405
|
temp: "temperature",
|
|
47315
47406
|
thinking: "thinkingLevel"
|
|
47316
47407
|
};
|
|
47317
|
-
function parseAssignment(arg) {
|
|
47408
|
+
function parseAssignment(arg, aliases = {}) {
|
|
47318
47409
|
const eq = arg.indexOf("=");
|
|
47319
47410
|
if (eq < 1) {
|
|
47320
47411
|
process.stderr.write(`${RED}Invalid field assignment '${arg}', expected field=value${RESET}
|
|
@@ -47322,7 +47413,7 @@ function parseAssignment(arg) {
|
|
|
47322
47413
|
process.exit(2);
|
|
47323
47414
|
}
|
|
47324
47415
|
const rawKey = arg.slice(0, eq);
|
|
47325
|
-
const key =
|
|
47416
|
+
const key = aliases[rawKey] || rawKey;
|
|
47326
47417
|
const raw = arg.slice(eq + 1);
|
|
47327
47418
|
try {
|
|
47328
47419
|
return [key, JSON.parse(raw)];
|
|
@@ -47330,6 +47421,9 @@ function parseAssignment(arg) {
|
|
|
47330
47421
|
return [key, raw];
|
|
47331
47422
|
}
|
|
47332
47423
|
}
|
|
47424
|
+
function parseAssignments(args, aliases = {}) {
|
|
47425
|
+
return Object.fromEntries(args.map((a) => parseAssignment(a, aliases)));
|
|
47426
|
+
}
|
|
47333
47427
|
function resolveAgent(agents, query) {
|
|
47334
47428
|
const { match, ambiguous } = resolveAgentMatch2(agents, query);
|
|
47335
47429
|
if (match)
|
|
@@ -47377,7 +47471,7 @@ async function agentCommand(api, positionals, args, formatPath) {
|
|
|
47377
47471
|
`);
|
|
47378
47472
|
process.exit(2);
|
|
47379
47473
|
}
|
|
47380
|
-
const updates =
|
|
47474
|
+
const updates = parseAssignments(assignments, FIELD_ALIASES);
|
|
47381
47475
|
const agents = await api.listAgentSettings();
|
|
47382
47476
|
const agent = resolveAgent(agents, query);
|
|
47383
47477
|
const id = getItemId2(agent);
|
|
@@ -47388,6 +47482,45 @@ async function agentCommand(api, positionals, args, formatPath) {
|
|
|
47388
47482
|
}
|
|
47389
47483
|
const summary = Object.keys(updates).map((k) => `${k}=${JSON.stringify(updated[k])}`).join(" ");
|
|
47390
47484
|
process.stderr.write(`${GREEN}✅ ${getDisplayName2(agent)} updated: ${summary}${RESET}
|
|
47485
|
+
`);
|
|
47486
|
+
return;
|
|
47487
|
+
}
|
|
47488
|
+
if (sub === "global") {
|
|
47489
|
+
const updates = parseAssignments(positionals.slice(2), FIELD_ALIASES);
|
|
47490
|
+
const global = Object.keys(updates).length ? await api.updateGlobalAgentSettings(updates) : await api.getGlobalAgentSettings();
|
|
47491
|
+
if (args.json) {
|
|
47492
|
+
console.log(JSON.stringify(global, null, 2));
|
|
47493
|
+
return;
|
|
47494
|
+
}
|
|
47495
|
+
for (const [k, v] of Object.entries(global))
|
|
47496
|
+
process.stderr.write(` ${DIM}${k}:${RESET} ${typeof v === "string" ? v : JSON.stringify(v)}
|
|
47497
|
+
`);
|
|
47498
|
+
return;
|
|
47499
|
+
}
|
|
47500
|
+
if (sub === "reorder") {
|
|
47501
|
+
const queries = positionals.slice(2);
|
|
47502
|
+
if (!queries.length) {
|
|
47503
|
+
process.stderr.write(`${RED}Usage: tfa-cli agent reorder <agent>…${RESET}
|
|
47504
|
+
`);
|
|
47505
|
+
process.exit(2);
|
|
47506
|
+
}
|
|
47507
|
+
const agents = await api.listAgentSettings();
|
|
47508
|
+
const ids = queries.map((q) => getItemId2(resolveAgent(agents, q)));
|
|
47509
|
+
await api.reorderAgentSettings(ids);
|
|
47510
|
+
process.stderr.write(`${GREEN}✅ Agents reordered${RESET}
|
|
47511
|
+
`);
|
|
47512
|
+
return;
|
|
47513
|
+
}
|
|
47514
|
+
if (sub === "create") {
|
|
47515
|
+
const updates = parseAssignments(positionals.slice(2), FIELD_ALIASES);
|
|
47516
|
+
const created = await api.createAgent();
|
|
47517
|
+
const id = getItemId2(created);
|
|
47518
|
+
const agent = Object.keys(updates).length ? await api.updateAgentSettings(id, id, updates) : created;
|
|
47519
|
+
if (args.json) {
|
|
47520
|
+
console.log(JSON.stringify(agent, null, 2));
|
|
47521
|
+
return;
|
|
47522
|
+
}
|
|
47523
|
+
process.stderr.write(`${GREEN}✅ Created agent ${getDisplayName2(agent)}${RESET} ${DIM}${id}${RESET}
|
|
47391
47524
|
`);
|
|
47392
47525
|
return;
|
|
47393
47526
|
}
|
|
@@ -47423,6 +47556,493 @@ async function agentCommand(api, positionals, args, formatPath) {
|
|
|
47423
47556
|
process.exit(2);
|
|
47424
47557
|
}
|
|
47425
47558
|
|
|
47559
|
+
// src/agent-command.ts
|
|
47560
|
+
function parseAssignment2(arg, aliases = {}) {
|
|
47561
|
+
const eq = arg.indexOf("=");
|
|
47562
|
+
if (eq < 1) {
|
|
47563
|
+
process.stderr.write(`${RED}Invalid field assignment '${arg}', expected field=value${RESET}
|
|
47564
|
+
`);
|
|
47565
|
+
process.exit(2);
|
|
47566
|
+
}
|
|
47567
|
+
const rawKey = arg.slice(0, eq);
|
|
47568
|
+
const key = aliases[rawKey] || rawKey;
|
|
47569
|
+
const raw = arg.slice(eq + 1);
|
|
47570
|
+
try {
|
|
47571
|
+
return [key, JSON.parse(raw)];
|
|
47572
|
+
} catch {
|
|
47573
|
+
return [key, raw];
|
|
47574
|
+
}
|
|
47575
|
+
}
|
|
47576
|
+
function parseAssignments2(args, aliases = {}) {
|
|
47577
|
+
return Object.fromEntries(args.map((a) => parseAssignment2(a, aliases)));
|
|
47578
|
+
}
|
|
47579
|
+
function resolveAgent2(agents, query) {
|
|
47580
|
+
const { match, ambiguous } = resolveAgentMatch2(agents, query);
|
|
47581
|
+
if (match)
|
|
47582
|
+
return match;
|
|
47583
|
+
if (ambiguous) {
|
|
47584
|
+
process.stderr.write(`${RED}Ambiguous agent '${query}' — ${ambiguous.length} matches. Re-run with the exact id:${RESET}
|
|
47585
|
+
`);
|
|
47586
|
+
for (const a of ambiguous)
|
|
47587
|
+
process.stderr.write(` ${getDisplayName2(a)} ${DIM}${getItemId2(a)}${RESET}
|
|
47588
|
+
`);
|
|
47589
|
+
process.exit(2);
|
|
47590
|
+
}
|
|
47591
|
+
process.stderr.write(`${RED}No agent matching '${query}'${RESET}
|
|
47592
|
+
`);
|
|
47593
|
+
process.exit(2);
|
|
47594
|
+
}
|
|
47595
|
+
|
|
47596
|
+
// src/args.ts
|
|
47597
|
+
var VERSION2 = package_default.version;
|
|
47598
|
+
function getEnv2(name) {
|
|
47599
|
+
return (process.env[`TODOFORAI_${name}`] || process.env[`TODO4AI_${name}`] || "").trim();
|
|
47600
|
+
}
|
|
47601
|
+
var STATUS_HELP2 = {
|
|
47602
|
+
["READY" /* READY */]: "AI finished the work on the TODO",
|
|
47603
|
+
["READY_CHECKED" /* READY_CHECKED */]: "AI finished and the user reviewed it",
|
|
47604
|
+
["DONE" /* DONE */]: "Completed and finalized",
|
|
47605
|
+
["REVIEW_REQUESTED" /* REVIEW_REQUESTED */]: "Asks the user to review",
|
|
47606
|
+
["POSTPONED" /* POSTPONED */]: "Put off for later",
|
|
47607
|
+
["ARCHIVED" /* ARCHIVED */]: "Archived (hidden from active list)",
|
|
47608
|
+
["DELETED" /* DELETED */]: "Marked for deletion"
|
|
47609
|
+
};
|
|
47610
|
+
|
|
47611
|
+
// src/manage-command.ts
|
|
47612
|
+
function printTodoHelp() {
|
|
47613
|
+
process.stderr.write(`
|
|
47614
|
+
tfa-cli todo — edit a todo's fields
|
|
47615
|
+
|
|
47616
|
+
Usage:
|
|
47617
|
+
tfa-cli todo set <todo-id|-> <field=value>… Update fields ("-" = $TODOFORAI_TODO_ID)
|
|
47618
|
+
tfa-cli todo restore <todo-id> Bring a trashed todo back (undo of 'delete')
|
|
47619
|
+
|
|
47620
|
+
Fields (PUT /todos/{id}):
|
|
47621
|
+
title first-line content (alias: content)
|
|
47622
|
+
group group slug; "" makes it ungrouped (alias: groupTag)
|
|
47623
|
+
star true|false (starredAt now / 0)
|
|
47624
|
+
schedule unix ms timestamp, 0 = immediate (alias: scheduledTimestamp)
|
|
47625
|
+
agent agentSettingsId (alias: agentSettingsId)
|
|
47626
|
+
brand businessContextId (alias: businessContextId)
|
|
47627
|
+
public true|false — refused from an agent shell (isPublic)
|
|
47628
|
+
|
|
47629
|
+
tfa-cli todo message <todo-id|-> <message-id> <field=value>…
|
|
47630
|
+
Edit a SCHEDULED (not yet run) message: content, schedule (unix ms;
|
|
47631
|
+
0 = run now). Runs with the todo's own agent.
|
|
47632
|
+
|
|
47633
|
+
Examples:
|
|
47634
|
+
tfa-cli todo set - title="Ship v2 landing" group=marketing
|
|
47635
|
+
tfa-cli todo set 3f2a91 star=true
|
|
47636
|
+
tfa-cli todo message - 8c1d… schedule=1760000000000
|
|
47637
|
+
tfa-cli status <todo-id> DONE (status has its own command)
|
|
47638
|
+
`);
|
|
47639
|
+
}
|
|
47640
|
+
function printProjectHelp() {
|
|
47641
|
+
process.stderr.write(`
|
|
47642
|
+
tfa-cli project — edit the current project
|
|
47643
|
+
|
|
47644
|
+
--project <id> or $TODOFORAI_PROJECT_ID selects the project.
|
|
47645
|
+
|
|
47646
|
+
Usage:
|
|
47647
|
+
tfa-cli project set <field=value>… name=… description=… brand=<businessContextId>
|
|
47648
|
+
(isPublic refused from an agent shell)
|
|
47649
|
+
tfa-cli project default Make it the project you land on at /
|
|
47650
|
+
tfa-cli project agent <agent> Default agent for new todos in this project
|
|
47651
|
+
tfa-cli project settings <field=value>… Project settings (PUT /settings/projects/{id})
|
|
47652
|
+
tfa-cli project groups List todo groups
|
|
47653
|
+
tfa-cli project groups set <slug> <field=value>… Create/update a group: name description pinned archived order
|
|
47654
|
+
tfa-cli project groups reorder <slug>… Set wall order
|
|
47655
|
+
|
|
47656
|
+
Examples:
|
|
47657
|
+
tfa-cli project set name="Q4 launch"
|
|
47658
|
+
tfa-cli project groups set marketing name=Marketing description="Top-of-funnel work"
|
|
47659
|
+
tfa-cli project groups reorder marketing sales ops
|
|
47660
|
+
`);
|
|
47661
|
+
}
|
|
47662
|
+
var TODO_ALIASES = {
|
|
47663
|
+
title: "content",
|
|
47664
|
+
group: "groupTag",
|
|
47665
|
+
schedule: "scheduledTimestamp",
|
|
47666
|
+
agent: "agentSettingsId",
|
|
47667
|
+
brand: "businessContextId",
|
|
47668
|
+
public: "isPublic"
|
|
47669
|
+
};
|
|
47670
|
+
var PROJECT_ALIASES = { brand: "businessContextId" };
|
|
47671
|
+
function fail(msg) {
|
|
47672
|
+
process.stderr.write(`${RED}${msg}${RESET}
|
|
47673
|
+
`);
|
|
47674
|
+
process.exit(2);
|
|
47675
|
+
}
|
|
47676
|
+
async function todoCommand(api, positionals, args) {
|
|
47677
|
+
const [, sub, idArg, ...rest] = positionals;
|
|
47678
|
+
if (sub === "restore") {
|
|
47679
|
+
if (!idArg)
|
|
47680
|
+
fail("Usage: tfa-cli todo restore <todo-id>");
|
|
47681
|
+
await api.restoreTodo(idArg);
|
|
47682
|
+
process.stderr.write(`${GREEN}✅ Restored ${idArg}${RESET}
|
|
47683
|
+
`);
|
|
47684
|
+
return;
|
|
47685
|
+
}
|
|
47686
|
+
const todoId = !idArg || idArg === "-" ? getEnv2("TODO_ID") : idArg;
|
|
47687
|
+
if (sub === "message") {
|
|
47688
|
+
const [messageId, ...fields] = rest;
|
|
47689
|
+
if (!todoId || !messageId || !fields.length)
|
|
47690
|
+
fail("Usage: tfa-cli todo message <todo-id|-> <message-id> <field=value>…");
|
|
47691
|
+
const updates2 = parseAssignments2(fields, { schedule: "scheduledTimestamp" });
|
|
47692
|
+
const agentSettingsId = (await api.getTodo(todoId))?.agentSettingsId;
|
|
47693
|
+
if (!agentSettingsId)
|
|
47694
|
+
fail("Todo has no agent assigned");
|
|
47695
|
+
await api.updateScheduledMessage(todoId, messageId, agentSettingsId, updates2);
|
|
47696
|
+
process.stderr.write(`${GREEN}✅ message ${messageId} updated: ${Object.keys(updates2).join(", ")}${RESET}
|
|
47697
|
+
`);
|
|
47698
|
+
return;
|
|
47699
|
+
}
|
|
47700
|
+
if (sub !== "set") {
|
|
47701
|
+
printTodoHelp();
|
|
47702
|
+
process.exit(sub ? 2 : 0);
|
|
47703
|
+
}
|
|
47704
|
+
if (!todoId || !rest.length)
|
|
47705
|
+
fail("Usage: tfa-cli todo set <todo-id|-> <field=value>…");
|
|
47706
|
+
const updates = parseAssignments2(rest, TODO_ALIASES);
|
|
47707
|
+
if ("star" in updates) {
|
|
47708
|
+
if (typeof updates.star !== "boolean")
|
|
47709
|
+
fail("star must be true or false");
|
|
47710
|
+
updates.starredAt = updates.star ? Date.now() : 0;
|
|
47711
|
+
delete updates.star;
|
|
47712
|
+
}
|
|
47713
|
+
await api.updateTodo(todoId, updates);
|
|
47714
|
+
if (args.json) {
|
|
47715
|
+
console.log(JSON.stringify({ todoId, ...updates }));
|
|
47716
|
+
return;
|
|
47717
|
+
}
|
|
47718
|
+
process.stderr.write(`${GREEN}✅ ${todoId} updated: ${Object.keys(updates).join(", ")}${RESET}
|
|
47719
|
+
`);
|
|
47720
|
+
}
|
|
47721
|
+
async function projectCommand(api, positionals, args) {
|
|
47722
|
+
const [, sub, ...rest] = positionals;
|
|
47723
|
+
const projectId = args.project || getEnv2("PROJECT_ID");
|
|
47724
|
+
if (!sub) {
|
|
47725
|
+
printProjectHelp();
|
|
47726
|
+
process.exit(0);
|
|
47727
|
+
}
|
|
47728
|
+
if (!projectId)
|
|
47729
|
+
fail("No project — pass --project <id> or set TODOFORAI_PROJECT_ID");
|
|
47730
|
+
if (sub === "set") {
|
|
47731
|
+
if (!rest.length)
|
|
47732
|
+
fail("Usage: tfa-cli project set <field=value>…");
|
|
47733
|
+
const updates = parseAssignments2(rest, PROJECT_ALIASES);
|
|
47734
|
+
await api.updateProject(projectId, updates);
|
|
47735
|
+
process.stderr.write(`${GREEN}✅ project updated: ${Object.keys(updates).join(", ")}${RESET}
|
|
47736
|
+
`);
|
|
47737
|
+
return;
|
|
47738
|
+
}
|
|
47739
|
+
if (sub === "default") {
|
|
47740
|
+
await api.setDefaultProject(projectId);
|
|
47741
|
+
process.stderr.write(`${GREEN}✅ ${projectId} is now the default project${RESET}
|
|
47742
|
+
`);
|
|
47743
|
+
return;
|
|
47744
|
+
}
|
|
47745
|
+
if (sub === "agent") {
|
|
47746
|
+
if (!rest[0])
|
|
47747
|
+
fail("Usage: tfa-cli project agent <agent>");
|
|
47748
|
+
const agent = resolveAgent2(await api.listAgentSettings(), rest[0]);
|
|
47749
|
+
await api.setProjectDefaultAgent(projectId, getItemId2(agent));
|
|
47750
|
+
process.stderr.write(`${GREEN}✅ default agent for ${projectId}: ${getDisplayName2(agent)}${RESET}
|
|
47751
|
+
`);
|
|
47752
|
+
return;
|
|
47753
|
+
}
|
|
47754
|
+
if (sub === "settings") {
|
|
47755
|
+
if (!rest.length)
|
|
47756
|
+
fail("Usage: tfa-cli project settings <field=value>…");
|
|
47757
|
+
const settings = parseAssignments2(rest);
|
|
47758
|
+
await api.updateProjectSettings(projectId, settings);
|
|
47759
|
+
process.stderr.write(`${GREEN}✅ project settings updated: ${Object.keys(settings).join(", ")}${RESET}
|
|
47760
|
+
`);
|
|
47761
|
+
return;
|
|
47762
|
+
}
|
|
47763
|
+
if (sub === "groups") {
|
|
47764
|
+
const [verb, ...gargs] = rest;
|
|
47765
|
+
if (!verb) {
|
|
47766
|
+
const groups = await api.listProjectGroups(projectId);
|
|
47767
|
+
if (args.json) {
|
|
47768
|
+
console.log(JSON.stringify(groups, null, 2));
|
|
47769
|
+
return;
|
|
47770
|
+
}
|
|
47771
|
+
for (const g of groups)
|
|
47772
|
+
process.stderr.write(`${getItemId2(g) || g.slug} ${g.name ?? ""} ${DIM}${g.description ?? ""}${RESET}
|
|
47773
|
+
`);
|
|
47774
|
+
return;
|
|
47775
|
+
}
|
|
47776
|
+
if (verb === "set") {
|
|
47777
|
+
const [slug, ...fields] = gargs;
|
|
47778
|
+
if (!slug)
|
|
47779
|
+
fail("Usage: tfa-cli project groups set <slug> <field=value>…");
|
|
47780
|
+
const group = await api.upsertProjectGroup(projectId, slug, parseAssignments2(fields));
|
|
47781
|
+
if (args.json) {
|
|
47782
|
+
console.log(JSON.stringify(group, null, 2));
|
|
47783
|
+
return;
|
|
47784
|
+
}
|
|
47785
|
+
process.stderr.write(`${GREEN}✅ group ${slug} saved${RESET}
|
|
47786
|
+
`);
|
|
47787
|
+
return;
|
|
47788
|
+
}
|
|
47789
|
+
if (verb === "reorder") {
|
|
47790
|
+
if (!gargs.length)
|
|
47791
|
+
fail("Usage: tfa-cli project groups reorder <slug>…");
|
|
47792
|
+
await api.reorderProjectGroups(projectId, gargs);
|
|
47793
|
+
process.stderr.write(`${GREEN}✅ groups reordered${RESET}
|
|
47794
|
+
`);
|
|
47795
|
+
return;
|
|
47796
|
+
}
|
|
47797
|
+
fail(`Unknown 'project groups' verb: ${verb}`);
|
|
47798
|
+
}
|
|
47799
|
+
fail(`Unknown 'project' subcommand: ${sub}`);
|
|
47800
|
+
}
|
|
47801
|
+
function printBrandHelp() {
|
|
47802
|
+
process.stderr.write(`
|
|
47803
|
+
tfa-cli brand — business contexts (brands) and the learned writing voice
|
|
47804
|
+
|
|
47805
|
+
The brand page text itself is a file: read/write todoforai:business-context.
|
|
47806
|
+
These commands manage the contexts and the voice learned for them.
|
|
47807
|
+
|
|
47808
|
+
Usage:
|
|
47809
|
+
tfa-cli brand list Contexts (* = selected)
|
|
47810
|
+
tfa-cli brand create <name> New brand (empty .md page)
|
|
47811
|
+
tfa-cli brand rename <brand> <name>
|
|
47812
|
+
tfa-cli brand select <brand|none> Active brand for the account
|
|
47813
|
+
tfa-cli brand voice Learned profile + sources
|
|
47814
|
+
tfa-cli brand voice answers [<q>=<a>…] Show / set the brand-voice answers (strings)
|
|
47815
|
+
tfa-cli brand voice collect <channel> [--url U | --pasted-file <F|->]
|
|
47816
|
+
Add a writing sample source
|
|
47817
|
+
channels: X LinkedIn Facebook Instagram
|
|
47818
|
+
Gmail Outlook Slack Teams
|
|
47819
|
+
tfa-cli brand voice remove <channel>
|
|
47820
|
+
tfa-cli brand voice learn [--from-company] Run the refinement loop, store the profile
|
|
47821
|
+
|
|
47822
|
+
<brand> is an id or name (unique partial works). Voice subcommands use the
|
|
47823
|
+
selected brand unless --brand <id|name> is given (--pasted-file - reads stdin).
|
|
47824
|
+
Delete / reset are UI-only.
|
|
47825
|
+
|
|
47826
|
+
Questions the UI asks (keys for 'answers'):
|
|
47827
|
+
"What makes you different from competitors?"
|
|
47828
|
+
"What are you working on right now?"
|
|
47829
|
+
"A frustrated customer says things aren't working. How do you reply?"
|
|
47830
|
+
`);
|
|
47831
|
+
}
|
|
47832
|
+
async function resolveBrand(api, query, selectedId) {
|
|
47833
|
+
const contexts = await api.listBusinessContexts();
|
|
47834
|
+
if (!query) {
|
|
47835
|
+
const sel = contexts.find((c3) => c3.id === selectedId);
|
|
47836
|
+
if (sel)
|
|
47837
|
+
return sel;
|
|
47838
|
+
if (contexts.length === 1)
|
|
47839
|
+
return contexts[0];
|
|
47840
|
+
fail("No brand selected — pass --brand <id|name> or 'tfa-cli brand select'");
|
|
47841
|
+
}
|
|
47842
|
+
const q = query.toLowerCase();
|
|
47843
|
+
const exact = contexts.find((c3) => c3.id === query || c3.name.toLowerCase() === q);
|
|
47844
|
+
if (exact)
|
|
47845
|
+
return exact;
|
|
47846
|
+
const partial = contexts.filter((c3) => c3.id.startsWith(query) || c3.name.toLowerCase().includes(q));
|
|
47847
|
+
if (partial.length === 1)
|
|
47848
|
+
return partial[0];
|
|
47849
|
+
fail(partial.length ? `Ambiguous brand '${query}'` : `No brand matching '${query}'`);
|
|
47850
|
+
}
|
|
47851
|
+
async function brandCommand(api, positionals, args) {
|
|
47852
|
+
const [, sub, ...rest] = positionals;
|
|
47853
|
+
if (!sub || sub === "list") {
|
|
47854
|
+
const contexts = await api.listBusinessContexts();
|
|
47855
|
+
const selected = (await api.getProfile()).user?.selectedBusinessContextId;
|
|
47856
|
+
if (args.json) {
|
|
47857
|
+
console.log(JSON.stringify(contexts.map((c3) => ({ ...c3, selected: c3.id === selected })), null, 2));
|
|
47858
|
+
return;
|
|
47859
|
+
}
|
|
47860
|
+
for (const c3 of contexts)
|
|
47861
|
+
process.stderr.write(`${c3.id === selected ? "*" : " "} ${c3.name} ${DIM}${c3.id}${RESET}
|
|
47862
|
+
`);
|
|
47863
|
+
return;
|
|
47864
|
+
}
|
|
47865
|
+
if (sub === "create") {
|
|
47866
|
+
if (!rest[0])
|
|
47867
|
+
fail("Usage: tfa-cli brand create <name>");
|
|
47868
|
+
const c3 = await api.createBusinessContext(rest[0]);
|
|
47869
|
+
if (args.json) {
|
|
47870
|
+
console.log(JSON.stringify(c3, null, 2));
|
|
47871
|
+
return;
|
|
47872
|
+
}
|
|
47873
|
+
process.stderr.write(`${GREEN}✅ brand ${c3.name} created ${DIM}${c3.id}${RESET}
|
|
47874
|
+
`);
|
|
47875
|
+
return;
|
|
47876
|
+
}
|
|
47877
|
+
if (sub === "rename") {
|
|
47878
|
+
if (!rest[1])
|
|
47879
|
+
fail("Usage: tfa-cli brand rename <brand> <name>");
|
|
47880
|
+
const c3 = await resolveBrand(api, rest[0]);
|
|
47881
|
+
await api.renameBusinessContext(c3.id, rest[1]);
|
|
47882
|
+
process.stderr.write(`${GREEN}✅ renamed to ${rest[1]}${RESET}
|
|
47883
|
+
`);
|
|
47884
|
+
return;
|
|
47885
|
+
}
|
|
47886
|
+
if (sub === "select") {
|
|
47887
|
+
if (!rest[0])
|
|
47888
|
+
fail("Usage: tfa-cli brand select <brand|none>");
|
|
47889
|
+
const id = rest[0] === "none" ? null : (await resolveBrand(api, rest[0])).id;
|
|
47890
|
+
await api.selectBusinessContext(id);
|
|
47891
|
+
process.stderr.write(`${GREEN}✅ selected brand: ${id ?? "none"}${RESET}
|
|
47892
|
+
`);
|
|
47893
|
+
return;
|
|
47894
|
+
}
|
|
47895
|
+
if (sub === "voice")
|
|
47896
|
+
return voiceCommand(api, rest, args);
|
|
47897
|
+
fail(`Unknown 'brand' subcommand: ${sub}`);
|
|
47898
|
+
}
|
|
47899
|
+
async function voiceCommand(api, rest, args) {
|
|
47900
|
+
const [verb, ...vargs] = rest;
|
|
47901
|
+
const onboarding = await api.getOnboarding();
|
|
47902
|
+
if (verb === "answers") {
|
|
47903
|
+
if (vargs.length) {
|
|
47904
|
+
const given = Object.fromEntries(vargs.map((a) => {
|
|
47905
|
+
const i = a.indexOf("=");
|
|
47906
|
+
if (i < 1)
|
|
47907
|
+
fail(`Expected question=answer, got '${a}'`);
|
|
47908
|
+
return [a.slice(0, i), a.slice(i + 1)];
|
|
47909
|
+
}));
|
|
47910
|
+
const styleAnswers = { ...onboarding.styleAnswers ?? {}, ...given };
|
|
47911
|
+
await api.patchOnboarding({ styleAnswers });
|
|
47912
|
+
process.stderr.write(`${GREEN}✅ ${vargs.length} answer(s) saved${RESET}
|
|
47913
|
+
`);
|
|
47914
|
+
return;
|
|
47915
|
+
}
|
|
47916
|
+
const answers = onboarding.styleAnswers ?? {};
|
|
47917
|
+
if (args.json) {
|
|
47918
|
+
console.log(JSON.stringify(answers, null, 2));
|
|
47919
|
+
return;
|
|
47920
|
+
}
|
|
47921
|
+
for (const [q, a] of Object.entries(answers))
|
|
47922
|
+
process.stderr.write(`${q}
|
|
47923
|
+
${DIM}${a || "(empty)"}${RESET}
|
|
47924
|
+
`);
|
|
47925
|
+
return;
|
|
47926
|
+
}
|
|
47927
|
+
const brand = await resolveBrand(api, args.brand, (await api.getProfile()).user?.selectedBusinessContextId);
|
|
47928
|
+
if (!verb || verb === "show") {
|
|
47929
|
+
const profile = onboarding.voiceProfiles?.[brand.id];
|
|
47930
|
+
const { sources } = await api.listVoiceSources(brand.id);
|
|
47931
|
+
if (args.json) {
|
|
47932
|
+
console.log(JSON.stringify({ brand, profile, sources }, null, 2));
|
|
47933
|
+
return;
|
|
47934
|
+
}
|
|
47935
|
+
process.stderr.write(`${brand.name} ${DIM}${brand.id}${RESET}
|
|
47936
|
+
`);
|
|
47937
|
+
process.stderr.write(profile ? `
|
|
47938
|
+
${profile.profile}
|
|
47939
|
+
${DIM}match ${profile.match}/100 · source ${profile.source}${RESET}
|
|
47940
|
+
` : `${DIM}(no voice learned yet)${RESET}
|
|
47941
|
+
`);
|
|
47942
|
+
for (const s of sources)
|
|
47943
|
+
process.stderr.write(` ${s.channel} ${DIM}${s.posts ?? "?"} posts · ${s.chars ?? "?"} chars${RESET}
|
|
47944
|
+
`);
|
|
47945
|
+
return;
|
|
47946
|
+
}
|
|
47947
|
+
if (verb === "collect") {
|
|
47948
|
+
const channel = vargs[0];
|
|
47949
|
+
if (!channel)
|
|
47950
|
+
fail("Usage: tfa-cli brand voice collect <channel> [--url U | --pasted-file F|-]");
|
|
47951
|
+
let pasted;
|
|
47952
|
+
if (args["pasted-file"]) {
|
|
47953
|
+
const { readFileSync: readFileSync3 } = await import("node:fs");
|
|
47954
|
+
pasted = readFileSync3(args["pasted-file"] === "-" ? 0 : args["pasted-file"], "utf8");
|
|
47955
|
+
}
|
|
47956
|
+
const { sources } = await api.collectVoiceSource(brand.id, channel, { url: args.url, pasted });
|
|
47957
|
+
process.stderr.write(`${GREEN}✅ ${channel} collected (${sources.length} source(s))${RESET}
|
|
47958
|
+
`);
|
|
47959
|
+
return;
|
|
47960
|
+
}
|
|
47961
|
+
if (verb === "remove") {
|
|
47962
|
+
if (!vargs[0])
|
|
47963
|
+
fail("Usage: tfa-cli brand voice remove <channel>");
|
|
47964
|
+
await api.removeVoiceSource(brand.id, vargs[0]);
|
|
47965
|
+
process.stderr.write(`${GREEN}✅ ${vargs[0]} removed${RESET}
|
|
47966
|
+
`);
|
|
47967
|
+
return;
|
|
47968
|
+
}
|
|
47969
|
+
if (verb === "learn") {
|
|
47970
|
+
process.stderr.write(`${DIM}learning voice for ${brand.name}…${RESET}
|
|
47971
|
+
`);
|
|
47972
|
+
const res = await api.refineBrandVoice(brand.id, onboarding.styleAnswers ?? {}, args["from-company"] ? "company" : undefined);
|
|
47973
|
+
if (!res.profile)
|
|
47974
|
+
fail("Nothing to learn from — add answers or collect a source first");
|
|
47975
|
+
const { [brand.id]: _stale, ...styleAiAnswers } = onboarding.styleAiAnswers ?? {};
|
|
47976
|
+
await api.patchOnboarding({
|
|
47977
|
+
voiceProfiles: { ...onboarding.voiceProfiles ?? {}, [brand.id]: { ...res, updatedAt: Date.now() } },
|
|
47978
|
+
styleAiAnswers
|
|
47979
|
+
});
|
|
47980
|
+
if (args.json) {
|
|
47981
|
+
console.log(JSON.stringify(res, null, 2));
|
|
47982
|
+
return;
|
|
47983
|
+
}
|
|
47984
|
+
process.stderr.write(`${GREEN}✅ voice learned (match ${res.match}/100, source ${res.source})${RESET}
|
|
47985
|
+
${res.profile}
|
|
47986
|
+
`);
|
|
47987
|
+
return;
|
|
47988
|
+
}
|
|
47989
|
+
fail(`Unknown 'brand voice' verb: ${verb}`);
|
|
47990
|
+
}
|
|
47991
|
+
function printDeviceHelp() {
|
|
47992
|
+
process.stderr.write(`
|
|
47993
|
+
tfa-cli device — the user's paired machines
|
|
47994
|
+
|
|
47995
|
+
Usage:
|
|
47996
|
+
tfa-cli device list
|
|
47997
|
+
tfa-cli device rename <device> <name> name: [a-zA-Z0-9][a-zA-Z0-9_]*, ≤64
|
|
47998
|
+
tfa-cli device wallpaper <device> auto|off desktop-wallpaper capture (off deletes stored images)
|
|
47999
|
+
|
|
48000
|
+
<device> is an id, name or hostname (unique partial works).
|
|
48001
|
+
exec / reboot / update / unpair / workspace paths are UI-only from an agent shell.
|
|
48002
|
+
`);
|
|
48003
|
+
}
|
|
48004
|
+
async function deviceCommand(api, positionals, args) {
|
|
48005
|
+
const [, sub, query, value] = positionals;
|
|
48006
|
+
const devices = await api.listDevices();
|
|
48007
|
+
if (!sub || sub === "list") {
|
|
48008
|
+
if (args.json) {
|
|
48009
|
+
console.log(JSON.stringify(devices, null, 2));
|
|
48010
|
+
return;
|
|
48011
|
+
}
|
|
48012
|
+
for (const d of devices)
|
|
48013
|
+
process.stderr.write(`${d.status === "ONLINE" ? GREEN + "●" : DIM + "○"}${RESET} ${d.name} ${DIM}${d.deviceType} ${d.metadata?.identity?.hostname ?? ""} ${d.id}${RESET}
|
|
48014
|
+
`);
|
|
48015
|
+
return;
|
|
48016
|
+
}
|
|
48017
|
+
if (!query)
|
|
48018
|
+
fail(`Usage: tfa-cli device ${sub} <device> …`);
|
|
48019
|
+
const q = query.toLowerCase();
|
|
48020
|
+
const hit = devices.filter((d) => d.id === query || d.name.toLowerCase() === q || d.metadata?.identity?.hostname?.toLowerCase() === q);
|
|
48021
|
+
const found = hit.length === 1 ? hit[0] : (() => {
|
|
48022
|
+
const p = devices.filter((d) => d.id.startsWith(query) || d.name.toLowerCase().includes(q) || d.metadata?.identity?.hostname?.toLowerCase().includes(q));
|
|
48023
|
+
if (p.length === 1)
|
|
48024
|
+
return p[0];
|
|
48025
|
+
fail(p.length ? `Ambiguous device '${query}'` : `No device matching '${query}'`);
|
|
48026
|
+
})();
|
|
48027
|
+
if (sub === "rename") {
|
|
48028
|
+
if (!value)
|
|
48029
|
+
fail("Usage: tfa-cli device rename <device> <name>");
|
|
48030
|
+
await api.renameDevice(found.id, value);
|
|
48031
|
+
process.stderr.write(`${GREEN}✅ ${found.name} → ${value}${RESET}
|
|
48032
|
+
`);
|
|
48033
|
+
return;
|
|
48034
|
+
}
|
|
48035
|
+
if (sub === "wallpaper") {
|
|
48036
|
+
if (value !== "auto" && value !== "off")
|
|
48037
|
+
fail("Usage: tfa-cli device wallpaper <device> auto|off");
|
|
48038
|
+
await api.setDeviceWallpaperMode(found.id, value);
|
|
48039
|
+
process.stderr.write(`${GREEN}✅ ${found.name} wallpaper: ${value}${RESET}
|
|
48040
|
+
`);
|
|
48041
|
+
return;
|
|
48042
|
+
}
|
|
48043
|
+
fail(`Unknown 'device' subcommand: ${sub}`);
|
|
48044
|
+
}
|
|
48045
|
+
|
|
47426
48046
|
// src/list-todos.ts
|
|
47427
48047
|
import { parseArgs as parseArgs2 } from "util";
|
|
47428
48048
|
var STATUS_COLOR = {
|
|
@@ -72037,11 +72657,27 @@ Cancelled by user (Ctrl+C)
|
|
|
72037
72657
|
printAgentHelp();
|
|
72038
72658
|
process.exit(0);
|
|
72039
72659
|
}
|
|
72660
|
+
if (positionals[0] === "todo" && args.help) {
|
|
72661
|
+
printTodoHelp();
|
|
72662
|
+
process.exit(0);
|
|
72663
|
+
}
|
|
72664
|
+
if (positionals[0] === "project" && args.help) {
|
|
72665
|
+
printProjectHelp();
|
|
72666
|
+
process.exit(0);
|
|
72667
|
+
}
|
|
72668
|
+
if (positionals[0] === "brand" && args.help) {
|
|
72669
|
+
printBrandHelp();
|
|
72670
|
+
process.exit(0);
|
|
72671
|
+
}
|
|
72672
|
+
if (positionals[0] === "device" && args.help) {
|
|
72673
|
+
printDeviceHelp();
|
|
72674
|
+
process.exit(0);
|
|
72675
|
+
}
|
|
72040
72676
|
if ((positionals[0] === "list" || positionals[0] === "ls") && args.help) {
|
|
72041
72677
|
printListTodosHelp();
|
|
72042
72678
|
process.exit(0);
|
|
72043
72679
|
}
|
|
72044
|
-
if (args.help && !["list", "ls", "agent"].includes(positionals[0])) {
|
|
72680
|
+
if (args.help && !["list", "ls", "agent", "todo", "project", "brand", "device"].includes(positionals[0])) {
|
|
72045
72681
|
printUsage();
|
|
72046
72682
|
process.exit(0);
|
|
72047
72683
|
}
|
|
@@ -72153,6 +72789,22 @@ Cancelled by user (Ctrl+C)
|
|
|
72153
72789
|
`);
|
|
72154
72790
|
return;
|
|
72155
72791
|
}
|
|
72792
|
+
if (positionals[0] === "todo") {
|
|
72793
|
+
await todoCommand(api2, positionals, args);
|
|
72794
|
+
return;
|
|
72795
|
+
}
|
|
72796
|
+
if (positionals[0] === "project") {
|
|
72797
|
+
await projectCommand(api2, positionals, args);
|
|
72798
|
+
return;
|
|
72799
|
+
}
|
|
72800
|
+
if (positionals[0] === "brand") {
|
|
72801
|
+
await brandCommand(api2, positionals, args);
|
|
72802
|
+
return;
|
|
72803
|
+
}
|
|
72804
|
+
if (positionals[0] === "device") {
|
|
72805
|
+
await deviceCommand(api2, positionals, args);
|
|
72806
|
+
return;
|
|
72807
|
+
}
|
|
72156
72808
|
if (positionals[0] === "delete") {
|
|
72157
72809
|
const todoId = positionals[1];
|
|
72158
72810
|
if (!todoId) {
|