@openeryc/pi-coding-agent 0.75.37 → 0.75.38

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.
@@ -50,6 +50,7 @@ import { ExtensionSelectorComponent } from "./components/extension-selector.js";
50
50
  import { FooterComponent } from "./components/footer.js";
51
51
  import { formatKeyText, keyDisplayText, keyHint, keyText, rawKeyHint } from "./components/keybinding-hints.js";
52
52
  import { LoginDialogComponent } from "./components/login-dialog.js";
53
+ import { McpSelectorComponent } from "./components/mcp-selector.js";
53
54
  import { ModelSelectorComponent } from "./components/model-selector.js";
54
55
  import { OAuthSelectorComponent } from "./components/oauth-selector.js";
55
56
  import { ScopedModelsSelectorComponent } from "./components/scoped-models-selector.js";
@@ -2022,14 +2023,19 @@ export class InteractiveMode {
2022
2023
  return;
2023
2024
  }
2024
2025
  if (text === "/mcp") {
2025
- this.handleMcpCommand();
2026
2026
  this.editor.setText("");
2027
+ this.showMcpSelector();
2027
2028
  return;
2028
2029
  }
2029
2030
  if (text.startsWith("/mcp ")) {
2030
2031
  const name = text.slice(5).trim();
2031
- this.handleMcpToggle(name);
2032
2032
  this.editor.setText("");
2033
+ this.showMcpSelector(name);
2034
+ return;
2035
+ }
2036
+ if (text === "/skills") {
2037
+ this.editor.setText("");
2038
+ this.showSkillsSelector();
2033
2039
  return;
2034
2040
  }
