@sunasteriskrnd/takumi 0.11.0 → 0.12.1
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/index.js +209 -31
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -19815,7 +19815,7 @@ var package_default;
|
|
|
19815
19815
|
var init_package = __esm(() => {
|
|
19816
19816
|
package_default = {
|
|
19817
19817
|
name: "@sunasteriskrnd/takumi",
|
|
19818
|
-
version: "0.
|
|
19818
|
+
version: "0.12.1",
|
|
19819
19819
|
description: "CLI tool for bootstrapping and managing Takumi projects",
|
|
19820
19820
|
type: "module",
|
|
19821
19821
|
repository: {
|
|
@@ -39263,7 +39263,7 @@ async function installSkillsDependencies(skillsDir, options2 = {}) {
|
|
|
39263
39263
|
let effectiveSkillsDir = skillsDir;
|
|
39264
39264
|
if (!existsSync8(scriptPath)) {
|
|
39265
39265
|
const { homedir: homedir6 } = await import("node:os");
|
|
39266
|
-
const globalSkillsDir = join38(homedir6(), ".claude", "skills");
|
|
39266
|
+
const globalSkillsDir = process.env.TKM_GLOBAL_SKILLS_DIR ?? join38(homedir6(), ".claude", "skills");
|
|
39267
39267
|
const globalScriptPath = join38(globalSkillsDir, scriptName);
|
|
39268
39268
|
if (existsSync8(globalScriptPath)) {
|
|
39269
39269
|
logger.debug(`Local install script not found, using global: ${globalScriptPath}`);
|
|
@@ -51332,6 +51332,82 @@ var init_auth_command_help = __esm(() => {
|
|
|
51332
51332
|
};
|
|
51333
51333
|
});
|
|
51334
51334
|
|
|
51335
|
+
// src/domains/help/commands/artifact-command-help.ts
|
|
51336
|
+
var artifactCommandHelp;
|
|
51337
|
+
var init_artifact_command_help = __esm(() => {
|
|
51338
|
+
artifactCommandHelp = {
|
|
51339
|
+
name: "artifact",
|
|
51340
|
+
description: "Upload, download, and delete Takumi artifacts (upload|download|delete)",
|
|
51341
|
+
usage: "tkm artifact <upload <file|dir> | download <uuid|url> | delete <uuid|url>>",
|
|
51342
|
+
examples: [
|
|
51343
|
+
{
|
|
51344
|
+
command: "tkm artifact upload ./report.html --title 'Weekly Report'",
|
|
51345
|
+
description: "Upload a file (or directory) as a new artifact and print its share URL"
|
|
51346
|
+
},
|
|
51347
|
+
{
|
|
51348
|
+
command: "tkm artifact download <uuid|url> -o ./out --ver 3",
|
|
51349
|
+
description: "Download a specific version's files into a directory"
|
|
51350
|
+
},
|
|
51351
|
+
{
|
|
51352
|
+
command: "tkm artifact delete <uuid|url> --ver 2",
|
|
51353
|
+
description: "Delete ONLY version 2 (soft delete; other versions stay). A pasted URL with ?v=2 does the same"
|
|
51354
|
+
}
|
|
51355
|
+
],
|
|
51356
|
+
optionGroups: [
|
|
51357
|
+
{
|
|
51358
|
+
title: "Actions",
|
|
51359
|
+
options: [
|
|
51360
|
+
{
|
|
51361
|
+
flags: "upload <file|dir>",
|
|
51362
|
+
description: "Upload a file or directory as a new artifact (or new version with --id)"
|
|
51363
|
+
},
|
|
51364
|
+
{
|
|
51365
|
+
flags: "download <uuid|url>",
|
|
51366
|
+
description: "Download an artifact's files (latest or --ver <n>)"
|
|
51367
|
+
},
|
|
51368
|
+
{
|
|
51369
|
+
flags: "delete <uuid|url>",
|
|
51370
|
+
description: "Soft-delete the whole artifact, or one version with --ver <n>"
|
|
51371
|
+
}
|
|
51372
|
+
]
|
|
51373
|
+
},
|
|
51374
|
+
{
|
|
51375
|
+
title: "Options",
|
|
51376
|
+
options: [
|
|
51377
|
+
{
|
|
51378
|
+
flags: "--id <uuid|url>",
|
|
51379
|
+
description: "(upload) Existing artifact to overwrite with a new version"
|
|
51380
|
+
},
|
|
51381
|
+
{
|
|
51382
|
+
flags: "--title <title>",
|
|
51383
|
+
description: "(upload) Display title for the artifact (max 200 chars)"
|
|
51384
|
+
},
|
|
51385
|
+
{
|
|
51386
|
+
flags: "-m, --message <message>",
|
|
51387
|
+
description: "(upload) Short note describing this version's change (max 100 chars)"
|
|
51388
|
+
},
|
|
51389
|
+
{
|
|
51390
|
+
flags: "-o, --output <dir>",
|
|
51391
|
+
description: "(download) Output directory; default: slug(title) or uuid in CWD"
|
|
51392
|
+
},
|
|
51393
|
+
{
|
|
51394
|
+
flags: "--ver <n>",
|
|
51395
|
+
description: "(download) Version to download | (delete) version to delete. ?v=<n> in a pasted URL works too; --ver wins when both given"
|
|
51396
|
+
},
|
|
51397
|
+
{
|
|
51398
|
+
flags: "--force",
|
|
51399
|
+
description: "(download) Allow writing into a non-empty directory"
|
|
51400
|
+
},
|
|
51401
|
+
{
|
|
51402
|
+
flags: "-y, --yes",
|
|
51403
|
+
description: "(delete) Skip the confirmation prompt"
|
|
51404
|
+
}
|
|
51405
|
+
]
|
|
51406
|
+
}
|
|
51407
|
+
]
|
|
51408
|
+
};
|
|
51409
|
+
});
|
|
51410
|
+
|
|
51335
51411
|
// src/domains/help/commands/index.ts
|
|
51336
51412
|
var init_commands2 = __esm(() => {
|
|
51337
51413
|
init_init_command_help();
|
|
@@ -51341,6 +51417,7 @@ var init_commands2 = __esm(() => {
|
|
|
51341
51417
|
init_versions_command_help();
|
|
51342
51418
|
init_config_command_help();
|
|
51343
51419
|
init_auth_command_help();
|
|
51420
|
+
init_artifact_command_help();
|
|
51344
51421
|
init_common_options();
|
|
51345
51422
|
});
|
|
51346
51423
|
|
|
@@ -51359,7 +51436,8 @@ var init_help_commands = __esm(() => {
|
|
|
51359
51436
|
versions: versionsCommandHelp,
|
|
51360
51437
|
doctor: doctorCommandHelp,
|
|
51361
51438
|
uninstall: uninstallCommandHelp,
|
|
51362
|
-
auth: authCommandHelp
|
|
51439
|
+
auth: authCommandHelp,
|
|
51440
|
+
artifact: artifactCommandHelp
|
|
51363
51441
|
};
|
|
51364
51442
|
});
|
|
51365
51443
|
|
|
@@ -53547,6 +53625,27 @@ async function remove9(token, uuid) {
|
|
|
53547
53625
|
throw new ArtifactApiError(res.status, `Delete failed (HTTP ${res.status}): ${msg}`);
|
|
53548
53626
|
}
|
|
53549
53627
|
}
|
|
53628
|
+
async function removeVersion(token, uuid, version3) {
|
|
53629
|
+
const base = getServerUrl();
|
|
53630
|
+
const res = await fetch(`${base}/api/artifacts/${encodeURIComponent(uuid)}/versions/${encodeURIComponent(String(version3))}`, {
|
|
53631
|
+
method: "DELETE",
|
|
53632
|
+
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" }
|
|
53633
|
+
});
|
|
53634
|
+
if (!res.ok) {
|
|
53635
|
+
const msg = await parseErrorMessage(res);
|
|
53636
|
+
throw new ArtifactApiError(res.status, `Delete version failed (HTTP ${res.status}): ${msg}`);
|
|
53637
|
+
}
|
|
53638
|
+
try {
|
|
53639
|
+
return await res.json();
|
|
53640
|
+
} catch {
|
|
53641
|
+
return {
|
|
53642
|
+
ok: true,
|
|
53643
|
+
deleted_version: undefined,
|
|
53644
|
+
live_version: undefined,
|
|
53645
|
+
shared_version: undefined
|
|
53646
|
+
};
|
|
53647
|
+
}
|
|
53648
|
+
}
|
|
53550
53649
|
async function getManifest(token, uuid, version3) {
|
|
53551
53650
|
const base = getServerUrl();
|
|
53552
53651
|
const qs = version3 !== undefined ? `?v=${encodeURIComponent(String(version3))}` : "";
|
|
@@ -53680,6 +53779,17 @@ function parseArtifactRef(input) {
|
|
|
53680
53779
|
const candidate = m2?.[1] ?? "";
|
|
53681
53780
|
return UUID_V4_RE.test(candidate) ? candidate.toLowerCase() : null;
|
|
53682
53781
|
}
|
|
53782
|
+
function extractVersionFromRef(ref) {
|
|
53783
|
+
try {
|
|
53784
|
+
const url = new URL(ref.trim());
|
|
53785
|
+
const v2 = url.searchParams.get("v");
|
|
53786
|
+
if (v2 !== null) {
|
|
53787
|
+
const n = Number.parseInt(v2, 10);
|
|
53788
|
+
return Number.isFinite(n) && n > 0 ? n : undefined;
|
|
53789
|
+
}
|
|
53790
|
+
} catch {}
|
|
53791
|
+
return;
|
|
53792
|
+
}
|
|
53683
53793
|
function warnIfHostMismatch(input) {
|
|
53684
53794
|
let inputUrl;
|
|
53685
53795
|
try {
|
|
@@ -53710,6 +53820,11 @@ async function artifactDelete(ref, opts) {
|
|
|
53710
53820
|
const token = await getToken(opts);
|
|
53711
53821
|
if (!token)
|
|
53712
53822
|
return;
|
|
53823
|
+
const version3 = opts.version !== undefined ? opts.version : extractVersionFromRef(ref);
|
|
53824
|
+
if (version3 !== undefined) {
|
|
53825
|
+
await deleteVersion(uuid, version3, token, opts);
|
|
53826
|
+
return;
|
|
53827
|
+
}
|
|
53713
53828
|
if (!opts.yes) {
|
|
53714
53829
|
const confirmed = await se({
|
|
53715
53830
|
message: `Delete artifact ${uuid}? This cannot be undone.`,
|
|
@@ -53730,6 +53845,36 @@ async function artifactDelete(ref, opts) {
|
|
|
53730
53845
|
await removeEntry(uuid);
|
|
53731
53846
|
console.log(`Deleted artifact ${uuid}.`);
|
|
53732
53847
|
}
|
|
53848
|
+
async function deleteVersion(uuid, version3, token, opts) {
|
|
53849
|
+
if (!opts.yes) {
|
|
53850
|
+
const confirmed = await se({
|
|
53851
|
+
message: `Delete version ${version3} of artifact ${uuid}? This cannot be undone.`,
|
|
53852
|
+
initialValue: false
|
|
53853
|
+
});
|
|
53854
|
+
if (lD(confirmed) || !confirmed) {
|
|
53855
|
+
console.log("Cancelled.");
|
|
53856
|
+
return;
|
|
53857
|
+
}
|
|
53858
|
+
}
|
|
53859
|
+
try {
|
|
53860
|
+
const result = await removeVersion(token, uuid, version3);
|
|
53861
|
+
if (result.live_version !== undefined) {
|
|
53862
|
+
console.log(`Deleted version ${version3} of artifact ${uuid}. Live version is now ${result.live_version}.`);
|
|
53863
|
+
} else {
|
|
53864
|
+
console.log(`Deleted version ${version3} of artifact ${uuid}.`);
|
|
53865
|
+
}
|
|
53866
|
+
} catch (err) {
|
|
53867
|
+
if (err instanceof ArtifactApiError && isCannotDeleteLastVersion(err)) {
|
|
53868
|
+
console.error(`Error: cannot delete version ${version3} — it is the last remaining version. ` + `Delete the whole artifact instead: tkm artifact delete ${uuid}`);
|
|
53869
|
+
} else {
|
|
53870
|
+
printApiError(err);
|
|
53871
|
+
}
|
|
53872
|
+
process.exitCode = 1;
|
|
53873
|
+
}
|
|
53874
|
+
}
|
|
53875
|
+
function isCannotDeleteLastVersion(err) {
|
|
53876
|
+
return err.status === 409 && err.message.includes("cannot_delete_last_version");
|
|
53877
|
+
}
|
|
53733
53878
|
|
|
53734
53879
|
// src/commands/artifact/download-command.ts
|
|
53735
53880
|
import { promises as fs11 } from "node:fs";
|
|
@@ -53797,6 +53942,11 @@ var EXT_TO_MIME = {
|
|
|
53797
53942
|
html: "text/html",
|
|
53798
53943
|
htm: "text/html",
|
|
53799
53944
|
md: "text/markdown",
|
|
53945
|
+
mmd: "text/vnd.mermaid",
|
|
53946
|
+
yaml: "application/yaml",
|
|
53947
|
+
yml: "application/yaml",
|
|
53948
|
+
csv: "text/csv",
|
|
53949
|
+
tsv: "text/tab-separated-values",
|
|
53800
53950
|
txt: "text/plain",
|
|
53801
53951
|
css: "text/css",
|
|
53802
53952
|
js: "text/javascript",
|
|
@@ -53905,17 +54055,6 @@ function deriveSlug(title, uuid) {
|
|
|
53905
54055
|
const slug = (title ?? "").trim().replace(/[/\\:*?"<>|.]/g, " ").split("").map((c2) => c2.charCodeAt(0) < 32 ? " " : c2).join("").replace(/\s+/g, "-").replace(/^[.\-]+|[.\-]+$/g, "").slice(0, 80);
|
|
53906
54056
|
return slug || uuid;
|
|
53907
54057
|
}
|
|
53908
|
-
function extractVersionFromRef(ref) {
|
|
53909
|
-
try {
|
|
53910
|
-
const url = new URL(ref.trim());
|
|
53911
|
-
const v2 = url.searchParams.get("v");
|
|
53912
|
-
if (v2 !== null) {
|
|
53913
|
-
const n = Number.parseInt(v2, 10);
|
|
53914
|
-
return Number.isFinite(n) && n > 0 ? n : undefined;
|
|
53915
|
-
}
|
|
53916
|
-
} catch {}
|
|
53917
|
-
return;
|
|
53918
|
-
}
|
|
53919
54058
|
async function artifactDownload(ref, opts) {
|
|
53920
54059
|
const uuid = parseArtifactRef(ref);
|
|
53921
54060
|
if (!uuid) {
|
|
@@ -54005,9 +54144,13 @@ import { promises as fs13 } from "node:fs";
|
|
|
54005
54144
|
import { basename as basename12, extname as extname5, resolve as resolve16 } from "node:path";
|
|
54006
54145
|
|
|
54007
54146
|
// src/domains/artifact/folder-walk.ts
|
|
54147
|
+
var import_ignore3 = __toESM(require_ignore(), 1);
|
|
54008
54148
|
import { promises as fs12 } from "node:fs";
|
|
54009
54149
|
import { join as join72, relative as relative14 } from "node:path";
|
|
54010
54150
|
var MAX_FILE_BYTES = 20 * 1024 * 1024;
|
|
54151
|
+
var IGNORE_FILES = [".gitignore", ".tkmignore"];
|
|
54152
|
+
var HARD_IGNORES = [".git", ".gitignore", ".tkmignore"];
|
|
54153
|
+
var HARD_IGNORE_NAMES = new Set(HARD_IGNORES);
|
|
54011
54154
|
|
|
54012
54155
|
class FolderLimitError extends Error {
|
|
54013
54156
|
constructor(message) {
|
|
@@ -54015,9 +54158,23 @@ class FolderLimitError extends Error {
|
|
|
54015
54158
|
this.name = "FolderLimitError";
|
|
54016
54159
|
}
|
|
54017
54160
|
}
|
|
54018
|
-
async function
|
|
54161
|
+
async function buildIgnoreMatcher(rootDir) {
|
|
54162
|
+
const ig = import_ignore3.default();
|
|
54163
|
+
for (const file of IGNORE_FILES) {
|
|
54164
|
+
try {
|
|
54165
|
+
ig.add(await fs12.readFile(join72(rootDir, file), "utf8"));
|
|
54166
|
+
} catch {}
|
|
54167
|
+
}
|
|
54168
|
+
ig.add(HARD_IGNORES);
|
|
54169
|
+
return ig;
|
|
54170
|
+
}
|
|
54171
|
+
async function walkFolder(rootDir, skipped) {
|
|
54172
|
+
const ig = await buildIgnoreMatcher(rootDir);
|
|
54019
54173
|
const entries = [];
|
|
54020
|
-
|
|
54174
|
+
const collectedSkips = [];
|
|
54175
|
+
await walk(rootDir, rootDir, ig, entries, collectedSkips);
|
|
54176
|
+
if (skipped)
|
|
54177
|
+
skipped.push(...collectedSkips);
|
|
54021
54178
|
entries.sort((a3, b3) => a3.relPath.localeCompare(b3.relPath));
|
|
54022
54179
|
const oversized = entries.find((e2) => e2.size > MAX_FILE_BYTES);
|
|
54023
54180
|
if (oversized) {
|
|
@@ -54026,7 +54183,7 @@ async function walkFolder(rootDir) {
|
|
|
54026
54183
|
}
|
|
54027
54184
|
return entries;
|
|
54028
54185
|
}
|
|
54029
|
-
async function walk(rootDir, dir, out) {
|
|
54186
|
+
async function walk(rootDir, dir, ig, out, skipped) {
|
|
54030
54187
|
let dirents;
|
|
54031
54188
|
try {
|
|
54032
54189
|
dirents = await fs12.readdir(dir, { withFileTypes: true });
|
|
@@ -54038,11 +54195,21 @@ async function walk(rootDir, dir, out) {
|
|
|
54038
54195
|
continue;
|
|
54039
54196
|
const name = String(dirent.name);
|
|
54040
54197
|
const absPath = join72(dir, name);
|
|
54198
|
+
const relPath = relative14(rootDir, absPath).split("\\").join("/");
|
|
54041
54199
|
if (dirent.isDirectory()) {
|
|
54042
|
-
|
|
54200
|
+
if (ig.ignores(`${relPath}/`)) {
|
|
54201
|
+
if (!HARD_IGNORE_NAMES.has(name))
|
|
54202
|
+
skipped.push(`${relPath}/`);
|
|
54203
|
+
continue;
|
|
54204
|
+
}
|
|
54205
|
+
await walk(rootDir, absPath, ig, out, skipped);
|
|
54043
54206
|
} else if (dirent.isFile()) {
|
|
54207
|
+
if (ig.ignores(relPath)) {
|
|
54208
|
+
if (!HARD_IGNORE_NAMES.has(name))
|
|
54209
|
+
skipped.push(relPath);
|
|
54210
|
+
continue;
|
|
54211
|
+
}
|
|
54044
54212
|
const stat8 = await fs12.stat(absPath);
|
|
54045
|
-
const relPath = relative14(rootDir, absPath).split("\\").join("/");
|
|
54046
54213
|
out.push({ absPath, relPath, size: stat8.size });
|
|
54047
54214
|
}
|
|
54048
54215
|
}
|
|
@@ -54186,8 +54353,9 @@ async function uploadFolder(absPath, displayPath, token, opts) {
|
|
|
54186
54353
|
const spinner = de();
|
|
54187
54354
|
spinner.start(`Scanning ${displayPath}…`);
|
|
54188
54355
|
let entries;
|
|
54356
|
+
const skippedPaths = [];
|
|
54189
54357
|
try {
|
|
54190
|
-
entries = await walkFolder(absPath);
|
|
54358
|
+
entries = await walkFolder(absPath, skippedPaths);
|
|
54191
54359
|
} catch (err) {
|
|
54192
54360
|
spinner.stop("Scan failed.", 1);
|
|
54193
54361
|
if (err instanceof FolderLimitError) {
|
|
@@ -54204,6 +54372,11 @@ async function uploadFolder(absPath, displayPath, token, opts) {
|
|
|
54204
54372
|
process.exitCode = 1;
|
|
54205
54373
|
return;
|
|
54206
54374
|
}
|
|
54375
|
+
if (skippedPaths.length > 0) {
|
|
54376
|
+
const preview = skippedPaths.slice(0, 5).join(", ");
|
|
54377
|
+
const more = skippedPaths.length > 5 ? `, +${skippedPaths.length - 5} more` : "";
|
|
54378
|
+
console.warn(`Skipped ${skippedPaths.length} path(s) matched by .gitignore/.tkmignore: ${preview}${more}`);
|
|
54379
|
+
}
|
|
54207
54380
|
let files;
|
|
54208
54381
|
let folderHash;
|
|
54209
54382
|
try {
|
|
@@ -54306,16 +54479,16 @@ async function artifactCommand(action, target, opts) {
|
|
|
54306
54479
|
break;
|
|
54307
54480
|
case "download":
|
|
54308
54481
|
if (!target)
|
|
54309
|
-
return usageError("tkm artifact download <uuid|url> [-o <dir>] [
|
|
54482
|
+
return usageError("tkm artifact download <uuid|url> [-o <dir>] [--ver <n>] [--force]");
|
|
54310
54483
|
await artifactDownload(target, opts);
|
|
54311
54484
|
break;
|
|
54312
54485
|
case "delete":
|
|
54313
54486
|
if (!target)
|
|
54314
|
-
return usageError("tkm artifact delete <uuid|url>");
|
|
54487
|
+
return usageError("tkm artifact delete <uuid|url> [--ver <n>]");
|
|
54315
54488
|
await artifactDelete(target, opts);
|
|
54316
54489
|
break;
|
|
54317
54490
|
case undefined:
|
|
54318
|
-
usageError("tkm artifact <upload <file> | download <uuid|url> | delete <uuid|url
|
|
54491
|
+
usageError("tkm artifact <upload <file> | download <uuid|url> | delete <uuid|url> [--ver <n>]>");
|
|
54319
54492
|
break;
|
|
54320
54493
|
default:
|
|
54321
54494
|
console.error(`Unknown artifact action: ${action}. Available: upload, download, delete`);
|
|
@@ -60842,7 +61015,7 @@ function detectBroadGlob(pattern, pathHint) {
|
|
|
60842
61015
|
}
|
|
60843
61016
|
|
|
60844
61017
|
// src/domains/hooks/handlers/guard-breadth-scout/check-ignore.ts
|
|
60845
|
-
var
|
|
61018
|
+
var import_ignore4 = __toESM(require_ignore(), 1);
|
|
60846
61019
|
import { existsSync as existsSync44, readFileSync as readFileSync13 } from "node:fs";
|
|
60847
61020
|
import { dirname as dirname24, join as join93 } from "node:path";
|
|
60848
61021
|
var BUILTIN_HEAVY_DIR_LINES = [
|
|
@@ -60903,7 +61076,7 @@ function cleanLines(lines) {
|
|
|
60903
61076
|
}
|
|
60904
61077
|
function buildIgnoreConfig(lines, sourceLabel) {
|
|
60905
61078
|
const cleaned = cleanLines(lines);
|
|
60906
|
-
const ig =
|
|
61079
|
+
const ig = import_ignore4.default().add(cleaned);
|
|
60907
61080
|
const patterns = cleaned.filter((line) => !line.startsWith("!"));
|
|
60908
61081
|
return { ig, patterns, sourceLabel };
|
|
60909
61082
|
}
|
|
@@ -60943,7 +61116,7 @@ function findMatchingIgnoreRule(candidatePath, config) {
|
|
|
60943
61116
|
let matched = null;
|
|
60944
61117
|
for (const pattern of config.patterns) {
|
|
60945
61118
|
try {
|
|
60946
|
-
if (
|
|
61119
|
+
if (import_ignore4.default().add(pattern).ignores(rel))
|
|
60947
61120
|
matched = pattern;
|
|
60948
61121
|
} catch {}
|
|
60949
61122
|
}
|
|
@@ -68150,7 +68323,7 @@ function registerTempDir(dir) {
|
|
|
68150
68323
|
|
|
68151
68324
|
// src/domains/installation/download-manager.ts
|
|
68152
68325
|
init_types2();
|
|
68153
|
-
var
|
|
68326
|
+
var import_ignore5 = __toESM(require_ignore(), 1);
|
|
68154
68327
|
|
|
68155
68328
|
// src/domains/installation/download/file-downloader.ts
|
|
68156
68329
|
init_logger();
|
|
@@ -72045,11 +72218,11 @@ class DownloadManager {
|
|
|
72045
72218
|
ig;
|
|
72046
72219
|
userExcludePatterns = [];
|
|
72047
72220
|
constructor() {
|
|
72048
|
-
this.ig =
|
|
72221
|
+
this.ig = import_ignore5.default().add(EXCLUDE_PATTERNS);
|
|
72049
72222
|
}
|
|
72050
72223
|
setExcludePatterns(patterns) {
|
|
72051
72224
|
this.userExcludePatterns = patterns;
|
|
72052
|
-
this.ig =
|
|
72225
|
+
this.ig = import_ignore5.default().add([...EXCLUDE_PATTERNS, ...this.userExcludePatterns]);
|
|
72053
72226
|
if (patterns.length > 0) {
|
|
72054
72227
|
logger.info(`Added ${patterns.length} custom exclude pattern(s)`);
|
|
72055
72228
|
patterns.forEach((p2) => logger.debug(` - ${p2}`));
|
|
@@ -77653,8 +77826,13 @@ function registerCommands(cli) {
|
|
|
77653
77826
|
cli.command("api [action] [service] [path]", "Interact with Takumi API and proxy services").option("--method <method>", "HTTP method for proxy requests (default: GET)").option("--body <json>", "Request body as JSON string (proxy only)").option("--query <json>", "Query params as JSON string (proxy only)").option("--key <key>", "API key to use (setup only)").option("--force", "Force re-setup even if key exists (setup only)").option("--json", "Output raw JSON instead of formatted display").option("--locale <locale>", "Locale for vidcap summary/caption (default: en)").option("--max-results <n>", "Max results for vidcap search").option("--second <s>", "Timestamp in seconds for vidcap screenshot").option("--order <order>", "Sort order for vidcap comments (time/relevance)").option("--format <fmt>", "Summary format for reviewweb (bullet/paragraph)").option("--max-length <n>", "Max summary length for reviewweb").option("--instructions <text>", "Extraction instructions for reviewweb extract").option("--template <json>", "JSON template for reviewweb extract").option("--type <type>", "Link type filter for reviewweb links (web/image/file/all)").option("--country <code>", "Country code for reviewweb SEO commands").action(async (action, service, path12, options2) => {
|
|
77654
77827
|
await apiCommand(action, service, path12, options2);
|
|
77655
77828
|
});
|
|
77656
|
-
cli.command("artifact [action] [target]", "Manage Takumi artifacts (upload <file> | download <uuid|url> | delete <uuid|url>)").option("--id <uuid|url>", "Existing artifact (UUID or viewer URL) to overwrite on upload").option("--title <title>", "Display title for the artifact (max 200 chars)").option("-m, --message <message>", "Short note describing this version's change (max 100 chars)").option("-o, --output <dir>", "(download) Output directory; default: slug(title) or uuid in CWD").option("
|
|
77657
|
-
const version3 = opts.
|
|
77829
|
+
cli.command("artifact [action] [target]", "Manage Takumi artifacts (upload <file> | download <uuid|url> | delete <uuid|url>)").option("--id <uuid|url>", "Existing artifact (UUID or viewer URL) to overwrite on upload").option("--title <title>", "Display title for the artifact (max 200 chars)").option("-m, --message <message>", "Short note describing this version's change (max 100 chars)").option("-o, --output <dir>", "(download) Output directory; default: slug(title) or uuid in CWD").option("--ver <n>", "Version number (download: download it; delete: delete only that version)").option("--force", "(download) Allow writing into a non-empty directory").option("-y, --yes", "Skip delete confirmation prompt").action(async (action, target, opts) => {
|
|
77830
|
+
const version3 = opts.ver !== undefined ? Number.parseInt(String(opts.ver), 10) : undefined;
|
|
77831
|
+
if (version3 !== undefined && (!Number.isInteger(version3) || version3 < 1)) {
|
|
77832
|
+
console.error(`Invalid version: ${opts.ver}. Use a positive integer, e.g. --ver 2`);
|
|
77833
|
+
process.exitCode = 1;
|
|
77834
|
+
return;
|
|
77835
|
+
}
|
|
77658
77836
|
await artifactCommand(action, target, { ...opts, version: version3 });
|
|
77659
77837
|
});
|
|
77660
77838
|
cli.command("auth [action]", "Sign in/out, refresh, and check Takumi session (login|logout|refresh|status)").option("--json", "Machine-readable JSON output (status, refresh)").option("-f, --force", "Force a token refresh even when the current token is still valid (refresh only)").action(async (action, options2 = {}) => {
|