@topolo/cli 0.12.33 → 0.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +45 -0
- package/agent-packs/README.md +495 -0
- package/agent-packs/pyproject.toml +16 -0
- package/agent-packs/requirements-test.txt +1 -0
- package/agent-packs/src/topolo_agent_pack/__init__.py +1 -0
- package/agent-packs/src/topolo_agent_pack/blueprint.py +57 -0
- package/agent-packs/src/topolo_agent_pack/claude.py +265 -0
- package/agent-packs/src/topolo_agent_pack/cli.py +443 -0
- package/agent-packs/src/topolo_agent_pack/execution.py +154 -0
- package/agent-packs/src/topolo_agent_pack/fresh.py +158 -0
- package/agent-packs/src/topolo_agent_pack/live.py +403 -0
- package/agent-packs/src/topolo_agent_pack/native.py +645 -0
- package/agent-packs/src/topolo_agent_pack/policy.py +92 -0
- package/agent-packs/src/topolo_agent_pack/storage.py +271 -0
- package/agent-packs/src/topolo_agent_pack/topolo.py +321 -0
- package/agent-packs/templates/career/AGENTS.md +17 -0
- package/agent-packs/templates/career/README.md +14 -0
- package/agent-packs/templates/career/agents/intakes/career-intake/AGENTS.md +21 -0
- package/agent-packs/templates/career/agents/specialists/application-preparation/AGENTS.md +21 -0
- package/agent-packs/templates/career/agents/specialists/application-tracker/AGENTS.md +21 -0
- package/agent-packs/templates/career/agents/specialists/interview-coach/AGENTS.md +21 -0
- package/agent-packs/templates/career/agents/specialists/opportunity-research/AGENTS.md +21 -0
- package/agent-packs/templates/career/agents/specialists/profile-cv/AGENTS.md +21 -0
- package/agent-packs/templates/career/pack.json +124 -0
- package/agent-packs/templates/career/shared/PACK.md +22 -0
- package/agent-packs/templates/career/shared/TOPOLO.md +13 -0
- package/agent-packs/templates/career/shared/WORKFLOW.md +13 -0
- package/agent-packs/templates/career/skills/topolo/SKILL.md +305 -0
- package/agent-packs/templates/clients/AGENTS.md +17 -0
- package/agent-packs/templates/clients/README.md +14 -0
- package/agent-packs/templates/clients/agents/intakes/client-intake/AGENTS.md +21 -0
- package/agent-packs/templates/clients/agents/specialists/acceptance-review/AGENTS.md +21 -0
- package/agent-packs/templates/clients/agents/specialists/delivery-planner/AGENTS.md +21 -0
- package/agent-packs/templates/clients/agents/specialists/discovery/AGENTS.md +21 -0
- package/agent-packs/templates/clients/agents/specialists/proposal-writer/AGENTS.md +21 -0
- package/agent-packs/templates/clients/agents/specialists/solution-design/AGENTS.md +21 -0
- package/agent-packs/templates/clients/pack.json +126 -0
- package/agent-packs/templates/clients/shared/PACK.md +22 -0
- package/agent-packs/templates/clients/shared/TOPOLO.md +13 -0
- package/agent-packs/templates/clients/shared/WORKFLOW.md +13 -0
- package/agent-packs/templates/clients/skills/topolo/SKILL.md +305 -0
- package/agent-packs/templates/creative/AGENTS.md +17 -0
- package/agent-packs/templates/creative/README.md +14 -0
- package/agent-packs/templates/creative/agents/intakes/creative-director/AGENTS.md +21 -0
- package/agent-packs/templates/creative/agents/specialists/brand-copy/AGENTS.md +21 -0
- package/agent-packs/templates/creative/agents/specialists/media-production/AGENTS.md +21 -0
- package/agent-packs/templates/creative/agents/specialists/quality-review/AGENTS.md +21 -0
- package/agent-packs/templates/creative/agents/specialists/storytelling/AGENTS.md +21 -0
- package/agent-packs/templates/creative/agents/specialists/visual-design/AGENTS.md +21 -0
- package/agent-packs/templates/creative/pack.json +128 -0
- package/agent-packs/templates/creative/shared/PACK.md +22 -0
- package/agent-packs/templates/creative/shared/TOPOLO.md +13 -0
- package/agent-packs/templates/creative/shared/WORKFLOW.md +13 -0
- package/agent-packs/templates/creative/skills/topolo/SKILL.md +305 -0
- package/agent-packs/templates/founder/AGENTS.md +17 -0
- package/agent-packs/templates/founder/README.md +14 -0
- package/agent-packs/templates/founder/agents/intakes/founder-intake/AGENTS.md +21 -0
- package/agent-packs/templates/founder/agents/specialists/commercial-modelling/AGENTS.md +21 -0
- package/agent-packs/templates/founder/agents/specialists/customer-research/AGENTS.md +21 -0
- package/agent-packs/templates/founder/agents/specialists/decision-review/AGENTS.md +21 -0
- package/agent-packs/templates/founder/agents/specialists/partnerships/AGENTS.md +21 -0
- package/agent-packs/templates/founder/agents/specialists/strategy/AGENTS.md +21 -0
- package/agent-packs/templates/founder/pack.json +126 -0
- package/agent-packs/templates/founder/shared/PACK.md +22 -0
- package/agent-packs/templates/founder/shared/TOPOLO.md +13 -0
- package/agent-packs/templates/founder/shared/WORKFLOW.md +13 -0
- package/agent-packs/templates/founder/skills/topolo/SKILL.md +305 -0
- package/agent-packs/templates/learning/AGENTS.md +17 -0
- package/agent-packs/templates/learning/README.md +14 -0
- package/agent-packs/templates/learning/agents/intakes/learning-intake/AGENTS.md +21 -0
- package/agent-packs/templates/learning/agents/specialists/critical-reviewer/AGENTS.md +21 -0
- package/agent-packs/templates/learning/agents/specialists/curriculum-designer/AGENTS.md +21 -0
- package/agent-packs/templates/learning/agents/specialists/knowledge-steward/AGENTS.md +21 -0
- package/agent-packs/templates/learning/agents/specialists/practice-coach/AGENTS.md +21 -0
- package/agent-packs/templates/learning/agents/specialists/tutor/AGENTS.md +21 -0
- package/agent-packs/templates/learning/pack.json +124 -0
- package/agent-packs/templates/learning/shared/PACK.md +22 -0
- package/agent-packs/templates/learning/shared/TOPOLO.md +13 -0
- package/agent-packs/templates/learning/shared/WORKFLOW.md +13 -0
- package/agent-packs/templates/learning/skills/topolo/SKILL.md +305 -0
- package/agent-packs/templates/personal/AGENTS.md +17 -0
- package/agent-packs/templates/personal/README.md +14 -0
- package/agent-packs/templates/personal/agents/intakes/personal-intake/AGENTS.md +21 -0
- package/agent-packs/templates/personal/agents/specialists/correspondence/AGENTS.md +21 -0
- package/agent-packs/templates/personal/agents/specialists/document-assistant/AGENTS.md +21 -0
- package/agent-packs/templates/personal/agents/specialists/planning/AGENTS.md +21 -0
- package/agent-packs/templates/personal/agents/specialists/research/AGENTS.md +21 -0
- package/agent-packs/templates/personal/agents/specialists/travel-logistics/AGENTS.md +21 -0
- package/agent-packs/templates/personal/pack.json +125 -0
- package/agent-packs/templates/personal/shared/PACK.md +22 -0
- package/agent-packs/templates/personal/shared/TOPOLO.md +13 -0
- package/agent-packs/templates/personal/shared/WORKFLOW.md +13 -0
- package/agent-packs/templates/personal/skills/topolo/SKILL.md +305 -0
- package/agent-packs/templates/research/AGENTS.md +17 -0
- package/agent-packs/templates/research/README.md +14 -0
- package/agent-packs/templates/research/agents/intakes/research-intake/AGENTS.md +21 -0
- package/agent-packs/templates/research/agents/specialists/adversarial-review/AGENTS.md +21 -0
- package/agent-packs/templates/research/agents/specialists/data-analysis/AGENTS.md +21 -0
- package/agent-packs/templates/research/agents/specialists/source-research/AGENTS.md +21 -0
- package/agent-packs/templates/research/agents/specialists/synthesis/AGENTS.md +21 -0
- package/agent-packs/templates/research/agents/specialists/technical-research/AGENTS.md +21 -0
- package/agent-packs/templates/research/pack.json +124 -0
- package/agent-packs/templates/research/shared/PACK.md +22 -0
- package/agent-packs/templates/research/shared/TOPOLO.md +13 -0
- package/agent-packs/templates/research/shared/WORKFLOW.md +13 -0
- package/agent-packs/templates/research/skills/topolo/SKILL.md +305 -0
- package/agent-packs/templates/ventures/AGENTS.md +17 -0
- package/agent-packs/templates/ventures/README.md +14 -0
- package/agent-packs/templates/ventures/agents/intakes/venture-intake/AGENTS.md +21 -0
- package/agent-packs/templates/ventures/agents/specialists/customer-discovery/AGENTS.md +21 -0
- package/agent-packs/templates/ventures/agents/specialists/economics/AGENTS.md +21 -0
- package/agent-packs/templates/ventures/agents/specialists/experiment-design/AGENTS.md +21 -0
- package/agent-packs/templates/ventures/agents/specialists/market-research/AGENTS.md +21 -0
- package/agent-packs/templates/ventures/agents/specialists/product-concept/AGENTS.md +21 -0
- package/agent-packs/templates/ventures/pack.json +126 -0
- package/agent-packs/templates/ventures/shared/PACK.md +22 -0
- package/agent-packs/templates/ventures/shared/TOPOLO.md +13 -0
- package/agent-packs/templates/ventures/shared/WORKFLOW.md +13 -0
- package/agent-packs/templates/ventures/skills/topolo/SKILL.md +305 -0
- package/agent-packs/topolo-agent-pack +8 -0
- package/dist/claude-pack-backend-IDQQX3DG.js +555 -0
- package/dist/index.js +143 -58
- package/package.json +7 -4
package/dist/index.js
CHANGED
|
@@ -1,5 +1,86 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
// src/commands/agent-packs.ts
|
|
4
|
+
import { spawnSync } from "child_process";
|
|
5
|
+
import { existsSync } from "fs";
|
|
6
|
+
import { dirname, resolve } from "path";
|
|
7
|
+
import { fileURLToPath } from "url";
|
|
8
|
+
import { homedir } from "os";
|
|
9
|
+
function registerAgentPacksCommand(program2) {
|
|
10
|
+
const packs = program2.command("agent-packs").description("Install and operate Topolo Agent Packs in supported local hosts").option("--store <path>", "Portable pack library (default ~/AgentPacks)");
|
|
11
|
+
packs.command("configure").description("Qualify and configure an adopted Claude roster through its live native backend").argument("<pack>").option("--harness <name>", "Host adapter", "claude").requiredOption("--policy <path>", "Reviewed execution policy JSON").requiredOption("--endpoint <url>", "Explicit loopback main-process inspector endpoint, enabled separately with authorization").requiredOption("--pid <pid>", "Expected Claude main-process PID").option("--apply", "Apply native groups, pins, models, effort and permission modes; otherwise preflight only").action(async (pack, options) => {
|
|
12
|
+
if (options.harness !== "claude") throw new Error("Native configure is currently qualified only for Claude Desktop.");
|
|
13
|
+
const { configureClaudePack } = await import("./claude-pack-backend-IDQQX3DG.js");
|
|
14
|
+
const result = await configureClaudePack({
|
|
15
|
+
store: packs.opts().store ?? resolve(homedir(), "AgentPacks"),
|
|
16
|
+
pack,
|
|
17
|
+
policy: options.policy,
|
|
18
|
+
endpoint: options.endpoint,
|
|
19
|
+
pid: Number(options.pid),
|
|
20
|
+
apply: options.apply === true
|
|
21
|
+
});
|
|
22
|
+
console.log(JSON.stringify(result, null, 2));
|
|
23
|
+
});
|
|
24
|
+
const commands = [
|
|
25
|
+
"add",
|
|
26
|
+
"replace",
|
|
27
|
+
"switch",
|
|
28
|
+
"capture",
|
|
29
|
+
"build",
|
|
30
|
+
"install",
|
|
31
|
+
"export",
|
|
32
|
+
"status",
|
|
33
|
+
"list",
|
|
34
|
+
"recover",
|
|
35
|
+
"doctor",
|
|
36
|
+
"policy",
|
|
37
|
+
"remote-recover",
|
|
38
|
+
"connect",
|
|
39
|
+
"remote-context",
|
|
40
|
+
"remember",
|
|
41
|
+
"artifact",
|
|
42
|
+
"artifact-get"
|
|
43
|
+
];
|
|
44
|
+
for (const name of commands) {
|
|
45
|
+
const command = packs.command(name).description(name === "add" ? "Add an installed or bundled pack, group, or agent" : `Run the pack ${name} operation`);
|
|
46
|
+
if (name === "switch" || name === "recover") command.option("--policy <path>", "Reviewed policy for an adopted Claude roster").option("--endpoint <url>", "Explicit authorized Claude main-process inspector endpoint").option("--pid <pid>", "Expected Claude main-process PID").option("--apply", "Apply a native switch; recovery is always read-only");
|
|
47
|
+
command.option("--harness <name>", "Local host adapter (codex, claude Desktop Code sessions)", "codex").option("--adapter-help", "Show every option supported by the selected adapter").argument("[arguments...]").allowUnknownOption().allowExcessArguments().addHelpText("after", name === "add" ? "\nExamples:\n topolo agent-packs add founder\n topolo agent-packs add founder --group specialists\n topolo agent-packs add founder --agent strategy\n" : "\nRun topolo agent-packs <command> --adapter-help for all adapter options. Cloud commands require explicit --environment and --context-key.\n").action(async (args, options) => {
|
|
48
|
+
if (!["codex", "claude"].includes(options.harness)) throw new Error(`The ${options.harness} pack adapter is not available. Supported adapters: codex, claude.`);
|
|
49
|
+
if (options.policy || options.endpoint || options.pid || options.apply) {
|
|
50
|
+
if (options.harness !== "claude" || !options.policy || !options.endpoint || !options.pid || args.length !== 1)
|
|
51
|
+
throw new Error("Native switch/recovery requires one Claude pack, --policy, --endpoint and --pid.");
|
|
52
|
+
const { configureClaudePack } = await import("./claude-pack-backend-IDQQX3DG.js");
|
|
53
|
+
const result2 = await configureClaudePack({
|
|
54
|
+
store: packs.opts().store ?? resolve(homedir(), "AgentPacks"),
|
|
55
|
+
pack: args[0],
|
|
56
|
+
policy: options.policy,
|
|
57
|
+
endpoint: options.endpoint,
|
|
58
|
+
pid: Number(options.pid),
|
|
59
|
+
mode: name,
|
|
60
|
+
apply: options.apply === true
|
|
61
|
+
});
|
|
62
|
+
console.log(JSON.stringify(result2, null, 2));
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
66
|
+
const adapter = [resolve(here, "../agent-packs/topolo-agent-pack"), resolve(here, "../../agent-packs/topolo-agent-pack")].find(existsSync);
|
|
67
|
+
if (!adapter) throw new Error("This CLI installation is missing its bundled Topolo Agent Pack adapter. Reinstall @topolo/cli.");
|
|
68
|
+
const store = packs.opts().store;
|
|
69
|
+
const forwarded = (options.adapterHelp ? ["--help"] : args).map((value) => value === "--group" ? "--set" : value);
|
|
70
|
+
const result = spawnSync("python3", [
|
|
71
|
+
adapter,
|
|
72
|
+
...store ? ["--store", store] : [],
|
|
73
|
+
...options.harness === "claude" ? ["--harness", "claude"] : [],
|
|
74
|
+
name,
|
|
75
|
+
...forwarded,
|
|
76
|
+
...name === "add" && !options.adapterHelp ? ["--catalog"] : []
|
|
77
|
+
], { stdio: "inherit", env: { ...process.env, PYTHONDONTWRITEBYTECODE: "1", TOPOLO_AGENT_PACK_PUBLIC_CLI: "1" } });
|
|
78
|
+
if (result.error) throw new Error(`Python 3.11 or later is required for local packs: ${result.error.message}`);
|
|
79
|
+
if (result.status !== 0) process.exitCode = result.status ?? 2;
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
3
84
|
// src/index.ts
|
|
4
85
|
import { Command, Help } from "commander";
|
|
5
86
|
|
|
@@ -1592,7 +1673,7 @@ var TopoloClient = class _TopoloClient {
|
|
|
1592
1673
|
} catch (error) {
|
|
1593
1674
|
const transportFailure = !(error instanceof TopoloSdkError) && !opts.signal?.aborted;
|
|
1594
1675
|
if (!transportFailure || attempt === maxAttempts) throw error;
|
|
1595
|
-
await new Promise((
|
|
1676
|
+
await new Promise((resolve4) => setTimeout(resolve4, 250));
|
|
1596
1677
|
}
|
|
1597
1678
|
}
|
|
1598
1679
|
throw new TopoloSdkError("network_error", "Topolo read retry loop exhausted.");
|
|
@@ -3582,7 +3663,7 @@ function createTopolo(options) {
|
|
|
3582
3663
|
async function pollUntilApproved(params) {
|
|
3583
3664
|
let interval = Math.max(params.intervalSeconds ?? 5, 1);
|
|
3584
3665
|
while (Date.now() < params.expiresAtMs) {
|
|
3585
|
-
await new Promise((
|
|
3666
|
+
await new Promise((resolve4) => setTimeout(resolve4, Math.min(interval * 1e3, params.expiresAtMs - Date.now())));
|
|
3586
3667
|
if (Date.now() >= params.expiresAtMs) break;
|
|
3587
3668
|
try {
|
|
3588
3669
|
return await params.oauth.pollDeviceToken({
|
|
@@ -3617,11 +3698,11 @@ import { homedir as homedir2, platform } from "os";
|
|
|
3617
3698
|
import { dirname as dirname2, join as join3 } from "path";
|
|
3618
3699
|
import { createHash, randomUUID } from "crypto";
|
|
3619
3700
|
import { join as join2 } from "path";
|
|
3620
|
-
import { spawnSync } from "child_process";
|
|
3701
|
+
import { spawnSync as spawnSync2 } from "child_process";
|
|
3621
3702
|
import { mkdir, readFile, readdir, rename, rm, writeFile, chmod } from "fs/promises";
|
|
3622
|
-
import { existsSync } from "fs";
|
|
3623
|
-
import { homedir, platform as hostPlatform } from "os";
|
|
3624
|
-
import { dirname, join } from "path";
|
|
3703
|
+
import { existsSync as existsSync3 } from "fs";
|
|
3704
|
+
import { homedir as homedir3, platform as hostPlatform } from "os";
|
|
3705
|
+
import { dirname as dirname3, join } from "path";
|
|
3625
3706
|
var TopoloSdkError2 = class extends Error {
|
|
3626
3707
|
code;
|
|
3627
3708
|
constructor(code, message2) {
|
|
@@ -4050,7 +4131,7 @@ var MACOS_KEYCHAIN_WRITE_SCRIPT = [
|
|
|
4050
4131
|
function installationStorePath() {
|
|
4051
4132
|
const override = process.env.TOPOLO_INSTALLATIONS_PATH?.trim();
|
|
4052
4133
|
if (override) return override;
|
|
4053
|
-
const base = process.env.XDG_CONFIG_HOME || (hostPlatform() === "win32" ? join(
|
|
4134
|
+
const base = process.env.XDG_CONFIG_HOME || (hostPlatform() === "win32" ? join(homedir3(), "AppData", "Roaming") : join(homedir3(), ".config"));
|
|
4054
4135
|
return join(base, "topolo", "installations");
|
|
4055
4136
|
}
|
|
4056
4137
|
function installationPath(environment, id) {
|
|
@@ -4068,7 +4149,7 @@ function runOrThrow(result, operation) {
|
|
|
4068
4149
|
}
|
|
4069
4150
|
function createPlatformInstallationSecretBackend(options = {}) {
|
|
4070
4151
|
const platform22 = options.platform ?? hostPlatform();
|
|
4071
|
-
const spawn3 = options.spawn ?? ((command, args, spawnOptions) =>
|
|
4152
|
+
const spawn3 = options.spawn ?? ((command, args, spawnOptions) => spawnSync2(command, args, spawnOptions));
|
|
4072
4153
|
const root = options.root ?? installationStorePath();
|
|
4073
4154
|
const service = options.service ?? KEYCHAIN_SERVICE;
|
|
4074
4155
|
if (platform22 === "darwin") {
|
|
@@ -4187,13 +4268,13 @@ function createPlatformInstallationSecretBackend(options = {}) {
|
|
|
4187
4268
|
return {
|
|
4188
4269
|
async set(account, value) {
|
|
4189
4270
|
const path = secretPath(account);
|
|
4190
|
-
await mkdir(
|
|
4271
|
+
await mkdir(dirname3(path), { recursive: true });
|
|
4191
4272
|
const script = "$p=$env:TOPOLO_SECRET_PATH;$v=[Console]::In.ReadToEnd();$b=[Text.Encoding]::UTF8.GetBytes($v);$e=[Security.Cryptography.ProtectedData]::Protect($b,$null,[Security.Cryptography.DataProtectionScope]::CurrentUser);[IO.File]::WriteAllBytes($p,$e)";
|
|
4192
4273
|
runOrThrow(powershell(script, path, value), "Windows DPAPI write");
|
|
4193
4274
|
},
|
|
4194
4275
|
async get(account) {
|
|
4195
4276
|
const path = secretPath(account);
|
|
4196
|
-
if (!
|
|
4277
|
+
if (!existsSync3(path)) return null;
|
|
4197
4278
|
const script = "$p=$env:TOPOLO_SECRET_PATH;$b=[IO.File]::ReadAllBytes($p);$d=[Security.Cryptography.ProtectedData]::Unprotect($b,$null,[Security.Cryptography.DataProtectionScope]::CurrentUser);[Console]::Out.Write([Text.Encoding]::UTF8.GetString($d))";
|
|
4198
4279
|
return runOrThrow(powershell(script, path), "Windows DPAPI read");
|
|
4199
4280
|
},
|
|
@@ -4209,7 +4290,7 @@ async function writeExternalAgentInstallation(installation, secret, backend = cr
|
|
|
4209
4290
|
await backend.set(accountName(installation.environment, installation.id), JSON.stringify(secret));
|
|
4210
4291
|
const temporary = `${path}.${process.pid}.tmp`;
|
|
4211
4292
|
try {
|
|
4212
|
-
await mkdir(
|
|
4293
|
+
await mkdir(dirname3(path), { recursive: true, mode: 448 });
|
|
4213
4294
|
await writeFile(temporary, `${JSON.stringify(installation, null, 2)}
|
|
4214
4295
|
`, { encoding: "utf8", mode: 384 });
|
|
4215
4296
|
await rename(temporary, path);
|
|
@@ -4222,7 +4303,7 @@ async function writeExternalAgentInstallation(installation, secret, backend = cr
|
|
|
4222
4303
|
}
|
|
4223
4304
|
async function listExternalAgentInstallations(environment) {
|
|
4224
4305
|
const directory = join(installationStorePath(), environment);
|
|
4225
|
-
if (!
|
|
4306
|
+
if (!existsSync3(directory)) return [];
|
|
4226
4307
|
const entries = await readdir(directory, { withFileTypes: true });
|
|
4227
4308
|
const installations = await Promise.all(entries.filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map(async (entry) => JSON.parse(await readFile(join(directory, entry.name), "utf8"))));
|
|
4228
4309
|
return installations.sort((left, right) => left.createdAt.localeCompare(right.createdAt));
|
|
@@ -4493,7 +4574,7 @@ async function withConfigWriteLock(operation) {
|
|
|
4493
4574
|
if (Date.now() - startedAt >= CONFIG_LOCK_TIMEOUT_MS) {
|
|
4494
4575
|
throw new Error(`Timed out waiting for credential configuration lock at ${lockPath}.`);
|
|
4495
4576
|
}
|
|
4496
|
-
await new Promise((
|
|
4577
|
+
await new Promise((resolve4) => setTimeout(resolve4, CONFIG_LOCK_RETRY_MS));
|
|
4497
4578
|
}
|
|
4498
4579
|
}
|
|
4499
4580
|
try {
|
|
@@ -4765,11 +4846,11 @@ function normalizeError(err) {
|
|
|
4765
4846
|
|
|
4766
4847
|
// src/version.ts
|
|
4767
4848
|
import { readFileSync } from "fs";
|
|
4768
|
-
import { dirname as
|
|
4769
|
-
import { fileURLToPath } from "url";
|
|
4849
|
+
import { dirname as dirname4, join as join4 } from "path";
|
|
4850
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
4770
4851
|
function readCliVersion() {
|
|
4771
4852
|
try {
|
|
4772
|
-
const here =
|
|
4853
|
+
const here = dirname4(fileURLToPath2(import.meta.url));
|
|
4773
4854
|
const candidates = [
|
|
4774
4855
|
join4(here, "package.json"),
|
|
4775
4856
|
join4(here, "..", "package.json")
|
|
@@ -6076,19 +6157,19 @@ function formatCheckResult(result) {
|
|
|
6076
6157
|
}
|
|
6077
6158
|
|
|
6078
6159
|
// src/commands/skills.ts
|
|
6079
|
-
import { spawnSync as
|
|
6080
|
-
import { existsSync as
|
|
6160
|
+
import { spawnSync as spawnSync4 } from "child_process";
|
|
6161
|
+
import { existsSync as existsSync6 } from "fs";
|
|
6081
6162
|
import { readFile as readFile6, rm as rm3 } from "fs/promises";
|
|
6082
|
-
import { homedir as
|
|
6083
|
-
import { dirname as
|
|
6084
|
-
import { fileURLToPath as
|
|
6163
|
+
import { homedir as homedir5 } from "os";
|
|
6164
|
+
import { dirname as dirname6, join as join7, resolve as resolve2 } from "path";
|
|
6165
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
6085
6166
|
import { createRequire } from "module";
|
|
6086
6167
|
|
|
6087
6168
|
// src/commands/agent-host.ts
|
|
6088
|
-
import { spawnSync as
|
|
6089
|
-
import { existsSync as
|
|
6169
|
+
import { spawnSync as spawnSync3 } from "child_process";
|
|
6170
|
+
import { existsSync as existsSync4 } from "fs";
|
|
6090
6171
|
import { readFile as readFile4 } from "fs/promises";
|
|
6091
|
-
import { homedir as
|
|
6172
|
+
import { homedir as homedir4 } from "os";
|
|
6092
6173
|
import { isAbsolute, join as join6 } from "path";
|
|
6093
6174
|
var SUPPORTED_AGENT_IDS = [
|
|
6094
6175
|
"claude",
|
|
@@ -6138,13 +6219,13 @@ function selectStableNodeCommand(whichOutput, fallback = process.execPath) {
|
|
|
6138
6219
|
return candidate && isAbsolute(candidate) ? candidate : fallback;
|
|
6139
6220
|
}
|
|
6140
6221
|
function stableNodeCommand() {
|
|
6141
|
-
const probe =
|
|
6222
|
+
const probe = spawnSync3(process.platform === "win32" ? "where" : "which", ["node"], {
|
|
6142
6223
|
encoding: "utf8",
|
|
6143
6224
|
stdio: ["ignore", "pipe", "ignore"]
|
|
6144
6225
|
});
|
|
6145
6226
|
return selectStableNodeCommand(probe.status === 0 ? probe.stdout : void 0);
|
|
6146
6227
|
}
|
|
6147
|
-
function agentSkillPath(agent, homeDir =
|
|
6228
|
+
function agentSkillPath(agent, homeDir = homedir4(), projectDir) {
|
|
6148
6229
|
switch (agent) {
|
|
6149
6230
|
case "claude":
|
|
6150
6231
|
return projectDir ? join6(projectDir, ".claude", "skills", "topolo", "SKILL.md") : join6(homeDir, ".claude", "skills", "topolo", "SKILL.md");
|
|
@@ -6169,7 +6250,7 @@ function agentSkillPath(agent, homeDir = homedir3(), projectDir) {
|
|
|
6169
6250
|
return void 0;
|
|
6170
6251
|
}
|
|
6171
6252
|
}
|
|
6172
|
-
function agentConfigPaths(agent, homeDir =
|
|
6253
|
+
function agentConfigPaths(agent, homeDir = homedir4(), projectDir) {
|
|
6173
6254
|
switch (agent) {
|
|
6174
6255
|
case "claude":
|
|
6175
6256
|
return [{ path: join6(homeDir, ".claude.json"), format: "json", rootKey: "mcpServers" }];
|
|
@@ -6229,7 +6310,7 @@ function agentConfigPaths(agent, homeDir = homedir3(), projectDir) {
|
|
|
6229
6310
|
return [{ path: join6(projectDir, ".amazonq", "mcp.json"), format: "json", rootKey: "mcpServers" }];
|
|
6230
6311
|
}
|
|
6231
6312
|
return [{
|
|
6232
|
-
path:
|
|
6313
|
+
path: existsSync4(join6(homeDir, ".aws", "amazonq", "mcp.json")) ? join6(homeDir, ".aws", "amazonq", "mcp.json") : join6(homeDir, ".aws", "amazonq", "default.json"),
|
|
6233
6314
|
format: "json",
|
|
6234
6315
|
rootKey: "mcpServers"
|
|
6235
6316
|
}];
|
|
@@ -6261,8 +6342,8 @@ function agentCliNames(agent) {
|
|
|
6261
6342
|
return ["qchat", "q"];
|
|
6262
6343
|
}
|
|
6263
6344
|
}
|
|
6264
|
-
function agentConfigExists(agent, homeDir =
|
|
6265
|
-
return agentConfigPaths(agent, homeDir, projectDir).some((config) =>
|
|
6345
|
+
function agentConfigExists(agent, homeDir = homedir4(), projectDir) {
|
|
6346
|
+
return agentConfigPaths(agent, homeDir, projectDir).some((config) => existsSync4(config.path));
|
|
6266
6347
|
}
|
|
6267
6348
|
function claudeDesktopConfigPath(homeDir) {
|
|
6268
6349
|
if (process.platform === "darwin") return join6(homeDir, "Library", "Application Support", "Claude", "claude_desktop_config.json");
|
|
@@ -6274,10 +6355,10 @@ function vscodeUserConfigPath(homeDir) {
|
|
|
6274
6355
|
if (process.platform === "win32") return join6(process.env.APPDATA ?? join6(homeDir, "AppData", "Roaming"), "Code", "User", "mcp.json");
|
|
6275
6356
|
return join6(process.env.XDG_CONFIG_HOME ?? join6(homeDir, ".config"), "Code", "User", "mcp.json");
|
|
6276
6357
|
}
|
|
6277
|
-
async function readAgentRegistrations(agent, homeDir =
|
|
6358
|
+
async function readAgentRegistrations(agent, homeDir = homedir4(), projectDir) {
|
|
6278
6359
|
const registrations = [];
|
|
6279
6360
|
for (const config of agentConfigPaths(agent, homeDir, projectDir)) {
|
|
6280
|
-
if (!
|
|
6361
|
+
if (!existsSync4(config.path)) continue;
|
|
6281
6362
|
if (config.format === "json") {
|
|
6282
6363
|
registrations.push(...await readJsonRegistrations(config.path, config.rootKey ?? "mcpServers", agent));
|
|
6283
6364
|
} else if (config.format === "toml") {
|
|
@@ -6538,9 +6619,9 @@ function message(error) {
|
|
|
6538
6619
|
}
|
|
6539
6620
|
|
|
6540
6621
|
// src/commands/agent-config.ts
|
|
6541
|
-
import { existsSync as
|
|
6622
|
+
import { existsSync as existsSync5 } from "fs";
|
|
6542
6623
|
import { mkdir as mkdir3, readFile as readFile5, rename as rename2, writeFile as writeFile3 } from "fs/promises";
|
|
6543
|
-
import { dirname as
|
|
6624
|
+
import { dirname as dirname5 } from "path";
|
|
6544
6625
|
async function installAgentSkill(agent, source, homeDir, projectDir) {
|
|
6545
6626
|
const path = agentSkillPath(agent, homeDir, projectDir);
|
|
6546
6627
|
if (!path) return { installed: false };
|
|
@@ -6561,7 +6642,7 @@ async function registerAgentConfig(agent, mcp, homeDir, registration, projectDir
|
|
|
6561
6642
|
}
|
|
6562
6643
|
async function unregisterAgentConfig(agent, homeDir, name, projectDir) {
|
|
6563
6644
|
for (const config of agentConfigPaths(agent, homeDir, projectDir)) {
|
|
6564
|
-
if (!
|
|
6645
|
+
if (!existsSync5(config.path)) continue;
|
|
6565
6646
|
if (config.format === "json") {
|
|
6566
6647
|
await unregisterJson(config, agent, name);
|
|
6567
6648
|
} else if (config.format === "toml") {
|
|
@@ -6581,7 +6662,7 @@ function registrationEnvironment(agent, registration) {
|
|
|
6581
6662
|
}
|
|
6582
6663
|
async function registerJson(config, agent, mcp, registration) {
|
|
6583
6664
|
let parsed = {};
|
|
6584
|
-
if (
|
|
6665
|
+
if (existsSync5(config.path)) {
|
|
6585
6666
|
try {
|
|
6586
6667
|
parsed = JSON.parse(await readFile5(config.path, "utf8"));
|
|
6587
6668
|
} catch (error) {
|
|
@@ -6626,7 +6707,7 @@ async function unregisterJson(config, agent, name) {
|
|
|
6626
6707
|
await atomicWrite(config.path, JSON.stringify(parsed, null, 2) + "\n");
|
|
6627
6708
|
}
|
|
6628
6709
|
async function registerToml(path, agent, mcp, registration) {
|
|
6629
|
-
const existing =
|
|
6710
|
+
const existing = existsSync5(path) ? await readFile5(path, "utf8") : "";
|
|
6630
6711
|
const text2 = withoutMcpServerSections(existing, registration.name);
|
|
6631
6712
|
const args = mcp.args.length ? "\nargs = [" + mcp.args.map((item) => JSON.stringify(item)).join(", ") + "]" : "";
|
|
6632
6713
|
const environment = registrationEnvironment(agent, registration);
|
|
@@ -6635,7 +6716,7 @@ async function registerToml(path, agent, mcp, registration) {
|
|
|
6635
6716
|
await atomicWrite(path, text2 + block);
|
|
6636
6717
|
}
|
|
6637
6718
|
async function registerGoose(path, mcp, registration) {
|
|
6638
|
-
const existing =
|
|
6719
|
+
const existing = existsSync5(path) ? await readFile5(path, "utf8") : "";
|
|
6639
6720
|
const withoutTopolo = removeGooseExtension(existing, registration.name);
|
|
6640
6721
|
const environment = registrationEnvironment("goose", registration);
|
|
6641
6722
|
const block = [
|
|
@@ -6703,7 +6784,7 @@ function formatSkillForAgent(agent, source) {
|
|
|
6703
6784
|
return "---\ntrigger: model_decision\ndescription: Use Topolo MCP for Topolo platform operations.\n---\n\n" + body;
|
|
6704
6785
|
}
|
|
6705
6786
|
async function atomicWrite(path, contents) {
|
|
6706
|
-
await mkdir3(
|
|
6787
|
+
await mkdir3(dirname5(path), { recursive: true });
|
|
6707
6788
|
const temporaryPath = path + ".topolo-" + process.pid + ".tmp";
|
|
6708
6789
|
await writeFile3(temporaryPath, contents, { encoding: "utf8", mode: 384 });
|
|
6709
6790
|
await rename2(temporaryPath, path);
|
|
@@ -6726,11 +6807,11 @@ function withoutMcpServerSections(text2, name) {
|
|
|
6726
6807
|
// src/commands/skills.ts
|
|
6727
6808
|
var AGENT_LABELS2 = AGENT_LABELS;
|
|
6728
6809
|
function skillsSourceDir() {
|
|
6729
|
-
const here =
|
|
6730
|
-
const distCandidate =
|
|
6731
|
-
const srcCandidate =
|
|
6810
|
+
const here = dirname6(fileURLToPath3(import.meta.url));
|
|
6811
|
+
const distCandidate = resolve2(here, "../skills");
|
|
6812
|
+
const srcCandidate = resolve2(here, "../../skills");
|
|
6732
6813
|
for (const candidate of [distCandidate, srcCandidate]) {
|
|
6733
|
-
if (
|
|
6814
|
+
if (existsSync6(join7(candidate, "topolo", "SKILL.md"))) return candidate;
|
|
6734
6815
|
}
|
|
6735
6816
|
return distCandidate;
|
|
6736
6817
|
}
|
|
@@ -6740,7 +6821,7 @@ function resolveMcpCommand() {
|
|
|
6740
6821
|
}
|
|
6741
6822
|
function agentBinaryExists(agent) {
|
|
6742
6823
|
return agentCliNames(agent).some((bin) => {
|
|
6743
|
-
const probe =
|
|
6824
|
+
const probe = spawnSync4(process.platform === "win32" ? "where" : "which", [bin], {
|
|
6744
6825
|
stdio: "ignore"
|
|
6745
6826
|
});
|
|
6746
6827
|
return probe.status === 0;
|
|
@@ -6812,8 +6893,8 @@ function resolveTargets(opts) {
|
|
|
6812
6893
|
}))];
|
|
6813
6894
|
}
|
|
6814
6895
|
if (opts.all) return [...SUPPORTED_AGENT_IDS];
|
|
6815
|
-
const homeDir = opts.homeDir ??
|
|
6816
|
-
const detectBinaries = homeDir ===
|
|
6896
|
+
const homeDir = opts.homeDir ?? homedir5();
|
|
6897
|
+
const detectBinaries = homeDir === homedir5();
|
|
6817
6898
|
const detected = SUPPORTED_AGENT_IDS.filter((agent) => agentConfigExists(agent, homeDir, opts.project) || detectBinaries && agentBinaryExists(agent));
|
|
6818
6899
|
return [.../* @__PURE__ */ new Set(["claude", "codex", ...detected])];
|
|
6819
6900
|
}
|
|
@@ -6839,7 +6920,7 @@ function registerSkillsCommand(program2) {
|
|
|
6839
6920
|
const mode = resolveOutputMode(opts.json);
|
|
6840
6921
|
try {
|
|
6841
6922
|
const rows = await agentSurfaceStatus({
|
|
6842
|
-
homeDir: opts.agentHome ?
|
|
6923
|
+
homeDir: opts.agentHome ? resolve2(opts.agentHome) : void 0,
|
|
6843
6924
|
name: opts.name,
|
|
6844
6925
|
agent: opts.agent,
|
|
6845
6926
|
all: opts.all,
|
|
@@ -6855,7 +6936,7 @@ function registerSkillsCommand(program2) {
|
|
|
6855
6936
|
try {
|
|
6856
6937
|
const removed = await uninstallAgentSurfaces({
|
|
6857
6938
|
...opts,
|
|
6858
|
-
homeDir: opts.agentHome ?
|
|
6939
|
+
homeDir: opts.agentHome ? resolve2(opts.agentHome) : void 0
|
|
6859
6940
|
});
|
|
6860
6941
|
emit(
|
|
6861
6942
|
{ removed },
|
|
@@ -6869,12 +6950,12 @@ function registerSkillsCommand(program2) {
|
|
|
6869
6950
|
}
|
|
6870
6951
|
async function installAgentSurfaces(opts) {
|
|
6871
6952
|
const sourceDir = skillsSourceDir();
|
|
6872
|
-
if (!
|
|
6953
|
+
if (!existsSync6(join7(sourceDir, "topolo", "SKILL.md"))) {
|
|
6873
6954
|
throw new Error("Bundled skill file not found. Reinstall the CLI: npm install -g @topolo/cli");
|
|
6874
6955
|
}
|
|
6875
6956
|
const mcp = resolveMcpCommand();
|
|
6876
6957
|
const registration = resolveMcpRegistration(opts);
|
|
6877
|
-
const homeDir = opts.homeDir ??
|
|
6958
|
+
const homeDir = opts.homeDir ?? homedir5();
|
|
6878
6959
|
const results = [];
|
|
6879
6960
|
for (const agent of resolveTargets({ ...opts, homeDir, project: opts.project })) {
|
|
6880
6961
|
results.push(await installForAgent(agent, sourceDir, mcp, {
|
|
@@ -6909,7 +6990,7 @@ function assertAgentSetupSucceeded(results) {
|
|
|
6909
6990
|
}
|
|
6910
6991
|
}
|
|
6911
6992
|
async function agentSurfaceStatus(options = {}) {
|
|
6912
|
-
const homeDir = options.homeDir ??
|
|
6993
|
+
const homeDir = options.homeDir ?? homedir5();
|
|
6913
6994
|
const sourceSkill = await readFile6(join7(skillsSourceDir(), "topolo", "SKILL.md"), "utf8");
|
|
6914
6995
|
const agents = resolveTargets({
|
|
6915
6996
|
agent: options.agent,
|
|
@@ -6919,7 +7000,7 @@ async function agentSurfaceStatus(options = {}) {
|
|
|
6919
7000
|
});
|
|
6920
7001
|
return Promise.all(agents.map(async (agent) => {
|
|
6921
7002
|
const skillPath = agentSkillPath(agent, homeDir, options.project);
|
|
6922
|
-
const installedSkill = skillPath &&
|
|
7003
|
+
const installedSkill = skillPath && existsSync6(skillPath) ? await readFile6(skillPath, "utf8") : void 0;
|
|
6923
7004
|
const registrations = (await readAgentRegistrations(agent, homeDir, options.project)).filter((registration) => !options.name || registration.name === options.name);
|
|
6924
7005
|
return {
|
|
6925
7006
|
agent,
|
|
@@ -6933,7 +7014,7 @@ async function agentSurfaceStatus(options = {}) {
|
|
|
6933
7014
|
}));
|
|
6934
7015
|
}
|
|
6935
7016
|
async function uninstallAgentSurfaces(options) {
|
|
6936
|
-
const homeDir = options.homeDir ??
|
|
7017
|
+
const homeDir = options.homeDir ?? homedir5();
|
|
6937
7018
|
const name = options.name?.trim() || "topolo";
|
|
6938
7019
|
resolveMcpRegistration({ name, ...name === "topolo" ? {} : { context: "uninstall-validation" } });
|
|
6939
7020
|
const removed = [];
|
|
@@ -6943,8 +7024,8 @@ async function uninstallAgentSurfaces(options) {
|
|
|
6943
7024
|
await unregisterAgentConfig(agent, homeDir, name, options.project);
|
|
6944
7025
|
const remaining = await readAgentRegistrations(agent, homeDir, options.project);
|
|
6945
7026
|
const skillPath = agentSkillPath(agent, homeDir, options.project);
|
|
6946
|
-
const skillRemoved = remaining.length === 0 && Boolean(skillPath &&
|
|
6947
|
-
if (skillRemoved && skillPath) await rm3(
|
|
7027
|
+
const skillRemoved = remaining.length === 0 && Boolean(skillPath && existsSync6(skillPath));
|
|
7028
|
+
if (skillRemoved && skillPath) await rm3(dirname6(skillPath), { recursive: true, force: true });
|
|
6948
7029
|
removed.push({ agent, name, registrationRemoved, skillRemoved });
|
|
6949
7030
|
}
|
|
6950
7031
|
return removed;
|
|
@@ -6974,8 +7055,8 @@ function formatStatus(rows) {
|
|
|
6974
7055
|
|
|
6975
7056
|
// src/commands/doctor.ts
|
|
6976
7057
|
import { access } from "fs/promises";
|
|
6977
|
-
import { homedir as
|
|
6978
|
-
import { resolve as
|
|
7058
|
+
import { homedir as homedir6 } from "os";
|
|
7059
|
+
import { resolve as resolve3 } from "path";
|
|
6979
7060
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
6980
7061
|
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
6981
7062
|
var defaultDependencies = {
|
|
@@ -7037,7 +7118,7 @@ async function verifyMcpProtocol(command, args, env = definedEnvironment(process
|
|
|
7037
7118
|
}
|
|
7038
7119
|
async function resolveInstalledDoctorTarget(options) {
|
|
7039
7120
|
const name = options.name?.trim() || "topolo";
|
|
7040
|
-
const homeDir = options.agentHome ?
|
|
7121
|
+
const homeDir = options.agentHome ? resolve3(options.agentHome) : homedir6();
|
|
7041
7122
|
const expected = resolveMcpCommand();
|
|
7042
7123
|
const requestedAgents = resolveTargets({
|
|
7043
7124
|
...options,
|
|
@@ -7700,6 +7781,9 @@ program.hook("preAction", async (thisCommand, actionCommand) => {
|
|
|
7700
7781
|
const opts = thisCommand.opts();
|
|
7701
7782
|
if (opts.env) process.env.TOPOLO_ENV = normalizeEnvironment(opts.env);
|
|
7702
7783
|
if (opts.env || environmentWasStated) return;
|
|
7784
|
+
for (let node = actionCommand; node; node = node.parent) {
|
|
7785
|
+
if (node.name() === "agent-packs") return;
|
|
7786
|
+
}
|
|
7703
7787
|
const authenticated = await authenticatedEnvironments();
|
|
7704
7788
|
if (authenticated.length < 2) return;
|
|
7705
7789
|
const path = [];
|
|
@@ -7733,6 +7817,7 @@ registerContextCommand(program);
|
|
|
7733
7817
|
registerResourcesCommand(program);
|
|
7734
7818
|
registerWorkspacesCommand(program);
|
|
7735
7819
|
registerInstallationsCommand(program);
|
|
7820
|
+
registerAgentPacksCommand(program);
|
|
7736
7821
|
var helpCommands = [program];
|
|
7737
7822
|
for (const command of helpCommands) {
|
|
7738
7823
|
command.configureHelp({
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@topolo/cli",
|
|
3
3
|
"packageManager": "pnpm@10.17.1",
|
|
4
|
-
"version": "0.
|
|
5
|
-
"topoloPublishedVersion": "0.
|
|
4
|
+
"version": "0.13.1",
|
|
5
|
+
"topoloPublishedVersion": "0.13.1",
|
|
6
6
|
"description": "Public command-line interface for Topolo customer organizations, developers, and agents.",
|
|
7
7
|
"license": "UNLICENSED",
|
|
8
8
|
"author": "Topolo",
|
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
"files": [
|
|
15
15
|
"dist",
|
|
16
16
|
"skills",
|
|
17
|
-
"postinstall.mjs"
|
|
17
|
+
"postinstall.mjs",
|
|
18
|
+
"agent-packs"
|
|
18
19
|
],
|
|
19
20
|
"scripts": {
|
|
20
21
|
"postinstall": "node postinstall.mjs",
|
|
@@ -24,7 +25,9 @@
|
|
|
24
25
|
"start": "node dist/index.js",
|
|
25
26
|
"test": "vitest run",
|
|
26
27
|
"test:watch": "vitest",
|
|
27
|
-
"coverage": "
|
|
28
|
+
"coverage": "pnpm run coverage:node && pnpm run coverage:adapter",
|
|
29
|
+
"coverage:node": "vitest run --coverage",
|
|
30
|
+
"coverage:adapter": "python3 -m venv node_modules/.cache/agent-pack-test && node_modules/.cache/agent-pack-test/bin/python -m pip install --disable-pip-version-check --quiet --timeout 15 --retries 0 -r agent-packs/requirements-test.txt && PYTHONPATH=agent-packs/src COVERAGE_FILE=node_modules/.cache/agent-pack-test/.coverage node_modules/.cache/agent-pack-test/bin/python -m coverage run --branch --source=topolo_agent_pack.topolo,topolo_agent_pack.claude,topolo_agent_pack.policy -m unittest discover -s agent-packs/tests && COVERAGE_FILE=node_modules/.cache/agent-pack-test/.coverage node_modules/.cache/agent-pack-test/bin/python -m coverage report --fail-under=100"
|
|
28
31
|
},
|
|
29
32
|
"dependencies": {
|
|
30
33
|
"@modelcontextprotocol/sdk": "^1.0.0",
|