orquesta-cli 0.2.108 → 0.2.112

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.
Files changed (34) hide show
  1. package/dist/cli.js +23 -1
  2. package/dist/core/commands/help.js +5 -0
  3. package/dist/core/commands/index.js +7 -0
  4. package/dist/core/commands/lsp.d.ts +3 -0
  5. package/dist/core/commands/lsp.js +37 -0
  6. package/dist/core/commands/mcp.d.ts +3 -0
  7. package/dist/core/commands/mcp.js +46 -0
  8. package/dist/core/commands/undo.d.ts +4 -0
  9. package/dist/core/commands/undo.js +45 -0
  10. package/dist/core/config/config-manager.d.ts +7 -1
  11. package/dist/core/config/config-manager.js +36 -0
  12. package/dist/core/file-snapshot-store.d.ts +25 -0
  13. package/dist/core/file-snapshot-store.js +104 -0
  14. package/dist/core/lsp/index.d.ts +6 -0
  15. package/dist/core/lsp/index.js +75 -0
  16. package/dist/core/lsp/jsonrpc.d.ts +18 -0
  17. package/dist/core/lsp/jsonrpc.js +38 -0
  18. package/dist/core/lsp/lsp-client.d.ts +40 -0
  19. package/dist/core/lsp/lsp-client.js +201 -0
  20. package/dist/core/lsp/server-registry.d.ts +14 -0
  21. package/dist/core/lsp/server-registry.js +85 -0
  22. package/dist/eval/eval-runner.js +14 -0
  23. package/dist/orchestration/plan-executor.js +2 -0
  24. package/dist/tools/llm/simple/file-tools.js +8 -2
  25. package/dist/tools/mcp/index.d.ts +3 -0
  26. package/dist/tools/mcp/index.js +3 -0
  27. package/dist/tools/mcp/mcp-client.d.ts +16 -0
  28. package/dist/tools/mcp/mcp-client.js +180 -0
  29. package/dist/tools/mcp/mcp-config.d.ts +4 -0
  30. package/dist/tools/mcp/mcp-config.js +87 -0
  31. package/dist/types/index.d.ts +21 -0
  32. package/dist/ui/components/PlanExecuteApp.js +25 -2
  33. package/dist/ui/hooks/slashCommandProcessor.js +17 -0
  34. package/package.json +2 -1
