@topolo/cli 0.12.33 → 0.13.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/README.md +45 -0
- package/agent-packs/README.md +341 -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/cli.py +416 -0
- package/agent-packs/src/topolo_agent_pack/fresh.py +158 -0
- package/agent-packs/src/topolo_agent_pack/live.py +362 -0
- package/agent-packs/src/topolo_agent_pack/native.py +645 -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/index.js +95 -44
- package/package.json +7 -4
package/dist/index.js
CHANGED
|
@@ -1,5 +1,52 @@
|
|
|
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
|
+
function registerAgentPacksCommand(program2) {
|
|
9
|
+
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)");
|
|
10
|
+
const commands = [
|
|
11
|
+
"add",
|
|
12
|
+
"replace",
|
|
13
|
+
"switch",
|
|
14
|
+
"capture",
|
|
15
|
+
"build",
|
|
16
|
+
"install",
|
|
17
|
+
"export",
|
|
18
|
+
"status",
|
|
19
|
+
"list",
|
|
20
|
+
"recover",
|
|
21
|
+
"doctor",
|
|
22
|
+
"remote-recover",
|
|
23
|
+
"connect",
|
|
24
|
+
"remote-context",
|
|
25
|
+
"remember",
|
|
26
|
+
"artifact",
|
|
27
|
+
"artifact-get"
|
|
28
|
+
];
|
|
29
|
+
for (const name of commands) {
|
|
30
|
+
packs.command(name).description(name === "add" ? "Add an installed or bundled pack, group, or agent" : `Run the pack ${name} operation`).option("--harness <name>", "Local host adapter (currently codex)", "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((args, options) => {
|
|
31
|
+
if (options.harness !== "codex") throw new Error(`The ${options.harness} pack adapter is not available. Only Codex switching has been verified.`);
|
|
32
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
33
|
+
const adapter = [resolve(here, "../agent-packs/topolo-agent-pack"), resolve(here, "../../agent-packs/topolo-agent-pack")].find(existsSync);
|
|
34
|
+
if (!adapter) throw new Error("This CLI installation is missing its bundled Topolo Agent Pack adapter. Reinstall @topolo/cli.");
|
|
35
|
+
const store = packs.opts().store;
|
|
36
|
+
const forwarded = (options.adapterHelp ? ["--help"] : args).map((value) => value === "--group" ? "--set" : value);
|
|
37
|
+
const result = spawnSync("python3", [
|
|
38
|
+
adapter,
|
|
39
|
+
...store ? ["--store", store] : [],
|
|
40
|
+
name,
|
|
41
|
+
...forwarded,
|
|
42
|
+
...name === "add" && !options.adapterHelp ? ["--catalog"] : []
|
|
43
|
+
], { stdio: "inherit", env: { ...process.env, PYTHONDONTWRITEBYTECODE: "1", TOPOLO_AGENT_PACK_PUBLIC_CLI: "1" } });
|
|
44
|
+
if (result.error) throw new Error(`Python 3.11 or later is required for local packs: ${result.error.message}`);
|
|
45
|
+
if (result.status !== 0) process.exitCode = result.status ?? 2;
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
3
50
|
// src/index.ts
|
|
4
51
|
import { Command, Help } from "commander";
|
|
5
52
|
|
|
@@ -1592,7 +1639,7 @@ var TopoloClient = class _TopoloClient {
|
|
|
1592
1639
|
} catch (error) {
|
|
1593
1640
|
const transportFailure = !(error instanceof TopoloSdkError) && !opts.signal?.aborted;
|
|
1594
1641
|
if (!transportFailure || attempt === maxAttempts) throw error;
|
|
1595
|
-
await new Promise((
|
|
1642
|
+
await new Promise((resolve4) => setTimeout(resolve4, 250));
|
|
1596
1643
|
}
|
|
1597
1644
|
}
|
|
1598
1645
|
throw new TopoloSdkError("network_error", "Topolo read retry loop exhausted.");
|
|
@@ -3582,7 +3629,7 @@ function createTopolo(options) {
|
|
|
3582
3629
|
async function pollUntilApproved(params) {
|
|
3583
3630
|
let interval = Math.max(params.intervalSeconds ?? 5, 1);
|
|
3584
3631
|
while (Date.now() < params.expiresAtMs) {
|
|
3585
|
-
await new Promise((
|
|
3632
|
+
await new Promise((resolve4) => setTimeout(resolve4, Math.min(interval * 1e3, params.expiresAtMs - Date.now())));
|
|
3586
3633
|
if (Date.now() >= params.expiresAtMs) break;
|
|
3587
3634
|
try {
|
|
3588
3635
|
return await params.oauth.pollDeviceToken({
|
|
@@ -3617,11 +3664,11 @@ import { homedir as homedir2, platform } from "os";
|
|
|
3617
3664
|
import { dirname as dirname2, join as join3 } from "path";
|
|
3618
3665
|
import { createHash, randomUUID } from "crypto";
|
|
3619
3666
|
import { join as join2 } from "path";
|
|
3620
|
-
import { spawnSync } from "child_process";
|
|
3667
|
+
import { spawnSync as spawnSync2 } from "child_process";
|
|
3621
3668
|
import { mkdir, readFile, readdir, rename, rm, writeFile, chmod } from "fs/promises";
|
|
3622
|
-
import { existsSync } from "fs";
|
|
3669
|
+
import { existsSync as existsSync3 } from "fs";
|
|
3623
3670
|
import { homedir, platform as hostPlatform } from "os";
|
|
3624
|
-
import { dirname, join } from "path";
|
|
3671
|
+
import { dirname as dirname3, join } from "path";
|
|
3625
3672
|
var TopoloSdkError2 = class extends Error {
|
|
3626
3673
|
code;
|
|
3627
3674
|
constructor(code, message2) {
|
|
@@ -4068,7 +4115,7 @@ function runOrThrow(result, operation) {
|
|
|
4068
4115
|
}
|
|
4069
4116
|
function createPlatformInstallationSecretBackend(options = {}) {
|
|
4070
4117
|
const platform22 = options.platform ?? hostPlatform();
|
|
4071
|
-
const spawn3 = options.spawn ?? ((command, args, spawnOptions) =>
|
|
4118
|
+
const spawn3 = options.spawn ?? ((command, args, spawnOptions) => spawnSync2(command, args, spawnOptions));
|
|
4072
4119
|
const root = options.root ?? installationStorePath();
|
|
4073
4120
|
const service = options.service ?? KEYCHAIN_SERVICE;
|
|
4074
4121
|
if (platform22 === "darwin") {
|
|
@@ -4187,13 +4234,13 @@ function createPlatformInstallationSecretBackend(options = {}) {
|
|
|
4187
4234
|
return {
|
|
4188
4235
|
async set(account, value) {
|
|
4189
4236
|
const path = secretPath(account);
|
|
4190
|
-
await mkdir(
|
|
4237
|
+
await mkdir(dirname3(path), { recursive: true });
|
|
4191
4238
|
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
4239
|
runOrThrow(powershell(script, path, value), "Windows DPAPI write");
|
|
4193
4240
|
},
|
|
4194
4241
|
async get(account) {
|
|
4195
4242
|
const path = secretPath(account);
|
|
4196
|
-
if (!
|
|
4243
|
+
if (!existsSync3(path)) return null;
|
|
4197
4244
|
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
4245
|
return runOrThrow(powershell(script, path), "Windows DPAPI read");
|
|
4199
4246
|
},
|
|
@@ -4209,7 +4256,7 @@ async function writeExternalAgentInstallation(installation, secret, backend = cr
|
|
|
4209
4256
|
await backend.set(accountName(installation.environment, installation.id), JSON.stringify(secret));
|
|
4210
4257
|
const temporary = `${path}.${process.pid}.tmp`;
|
|
4211
4258
|
try {
|
|
4212
|
-
await mkdir(
|
|
4259
|
+
await mkdir(dirname3(path), { recursive: true, mode: 448 });
|
|
4213
4260
|
await writeFile(temporary, `${JSON.stringify(installation, null, 2)}
|
|
4214
4261
|
`, { encoding: "utf8", mode: 384 });
|
|
4215
4262
|
await rename(temporary, path);
|
|
@@ -4222,7 +4269,7 @@ async function writeExternalAgentInstallation(installation, secret, backend = cr
|
|
|
4222
4269
|
}
|
|
4223
4270
|
async function listExternalAgentInstallations(environment) {
|
|
4224
4271
|
const directory = join(installationStorePath(), environment);
|
|
4225
|
-
if (!
|
|
4272
|
+
if (!existsSync3(directory)) return [];
|
|
4226
4273
|
const entries = await readdir(directory, { withFileTypes: true });
|
|
4227
4274
|
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
4275
|
return installations.sort((left, right) => left.createdAt.localeCompare(right.createdAt));
|
|
@@ -4493,7 +4540,7 @@ async function withConfigWriteLock(operation) {
|
|
|
4493
4540
|
if (Date.now() - startedAt >= CONFIG_LOCK_TIMEOUT_MS) {
|
|
4494
4541
|
throw new Error(`Timed out waiting for credential configuration lock at ${lockPath}.`);
|
|
4495
4542
|
}
|
|
4496
|
-
await new Promise((
|
|
4543
|
+
await new Promise((resolve4) => setTimeout(resolve4, CONFIG_LOCK_RETRY_MS));
|
|
4497
4544
|
}
|
|
4498
4545
|
}
|
|
4499
4546
|
try {
|
|
@@ -4765,11 +4812,11 @@ function normalizeError(err) {
|
|
|
4765
4812
|
|
|
4766
4813
|
// src/version.ts
|
|
4767
4814
|
import { readFileSync } from "fs";
|
|
4768
|
-
import { dirname as
|
|
4769
|
-
import { fileURLToPath } from "url";
|
|
4815
|
+
import { dirname as dirname4, join as join4 } from "path";
|
|
4816
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
4770
4817
|
function readCliVersion() {
|
|
4771
4818
|
try {
|
|
4772
|
-
const here =
|
|
4819
|
+
const here = dirname4(fileURLToPath2(import.meta.url));
|
|
4773
4820
|
const candidates = [
|
|
4774
4821
|
join4(here, "package.json"),
|
|
4775
4822
|
join4(here, "..", "package.json")
|
|
@@ -6076,17 +6123,17 @@ function formatCheckResult(result) {
|
|
|
6076
6123
|
}
|
|
6077
6124
|
|
|
6078
6125
|
// src/commands/skills.ts
|
|
6079
|
-
import { spawnSync as
|
|
6080
|
-
import { existsSync as
|
|
6126
|
+
import { spawnSync as spawnSync4 } from "child_process";
|
|
6127
|
+
import { existsSync as existsSync6 } from "fs";
|
|
6081
6128
|
import { readFile as readFile6, rm as rm3 } from "fs/promises";
|
|
6082
6129
|
import { homedir as homedir4 } from "os";
|
|
6083
|
-
import { dirname as
|
|
6084
|
-
import { fileURLToPath as
|
|
6130
|
+
import { dirname as dirname6, join as join7, resolve as resolve2 } from "path";
|
|
6131
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
6085
6132
|
import { createRequire } from "module";
|
|
6086
6133
|
|
|
6087
6134
|
// src/commands/agent-host.ts
|
|
6088
|
-
import { spawnSync as
|
|
6089
|
-
import { existsSync as
|
|
6135
|
+
import { spawnSync as spawnSync3 } from "child_process";
|
|
6136
|
+
import { existsSync as existsSync4 } from "fs";
|
|
6090
6137
|
import { readFile as readFile4 } from "fs/promises";
|
|
6091
6138
|
import { homedir as homedir3 } from "os";
|
|
6092
6139
|
import { isAbsolute, join as join6 } from "path";
|
|
@@ -6138,7 +6185,7 @@ function selectStableNodeCommand(whichOutput, fallback = process.execPath) {
|
|
|
6138
6185
|
return candidate && isAbsolute(candidate) ? candidate : fallback;
|
|
6139
6186
|
}
|
|
6140
6187
|
function stableNodeCommand() {
|
|
6141
|
-
const probe =
|
|
6188
|
+
const probe = spawnSync3(process.platform === "win32" ? "where" : "which", ["node"], {
|
|
6142
6189
|
encoding: "utf8",
|
|
6143
6190
|
stdio: ["ignore", "pipe", "ignore"]
|
|
6144
6191
|
});
|
|
@@ -6229,7 +6276,7 @@ function agentConfigPaths(agent, homeDir = homedir3(), projectDir) {
|
|
|
6229
6276
|
return [{ path: join6(projectDir, ".amazonq", "mcp.json"), format: "json", rootKey: "mcpServers" }];
|
|
6230
6277
|
}
|
|
6231
6278
|
return [{
|
|
6232
|
-
path:
|
|
6279
|
+
path: existsSync4(join6(homeDir, ".aws", "amazonq", "mcp.json")) ? join6(homeDir, ".aws", "amazonq", "mcp.json") : join6(homeDir, ".aws", "amazonq", "default.json"),
|
|
6233
6280
|
format: "json",
|
|
6234
6281
|
rootKey: "mcpServers"
|
|
6235
6282
|
}];
|
|
@@ -6262,7 +6309,7 @@ function agentCliNames(agent) {
|
|
|
6262
6309
|
}
|
|
6263
6310
|
}
|
|
6264
6311
|
function agentConfigExists(agent, homeDir = homedir3(), projectDir) {
|
|
6265
|
-
return agentConfigPaths(agent, homeDir, projectDir).some((config) =>
|
|
6312
|
+
return agentConfigPaths(agent, homeDir, projectDir).some((config) => existsSync4(config.path));
|
|
6266
6313
|
}
|
|
6267
6314
|
function claudeDesktopConfigPath(homeDir) {
|
|
6268
6315
|
if (process.platform === "darwin") return join6(homeDir, "Library", "Application Support", "Claude", "claude_desktop_config.json");
|
|
@@ -6277,7 +6324,7 @@ function vscodeUserConfigPath(homeDir) {
|
|
|
6277
6324
|
async function readAgentRegistrations(agent, homeDir = homedir3(), projectDir) {
|
|
6278
6325
|
const registrations = [];
|
|
6279
6326
|
for (const config of agentConfigPaths(agent, homeDir, projectDir)) {
|
|
6280
|
-
if (!
|
|
6327
|
+
if (!existsSync4(config.path)) continue;
|
|
6281
6328
|
if (config.format === "json") {
|
|
6282
6329
|
registrations.push(...await readJsonRegistrations(config.path, config.rootKey ?? "mcpServers", agent));
|
|
6283
6330
|
} else if (config.format === "toml") {
|
|
@@ -6538,9 +6585,9 @@ function message(error) {
|
|
|
6538
6585
|
}
|
|
6539
6586
|
|
|
6540
6587
|
// src/commands/agent-config.ts
|
|
6541
|
-
import { existsSync as
|
|
6588
|
+
import { existsSync as existsSync5 } from "fs";
|
|
6542
6589
|
import { mkdir as mkdir3, readFile as readFile5, rename as rename2, writeFile as writeFile3 } from "fs/promises";
|
|
6543
|
-
import { dirname as
|
|
6590
|
+
import { dirname as dirname5 } from "path";
|
|
6544
6591
|
async function installAgentSkill(agent, source, homeDir, projectDir) {
|
|
6545
6592
|
const path = agentSkillPath(agent, homeDir, projectDir);
|
|
6546
6593
|
if (!path) return { installed: false };
|
|
@@ -6561,7 +6608,7 @@ async function registerAgentConfig(agent, mcp, homeDir, registration, projectDir
|
|
|
6561
6608
|
}
|
|
6562
6609
|
async function unregisterAgentConfig(agent, homeDir, name, projectDir) {
|
|
6563
6610
|
for (const config of agentConfigPaths(agent, homeDir, projectDir)) {
|
|
6564
|
-
if (!
|
|
6611
|
+
if (!existsSync5(config.path)) continue;
|
|
6565
6612
|
if (config.format === "json") {
|
|
6566
6613
|
await unregisterJson(config, agent, name);
|
|
6567
6614
|
} else if (config.format === "toml") {
|
|
@@ -6581,7 +6628,7 @@ function registrationEnvironment(agent, registration) {
|
|
|
6581
6628
|
}
|
|
6582
6629
|
async function registerJson(config, agent, mcp, registration) {
|
|
6583
6630
|
let parsed = {};
|
|
6584
|
-
if (
|
|
6631
|
+
if (existsSync5(config.path)) {
|
|
6585
6632
|
try {
|
|
6586
6633
|
parsed = JSON.parse(await readFile5(config.path, "utf8"));
|
|
6587
6634
|
} catch (error) {
|
|
@@ -6626,7 +6673,7 @@ async function unregisterJson(config, agent, name) {
|
|
|
6626
6673
|
await atomicWrite(config.path, JSON.stringify(parsed, null, 2) + "\n");
|
|
6627
6674
|
}
|
|
6628
6675
|
async function registerToml(path, agent, mcp, registration) {
|
|
6629
|
-
const existing =
|
|
6676
|
+
const existing = existsSync5(path) ? await readFile5(path, "utf8") : "";
|
|
6630
6677
|
const text2 = withoutMcpServerSections(existing, registration.name);
|
|
6631
6678
|
const args = mcp.args.length ? "\nargs = [" + mcp.args.map((item) => JSON.stringify(item)).join(", ") + "]" : "";
|
|
6632
6679
|
const environment = registrationEnvironment(agent, registration);
|
|
@@ -6635,7 +6682,7 @@ async function registerToml(path, agent, mcp, registration) {
|
|
|
6635
6682
|
await atomicWrite(path, text2 + block);
|
|
6636
6683
|
}
|
|
6637
6684
|
async function registerGoose(path, mcp, registration) {
|
|
6638
|
-
const existing =
|
|
6685
|
+
const existing = existsSync5(path) ? await readFile5(path, "utf8") : "";
|
|
6639
6686
|
const withoutTopolo = removeGooseExtension(existing, registration.name);
|
|
6640
6687
|
const environment = registrationEnvironment("goose", registration);
|
|
6641
6688
|
const block = [
|
|
@@ -6703,7 +6750,7 @@ function formatSkillForAgent(agent, source) {
|
|
|
6703
6750
|
return "---\ntrigger: model_decision\ndescription: Use Topolo MCP for Topolo platform operations.\n---\n\n" + body;
|
|
6704
6751
|
}
|
|
6705
6752
|
async function atomicWrite(path, contents) {
|
|
6706
|
-
await mkdir3(
|
|
6753
|
+
await mkdir3(dirname5(path), { recursive: true });
|
|
6707
6754
|
const temporaryPath = path + ".topolo-" + process.pid + ".tmp";
|
|
6708
6755
|
await writeFile3(temporaryPath, contents, { encoding: "utf8", mode: 384 });
|
|
6709
6756
|
await rename2(temporaryPath, path);
|
|
@@ -6726,11 +6773,11 @@ function withoutMcpServerSections(text2, name) {
|
|
|
6726
6773
|
// src/commands/skills.ts
|
|
6727
6774
|
var AGENT_LABELS2 = AGENT_LABELS;
|
|
6728
6775
|
function skillsSourceDir() {
|
|
6729
|
-
const here =
|
|
6730
|
-
const distCandidate =
|
|
6731
|
-
const srcCandidate =
|
|
6776
|
+
const here = dirname6(fileURLToPath3(import.meta.url));
|
|
6777
|
+
const distCandidate = resolve2(here, "../skills");
|
|
6778
|
+
const srcCandidate = resolve2(here, "../../skills");
|
|
6732
6779
|
for (const candidate of [distCandidate, srcCandidate]) {
|
|
6733
|
-
if (
|
|
6780
|
+
if (existsSync6(join7(candidate, "topolo", "SKILL.md"))) return candidate;
|
|
6734
6781
|
}
|
|
6735
6782
|
return distCandidate;
|
|
6736
6783
|
}
|
|
@@ -6740,7 +6787,7 @@ function resolveMcpCommand() {
|
|
|
6740
6787
|
}
|
|
6741
6788
|
function agentBinaryExists(agent) {
|
|
6742
6789
|
return agentCliNames(agent).some((bin) => {
|
|
6743
|
-
const probe =
|
|
6790
|
+
const probe = spawnSync4(process.platform === "win32" ? "where" : "which", [bin], {
|
|
6744
6791
|
stdio: "ignore"
|
|
6745
6792
|
});
|
|
6746
6793
|
return probe.status === 0;
|
|
@@ -6839,7 +6886,7 @@ function registerSkillsCommand(program2) {
|
|
|
6839
6886
|
const mode = resolveOutputMode(opts.json);
|
|
6840
6887
|
try {
|
|
6841
6888
|
const rows = await agentSurfaceStatus({
|
|
6842
|
-
homeDir: opts.agentHome ?
|
|
6889
|
+
homeDir: opts.agentHome ? resolve2(opts.agentHome) : void 0,
|
|
6843
6890
|
name: opts.name,
|
|
6844
6891
|
agent: opts.agent,
|
|
6845
6892
|
all: opts.all,
|
|
@@ -6855,7 +6902,7 @@ function registerSkillsCommand(program2) {
|
|
|
6855
6902
|
try {
|
|
6856
6903
|
const removed = await uninstallAgentSurfaces({
|
|
6857
6904
|
...opts,
|
|
6858
|
-
homeDir: opts.agentHome ?
|
|
6905
|
+
homeDir: opts.agentHome ? resolve2(opts.agentHome) : void 0
|
|
6859
6906
|
});
|
|
6860
6907
|
emit(
|
|
6861
6908
|
{ removed },
|
|
@@ -6869,7 +6916,7 @@ function registerSkillsCommand(program2) {
|
|
|
6869
6916
|
}
|
|
6870
6917
|
async function installAgentSurfaces(opts) {
|
|
6871
6918
|
const sourceDir = skillsSourceDir();
|
|
6872
|
-
if (!
|
|
6919
|
+
if (!existsSync6(join7(sourceDir, "topolo", "SKILL.md"))) {
|
|
6873
6920
|
throw new Error("Bundled skill file not found. Reinstall the CLI: npm install -g @topolo/cli");
|
|
6874
6921
|
}
|
|
6875
6922
|
const mcp = resolveMcpCommand();
|
|
@@ -6919,7 +6966,7 @@ async function agentSurfaceStatus(options = {}) {
|
|
|
6919
6966
|
});
|
|
6920
6967
|
return Promise.all(agents.map(async (agent) => {
|
|
6921
6968
|
const skillPath = agentSkillPath(agent, homeDir, options.project);
|
|
6922
|
-
const installedSkill = skillPath &&
|
|
6969
|
+
const installedSkill = skillPath && existsSync6(skillPath) ? await readFile6(skillPath, "utf8") : void 0;
|
|
6923
6970
|
const registrations = (await readAgentRegistrations(agent, homeDir, options.project)).filter((registration) => !options.name || registration.name === options.name);
|
|
6924
6971
|
return {
|
|
6925
6972
|
agent,
|
|
@@ -6943,8 +6990,8 @@ async function uninstallAgentSurfaces(options) {
|
|
|
6943
6990
|
await unregisterAgentConfig(agent, homeDir, name, options.project);
|
|
6944
6991
|
const remaining = await readAgentRegistrations(agent, homeDir, options.project);
|
|
6945
6992
|
const skillPath = agentSkillPath(agent, homeDir, options.project);
|
|
6946
|
-
const skillRemoved = remaining.length === 0 && Boolean(skillPath &&
|
|
6947
|
-
if (skillRemoved && skillPath) await rm3(
|
|
6993
|
+
const skillRemoved = remaining.length === 0 && Boolean(skillPath && existsSync6(skillPath));
|
|
6994
|
+
if (skillRemoved && skillPath) await rm3(dirname6(skillPath), { recursive: true, force: true });
|
|
6948
6995
|
removed.push({ agent, name, registrationRemoved, skillRemoved });
|
|
6949
6996
|
}
|
|
6950
6997
|
return removed;
|
|
@@ -6975,7 +7022,7 @@ function formatStatus(rows) {
|
|
|
6975
7022
|
// src/commands/doctor.ts
|
|
6976
7023
|
import { access } from "fs/promises";
|
|
6977
7024
|
import { homedir as homedir5 } from "os";
|
|
6978
|
-
import { resolve as
|
|
7025
|
+
import { resolve as resolve3 } from "path";
|
|
6979
7026
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
6980
7027
|
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
6981
7028
|
var defaultDependencies = {
|
|
@@ -7037,7 +7084,7 @@ async function verifyMcpProtocol(command, args, env = definedEnvironment(process
|
|
|
7037
7084
|
}
|
|
7038
7085
|
async function resolveInstalledDoctorTarget(options) {
|
|
7039
7086
|
const name = options.name?.trim() || "topolo";
|
|
7040
|
-
const homeDir = options.agentHome ?
|
|
7087
|
+
const homeDir = options.agentHome ? resolve3(options.agentHome) : homedir5();
|
|
7041
7088
|
const expected = resolveMcpCommand();
|
|
7042
7089
|
const requestedAgents = resolveTargets({
|
|
7043
7090
|
...options,
|
|
@@ -7700,6 +7747,9 @@ program.hook("preAction", async (thisCommand, actionCommand) => {
|
|
|
7700
7747
|
const opts = thisCommand.opts();
|
|
7701
7748
|
if (opts.env) process.env.TOPOLO_ENV = normalizeEnvironment(opts.env);
|
|
7702
7749
|
if (opts.env || environmentWasStated) return;
|
|
7750
|
+
for (let node = actionCommand; node; node = node.parent) {
|
|
7751
|
+
if (node.name() === "agent-packs") return;
|
|
7752
|
+
}
|
|
7703
7753
|
const authenticated = await authenticatedEnvironments();
|
|
7704
7754
|
if (authenticated.length < 2) return;
|
|
7705
7755
|
const path = [];
|
|
@@ -7733,6 +7783,7 @@ registerContextCommand(program);
|
|
|
7733
7783
|
registerResourcesCommand(program);
|
|
7734
7784
|
registerWorkspacesCommand(program);
|
|
7735
7785
|
registerInstallationsCommand(program);
|
|
7786
|
+
registerAgentPacksCommand(program);
|
|
7736
7787
|
var helpCommands = [program];
|
|
7737
7788
|
for (const command of helpCommands) {
|
|
7738
7789
|
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.0",
|
|
5
|
+
"topoloPublishedVersion": "0.13.0",
|
|
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 -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",
|