@bonnard/agentops
Advanced tools
+61
-49
@@ -67,4 +67,16 @@ #!/usr/bin/env node | ||
| //#region src/lib/api.ts | ||
| function getBaseUrl(urlOverride) { | ||
| if (urlOverride) return urlOverride.replace(/\/$/, ""); | ||
| /** | ||
| * Resolve the AgentOps server URL. | ||
| * | ||
| * Precedence: | ||
| * 1. AGENTOPS_API_URL env var — dev-only override. Set this when you want | ||
| * the CLI to talk to a local server (http://localhost:3000) or a staging | ||
| * environment. Takes precedence over saved credentials so an accidentally | ||
| * persisted dev URL can be overridden by setting or unsetting the env var. | ||
| * 2. Saved config (from the last successful login) | ||
| * 3. Production default | ||
| */ | ||
| function getBaseUrl() { | ||
| const envUrl = process.env.AGENTOPS_API_URL; | ||
| if (envUrl) return envUrl.replace(/\/$/, ""); | ||
| const config = loadConfig(); | ||
@@ -197,4 +209,4 @@ if (config?.url) return config.url.replace(/\/$/, ""); | ||
| const CALLBACK_HOST = "127.0.0.1"; | ||
| async function loginCommand(options) { | ||
| const baseUrl = getBaseUrl(options.url); | ||
| async function loginCommand() { | ||
| const baseUrl = getBaseUrl(); | ||
| console.log(pc.dim(`Server: ${baseUrl}`)); | ||
@@ -428,3 +440,3 @@ const expectedState = crypto.randomBytes(20).toString("hex"); | ||
| } | ||
| const baseUrl = getBaseUrl(opts.url); | ||
| const baseUrl = getBaseUrl(); | ||
| if (opts.tags === true) { | ||
@@ -852,3 +864,3 @@ const res = await get("/api/skills?list=tags", baseUrl); | ||
| const { name, version } = parsed; | ||
| const baseUrl = getBaseUrl(opts.url); | ||
| const baseUrl = getBaseUrl(); | ||
| const scope = { user: opts.user ?? false }; | ||
@@ -916,3 +928,3 @@ let dir; | ||
| }; | ||
| async function infoCommand(spec, opts) { | ||
| async function infoCommand(spec) { | ||
| if (!loadCredentials()) { | ||
@@ -929,3 +941,3 @@ console.log(pc.yellow("Not logged in. Run: agentops login")); | ||
| } | ||
| const baseUrl = getBaseUrl(opts.url); | ||
| const baseUrl = getBaseUrl(); | ||
| if (typeof parsed.version === "number") await renderPinnedVersion(parsed.name, parsed.version, baseUrl); | ||
@@ -1035,3 +1047,3 @@ else await renderLatest(parsed.name, baseUrl); | ||
| //#region src/commands/uninstall.ts | ||
| async function uninstallCommand(name, opts) { | ||
| async function uninstallCommand(name) { | ||
| if (!loadCredentials()) { | ||
@@ -1041,3 +1053,3 @@ console.log(pc.yellow("Not logged in. Run: agentops login")); | ||
| } | ||
| const baseUrl = getBaseUrl(opts.url); | ||
| const baseUrl = getBaseUrl(); | ||
| const res = await del(`/api/user/skills/${encodeURIComponent(name)}`, baseUrl); | ||
@@ -1047,3 +1059,3 @@ if (!res.ok) { | ||
| console.error(pc.red(err.error?.message ?? `Error: ${res.status}`)); | ||
| if (err.error?.code === "not_found") console.log(pc.dim(` Check your installed skills: agentops skills list`)); | ||
| if (err.error?.code === "not_found") console.log(pc.dim(` Check your installed skills: agentops skills installed`)); | ||
| process.exit(1); | ||
@@ -1055,4 +1067,4 @@ } | ||
| //#endregion | ||
| //#region src/commands/list.ts | ||
| async function listCommand() { | ||
| //#region src/commands/installed.ts | ||
| async function installedCommand() { | ||
| let result; | ||
@@ -1313,3 +1325,3 @@ try { | ||
| const { dir, frontmatter, content } = skill; | ||
| const baseUrl = getBaseUrl(opts.url); | ||
| const baseUrl = getBaseUrl(); | ||
| const check = validateSkill(dir); | ||
@@ -1341,3 +1353,3 @@ if (check.errors.length > 0) { | ||
| console.log(pc.dim(" Wait for an admin to approve or reject, then you can edit again.")); | ||
| console.log(pc.dim(" Check status: agentops skills authored")); | ||
| console.log(pc.dim(" Check status: agentops skills mine")); | ||
| process.exit(1); | ||
@@ -1385,7 +1397,7 @@ } | ||
| } else console.log(pc.green(`✓ "${frontmatter.name}" submitted for review${tagList}`)); | ||
| console.log(pc.dim(` Check status: agentops skills authored`)); | ||
| console.log(pc.dim(` Check status: agentops skills mine`)); | ||
| } | ||
| } | ||
| //#endregion | ||
| //#region src/commands/authored.ts | ||
| //#region src/commands/mine.ts | ||
| const STATUS_COLORS = { | ||
@@ -1398,3 +1410,3 @@ draft: pc.dim, | ||
| }; | ||
| async function authoredCommand(opts) { | ||
| async function mineCommand() { | ||
| if (!loadCredentials()) { | ||
@@ -1404,3 +1416,3 @@ console.log(pc.yellow("Not logged in. Run: agentops login")); | ||
| } | ||
| const res = await get("/api/user/skills", getBaseUrl(opts.url)); | ||
| const res = await get("/api/user/skills", getBaseUrl()); | ||
| if (!res.ok) { | ||
@@ -1430,4 +1442,4 @@ const err = await res.json(); | ||
| //#endregion | ||
| //#region src/commands/publish.ts | ||
| async function publishCommand(name, opts) { | ||
| //#region src/commands/approve.ts | ||
| async function approveCommand(name) { | ||
| const creds = loadCredentials(); | ||
@@ -1439,7 +1451,7 @@ if (!creds) { | ||
| if (creds.user.role !== "admin") { | ||
| console.error(pc.red("Only admins can publish skills.")); | ||
| console.log(pc.dim(" Ask an admin to run: agentops skills publish " + name)); | ||
| console.error(pc.red("Only admins can approve skills.")); | ||
| console.log(pc.dim(" Ask an admin to run: agentops skills approve " + name)); | ||
| process.exit(1); | ||
| } | ||
| const baseUrl = getBaseUrl(opts.url); | ||
| const baseUrl = getBaseUrl(); | ||
| const res = await put(`/api/skills/${encodeURIComponent(name)}/publish`, {}, baseUrl); | ||
@@ -1449,7 +1461,7 @@ if (!res.ok) { | ||
| console.error(pc.red(err.error?.message ?? `Error: ${res.status}`)); | ||
| if (err.error?.code === "invalid_state") console.log(pc.dim(" Only \"submitted\" skills can be published. Check status: agentops skills authored")); | ||
| if (err.error?.code === "invalid_state") console.log(pc.dim(" Only \"submitted\" skills can be approved. Check status: agentops skills mine")); | ||
| else if (err.error?.code === "not_found") console.log(pc.dim(` Skill not found. Search: agentops skills search ${name}`)); | ||
| process.exit(1); | ||
| } | ||
| console.log(pc.green(`✓ "${name}" published — available to the org now.`)); | ||
| console.log(pc.green(`✓ "${name}" approved — now live for the org.`)); | ||
| console.log(pc.dim(` Install: agentops skills install ${name}`)); | ||
@@ -1474,3 +1486,3 @@ } | ||
| } | ||
| const baseUrl = getBaseUrl(opts.url); | ||
| const baseUrl = getBaseUrl(); | ||
| const res = await put(`/api/skills/${encodeURIComponent(name)}/reject`, { comment: opts.comment }, baseUrl); | ||
@@ -1488,3 +1500,3 @@ if (!res.ok) { | ||
| //#region src/commands/whoami.ts | ||
| async function whoamiCommand(opts) { | ||
| async function whoamiCommand() { | ||
| const creds = loadCredentials(); | ||
@@ -1495,3 +1507,3 @@ if (!creds) { | ||
| } | ||
| const res = await get("/api/me", getBaseUrl(opts.url)); | ||
| const res = await get("/api/me", getBaseUrl()); | ||
| if (!res.ok) { | ||
@@ -1529,3 +1541,3 @@ console.log(`${pc.bold(creds.user.email)} (${creds.org.name})`); | ||
| //#region src/commands/history.ts | ||
| async function historyCommand(name, opts) { | ||
| async function historyCommand(name) { | ||
| if (!loadCredentials()) { | ||
@@ -1535,3 +1547,3 @@ console.log(pc.yellow("Not logged in. Run: agentops login")); | ||
| } | ||
| const baseUrl = getBaseUrl(opts.url); | ||
| const baseUrl = getBaseUrl(); | ||
| const res = await get(`/api/skills/${encodeURIComponent(name)}/versions`, baseUrl); | ||
@@ -1568,3 +1580,3 @@ if (!res.ok) { | ||
| //#region src/commands/rollback.ts | ||
| async function rollbackCommand(spec, opts) { | ||
| async function rollbackCommand(spec) { | ||
| if (!loadCredentials()) { | ||
@@ -1586,3 +1598,3 @@ console.log(pc.yellow("Not logged in. Run: agentops login")); | ||
| } | ||
| const baseUrl = getBaseUrl(opts.url); | ||
| const baseUrl = getBaseUrl(); | ||
| console.log(pc.dim(`Rolling back "${parsed.name}" to v${parsed.version}...`)); | ||
@@ -1623,3 +1635,3 @@ const res = await post(`/api/skills/${encodeURIComponent(parsed.name)}/rollback`, { version: parsed.version }, baseUrl); | ||
| } | ||
| const baseUrl = getBaseUrl(opts.url); | ||
| const baseUrl = getBaseUrl(); | ||
| const res = await del(`/api/skills/${encodeURIComponent(name)}`, baseUrl); | ||
@@ -1641,4 +1653,4 @@ if (!res.ok) { | ||
| program.name("agentops").description("AgentOps CLI — setup and manage your AI agent skills").version(pkg.version); | ||
| program.command("login").description("Authenticate with AgentOps via your browser").option("--url <url>", "AgentOps server URL").action(loginCommand); | ||
| program.command("setup").description("Configure your editor (claude, cursor, codex, windsurf, copilot, gemini)").requiredOption("--editor <editor>", "Editor to configure (claude, cursor, codex, windsurf, copilot, gemini)").option("--url <url>", "AgentOps server URL").action(setupCommand); | ||
| program.command("login").description("Authenticate with AgentOps via your browser").action(loginCommand); | ||
| program.command("setup").description("Configure your editor (claude, cursor, codex, windsurf, copilot, gemini)").requiredOption("--editor <editor>", "Editor to configure (claude, cursor, codex, windsurf, copilot, gemini)").action(setupCommand); | ||
| program.command("logout").description("Clear saved credentials").action(() => { | ||
@@ -1648,20 +1660,20 @@ clearCredentials(); | ||
| }); | ||
| program.command("whoami").description("Show current user, plan, and usage").option("--url <url>", "AgentOps server URL").action(whoamiCommand); | ||
| program.command("whoami").description("Show current user, plan, and usage").action(whoamiCommand); | ||
| const skills = program.command("skills").description("Manage org skills — search, install, create, submit, version"); | ||
| skills.command("search [query]").description("Search the org skill library").option("--url <url>", "AgentOps server URL").option("--tags [tags]", "List all tags (no value) or filter by tags (comma-separated)").option("--authors", "List all skill authors").option("--author <name>", "Filter by author name").option("--status <status>", "Filter by status (admin only)").action(searchCommand); | ||
| skills.command("info <spec>").description("Show details for a skill — use <name> for latest or <name>@v1 for a specific version").option("--url <url>", "AgentOps server URL").action(infoCommand); | ||
| skills.command("install <spec>").description("Install a skill — use <name> for latest or <name>@v2 to pin a version").option("--url <url>", "AgentOps server URL").option("--user", "Install to user-level (available in all projects)").option("--project", "Install to project-level (default)").option("--force", "Overwrite existing skill").action(installCommand); | ||
| skills.command("uninstall <name>").description("Uninstall a personal skill").option("--url <url>", "AgentOps server URL").action(uninstallCommand); | ||
| skills.command("list").description("Show installed skills (project + user)").action(listCommand); | ||
| skills.command("search [query]").description("Search the org skill library").option("--tags [tags]", "List all tags (no value) or filter by tags (comma-separated)").option("--authors", "List all skill authors").option("--author <name>", "Filter by author name").option("--status <status>", "Filter by status (admin only)").action(searchCommand); | ||
| skills.command("info <spec>").description("Show details for a skill — use <name> for latest or <name>@v1 for a specific version").action(infoCommand); | ||
| skills.command("install <spec>").description("Install a skill — use <name> for latest or <name>@v2 to pin a version").option("--user", "Install to user-level (available in all projects)").option("--project", "Install to project-level (default)").option("--force", "Overwrite existing skill").action(installCommand); | ||
| skills.command("uninstall <name>").description("Uninstall a personal skill").action(uninstallCommand); | ||
| skills.command("installed").description("Show skills installed locally (project + user scopes)").action(installedCommand); | ||
| skills.command("create [name]").description("Scaffold a new skill locally").option("--tags <tags>", "Tags for discovery (comma-separated)").option("--user", "Create at user-level (available in all projects)").option("--project", "Create at project-level (default)").action(createCommand); | ||
| skills.command("check <name>").description("Check a local skill for issues before submitting").action(checkCommand); | ||
| skills.command("submit <name>").description("Publish a skill — creates a new version each time").option("--url <url>", "AgentOps server URL").option("--tags <tags>", "Tags for discovery (comma-separated)").action(submitCommand); | ||
| skills.command("history <name>").description("Show version history for a skill").option("--url <url>", "AgentOps server URL").action(historyCommand); | ||
| skills.command("rollback <spec>").description("Re-publish an older version as the new latest — use <name>@v<N> (pro+)").option("--url <url>", "AgentOps server URL").action(rollbackCommand); | ||
| skills.command("authored").description("Show skills you've authored (draft, submitted, published, rejected)").option("--url <url>", "AgentOps server URL").action(authoredCommand); | ||
| skills.command("publish <name>").description("Publish a submitted skill (admin only)").option("--url <url>", "AgentOps server URL").action(publishCommand); | ||
| skills.command("reject <name>").description("Reject a submitted skill (admin only)").requiredOption("--comment <comment>", "Reason for rejection").option("--url <url>", "AgentOps server URL").action(rejectCommand); | ||
| skills.command("delete <name>").description("Permanently delete a skill and all its versions (admin only)").option("--force", "Confirm the deletion").option("--url <url>", "AgentOps server URL").action(deleteCommand); | ||
| skills.command("submit <name>").description("Publish a skill — creates a new version each time").option("--tags <tags>", "Tags for discovery (comma-separated)").action(submitCommand); | ||
| skills.command("history <name>").description("Show version history for a skill").action(historyCommand); | ||
| skills.command("rollback <spec>").description("Re-publish an older version as the new latest — use <name>@v<N> (pro+)").action(rollbackCommand); | ||
| skills.command("mine").description("Show skills you've authored (draft, submitted, published, rejected)").action(mineCommand); | ||
| skills.command("approve <name>").description("Approve a submitted skill — makes it live for the org (admin only)").action(approveCommand); | ||
| skills.command("reject <name>").description("Reject a submitted skill (admin only)").requiredOption("--comment <comment>", "Reason for rejection").action(rejectCommand); | ||
| skills.command("delete <name>").description("Permanently delete a skill and all its versions (admin only)").option("--force", "Confirm the deletion").action(deleteCommand); | ||
| program.parse(); | ||
| //#endregion | ||
| export {}; |
+1
-1
| { | ||
| "name": "@bonnard/agentops", | ||
| "version": "0.7.8", | ||
| "version": "0.7.9", | ||
| "type": "module", | ||
@@ -5,0 +5,0 @@ "bin": { |
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
1649
0.67%62749
-0.43%2
100%