@@ -0,0 +1,87 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import { configManager } from '../../core/config/config-manager.js';
4
+ import { logger } from '../../utils/logger.js';
5
+ function normalizeEntry(name, raw) {
6
+ if (!name || typeof name !== 'string' || !raw || typeof raw !== 'object')
7
+ return null;
8
+ const e = raw;
9
+ const enabled = e.enabled === false || e.disabled === true ? false : true;
10
+ const cfg = {
11
+ name,
12
+ enabled,
13
+ ...(e.command ? { command: e.command } : {}),
14
+ ...(Array.isArray(e.args) ? { args: e.args } : {}),
15
+ ...(e.env && typeof e.env === 'object' ? { env: e.env } : {}),
16
+ ...(e.cwd ? { cwd: e.cwd } : {}),
17
+ ...(e.url ? { url: e.url } : {}),
18
+ ...(e.headers && typeof e.headers === 'object' ? { headers: e.headers } : {}),
19
+ };
20
+ if (!cfg.command && !cfg.url) {
21
+ logger.warn('MCP server entry has neither command nor url; skipping', { name });
22
+ return null;
23
+ }
24
+ return cfg;
25
+ }
26
+ function parseFile(filePath) {
27
+ let raw;
28
+ try {
29
+ raw = fs.readFileSync(filePath, 'utf8');
30
+ }
31
+ catch {
32
+ return [];
33
+ }
34
+ let parsed;
35
+ try {
36
+ parsed = JSON.parse(raw);
37
+ }
38
+ catch (err) {
39
+ logger.warn('MCP config file is not valid JSON; skipping', {
40
+ filePath,
41
+ error: err instanceof Error ? err.message : String(err),
42
+ });
43
+ return [];
44
+ }
45
+ return normalizeSource(parsed);
46
+ }
47
+ export function normalizeSource(parsed) {
48
+ if (parsed == null || typeof parsed !== 'object')
49
+ return [];
50
+ if (Array.isArray(parsed)) {
51
+ return parsed
52
+ .map((entry) => {
53
+ const name = entry?.name;
54
+ return name ? normalizeEntry(name, entry) : null;
55
+ })
56
+ .filter((x) => x !== null);
57
+ }
58
+ const obj = parsed;
59
+ const map = obj.mcpServers && typeof obj.mcpServers === 'object' ? obj.mcpServers : obj;
60
+ const out = [];
61
+ for (const [name, entry] of Object.entries(map)) {
62
+ if (!entry || typeof entry !== 'object')
63
+ continue;
64
+ const cfg = normalizeEntry(name, entry);
65
+ if (cfg)
66
+ out.push(cfg);
67
+ }
68
+ return out;
69
+ }
70
+ export function loadMcpServerConfigs(cwd = process.cwd()) {
71
+ const byName = new Map();
72
+ const add = (servers) => {
73
+ for (const s of servers)
74
+ byName.set(s.name, s);
75
+ };
76
+ try {
77
+ const global = configManager.getConfig().mcpServers;
78
+ if (Array.isArray(global))
79
+ add(normalizeSource(global));
80
+ }
81
+ catch {
82
+ }
83
+ add(parseFile(path.join(cwd, '.mcp.json')));
84
+ add(parseFile(path.join(cwd, '.orquesta', 'mcp.json')));
85
+ return Array.from(byName.values()).filter((s) => s.enabled !== false);
86
+ }
87
+ //# sourceMappingURL=mcp-config.js.map
@@ -128,6 +128,22 @@ export interface OrchestrationConfig {
128
128
  worktreeIsolation?: boolean;
129
129
  singleAgentMode?: boolean;
130
130
  }
131
+ export interface McpServerConfig {
132
+ name: string;
133
+ command?: string;
134
+ args?: string[];
135
+ env?: Record<string, string>;
136
+ cwd?: string;
137
+ url?: string;
138
+ headers?: Record<string, string>;
139
+ enabled?: boolean;
140
+ }
141
+ export interface LspServerConfig {
142
+ id: string;
143
+ extensions: string[];
144
+ command: string;
145
+ args: string[];
146
+ }
131
147
  export interface OpenConfig {
132
148
  version: string;
133
149
  currentEndpoint?: string;
@@ -143,6 +159,11 @@ export interface OpenConfig {
143
159
  safeEnvVars?: string[];
144
160
  orquesta?: OrquestaConfig;
145
161
  orchestration?: OrchestrationConfig;
162
+ mcpServers?: McpServerConfig[];
163
+ lspServers?: LspServerConfig[];
164
+ lsp?: {
165
+ enabled?: boolean;
166
+ };
146
167
  }
147
168
  export interface TodoItem {
148
169
  id: string;
@@ -640,6 +640,29 @@ export const PlanExecuteApp = ({ llmClient: initialLlmClient, modelInfo, resumeL
640
640
  if (key.ctrl && inputChar === 'o') {
641
641
  setShowLogFiles(prev => !prev);
642
642
  }
643
+ if (key.ctrl && inputChar === 's') {
644
+ if (showSessionBrowser ||
645
+ showSettings ||
646
+ showSetupWizard ||
647
+ fileBrowserState.showFileBrowser ||
648
+ commandBrowserState.showCommandBrowser ||
649
+ planExecutionState.askUserRequest ||
650
+ pendingToolApproval) {
651
+ return;
652
+ }
653
+ const text = input.trim();
654
+ if (text) {
655
+ if (isProcessing) {
656
+ addLog({ type: 'user_input', content: `(⚡ steering now — picked up at next step) ${text}` });
657
+ setPendingUserMessage(text);
658
+ setInput('');
659
+ }
660
+ else {
661
+ handleSubmitRef.current?.(text);
662
+ }
663
+ }
664
+ return;
665
+ }
643
666
  });
644
667
  const handleFileSelect = useCallback((filePaths) => {
645
668
  logger.debug('File selected', { filePaths });
@@ -1486,14 +1509,14 @@ export const PlanExecuteApp = ({ llmClient: initialLlmClient, modelInfo, resumeL
1486
1509
  }
1487
1510
  setInput(value);
1488
1511
  }, onSubmit: handleSubmit, onHistoryPrev: isAnyPanelOpen ? undefined : handleHistoryPrev, onHistoryNext: isAnyPanelOpen ? undefined : handleHistoryNext, placeholder: isProcessing
1489
- ? "AI is working..."
1512
+ ? "AI is working... (type + Ctrl+S to steer now)"
1490
1513
  : showSessionBrowser
1491
1514
  ? "Select a session or press ESC..."
1492
1515
  : showSettings
1493
1516
  ? "Press ESC to close settings..."
1494
1517
  : showDocsBrowser
1495
1518
  ? "Select a doc source or press ESC..."
1496
- : "Type your message... (@ files, / commands, Alt+Enter newline)", focus: !showSessionBrowser && !showSettings && !showDocsBrowser && !planExecutionState.askUserRequest && updatePhase === 'hidden' })),
1519
+ : "Type your message... (@ files, / commands, Alt+Enter newline, Ctrl+S send)", focus: !showSessionBrowser && !showSettings && !showDocsBrowser && !planExecutionState.askUserRequest && updatePhase === 'hidden' })),
1497
1520
  input.length > 0 && (React.createElement(Text, { color: input.length > 4000 ? 'red' : input.length > 2000 ? 'yellow' : 'gray', dimColor: true }, input.length.toLocaleString())))),