2035
2041
  if (text === "/usage") {
@@ -4408,84 +4414,75 @@ export class InteractiveMode {
4408
4414
  this.chatContainer.addChild(new Text(info, 1, 0));
4409
4415
  this.ui.requestRender();
4410
4416
  }
4411
- handleMcpCommand(highlightServer) {
4412
- const configuredServers = this.settingsManager.getMcpServers();
4417
+ showMcpSelector(highlightServer) {
4418
+ const configured = this.settingsManager.getMcpServers();
4413
4419
  const allTools = this.session.getAllTools();
4414
4420
  const mcpTools = allTools.filter((t) => t.name.startsWith("mcp_"));
4415
- const toolsByServer = new Map();
4421
+ const toolCountByServer = new Map();
4416
4422
  for (const tool of mcpTools) {
4417
4423
  const rest = tool.name.slice(4);
4418
- const secondUnderscore = rest.indexOf("_");
4419
- const serverName = secondUnderscore === -1 ? rest : rest.slice(0, secondUnderscore);
4420
- const existing = toolsByServer.get(serverName);
4421
- if (existing) {
4422
- existing.push(tool);
4423
- }
4424
- else {
4425
- toolsByServer.set(serverName, [tool]);
4426
- }
4427
- }
4428
- this.chatContainer.addChild(new Spacer(1));
4429
- if (!configuredServers || Object.keys(configuredServers).length === 0) {
4424
+ const idx = rest.indexOf("_");
4425
+ const srv = idx === -1 ? rest : rest.slice(0, idx);
4426
+ toolCountByServer.set(srv, (toolCountByServer.get(srv) ?? 0) + 1);
4427
+ }
4428
+ const items = (configured ? Object.entries(configured) : []).map(([name, cfg]) => {
4429
+ const disabled = cfg.enabled === false;
4430
+ const connected = (toolCountByServer.get(name) ?? 0) > 0;
4431
+ const transport = cfg.url ? (cfg.transport ?? "sse") : cfg.command ? "stdio" : "unknown";
4432
+ return {
4433
+ name,
4434
+ status: disabled ? "disabled" : connected ? "connected" : "disconnected",
4435
+ toolCount: toolCountByServer.get(name) ?? 0,
4436
+ transport,
4437
+ };
4438
+ });
4439
+ if (items.length === 0) {
4440
+ this.chatContainer.addChild(new Spacer(1));
4430
4441
  this.chatContainer.addChild(new Text(`${theme.bold("MCP Servers")}\n\n${theme.fg("dim", "No MCP servers configured. Add 'mcpServers' to settings.json.")}`, 1, 0));
4431
4442
  this.ui.requestRender();
4432
4443
  return;
4433
4444
  }
4434
- let info = `${theme.bold("MCP Servers")}\n`;
4435
- info += `${theme.fg("dim", "Use /mcp <name> to toggle or view details")}\n\n`;
4436
- let idx = 0;
4437
- for (const [serverName, config] of Object.entries(configuredServers)) {
4438
- const tools = toolsByServer.get(serverName) ?? [];
4439
- const disabled = config.enabled === false;
4440
- const connected = tools.length > 0;
4441
- let status;
4442
- if (disabled) {
4443
- status = theme.fg("muted", "disabled");
4444
- }
4445
- else if (connected) {
4446
- status = theme.fg("success", "connected");
4447
- }
4448
- else {
4449
- status = theme.fg("warning", "disconnected");
4450
- }
4451
- const toggleHint = disabled ? "[/mcp " + serverName + " to enable]" : "[/mcp " + serverName + " to disable]";
4452
- const transport = config.url ? (config.transport ?? "sse") : config.command ? "stdio" : "unknown";
4453
- const toolCount = tools.length;
4454
- info += `${theme.bold(++idx + ". " + serverName)} ${status} ${theme.fg("dim", toggleHint)}\n`;
4455
- info += `${theme.fg("dim", ` Transport: ${transport} | Tools: ${toolCount}`)}\n`;
4456
- if (config.command) {
4457
- const cmd = config.args ? `${config.command} ${config.args.join(" ")}` : config.command;
4458
- info += `${theme.fg("dim", ` Command: ${cmd}`)}\n`;
4459
- }
4460
- if (config.url) {
4461
- info += `${theme.fg("dim", ` URL: ${config.url}`)}\n`;
4462
- }
4463
- // Show detailed tool list only for highlighted server
4464
- if (highlightServer === serverName && connected) {
4465
- for (const tool of tools) {
4466
- const desc = tool.description ? ` - ${tool.description.split("\n")[0].slice(0, 80)}` : "";
4467
- info += `${theme.fg("dim", ` ${tool.name}${desc}`)}\n`;
4468
- }
4445
+ if (highlightServer) {
4446
+ const server = configured?.[highlightServer];
4447
+ if (server) {
4448
+ const currentEnabled = server.enabled !== false;
4449
+ this.settingsManager.setMcpServerEnabled(highlightServer, !currentEnabled);
4450
+ this.session.reloadMcp();
4469
4451
  }
4470
- info += "\n";
4471
4452
  }
4472
- this.chatContainer.addChild(new Text(info, 1, 0));
4473
- this.ui.requestRender();
4453
+ this.showSelector((done) => {
4454
+ const selector = new McpSelectorComponent(items, async (name) => {
4455
+ const server = configured?.[name];
4456
+ if (!server)
4457
+ return;
4458
+ const currentEnabled = server.enabled !== false;
4459
+ this.settingsManager.setMcpServerEnabled(name, !currentEnabled);
4460
+ await this.session.reloadMcp();
4461
+ done();
4462
+ this.showStatus(`${name} ${currentEnabled ? "disabled" : "enabled"}`);
4463
+ }, () => done());
4464
+ return { component: selector, focus: selector };
4465
+ });
4474
4466
  }
4475
- async handleMcpToggle(serverName) {
4476
- const mcpServers = this.settingsManager.getMcpServers();
4477
- if (!mcpServers || !mcpServers[serverName]) {
4467
+ showSkillsSelector() {
4468
+ const skills = this.session.resourceLoader.getSkills().skills;
4469
+ if (skills.length === 0) {
4478
4470
  this.chatContainer.addChild(new Spacer(1));
4479
- this.chatContainer.addChild(new Text(theme.fg("warning", `MCP server "${serverName}" not found.`), 1, 0));
4471
+ this.chatContainer.addChild(new Text(theme.fg("dim", "No skills loaded."), 1, 0));
4480
4472
  this.ui.requestRender();
4481
4473
  return;
4482
4474
  }
4483
- const currentEnabled = mcpServers[serverName].enabled !== false;
4484
- this.settingsManager.setMcpServerEnabled(serverName, !currentEnabled);
4485
- await this.session.reloadMcp();
4486
- this.chatContainer.addChild(new Spacer(1));
4487
- this.chatContainer.addChild(new Text(`${theme.bold(serverName)} ${theme.fg(currentEnabled ? "muted" : "success", currentEnabled ? "disabled" : "enabled")}`, 1, 0));
4488
- this.handleMcpCommand(serverName);
4475
+ this.showSelector((done) => {
4476
+ const selector = new McpSelectorComponent(skills.map((s) => ({
4477
+ name: s.name,
4478
+ status: s.disableModelInvocation ? "disabled" : "connected",
4479
+ toolCount: 0,
4480
+ transport: s.description.slice(0, 60),
4481
+ })), (_name) => {
4482
+ done();
4483
+ }, () => done());
4484
+ return { component: selector, focus: selector };
4485
+ });
4489
4486
  }
4490
4487
  async handleUsageCommand() {
4491
4488
  this.showStatus("Loading usage stats...");