rrce-workflow 0.3.12 → 0.3.14
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 +12 -0
- package/agent-core/prompts/_base.md +8 -1
- package/agent-core/prompts/doctor.md +2 -2
- package/agent-core/prompts/documentation.md +1 -1
- package/agent-core/prompts/executor.md +1 -1
- package/agent-core/prompts/init.md +1 -1
- package/agent-core/prompts/orchestrator.md +13 -3
- package/agent-core/prompts/planning_discussion.md +1 -1
- package/agent-core/prompts/research_discussion.md +2 -2
- package/agent-core/prompts/sync.md +1 -1
- package/dist/index.js +469 -519
- package/docs/AI_AGENT_GUIDE.md +65 -0
- package/package.json +1 -1
- package/dist/commands/selector.d.ts +0 -1
- package/dist/commands/selector.js +0 -29
- package/dist/commands/wizard/index.d.ts +0 -1
- package/dist/commands/wizard/index.js +0 -86
- package/dist/commands/wizard/link-flow.d.ts +0 -5
- package/dist/commands/wizard/link-flow.js +0 -97
- package/dist/commands/wizard/setup-flow.d.ts +0 -4
- package/dist/commands/wizard/setup-flow.js +0 -262
- package/dist/commands/wizard/sync-flow.d.ts +0 -4
- package/dist/commands/wizard/sync-flow.js +0 -67
- package/dist/commands/wizard/update-flow.d.ts +0 -4
- package/dist/commands/wizard/update-flow.js +0 -85
- package/dist/commands/wizard/utils.d.ts +0 -9
- package/dist/commands/wizard/utils.js +0 -33
- package/dist/commands/wizard/vscode.d.ts +0 -15
- package/dist/commands/wizard/vscode.js +0 -148
- package/dist/index.d.ts +0 -1
- package/dist/lib/autocomplete-prompt.d.ts +0 -14
- package/dist/lib/autocomplete-prompt.js +0 -167
- package/dist/lib/detection.d.ts +0 -44
- package/dist/lib/detection.js +0 -185
- package/dist/lib/git.d.ts +0 -12
- package/dist/lib/git.js +0 -37
- package/dist/lib/paths.d.ts +0 -108
- package/dist/lib/paths.js +0 -296
- package/dist/lib/prompts.d.ts +0 -18
- package/dist/lib/prompts.js +0 -62
- package/dist/types/prompt.d.ts +0 -54
- package/dist/types/prompt.js +0 -20
package/dist/index.js
CHANGED
|
@@ -857,207 +857,74 @@ var init_tui_utils = __esm({
|
|
|
857
857
|
import * as fs6 from "fs";
|
|
858
858
|
import * as path7 from "path";
|
|
859
859
|
import * as os from "os";
|
|
860
|
-
function
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
claude: checkClaudeConfig(),
|
|
864
|
-
vscodeGlobal: checkVSCodeGlobalConfig(),
|
|
865
|
-
vscodeWorkspace: workspacePath ? checkVSCodeWorkspaceConfig(workspacePath) : false,
|
|
866
|
-
opencode: checkOpenCodeConfig()
|
|
867
|
-
};
|
|
868
|
-
}
|
|
869
|
-
function checkAntigravityConfig() {
|
|
870
|
-
if (!fs6.existsSync(ANTIGRAVITY_CONFIG)) return false;
|
|
871
|
-
try {
|
|
872
|
-
const content = JSON.parse(fs6.readFileSync(ANTIGRAVITY_CONFIG, "utf-8"));
|
|
873
|
-
return !!content.mcpServers?.["rrce"];
|
|
874
|
-
} catch {
|
|
875
|
-
return false;
|
|
876
|
-
}
|
|
877
|
-
}
|
|
878
|
-
function checkClaudeConfig() {
|
|
879
|
-
if (!fs6.existsSync(CLAUDE_CONFIG)) return false;
|
|
880
|
-
try {
|
|
881
|
-
const content = JSON.parse(fs6.readFileSync(CLAUDE_CONFIG, "utf-8"));
|
|
882
|
-
return !!content.mcpServers?.["rrce"];
|
|
883
|
-
} catch {
|
|
884
|
-
return false;
|
|
885
|
-
}
|
|
886
|
-
}
|
|
887
|
-
function checkVSCodeGlobalConfig() {
|
|
888
|
-
if (!fs6.existsSync(VSCODE_GLOBAL_CONFIG)) return false;
|
|
889
|
-
try {
|
|
890
|
-
const content = JSON.parse(fs6.readFileSync(VSCODE_GLOBAL_CONFIG, "utf-8"));
|
|
891
|
-
return !!content["mcp.servers"]?.["rrce"];
|
|
892
|
-
} catch {
|
|
893
|
-
return false;
|
|
894
|
-
}
|
|
895
|
-
}
|
|
896
|
-
function checkVSCodeWorkspaceConfig(workspacePath) {
|
|
897
|
-
const configPath = path7.join(workspacePath, ".vscode", "mcp.json");
|
|
860
|
+
function checkConfig(target, workspacePath) {
|
|
861
|
+
const config = TARGET_CONFIGS[target];
|
|
862
|
+
const configPath = config.requiresWorkspacePath && workspacePath ? path7.join(workspacePath, ".vscode", "mcp.json") : config.path;
|
|
898
863
|
if (!fs6.existsSync(configPath)) return false;
|
|
899
864
|
try {
|
|
900
865
|
const content = JSON.parse(fs6.readFileSync(configPath, "utf-8"));
|
|
901
|
-
|
|
866
|
+
const targetContainer = config.configKey === "mcp" && target === "opencode" ? content.mcp : config.configKey === "mcp.servers" ? content.mcpServers : config.configKey === "servers" ? content.servers : config.configKey === "mcp.servers" ? content["mcp.servers"] : content[config.configKey];
|
|
867
|
+
return !!(targetContainer && targetContainer[config.mcpKey]);
|
|
902
868
|
} catch {
|
|
903
869
|
return false;
|
|
904
870
|
}
|
|
905
871
|
}
|
|
906
|
-
function
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
}
|
|
872
|
+
function checkInstallStatus(workspacePath) {
|
|
873
|
+
return {
|
|
874
|
+
antigravity: checkConfig("antigravity"),
|
|
875
|
+
claude: checkConfig("claude"),
|
|
876
|
+
vscodeGlobal: checkConfig("vscode-global"),
|
|
877
|
+
vscodeWorkspace: workspacePath ? checkConfig("vscode-workspace", workspacePath) : false,
|
|
878
|
+
opencode: checkConfig("opencode")
|
|
879
|
+
};
|
|
914
880
|
}
|
|
915
881
|
function isInstalledAnywhere(workspacePath) {
|
|
916
882
|
const status = checkInstallStatus(workspacePath);
|
|
917
883
|
return status.antigravity || status.claude || status.vscodeGlobal || status.vscodeWorkspace || status.opencode;
|
|
918
884
|
}
|
|
919
|
-
function
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
case "claude":
|
|
924
|
-
return installToClaude();
|
|
925
|
-
case "vscode-global":
|
|
926
|
-
return installToVSCodeGlobal();
|
|
927
|
-
case "vscode-workspace":
|
|
928
|
-
return workspacePath ? installToVSCodeWorkspace(workspacePath) : false;
|
|
929
|
-
case "opencode":
|
|
930
|
-
return installToOpenCode();
|
|
931
|
-
default:
|
|
932
|
-
return false;
|
|
933
|
-
}
|
|
934
|
-
}
|
|
935
|
-
function installToAntigravity() {
|
|
936
|
-
const dir = path7.dirname(ANTIGRAVITY_CONFIG);
|
|
937
|
-
if (!fs6.existsSync(dir)) {
|
|
938
|
-
fs6.mkdirSync(dir, { recursive: true });
|
|
939
|
-
}
|
|
940
|
-
let config = { mcpServers: {} };
|
|
941
|
-
if (fs6.existsSync(ANTIGRAVITY_CONFIG)) {
|
|
942
|
-
try {
|
|
943
|
-
config = JSON.parse(fs6.readFileSync(ANTIGRAVITY_CONFIG, "utf-8"));
|
|
944
|
-
} catch {
|
|
945
|
-
}
|
|
946
|
-
}
|
|
947
|
-
if (!config.mcpServers) config.mcpServers = {};
|
|
948
|
-
config.mcpServers["rrce"] = {
|
|
949
|
-
command: "npx",
|
|
950
|
-
args: ["-y", "rrce-workflow", "mcp", "start"]
|
|
951
|
-
};
|
|
952
|
-
try {
|
|
953
|
-
fs6.writeFileSync(ANTIGRAVITY_CONFIG, JSON.stringify(config, null, 2));
|
|
954
|
-
return true;
|
|
955
|
-
} catch {
|
|
956
|
-
return false;
|
|
957
|
-
}
|
|
958
|
-
}
|
|
959
|
-
function installToClaude() {
|
|
960
|
-
const dir = path7.dirname(CLAUDE_CONFIG);
|
|
961
|
-
if (!fs6.existsSync(dir)) {
|
|
962
|
-
fs6.mkdirSync(dir, { recursive: true });
|
|
963
|
-
}
|
|
964
|
-
let config = { mcpServers: {} };
|
|
965
|
-
if (fs6.existsSync(CLAUDE_CONFIG)) {
|
|
966
|
-
try {
|
|
967
|
-
config = JSON.parse(fs6.readFileSync(CLAUDE_CONFIG, "utf-8"));
|
|
968
|
-
} catch {
|
|
969
|
-
}
|
|
970
|
-
}
|
|
971
|
-
if (!config.mcpServers) config.mcpServers = {};
|
|
972
|
-
config.mcpServers["rrce"] = {
|
|
973
|
-
command: "npx",
|
|
974
|
-
args: ["-y", "rrce-workflow", "mcp", "start"]
|
|
975
|
-
};
|
|
976
|
-
try {
|
|
977
|
-
fs6.writeFileSync(CLAUDE_CONFIG, JSON.stringify(config, null, 2));
|
|
978
|
-
return true;
|
|
979
|
-
} catch {
|
|
980
|
-
return false;
|
|
981
|
-
}
|
|
982
|
-
}
|
|
983
|
-
function installToVSCodeGlobal() {
|
|
984
|
-
const dir = path7.dirname(VSCODE_GLOBAL_CONFIG);
|
|
885
|
+
function installToTarget(target, workspacePath) {
|
|
886
|
+
const config = TARGET_CONFIGS[target];
|
|
887
|
+
const configPath = config.requiresWorkspacePath && workspacePath ? path7.join(workspacePath, ".vscode", "mcp.json") : config.path;
|
|
888
|
+
const dir = path7.dirname(configPath);
|
|
985
889
|
if (!fs6.existsSync(dir)) {
|
|
986
890
|
fs6.mkdirSync(dir, { recursive: true });
|
|
987
891
|
}
|
|
988
|
-
let
|
|
989
|
-
if (
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
if (
|
|
996
|
-
|
|
997
|
-
command: "npx",
|
|
998
|
-
args: ["-y", "rrce-workflow", "mcp", "start"]
|
|
999
|
-
};
|
|
1000
|
-
try {
|
|
1001
|
-
fs6.writeFileSync(VSCODE_GLOBAL_CONFIG, JSON.stringify(settings, null, 2));
|
|
1002
|
-
return true;
|
|
1003
|
-
} catch {
|
|
1004
|
-
return false;
|
|
892
|
+
let existingConfig = {};
|
|
893
|
+
if (target === "opencode") {
|
|
894
|
+
existingConfig = { $schema: "https://opencode.ai/config.json" };
|
|
895
|
+
} else if (config.configKey === "servers") {
|
|
896
|
+
existingConfig = { servers: {} };
|
|
897
|
+
} else if (config.configKey === "mcp.servers") {
|
|
898
|
+
existingConfig = { mcpServers: {} };
|
|
899
|
+
} else if (config.configKey === "mcp") {
|
|
900
|
+
existingConfig = {};
|
|
1005
901
|
}
|
|
1006
|
-
}
|
|
1007
|
-
function installToVSCodeWorkspace(workspacePath) {
|
|
1008
|
-
const vscodeDir = path7.join(workspacePath, ".vscode");
|
|
1009
|
-
const configPath = path7.join(vscodeDir, "mcp.json");
|
|
1010
|
-
if (!fs6.existsSync(vscodeDir)) {
|
|
1011
|
-
fs6.mkdirSync(vscodeDir, { recursive: true });
|
|
1012
|
-
}
|
|
1013
|
-
let config = { servers: {} };
|
|
1014
902
|
if (fs6.existsSync(configPath)) {
|
|
1015
903
|
try {
|
|
1016
|
-
|
|
1017
|
-
} catch {
|
|
1018
|
-
}
|
|
1019
|
-
}
|
|
1020
|
-
if (!config.servers) config.servers = {};
|
|
1021
|
-
config.servers["rrce"] = {
|
|
1022
|
-
command: "npx",
|
|
1023
|
-
args: ["-y", "rrce-workflow", "mcp", "start"]
|
|
1024
|
-
};
|
|
1025
|
-
try {
|
|
1026
|
-
fs6.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
1027
|
-
return true;
|
|
1028
|
-
} catch {
|
|
1029
|
-
return false;
|
|
1030
|
-
}
|
|
1031
|
-
}
|
|
1032
|
-
function installToOpenCode() {
|
|
1033
|
-
const dir = path7.dirname(OPENCODE_CONFIG);
|
|
1034
|
-
if (!fs6.existsSync(dir)) {
|
|
1035
|
-
fs6.mkdirSync(dir, { recursive: true });
|
|
1036
|
-
}
|
|
1037
|
-
let config = {
|
|
1038
|
-
$schema: "https://opencode.ai/config.json"
|
|
1039
|
-
};
|
|
1040
|
-
if (fs6.existsSync(OPENCODE_CONFIG)) {
|
|
1041
|
-
try {
|
|
1042
|
-
config = JSON.parse(fs6.readFileSync(OPENCODE_CONFIG, "utf-8"));
|
|
904
|
+
existingConfig = JSON.parse(fs6.readFileSync(configPath, "utf-8"));
|
|
1043
905
|
} catch (error) {
|
|
1044
|
-
|
|
906
|
+
if (target === "opencode") {
|
|
907
|
+
console.error("Warning: Could not parse existing OpenCode config, creating fresh config");
|
|
908
|
+
}
|
|
1045
909
|
}
|
|
1046
910
|
}
|
|
1047
|
-
|
|
1048
|
-
config.
|
|
1049
|
-
type: "local",
|
|
1050
|
-
command: ["npx", "-y", "rrce-workflow", "mcp", "start"],
|
|
1051
|
-
enabled: true
|
|
1052
|
-
};
|
|
911
|
+
const container = config.configKey === "mcp" && target === "opencode" ? existingConfig.mcp || (existingConfig.mcp = {}) : config.configKey === "mcp.servers" ? existingConfig.mcpServers || (existingConfig.mcpServers = {}) : config.configKey === "servers" ? existingConfig.servers || (existingConfig.servers = {}) : config.configKey === "mcp.servers" ? existingConfig["mcp.servers"] || (existingConfig["mcp.servers"] = {}) : existingConfig[config.configKey] || (existingConfig[config.configKey] = {});
|
|
912
|
+
container[config.mcpKey] = config.serverConfig;
|
|
1053
913
|
try {
|
|
1054
|
-
|
|
914
|
+
const json = JSON.stringify(existingConfig, null, 2);
|
|
915
|
+
fs6.writeFileSync(configPath, json + (target === "opencode" ? "\n" : ""));
|
|
1055
916
|
return true;
|
|
1056
917
|
} catch (error) {
|
|
1057
|
-
|
|
918
|
+
if (target === "opencode") {
|
|
919
|
+
console.error("Failed to write OpenCode config:", error instanceof Error ? error.message : String(error));
|
|
920
|
+
}
|
|
1058
921
|
return false;
|
|
1059
922
|
}
|
|
1060
923
|
}
|
|
924
|
+
function installToConfig(target, workspacePath) {
|
|
925
|
+
if (target === "vscode-workspace" && !workspacePath) return false;
|
|
926
|
+
return installToTarget(target, workspacePath);
|
|
927
|
+
}
|
|
1061
928
|
function getTargetLabel(target) {
|
|
1062
929
|
switch (target) {
|
|
1063
930
|
case "antigravity":
|
|
@@ -1087,7 +954,7 @@ function isVSCodeInstalled() {
|
|
|
1087
954
|
const configDir = path7.join(os.homedir(), ".config/Code/User");
|
|
1088
955
|
return fs6.existsSync(configDir);
|
|
1089
956
|
}
|
|
1090
|
-
var ANTIGRAVITY_CONFIG, CLAUDE_CONFIG, VSCODE_GLOBAL_CONFIG, OPENCODE_CONFIG_DIR, OPENCODE_CONFIG;
|
|
957
|
+
var ANTIGRAVITY_CONFIG, CLAUDE_CONFIG, VSCODE_GLOBAL_CONFIG, OPENCODE_CONFIG_DIR, OPENCODE_CONFIG, TARGET_CONFIGS;
|
|
1091
958
|
var init_install = __esm({
|
|
1092
959
|
"src/mcp/install.ts"() {
|
|
1093
960
|
"use strict";
|
|
@@ -1096,6 +963,56 @@ var init_install = __esm({
|
|
|
1096
963
|
VSCODE_GLOBAL_CONFIG = path7.join(os.homedir(), ".config/Code/User/settings.json");
|
|
1097
964
|
OPENCODE_CONFIG_DIR = path7.join(os.homedir(), ".config/opencode");
|
|
1098
965
|
OPENCODE_CONFIG = path7.join(OPENCODE_CONFIG_DIR, "opencode.json");
|
|
966
|
+
TARGET_CONFIGS = {
|
|
967
|
+
antigravity: {
|
|
968
|
+
path: ANTIGRAVITY_CONFIG,
|
|
969
|
+
configKey: "mcpServers",
|
|
970
|
+
mcpKey: "rrce",
|
|
971
|
+
serverConfig: {
|
|
972
|
+
command: "npx",
|
|
973
|
+
args: ["-y", "rrce-workflow", "mcp", "start"]
|
|
974
|
+
}
|
|
975
|
+
},
|
|
976
|
+
claude: {
|
|
977
|
+
path: CLAUDE_CONFIG,
|
|
978
|
+
configKey: "mcpServers",
|
|
979
|
+
mcpKey: "rrce",
|
|
980
|
+
serverConfig: {
|
|
981
|
+
command: "npx",
|
|
982
|
+
args: ["-y", "rrce-workflow", "mcp", "start"]
|
|
983
|
+
}
|
|
984
|
+
},
|
|
985
|
+
"vscode-global": {
|
|
986
|
+
path: VSCODE_GLOBAL_CONFIG,
|
|
987
|
+
configKey: "mcp.servers",
|
|
988
|
+
mcpKey: "rrce",
|
|
989
|
+
serverConfig: {
|
|
990
|
+
command: "npx",
|
|
991
|
+
args: ["-y", "rrce-workflow", "mcp", "start"]
|
|
992
|
+
}
|
|
993
|
+
},
|
|
994
|
+
"vscode-workspace": {
|
|
995
|
+
path: "",
|
|
996
|
+
// Resolved dynamically
|
|
997
|
+
configKey: "servers",
|
|
998
|
+
mcpKey: "rrce",
|
|
999
|
+
serverConfig: {
|
|
1000
|
+
command: "npx",
|
|
1001
|
+
args: ["-y", "rrce-workflow", "mcp", "start"]
|
|
1002
|
+
},
|
|
1003
|
+
requiresWorkspacePath: true
|
|
1004
|
+
},
|
|
1005
|
+
opencode: {
|
|
1006
|
+
path: OPENCODE_CONFIG,
|
|
1007
|
+
configKey: "mcp",
|
|
1008
|
+
mcpKey: "rrce",
|
|
1009
|
+
serverConfig: {
|
|
1010
|
+
type: "local",
|
|
1011
|
+
command: ["npx", "-y", "rrce-workflow", "mcp", "start"],
|
|
1012
|
+
enabled: true
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
};
|
|
1099
1016
|
}
|
|
1100
1017
|
});
|
|
1101
1018
|
|
|
@@ -1239,11 +1156,7 @@ function convertToOpenCodeAgent(prompt, useFileReference = false, promptFilePath
|
|
|
1239
1156
|
const hostTools = ["read", "write", "edit", "bash", "grep", "glob", "webfetch", "terminalLastCommand", "task"];
|
|
1240
1157
|
if (frontmatter.tools) {
|
|
1241
1158
|
for (const tool of frontmatter.tools) {
|
|
1242
|
-
|
|
1243
|
-
tools[tool] = true;
|
|
1244
|
-
} else {
|
|
1245
|
-
tools[`rrce_${tool}`] = true;
|
|
1246
|
-
}
|
|
1159
|
+
tools[tool] = true;
|
|
1247
1160
|
}
|
|
1248
1161
|
}
|
|
1249
1162
|
tools["webfetch"] = true;
|
|
@@ -1397,10 +1310,10 @@ function findProjectConfig(config, identifier) {
|
|
|
1397
1310
|
if (targetPath && configPath) {
|
|
1398
1311
|
return configPath === targetPath;
|
|
1399
1312
|
}
|
|
1400
|
-
if (!targetPath && !configPath) {
|
|
1313
|
+
if (!targetPath && !configPath && identifier.name) {
|
|
1401
1314
|
return p.name === identifier.name;
|
|
1402
1315
|
}
|
|
1403
|
-
if (targetPath && !configPath) {
|
|
1316
|
+
if (targetPath && !configPath && identifier.name) {
|
|
1404
1317
|
return p.name === identifier.name;
|
|
1405
1318
|
}
|
|
1406
1319
|
return false;
|
|
@@ -2622,13 +2535,13 @@ function resolveProjectPaths(project, pathInput) {
|
|
|
2622
2535
|
let workspaceRoot = pathInput;
|
|
2623
2536
|
let workspaceName = project;
|
|
2624
2537
|
if (!workspaceRoot && project) {
|
|
2625
|
-
const projConfig = config
|
|
2538
|
+
const projConfig = findProjectConfig(config, { name: project });
|
|
2626
2539
|
if (projConfig?.path) {
|
|
2627
2540
|
workspaceRoot = projConfig.path;
|
|
2628
2541
|
}
|
|
2629
2542
|
}
|
|
2630
2543
|
if (!workspaceName && workspaceRoot) {
|
|
2631
|
-
const projConfig = config
|
|
2544
|
+
const projConfig = findProjectConfig(config, { path: workspaceRoot });
|
|
2632
2545
|
workspaceName = projConfig?.name || getWorkspaceName(workspaceRoot);
|
|
2633
2546
|
}
|
|
2634
2547
|
if (!workspaceName) {
|
|
@@ -2766,11 +2679,13 @@ function getProjectTasks(projectName) {
|
|
|
2766
2679
|
try {
|
|
2767
2680
|
const meta = JSON.parse(fs15.readFileSync(metaPath, "utf-8"));
|
|
2768
2681
|
tasks.push(meta);
|
|
2769
|
-
} catch {
|
|
2682
|
+
} catch (err) {
|
|
2683
|
+
logger.error(`[getProjectTasks] Failed to parse meta.json in ${dir.name}`, err);
|
|
2770
2684
|
}
|
|
2771
2685
|
}
|
|
2772
2686
|
}
|
|
2773
|
-
} catch {
|
|
2687
|
+
} catch (err) {
|
|
2688
|
+
logger.error(`[getProjectTasks] Failed to read tasks directory ${project.tasksPath}`, err);
|
|
2774
2689
|
}
|
|
2775
2690
|
return tasks;
|
|
2776
2691
|
}
|
|
@@ -2784,9 +2699,7 @@ async function searchCode(query, projectFilter, limit = 10) {
|
|
|
2784
2699
|
if (!permissions.knowledge || !project.knowledgePath) continue;
|
|
2785
2700
|
const indexingInProgress = indexingJobs.isRunning(project.name);
|
|
2786
2701
|
const advisoryMessage = indexingInProgress ? "Indexing in progress; results may be stale/incomplete." : void 0;
|
|
2787
|
-
const projConfig = config.
|
|
2788
|
-
(p) => p.path && normalizeProjectPath(p.path) === normalizeProjectPath(project.sourcePath || project.path) || !p.path && p.name === project.name
|
|
2789
|
-
);
|
|
2702
|
+
const projConfig = findProjectConfig(config, { name: project.name, path: project.sourcePath || project.path });
|
|
2790
2703
|
const useRAG = projConfig?.semanticSearch?.enabled;
|
|
2791
2704
|
if (!useRAG) {
|
|
2792
2705
|
logger.debug(`[searchCode] Semantic search not enabled for project '${project.name}'`);
|
|
@@ -2833,9 +2746,7 @@ async function searchKnowledge(query, projectFilter) {
|
|
|
2833
2746
|
if (!permissions.knowledge || !project.knowledgePath) continue;
|
|
2834
2747
|
const indexingInProgress = indexingJobs.isRunning(project.name);
|
|
2835
2748
|
const advisoryMessage = indexingInProgress ? "Indexing in progress; results may be stale/incomplete." : void 0;
|
|
2836
|
-
const projConfig = config.
|
|
2837
|
-
(p) => p.path && normalizeProjectPath(p.path) === normalizeProjectPath(project.sourcePath || project.path) || !p.path && p.name === project.name
|
|
2838
|
-
);
|
|
2749
|
+
const projConfig = findProjectConfig(config, { name: project.name, path: project.sourcePath || project.path });
|
|
2839
2750
|
const useRAG = projConfig?.semanticSearch?.enabled;
|
|
2840
2751
|
if (useRAG) {
|
|
2841
2752
|
logger.info(`[RAG] Using semantic search for project '${project.name}'`);
|
|
@@ -2883,11 +2794,42 @@ async function searchKnowledge(query, projectFilter) {
|
|
|
2883
2794
|
});
|
|
2884
2795
|
}
|
|
2885
2796
|
}
|
|
2886
|
-
} catch {
|
|
2797
|
+
} catch (err) {
|
|
2798
|
+
logger.error(`[searchKnowledge] Failed to read knowledge directory ${project.knowledgePath}`, err);
|
|
2887
2799
|
}
|
|
2888
2800
|
}
|
|
2889
2801
|
return results;
|
|
2890
2802
|
}
|
|
2803
|
+
function getScanContext(project, scanRoot) {
|
|
2804
|
+
const gitignorePath = path17.join(scanRoot, ".gitignore");
|
|
2805
|
+
const ig = fs15.existsSync(gitignorePath) ? ignore().add(fs15.readFileSync(gitignorePath, "utf-8")) : null;
|
|
2806
|
+
const toPosixRelativePath = (absolutePath) => {
|
|
2807
|
+
const rel = path17.relative(scanRoot, absolutePath);
|
|
2808
|
+
return rel.split(path17.sep).join("/");
|
|
2809
|
+
};
|
|
2810
|
+
const isUnderGitDir = (absolutePath) => {
|
|
2811
|
+
const rel = toPosixRelativePath(absolutePath);
|
|
2812
|
+
return rel === ".git" || rel.startsWith(".git/");
|
|
2813
|
+
};
|
|
2814
|
+
const isIgnoredByGitignore = (absolutePath, isDir) => {
|
|
2815
|
+
if (!ig) return false;
|
|
2816
|
+
const rel = toPosixRelativePath(absolutePath);
|
|
2817
|
+
return ig.ignores(isDir ? `${rel}/` : rel);
|
|
2818
|
+
};
|
|
2819
|
+
const shouldSkipEntryDir = (absolutePath) => {
|
|
2820
|
+
const dirName = path17.basename(absolutePath);
|
|
2821
|
+
if (dirName === ".git") return true;
|
|
2822
|
+
if (SKIP_DIRS.includes(dirName)) return true;
|
|
2823
|
+
if (isIgnoredByGitignore(absolutePath, true)) return true;
|
|
2824
|
+
return false;
|
|
2825
|
+
};
|
|
2826
|
+
const shouldSkipEntryFile = (absolutePath) => {
|
|
2827
|
+
if (isUnderGitDir(absolutePath)) return true;
|
|
2828
|
+
if (isIgnoredByGitignore(absolutePath, false)) return true;
|
|
2829
|
+
return false;
|
|
2830
|
+
};
|
|
2831
|
+
return { shouldSkipEntryDir, shouldSkipEntryFile };
|
|
2832
|
+
}
|
|
2891
2833
|
async function indexKnowledge(projectName, force = false) {
|
|
2892
2834
|
const config = loadMCPConfig();
|
|
2893
2835
|
const projects = getExposedProjects();
|
|
@@ -2903,9 +2845,7 @@ async function indexKnowledge(projectName, force = false) {
|
|
|
2903
2845
|
progress: { itemsDone: 0 }
|
|
2904
2846
|
};
|
|
2905
2847
|
}
|
|
2906
|
-
const projConfig = config.
|
|
2907
|
-
(p2) => p2.path && normalizeProjectPath(p2.path) === normalizeProjectPath(project.sourcePath || project.path) || !p2.path && p2.name === project.name
|
|
2908
|
-
) || (project.source === "global" ? { semanticSearch: { enabled: true, model: "Xenova/all-MiniLM-L6-v2" } } : void 0);
|
|
2848
|
+
const projConfig = findProjectConfig(config, { name: project.name, path: project.sourcePath || project.path }) || (project.source === "global" ? { semanticSearch: { enabled: true, model: "Xenova/all-MiniLM-L6-v2" } } : void 0);
|
|
2909
2849
|
const isEnabled = projConfig?.semanticSearch?.enabled || project.semanticSearchEnabled;
|
|
2910
2850
|
if (!isEnabled) {
|
|
2911
2851
|
return {
|
|
@@ -2930,100 +2870,8 @@ async function indexKnowledge(projectName, force = false) {
|
|
|
2930
2870
|
progress: { itemsDone: 0 }
|
|
2931
2871
|
};
|
|
2932
2872
|
}
|
|
2933
|
-
const INDEXABLE_EXTENSIONS = [
|
|
2934
|
-
".ts",
|
|
2935
|
-
".tsx",
|
|
2936
|
-
".js",
|
|
2937
|
-
".jsx",
|
|
2938
|
-
".mjs",
|
|
2939
|
-
".cjs",
|
|
2940
|
-
".py",
|
|
2941
|
-
".pyw",
|
|
2942
|
-
".go",
|
|
2943
|
-
".rs",
|
|
2944
|
-
".java",
|
|
2945
|
-
".kt",
|
|
2946
|
-
".kts",
|
|
2947
|
-
".c",
|
|
2948
|
-
".cpp",
|
|
2949
|
-
".h",
|
|
2950
|
-
".hpp",
|
|
2951
|
-
".cs",
|
|
2952
|
-
".rb",
|
|
2953
|
-
".php",
|
|
2954
|
-
".swift",
|
|
2955
|
-
".md",
|
|
2956
|
-
".mdx",
|
|
2957
|
-
".json",
|
|
2958
|
-
".yaml",
|
|
2959
|
-
".yml",
|
|
2960
|
-
".toml",
|
|
2961
|
-
".sh",
|
|
2962
|
-
".bash",
|
|
2963
|
-
".zsh",
|
|
2964
|
-
".sql",
|
|
2965
|
-
".html",
|
|
2966
|
-
".css",
|
|
2967
|
-
".scss",
|
|
2968
|
-
".sass",
|
|
2969
|
-
".less"
|
|
2970
|
-
];
|
|
2971
|
-
const CODE_EXTENSIONS = [
|
|
2972
|
-
".ts",
|
|
2973
|
-
".tsx",
|
|
2974
|
-
".js",
|
|
2975
|
-
".jsx",
|
|
2976
|
-
".mjs",
|
|
2977
|
-
".cjs",
|
|
2978
|
-
".py",
|
|
2979
|
-
".pyw",
|
|
2980
|
-
".go",
|
|
2981
|
-
".rs",
|
|
2982
|
-
".java",
|
|
2983
|
-
".kt",
|
|
2984
|
-
".kts",
|
|
2985
|
-
".c",
|
|
2986
|
-
".cpp",
|
|
2987
|
-
".h",
|
|
2988
|
-
".hpp",
|
|
2989
|
-
".cs",
|
|
2990
|
-
".rb",
|
|
2991
|
-
".php",
|
|
2992
|
-
".swift",
|
|
2993
|
-
".sh",
|
|
2994
|
-
".bash",
|
|
2995
|
-
".zsh",
|
|
2996
|
-
".sql"
|
|
2997
|
-
];
|
|
2998
|
-
const SKIP_DIRS = ["node_modules", ".git", "dist", "build", ".next", "__pycache__", "venv", ".venv", "target", "vendor"];
|
|
2999
|
-
const gitignorePath = path17.join(scanRoot, ".gitignore");
|
|
3000
|
-
const ig = fs15.existsSync(gitignorePath) ? ignore().add(fs15.readFileSync(gitignorePath, "utf-8")) : null;
|
|
3001
|
-
const toPosixRelativePath = (absolutePath) => {
|
|
3002
|
-
const rel = path17.relative(scanRoot, absolutePath);
|
|
3003
|
-
return rel.split(path17.sep).join("/");
|
|
3004
|
-
};
|
|
3005
|
-
const isUnderGitDir = (absolutePath) => {
|
|
3006
|
-
const rel = toPosixRelativePath(absolutePath);
|
|
3007
|
-
return rel === ".git" || rel.startsWith(".git/");
|
|
3008
|
-
};
|
|
3009
|
-
const isIgnoredByGitignore = (absolutePath, isDir) => {
|
|
3010
|
-
if (!ig) return false;
|
|
3011
|
-
const rel = toPosixRelativePath(absolutePath);
|
|
3012
|
-
return ig.ignores(isDir ? `${rel}/` : rel);
|
|
3013
|
-
};
|
|
3014
|
-
const shouldSkipEntryDir = (absolutePath) => {
|
|
3015
|
-
const dirName = path17.basename(absolutePath);
|
|
3016
|
-
if (dirName === ".git") return true;
|
|
3017
|
-
if (SKIP_DIRS.includes(dirName)) return true;
|
|
3018
|
-
if (isIgnoredByGitignore(absolutePath, true)) return true;
|
|
3019
|
-
return false;
|
|
3020
|
-
};
|
|
3021
|
-
const shouldSkipEntryFile = (absolutePath) => {
|
|
3022
|
-
if (isUnderGitDir(absolutePath)) return true;
|
|
3023
|
-
if (isIgnoredByGitignore(absolutePath, false)) return true;
|
|
3024
|
-
return false;
|
|
3025
|
-
};
|
|
3026
2873
|
const runIndexing = async () => {
|
|
2874
|
+
const { shouldSkipEntryDir, shouldSkipEntryFile } = getScanContext(project, scanRoot);
|
|
3027
2875
|
const indexPath = path17.join(project.knowledgePath || path17.join(scanRoot, ".rrce-workflow", "knowledge"), "embeddings.json");
|
|
3028
2876
|
const codeIndexPath = path17.join(project.knowledgePath || path17.join(scanRoot, ".rrce-workflow", "knowledge"), "code-embeddings.json");
|
|
3029
2877
|
const model = projConfig?.semanticSearch?.model || "Xenova/all-MiniLM-L6-v2";
|
|
@@ -3072,18 +2920,12 @@ async function indexKnowledge(projectName, force = false) {
|
|
|
3072
2920
|
for (const entry of entries) {
|
|
3073
2921
|
const fullPath = path17.join(dir, entry.name);
|
|
3074
2922
|
if (entry.isDirectory()) {
|
|
3075
|
-
if (shouldSkipEntryDir(fullPath))
|
|
3076
|
-
continue;
|
|
3077
|
-
}
|
|
2923
|
+
if (shouldSkipEntryDir(fullPath)) continue;
|
|
3078
2924
|
await scanDir(fullPath);
|
|
3079
2925
|
} else if (entry.isFile()) {
|
|
3080
2926
|
const ext = path17.extname(entry.name).toLowerCase();
|
|
3081
|
-
if (!INDEXABLE_EXTENSIONS.includes(ext))
|
|
3082
|
-
|
|
3083
|
-
}
|
|
3084
|
-
if (shouldSkipEntryFile(fullPath)) {
|
|
3085
|
-
continue;
|
|
3086
|
-
}
|
|
2927
|
+
if (!INDEXABLE_EXTENSIONS.includes(ext)) continue;
|
|
2928
|
+
if (shouldSkipEntryFile(fullPath)) continue;
|
|
3087
2929
|
try {
|
|
3088
2930
|
indexingJobs.update(project.name, { currentItem: fullPath, itemsDone });
|
|
3089
2931
|
const stat = fs15.statSync(fullPath);
|
|
@@ -3109,6 +2951,7 @@ async function indexKnowledge(projectName, force = false) {
|
|
|
3109
2951
|
}
|
|
3110
2952
|
}
|
|
3111
2953
|
} catch (err) {
|
|
2954
|
+
logger.error(`[indexKnowledge] Failed to index ${fullPath}`, err);
|
|
3112
2955
|
} finally {
|
|
3113
2956
|
itemsDone++;
|
|
3114
2957
|
indexingJobs.update(project.name, { itemsDone });
|
|
@@ -3178,7 +3021,8 @@ function getTask(projectName, taskSlug) {
|
|
|
3178
3021
|
if (!fs15.existsSync(metaPath)) return null;
|
|
3179
3022
|
try {
|
|
3180
3023
|
return JSON.parse(fs15.readFileSync(metaPath, "utf-8"));
|
|
3181
|
-
} catch {
|
|
3024
|
+
} catch (err) {
|
|
3025
|
+
logger.error(`[getTask] Failed to parse meta.json for task ${taskSlug}`, err);
|
|
3182
3026
|
return null;
|
|
3183
3027
|
}
|
|
3184
3028
|
}
|
|
@@ -3316,6 +3160,7 @@ async function findRelatedFiles2(filePath, projectName, options = {}) {
|
|
|
3316
3160
|
};
|
|
3317
3161
|
}
|
|
3318
3162
|
}
|
|
3163
|
+
var INDEXABLE_EXTENSIONS, CODE_EXTENSIONS, SKIP_DIRS;
|
|
3319
3164
|
var init_resources = __esm({
|
|
3320
3165
|
"src/mcp/resources.ts"() {
|
|
3321
3166
|
"use strict";
|
|
@@ -3329,6 +3174,72 @@ var init_resources = __esm({
|
|
|
3329
3174
|
init_context_extractor();
|
|
3330
3175
|
init_dependency_graph();
|
|
3331
3176
|
init_paths();
|
|
3177
|
+
INDEXABLE_EXTENSIONS = [
|
|
3178
|
+
".ts",
|
|
3179
|
+
".tsx",
|
|
3180
|
+
".js",
|
|
3181
|
+
".jsx",
|
|
3182
|
+
".mjs",
|
|
3183
|
+
".cjs",
|
|
3184
|
+
".py",
|
|
3185
|
+
".pyw",
|
|
3186
|
+
".go",
|
|
3187
|
+
".rs",
|
|
3188
|
+
".java",
|
|
3189
|
+
".kt",
|
|
3190
|
+
".kts",
|
|
3191
|
+
".c",
|
|
3192
|
+
".cpp",
|
|
3193
|
+
".h",
|
|
3194
|
+
".hpp",
|
|
3195
|
+
".cs",
|
|
3196
|
+
".rb",
|
|
3197
|
+
".php",
|
|
3198
|
+
".swift",
|
|
3199
|
+
".md",
|
|
3200
|
+
".mdx",
|
|
3201
|
+
".json",
|
|
3202
|
+
".yaml",
|
|
3203
|
+
".yml",
|
|
3204
|
+
".toml",
|
|
3205
|
+
".sh",
|
|
3206
|
+
".bash",
|
|
3207
|
+
".zsh",
|
|
3208
|
+
".sql",
|
|
3209
|
+
".html",
|
|
3210
|
+
".css",
|
|
3211
|
+
".scss",
|
|
3212
|
+
".sass",
|
|
3213
|
+
".less"
|
|
3214
|
+
];
|
|
3215
|
+
CODE_EXTENSIONS = [
|
|
3216
|
+
".ts",
|
|
3217
|
+
".tsx",
|
|
3218
|
+
".js",
|
|
3219
|
+
".jsx",
|
|
3220
|
+
".mjs",
|
|
3221
|
+
".cjs",
|
|
3222
|
+
".py",
|
|
3223
|
+
".pyw",
|
|
3224
|
+
".go",
|
|
3225
|
+
".rs",
|
|
3226
|
+
".java",
|
|
3227
|
+
".kt",
|
|
3228
|
+
".kts",
|
|
3229
|
+
".c",
|
|
3230
|
+
".cpp",
|
|
3231
|
+
".h",
|
|
3232
|
+
".hpp",
|
|
3233
|
+
".cs",
|
|
3234
|
+
".rb",
|
|
3235
|
+
".php",
|
|
3236
|
+
".swift",
|
|
3237
|
+
".sh",
|
|
3238
|
+
".bash",
|
|
3239
|
+
".zsh",
|
|
3240
|
+
".sql"
|
|
3241
|
+
];
|
|
3242
|
+
SKIP_DIRS = ["node_modules", ".git", "dist", "build", ".next", "__pycache__", "venv", ".venv", "target", "vendor"];
|
|
3332
3243
|
}
|
|
3333
3244
|
});
|
|
3334
3245
|
|
|
@@ -4666,17 +4577,37 @@ var init_SimpleSelect = __esm({
|
|
|
4666
4577
|
}
|
|
4667
4578
|
});
|
|
4668
4579
|
|
|
4580
|
+
// src/lib/project-utils.ts
|
|
4581
|
+
function sortProjects(projects, workspacePath) {
|
|
4582
|
+
return [...projects].sort((a, b) => {
|
|
4583
|
+
const aIsCurrent = workspacePath ? a.path === workspacePath : false;
|
|
4584
|
+
const bIsCurrent = workspacePath ? b.path === workspacePath : false;
|
|
4585
|
+
if (aIsCurrent && !bIsCurrent) return -1;
|
|
4586
|
+
if (!aIsCurrent && bIsCurrent) return 1;
|
|
4587
|
+
const byName = a.name.localeCompare(b.name);
|
|
4588
|
+
if (byName !== 0) return byName;
|
|
4589
|
+
const aKey = a.sourcePath ?? a.path;
|
|
4590
|
+
const bKey = b.sourcePath ?? b.path;
|
|
4591
|
+
return aKey.localeCompare(bKey);
|
|
4592
|
+
});
|
|
4593
|
+
}
|
|
4594
|
+
function projectKey(project) {
|
|
4595
|
+
return project.sourcePath ?? project.path;
|
|
4596
|
+
}
|
|
4597
|
+
function formatProjectLabel(project) {
|
|
4598
|
+
const root = project.sourcePath ?? project.path;
|
|
4599
|
+
return `${project.name} (${project.source})${root ? ` - ${root}` : ""}`;
|
|
4600
|
+
}
|
|
4601
|
+
var init_project_utils = __esm({
|
|
4602
|
+
"src/lib/project-utils.ts"() {
|
|
4603
|
+
"use strict";
|
|
4604
|
+
}
|
|
4605
|
+
});
|
|
4606
|
+
|
|
4669
4607
|
// src/mcp/ui/ProjectsView.tsx
|
|
4670
4608
|
import { useEffect as useEffect3, useMemo as useMemo3, useState as useState3 } from "react";
|
|
4671
4609
|
import { Box as Box4, Text as Text4, useInput as useInput2 } from "ink";
|
|
4672
4610
|
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
4673
|
-
function projectKey(p) {
|
|
4674
|
-
return p.sourcePath ?? p.path;
|
|
4675
|
-
}
|
|
4676
|
-
function formatProjectLabel(p) {
|
|
4677
|
-
const root = p.sourcePath ?? p.path;
|
|
4678
|
-
return `${p.name} (${p.source})${root ? ` - ${root}` : ""}`;
|
|
4679
|
-
}
|
|
4680
4611
|
var ProjectsView;
|
|
4681
4612
|
var init_ProjectsView = __esm({
|
|
4682
4613
|
"src/mcp/ui/ProjectsView.tsx"() {
|
|
@@ -4686,29 +4617,19 @@ var init_ProjectsView = __esm({
|
|
|
4686
4617
|
init_ConfigContext();
|
|
4687
4618
|
init_indexing_jobs();
|
|
4688
4619
|
init_config_utils();
|
|
4620
|
+
init_project_utils();
|
|
4689
4621
|
ProjectsView = ({ config: initialConfig, projects: allProjects, onConfigChange, workspacePath }) => {
|
|
4690
4622
|
const { driftReports, checkAllDrift } = useConfig();
|
|
4691
4623
|
const [config, setConfig] = useState3(initialConfig);
|
|
4692
4624
|
const [indexingStats, setIndexingStats] = useState3({});
|
|
4693
4625
|
const sortedProjects = useMemo3(() => {
|
|
4694
|
-
return
|
|
4695
|
-
const aIsCurrent = a.path === workspacePath;
|
|
4696
|
-
const bIsCurrent = b.path === workspacePath;
|
|
4697
|
-
if (aIsCurrent && !bIsCurrent) return -1;
|
|
4698
|
-
if (!aIsCurrent && bIsCurrent) return 1;
|
|
4699
|
-
const byName = a.name.localeCompare(b.name);
|
|
4700
|
-
if (byName !== 0) return byName;
|
|
4701
|
-
return projectKey(a).localeCompare(projectKey(b));
|
|
4702
|
-
});
|
|
4626
|
+
return sortProjects(allProjects, workspacePath);
|
|
4703
4627
|
}, [allProjects, workspacePath]);
|
|
4704
4628
|
useEffect3(() => {
|
|
4705
4629
|
const updateStats = () => {
|
|
4706
4630
|
const next = {};
|
|
4707
4631
|
for (const p of allProjects) {
|
|
4708
|
-
|
|
4709
|
-
if (!projConfig && p.source === "global") {
|
|
4710
|
-
projConfig = config.projects.find((c) => c.name === p.name);
|
|
4711
|
-
}
|
|
4632
|
+
const projConfig = findProjectConfig(config, { name: p.name, path: p.path });
|
|
4712
4633
|
const enabled = projConfig?.semanticSearch?.enabled || p.semanticSearchEnabled || false;
|
|
4713
4634
|
const prog = indexingJobs.getProgress(p.name);
|
|
4714
4635
|
next[p.name] = { enabled, ...prog };
|
|
@@ -4739,9 +4660,7 @@ var init_ProjectsView = __esm({
|
|
|
4739
4660
|
});
|
|
4740
4661
|
const projectItems = useMemo3(() => {
|
|
4741
4662
|
return sortedProjects.map((p) => {
|
|
4742
|
-
const projectConfig = config.
|
|
4743
|
-
(c) => c.path && c.path === p.path || p.source === "global" && c.name === p.name || !c.path && c.name === p.name
|
|
4744
|
-
);
|
|
4663
|
+
const projectConfig = findProjectConfig(config, { name: p.name, path: p.path });
|
|
4745
4664
|
const isExposed = projectConfig ? projectConfig.expose : config.defaults.includeNew;
|
|
4746
4665
|
const drift = driftReports[p.path];
|
|
4747
4666
|
const idx = indexingStats[p.name];
|
|
@@ -4777,7 +4696,7 @@ var init_ProjectsView = __esm({
|
|
|
4777
4696
|
const isSelected = selectedIds.includes(item.value);
|
|
4778
4697
|
const project = allProjects.find((p) => p.path === item.value);
|
|
4779
4698
|
if (project) {
|
|
4780
|
-
const existingConfig = newConfig
|
|
4699
|
+
const existingConfig = findProjectConfig(newConfig, { name: project.name, path: project.path });
|
|
4781
4700
|
const projectPath = project.source === "global" && existingConfig?.path ? existingConfig.path : project.path;
|
|
4782
4701
|
newConfig = setProjectConfig(
|
|
4783
4702
|
newConfig,
|
|
@@ -4874,28 +4793,168 @@ var init_ui_helpers = __esm({
|
|
|
4874
4793
|
}
|
|
4875
4794
|
});
|
|
4876
4795
|
|
|
4796
|
+
// src/mcp/ui/components/TaskRow.tsx
|
|
4797
|
+
import "react";
|
|
4798
|
+
import { Box as Box5, Text as Text5 } from "ink";
|
|
4799
|
+
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
4800
|
+
var TaskRow;
|
|
4801
|
+
var init_TaskRow = __esm({
|
|
4802
|
+
"src/mcp/ui/components/TaskRow.tsx"() {
|
|
4803
|
+
"use strict";
|
|
4804
|
+
init_ui_helpers();
|
|
4805
|
+
init_project_utils();
|
|
4806
|
+
TaskRow = ({ row, isSelected, isExpanded, taskCount, hasDrift }) => {
|
|
4807
|
+
if (row.kind === "project") {
|
|
4808
|
+
return /* @__PURE__ */ jsx6(Box5, { flexDirection: "column", children: /* @__PURE__ */ jsxs4(Box5, { children: [
|
|
4809
|
+
/* @__PURE__ */ jsx6(Text5, { color: isSelected ? "cyan" : "white", children: isSelected ? "> " : " " }),
|
|
4810
|
+
/* @__PURE__ */ jsxs4(Text5, { color: isSelected ? "cyan" : "white", children: [
|
|
4811
|
+
getFolderIcon(isExpanded),
|
|
4812
|
+
" ",
|
|
4813
|
+
formatProjectLabel(row.project)
|
|
4814
|
+
] }),
|
|
4815
|
+
hasDrift && /* @__PURE__ */ jsx6(Text5, { color: "magenta", children: " \u26A0" }),
|
|
4816
|
+
/* @__PURE__ */ jsxs4(Text5, { color: "dim", children: [
|
|
4817
|
+
" ",
|
|
4818
|
+
taskCount > 0 ? `(${taskCount})` : ""
|
|
4819
|
+
] })
|
|
4820
|
+
] }) });
|
|
4821
|
+
}
|
|
4822
|
+
const taskLabel = row.task.title || row.task.task_slug;
|
|
4823
|
+
const status = row.task.status || "";
|
|
4824
|
+
return /* @__PURE__ */ jsxs4(Box5, { children: [
|
|
4825
|
+
/* @__PURE__ */ jsx6(Text5, { color: isSelected ? "cyan" : "white", children: isSelected ? "> " : " " }),
|
|
4826
|
+
/* @__PURE__ */ jsx6(Text5, { color: "dim", children: " - " }),
|
|
4827
|
+
/* @__PURE__ */ jsx6(Text5, { color: isSelected ? "cyan" : "white", children: taskLabel }),
|
|
4828
|
+
row.task.task_slug !== "__none__" && /* @__PURE__ */ jsx6(Text5, { backgroundColor: getStatusColor(status), color: "black", children: ` ${getStatusIcon(status)} ${status.toUpperCase().replace("_", " ")} ` })
|
|
4829
|
+
] });
|
|
4830
|
+
};
|
|
4831
|
+
}
|
|
4832
|
+
});
|
|
4833
|
+
|
|
4834
|
+
// src/mcp/ui/components/TaskDetails.tsx
|
|
4835
|
+
import "react";
|
|
4836
|
+
import { Box as Box6, Text as Text6 } from "ink";
|
|
4837
|
+
import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
4838
|
+
var TaskDetails;
|
|
4839
|
+
var init_TaskDetails = __esm({
|
|
4840
|
+
"src/mcp/ui/components/TaskDetails.tsx"() {
|
|
4841
|
+
"use strict";
|
|
4842
|
+
init_ui_helpers();
|
|
4843
|
+
TaskDetails = ({ task }) => {
|
|
4844
|
+
if (!task) {
|
|
4845
|
+
return /* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", justifyContent: "center", alignItems: "center", gap: 1, flexGrow: 1, children: [
|
|
4846
|
+
/* @__PURE__ */ jsx7(Text6, { bold: true, color: "dim", children: "\u2500 No Task Selected \u2500" }),
|
|
4847
|
+
/* @__PURE__ */ jsx7(Text6, { color: "dim", children: "Use \u2191/\u2193 to navigate, Enter to expand projects" }),
|
|
4848
|
+
/* @__PURE__ */ jsx7(Text6, { color: "dim", children: "Press 's' to cycle task status" })
|
|
4849
|
+
] });
|
|
4850
|
+
}
|
|
4851
|
+
return /* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", children: [
|
|
4852
|
+
/* @__PURE__ */ jsxs5(Box6, { marginBottom: 1, flexDirection: "column", children: [
|
|
4853
|
+
/* @__PURE__ */ jsx7(Text6, { bold: true, color: "cyan", children: task.title || task.task_slug }),
|
|
4854
|
+
task.summary && /* @__PURE__ */ jsx7(Text6, { color: "white", children: task.summary })
|
|
4855
|
+
] }),
|
|
4856
|
+
/* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" }),
|
|
4857
|
+
/* @__PURE__ */ jsxs5(Box6, { marginTop: 1, paddingX: 1, flexDirection: "column", children: [
|
|
4858
|
+
/* @__PURE__ */ jsx7(Text6, { bold: true, color: "white", children: "\u{1F4CB} STATUS" }),
|
|
4859
|
+
/* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", marginTop: 1, children: [
|
|
4860
|
+
/* @__PURE__ */ jsxs5(Text6, { children: [
|
|
4861
|
+
/* @__PURE__ */ jsx7(Text6, { color: "dim", children: "Status: " }),
|
|
4862
|
+
" ",
|
|
4863
|
+
/* @__PURE__ */ jsx7(Text6, { color: getStatusColor(task.status || ""), children: task.status || "unknown" })
|
|
4864
|
+
] }),
|
|
4865
|
+
/* @__PURE__ */ jsxs5(Text6, { children: [
|
|
4866
|
+
/* @__PURE__ */ jsx7(Text6, { color: "dim", children: "Updated:" }),
|
|
4867
|
+
" ",
|
|
4868
|
+
/* @__PURE__ */ jsx7(Text6, { children: task.updated_at || "\u2014" })
|
|
4869
|
+
] }),
|
|
4870
|
+
/* @__PURE__ */ jsxs5(Text6, { children: [
|
|
4871
|
+
/* @__PURE__ */ jsx7(Text6, { color: "dim", children: "Tags: " }),
|
|
4872
|
+
" ",
|
|
4873
|
+
" ",
|
|
4874
|
+
(() => {
|
|
4875
|
+
const tags = task.tags || [];
|
|
4876
|
+
return tags.length > 0 ? tags.map((tag, i) => /* @__PURE__ */ jsxs5(Text6, { children: [
|
|
4877
|
+
/* @__PURE__ */ jsx7(Text6, { color: "cyan", children: tag }),
|
|
4878
|
+
i < tags.length - 1 && /* @__PURE__ */ jsx7(Text6, { color: "dim", children: ", " })
|
|
4879
|
+
] }, tag)) : /* @__PURE__ */ jsx7(Text6, { color: "dim", children: "\u2014" });
|
|
4880
|
+
})()
|
|
4881
|
+
] })
|
|
4882
|
+
] })
|
|
4883
|
+
] }),
|
|
4884
|
+
/* @__PURE__ */ jsx7(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" }) }),
|
|
4885
|
+
/* @__PURE__ */ jsxs5(Box6, { marginTop: 1, paddingX: 1, flexDirection: "column", children: [
|
|
4886
|
+
/* @__PURE__ */ jsx7(Text6, { bold: true, color: "white", children: "\u{1F4CB} CHECKLIST" }),
|
|
4887
|
+
task.checklist && task.checklist.length > 0 && /* @__PURE__ */ jsx7(Box6, { marginTop: 1, flexDirection: "column", children: /* @__PURE__ */ jsxs5(Box6, { marginBottom: 1, children: [
|
|
4888
|
+
/* @__PURE__ */ jsx7(Text6, { backgroundColor: "white", children: getProgressBar(getChecklistProgress(task.checklist).percentage) }),
|
|
4889
|
+
/* @__PURE__ */ jsxs5(Text6, { dimColor: true, children: [
|
|
4890
|
+
" ",
|
|
4891
|
+
" ",
|
|
4892
|
+
getChecklistProgress(task.checklist).completed,
|
|
4893
|
+
"/",
|
|
4894
|
+
getChecklistProgress(task.checklist).total,
|
|
4895
|
+
" (",
|
|
4896
|
+
getChecklistProgress(task.checklist).percentage,
|
|
4897
|
+
"%)"
|
|
4898
|
+
] })
|
|
4899
|
+
] }) }),
|
|
4900
|
+
(task.checklist || []).length === 0 ? /* @__PURE__ */ jsx7(Text6, { color: "dim", children: "\u2014" }) : (task.checklist || []).slice(0, 12).map((c, i) => {
|
|
4901
|
+
const isDone = c.status === "done";
|
|
4902
|
+
return /* @__PURE__ */ jsxs5(Text6, { color: isDone ? "dim" : "white", children: [
|
|
4903
|
+
/* @__PURE__ */ jsxs5(Text6, { color: isDone ? "green" : "dim", children: [
|
|
4904
|
+
getCheckbox(c.status || "pending"),
|
|
4905
|
+
" "
|
|
4906
|
+
] }),
|
|
4907
|
+
c.label || c.id || "item"
|
|
4908
|
+
] }, c.id || i);
|
|
4909
|
+
})
|
|
4910
|
+
] }),
|
|
4911
|
+
/* @__PURE__ */ jsx7(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" }) }),
|
|
4912
|
+
/* @__PURE__ */ jsxs5(Box6, { marginTop: 1, paddingX: 1, flexDirection: "column", children: [
|
|
4913
|
+
/* @__PURE__ */ jsx7(Text6, { bold: true, color: "white", children: "\u{1F916} AGENTS" }),
|
|
4914
|
+
/* @__PURE__ */ jsx7(Box6, { marginTop: 1, flexDirection: "column", children: !task.agents ? /* @__PURE__ */ jsx7(Text6, { color: "dim", children: "\u2014" }) : Object.entries(task.agents).map(([agent, info]) => /* @__PURE__ */ jsxs5(Text6, { children: [
|
|
4915
|
+
/* @__PURE__ */ jsxs5(Text6, { color: "dim", children: [
|
|
4916
|
+
"- ",
|
|
4917
|
+
agent,
|
|
4918
|
+
": "
|
|
4919
|
+
] }),
|
|
4920
|
+
info?.status === "complete" && /* @__PURE__ */ jsx7(Text6, { color: "green", children: "\u2713" }),
|
|
4921
|
+
info?.status === "in_progress" && /* @__PURE__ */ jsx7(Text6, { color: "yellow", children: "\u27F3" }),
|
|
4922
|
+
info?.status === "pending" && /* @__PURE__ */ jsx7(Text6, { color: "dim", children: "\u25CB" }),
|
|
4923
|
+
info?.blocked && /* @__PURE__ */ jsx7(Text6, { color: "red", children: "\u2715" }),
|
|
4924
|
+
/* @__PURE__ */ jsxs5(Text6, { color: info?.status === "complete" ? "dim" : "white", children: [
|
|
4925
|
+
" ",
|
|
4926
|
+
info?.status || "\u2014"
|
|
4927
|
+
] }),
|
|
4928
|
+
info?.artifact && /* @__PURE__ */ jsxs5(Text6, { dimColor: true, children: [
|
|
4929
|
+
" (",
|
|
4930
|
+
info.artifact,
|
|
4931
|
+
")"
|
|
4932
|
+
] })
|
|
4933
|
+
] }, agent)) })
|
|
4934
|
+
] })
|
|
4935
|
+
] });
|
|
4936
|
+
};
|
|
4937
|
+
}
|
|
4938
|
+
});
|
|
4939
|
+
|
|
4877
4940
|
// src/mcp/ui/TasksView.tsx
|
|
4878
4941
|
import { useEffect as useEffect4, useMemo as useMemo4, useState as useState4 } from "react";
|
|
4879
|
-
import { Box as
|
|
4880
|
-
import { jsx as
|
|
4942
|
+
import { Box as Box7, Text as Text7, useInput as useInput3 } from "ink";
|
|
4943
|
+
import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
4881
4944
|
function nextStatus(current) {
|
|
4882
4945
|
const idx = STATUS_CYCLE.indexOf(current || "");
|
|
4883
4946
|
if (idx === -1) return STATUS_CYCLE[0];
|
|
4884
4947
|
return STATUS_CYCLE[(idx + 1) % STATUS_CYCLE.length];
|
|
4885
4948
|
}
|
|
4886
|
-
function projectKey2(p) {
|
|
4887
|
-
return p.sourcePath ?? p.path;
|
|
4888
|
-
}
|
|
4889
|
-
function formatProjectLabel2(p) {
|
|
4890
|
-
return `${p.name} (${p.source})`;
|
|
4891
|
-
}
|
|
4892
4949
|
var STATUS_CYCLE, TasksView;
|
|
4893
4950
|
var init_TasksView = __esm({
|
|
4894
4951
|
"src/mcp/ui/TasksView.tsx"() {
|
|
4895
4952
|
"use strict";
|
|
4896
4953
|
init_tasks_fs();
|
|
4897
4954
|
init_ConfigContext();
|
|
4898
|
-
|
|
4955
|
+
init_project_utils();
|
|
4956
|
+
init_TaskRow();
|
|
4957
|
+
init_TaskDetails();
|
|
4899
4958
|
STATUS_CYCLE = ["pending", "in_progress", "blocked", "complete"];
|
|
4900
4959
|
TasksView = ({ projects: allProjects, workspacePath }) => {
|
|
4901
4960
|
const { driftReports } = useConfig();
|
|
@@ -4904,20 +4963,12 @@ var init_TasksView = __esm({
|
|
|
4904
4963
|
const [taskCache, setTaskCache] = useState4({});
|
|
4905
4964
|
const [errorLine, setErrorLine] = useState4(null);
|
|
4906
4965
|
const sortedProjects = useMemo4(() => {
|
|
4907
|
-
return
|
|
4908
|
-
const aIsCurrent = a.path === workspacePath;
|
|
4909
|
-
const bIsCurrent = b.path === workspacePath;
|
|
4910
|
-
if (aIsCurrent && !bIsCurrent) return -1;
|
|
4911
|
-
if (!aIsCurrent && bIsCurrent) return 1;
|
|
4912
|
-
const byName = a.name.localeCompare(b.name);
|
|
4913
|
-
if (byName !== 0) return byName;
|
|
4914
|
-
return projectKey2(a).localeCompare(projectKey2(b));
|
|
4915
|
-
});
|
|
4966
|
+
return sortProjects(allProjects, workspacePath);
|
|
4916
4967
|
}, [allProjects, workspacePath]);
|
|
4917
4968
|
useEffect4(() => {
|
|
4918
4969
|
const current = sortedProjects.find((p) => p.path === workspacePath);
|
|
4919
4970
|
if (current) {
|
|
4920
|
-
const k =
|
|
4971
|
+
const k = projectKey(current);
|
|
4921
4972
|
setExpanded((prev) => {
|
|
4922
4973
|
const next = new Set(prev);
|
|
4923
4974
|
if (!next.has(k)) {
|
|
@@ -4930,12 +4981,12 @@ var init_TasksView = __esm({
|
|
|
4930
4981
|
}, [sortedProjects, workspacePath]);
|
|
4931
4982
|
const refreshTasksForProject = (project) => {
|
|
4932
4983
|
const res = listProjectTasks(project);
|
|
4933
|
-
setTaskCache((prev) => ({ ...prev, [
|
|
4984
|
+
setTaskCache((prev) => ({ ...prev, [projectKey(project)]: res.tasks }));
|
|
4934
4985
|
};
|
|
4935
4986
|
const refreshAllTasks = () => {
|
|
4936
4987
|
const next = {};
|
|
4937
4988
|
for (const p of sortedProjects) {
|
|
4938
|
-
next[
|
|
4989
|
+
next[projectKey(p)] = listProjectTasks(p).tasks;
|
|
4939
4990
|
}
|
|
4940
4991
|
setTaskCache(next);
|
|
4941
4992
|
};
|
|
@@ -4943,7 +4994,7 @@ var init_TasksView = __esm({
|
|
|
4943
4994
|
const rows = [];
|
|
4944
4995
|
for (const p of sortedProjects) {
|
|
4945
4996
|
rows.push({ kind: "project", project: p });
|
|
4946
|
-
const k =
|
|
4997
|
+
const k = projectKey(p);
|
|
4947
4998
|
if (!expanded.has(k)) continue;
|
|
4948
4999
|
const tasks = taskCache[k] || [];
|
|
4949
5000
|
for (const t of tasks) {
|
|
@@ -4972,7 +5023,7 @@ var init_TasksView = __esm({
|
|
|
4972
5023
|
if (key.return) {
|
|
4973
5024
|
const row = flattenedRows[selectedIndex];
|
|
4974
5025
|
if (row?.kind === "project") {
|
|
4975
|
-
const k =
|
|
5026
|
+
const k = projectKey(row.project);
|
|
4976
5027
|
const next = new Set(expanded);
|
|
4977
5028
|
if (next.has(k)) {
|
|
4978
5029
|
next.delete(k);
|
|
@@ -4995,7 +5046,7 @@ var init_TasksView = __esm({
|
|
|
4995
5046
|
return;
|
|
4996
5047
|
}
|
|
4997
5048
|
setTaskCache((prev) => {
|
|
4998
|
-
const k =
|
|
5049
|
+
const k = projectKey(row.project);
|
|
4999
5050
|
const tasks = prev[k] || [];
|
|
5000
5051
|
const updated = tasks.map((t) => t.task_slug === row.task.task_slug ? result.meta : t);
|
|
5001
5052
|
return { ...prev, [k]: updated };
|
|
@@ -5012,147 +5063,43 @@ var init_TasksView = __esm({
|
|
|
5012
5063
|
}, [flattenedRows]);
|
|
5013
5064
|
const selectedRow = flattenedRows[selectedIndex];
|
|
5014
5065
|
const selectedTask = selectedRow?.kind === "task" && selectedRow.task.task_slug !== "__none__" ? selectedRow.task : null;
|
|
5015
|
-
return /* @__PURE__ */
|
|
5016
|
-
/* @__PURE__ */
|
|
5017
|
-
/* @__PURE__ */
|
|
5018
|
-
/* @__PURE__ */
|
|
5019
|
-
/* @__PURE__ */
|
|
5020
|
-
/* @__PURE__ */
|
|
5066
|
+
return /* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", padding: 1, borderStyle: "round", borderColor: "white", flexGrow: 1, children: [
|
|
5067
|
+
/* @__PURE__ */ jsxs6(Box7, { justifyContent: "space-between", children: [
|
|
5068
|
+
/* @__PURE__ */ jsxs6(Box7, { children: [
|
|
5069
|
+
/* @__PURE__ */ jsx8(Text7, { bold: true, color: "cyan", children: "\u2699 Tasks" }),
|
|
5070
|
+
/* @__PURE__ */ jsx8(Text7, { dimColor: true, children: " \u2022 " }),
|
|
5071
|
+
/* @__PURE__ */ jsxs6(Text7, { children: [
|
|
5021
5072
|
sortedProjects.length,
|
|
5022
5073
|
" projects"
|
|
5023
5074
|
] }),
|
|
5024
|
-
/* @__PURE__ */
|
|
5025
|
-
/* @__PURE__ */
|
|
5075
|
+
/* @__PURE__ */ jsx8(Text7, { dimColor: true, children: " \u2022 " }),
|
|
5076
|
+
/* @__PURE__ */ jsxs6(Text7, { children: [
|
|
5026
5077
|
Object.values(taskCache).flat().length,
|
|
5027
5078
|
" tasks"
|
|
5028
5079
|
] })
|
|
5029
5080
|
] }),
|
|
5030
|
-
/* @__PURE__ */
|
|
5081
|
+
/* @__PURE__ */ jsx8(Text7, { color: "dim", children: "\u2191/\u2193:Nav Enter:Expand s:Status R:Refresh" })
|
|
5031
5082
|
] }),
|
|
5032
|
-
errorLine && /* @__PURE__ */
|
|
5033
|
-
/* @__PURE__ */
|
|
5034
|
-
/* @__PURE__ */
|
|
5035
|
-
flattenedRows.length === 0 ? /* @__PURE__ */
|
|
5036
|
-
const
|
|
5037
|
-
|
|
5038
|
-
|
|
5039
|
-
|
|
5040
|
-
|
|
5041
|
-
|
|
5042
|
-
|
|
5043
|
-
|
|
5044
|
-
|
|
5045
|
-
|
|
5046
|
-
|
|
5047
|
-
|
|
5048
|
-
] }),
|
|
5049
|
-
drift?.hasDrift && /* @__PURE__ */ jsx6(Text5, { color: "magenta", children: " \u26A0" }),
|
|
5050
|
-
/* @__PURE__ */ jsxs4(Text5, { color: "dim", children: [
|
|
5051
|
-
" ",
|
|
5052
|
-
count > 0 ? `(${count})` : ""
|
|
5053
|
-
] })
|
|
5054
|
-
] }) }, `p:${k}`);
|
|
5055
|
-
}
|
|
5056
|
-
const taskLabel = row.task.title || row.task.task_slug;
|
|
5057
|
-
const status = row.task.status || "";
|
|
5058
|
-
return /* @__PURE__ */ jsxs4(Box5, { children: [
|
|
5059
|
-
/* @__PURE__ */ jsx6(Text5, { color: isSel ? "cyan" : "white", children: isSel ? "> " : " " }),
|
|
5060
|
-
/* @__PURE__ */ jsx6(Text5, { color: "dim", children: " - " }),
|
|
5061
|
-
/* @__PURE__ */ jsx6(Text5, { color: isSel ? "cyan" : "white", children: taskLabel }),
|
|
5062
|
-
row.task.task_slug !== "__none__" && /* @__PURE__ */ jsx6(Text5, { backgroundColor: getStatusColor(status), color: "black", children: ` ${getStatusIcon(status)} ${status.toUpperCase().replace("_", " ")} ` })
|
|
5063
|
-
] }, `t:${projectKey2(row.project)}:${row.task.task_slug}`);
|
|
5083
|
+
errorLine && /* @__PURE__ */ jsx8(Box7, { marginTop: 0, children: /* @__PURE__ */ jsx8(Text7, { color: "red", children: errorLine }) }),
|
|
5084
|
+
/* @__PURE__ */ jsxs6(Box7, { marginTop: 1, flexDirection: "row", flexGrow: 1, children: [
|
|
5085
|
+
/* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", width: "55%", children: [
|
|
5086
|
+
flattenedRows.length === 0 ? /* @__PURE__ */ jsx8(Text7, { color: "dim", children: "No projects detected." }) : flattenedRows.map((row, idx) => {
|
|
5087
|
+
const k = projectKey(row.project);
|
|
5088
|
+
return /* @__PURE__ */ jsx8(
|
|
5089
|
+
TaskRow,
|
|
5090
|
+
{
|
|
5091
|
+
row,
|
|
5092
|
+
isSelected: idx === selectedIndex,
|
|
5093
|
+
isExpanded: expanded.has(k),
|
|
5094
|
+
taskCount: (taskCache[k] || []).length,
|
|
5095
|
+
hasDrift: !!driftReports[row.project.path]?.hasDrift
|
|
5096
|
+
},
|
|
5097
|
+
row.kind === "project" ? `p:${k}` : `t:${k}:${row.task.task_slug}`
|
|
5098
|
+
);
|
|
5064
5099
|
}),
|
|
5065
|
-
/* @__PURE__ */
|
|
5100
|
+
/* @__PURE__ */ jsx8(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx8(Text7, { color: "gray", children: "\u25B2/\u25BC navigate \u2022 Enter expand/collapse \u2022 s cycle status \u2022 R refresh" }) })
|
|
5066
5101
|
] }),
|
|
5067
|
-
/* @__PURE__ */
|
|
5068
|
-
/* @__PURE__ */ jsx6(Text5, { bold: true, color: "dim", children: "\u2500 No Task Selected \u2500" }),
|
|
5069
|
-
/* @__PURE__ */ jsx6(Text5, { color: "dim", children: "Use \u2191/\u2193 to navigate, Enter to expand projects" }),
|
|
5070
|
-
/* @__PURE__ */ jsx6(Text5, { color: "dim", children: "Press 's' to cycle task status" })
|
|
5071
|
-
] }) : /* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", children: [
|
|
5072
|
-
/* @__PURE__ */ jsxs4(Box5, { marginBottom: 1, flexDirection: "column", children: [
|
|
5073
|
-
/* @__PURE__ */ jsx6(Text5, { bold: true, color: "cyan", children: selectedTask.title || selectedTask.task_slug }),
|
|
5074
|
-
selectedTask.summary && /* @__PURE__ */ jsx6(Text5, { color: "white", children: selectedTask.summary })
|
|
5075
|
-
] }),
|
|
5076
|
-
/* @__PURE__ */ jsx6(Text5, { dimColor: true, children: "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" }),
|
|
5077
|
-
/* @__PURE__ */ jsxs4(Box5, { marginTop: 1, paddingX: 1, flexDirection: "column", children: [
|
|
5078
|
-
/* @__PURE__ */ jsx6(Text5, { bold: true, color: "white", children: "\u{1F4CB} STATUS" }),
|
|
5079
|
-
/* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", marginTop: 1, children: [
|
|
5080
|
-
/* @__PURE__ */ jsxs4(Text5, { children: [
|
|
5081
|
-
/* @__PURE__ */ jsx6(Text5, { color: "dim", children: "Status: " }),
|
|
5082
|
-
" ",
|
|
5083
|
-
/* @__PURE__ */ jsx6(Text5, { color: getStatusColor(selectedTask.status || ""), children: selectedTask.status || "unknown" })
|
|
5084
|
-
] }),
|
|
5085
|
-
/* @__PURE__ */ jsxs4(Text5, { children: [
|
|
5086
|
-
/* @__PURE__ */ jsx6(Text5, { color: "dim", children: "Updated:" }),
|
|
5087
|
-
" ",
|
|
5088
|
-
/* @__PURE__ */ jsx6(Text5, { children: selectedTask.updated_at || "\u2014" })
|
|
5089
|
-
] }),
|
|
5090
|
-
/* @__PURE__ */ jsxs4(Text5, { children: [
|
|
5091
|
-
/* @__PURE__ */ jsx6(Text5, { color: "dim", children: "Tags: " }),
|
|
5092
|
-
" ",
|
|
5093
|
-
" ",
|
|
5094
|
-
(() => {
|
|
5095
|
-
const tags = selectedTask.tags || [];
|
|
5096
|
-
return tags.length > 0 ? tags.map((tag, i) => /* @__PURE__ */ jsxs4(Text5, { children: [
|
|
5097
|
-
/* @__PURE__ */ jsx6(Text5, { color: "cyan", children: tag }),
|
|
5098
|
-
i < tags.length - 1 && /* @__PURE__ */ jsx6(Text5, { color: "dim", children: ", " })
|
|
5099
|
-
] }, tag)) : /* @__PURE__ */ jsx6(Text5, { color: "dim", children: "\u2014" });
|
|
5100
|
-
})()
|
|
5101
|
-
] })
|
|
5102
|
-
] })
|
|
5103
|
-
] }),
|
|
5104
|
-
/* @__PURE__ */ jsx6(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" }) }),
|
|
5105
|
-
/* @__PURE__ */ jsxs4(Box5, { marginTop: 1, paddingX: 1, flexDirection: "column", children: [
|
|
5106
|
-
/* @__PURE__ */ jsx6(Text5, { bold: true, color: "white", children: "\u{1F4CB} CHECKLIST" }),
|
|
5107
|
-
selectedTask.checklist && selectedTask.checklist.length > 0 && /* @__PURE__ */ jsx6(Box5, { marginTop: 1, flexDirection: "column", children: /* @__PURE__ */ jsxs4(Box5, { marginBottom: 1, children: [
|
|
5108
|
-
/* @__PURE__ */ jsx6(Text5, { backgroundColor: "white", children: getProgressBar(getChecklistProgress(selectedTask.checklist).percentage) }),
|
|
5109
|
-
/* @__PURE__ */ jsxs4(Text5, { dimColor: true, children: [
|
|
5110
|
-
" ",
|
|
5111
|
-
" ",
|
|
5112
|
-
getChecklistProgress(selectedTask.checklist).completed,
|
|
5113
|
-
"/",
|
|
5114
|
-
getChecklistProgress(selectedTask.checklist).total,
|
|
5115
|
-
" (",
|
|
5116
|
-
getChecklistProgress(selectedTask.checklist).percentage,
|
|
5117
|
-
"%)"
|
|
5118
|
-
] })
|
|
5119
|
-
] }) }),
|
|
5120
|
-
(selectedTask.checklist || []).length === 0 ? /* @__PURE__ */ jsx6(Text5, { color: "dim", children: "\u2014" }) : (selectedTask.checklist || []).slice(0, 12).map((c, i) => {
|
|
5121
|
-
const isDone = c.status === "done";
|
|
5122
|
-
return /* @__PURE__ */ jsxs4(Text5, { color: isDone ? "dim" : "white", children: [
|
|
5123
|
-
/* @__PURE__ */ jsxs4(Text5, { color: isDone ? "green" : "dim", children: [
|
|
5124
|
-
getCheckbox(c.status || "pending"),
|
|
5125
|
-
" "
|
|
5126
|
-
] }),
|
|
5127
|
-
c.label || c.id || "item"
|
|
5128
|
-
] }, c.id || i);
|
|
5129
|
-
})
|
|
5130
|
-
] }),
|
|
5131
|
-
/* @__PURE__ */ jsx6(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" }) }),
|
|
5132
|
-
/* @__PURE__ */ jsxs4(Box5, { marginTop: 1, paddingX: 1, flexDirection: "column", children: [
|
|
5133
|
-
/* @__PURE__ */ jsx6(Text5, { bold: true, color: "white", children: "\u{1F916} AGENTS" }),
|
|
5134
|
-
/* @__PURE__ */ jsx6(Box5, { marginTop: 1, flexDirection: "column", children: !selectedTask.agents ? /* @__PURE__ */ jsx6(Text5, { color: "dim", children: "\u2014" }) : Object.entries(selectedTask.agents).map(([agent, info]) => /* @__PURE__ */ jsxs4(Text5, { children: [
|
|
5135
|
-
/* @__PURE__ */ jsxs4(Text5, { color: "dim", children: [
|
|
5136
|
-
"- ",
|
|
5137
|
-
agent,
|
|
5138
|
-
": "
|
|
5139
|
-
] }),
|
|
5140
|
-
info?.status === "complete" && /* @__PURE__ */ jsx6(Text5, { color: "green", children: "\u2713" }),
|
|
5141
|
-
info?.status === "in_progress" && /* @__PURE__ */ jsx6(Text5, { color: "yellow", children: "\u27F3" }),
|
|
5142
|
-
info?.status === "pending" && /* @__PURE__ */ jsx6(Text5, { color: "dim", children: "\u25CB" }),
|
|
5143
|
-
info?.blocked && /* @__PURE__ */ jsx6(Text5, { color: "red", children: "\u2715" }),
|
|
5144
|
-
/* @__PURE__ */ jsxs4(Text5, { color: info?.status === "complete" ? "dim" : "white", children: [
|
|
5145
|
-
" ",
|
|
5146
|
-
info?.status || "\u2014"
|
|
5147
|
-
] }),
|
|
5148
|
-
info?.artifact && /* @__PURE__ */ jsxs4(Text5, { dimColor: true, children: [
|
|
5149
|
-
" (",
|
|
5150
|
-
info.artifact,
|
|
5151
|
-
")"
|
|
5152
|
-
] })
|
|
5153
|
-
] }, agent)) })
|
|
5154
|
-
] })
|
|
5155
|
-
] }) })
|
|
5102
|
+
/* @__PURE__ */ jsx8(Box7, { flexDirection: "column", width: "45%", paddingLeft: 2, children: /* @__PURE__ */ jsx8(TaskDetails, { task: selectedTask }) })
|
|
5156
5103
|
] })
|
|
5157
5104
|
] });
|
|
5158
5105
|
};
|
|
@@ -5161,8 +5108,8 @@ var init_TasksView = __esm({
|
|
|
5161
5108
|
|
|
5162
5109
|
// src/mcp/ui/LogViewer.tsx
|
|
5163
5110
|
import "react";
|
|
5164
|
-
import { Box as
|
|
5165
|
-
import { jsx as
|
|
5111
|
+
import { Box as Box8, Text as Text8 } from "ink";
|
|
5112
|
+
import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
5166
5113
|
var LogViewer;
|
|
5167
5114
|
var init_LogViewer = __esm({
|
|
5168
5115
|
"src/mcp/ui/LogViewer.tsx"() {
|
|
@@ -5172,16 +5119,16 @@ var init_LogViewer = __esm({
|
|
|
5172
5119
|
const emptyLines = Math.max(0, height - visibleLogs.length);
|
|
5173
5120
|
const padding = Array(emptyLines).fill("");
|
|
5174
5121
|
const formatLog = (log) => {
|
|
5175
|
-
if (log.includes("[RAG]")) return /* @__PURE__ */
|
|
5176
|
-
if (log.includes("[ERROR]")) return /* @__PURE__ */
|
|
5177
|
-
if (log.includes("[WARN]")) return /* @__PURE__ */
|
|
5178
|
-
if (log.includes("[INFO]")) return /* @__PURE__ */
|
|
5179
|
-
if (log.includes("Success")) return /* @__PURE__ */
|
|
5180
|
-
return /* @__PURE__ */
|
|
5122
|
+
if (log.includes("[RAG]")) return /* @__PURE__ */ jsx9(Text8, { color: "cyan", children: log });
|
|
5123
|
+
if (log.includes("[ERROR]")) return /* @__PURE__ */ jsx9(Text8, { color: "red", children: log });
|
|
5124
|
+
if (log.includes("[WARN]")) return /* @__PURE__ */ jsx9(Text8, { color: "yellow", children: log });
|
|
5125
|
+
if (log.includes("[INFO]")) return /* @__PURE__ */ jsx9(Text8, { color: "green", children: log });
|
|
5126
|
+
if (log.includes("Success")) return /* @__PURE__ */ jsx9(Text8, { color: "green", children: log });
|
|
5127
|
+
return /* @__PURE__ */ jsx9(Text8, { children: log });
|
|
5181
5128
|
};
|
|
5182
|
-
return /* @__PURE__ */
|
|
5183
|
-
padding.map((_, i) => /* @__PURE__ */
|
|
5184
|
-
visibleLogs.map((log, i) => /* @__PURE__ */
|
|
5129
|
+
return /* @__PURE__ */ jsxs7(Box8, { flexDirection: "column", borderStyle: "round", borderColor: "white", paddingX: 1, height: height + 2, flexGrow: 1, children: [
|
|
5130
|
+
padding.map((_, i) => /* @__PURE__ */ jsx9(Text8, { children: " " }, `empty-${i}`)),
|
|
5131
|
+
visibleLogs.map((log, i) => /* @__PURE__ */ jsx9(Box8, { children: formatLog(log) }, `log-${i}`))
|
|
5185
5132
|
] });
|
|
5186
5133
|
};
|
|
5187
5134
|
}
|
|
@@ -5189,28 +5136,28 @@ var init_LogViewer = __esm({
|
|
|
5189
5136
|
|
|
5190
5137
|
// src/mcp/ui/StatusBoard.tsx
|
|
5191
5138
|
import "react";
|
|
5192
|
-
import { Box as
|
|
5193
|
-
import { jsx as
|
|
5139
|
+
import { Box as Box9, Text as Text9 } from "ink";
|
|
5140
|
+
import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
5194
5141
|
var StatusBoard;
|
|
5195
5142
|
var init_StatusBoard = __esm({
|
|
5196
5143
|
"src/mcp/ui/StatusBoard.tsx"() {
|
|
5197
5144
|
"use strict";
|
|
5198
5145
|
StatusBoard = ({ exposedLabel, port, pid, running, hasDrift }) => {
|
|
5199
|
-
return /* @__PURE__ */
|
|
5200
|
-
running ? /* @__PURE__ */
|
|
5146
|
+
return /* @__PURE__ */ jsx10(Box9, { borderStyle: "single", borderColor: "white", paddingX: 1, flexGrow: 1, children: /* @__PURE__ */ jsxs8(Text9, { children: [
|
|
5147
|
+
running ? /* @__PURE__ */ jsx10(Text9, { color: "green", children: "\u25CF RUNNING" }) : /* @__PURE__ */ jsx10(Text9, { color: "red", children: "\u25CF STOPPED" }),
|
|
5201
5148
|
" ",
|
|
5202
5149
|
"\u2502",
|
|
5203
5150
|
" \u{1F4CB} ",
|
|
5204
|
-
/* @__PURE__ */
|
|
5151
|
+
/* @__PURE__ */ jsx10(Text9, { color: "yellow", children: exposedLabel }),
|
|
5205
5152
|
" ",
|
|
5206
5153
|
"\u2502",
|
|
5207
5154
|
" Port: ",
|
|
5208
|
-
/* @__PURE__ */
|
|
5155
|
+
/* @__PURE__ */ jsx10(Text9, { color: "green", children: port }),
|
|
5209
5156
|
" ",
|
|
5210
5157
|
"\u2502",
|
|
5211
5158
|
" PID: ",
|
|
5212
|
-
/* @__PURE__ */
|
|
5213
|
-
hasDrift && /* @__PURE__ */
|
|
5159
|
+
/* @__PURE__ */ jsx10(Text9, { color: "green", children: pid }),
|
|
5160
|
+
hasDrift && /* @__PURE__ */ jsxs8(Text9, { color: "magenta", bold: true, children: [
|
|
5214
5161
|
" ",
|
|
5215
5162
|
"\u2502",
|
|
5216
5163
|
" \u2B06 UPDATE AVAILABLE"
|
|
@@ -5222,26 +5169,29 @@ var init_StatusBoard = __esm({
|
|
|
5222
5169
|
|
|
5223
5170
|
// src/mcp/ui/components/TabBar.tsx
|
|
5224
5171
|
import "react";
|
|
5225
|
-
import { Box as
|
|
5226
|
-
import { jsx as
|
|
5172
|
+
import { Box as Box10, Text as Text10, useInput as useInput4 } from "ink";
|
|
5173
|
+
import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
5227
5174
|
var TabBar;
|
|
5228
5175
|
var init_TabBar = __esm({
|
|
5229
5176
|
"src/mcp/ui/components/TabBar.tsx"() {
|
|
5230
5177
|
"use strict";
|
|
5231
5178
|
TabBar = ({ tabs, activeTab, onChange }) => {
|
|
5232
5179
|
useInput4((input, key) => {
|
|
5180
|
+
if (tabs.length === 0) return;
|
|
5233
5181
|
if (key.leftArrow) {
|
|
5234
5182
|
const index = tabs.findIndex((t) => t.id === activeTab);
|
|
5235
5183
|
if (index !== -1) {
|
|
5236
5184
|
const nextIndex = (index - 1 + tabs.length) % tabs.length;
|
|
5237
|
-
|
|
5185
|
+
const nextTab = tabs[nextIndex];
|
|
5186
|
+
if (nextTab) onChange(nextTab.id);
|
|
5238
5187
|
}
|
|
5239
5188
|
}
|
|
5240
5189
|
if (key.rightArrow) {
|
|
5241
5190
|
const index = tabs.findIndex((t) => t.id === activeTab);
|
|
5242
5191
|
if (index !== -1) {
|
|
5243
5192
|
const nextIndex = (index + 1) % tabs.length;
|
|
5244
|
-
|
|
5193
|
+
const nextTab = tabs[nextIndex];
|
|
5194
|
+
if (nextTab) onChange(nextTab.id);
|
|
5245
5195
|
}
|
|
5246
5196
|
}
|
|
5247
5197
|
const num = parseInt(input);
|
|
@@ -5250,11 +5200,11 @@ var init_TabBar = __esm({
|
|
|
5250
5200
|
if (tab) onChange(tab.id);
|
|
5251
5201
|
}
|
|
5252
5202
|
});
|
|
5253
|
-
return /* @__PURE__ */
|
|
5203
|
+
return /* @__PURE__ */ jsxs9(Box10, { borderStyle: "single", paddingX: 1, borderColor: "gray", children: [
|
|
5254
5204
|
tabs.map((tab, index) => {
|
|
5255
5205
|
const isActive = tab.id === activeTab;
|
|
5256
|
-
return /* @__PURE__ */
|
|
5257
|
-
|
|
5206
|
+
return /* @__PURE__ */ jsx11(Box10, { marginRight: 2, children: /* @__PURE__ */ jsx11(
|
|
5207
|
+
Text10,
|
|
5258
5208
|
{
|
|
5259
5209
|
color: isActive ? "cyan" : "white",
|
|
5260
5210
|
bold: isActive,
|
|
@@ -5263,8 +5213,8 @@ var init_TabBar = __esm({
|
|
|
5263
5213
|
}
|
|
5264
5214
|
) }, tab.id);
|
|
5265
5215
|
}),
|
|
5266
|
-
/* @__PURE__ */
|
|
5267
|
-
/* @__PURE__ */
|
|
5216
|
+
/* @__PURE__ */ jsx11(Box10, { flexGrow: 1 }),
|
|
5217
|
+
/* @__PURE__ */ jsx11(Text10, { color: "dim", children: "Use \u25C4/\u25BA arrows to navigate" })
|
|
5268
5218
|
] });
|
|
5269
5219
|
};
|
|
5270
5220
|
}
|
|
@@ -5276,9 +5226,9 @@ __export(App_exports, {
|
|
|
5276
5226
|
App: () => App
|
|
5277
5227
|
});
|
|
5278
5228
|
import { useState as useState5, useEffect as useEffect6, useMemo as useMemo5, useCallback as useCallback3 } from "react";
|
|
5279
|
-
import { Box as
|
|
5229
|
+
import { Box as Box11, useInput as useInput5, useApp } from "ink";
|
|
5280
5230
|
import fs20 from "fs";
|
|
5281
|
-
import { jsx as
|
|
5231
|
+
import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
5282
5232
|
var App;
|
|
5283
5233
|
var init_App = __esm({
|
|
5284
5234
|
"src/mcp/ui/App.tsx"() {
|
|
@@ -5398,10 +5348,10 @@ var init_App = __esm({
|
|
|
5398
5348
|
const handleConfigChange = useCallback3(() => {
|
|
5399
5349
|
refreshData();
|
|
5400
5350
|
}, [refreshData]);
|
|
5401
|
-
return /* @__PURE__ */
|
|
5402
|
-
/* @__PURE__ */
|
|
5403
|
-
/* @__PURE__ */
|
|
5404
|
-
activeTab === "overview" && /* @__PURE__ */
|
|
5351
|
+
return /* @__PURE__ */ jsxs10(Box11, { flexDirection: "column", padding: 0, height: termHeight, children: [
|
|
5352
|
+
/* @__PURE__ */ jsx12(TabBar, { tabs, activeTab, onChange: setActiveTab }),
|
|
5353
|
+
/* @__PURE__ */ jsxs10(Box11, { marginTop: 1, flexGrow: 1, children: [
|
|
5354
|
+
activeTab === "overview" && /* @__PURE__ */ jsx12(
|
|
5405
5355
|
Overview,
|
|
5406
5356
|
{
|
|
5407
5357
|
serverStatus: serverInfo,
|
|
@@ -5413,11 +5363,11 @@ var init_App = __esm({
|
|
|
5413
5363
|
logs
|
|
5414
5364
|
}
|
|
5415
5365
|
),
|
|
5416
|
-
activeTab === "logs" && /* @__PURE__ */
|
|
5417
|
-
activeTab === "tasks" && /* @__PURE__ */
|
|
5418
|
-
activeTab === "projects" && /* @__PURE__ */
|
|
5366
|
+
activeTab === "logs" && /* @__PURE__ */ jsx12(LogViewer, { logs, height: contentHeight }),
|
|
5367
|
+
activeTab === "tasks" && /* @__PURE__ */ jsx12(TasksView, { projects, workspacePath }),
|
|
5368
|
+
activeTab === "projects" && /* @__PURE__ */ jsx12(ProjectsView, { config, projects, onConfigChange: handleConfigChange, workspacePath })
|
|
5419
5369
|
] }),
|
|
5420
|
-
/* @__PURE__ */
|
|
5370
|
+
/* @__PURE__ */ jsx12(Box11, { marginTop: 0, children: /* @__PURE__ */ jsx12(
|
|
5421
5371
|
StatusBoard,
|
|
5422
5372
|
{
|
|
5423
5373
|
exposedLabel: `${exposedProjects.length} / ${projects.length} projects`,
|
|
@@ -5435,7 +5385,7 @@ var init_App = __esm({
|
|
|
5435
5385
|
// src/mcp/commands/start.ts
|
|
5436
5386
|
import { confirm as confirm3, isCancel as isCancel5, text } from "@clack/prompts";
|
|
5437
5387
|
async function handleStartServer() {
|
|
5438
|
-
const
|
|
5388
|
+
const React13 = await import("react");
|
|
5439
5389
|
const { render } = await import("ink");
|
|
5440
5390
|
const { App: App2 } = await Promise.resolve().then(() => (init_App(), App_exports));
|
|
5441
5391
|
const { ConfigProvider: ConfigProvider2 } = await Promise.resolve().then(() => (init_ConfigContext(), ConfigContext_exports));
|
|
@@ -5478,10 +5428,10 @@ async function handleStartServer() {
|
|
|
5478
5428
|
}
|
|
5479
5429
|
process.stdin.resume();
|
|
5480
5430
|
const app = render(
|
|
5481
|
-
|
|
5431
|
+
React13.createElement(
|
|
5482
5432
|
ConfigProvider2,
|
|
5483
5433
|
null,
|
|
5484
|
-
|
|
5434
|
+
React13.createElement(App2, {
|
|
5485
5435
|
initialPort,
|
|
5486
5436
|
onExit: () => {
|
|
5487
5437
|
}
|