@agentver/cli 0.1.3 → 0.2.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/agentver.js +1557 -651
- package/dist/agentver.js.map +1 -1
- package/package.json +1 -1
package/dist/agentver.js
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
// bin/agentver.ts
|
|
4
4
|
import { createRequire as createRequire2 } from "module";
|
|
5
|
-
import { dirname as
|
|
5
|
+
import { dirname as dirname7, join as join26 } from "path";
|
|
6
6
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
7
7
|
import { Command } from "commander";
|
|
8
|
-
import
|
|
8
|
+
import chalk33 from "chalk";
|
|
9
9
|
import updateNotifier from "update-notifier";
|
|
10
10
|
|
|
11
11
|
// src/commands/adopt.ts
|
|
@@ -960,7 +960,8 @@ var manifestV2PackageSchema = z.object({
|
|
|
960
960
|
source: packageSourceSchema,
|
|
961
961
|
agents: z.array(z.string()).default([]),
|
|
962
962
|
installedAt: z.string().datetime(),
|
|
963
|
-
modified: z.boolean().default(false)
|
|
963
|
+
modified: z.boolean().default(false),
|
|
964
|
+
pinned: z.boolean().optional()
|
|
964
965
|
});
|
|
965
966
|
var manifestV2Schema = z.object({
|
|
966
967
|
version: z.literal(2),
|
|
@@ -1147,7 +1148,8 @@ var statusResultSchema = z2.object({
|
|
|
1147
1148
|
name: z2.string(),
|
|
1148
1149
|
status: z2.string(),
|
|
1149
1150
|
modified: z2.boolean(),
|
|
1150
|
-
upstream: z2.boolean()
|
|
1151
|
+
upstream: z2.boolean(),
|
|
1152
|
+
pinned: z2.boolean().optional()
|
|
1151
1153
|
})),
|
|
1152
1154
|
summary: z2.object({
|
|
1153
1155
|
total: z2.number(),
|
|
@@ -1205,6 +1207,39 @@ var adoptResultSchema = z2.object({
|
|
|
1205
1207
|
reason: z2.string()
|
|
1206
1208
|
}))
|
|
1207
1209
|
});
|
|
1210
|
+
var infoResultSchema = z2.object({
|
|
1211
|
+
name: z2.string(),
|
|
1212
|
+
source: z2.object({
|
|
1213
|
+
type: z2.string(),
|
|
1214
|
+
uri: z2.string().optional(),
|
|
1215
|
+
ref: z2.string().optional(),
|
|
1216
|
+
commit: z2.string().optional(),
|
|
1217
|
+
hostname: z2.string().optional()
|
|
1218
|
+
}),
|
|
1219
|
+
agents: z2.array(z2.string()),
|
|
1220
|
+
installedAt: z2.string(),
|
|
1221
|
+
modified: z2.boolean(),
|
|
1222
|
+
integrity: z2.string().optional(),
|
|
1223
|
+
files: z2.object({
|
|
1224
|
+
count: z2.number(),
|
|
1225
|
+
totalSize: z2.number()
|
|
1226
|
+
}),
|
|
1227
|
+
skill: z2.object({
|
|
1228
|
+
title: z2.string(),
|
|
1229
|
+
description: z2.string()
|
|
1230
|
+
}).optional()
|
|
1231
|
+
});
|
|
1232
|
+
var doctorCheckSchema = z2.object({
|
|
1233
|
+
name: z2.string(),
|
|
1234
|
+
status: z2.enum(["pass", "fail", "warn"]),
|
|
1235
|
+
message: z2.string()
|
|
1236
|
+
});
|
|
1237
|
+
var doctorResultSchema = z2.object({
|
|
1238
|
+
checks: z2.array(doctorCheckSchema),
|
|
1239
|
+
passed: z2.number(),
|
|
1240
|
+
failed: z2.number(),
|
|
1241
|
+
warnings: z2.number()
|
|
1242
|
+
});
|
|
1208
1243
|
|
|
1209
1244
|
// ../shared/dist/errors.js
|
|
1210
1245
|
var AgentverError = class extends Error {
|
|
@@ -1774,7 +1809,7 @@ function formatWithOptions(inspectOptions, ...args) {
|
|
|
1774
1809
|
const first = args[0];
|
|
1775
1810
|
let a = 0;
|
|
1776
1811
|
let str = "";
|
|
1777
|
-
let
|
|
1812
|
+
let join27 = "";
|
|
1778
1813
|
if (typeof first === "string") {
|
|
1779
1814
|
if (args.length === 1) {
|
|
1780
1815
|
return first;
|
|
@@ -1873,7 +1908,7 @@ function formatWithOptions(inspectOptions, ...args) {
|
|
|
1873
1908
|
}
|
|
1874
1909
|
if (lastPos !== 0) {
|
|
1875
1910
|
a++;
|
|
1876
|
-
|
|
1911
|
+
join27 = " ";
|
|
1877
1912
|
if (lastPos < first.length) {
|
|
1878
1913
|
str += first.slice(lastPos);
|
|
1879
1914
|
}
|
|
@@ -1881,9 +1916,9 @@ function formatWithOptions(inspectOptions, ...args) {
|
|
|
1881
1916
|
}
|
|
1882
1917
|
while (a < args.length) {
|
|
1883
1918
|
const value = args[a];
|
|
1884
|
-
str +=
|
|
1919
|
+
str += join27;
|
|
1885
1920
|
str += typeof value !== "string" ? inspect(value, inspectOptions) : value;
|
|
1886
|
-
|
|
1921
|
+
join27 = " ";
|
|
1887
1922
|
a++;
|
|
1888
1923
|
}
|
|
1889
1924
|
return str;
|
|
@@ -2957,6 +2992,22 @@ var AGENTVER_EXTENSION_FIELDS = [
|
|
|
2957
2992
|
"dependsOn",
|
|
2958
2993
|
"conflictsWith"
|
|
2959
2994
|
];
|
|
2995
|
+
function parseSkillFrontmatter(content) {
|
|
2996
|
+
const { rawData, body, hasFrontmatter } = parseFrontmatter(content);
|
|
2997
|
+
if (!hasFrontmatter) {
|
|
2998
|
+
throw new Error("No YAML frontmatter found. Expected content delimited by --- markers.");
|
|
2999
|
+
}
|
|
3000
|
+
const parsed = agentverSkillSchema.safeParse(rawData);
|
|
3001
|
+
if (!parsed.success) {
|
|
3002
|
+
const messages = parsed.error.issues.map((issue) => {
|
|
3003
|
+
const path = issue.path.join(".");
|
|
3004
|
+
return path ? `${path}: ${issue.message}` : issue.message;
|
|
3005
|
+
});
|
|
3006
|
+
throw new Error(`Invalid SKILL.md frontmatter:
|
|
3007
|
+
${messages.join("\n")}`);
|
|
3008
|
+
}
|
|
3009
|
+
return { frontmatter: parsed.data, body };
|
|
3010
|
+
}
|
|
2960
3011
|
function validateSkillMd(content) {
|
|
2961
3012
|
const errors = [];
|
|
2962
3013
|
const warnings = [];
|
|
@@ -4526,6 +4577,9 @@ async function isAuthenticated() {
|
|
|
4526
4577
|
// src/registry/config.ts
|
|
4527
4578
|
var CONFIG_DIR = join7(homedir4(), ".agentver");
|
|
4528
4579
|
var CONFIG_PATH = join7(CONFIG_DIR, "config.json");
|
|
4580
|
+
function getConfigPath() {
|
|
4581
|
+
return CONFIG_PATH;
|
|
4582
|
+
}
|
|
4529
4583
|
function readConfig() {
|
|
4530
4584
|
if (!existsSync6(CONFIG_PATH)) {
|
|
4531
4585
|
return {};
|
|
@@ -4928,8 +4982,325 @@ Auditing ${packageNames.length} package${packageNames.length === 1 ? "" : "s"}..
|
|
|
4928
4982
|
});
|
|
4929
4983
|
}
|
|
4930
4984
|
|
|
4931
|
-
// src/commands/
|
|
4985
|
+
// src/commands/completion.ts
|
|
4986
|
+
import { appendFileSync, existsSync as existsSync8, readFileSync as readFileSync7 } from "fs";
|
|
4987
|
+
import { homedir as homedir6 } from "os";
|
|
4988
|
+
import { join as join10 } from "path";
|
|
4932
4989
|
import chalk5 from "chalk";
|
|
4990
|
+
var TOP_LEVEL_COMMANDS = [
|
|
4991
|
+
"adopt",
|
|
4992
|
+
"audit",
|
|
4993
|
+
"completion",
|
|
4994
|
+
"config",
|
|
4995
|
+
"diff",
|
|
4996
|
+
"doctor",
|
|
4997
|
+
"draft",
|
|
4998
|
+
"info",
|
|
4999
|
+
"init",
|
|
5000
|
+
"install",
|
|
5001
|
+
"list",
|
|
5002
|
+
"log",
|
|
5003
|
+
"login",
|
|
5004
|
+
"logout",
|
|
5005
|
+
"publish",
|
|
5006
|
+
"remove",
|
|
5007
|
+
"save",
|
|
5008
|
+
"scan",
|
|
5009
|
+
"search",
|
|
5010
|
+
"status",
|
|
5011
|
+
"suggest",
|
|
5012
|
+
"suggestions",
|
|
5013
|
+
"sync",
|
|
5014
|
+
"update",
|
|
5015
|
+
"upgrade",
|
|
5016
|
+
"verify",
|
|
5017
|
+
"version",
|
|
5018
|
+
"whoami"
|
|
5019
|
+
];
|
|
5020
|
+
var SUBCOMMANDS = {
|
|
5021
|
+
draft: ["create", "list", "switch", "publish", "discard"],
|
|
5022
|
+
version: ["create", "list"],
|
|
5023
|
+
config: ["list", "get", "set", "unset", "path"],
|
|
5024
|
+
completion: ["bash", "zsh", "fish"]
|
|
5025
|
+
};
|
|
5026
|
+
var COMMON_FLAGS = ["--json", "--global", "--dry-run", "--help"];
|
|
5027
|
+
function generateBashScript() {
|
|
5028
|
+
const subcmdCases = Object.entries(SUBCOMMANDS).map(
|
|
5029
|
+
([cmd, subs]) => ` ${cmd})
|
|
5030
|
+
COMPREPLY=( $(compgen -W "${subs.join(" ")}" -- "$cur") )
|
|
5031
|
+
return 0
|
|
5032
|
+
;;`
|
|
5033
|
+
).join("\n");
|
|
5034
|
+
return `# agentver bash completion
|
|
5035
|
+
_agentver() {
|
|
5036
|
+
local cur prev commands
|
|
5037
|
+
COMPREPLY=()
|
|
5038
|
+
cur="\${COMP_WORDS[COMP_CWORD]}"
|
|
5039
|
+
prev="\${COMP_WORDS[COMP_CWORD-1]}"
|
|
5040
|
+
commands="${TOP_LEVEL_COMMANDS.join(" ")}"
|
|
5041
|
+
|
|
5042
|
+
if [[ "$COMP_CWORD" -eq 1 ]]; then
|
|
5043
|
+
COMPREPLY=( $(compgen -W "$commands" -- "$cur") )
|
|
5044
|
+
return 0
|
|
5045
|
+
fi
|
|
5046
|
+
|
|
5047
|
+
if [[ "$cur" == -* ]]; then
|
|
5048
|
+
COMPREPLY=( $(compgen -W "${COMMON_FLAGS.join(" ")}" -- "$cur") )
|
|
5049
|
+
return 0
|
|
5050
|
+
fi
|
|
5051
|
+
|
|
5052
|
+
case "$prev" in
|
|
5053
|
+
${subcmdCases}
|
|
5054
|
+
esac
|
|
5055
|
+
|
|
5056
|
+
return 0
|
|
5057
|
+
}
|
|
5058
|
+
|
|
5059
|
+
complete -F _agentver agentver
|
|
5060
|
+
`;
|
|
5061
|
+
}
|
|
5062
|
+
function generateZshScript() {
|
|
5063
|
+
const subcmdCases = Object.entries(SUBCOMMANDS).map(
|
|
5064
|
+
([cmd, subs]) => ` ${cmd})
|
|
5065
|
+
_values 'subcommand' ${subs.map((s) => `'${s}'`).join(" ")}
|
|
5066
|
+
;;`
|
|
5067
|
+
).join("\n");
|
|
5068
|
+
return `# agentver zsh completion
|
|
5069
|
+
_agentver() {
|
|
5070
|
+
local -a commands
|
|
5071
|
+
commands=(
|
|
5072
|
+
${TOP_LEVEL_COMMANDS.map((c) => ` '${c}'`).join("\n")}
|
|
5073
|
+
)
|
|
5074
|
+
|
|
5075
|
+
_arguments -C '--json[Output results as structured JSON]' '--global[Apply globally]' '--dry-run[Preview changes without applying]' '--help[Show help]' '1:command:->cmd' '*::arg:->args'
|
|
5076
|
+
|
|
5077
|
+
case "$state" in
|
|
5078
|
+
cmd)
|
|
5079
|
+
_describe 'command' commands
|
|
5080
|
+
;;
|
|
5081
|
+
args)
|
|
5082
|
+
case "\${words[1]}" in
|
|
5083
|
+
${subcmdCases}
|
|
5084
|
+
esac
|
|
5085
|
+
;;
|
|
5086
|
+
esac
|
|
5087
|
+
}
|
|
5088
|
+
|
|
5089
|
+
compdef _agentver agentver
|
|
5090
|
+
`;
|
|
5091
|
+
}
|
|
5092
|
+
function generateFishScript() {
|
|
5093
|
+
const topLevelCompletions = TOP_LEVEL_COMMANDS.map(
|
|
5094
|
+
(cmd) => `complete -c agentver -n '__fish_use_subcommand' -a '${cmd}'`
|
|
5095
|
+
).join("\n");
|
|
5096
|
+
const subcmdCompletions = Object.entries(SUBCOMMANDS).flatMap(
|
|
5097
|
+
([cmd, subs]) => subs.map((sub) => `complete -c agentver -n '__fish_seen_subcommand_from ${cmd}' -a '${sub}'`)
|
|
5098
|
+
).join("\n");
|
|
5099
|
+
const flagCompletions = [
|
|
5100
|
+
"complete -c agentver -l json -d 'Output results as structured JSON'",
|
|
5101
|
+
"complete -c agentver -l global -d 'Apply globally'",
|
|
5102
|
+
"complete -c agentver -l dry-run -d 'Preview changes without applying'",
|
|
5103
|
+
"complete -c agentver -l help -d 'Show help'"
|
|
5104
|
+
].join("\n");
|
|
5105
|
+
return `# agentver fish completion
|
|
5106
|
+
${topLevelCompletions}
|
|
5107
|
+
${subcmdCompletions}
|
|
5108
|
+
${flagCompletions}
|
|
5109
|
+
`;
|
|
5110
|
+
}
|
|
5111
|
+
var SHELL_GENERATORS = {
|
|
5112
|
+
bash: generateBashScript,
|
|
5113
|
+
zsh: generateZshScript,
|
|
5114
|
+
fish: generateFishScript
|
|
5115
|
+
};
|
|
5116
|
+
var RC_PATHS = {
|
|
5117
|
+
bash: join10(homedir6(), ".bashrc"),
|
|
5118
|
+
zsh: join10(homedir6(), ".zshrc"),
|
|
5119
|
+
fish: join10(homedir6(), ".config", "fish", "config.fish")
|
|
5120
|
+
};
|
|
5121
|
+
var EVAL_LINES = {
|
|
5122
|
+
bash: 'eval "$(agentver completion bash)"',
|
|
5123
|
+
zsh: 'eval "$(agentver completion zsh)"',
|
|
5124
|
+
fish: "agentver completion fish | source"
|
|
5125
|
+
};
|
|
5126
|
+
function installCompletion(shell) {
|
|
5127
|
+
const rcPath = RC_PATHS[shell];
|
|
5128
|
+
const evalLine = EVAL_LINES[shell];
|
|
5129
|
+
if (existsSync8(rcPath)) {
|
|
5130
|
+
const content = readFileSync7(rcPath, "utf-8");
|
|
5131
|
+
if (content.includes(evalLine)) {
|
|
5132
|
+
process.stdout.write(chalk5.dim(`Completion already installed in ${rcPath}
|
|
5133
|
+
`));
|
|
5134
|
+
return;
|
|
5135
|
+
}
|
|
5136
|
+
}
|
|
5137
|
+
appendFileSync(rcPath, `
|
|
5138
|
+
# agentver shell completion
|
|
5139
|
+
${evalLine}
|
|
5140
|
+
`);
|
|
5141
|
+
process.stdout.write(
|
|
5142
|
+
chalk5.green(`Completion installed in ${rcPath}
|
|
5143
|
+
`) + chalk5.dim("Restart your shell or run: ") + chalk5.cyan(`source ${rcPath}`) + "\n"
|
|
5144
|
+
);
|
|
5145
|
+
}
|
|
5146
|
+
function registerCompletionCommand(program2) {
|
|
5147
|
+
program2.command("completion <shell>").description("Generate shell completion scripts (bash, zsh, fish)").option("--install", "Install the completion script to your shell RC file").action((shell, options) => {
|
|
5148
|
+
const jsonMode = isJSONMode();
|
|
5149
|
+
if (!["bash", "zsh", "fish"].includes(shell)) {
|
|
5150
|
+
if (jsonMode) {
|
|
5151
|
+
outputError("INVALID_SHELL", `Unsupported shell "${shell}". Supported: bash, zsh, fish`);
|
|
5152
|
+
process.exit(1);
|
|
5153
|
+
}
|
|
5154
|
+
process.stderr.write(
|
|
5155
|
+
chalk5.red(`Unsupported shell "${shell}". Supported: bash, zsh, fish
|
|
5156
|
+
`)
|
|
5157
|
+
);
|
|
5158
|
+
process.exit(1);
|
|
5159
|
+
}
|
|
5160
|
+
const validShell = shell;
|
|
5161
|
+
const script = SHELL_GENERATORS[validShell]();
|
|
5162
|
+
if (options.install) {
|
|
5163
|
+
if (jsonMode) {
|
|
5164
|
+
installCompletion(validShell);
|
|
5165
|
+
outputSuccess({ shell: validShell, installed: true, rcPath: RC_PATHS[validShell] });
|
|
5166
|
+
return;
|
|
5167
|
+
}
|
|
5168
|
+
installCompletion(validShell);
|
|
5169
|
+
return;
|
|
5170
|
+
}
|
|
5171
|
+
if (jsonMode) {
|
|
5172
|
+
outputSuccess({ shell: validShell, script });
|
|
5173
|
+
return;
|
|
5174
|
+
}
|
|
5175
|
+
process.stdout.write(script);
|
|
5176
|
+
});
|
|
5177
|
+
}
|
|
5178
|
+
|
|
5179
|
+
// src/commands/config.ts
|
|
5180
|
+
import chalk6 from "chalk";
|
|
5181
|
+
var KNOWN_KEYS = ["platformUrl", "defaultOrg", "telemetry"];
|
|
5182
|
+
function isKnownKey(key) {
|
|
5183
|
+
return KNOWN_KEYS.includes(key);
|
|
5184
|
+
}
|
|
5185
|
+
function formatValue2(value) {
|
|
5186
|
+
if (value === void 0 || value === null) return "";
|
|
5187
|
+
if (typeof value === "object") return JSON.stringify(value);
|
|
5188
|
+
return String(value);
|
|
5189
|
+
}
|
|
5190
|
+
function validateKey(key) {
|
|
5191
|
+
if (!isKnownKey(key)) {
|
|
5192
|
+
if (isJSONMode()) {
|
|
5193
|
+
outputError("INVALID_KEY", `Unknown config key: ${key}. Valid keys: ${KNOWN_KEYS.join(", ")}`);
|
|
5194
|
+
} else {
|
|
5195
|
+
console.error(chalk6.red(`Unknown config key: ${key}. Valid keys: ${KNOWN_KEYS.join(", ")}`));
|
|
5196
|
+
}
|
|
5197
|
+
return false;
|
|
5198
|
+
}
|
|
5199
|
+
return true;
|
|
5200
|
+
}
|
|
5201
|
+
function validateValue(key, value) {
|
|
5202
|
+
switch (key) {
|
|
5203
|
+
case "telemetry": {
|
|
5204
|
+
if (value !== "true" && value !== "false") {
|
|
5205
|
+
if (isJSONMode()) {
|
|
5206
|
+
outputError("INVALID_VALUE", "telemetry must be true or false");
|
|
5207
|
+
} else {
|
|
5208
|
+
console.error(chalk6.red("telemetry must be true or false"));
|
|
5209
|
+
}
|
|
5210
|
+
return { valid: false };
|
|
5211
|
+
}
|
|
5212
|
+
return { valid: true, parsed: value === "true" };
|
|
5213
|
+
}
|
|
5214
|
+
case "platformUrl": {
|
|
5215
|
+
if (!value.startsWith("https://")) {
|
|
5216
|
+
if (isJSONMode()) {
|
|
5217
|
+
outputError("INVALID_VALUE", "platformUrl must start with https://");
|
|
5218
|
+
} else {
|
|
5219
|
+
console.error(chalk6.red("platformUrl must start with https://"));
|
|
5220
|
+
}
|
|
5221
|
+
return { valid: false };
|
|
5222
|
+
}
|
|
5223
|
+
return { valid: true, parsed: value };
|
|
5224
|
+
}
|
|
5225
|
+
default:
|
|
5226
|
+
return { valid: true, parsed: value };
|
|
5227
|
+
}
|
|
5228
|
+
}
|
|
5229
|
+
function registerConfigCommand(program2) {
|
|
5230
|
+
const configCmd = program2.command("config").description("Manage CLI configuration");
|
|
5231
|
+
configCmd.command("list").description("Show all config values").option("--json", "Output as JSON").action(() => {
|
|
5232
|
+
const config = readConfig();
|
|
5233
|
+
const jsonMode = isJSONMode();
|
|
5234
|
+
if (jsonMode) {
|
|
5235
|
+
outputSuccess(config);
|
|
5236
|
+
return;
|
|
5237
|
+
}
|
|
5238
|
+
const entries = Object.entries(config);
|
|
5239
|
+
if (entries.length === 0) {
|
|
5240
|
+
console.log(chalk6.dim("No configuration set."));
|
|
5241
|
+
return;
|
|
5242
|
+
}
|
|
5243
|
+
console.log(chalk6.bold("\nConfiguration:\n"));
|
|
5244
|
+
for (const [key, value] of entries) {
|
|
5245
|
+
console.log(` ${chalk6.green(key)} = ${chalk6.cyan(formatValue2(value))}`);
|
|
5246
|
+
}
|
|
5247
|
+
console.log();
|
|
5248
|
+
});
|
|
5249
|
+
configCmd.command("get").description("Get a config value").argument("<key>", "Config key to read").option("--json", "Output as JSON").action((key) => {
|
|
5250
|
+
const jsonMode = isJSONMode();
|
|
5251
|
+
if (!validateKey(key)) {
|
|
5252
|
+
process.exit(1);
|
|
5253
|
+
}
|
|
5254
|
+
const config = readConfig();
|
|
5255
|
+
const value = config[key];
|
|
5256
|
+
if (jsonMode) {
|
|
5257
|
+
outputSuccess({ key, value: value ?? null });
|
|
5258
|
+
return;
|
|
5259
|
+
}
|
|
5260
|
+
if (value === void 0) {
|
|
5261
|
+
process.exit(0);
|
|
5262
|
+
}
|
|
5263
|
+
console.log(formatValue2(value));
|
|
5264
|
+
});
|
|
5265
|
+
configCmd.command("set").description("Set a config value").argument("<key>", "Config key to set").argument("<value>", "Value to set").option("--json", "Output as JSON").action((key, value) => {
|
|
5266
|
+
const jsonMode = isJSONMode();
|
|
5267
|
+
if (!validateKey(key)) {
|
|
5268
|
+
process.exit(1);
|
|
5269
|
+
}
|
|
5270
|
+
const validation = validateValue(key, value);
|
|
5271
|
+
if (!validation.valid) {
|
|
5272
|
+
process.exit(1);
|
|
5273
|
+
}
|
|
5274
|
+
const config = readConfig();
|
|
5275
|
+
const updated = { ...config, [key]: validation.parsed };
|
|
5276
|
+
writeConfig(updated);
|
|
5277
|
+
if (jsonMode) {
|
|
5278
|
+
outputSuccess({ key, value: validation.parsed });
|
|
5279
|
+
return;
|
|
5280
|
+
}
|
|
5281
|
+
console.log(chalk6.green(`Set ${key} = ${formatValue2(validation.parsed)}`));
|
|
5282
|
+
});
|
|
5283
|
+
configCmd.command("unset").description("Remove a config key").argument("<key>", "Config key to remove").option("--json", "Output as JSON").action((key) => {
|
|
5284
|
+
const jsonMode = isJSONMode();
|
|
5285
|
+
if (!validateKey(key)) {
|
|
5286
|
+
process.exit(1);
|
|
5287
|
+
}
|
|
5288
|
+
const config = readConfig();
|
|
5289
|
+
delete config[key];
|
|
5290
|
+
writeConfig(config);
|
|
5291
|
+
if (jsonMode) {
|
|
5292
|
+
outputSuccess({ key, removed: true });
|
|
5293
|
+
return;
|
|
5294
|
+
}
|
|
5295
|
+
console.log(chalk6.green(`Removed ${key}`));
|
|
5296
|
+
});
|
|
5297
|
+
configCmd.command("path").description("Print the config file path").action(() => {
|
|
5298
|
+
console.log(getConfigPath());
|
|
5299
|
+
});
|
|
5300
|
+
}
|
|
5301
|
+
|
|
5302
|
+
// src/commands/diff.ts
|
|
5303
|
+
import chalk7 from "chalk";
|
|
4933
5304
|
|
|
4934
5305
|
// src/git/resolver.ts
|
|
4935
5306
|
var logger4 = createLogger("git:resolver");
|
|
@@ -5314,17 +5685,17 @@ function diffFiles(upstreamFiles, localFiles) {
|
|
|
5314
5685
|
function formatDiff(diffs) {
|
|
5315
5686
|
const output = [];
|
|
5316
5687
|
for (const diff of diffs) {
|
|
5317
|
-
output.push(
|
|
5318
|
-
output.push(
|
|
5688
|
+
output.push(chalk7.bold(`--- a/${diff.path}`));
|
|
5689
|
+
output.push(chalk7.bold(`+++ b/${diff.path}`));
|
|
5319
5690
|
for (const hunk of diff.hunks) {
|
|
5320
5691
|
output.push(
|
|
5321
|
-
|
|
5692
|
+
chalk7.cyan(`@@ -${hunk.oldStart},${hunk.oldCount} +${hunk.newStart},${hunk.newCount} @@`)
|
|
5322
5693
|
);
|
|
5323
5694
|
for (const line of hunk.lines) {
|
|
5324
5695
|
if (line.startsWith("+")) {
|
|
5325
|
-
output.push(
|
|
5696
|
+
output.push(chalk7.green(line));
|
|
5326
5697
|
} else if (line.startsWith("-")) {
|
|
5327
|
-
output.push(
|
|
5698
|
+
output.push(chalk7.red(line));
|
|
5328
5699
|
} else {
|
|
5329
5700
|
output.push(line);
|
|
5330
5701
|
}
|
|
@@ -5346,7 +5717,7 @@ function registerDiffCommand(program2) {
|
|
|
5346
5717
|
outputError("NOT_INSTALLED", `Package "${name}" is not installed.`);
|
|
5347
5718
|
process.exit(1);
|
|
5348
5719
|
}
|
|
5349
|
-
console.error(
|
|
5720
|
+
console.error(chalk7.red(`Package "${name}" is not installed.`));
|
|
5350
5721
|
process.exit(1);
|
|
5351
5722
|
}
|
|
5352
5723
|
const { source, agents } = manifestEntry;
|
|
@@ -5356,11 +5727,11 @@ function registerDiffCommand(program2) {
|
|
|
5356
5727
|
process.exit(1);
|
|
5357
5728
|
}
|
|
5358
5729
|
console.error(
|
|
5359
|
-
|
|
5730
|
+
chalk7.red(
|
|
5360
5731
|
`Package "${name}" was installed from a well-known source (${source.hostname}).`
|
|
5361
5732
|
)
|
|
5362
5733
|
);
|
|
5363
|
-
console.error(
|
|
5734
|
+
console.error(chalk7.dim("Diff is not yet supported for well-known sources."));
|
|
5364
5735
|
process.exit(1);
|
|
5365
5736
|
}
|
|
5366
5737
|
if (source.uri === "unknown") {
|
|
@@ -5372,11 +5743,11 @@ function registerDiffCommand(program2) {
|
|
|
5372
5743
|
process.exit(1);
|
|
5373
5744
|
}
|
|
5374
5745
|
console.error(
|
|
5375
|
-
|
|
5746
|
+
chalk7.red(`Package "${name}" was migrated from v1 and has no known Git source.`)
|
|
5376
5747
|
);
|
|
5377
5748
|
console.error(
|
|
5378
|
-
|
|
5379
|
-
`) +
|
|
5749
|
+
chalk7.dim("Reinstall it using a Git source URL to enable diff:\n") + chalk7.dim(` agentver remove ${name}
|
|
5750
|
+
`) + chalk7.dim(` agentver install <git-source>`)
|
|
5380
5751
|
);
|
|
5381
5752
|
process.exit(1);
|
|
5382
5753
|
}
|
|
@@ -5430,7 +5801,7 @@ function registerDiffCommand(program2) {
|
|
|
5430
5801
|
return;
|
|
5431
5802
|
}
|
|
5432
5803
|
if (diffs.length === 0) {
|
|
5433
|
-
console.log(
|
|
5804
|
+
console.log(chalk7.green("No differences found."));
|
|
5434
5805
|
return;
|
|
5435
5806
|
}
|
|
5436
5807
|
console.log(formatDiff(diffs));
|
|
@@ -5446,132 +5817,449 @@ function registerDiffCommand(program2) {
|
|
|
5446
5817
|
});
|
|
5447
5818
|
}
|
|
5448
5819
|
|
|
5449
|
-
// src/commands/
|
|
5450
|
-
import {
|
|
5451
|
-
import {
|
|
5452
|
-
import
|
|
5453
|
-
import
|
|
5454
|
-
|
|
5455
|
-
|
|
5456
|
-
var
|
|
5457
|
-
|
|
5458
|
-
|
|
5459
|
-
|
|
5460
|
-
|
|
5461
|
-
|
|
5462
|
-
|
|
5463
|
-
|
|
5820
|
+
// src/commands/doctor.ts
|
|
5821
|
+
import { execSync } from "child_process";
|
|
5822
|
+
import { existsSync as existsSync9, lstatSync as lstatSync2, readFileSync as readFileSync8, readlinkSync as readlinkSync2 } from "fs";
|
|
5823
|
+
import { dirname as dirname4, join as join11 } from "path";
|
|
5824
|
+
import chalk8 from "chalk";
|
|
5825
|
+
var MANIFEST_DIR2 = ".agentver";
|
|
5826
|
+
var MANIFEST_FILE2 = "manifest.json";
|
|
5827
|
+
var LOCKFILE_FILE2 = "lockfile.json";
|
|
5828
|
+
var NETWORK_TIMEOUT_MS = 3e3;
|
|
5829
|
+
var MIN_NODE_VERSION = 20;
|
|
5830
|
+
function check(name, status, message) {
|
|
5831
|
+
return { name, status, message };
|
|
5832
|
+
}
|
|
5833
|
+
function checkManifestIntegrity(projectRoot) {
|
|
5834
|
+
const manifestPath = join11(projectRoot, MANIFEST_DIR2, MANIFEST_FILE2);
|
|
5835
|
+
if (!existsSync9(manifestPath)) {
|
|
5836
|
+
return check("manifest-integrity", "warn", "Manifest file not found (no skills installed yet)");
|
|
5837
|
+
}
|
|
5838
|
+
let raw;
|
|
5839
|
+
try {
|
|
5840
|
+
raw = readFileSync8(manifestPath, "utf-8");
|
|
5841
|
+
} catch {
|
|
5842
|
+
return check("manifest-integrity", "fail", "Cannot read manifest file");
|
|
5464
5843
|
}
|
|
5465
|
-
|
|
5466
|
-
|
|
5467
|
-
|
|
5844
|
+
let parsed;
|
|
5845
|
+
try {
|
|
5846
|
+
parsed = JSON.parse(raw);
|
|
5847
|
+
} catch {
|
|
5848
|
+
return check("manifest-integrity", "fail", "Manifest contains invalid JSON");
|
|
5468
5849
|
}
|
|
5469
|
-
const
|
|
5470
|
-
|
|
5471
|
-
"
|
|
5472
|
-
};
|
|
5473
|
-
if (credentials.token) {
|
|
5474
|
-
headers.Authorization = `Bearer ${credentials.token}`;
|
|
5475
|
-
} else if (credentials.apiKey) {
|
|
5476
|
-
headers["X-API-Key"] = credentials.apiKey;
|
|
5850
|
+
const result = manifestAnySchema.safeParse(parsed);
|
|
5851
|
+
if (!result.success) {
|
|
5852
|
+
return check("manifest-integrity", "fail", "Manifest does not match expected schema");
|
|
5477
5853
|
}
|
|
5478
|
-
|
|
5479
|
-
|
|
5480
|
-
|
|
5854
|
+
return check("manifest-integrity", "pass", "Manifest is valid");
|
|
5855
|
+
}
|
|
5856
|
+
function checkLockfileIntegrity(projectRoot) {
|
|
5857
|
+
const lockfilePath = join11(projectRoot, MANIFEST_DIR2, LOCKFILE_FILE2);
|
|
5858
|
+
if (!existsSync9(lockfilePath)) {
|
|
5859
|
+
return check("lockfile-integrity", "warn", "Lockfile not found (no skills installed yet)");
|
|
5860
|
+
}
|
|
5861
|
+
let raw;
|
|
5481
5862
|
try {
|
|
5482
|
-
|
|
5483
|
-
|
|
5484
|
-
|
|
5485
|
-
body: options.body ? JSON.stringify(options.body) : void 0,
|
|
5486
|
-
signal: controller.signal
|
|
5487
|
-
});
|
|
5488
|
-
if (!response.ok) {
|
|
5489
|
-
const errorBody = await response.text().catch(() => "Unknown error");
|
|
5490
|
-
throw new AgentverError("INTERNAL_ERROR", `Platform error (${response.status}): ${errorBody}`);
|
|
5491
|
-
}
|
|
5492
|
-
return response.json();
|
|
5493
|
-
} finally {
|
|
5494
|
-
clearTimeout(timeoutId);
|
|
5863
|
+
raw = readFileSync8(lockfilePath, "utf-8");
|
|
5864
|
+
} catch {
|
|
5865
|
+
return check("lockfile-integrity", "fail", "Cannot read lockfile");
|
|
5495
5866
|
}
|
|
5496
|
-
|
|
5497
|
-
async function platformFetchSilent(path, options = {}) {
|
|
5867
|
+
let parsed;
|
|
5498
5868
|
try {
|
|
5499
|
-
|
|
5869
|
+
parsed = JSON.parse(raw);
|
|
5500
5870
|
} catch {
|
|
5501
|
-
return
|
|
5871
|
+
return check("lockfile-integrity", "fail", "Lockfile contains invalid JSON");
|
|
5502
5872
|
}
|
|
5873
|
+
const result = lockfileAnySchema.safeParse(parsed);
|
|
5874
|
+
if (!result.success) {
|
|
5875
|
+
return check("lockfile-integrity", "fail", "Lockfile does not match expected schema");
|
|
5876
|
+
}
|
|
5877
|
+
return check("lockfile-integrity", "pass", "Lockfile is valid");
|
|
5503
5878
|
}
|
|
5504
|
-
|
|
5505
|
-
|
|
5506
|
-
|
|
5507
|
-
const
|
|
5508
|
-
const
|
|
5509
|
-
|
|
5510
|
-
|
|
5511
|
-
const content = readFileSync7(skillMdPath, "utf-8");
|
|
5512
|
-
const nameMatch = content.match(/^name:\s*(.+)$/m);
|
|
5513
|
-
skillName = nameMatch?.[1]?.trim() ?? basename2(cwd);
|
|
5879
|
+
function checkManifestLockfileSync(projectRoot) {
|
|
5880
|
+
const manifest = readManifest(projectRoot);
|
|
5881
|
+
const lockfile = readLockfile(projectRoot);
|
|
5882
|
+
const manifestNames = new Set(Object.keys(manifest.packages));
|
|
5883
|
+
const lockfileNames = new Set(Object.keys(lockfile.packages));
|
|
5884
|
+
if (manifestNames.size === 0 && lockfileNames.size === 0) {
|
|
5885
|
+
return check("manifest-lockfile-sync", "pass", "Manifest and lockfile are in sync (both empty)");
|
|
5514
5886
|
}
|
|
5515
|
-
|
|
5516
|
-
|
|
5887
|
+
const inManifestOnly = [];
|
|
5888
|
+
const inLockfileOnly = [];
|
|
5889
|
+
for (const name of manifestNames) {
|
|
5890
|
+
if (!lockfileNames.has(name)) {
|
|
5891
|
+
inManifestOnly.push(name);
|
|
5892
|
+
}
|
|
5517
5893
|
}
|
|
5518
|
-
const
|
|
5519
|
-
|
|
5520
|
-
|
|
5521
|
-
const parts = entry.source.uri.split("/");
|
|
5522
|
-
const org = parts.length >= 2 ? parts[parts.length - 2] : parts[0];
|
|
5523
|
-
if (org) {
|
|
5524
|
-
return { org, name: skillName };
|
|
5894
|
+
for (const name of lockfileNames) {
|
|
5895
|
+
if (!manifestNames.has(name)) {
|
|
5896
|
+
inLockfileOnly.push(name);
|
|
5525
5897
|
}
|
|
5526
5898
|
}
|
|
5527
|
-
|
|
5528
|
-
|
|
5529
|
-
|
|
5530
|
-
|
|
5899
|
+
if (inManifestOnly.length > 0 || inLockfileOnly.length > 0) {
|
|
5900
|
+
const parts = [];
|
|
5901
|
+
if (inManifestOnly.length > 0) {
|
|
5902
|
+
parts.push(`in manifest but not lockfile: ${inManifestOnly.join(", ")}`);
|
|
5903
|
+
}
|
|
5904
|
+
if (inLockfileOnly.length > 0) {
|
|
5905
|
+
parts.push(`in lockfile but not manifest: ${inLockfileOnly.join(", ")}`);
|
|
5906
|
+
}
|
|
5907
|
+
return check("manifest-lockfile-sync", "fail", `Out of sync \u2014 ${parts.join("; ")}`);
|
|
5531
5908
|
}
|
|
5532
|
-
return
|
|
5909
|
+
return check("manifest-lockfile-sync", "pass", "Manifest and lockfile are in sync");
|
|
5533
5910
|
}
|
|
5534
|
-
function
|
|
5535
|
-
const
|
|
5536
|
-
|
|
5537
|
-
|
|
5538
|
-
|
|
5539
|
-
|
|
5540
|
-
|
|
5541
|
-
|
|
5542
|
-
|
|
5911
|
+
function checkSkillFilesExist(projectRoot) {
|
|
5912
|
+
const manifest = readManifest(projectRoot);
|
|
5913
|
+
const entries = Object.keys(manifest.packages);
|
|
5914
|
+
if (entries.length === 0) {
|
|
5915
|
+
return check("skill-files-exist", "pass", "No packages installed");
|
|
5916
|
+
}
|
|
5917
|
+
const missing = [];
|
|
5918
|
+
for (const name of entries) {
|
|
5919
|
+
const canonicalPath = getCanonicalSkillPath(projectRoot, name, "project");
|
|
5920
|
+
if (!existsSync9(canonicalPath) || !lstatSync2(canonicalPath).isDirectory()) {
|
|
5921
|
+
missing.push(name);
|
|
5543
5922
|
}
|
|
5544
|
-
|
|
5545
|
-
|
|
5546
|
-
|
|
5547
|
-
|
|
5548
|
-
|
|
5549
|
-
|
|
5550
|
-
|
|
5923
|
+
}
|
|
5924
|
+
if (missing.length > 0) {
|
|
5925
|
+
return check("skill-files-exist", "fail", `Missing skill directories: ${missing.join(", ")}`);
|
|
5926
|
+
}
|
|
5927
|
+
return check("skill-files-exist", "pass", `All ${entries.length} skill directories present`);
|
|
5928
|
+
}
|
|
5929
|
+
function checkSymlinksValid(projectRoot) {
|
|
5930
|
+
const manifest = readManifest(projectRoot);
|
|
5931
|
+
const entries = Object.entries(manifest.packages);
|
|
5932
|
+
if (entries.length === 0) {
|
|
5933
|
+
return check("symlinks-valid", "pass", "No packages installed");
|
|
5934
|
+
}
|
|
5935
|
+
const broken = [];
|
|
5936
|
+
for (const [name, pkg2] of entries) {
|
|
5937
|
+
for (const agentId of pkg2.agents) {
|
|
5938
|
+
const placementPath = getSkillPlacementPath(agentId, name, "project");
|
|
5939
|
+
if (!placementPath) continue;
|
|
5940
|
+
const agentSkillPath = join11(projectRoot, placementPath);
|
|
5941
|
+
if (!existsSync9(agentSkillPath)) {
|
|
5942
|
+
broken.push(`${name}/${agentId}`);
|
|
5943
|
+
continue;
|
|
5944
|
+
}
|
|
5945
|
+
try {
|
|
5946
|
+
const stats = lstatSync2(agentSkillPath);
|
|
5947
|
+
if (stats.isSymbolicLink()) {
|
|
5948
|
+
const target = readlinkSync2(agentSkillPath);
|
|
5949
|
+
const resolvedTarget = join11(dirname4(agentSkillPath), target);
|
|
5950
|
+
if (!existsSync9(resolvedTarget)) {
|
|
5951
|
+
broken.push(`${name}/${agentId} (broken symlink)`);
|
|
5952
|
+
}
|
|
5551
5953
|
}
|
|
5552
|
-
|
|
5553
|
-
|
|
5554
|
-
spinner.stop();
|
|
5555
|
-
console.log(JSON.stringify(result, null, 2));
|
|
5556
|
-
} else {
|
|
5557
|
-
spinner.succeed(
|
|
5558
|
-
`Draft ${chalk6.green(result.name)} created on branch ${chalk6.cyan(result.branchName)}`
|
|
5559
|
-
);
|
|
5954
|
+
} catch {
|
|
5955
|
+
broken.push(`${name}/${agentId} (unreadable)`);
|
|
5560
5956
|
}
|
|
5561
|
-
}
|
|
5562
|
-
|
|
5563
|
-
|
|
5564
|
-
|
|
5565
|
-
|
|
5566
|
-
|
|
5567
|
-
});
|
|
5568
|
-
|
|
5569
|
-
|
|
5570
|
-
|
|
5571
|
-
|
|
5572
|
-
|
|
5573
|
-
|
|
5574
|
-
|
|
5957
|
+
}
|
|
5958
|
+
}
|
|
5959
|
+
if (broken.length > 0) {
|
|
5960
|
+
return check("symlinks-valid", "fail", `Invalid symlinks: ${broken.join(", ")}`);
|
|
5961
|
+
}
|
|
5962
|
+
const totalLinks = entries.reduce((sum, [, pkg2]) => sum + pkg2.agents.length, 0);
|
|
5963
|
+
return check("symlinks-valid", "pass", `All ${totalLinks} symlinks valid`);
|
|
5964
|
+
}
|
|
5965
|
+
async function checkAuthentication() {
|
|
5966
|
+
const creds = await getCredentials();
|
|
5967
|
+
const hasCredentials = !!(creds?.token ?? creds?.apiKey);
|
|
5968
|
+
if (!hasCredentials) {
|
|
5969
|
+
return check("authentication", "warn", "No credentials configured (run agentver login)");
|
|
5970
|
+
}
|
|
5971
|
+
const platformUrl = getPlatformUrl();
|
|
5972
|
+
if (!platformUrl) {
|
|
5973
|
+
return check("authentication", "warn", "Credentials present but no platform URL configured");
|
|
5974
|
+
}
|
|
5975
|
+
try {
|
|
5976
|
+
const controller = new AbortController();
|
|
5977
|
+
const timeout = setTimeout(() => controller.abort(), NETWORK_TIMEOUT_MS);
|
|
5978
|
+
const response = await fetch(`${platformUrl}/health`, {
|
|
5979
|
+
signal: controller.signal
|
|
5980
|
+
});
|
|
5981
|
+
clearTimeout(timeout);
|
|
5982
|
+
if (response.ok) {
|
|
5983
|
+
return check("authentication", "pass", "Authenticated and platform reachable");
|
|
5984
|
+
}
|
|
5985
|
+
return check(
|
|
5986
|
+
"authentication",
|
|
5987
|
+
"warn",
|
|
5988
|
+
`Platform returned status ${String(response.status)} (offline mode available)`
|
|
5989
|
+
);
|
|
5990
|
+
} catch {
|
|
5991
|
+
return check("authentication", "warn", "Platform unreachable (offline mode available)");
|
|
5992
|
+
}
|
|
5993
|
+
}
|
|
5994
|
+
function checkGitAvailable() {
|
|
5995
|
+
try {
|
|
5996
|
+
execSync("git --version", { stdio: "pipe" });
|
|
5997
|
+
return check("git-available", "pass", "Git is available");
|
|
5998
|
+
} catch {
|
|
5999
|
+
return check("git-available", "fail", "Git is not installed or not on PATH");
|
|
6000
|
+
}
|
|
6001
|
+
}
|
|
6002
|
+
function checkNodeVersion() {
|
|
6003
|
+
const major = parseInt(process.versions.node.split(".")[0] ?? "0", 10);
|
|
6004
|
+
if (major >= MIN_NODE_VERSION) {
|
|
6005
|
+
return check(
|
|
6006
|
+
"node-version",
|
|
6007
|
+
"pass",
|
|
6008
|
+
`Node ${process.versions.node} (>= ${String(MIN_NODE_VERSION)})`
|
|
6009
|
+
);
|
|
6010
|
+
}
|
|
6011
|
+
return check(
|
|
6012
|
+
"node-version",
|
|
6013
|
+
"fail",
|
|
6014
|
+
`Node ${process.versions.node} is below minimum ${String(MIN_NODE_VERSION)}`
|
|
6015
|
+
);
|
|
6016
|
+
}
|
|
6017
|
+
function formatCheck(result) {
|
|
6018
|
+
switch (result.status) {
|
|
6019
|
+
case "pass":
|
|
6020
|
+
return ` ${chalk8.green("\u2713")} ${result.message}`;
|
|
6021
|
+
case "fail":
|
|
6022
|
+
return ` ${chalk8.red("\u2717")} ${result.message}`;
|
|
6023
|
+
case "warn":
|
|
6024
|
+
return ` ${chalk8.yellow("\u26A0")} ${result.message}`;
|
|
6025
|
+
}
|
|
6026
|
+
}
|
|
6027
|
+
function registerDoctorCommand(program2) {
|
|
6028
|
+
program2.command("doctor").description("Run health checks to diagnose common issues").option("--json", "Output as JSON").action(async (options) => {
|
|
6029
|
+
const jsonMode = isJSONMode() || options.json === true;
|
|
6030
|
+
const projectRoot = process.cwd();
|
|
6031
|
+
const checks = [];
|
|
6032
|
+
checks.push(checkManifestIntegrity(projectRoot));
|
|
6033
|
+
checks.push(checkLockfileIntegrity(projectRoot));
|
|
6034
|
+
checks.push(checkManifestLockfileSync(projectRoot));
|
|
6035
|
+
checks.push(checkSkillFilesExist(projectRoot));
|
|
6036
|
+
checks.push(checkSymlinksValid(projectRoot));
|
|
6037
|
+
checks.push(await checkAuthentication());
|
|
6038
|
+
checks.push(checkGitAvailable());
|
|
6039
|
+
checks.push(checkNodeVersion());
|
|
6040
|
+
const passed = checks.filter((c) => c.status === "pass").length;
|
|
6041
|
+
const failed = checks.filter((c) => c.status === "fail").length;
|
|
6042
|
+
const warnings = checks.filter((c) => c.status === "warn").length;
|
|
6043
|
+
if (jsonMode) {
|
|
6044
|
+
const result = { checks, passed, failed, warnings };
|
|
6045
|
+
outputSuccess(result);
|
|
6046
|
+
process.exit(failed > 0 ? 1 : 0);
|
|
6047
|
+
return;
|
|
6048
|
+
}
|
|
6049
|
+
console.log(chalk8.bold("\nHealth checks:\n"));
|
|
6050
|
+
for (const result of checks) {
|
|
6051
|
+
console.log(formatCheck(result));
|
|
6052
|
+
}
|
|
6053
|
+
console.log();
|
|
6054
|
+
console.log(
|
|
6055
|
+
chalk8.dim(
|
|
6056
|
+
`${chalk8.green(String(passed))} passed, ${chalk8.red(String(failed))} failed, ${chalk8.yellow(String(warnings))} warnings`
|
|
6057
|
+
)
|
|
6058
|
+
);
|
|
6059
|
+
console.log();
|
|
6060
|
+
process.exit(failed > 0 ? 1 : 0);
|
|
6061
|
+
});
|
|
6062
|
+
}
|
|
6063
|
+
|
|
6064
|
+
// src/commands/draft.ts
|
|
6065
|
+
import { existsSync as existsSync10, readFileSync as readFileSync9 } from "fs";
|
|
6066
|
+
import { basename as basename2, join as join12 } from "path";
|
|
6067
|
+
import chalk9 from "chalk";
|
|
6068
|
+
import ora2 from "ora";
|
|
6069
|
+
|
|
6070
|
+
// src/utils/retry.ts
|
|
6071
|
+
var MAX_RETRY_ATTEMPTS = 3;
|
|
6072
|
+
var RETRY_BASE_DELAY_MS = 1e3;
|
|
6073
|
+
var RequestTimeoutError = class extends Error {
|
|
6074
|
+
constructor(label) {
|
|
6075
|
+
super(`${label} request timed out. The service may be experiencing issues.`);
|
|
6076
|
+
this.name = "RequestTimeoutError";
|
|
6077
|
+
}
|
|
6078
|
+
};
|
|
6079
|
+
function isRetryable(error, response) {
|
|
6080
|
+
if (error instanceof RequestTimeoutError) return false;
|
|
6081
|
+
if (error instanceof DOMException && error.name === "AbortError") return false;
|
|
6082
|
+
if (!response) return true;
|
|
6083
|
+
return response.status >= 500;
|
|
6084
|
+
}
|
|
6085
|
+
function delay(ms) {
|
|
6086
|
+
return new Promise((resolve4) => setTimeout(resolve4, ms));
|
|
6087
|
+
}
|
|
6088
|
+
function isAuthExpired(status) {
|
|
6089
|
+
return status === 401;
|
|
6090
|
+
}
|
|
6091
|
+
async function fetchWithRetry(options) {
|
|
6092
|
+
let lastError;
|
|
6093
|
+
let lastResponse;
|
|
6094
|
+
for (let attempt = 1; attempt <= MAX_RETRY_ATTEMPTS; attempt++) {
|
|
6095
|
+
const controller = new AbortController();
|
|
6096
|
+
const timeoutId = setTimeout(() => controller.abort(), options.timeoutMs);
|
|
6097
|
+
try {
|
|
6098
|
+
const config = options.buildRequest();
|
|
6099
|
+
const response = await fetch(config.url, {
|
|
6100
|
+
method: config.method ?? "GET",
|
|
6101
|
+
headers: config.headers,
|
|
6102
|
+
body: config.body,
|
|
6103
|
+
signal: controller.signal
|
|
6104
|
+
});
|
|
6105
|
+
clearTimeout(timeoutId);
|
|
6106
|
+
if (response.ok) {
|
|
6107
|
+
return response.json();
|
|
6108
|
+
}
|
|
6109
|
+
if (isAuthExpired(response.status)) {
|
|
6110
|
+
options.onAuthExpired();
|
|
6111
|
+
}
|
|
6112
|
+
lastResponse = response;
|
|
6113
|
+
lastError = new Error(
|
|
6114
|
+
`${options.label} error (${response.status}): ${await response.text().catch(() => "Unknown error")}`
|
|
6115
|
+
);
|
|
6116
|
+
if (!isRetryable(void 0, response)) {
|
|
6117
|
+
throw lastError;
|
|
6118
|
+
}
|
|
6119
|
+
} catch (error) {
|
|
6120
|
+
clearTimeout(timeoutId);
|
|
6121
|
+
if (error instanceof DOMException && error.name === "AbortError") {
|
|
6122
|
+
throw new RequestTimeoutError(options.label);
|
|
6123
|
+
}
|
|
6124
|
+
lastError = error;
|
|
6125
|
+
lastResponse = void 0;
|
|
6126
|
+
if (!isRetryable(error)) {
|
|
6127
|
+
throw error;
|
|
6128
|
+
}
|
|
6129
|
+
}
|
|
6130
|
+
if (attempt < MAX_RETRY_ATTEMPTS) {
|
|
6131
|
+
const retryDelay = RETRY_BASE_DELAY_MS * 2 ** (attempt - 1);
|
|
6132
|
+
process.stderr.write(
|
|
6133
|
+
`${options.label} request failed (attempt ${attempt}/${MAX_RETRY_ATTEMPTS}), retrying in ${retryDelay / 1e3}s...
|
|
6134
|
+
`
|
|
6135
|
+
);
|
|
6136
|
+
await delay(retryDelay);
|
|
6137
|
+
}
|
|
6138
|
+
}
|
|
6139
|
+
if (lastResponse && !lastResponse.ok) {
|
|
6140
|
+
throw lastError;
|
|
6141
|
+
}
|
|
6142
|
+
throw lastError;
|
|
6143
|
+
}
|
|
6144
|
+
|
|
6145
|
+
// src/registry/platform.ts
|
|
6146
|
+
var REQUEST_TIMEOUT_MS = 3e4;
|
|
6147
|
+
async function platformFetch(path, options = {}) {
|
|
6148
|
+
const platformUrl = getPlatformUrl();
|
|
6149
|
+
if (!platformUrl) {
|
|
6150
|
+
throw new AgentverError(
|
|
6151
|
+
"UNAUTHORISED",
|
|
6152
|
+
"No platform URL configured. Run `agentver login <url>` to connect."
|
|
6153
|
+
);
|
|
6154
|
+
}
|
|
6155
|
+
const credentials = await getCredentials();
|
|
6156
|
+
if (!credentials?.token && !credentials?.apiKey) {
|
|
6157
|
+
throw new AgentverError("UNAUTHORISED", "Not authenticated. Run `agentver login` to sign in.");
|
|
6158
|
+
}
|
|
6159
|
+
const url = `${platformUrl}/api/v1${path}`;
|
|
6160
|
+
const headers = {
|
|
6161
|
+
"Content-Type": "application/json"
|
|
6162
|
+
};
|
|
6163
|
+
if (credentials.token) {
|
|
6164
|
+
headers.Authorization = `Bearer ${credentials.token}`;
|
|
6165
|
+
} else if (credentials.apiKey) {
|
|
6166
|
+
headers["X-API-Key"] = credentials.apiKey;
|
|
6167
|
+
}
|
|
6168
|
+
return fetchWithRetry({
|
|
6169
|
+
label: "Platform",
|
|
6170
|
+
timeoutMs: options.timeout ?? REQUEST_TIMEOUT_MS,
|
|
6171
|
+
buildRequest: () => ({
|
|
6172
|
+
url,
|
|
6173
|
+
method: options.method ?? "GET",
|
|
6174
|
+
headers,
|
|
6175
|
+
body: options.body ? JSON.stringify(options.body) : void 0
|
|
6176
|
+
}),
|
|
6177
|
+
onAuthExpired: () => {
|
|
6178
|
+
throw new AgentverError(
|
|
6179
|
+
"UNAUTHORISED",
|
|
6180
|
+
"Authentication expired. Run `agentver login` to re-authenticate."
|
|
6181
|
+
);
|
|
6182
|
+
}
|
|
6183
|
+
});
|
|
6184
|
+
}
|
|
6185
|
+
async function platformFetchSilent(path, options = {}) {
|
|
6186
|
+
try {
|
|
6187
|
+
return await platformFetch(path, options);
|
|
6188
|
+
} catch {
|
|
6189
|
+
return null;
|
|
6190
|
+
}
|
|
6191
|
+
}
|
|
6192
|
+
|
|
6193
|
+
// src/commands/draft.ts
|
|
6194
|
+
function resolveSkillIdentity() {
|
|
6195
|
+
const cwd = process.cwd();
|
|
6196
|
+
const skillMdPath = join12(cwd, "SKILL.md");
|
|
6197
|
+
let skillName = null;
|
|
6198
|
+
if (existsSync10(skillMdPath)) {
|
|
6199
|
+
const content = readFileSync9(skillMdPath, "utf-8");
|
|
6200
|
+
const nameMatch = content.match(/^name:\s*(.+)$/m);
|
|
6201
|
+
skillName = nameMatch?.[1]?.trim() ?? basename2(cwd);
|
|
6202
|
+
}
|
|
6203
|
+
if (!skillName) {
|
|
6204
|
+
skillName = basename2(cwd);
|
|
6205
|
+
}
|
|
6206
|
+
const manifest = readManifest(cwd);
|
|
6207
|
+
const entry = manifest.packages[skillName];
|
|
6208
|
+
if (entry?.source.type === "git") {
|
|
6209
|
+
const parts = entry.source.uri.split("/");
|
|
6210
|
+
const org = parts.length >= 2 ? parts[parts.length - 2] : parts[0];
|
|
6211
|
+
if (org) {
|
|
6212
|
+
return { org, name: skillName };
|
|
6213
|
+
}
|
|
6214
|
+
}
|
|
6215
|
+
const pathParts = cwd.split("/");
|
|
6216
|
+
const skillsIdx = pathParts.lastIndexOf("skills");
|
|
6217
|
+
if (skillsIdx >= 0 && pathParts.length > skillsIdx + 2) {
|
|
6218
|
+
return { org: pathParts[skillsIdx + 1], name: skillName };
|
|
6219
|
+
}
|
|
6220
|
+
return null;
|
|
6221
|
+
}
|
|
6222
|
+
function registerDraftCommand(program2) {
|
|
6223
|
+
const draft = program2.command("draft").description("Manage skill drafts (branches)");
|
|
6224
|
+
draft.command("create <name>").description("Create a draft branch for the current skill").option("--json", "Output as JSON").action(async (name, options) => {
|
|
6225
|
+
const identity = resolveSkillIdentity();
|
|
6226
|
+
if (!identity) {
|
|
6227
|
+
process.stderr.write(
|
|
6228
|
+
chalk9.red("Could not determine skill identity. Run this from a skill directory.\n")
|
|
6229
|
+
);
|
|
6230
|
+
process.exit(1);
|
|
6231
|
+
}
|
|
6232
|
+
const spinner = ora2(`Creating draft "${name}"...`).start();
|
|
6233
|
+
try {
|
|
6234
|
+
const result = await platformFetch(
|
|
6235
|
+
`/skills/@${identity.org}/${identity.name}/drafts`,
|
|
6236
|
+
{
|
|
6237
|
+
method: "POST",
|
|
6238
|
+
body: { name }
|
|
6239
|
+
}
|
|
6240
|
+
);
|
|
6241
|
+
if (options.json) {
|
|
6242
|
+
spinner.stop();
|
|
6243
|
+
console.log(JSON.stringify(result, null, 2));
|
|
6244
|
+
} else {
|
|
6245
|
+
spinner.succeed(
|
|
6246
|
+
`Draft ${chalk9.green(result.name)} created on branch ${chalk9.cyan(result.branchName)}`
|
|
6247
|
+
);
|
|
6248
|
+
}
|
|
6249
|
+
} catch (error) {
|
|
6250
|
+
spinner.fail(
|
|
6251
|
+
`Failed to create draft: ${error instanceof Error ? error.message : String(error)}`
|
|
6252
|
+
);
|
|
6253
|
+
process.exit(1);
|
|
6254
|
+
}
|
|
6255
|
+
});
|
|
6256
|
+
draft.command("list").description("List open drafts for the current skill").option("--json", "Output as JSON").action(async (options) => {
|
|
6257
|
+
const identity = resolveSkillIdentity();
|
|
6258
|
+
if (!identity) {
|
|
6259
|
+
process.stderr.write(
|
|
6260
|
+
chalk9.red("Could not determine skill identity. Run this from a skill directory.\n")
|
|
6261
|
+
);
|
|
6262
|
+
process.exit(1);
|
|
5575
6263
|
}
|
|
5576
6264
|
const spinner = ora2("Fetching drafts...").start();
|
|
5577
6265
|
try {
|
|
@@ -5584,16 +6272,16 @@ function registerDraftCommand(program2) {
|
|
|
5584
6272
|
return;
|
|
5585
6273
|
}
|
|
5586
6274
|
if (drafts.length === 0) {
|
|
5587
|
-
process.stdout.write(
|
|
6275
|
+
process.stdout.write(chalk9.dim("No open drafts.\n"));
|
|
5588
6276
|
return;
|
|
5589
6277
|
}
|
|
5590
|
-
process.stdout.write(
|
|
6278
|
+
process.stdout.write(chalk9.bold(`
|
|
5591
6279
|
Drafts for @${identity.org}/${identity.name}:
|
|
5592
6280
|
|
|
5593
6281
|
`));
|
|
5594
6282
|
for (const d of drafts) {
|
|
5595
6283
|
process.stdout.write(
|
|
5596
|
-
` ${
|
|
6284
|
+
` ${chalk9.green(d.name)} ${chalk9.dim(`(${d.latestCommitId.slice(0, 7)})`)} ${chalk9.dim(d.latestMessage)}
|
|
5597
6285
|
`
|
|
5598
6286
|
);
|
|
5599
6287
|
}
|
|
@@ -5609,7 +6297,7 @@ Drafts for @${identity.org}/${identity.name}:
|
|
|
5609
6297
|
const identity = resolveSkillIdentity();
|
|
5610
6298
|
if (!identity) {
|
|
5611
6299
|
process.stderr.write(
|
|
5612
|
-
|
|
6300
|
+
chalk9.red("Could not determine skill identity. Run this from a skill directory.\n")
|
|
5613
6301
|
);
|
|
5614
6302
|
process.exit(1);
|
|
5615
6303
|
}
|
|
@@ -5617,7 +6305,7 @@ Drafts for @${identity.org}/${identity.name}:
|
|
|
5617
6305
|
const lockfile = readLockfile(projectRoot);
|
|
5618
6306
|
const lockEntry = lockfile.packages[identity.name];
|
|
5619
6307
|
if (!lockEntry) {
|
|
5620
|
-
process.stderr.write(
|
|
6308
|
+
process.stderr.write(chalk9.red(`Skill "${identity.name}" not found in lockfile.
|
|
5621
6309
|
`));
|
|
5622
6310
|
process.exit(1);
|
|
5623
6311
|
}
|
|
@@ -5639,7 +6327,7 @@ Drafts for @${identity.org}/${identity.name}:
|
|
|
5639
6327
|
);
|
|
5640
6328
|
} else {
|
|
5641
6329
|
process.stdout.write(
|
|
5642
|
-
`Switched to draft ${
|
|
6330
|
+
`Switched to draft ${chalk9.green(name)} ${chalk9.dim(`(ref: draft/${identity.name}/${name})`)}
|
|
5643
6331
|
`
|
|
5644
6332
|
);
|
|
5645
6333
|
}
|
|
@@ -5648,7 +6336,7 @@ Drafts for @${identity.org}/${identity.name}:
|
|
|
5648
6336
|
const identity = resolveSkillIdentity();
|
|
5649
6337
|
if (!identity) {
|
|
5650
6338
|
process.stderr.write(
|
|
5651
|
-
|
|
6339
|
+
chalk9.red("Could not determine skill identity. Run this from a skill directory.\n")
|
|
5652
6340
|
);
|
|
5653
6341
|
process.exit(1);
|
|
5654
6342
|
}
|
|
@@ -5656,12 +6344,12 @@ Drafts for @${identity.org}/${identity.name}:
|
|
|
5656
6344
|
const lockfile = readLockfile(projectRoot);
|
|
5657
6345
|
const lockEntry = lockfile.packages[identity.name];
|
|
5658
6346
|
if (!lockEntry || lockEntry.source.type !== "git") {
|
|
5659
|
-
process.stderr.write(
|
|
6347
|
+
process.stderr.write(chalk9.red("Skill not found in lockfile.\n"));
|
|
5660
6348
|
process.exit(1);
|
|
5661
6349
|
}
|
|
5662
6350
|
const currentRef = lockEntry.source.ref;
|
|
5663
6351
|
if (!currentRef.startsWith("draft/")) {
|
|
5664
|
-
process.stderr.write(
|
|
6352
|
+
process.stderr.write(chalk9.red(`Not on a draft branch. Current ref: ${currentRef}
|
|
5665
6353
|
`));
|
|
5666
6354
|
process.exit(1);
|
|
5667
6355
|
}
|
|
@@ -5694,7 +6382,7 @@ Drafts for @${identity.org}/${identity.name}:
|
|
|
5694
6382
|
);
|
|
5695
6383
|
} else {
|
|
5696
6384
|
spinner.succeed(
|
|
5697
|
-
`Draft merged to main ${result.commitSha ?
|
|
6385
|
+
`Draft merged to main ${result.commitSha ? chalk9.dim(`(${result.commitSha.slice(0, 7)})`) : ""}`
|
|
5698
6386
|
);
|
|
5699
6387
|
}
|
|
5700
6388
|
} catch (error) {
|
|
@@ -5708,7 +6396,7 @@ Drafts for @${identity.org}/${identity.name}:
|
|
|
5708
6396
|
const identity = resolveSkillIdentity();
|
|
5709
6397
|
if (!identity) {
|
|
5710
6398
|
process.stderr.write(
|
|
5711
|
-
|
|
6399
|
+
chalk9.red("Could not determine skill identity. Run this from a skill directory.\n")
|
|
5712
6400
|
);
|
|
5713
6401
|
process.exit(1);
|
|
5714
6402
|
}
|
|
@@ -5716,12 +6404,12 @@ Drafts for @${identity.org}/${identity.name}:
|
|
|
5716
6404
|
const lockfile = readLockfile(projectRoot);
|
|
5717
6405
|
const lockEntry = lockfile.packages[identity.name];
|
|
5718
6406
|
if (!lockEntry || lockEntry.source.type !== "git") {
|
|
5719
|
-
process.stderr.write(
|
|
6407
|
+
process.stderr.write(chalk9.red("Skill not found in lockfile.\n"));
|
|
5720
6408
|
process.exit(1);
|
|
5721
6409
|
}
|
|
5722
6410
|
const currentRef = lockEntry.source.ref;
|
|
5723
6411
|
if (!currentRef.startsWith("draft/")) {
|
|
5724
|
-
process.stderr.write(
|
|
6412
|
+
process.stderr.write(chalk9.red(`Not on a draft branch. Current ref: ${currentRef}
|
|
5725
6413
|
`));
|
|
5726
6414
|
process.exit(1);
|
|
5727
6415
|
}
|
|
@@ -5750,7 +6438,7 @@ Drafts for @${identity.org}/${identity.name}:
|
|
|
5750
6438
|
)
|
|
5751
6439
|
);
|
|
5752
6440
|
} else {
|
|
5753
|
-
spinner.succeed(`Draft discarded. Switched back to ${
|
|
6441
|
+
spinner.succeed(`Draft discarded. Switched back to ${chalk9.cyan("main")}.`);
|
|
5754
6442
|
}
|
|
5755
6443
|
} catch (error) {
|
|
5756
6444
|
spinner.fail(
|
|
@@ -5761,10 +6449,124 @@ Drafts for @${identity.org}/${identity.name}:
|
|
|
5761
6449
|
});
|
|
5762
6450
|
}
|
|
5763
6451
|
|
|
6452
|
+
// src/commands/info.ts
|
|
6453
|
+
import { readFileSync as readFileSync10 } from "fs";
|
|
6454
|
+
import { join as join13 } from "path";
|
|
6455
|
+
import chalk10 from "chalk";
|
|
6456
|
+
function formatBytes2(bytes) {
|
|
6457
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
6458
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
6459
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
6460
|
+
}
|
|
6461
|
+
function registerInfoCommand(program2) {
|
|
6462
|
+
program2.command("info <name>").description("Show detailed information about an installed package").option("--json", "Output as JSON").action(async (name, options) => {
|
|
6463
|
+
const jsonMode = isJSONMode() || options.json === true;
|
|
6464
|
+
const projectRoot = process.cwd();
|
|
6465
|
+
const manifest = readManifest(projectRoot);
|
|
6466
|
+
const pkg2 = manifest.packages[name];
|
|
6467
|
+
if (!pkg2) {
|
|
6468
|
+
if (jsonMode) {
|
|
6469
|
+
outputError("NOT_FOUND", `Package "${name}" is not installed.`);
|
|
6470
|
+
process.exit(1);
|
|
6471
|
+
}
|
|
6472
|
+
console.error(chalk10.red(`Package "${name}" is not installed.`));
|
|
6473
|
+
process.exit(1);
|
|
6474
|
+
}
|
|
6475
|
+
const spinner = createSpinner("Reading package information...").start();
|
|
6476
|
+
const lockfile = readLockfile(projectRoot);
|
|
6477
|
+
const lockfileEntry = lockfile.packages[name];
|
|
6478
|
+
const shortName = name.split("/").pop();
|
|
6479
|
+
let fileCount = 0;
|
|
6480
|
+
let totalSize = 0;
|
|
6481
|
+
let locallyModified = false;
|
|
6482
|
+
let skillTitle;
|
|
6483
|
+
let skillDescription;
|
|
6484
|
+
const readPath = resolveReadPath(projectRoot, shortName, pkg2.agents);
|
|
6485
|
+
if (readPath) {
|
|
6486
|
+
try {
|
|
6487
|
+
const files = await readFilesFromDirectory(readPath);
|
|
6488
|
+
fileCount = files.length;
|
|
6489
|
+
totalSize = files.reduce((sum, f) => sum + f.size, 0);
|
|
6490
|
+
if (lockfileEntry?.integrity && files.length > 0) {
|
|
6491
|
+
const localIntegrity = computeSha256FromFiles(files);
|
|
6492
|
+
locallyModified = localIntegrity !== lockfileEntry.integrity;
|
|
6493
|
+
}
|
|
6494
|
+
const skillMdPath = join13(readPath, "SKILL.md");
|
|
6495
|
+
try {
|
|
6496
|
+
const skillMdContent = readFileSync10(skillMdPath, "utf-8");
|
|
6497
|
+
const { frontmatter } = parseSkillFrontmatter(skillMdContent);
|
|
6498
|
+
skillTitle = frontmatter.name;
|
|
6499
|
+
skillDescription = frontmatter.description;
|
|
6500
|
+
} catch {
|
|
6501
|
+
}
|
|
6502
|
+
} catch {
|
|
6503
|
+
}
|
|
6504
|
+
}
|
|
6505
|
+
const sourceInfo = pkg2.source.type === "git" ? {
|
|
6506
|
+
type: "git",
|
|
6507
|
+
uri: pkg2.source.uri,
|
|
6508
|
+
ref: pkg2.source.ref,
|
|
6509
|
+
commit: pkg2.source.commit
|
|
6510
|
+
} : { type: "well-known", hostname: pkg2.source.hostname };
|
|
6511
|
+
const result = {
|
|
6512
|
+
name,
|
|
6513
|
+
source: sourceInfo,
|
|
6514
|
+
agents: pkg2.agents,
|
|
6515
|
+
installedAt: pkg2.installedAt,
|
|
6516
|
+
modified: locallyModified,
|
|
6517
|
+
integrity: lockfileEntry?.integrity,
|
|
6518
|
+
files: {
|
|
6519
|
+
count: fileCount,
|
|
6520
|
+
totalSize
|
|
6521
|
+
},
|
|
6522
|
+
skill: skillTitle && skillDescription ? { title: skillTitle, description: skillDescription } : void 0
|
|
6523
|
+
};
|
|
6524
|
+
if (jsonMode) {
|
|
6525
|
+
spinner.stop();
|
|
6526
|
+
outputSuccess(result);
|
|
6527
|
+
return;
|
|
6528
|
+
}
|
|
6529
|
+
spinner.stop();
|
|
6530
|
+
console.log();
|
|
6531
|
+
console.log(chalk10.bold(name));
|
|
6532
|
+
console.log();
|
|
6533
|
+
if (pkg2.source.type === "git") {
|
|
6534
|
+
console.log(` ${chalk10.dim("Source:")} ${pkg2.source.uri}`);
|
|
6535
|
+
console.log(` ${chalk10.dim("Ref:")} ${chalk10.cyan(pkg2.source.ref)}`);
|
|
6536
|
+
console.log(` ${chalk10.dim("Commit:")} ${chalk10.dim(pkg2.source.commit.slice(0, 7))}`);
|
|
6537
|
+
} else {
|
|
6538
|
+
console.log(
|
|
6539
|
+
` ${chalk10.dim("Source:")} ${pkg2.source.hostname} ${chalk10.dim("[well-known]")}`
|
|
6540
|
+
);
|
|
6541
|
+
}
|
|
6542
|
+
console.log(
|
|
6543
|
+
` ${chalk10.dim("Agents:")} ${pkg2.agents.length > 0 ? pkg2.agents.join(", ") : chalk10.dim("none")}`
|
|
6544
|
+
);
|
|
6545
|
+
console.log(` ${chalk10.dim("Installed:")} ${pkg2.installedAt}`);
|
|
6546
|
+
console.log(
|
|
6547
|
+
` ${chalk10.dim("Modified:")} ${locallyModified ? chalk10.yellow("yes") : chalk10.green("no")}`
|
|
6548
|
+
);
|
|
6549
|
+
if (lockfileEntry?.integrity) {
|
|
6550
|
+
console.log(` ${chalk10.dim("Integrity:")} ${lockfileEntry.integrity}`);
|
|
6551
|
+
}
|
|
6552
|
+
console.log(
|
|
6553
|
+
` ${chalk10.dim("Files:")} ${fileCount} file${fileCount !== 1 ? "s" : ""} (${formatBytes2(totalSize)})`
|
|
6554
|
+
);
|
|
6555
|
+
if (skillTitle) {
|
|
6556
|
+
console.log();
|
|
6557
|
+
console.log(` ${chalk10.dim("Skill:")} ${skillTitle}`);
|
|
6558
|
+
if (skillDescription) {
|
|
6559
|
+
console.log(` ${chalk10.dim("Description:")} ${skillDescription}`);
|
|
6560
|
+
}
|
|
6561
|
+
}
|
|
6562
|
+
console.log();
|
|
6563
|
+
});
|
|
6564
|
+
}
|
|
6565
|
+
|
|
5764
6566
|
// src/commands/init.ts
|
|
5765
|
-
import { existsSync as
|
|
5766
|
-
import { join as
|
|
5767
|
-
import
|
|
6567
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync7, writeFileSync as writeFileSync6 } from "fs";
|
|
6568
|
+
import { join as join14 } from "path";
|
|
6569
|
+
import chalk11 from "chalk";
|
|
5768
6570
|
import prompts from "prompts";
|
|
5769
6571
|
var TOKEN_BUDGET = 5e3;
|
|
5770
6572
|
function estimateTokens(content) {
|
|
@@ -5774,11 +6576,11 @@ function warnIfOverBudget(filePath, content) {
|
|
|
5774
6576
|
const tokens = estimateTokens(content);
|
|
5775
6577
|
if (tokens > TOKEN_BUDGET) {
|
|
5776
6578
|
console.log(
|
|
5777
|
-
|
|
6579
|
+
chalk11.yellow(`
|
|
5778
6580
|
Warning: ${filePath} is ~${tokens} tokens (recommended < ${TOKEN_BUDGET}).`)
|
|
5779
6581
|
);
|
|
5780
6582
|
console.log(
|
|
5781
|
-
|
|
6583
|
+
chalk11.yellow(" Move detailed content to docs/ or examples/ for progressive disclosure.")
|
|
5782
6584
|
);
|
|
5783
6585
|
}
|
|
5784
6586
|
}
|
|
@@ -6007,7 +6809,7 @@ agentver install github.com/YOUR_ORG/YOUR_REPO@main
|
|
|
6007
6809
|
}
|
|
6008
6810
|
function createGitkeep(dirPath) {
|
|
6009
6811
|
mkdirSync7(dirPath, { recursive: true });
|
|
6010
|
-
writeFileSync6(
|
|
6812
|
+
writeFileSync6(join14(dirPath, ".gitkeep"), "", "utf-8");
|
|
6011
6813
|
}
|
|
6012
6814
|
function registerInitCommand(program2) {
|
|
6013
6815
|
program2.command("init").description("Scaffold a new package").option("--type <type>", "Package type: skill, agent, plugin, script, prompt", "skill").option("--repo", "Scaffold in a Git-repo-friendly structure").option("--name <name>", "Package name (required in JSON mode)").option("--description <desc>", "Package description").action(
|
|
@@ -6060,13 +6862,13 @@ function registerInitCommand(program2) {
|
|
|
6060
6862
|
description = response.description ?? "";
|
|
6061
6863
|
author = response.author ?? "";
|
|
6062
6864
|
}
|
|
6063
|
-
const dir =
|
|
6064
|
-
if (
|
|
6865
|
+
const dir = join14(process.cwd(), packageName);
|
|
6866
|
+
if (existsSync11(dir)) {
|
|
6065
6867
|
if (isJSONMode()) {
|
|
6066
6868
|
outputError("ALREADY_EXISTS", `Directory "${packageName}" already exists.`);
|
|
6067
6869
|
process.exit(1);
|
|
6068
6870
|
}
|
|
6069
|
-
console.error(
|
|
6871
|
+
console.error(chalk11.red(`Directory "${packageName}" already exists.`));
|
|
6070
6872
|
process.exit(1);
|
|
6071
6873
|
}
|
|
6072
6874
|
mkdirSync7(dir, { recursive: true });
|
|
@@ -6077,14 +6879,14 @@ function registerInitCommand(program2) {
|
|
|
6077
6879
|
case "skill": {
|
|
6078
6880
|
fileName = "SKILL.md";
|
|
6079
6881
|
const content = applyReplacements(SKILL_TEMPLATE);
|
|
6080
|
-
writeFileSync6(
|
|
6882
|
+
writeFileSync6(join14(dir, fileName), content, "utf-8");
|
|
6081
6883
|
createdFiles.push(fileName);
|
|
6082
6884
|
if (!options.repo) {
|
|
6083
|
-
mkdirSync7(
|
|
6084
|
-
writeFileSync6(
|
|
6885
|
+
mkdirSync7(join14(dir, "examples"), { recursive: true });
|
|
6886
|
+
writeFileSync6(join14(dir, "examples", "README.md"), EXAMPLES_README, "utf-8");
|
|
6085
6887
|
createdFiles.push("examples/README.md");
|
|
6086
|
-
mkdirSync7(
|
|
6087
|
-
writeFileSync6(
|
|
6888
|
+
mkdirSync7(join14(dir, "docs"), { recursive: true });
|
|
6889
|
+
writeFileSync6(join14(dir, "docs", "README.md"), DOCS_README, "utf-8");
|
|
6088
6890
|
createdFiles.push("docs/README.md");
|
|
6089
6891
|
}
|
|
6090
6892
|
if (!isJSONMode()) {
|
|
@@ -6095,29 +6897,29 @@ function registerInitCommand(program2) {
|
|
|
6095
6897
|
case "agent": {
|
|
6096
6898
|
fileName = "CLAUDE.md";
|
|
6097
6899
|
const content = applyReplacements(AGENT_CONFIG_TEMPLATE);
|
|
6098
|
-
writeFileSync6(
|
|
6900
|
+
writeFileSync6(join14(dir, fileName), content, "utf-8");
|
|
6099
6901
|
createdFiles.push(fileName);
|
|
6100
6902
|
if (!options.repo) {
|
|
6101
|
-
mkdirSync7(
|
|
6903
|
+
mkdirSync7(join14(dir, "rules"), { recursive: true });
|
|
6102
6904
|
}
|
|
6103
6905
|
break;
|
|
6104
6906
|
}
|
|
6105
6907
|
case "plugin": {
|
|
6106
6908
|
fileName = "plugin.json";
|
|
6107
|
-
writeFileSync6(
|
|
6909
|
+
writeFileSync6(join14(dir, fileName), applyReplacements(PLUGIN_TEMPLATE), "utf-8");
|
|
6108
6910
|
createdFiles.push(fileName);
|
|
6109
6911
|
if (!options.repo) {
|
|
6110
|
-
mkdirSync7(
|
|
6912
|
+
mkdirSync7(join14(dir, "scripts"), { recursive: true });
|
|
6111
6913
|
}
|
|
6112
6914
|
break;
|
|
6113
6915
|
}
|
|
6114
6916
|
case "script": {
|
|
6115
6917
|
fileName = "script.json";
|
|
6116
|
-
writeFileSync6(
|
|
6918
|
+
writeFileSync6(join14(dir, fileName), applyReplacements(SCRIPT_TEMPLATE), "utf-8");
|
|
6117
6919
|
createdFiles.push(fileName);
|
|
6118
|
-
mkdirSync7(
|
|
6920
|
+
mkdirSync7(join14(dir, "src"), { recursive: true });
|
|
6119
6921
|
writeFileSync6(
|
|
6120
|
-
|
|
6922
|
+
join14(dir, "src", "index.ts"),
|
|
6121
6923
|
applyReplacements(SCRIPT_ENTRY_TEMPLATE),
|
|
6122
6924
|
"utf-8"
|
|
6123
6925
|
);
|
|
@@ -6127,10 +6929,10 @@ function registerInitCommand(program2) {
|
|
|
6127
6929
|
case "prompt": {
|
|
6128
6930
|
fileName = "PROMPT.md";
|
|
6129
6931
|
const content = applyReplacements(PROMPT_TEMPLATE);
|
|
6130
|
-
writeFileSync6(
|
|
6932
|
+
writeFileSync6(join14(dir, fileName), content, "utf-8");
|
|
6131
6933
|
createdFiles.push(fileName);
|
|
6132
6934
|
if (!options.repo) {
|
|
6133
|
-
mkdirSync7(
|
|
6935
|
+
mkdirSync7(join14(dir, "variants"), { recursive: true });
|
|
6134
6936
|
}
|
|
6135
6937
|
if (!isJSONMode()) {
|
|
6136
6938
|
warnIfOverBudget(fileName, content);
|
|
@@ -6142,28 +6944,28 @@ function registerInitCommand(program2) {
|
|
|
6142
6944
|
outputError("VALIDATION_ERROR", `Unknown package type: "${options.type}"`);
|
|
6143
6945
|
process.exit(1);
|
|
6144
6946
|
}
|
|
6145
|
-
console.error(
|
|
6947
|
+
console.error(chalk11.red(`Unknown package type: "${options.type}"`));
|
|
6146
6948
|
process.exit(1);
|
|
6147
6949
|
}
|
|
6148
6950
|
}
|
|
6149
6951
|
if (options.repo) {
|
|
6150
|
-
const skillsDir =
|
|
6952
|
+
const skillsDir = join14(dir, "skills", "example-skill");
|
|
6151
6953
|
mkdirSync7(skillsDir, { recursive: true });
|
|
6152
|
-
writeFileSync6(
|
|
6954
|
+
writeFileSync6(join14(skillsDir, "SKILL.md"), EXAMPLE_SKILL_TEMPLATE, "utf-8");
|
|
6153
6955
|
createdFiles.push("skills/example-skill/SKILL.md");
|
|
6154
|
-
mkdirSync7(
|
|
6155
|
-
writeFileSync6(
|
|
6956
|
+
mkdirSync7(join14(skillsDir, "examples"), { recursive: true });
|
|
6957
|
+
writeFileSync6(join14(skillsDir, "examples", "README.md"), EXAMPLES_README, "utf-8");
|
|
6156
6958
|
createdFiles.push("skills/example-skill/examples/README.md");
|
|
6157
|
-
mkdirSync7(
|
|
6158
|
-
writeFileSync6(
|
|
6959
|
+
mkdirSync7(join14(skillsDir, "docs"), { recursive: true });
|
|
6960
|
+
writeFileSync6(join14(skillsDir, "docs", "README.md"), DOCS_README, "utf-8");
|
|
6159
6961
|
createdFiles.push("skills/example-skill/docs/README.md");
|
|
6160
|
-
createGitkeep(
|
|
6962
|
+
createGitkeep(join14(dir, "configs"));
|
|
6161
6963
|
createdFiles.push("configs/.gitkeep");
|
|
6162
|
-
createGitkeep(
|
|
6964
|
+
createGitkeep(join14(dir, "prompts"));
|
|
6163
6965
|
createdFiles.push("prompts/.gitkeep");
|
|
6164
|
-
writeFileSync6(
|
|
6966
|
+
writeFileSync6(join14(dir, "README.md"), buildReadme(packageName, description), "utf-8");
|
|
6165
6967
|
createdFiles.push("README.md");
|
|
6166
|
-
writeFileSync6(
|
|
6968
|
+
writeFileSync6(join14(dir, ".agentverignore"), AGENTVERIGNORE_CONTENT, "utf-8");
|
|
6167
6969
|
createdFiles.push(".agentverignore");
|
|
6168
6970
|
}
|
|
6169
6971
|
if (isJSONMode()) {
|
|
@@ -6175,25 +6977,25 @@ function registerInitCommand(program2) {
|
|
|
6175
6977
|
});
|
|
6176
6978
|
return;
|
|
6177
6979
|
}
|
|
6178
|
-
console.log(
|
|
6980
|
+
console.log(chalk11.green(`
|
|
6179
6981
|
Created ${fileName} in ./${packageName}/`));
|
|
6180
6982
|
if (options.repo) {
|
|
6181
|
-
console.log(
|
|
6983
|
+
console.log(chalk11.dim("Repo structure created with skills/, configs/, prompts/"));
|
|
6182
6984
|
console.log(
|
|
6183
|
-
|
|
6985
|
+
chalk11.dim(`Install with: agentver install github.com/YOUR_ORG/YOUR_REPO@main`)
|
|
6184
6986
|
);
|
|
6185
6987
|
} else {
|
|
6186
|
-
console.log(
|
|
6988
|
+
console.log(chalk11.dim(`Edit the file, then run: agentver publish ./${packageName}`));
|
|
6187
6989
|
}
|
|
6188
6990
|
}
|
|
6189
6991
|
);
|
|
6190
6992
|
}
|
|
6191
6993
|
|
|
6192
6994
|
// src/commands/install.ts
|
|
6193
|
-
import { existsSync as
|
|
6194
|
-
import { homedir as
|
|
6195
|
-
import { dirname as
|
|
6196
|
-
import
|
|
6995
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync8, readFileSync as readFileSync11, writeFileSync as writeFileSync7 } from "fs";
|
|
6996
|
+
import { homedir as homedir7 } from "os";
|
|
6997
|
+
import { dirname as dirname5, join as join15, relative as relative2, resolve } from "path";
|
|
6998
|
+
import chalk12 from "chalk";
|
|
6197
6999
|
import prompts2 from "prompts";
|
|
6198
7000
|
|
|
6199
7001
|
// src/registry/reporter.ts
|
|
@@ -6502,19 +7304,19 @@ async function installFromWellKnown(source, options) {
|
|
|
6502
7304
|
process.exit(1);
|
|
6503
7305
|
}
|
|
6504
7306
|
spinner.stop();
|
|
6505
|
-
process.stdout.write(
|
|
7307
|
+
process.stdout.write(chalk12.bold(`
|
|
6506
7308
|
Multiple skills available at ${hostname3}:
|
|
6507
7309
|
|
|
6508
7310
|
`));
|
|
6509
7311
|
for (const skill of index.skills) {
|
|
6510
7312
|
process.stdout.write(
|
|
6511
|
-
` ${
|
|
7313
|
+
` ${chalk12.green(skill.name)} ${chalk12.dim(`\u2014 ${skill.description}`)}
|
|
6512
7314
|
`
|
|
6513
7315
|
);
|
|
6514
7316
|
}
|
|
6515
7317
|
process.stdout.write(
|
|
6516
7318
|
`
|
|
6517
|
-
${
|
|
7319
|
+
${chalk12.dim("Specify a skill:")} ${chalk12.white(`agentver install ${hostname3}/<skill-name>`)}
|
|
6518
7320
|
`
|
|
6519
7321
|
);
|
|
6520
7322
|
process.exit(1);
|
|
@@ -6631,7 +7433,7 @@ ${chalk8.dim("Specify a skill:")} ${chalk8.white(`agentver install ${hostname3}/
|
|
|
6631
7433
|
});
|
|
6632
7434
|
} else {
|
|
6633
7435
|
spinner.succeed(
|
|
6634
|
-
`Installed ${
|
|
7436
|
+
`Installed ${chalk12.green(selectedEntry.name)} from ${chalk12.dim(hostname3)} ${chalk12.dim("(well-known)")} to ${target}`
|
|
6635
7437
|
);
|
|
6636
7438
|
}
|
|
6637
7439
|
return { name: selectedEntry.name, ref: "well-known", commitSha: "", agents };
|
|
@@ -6695,14 +7497,14 @@ async function installPackage(source, options) {
|
|
|
6695
7497
|
initial: false
|
|
6696
7498
|
});
|
|
6697
7499
|
if (!proceed) {
|
|
6698
|
-
console.log(
|
|
7500
|
+
console.log(chalk12.dim("Installation cancelled."));
|
|
6699
7501
|
process.exit(0);
|
|
6700
7502
|
}
|
|
6701
7503
|
spinner.start("Continuing installation...");
|
|
6702
7504
|
}
|
|
6703
7505
|
} else {
|
|
6704
7506
|
if (!jsonMode) {
|
|
6705
|
-
spinner.succeed(
|
|
7507
|
+
spinner.succeed(chalk12.green("Security scan passed"));
|
|
6706
7508
|
spinner.start("Installing...");
|
|
6707
7509
|
}
|
|
6708
7510
|
}
|
|
@@ -6810,7 +7612,7 @@ async function installPackage(source, options) {
|
|
|
6810
7612
|
);
|
|
6811
7613
|
} else {
|
|
6812
7614
|
spinner.succeed(
|
|
6813
|
-
`Installed ${
|
|
7615
|
+
`Installed ${chalk12.green(shortName)} from ${chalk12.dim(formatSource(gitSource))} ${chalk12.cyan(`@${gitSource.ref}`)} ${chalk12.dim(`(${resolved.commitSha.slice(0, 7)})`)} to ${target}`
|
|
6814
7616
|
);
|
|
6815
7617
|
}
|
|
6816
7618
|
return { name: shortName, ref: gitSource.ref, commitSha: resolved.commitSha, agents };
|
|
@@ -6857,7 +7659,7 @@ async function installAgentConfig(name, files, agents, options, spinner) {
|
|
|
6857
7659
|
const projectRoot = process.cwd();
|
|
6858
7660
|
if (options.dryRun) {
|
|
6859
7661
|
spinner.info(
|
|
6860
|
-
`${
|
|
7662
|
+
`${chalk12.yellow("[dry-run]")} Would install agent config ${chalk12.green(name)} to ${agents.join(", ")}`
|
|
6861
7663
|
);
|
|
6862
7664
|
return;
|
|
6863
7665
|
}
|
|
@@ -6873,14 +7675,14 @@ async function installAgentConfig(name, files, agents, options, spinner) {
|
|
|
6873
7675
|
for (const agentId of agents) {
|
|
6874
7676
|
const configPath = getConfigFilePath(agentId, name);
|
|
6875
7677
|
if (!configPath) continue;
|
|
6876
|
-
const fullConfigPath = options.global ? configPath.replace("~",
|
|
6877
|
-
const configDir =
|
|
6878
|
-
if (!
|
|
7678
|
+
const fullConfigPath = options.global ? configPath.replace("~", homedir7()) : join15(projectRoot, configPath);
|
|
7679
|
+
const configDir = join15(fullConfigPath, "..");
|
|
7680
|
+
if (!existsSync12(configDir)) {
|
|
6879
7681
|
mkdirSync8(configDir, { recursive: true });
|
|
6880
7682
|
}
|
|
6881
7683
|
let finalContent = configContent;
|
|
6882
|
-
if (
|
|
6883
|
-
const existingContent =
|
|
7684
|
+
if (existsSync12(fullConfigPath)) {
|
|
7685
|
+
const existingContent = readFileSync11(fullConfigPath, "utf-8");
|
|
6884
7686
|
if (isComposedConfig(existingContent)) {
|
|
6885
7687
|
const existingSections = parseComposedSections(existingContent);
|
|
6886
7688
|
const alreadyPresent = existingSections.some((s) => s.packageName === name);
|
|
@@ -6909,13 +7711,13 @@ async function installToCustomPath(name, files, options, spinner) {
|
|
|
6909
7711
|
const targetPath = resolve(process.cwd(), options.path);
|
|
6910
7712
|
if (options.dryRun) {
|
|
6911
7713
|
spinner.info(
|
|
6912
|
-
`${
|
|
7714
|
+
`${chalk12.yellow("[dry-run]")} Would install ${chalk12.green(name)} to ${chalk12.dim(targetPath)}`
|
|
6913
7715
|
);
|
|
6914
|
-
console.log(
|
|
7716
|
+
console.log(chalk12.dim(` Files: ${files.map((f) => f.path).join(", ")}`));
|
|
6915
7717
|
return;
|
|
6916
7718
|
}
|
|
6917
7719
|
spinner.text = `Installing to ${targetPath}...`;
|
|
6918
|
-
if (!
|
|
7720
|
+
if (!existsSync12(targetPath)) {
|
|
6919
7721
|
mkdirSync8(targetPath, { recursive: true });
|
|
6920
7722
|
}
|
|
6921
7723
|
for (const file of files) {
|
|
@@ -6924,8 +7726,8 @@ async function installToCustomPath(name, files, options, spinner) {
|
|
|
6924
7726
|
if (relativePath.startsWith("..") || resolve(resolvedFilePath) !== resolvedFilePath) {
|
|
6925
7727
|
continue;
|
|
6926
7728
|
}
|
|
6927
|
-
const dir =
|
|
6928
|
-
if (!
|
|
7729
|
+
const dir = join15(resolvedFilePath, "..");
|
|
7730
|
+
if (!existsSync12(dir)) {
|
|
6929
7731
|
mkdirSync8(dir, { recursive: true });
|
|
6930
7732
|
}
|
|
6931
7733
|
writeFileSync7(resolvedFilePath, file.content, "utf-8");
|
|
@@ -6937,15 +7739,15 @@ async function installStandardPackage(name, files, agents, options, spinner) {
|
|
|
6937
7739
|
if (options.dryRun) {
|
|
6938
7740
|
const canonicalPath2 = getCanonicalSkillPath(projectRoot, name, scope);
|
|
6939
7741
|
spinner.info(
|
|
6940
|
-
`${
|
|
7742
|
+
`${chalk12.yellow("[dry-run]")} Would install ${chalk12.green(name)} to ${chalk12.dim(canonicalPath2)}`
|
|
6941
7743
|
);
|
|
6942
|
-
console.log(
|
|
6943
|
-
console.log(
|
|
7744
|
+
console.log(chalk12.dim(` Files: ${files.map((f) => f.path).join(", ")}`));
|
|
7745
|
+
console.log(chalk12.dim(` Symlinks: ${agents.join(", ")}`));
|
|
6944
7746
|
return;
|
|
6945
7747
|
}
|
|
6946
7748
|
spinner.text = `Installing to canonical path and symlinking to ${agents.length} agent(s)...`;
|
|
6947
7749
|
const canonicalPath = getCanonicalSkillPath(projectRoot, name, scope);
|
|
6948
|
-
if (!
|
|
7750
|
+
if (!existsSync12(canonicalPath)) {
|
|
6949
7751
|
mkdirSync8(canonicalPath, { recursive: true });
|
|
6950
7752
|
}
|
|
6951
7753
|
for (const file of files) {
|
|
@@ -6954,8 +7756,8 @@ async function installStandardPackage(name, files, agents, options, spinner) {
|
|
|
6954
7756
|
if (relativePath.startsWith("..") || resolve(resolvedFilePath) !== resolvedFilePath) {
|
|
6955
7757
|
continue;
|
|
6956
7758
|
}
|
|
6957
|
-
const dir =
|
|
6958
|
-
if (!
|
|
7759
|
+
const dir = dirname5(resolvedFilePath);
|
|
7760
|
+
if (!existsSync12(dir)) {
|
|
6959
7761
|
mkdirSync8(dir, { recursive: true });
|
|
6960
7762
|
}
|
|
6961
7763
|
writeFileSync7(resolvedFilePath, file.content, "utf-8");
|
|
@@ -6969,7 +7771,7 @@ function registerInstallCommand(program2) {
|
|
|
6969
7771
|
}
|
|
6970
7772
|
|
|
6971
7773
|
// src/commands/list.ts
|
|
6972
|
-
import
|
|
7774
|
+
import chalk13 from "chalk";
|
|
6973
7775
|
function registerListCommand(program2) {
|
|
6974
7776
|
program2.command("list").description("Show installed packages").option("--json", "Output as JSON").action(() => {
|
|
6975
7777
|
const jsonMode = isJSONMode();
|
|
@@ -6980,24 +7782,25 @@ function registerListCommand(program2) {
|
|
|
6980
7782
|
return;
|
|
6981
7783
|
}
|
|
6982
7784
|
if (entries.length === 0) {
|
|
6983
|
-
console.log(
|
|
7785
|
+
console.log(chalk13.dim("No packages installed."));
|
|
6984
7786
|
return;
|
|
6985
7787
|
}
|
|
6986
|
-
console.log(
|
|
7788
|
+
console.log(chalk13.bold(`
|
|
6987
7789
|
Installed packages (${entries.length}):
|
|
6988
7790
|
`));
|
|
6989
7791
|
for (const [name, pkg2] of entries) {
|
|
6990
|
-
const agents = pkg2.agents.length > 0 ?
|
|
7792
|
+
const agents = pkg2.agents.length > 0 ? chalk13.dim(` [${pkg2.agents.join(", ")}]`) : "";
|
|
7793
|
+
const pinned = pkg2.pinned === true ? chalk13.yellow(" [pinned]") : "";
|
|
6991
7794
|
if (pkg2.source.type === "git") {
|
|
6992
7795
|
const ref = pkg2.source.ref;
|
|
6993
7796
|
const commit = pkg2.source.commit.slice(0, 7);
|
|
6994
7797
|
console.log(
|
|
6995
|
-
` ${
|
|
7798
|
+
` ${chalk13.green(name)}@${chalk13.cyan(ref)} ${chalk13.dim(`(${commit})`)}${pinned}${agents}`
|
|
6996
7799
|
);
|
|
6997
7800
|
} else {
|
|
6998
7801
|
const hostname3 = pkg2.source.hostname;
|
|
6999
7802
|
console.log(
|
|
7000
|
-
` ${
|
|
7803
|
+
` ${chalk13.green(name)} ${chalk13.dim(`(${hostname3})`)} ${chalk13.dim("[well-known]")}${pinned}${agents}`
|
|
7001
7804
|
);
|
|
7002
7805
|
}
|
|
7003
7806
|
}
|
|
@@ -7006,9 +7809,9 @@ Installed packages (${entries.length}):
|
|
|
7006
7809
|
}
|
|
7007
7810
|
|
|
7008
7811
|
// src/commands/log.ts
|
|
7009
|
-
import { existsSync as
|
|
7010
|
-
import { basename as basename3, join as
|
|
7011
|
-
import
|
|
7812
|
+
import { existsSync as existsSync13, readFileSync as readFileSync12 } from "fs";
|
|
7813
|
+
import { basename as basename3, join as join16 } from "path";
|
|
7814
|
+
import chalk14 from "chalk";
|
|
7012
7815
|
import ora3 from "ora";
|
|
7013
7816
|
function resolveSkillIdentity2(nameArg) {
|
|
7014
7817
|
const cwd = process.cwd();
|
|
@@ -7024,10 +7827,10 @@ function resolveSkillIdentity2(nameArg) {
|
|
|
7024
7827
|
}
|
|
7025
7828
|
return null;
|
|
7026
7829
|
}
|
|
7027
|
-
const skillMdPath =
|
|
7830
|
+
const skillMdPath = join16(cwd, "SKILL.md");
|
|
7028
7831
|
let skillName = null;
|
|
7029
|
-
if (
|
|
7030
|
-
const content =
|
|
7832
|
+
if (existsSync13(skillMdPath)) {
|
|
7833
|
+
const content = readFileSync12(skillMdPath, "utf-8");
|
|
7031
7834
|
const nameMatch = content.match(/^name:\s*(.+)$/m);
|
|
7032
7835
|
skillName = nameMatch?.[1]?.trim() ?? basename3(cwd);
|
|
7033
7836
|
}
|
|
@@ -7067,7 +7870,7 @@ function registerLogCommand(program2) {
|
|
|
7067
7870
|
if (!identity) {
|
|
7068
7871
|
const target = nameArg ?? "current directory";
|
|
7069
7872
|
process.stderr.write(
|
|
7070
|
-
|
|
7873
|
+
chalk14.red(
|
|
7071
7874
|
`Could not determine skill identity for "${target}". Provide a skill name or run from a skill directory.
|
|
7072
7875
|
`
|
|
7073
7876
|
)
|
|
@@ -7076,7 +7879,7 @@ function registerLogCommand(program2) {
|
|
|
7076
7879
|
}
|
|
7077
7880
|
const limit = Number.parseInt(options.limit ?? "20", 10);
|
|
7078
7881
|
if (Number.isNaN(limit) || limit < 1) {
|
|
7079
|
-
process.stderr.write(
|
|
7882
|
+
process.stderr.write(chalk14.red("Limit must be a positive number.\n"));
|
|
7080
7883
|
process.exit(1);
|
|
7081
7884
|
}
|
|
7082
7885
|
const spinner = ora3("Fetching history...").start();
|
|
@@ -7091,10 +7894,10 @@ function registerLogCommand(program2) {
|
|
|
7091
7894
|
return;
|
|
7092
7895
|
}
|
|
7093
7896
|
if (commits.length === 0) {
|
|
7094
|
-
process.stdout.write(
|
|
7897
|
+
process.stdout.write(chalk14.dim("No commits found.\n"));
|
|
7095
7898
|
return;
|
|
7096
7899
|
}
|
|
7097
|
-
process.stdout.write(
|
|
7900
|
+
process.stdout.write(chalk14.bold(`
|
|
7098
7901
|
History for @${identity.org}/${identity.name}:
|
|
7099
7902
|
|
|
7100
7903
|
`));
|
|
@@ -7103,7 +7906,7 @@ History for @${identity.org}/${identity.name}:
|
|
|
7103
7906
|
const date = formatDate(commit.author.date || commit.createdAt);
|
|
7104
7907
|
const firstLine = commit.message.split("\n")[0] ?? commit.message;
|
|
7105
7908
|
process.stdout.write(
|
|
7106
|
-
` ${
|
|
7909
|
+
` ${chalk14.yellow(shortSha)} ${chalk14.dim("|")} ${chalk14.dim(date)} ${chalk14.dim("|")} ${firstLine}
|
|
7107
7910
|
`
|
|
7108
7911
|
);
|
|
7109
7912
|
}
|
|
@@ -7121,31 +7924,14 @@ History for @${identity.org}/${identity.name}:
|
|
|
7121
7924
|
import { createHash as createHash3, randomBytes } from "crypto";
|
|
7122
7925
|
import { createServer } from "http";
|
|
7123
7926
|
import { URL as URL2 } from "url";
|
|
7124
|
-
import
|
|
7927
|
+
import chalk16 from "chalk";
|
|
7125
7928
|
import open from "open";
|
|
7126
7929
|
|
|
7127
7930
|
// src/registry/client.ts
|
|
7128
7931
|
var DEFAULT_REGISTRY = "https://app.agentver.com/api/v1";
|
|
7129
|
-
var
|
|
7130
|
-
|
|
7131
|
-
|
|
7132
|
-
var RegistryTimeoutError = class extends Error {
|
|
7133
|
-
constructor() {
|
|
7134
|
-
super("Registry request timed out. The service may be experiencing issues.");
|
|
7135
|
-
this.name = "RegistryTimeoutError";
|
|
7136
|
-
}
|
|
7137
|
-
};
|
|
7138
|
-
function getRegistryUrl() {
|
|
7139
|
-
return process.env.AGENTVER_REGISTRY ?? DEFAULT_REGISTRY;
|
|
7140
|
-
}
|
|
7141
|
-
function isRetryable(error, response) {
|
|
7142
|
-
if (error instanceof RegistryTimeoutError) return false;
|
|
7143
|
-
if (error instanceof DOMException && error.name === "AbortError") return false;
|
|
7144
|
-
if (!response) return true;
|
|
7145
|
-
return response.status >= 500;
|
|
7146
|
-
}
|
|
7147
|
-
function delay(ms) {
|
|
7148
|
-
return new Promise((resolve4) => setTimeout(resolve4, ms));
|
|
7932
|
+
var REQUEST_TIMEOUT_MS2 = 3e4;
|
|
7933
|
+
function getRegistryUrl() {
|
|
7934
|
+
return process.env.AGENTVER_REGISTRY ?? DEFAULT_REGISTRY;
|
|
7149
7935
|
}
|
|
7150
7936
|
async function registryFetch(path, options = {}) {
|
|
7151
7937
|
const credentials = await getCredentials();
|
|
@@ -7159,57 +7945,23 @@ async function registryFetch(path, options = {}) {
|
|
|
7159
7945
|
} else if (credentials?.apiKey) {
|
|
7160
7946
|
headers["X-API-Key"] = credentials.apiKey;
|
|
7161
7947
|
}
|
|
7162
|
-
|
|
7163
|
-
|
|
7164
|
-
|
|
7165
|
-
|
|
7166
|
-
|
|
7167
|
-
|
|
7168
|
-
|
|
7169
|
-
|
|
7170
|
-
|
|
7171
|
-
|
|
7172
|
-
|
|
7173
|
-
});
|
|
7174
|
-
clearTimeout(timeoutId);
|
|
7175
|
-
if (response.ok) {
|
|
7176
|
-
return response.json();
|
|
7177
|
-
}
|
|
7178
|
-
lastResponse = response;
|
|
7179
|
-
lastError = new Error(
|
|
7180
|
-
`Registry error (${response.status}): ${await response.text().catch(() => "Unknown error")}`
|
|
7181
|
-
);
|
|
7182
|
-
if (!isRetryable(void 0, response)) {
|
|
7183
|
-
throw lastError;
|
|
7184
|
-
}
|
|
7185
|
-
} catch (error) {
|
|
7186
|
-
clearTimeout(timeoutId);
|
|
7187
|
-
if (error instanceof DOMException && error.name === "AbortError") {
|
|
7188
|
-
throw new RegistryTimeoutError();
|
|
7189
|
-
}
|
|
7190
|
-
lastError = error;
|
|
7191
|
-
lastResponse = void 0;
|
|
7192
|
-
if (!isRetryable(error)) {
|
|
7193
|
-
throw error;
|
|
7194
|
-
}
|
|
7195
|
-
}
|
|
7196
|
-
if (attempt < MAX_RETRY_ATTEMPTS) {
|
|
7197
|
-
const retryDelay = RETRY_BASE_DELAY_MS * 2 ** (attempt - 1);
|
|
7198
|
-
process.stderr.write(
|
|
7199
|
-
`Registry request failed (attempt ${attempt}/${MAX_RETRY_ATTEMPTS}), retrying in ${retryDelay / 1e3}s...
|
|
7200
|
-
`
|
|
7201
|
-
);
|
|
7202
|
-
await delay(retryDelay);
|
|
7948
|
+
return fetchWithRetry({
|
|
7949
|
+
label: "Registry",
|
|
7950
|
+
timeoutMs: REQUEST_TIMEOUT_MS2,
|
|
7951
|
+
buildRequest: () => ({
|
|
7952
|
+
url,
|
|
7953
|
+
method: options.method ?? "GET",
|
|
7954
|
+
headers,
|
|
7955
|
+
body: options.body ? JSON.stringify(options.body) : void 0
|
|
7956
|
+
}),
|
|
7957
|
+
onAuthExpired: () => {
|
|
7958
|
+
throw new Error("Authentication expired. Run `agentver login` to re-authenticate.");
|
|
7203
7959
|
}
|
|
7204
|
-
}
|
|
7205
|
-
if (lastResponse && !lastResponse.ok) {
|
|
7206
|
-
throw lastError;
|
|
7207
|
-
}
|
|
7208
|
-
throw lastError;
|
|
7960
|
+
});
|
|
7209
7961
|
}
|
|
7210
7962
|
|
|
7211
7963
|
// src/utils/network.ts
|
|
7212
|
-
import
|
|
7964
|
+
import chalk15 from "chalk";
|
|
7213
7965
|
var ONLINE_CHECK_TIMEOUT_MS = 3e3;
|
|
7214
7966
|
async function checkOnline() {
|
|
7215
7967
|
const registryUrl = getRegistryUrl();
|
|
@@ -7229,10 +7981,10 @@ async function checkOnline() {
|
|
|
7229
7981
|
}
|
|
7230
7982
|
function showOfflineError() {
|
|
7231
7983
|
console.error(
|
|
7232
|
-
|
|
7984
|
+
chalk15.red("Unable to reach the Agentver registry.") + " Please check your internet connection.\n"
|
|
7233
7985
|
);
|
|
7234
7986
|
console.error(
|
|
7235
|
-
|
|
7987
|
+
chalk15.dim(
|
|
7236
7988
|
`If you're behind a proxy, set the HTTPS_PROXY environment variable.
|
|
7237
7989
|
If the registry is down, try again later.
|
|
7238
7990
|
|
|
@@ -7305,6 +8057,7 @@ function startCallbackServer(expectedState) {
|
|
|
7305
8057
|
port: address.port,
|
|
7306
8058
|
waitForCallback: () => callbackPromise,
|
|
7307
8059
|
close: () => {
|
|
8060
|
+
server.closeAllConnections();
|
|
7308
8061
|
server.close();
|
|
7309
8062
|
}
|
|
7310
8063
|
});
|
|
@@ -7369,9 +8122,9 @@ function registerLoginCommand(program2) {
|
|
|
7369
8122
|
});
|
|
7370
8123
|
return;
|
|
7371
8124
|
}
|
|
7372
|
-
console.log(
|
|
8125
|
+
console.log(chalk16.green("Saved API key. You are now authenticated."));
|
|
7373
8126
|
if (target) {
|
|
7374
|
-
console.log(
|
|
8127
|
+
console.log(chalk16.dim(`Connected to ${target}`));
|
|
7375
8128
|
}
|
|
7376
8129
|
return;
|
|
7377
8130
|
}
|
|
@@ -7411,28 +8164,31 @@ function registerLoginCommand(program2) {
|
|
|
7411
8164
|
const redirectUri = `http://localhost:${port}/callback`;
|
|
7412
8165
|
const authUrl = `${baseUrl}/auth/cli?code_challenge=${encodeURIComponent(codeChallenge)}&state=${encodeURIComponent(state)}&redirect_uri=${encodeURIComponent(redirectUri)}`;
|
|
7413
8166
|
spinner.text = "Opening browser for authentication...";
|
|
7414
|
-
console.log(
|
|
8167
|
+
console.log(chalk16.dim(`
|
|
7415
8168
|
If the browser doesn't open, visit:
|
|
7416
8169
|
${authUrl}
|
|
7417
8170
|
`));
|
|
7418
8171
|
await open(authUrl);
|
|
7419
8172
|
spinner.text = "Waiting for authentication in browser...";
|
|
8173
|
+
let authTimeout;
|
|
7420
8174
|
const { code } = await Promise.race([
|
|
7421
8175
|
callbackServer.waitForCallback(),
|
|
7422
8176
|
new Promise((_resolve, reject) => {
|
|
7423
|
-
setTimeout(() => {
|
|
8177
|
+
authTimeout = setTimeout(() => {
|
|
7424
8178
|
reject(new Error("Authentication timed out after 120 seconds"));
|
|
7425
8179
|
}, AUTH_TIMEOUT_MS);
|
|
7426
8180
|
})
|
|
7427
8181
|
]);
|
|
8182
|
+
clearTimeout(authTimeout);
|
|
7428
8183
|
spinner.text = "Exchanging authorisation code for token...";
|
|
7429
8184
|
const tokenResponse = await exchangeCodeForToken(apiUrl, code, codeVerifier, redirectUri);
|
|
7430
8185
|
saveCredentials({ token: tokenResponse.access_token });
|
|
7431
8186
|
spinner.succeed("Authenticated successfully.");
|
|
7432
8187
|
const connectedUrl = url ?? getPlatformUrl();
|
|
7433
8188
|
if (connectedUrl) {
|
|
7434
|
-
console.log(
|
|
8189
|
+
console.log(chalk16.dim(`Connected to ${connectedUrl}`));
|
|
7435
8190
|
}
|
|
8191
|
+
process.exit(0);
|
|
7436
8192
|
} catch (error) {
|
|
7437
8193
|
const message = error instanceof Error ? error.message : String(error);
|
|
7438
8194
|
spinner.fail(`Authentication failed: ${message}`);
|
|
@@ -7444,7 +8200,7 @@ function registerLoginCommand(program2) {
|
|
|
7444
8200
|
}
|
|
7445
8201
|
|
|
7446
8202
|
// src/commands/logout.ts
|
|
7447
|
-
import
|
|
8203
|
+
import chalk17 from "chalk";
|
|
7448
8204
|
function registerLogoutCommand(program2) {
|
|
7449
8205
|
program2.command("logout").description("Log out from the Agentver registry").action(async () => {
|
|
7450
8206
|
if (!await isAuthenticated()) {
|
|
@@ -7452,7 +8208,7 @@ function registerLogoutCommand(program2) {
|
|
|
7452
8208
|
outputSuccess({ cleared: true });
|
|
7453
8209
|
return;
|
|
7454
8210
|
}
|
|
7455
|
-
console.log(
|
|
8211
|
+
console.log(chalk17.dim("You are not currently logged in."));
|
|
7456
8212
|
return;
|
|
7457
8213
|
}
|
|
7458
8214
|
const platformUrl = getPlatformUrl();
|
|
@@ -7467,19 +8223,72 @@ function registerLogoutCommand(program2) {
|
|
|
7467
8223
|
return;
|
|
7468
8224
|
}
|
|
7469
8225
|
if (platformUrl) {
|
|
7470
|
-
console.log(`${
|
|
8226
|
+
console.log(`${chalk17.green("Logged out successfully.")} Disconnected from ${platformUrl}`);
|
|
7471
8227
|
} else {
|
|
7472
8228
|
console.log(
|
|
7473
|
-
`${
|
|
8229
|
+
`${chalk17.green("Logged out successfully.")} Run \`agentver login\` to sign in again.`
|
|
7474
8230
|
);
|
|
7475
8231
|
}
|
|
7476
8232
|
});
|
|
7477
8233
|
}
|
|
7478
8234
|
|
|
8235
|
+
// src/commands/pin.ts
|
|
8236
|
+
import chalk18 from "chalk";
|
|
8237
|
+
function registerPinCommand(program2) {
|
|
8238
|
+
program2.command("pin <name>").description("Pin a package to skip it during updates").action((name) => {
|
|
8239
|
+
const jsonMode = isJSONMode();
|
|
8240
|
+
const projectRoot = process.cwd();
|
|
8241
|
+
const manifest = readManifest(projectRoot);
|
|
8242
|
+
const pkg2 = manifest.packages[name];
|
|
8243
|
+
if (!pkg2) {
|
|
8244
|
+
if (jsonMode) {
|
|
8245
|
+
outputError("NOT_FOUND", `Package "${name}" is not installed.`);
|
|
8246
|
+
} else {
|
|
8247
|
+
console.error(chalk18.red(`Package "${name}" is not installed.`));
|
|
8248
|
+
}
|
|
8249
|
+
process.exit(1);
|
|
8250
|
+
}
|
|
8251
|
+
pkg2.pinned = true;
|
|
8252
|
+
writeManifest(projectRoot, manifest);
|
|
8253
|
+
if (jsonMode) {
|
|
8254
|
+
outputSuccess({ name, pinned: true });
|
|
8255
|
+
return;
|
|
8256
|
+
}
|
|
8257
|
+
console.log(
|
|
8258
|
+
chalk18.green(`Pinned ${name}`) + chalk18.dim(" \u2014 this package will be skipped during updates")
|
|
8259
|
+
);
|
|
8260
|
+
});
|
|
8261
|
+
}
|
|
8262
|
+
function registerUnpinCommand(program2) {
|
|
8263
|
+
program2.command("unpin <name>").description("Unpin a package so it is included in updates").action((name) => {
|
|
8264
|
+
const jsonMode = isJSONMode();
|
|
8265
|
+
const projectRoot = process.cwd();
|
|
8266
|
+
const manifest = readManifest(projectRoot);
|
|
8267
|
+
const pkg2 = manifest.packages[name];
|
|
8268
|
+
if (!pkg2) {
|
|
8269
|
+
if (jsonMode) {
|
|
8270
|
+
outputError("NOT_FOUND", `Package "${name}" is not installed.`);
|
|
8271
|
+
} else {
|
|
8272
|
+
console.error(chalk18.red(`Package "${name}" is not installed.`));
|
|
8273
|
+
}
|
|
8274
|
+
process.exit(1);
|
|
8275
|
+
}
|
|
8276
|
+
delete pkg2.pinned;
|
|
8277
|
+
writeManifest(projectRoot, manifest);
|
|
8278
|
+
if (jsonMode) {
|
|
8279
|
+
outputSuccess({ name, pinned: false });
|
|
8280
|
+
return;
|
|
8281
|
+
}
|
|
8282
|
+
console.log(
|
|
8283
|
+
chalk18.green(`Unpinned ${name}`) + chalk18.dim(" \u2014 this package will be included in updates")
|
|
8284
|
+
);
|
|
8285
|
+
});
|
|
8286
|
+
}
|
|
8287
|
+
|
|
7479
8288
|
// src/commands/publish.ts
|
|
7480
|
-
import { existsSync as
|
|
7481
|
-
import { basename as basename4, join as
|
|
7482
|
-
import
|
|
8289
|
+
import { existsSync as existsSync14, readFileSync as readFileSync13 } from "fs";
|
|
8290
|
+
import { basename as basename4, join as join17, resolve as resolve2 } from "path";
|
|
8291
|
+
import chalk19 from "chalk";
|
|
7483
8292
|
import ora4 from "ora";
|
|
7484
8293
|
var SEMVER_REGEX = /^\d+\.\d+\.\d+(-[\w.]+)?$/;
|
|
7485
8294
|
function parseFrontmatter2(content) {
|
|
@@ -7506,9 +8315,9 @@ function parseFrontmatter2(content) {
|
|
|
7506
8315
|
};
|
|
7507
8316
|
}
|
|
7508
8317
|
function detectNamespace(skillDir) {
|
|
7509
|
-
const skillMdPath =
|
|
7510
|
-
if (!
|
|
7511
|
-
const content =
|
|
8318
|
+
const skillMdPath = join17(skillDir, "SKILL.md");
|
|
8319
|
+
if (!existsSync14(skillMdPath)) return null;
|
|
8320
|
+
const content = readFileSync13(skillMdPath, "utf-8");
|
|
7512
8321
|
const fm = parseFrontmatter2(content);
|
|
7513
8322
|
if (!fm) return null;
|
|
7514
8323
|
const parts = skillDir.split("/");
|
|
@@ -7522,16 +8331,16 @@ function detectNamespace(skillDir) {
|
|
|
7522
8331
|
function registerPublishCommand(program2) {
|
|
7523
8332
|
program2.command("publish [path]").description("Publish a skill to the registry").option("--version <semver>", "Version to publish (uses frontmatter version if omitted)").option("--dry-run", "Validate without publishing").option("--skip-audit", "Skip security scan").option("--json", "Output as JSON").action(async (pathArg, options) => {
|
|
7524
8333
|
const skillDir = pathArg ? resolve2(process.cwd(), pathArg) : process.cwd();
|
|
7525
|
-
if (!
|
|
8334
|
+
if (!existsSync14(join17(skillDir, "SKILL.md"))) {
|
|
7526
8335
|
process.stderr.write(
|
|
7527
|
-
|
|
8336
|
+
chalk19.red(`No SKILL.md found in ${skillDir}. Cannot publish without a skill manifest.
|
|
7528
8337
|
`)
|
|
7529
8338
|
);
|
|
7530
8339
|
process.exit(1);
|
|
7531
8340
|
}
|
|
7532
8341
|
const spinner = ora4("Reading skill metadata...").start();
|
|
7533
8342
|
try {
|
|
7534
|
-
const skillMdContent =
|
|
8343
|
+
const skillMdContent = readFileSync13(join17(skillDir, "SKILL.md"), "utf-8");
|
|
7535
8344
|
const frontmatter = parseFrontmatter2(skillMdContent);
|
|
7536
8345
|
if (!frontmatter) {
|
|
7537
8346
|
spinner.fail(
|
|
@@ -7573,7 +8382,7 @@ function registerPublishCommand(program2) {
|
|
|
7573
8382
|
spinner.fail("Security audit failed. Fix the issues before publishing.");
|
|
7574
8383
|
for (const finding of scanResult.findings) {
|
|
7575
8384
|
process.stderr.write(
|
|
7576
|
-
` ${
|
|
8385
|
+
` ${chalk19.red("BLOCK")} ${finding.file}:${String(finding.line ?? "?")} \u2014 ${finding.message}
|
|
7577
8386
|
`
|
|
7578
8387
|
);
|
|
7579
8388
|
}
|
|
@@ -7583,7 +8392,7 @@ function registerPublishCommand(program2) {
|
|
|
7583
8392
|
spinner.warn("Security audit warnings found:");
|
|
7584
8393
|
for (const finding of scanResult.findings) {
|
|
7585
8394
|
process.stderr.write(
|
|
7586
|
-
` ${
|
|
8395
|
+
` ${chalk19.yellow("WARN")} ${finding.file}:${String(finding.line ?? "?")} \u2014 ${finding.message}
|
|
7587
8396
|
`
|
|
7588
8397
|
);
|
|
7589
8398
|
}
|
|
@@ -7612,13 +8421,13 @@ function registerPublishCommand(program2) {
|
|
|
7612
8421
|
);
|
|
7613
8422
|
} else {
|
|
7614
8423
|
process.stdout.write(
|
|
7615
|
-
|
|
8424
|
+
chalk19.yellow("[dry-run]") + ` Would publish ${chalk19.green(frontmatter.name)}@${chalk19.cyan(version)}
|
|
7616
8425
|
`
|
|
7617
8426
|
);
|
|
7618
|
-
process.stdout.write(
|
|
8427
|
+
process.stdout.write(chalk19.dim(` Namespace: @${namespace.org}/${namespace.name}
|
|
7619
8428
|
`));
|
|
7620
8429
|
process.stdout.write(
|
|
7621
|
-
|
|
8430
|
+
chalk19.dim(
|
|
7622
8431
|
` Files (${filesToPublish.length}): ${filesToPublish.map((f) => f.path).join(", ")}
|
|
7623
8432
|
`
|
|
7624
8433
|
)
|
|
@@ -7651,7 +8460,7 @@ function registerPublishCommand(program2) {
|
|
|
7651
8460
|
);
|
|
7652
8461
|
} else {
|
|
7653
8462
|
spinner.succeed(
|
|
7654
|
-
`Published ${
|
|
8463
|
+
`Published ${chalk19.green(frontmatter.name)}@${chalk19.cyan(result.version)} ${chalk19.dim(`(${result.commitSha.slice(0, 7)})`)}`
|
|
7655
8464
|
);
|
|
7656
8465
|
}
|
|
7657
8466
|
} catch (error) {
|
|
@@ -7662,11 +8471,11 @@ function registerPublishCommand(program2) {
|
|
|
7662
8471
|
}
|
|
7663
8472
|
|
|
7664
8473
|
// src/commands/remove.ts
|
|
7665
|
-
import { existsSync as
|
|
7666
|
-
import { join as
|
|
7667
|
-
import
|
|
8474
|
+
import { existsSync as existsSync15, lstatSync as lstatSync3, rmSync as rmSync2 } from "fs";
|
|
8475
|
+
import { join as join18 } from "path";
|
|
8476
|
+
import chalk20 from "chalk";
|
|
7668
8477
|
function registerRemoveCommand(program2) {
|
|
7669
|
-
program2.command("remove <name>").description("Remove an installed package").option("--dry-run", "Show what would be removed without making changes").action(async (name, options) => {
|
|
8478
|
+
program2.command("remove <name>").alias("uninstall").description("Remove an installed package").option("--dry-run", "Show what would be removed without making changes").action(async (name, options) => {
|
|
7670
8479
|
const jsonMode = isJSONMode();
|
|
7671
8480
|
const projectRoot = process.cwd();
|
|
7672
8481
|
const manifest = readManifest(projectRoot);
|
|
@@ -7676,7 +8485,7 @@ function registerRemoveCommand(program2) {
|
|
|
7676
8485
|
outputError("NOT_FOUND", `Package "${name}" is not installed.`);
|
|
7677
8486
|
process.exit(1);
|
|
7678
8487
|
}
|
|
7679
|
-
console.error(
|
|
8488
|
+
console.error(chalk20.red(`Package "${name}" is not installed.`));
|
|
7680
8489
|
process.exit(1);
|
|
7681
8490
|
}
|
|
7682
8491
|
const shortName = name.split("/").pop();
|
|
@@ -7688,15 +8497,15 @@ function registerRemoveCommand(program2) {
|
|
|
7688
8497
|
for (const agentId of pkg2.agents) {
|
|
7689
8498
|
const placementPath = getSkillPlacementPath(agentId, shortName, "project");
|
|
7690
8499
|
if (placementPath) {
|
|
7691
|
-
removedPaths.push(
|
|
8500
|
+
removedPaths.push(join18(projectRoot, placementPath));
|
|
7692
8501
|
}
|
|
7693
8502
|
}
|
|
7694
8503
|
} else {
|
|
7695
8504
|
for (const agentId of pkg2.agents) {
|
|
7696
8505
|
const placementPath = getSkillPlacementPath(agentId, shortName, "project");
|
|
7697
8506
|
if (!placementPath) continue;
|
|
7698
|
-
const fullPath =
|
|
7699
|
-
if (
|
|
8507
|
+
const fullPath = join18(projectRoot, placementPath);
|
|
8508
|
+
if (existsSync15(fullPath)) {
|
|
7700
8509
|
removedPaths.push(fullPath);
|
|
7701
8510
|
}
|
|
7702
8511
|
}
|
|
@@ -7710,28 +8519,28 @@ function registerRemoveCommand(program2) {
|
|
|
7710
8519
|
});
|
|
7711
8520
|
return;
|
|
7712
8521
|
}
|
|
7713
|
-
console.log(`${
|
|
8522
|
+
console.log(`${chalk20.yellow("[dry-run]")} Would remove ${chalk20.green(name)}`);
|
|
7714
8523
|
if (hasCanonical) {
|
|
7715
8524
|
const canonicalPath = getCanonicalSkillPath(projectRoot, shortName, "project");
|
|
7716
|
-
console.log(
|
|
7717
|
-
console.log(
|
|
7718
|
-
console.log(
|
|
8525
|
+
console.log(chalk20.dim(" Canonical path to remove:"));
|
|
8526
|
+
console.log(chalk20.dim(` ${canonicalPath}`));
|
|
8527
|
+
console.log(chalk20.dim(" Agent symlinks to remove:"));
|
|
7719
8528
|
for (const agentId of pkg2.agents) {
|
|
7720
8529
|
const placementPath = getSkillPlacementPath(agentId, shortName, "project");
|
|
7721
8530
|
if (placementPath) {
|
|
7722
|
-
console.log(
|
|
8531
|
+
console.log(chalk20.dim(` ${join18(projectRoot, placementPath)}`));
|
|
7723
8532
|
}
|
|
7724
8533
|
}
|
|
7725
8534
|
} else {
|
|
7726
|
-
const pathsToRemove = removedPaths.filter((p) =>
|
|
8535
|
+
const pathsToRemove = removedPaths.filter((p) => existsSync15(p));
|
|
7727
8536
|
if (pathsToRemove.length > 0) {
|
|
7728
|
-
console.log(
|
|
8537
|
+
console.log(chalk20.dim(" Paths to remove:"));
|
|
7729
8538
|
for (const p of pathsToRemove) {
|
|
7730
|
-
console.log(
|
|
8539
|
+
console.log(chalk20.dim(` ${p}`));
|
|
7731
8540
|
}
|
|
7732
8541
|
}
|
|
7733
8542
|
}
|
|
7734
|
-
console.log(
|
|
8543
|
+
console.log(chalk20.dim(" Would update manifest and lockfile"));
|
|
7735
8544
|
return;
|
|
7736
8545
|
}
|
|
7737
8546
|
const spinner = createSpinner(`Removing ${name}...`).start();
|
|
@@ -7742,8 +8551,8 @@ function registerRemoveCommand(program2) {
|
|
|
7742
8551
|
for (const agentId of pkg2.agents) {
|
|
7743
8552
|
const placementPath = getSkillPlacementPath(agentId, shortName, "project");
|
|
7744
8553
|
if (!placementPath) continue;
|
|
7745
|
-
const fullPath =
|
|
7746
|
-
if (
|
|
8554
|
+
const fullPath = join18(projectRoot, placementPath);
|
|
8555
|
+
if (existsSync15(fullPath) || isSymlinkPath(fullPath)) {
|
|
7747
8556
|
rmSync2(fullPath, { recursive: true, force: true });
|
|
7748
8557
|
}
|
|
7749
8558
|
}
|
|
@@ -7761,35 +8570,35 @@ function registerRemoveCommand(program2) {
|
|
|
7761
8570
|
paths: removedPaths
|
|
7762
8571
|
});
|
|
7763
8572
|
} else {
|
|
7764
|
-
spinner.succeed(`Removed ${
|
|
8573
|
+
spinner.succeed(`Removed ${chalk20.green(name)}`);
|
|
7765
8574
|
}
|
|
7766
8575
|
});
|
|
7767
8576
|
}
|
|
7768
8577
|
function isSymlinkPath(filePath) {
|
|
7769
8578
|
try {
|
|
7770
|
-
return
|
|
8579
|
+
return lstatSync3(filePath).isSymbolicLink();
|
|
7771
8580
|
} catch {
|
|
7772
8581
|
return false;
|
|
7773
8582
|
}
|
|
7774
8583
|
}
|
|
7775
8584
|
|
|
7776
8585
|
// src/commands/save.ts
|
|
7777
|
-
import { existsSync as
|
|
7778
|
-
import { basename as basename5, join as
|
|
7779
|
-
import
|
|
8586
|
+
import { existsSync as existsSync16, readFileSync as readFileSync14 } from "fs";
|
|
8587
|
+
import { basename as basename5, join as join19, resolve as resolve3 } from "path";
|
|
8588
|
+
import chalk21 from "chalk";
|
|
7780
8589
|
import ora5 from "ora";
|
|
7781
8590
|
function detectSkillName(skillDir) {
|
|
7782
|
-
const skillMdPath =
|
|
7783
|
-
if (!
|
|
8591
|
+
const skillMdPath = join19(skillDir, "SKILL.md");
|
|
8592
|
+
if (!existsSync16(skillMdPath)) {
|
|
7784
8593
|
return null;
|
|
7785
8594
|
}
|
|
7786
|
-
const content =
|
|
8595
|
+
const content = readFileSync14(skillMdPath, "utf-8");
|
|
7787
8596
|
const nameMatch = content.match(/^name:\s*(.+)$/m);
|
|
7788
8597
|
return nameMatch?.[1]?.trim() ?? basename5(skillDir);
|
|
7789
8598
|
}
|
|
7790
8599
|
function resolveSkillContext(options) {
|
|
7791
8600
|
const skillDir = options.path ? resolve3(process.cwd(), options.path) : process.cwd();
|
|
7792
|
-
if (!
|
|
8601
|
+
if (!existsSync16(skillDir)) {
|
|
7793
8602
|
return null;
|
|
7794
8603
|
}
|
|
7795
8604
|
const skillName = detectSkillName(skillDir);
|
|
@@ -7815,7 +8624,7 @@ function registerSaveCommand(program2) {
|
|
|
7815
8624
|
if (!context) {
|
|
7816
8625
|
const target = options.path ?? process.cwd();
|
|
7817
8626
|
process.stderr.write(
|
|
7818
|
-
|
|
8627
|
+
chalk21.red(`No SKILL.md found in ${target}. Run this from a skill directory.
|
|
7819
8628
|
`)
|
|
7820
8629
|
);
|
|
7821
8630
|
process.exit(1);
|
|
@@ -7825,7 +8634,7 @@ function registerSaveCommand(program2) {
|
|
|
7825
8634
|
const namespace = findNamespace(projectRoot, skillName);
|
|
7826
8635
|
if (!namespace) {
|
|
7827
8636
|
process.stderr.write(
|
|
7828
|
-
|
|
8637
|
+
chalk21.red(
|
|
7829
8638
|
`Skill "${skillName}" not found in manifest. Install it first or check the directory.
|
|
7830
8639
|
`
|
|
7831
8640
|
)
|
|
@@ -7861,13 +8670,13 @@ function registerSaveCommand(program2) {
|
|
|
7861
8670
|
);
|
|
7862
8671
|
} else {
|
|
7863
8672
|
process.stdout.write(
|
|
7864
|
-
|
|
8673
|
+
chalk21.yellow("[dry-run]") + ` Would save ${chalk21.green(skillName)} to @${namespace.org}/${namespace.name}
|
|
7865
8674
|
`
|
|
7866
8675
|
);
|
|
7867
|
-
process.stdout.write(
|
|
8676
|
+
process.stdout.write(chalk21.dim(` Message: ${commitMessage}
|
|
7868
8677
|
`));
|
|
7869
8678
|
process.stdout.write(
|
|
7870
|
-
|
|
8679
|
+
chalk21.dim(` Files: ${filesToSave.map((f) => f.path).join(", ")}
|
|
7871
8680
|
`)
|
|
7872
8681
|
);
|
|
7873
8682
|
}
|
|
@@ -7904,7 +8713,7 @@ function registerSaveCommand(program2) {
|
|
|
7904
8713
|
);
|
|
7905
8714
|
} else {
|
|
7906
8715
|
spinner.succeed(
|
|
7907
|
-
`Saved ${
|
|
8716
|
+
`Saved ${chalk21.green(skillName)} ${chalk21.dim(`(${result.commitSha.slice(0, 7)})`)}`
|
|
7908
8717
|
);
|
|
7909
8718
|
}
|
|
7910
8719
|
} catch (error) {
|
|
@@ -7915,19 +8724,19 @@ function registerSaveCommand(program2) {
|
|
|
7915
8724
|
}
|
|
7916
8725
|
|
|
7917
8726
|
// src/commands/scan.ts
|
|
7918
|
-
import { readFileSync as
|
|
7919
|
-
import { homedir as
|
|
7920
|
-
import
|
|
8727
|
+
import { readFileSync as readFileSync15 } from "fs";
|
|
8728
|
+
import { homedir as homedir8 } from "os";
|
|
8729
|
+
import chalk22 from "chalk";
|
|
7921
8730
|
function registerScanCommand(program2) {
|
|
7922
8731
|
program2.command("scan [path]").description("Scan directory for agent configs and skills").action(async (path) => {
|
|
7923
8732
|
const jsonMode = isJSONMode();
|
|
7924
8733
|
const targetPath = path ?? process.cwd();
|
|
7925
8734
|
const projectAgents = detectInstalledAgents(targetPath);
|
|
7926
|
-
const globalAgents = detectGlobalAgents(
|
|
8735
|
+
const globalAgents = detectGlobalAgents(homedir8());
|
|
7927
8736
|
const seenIds = new Set(projectAgents.map((a) => a.id));
|
|
7928
8737
|
const agents = [...projectAgents, ...globalAgents.filter((a) => !seenIds.has(a.id))];
|
|
7929
8738
|
const projectFiles = scanForSkillFiles(targetPath);
|
|
7930
|
-
const globalFiles = scanGlobalSkillFiles(
|
|
8739
|
+
const globalFiles = scanGlobalSkillFiles(homedir8());
|
|
7931
8740
|
const seenPaths = new Set(projectFiles.map((f) => f.path));
|
|
7932
8741
|
const files = [...projectFiles, ...globalFiles.filter((f) => !seenPaths.has(f.path))];
|
|
7933
8742
|
if (jsonMode) {
|
|
@@ -7946,58 +8755,58 @@ function registerScanCommand(program2) {
|
|
|
7946
8755
|
outputSuccess(result);
|
|
7947
8756
|
return;
|
|
7948
8757
|
}
|
|
7949
|
-
console.log(
|
|
8758
|
+
console.log(chalk22.bold("\nDetected agents:\n"));
|
|
7950
8759
|
if (agents.length === 0) {
|
|
7951
|
-
console.log(
|
|
8760
|
+
console.log(chalk22.dim(" No agents detected."));
|
|
7952
8761
|
} else {
|
|
7953
8762
|
for (const agent of agents) {
|
|
7954
|
-
console.log(` ${
|
|
8763
|
+
console.log(` ${chalk22.green(agent.name)} ${chalk22.dim(agent.configPath)}`);
|
|
7955
8764
|
}
|
|
7956
8765
|
}
|
|
7957
|
-
console.log(
|
|
8766
|
+
console.log(chalk22.bold("\nDiscovered files:\n"));
|
|
7958
8767
|
if (files.length === 0) {
|
|
7959
|
-
console.log(
|
|
8768
|
+
console.log(chalk22.dim(" No skill or config files found."));
|
|
7960
8769
|
} else {
|
|
7961
8770
|
for (const file of files) {
|
|
7962
|
-
const typeLabel =
|
|
7963
|
-
const agentLabel =
|
|
7964
|
-
console.log(` ${typeLabel} ${agentLabel} ${file.name} ${
|
|
8771
|
+
const typeLabel = chalk22.dim(`[${file.detectedType}]`);
|
|
8772
|
+
const agentLabel = chalk22.cyan(`(${file.agentId})`);
|
|
8773
|
+
console.log(` ${typeLabel} ${agentLabel} ${file.name} ${chalk22.dim(file.path)}`);
|
|
7965
8774
|
}
|
|
7966
8775
|
}
|
|
7967
8776
|
const skillFiles = files.filter((f) => f.detectedType === "SKILL");
|
|
7968
8777
|
if (skillFiles.length > 0) {
|
|
7969
|
-
console.log(
|
|
8778
|
+
console.log(chalk22.bold("\nSkill spec validation:\n"));
|
|
7970
8779
|
for (const file of skillFiles) {
|
|
7971
8780
|
let content;
|
|
7972
8781
|
try {
|
|
7973
|
-
content =
|
|
8782
|
+
content = readFileSync15(file.path, "utf-8");
|
|
7974
8783
|
} catch {
|
|
7975
|
-
console.log(` ${
|
|
8784
|
+
console.log(` ${chalk22.red("\u2717")} ${file.name} ${chalk22.dim("Could not read file")}`);
|
|
7976
8785
|
continue;
|
|
7977
8786
|
}
|
|
7978
8787
|
const result = validateSkillMd(content);
|
|
7979
8788
|
if (result.valid && result.specCompliant) {
|
|
7980
8789
|
console.log(
|
|
7981
|
-
` ${
|
|
8790
|
+
` ${chalk22.green("\u2713")} ${file.name} ${chalk22.green("Agent Skills spec compliant")}`
|
|
7982
8791
|
);
|
|
7983
8792
|
} else if (result.valid && !result.specCompliant) {
|
|
7984
8793
|
console.log(
|
|
7985
|
-
` ${
|
|
8794
|
+
` ${chalk22.yellow("\u2713")} ${file.name} ${chalk22.yellow("Valid (Agentver extended)")}`
|
|
7986
8795
|
);
|
|
7987
8796
|
} else {
|
|
7988
|
-
console.log(` ${
|
|
8797
|
+
console.log(` ${chalk22.red("\u2717")} ${file.name} ${chalk22.red("Invalid")}`);
|
|
7989
8798
|
for (const error of result.errors) {
|
|
7990
|
-
console.log(` ${
|
|
8799
|
+
console.log(` ${chalk22.red(`\u2514 ${error}`)}`);
|
|
7991
8800
|
}
|
|
7992
8801
|
}
|
|
7993
8802
|
if (result.warnings.length > 0) {
|
|
7994
8803
|
for (const warning of result.warnings) {
|
|
7995
|
-
console.log(` ${
|
|
8804
|
+
console.log(` ${chalk22.yellow(`\u26A0 ${warning}`)}`);
|
|
7996
8805
|
}
|
|
7997
8806
|
}
|
|
7998
8807
|
if (result.agentverExtensions.length > 0) {
|
|
7999
8808
|
console.log(
|
|
8000
|
-
` ${
|
|
8809
|
+
` ${chalk22.dim(`Agentver extensions: ${result.agentverExtensions.join(", ")}`)}`
|
|
8001
8810
|
);
|
|
8002
8811
|
}
|
|
8003
8812
|
}
|
|
@@ -8005,7 +8814,7 @@ function registerScanCommand(program2) {
|
|
|
8005
8814
|
const manifest = readManifest(targetPath);
|
|
8006
8815
|
const manifestEntries = Object.entries(manifest.packages);
|
|
8007
8816
|
if (manifestEntries.length > 0) {
|
|
8008
|
-
console.log(
|
|
8817
|
+
console.log(chalk22.bold(`
|
|
8009
8818
|
Installed skills (${manifestEntries.length}):
|
|
8010
8819
|
`));
|
|
8011
8820
|
for (const [name, pkg2] of manifestEntries) {
|
|
@@ -8016,12 +8825,12 @@ Installed skills (${manifestEntries.length}):
|
|
|
8016
8825
|
const ref = `@${source.ref}`;
|
|
8017
8826
|
const commit = `(${source.commit.slice(0, 7)})`;
|
|
8018
8827
|
console.log(
|
|
8019
|
-
` ${
|
|
8828
|
+
` ${chalk22.green(name.padEnd(18))} ${chalk22.dim(sourcePath.padEnd(40))} ${chalk22.cyan(ref.padEnd(10))} ${chalk22.dim(commit)} ${chalk22.dim(agentList)}`
|
|
8020
8829
|
);
|
|
8021
8830
|
} else {
|
|
8022
8831
|
const sourceLabel = `${source.hostname} (well-known)`;
|
|
8023
8832
|
console.log(
|
|
8024
|
-
` ${
|
|
8833
|
+
` ${chalk22.green(name.padEnd(18))} ${chalk22.dim(sourceLabel.padEnd(40))} ${chalk22.dim("[well-known]").padEnd(10)} ${chalk22.dim(agentList)}`
|
|
8025
8834
|
);
|
|
8026
8835
|
}
|
|
8027
8836
|
}
|
|
@@ -8031,7 +8840,7 @@ Installed skills (${manifestEntries.length}):
|
|
|
8031
8840
|
}
|
|
8032
8841
|
|
|
8033
8842
|
// src/commands/search.ts
|
|
8034
|
-
import
|
|
8843
|
+
import chalk23 from "chalk";
|
|
8035
8844
|
import ora6 from "ora";
|
|
8036
8845
|
|
|
8037
8846
|
// src/registry/skills-sh.ts
|
|
@@ -8109,60 +8918,60 @@ function formatInstallCount(count) {
|
|
|
8109
8918
|
}
|
|
8110
8919
|
function renderPlatformResults(results, total) {
|
|
8111
8920
|
if (results.length === 0) return;
|
|
8112
|
-
process.stdout.write(
|
|
8921
|
+
process.stdout.write(chalk23.bold(`
|
|
8113
8922
|
Platform results (${total}):
|
|
8114
8923
|
|
|
8115
8924
|
`));
|
|
8116
8925
|
for (const result of results) {
|
|
8117
|
-
const desc = result.description ?
|
|
8118
|
-
const stars = result.starCount > 0 ?
|
|
8119
|
-
const installs = result.installCount > 0 ?
|
|
8120
|
-
const cats = result.categories.length > 0 ?
|
|
8121
|
-
process.stdout.write(` ${
|
|
8926
|
+
const desc = result.description ? chalk23.dim(` \u2014 ${result.description}`) : "";
|
|
8927
|
+
const stars = result.starCount > 0 ? chalk23.yellow(` \u2605 ${result.starCount}`) : "";
|
|
8928
|
+
const installs = result.installCount > 0 ? chalk23.cyan(` \u2193 ${formatInstallCount(result.installCount)}`) : "";
|
|
8929
|
+
const cats = result.categories.length > 0 ? chalk23.dim(` [${result.categories.map((c) => c.name).join(", ")}]`) : "";
|
|
8930
|
+
process.stdout.write(` ${chalk23.green(result.slug)}${stars}${installs}${cats}${desc}
|
|
8122
8931
|
`);
|
|
8123
8932
|
}
|
|
8124
8933
|
process.stdout.write("\n");
|
|
8125
8934
|
}
|
|
8126
8935
|
function renderCommunityResults(results) {
|
|
8127
8936
|
if (results.length === 0) return;
|
|
8128
|
-
process.stdout.write(
|
|
8937
|
+
process.stdout.write(chalk23.bold(`
|
|
8129
8938
|
Skills from skills.sh:
|
|
8130
8939
|
|
|
8131
8940
|
`));
|
|
8132
8941
|
for (const result of results) {
|
|
8133
|
-
const nameCol =
|
|
8134
|
-
const sourceCol =
|
|
8135
|
-
const installCol =
|
|
8942
|
+
const nameCol = chalk23.green(result.name);
|
|
8943
|
+
const sourceCol = chalk23.dim(`(${result.source})`);
|
|
8944
|
+
const installCol = chalk23.cyan(`\u2193 ${formatInstallCount(result.installCount)}`);
|
|
8136
8945
|
process.stdout.write(` ${nameCol} ${sourceCol} ${installCol}
|
|
8137
8946
|
`);
|
|
8138
8947
|
if (result.description) {
|
|
8139
|
-
process.stdout.write(` ${
|
|
8948
|
+
process.stdout.write(` ${chalk23.dim(result.description)}
|
|
8140
8949
|
`);
|
|
8141
8950
|
}
|
|
8142
8951
|
process.stdout.write("\n");
|
|
8143
8952
|
}
|
|
8144
8953
|
process.stdout.write(
|
|
8145
|
-
|
|
8954
|
+
chalk23.dim(" Install with: ") + chalk23.white("agentver install github.com/{source}/{name}") + "\n\n"
|
|
8146
8955
|
);
|
|
8147
8956
|
}
|
|
8148
8957
|
function renderWellKnownResults(hostname3, skills) {
|
|
8149
8958
|
if (skills.length === 0) return;
|
|
8150
|
-
process.stdout.write(
|
|
8959
|
+
process.stdout.write(chalk23.bold(`
|
|
8151
8960
|
Skills from ${hostname3}:
|
|
8152
8961
|
|
|
8153
8962
|
`));
|
|
8154
8963
|
for (const skill of skills) {
|
|
8155
|
-
process.stdout.write(` ${
|
|
8964
|
+
process.stdout.write(` ${chalk23.green(skill.name)} ${chalk23.dim(`\u2014 ${skill.description}`)}
|
|
8156
8965
|
`);
|
|
8157
8966
|
process.stdout.write(
|
|
8158
|
-
` ${
|
|
8967
|
+
` ${chalk23.dim("Install:")} ${chalk23.white(`agentver install ${hostname3}/${skill.name}`)}
|
|
8159
8968
|
`
|
|
8160
8969
|
);
|
|
8161
8970
|
process.stdout.write("\n");
|
|
8162
8971
|
}
|
|
8163
8972
|
}
|
|
8164
8973
|
function renderNoResults(query) {
|
|
8165
|
-
process.stdout.write(
|
|
8974
|
+
process.stdout.write(chalk23.dim(`No results for "${query}"
|
|
8166
8975
|
`));
|
|
8167
8976
|
}
|
|
8168
8977
|
function registerSearchCommand(program2) {
|
|
@@ -8177,7 +8986,7 @@ function registerSearchCommand(program2) {
|
|
|
8177
8986
|
if (requestedSource) {
|
|
8178
8987
|
if (!["platform", "community", "well-known", "all"].includes(requestedSource)) {
|
|
8179
8988
|
process.stderr.write(
|
|
8180
|
-
|
|
8989
|
+
chalk23.red(
|
|
8181
8990
|
`Invalid source "${requestedSource}". Use: platform, community, well-known, or all
|
|
8182
8991
|
`
|
|
8183
8992
|
)
|
|
@@ -8187,7 +8996,7 @@ function registerSearchCommand(program2) {
|
|
|
8187
8996
|
source = requestedSource;
|
|
8188
8997
|
if (source === "platform" && !connected) {
|
|
8189
8998
|
process.stderr.write(
|
|
8190
|
-
|
|
8999
|
+
chalk23.red("Not connected to a platform. Run `agentver login <url>` to connect.\n")
|
|
8191
9000
|
);
|
|
8192
9001
|
process.exit(1);
|
|
8193
9002
|
}
|
|
@@ -8255,7 +9064,7 @@ function registerSearchCommand(program2) {
|
|
|
8255
9064
|
if (communityResults.length > 0) {
|
|
8256
9065
|
const example = communityResults[0];
|
|
8257
9066
|
process.stdout.write(
|
|
8258
|
-
|
|
9067
|
+
chalk23.dim(" Example: ") + chalk23.white(`agentver install ${toGitInstallSource(example)}`) + "\n"
|
|
8259
9068
|
);
|
|
8260
9069
|
}
|
|
8261
9070
|
} catch (error) {
|
|
@@ -8267,13 +9076,13 @@ function registerSearchCommand(program2) {
|
|
|
8267
9076
|
}
|
|
8268
9077
|
|
|
8269
9078
|
// src/commands/status.ts
|
|
8270
|
-
import
|
|
9079
|
+
import chalk24 from "chalk";
|
|
8271
9080
|
var STATUS_SYMBOLS = {
|
|
8272
|
-
"up-to-date":
|
|
8273
|
-
modified:
|
|
8274
|
-
upstream:
|
|
8275
|
-
both:
|
|
8276
|
-
unknown:
|
|
9081
|
+
"up-to-date": chalk24.green("\u2713"),
|
|
9082
|
+
modified: chalk24.yellow("M"),
|
|
9083
|
+
upstream: chalk24.cyan("U"),
|
|
9084
|
+
both: chalk24.red("MU"),
|
|
9085
|
+
unknown: chalk24.dim("?")
|
|
8277
9086
|
};
|
|
8278
9087
|
function parseManifestUri2(uri) {
|
|
8279
9088
|
const parts = uri.split("/");
|
|
@@ -8295,7 +9104,7 @@ async function readLocalFiles2(projectRoot, packageName, agents) {
|
|
|
8295
9104
|
return [];
|
|
8296
9105
|
}
|
|
8297
9106
|
async function checkPackageStatus(projectRoot, name, manifestEntry, lockfileIntegrity, offline) {
|
|
8298
|
-
const { source, agents } = manifestEntry;
|
|
9107
|
+
const { source, agents, pinned } = manifestEntry;
|
|
8299
9108
|
if (source.type === "well-known") {
|
|
8300
9109
|
let locallyModified2 = false;
|
|
8301
9110
|
try {
|
|
@@ -8313,7 +9122,8 @@ async function checkPackageStatus(projectRoot, name, manifestEntry, lockfileInte
|
|
|
8313
9122
|
sourceUri: source.hostname,
|
|
8314
9123
|
ref: "well-known",
|
|
8315
9124
|
commit: "",
|
|
8316
|
-
agents
|
|
9125
|
+
agents,
|
|
9126
|
+
pinned: pinned || void 0
|
|
8317
9127
|
};
|
|
8318
9128
|
}
|
|
8319
9129
|
if (source.uri === "unknown") {
|
|
@@ -8323,7 +9133,8 @@ async function checkPackageStatus(projectRoot, name, manifestEntry, lockfileInte
|
|
|
8323
9133
|
sourceUri: source.uri,
|
|
8324
9134
|
ref: source.ref,
|
|
8325
9135
|
commit: source.commit,
|
|
8326
|
-
agents
|
|
9136
|
+
agents,
|
|
9137
|
+
pinned: pinned || void 0
|
|
8327
9138
|
};
|
|
8328
9139
|
}
|
|
8329
9140
|
let locallyModified = false;
|
|
@@ -8367,18 +9178,20 @@ async function checkPackageStatus(projectRoot, name, manifestEntry, lockfileInte
|
|
|
8367
9178
|
ref: source.ref,
|
|
8368
9179
|
commit: source.commit,
|
|
8369
9180
|
upstreamCommit: upstreamChanged ? upstreamCommit : void 0,
|
|
8370
|
-
agents
|
|
9181
|
+
agents,
|
|
9182
|
+
pinned: pinned || void 0
|
|
8371
9183
|
};
|
|
8372
9184
|
}
|
|
8373
9185
|
function formatStatusLine(status) {
|
|
8374
9186
|
const symbol = STATUS_SYMBOLS[status.category];
|
|
8375
9187
|
const padding = status.category === "both" ? "" : " ";
|
|
8376
9188
|
if (status.category === "unknown") {
|
|
8377
|
-
return ` ${symbol} ${
|
|
9189
|
+
return ` ${symbol} ${chalk24.white(status.name)} ${chalk24.dim("unknown source")}`;
|
|
8378
9190
|
}
|
|
8379
9191
|
const shortCommit = status.commit.slice(0, 7);
|
|
8380
|
-
const upstream = status.upstreamCommit ? ` ${
|
|
8381
|
-
|
|
9192
|
+
const upstream = status.upstreamCommit ? ` ${chalk24.dim("\u2192")} ${chalk24.cyan(`upstream: ${status.upstreamCommit.slice(0, 7)}`)}` : "";
|
|
9193
|
+
const pinned = status.pinned ? chalk24.yellow(" [pinned]") : "";
|
|
9194
|
+
return ` ${symbol}${padding} ${chalk24.white(status.name)}${pinned} ${chalk24.dim(status.sourceUri)} ${chalk24.cyan(`@${status.ref}`)} ${chalk24.dim(`(${shortCommit})`)}${upstream}`;
|
|
8382
9195
|
}
|
|
8383
9196
|
function buildStatusOutput(statuses) {
|
|
8384
9197
|
return {
|
|
@@ -8396,7 +9209,8 @@ function toStatusResult(output) {
|
|
|
8396
9209
|
name: p.name,
|
|
8397
9210
|
status: p.category,
|
|
8398
9211
|
modified: p.category === "modified" || p.category === "both",
|
|
8399
|
-
upstream: p.category === "upstream" || p.category === "both"
|
|
9212
|
+
upstream: p.category === "upstream" || p.category === "both",
|
|
9213
|
+
pinned: p.pinned || void 0
|
|
8400
9214
|
})),
|
|
8401
9215
|
summary: {
|
|
8402
9216
|
total: output.total,
|
|
@@ -8418,7 +9232,7 @@ function registerStatusCommand(program2) {
|
|
|
8418
9232
|
if (jsonMode) {
|
|
8419
9233
|
outputSuccess(toStatusResult(buildStatusOutput([])));
|
|
8420
9234
|
} else {
|
|
8421
|
-
console.log(
|
|
9235
|
+
console.log(chalk24.dim("No packages installed."));
|
|
8422
9236
|
}
|
|
8423
9237
|
return;
|
|
8424
9238
|
}
|
|
@@ -8441,7 +9255,7 @@ function registerStatusCommand(program2) {
|
|
|
8441
9255
|
outputSuccess(toStatusResult(buildStatusOutput(statuses)));
|
|
8442
9256
|
return;
|
|
8443
9257
|
}
|
|
8444
|
-
console.log(
|
|
9258
|
+
console.log(chalk24.bold(`
|
|
8445
9259
|
Installed skills (${statuses.length}):
|
|
8446
9260
|
`));
|
|
8447
9261
|
for (const status of statuses) {
|
|
@@ -8452,16 +9266,16 @@ Installed skills (${statuses.length}):
|
|
|
8452
9266
|
}
|
|
8453
9267
|
|
|
8454
9268
|
// src/commands/suggest.ts
|
|
8455
|
-
import { existsSync as
|
|
8456
|
-
import { join as
|
|
8457
|
-
import
|
|
9269
|
+
import { existsSync as existsSync17 } from "fs";
|
|
9270
|
+
import { join as join20 } from "path";
|
|
9271
|
+
import chalk25 from "chalk";
|
|
8458
9272
|
var HTTP_TIMEOUT_MS2 = 15e3;
|
|
8459
9273
|
async function readLocalFiles3(projectRoot, packageName, agents) {
|
|
8460
9274
|
for (const agentId of agents) {
|
|
8461
9275
|
const placementPath = getSkillPlacementPath(agentId, packageName, "project");
|
|
8462
9276
|
if (!placementPath) continue;
|
|
8463
|
-
const fullPath =
|
|
8464
|
-
if (!
|
|
9277
|
+
const fullPath = join20(projectRoot, placementPath);
|
|
9278
|
+
if (!existsSync17(fullPath)) continue;
|
|
8465
9279
|
const files = await readFilesFromDirectory(fullPath);
|
|
8466
9280
|
return files.map((f) => ({ path: f.path, content: f.content }));
|
|
8467
9281
|
}
|
|
@@ -8509,141 +9323,211 @@ async function postToPlatform(path, body) {
|
|
|
8509
9323
|
throw error;
|
|
8510
9324
|
}
|
|
8511
9325
|
}
|
|
9326
|
+
function buildEndpoint(manifestEntry, packageName) {
|
|
9327
|
+
if (manifestEntry.source.type !== "git") return "";
|
|
9328
|
+
const orgSlug = manifestEntry.source.uri.split("/")[1] ?? "";
|
|
9329
|
+
return `/skills/@${orgSlug}/${packageName}/suggestions`;
|
|
9330
|
+
}
|
|
9331
|
+
async function submitSuggestion(projectRoot, packageName, manifestEntry, title, description) {
|
|
9332
|
+
const localFiles = await readLocalFiles3(projectRoot, packageName, manifestEntry.agents);
|
|
9333
|
+
if (localFiles.length === 0) {
|
|
9334
|
+
throw new Error(`No local files found for "${packageName}".`);
|
|
9335
|
+
}
|
|
9336
|
+
const endpoint = buildEndpoint(manifestEntry, packageName);
|
|
9337
|
+
const requestBody = {
|
|
9338
|
+
title,
|
|
9339
|
+
description,
|
|
9340
|
+
files: localFiles
|
|
9341
|
+
};
|
|
9342
|
+
const result = await postToPlatform(endpoint, requestBody);
|
|
9343
|
+
return { localFiles, result };
|
|
9344
|
+
}
|
|
8512
9345
|
function registerSuggestCommand(program2) {
|
|
8513
|
-
program2.command("suggest <title>").alias("propose").description("Create a suggestion from local modifications (requires platform connection)").option("-d, --description <text>", "Suggestion description").option("--dry-run", "Show what would be suggested without submitting").action(
|
|
8514
|
-
|
|
8515
|
-
|
|
8516
|
-
|
|
8517
|
-
|
|
8518
|
-
if (
|
|
8519
|
-
|
|
8520
|
-
|
|
8521
|
-
|
|
8522
|
-
|
|
9346
|
+
program2.command("suggest <title>").alias("propose").description("Create a suggestion from local modifications (requires platform connection)").option("-d, --description <text>", "Suggestion description").option("--name <name>", "Target a specific modified package by name").option("--dry-run", "Show what would be suggested without submitting").action(
|
|
9347
|
+
async (title, options) => {
|
|
9348
|
+
const json = isJSONMode();
|
|
9349
|
+
const platformUrl = getPlatformUrl();
|
|
9350
|
+
const creds = await getCredentials();
|
|
9351
|
+
if (!options.dryRun && (!platformUrl || !creds?.token && !creds?.apiKey)) {
|
|
9352
|
+
if (json) {
|
|
9353
|
+
outputError(
|
|
9354
|
+
"AUTH_REQUIRED",
|
|
9355
|
+
"Not connected to a platform. Run `agentver login <url>` first."
|
|
9356
|
+
);
|
|
9357
|
+
process.exit(1);
|
|
9358
|
+
}
|
|
9359
|
+
console.error(chalk25.red("Not connected to a platform. Run `agentver login <url>` first."));
|
|
8523
9360
|
process.exit(1);
|
|
8524
9361
|
}
|
|
8525
|
-
|
|
8526
|
-
|
|
8527
|
-
|
|
8528
|
-
|
|
8529
|
-
|
|
8530
|
-
|
|
8531
|
-
|
|
8532
|
-
|
|
8533
|
-
|
|
8534
|
-
|
|
8535
|
-
|
|
8536
|
-
|
|
8537
|
-
|
|
8538
|
-
|
|
8539
|
-
if (currentIntegrity !== lockfileEntry.integrity) {
|
|
8540
|
-
modifiedPackages.push(name);
|
|
8541
|
-
}
|
|
8542
|
-
}
|
|
8543
|
-
if (modifiedPackages.length === 0) {
|
|
8544
|
-
if (json) {
|
|
8545
|
-
outputError("NO_CHANGES", "No modified packages detected.");
|
|
8546
|
-
process.exit(1);
|
|
9362
|
+
const projectRoot = process.cwd();
|
|
9363
|
+
const manifest = readManifest(projectRoot);
|
|
9364
|
+
const lockfile = readLockfile(projectRoot);
|
|
9365
|
+
const modifiedPackages = [];
|
|
9366
|
+
for (const [name, manifestEntry] of Object.entries(manifest.packages)) {
|
|
9367
|
+
const lockfileEntry = lockfile.packages[name];
|
|
9368
|
+
if (!lockfileEntry) continue;
|
|
9369
|
+
const { agents } = manifestEntry;
|
|
9370
|
+
const localFiles = await readLocalFiles3(projectRoot, name, agents);
|
|
9371
|
+
if (localFiles.length === 0) continue;
|
|
9372
|
+
const currentIntegrity = computeSha256FromFiles(localFiles);
|
|
9373
|
+
if (currentIntegrity !== lockfileEntry.integrity) {
|
|
9374
|
+
modifiedPackages.push(name);
|
|
9375
|
+
}
|
|
8547
9376
|
}
|
|
8548
|
-
|
|
8549
|
-
|
|
8550
|
-
|
|
8551
|
-
|
|
8552
|
-
|
|
8553
|
-
|
|
8554
|
-
|
|
8555
|
-
if (json) {
|
|
8556
|
-
outputError(
|
|
8557
|
-
"UNSUPPORTED_SOURCE",
|
|
8558
|
-
`Package "${targetName}" was installed from a well-known source. Suggestions are not supported.`
|
|
8559
|
-
);
|
|
8560
|
-
} else {
|
|
8561
|
-
console.error(
|
|
8562
|
-
chalk20.red(
|
|
8563
|
-
`Package "${targetName}" was installed from a well-known source (${source.hostname}).`
|
|
8564
|
-
)
|
|
8565
|
-
);
|
|
8566
|
-
console.error(chalk20.dim("Suggestions are not supported for well-known sources."));
|
|
9377
|
+
if (modifiedPackages.length === 0) {
|
|
9378
|
+
if (json) {
|
|
9379
|
+
outputError("NO_CHANGES", "No modified packages detected.");
|
|
9380
|
+
process.exit(1);
|
|
9381
|
+
}
|
|
9382
|
+
console.log(chalk25.dim("No modified packages detected."));
|
|
9383
|
+
return;
|
|
8567
9384
|
}
|
|
8568
|
-
|
|
8569
|
-
|
|
8570
|
-
|
|
8571
|
-
try {
|
|
8572
|
-
const localFiles = await readLocalFiles3(projectRoot, targetName, agents);
|
|
8573
|
-
if (localFiles.length === 0) {
|
|
8574
|
-
spinner.fail(`No local files found for "${targetName}".`);
|
|
9385
|
+
const targets = options.name ? modifiedPackages.filter((n) => n === options.name) : modifiedPackages;
|
|
9386
|
+
if (targets.length === 0 && options.name) {
|
|
9387
|
+
const message = `Package "${options.name}" is not in the modified list. Modified: ${modifiedPackages.join(", ")}`;
|
|
8575
9388
|
if (json) {
|
|
8576
|
-
outputError("NOT_FOUND",
|
|
9389
|
+
outputError("NOT_FOUND", message);
|
|
9390
|
+
process.exit(1);
|
|
9391
|
+
}
|
|
9392
|
+
console.error(chalk25.red(message));
|
|
9393
|
+
process.exit(1);
|
|
9394
|
+
}
|
|
9395
|
+
const unsupportedTargets = targets.filter(
|
|
9396
|
+
(name) => manifest.packages[name]?.source.type === "well-known"
|
|
9397
|
+
);
|
|
9398
|
+
if (unsupportedTargets.length > 0) {
|
|
9399
|
+
for (const name of unsupportedTargets) {
|
|
9400
|
+
const source = manifest.packages[name].source;
|
|
9401
|
+
if (json) {
|
|
9402
|
+
outputError(
|
|
9403
|
+
"UNSUPPORTED_SOURCE",
|
|
9404
|
+
`Package "${name}" was installed from a well-known source. Suggestions are not supported.`
|
|
9405
|
+
);
|
|
9406
|
+
} else {
|
|
9407
|
+
console.error(
|
|
9408
|
+
chalk25.red(
|
|
9409
|
+
`Package "${name}" was installed from a well-known source (${source.type === "well-known" ? source.hostname : "unknown"}).`
|
|
9410
|
+
)
|
|
9411
|
+
);
|
|
9412
|
+
console.error(chalk25.dim("Suggestions are not supported for well-known sources."));
|
|
9413
|
+
}
|
|
8577
9414
|
}
|
|
9415
|
+
}
|
|
9416
|
+
const validTargets = targets.filter((n) => !unsupportedTargets.includes(n));
|
|
9417
|
+
if (validTargets.length === 0) {
|
|
8578
9418
|
process.exit(1);
|
|
8579
9419
|
}
|
|
8580
|
-
const orgSlug = source.uri.split("/")[1] ?? "";
|
|
8581
|
-
const pkgName = targetName;
|
|
8582
9420
|
if (options.dryRun) {
|
|
8583
|
-
const
|
|
8584
|
-
|
|
8585
|
-
|
|
8586
|
-
|
|
8587
|
-
|
|
8588
|
-
|
|
8589
|
-
|
|
8590
|
-
|
|
8591
|
-
|
|
8592
|
-
|
|
8593
|
-
|
|
9421
|
+
const dryRunResults = [];
|
|
9422
|
+
for (const targetName of validTargets) {
|
|
9423
|
+
const manifestEntry = manifest.packages[targetName];
|
|
9424
|
+
const localFiles = await readLocalFiles3(projectRoot, targetName, manifestEntry.agents);
|
|
9425
|
+
const endpoint = `/api/v1${buildEndpoint(manifestEntry, targetName)}`;
|
|
9426
|
+
dryRunResults.push({
|
|
9427
|
+
package: targetName,
|
|
9428
|
+
title,
|
|
9429
|
+
description: options.description,
|
|
9430
|
+
files: localFiles.map((f) => ({
|
|
9431
|
+
path: f.path,
|
|
9432
|
+
contentLength: f.content.length
|
|
9433
|
+
})),
|
|
9434
|
+
endpoint
|
|
9435
|
+
});
|
|
9436
|
+
}
|
|
8594
9437
|
if (json) {
|
|
8595
|
-
outputSuccess(
|
|
9438
|
+
outputSuccess(dryRunResults);
|
|
8596
9439
|
} else {
|
|
8597
|
-
console.log(
|
|
8598
|
-
|
|
8599
|
-
|
|
8600
|
-
|
|
8601
|
-
|
|
8602
|
-
|
|
8603
|
-
|
|
8604
|
-
|
|
8605
|
-
|
|
9440
|
+
console.log(chalk25.bold("\nDry run \u2014 suggestion preview:\n"));
|
|
9441
|
+
for (const entry of dryRunResults) {
|
|
9442
|
+
console.log(` ${chalk25.dim("Package:")} ${entry.package}`);
|
|
9443
|
+
console.log(` ${chalk25.dim("Title:")} ${entry.title}`);
|
|
9444
|
+
if (entry.description) {
|
|
9445
|
+
console.log(` ${chalk25.dim("Desc:")} ${entry.description}`);
|
|
9446
|
+
}
|
|
9447
|
+
console.log(` ${chalk25.dim("Files:")}`);
|
|
9448
|
+
for (const f of entry.files) {
|
|
9449
|
+
console.log(` ${chalk25.cyan(f.path)} (${f.contentLength} bytes)`);
|
|
9450
|
+
}
|
|
9451
|
+
console.log(` ${chalk25.dim("Endpoint:")} ${entry.endpoint}`);
|
|
9452
|
+
console.log();
|
|
8606
9453
|
}
|
|
8607
|
-
console.log(
|
|
8608
|
-
|
|
9454
|
+
console.log(
|
|
9455
|
+
chalk25.dim(
|
|
9456
|
+
`${dryRunResults.length} package${dryRunResults.length === 1 ? "" : "s"} would get suggestions.`
|
|
9457
|
+
)
|
|
9458
|
+
);
|
|
8609
9459
|
}
|
|
8610
9460
|
return;
|
|
8611
9461
|
}
|
|
8612
|
-
|
|
8613
|
-
const
|
|
8614
|
-
|
|
8615
|
-
|
|
8616
|
-
|
|
8617
|
-
|
|
8618
|
-
|
|
8619
|
-
|
|
8620
|
-
|
|
8621
|
-
|
|
8622
|
-
|
|
8623
|
-
|
|
8624
|
-
|
|
8625
|
-
|
|
8626
|
-
|
|
8627
|
-
|
|
8628
|
-
|
|
8629
|
-
|
|
8630
|
-
|
|
8631
|
-
|
|
8632
|
-
|
|
9462
|
+
const outcomes = [];
|
|
9463
|
+
for (const targetName of validTargets) {
|
|
9464
|
+
const manifestEntry = manifest.packages[targetName];
|
|
9465
|
+
const spinner = createSpinner(`Creating suggestion for ${targetName}...`).start();
|
|
9466
|
+
try {
|
|
9467
|
+
const { result } = await submitSuggestion(
|
|
9468
|
+
projectRoot,
|
|
9469
|
+
targetName,
|
|
9470
|
+
manifestEntry,
|
|
9471
|
+
title,
|
|
9472
|
+
options.description
|
|
9473
|
+
);
|
|
9474
|
+
const proposeResult = {
|
|
9475
|
+
proposalId: result.id,
|
|
9476
|
+
title: result.title ?? title,
|
|
9477
|
+
url: result.url ?? ""
|
|
9478
|
+
};
|
|
9479
|
+
outcomes.push({ package: targetName, success: true, result: proposeResult });
|
|
9480
|
+
if (!json) {
|
|
9481
|
+
spinner.succeed(
|
|
9482
|
+
`Created suggestion for ${chalk25.bold(targetName)}: ${chalk25.bold(proposeResult.title)}`
|
|
9483
|
+
);
|
|
9484
|
+
if (result.url) {
|
|
9485
|
+
console.log(chalk25.dim(` ${result.url}`));
|
|
9486
|
+
}
|
|
9487
|
+
} else {
|
|
9488
|
+
spinner.stop();
|
|
9489
|
+
}
|
|
9490
|
+
} catch (error) {
|
|
9491
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
9492
|
+
outcomes.push({ package: targetName, success: false, error: message });
|
|
9493
|
+
if (!json) {
|
|
9494
|
+
spinner.fail(`Failed to create suggestion for ${chalk25.bold(targetName)}: ${message}`);
|
|
9495
|
+
} else {
|
|
9496
|
+
spinner.stop();
|
|
9497
|
+
}
|
|
9498
|
+
}
|
|
8633
9499
|
}
|
|
8634
|
-
|
|
8635
|
-
const
|
|
8636
|
-
spinner.fail(`Failed to create suggestion: ${message}`);
|
|
9500
|
+
const succeeded = outcomes.filter((o) => o.success);
|
|
9501
|
+
const failed = outcomes.filter((o) => !o.success);
|
|
8637
9502
|
if (json) {
|
|
8638
|
-
|
|
9503
|
+
if (validTargets.length === 1) {
|
|
9504
|
+
const outcome = outcomes[0];
|
|
9505
|
+
if (outcome.success) {
|
|
9506
|
+
outputSuccess(outcome.result);
|
|
9507
|
+
} else {
|
|
9508
|
+
outputError("SUGGEST_FAILED", outcome.error);
|
|
9509
|
+
process.exit(1);
|
|
9510
|
+
}
|
|
9511
|
+
} else {
|
|
9512
|
+
outputSuccess(outcomes);
|
|
9513
|
+
}
|
|
9514
|
+
} else if (validTargets.length > 1) {
|
|
9515
|
+
console.log();
|
|
9516
|
+
console.log(
|
|
9517
|
+
chalk25.bold(
|
|
9518
|
+
`Created ${succeeded.length} suggestion${succeeded.length === 1 ? "" : "s"}` + (failed.length > 0 ? ` (${failed.length} failed)` : "")
|
|
9519
|
+
)
|
|
9520
|
+
);
|
|
9521
|
+
}
|
|
9522
|
+
if (failed.length > 0 && succeeded.length === 0) {
|
|
9523
|
+
process.exit(1);
|
|
8639
9524
|
}
|
|
8640
|
-
process.exit(1);
|
|
8641
9525
|
}
|
|
8642
|
-
|
|
9526
|
+
);
|
|
8643
9527
|
}
|
|
8644
9528
|
|
|
8645
9529
|
// src/commands/suggestions.ts
|
|
8646
|
-
import
|
|
9530
|
+
import chalk26 from "chalk";
|
|
8647
9531
|
var HTTP_TIMEOUT_MS3 = 15e3;
|
|
8648
9532
|
async function getFromPlatform(path) {
|
|
8649
9533
|
const platformUrl = getPlatformUrl();
|
|
@@ -8698,21 +9582,21 @@ function formatDate2(isoDate) {
|
|
|
8698
9582
|
}
|
|
8699
9583
|
}
|
|
8700
9584
|
var STATUS_COLOURS = {
|
|
8701
|
-
OPEN:
|
|
8702
|
-
IN_REVIEW:
|
|
8703
|
-
APPROVED:
|
|
8704
|
-
MERGED:
|
|
8705
|
-
REJECTED:
|
|
8706
|
-
CLOSED:
|
|
9585
|
+
OPEN: chalk26.green,
|
|
9586
|
+
IN_REVIEW: chalk26.yellow,
|
|
9587
|
+
APPROVED: chalk26.blue,
|
|
9588
|
+
MERGED: chalk26.magenta,
|
|
9589
|
+
REJECTED: chalk26.red,
|
|
9590
|
+
CLOSED: chalk26.dim
|
|
8707
9591
|
};
|
|
8708
9592
|
function formatSuggestionRow(suggestion, idWidth, titleWidth, slugWidth, authorWidth) {
|
|
8709
|
-
const id =
|
|
9593
|
+
const id = chalk26.dim(`#${suggestion.id}`.padEnd(idWidth + 1));
|
|
8710
9594
|
const title = suggestion.title.padEnd(titleWidth);
|
|
8711
|
-
const slug =
|
|
8712
|
-
const statusFn = STATUS_COLOURS[suggestion.status] ??
|
|
9595
|
+
const slug = chalk26.cyan(suggestion.packageSlug.padEnd(slugWidth));
|
|
9596
|
+
const statusFn = STATUS_COLOURS[suggestion.status] ?? chalk26.dim;
|
|
8713
9597
|
const status = statusFn(suggestion.status.padEnd(11));
|
|
8714
|
-
const author =
|
|
8715
|
-
const date =
|
|
9598
|
+
const author = chalk26.dim(suggestion.author.padEnd(authorWidth));
|
|
9599
|
+
const date = chalk26.dim(formatDate2(suggestion.createdAt));
|
|
8716
9600
|
return ` ${id} ${title} ${slug} ${status} ${author} ${date}`;
|
|
8717
9601
|
}
|
|
8718
9602
|
function registerSuggestionsCommand(program2) {
|
|
@@ -8728,7 +9612,7 @@ function registerSuggestionsCommand(program2) {
|
|
|
8728
9612
|
);
|
|
8729
9613
|
process.exit(1);
|
|
8730
9614
|
}
|
|
8731
|
-
console.error(
|
|
9615
|
+
console.error(chalk26.red("Not connected to a platform. Run `agentver login <url>` first."));
|
|
8732
9616
|
process.exit(1);
|
|
8733
9617
|
}
|
|
8734
9618
|
const spinner = createSpinner("Fetching suggestions...").start();
|
|
@@ -8760,7 +9644,7 @@ function registerSuggestionsCommand(program2) {
|
|
|
8760
9644
|
}
|
|
8761
9645
|
if (suggestions.length === 0) {
|
|
8762
9646
|
const filterLabel = statusFilter === "ALL" ? "" : ` ${options.status}`;
|
|
8763
|
-
console.log(
|
|
9647
|
+
console.log(chalk26.dim(`No${filterLabel} suggestions found.`));
|
|
8764
9648
|
return;
|
|
8765
9649
|
}
|
|
8766
9650
|
const idWidth = Math.max(...suggestions.map((s) => `#${s.id}`.length));
|
|
@@ -8768,7 +9652,7 @@ function registerSuggestionsCommand(program2) {
|
|
|
8768
9652
|
const slugWidth = Math.max(...suggestions.map((s) => s.packageSlug.length));
|
|
8769
9653
|
const authorWidth = Math.max(...suggestions.map((s) => s.author.length));
|
|
8770
9654
|
const heading = statusFilter === "ALL" ? `Suggestions (${suggestions.length})` : `${options.status.charAt(0).toUpperCase() + options.status.slice(1)} suggestions (${suggestions.length})`;
|
|
8771
|
-
console.log(
|
|
9655
|
+
console.log(chalk26.bold(`
|
|
8772
9656
|
${heading}:
|
|
8773
9657
|
`));
|
|
8774
9658
|
for (const suggestion of suggestions) {
|
|
@@ -8789,7 +9673,7 @@ ${heading}:
|
|
|
8789
9673
|
// src/commands/sync.ts
|
|
8790
9674
|
import { createHash as createHash4 } from "crypto";
|
|
8791
9675
|
import { hostname as hostname2 } from "os";
|
|
8792
|
-
import
|
|
9676
|
+
import chalk27 from "chalk";
|
|
8793
9677
|
var SYNC_TIMEOUT_MS = 3e4;
|
|
8794
9678
|
function getMachineId2() {
|
|
8795
9679
|
return createHash4("sha256").update(hostname2()).digest("hex");
|
|
@@ -8806,7 +9690,7 @@ function registerSyncCommand(program2) {
|
|
|
8806
9690
|
process.exit(1);
|
|
8807
9691
|
}
|
|
8808
9692
|
console.error(
|
|
8809
|
-
|
|
9693
|
+
chalk27.red("Not connected to a platform.") + " Run " + chalk27.cyan("`agentver login <url>`") + " first."
|
|
8810
9694
|
);
|
|
8811
9695
|
process.exit(1);
|
|
8812
9696
|
}
|
|
@@ -8820,7 +9704,7 @@ function registerSyncCommand(program2) {
|
|
|
8820
9704
|
process.exit(1);
|
|
8821
9705
|
}
|
|
8822
9706
|
console.error(
|
|
8823
|
-
|
|
9707
|
+
chalk27.red("Not connected to a platform.") + " Run " + chalk27.cyan("`agentver login <url>`") + " first."
|
|
8824
9708
|
);
|
|
8825
9709
|
process.exit(1);
|
|
8826
9710
|
}
|
|
@@ -8892,7 +9776,7 @@ function registerSyncCommand(program2) {
|
|
|
8892
9776
|
return;
|
|
8893
9777
|
}
|
|
8894
9778
|
spinner.succeed(
|
|
8895
|
-
`Synced ${
|
|
9779
|
+
`Synced ${chalk27.green(String(result.synced))} skill${result.synced === 1 ? "" : "s"} to platform` + (result.removed > 0 ? chalk27.dim(` (${result.removed} removed)`) : "")
|
|
8896
9780
|
);
|
|
8897
9781
|
} catch (error) {
|
|
8898
9782
|
if (error instanceof DOMException && error.name === "AbortError") {
|
|
@@ -8916,23 +9800,23 @@ function registerSyncCommand(program2) {
|
|
|
8916
9800
|
}
|
|
8917
9801
|
|
|
8918
9802
|
// src/commands/update.ts
|
|
8919
|
-
import { join as
|
|
8920
|
-
import
|
|
9803
|
+
import { join as join23 } from "path";
|
|
9804
|
+
import chalk28 from "chalk";
|
|
8921
9805
|
import ora7 from "ora";
|
|
8922
9806
|
import prompts3 from "prompts";
|
|
8923
9807
|
|
|
8924
9808
|
// src/storage/patches.ts
|
|
8925
|
-
import { existsSync as
|
|
8926
|
-
import { join as
|
|
9809
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync9, readFileSync as readFileSync16, rmSync as rmSync3, writeFileSync as writeFileSync8 } from "fs";
|
|
9810
|
+
import { join as join21 } from "path";
|
|
8927
9811
|
var PATCHES_DIR = ".agentver/patches";
|
|
8928
9812
|
var CONTEXT_LINES2 = 3;
|
|
8929
9813
|
function getPatchPath(projectRoot, packageName) {
|
|
8930
|
-
return
|
|
9814
|
+
return join21(projectRoot, PATCHES_DIR, `${packageName}.patch`);
|
|
8931
9815
|
}
|
|
8932
9816
|
function savePatch(projectRoot, packageName, patchContent) {
|
|
8933
9817
|
const patchPath = getPatchPath(projectRoot, packageName);
|
|
8934
|
-
const dir =
|
|
8935
|
-
if (!
|
|
9818
|
+
const dir = join21(projectRoot, PATCHES_DIR);
|
|
9819
|
+
if (!existsSync18(dir)) {
|
|
8936
9820
|
mkdirSync9(dir, { recursive: true });
|
|
8937
9821
|
}
|
|
8938
9822
|
writeFileSync8(patchPath, patchContent, "utf-8");
|
|
@@ -8940,7 +9824,7 @@ function savePatch(projectRoot, packageName, patchContent) {
|
|
|
8940
9824
|
}
|
|
8941
9825
|
function removePatch(projectRoot, packageName) {
|
|
8942
9826
|
const patchPath = getPatchPath(projectRoot, packageName);
|
|
8943
|
-
if (
|
|
9827
|
+
if (existsSync18(patchPath)) {
|
|
8944
9828
|
rmSync3(patchPath);
|
|
8945
9829
|
}
|
|
8946
9830
|
}
|
|
@@ -8987,30 +9871,30 @@ function applyPatch(projectRoot, patchContent) {
|
|
|
8987
9871
|
};
|
|
8988
9872
|
}
|
|
8989
9873
|
function applyFilePatch(projectRoot, filePatch) {
|
|
8990
|
-
const fullPath =
|
|
9874
|
+
const fullPath = join21(projectRoot, filePatch.filePath);
|
|
8991
9875
|
const hasOnlyAdditions = filePatch.hunks.every(
|
|
8992
9876
|
(h) => h.lines.every((l) => l.startsWith("+") || l.startsWith(" "))
|
|
8993
9877
|
);
|
|
8994
9878
|
const hasOnlyDeletions = filePatch.hunks.every(
|
|
8995
9879
|
(h) => h.lines.every((l) => l.startsWith("-") || l.startsWith(" "))
|
|
8996
9880
|
);
|
|
8997
|
-
if (hasOnlyAdditions && !
|
|
9881
|
+
if (hasOnlyAdditions && !existsSync18(fullPath)) {
|
|
8998
9882
|
const content = filePatch.hunks.flatMap((h) => h.lines.filter((l) => l.startsWith("+")).map((l) => l.slice(1))).join("\n");
|
|
8999
|
-
const dir =
|
|
9000
|
-
if (!
|
|
9883
|
+
const dir = join21(fullPath, "..");
|
|
9884
|
+
if (!existsSync18(dir)) {
|
|
9001
9885
|
mkdirSync9(dir, { recursive: true });
|
|
9002
9886
|
}
|
|
9003
9887
|
writeFileSync8(fullPath, content, "utf-8");
|
|
9004
9888
|
return true;
|
|
9005
9889
|
}
|
|
9006
|
-
if (hasOnlyDeletions &&
|
|
9890
|
+
if (hasOnlyDeletions && existsSync18(fullPath)) {
|
|
9007
9891
|
rmSync3(fullPath);
|
|
9008
9892
|
return true;
|
|
9009
9893
|
}
|
|
9010
|
-
if (!
|
|
9894
|
+
if (!existsSync18(fullPath)) {
|
|
9011
9895
|
return false;
|
|
9012
9896
|
}
|
|
9013
|
-
const currentContent =
|
|
9897
|
+
const currentContent = readFileSync16(fullPath, "utf-8");
|
|
9014
9898
|
const currentLines = currentContent.split("\n");
|
|
9015
9899
|
let offset = 0;
|
|
9016
9900
|
for (const hunk of filePatch.hunks) {
|
|
@@ -9294,17 +10178,17 @@ function backtrackMyers(trace, oldLines, newLines, finalD, max) {
|
|
|
9294
10178
|
}
|
|
9295
10179
|
|
|
9296
10180
|
// src/utils/backup.ts
|
|
9297
|
-
import { cpSync, existsSync as
|
|
10181
|
+
import { cpSync, existsSync as existsSync19, mkdirSync as mkdirSync10, mkdtempSync, rmSync as rmSync4 } from "fs";
|
|
9298
10182
|
import { tmpdir as tmpdir2 } from "os";
|
|
9299
|
-
import { join as
|
|
10183
|
+
import { join as join22 } from "path";
|
|
9300
10184
|
function createBackup(packageName, projectRoot, skillDir) {
|
|
9301
|
-
const tempDir = mkdtempSync(
|
|
10185
|
+
const tempDir = mkdtempSync(join22(tmpdir2(), "agentver-backup-"));
|
|
9302
10186
|
const manifest = readManifest(projectRoot);
|
|
9303
10187
|
const manifestEntry = manifest.packages[packageName] ?? null;
|
|
9304
10188
|
const lockfile = readLockfile(projectRoot);
|
|
9305
10189
|
const lockfileEntry = lockfile.packages[packageName] ?? null;
|
|
9306
|
-
if (skillDir &&
|
|
9307
|
-
const backupSkillDir =
|
|
10190
|
+
if (skillDir && existsSync19(skillDir)) {
|
|
10191
|
+
const backupSkillDir = join22(tempDir, "files");
|
|
9308
10192
|
mkdirSync10(backupSkillDir, { recursive: true });
|
|
9309
10193
|
cpSync(skillDir, backupSkillDir, { recursive: true });
|
|
9310
10194
|
}
|
|
@@ -9319,9 +10203,9 @@ function createBackup(packageName, projectRoot, skillDir) {
|
|
|
9319
10203
|
}
|
|
9320
10204
|
function restoreBackup(backup) {
|
|
9321
10205
|
if (backup.skillDir) {
|
|
9322
|
-
const backupSkillDir =
|
|
9323
|
-
if (
|
|
9324
|
-
if (
|
|
10206
|
+
const backupSkillDir = join22(backup.tempDir, "files");
|
|
10207
|
+
if (existsSync19(backupSkillDir)) {
|
|
10208
|
+
if (existsSync19(backup.skillDir)) {
|
|
9325
10209
|
rmSync4(backup.skillDir, { recursive: true, force: true });
|
|
9326
10210
|
}
|
|
9327
10211
|
mkdirSync10(backup.skillDir, { recursive: true });
|
|
@@ -9344,7 +10228,7 @@ function restoreBackup(backup) {
|
|
|
9344
10228
|
writeLockfile(backup.projectRoot, lockfile);
|
|
9345
10229
|
}
|
|
9346
10230
|
function cleanupBackup(backup) {
|
|
9347
|
-
if (
|
|
10231
|
+
if (existsSync19(backup.tempDir)) {
|
|
9348
10232
|
rmSync4(backup.tempDir, { recursive: true, force: true });
|
|
9349
10233
|
}
|
|
9350
10234
|
}
|
|
@@ -9450,13 +10334,13 @@ async function handlePatchUpdate(update, projectRoot, agents, spinner) {
|
|
|
9450
10334
|
const applyResult = applyPatch(projectRoot, patchContent);
|
|
9451
10335
|
if (applyResult.applied) {
|
|
9452
10336
|
removePatch(projectRoot, update.name);
|
|
9453
|
-
spinner.succeed(`${
|
|
10337
|
+
spinner.succeed(`${chalk28.green(update.name)}: updated and local patch reapplied successfully`);
|
|
9454
10338
|
} else {
|
|
9455
10339
|
spinner.warn(
|
|
9456
|
-
`${
|
|
10340
|
+
`${chalk28.yellow(update.name)}: updated but patch had conflicts in: ${applyResult.conflicts.join(", ")}`
|
|
9457
10341
|
);
|
|
9458
|
-
console.log(
|
|
9459
|
-
console.log(
|
|
10342
|
+
console.log(chalk28.dim(` Patch saved at: ${patchPath}`));
|
|
10343
|
+
console.log(chalk28.dim(" Review the patch file and apply remaining changes manually."));
|
|
9460
10344
|
}
|
|
9461
10345
|
return { commitSha: result.commitSha };
|
|
9462
10346
|
}
|
|
@@ -9473,27 +10357,43 @@ function registerUpdateCommand(program2) {
|
|
|
9473
10357
|
return;
|
|
9474
10358
|
}
|
|
9475
10359
|
console.log(
|
|
9476
|
-
|
|
10360
|
+
chalk28.dim(name ? `Package "${name}" is not installed.` : "No packages installed.")
|
|
9477
10361
|
);
|
|
9478
10362
|
return;
|
|
9479
10363
|
}
|
|
10364
|
+
const pinnedNames = [];
|
|
9480
10365
|
const updatable = packageNames.filter((n) => {
|
|
9481
10366
|
const pkg2 = packages[n];
|
|
9482
|
-
|
|
10367
|
+
if (!pkg2) return false;
|
|
10368
|
+
if (pkg2.pinned === true) {
|
|
10369
|
+
pinnedNames.push(n);
|
|
10370
|
+
return false;
|
|
10371
|
+
}
|
|
10372
|
+
return pkg2.source.type === "git" && pkg2.source.uri !== "unknown";
|
|
9483
10373
|
});
|
|
10374
|
+
if (pinnedNames.length > 0 && !jsonMode) {
|
|
10375
|
+
for (const pinnedName of pinnedNames) {
|
|
10376
|
+
console.log(chalk28.dim(`Skipping ${pinnedName} (pinned)`));
|
|
10377
|
+
}
|
|
10378
|
+
}
|
|
9484
10379
|
if (updatable.length === 0) {
|
|
9485
10380
|
if (jsonMode) {
|
|
9486
10381
|
outputSuccess({
|
|
9487
10382
|
updated: [],
|
|
9488
|
-
skipped:
|
|
10383
|
+
skipped: [
|
|
10384
|
+
...pinnedNames.map((n) => ({ name: n, reason: "pinned" })),
|
|
10385
|
+
...packageNames.filter((n) => !pinnedNames.includes(n)).map((n) => ({ name: n, reason: "No known Git source" }))
|
|
10386
|
+
]
|
|
9489
10387
|
});
|
|
9490
10388
|
return;
|
|
9491
10389
|
}
|
|
9492
|
-
|
|
9493
|
-
|
|
9494
|
-
|
|
9495
|
-
|
|
9496
|
-
|
|
10390
|
+
if (pinnedNames.length === 0) {
|
|
10391
|
+
console.log(
|
|
10392
|
+
chalk28.dim(
|
|
10393
|
+
"No packages with known Git sources. Reinstall packages using Git source URLs to enable updates."
|
|
10394
|
+
)
|
|
10395
|
+
);
|
|
10396
|
+
}
|
|
9497
10397
|
return;
|
|
9498
10398
|
}
|
|
9499
10399
|
const spinner = createSpinner("Checking for upstream changes...").start();
|
|
@@ -9533,17 +10433,17 @@ function registerUpdateCommand(program2) {
|
|
|
9533
10433
|
outputSuccess({ updated: [], skipped: [] });
|
|
9534
10434
|
return;
|
|
9535
10435
|
}
|
|
9536
|
-
console.log(
|
|
10436
|
+
console.log(chalk28.green("All packages are up to date."));
|
|
9537
10437
|
return;
|
|
9538
10438
|
}
|
|
9539
10439
|
if (!jsonMode) {
|
|
9540
|
-
console.log(
|
|
10440
|
+
console.log(chalk28.bold(`
|
|
9541
10441
|
Upstream changes available (${updates.length}):
|
|
9542
10442
|
`));
|
|
9543
10443
|
for (const update of updates) {
|
|
9544
|
-
const modifiedIndicator = update.locallyModified ? ` ${
|
|
10444
|
+
const modifiedIndicator = update.locallyModified ? ` ${chalk28.yellow("\u26A0 locally modified")}` : "";
|
|
9545
10445
|
console.log(
|
|
9546
|
-
` ${
|
|
10446
|
+
` ${chalk28.green(update.name)}: ${chalk28.dim(update.currentCommit.slice(0, 7))} \u2192 ${chalk28.cyan(update.latestCommit.slice(0, 7))} ${chalk28.dim(`(${update.ref})`)}${modifiedIndicator}`
|
|
9547
10447
|
);
|
|
9548
10448
|
}
|
|
9549
10449
|
console.log();
|
|
@@ -9556,7 +10456,7 @@ Upstream changes available (${updates.length}):
|
|
|
9556
10456
|
});
|
|
9557
10457
|
return;
|
|
9558
10458
|
}
|
|
9559
|
-
console.log(`${
|
|
10459
|
+
console.log(`${chalk28.yellow("[dry-run]")} No changes made.`);
|
|
9560
10460
|
return;
|
|
9561
10461
|
}
|
|
9562
10462
|
if (!jsonMode) {
|
|
@@ -9567,7 +10467,7 @@ Upstream changes available (${updates.length}):
|
|
|
9567
10467
|
initial: true
|
|
9568
10468
|
});
|
|
9569
10469
|
if (!confirmed) {
|
|
9570
|
-
console.log(
|
|
10470
|
+
console.log(chalk28.dim("Update cancelled."));
|
|
9571
10471
|
return;
|
|
9572
10472
|
}
|
|
9573
10473
|
}
|
|
@@ -9633,7 +10533,7 @@ Upstream changes available (${updates.length}):
|
|
|
9633
10533
|
}
|
|
9634
10534
|
}
|
|
9635
10535
|
const shortName = update.name.split("/").pop();
|
|
9636
|
-
const skillDir = resolveReadPath(projectRoot, shortName, agents) ?? (agentId ?
|
|
10536
|
+
const skillDir = resolveReadPath(projectRoot, shortName, agents) ?? (agentId ? join23(
|
|
9637
10537
|
projectRoot,
|
|
9638
10538
|
getSkillPlacementPath(agentId, shortName, "project") ?? ""
|
|
9639
10539
|
) : null);
|
|
@@ -9675,25 +10575,25 @@ Upstream changes available (${updates.length}):
|
|
|
9675
10575
|
if (jsonMode) {
|
|
9676
10576
|
outputSuccess({
|
|
9677
10577
|
updated: jsonUpdated,
|
|
9678
|
-
skipped: jsonSkipped
|
|
10578
|
+
skipped: [...pinnedNames.map((n) => ({ name: n, reason: "pinned" })), ...jsonSkipped]
|
|
9679
10579
|
});
|
|
9680
10580
|
return;
|
|
9681
10581
|
}
|
|
9682
|
-
console.log(
|
|
10582
|
+
console.log(chalk28.bold("\nUpdate summary:\n"));
|
|
9683
10583
|
for (const result of results) {
|
|
9684
|
-
const patchNote = result.patched ?
|
|
10584
|
+
const patchNote = result.patched ? chalk28.dim(" (patch reapplied)") : "";
|
|
9685
10585
|
console.log(
|
|
9686
|
-
` ${
|
|
10586
|
+
` ${chalk28.green("\u2713")} ${result.name}: ${chalk28.dim(result.from)} \u2192 ${chalk28.cyan(result.to)}${patchNote}`
|
|
9687
10587
|
);
|
|
9688
10588
|
}
|
|
9689
10589
|
for (const skippedName of skipped) {
|
|
9690
|
-
console.log(` ${
|
|
10590
|
+
console.log(` ${chalk28.dim("\u2013")} ${skippedName}: ${chalk28.dim("skipped")}`);
|
|
9691
10591
|
}
|
|
9692
10592
|
for (const failure of failures) {
|
|
9693
|
-
console.log(` ${
|
|
10593
|
+
console.log(` ${chalk28.red("\u2717")} ${failure.name}: ${failure.error}`);
|
|
9694
10594
|
}
|
|
9695
10595
|
if (failures.length > 0) {
|
|
9696
|
-
console.log(
|
|
10596
|
+
console.log(chalk28.dim("\nFailed packages were rolled back to their previous versions."));
|
|
9697
10597
|
}
|
|
9698
10598
|
console.log();
|
|
9699
10599
|
} catch (error) {
|
|
@@ -9712,16 +10612,16 @@ Upstream changes available (${updates.length}):
|
|
|
9712
10612
|
// src/commands/upgrade.ts
|
|
9713
10613
|
import { execFile as execFile2 } from "child_process";
|
|
9714
10614
|
import { createRequire } from "module";
|
|
9715
|
-
import { dirname as
|
|
10615
|
+
import { dirname as dirname6, join as join24 } from "path";
|
|
9716
10616
|
import { fileURLToPath } from "url";
|
|
9717
10617
|
import { promisify as promisify2 } from "util";
|
|
9718
|
-
import
|
|
10618
|
+
import chalk29 from "chalk";
|
|
9719
10619
|
var execFileAsync2 = promisify2(execFile2);
|
|
9720
10620
|
var PACKAGE_NAME = "@agentver/cli";
|
|
9721
10621
|
function getCurrentVersion() {
|
|
9722
|
-
const __dirname2 =
|
|
10622
|
+
const __dirname2 = dirname6(fileURLToPath(import.meta.url));
|
|
9723
10623
|
const require3 = createRequire(import.meta.url);
|
|
9724
|
-
const pkg2 = require3(
|
|
10624
|
+
const pkg2 = require3(join24(__dirname2, "..", "package.json"));
|
|
9725
10625
|
return pkg2.version;
|
|
9726
10626
|
}
|
|
9727
10627
|
async function getLatestVersion() {
|
|
@@ -9777,11 +10677,11 @@ function registerUpgradeCommand(program2) {
|
|
|
9777
10677
|
if (json) {
|
|
9778
10678
|
outputSuccess({ current: currentVersion, latest: latestVersion, upToDate: true });
|
|
9779
10679
|
} else {
|
|
9780
|
-
spinner.succeed(`Already on the latest version ${
|
|
10680
|
+
spinner.succeed(`Already on the latest version ${chalk29.green(`v${currentVersion}`)}`);
|
|
9781
10681
|
}
|
|
9782
10682
|
return;
|
|
9783
10683
|
}
|
|
9784
|
-
spinner.text = `Upgrading ${
|
|
10684
|
+
spinner.text = `Upgrading ${chalk29.dim(`v${currentVersion}`)} \u2192 ${chalk29.green(`v${latestVersion}`)}\u2026`;
|
|
9785
10685
|
const pm = await detectPackageManager();
|
|
9786
10686
|
const args = getInstallArgs(pm);
|
|
9787
10687
|
await execFileAsync2(pm, args, { timeout: 6e4 });
|
|
@@ -9794,7 +10694,7 @@ function registerUpgradeCommand(program2) {
|
|
|
9794
10694
|
outputSuccess(result);
|
|
9795
10695
|
} else {
|
|
9796
10696
|
spinner.succeed(
|
|
9797
|
-
`Upgraded ${
|
|
10697
|
+
`Upgraded ${chalk29.green(`v${currentVersion}`)} \u2192 ${chalk29.green(`v${latestVersion}`)} via ${pm}`
|
|
9798
10698
|
);
|
|
9799
10699
|
}
|
|
9800
10700
|
} catch (error) {
|
|
@@ -9811,7 +10711,7 @@ function registerUpgradeCommand(program2) {
|
|
|
9811
10711
|
}
|
|
9812
10712
|
|
|
9813
10713
|
// src/commands/verify.ts
|
|
9814
|
-
import
|
|
10714
|
+
import chalk30 from "chalk";
|
|
9815
10715
|
var FALLBACK_SOURCE2 = {
|
|
9816
10716
|
host: "github.com",
|
|
9817
10717
|
owner: "local",
|
|
@@ -9878,8 +10778,8 @@ function registerVerifyCommand(program2) {
|
|
|
9878
10778
|
outputError("NO_SKILL", "No skill name provided and no packages installed");
|
|
9879
10779
|
return;
|
|
9880
10780
|
}
|
|
9881
|
-
process.stderr.write(
|
|
9882
|
-
process.stderr.write(
|
|
10781
|
+
process.stderr.write(chalk30.red("No skill name provided and no packages installed.\n"));
|
|
10782
|
+
process.stderr.write(chalk30.dim("Usage: agentver verify @org/skill-name\n"));
|
|
9883
10783
|
process.exitCode = 1;
|
|
9884
10784
|
return;
|
|
9885
10785
|
}
|
|
@@ -9894,10 +10794,10 @@ function registerVerifyCommand(program2) {
|
|
|
9894
10794
|
return;
|
|
9895
10795
|
}
|
|
9896
10796
|
process.stderr.write(
|
|
9897
|
-
|
|
10797
|
+
chalk30.red("Multiple packages installed. Please specify which to verify:\n")
|
|
9898
10798
|
);
|
|
9899
10799
|
for (const pkg2 of packageNames) {
|
|
9900
|
-
process.stderr.write(` ${
|
|
10800
|
+
process.stderr.write(` ${chalk30.cyan(pkg2)}
|
|
9901
10801
|
`);
|
|
9902
10802
|
}
|
|
9903
10803
|
process.exitCode = 1;
|
|
@@ -9914,7 +10814,7 @@ function registerVerifyCommand(program2) {
|
|
|
9914
10814
|
return;
|
|
9915
10815
|
}
|
|
9916
10816
|
process.stderr.write(
|
|
9917
|
-
|
|
10817
|
+
chalk30.red(`Invalid skill name "${skillName}". Expected format: @org/skill-name
|
|
9918
10818
|
`)
|
|
9919
10819
|
);
|
|
9920
10820
|
process.exitCode = 1;
|
|
@@ -9922,7 +10822,7 @@ function registerVerifyCommand(program2) {
|
|
|
9922
10822
|
}
|
|
9923
10823
|
if (!jsonMode) {
|
|
9924
10824
|
process.stderr.write(`
|
|
9925
|
-
${
|
|
10825
|
+
${chalk30.bold(`Verifying @${parsed.org}/${parsed.skill}...`)}
|
|
9926
10826
|
|
|
9927
10827
|
`);
|
|
9928
10828
|
}
|
|
@@ -10064,26 +10964,26 @@ ${chalk25.bold(`Verifying @${parsed.org}/${parsed.skill}...`)}
|
|
|
10064
10964
|
}
|
|
10065
10965
|
process.stderr.write("\n");
|
|
10066
10966
|
if (overallPassed) {
|
|
10067
|
-
process.stderr.write(
|
|
10967
|
+
process.stderr.write(chalk30.green.bold("Skill is verified and safe to use.\n"));
|
|
10068
10968
|
} else {
|
|
10069
|
-
process.stderr.write(
|
|
10969
|
+
process.stderr.write(chalk30.red.bold("Skill verification failed.\n"));
|
|
10070
10970
|
process.exitCode = 1;
|
|
10071
10971
|
}
|
|
10072
10972
|
});
|
|
10073
10973
|
}
|
|
10074
10974
|
|
|
10075
10975
|
// src/commands/version.ts
|
|
10076
|
-
import { existsSync as
|
|
10077
|
-
import { basename as basename6, join as
|
|
10078
|
-
import
|
|
10976
|
+
import { existsSync as existsSync20, readFileSync as readFileSync17 } from "fs";
|
|
10977
|
+
import { basename as basename6, join as join25 } from "path";
|
|
10978
|
+
import chalk31 from "chalk";
|
|
10079
10979
|
import ora8 from "ora";
|
|
10080
10980
|
var SEMVER_REGEX2 = /^\d+\.\d+\.\d+(-[\w.]+)?$/;
|
|
10081
10981
|
function resolveSkillIdentity3() {
|
|
10082
10982
|
const cwd = process.cwd();
|
|
10083
|
-
const skillMdPath =
|
|
10983
|
+
const skillMdPath = join25(cwd, "SKILL.md");
|
|
10084
10984
|
let skillName = null;
|
|
10085
|
-
if (
|
|
10086
|
-
const content =
|
|
10985
|
+
if (existsSync20(skillMdPath)) {
|
|
10986
|
+
const content = readFileSync17(skillMdPath, "utf-8");
|
|
10087
10987
|
const nameMatch = content.match(/^name:\s*(.+)$/m);
|
|
10088
10988
|
skillName = nameMatch?.[1]?.trim() ?? basename6(cwd);
|
|
10089
10989
|
}
|
|
@@ -10111,7 +11011,7 @@ function registerVersionCommand(program2) {
|
|
|
10111
11011
|
version.command("create <semver>").description("Create a version tag for the current skill").option("--notes <text>", "Release notes").option("--json", "Output as JSON").action(async (semver, options) => {
|
|
10112
11012
|
if (!SEMVER_REGEX2.test(semver)) {
|
|
10113
11013
|
process.stderr.write(
|
|
10114
|
-
|
|
11014
|
+
chalk31.red(`Invalid semver "${semver}". Expected format: 1.0.0 or 1.0.0-beta.1
|
|
10115
11015
|
`)
|
|
10116
11016
|
);
|
|
10117
11017
|
process.exit(1);
|
|
@@ -10119,7 +11019,7 @@ function registerVersionCommand(program2) {
|
|
|
10119
11019
|
const identity = resolveSkillIdentity3();
|
|
10120
11020
|
if (!identity) {
|
|
10121
11021
|
process.stderr.write(
|
|
10122
|
-
|
|
11022
|
+
chalk31.red("Could not determine skill identity. Run this from a skill directory.\n")
|
|
10123
11023
|
);
|
|
10124
11024
|
process.exit(1);
|
|
10125
11025
|
}
|
|
@@ -10127,7 +11027,7 @@ function registerVersionCommand(program2) {
|
|
|
10127
11027
|
const lockEntry = lockfile.packages[identity.name];
|
|
10128
11028
|
const commitSha = lockEntry?.source.type === "git" ? lockEntry.source.commit : void 0;
|
|
10129
11029
|
if (!commitSha || commitSha === "unknown") {
|
|
10130
|
-
process.stderr.write(
|
|
11030
|
+
process.stderr.write(chalk31.red("No commit SHA found in lockfile. Save changes first.\n"));
|
|
10131
11031
|
process.exit(1);
|
|
10132
11032
|
}
|
|
10133
11033
|
const spinner = ora8(`Creating version ${semver}...`).start();
|
|
@@ -10159,7 +11059,7 @@ function registerVersionCommand(program2) {
|
|
|
10159
11059
|
);
|
|
10160
11060
|
} else {
|
|
10161
11061
|
spinner.succeed(
|
|
10162
|
-
`Version ${
|
|
11062
|
+
`Version ${chalk31.cyan(semver)} created ${chalk31.dim(`(${result.commitSha.slice(0, 7)})`)}`
|
|
10163
11063
|
);
|
|
10164
11064
|
}
|
|
10165
11065
|
} catch (error) {
|
|
@@ -10173,7 +11073,7 @@ function registerVersionCommand(program2) {
|
|
|
10173
11073
|
const identity = resolveSkillIdentity3();
|
|
10174
11074
|
if (!identity) {
|
|
10175
11075
|
process.stderr.write(
|
|
10176
|
-
|
|
11076
|
+
chalk31.red("Could not determine skill identity. Run this from a skill directory.\n")
|
|
10177
11077
|
);
|
|
10178
11078
|
process.exit(1);
|
|
10179
11079
|
}
|
|
@@ -10188,16 +11088,16 @@ function registerVersionCommand(program2) {
|
|
|
10188
11088
|
return;
|
|
10189
11089
|
}
|
|
10190
11090
|
if (versions.length === 0) {
|
|
10191
|
-
process.stdout.write(
|
|
11091
|
+
process.stdout.write(chalk31.dim("No versions found.\n"));
|
|
10192
11092
|
return;
|
|
10193
11093
|
}
|
|
10194
|
-
process.stdout.write(
|
|
11094
|
+
process.stdout.write(chalk31.bold(`
|
|
10195
11095
|
Versions for @${identity.org}/${identity.name}:
|
|
10196
11096
|
|
|
10197
11097
|
`));
|
|
10198
11098
|
for (const v of versions) {
|
|
10199
11099
|
process.stdout.write(
|
|
10200
|
-
` ${
|
|
11100
|
+
` ${chalk31.cyan(v.name)} ${chalk31.dim(`(${v.commitSha.slice(0, 7)})`)} ${chalk31.dim(v.message)}
|
|
10201
11101
|
`
|
|
10202
11102
|
);
|
|
10203
11103
|
}
|
|
@@ -10212,7 +11112,7 @@ Versions for @${identity.org}/${identity.name}:
|
|
|
10212
11112
|
}
|
|
10213
11113
|
|
|
10214
11114
|
// src/commands/whoami.ts
|
|
10215
|
-
import
|
|
11115
|
+
import chalk32 from "chalk";
|
|
10216
11116
|
function registerWhoamiCommand(program2) {
|
|
10217
11117
|
program2.command("whoami").description("Show authentication state").action(async () => {
|
|
10218
11118
|
const credentials = await getCredentials();
|
|
@@ -10221,15 +11121,15 @@ function registerWhoamiCommand(program2) {
|
|
|
10221
11121
|
outputSuccess({ authenticated: false });
|
|
10222
11122
|
return;
|
|
10223
11123
|
}
|
|
10224
|
-
console.log(
|
|
11124
|
+
console.log(chalk32.dim("Not authenticated. Run `agentver login` to sign in."));
|
|
10225
11125
|
return;
|
|
10226
11126
|
}
|
|
10227
11127
|
if (!isJSONMode()) {
|
|
10228
11128
|
if (credentials.apiKey) {
|
|
10229
11129
|
const prefix = credentials.apiKey.slice(0, 8);
|
|
10230
|
-
console.log(`Authenticated via API key: ${
|
|
11130
|
+
console.log(`Authenticated via API key: ${chalk32.green(`${prefix}...`)}`);
|
|
10231
11131
|
} else {
|
|
10232
|
-
console.log(
|
|
11132
|
+
console.log(chalk32.green("Authenticated via OAuth."));
|
|
10233
11133
|
}
|
|
10234
11134
|
}
|
|
10235
11135
|
const platformUrl = getPlatformUrl();
|
|
@@ -10238,11 +11138,11 @@ function registerWhoamiCommand(program2) {
|
|
|
10238
11138
|
outputSuccess({ authenticated: true });
|
|
10239
11139
|
return;
|
|
10240
11140
|
}
|
|
10241
|
-
console.log(
|
|
11141
|
+
console.log(chalk32.dim("Platform: not connected (run `agentver login <url>` to connect)"));
|
|
10242
11142
|
return;
|
|
10243
11143
|
}
|
|
10244
11144
|
if (!isJSONMode()) {
|
|
10245
|
-
console.log(`Platform: ${
|
|
11145
|
+
console.log(`Platform: ${chalk32.cyan(platformUrl)}`);
|
|
10246
11146
|
}
|
|
10247
11147
|
const me = await platformFetchSilent("/me");
|
|
10248
11148
|
if (isJSONMode()) {
|
|
@@ -10269,38 +11169,44 @@ function registerWhoamiCommand(program2) {
|
|
|
10269
11169
|
}
|
|
10270
11170
|
|
|
10271
11171
|
// bin/agentver.ts
|
|
10272
|
-
var __dirname =
|
|
11172
|
+
var __dirname = dirname7(fileURLToPath2(import.meta.url));
|
|
10273
11173
|
var require2 = createRequire2(import.meta.url);
|
|
10274
|
-
var pkg = require2(
|
|
11174
|
+
var pkg = require2(join26(__dirname, "..", "package.json"));
|
|
10275
11175
|
updateNotifier({ pkg }).notify({
|
|
10276
11176
|
message: `Update available: {currentVersion} \u2192 {latestVersion}
|
|
10277
|
-
Run ${
|
|
11177
|
+
Run ${chalk33.cyan("agentver upgrade")} to update`
|
|
10278
11178
|
});
|
|
10279
11179
|
var program = new Command();
|
|
10280
11180
|
program.name("agentver").description("Agent skill registry \u2014 store, version, and distribute AI agent skills").version(pkg.version).option("--json", "Output results as structured JSON");
|
|
10281
11181
|
registerAdoptCommand(program);
|
|
10282
|
-
registerInstallCommand(program);
|
|
10283
11182
|
registerAuditCommand(program);
|
|
11183
|
+
registerCompletionCommand(program);
|
|
11184
|
+
registerConfigCommand(program);
|
|
11185
|
+
registerDiffCommand(program);
|
|
11186
|
+
registerDoctorCommand(program);
|
|
11187
|
+
registerDraftCommand(program);
|
|
11188
|
+
registerInfoCommand(program);
|
|
11189
|
+
registerInitCommand(program);
|
|
11190
|
+
registerInstallCommand(program);
|
|
11191
|
+
registerListCommand(program);
|
|
11192
|
+
registerLogCommand(program);
|
|
10284
11193
|
registerLoginCommand(program);
|
|
10285
11194
|
registerLogoutCommand(program);
|
|
10286
|
-
|
|
10287
|
-
|
|
10288
|
-
registerUpdateCommand(program);
|
|
11195
|
+
registerPinCommand(program);
|
|
11196
|
+
registerPublishCommand(program);
|
|
10289
11197
|
registerRemoveCommand(program);
|
|
10290
|
-
|
|
11198
|
+
registerSaveCommand(program);
|
|
10291
11199
|
registerScanCommand(program);
|
|
10292
|
-
|
|
11200
|
+
registerSearchCommand(program);
|
|
10293
11201
|
registerStatusCommand(program);
|
|
10294
|
-
registerDiffCommand(program);
|
|
10295
|
-
registerSyncCommand(program);
|
|
10296
11202
|
registerSuggestCommand(program);
|
|
10297
11203
|
registerSuggestionsCommand(program);
|
|
10298
|
-
|
|
10299
|
-
|
|
10300
|
-
|
|
11204
|
+
registerSyncCommand(program);
|
|
11205
|
+
registerUnpinCommand(program);
|
|
11206
|
+
registerUpdateCommand(program);
|
|
10301
11207
|
registerUpgradeCommand(program);
|
|
10302
11208
|
registerVerifyCommand(program);
|
|
10303
11209
|
registerVersionCommand(program);
|
|
10304
|
-
|
|
11210
|
+
registerWhoamiCommand(program);
|
|
10305
11211
|
program.parse();
|
|
10306
11212
|
//# sourceMappingURL=agentver.js.map
|