@agentver/cli 0.1.3 → 0.2.0
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 +1552 -650
- 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
|
|
|
@@ -7369,9 +8121,9 @@ function registerLoginCommand(program2) {
|
|
|
7369
8121
|
});
|
|
7370
8122
|
return;
|
|
7371
8123
|
}
|
|
7372
|
-
console.log(
|
|
8124
|
+
console.log(chalk16.green("Saved API key. You are now authenticated."));
|
|
7373
8125
|
if (target) {
|
|
7374
|
-
console.log(
|
|
8126
|
+
console.log(chalk16.dim(`Connected to ${target}`));
|
|
7375
8127
|
}
|
|
7376
8128
|
return;
|
|
7377
8129
|
}
|
|
@@ -7411,7 +8163,7 @@ function registerLoginCommand(program2) {
|
|
|
7411
8163
|
const redirectUri = `http://localhost:${port}/callback`;
|
|
7412
8164
|
const authUrl = `${baseUrl}/auth/cli?code_challenge=${encodeURIComponent(codeChallenge)}&state=${encodeURIComponent(state)}&redirect_uri=${encodeURIComponent(redirectUri)}`;
|
|
7413
8165
|
spinner.text = "Opening browser for authentication...";
|
|
7414
|
-
console.log(
|
|
8166
|
+
console.log(chalk16.dim(`
|
|
7415
8167
|
If the browser doesn't open, visit:
|
|
7416
8168
|
${authUrl}
|
|
7417
8169
|
`));
|
|
@@ -7431,7 +8183,7 @@ function registerLoginCommand(program2) {
|
|
|
7431
8183
|
spinner.succeed("Authenticated successfully.");
|
|
7432
8184
|
const connectedUrl = url ?? getPlatformUrl();
|
|
7433
8185
|
if (connectedUrl) {
|
|
7434
|
-
console.log(
|
|
8186
|
+
console.log(chalk16.dim(`Connected to ${connectedUrl}`));
|
|
7435
8187
|
}
|
|
7436
8188
|
} catch (error) {
|
|
7437
8189
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -7444,7 +8196,7 @@ function registerLoginCommand(program2) {
|
|
|
7444
8196
|
}
|
|
7445
8197
|
|
|
7446
8198
|
// src/commands/logout.ts
|
|
7447
|
-
import
|
|
8199
|
+
import chalk17 from "chalk";
|
|
7448
8200
|
function registerLogoutCommand(program2) {
|
|
7449
8201
|
program2.command("logout").description("Log out from the Agentver registry").action(async () => {
|
|
7450
8202
|
if (!await isAuthenticated()) {
|
|
@@ -7452,7 +8204,7 @@ function registerLogoutCommand(program2) {
|
|
|
7452
8204
|
outputSuccess({ cleared: true });
|
|
7453
8205
|
return;
|
|
7454
8206
|
}
|
|
7455
|
-
console.log(
|
|
8207
|
+
console.log(chalk17.dim("You are not currently logged in."));
|
|
7456
8208
|
return;
|
|
7457
8209
|
}
|
|
7458
8210
|
const platformUrl = getPlatformUrl();
|
|
@@ -7467,19 +8219,72 @@ function registerLogoutCommand(program2) {
|
|
|
7467
8219
|
return;
|
|
7468
8220
|
}
|
|
7469
8221
|
if (platformUrl) {
|
|
7470
|
-
console.log(`${
|
|
8222
|
+
console.log(`${chalk17.green("Logged out successfully.")} Disconnected from ${platformUrl}`);
|
|
7471
8223
|
} else {
|
|
7472
8224
|
console.log(
|
|
7473
|
-
`${
|
|
8225
|
+
`${chalk17.green("Logged out successfully.")} Run \`agentver login\` to sign in again.`
|
|
7474
8226
|
);
|
|
7475
8227
|
}
|
|
7476
8228
|
});
|
|
7477
8229
|
}
|
|
7478
8230
|
|
|
8231
|
+
// src/commands/pin.ts
|
|
8232
|
+
import chalk18 from "chalk";
|
|
8233
|
+
function registerPinCommand(program2) {
|
|
8234
|
+
program2.command("pin <name>").description("Pin a package to skip it during updates").action((name) => {
|
|
8235
|
+
const jsonMode = isJSONMode();
|
|
8236
|
+
const projectRoot = process.cwd();
|
|
8237
|
+
const manifest = readManifest(projectRoot);
|
|
8238
|
+
const pkg2 = manifest.packages[name];
|
|
8239
|
+
if (!pkg2) {
|
|
8240
|
+
if (jsonMode) {
|
|
8241
|
+
outputError("NOT_FOUND", `Package "${name}" is not installed.`);
|
|
8242
|
+
} else {
|
|
8243
|
+
console.error(chalk18.red(`Package "${name}" is not installed.`));
|
|
8244
|
+
}
|
|
8245
|
+
process.exit(1);
|
|
8246
|
+
}
|
|
8247
|
+
pkg2.pinned = true;
|
|
8248
|
+
writeManifest(projectRoot, manifest);
|
|
8249
|
+
if (jsonMode) {
|
|
8250
|
+
outputSuccess({ name, pinned: true });
|
|
8251
|
+
return;
|
|
8252
|
+
}
|
|
8253
|
+
console.log(
|
|
8254
|
+
chalk18.green(`Pinned ${name}`) + chalk18.dim(" \u2014 this package will be skipped during updates")
|
|
8255
|
+
);
|
|
8256
|
+
});
|
|
8257
|
+
}
|
|
8258
|
+
function registerUnpinCommand(program2) {
|
|
8259
|
+
program2.command("unpin <name>").description("Unpin a package so it is included in updates").action((name) => {
|
|
8260
|
+
const jsonMode = isJSONMode();
|
|
8261
|
+
const projectRoot = process.cwd();
|
|
8262
|
+
const manifest = readManifest(projectRoot);
|
|
8263
|
+
const pkg2 = manifest.packages[name];
|
|
8264
|
+
if (!pkg2) {
|
|
8265
|
+
if (jsonMode) {
|
|
8266
|
+
outputError("NOT_FOUND", `Package "${name}" is not installed.`);
|
|
8267
|
+
} else {
|
|
8268
|
+
console.error(chalk18.red(`Package "${name}" is not installed.`));
|
|
8269
|
+
}
|
|
8270
|
+
process.exit(1);
|
|
8271
|
+
}
|
|
8272
|
+
delete pkg2.pinned;
|
|
8273
|
+
writeManifest(projectRoot, manifest);
|
|
8274
|
+
if (jsonMode) {
|
|
8275
|
+
outputSuccess({ name, pinned: false });
|
|
8276
|
+
return;
|
|
8277
|
+
}
|
|
8278
|
+
console.log(
|
|
8279
|
+
chalk18.green(`Unpinned ${name}`) + chalk18.dim(" \u2014 this package will be included in updates")
|
|
8280
|
+
);
|
|
8281
|
+
});
|
|
8282
|
+
}
|
|
8283
|
+
|
|
7479
8284
|
// src/commands/publish.ts
|
|
7480
|
-
import { existsSync as
|
|
7481
|
-
import { basename as basename4, join as
|
|
7482
|
-
import
|
|
8285
|
+
import { existsSync as existsSync14, readFileSync as readFileSync13 } from "fs";
|
|
8286
|
+
import { basename as basename4, join as join17, resolve as resolve2 } from "path";
|
|
8287
|
+
import chalk19 from "chalk";
|
|
7483
8288
|
import ora4 from "ora";
|
|
7484
8289
|
var SEMVER_REGEX = /^\d+\.\d+\.\d+(-[\w.]+)?$/;
|
|
7485
8290
|
function parseFrontmatter2(content) {
|
|
@@ -7506,9 +8311,9 @@ function parseFrontmatter2(content) {
|
|
|
7506
8311
|
};
|
|
7507
8312
|
}
|
|
7508
8313
|
function detectNamespace(skillDir) {
|
|
7509
|
-
const skillMdPath =
|
|
7510
|
-
if (!
|
|
7511
|
-
const content =
|
|
8314
|
+
const skillMdPath = join17(skillDir, "SKILL.md");
|
|
8315
|
+
if (!existsSync14(skillMdPath)) return null;
|
|
8316
|
+
const content = readFileSync13(skillMdPath, "utf-8");
|
|
7512
8317
|
const fm = parseFrontmatter2(content);
|
|
7513
8318
|
if (!fm) return null;
|
|
7514
8319
|
const parts = skillDir.split("/");
|
|
@@ -7522,16 +8327,16 @@ function detectNamespace(skillDir) {
|
|
|
7522
8327
|
function registerPublishCommand(program2) {
|
|
7523
8328
|
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
8329
|
const skillDir = pathArg ? resolve2(process.cwd(), pathArg) : process.cwd();
|
|
7525
|
-
if (!
|
|
8330
|
+
if (!existsSync14(join17(skillDir, "SKILL.md"))) {
|
|
7526
8331
|
process.stderr.write(
|
|
7527
|
-
|
|
8332
|
+
chalk19.red(`No SKILL.md found in ${skillDir}. Cannot publish without a skill manifest.
|
|
7528
8333
|
`)
|
|
7529
8334
|
);
|
|
7530
8335
|
process.exit(1);
|
|
7531
8336
|
}
|
|
7532
8337
|
const spinner = ora4("Reading skill metadata...").start();
|
|
7533
8338
|
try {
|
|
7534
|
-
const skillMdContent =
|
|
8339
|
+
const skillMdContent = readFileSync13(join17(skillDir, "SKILL.md"), "utf-8");
|
|
7535
8340
|
const frontmatter = parseFrontmatter2(skillMdContent);
|
|
7536
8341
|
if (!frontmatter) {
|
|
7537
8342
|
spinner.fail(
|
|
@@ -7573,7 +8378,7 @@ function registerPublishCommand(program2) {
|
|
|
7573
8378
|
spinner.fail("Security audit failed. Fix the issues before publishing.");
|
|
7574
8379
|
for (const finding of scanResult.findings) {
|
|
7575
8380
|
process.stderr.write(
|
|
7576
|
-
` ${
|
|
8381
|
+
` ${chalk19.red("BLOCK")} ${finding.file}:${String(finding.line ?? "?")} \u2014 ${finding.message}
|
|
7577
8382
|
`
|
|
7578
8383
|
);
|
|
7579
8384
|
}
|
|
@@ -7583,7 +8388,7 @@ function registerPublishCommand(program2) {
|
|
|
7583
8388
|
spinner.warn("Security audit warnings found:");
|
|
7584
8389
|
for (const finding of scanResult.findings) {
|
|
7585
8390
|
process.stderr.write(
|
|
7586
|
-
` ${
|
|
8391
|
+
` ${chalk19.yellow("WARN")} ${finding.file}:${String(finding.line ?? "?")} \u2014 ${finding.message}
|
|
7587
8392
|
`
|
|
7588
8393
|
);
|
|
7589
8394
|
}
|
|
@@ -7612,13 +8417,13 @@ function registerPublishCommand(program2) {
|
|
|
7612
8417
|
);
|
|
7613
8418
|
} else {
|
|
7614
8419
|
process.stdout.write(
|
|
7615
|
-
|
|
8420
|
+
chalk19.yellow("[dry-run]") + ` Would publish ${chalk19.green(frontmatter.name)}@${chalk19.cyan(version)}
|
|
7616
8421
|
`
|
|
7617
8422
|
);
|
|
7618
|
-
process.stdout.write(
|
|
8423
|
+
process.stdout.write(chalk19.dim(` Namespace: @${namespace.org}/${namespace.name}
|
|
7619
8424
|
`));
|
|
7620
8425
|
process.stdout.write(
|
|
7621
|
-
|
|
8426
|
+
chalk19.dim(
|
|
7622
8427
|
` Files (${filesToPublish.length}): ${filesToPublish.map((f) => f.path).join(", ")}
|
|
7623
8428
|
`
|
|
7624
8429
|
)
|
|
@@ -7651,7 +8456,7 @@ function registerPublishCommand(program2) {
|
|
|
7651
8456
|
);
|
|
7652
8457
|
} else {
|
|
7653
8458
|
spinner.succeed(
|
|
7654
|
-
`Published ${
|
|
8459
|
+
`Published ${chalk19.green(frontmatter.name)}@${chalk19.cyan(result.version)} ${chalk19.dim(`(${result.commitSha.slice(0, 7)})`)}`
|
|
7655
8460
|
);
|
|
7656
8461
|
}
|
|
7657
8462
|
} catch (error) {
|
|
@@ -7662,11 +8467,11 @@ function registerPublishCommand(program2) {
|
|
|
7662
8467
|
}
|
|
7663
8468
|
|
|
7664
8469
|
// src/commands/remove.ts
|
|
7665
|
-
import { existsSync as
|
|
7666
|
-
import { join as
|
|
7667
|
-
import
|
|
8470
|
+
import { existsSync as existsSync15, lstatSync as lstatSync3, rmSync as rmSync2 } from "fs";
|
|
8471
|
+
import { join as join18 } from "path";
|
|
8472
|
+
import chalk20 from "chalk";
|
|
7668
8473
|
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) => {
|
|
8474
|
+
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
8475
|
const jsonMode = isJSONMode();
|
|
7671
8476
|
const projectRoot = process.cwd();
|
|
7672
8477
|
const manifest = readManifest(projectRoot);
|
|
@@ -7676,7 +8481,7 @@ function registerRemoveCommand(program2) {
|
|
|
7676
8481
|
outputError("NOT_FOUND", `Package "${name}" is not installed.`);
|
|
7677
8482
|
process.exit(1);
|
|
7678
8483
|
}
|
|
7679
|
-
console.error(
|
|
8484
|
+
console.error(chalk20.red(`Package "${name}" is not installed.`));
|
|
7680
8485
|
process.exit(1);
|
|
7681
8486
|
}
|
|
7682
8487
|
const shortName = name.split("/").pop();
|
|
@@ -7688,15 +8493,15 @@ function registerRemoveCommand(program2) {
|
|
|
7688
8493
|
for (const agentId of pkg2.agents) {
|
|
7689
8494
|
const placementPath = getSkillPlacementPath(agentId, shortName, "project");
|
|
7690
8495
|
if (placementPath) {
|
|
7691
|
-
removedPaths.push(
|
|
8496
|
+
removedPaths.push(join18(projectRoot, placementPath));
|
|
7692
8497
|
}
|
|
7693
8498
|
}
|
|
7694
8499
|
} else {
|
|
7695
8500
|
for (const agentId of pkg2.agents) {
|
|
7696
8501
|
const placementPath = getSkillPlacementPath(agentId, shortName, "project");
|
|
7697
8502
|
if (!placementPath) continue;
|
|
7698
|
-
const fullPath =
|
|
7699
|
-
if (
|
|
8503
|
+
const fullPath = join18(projectRoot, placementPath);
|
|
8504
|
+
if (existsSync15(fullPath)) {
|
|
7700
8505
|
removedPaths.push(fullPath);
|
|
7701
8506
|
}
|
|
7702
8507
|
}
|
|
@@ -7710,28 +8515,28 @@ function registerRemoveCommand(program2) {
|
|
|
7710
8515
|
});
|
|
7711
8516
|
return;
|
|
7712
8517
|
}
|
|
7713
|
-
console.log(`${
|
|
8518
|
+
console.log(`${chalk20.yellow("[dry-run]")} Would remove ${chalk20.green(name)}`);
|
|
7714
8519
|
if (hasCanonical) {
|
|
7715
8520
|
const canonicalPath = getCanonicalSkillPath(projectRoot, shortName, "project");
|
|
7716
|
-
console.log(
|
|
7717
|
-
console.log(
|
|
7718
|
-
console.log(
|
|
8521
|
+
console.log(chalk20.dim(" Canonical path to remove:"));
|
|
8522
|
+
console.log(chalk20.dim(` ${canonicalPath}`));
|
|
8523
|
+
console.log(chalk20.dim(" Agent symlinks to remove:"));
|
|
7719
8524
|
for (const agentId of pkg2.agents) {
|
|
7720
8525
|
const placementPath = getSkillPlacementPath(agentId, shortName, "project");
|
|
7721
8526
|
if (placementPath) {
|
|
7722
|
-
console.log(
|
|
8527
|
+
console.log(chalk20.dim(` ${join18(projectRoot, placementPath)}`));
|
|
7723
8528
|
}
|
|
7724
8529
|
}
|
|
7725
8530
|
} else {
|
|
7726
|
-
const pathsToRemove = removedPaths.filter((p) =>
|
|
8531
|
+
const pathsToRemove = removedPaths.filter((p) => existsSync15(p));
|
|
7727
8532
|
if (pathsToRemove.length > 0) {
|
|
7728
|
-
console.log(
|
|
8533
|
+
console.log(chalk20.dim(" Paths to remove:"));
|
|
7729
8534
|
for (const p of pathsToRemove) {
|
|
7730
|
-
console.log(
|
|
8535
|
+
console.log(chalk20.dim(` ${p}`));
|
|
7731
8536
|
}
|
|
7732
8537
|
}
|
|
7733
8538
|
}
|
|
7734
|
-
console.log(
|
|
8539
|
+
console.log(chalk20.dim(" Would update manifest and lockfile"));
|
|
7735
8540
|
return;
|
|
7736
8541
|
}
|
|
7737
8542
|
const spinner = createSpinner(`Removing ${name}...`).start();
|
|
@@ -7742,8 +8547,8 @@ function registerRemoveCommand(program2) {
|
|
|
7742
8547
|
for (const agentId of pkg2.agents) {
|
|
7743
8548
|
const placementPath = getSkillPlacementPath(agentId, shortName, "project");
|
|
7744
8549
|
if (!placementPath) continue;
|
|
7745
|
-
const fullPath =
|
|
7746
|
-
if (
|
|
8550
|
+
const fullPath = join18(projectRoot, placementPath);
|
|
8551
|
+
if (existsSync15(fullPath) || isSymlinkPath(fullPath)) {
|
|
7747
8552
|
rmSync2(fullPath, { recursive: true, force: true });
|
|
7748
8553
|
}
|
|
7749
8554
|
}
|
|
@@ -7761,35 +8566,35 @@ function registerRemoveCommand(program2) {
|
|
|
7761
8566
|
paths: removedPaths
|
|
7762
8567
|
});
|
|
7763
8568
|
} else {
|
|
7764
|
-
spinner.succeed(`Removed ${
|
|
8569
|
+
spinner.succeed(`Removed ${chalk20.green(name)}`);
|
|
7765
8570
|
}
|
|
7766
8571
|
});
|
|
7767
8572
|
}
|
|
7768
8573
|
function isSymlinkPath(filePath) {
|
|
7769
8574
|
try {
|
|
7770
|
-
return
|
|
8575
|
+
return lstatSync3(filePath).isSymbolicLink();
|
|
7771
8576
|
} catch {
|
|
7772
8577
|
return false;
|
|
7773
8578
|
}
|
|
7774
8579
|
}
|
|
7775
8580
|
|
|
7776
8581
|
// src/commands/save.ts
|
|
7777
|
-
import { existsSync as
|
|
7778
|
-
import { basename as basename5, join as
|
|
7779
|
-
import
|
|
8582
|
+
import { existsSync as existsSync16, readFileSync as readFileSync14 } from "fs";
|
|
8583
|
+
import { basename as basename5, join as join19, resolve as resolve3 } from "path";
|
|
8584
|
+
import chalk21 from "chalk";
|
|
7780
8585
|
import ora5 from "ora";
|
|
7781
8586
|
function detectSkillName(skillDir) {
|
|
7782
|
-
const skillMdPath =
|
|
7783
|
-
if (!
|
|
8587
|
+
const skillMdPath = join19(skillDir, "SKILL.md");
|
|
8588
|
+
if (!existsSync16(skillMdPath)) {
|
|
7784
8589
|
return null;
|
|
7785
8590
|
}
|
|
7786
|
-
const content =
|
|
8591
|
+
const content = readFileSync14(skillMdPath, "utf-8");
|
|
7787
8592
|
const nameMatch = content.match(/^name:\s*(.+)$/m);
|
|
7788
8593
|
return nameMatch?.[1]?.trim() ?? basename5(skillDir);
|
|
7789
8594
|
}
|
|
7790
8595
|
function resolveSkillContext(options) {
|
|
7791
8596
|
const skillDir = options.path ? resolve3(process.cwd(), options.path) : process.cwd();
|
|
7792
|
-
if (!
|
|
8597
|
+
if (!existsSync16(skillDir)) {
|
|
7793
8598
|
return null;
|
|
7794
8599
|
}
|
|
7795
8600
|
const skillName = detectSkillName(skillDir);
|
|
@@ -7815,7 +8620,7 @@ function registerSaveCommand(program2) {
|
|
|
7815
8620
|
if (!context) {
|
|
7816
8621
|
const target = options.path ?? process.cwd();
|
|
7817
8622
|
process.stderr.write(
|
|
7818
|
-
|
|
8623
|
+
chalk21.red(`No SKILL.md found in ${target}. Run this from a skill directory.
|
|
7819
8624
|
`)
|
|
7820
8625
|
);
|
|
7821
8626
|
process.exit(1);
|
|
@@ -7825,7 +8630,7 @@ function registerSaveCommand(program2) {
|
|
|
7825
8630
|
const namespace = findNamespace(projectRoot, skillName);
|
|
7826
8631
|
if (!namespace) {
|
|
7827
8632
|
process.stderr.write(
|
|
7828
|
-
|
|
8633
|
+
chalk21.red(
|
|
7829
8634
|
`Skill "${skillName}" not found in manifest. Install it first or check the directory.
|
|
7830
8635
|
`
|
|
7831
8636
|
)
|
|
@@ -7861,13 +8666,13 @@ function registerSaveCommand(program2) {
|
|
|
7861
8666
|
);
|
|
7862
8667
|
} else {
|
|
7863
8668
|
process.stdout.write(
|
|
7864
|
-
|
|
8669
|
+
chalk21.yellow("[dry-run]") + ` Would save ${chalk21.green(skillName)} to @${namespace.org}/${namespace.name}
|
|
7865
8670
|
`
|
|
7866
8671
|
);
|
|
7867
|
-
process.stdout.write(
|
|
8672
|
+
process.stdout.write(chalk21.dim(` Message: ${commitMessage}
|
|
7868
8673
|
`));
|
|
7869
8674
|
process.stdout.write(
|
|
7870
|
-
|
|
8675
|
+
chalk21.dim(` Files: ${filesToSave.map((f) => f.path).join(", ")}
|
|
7871
8676
|
`)
|
|
7872
8677
|
);
|
|
7873
8678
|
}
|
|
@@ -7904,7 +8709,7 @@ function registerSaveCommand(program2) {
|
|
|
7904
8709
|
);
|
|
7905
8710
|
} else {
|
|
7906
8711
|
spinner.succeed(
|
|
7907
|
-
`Saved ${
|
|
8712
|
+
`Saved ${chalk21.green(skillName)} ${chalk21.dim(`(${result.commitSha.slice(0, 7)})`)}`
|
|
7908
8713
|
);
|
|
7909
8714
|
}
|
|
7910
8715
|
} catch (error) {
|
|
@@ -7915,19 +8720,19 @@ function registerSaveCommand(program2) {
|
|
|
7915
8720
|
}
|
|
7916
8721
|
|
|
7917
8722
|
// src/commands/scan.ts
|
|
7918
|
-
import { readFileSync as
|
|
7919
|
-
import { homedir as
|
|
7920
|
-
import
|
|
8723
|
+
import { readFileSync as readFileSync15 } from "fs";
|
|
8724
|
+
import { homedir as homedir8 } from "os";
|
|
8725
|
+
import chalk22 from "chalk";
|
|
7921
8726
|
function registerScanCommand(program2) {
|
|
7922
8727
|
program2.command("scan [path]").description("Scan directory for agent configs and skills").action(async (path) => {
|
|
7923
8728
|
const jsonMode = isJSONMode();
|
|
7924
8729
|
const targetPath = path ?? process.cwd();
|
|
7925
8730
|
const projectAgents = detectInstalledAgents(targetPath);
|
|
7926
|
-
const globalAgents = detectGlobalAgents(
|
|
8731
|
+
const globalAgents = detectGlobalAgents(homedir8());
|
|
7927
8732
|
const seenIds = new Set(projectAgents.map((a) => a.id));
|
|
7928
8733
|
const agents = [...projectAgents, ...globalAgents.filter((a) => !seenIds.has(a.id))];
|
|
7929
8734
|
const projectFiles = scanForSkillFiles(targetPath);
|
|
7930
|
-
const globalFiles = scanGlobalSkillFiles(
|
|
8735
|
+
const globalFiles = scanGlobalSkillFiles(homedir8());
|
|
7931
8736
|
const seenPaths = new Set(projectFiles.map((f) => f.path));
|
|
7932
8737
|
const files = [...projectFiles, ...globalFiles.filter((f) => !seenPaths.has(f.path))];
|
|
7933
8738
|
if (jsonMode) {
|
|
@@ -7946,58 +8751,58 @@ function registerScanCommand(program2) {
|
|
|
7946
8751
|
outputSuccess(result);
|
|
7947
8752
|
return;
|
|
7948
8753
|
}
|
|
7949
|
-
console.log(
|
|
8754
|
+
console.log(chalk22.bold("\nDetected agents:\n"));
|
|
7950
8755
|
if (agents.length === 0) {
|
|
7951
|
-
console.log(
|
|
8756
|
+
console.log(chalk22.dim(" No agents detected."));
|
|
7952
8757
|
} else {
|
|
7953
8758
|
for (const agent of agents) {
|
|
7954
|
-
console.log(` ${
|
|
8759
|
+
console.log(` ${chalk22.green(agent.name)} ${chalk22.dim(agent.configPath)}`);
|
|
7955
8760
|
}
|
|
7956
8761
|
}
|
|
7957
|
-
console.log(
|
|
8762
|
+
console.log(chalk22.bold("\nDiscovered files:\n"));
|
|
7958
8763
|
if (files.length === 0) {
|
|
7959
|
-
console.log(
|
|
8764
|
+
console.log(chalk22.dim(" No skill or config files found."));
|
|
7960
8765
|
} else {
|
|
7961
8766
|
for (const file of files) {
|
|
7962
|
-
const typeLabel =
|
|
7963
|
-
const agentLabel =
|
|
7964
|
-
console.log(` ${typeLabel} ${agentLabel} ${file.name} ${
|
|
8767
|
+
const typeLabel = chalk22.dim(`[${file.detectedType}]`);
|
|
8768
|
+
const agentLabel = chalk22.cyan(`(${file.agentId})`);
|
|
8769
|
+
console.log(` ${typeLabel} ${agentLabel} ${file.name} ${chalk22.dim(file.path)}`);
|
|
7965
8770
|
}
|
|
7966
8771
|
}
|
|
7967
8772
|
const skillFiles = files.filter((f) => f.detectedType === "SKILL");
|
|
7968
8773
|
if (skillFiles.length > 0) {
|
|
7969
|
-
console.log(
|
|
8774
|
+
console.log(chalk22.bold("\nSkill spec validation:\n"));
|
|
7970
8775
|
for (const file of skillFiles) {
|
|
7971
8776
|
let content;
|
|
7972
8777
|
try {
|
|
7973
|
-
content =
|
|
8778
|
+
content = readFileSync15(file.path, "utf-8");
|
|
7974
8779
|
} catch {
|
|
7975
|
-
console.log(` ${
|
|
8780
|
+
console.log(` ${chalk22.red("\u2717")} ${file.name} ${chalk22.dim("Could not read file")}`);
|
|
7976
8781
|
continue;
|
|
7977
8782
|
}
|
|
7978
8783
|
const result = validateSkillMd(content);
|
|
7979
8784
|
if (result.valid && result.specCompliant) {
|
|
7980
8785
|
console.log(
|
|
7981
|
-
` ${
|
|
8786
|
+
` ${chalk22.green("\u2713")} ${file.name} ${chalk22.green("Agent Skills spec compliant")}`
|
|
7982
8787
|
);
|
|
7983
8788
|
} else if (result.valid && !result.specCompliant) {
|
|
7984
8789
|
console.log(
|
|
7985
|
-
` ${
|
|
8790
|
+
` ${chalk22.yellow("\u2713")} ${file.name} ${chalk22.yellow("Valid (Agentver extended)")}`
|
|
7986
8791
|
);
|
|
7987
8792
|
} else {
|
|
7988
|
-
console.log(` ${
|
|
8793
|
+
console.log(` ${chalk22.red("\u2717")} ${file.name} ${chalk22.red("Invalid")}`);
|
|
7989
8794
|
for (const error of result.errors) {
|
|
7990
|
-
console.log(` ${
|
|
8795
|
+
console.log(` ${chalk22.red(`\u2514 ${error}`)}`);
|
|
7991
8796
|
}
|
|
7992
8797
|
}
|
|
7993
8798
|
if (result.warnings.length > 0) {
|
|
7994
8799
|
for (const warning of result.warnings) {
|
|
7995
|
-
console.log(` ${
|
|
8800
|
+
console.log(` ${chalk22.yellow(`\u26A0 ${warning}`)}`);
|
|
7996
8801
|
}
|
|
7997
8802
|
}
|
|
7998
8803
|
if (result.agentverExtensions.length > 0) {
|
|
7999
8804
|
console.log(
|
|
8000
|
-
` ${
|
|
8805
|
+
` ${chalk22.dim(`Agentver extensions: ${result.agentverExtensions.join(", ")}`)}`
|
|
8001
8806
|
);
|
|
8002
8807
|
}
|
|
8003
8808
|
}
|
|
@@ -8005,7 +8810,7 @@ function registerScanCommand(program2) {
|
|
|
8005
8810
|
const manifest = readManifest(targetPath);
|
|
8006
8811
|
const manifestEntries = Object.entries(manifest.packages);
|
|
8007
8812
|
if (manifestEntries.length > 0) {
|
|
8008
|
-
console.log(
|
|
8813
|
+
console.log(chalk22.bold(`
|
|
8009
8814
|
Installed skills (${manifestEntries.length}):
|
|
8010
8815
|
`));
|
|
8011
8816
|
for (const [name, pkg2] of manifestEntries) {
|
|
@@ -8016,12 +8821,12 @@ Installed skills (${manifestEntries.length}):
|
|
|
8016
8821
|
const ref = `@${source.ref}`;
|
|
8017
8822
|
const commit = `(${source.commit.slice(0, 7)})`;
|
|
8018
8823
|
console.log(
|
|
8019
|
-
` ${
|
|
8824
|
+
` ${chalk22.green(name.padEnd(18))} ${chalk22.dim(sourcePath.padEnd(40))} ${chalk22.cyan(ref.padEnd(10))} ${chalk22.dim(commit)} ${chalk22.dim(agentList)}`
|
|
8020
8825
|
);
|
|
8021
8826
|
} else {
|
|
8022
8827
|
const sourceLabel = `${source.hostname} (well-known)`;
|
|
8023
8828
|
console.log(
|
|
8024
|
-
` ${
|
|
8829
|
+
` ${chalk22.green(name.padEnd(18))} ${chalk22.dim(sourceLabel.padEnd(40))} ${chalk22.dim("[well-known]").padEnd(10)} ${chalk22.dim(agentList)}`
|
|
8025
8830
|
);
|
|
8026
8831
|
}
|
|
8027
8832
|
}
|
|
@@ -8031,7 +8836,7 @@ Installed skills (${manifestEntries.length}):
|
|
|
8031
8836
|
}
|
|
8032
8837
|
|
|
8033
8838
|
// src/commands/search.ts
|
|
8034
|
-
import
|
|
8839
|
+
import chalk23 from "chalk";
|
|
8035
8840
|
import ora6 from "ora";
|
|
8036
8841
|
|
|
8037
8842
|
// src/registry/skills-sh.ts
|
|
@@ -8109,60 +8914,60 @@ function formatInstallCount(count) {
|
|
|
8109
8914
|
}
|
|
8110
8915
|
function renderPlatformResults(results, total) {
|
|
8111
8916
|
if (results.length === 0) return;
|
|
8112
|
-
process.stdout.write(
|
|
8917
|
+
process.stdout.write(chalk23.bold(`
|
|
8113
8918
|
Platform results (${total}):
|
|
8114
8919
|
|
|
8115
8920
|
`));
|
|
8116
8921
|
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(` ${
|
|
8922
|
+
const desc = result.description ? chalk23.dim(` \u2014 ${result.description}`) : "";
|
|
8923
|
+
const stars = result.starCount > 0 ? chalk23.yellow(` \u2605 ${result.starCount}`) : "";
|
|
8924
|
+
const installs = result.installCount > 0 ? chalk23.cyan(` \u2193 ${formatInstallCount(result.installCount)}`) : "";
|
|
8925
|
+
const cats = result.categories.length > 0 ? chalk23.dim(` [${result.categories.map((c) => c.name).join(", ")}]`) : "";
|
|
8926
|
+
process.stdout.write(` ${chalk23.green(result.slug)}${stars}${installs}${cats}${desc}
|
|
8122
8927
|
`);
|
|
8123
8928
|
}
|
|
8124
8929
|
process.stdout.write("\n");
|
|
8125
8930
|
}
|
|
8126
8931
|
function renderCommunityResults(results) {
|
|
8127
8932
|
if (results.length === 0) return;
|
|
8128
|
-
process.stdout.write(
|
|
8933
|
+
process.stdout.write(chalk23.bold(`
|
|
8129
8934
|
Skills from skills.sh:
|
|
8130
8935
|
|
|
8131
8936
|
`));
|
|
8132
8937
|
for (const result of results) {
|
|
8133
|
-
const nameCol =
|
|
8134
|
-
const sourceCol =
|
|
8135
|
-
const installCol =
|
|
8938
|
+
const nameCol = chalk23.green(result.name);
|
|
8939
|
+
const sourceCol = chalk23.dim(`(${result.source})`);
|
|
8940
|
+
const installCol = chalk23.cyan(`\u2193 ${formatInstallCount(result.installCount)}`);
|
|
8136
8941
|
process.stdout.write(` ${nameCol} ${sourceCol} ${installCol}
|
|
8137
8942
|
`);
|
|
8138
8943
|
if (result.description) {
|
|
8139
|
-
process.stdout.write(` ${
|
|
8944
|
+
process.stdout.write(` ${chalk23.dim(result.description)}
|
|
8140
8945
|
`);
|
|
8141
8946
|
}
|
|
8142
8947
|
process.stdout.write("\n");
|
|
8143
8948
|
}
|
|
8144
8949
|
process.stdout.write(
|
|
8145
|
-
|
|
8950
|
+
chalk23.dim(" Install with: ") + chalk23.white("agentver install github.com/{source}/{name}") + "\n\n"
|
|
8146
8951
|
);
|
|
8147
8952
|
}
|
|
8148
8953
|
function renderWellKnownResults(hostname3, skills) {
|
|
8149
8954
|
if (skills.length === 0) return;
|
|
8150
|
-
process.stdout.write(
|
|
8955
|
+
process.stdout.write(chalk23.bold(`
|
|
8151
8956
|
Skills from ${hostname3}:
|
|
8152
8957
|
|
|
8153
8958
|
`));
|
|
8154
8959
|
for (const skill of skills) {
|
|
8155
|
-
process.stdout.write(` ${
|
|
8960
|
+
process.stdout.write(` ${chalk23.green(skill.name)} ${chalk23.dim(`\u2014 ${skill.description}`)}
|
|
8156
8961
|
`);
|
|
8157
8962
|
process.stdout.write(
|
|
8158
|
-
` ${
|
|
8963
|
+
` ${chalk23.dim("Install:")} ${chalk23.white(`agentver install ${hostname3}/${skill.name}`)}
|
|
8159
8964
|
`
|
|
8160
8965
|
);
|
|
8161
8966
|
process.stdout.write("\n");
|
|
8162
8967
|
}
|
|
8163
8968
|
}
|
|
8164
8969
|
function renderNoResults(query) {
|
|
8165
|
-
process.stdout.write(
|
|
8970
|
+
process.stdout.write(chalk23.dim(`No results for "${query}"
|
|
8166
8971
|
`));
|
|
8167
8972
|
}
|
|
8168
8973
|
function registerSearchCommand(program2) {
|
|
@@ -8177,7 +8982,7 @@ function registerSearchCommand(program2) {
|
|
|
8177
8982
|
if (requestedSource) {
|
|
8178
8983
|
if (!["platform", "community", "well-known", "all"].includes(requestedSource)) {
|
|
8179
8984
|
process.stderr.write(
|
|
8180
|
-
|
|
8985
|
+
chalk23.red(
|
|
8181
8986
|
`Invalid source "${requestedSource}". Use: platform, community, well-known, or all
|
|
8182
8987
|
`
|
|
8183
8988
|
)
|
|
@@ -8187,7 +8992,7 @@ function registerSearchCommand(program2) {
|
|
|
8187
8992
|
source = requestedSource;
|
|
8188
8993
|
if (source === "platform" && !connected) {
|
|
8189
8994
|
process.stderr.write(
|
|
8190
|
-
|
|
8995
|
+
chalk23.red("Not connected to a platform. Run `agentver login <url>` to connect.\n")
|
|
8191
8996
|
);
|
|
8192
8997
|
process.exit(1);
|
|
8193
8998
|
}
|
|
@@ -8255,7 +9060,7 @@ function registerSearchCommand(program2) {
|
|
|
8255
9060
|
if (communityResults.length > 0) {
|
|
8256
9061
|
const example = communityResults[0];
|
|
8257
9062
|
process.stdout.write(
|
|
8258
|
-
|
|
9063
|
+
chalk23.dim(" Example: ") + chalk23.white(`agentver install ${toGitInstallSource(example)}`) + "\n"
|
|
8259
9064
|
);
|
|
8260
9065
|
}
|
|
8261
9066
|
} catch (error) {
|
|
@@ -8267,13 +9072,13 @@ function registerSearchCommand(program2) {
|
|
|
8267
9072
|
}
|
|
8268
9073
|
|
|
8269
9074
|
// src/commands/status.ts
|
|
8270
|
-
import
|
|
9075
|
+
import chalk24 from "chalk";
|
|
8271
9076
|
var STATUS_SYMBOLS = {
|
|
8272
|
-
"up-to-date":
|
|
8273
|
-
modified:
|
|
8274
|
-
upstream:
|
|
8275
|
-
both:
|
|
8276
|
-
unknown:
|
|
9077
|
+
"up-to-date": chalk24.green("\u2713"),
|
|
9078
|
+
modified: chalk24.yellow("M"),
|
|
9079
|
+
upstream: chalk24.cyan("U"),
|
|
9080
|
+
both: chalk24.red("MU"),
|
|
9081
|
+
unknown: chalk24.dim("?")
|
|
8277
9082
|
};
|
|
8278
9083
|
function parseManifestUri2(uri) {
|
|
8279
9084
|
const parts = uri.split("/");
|
|
@@ -8295,7 +9100,7 @@ async function readLocalFiles2(projectRoot, packageName, agents) {
|
|
|
8295
9100
|
return [];
|
|
8296
9101
|
}
|
|
8297
9102
|
async function checkPackageStatus(projectRoot, name, manifestEntry, lockfileIntegrity, offline) {
|
|
8298
|
-
const { source, agents } = manifestEntry;
|
|
9103
|
+
const { source, agents, pinned } = manifestEntry;
|
|
8299
9104
|
if (source.type === "well-known") {
|
|
8300
9105
|
let locallyModified2 = false;
|
|
8301
9106
|
try {
|
|
@@ -8313,7 +9118,8 @@ async function checkPackageStatus(projectRoot, name, manifestEntry, lockfileInte
|
|
|
8313
9118
|
sourceUri: source.hostname,
|
|
8314
9119
|
ref: "well-known",
|
|
8315
9120
|
commit: "",
|
|
8316
|
-
agents
|
|
9121
|
+
agents,
|
|
9122
|
+
pinned: pinned || void 0
|
|
8317
9123
|
};
|
|
8318
9124
|
}
|
|
8319
9125
|
if (source.uri === "unknown") {
|
|
@@ -8323,7 +9129,8 @@ async function checkPackageStatus(projectRoot, name, manifestEntry, lockfileInte
|
|
|
8323
9129
|
sourceUri: source.uri,
|
|
8324
9130
|
ref: source.ref,
|
|
8325
9131
|
commit: source.commit,
|
|
8326
|
-
agents
|
|
9132
|
+
agents,
|
|
9133
|
+
pinned: pinned || void 0
|
|
8327
9134
|
};
|
|
8328
9135
|
}
|
|
8329
9136
|
let locallyModified = false;
|
|
@@ -8367,18 +9174,20 @@ async function checkPackageStatus(projectRoot, name, manifestEntry, lockfileInte
|
|
|
8367
9174
|
ref: source.ref,
|
|
8368
9175
|
commit: source.commit,
|
|
8369
9176
|
upstreamCommit: upstreamChanged ? upstreamCommit : void 0,
|
|
8370
|
-
agents
|
|
9177
|
+
agents,
|
|
9178
|
+
pinned: pinned || void 0
|
|
8371
9179
|
};
|
|
8372
9180
|
}
|
|
8373
9181
|
function formatStatusLine(status) {
|
|
8374
9182
|
const symbol = STATUS_SYMBOLS[status.category];
|
|
8375
9183
|
const padding = status.category === "both" ? "" : " ";
|
|
8376
9184
|
if (status.category === "unknown") {
|
|
8377
|
-
return ` ${symbol} ${
|
|
9185
|
+
return ` ${symbol} ${chalk24.white(status.name)} ${chalk24.dim("unknown source")}`;
|
|
8378
9186
|
}
|
|
8379
9187
|
const shortCommit = status.commit.slice(0, 7);
|
|
8380
|
-
const upstream = status.upstreamCommit ? ` ${
|
|
8381
|
-
|
|
9188
|
+
const upstream = status.upstreamCommit ? ` ${chalk24.dim("\u2192")} ${chalk24.cyan(`upstream: ${status.upstreamCommit.slice(0, 7)}`)}` : "";
|
|
9189
|
+
const pinned = status.pinned ? chalk24.yellow(" [pinned]") : "";
|
|
9190
|
+
return ` ${symbol}${padding} ${chalk24.white(status.name)}${pinned} ${chalk24.dim(status.sourceUri)} ${chalk24.cyan(`@${status.ref}`)} ${chalk24.dim(`(${shortCommit})`)}${upstream}`;
|
|
8382
9191
|
}
|
|
8383
9192
|
function buildStatusOutput(statuses) {
|
|
8384
9193
|
return {
|
|
@@ -8396,7 +9205,8 @@ function toStatusResult(output) {
|
|
|
8396
9205
|
name: p.name,
|
|
8397
9206
|
status: p.category,
|
|
8398
9207
|
modified: p.category === "modified" || p.category === "both",
|
|
8399
|
-
upstream: p.category === "upstream" || p.category === "both"
|
|
9208
|
+
upstream: p.category === "upstream" || p.category === "both",
|
|
9209
|
+
pinned: p.pinned || void 0
|
|
8400
9210
|
})),
|
|
8401
9211
|
summary: {
|
|
8402
9212
|
total: output.total,
|
|
@@ -8418,7 +9228,7 @@ function registerStatusCommand(program2) {
|
|
|
8418
9228
|
if (jsonMode) {
|
|
8419
9229
|
outputSuccess(toStatusResult(buildStatusOutput([])));
|
|
8420
9230
|
} else {
|
|
8421
|
-
console.log(
|
|
9231
|
+
console.log(chalk24.dim("No packages installed."));
|
|
8422
9232
|
}
|
|
8423
9233
|
return;
|
|
8424
9234
|
}
|
|
@@ -8441,7 +9251,7 @@ function registerStatusCommand(program2) {
|
|
|
8441
9251
|
outputSuccess(toStatusResult(buildStatusOutput(statuses)));
|
|
8442
9252
|
return;
|
|
8443
9253
|
}
|
|
8444
|
-
console.log(
|
|
9254
|
+
console.log(chalk24.bold(`
|
|
8445
9255
|
Installed skills (${statuses.length}):
|
|
8446
9256
|
`));
|
|
8447
9257
|
for (const status of statuses) {
|
|
@@ -8452,16 +9262,16 @@ Installed skills (${statuses.length}):
|
|
|
8452
9262
|
}
|
|
8453
9263
|
|
|
8454
9264
|
// src/commands/suggest.ts
|
|
8455
|
-
import { existsSync as
|
|
8456
|
-
import { join as
|
|
8457
|
-
import
|
|
9265
|
+
import { existsSync as existsSync17 } from "fs";
|
|
9266
|
+
import { join as join20 } from "path";
|
|
9267
|
+
import chalk25 from "chalk";
|
|
8458
9268
|
var HTTP_TIMEOUT_MS2 = 15e3;
|
|
8459
9269
|
async function readLocalFiles3(projectRoot, packageName, agents) {
|
|
8460
9270
|
for (const agentId of agents) {
|
|
8461
9271
|
const placementPath = getSkillPlacementPath(agentId, packageName, "project");
|
|
8462
9272
|
if (!placementPath) continue;
|
|
8463
|
-
const fullPath =
|
|
8464
|
-
if (!
|
|
9273
|
+
const fullPath = join20(projectRoot, placementPath);
|
|
9274
|
+
if (!existsSync17(fullPath)) continue;
|
|
8465
9275
|
const files = await readFilesFromDirectory(fullPath);
|
|
8466
9276
|
return files.map((f) => ({ path: f.path, content: f.content }));
|
|
8467
9277
|
}
|
|
@@ -8509,141 +9319,211 @@ async function postToPlatform(path, body) {
|
|
|
8509
9319
|
throw error;
|
|
8510
9320
|
}
|
|
8511
9321
|
}
|
|
9322
|
+
function buildEndpoint(manifestEntry, packageName) {
|
|
9323
|
+
if (manifestEntry.source.type !== "git") return "";
|
|
9324
|
+
const orgSlug = manifestEntry.source.uri.split("/")[1] ?? "";
|
|
9325
|
+
return `/skills/@${orgSlug}/${packageName}/suggestions`;
|
|
9326
|
+
}
|
|
9327
|
+
async function submitSuggestion(projectRoot, packageName, manifestEntry, title, description) {
|
|
9328
|
+
const localFiles = await readLocalFiles3(projectRoot, packageName, manifestEntry.agents);
|
|
9329
|
+
if (localFiles.length === 0) {
|
|
9330
|
+
throw new Error(`No local files found for "${packageName}".`);
|
|
9331
|
+
}
|
|
9332
|
+
const endpoint = buildEndpoint(manifestEntry, packageName);
|
|
9333
|
+
const requestBody = {
|
|
9334
|
+
title,
|
|
9335
|
+
description,
|
|
9336
|
+
files: localFiles
|
|
9337
|
+
};
|
|
9338
|
+
const result = await postToPlatform(endpoint, requestBody);
|
|
9339
|
+
return { localFiles, result };
|
|
9340
|
+
}
|
|
8512
9341
|
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
|
-
|
|
9342
|
+
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(
|
|
9343
|
+
async (title, options) => {
|
|
9344
|
+
const json = isJSONMode();
|
|
9345
|
+
const platformUrl = getPlatformUrl();
|
|
9346
|
+
const creds = await getCredentials();
|
|
9347
|
+
if (!options.dryRun && (!platformUrl || !creds?.token && !creds?.apiKey)) {
|
|
9348
|
+
if (json) {
|
|
9349
|
+
outputError(
|
|
9350
|
+
"AUTH_REQUIRED",
|
|
9351
|
+
"Not connected to a platform. Run `agentver login <url>` first."
|
|
9352
|
+
);
|
|
9353
|
+
process.exit(1);
|
|
9354
|
+
}
|
|
9355
|
+
console.error(chalk25.red("Not connected to a platform. Run `agentver login <url>` first."));
|
|
8523
9356
|
process.exit(1);
|
|
8524
9357
|
}
|
|
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);
|
|
9358
|
+
const projectRoot = process.cwd();
|
|
9359
|
+
const manifest = readManifest(projectRoot);
|
|
9360
|
+
const lockfile = readLockfile(projectRoot);
|
|
9361
|
+
const modifiedPackages = [];
|
|
9362
|
+
for (const [name, manifestEntry] of Object.entries(manifest.packages)) {
|
|
9363
|
+
const lockfileEntry = lockfile.packages[name];
|
|
9364
|
+
if (!lockfileEntry) continue;
|
|
9365
|
+
const { agents } = manifestEntry;
|
|
9366
|
+
const localFiles = await readLocalFiles3(projectRoot, name, agents);
|
|
9367
|
+
if (localFiles.length === 0) continue;
|
|
9368
|
+
const currentIntegrity = computeSha256FromFiles(localFiles);
|
|
9369
|
+
if (currentIntegrity !== lockfileEntry.integrity) {
|
|
9370
|
+
modifiedPackages.push(name);
|
|
9371
|
+
}
|
|
8547
9372
|
}
|
|
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."));
|
|
9373
|
+
if (modifiedPackages.length === 0) {
|
|
9374
|
+
if (json) {
|
|
9375
|
+
outputError("NO_CHANGES", "No modified packages detected.");
|
|
9376
|
+
process.exit(1);
|
|
9377
|
+
}
|
|
9378
|
+
console.log(chalk25.dim("No modified packages detected."));
|
|
9379
|
+
return;
|
|
8567
9380
|
}
|
|
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}".`);
|
|
9381
|
+
const targets = options.name ? modifiedPackages.filter((n) => n === options.name) : modifiedPackages;
|
|
9382
|
+
if (targets.length === 0 && options.name) {
|
|
9383
|
+
const message = `Package "${options.name}" is not in the modified list. Modified: ${modifiedPackages.join(", ")}`;
|
|
8575
9384
|
if (json) {
|
|
8576
|
-
outputError("NOT_FOUND",
|
|
9385
|
+
outputError("NOT_FOUND", message);
|
|
9386
|
+
process.exit(1);
|
|
9387
|
+
}
|
|
9388
|
+
console.error(chalk25.red(message));
|
|
9389
|
+
process.exit(1);
|
|
9390
|
+
}
|
|
9391
|
+
const unsupportedTargets = targets.filter(
|
|
9392
|
+
(name) => manifest.packages[name]?.source.type === "well-known"
|
|
9393
|
+
);
|
|
9394
|
+
if (unsupportedTargets.length > 0) {
|
|
9395
|
+
for (const name of unsupportedTargets) {
|
|
9396
|
+
const source = manifest.packages[name].source;
|
|
9397
|
+
if (json) {
|
|
9398
|
+
outputError(
|
|
9399
|
+
"UNSUPPORTED_SOURCE",
|
|
9400
|
+
`Package "${name}" was installed from a well-known source. Suggestions are not supported.`
|
|
9401
|
+
);
|
|
9402
|
+
} else {
|
|
9403
|
+
console.error(
|
|
9404
|
+
chalk25.red(
|
|
9405
|
+
`Package "${name}" was installed from a well-known source (${source.type === "well-known" ? source.hostname : "unknown"}).`
|
|
9406
|
+
)
|
|
9407
|
+
);
|
|
9408
|
+
console.error(chalk25.dim("Suggestions are not supported for well-known sources."));
|
|
9409
|
+
}
|
|
8577
9410
|
}
|
|
9411
|
+
}
|
|
9412
|
+
const validTargets = targets.filter((n) => !unsupportedTargets.includes(n));
|
|
9413
|
+
if (validTargets.length === 0) {
|
|
8578
9414
|
process.exit(1);
|
|
8579
9415
|
}
|
|
8580
|
-
const orgSlug = source.uri.split("/")[1] ?? "";
|
|
8581
|
-
const pkgName = targetName;
|
|
8582
9416
|
if (options.dryRun) {
|
|
8583
|
-
const
|
|
8584
|
-
|
|
8585
|
-
|
|
8586
|
-
|
|
8587
|
-
|
|
8588
|
-
|
|
8589
|
-
|
|
8590
|
-
|
|
8591
|
-
|
|
8592
|
-
|
|
8593
|
-
|
|
9417
|
+
const dryRunResults = [];
|
|
9418
|
+
for (const targetName of validTargets) {
|
|
9419
|
+
const manifestEntry = manifest.packages[targetName];
|
|
9420
|
+
const localFiles = await readLocalFiles3(projectRoot, targetName, manifestEntry.agents);
|
|
9421
|
+
const endpoint = `/api/v1${buildEndpoint(manifestEntry, targetName)}`;
|
|
9422
|
+
dryRunResults.push({
|
|
9423
|
+
package: targetName,
|
|
9424
|
+
title,
|
|
9425
|
+
description: options.description,
|
|
9426
|
+
files: localFiles.map((f) => ({
|
|
9427
|
+
path: f.path,
|
|
9428
|
+
contentLength: f.content.length
|
|
9429
|
+
})),
|
|
9430
|
+
endpoint
|
|
9431
|
+
});
|
|
9432
|
+
}
|
|
8594
9433
|
if (json) {
|
|
8595
|
-
outputSuccess(
|
|
9434
|
+
outputSuccess(dryRunResults);
|
|
8596
9435
|
} else {
|
|
8597
|
-
console.log(
|
|
8598
|
-
|
|
8599
|
-
|
|
8600
|
-
|
|
8601
|
-
|
|
8602
|
-
|
|
8603
|
-
|
|
8604
|
-
|
|
8605
|
-
|
|
9436
|
+
console.log(chalk25.bold("\nDry run \u2014 suggestion preview:\n"));
|
|
9437
|
+
for (const entry of dryRunResults) {
|
|
9438
|
+
console.log(` ${chalk25.dim("Package:")} ${entry.package}`);
|
|
9439
|
+
console.log(` ${chalk25.dim("Title:")} ${entry.title}`);
|
|
9440
|
+
if (entry.description) {
|
|
9441
|
+
console.log(` ${chalk25.dim("Desc:")} ${entry.description}`);
|
|
9442
|
+
}
|
|
9443
|
+
console.log(` ${chalk25.dim("Files:")}`);
|
|
9444
|
+
for (const f of entry.files) {
|
|
9445
|
+
console.log(` ${chalk25.cyan(f.path)} (${f.contentLength} bytes)`);
|
|
9446
|
+
}
|
|
9447
|
+
console.log(` ${chalk25.dim("Endpoint:")} ${entry.endpoint}`);
|
|
9448
|
+
console.log();
|
|
8606
9449
|
}
|
|
8607
|
-
console.log(
|
|
8608
|
-
|
|
9450
|
+
console.log(
|
|
9451
|
+
chalk25.dim(
|
|
9452
|
+
`${dryRunResults.length} package${dryRunResults.length === 1 ? "" : "s"} would get suggestions.`
|
|
9453
|
+
)
|
|
9454
|
+
);
|
|
8609
9455
|
}
|
|
8610
9456
|
return;
|
|
8611
9457
|
}
|
|
8612
|
-
|
|
8613
|
-
const
|
|
8614
|
-
|
|
8615
|
-
|
|
8616
|
-
|
|
8617
|
-
|
|
8618
|
-
|
|
8619
|
-
|
|
8620
|
-
|
|
8621
|
-
|
|
8622
|
-
|
|
8623
|
-
|
|
8624
|
-
|
|
8625
|
-
|
|
8626
|
-
|
|
8627
|
-
|
|
8628
|
-
|
|
8629
|
-
|
|
8630
|
-
|
|
8631
|
-
|
|
8632
|
-
|
|
9458
|
+
const outcomes = [];
|
|
9459
|
+
for (const targetName of validTargets) {
|
|
9460
|
+
const manifestEntry = manifest.packages[targetName];
|
|
9461
|
+
const spinner = createSpinner(`Creating suggestion for ${targetName}...`).start();
|
|
9462
|
+
try {
|
|
9463
|
+
const { result } = await submitSuggestion(
|
|
9464
|
+
projectRoot,
|
|
9465
|
+
targetName,
|
|
9466
|
+
manifestEntry,
|
|
9467
|
+
title,
|
|
9468
|
+
options.description
|
|
9469
|
+
);
|
|
9470
|
+
const proposeResult = {
|
|
9471
|
+
proposalId: result.id,
|
|
9472
|
+
title: result.title ?? title,
|
|
9473
|
+
url: result.url ?? ""
|
|
9474
|
+
};
|
|
9475
|
+
outcomes.push({ package: targetName, success: true, result: proposeResult });
|
|
9476
|
+
if (!json) {
|
|
9477
|
+
spinner.succeed(
|
|
9478
|
+
`Created suggestion for ${chalk25.bold(targetName)}: ${chalk25.bold(proposeResult.title)}`
|
|
9479
|
+
);
|
|
9480
|
+
if (result.url) {
|
|
9481
|
+
console.log(chalk25.dim(` ${result.url}`));
|
|
9482
|
+
}
|
|
9483
|
+
} else {
|
|
9484
|
+
spinner.stop();
|
|
9485
|
+
}
|
|
9486
|
+
} catch (error) {
|
|
9487
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
9488
|
+
outcomes.push({ package: targetName, success: false, error: message });
|
|
9489
|
+
if (!json) {
|
|
9490
|
+
spinner.fail(`Failed to create suggestion for ${chalk25.bold(targetName)}: ${message}`);
|
|
9491
|
+
} else {
|
|
9492
|
+
spinner.stop();
|
|
9493
|
+
}
|
|
9494
|
+
}
|
|
8633
9495
|
}
|
|
8634
|
-
|
|
8635
|
-
const
|
|
8636
|
-
spinner.fail(`Failed to create suggestion: ${message}`);
|
|
9496
|
+
const succeeded = outcomes.filter((o) => o.success);
|
|
9497
|
+
const failed = outcomes.filter((o) => !o.success);
|
|
8637
9498
|
if (json) {
|
|
8638
|
-
|
|
9499
|
+
if (validTargets.length === 1) {
|
|
9500
|
+
const outcome = outcomes[0];
|
|
9501
|
+
if (outcome.success) {
|
|
9502
|
+
outputSuccess(outcome.result);
|
|
9503
|
+
} else {
|
|
9504
|
+
outputError("SUGGEST_FAILED", outcome.error);
|
|
9505
|
+
process.exit(1);
|
|
9506
|
+
}
|
|
9507
|
+
} else {
|
|
9508
|
+
outputSuccess(outcomes);
|
|
9509
|
+
}
|
|
9510
|
+
} else if (validTargets.length > 1) {
|
|
9511
|
+
console.log();
|
|
9512
|
+
console.log(
|
|
9513
|
+
chalk25.bold(
|
|
9514
|
+
`Created ${succeeded.length} suggestion${succeeded.length === 1 ? "" : "s"}` + (failed.length > 0 ? ` (${failed.length} failed)` : "")
|
|
9515
|
+
)
|
|
9516
|
+
);
|
|
9517
|
+
}
|
|
9518
|
+
if (failed.length > 0 && succeeded.length === 0) {
|
|
9519
|
+
process.exit(1);
|
|
8639
9520
|
}
|
|
8640
|
-
process.exit(1);
|
|
8641
9521
|
}
|
|
8642
|
-
|
|
9522
|
+
);
|
|
8643
9523
|
}
|
|
8644
9524
|
|
|
8645
9525
|
// src/commands/suggestions.ts
|
|
8646
|
-
import
|
|
9526
|
+
import chalk26 from "chalk";
|
|
8647
9527
|
var HTTP_TIMEOUT_MS3 = 15e3;
|
|
8648
9528
|
async function getFromPlatform(path) {
|
|
8649
9529
|
const platformUrl = getPlatformUrl();
|
|
@@ -8698,21 +9578,21 @@ function formatDate2(isoDate) {
|
|
|
8698
9578
|
}
|
|
8699
9579
|
}
|
|
8700
9580
|
var STATUS_COLOURS = {
|
|
8701
|
-
OPEN:
|
|
8702
|
-
IN_REVIEW:
|
|
8703
|
-
APPROVED:
|
|
8704
|
-
MERGED:
|
|
8705
|
-
REJECTED:
|
|
8706
|
-
CLOSED:
|
|
9581
|
+
OPEN: chalk26.green,
|
|
9582
|
+
IN_REVIEW: chalk26.yellow,
|
|
9583
|
+
APPROVED: chalk26.blue,
|
|
9584
|
+
MERGED: chalk26.magenta,
|
|
9585
|
+
REJECTED: chalk26.red,
|
|
9586
|
+
CLOSED: chalk26.dim
|
|
8707
9587
|
};
|
|
8708
9588
|
function formatSuggestionRow(suggestion, idWidth, titleWidth, slugWidth, authorWidth) {
|
|
8709
|
-
const id =
|
|
9589
|
+
const id = chalk26.dim(`#${suggestion.id}`.padEnd(idWidth + 1));
|
|
8710
9590
|
const title = suggestion.title.padEnd(titleWidth);
|
|
8711
|
-
const slug =
|
|
8712
|
-
const statusFn = STATUS_COLOURS[suggestion.status] ??
|
|
9591
|
+
const slug = chalk26.cyan(suggestion.packageSlug.padEnd(slugWidth));
|
|
9592
|
+
const statusFn = STATUS_COLOURS[suggestion.status] ?? chalk26.dim;
|
|
8713
9593
|
const status = statusFn(suggestion.status.padEnd(11));
|
|
8714
|
-
const author =
|
|
8715
|
-
const date =
|
|
9594
|
+
const author = chalk26.dim(suggestion.author.padEnd(authorWidth));
|
|
9595
|
+
const date = chalk26.dim(formatDate2(suggestion.createdAt));
|
|
8716
9596
|
return ` ${id} ${title} ${slug} ${status} ${author} ${date}`;
|
|
8717
9597
|
}
|
|
8718
9598
|
function registerSuggestionsCommand(program2) {
|
|
@@ -8728,7 +9608,7 @@ function registerSuggestionsCommand(program2) {
|
|
|
8728
9608
|
);
|
|
8729
9609
|
process.exit(1);
|
|
8730
9610
|
}
|
|
8731
|
-
console.error(
|
|
9611
|
+
console.error(chalk26.red("Not connected to a platform. Run `agentver login <url>` first."));
|
|
8732
9612
|
process.exit(1);
|
|
8733
9613
|
}
|
|
8734
9614
|
const spinner = createSpinner("Fetching suggestions...").start();
|
|
@@ -8760,7 +9640,7 @@ function registerSuggestionsCommand(program2) {
|
|
|
8760
9640
|
}
|
|
8761
9641
|
if (suggestions.length === 0) {
|
|
8762
9642
|
const filterLabel = statusFilter === "ALL" ? "" : ` ${options.status}`;
|
|
8763
|
-
console.log(
|
|
9643
|
+
console.log(chalk26.dim(`No${filterLabel} suggestions found.`));
|
|
8764
9644
|
return;
|
|
8765
9645
|
}
|
|
8766
9646
|
const idWidth = Math.max(...suggestions.map((s) => `#${s.id}`.length));
|
|
@@ -8768,7 +9648,7 @@ function registerSuggestionsCommand(program2) {
|
|
|
8768
9648
|
const slugWidth = Math.max(...suggestions.map((s) => s.packageSlug.length));
|
|
8769
9649
|
const authorWidth = Math.max(...suggestions.map((s) => s.author.length));
|
|
8770
9650
|
const heading = statusFilter === "ALL" ? `Suggestions (${suggestions.length})` : `${options.status.charAt(0).toUpperCase() + options.status.slice(1)} suggestions (${suggestions.length})`;
|
|
8771
|
-
console.log(
|
|
9651
|
+
console.log(chalk26.bold(`
|
|
8772
9652
|
${heading}:
|
|
8773
9653
|
`));
|
|
8774
9654
|
for (const suggestion of suggestions) {
|
|
@@ -8789,7 +9669,7 @@ ${heading}:
|
|
|
8789
9669
|
// src/commands/sync.ts
|
|
8790
9670
|
import { createHash as createHash4 } from "crypto";
|
|
8791
9671
|
import { hostname as hostname2 } from "os";
|
|
8792
|
-
import
|
|
9672
|
+
import chalk27 from "chalk";
|
|
8793
9673
|
var SYNC_TIMEOUT_MS = 3e4;
|
|
8794
9674
|
function getMachineId2() {
|
|
8795
9675
|
return createHash4("sha256").update(hostname2()).digest("hex");
|
|
@@ -8806,7 +9686,7 @@ function registerSyncCommand(program2) {
|
|
|
8806
9686
|
process.exit(1);
|
|
8807
9687
|
}
|
|
8808
9688
|
console.error(
|
|
8809
|
-
|
|
9689
|
+
chalk27.red("Not connected to a platform.") + " Run " + chalk27.cyan("`agentver login <url>`") + " first."
|
|
8810
9690
|
);
|
|
8811
9691
|
process.exit(1);
|
|
8812
9692
|
}
|
|
@@ -8820,7 +9700,7 @@ function registerSyncCommand(program2) {
|
|
|
8820
9700
|
process.exit(1);
|
|
8821
9701
|
}
|
|
8822
9702
|
console.error(
|
|
8823
|
-
|
|
9703
|
+
chalk27.red("Not connected to a platform.") + " Run " + chalk27.cyan("`agentver login <url>`") + " first."
|
|
8824
9704
|
);
|
|
8825
9705
|
process.exit(1);
|
|
8826
9706
|
}
|
|
@@ -8892,7 +9772,7 @@ function registerSyncCommand(program2) {
|
|
|
8892
9772
|
return;
|
|
8893
9773
|
}
|
|
8894
9774
|
spinner.succeed(
|
|
8895
|
-
`Synced ${
|
|
9775
|
+
`Synced ${chalk27.green(String(result.synced))} skill${result.synced === 1 ? "" : "s"} to platform` + (result.removed > 0 ? chalk27.dim(` (${result.removed} removed)`) : "")
|
|
8896
9776
|
);
|
|
8897
9777
|
} catch (error) {
|
|
8898
9778
|
if (error instanceof DOMException && error.name === "AbortError") {
|
|
@@ -8916,23 +9796,23 @@ function registerSyncCommand(program2) {
|
|
|
8916
9796
|
}
|
|
8917
9797
|
|
|
8918
9798
|
// src/commands/update.ts
|
|
8919
|
-
import { join as
|
|
8920
|
-
import
|
|
9799
|
+
import { join as join23 } from "path";
|
|
9800
|
+
import chalk28 from "chalk";
|
|
8921
9801
|
import ora7 from "ora";
|
|
8922
9802
|
import prompts3 from "prompts";
|
|
8923
9803
|
|
|
8924
9804
|
// src/storage/patches.ts
|
|
8925
|
-
import { existsSync as
|
|
8926
|
-
import { join as
|
|
9805
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync9, readFileSync as readFileSync16, rmSync as rmSync3, writeFileSync as writeFileSync8 } from "fs";
|
|
9806
|
+
import { join as join21 } from "path";
|
|
8927
9807
|
var PATCHES_DIR = ".agentver/patches";
|
|
8928
9808
|
var CONTEXT_LINES2 = 3;
|
|
8929
9809
|
function getPatchPath(projectRoot, packageName) {
|
|
8930
|
-
return
|
|
9810
|
+
return join21(projectRoot, PATCHES_DIR, `${packageName}.patch`);
|
|
8931
9811
|
}
|
|
8932
9812
|
function savePatch(projectRoot, packageName, patchContent) {
|
|
8933
9813
|
const patchPath = getPatchPath(projectRoot, packageName);
|
|
8934
|
-
const dir =
|
|
8935
|
-
if (!
|
|
9814
|
+
const dir = join21(projectRoot, PATCHES_DIR);
|
|
9815
|
+
if (!existsSync18(dir)) {
|
|
8936
9816
|
mkdirSync9(dir, { recursive: true });
|
|
8937
9817
|
}
|
|
8938
9818
|
writeFileSync8(patchPath, patchContent, "utf-8");
|
|
@@ -8940,7 +9820,7 @@ function savePatch(projectRoot, packageName, patchContent) {
|
|
|
8940
9820
|
}
|
|
8941
9821
|
function removePatch(projectRoot, packageName) {
|
|
8942
9822
|
const patchPath = getPatchPath(projectRoot, packageName);
|
|
8943
|
-
if (
|
|
9823
|
+
if (existsSync18(patchPath)) {
|
|
8944
9824
|
rmSync3(patchPath);
|
|
8945
9825
|
}
|
|
8946
9826
|
}
|
|
@@ -8987,30 +9867,30 @@ function applyPatch(projectRoot, patchContent) {
|
|
|
8987
9867
|
};
|
|
8988
9868
|
}
|
|
8989
9869
|
function applyFilePatch(projectRoot, filePatch) {
|
|
8990
|
-
const fullPath =
|
|
9870
|
+
const fullPath = join21(projectRoot, filePatch.filePath);
|
|
8991
9871
|
const hasOnlyAdditions = filePatch.hunks.every(
|
|
8992
9872
|
(h) => h.lines.every((l) => l.startsWith("+") || l.startsWith(" "))
|
|
8993
9873
|
);
|
|
8994
9874
|
const hasOnlyDeletions = filePatch.hunks.every(
|
|
8995
9875
|
(h) => h.lines.every((l) => l.startsWith("-") || l.startsWith(" "))
|
|
8996
9876
|
);
|
|
8997
|
-
if (hasOnlyAdditions && !
|
|
9877
|
+
if (hasOnlyAdditions && !existsSync18(fullPath)) {
|
|
8998
9878
|
const content = filePatch.hunks.flatMap((h) => h.lines.filter((l) => l.startsWith("+")).map((l) => l.slice(1))).join("\n");
|
|
8999
|
-
const dir =
|
|
9000
|
-
if (!
|
|
9879
|
+
const dir = join21(fullPath, "..");
|
|
9880
|
+
if (!existsSync18(dir)) {
|
|
9001
9881
|
mkdirSync9(dir, { recursive: true });
|
|
9002
9882
|
}
|
|
9003
9883
|
writeFileSync8(fullPath, content, "utf-8");
|
|
9004
9884
|
return true;
|
|
9005
9885
|
}
|
|
9006
|
-
if (hasOnlyDeletions &&
|
|
9886
|
+
if (hasOnlyDeletions && existsSync18(fullPath)) {
|
|
9007
9887
|
rmSync3(fullPath);
|
|
9008
9888
|
return true;
|
|
9009
9889
|
}
|
|
9010
|
-
if (!
|
|
9890
|
+
if (!existsSync18(fullPath)) {
|
|
9011
9891
|
return false;
|
|
9012
9892
|
}
|
|
9013
|
-
const currentContent =
|
|
9893
|
+
const currentContent = readFileSync16(fullPath, "utf-8");
|
|
9014
9894
|
const currentLines = currentContent.split("\n");
|
|
9015
9895
|
let offset = 0;
|
|
9016
9896
|
for (const hunk of filePatch.hunks) {
|
|
@@ -9294,17 +10174,17 @@ function backtrackMyers(trace, oldLines, newLines, finalD, max) {
|
|
|
9294
10174
|
}
|
|
9295
10175
|
|
|
9296
10176
|
// src/utils/backup.ts
|
|
9297
|
-
import { cpSync, existsSync as
|
|
10177
|
+
import { cpSync, existsSync as existsSync19, mkdirSync as mkdirSync10, mkdtempSync, rmSync as rmSync4 } from "fs";
|
|
9298
10178
|
import { tmpdir as tmpdir2 } from "os";
|
|
9299
|
-
import { join as
|
|
10179
|
+
import { join as join22 } from "path";
|
|
9300
10180
|
function createBackup(packageName, projectRoot, skillDir) {
|
|
9301
|
-
const tempDir = mkdtempSync(
|
|
10181
|
+
const tempDir = mkdtempSync(join22(tmpdir2(), "agentver-backup-"));
|
|
9302
10182
|
const manifest = readManifest(projectRoot);
|
|
9303
10183
|
const manifestEntry = manifest.packages[packageName] ?? null;
|
|
9304
10184
|
const lockfile = readLockfile(projectRoot);
|
|
9305
10185
|
const lockfileEntry = lockfile.packages[packageName] ?? null;
|
|
9306
|
-
if (skillDir &&
|
|
9307
|
-
const backupSkillDir =
|
|
10186
|
+
if (skillDir && existsSync19(skillDir)) {
|
|
10187
|
+
const backupSkillDir = join22(tempDir, "files");
|
|
9308
10188
|
mkdirSync10(backupSkillDir, { recursive: true });
|
|
9309
10189
|
cpSync(skillDir, backupSkillDir, { recursive: true });
|
|
9310
10190
|
}
|
|
@@ -9319,9 +10199,9 @@ function createBackup(packageName, projectRoot, skillDir) {
|
|
|
9319
10199
|
}
|
|
9320
10200
|
function restoreBackup(backup) {
|
|
9321
10201
|
if (backup.skillDir) {
|
|
9322
|
-
const backupSkillDir =
|
|
9323
|
-
if (
|
|
9324
|
-
if (
|
|
10202
|
+
const backupSkillDir = join22(backup.tempDir, "files");
|
|
10203
|
+
if (existsSync19(backupSkillDir)) {
|
|
10204
|
+
if (existsSync19(backup.skillDir)) {
|
|
9325
10205
|
rmSync4(backup.skillDir, { recursive: true, force: true });
|
|
9326
10206
|
}
|
|
9327
10207
|
mkdirSync10(backup.skillDir, { recursive: true });
|
|
@@ -9344,7 +10224,7 @@ function restoreBackup(backup) {
|
|
|
9344
10224
|
writeLockfile(backup.projectRoot, lockfile);
|
|
9345
10225
|
}
|
|
9346
10226
|
function cleanupBackup(backup) {
|
|
9347
|
-
if (
|
|
10227
|
+
if (existsSync19(backup.tempDir)) {
|
|
9348
10228
|
rmSync4(backup.tempDir, { recursive: true, force: true });
|
|
9349
10229
|
}
|
|
9350
10230
|
}
|
|
@@ -9450,13 +10330,13 @@ async function handlePatchUpdate(update, projectRoot, agents, spinner) {
|
|
|
9450
10330
|
const applyResult = applyPatch(projectRoot, patchContent);
|
|
9451
10331
|
if (applyResult.applied) {
|
|
9452
10332
|
removePatch(projectRoot, update.name);
|
|
9453
|
-
spinner.succeed(`${
|
|
10333
|
+
spinner.succeed(`${chalk28.green(update.name)}: updated and local patch reapplied successfully`);
|
|
9454
10334
|
} else {
|
|
9455
10335
|
spinner.warn(
|
|
9456
|
-
`${
|
|
10336
|
+
`${chalk28.yellow(update.name)}: updated but patch had conflicts in: ${applyResult.conflicts.join(", ")}`
|
|
9457
10337
|
);
|
|
9458
|
-
console.log(
|
|
9459
|
-
console.log(
|
|
10338
|
+
console.log(chalk28.dim(` Patch saved at: ${patchPath}`));
|
|
10339
|
+
console.log(chalk28.dim(" Review the patch file and apply remaining changes manually."));
|
|
9460
10340
|
}
|
|
9461
10341
|
return { commitSha: result.commitSha };
|
|
9462
10342
|
}
|
|
@@ -9473,27 +10353,43 @@ function registerUpdateCommand(program2) {
|
|
|
9473
10353
|
return;
|
|
9474
10354
|
}
|
|
9475
10355
|
console.log(
|
|
9476
|
-
|
|
10356
|
+
chalk28.dim(name ? `Package "${name}" is not installed.` : "No packages installed.")
|
|
9477
10357
|
);
|
|
9478
10358
|
return;
|
|
9479
10359
|
}
|
|
10360
|
+
const pinnedNames = [];
|
|
9480
10361
|
const updatable = packageNames.filter((n) => {
|
|
9481
10362
|
const pkg2 = packages[n];
|
|
9482
|
-
|
|
10363
|
+
if (!pkg2) return false;
|
|
10364
|
+
if (pkg2.pinned === true) {
|
|
10365
|
+
pinnedNames.push(n);
|
|
10366
|
+
return false;
|
|
10367
|
+
}
|
|
10368
|
+
return pkg2.source.type === "git" && pkg2.source.uri !== "unknown";
|
|
9483
10369
|
});
|
|
10370
|
+
if (pinnedNames.length > 0 && !jsonMode) {
|
|
10371
|
+
for (const pinnedName of pinnedNames) {
|
|
10372
|
+
console.log(chalk28.dim(`Skipping ${pinnedName} (pinned)`));
|
|
10373
|
+
}
|
|
10374
|
+
}
|
|
9484
10375
|
if (updatable.length === 0) {
|
|
9485
10376
|
if (jsonMode) {
|
|
9486
10377
|
outputSuccess({
|
|
9487
10378
|
updated: [],
|
|
9488
|
-
skipped:
|
|
10379
|
+
skipped: [
|
|
10380
|
+
...pinnedNames.map((n) => ({ name: n, reason: "pinned" })),
|
|
10381
|
+
...packageNames.filter((n) => !pinnedNames.includes(n)).map((n) => ({ name: n, reason: "No known Git source" }))
|
|
10382
|
+
]
|
|
9489
10383
|
});
|
|
9490
10384
|
return;
|
|
9491
10385
|
}
|
|
9492
|
-
|
|
9493
|
-
|
|
9494
|
-
|
|
9495
|
-
|
|
9496
|
-
|
|
10386
|
+
if (pinnedNames.length === 0) {
|
|
10387
|
+
console.log(
|
|
10388
|
+
chalk28.dim(
|
|
10389
|
+
"No packages with known Git sources. Reinstall packages using Git source URLs to enable updates."
|
|
10390
|
+
)
|
|
10391
|
+
);
|
|
10392
|
+
}
|
|
9497
10393
|
return;
|
|
9498
10394
|
}
|
|
9499
10395
|
const spinner = createSpinner("Checking for upstream changes...").start();
|
|
@@ -9533,17 +10429,17 @@ function registerUpdateCommand(program2) {
|
|
|
9533
10429
|
outputSuccess({ updated: [], skipped: [] });
|
|
9534
10430
|
return;
|
|
9535
10431
|
}
|
|
9536
|
-
console.log(
|
|
10432
|
+
console.log(chalk28.green("All packages are up to date."));
|
|
9537
10433
|
return;
|
|
9538
10434
|
}
|
|
9539
10435
|
if (!jsonMode) {
|
|
9540
|
-
console.log(
|
|
10436
|
+
console.log(chalk28.bold(`
|
|
9541
10437
|
Upstream changes available (${updates.length}):
|
|
9542
10438
|
`));
|
|
9543
10439
|
for (const update of updates) {
|
|
9544
|
-
const modifiedIndicator = update.locallyModified ? ` ${
|
|
10440
|
+
const modifiedIndicator = update.locallyModified ? ` ${chalk28.yellow("\u26A0 locally modified")}` : "";
|
|
9545
10441
|
console.log(
|
|
9546
|
-
` ${
|
|
10442
|
+
` ${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
10443
|
);
|
|
9548
10444
|
}
|
|
9549
10445
|
console.log();
|
|
@@ -9556,7 +10452,7 @@ Upstream changes available (${updates.length}):
|
|
|
9556
10452
|
});
|
|
9557
10453
|
return;
|
|
9558
10454
|
}
|
|
9559
|
-
console.log(`${
|
|
10455
|
+
console.log(`${chalk28.yellow("[dry-run]")} No changes made.`);
|
|
9560
10456
|
return;
|
|
9561
10457
|
}
|
|
9562
10458
|
if (!jsonMode) {
|
|
@@ -9567,7 +10463,7 @@ Upstream changes available (${updates.length}):
|
|
|
9567
10463
|
initial: true
|
|
9568
10464
|
});
|
|
9569
10465
|
if (!confirmed) {
|
|
9570
|
-
console.log(
|
|
10466
|
+
console.log(chalk28.dim("Update cancelled."));
|
|
9571
10467
|
return;
|
|
9572
10468
|
}
|
|
9573
10469
|
}
|
|
@@ -9633,7 +10529,7 @@ Upstream changes available (${updates.length}):
|
|
|
9633
10529
|
}
|
|
9634
10530
|
}
|
|
9635
10531
|
const shortName = update.name.split("/").pop();
|
|
9636
|
-
const skillDir = resolveReadPath(projectRoot, shortName, agents) ?? (agentId ?
|
|
10532
|
+
const skillDir = resolveReadPath(projectRoot, shortName, agents) ?? (agentId ? join23(
|
|
9637
10533
|
projectRoot,
|
|
9638
10534
|
getSkillPlacementPath(agentId, shortName, "project") ?? ""
|
|
9639
10535
|
) : null);
|
|
@@ -9675,25 +10571,25 @@ Upstream changes available (${updates.length}):
|
|
|
9675
10571
|
if (jsonMode) {
|
|
9676
10572
|
outputSuccess({
|
|
9677
10573
|
updated: jsonUpdated,
|
|
9678
|
-
skipped: jsonSkipped
|
|
10574
|
+
skipped: [...pinnedNames.map((n) => ({ name: n, reason: "pinned" })), ...jsonSkipped]
|
|
9679
10575
|
});
|
|
9680
10576
|
return;
|
|
9681
10577
|
}
|
|
9682
|
-
console.log(
|
|
10578
|
+
console.log(chalk28.bold("\nUpdate summary:\n"));
|
|
9683
10579
|
for (const result of results) {
|
|
9684
|
-
const patchNote = result.patched ?
|
|
10580
|
+
const patchNote = result.patched ? chalk28.dim(" (patch reapplied)") : "";
|
|
9685
10581
|
console.log(
|
|
9686
|
-
` ${
|
|
10582
|
+
` ${chalk28.green("\u2713")} ${result.name}: ${chalk28.dim(result.from)} \u2192 ${chalk28.cyan(result.to)}${patchNote}`
|
|
9687
10583
|
);
|
|
9688
10584
|
}
|
|
9689
10585
|
for (const skippedName of skipped) {
|
|
9690
|
-
console.log(` ${
|
|
10586
|
+
console.log(` ${chalk28.dim("\u2013")} ${skippedName}: ${chalk28.dim("skipped")}`);
|
|
9691
10587
|
}
|
|
9692
10588
|
for (const failure of failures) {
|
|
9693
|
-
console.log(` ${
|
|
10589
|
+
console.log(` ${chalk28.red("\u2717")} ${failure.name}: ${failure.error}`);
|
|
9694
10590
|
}
|
|
9695
10591
|
if (failures.length > 0) {
|
|
9696
|
-
console.log(
|
|
10592
|
+
console.log(chalk28.dim("\nFailed packages were rolled back to their previous versions."));
|
|
9697
10593
|
}
|
|
9698
10594
|
console.log();
|
|
9699
10595
|
} catch (error) {
|
|
@@ -9712,16 +10608,16 @@ Upstream changes available (${updates.length}):
|
|
|
9712
10608
|
// src/commands/upgrade.ts
|
|
9713
10609
|
import { execFile as execFile2 } from "child_process";
|
|
9714
10610
|
import { createRequire } from "module";
|
|
9715
|
-
import { dirname as
|
|
10611
|
+
import { dirname as dirname6, join as join24 } from "path";
|
|
9716
10612
|
import { fileURLToPath } from "url";
|
|
9717
10613
|
import { promisify as promisify2 } from "util";
|
|
9718
|
-
import
|
|
10614
|
+
import chalk29 from "chalk";
|
|
9719
10615
|
var execFileAsync2 = promisify2(execFile2);
|
|
9720
10616
|
var PACKAGE_NAME = "@agentver/cli";
|
|
9721
10617
|
function getCurrentVersion() {
|
|
9722
|
-
const __dirname2 =
|
|
10618
|
+
const __dirname2 = dirname6(fileURLToPath(import.meta.url));
|
|
9723
10619
|
const require3 = createRequire(import.meta.url);
|
|
9724
|
-
const pkg2 = require3(
|
|
10620
|
+
const pkg2 = require3(join24(__dirname2, "..", "package.json"));
|
|
9725
10621
|
return pkg2.version;
|
|
9726
10622
|
}
|
|
9727
10623
|
async function getLatestVersion() {
|
|
@@ -9777,11 +10673,11 @@ function registerUpgradeCommand(program2) {
|
|
|
9777
10673
|
if (json) {
|
|
9778
10674
|
outputSuccess({ current: currentVersion, latest: latestVersion, upToDate: true });
|
|
9779
10675
|
} else {
|
|
9780
|
-
spinner.succeed(`Already on the latest version ${
|
|
10676
|
+
spinner.succeed(`Already on the latest version ${chalk29.green(`v${currentVersion}`)}`);
|
|
9781
10677
|
}
|
|
9782
10678
|
return;
|
|
9783
10679
|
}
|
|
9784
|
-
spinner.text = `Upgrading ${
|
|
10680
|
+
spinner.text = `Upgrading ${chalk29.dim(`v${currentVersion}`)} \u2192 ${chalk29.green(`v${latestVersion}`)}\u2026`;
|
|
9785
10681
|
const pm = await detectPackageManager();
|
|
9786
10682
|
const args = getInstallArgs(pm);
|
|
9787
10683
|
await execFileAsync2(pm, args, { timeout: 6e4 });
|
|
@@ -9794,7 +10690,7 @@ function registerUpgradeCommand(program2) {
|
|
|
9794
10690
|
outputSuccess(result);
|
|
9795
10691
|
} else {
|
|
9796
10692
|
spinner.succeed(
|
|
9797
|
-
`Upgraded ${
|
|
10693
|
+
`Upgraded ${chalk29.green(`v${currentVersion}`)} \u2192 ${chalk29.green(`v${latestVersion}`)} via ${pm}`
|
|
9798
10694
|
);
|
|
9799
10695
|
}
|
|
9800
10696
|
} catch (error) {
|
|
@@ -9811,7 +10707,7 @@ function registerUpgradeCommand(program2) {
|
|
|
9811
10707
|
}
|
|
9812
10708
|
|
|
9813
10709
|
// src/commands/verify.ts
|
|
9814
|
-
import
|
|
10710
|
+
import chalk30 from "chalk";
|
|
9815
10711
|
var FALLBACK_SOURCE2 = {
|
|
9816
10712
|
host: "github.com",
|
|
9817
10713
|
owner: "local",
|
|
@@ -9878,8 +10774,8 @@ function registerVerifyCommand(program2) {
|
|
|
9878
10774
|
outputError("NO_SKILL", "No skill name provided and no packages installed");
|
|
9879
10775
|
return;
|
|
9880
10776
|
}
|
|
9881
|
-
process.stderr.write(
|
|
9882
|
-
process.stderr.write(
|
|
10777
|
+
process.stderr.write(chalk30.red("No skill name provided and no packages installed.\n"));
|
|
10778
|
+
process.stderr.write(chalk30.dim("Usage: agentver verify @org/skill-name\n"));
|
|
9883
10779
|
process.exitCode = 1;
|
|
9884
10780
|
return;
|
|
9885
10781
|
}
|
|
@@ -9894,10 +10790,10 @@ function registerVerifyCommand(program2) {
|
|
|
9894
10790
|
return;
|
|
9895
10791
|
}
|
|
9896
10792
|
process.stderr.write(
|
|
9897
|
-
|
|
10793
|
+
chalk30.red("Multiple packages installed. Please specify which to verify:\n")
|
|
9898
10794
|
);
|
|
9899
10795
|
for (const pkg2 of packageNames) {
|
|
9900
|
-
process.stderr.write(` ${
|
|
10796
|
+
process.stderr.write(` ${chalk30.cyan(pkg2)}
|
|
9901
10797
|
`);
|
|
9902
10798
|
}
|
|
9903
10799
|
process.exitCode = 1;
|
|
@@ -9914,7 +10810,7 @@ function registerVerifyCommand(program2) {
|
|
|
9914
10810
|
return;
|
|
9915
10811
|
}
|
|
9916
10812
|
process.stderr.write(
|
|
9917
|
-
|
|
10813
|
+
chalk30.red(`Invalid skill name "${skillName}". Expected format: @org/skill-name
|
|
9918
10814
|
`)
|
|
9919
10815
|
);
|
|
9920
10816
|
process.exitCode = 1;
|
|
@@ -9922,7 +10818,7 @@ function registerVerifyCommand(program2) {
|
|
|
9922
10818
|
}
|
|
9923
10819
|
if (!jsonMode) {
|
|
9924
10820
|
process.stderr.write(`
|
|
9925
|
-
${
|
|
10821
|
+
${chalk30.bold(`Verifying @${parsed.org}/${parsed.skill}...`)}
|
|
9926
10822
|
|
|
9927
10823
|
`);
|
|
9928
10824
|
}
|
|
@@ -10064,26 +10960,26 @@ ${chalk25.bold(`Verifying @${parsed.org}/${parsed.skill}...`)}
|
|
|
10064
10960
|
}
|
|
10065
10961
|
process.stderr.write("\n");
|
|
10066
10962
|
if (overallPassed) {
|
|
10067
|
-
process.stderr.write(
|
|
10963
|
+
process.stderr.write(chalk30.green.bold("Skill is verified and safe to use.\n"));
|
|
10068
10964
|
} else {
|
|
10069
|
-
process.stderr.write(
|
|
10965
|
+
process.stderr.write(chalk30.red.bold("Skill verification failed.\n"));
|
|
10070
10966
|
process.exitCode = 1;
|
|
10071
10967
|
}
|
|
10072
10968
|
});
|
|
10073
10969
|
}
|
|
10074
10970
|
|
|
10075
10971
|
// src/commands/version.ts
|
|
10076
|
-
import { existsSync as
|
|
10077
|
-
import { basename as basename6, join as
|
|
10078
|
-
import
|
|
10972
|
+
import { existsSync as existsSync20, readFileSync as readFileSync17 } from "fs";
|
|
10973
|
+
import { basename as basename6, join as join25 } from "path";
|
|
10974
|
+
import chalk31 from "chalk";
|
|
10079
10975
|
import ora8 from "ora";
|
|
10080
10976
|
var SEMVER_REGEX2 = /^\d+\.\d+\.\d+(-[\w.]+)?$/;
|
|
10081
10977
|
function resolveSkillIdentity3() {
|
|
10082
10978
|
const cwd = process.cwd();
|
|
10083
|
-
const skillMdPath =
|
|
10979
|
+
const skillMdPath = join25(cwd, "SKILL.md");
|
|
10084
10980
|
let skillName = null;
|
|
10085
|
-
if (
|
|
10086
|
-
const content =
|
|
10981
|
+
if (existsSync20(skillMdPath)) {
|
|
10982
|
+
const content = readFileSync17(skillMdPath, "utf-8");
|
|
10087
10983
|
const nameMatch = content.match(/^name:\s*(.+)$/m);
|
|
10088
10984
|
skillName = nameMatch?.[1]?.trim() ?? basename6(cwd);
|
|
10089
10985
|
}
|
|
@@ -10111,7 +11007,7 @@ function registerVersionCommand(program2) {
|
|
|
10111
11007
|
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
11008
|
if (!SEMVER_REGEX2.test(semver)) {
|
|
10113
11009
|
process.stderr.write(
|
|
10114
|
-
|
|
11010
|
+
chalk31.red(`Invalid semver "${semver}". Expected format: 1.0.0 or 1.0.0-beta.1
|
|
10115
11011
|
`)
|
|
10116
11012
|
);
|
|
10117
11013
|
process.exit(1);
|
|
@@ -10119,7 +11015,7 @@ function registerVersionCommand(program2) {
|
|
|
10119
11015
|
const identity = resolveSkillIdentity3();
|
|
10120
11016
|
if (!identity) {
|
|
10121
11017
|
process.stderr.write(
|
|
10122
|
-
|
|
11018
|
+
chalk31.red("Could not determine skill identity. Run this from a skill directory.\n")
|
|
10123
11019
|
);
|
|
10124
11020
|
process.exit(1);
|
|
10125
11021
|
}
|
|
@@ -10127,7 +11023,7 @@ function registerVersionCommand(program2) {
|
|
|
10127
11023
|
const lockEntry = lockfile.packages[identity.name];
|
|
10128
11024
|
const commitSha = lockEntry?.source.type === "git" ? lockEntry.source.commit : void 0;
|
|
10129
11025
|
if (!commitSha || commitSha === "unknown") {
|
|
10130
|
-
process.stderr.write(
|
|
11026
|
+
process.stderr.write(chalk31.red("No commit SHA found in lockfile. Save changes first.\n"));
|
|
10131
11027
|
process.exit(1);
|
|
10132
11028
|
}
|
|
10133
11029
|
const spinner = ora8(`Creating version ${semver}...`).start();
|
|
@@ -10159,7 +11055,7 @@ function registerVersionCommand(program2) {
|
|
|
10159
11055
|
);
|
|
10160
11056
|
} else {
|
|
10161
11057
|
spinner.succeed(
|
|
10162
|
-
`Version ${
|
|
11058
|
+
`Version ${chalk31.cyan(semver)} created ${chalk31.dim(`(${result.commitSha.slice(0, 7)})`)}`
|
|
10163
11059
|
);
|
|
10164
11060
|
}
|
|
10165
11061
|
} catch (error) {
|
|
@@ -10173,7 +11069,7 @@ function registerVersionCommand(program2) {
|
|
|
10173
11069
|
const identity = resolveSkillIdentity3();
|
|
10174
11070
|
if (!identity) {
|
|
10175
11071
|
process.stderr.write(
|
|
10176
|
-
|
|
11072
|
+
chalk31.red("Could not determine skill identity. Run this from a skill directory.\n")
|
|
10177
11073
|
);
|
|
10178
11074
|
process.exit(1);
|
|
10179
11075
|
}
|
|
@@ -10188,16 +11084,16 @@ function registerVersionCommand(program2) {
|
|
|
10188
11084
|
return;
|
|
10189
11085
|
}
|
|
10190
11086
|
if (versions.length === 0) {
|
|
10191
|
-
process.stdout.write(
|
|
11087
|
+
process.stdout.write(chalk31.dim("No versions found.\n"));
|
|
10192
11088
|
return;
|
|
10193
11089
|
}
|
|
10194
|
-
process.stdout.write(
|
|
11090
|
+
process.stdout.write(chalk31.bold(`
|
|
10195
11091
|
Versions for @${identity.org}/${identity.name}:
|
|
10196
11092
|
|
|
10197
11093
|
`));
|
|
10198
11094
|
for (const v of versions) {
|
|
10199
11095
|
process.stdout.write(
|
|
10200
|
-
` ${
|
|
11096
|
+
` ${chalk31.cyan(v.name)} ${chalk31.dim(`(${v.commitSha.slice(0, 7)})`)} ${chalk31.dim(v.message)}
|
|
10201
11097
|
`
|
|
10202
11098
|
);
|
|
10203
11099
|
}
|
|
@@ -10212,7 +11108,7 @@ Versions for @${identity.org}/${identity.name}:
|
|
|
10212
11108
|
}
|
|
10213
11109
|
|
|
10214
11110
|
// src/commands/whoami.ts
|
|
10215
|
-
import
|
|
11111
|
+
import chalk32 from "chalk";
|
|
10216
11112
|
function registerWhoamiCommand(program2) {
|
|
10217
11113
|
program2.command("whoami").description("Show authentication state").action(async () => {
|
|
10218
11114
|
const credentials = await getCredentials();
|
|
@@ -10221,15 +11117,15 @@ function registerWhoamiCommand(program2) {
|
|
|
10221
11117
|
outputSuccess({ authenticated: false });
|
|
10222
11118
|
return;
|
|
10223
11119
|
}
|
|
10224
|
-
console.log(
|
|
11120
|
+
console.log(chalk32.dim("Not authenticated. Run `agentver login` to sign in."));
|
|
10225
11121
|
return;
|
|
10226
11122
|
}
|
|
10227
11123
|
if (!isJSONMode()) {
|
|
10228
11124
|
if (credentials.apiKey) {
|
|
10229
11125
|
const prefix = credentials.apiKey.slice(0, 8);
|
|
10230
|
-
console.log(`Authenticated via API key: ${
|
|
11126
|
+
console.log(`Authenticated via API key: ${chalk32.green(`${prefix}...`)}`);
|
|
10231
11127
|
} else {
|
|
10232
|
-
console.log(
|
|
11128
|
+
console.log(chalk32.green("Authenticated via OAuth."));
|
|
10233
11129
|
}
|
|
10234
11130
|
}
|
|
10235
11131
|
const platformUrl = getPlatformUrl();
|
|
@@ -10238,11 +11134,11 @@ function registerWhoamiCommand(program2) {
|
|
|
10238
11134
|
outputSuccess({ authenticated: true });
|
|
10239
11135
|
return;
|
|
10240
11136
|
}
|
|
10241
|
-
console.log(
|
|
11137
|
+
console.log(chalk32.dim("Platform: not connected (run `agentver login <url>` to connect)"));
|
|
10242
11138
|
return;
|
|
10243
11139
|
}
|
|
10244
11140
|
if (!isJSONMode()) {
|
|
10245
|
-
console.log(`Platform: ${
|
|
11141
|
+
console.log(`Platform: ${chalk32.cyan(platformUrl)}`);
|
|
10246
11142
|
}
|
|
10247
11143
|
const me = await platformFetchSilent("/me");
|
|
10248
11144
|
if (isJSONMode()) {
|
|
@@ -10269,38 +11165,44 @@ function registerWhoamiCommand(program2) {
|
|
|
10269
11165
|
}
|
|
10270
11166
|
|
|
10271
11167
|
// bin/agentver.ts
|
|
10272
|
-
var __dirname =
|
|
11168
|
+
var __dirname = dirname7(fileURLToPath2(import.meta.url));
|
|
10273
11169
|
var require2 = createRequire2(import.meta.url);
|
|
10274
|
-
var pkg = require2(
|
|
11170
|
+
var pkg = require2(join26(__dirname, "..", "package.json"));
|
|
10275
11171
|
updateNotifier({ pkg }).notify({
|
|
10276
11172
|
message: `Update available: {currentVersion} \u2192 {latestVersion}
|
|
10277
|
-
Run ${
|
|
11173
|
+
Run ${chalk33.cyan("agentver upgrade")} to update`
|
|
10278
11174
|
});
|
|
10279
11175
|
var program = new Command();
|
|
10280
11176
|
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
11177
|
registerAdoptCommand(program);
|
|
10282
|
-
registerInstallCommand(program);
|
|
10283
11178
|
registerAuditCommand(program);
|
|
11179
|
+
registerCompletionCommand(program);
|
|
11180
|
+
registerConfigCommand(program);
|
|
11181
|
+
registerDiffCommand(program);
|
|
11182
|
+
registerDoctorCommand(program);
|
|
11183
|
+
registerDraftCommand(program);
|
|
11184
|
+
registerInfoCommand(program);
|
|
11185
|
+
registerInitCommand(program);
|
|
11186
|
+
registerInstallCommand(program);
|
|
11187
|
+
registerListCommand(program);
|
|
11188
|
+
registerLogCommand(program);
|
|
10284
11189
|
registerLoginCommand(program);
|
|
10285
11190
|
registerLogoutCommand(program);
|
|
10286
|
-
|
|
10287
|
-
|
|
10288
|
-
registerUpdateCommand(program);
|
|
11191
|
+
registerPinCommand(program);
|
|
11192
|
+
registerPublishCommand(program);
|
|
10289
11193
|
registerRemoveCommand(program);
|
|
10290
|
-
|
|
11194
|
+
registerSaveCommand(program);
|
|
10291
11195
|
registerScanCommand(program);
|
|
10292
|
-
|
|
11196
|
+
registerSearchCommand(program);
|
|
10293
11197
|
registerStatusCommand(program);
|
|
10294
|
-
registerDiffCommand(program);
|
|
10295
|
-
registerSyncCommand(program);
|
|
10296
11198
|
registerSuggestCommand(program);
|
|
10297
11199
|
registerSuggestionsCommand(program);
|
|
10298
|
-
|
|
10299
|
-
|
|
10300
|
-
|
|
11200
|
+
registerSyncCommand(program);
|
|
11201
|
+
registerUnpinCommand(program);
|
|
11202
|
+
registerUpdateCommand(program);
|
|
10301
11203
|
registerUpgradeCommand(program);
|
|
10302
11204
|
registerVerifyCommand(program);
|
|
10303
11205
|
registerVersionCommand(program);
|
|
10304
|
-
|
|
11206
|
+
registerWhoamiCommand(program);
|
|
10305
11207
|
program.parse();
|
|
10306
11208
|
//# sourceMappingURL=agentver.js.map
|