@tankpkg/cli 0.16.3 → 0.16.5
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/bin/tank.js +66 -21
- package/dist/bin/tank.js.map +1 -1
- package/dist/{debug-logger-Ds5BG5rk.js → debug-logger-BpF5Gl-T.js} +2 -2
- package/dist/{debug-logger-Ds5BG5rk.js.map → debug-logger-BpF5Gl-T.js.map} +1 -1
- package/dist/index.js +1 -1
- package/dist/package.json +1 -1
- package/package.json +1 -1
package/dist/bin/tank.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as VERSION, i as USER_AGENT, l as setConfig, n as flushLogs, o as getConfig, s as getConfigDir, t as authFlowLog } from "../debug-logger-
|
|
2
|
+
import { a as VERSION, i as USER_AGENT, l as setConfig, n as flushLogs, o as getConfig, s as getConfigDir, t as authFlowLog } from "../debug-logger-BpF5Gl-T.js";
|
|
3
3
|
import { t as logger } from "../logger-BhULz3Uz.js";
|
|
4
4
|
import { createRequire } from "node:module";
|
|
5
5
|
import { Command } from "commander";
|
|
@@ -21,6 +21,7 @@ import { pipeline } from "node:stream/promises";
|
|
|
21
21
|
import open from "open";
|
|
22
22
|
import ignore from "ignore";
|
|
23
23
|
import { fileURLToPath } from "node:url";
|
|
24
|
+
import { inspect } from "node:util";
|
|
24
25
|
//#region \0rolldown/runtime.js
|
|
25
26
|
var __defProp$1 = Object.defineProperty;
|
|
26
27
|
var __exportAll = (all, no_symbols) => {
|
|
@@ -9067,18 +9068,31 @@ function writeLockfileWithResolvedGraph(lock, nodes, downloaded, onProgress) {
|
|
|
9067
9068
|
lock.skills = sortedSkills;
|
|
9068
9069
|
return lock;
|
|
9069
9070
|
}
|
|
9070
|
-
|
|
9071
|
-
|
|
9072
|
-
|
|
9073
|
-
|
|
9074
|
-
|
|
9075
|
-
|
|
9076
|
-
|
|
9077
|
-
|
|
9078
|
-
|
|
9079
|
-
|
|
9080
|
-
|
|
9071
|
+
/**
|
|
9072
|
+
* Plan the ordered list of ancestor directories to create for `targetDir`,
|
|
9073
|
+
* from just below the filesystem root down to the leaf (the root itself is
|
|
9074
|
+
* never returned — it always exists and must not be `mkdir`'d).
|
|
9075
|
+
*
|
|
9076
|
+
* The path module is injectable so Windows drive/UNC root handling can be
|
|
9077
|
+
* verified on any host via `path.win32` without a real Windows machine.
|
|
9078
|
+
*/
|
|
9079
|
+
function planMkdirSegments(targetDir, pathMod = path) {
|
|
9080
|
+
const resolved = pathMod.resolve(targetDir);
|
|
9081
|
+
const { root } = pathMod.parse(resolved);
|
|
9082
|
+
const dirs = [];
|
|
9083
|
+
let current = root;
|
|
9084
|
+
for (const seg of resolved.slice(root.length).split(pathMod.sep).filter(Boolean)) {
|
|
9085
|
+
current = pathMod.join(current, seg);
|
|
9086
|
+
dirs.push(current);
|
|
9081
9087
|
}
|
|
9088
|
+
return dirs;
|
|
9089
|
+
}
|
|
9090
|
+
function mkdirSafeNoSymlinks(targetDir) {
|
|
9091
|
+
for (const current of planMkdirSegments(targetDir)) if (fs.existsSync(current)) {
|
|
9092
|
+
const stat = fs.lstatSync(current);
|
|
9093
|
+
if (stat.isSymbolicLink()) throw new TankIntegrityError(`Symlink in install path: ${current}`);
|
|
9094
|
+
if (!stat.isDirectory()) throw new TankIntegrityError(`Non-directory in install path: ${current}`);
|
|
9095
|
+
} else fs.mkdirSync(current);
|
|
9082
9096
|
}
|
|
9083
9097
|
function isDirNonEmpty(dir) {
|
|
9084
9098
|
try {
|
|
@@ -9965,11 +9979,11 @@ function wrapMcpServerForSkill(options) {
|
|
|
9965
9979
|
logger.warn(`MCP proxy wrapping skipped for ${options.skillName}: ${msg}`);
|
|
9966
9980
|
}
|
|
9967
9981
|
}
|
|
9968
|
-
async function
|
|
9969
|
-
const {
|
|
9982
|
+
async function linkInstalledSkills(options) {
|
|
9983
|
+
const { skillNames, resolvedNodeByName, extractDirForSkill, directory, global, resolvedHome, homedir, dangerouslyNoTankProxy } = options;
|
|
9970
9984
|
const agentSkillsBaseDir = global ? getGlobalAgentSkillsDir(resolvedHome) : path.join(directory, ".tank", "agent-skills");
|
|
9971
9985
|
const linksDir = global ? path.join(resolvedHome, ".tank") : path.join(directory, ".tank");
|
|
9972
|
-
for (const skillName of
|
|
9986
|
+
for (const skillName of skillNames) try {
|
|
9973
9987
|
const node = resolvedNodeByName.get(skillName);
|
|
9974
9988
|
if (!node) continue;
|
|
9975
9989
|
const linkResult = linkSkillToAgents({
|
|
@@ -9993,7 +10007,7 @@ async function linkInstalledRoots(options) {
|
|
|
9993
10007
|
dangerouslyNoTankProxy
|
|
9994
10008
|
});
|
|
9995
10009
|
} catch {
|
|
9996
|
-
if (
|
|
10010
|
+
if (skillNames.length === 1) logger.warn("Agent linking skipped (non-fatal)");
|
|
9997
10011
|
else logger.warn(`Agent linking skipped for ${skillName} (non-fatal)`);
|
|
9998
10012
|
}
|
|
9999
10013
|
const detectedAgents = detectInstalledAgents(homedir);
|
|
@@ -10006,7 +10020,7 @@ async function linkInstalledRoots(options) {
|
|
|
10006
10020
|
openclaw: "opencode"
|
|
10007
10021
|
};
|
|
10008
10022
|
const platforms = new Set(detectedAgents.map((a) => agentToPlatform[a.id]).filter(Boolean));
|
|
10009
|
-
for (const skillName of
|
|
10023
|
+
for (const skillName of skillNames) {
|
|
10010
10024
|
if (!resolvedNodeByName.get(skillName)) continue;
|
|
10011
10025
|
const skillDir = extractDirForSkill(skillName);
|
|
10012
10026
|
const manifestPath = path.join(skillDir, "tank.json");
|
|
@@ -10057,8 +10071,8 @@ async function executeInstallPipeline(options) {
|
|
|
10057
10071
|
global,
|
|
10058
10072
|
homedir
|
|
10059
10073
|
});
|
|
10060
|
-
await
|
|
10061
|
-
|
|
10074
|
+
await linkInstalledSkills({
|
|
10075
|
+
skillNames: nodesToInstall.map((node) => node.name),
|
|
10062
10076
|
resolvedNodeByName,
|
|
10063
10077
|
extractDirForSkill,
|
|
10064
10078
|
directory,
|
|
@@ -12084,6 +12098,37 @@ function printUserInfo(user) {
|
|
|
12084
12098
|
logger.info(`Email: ${user.email ?? "unknown"}`);
|
|
12085
12099
|
}
|
|
12086
12100
|
//#endregion
|
|
12101
|
+
//#region src/lib/describe-error.ts
|
|
12102
|
+
/** Format a real Error, surfacing Node errno fields (code/syscall/path) when present. */
|
|
12103
|
+
function describeErrorObject(err) {
|
|
12104
|
+
const e = err;
|
|
12105
|
+
const base = err.message?.trim() || err.name || "Error";
|
|
12106
|
+
const tags = [
|
|
12107
|
+
e.code != null ? `code=${String(e.code)}` : null,
|
|
12108
|
+
e.syscall != null ? `syscall=${String(e.syscall)}` : null,
|
|
12109
|
+
e.path != null ? `path=${String(e.path)}` : null
|
|
12110
|
+
].filter((tag) => tag !== null);
|
|
12111
|
+
return tags.length > 0 ? `${base} (${tags.join(", ")})` : base;
|
|
12112
|
+
}
|
|
12113
|
+
/**
|
|
12114
|
+
* Render an unknown thrown value as a non-empty, actionable string.
|
|
12115
|
+
*
|
|
12116
|
+
* Guarantees a useful message for every input: errno errors surface their
|
|
12117
|
+
* `code`/`syscall`/`path`, non-Error objects are inspected, and the result
|
|
12118
|
+
* never collapses to an empty string or a bare placeholder like `<none>`
|
|
12119
|
+
* (the symptom Windows users hit during `tank install`).
|
|
12120
|
+
*/
|
|
12121
|
+
function describeError(err) {
|
|
12122
|
+
if (err instanceof Error) return describeErrorObject(err);
|
|
12123
|
+
if (err === null || err === void 0) return `${String(err)} (non-error thrown)`;
|
|
12124
|
+
if (typeof err === "object") try {
|
|
12125
|
+
return `${err.constructor?.name ?? "object"}: ${inspect(err, { depth: 2 })}`;
|
|
12126
|
+
} catch {
|
|
12127
|
+
return Object.prototype.toString.call(err);
|
|
12128
|
+
}
|
|
12129
|
+
return `${typeof err} ${String(err)}`;
|
|
12130
|
+
}
|
|
12131
|
+
//#endregion
|
|
12087
12132
|
//#region src/lib/install-suggestions.ts
|
|
12088
12133
|
/**
|
|
12089
12134
|
* Best-effort fuzzy lookup of similar skill names. Hits the public /api/v1/search
|
|
@@ -12304,7 +12349,7 @@ program.command("install").alias("i").description("Install one or more skills fr
|
|
|
12304
12349
|
...proxyOpt
|
|
12305
12350
|
});
|
|
12306
12351
|
} catch (err) {
|
|
12307
|
-
const msg =
|
|
12352
|
+
const msg = describeError(err);
|
|
12308
12353
|
console.error(`Install failed: ${msg}`);
|
|
12309
12354
|
process.exit(1);
|
|
12310
12355
|
}
|
|
@@ -12327,7 +12372,7 @@ program.command("install").alias("i").description("Install one or more skills fr
|
|
|
12327
12372
|
...proxyOpt
|
|
12328
12373
|
});
|
|
12329
12374
|
} catch (err) {
|
|
12330
|
-
const msg =
|
|
12375
|
+
const msg = describeError(err);
|
|
12331
12376
|
failures.push({
|
|
12332
12377
|
target,
|
|
12333
12378
|
error: msg,
|