@todoforai/cli 0.1.35 → 0.1.37
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 +137 -9
- package/package.json +1 -1
package/dist/todoforai-cli.js
CHANGED
|
@@ -42868,6 +42868,9 @@ class ApiClient {
|
|
|
42868
42868
|
payload.groupTag = groupTag;
|
|
42869
42869
|
if (groupName)
|
|
42870
42870
|
payload.groupName = groupName;
|
|
42871
|
+
const parentTodoId = typeof process !== "undefined" ? process.env?.TODOFORAI_TODO_ID : undefined;
|
|
42872
|
+
if (parentTodoId && parentTodoId !== todoId)
|
|
42873
|
+
payload.parentTodoId = parentTodoId;
|
|
42871
42874
|
return this.request("POST", `/api/v1/projects/${projectId}/todos`, payload);
|
|
42872
42875
|
}
|
|
42873
42876
|
async registerAttachment(file, filename, opts = {}) {
|
|
@@ -42890,8 +42893,8 @@ class ApiClient {
|
|
|
42890
42893
|
form.append("file", file, filename);
|
|
42891
42894
|
form.append("todoId", todoId);
|
|
42892
42895
|
for (const [k, v] of Object.entries(opts))
|
|
42893
|
-
if (v)
|
|
42894
|
-
form.append(k, v);
|
|
42896
|
+
if (v !== undefined && v !== "")
|
|
42897
|
+
form.append(k, String(v));
|
|
42895
42898
|
const url = `${this.apiUrl}${restBasePath(this.apiKey)}/resources/show`;
|
|
42896
42899
|
const res = await fetch(url, {
|
|
42897
42900
|
method: "POST",
|
|
@@ -42929,6 +42932,61 @@ class ApiClient {
|
|
|
42929
42932
|
throw new Error(`API GET /resources/show failed: ${res.status} ${await res.text()}`);
|
|
42930
42933
|
return res.json();
|
|
42931
42934
|
}
|
|
42935
|
+
async pushSite(file, filename, opts = {}) {
|
|
42936
|
+
const form = new FormData;
|
|
42937
|
+
form.append("file", file, filename);
|
|
42938
|
+
for (const [k, v] of Object.entries(opts))
|
|
42939
|
+
if (v !== undefined && v !== "")
|
|
42940
|
+
form.append(k, String(v));
|
|
42941
|
+
const res = await fetch(`${this.apiUrl}${restBasePath(this.apiKey)}/resources/sites`, {
|
|
42942
|
+
method: "POST",
|
|
42943
|
+
headers: { "x-api-key": this.apiKey },
|
|
42944
|
+
body: form,
|
|
42945
|
+
signal: AbortSignal.timeout(120000)
|
|
42946
|
+
});
|
|
42947
|
+
if (!res.ok)
|
|
42948
|
+
throw new Error(`API POST /resources/sites failed: ${res.status} ${await res.text()}`);
|
|
42949
|
+
return res.json();
|
|
42950
|
+
}
|
|
42951
|
+
async listSites() {
|
|
42952
|
+
const res = await fetch(`${this.apiUrl}${restBasePath(this.apiKey)}/resources/sites`, {
|
|
42953
|
+
headers: { "x-api-key": this.apiKey },
|
|
42954
|
+
signal: AbortSignal.timeout(30000)
|
|
42955
|
+
});
|
|
42956
|
+
if (!res.ok)
|
|
42957
|
+
throw new Error(`API GET /resources/sites failed: ${res.status} ${await res.text()}`);
|
|
42958
|
+
return res.json();
|
|
42959
|
+
}
|
|
42960
|
+
async getSiteBytes(siteId, version) {
|
|
42961
|
+
const qs = version ? `?version=${encodeURIComponent(version)}` : "";
|
|
42962
|
+
const res = await fetch(`${this.apiUrl}${restBasePath(this.apiKey)}/resources/sites/${siteId}/bytes${qs}`, {
|
|
42963
|
+
headers: { "x-api-key": this.apiKey },
|
|
42964
|
+
signal: AbortSignal.timeout(120000)
|
|
42965
|
+
});
|
|
42966
|
+
if (!res.ok)
|
|
42967
|
+
throw new Error(`API GET site bytes failed: ${res.status} ${await res.text()}`);
|
|
42968
|
+
return res.arrayBuffer();
|
|
42969
|
+
}
|
|
42970
|
+
async patchSite(siteId, body) {
|
|
42971
|
+
const res = await fetch(`${this.apiUrl}${restBasePath(this.apiKey)}/resources/sites/${siteId}`, {
|
|
42972
|
+
method: "PATCH",
|
|
42973
|
+
headers: { "x-api-key": this.apiKey, "Content-Type": "application/json" },
|
|
42974
|
+
body: JSON.stringify(body),
|
|
42975
|
+
signal: AbortSignal.timeout(30000)
|
|
42976
|
+
});
|
|
42977
|
+
if (!res.ok)
|
|
42978
|
+
throw new Error(`API PATCH site failed: ${res.status} ${await res.text()}`);
|
|
42979
|
+
return res.json();
|
|
42980
|
+
}
|
|
42981
|
+
async deleteSite(siteId) {
|
|
42982
|
+
const res = await fetch(`${this.apiUrl}${restBasePath(this.apiKey)}/resources/sites/${siteId}`, {
|
|
42983
|
+
method: "DELETE",
|
|
42984
|
+
headers: { "x-api-key": this.apiKey },
|
|
42985
|
+
signal: AbortSignal.timeout(30000)
|
|
42986
|
+
});
|
|
42987
|
+
if (!res.ok)
|
|
42988
|
+
throw new Error(`API DELETE site failed: ${res.status} ${await res.text()}`);
|
|
42989
|
+
}
|
|
42932
42990
|
async upsertCard(projectId, name, html, opts = {}) {
|
|
42933
42991
|
const form = new FormData;
|
|
42934
42992
|
form.append("file", html, `${name}.html`);
|
|
@@ -43425,9 +43483,9 @@ var mimetypes_default = {
|
|
|
43425
43483
|
doc: { mime: "application/msword", type: "document" },
|
|
43426
43484
|
docx: { mime: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", type: "document", tags: ["docx"] },
|
|
43427
43485
|
ppt: { mime: "application/vnd.ms-powerpoint", type: "document" },
|
|
43428
|
-
pptx: { mime: "application/vnd.openxmlformats-officedocument.presentationml.presentation", type: "document" },
|
|
43486
|
+
pptx: { mime: "application/vnd.openxmlformats-officedocument.presentationml.presentation", type: "document", tags: ["pptx"] },
|
|
43429
43487
|
xls: { mime: "application/vnd.ms-excel", type: "spreadsheet" },
|
|
43430
|
-
xlsx: { mime: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", type: "spreadsheet" },
|
|
43488
|
+
xlsx: { mime: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", type: "spreadsheet", tags: ["xlsx"] },
|
|
43431
43489
|
zip: { mime: "application/zip", type: "archive" },
|
|
43432
43490
|
rar: { mime: "application/vnd.rar", type: "archive" },
|
|
43433
43491
|
tar: { mime: "application/x-tar", type: "archive" },
|
|
@@ -44127,8 +44185,39 @@ var OUTPUT_POLICIES = {
|
|
|
44127
44185
|
raw: { firstLimit: Infinity, lastLimit: 0, hardCap: Infinity, lineLimit: Infinity }
|
|
44128
44186
|
};
|
|
44129
44187
|
// ../packages/shared-fbe/src/toolInstallCommand.ts
|
|
44130
|
-
var PYTHON_MIN_MINOR =
|
|
44188
|
+
var PYTHON_MIN_MINOR = 11;
|
|
44131
44189
|
var PYTHON_VERSION_CHECK = `-c 'import sys; sys.exit(0 if sys.version_info[:2] >= (3, ${PYTHON_MIN_MINOR}) else 1)'`;
|
|
44190
|
+
// ../packages/shared-fbe/src/model_promos.json
|
|
44191
|
+
var model_promos_default = {
|
|
44192
|
+
_doc: [
|
|
44193
|
+
"Single source of truth for TODOforAI promotional model discounts.",
|
|
44194
|
+
"Consumed by frontend (display, bundled via getModelDiscount) and served by backend at GET /public/v1/model-promos, which the agent fetches at startup (billing: model_promos.jl).",
|
|
44195
|
+
"`family` is a regex on the normalized model id (last path segment, lowercase, dots\u2192dashes, '(level)' suffix stripped);",
|
|
44196
|
+
"'(-\\\\d+)*' trailing point versions are appended by the consumer, so 'claude-opus-5' covers claude-opus-5.2 too.",
|
|
44197
|
+
"`provider` matches the provider name instead (TODO GO / Ollama Cloud, subscription-wide).",
|
|
44198
|
+
"`rate` = fraction off. `boostable:false` = the Ultra/Team promo boost (halves the remaining price) is NOT applied.",
|
|
44199
|
+
"`ends` is the last inclusive day (UTC).",
|
|
44200
|
+
"A change here goes live with a backend + frontend deploy; agent/src/assets/model_promos.json is only the agent's offline fallback, refresh it occasionally."
|
|
44201
|
+
],
|
|
44202
|
+
boost_remaining_price_factor: 0.5,
|
|
44203
|
+
promos: [
|
|
44204
|
+
{ family: "claude-fable-5", rate: 0.3, starts: "2026-06-29", ends: "2026-09-15", boostable: false },
|
|
44205
|
+
{ family: "claude-opus-5", rate: 0.85, starts: "2026-06-29", ends: "2026-09-15" },
|
|
44206
|
+
{ family: "claude-opus-4-[78]", rate: 0.85, starts: "2026-06-29", ends: "2026-09-15" },
|
|
44207
|
+
{ family: "claude-sonnet-5", rate: 0.85, starts: "2026-06-29", ends: "2026-09-15" },
|
|
44208
|
+
{ family: "claude-haiku-4-5", rate: 0.85, starts: "2026-06-29", ends: "2026-09-15" },
|
|
44209
|
+
{ family: "claude-haiku-5", rate: 0.85, starts: "2026-06-29", ends: "2026-09-15" },
|
|
44210
|
+
{ family: "gpt-5-5(-pro)?", rate: 0.85, starts: "2026-06-29", ends: "2026-09-15" },
|
|
44211
|
+
{ family: "gpt-5-6-sol", rate: 0.9, starts: "2026-08-26", ends: "2026-11-21" },
|
|
44212
|
+
{ family: "gpt-5-6-terra", rate: 0.85, starts: "2026-06-29", ends: "2026-09-15" },
|
|
44213
|
+
{ family: "gpt-5-6-luna", rate: 0.85, starts: "2026-06-29", ends: "2026-09-15" },
|
|
44214
|
+
{ provider: "opencode[_ -]?go|ollama[_ -]?cloud", rate: 0.5, starts: "2026-06-29", ends: "2026-09-15" }
|
|
44215
|
+
]
|
|
44216
|
+
};
|
|
44217
|
+
|
|
44218
|
+
// ../packages/shared-fbe/src/modelPromos.ts
|
|
44219
|
+
var BOOST_FACTOR = model_promos_default.boost_remaining_price_factor;
|
|
44220
|
+
var MODEL_PROMOS = model_promos_default.promos;
|
|
44132
44221
|
// ../packages/shared-fbe/src/realtime/topics.ts
|
|
44133
44222
|
var TOPICS = {
|
|
44134
44223
|
["todo:new" /* NEW_TODO */]: {
|
|
@@ -44269,7 +44358,7 @@ import { parseArgs } from "util";
|
|
|
44269
44358
|
// package.json
|
|
44270
44359
|
var package_default = {
|
|
44271
44360
|
name: "@todoforai/cli",
|
|
44272
|
-
version: "0.1.
|
|
44361
|
+
version: "0.1.37",
|
|
44273
44362
|
type: "module",
|
|
44274
44363
|
bin: {
|
|
44275
44364
|
"todoforai-cli": "bin/todoforai-cli.js",
|
|
@@ -44329,6 +44418,12 @@ Usage:
|
|
|
44329
44418
|
tfa-cli show <file|-> [todo-id] # Show a file in the chat (rendered by mimetype; - reads stdin)
|
|
44330
44419
|
# [--title T] [--alias A] [--mime M] [--card <name>] [--link] [--json]
|
|
44331
44420
|
# --link = compact chip (name+size+download) instead of inline render
|
|
44421
|
+
# The bytes get a stable, versioned site id (printed). --site <id>
|
|
44422
|
+
# pushes a new version of an existing one (from any todo);
|
|
44423
|
+
# --public serves the latest at sites.todofor.ai/<id>
|
|
44424
|
+
tfa-cli show public <site-id> [--off] # Publish / unpublish a shown file
|
|
44425
|
+
tfa-cli show get <site-id> [out] [--rev <att>] # Fetch its bytes (latest, or a given version)
|
|
44426
|
+
tfa-cli show rm <site-id> # Delete it and all its versions
|
|
44332
44427
|
tfa-cli show list [todo-id] # List show blocks (ref, title, mime/url, card)
|
|
44333
44428
|
# [--project <id>] [--card <name>] [--json]
|
|
44334
44429
|
# no todo-id + --project (or $TODOFORAI_PROJECT_ID) = every todo
|
|
@@ -44422,6 +44517,10 @@ function parseCliArgs() {
|
|
|
44422
44517
|
mime: { type: "string" },
|
|
44423
44518
|
card: { type: "string" },
|
|
44424
44519
|
link: { type: "boolean", default: false },
|
|
44520
|
+
site: { type: "string" },
|
|
44521
|
+
public: { type: "boolean", default: false },
|
|
44522
|
+
rev: { type: "string" },
|
|
44523
|
+
off: { type: "boolean", default: false },
|
|
44425
44524
|
direction: { type: "string" },
|
|
44426
44525
|
"business-context": { type: "string" },
|
|
44427
44526
|
seed: { type: "string" },
|
|
@@ -47606,11 +47705,38 @@ Cancelled by user (Ctrl+C)
|
|
|
47606
47705
|
}
|
|
47607
47706
|
return;
|
|
47608
47707
|
}
|
|
47708
|
+
if (positionals[0] === "show" && ["public", "get", "rm"].includes(positionals[1] ?? "")) {
|
|
47709
|
+
const sub = positionals[1];
|
|
47710
|
+
const id = positionals[2];
|
|
47711
|
+
if (!id) {
|
|
47712
|
+
process.stderr.write(`${RED}Usage: tfa-cli show public <site-id> [--off] | get <site-id> [out] [--rev <att>] | rm <site-id>${RESET}
|
|
47713
|
+
`);
|
|
47714
|
+
process.exit(2);
|
|
47715
|
+
}
|
|
47716
|
+
if (sub === "public") {
|
|
47717
|
+
const site = await api.patchSite(id, { isPublic: !args.off });
|
|
47718
|
+
console.log(site.url ?? `${site.id} (private)`);
|
|
47719
|
+
} else if (sub === "rm") {
|
|
47720
|
+
await api.deleteSite(id);
|
|
47721
|
+
process.stderr.write(`${GREEN}\u2705 deleted ${id}${RESET}
|
|
47722
|
+
`);
|
|
47723
|
+
} else {
|
|
47724
|
+
const bytes = await api.getSiteBytes(id, args.rev);
|
|
47725
|
+
const out = positionals[3];
|
|
47726
|
+
if (out && out !== "-") {
|
|
47727
|
+
await Bun.write(resolve3(out), bytes);
|
|
47728
|
+
process.stderr.write(`${GREEN}\u2705 ${out}${RESET}
|
|
47729
|
+
`);
|
|
47730
|
+
} else
|
|
47731
|
+
process.stdout.write(new Uint8Array(bytes));
|
|
47732
|
+
}
|
|
47733
|
+
return;
|
|
47734
|
+
}
|
|
47609
47735
|
if (positionals[0] === "show") {
|
|
47610
47736
|
const [, filePath, todoArg] = positionals;
|
|
47611
47737
|
const todoId = todoArg || getEnv("TODO_ID") || cfgScope.data.last_todo_id;
|
|
47612
47738
|
if (!filePath || !todoId) {
|
|
47613
|
-
process.stderr.write(`${RED}Usage: tfa-cli show <file|-> [todo-id] [--title T] [--alias A] [--mime M] [--card <name>] [--link]${RESET}
|
|
47739
|
+
process.stderr.write(`${RED}Usage: tfa-cli show <file|-> [todo-id] [--title T] [--alias A] [--mime M] [--card <name>] [--link] [--site <id>] [--public]${RESET}
|
|
47614
47740
|
`);
|
|
47615
47741
|
process.exit(2);
|
|
47616
47742
|
}
|
|
@@ -47638,12 +47764,14 @@ Cancelled by user (Ctrl+C)
|
|
|
47638
47764
|
alias: args.alias,
|
|
47639
47765
|
mime: args.mime,
|
|
47640
47766
|
card: args.card,
|
|
47641
|
-
display: args.link ? "link" : undefined
|
|
47767
|
+
display: args.link ? "link" : undefined,
|
|
47768
|
+
site: args.site,
|
|
47769
|
+
public: args.public ? true : undefined
|
|
47642
47770
|
});
|
|
47643
47771
|
if (args.json)
|
|
47644
47772
|
console.log(JSON.stringify(res, null, 2));
|
|
47645
47773
|
else
|
|
47646
|
-
console.log(res.ref);
|
|
47774
|
+
console.log(res.siteUrl ? `${res.ref} site=${res.siteId} ${res.siteUrl}` : `${res.ref} site=${res.siteId}`);
|
|
47647
47775
|
return;
|
|
47648
47776
|
}
|
|
47649
47777
|
if (positionals[0] === "open") {
|