topchester-ai 0.59.0 → 0.61.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/bin.mjs +1 -1
- package/dist/{cli-DNu9mjMF.mjs → cli-YPKTdpQH.mjs} +94 -203
- package/dist/cli-YPKTdpQH.mjs.map +1 -0
- package/dist/cli.mjs +1 -1
- package/package.json +1 -1
- package/dist/cli-DNu9mjMF.mjs.map +0 -1
package/dist/bin.mjs
CHANGED
|
@@ -249,7 +249,7 @@ async function readAuthStore(options = {}) {
|
|
|
249
249
|
try {
|
|
250
250
|
source = await readFile(path, "utf8");
|
|
251
251
|
} catch (error) {
|
|
252
|
-
if (isNodeError$
|
|
252
|
+
if (isNodeError$4(error) && error.code === "ENOENT") return createEmptyAuthStore();
|
|
253
253
|
throw error;
|
|
254
254
|
}
|
|
255
255
|
let parsed;
|
|
@@ -297,7 +297,7 @@ async function getAuthStoreStatus(options = {}) {
|
|
|
297
297
|
try {
|
|
298
298
|
await stat(path);
|
|
299
299
|
} catch (error) {
|
|
300
|
-
if (isNodeError$
|
|
300
|
+
if (isNodeError$4(error) && error.code === "ENOENT") return {
|
|
301
301
|
path,
|
|
302
302
|
exists: false,
|
|
303
303
|
providers: []
|
|
@@ -388,14 +388,14 @@ function redactProviderStatus(id, record, now) {
|
|
|
388
388
|
}
|
|
389
389
|
async function setModeIfSupported(path, mode) {
|
|
390
390
|
await chmod(path, mode).catch((error) => {
|
|
391
|
-
if (isNodeError$
|
|
391
|
+
if (isNodeError$4(error) && (error.code === "ENOSYS" || error.code === "EPERM" || error.code === "EINVAL")) return;
|
|
392
392
|
throw error;
|
|
393
393
|
});
|
|
394
394
|
}
|
|
395
395
|
function isPlainObject$2(value) {
|
|
396
396
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
397
397
|
}
|
|
398
|
-
function isNodeError$
|
|
398
|
+
function isNodeError$4(error) {
|
|
399
399
|
return error instanceof Error && "code" in error;
|
|
400
400
|
}
|
|
401
401
|
function formatErrorMessage$3(error) {
|
|
@@ -1299,7 +1299,7 @@ async function statExistingFile(resolvedPath, originalPath) {
|
|
|
1299
1299
|
try {
|
|
1300
1300
|
fileStat = await stat(resolvedPath);
|
|
1301
1301
|
} catch (error) {
|
|
1302
|
-
if (isNodeError$
|
|
1302
|
+
if (isNodeError$3(error) && error.code === "ENOENT") throw new Error(`edit_file can only edit existing files: ${originalPath}`);
|
|
1303
1303
|
throw error;
|
|
1304
1304
|
}
|
|
1305
1305
|
if (!fileStat.isFile()) throw new Error(`edit_file can only edit regular files: ${originalPath}`);
|
|
@@ -1341,7 +1341,7 @@ function summarizeDiff(diff) {
|
|
|
1341
1341
|
}
|
|
1342
1342
|
return `+${added}/-${removed}`;
|
|
1343
1343
|
}
|
|
1344
|
-
function isNodeError$
|
|
1344
|
+
function isNodeError$3(error) {
|
|
1345
1345
|
return error instanceof Error && "code" in error;
|
|
1346
1346
|
}
|
|
1347
1347
|
function normalizeEdits(edits) {
|
|
@@ -4859,7 +4859,7 @@ async function statTarget(path) {
|
|
|
4859
4859
|
try {
|
|
4860
4860
|
return await stat(path);
|
|
4861
4861
|
} catch (error) {
|
|
4862
|
-
if (isNodeError$
|
|
4862
|
+
if (isNodeError$2(error) && error.code === "ENOENT") return;
|
|
4863
4863
|
throw error;
|
|
4864
4864
|
}
|
|
4865
4865
|
}
|
|
@@ -4869,7 +4869,7 @@ async function ensureParentDirectory(workspaceRoot, path, relativePath, createPa
|
|
|
4869
4869
|
if (!(await stat(parent)).isDirectory()) throw new Error(`write_file parent path is not a directory: ${dirname(relativePath)}`);
|
|
4870
4870
|
return [];
|
|
4871
4871
|
} catch (error) {
|
|
4872
|
-
if (!isNodeError$
|
|
4872
|
+
if (!isNodeError$2(error) || error.code !== "ENOENT") throw error;
|
|
4873
4873
|
}
|
|
4874
4874
|
if (!createParentDirs) throw new Error(`write_file parent directory does not exist: ${dirname(relativePath)}`);
|
|
4875
4875
|
const createdParentDirs = await collectMissingParentDirs(workspaceRoot, parent);
|
|
@@ -4883,7 +4883,7 @@ async function collectMissingParentDirs(workspaceRoot, parent) {
|
|
|
4883
4883
|
if (!(await stat(current)).isDirectory()) throw new Error(`write_file parent path is not a directory: ${relative(workspaceRoot, current)}`);
|
|
4884
4884
|
break;
|
|
4885
4885
|
} catch (error) {
|
|
4886
|
-
if (!isNodeError$
|
|
4886
|
+
if (!isNodeError$2(error) || error.code !== "ENOENT") throw error;
|
|
4887
4887
|
missing.push(relative(workspaceRoot, current));
|
|
4888
4888
|
current = dirname(current);
|
|
4889
4889
|
}
|
|
@@ -4924,7 +4924,7 @@ function countLogicalLines$1(content) {
|
|
|
4924
4924
|
const withoutTrailingLineEnding = content.replace(/\r?\n$/u, "");
|
|
4925
4925
|
return withoutTrailingLineEnding.length === 0 ? 1 : withoutTrailingLineEnding.split(/\r?\n/u).length;
|
|
4926
4926
|
}
|
|
4927
|
-
function isNodeError$
|
|
4927
|
+
function isNodeError$2(error) {
|
|
4928
4928
|
return error instanceof Error && "code" in error;
|
|
4929
4929
|
}
|
|
4930
4930
|
//#endregion
|
|
@@ -6555,6 +6555,37 @@ async function addProjectBashAllowExactRule(workspaceRoot, command) {
|
|
|
6555
6555
|
allowExact
|
|
6556
6556
|
};
|
|
6557
6557
|
}
|
|
6558
|
+
async function addMcpStdioServerConfig(configPath, options) {
|
|
6559
|
+
const serverName = options.serverName.trim();
|
|
6560
|
+
if (!isValidMcpServerName(serverName)) throw new Error(`invalid MCP server name "${options.serverName}" (use letters, numbers, "-", "_")`);
|
|
6561
|
+
const command = options.command.trim();
|
|
6562
|
+
if (!command) throw new Error("MCP stdio command is required.");
|
|
6563
|
+
const config = readConfigObject(configPath);
|
|
6564
|
+
const mcp = ensurePlainObjectProperty(config, "mcp");
|
|
6565
|
+
const replaced = mcp[serverName] !== void 0;
|
|
6566
|
+
const env = options.env ?? {};
|
|
6567
|
+
const server = {
|
|
6568
|
+
type: "stdio",
|
|
6569
|
+
command,
|
|
6570
|
+
args: options.args ?? [],
|
|
6571
|
+
...Object.keys(env).length > 0 ? { env } : {}
|
|
6572
|
+
};
|
|
6573
|
+
mcp[serverName] = server;
|
|
6574
|
+
mkdirSync(dirname(configPath), {
|
|
6575
|
+
recursive: true,
|
|
6576
|
+
mode: 448
|
|
6577
|
+
});
|
|
6578
|
+
parseConfigFile(configPath, config);
|
|
6579
|
+
await writeFile(configPath, `${JSON.stringify(config, null, 2)}\n`);
|
|
6580
|
+
return {
|
|
6581
|
+
path: configPath,
|
|
6582
|
+
serverName,
|
|
6583
|
+
command,
|
|
6584
|
+
args: server.args,
|
|
6585
|
+
env,
|
|
6586
|
+
replaced
|
|
6587
|
+
};
|
|
6588
|
+
}
|
|
6558
6589
|
function readProjectConfigObject(configPath) {
|
|
6559
6590
|
return readConfigObject(configPath);
|
|
6560
6591
|
}
|
|
@@ -6592,6 +6623,9 @@ function ensureStringArrayProperty(parent, key) {
|
|
|
6592
6623
|
if (!Array.isArray(value) || !value.every((entry) => typeof entry === "string")) throw new Error(`Invalid Topchester config property '${key}': expected a string array.`);
|
|
6593
6624
|
return value;
|
|
6594
6625
|
}
|
|
6626
|
+
function isValidMcpServerName(name) {
|
|
6627
|
+
return name.length > 0 && /^[A-Za-z0-9_-]+$/u.test(name);
|
|
6628
|
+
}
|
|
6595
6629
|
function readConfigFile(path) {
|
|
6596
6630
|
try {
|
|
6597
6631
|
return parseJsonc(readFileSync(path, "utf8"));
|
|
@@ -8215,11 +8249,11 @@ async function directoryExists(path) {
|
|
|
8215
8249
|
if (!(await stat(path)).isDirectory()) throw new Error(`${path} exists but is not a folder`);
|
|
8216
8250
|
return true;
|
|
8217
8251
|
} catch (error) {
|
|
8218
|
-
if (isNodeError$
|
|
8252
|
+
if (isNodeError$1(error) && error.code === "ENOENT") return false;
|
|
8219
8253
|
throw error;
|
|
8220
8254
|
}
|
|
8221
8255
|
}
|
|
8222
|
-
function isNodeError$
|
|
8256
|
+
function isNodeError$1(error) {
|
|
8223
8257
|
return error instanceof Error && "code" in error;
|
|
8224
8258
|
}
|
|
8225
8259
|
//#endregion
|
|
@@ -8258,7 +8292,7 @@ async function removeIfPresent(path) {
|
|
|
8258
8292
|
});
|
|
8259
8293
|
return true;
|
|
8260
8294
|
} catch (error) {
|
|
8261
|
-
if (isNodeError
|
|
8295
|
+
if (isNodeError(error) && error.code === "ENOENT") return false;
|
|
8262
8296
|
throw error;
|
|
8263
8297
|
}
|
|
8264
8298
|
}
|
|
@@ -8271,7 +8305,7 @@ function assertSafeResetPath(workspaceRoot, path) {
|
|
|
8271
8305
|
if (target === workspace) throw new Error(`Refusing to reset KB because the configured KB path is the workspace root: ${target}`);
|
|
8272
8306
|
if (dirname(target) === target) throw new Error(`Refusing to reset KB because the configured KB path is a filesystem root: ${target}`);
|
|
8273
8307
|
}
|
|
8274
|
-
function isNodeError
|
|
8308
|
+
function isNodeError(error) {
|
|
8275
8309
|
return error instanceof Error && "code" in error;
|
|
8276
8310
|
}
|
|
8277
8311
|
//#endregion
|
|
@@ -12124,16 +12158,10 @@ const agentMetadataSchema = z.object({
|
|
|
12124
12158
|
capabilities: z.array(z.string().min(1)).optional(),
|
|
12125
12159
|
model_support: agentModelSupportSchema.optional()
|
|
12126
12160
|
}).strict();
|
|
12127
|
-
|
|
12161
|
+
z.object({
|
|
12128
12162
|
version: z.literal(1),
|
|
12129
12163
|
agents: z.record(z.string().min(1), agentMetadataSchema)
|
|
12130
12164
|
}).strict().parse(agents_default);
|
|
12131
|
-
function listAgentMetadata() {
|
|
12132
|
-
return Object.entries(agentsMetadata.agents).map(([id, metadata]) => ({
|
|
12133
|
-
id,
|
|
12134
|
-
metadata
|
|
12135
|
-
})).sort((left, right) => left.id.localeCompare(right.id));
|
|
12136
|
-
}
|
|
12137
12165
|
//#endregion
|
|
12138
12166
|
//#region src/agent/prompts.ts
|
|
12139
12167
|
function getChatSystemPrompt(options = {}) {
|
|
@@ -15677,135 +15705,6 @@ function formatInfoError(error) {
|
|
|
15677
15705
|
return error instanceof Error ? error.message : String(error);
|
|
15678
15706
|
}
|
|
15679
15707
|
//#endregion
|
|
15680
|
-
//#region src/cli/integrations.ts
|
|
15681
|
-
const TOPCHESTER_CODEX_BLOCK_START = "# >>> topchester integration: codex";
|
|
15682
|
-
const TOPCHESTER_CODEX_BLOCK_END = "# <<< topchester integration: codex";
|
|
15683
|
-
function listIntegrationStatuses() {
|
|
15684
|
-
return listAgentMetadata().filter(({ id }) => id !== "topchester").map(({ id, metadata }) => getIntegrationStatus(id, metadata.display_name));
|
|
15685
|
-
}
|
|
15686
|
-
function getIntegrationStatus(agent, displayName) {
|
|
15687
|
-
const normalizedAgent = normalizeAgentId(agent);
|
|
15688
|
-
const metadata = listAgentMetadata().find(({ id }) => id === normalizedAgent)?.metadata;
|
|
15689
|
-
const name = displayName ?? metadata?.display_name ?? normalizedAgent;
|
|
15690
|
-
if (normalizedAgent !== "codex") return {
|
|
15691
|
-
agent: normalizedAgent,
|
|
15692
|
-
displayName: name,
|
|
15693
|
-
supported: false,
|
|
15694
|
-
installed: false,
|
|
15695
|
-
detail: "not supported yet"
|
|
15696
|
-
};
|
|
15697
|
-
return {
|
|
15698
|
-
agent: normalizedAgent,
|
|
15699
|
-
displayName: name,
|
|
15700
|
-
supported: true,
|
|
15701
|
-
installed: false,
|
|
15702
|
-
configPath: getCodexConfigPath(),
|
|
15703
|
-
detail: "not installed"
|
|
15704
|
-
};
|
|
15705
|
-
}
|
|
15706
|
-
async function getIntegrationStatusAsync(agent) {
|
|
15707
|
-
const status = getIntegrationStatus(agent);
|
|
15708
|
-
if (status.agent !== "codex" || !status.configPath) return status;
|
|
15709
|
-
const contents = await readTextIfExists(status.configPath);
|
|
15710
|
-
const installed = contents.includes(TOPCHESTER_CODEX_BLOCK_START) && contents.includes(TOPCHESTER_CODEX_BLOCK_END);
|
|
15711
|
-
return {
|
|
15712
|
-
...status,
|
|
15713
|
-
installed,
|
|
15714
|
-
detail: installed ? "installed" : "not installed"
|
|
15715
|
-
};
|
|
15716
|
-
}
|
|
15717
|
-
async function listIntegrationStatusesAsync(agent) {
|
|
15718
|
-
if (agent) return [await getIntegrationStatusAsync(agent)];
|
|
15719
|
-
return await Promise.all(listIntegrationStatuses().map((status) => getIntegrationStatusAsync(status.agent)));
|
|
15720
|
-
}
|
|
15721
|
-
async function installIntegration(agent, action = "installed") {
|
|
15722
|
-
const status = await getIntegrationStatusAsync(agent);
|
|
15723
|
-
if (!status.supported || status.agent !== "codex" || !status.configPath) throw new Error(`Unsupported integration: ${agent}`);
|
|
15724
|
-
const next = appendMarkedBlock(removeMarkedBlock(await readTextIfExists(status.configPath)), formatCodexIntegrationBlock());
|
|
15725
|
-
await mkdir(dirname(status.configPath), { recursive: true });
|
|
15726
|
-
await writeFile(status.configPath, next);
|
|
15727
|
-
return {
|
|
15728
|
-
action,
|
|
15729
|
-
status: await getIntegrationStatusAsync(status.agent)
|
|
15730
|
-
};
|
|
15731
|
-
}
|
|
15732
|
-
async function removeIntegration(agent) {
|
|
15733
|
-
const status = await getIntegrationStatusAsync(agent);
|
|
15734
|
-
if (!status.supported || status.agent !== "codex" || !status.configPath) throw new Error(`Unsupported integration: ${agent}`);
|
|
15735
|
-
const before = await readTextIfExists(status.configPath);
|
|
15736
|
-
await mkdir(dirname(status.configPath), { recursive: true });
|
|
15737
|
-
await writeFile(status.configPath, ensureTrailingNewline(removeMarkedBlock(before)));
|
|
15738
|
-
return {
|
|
15739
|
-
action: "removed",
|
|
15740
|
-
status: await getIntegrationStatusAsync(status.agent)
|
|
15741
|
-
};
|
|
15742
|
-
}
|
|
15743
|
-
function formatIntegrationStatuses(statuses) {
|
|
15744
|
-
const lines = ["Integrations"];
|
|
15745
|
-
for (const status of statuses) {
|
|
15746
|
-
const state = status.supported ? status.installed ? "installed" : "not installed" : "unsupported";
|
|
15747
|
-
lines.push(`${status.agent}: ${state}`);
|
|
15748
|
-
if (status.configPath) lines.push(` config: ${status.configPath}`);
|
|
15749
|
-
if (!status.supported) lines.push(` detail: ${status.detail}`);
|
|
15750
|
-
}
|
|
15751
|
-
return lines;
|
|
15752
|
-
}
|
|
15753
|
-
function formatIntegrationAction(action, status) {
|
|
15754
|
-
return [
|
|
15755
|
-
action === "installed" ? "Integration installed" : action === "repaired" ? "Integration repaired" : "Integration removed",
|
|
15756
|
-
`agent: ${status.agent}`,
|
|
15757
|
-
`state: ${status.installed ? "installed" : "not installed"}`,
|
|
15758
|
-
...status.configPath ? [`config: ${status.configPath}`] : []
|
|
15759
|
-
];
|
|
15760
|
-
}
|
|
15761
|
-
async function executeHookStop(agent) {
|
|
15762
|
-
if (normalizeAgentId(agent ?? "") !== "codex") throw new Error(agent ? `Unsupported hook agent: ${agent}` : "Usage: topchester hook stop <agent>");
|
|
15763
|
-
}
|
|
15764
|
-
function getCodexConfigPath() {
|
|
15765
|
-
return join(process.env.CODEX_HOME?.trim() || join(process.env.HOME || homedir(), ".codex"), "config.toml");
|
|
15766
|
-
}
|
|
15767
|
-
function formatCodexIntegrationBlock() {
|
|
15768
|
-
return [
|
|
15769
|
-
TOPCHESTER_CODEX_BLOCK_START,
|
|
15770
|
-
"[[Stop]]",
|
|
15771
|
-
"",
|
|
15772
|
-
"[[Stop.hooks]]",
|
|
15773
|
-
"type = \"command\"",
|
|
15774
|
-
"command = \"topchester hook stop codex\"",
|
|
15775
|
-
"timeout = 10",
|
|
15776
|
-
"statusMessage = \"Notifying Topchester\"",
|
|
15777
|
-
TOPCHESTER_CODEX_BLOCK_END
|
|
15778
|
-
].join("\n");
|
|
15779
|
-
}
|
|
15780
|
-
function appendMarkedBlock(contents, block) {
|
|
15781
|
-
const base = contents.trimEnd();
|
|
15782
|
-
return `${base ? `${base}\n\n` : ""}${block}\n`;
|
|
15783
|
-
}
|
|
15784
|
-
function removeMarkedBlock(contents) {
|
|
15785
|
-
const start = contents.indexOf(TOPCHESTER_CODEX_BLOCK_START);
|
|
15786
|
-
if (start === -1) return contents;
|
|
15787
|
-
const end = contents.indexOf(TOPCHESTER_CODEX_BLOCK_END, start);
|
|
15788
|
-
if (end === -1) return contents;
|
|
15789
|
-
return `${contents.slice(0, start)}${contents.slice(end + 35)}`.trimEnd();
|
|
15790
|
-
}
|
|
15791
|
-
async function readTextIfExists(path) {
|
|
15792
|
-
try {
|
|
15793
|
-
return await readFile(path, "utf8");
|
|
15794
|
-
} catch (error) {
|
|
15795
|
-
if (isNodeError(error) && error.code === "ENOENT") return "";
|
|
15796
|
-
throw error;
|
|
15797
|
-
}
|
|
15798
|
-
}
|
|
15799
|
-
function ensureTrailingNewline(value) {
|
|
15800
|
-
return value ? `${value.trimEnd()}\n` : "";
|
|
15801
|
-
}
|
|
15802
|
-
function normalizeAgentId(value) {
|
|
15803
|
-
return value.trim().toLowerCase();
|
|
15804
|
-
}
|
|
15805
|
-
function isNodeError(error) {
|
|
15806
|
-
return error instanceof Error && "code" in error;
|
|
15807
|
-
}
|
|
15808
|
-
//#endregion
|
|
15809
15708
|
//#region src/cli.ts
|
|
15810
15709
|
async function runTopchesterCli(argv = process.argv, options = {}) {
|
|
15811
15710
|
const program = createTopchesterProgram();
|
|
@@ -15864,6 +15763,25 @@ function createTopchesterProgram() {
|
|
|
15864
15763
|
process.exitCode = 1;
|
|
15865
15764
|
}
|
|
15866
15765
|
});
|
|
15766
|
+
program.command("mcp").description("manage MCP servers").command("add").usage("[options] <server-name> -- <stdio server-command>").description("add or replace a stdio MCP server").argument("<server-name>", "server name").argument("<command...>", "stdio server command after --").option("--env <KEY=VALUE>", "environment variable for the server process", collectEnvPair, {}).addHelpText("after", formatMcpAddHelp).action(async (serverName, commandParts, options) => {
|
|
15767
|
+
try {
|
|
15768
|
+
const [command, ...args] = commandParts;
|
|
15769
|
+
if (!command) throw new Error("Usage: topchester mcp add <server-name> -- <stdio server-command>");
|
|
15770
|
+
const result = await addMcpStdioServerConfig(getWritableConfigPathFromProgram(program), {
|
|
15771
|
+
serverName,
|
|
15772
|
+
command,
|
|
15773
|
+
args,
|
|
15774
|
+
env: options.env
|
|
15775
|
+
});
|
|
15776
|
+
console.log(`${result.replaced ? "Updated" : "Added"} MCP stdio server "${result.serverName}".`);
|
|
15777
|
+
console.log(`config: ${result.path}`);
|
|
15778
|
+
console.log(`command: ${[result.command, ...result.args].join(" ")}`);
|
|
15779
|
+
if (Object.keys(result.env).length > 0) console.log(`env: ${Object.keys(result.env).join(", ")}`);
|
|
15780
|
+
} catch (error) {
|
|
15781
|
+
console.error(formatStartupError(error));
|
|
15782
|
+
process.exitCode = 1;
|
|
15783
|
+
}
|
|
15784
|
+
});
|
|
15867
15785
|
program.command("run").description("run one prompt or slash command without opening the TUI").argument("<prompt...>", "prompt text or slash command").option("--model <model>", "override the agent.primary model for this run").option("--timeout <ms>", "timeout for the run in milliseconds", parsePositiveInteger).option("--json", "write JSONL run events to stdout").option("--output-json <path>", "write JSONL run events to a file").action(async (promptParts, options) => {
|
|
15868
15786
|
const context = createContextFromOptions(program);
|
|
15869
15787
|
const globalOptions = program.opts();
|
|
@@ -15896,58 +15814,6 @@ function createTopchesterProgram() {
|
|
|
15896
15814
|
program.command("search").description("search compiled L1 knowledge entries").argument("<query...>", "search query").option("--limit <count>", "maximum number of matches", parsePositiveInteger).option("--json", "write full JSON search result to stdout").action(async (queryParts, options) => {
|
|
15897
15815
|
await executeKbSearchCommand(program, queryParts, options);
|
|
15898
15816
|
});
|
|
15899
|
-
const integrationsCommand = program.command("integrations").description("manage Topchester integrations with other agents");
|
|
15900
|
-
integrationsCommand.command("list").description("list supported integrations").action(async () => {
|
|
15901
|
-
try {
|
|
15902
|
-
console.log(formatIntegrationStatuses(await listIntegrationStatusesAsync()).join("\n"));
|
|
15903
|
-
} catch (error) {
|
|
15904
|
-
console.error(formatStartupError(error));
|
|
15905
|
-
process.exitCode = 1;
|
|
15906
|
-
}
|
|
15907
|
-
});
|
|
15908
|
-
integrationsCommand.command("status").description("check whether integrations are installed").argument("[agent]", "agent id").action(async (agent) => {
|
|
15909
|
-
try {
|
|
15910
|
-
console.log(formatIntegrationStatuses(await listIntegrationStatusesAsync(agent)).join("\n"));
|
|
15911
|
-
} catch (error) {
|
|
15912
|
-
console.error(formatStartupError(error));
|
|
15913
|
-
process.exitCode = 1;
|
|
15914
|
-
}
|
|
15915
|
-
});
|
|
15916
|
-
integrationsCommand.command("install").description("install Topchester lifecycle hooks for another agent").argument("<agent>", "agent id").action(async (agent) => {
|
|
15917
|
-
try {
|
|
15918
|
-
const result = await installIntegration(agent);
|
|
15919
|
-
console.log(formatIntegrationAction(result.action, result.status).join("\n"));
|
|
15920
|
-
} catch (error) {
|
|
15921
|
-
console.error(formatStartupError(error));
|
|
15922
|
-
process.exitCode = 1;
|
|
15923
|
-
}
|
|
15924
|
-
});
|
|
15925
|
-
integrationsCommand.command("repair").description("repair a Topchester integration").argument("<agent>", "agent id").action(async (agent) => {
|
|
15926
|
-
try {
|
|
15927
|
-
const result = await installIntegration(agent, "repaired");
|
|
15928
|
-
console.log(formatIntegrationAction(result.action, result.status).join("\n"));
|
|
15929
|
-
} catch (error) {
|
|
15930
|
-
console.error(formatStartupError(error));
|
|
15931
|
-
process.exitCode = 1;
|
|
15932
|
-
}
|
|
15933
|
-
});
|
|
15934
|
-
integrationsCommand.command("remove").description("remove a Topchester integration").argument("<agent>", "agent id").action(async (agent) => {
|
|
15935
|
-
try {
|
|
15936
|
-
const result = await removeIntegration(agent);
|
|
15937
|
-
console.log(formatIntegrationAction(result.action, result.status).join("\n"));
|
|
15938
|
-
} catch (error) {
|
|
15939
|
-
console.error(formatStartupError(error));
|
|
15940
|
-
process.exitCode = 1;
|
|
15941
|
-
}
|
|
15942
|
-
});
|
|
15943
|
-
program.command("hook").description("low-level lifecycle hook endpoints").command("stop").description("receive a Stop hook from another agent").argument("<agent>", "agent id").action(async (agent) => {
|
|
15944
|
-
try {
|
|
15945
|
-
await executeHookStop(agent);
|
|
15946
|
-
} catch (error) {
|
|
15947
|
-
console.error(formatStartupError(error));
|
|
15948
|
-
process.exitCode = 1;
|
|
15949
|
-
}
|
|
15950
|
-
});
|
|
15951
15817
|
const kbCommand = program.command("kb").description("knowledge base commands");
|
|
15952
15818
|
kbCommand.command("init").description("initialize a project knowledge base").action(async () => {
|
|
15953
15819
|
const context = createContextFromOptions(program);
|
|
@@ -16063,6 +15929,17 @@ function formatAuthLoginHelp() {
|
|
|
16063
15929
|
" Topchester prints a browser URL and one-time code, waits for approval, then stores tokens in the global auth store."
|
|
16064
15930
|
].join("\n");
|
|
16065
15931
|
}
|
|
15932
|
+
function formatMcpAddHelp() {
|
|
15933
|
+
return [
|
|
15934
|
+
"",
|
|
15935
|
+
ui.label("Examples:"),
|
|
15936
|
+
" topchester mcp add filesystem -- npx -y @modelcontextprotocol/server-filesystem .",
|
|
15937
|
+
" topchester mcp add github --env GITHUB_PERSONAL_ACCESS_TOKEN=ghp_xxx -- npx -y @modelcontextprotocol/server-github",
|
|
15938
|
+
"",
|
|
15939
|
+
ui.label("What happens:"),
|
|
15940
|
+
" Writes to --config when provided, otherwise to the global user config."
|
|
15941
|
+
].join("\n");
|
|
15942
|
+
}
|
|
16066
15943
|
function formatAuthLoginUsageError(reason) {
|
|
16067
15944
|
return [
|
|
16068
15945
|
ui.error(reason),
|
|
@@ -16137,6 +16014,10 @@ function getContextOptionsFromProgram(program) {
|
|
|
16137
16014
|
devFlags: options.dev
|
|
16138
16015
|
};
|
|
16139
16016
|
}
|
|
16017
|
+
function getWritableConfigPathFromProgram(program) {
|
|
16018
|
+
const options = program.opts();
|
|
16019
|
+
return options.config ? isAbsolute(options.config) ? options.config : resolve(cwd(), options.config) : getGlobalTopchesterConfigPath();
|
|
16020
|
+
}
|
|
16140
16021
|
async function executeKbSearchCommand(program, queryParts, options) {
|
|
16141
16022
|
const context = createContextFromOptions(program);
|
|
16142
16023
|
const query = queryParts.join(" ");
|
|
@@ -16170,6 +16051,16 @@ function formatStartupError(error) {
|
|
|
16170
16051
|
function collectDevFlag(flag, flags) {
|
|
16171
16052
|
return [...flags, flag];
|
|
16172
16053
|
}
|
|
16054
|
+
function collectEnvPair(raw, env) {
|
|
16055
|
+
const separatorIndex = raw.indexOf("=");
|
|
16056
|
+
if (separatorIndex <= 0) throw new Error("Environment entries must be in KEY=VALUE form.");
|
|
16057
|
+
const key = raw.slice(0, separatorIndex).trim();
|
|
16058
|
+
if (!key) throw new Error("Environment entries must be in KEY=VALUE form.");
|
|
16059
|
+
return {
|
|
16060
|
+
...env,
|
|
16061
|
+
[key]: raw.slice(separatorIndex + 1)
|
|
16062
|
+
};
|
|
16063
|
+
}
|
|
16173
16064
|
function parsePositiveInteger(value) {
|
|
16174
16065
|
const parsed = Number(value);
|
|
16175
16066
|
if (!Number.isInteger(parsed) || parsed <= 0) throw new Error("Expected a positive integer.");
|
|
@@ -16191,4 +16082,4 @@ function formatDryRunSyncStatus(status) {
|
|
|
16191
16082
|
//#endregion
|
|
16192
16083
|
export { runTopchesterCli as t };
|
|
16193
16084
|
|
|
16194
|
-
//# sourceMappingURL=cli-
|
|
16085
|
+
//# sourceMappingURL=cli-YPKTdpQH.mjs.map
|