orkestrate 0.1.13 → 0.1.15
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/cli.js +523 -111
- package/dist/cli.js.map +1 -1
- package/dist/mcp-entry.js +162 -41
- package/dist/mcp-entry.js.map +1 -1
- package/package.json +50 -50
package/dist/cli.js
CHANGED
|
@@ -112,21 +112,64 @@ var init_ui = __esm({
|
|
|
112
112
|
|
|
113
113
|
// src/lib/config.ts
|
|
114
114
|
import Conf from "conf";
|
|
115
|
+
import { readFileSync, writeFileSync, existsSync } from "fs";
|
|
116
|
+
import { dirname } from "path";
|
|
117
|
+
import { mkdirSync } from "fs";
|
|
115
118
|
function getServerUrl() {
|
|
116
119
|
return config.get("serverUrl");
|
|
117
120
|
}
|
|
121
|
+
function setConfigWithRetry(key, value, maxAttempts = 5) {
|
|
122
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
123
|
+
try {
|
|
124
|
+
config.set(key, value);
|
|
125
|
+
return;
|
|
126
|
+
} catch (err) {
|
|
127
|
+
if (err?.code !== "EPERM" && err?.code !== "EBUSY") {
|
|
128
|
+
throw err;
|
|
129
|
+
}
|
|
130
|
+
const delay = 50 * Math.pow(2, attempt);
|
|
131
|
+
if (attempt < maxAttempts - 1) {
|
|
132
|
+
const start = Date.now();
|
|
133
|
+
while (Date.now() - start < delay) {
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
try {
|
|
139
|
+
const configPath = config.path;
|
|
140
|
+
const dir = dirname(configPath);
|
|
141
|
+
if (!existsSync(dir)) {
|
|
142
|
+
mkdirSync(dir, { recursive: true });
|
|
143
|
+
}
|
|
144
|
+
let currentConfig = {};
|
|
145
|
+
if (existsSync(configPath)) {
|
|
146
|
+
try {
|
|
147
|
+
currentConfig = JSON.parse(readFileSync(configPath, "utf-8"));
|
|
148
|
+
} catch {
|
|
149
|
+
currentConfig = {};
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
currentConfig[key] = value;
|
|
153
|
+
writeFileSync(configPath, JSON.stringify(currentConfig, null, 2), "utf-8");
|
|
154
|
+
return;
|
|
155
|
+
} catch (fallbackErr) {
|
|
156
|
+
throw new Error(
|
|
157
|
+
`Failed to save config after ${maxAttempts} attempts. Original error: ${fallbackErr instanceof Error ? fallbackErr.message : String(fallbackErr)}`
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
118
161
|
function setCredentials(creds) {
|
|
119
|
-
|
|
162
|
+
setConfigWithRetry("credentials", creds);
|
|
120
163
|
}
|
|
121
164
|
function getCredentials() {
|
|
122
165
|
return config.get("credentials");
|
|
123
166
|
}
|
|
124
167
|
function clearCredentials() {
|
|
125
|
-
|
|
168
|
+
setConfigWithRetry("credentials", null);
|
|
126
169
|
}
|
|
127
170
|
function setActiveWorkspace(id, name) {
|
|
128
|
-
|
|
129
|
-
|
|
171
|
+
setConfigWithRetry("activeWorkspaceId", id);
|
|
172
|
+
setConfigWithRetry("activeWorkspaceName", name);
|
|
130
173
|
}
|
|
131
174
|
function getActiveWorkspace() {
|
|
132
175
|
return {
|
|
@@ -137,6 +180,64 @@ function getActiveWorkspace() {
|
|
|
137
180
|
function getConfigPath() {
|
|
138
181
|
return config.path;
|
|
139
182
|
}
|
|
183
|
+
function getUserToolSettings() {
|
|
184
|
+
return config.get("userToolSettings") || {};
|
|
185
|
+
}
|
|
186
|
+
function setUserToolSettings(settings) {
|
|
187
|
+
setConfigWithRetry("userToolSettings", settings);
|
|
188
|
+
}
|
|
189
|
+
function getEnabledTools() {
|
|
190
|
+
const settings = getUserToolSettings();
|
|
191
|
+
return settings.enabledTools ?? null;
|
|
192
|
+
}
|
|
193
|
+
function getDisabledTools() {
|
|
194
|
+
const settings = getUserToolSettings();
|
|
195
|
+
return settings.disabledTools || [];
|
|
196
|
+
}
|
|
197
|
+
function setEnabledTools(tools) {
|
|
198
|
+
const settings = getUserToolSettings();
|
|
199
|
+
settings.enabledTools = tools;
|
|
200
|
+
setUserToolSettings(settings);
|
|
201
|
+
}
|
|
202
|
+
function setDisabledTools(tools) {
|
|
203
|
+
const settings = getUserToolSettings();
|
|
204
|
+
settings.disabledTools = tools;
|
|
205
|
+
setUserToolSettings(settings);
|
|
206
|
+
}
|
|
207
|
+
function isToolAllowed(toolName) {
|
|
208
|
+
const enabledTools = getEnabledTools();
|
|
209
|
+
const disabledTools = getDisabledTools();
|
|
210
|
+
if (enabledTools !== null) {
|
|
211
|
+
return enabledTools.includes(toolName);
|
|
212
|
+
}
|
|
213
|
+
return !disabledTools.includes(toolName);
|
|
214
|
+
}
|
|
215
|
+
function enableTool(toolName) {
|
|
216
|
+
const enabledTools = getEnabledTools();
|
|
217
|
+
const disabledTools = getDisabledTools();
|
|
218
|
+
if (enabledTools !== null) {
|
|
219
|
+
if (!enabledTools.includes(toolName)) {
|
|
220
|
+
setEnabledTools([...enabledTools, toolName]);
|
|
221
|
+
}
|
|
222
|
+
} else {
|
|
223
|
+
if (disabledTools.includes(toolName)) {
|
|
224
|
+
setDisabledTools(disabledTools.filter((t) => t !== toolName));
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
function disableTool(toolName) {
|
|
229
|
+
const enabledTools = getEnabledTools();
|
|
230
|
+
const disabledTools = getDisabledTools();
|
|
231
|
+
if (enabledTools !== null) {
|
|
232
|
+
if (enabledTools.includes(toolName)) {
|
|
233
|
+
setEnabledTools(enabledTools.filter((t) => t !== toolName));
|
|
234
|
+
}
|
|
235
|
+
} else {
|
|
236
|
+
if (!disabledTools.includes(toolName)) {
|
|
237
|
+
setDisabledTools([...disabledTools, toolName]);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
140
241
|
function setGithubTokens(tokens) {
|
|
141
242
|
const creds = getCredentials();
|
|
142
243
|
if (!creds) return;
|
|
@@ -145,6 +246,25 @@ function setGithubTokens(tokens) {
|
|
|
145
246
|
creds.githubExpiresAt = tokens.expiresAt;
|
|
146
247
|
setCredentials(creds);
|
|
147
248
|
}
|
|
249
|
+
function getGithubTokens() {
|
|
250
|
+
const creds = getCredentials();
|
|
251
|
+
if (!creds?.githubAccessToken || !creds.githubExpiresAt) return null;
|
|
252
|
+
return {
|
|
253
|
+
accessToken: creds.githubAccessToken,
|
|
254
|
+
refreshToken: creds.githubRefreshToken,
|
|
255
|
+
expiresAt: creds.githubExpiresAt
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
function getValidGithubToken() {
|
|
259
|
+
const tokens = getGithubTokens();
|
|
260
|
+
if (!tokens) return null;
|
|
261
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
262
|
+
if (tokens.expiresAt <= now + 60) return null;
|
|
263
|
+
return tokens.accessToken;
|
|
264
|
+
}
|
|
265
|
+
function hasGithubToken() {
|
|
266
|
+
return getValidGithubToken() !== null;
|
|
267
|
+
}
|
|
148
268
|
var config;
|
|
149
269
|
var init_config = __esm({
|
|
150
270
|
"src/lib/config.ts"() {
|
|
@@ -156,7 +276,8 @@ var init_config = __esm({
|
|
|
156
276
|
credentials: null,
|
|
157
277
|
activeWorkspaceId: null,
|
|
158
278
|
activeWorkspaceName: null,
|
|
159
|
-
serverUrl: "https://orkestrate.space"
|
|
279
|
+
serverUrl: "https://orkestrate.space",
|
|
280
|
+
userToolSettings: {}
|
|
160
281
|
}
|
|
161
282
|
});
|
|
162
283
|
}
|
|
@@ -399,7 +520,7 @@ async function performLogin() {
|
|
|
399
520
|
});
|
|
400
521
|
if (meRes.ok) {
|
|
401
522
|
const me = await meRes.json();
|
|
402
|
-
userId = me.id || "";
|
|
523
|
+
userId = me.user?.id || me.id || "";
|
|
403
524
|
}
|
|
404
525
|
} catch {
|
|
405
526
|
}
|
|
@@ -626,10 +747,16 @@ __export(detect_exports, {
|
|
|
626
747
|
detectTools: () => detectTools,
|
|
627
748
|
getToolNames: () => getToolNames
|
|
628
749
|
});
|
|
629
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
750
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
630
751
|
import { homedir } from "os";
|
|
631
752
|
import { join } from "path";
|
|
632
753
|
import { execSync } from "child_process";
|
|
754
|
+
function getZedConfigPath() {
|
|
755
|
+
if (process.platform === "win32") {
|
|
756
|
+
return join(homedir(), "AppData", "Roaming", "Zed", "settings.json");
|
|
757
|
+
}
|
|
758
|
+
return join(homedir(), ".config", "zed", "settings.json");
|
|
759
|
+
}
|
|
633
760
|
function detectTools(projectDir = process.cwd()) {
|
|
634
761
|
const tools = [];
|
|
635
762
|
tools.push({
|
|
@@ -641,111 +768,197 @@ function detectTools(projectDir = process.cwd()) {
|
|
|
641
768
|
tools.push({
|
|
642
769
|
name: "opencode",
|
|
643
770
|
displayName: "OpenCode",
|
|
644
|
-
detected:
|
|
771
|
+
detected: existsSync2(opencodeConfig) || isCommandAvailable("opencode"),
|
|
645
772
|
configPath: opencodeConfig
|
|
646
773
|
});
|
|
647
774
|
const cursorConfig = join(projectDir, ".cursor", "mcp.json");
|
|
648
775
|
tools.push({
|
|
649
776
|
name: "cursor",
|
|
650
777
|
displayName: "Cursor",
|
|
651
|
-
detected:
|
|
778
|
+
detected: existsSync2(join(projectDir, ".cursor")) || existsSync2(cursorConfig),
|
|
652
779
|
configPath: cursorConfig
|
|
653
780
|
});
|
|
654
781
|
const windsurfConfig = join(projectDir, ".windsurf", "mcp.json");
|
|
655
782
|
tools.push({
|
|
656
783
|
name: "windsurf",
|
|
657
784
|
displayName: "Windsurf",
|
|
658
|
-
detected:
|
|
785
|
+
detected: existsSync2(join(projectDir, ".windsurf")) || existsSync2(windsurfConfig),
|
|
659
786
|
configPath: windsurfConfig
|
|
660
787
|
});
|
|
661
788
|
const codexDir = join(homedir(), ".codex");
|
|
662
789
|
tools.push({
|
|
663
790
|
name: "codex",
|
|
664
791
|
displayName: "Codex CLI",
|
|
665
|
-
detected: isCommandAvailable("codex") ||
|
|
792
|
+
detected: isCommandAvailable("codex") || existsSync2(codexDir)
|
|
793
|
+
});
|
|
794
|
+
const zedConfig = getZedConfigPath();
|
|
795
|
+
tools.push({
|
|
796
|
+
name: "zed",
|
|
797
|
+
displayName: "Zed",
|
|
798
|
+
detected: existsSync2(zedConfig),
|
|
799
|
+
configPath: zedConfig
|
|
666
800
|
});
|
|
667
801
|
return tools;
|
|
668
802
|
}
|
|
669
803
|
async function configureTool(tool, projectDir = process.cwd()) {
|
|
670
|
-
const bridge = resolveMcpBridge();
|
|
671
|
-
const mcpUrl = `${getServerUrl()}/api/mcp`;
|
|
804
|
+
const bridge = resolveMcpBridge(tool);
|
|
672
805
|
switch (tool) {
|
|
673
806
|
case "claude":
|
|
674
807
|
return configureClaudeCode(bridge);
|
|
675
808
|
case "opencode":
|
|
676
|
-
return configureOpenCode(join(projectDir, "opencode.json"), bridge);
|
|
809
|
+
return configureOpenCode(join(projectDir, "opencode.json"), bridge, tool);
|
|
677
810
|
case "cursor":
|
|
678
|
-
return configureMcpServersJson(
|
|
811
|
+
return configureMcpServersJson(
|
|
812
|
+
"Cursor",
|
|
813
|
+
join(projectDir, ".cursor", "mcp.json"),
|
|
814
|
+
bridge,
|
|
815
|
+
tool
|
|
816
|
+
);
|
|
679
817
|
case "windsurf":
|
|
680
|
-
return configureMcpServersJson(
|
|
818
|
+
return configureMcpServersJson(
|
|
819
|
+
"Windsurf",
|
|
820
|
+
join(projectDir, ".windsurf", "mcp.json"),
|
|
821
|
+
bridge,
|
|
822
|
+
tool
|
|
823
|
+
);
|
|
681
824
|
case "codex":
|
|
682
|
-
return configureCodex(bridge);
|
|
825
|
+
return configureCodex(bridge, tool);
|
|
826
|
+
case "zed":
|
|
827
|
+
return configureZed(bridge, tool);
|
|
683
828
|
default:
|
|
684
829
|
return { success: false, message: `Unknown tool: ${tool}` };
|
|
685
830
|
}
|
|
686
831
|
}
|
|
687
|
-
function resolveMcpBridge() {
|
|
832
|
+
function resolveMcpBridge(tool) {
|
|
688
833
|
return {
|
|
689
834
|
command: "orkestrate",
|
|
690
|
-
args: ["mcp"]
|
|
835
|
+
args: ["mcp", "--parent-tool", tool]
|
|
691
836
|
};
|
|
692
837
|
}
|
|
693
838
|
function configureClaudeCode(bridge) {
|
|
694
|
-
if (!isCommandAvailable("claude"))
|
|
839
|
+
if (!isCommandAvailable("claude"))
|
|
840
|
+
return { success: false, message: "Claude Code CLI not found." };
|
|
695
841
|
try {
|
|
696
|
-
try {
|
|
697
|
-
execSync("claude mcp remove Orkestrate", { stdio: "pipe" });
|
|
698
|
-
} catch {
|
|
699
|
-
}
|
|
700
842
|
const commandToRun = bridge.command;
|
|
701
843
|
const argsToRun = bridge.args.join(" ");
|
|
844
|
+
const mcpJsonPath = join(process.cwd(), ".mcp.json");
|
|
845
|
+
if (existsSync2(mcpJsonPath)) {
|
|
846
|
+
try {
|
|
847
|
+
const mcpConfig = JSON.parse(readFileSync2(mcpJsonPath, "utf-8"));
|
|
848
|
+
if (mcpConfig.mcpServers?.Orkestrate) {
|
|
849
|
+
delete mcpConfig.mcpServers.Orkestrate;
|
|
850
|
+
writeFileSync2(
|
|
851
|
+
mcpJsonPath,
|
|
852
|
+
JSON.stringify(mcpConfig, null, 2) + "\n",
|
|
853
|
+
"utf-8"
|
|
854
|
+
);
|
|
855
|
+
}
|
|
856
|
+
} catch {
|
|
857
|
+
}
|
|
858
|
+
}
|
|
702
859
|
execSync(
|
|
703
|
-
`claude mcp add --transport stdio --scope project Orkestrate ${commandToRun} ${argsToRun}`,
|
|
860
|
+
`claude mcp add --transport stdio --scope project Orkestrate -- ${commandToRun} ${argsToRun}`,
|
|
704
861
|
{ stdio: "pipe", encoding: "utf-8" }
|
|
705
862
|
);
|
|
706
863
|
return { success: true, message: "MCP added to Claude Code." };
|
|
707
864
|
} catch (err) {
|
|
708
|
-
return {
|
|
865
|
+
return {
|
|
866
|
+
success: false,
|
|
867
|
+
message: `Claude config failed: ${err instanceof Error ? err.message : String(err)}`
|
|
868
|
+
};
|
|
709
869
|
}
|
|
710
870
|
}
|
|
711
|
-
function configureOpenCode(configPath, bridge) {
|
|
871
|
+
function configureOpenCode(configPath, bridge, tool) {
|
|
712
872
|
try {
|
|
713
|
-
|
|
873
|
+
const config2 = existsSync2(configPath) ? JSON.parse(readFileSync2(configPath, "utf-8")) : {};
|
|
714
874
|
if (!config2.mcp || typeof config2.mcp !== "object") config2.mcp = {};
|
|
715
875
|
config2.mcp["Orkestrate"] = {
|
|
716
876
|
type: "local",
|
|
717
877
|
command: [bridge.command, ...bridge.args],
|
|
718
878
|
enabled: true
|
|
719
879
|
};
|
|
720
|
-
|
|
880
|
+
writeFileSync2(configPath, JSON.stringify(config2, null, 2) + "\n", "utf-8");
|
|
721
881
|
return { success: true, message: `Configured OpenCode at ${configPath}` };
|
|
722
882
|
} catch (err) {
|
|
723
|
-
return {
|
|
883
|
+
return {
|
|
884
|
+
success: false,
|
|
885
|
+
message: `OpenCode config failed: ${err instanceof Error ? err.message : String(err)}`
|
|
886
|
+
};
|
|
724
887
|
}
|
|
725
888
|
}
|
|
726
|
-
function configureMcpServersJson(displayName, configPath, bridge) {
|
|
889
|
+
function configureMcpServersJson(displayName, configPath, bridge, tool) {
|
|
727
890
|
try {
|
|
728
891
|
const dir = join(configPath, "..");
|
|
729
|
-
if (!
|
|
730
|
-
|
|
731
|
-
if (!config2.mcpServers || typeof config2.mcpServers !== "object")
|
|
892
|
+
if (!existsSync2(dir)) mkdirSync2(dir, { recursive: true });
|
|
893
|
+
const config2 = existsSync2(configPath) ? JSON.parse(readFileSync2(configPath, "utf-8")) : {};
|
|
894
|
+
if (!config2.mcpServers || typeof config2.mcpServers !== "object")
|
|
895
|
+
config2.mcpServers = {};
|
|
732
896
|
config2.mcpServers["Orkestrate"] = {
|
|
733
897
|
command: bridge.command,
|
|
734
898
|
args: bridge.args
|
|
735
899
|
};
|
|
736
|
-
|
|
737
|
-
return {
|
|
900
|
+
writeFileSync2(configPath, JSON.stringify(config2, null, 2) + "\n", "utf-8");
|
|
901
|
+
return {
|
|
902
|
+
success: true,
|
|
903
|
+
message: `Configured ${displayName} at ${configPath}`
|
|
904
|
+
};
|
|
905
|
+
} catch (err) {
|
|
906
|
+
return {
|
|
907
|
+
success: false,
|
|
908
|
+
message: `${displayName} config failed: ${err instanceof Error ? err.message : String(err)}`
|
|
909
|
+
};
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
function configureZed(bridge, tool) {
|
|
913
|
+
const configPath = getZedConfigPath();
|
|
914
|
+
try {
|
|
915
|
+
const dir = join(configPath, "..");
|
|
916
|
+
if (!existsSync2(dir)) mkdirSync2(dir, { recursive: true });
|
|
917
|
+
const serverEntry = {
|
|
918
|
+
enabled: true,
|
|
919
|
+
remote: false,
|
|
920
|
+
command: bridge.command,
|
|
921
|
+
args: bridge.args
|
|
922
|
+
};
|
|
923
|
+
let config2 = {};
|
|
924
|
+
if (existsSync2(configPath)) {
|
|
925
|
+
const content = readFileSync2(configPath, "utf-8").trim();
|
|
926
|
+
const jsonStart = content.indexOf("{");
|
|
927
|
+
const trimmedContent = jsonStart >= 0 ? content.slice(jsonStart) : "";
|
|
928
|
+
if (trimmedContent) {
|
|
929
|
+
try {
|
|
930
|
+
config2 = new Function("return " + trimmedContent)();
|
|
931
|
+
} catch {
|
|
932
|
+
return {
|
|
933
|
+
success: false,
|
|
934
|
+
message: "Zed config is not valid JSON - manual configuration required"
|
|
935
|
+
};
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
if (!config2.context_servers || typeof config2.context_servers !== "object") {
|
|
940
|
+
config2.context_servers = {};
|
|
941
|
+
}
|
|
942
|
+
config2.context_servers["mcp-server-orkestrate"] = serverEntry;
|
|
943
|
+
writeFileSync2(configPath, JSON.stringify(config2, null, 2), "utf-8");
|
|
944
|
+
return {
|
|
945
|
+
success: true,
|
|
946
|
+
message: `Configured Zed at ${configPath}`
|
|
947
|
+
};
|
|
738
948
|
} catch (err) {
|
|
739
|
-
return {
|
|
949
|
+
return {
|
|
950
|
+
success: false,
|
|
951
|
+
message: `Zed config failed: ${err instanceof Error ? err.message : String(err)}`
|
|
952
|
+
};
|
|
740
953
|
}
|
|
741
954
|
}
|
|
742
|
-
function configureCodex(bridge) {
|
|
955
|
+
function configureCodex(bridge, tool) {
|
|
743
956
|
const home = homedir();
|
|
744
957
|
const codexDir = join(home, ".codex");
|
|
745
958
|
const configPath = join(codexDir, "config.toml");
|
|
746
959
|
try {
|
|
747
|
-
if (!
|
|
748
|
-
let content =
|
|
960
|
+
if (!existsSync2(codexDir)) mkdirSync2(codexDir, { recursive: true });
|
|
961
|
+
let content = existsSync2(configPath) ? readFileSync2(configPath, "utf-8") : "[mcp_servers]\n";
|
|
749
962
|
const proxySection = `[mcp_servers.Orkestrate]
|
|
750
963
|
command = "${bridge.command}"
|
|
751
964
|
args = [${bridge.args.map((a) => `"${a}"`).join(", ")}]
|
|
@@ -763,10 +976,13 @@ args = [${bridge.args.map((a) => `"${a}"`).join(", ")}]
|
|
|
763
976
|
content = content.trimEnd() + "\n\n[mcp_servers]\n\n" + proxySection;
|
|
764
977
|
}
|
|
765
978
|
}
|
|
766
|
-
|
|
979
|
+
writeFileSync2(configPath, content, "utf-8");
|
|
767
980
|
return { success: true, message: `Configured Codex.` };
|
|
768
981
|
} catch (err) {
|
|
769
|
-
return {
|
|
982
|
+
return {
|
|
983
|
+
success: false,
|
|
984
|
+
message: `Codex config failed: ${err instanceof Error ? err.message : String(err)}`
|
|
985
|
+
};
|
|
770
986
|
}
|
|
771
987
|
}
|
|
772
988
|
function isCommandAvailable(command) {
|
|
@@ -780,12 +996,11 @@ function isCommandAvailable(command) {
|
|
|
780
996
|
}
|
|
781
997
|
}
|
|
782
998
|
function getToolNames() {
|
|
783
|
-
return ["claude", "opencode", "cursor", "windsurf", "codex"];
|
|
999
|
+
return ["claude", "opencode", "cursor", "windsurf", "codex", "zed"];
|
|
784
1000
|
}
|
|
785
1001
|
var init_detect = __esm({
|
|
786
1002
|
"src/lib/detect.ts"() {
|
|
787
1003
|
"use strict";
|
|
788
|
-
init_config();
|
|
789
1004
|
}
|
|
790
1005
|
});
|
|
791
1006
|
|
|
@@ -845,7 +1060,6 @@ async function connectCommand(toolName) {
|
|
|
845
1060
|
}
|
|
846
1061
|
}
|
|
847
1062
|
function displayGenericInstructions() {
|
|
848
|
-
const mcpUrl = `${getServerUrl()}/api/mcp`;
|
|
849
1063
|
const bridgeCommand = "orkestrate";
|
|
850
1064
|
const bridgeArgs = "mcp";
|
|
851
1065
|
ui.info("Generic MCP Setup (for any tool that supports stdio MCP):");
|
|
@@ -882,7 +1096,12 @@ function displayGenericInstructions() {
|
|
|
882
1096
|
ui.line(` command = "${bridgeCommand}"`);
|
|
883
1097
|
ui.line(` args = ["${bridgeArgs}"]`);
|
|
884
1098
|
ui.blank();
|
|
885
|
-
ui.
|
|
1099
|
+
ui.line(" Zed:");
|
|
1100
|
+
ui.line(" Add to settings.json under context_servers:");
|
|
1101
|
+
ui.line(" ~/.config/zed/settings.json (Linux/macOS)");
|
|
1102
|
+
ui.line(" ~/AppData/Roaming/Zed/settings.json (Windows)");
|
|
1103
|
+
ui.blank();
|
|
1104
|
+
ui.line(
|
|
886
1105
|
" Not sure if your tool supports MCP? Check its docs for 'MCP server'."
|
|
887
1106
|
);
|
|
888
1107
|
}
|
|
@@ -898,7 +1117,8 @@ var init_connect = __esm({
|
|
|
898
1117
|
"opencode",
|
|
899
1118
|
"cursor",
|
|
900
1119
|
"windsurf",
|
|
901
|
-
"codex"
|
|
1120
|
+
"codex",
|
|
1121
|
+
"zed"
|
|
902
1122
|
];
|
|
903
1123
|
}
|
|
904
1124
|
});
|
|
@@ -909,6 +1129,7 @@ __export(api_exports, {
|
|
|
909
1129
|
ApiError: () => ApiError,
|
|
910
1130
|
checkHealth: () => checkHealth,
|
|
911
1131
|
createWorkspace: () => createWorkspace,
|
|
1132
|
+
getGithubStatus: () => getGithubStatus,
|
|
912
1133
|
getMe: () => getMe,
|
|
913
1134
|
getTeamStatus: () => getTeamStatus,
|
|
914
1135
|
listWorkspaces: () => listWorkspaces,
|
|
@@ -937,7 +1158,7 @@ async function request(method, path, body) {
|
|
|
937
1158
|
method,
|
|
938
1159
|
headers: {
|
|
939
1160
|
...headers,
|
|
940
|
-
|
|
1161
|
+
Accept: "application/json",
|
|
941
1162
|
"User-Agent": "Orkestrate-CLI-v1"
|
|
942
1163
|
},
|
|
943
1164
|
body: body ? JSON.stringify(body) : void 0
|
|
@@ -952,8 +1173,18 @@ async function getMe() {
|
|
|
952
1173
|
const data = await request("GET", "/api/auth/me");
|
|
953
1174
|
return data.user;
|
|
954
1175
|
}
|
|
1176
|
+
async function getGithubStatus() {
|
|
1177
|
+
const data = await request(
|
|
1178
|
+
"GET",
|
|
1179
|
+
"/api/github/status"
|
|
1180
|
+
);
|
|
1181
|
+
return { connected: Boolean(data.connected) };
|
|
1182
|
+
}
|
|
955
1183
|
async function listWorkspaces() {
|
|
956
|
-
const data = await request(
|
|
1184
|
+
const data = await request(
|
|
1185
|
+
"GET",
|
|
1186
|
+
"/api/workspaces"
|
|
1187
|
+
);
|
|
957
1188
|
return data.workspaces || [];
|
|
958
1189
|
}
|
|
959
1190
|
async function switchWorkspace(workspaceId) {
|
|
@@ -963,12 +1194,16 @@ async function switchWorkspace(workspaceId) {
|
|
|
963
1194
|
});
|
|
964
1195
|
}
|
|
965
1196
|
async function createWorkspace(name, repoUrl, defaultBranch) {
|
|
966
|
-
const data = await request(
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
1197
|
+
const data = await request(
|
|
1198
|
+
"POST",
|
|
1199
|
+
"/api/workspaces",
|
|
1200
|
+
{
|
|
1201
|
+
action: "create",
|
|
1202
|
+
name,
|
|
1203
|
+
repoUrl,
|
|
1204
|
+
defaultBranch
|
|
1205
|
+
}
|
|
1206
|
+
);
|
|
972
1207
|
return data.workspace;
|
|
973
1208
|
}
|
|
974
1209
|
async function getTeamStatus() {
|
|
@@ -1143,7 +1378,9 @@ async function workspaceCommand(action, nameOrId, extra) {
|
|
|
1143
1378
|
case "create":
|
|
1144
1379
|
case "new":
|
|
1145
1380
|
if (!nameOrId) {
|
|
1146
|
-
ui.error(
|
|
1381
|
+
ui.error(
|
|
1382
|
+
"Usage: orkestrate workspace create <name> <repo-url> [branch]"
|
|
1383
|
+
);
|
|
1147
1384
|
process.exit(1);
|
|
1148
1385
|
}
|
|
1149
1386
|
return workspaceCreate(nameOrId, extra);
|
|
@@ -1164,7 +1401,9 @@ async function workspaceList() {
|
|
|
1164
1401
|
const active = getActiveWorkspace();
|
|
1165
1402
|
if (workspaces.length === 0) {
|
|
1166
1403
|
ui.dim("No workspaces found.");
|
|
1167
|
-
ui.info(
|
|
1404
|
+
ui.info(
|
|
1405
|
+
"Create one at orkestrate.space or run `orkestrate workspace create`."
|
|
1406
|
+
);
|
|
1168
1407
|
return;
|
|
1169
1408
|
}
|
|
1170
1409
|
for (const ws of workspaces) {
|
|
@@ -1183,7 +1422,9 @@ async function workspaceList() {
|
|
|
1183
1422
|
ui.blank();
|
|
1184
1423
|
ui.dim(`${workspaces.length} workspace(s)`);
|
|
1185
1424
|
} catch (err) {
|
|
1186
|
-
ui.error(
|
|
1425
|
+
ui.error(
|
|
1426
|
+
`Failed to list workspaces: ${err instanceof Error ? err.message : String(err)}`
|
|
1427
|
+
);
|
|
1187
1428
|
process.exit(1);
|
|
1188
1429
|
}
|
|
1189
1430
|
}
|
|
@@ -1206,11 +1447,32 @@ async function workspaceSwitch(nameOrId) {
|
|
|
1206
1447
|
setActiveWorkspace(target.id, target.name);
|
|
1207
1448
|
ui.success(`Switched to workspace: ${target.name}`);
|
|
1208
1449
|
} catch (err) {
|
|
1209
|
-
ui.error(
|
|
1450
|
+
ui.error(
|
|
1451
|
+
`Failed to switch workspace: ${err instanceof Error ? err.message : String(err)}`
|
|
1452
|
+
);
|
|
1210
1453
|
process.exit(1);
|
|
1211
1454
|
}
|
|
1212
1455
|
}
|
|
1213
1456
|
async function workspaceCreate(name, repoUrl) {
|
|
1457
|
+
const localGithubTokenAvailable = hasGithubToken();
|
|
1458
|
+
let serverGithubConnected = false;
|
|
1459
|
+
try {
|
|
1460
|
+
const status = await getGithubStatus();
|
|
1461
|
+
serverGithubConnected = status.connected;
|
|
1462
|
+
} catch (err) {
|
|
1463
|
+
ui.error(
|
|
1464
|
+
`Failed to verify GitHub connection with server: ${err instanceof Error ? err.message : String(err)}`
|
|
1465
|
+
);
|
|
1466
|
+
ui.info("Please re-run `orkestrate login` and ensure GitHub is connected.");
|
|
1467
|
+
process.exit(1);
|
|
1468
|
+
}
|
|
1469
|
+
if (!localGithubTokenAvailable || !serverGithubConnected) {
|
|
1470
|
+
ui.error("GitHub is not connected. Workspace creation is blocked.");
|
|
1471
|
+
ui.info(
|
|
1472
|
+
"Run `orkestrate login` and complete GitHub connection, then try again."
|
|
1473
|
+
);
|
|
1474
|
+
process.exit(1);
|
|
1475
|
+
}
|
|
1214
1476
|
if (!repoUrl) {
|
|
1215
1477
|
ui.error("Repository URL is required.");
|
|
1216
1478
|
ui.info("Usage: orkestrate workspace create <name> <repo-url>");
|
|
@@ -1223,7 +1485,9 @@ async function workspaceCreate(name, repoUrl) {
|
|
|
1223
1485
|
ui.kv("ID", workspace.id);
|
|
1224
1486
|
ui.kv("Repo", repoUrl);
|
|
1225
1487
|
} catch (err) {
|
|
1226
|
-
ui.error(
|
|
1488
|
+
ui.error(
|
|
1489
|
+
`Failed to create workspace: ${err instanceof Error ? err.message : String(err)}`
|
|
1490
|
+
);
|
|
1227
1491
|
process.exit(1);
|
|
1228
1492
|
}
|
|
1229
1493
|
}
|
|
@@ -1252,7 +1516,15 @@ function git(cmd, cwd) {
|
|
|
1252
1516
|
function detectGitContext(cwd = process.cwd()) {
|
|
1253
1517
|
const repoRoot = git("rev-parse --show-toplevel", cwd);
|
|
1254
1518
|
if (!repoRoot) return null;
|
|
1255
|
-
const
|
|
1519
|
+
const remotes = git("remote", cwd).split("\n").filter(Boolean);
|
|
1520
|
+
let remote = "";
|
|
1521
|
+
for (const r of remotes) {
|
|
1522
|
+
const url = git(`remote get-url ${r}`, cwd);
|
|
1523
|
+
if (url) {
|
|
1524
|
+
remote = url;
|
|
1525
|
+
break;
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1256
1528
|
const branch = git("rev-parse --abbrev-ref HEAD", cwd);
|
|
1257
1529
|
const headSha = git("rev-parse HEAD", cwd);
|
|
1258
1530
|
const status = git("status --porcelain", cwd);
|
|
@@ -1276,7 +1548,7 @@ var init_exports = {};
|
|
|
1276
1548
|
__export(init_exports, {
|
|
1277
1549
|
initCommand: () => initCommand
|
|
1278
1550
|
});
|
|
1279
|
-
import { existsSync as
|
|
1551
|
+
import { existsSync as existsSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
1280
1552
|
import { join as join2 } from "path";
|
|
1281
1553
|
async function initCommand() {
|
|
1282
1554
|
const creds = getCredentials();
|
|
@@ -1386,7 +1658,7 @@ async function initCommand() {
|
|
|
1386
1658
|
}
|
|
1387
1659
|
const configFile = join2(cwd, ".orkestrate.json");
|
|
1388
1660
|
const activeWs = getActiveWorkspace();
|
|
1389
|
-
if (!
|
|
1661
|
+
if (!existsSync3(configFile)) {
|
|
1390
1662
|
if (activeWs.id) {
|
|
1391
1663
|
const projectConfig = {
|
|
1392
1664
|
$schema: "https://orkestrate.space/schema/project.json",
|
|
@@ -1394,18 +1666,18 @@ async function initCommand() {
|
|
|
1394
1666
|
server: "https://orkestrate.space",
|
|
1395
1667
|
initialized: (/* @__PURE__ */ new Date()).toISOString()
|
|
1396
1668
|
};
|
|
1397
|
-
|
|
1669
|
+
writeFileSync3(configFile, JSON.stringify(projectConfig, null, 2) + "\n", "utf-8");
|
|
1398
1670
|
ui.blank();
|
|
1399
1671
|
ui.success(`Created .orkestrate.json`);
|
|
1400
1672
|
ui.dim("This file identifies your project workspace. It is gitignored by default.");
|
|
1401
1673
|
}
|
|
1402
1674
|
} else {
|
|
1403
1675
|
try {
|
|
1404
|
-
const { readFileSync:
|
|
1405
|
-
const existing = JSON.parse(
|
|
1676
|
+
const { readFileSync: readFileSync3 } = await import("fs");
|
|
1677
|
+
const existing = JSON.parse(readFileSync3(configFile, "utf-8"));
|
|
1406
1678
|
if (activeWs.id && existing.workspaceId !== activeWs.id) {
|
|
1407
1679
|
existing.workspaceId = activeWs.id;
|
|
1408
|
-
|
|
1680
|
+
writeFileSync3(configFile, JSON.stringify(existing, null, 2) + "\n", "utf-8");
|
|
1409
1681
|
ui.success(`Updated .orkestrate.json with workspace ID ${activeWs.id}`);
|
|
1410
1682
|
}
|
|
1411
1683
|
} catch {
|
|
@@ -1441,33 +1713,36 @@ var mcp_exports = {};
|
|
|
1441
1713
|
__export(mcp_exports, {
|
|
1442
1714
|
mcpCommand: () => mcpCommand
|
|
1443
1715
|
});
|
|
1444
|
-
async function mcpCommand() {
|
|
1716
|
+
async function mcpCommand(opts) {
|
|
1717
|
+
const PARENT_TOOL = opts.parentTool ?? null;
|
|
1445
1718
|
try {
|
|
1446
1719
|
const serverUrl = getServerUrl();
|
|
1447
1720
|
const mcpUrl = `${serverUrl}/api/mcp`;
|
|
1448
1721
|
process.stdin.setEncoding("utf-8");
|
|
1449
1722
|
let buffer = "";
|
|
1450
|
-
|
|
1451
|
-
|
|
1723
|
+
const startupMsg = `[Orkestrate-MCP] Starting bridge to ${mcpUrl}${PARENT_TOOL ? ` (parent: ${PARENT_TOOL})` : ""}
|
|
1724
|
+
`;
|
|
1725
|
+
process.stderr.write(startupMsg);
|
|
1452
1726
|
process.stdin.on("data", async (chunk) => {
|
|
1453
1727
|
const rawChunk = String(chunk);
|
|
1454
|
-
if (process.env.DEBUG)
|
|
1728
|
+
if (process.env.DEBUG)
|
|
1729
|
+
process.stderr.write(`[Orkestrate-MCP] Received chunk: ${rawChunk}
|
|
1455
1730
|
`);
|
|
1456
1731
|
buffer += rawChunk;
|
|
1457
1732
|
let lineEndIndex;
|
|
1458
1733
|
while ((lineEndIndex = buffer.indexOf("\n")) >= 0) {
|
|
1459
|
-
|
|
1734
|
+
const line = buffer.slice(0, lineEndIndex).trim();
|
|
1460
1735
|
buffer = buffer.slice(lineEndIndex + 1);
|
|
1461
1736
|
if (!line) continue;
|
|
1462
1737
|
if (line.includes("}{")) {
|
|
1463
1738
|
const parts = line.split("}{");
|
|
1464
|
-
await processLine(parts[0] + "}", mcpUrl);
|
|
1739
|
+
await processLine(parts[0] + "}", mcpUrl, PARENT_TOOL);
|
|
1465
1740
|
for (let i = 1; i < parts.length - 1; i++) {
|
|
1466
|
-
await processLine("{" + parts[i] + "}", mcpUrl);
|
|
1741
|
+
await processLine("{" + parts[i] + "}", mcpUrl, PARENT_TOOL);
|
|
1467
1742
|
}
|
|
1468
|
-
await processLine("{" + parts[parts.length - 1], mcpUrl);
|
|
1743
|
+
await processLine("{" + parts[parts.length - 1], mcpUrl, PARENT_TOOL);
|
|
1469
1744
|
} else {
|
|
1470
|
-
await processLine(line, mcpUrl);
|
|
1745
|
+
await processLine(line, mcpUrl, PARENT_TOOL);
|
|
1471
1746
|
}
|
|
1472
1747
|
}
|
|
1473
1748
|
});
|
|
@@ -1483,14 +1758,16 @@ async function mcpCommand() {
|
|
|
1483
1758
|
process.exit(1);
|
|
1484
1759
|
}
|
|
1485
1760
|
}
|
|
1486
|
-
async function processLine(line, mcpUrl) {
|
|
1487
|
-
if (process.env.DEBUG)
|
|
1761
|
+
async function processLine(line, mcpUrl, parentTool) {
|
|
1762
|
+
if (process.env.DEBUG)
|
|
1763
|
+
process.stderr.write(`[Orkestrate-MCP] Processing line: ${line}
|
|
1488
1764
|
`);
|
|
1489
1765
|
let payload;
|
|
1490
1766
|
try {
|
|
1491
1767
|
payload = JSON.parse(line);
|
|
1492
1768
|
} catch {
|
|
1493
|
-
if (process.env.DEBUG)
|
|
1769
|
+
if (process.env.DEBUG)
|
|
1770
|
+
process.stderr.write(`[Orkestrate-MCP] JSON Parse failed for: ${line}
|
|
1494
1771
|
`);
|
|
1495
1772
|
return;
|
|
1496
1773
|
}
|
|
@@ -1499,47 +1776,100 @@ async function processLine(line, mcpUrl) {
|
|
|
1499
1776
|
try {
|
|
1500
1777
|
const token = await getValidToken();
|
|
1501
1778
|
if (!token) {
|
|
1502
|
-
throw new Error(
|
|
1779
|
+
throw new Error(
|
|
1780
|
+
"NOT_LOGGED_IN: Please run 'orkestrate login' to authenticate."
|
|
1781
|
+
);
|
|
1503
1782
|
}
|
|
1783
|
+
const headers = {
|
|
1784
|
+
"Content-Type": "application/json",
|
|
1785
|
+
Authorization: `Bearer ${token}`,
|
|
1786
|
+
"User-Agent": "Orkestrate-CLI-Proxy"
|
|
1787
|
+
};
|
|
1788
|
+
const enrichedPayload = parentTool ? { ...payload, parentTool } : payload;
|
|
1504
1789
|
const res = await fetch(mcpUrl, {
|
|
1505
1790
|
method: "POST",
|
|
1506
|
-
headers
|
|
1507
|
-
|
|
1508
|
-
"Authorization": `Bearer ${token}`,
|
|
1509
|
-
"User-Agent": "Orkestrate-CLI-Proxy"
|
|
1510
|
-
},
|
|
1511
|
-
body: line
|
|
1791
|
+
headers,
|
|
1792
|
+
body: JSON.stringify(enrichedPayload)
|
|
1512
1793
|
});
|
|
1513
1794
|
if (isNotification) return;
|
|
1514
1795
|
const responseBody = await res.text();
|
|
1515
1796
|
if (!res.ok) {
|
|
1516
|
-
process.stderr.write(
|
|
1517
|
-
`)
|
|
1797
|
+
process.stderr.write(
|
|
1798
|
+
`[Orkestrate-MCP] Backend error (${res.status}): ${responseBody}
|
|
1799
|
+
`
|
|
1800
|
+
);
|
|
1518
1801
|
if (!isNotification) {
|
|
1519
|
-
process.stdout.write(
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1802
|
+
process.stdout.write(
|
|
1803
|
+
JSON.stringify({
|
|
1804
|
+
jsonrpc: "2.0",
|
|
1805
|
+
id: requestId,
|
|
1806
|
+
error: {
|
|
1807
|
+
code: -32603,
|
|
1808
|
+
message: `Orkestrate Cloud Error (${res.status}): ${responseBody || "Unauthorized"}. Please try 'orkestrate login'.`
|
|
1809
|
+
}
|
|
1810
|
+
}) + "\n"
|
|
1811
|
+
);
|
|
1527
1812
|
}
|
|
1528
1813
|
return;
|
|
1529
1814
|
}
|
|
1530
1815
|
if (responseBody) {
|
|
1531
|
-
|
|
1816
|
+
if (payload.method === "tools/list") {
|
|
1817
|
+
const filtered = filterToolsList(responseBody);
|
|
1818
|
+
process.stdout.write(filtered + "\n");
|
|
1819
|
+
} else {
|
|
1820
|
+
if (payload.method === "tools/call") {
|
|
1821
|
+
const toolName = payload.params?.name;
|
|
1822
|
+
if (toolName && !isToolAllowed(toolName)) {
|
|
1823
|
+
process.stdout.write(
|
|
1824
|
+
JSON.stringify({
|
|
1825
|
+
jsonrpc: "2.0",
|
|
1826
|
+
id: requestId,
|
|
1827
|
+
error: {
|
|
1828
|
+
code: -32600,
|
|
1829
|
+
message: `Tool '${toolName}' is disabled. Use 'orkestrate tools --list' to see available tools and 'orkestrate tools --enable ${toolName}' to enable it.`
|
|
1830
|
+
}
|
|
1831
|
+
}) + "\n"
|
|
1832
|
+
);
|
|
1833
|
+
return;
|
|
1834
|
+
}
|
|
1835
|
+
}
|
|
1836
|
+
process.stdout.write(responseBody + "\n");
|
|
1837
|
+
}
|
|
1532
1838
|
}
|
|
1533
1839
|
} catch (err) {
|
|
1534
1840
|
if (isNotification) return;
|
|
1535
|
-
process.stdout.write(
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1841
|
+
process.stdout.write(
|
|
1842
|
+
JSON.stringify({
|
|
1843
|
+
jsonrpc: "2.0",
|
|
1844
|
+
id: requestId,
|
|
1845
|
+
error: {
|
|
1846
|
+
code: -32603,
|
|
1847
|
+
message: err instanceof Error ? err.message : String(err)
|
|
1848
|
+
}
|
|
1849
|
+
}) + "\n"
|
|
1850
|
+
);
|
|
1851
|
+
}
|
|
1852
|
+
}
|
|
1853
|
+
function filterToolsList(responseBody) {
|
|
1854
|
+
try {
|
|
1855
|
+
const parsed = JSON.parse(responseBody);
|
|
1856
|
+
if (!parsed.result?.tools) return responseBody;
|
|
1857
|
+
const enabledTools = getEnabledTools();
|
|
1858
|
+
const disabledTools = getDisabledTools();
|
|
1859
|
+
let filteredTools = parsed.result.tools;
|
|
1860
|
+
if (enabledTools !== null) {
|
|
1861
|
+
filteredTools = filteredTools.filter(
|
|
1862
|
+
(tool) => enabledTools.includes(tool.name)
|
|
1863
|
+
);
|
|
1864
|
+
} else {
|
|
1865
|
+
filteredTools = filteredTools.filter(
|
|
1866
|
+
(tool) => !disabledTools.includes(tool.name)
|
|
1867
|
+
);
|
|
1868
|
+
}
|
|
1869
|
+
parsed.result.tools = filteredTools;
|
|
1870
|
+
return JSON.stringify(parsed);
|
|
1871
|
+
} catch {
|
|
1872
|
+
return responseBody;
|
|
1543
1873
|
}
|
|
1544
1874
|
}
|
|
1545
1875
|
var init_mcp = __esm({
|
|
@@ -1609,11 +1939,82 @@ var init_whoami = __esm({
|
|
|
1609
1939
|
}
|
|
1610
1940
|
});
|
|
1611
1941
|
|
|
1942
|
+
// src/commands/tools.ts
|
|
1943
|
+
var tools_exports = {};
|
|
1944
|
+
__export(tools_exports, {
|
|
1945
|
+
toolsCommand: () => toolsCommand
|
|
1946
|
+
});
|
|
1947
|
+
async function toolsCommand(opts) {
|
|
1948
|
+
const { list, enable, disable } = opts;
|
|
1949
|
+
if (list) {
|
|
1950
|
+
const enabledTools = getEnabledTools();
|
|
1951
|
+
const disabledTools = getDisabledTools();
|
|
1952
|
+
ui.header("Tool Filter Settings");
|
|
1953
|
+
if (enabledTools !== null) {
|
|
1954
|
+
ui.info(`Mode: Additive (only listed tools are enabled)`);
|
|
1955
|
+
if (enabledTools.length === 0) {
|
|
1956
|
+
ui.dim(" No tools enabled");
|
|
1957
|
+
} else {
|
|
1958
|
+
enabledTools.forEach((tool) => {
|
|
1959
|
+
ui.success(tool);
|
|
1960
|
+
});
|
|
1961
|
+
}
|
|
1962
|
+
} else {
|
|
1963
|
+
ui.info(`Mode: Subtractive (all tools except disabled)`);
|
|
1964
|
+
if (disabledTools.length === 0) {
|
|
1965
|
+
ui.dim(" No tools disabled");
|
|
1966
|
+
} else {
|
|
1967
|
+
disabledTools.forEach((tool) => {
|
|
1968
|
+
ui.error(tool);
|
|
1969
|
+
});
|
|
1970
|
+
}
|
|
1971
|
+
}
|
|
1972
|
+
console.log();
|
|
1973
|
+
ui.dim(` Use 'orkestrate tools --enable <tool>' to enable a tool`);
|
|
1974
|
+
ui.dim(` Use 'orkestrate tools --disable <tool>' to disable a tool`);
|
|
1975
|
+
return;
|
|
1976
|
+
}
|
|
1977
|
+
if (enable) {
|
|
1978
|
+
const toolName = enable;
|
|
1979
|
+
if (isToolAllowed(toolName)) {
|
|
1980
|
+
ui.warn(`Tool '${toolName}' is already enabled`);
|
|
1981
|
+
} else {
|
|
1982
|
+
enableTool(toolName);
|
|
1983
|
+
ui.success(`Enabled tool: ${toolName}`);
|
|
1984
|
+
}
|
|
1985
|
+
return;
|
|
1986
|
+
}
|
|
1987
|
+
if (disable) {
|
|
1988
|
+
const toolName = disable;
|
|
1989
|
+
if (!isToolAllowed(toolName)) {
|
|
1990
|
+
ui.warn(`Tool '${toolName}' is already disabled`);
|
|
1991
|
+
} else {
|
|
1992
|
+
disableTool(toolName);
|
|
1993
|
+
ui.success(`Disabled tool: ${toolName}`);
|
|
1994
|
+
}
|
|
1995
|
+
return;
|
|
1996
|
+
}
|
|
1997
|
+
ui.header("Orkestrate Tools Management");
|
|
1998
|
+
ui.info("Manage which tools are available through the local MCP proxy");
|
|
1999
|
+
console.log();
|
|
2000
|
+
ui.dim("Usage:");
|
|
2001
|
+
ui.dim(" orkestrate tools --list Show current settings");
|
|
2002
|
+
ui.dim(" orkestrate tools --enable <tool> Enable a specific tool");
|
|
2003
|
+
ui.dim(" orkestrate tools --disable <tool> Disable a specific tool");
|
|
2004
|
+
}
|
|
2005
|
+
var init_tools = __esm({
|
|
2006
|
+
"src/commands/tools.ts"() {
|
|
2007
|
+
"use strict";
|
|
2008
|
+
init_config();
|
|
2009
|
+
init_ui();
|
|
2010
|
+
}
|
|
2011
|
+
});
|
|
2012
|
+
|
|
1612
2013
|
// src/cli.ts
|
|
1613
2014
|
init_ui();
|
|
1614
2015
|
import { Command } from "commander";
|
|
1615
2016
|
var program = new Command();
|
|
1616
|
-
program.name("orkestrate").description("The coordination layer for autonomous AI coding agents").version("0.1.
|
|
2017
|
+
program.name("orkestrate").description("The coordination layer for autonomous AI coding agents").version("0.1.15").hook("preAction", () => {
|
|
1617
2018
|
});
|
|
1618
2019
|
program.command("login").description("Authenticate with Orkestrate via browser OAuth").action(async () => {
|
|
1619
2020
|
const { loginCommand: loginCommand2 } = await Promise.resolve().then(() => (init_login(), login_exports));
|
|
@@ -1623,7 +2024,9 @@ program.command("logout").description("Clear stored credentials").action(async (
|
|
|
1623
2024
|
const { logoutCommand: logoutCommand2 } = await Promise.resolve().then(() => (init_logout(), logout_exports));
|
|
1624
2025
|
logoutCommand2();
|
|
1625
2026
|
});
|
|
1626
|
-
program.command("connect [tool]").description(
|
|
2027
|
+
program.command("connect [tool]").description(
|
|
2028
|
+
"Configure MCP endpoint for an AI coding tool (claude, opencode, cursor, windsurf, codex)"
|
|
2029
|
+
).action(async (tool) => {
|
|
1627
2030
|
const { connectCommand: connectCommand2 } = await Promise.resolve().then(() => (init_connect(), connect_exports));
|
|
1628
2031
|
await connectCommand2(tool);
|
|
1629
2032
|
});
|
|
@@ -1639,13 +2042,18 @@ program.command("init").description("Initialize Orkestrate in the current projec
|
|
|
1639
2042
|
const { initCommand: initCommand2 } = await Promise.resolve().then(() => (init_init(), init_exports));
|
|
1640
2043
|
await initCommand2();
|
|
1641
2044
|
});
|
|
1642
|
-
program.command("mcp").description("Run as a local MCP server (stdio bridge to Orkestrate Cloud)").
|
|
2045
|
+
program.command("mcp").description("Run as a local MCP server (stdio bridge to Orkestrate Cloud)").option(
|
|
2046
|
+
"--parent-tool <tool>",
|
|
2047
|
+
"The AI coding tool invoking this bridge (claude, zed, cursor, etc.)"
|
|
2048
|
+
).action(async (opts) => {
|
|
1643
2049
|
try {
|
|
1644
2050
|
const { mcpCommand: mcpCommand2 } = await Promise.resolve().then(() => (init_mcp(), mcp_exports));
|
|
1645
|
-
await mcpCommand2();
|
|
2051
|
+
await mcpCommand2(opts);
|
|
1646
2052
|
} catch (err) {
|
|
1647
|
-
process.stderr.write(
|
|
1648
|
-
`)
|
|
2053
|
+
process.stderr.write(
|
|
2054
|
+
`[Orkestrate-MCP] ${err instanceof Error ? err.message : String(err)}
|
|
2055
|
+
`
|
|
2056
|
+
);
|
|
1649
2057
|
process.exit(1);
|
|
1650
2058
|
}
|
|
1651
2059
|
});
|
|
@@ -1653,6 +2061,10 @@ program.command("whoami").description("Show current authentication and configura
|
|
|
1653
2061
|
const { whoamiCommand: whoamiCommand2 } = await Promise.resolve().then(() => (init_whoami(), whoami_exports));
|
|
1654
2062
|
await whoamiCommand2();
|
|
1655
2063
|
});
|
|
2064
|
+
program.command("tools").description("Manage enabled/disabled tools for local MCP proxy").option("--list", "List current tool filter settings").option("--enable <tool>", "Enable a specific tool").option("--disable <tool>", "Disable a specific tool").action(async (opts) => {
|
|
2065
|
+
const { toolsCommand: toolsCommand2 } = await Promise.resolve().then(() => (init_tools(), tools_exports));
|
|
2066
|
+
await toolsCommand2(opts);
|
|
2067
|
+
});
|
|
1656
2068
|
program.action(() => {
|
|
1657
2069
|
ui.banner();
|
|
1658
2070
|
program.help();
|