1498
1521
  fileBrowserState.showFileBrowser && !isProcessing && (React.createElement(Box, { marginTop: 0 }, fileBrowserState.isLoadingFiles ? (React.createElement(Box, { borderStyle: "single", borderColor: "yellow", paddingX: 1 },
1499
1522
  React.createElement(Spinner, { type: "dots" }),
@@ -8,6 +8,14 @@ export const SLASH_COMMANDS = [
8
8
  name: '/clear',
9
9
  description: 'Clear conversation and TODOs',
10
10
  },
11
+ {
12
+ name: '/undo',
13
+ description: 'Revert the file changes from the last turn',
14
+ },
15
+ {
16
+ name: '/redo',
17
+ description: 'Re-apply the changes undone by /undo',
18
+ },
11
19
  {
12
20
  name: '/compact',
13
21
  description: 'Compact conversation to free up context',
@@ -49,6 +57,15 @@ export const SLASH_COMMANDS = [
49
57
  description: 'Enable/disable optional tools (Browser, Background)',
50
58
  aliases: ['/tools'],
51
59
  },
60
+ {
61
+ name: '/mcp',
62
+ description: 'List connected MCP servers and their tools',
63
+ },
64
+ {
65
+ name: '/lsp',
66
+ description: 'LSP diagnostics after edits: status | on | off',
67
+ argsHint: 'on | off',
68
+ },
52
69
  {
53
70
  name: '/usage',
54
71
  description: 'Show token usage statistics',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orquesta-cli",
3
- "version": "0.2.108",
3
+ "version": "0.2.112",
4
4
  "description": "Orquesta CLI - AI-powered coding assistant with team collaboration",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -92,6 +92,7 @@
92
92
  },
93
93
  "dependencies": {
94
94
  "@anthropic-ai/sdk": "^0.32.1",
95
+ "@modelcontextprotocol/sdk": "^1.29.0",
95
96
  "axios": "^1.6.2",
96
97
  "chalk": "^4.1.2",
97
98
  "commander": "^11.1.0",