opendevbrowser 0.0.21 → 0.0.22
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 -2
- package/dist/chunk-3ILXPKSJ.js +86 -0
- package/dist/chunk-3ILXPKSJ.js.map +1 -0
- package/dist/{chunk-4KVXCXV3.js → chunk-OGE5KJ4X.js} +10 -6
- package/dist/{chunk-4KVXCXV3.js.map → chunk-OGE5KJ4X.js.map} +1 -1
- package/dist/chunk-QVWOPIZJ.js +612 -0
- package/dist/chunk-QVWOPIZJ.js.map +1 -0
- package/dist/{chunk-3VA6XR25.js → chunk-STGGGVYT.js} +23 -100
- package/dist/chunk-STGGGVYT.js.map +1 -0
- package/dist/cli/commands/uninstall.d.ts +1 -0
- package/dist/cli/commands/uninstall.d.ts.map +1 -1
- package/dist/cli/index.js +249 -614
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/installers/postinstall-skill-sync.d.ts +15 -0
- package/dist/cli/installers/postinstall-skill-sync.d.ts.map +1 -0
- package/dist/cli/installers/postinstall-skill-sync.js +48 -0
- package/dist/cli/installers/postinstall-skill-sync.js.map +1 -0
- package/dist/cli/installers/skills.d.ts +9 -14
- package/dist/cli/installers/skills.d.ts.map +1 -1
- package/dist/cli/skill-lifecycle.d.ts +26 -0
- package/dist/cli/skill-lifecycle.d.ts.map +1 -0
- package/dist/cli/update-skill-modes.d.ts +3 -0
- package/dist/cli/update-skill-modes.d.ts.map +1 -0
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/opendevbrowser.js +3 -2
- package/dist/opendevbrowser.js.map +1 -1
- package/dist/public-surface/generated-manifest.d.ts +3 -3
- package/dist/public-surface/generated-manifest.d.ts.map +1 -1
- package/dist/public-surface/source.d.ts +4 -4
- package/dist/skills/skill-loader.js +2 -1
- package/extension/manifest.json +1 -1
- package/package.json +6 -4
- package/scripts/postinstall-sync-skills.mjs +33 -0
- package/dist/chunk-3VA6XR25.js.map +0 -1
package/dist/cli/index.js
CHANGED
|
@@ -31,11 +31,26 @@ import {
|
|
|
31
31
|
resolveExitCode,
|
|
32
32
|
startDaemon,
|
|
33
33
|
toCliError
|
|
34
|
-
} from "../chunk-
|
|
34
|
+
} from "../chunk-OGE5KJ4X.js";
|
|
35
|
+
import "../chunk-STGGGVYT.js";
|
|
35
36
|
import {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
createNoOpSkillRemovalResult,
|
|
38
|
+
ensureDir,
|
|
39
|
+
getBundledSkillLifecycleTargets,
|
|
40
|
+
getBundledSkillTargets,
|
|
41
|
+
getGlobalConfigPath,
|
|
42
|
+
getLocalConfigPath,
|
|
43
|
+
hasBundledSkillArtifacts,
|
|
44
|
+
hasManagedBundledSkillInstall,
|
|
45
|
+
hasPlugin,
|
|
46
|
+
readConfig,
|
|
47
|
+
removeBundledSkillsForTargets,
|
|
48
|
+
removePluginFromContent,
|
|
49
|
+
syncBundledSkills,
|
|
50
|
+
syncBundledSkillsForTargets,
|
|
51
|
+
updateConfigContent
|
|
52
|
+
} from "../chunk-QVWOPIZJ.js";
|
|
53
|
+
import "../chunk-3ILXPKSJ.js";
|
|
39
54
|
import {
|
|
40
55
|
writeFileAtomic
|
|
41
56
|
} from "../chunk-TBUCZX4A.js";
|
|
@@ -706,86 +721,12 @@ function getCommand(name) {
|
|
|
706
721
|
}
|
|
707
722
|
|
|
708
723
|
// src/cli/installers/global.ts
|
|
709
|
-
import * as
|
|
724
|
+
import * as fs2 from "fs";
|
|
710
725
|
|
|
711
|
-
// src/cli/
|
|
726
|
+
// src/cli/templates/config.ts
|
|
712
727
|
import * as fs from "fs";
|
|
713
728
|
import * as path from "path";
|
|
714
729
|
import * as os from "os";
|
|
715
|
-
import { parse as parseJsonc, modify, applyEdits } from "jsonc-parser";
|
|
716
|
-
var PLUGIN_NAME = "opendevbrowser";
|
|
717
|
-
var SCHEMA_URL = "https://opencode.ai/config.json";
|
|
718
|
-
function getGlobalConfigPath() {
|
|
719
|
-
const configDir = process.env.OPENCODE_CONFIG_DIR || path.join(os.homedir(), ".config", "opencode");
|
|
720
|
-
return path.join(configDir, "opencode.json");
|
|
721
|
-
}
|
|
722
|
-
function getLocalConfigPath() {
|
|
723
|
-
return path.join(process.cwd(), "opencode.json");
|
|
724
|
-
}
|
|
725
|
-
function ensureDir(dirPath) {
|
|
726
|
-
if (!fs.existsSync(dirPath)) {
|
|
727
|
-
fs.mkdirSync(dirPath, { recursive: true });
|
|
728
|
-
}
|
|
729
|
-
}
|
|
730
|
-
function readConfig(configPath) {
|
|
731
|
-
if (!fs.existsSync(configPath)) {
|
|
732
|
-
return { content: "", config: {} };
|
|
733
|
-
}
|
|
734
|
-
const content = fs.readFileSync(configPath, "utf-8");
|
|
735
|
-
const errors = [];
|
|
736
|
-
const parsed = parseJsonc(content, errors, { allowTrailingComma: true });
|
|
737
|
-
if (errors.length > 0) {
|
|
738
|
-
const firstError = errors[0];
|
|
739
|
-
throw new Error(`Invalid JSONC at ${configPath}: parse error at offset ${firstError?.offset ?? 0}`);
|
|
740
|
-
}
|
|
741
|
-
return { content, config: parsed ?? {} };
|
|
742
|
-
}
|
|
743
|
-
function hasPlugin(config, pluginName = PLUGIN_NAME) {
|
|
744
|
-
return config.plugin?.includes(pluginName) ?? false;
|
|
745
|
-
}
|
|
746
|
-
function createConfigWithPlugin(pluginName = PLUGIN_NAME) {
|
|
747
|
-
return {
|
|
748
|
-
$schema: SCHEMA_URL,
|
|
749
|
-
plugin: [pluginName]
|
|
750
|
-
};
|
|
751
|
-
}
|
|
752
|
-
function updateConfigContent(content, pluginName = PLUGIN_NAME) {
|
|
753
|
-
if (!content.trim()) {
|
|
754
|
-
return JSON.stringify(createConfigWithPlugin(pluginName), null, 2) + "\n";
|
|
755
|
-
}
|
|
756
|
-
const parsed = parseJsonc(content, [], { allowTrailingComma: true }) ?? {};
|
|
757
|
-
if (parsed.plugin?.includes(pluginName)) {
|
|
758
|
-
return content;
|
|
759
|
-
}
|
|
760
|
-
let result = content;
|
|
761
|
-
if (!parsed.$schema) {
|
|
762
|
-
const edits2 = modify(result, ["$schema"], SCHEMA_URL, { formattingOptions: { tabSize: 2, insertSpaces: true } });
|
|
763
|
-
result = applyEdits(result, edits2);
|
|
764
|
-
}
|
|
765
|
-
const newPlugins = parsed.plugin ? [...parsed.plugin, pluginName] : [pluginName];
|
|
766
|
-
const edits = modify(result, ["plugin"], newPlugins, { formattingOptions: { tabSize: 2, insertSpaces: true } });
|
|
767
|
-
result = applyEdits(result, edits);
|
|
768
|
-
return result;
|
|
769
|
-
}
|
|
770
|
-
function removePluginFromContent(content, pluginName = PLUGIN_NAME) {
|
|
771
|
-
if (!content.trim()) {
|
|
772
|
-
return content;
|
|
773
|
-
}
|
|
774
|
-
const parsed = parseJsonc(content, [], { allowTrailingComma: true }) ?? {};
|
|
775
|
-
if (!parsed.plugin?.includes(pluginName)) {
|
|
776
|
-
return content;
|
|
777
|
-
}
|
|
778
|
-
const newPlugins = parsed.plugin.filter((p) => p !== pluginName);
|
|
779
|
-
const edits = modify(content, ["plugin"], newPlugins.length > 0 ? newPlugins : void 0, {
|
|
780
|
-
formattingOptions: { tabSize: 2, insertSpaces: true }
|
|
781
|
-
});
|
|
782
|
-
return applyEdits(content, edits);
|
|
783
|
-
}
|
|
784
|
-
|
|
785
|
-
// src/cli/templates/config.ts
|
|
786
|
-
import * as fs2 from "fs";
|
|
787
|
-
import * as path2 from "path";
|
|
788
|
-
import * as os2 from "os";
|
|
789
730
|
function buildConfigTemplate(relayToken, daemonToken) {
|
|
790
731
|
return `{
|
|
791
732
|
// OpenDevBrowser Plugin Configuration
|
|
@@ -862,19 +803,19 @@ function buildConfigTemplate(relayToken, daemonToken) {
|
|
|
862
803
|
}
|
|
863
804
|
function getPluginConfigPath(mode) {
|
|
864
805
|
if (mode === "global") {
|
|
865
|
-
const configDir = process.env.OPENCODE_CONFIG_DIR ||
|
|
866
|
-
return
|
|
806
|
+
const configDir = process.env.OPENCODE_CONFIG_DIR || path.join(os.homedir(), ".config", "opencode");
|
|
807
|
+
return path.join(configDir, "opendevbrowser.jsonc");
|
|
867
808
|
}
|
|
868
|
-
return
|
|
809
|
+
return path.join(process.cwd(), "opendevbrowser.jsonc");
|
|
869
810
|
}
|
|
870
811
|
function createPluginConfig(mode) {
|
|
871
812
|
const configPath = getPluginConfigPath(mode);
|
|
872
|
-
if (
|
|
813
|
+
if (fs.existsSync(configPath)) {
|
|
873
814
|
return { created: false, path: configPath };
|
|
874
815
|
}
|
|
875
|
-
const dir =
|
|
876
|
-
if (!
|
|
877
|
-
|
|
816
|
+
const dir = path.dirname(configPath);
|
|
817
|
+
if (!fs.existsSync(dir)) {
|
|
818
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
878
819
|
}
|
|
879
820
|
const relayToken = generateSecureToken();
|
|
880
821
|
const daemonToken = generateSecureToken();
|
|
@@ -898,7 +839,7 @@ function installGlobal(withConfig = false) {
|
|
|
898
839
|
}
|
|
899
840
|
const newContent = updateConfigContent(content, "opendevbrowser");
|
|
900
841
|
ensureDir(configPath.replace(/[/\\][^/\\]+$/, ""));
|
|
901
|
-
|
|
842
|
+
fs2.writeFileSync(configPath, newContent, "utf-8");
|
|
902
843
|
if (withConfig) {
|
|
903
844
|
createPluginConfig("global");
|
|
904
845
|
}
|
|
@@ -922,7 +863,7 @@ function installGlobal(withConfig = false) {
|
|
|
922
863
|
}
|
|
923
864
|
|
|
924
865
|
// src/cli/installers/local.ts
|
|
925
|
-
import * as
|
|
866
|
+
import * as fs3 from "fs";
|
|
926
867
|
function installLocal(withConfig = false) {
|
|
927
868
|
const configPath = getLocalConfigPath();
|
|
928
869
|
try {
|
|
@@ -937,7 +878,7 @@ function installLocal(withConfig = false) {
|
|
|
937
878
|
};
|
|
938
879
|
}
|
|
939
880
|
const newContent = updateConfigContent(content, "opendevbrowser");
|
|
940
|
-
|
|
881
|
+
fs3.writeFileSync(configPath, newContent, "utf-8");
|
|
941
882
|
if (withConfig) {
|
|
942
883
|
createPluginConfig("local");
|
|
943
884
|
}
|
|
@@ -960,407 +901,32 @@ function installLocal(withConfig = false) {
|
|
|
960
901
|
}
|
|
961
902
|
}
|
|
962
903
|
|
|
963
|
-
// src/cli/installers/skills.ts
|
|
964
|
-
import * as crypto from "crypto";
|
|
965
|
-
import * as fs5 from "fs";
|
|
966
|
-
import * as path4 from "path";
|
|
967
|
-
|
|
968
|
-
// src/cli/utils/skills.ts
|
|
969
|
-
import * as path3 from "path";
|
|
970
|
-
import * as os3 from "os";
|
|
971
|
-
var SKILL_DIR_NAME = "skill";
|
|
972
|
-
var SKILLS_DIR_NAME = "skills";
|
|
973
|
-
function getGlobalSkillDir() {
|
|
974
|
-
const configDir = process.env.OPENCODE_CONFIG_DIR || path3.join(os3.homedir(), ".config", "opencode");
|
|
975
|
-
return path3.join(configDir, SKILL_DIR_NAME);
|
|
976
|
-
}
|
|
977
|
-
function getLocalSkillDir() {
|
|
978
|
-
return path3.join(process.cwd(), ".opencode", SKILL_DIR_NAME);
|
|
979
|
-
}
|
|
980
|
-
function getCodexHomeDir() {
|
|
981
|
-
return process.env.CODEX_HOME || path3.join(os3.homedir(), ".codex");
|
|
982
|
-
}
|
|
983
|
-
function getClaudeCodeHomeDir() {
|
|
984
|
-
return process.env.CLAUDECODE_HOME || path3.join(os3.homedir(), ".claude");
|
|
985
|
-
}
|
|
986
|
-
function getAmpHomeDir() {
|
|
987
|
-
return process.env.AMP_CLI_HOME || path3.join(os3.homedir(), ".amp");
|
|
988
|
-
}
|
|
989
|
-
function dedupeTargets(targets) {
|
|
990
|
-
const deduped = /* @__PURE__ */ new Map();
|
|
991
|
-
for (const target of targets) {
|
|
992
|
-
const key = path3.resolve(target.dir);
|
|
993
|
-
const existing = deduped.get(key);
|
|
994
|
-
if (existing) {
|
|
995
|
-
if (!existing.agents.includes(target.agent)) {
|
|
996
|
-
existing.agents.push(target.agent);
|
|
997
|
-
}
|
|
998
|
-
continue;
|
|
999
|
-
}
|
|
1000
|
-
deduped.set(key, { agents: [target.agent], dir: target.dir });
|
|
1001
|
-
}
|
|
1002
|
-
return Array.from(deduped.values());
|
|
1003
|
-
}
|
|
1004
|
-
function getGlobalSkillTargets() {
|
|
1005
|
-
const claudeSkillsDir = path3.join(getClaudeCodeHomeDir(), SKILLS_DIR_NAME);
|
|
1006
|
-
const ampSkillsDir = path3.join(getAmpHomeDir(), SKILLS_DIR_NAME);
|
|
1007
|
-
return dedupeTargets([
|
|
1008
|
-
{ agent: "opencode", dir: getGlobalSkillDir() },
|
|
1009
|
-
{ agent: "codex", dir: path3.join(getCodexHomeDir(), SKILLS_DIR_NAME) },
|
|
1010
|
-
{ agent: "claudecode", dir: claudeSkillsDir },
|
|
1011
|
-
{ agent: "ampcli", dir: ampSkillsDir }
|
|
1012
|
-
]);
|
|
1013
|
-
}
|
|
1014
|
-
function getLocalSkillTargets() {
|
|
1015
|
-
const localClaudeSkillsDir = path3.join(process.cwd(), ".claude", SKILLS_DIR_NAME);
|
|
1016
|
-
const localAmpSkillsDir = path3.join(process.cwd(), ".amp", SKILLS_DIR_NAME);
|
|
1017
|
-
return dedupeTargets([
|
|
1018
|
-
{ agent: "opencode", dir: getLocalSkillDir() },
|
|
1019
|
-
{ agent: "codex", dir: path3.join(process.cwd(), ".codex", SKILLS_DIR_NAME) },
|
|
1020
|
-
{ agent: "claudecode", dir: localClaudeSkillsDir },
|
|
1021
|
-
{ agent: "ampcli", dir: localAmpSkillsDir }
|
|
1022
|
-
]);
|
|
1023
|
-
}
|
|
1024
|
-
|
|
1025
|
-
// src/cli/installers/skills.ts
|
|
1026
|
-
var LEGACY_ALIAS_DIRS = [
|
|
1027
|
-
{ name: "research", canonical: "opendevbrowser-research" },
|
|
1028
|
-
{ name: "shopping", canonical: "opendevbrowser-shopping" }
|
|
1029
|
-
];
|
|
1030
|
-
function getTargets(mode) {
|
|
1031
|
-
return mode === "global" ? getGlobalSkillTargets() : getLocalSkillTargets();
|
|
1032
|
-
}
|
|
1033
|
-
function getCanonicalBundledSkillNames() {
|
|
1034
|
-
return listBundledSkillDirectories().map((entry) => entry.name);
|
|
1035
|
-
}
|
|
1036
|
-
function hasCanonicalBundledSkillInTarget(targetDir, packNames) {
|
|
1037
|
-
return packNames.some((packName) => fs5.existsSync(path4.join(targetDir, packName)));
|
|
1038
|
-
}
|
|
1039
|
-
function formatSummary(parts, totalTargets, failures) {
|
|
1040
|
-
const summary = parts.length > 0 ? parts.join(", ") : "no lifecycle changes";
|
|
1041
|
-
const failureSummary = failures > 0 ? `, ${failures} failed` : "";
|
|
1042
|
-
return `${summary} across ${totalTargets} targets${failureSummary}`;
|
|
1043
|
-
}
|
|
1044
|
-
function hashDirectoryTree(dirPath) {
|
|
1045
|
-
const hash = crypto.createHash("sha256");
|
|
1046
|
-
const visit = (currentPath, relativePath) => {
|
|
1047
|
-
const entries = fs5.readdirSync(currentPath, { withFileTypes: true }).sort((left, right) => left.name.localeCompare(right.name));
|
|
1048
|
-
for (const entry of entries) {
|
|
1049
|
-
const absolutePath = path4.join(currentPath, entry.name);
|
|
1050
|
-
const entryRelativePath = relativePath ? path4.posix.join(relativePath, entry.name) : entry.name;
|
|
1051
|
-
if (entry.isDirectory()) {
|
|
1052
|
-
hash.update(`D:${entryRelativePath}\0`);
|
|
1053
|
-
visit(absolutePath, entryRelativePath);
|
|
1054
|
-
continue;
|
|
1055
|
-
}
|
|
1056
|
-
if (entry.isFile()) {
|
|
1057
|
-
hash.update(`F:${entryRelativePath}\0`);
|
|
1058
|
-
hash.update(fs5.readFileSync(absolutePath));
|
|
1059
|
-
hash.update("\0");
|
|
1060
|
-
continue;
|
|
1061
|
-
}
|
|
1062
|
-
if (entry.isSymbolicLink()) {
|
|
1063
|
-
hash.update(`L:${entryRelativePath}\0${fs5.readlinkSync(absolutePath)}\0`);
|
|
1064
|
-
}
|
|
1065
|
-
}
|
|
1066
|
-
};
|
|
1067
|
-
visit(dirPath, "");
|
|
1068
|
-
return hash.digest("hex");
|
|
1069
|
-
}
|
|
1070
|
-
function syncSkillDirectory(sourcePath, targetPath, sourceFingerprint) {
|
|
1071
|
-
if (!fs5.existsSync(targetPath)) {
|
|
1072
|
-
fs5.cpSync(sourcePath, targetPath, { recursive: true });
|
|
1073
|
-
return "installed";
|
|
1074
|
-
}
|
|
1075
|
-
const targetFingerprint = hashDirectoryTree(targetPath);
|
|
1076
|
-
if (targetFingerprint === sourceFingerprint) {
|
|
1077
|
-
return "unchanged";
|
|
1078
|
-
}
|
|
1079
|
-
const parentDir = path4.dirname(targetPath);
|
|
1080
|
-
const targetName = path4.basename(targetPath);
|
|
1081
|
-
const stagingRoot = fs5.mkdtempSync(path4.join(parentDir, `.${targetName}-sync-`));
|
|
1082
|
-
const stagedPath = path4.join(stagingRoot, targetName);
|
|
1083
|
-
const backupPath = path4.join(stagingRoot, `${targetName}-backup`);
|
|
1084
|
-
try {
|
|
1085
|
-
fs5.cpSync(sourcePath, stagedPath, { recursive: true });
|
|
1086
|
-
fs5.renameSync(targetPath, backupPath);
|
|
1087
|
-
try {
|
|
1088
|
-
fs5.renameSync(stagedPath, targetPath);
|
|
1089
|
-
} catch (error) {
|
|
1090
|
-
if (fs5.existsSync(backupPath) && !fs5.existsSync(targetPath)) {
|
|
1091
|
-
fs5.renameSync(backupPath, targetPath);
|
|
1092
|
-
}
|
|
1093
|
-
throw error;
|
|
1094
|
-
}
|
|
1095
|
-
fs5.rmSync(backupPath, { recursive: true, force: true });
|
|
1096
|
-
return "refreshed";
|
|
1097
|
-
} finally {
|
|
1098
|
-
if (fs5.existsSync(stagedPath)) {
|
|
1099
|
-
fs5.rmSync(stagedPath, { recursive: true, force: true });
|
|
1100
|
-
}
|
|
1101
|
-
if (fs5.existsSync(backupPath)) {
|
|
1102
|
-
fs5.rmSync(backupPath, { recursive: true, force: true });
|
|
1103
|
-
}
|
|
1104
|
-
fs5.rmSync(stagingRoot, { recursive: true, force: true });
|
|
1105
|
-
}
|
|
1106
|
-
}
|
|
1107
|
-
function cleanupLegacyAlias(targetDir, aliasName) {
|
|
1108
|
-
const aliasPath = path4.join(targetDir, aliasName);
|
|
1109
|
-
if (!fs5.existsSync(aliasPath)) {
|
|
1110
|
-
return { removed: [], preserved: [] };
|
|
1111
|
-
}
|
|
1112
|
-
let stats;
|
|
1113
|
-
try {
|
|
1114
|
-
stats = fs5.statSync(aliasPath);
|
|
1115
|
-
} catch {
|
|
1116
|
-
return {
|
|
1117
|
-
removed: [],
|
|
1118
|
-
preserved: [{ targetDir, name: aliasName, reason: "unknown_layout" }]
|
|
1119
|
-
};
|
|
1120
|
-
}
|
|
1121
|
-
if (!stats.isDirectory()) {
|
|
1122
|
-
return {
|
|
1123
|
-
removed: [],
|
|
1124
|
-
preserved: [{ targetDir, name: aliasName, reason: "unknown_layout" }]
|
|
1125
|
-
};
|
|
1126
|
-
}
|
|
1127
|
-
if (fs5.existsSync(path4.join(aliasPath, "SKILL.md"))) {
|
|
1128
|
-
return {
|
|
1129
|
-
removed: [],
|
|
1130
|
-
preserved: [{ targetDir, name: aliasName, reason: "contains_skill_md" }]
|
|
1131
|
-
};
|
|
1132
|
-
}
|
|
1133
|
-
const entries = fs5.readdirSync(aliasPath);
|
|
1134
|
-
if (entries.length === 0) {
|
|
1135
|
-
fs5.rmSync(aliasPath, { recursive: true, force: true });
|
|
1136
|
-
return { removed: [aliasName], preserved: [] };
|
|
1137
|
-
}
|
|
1138
|
-
return {
|
|
1139
|
-
removed: [],
|
|
1140
|
-
preserved: [{ targetDir, name: aliasName, reason: "non_empty" }]
|
|
1141
|
-
};
|
|
1142
|
-
}
|
|
1143
|
-
function cleanupLegacyAliases(targetDir) {
|
|
1144
|
-
const removed = [];
|
|
1145
|
-
const preserved = [];
|
|
1146
|
-
for (const alias of LEGACY_ALIAS_DIRS) {
|
|
1147
|
-
const result = cleanupLegacyAlias(targetDir, alias.name);
|
|
1148
|
-
removed.push(...result.removed);
|
|
1149
|
-
preserved.push(...result.preserved);
|
|
1150
|
-
}
|
|
1151
|
-
return { removed, preserved };
|
|
1152
|
-
}
|
|
1153
|
-
function buildSyncMessage(mode, result) {
|
|
1154
|
-
return `Skills ${mode} sync: ${formatSummary(
|
|
1155
|
-
[
|
|
1156
|
-
result.installed.length > 0 ? `${result.installed.length} installed` : "",
|
|
1157
|
-
result.refreshed.length > 0 ? `${result.refreshed.length} refreshed` : "",
|
|
1158
|
-
result.unchanged.length > 0 ? `${result.unchanged.length} unchanged` : "",
|
|
1159
|
-
result.removedLegacyAliases.length > 0 ? `${result.removedLegacyAliases.length} legacy aliases removed` : "",
|
|
1160
|
-
result.preservedLegacyAliases.length > 0 ? `${result.preservedLegacyAliases.length} legacy aliases preserved` : ""
|
|
1161
|
-
].filter(Boolean),
|
|
1162
|
-
result.targets.length,
|
|
1163
|
-
result.targets.filter((entry) => !entry.success).length
|
|
1164
|
-
)}`;
|
|
1165
|
-
}
|
|
1166
|
-
function buildRemovalMessage(mode, result) {
|
|
1167
|
-
return `Skills ${mode} removal: ${formatSummary(
|
|
1168
|
-
[
|
|
1169
|
-
result.removed.length > 0 ? `${result.removed.length} removed` : "",
|
|
1170
|
-
result.missing.length > 0 ? `${result.missing.length} already absent` : "",
|
|
1171
|
-
result.removedLegacyAliases.length > 0 ? `${result.removedLegacyAliases.length} legacy aliases removed` : "",
|
|
1172
|
-
result.preservedLegacyAliases.length > 0 ? `${result.preservedLegacyAliases.length} legacy aliases preserved` : ""
|
|
1173
|
-
].filter(Boolean),
|
|
1174
|
-
result.targets.length,
|
|
1175
|
-
result.targets.filter((entry) => !entry.success).length
|
|
1176
|
-
)}`;
|
|
1177
|
-
}
|
|
1178
|
-
function syncBundledSkills(mode) {
|
|
1179
|
-
const targets = getTargets(mode);
|
|
1180
|
-
const targetResults = [];
|
|
1181
|
-
try {
|
|
1182
|
-
const sourceDir = getBundledSkillsDir();
|
|
1183
|
-
const packNames = getCanonicalBundledSkillNames();
|
|
1184
|
-
const bundledFingerprints = /* @__PURE__ */ new Map();
|
|
1185
|
-
for (const packName of packNames) {
|
|
1186
|
-
const sourcePath = path4.join(sourceDir, packName);
|
|
1187
|
-
if (!fs5.existsSync(sourcePath)) {
|
|
1188
|
-
throw new Error(`Bundled skill directory missing: ${packName}`);
|
|
1189
|
-
}
|
|
1190
|
-
bundledFingerprints.set(packName, hashDirectoryTree(sourcePath));
|
|
1191
|
-
}
|
|
1192
|
-
for (const target of targets) {
|
|
1193
|
-
const installed = [];
|
|
1194
|
-
const refreshed = [];
|
|
1195
|
-
const unchanged = [];
|
|
1196
|
-
const removedLegacyAliases = [];
|
|
1197
|
-
const preservedLegacyAliases = [];
|
|
1198
|
-
try {
|
|
1199
|
-
ensureDir(target.dir);
|
|
1200
|
-
for (const packName of packNames) {
|
|
1201
|
-
const sourcePath = path4.join(sourceDir, packName);
|
|
1202
|
-
const targetPath = path4.join(target.dir, packName);
|
|
1203
|
-
const sourceFingerprint = bundledFingerprints.get(packName);
|
|
1204
|
-
if (!sourceFingerprint) {
|
|
1205
|
-
throw new Error(`Bundled fingerprint missing: ${packName}`);
|
|
1206
|
-
}
|
|
1207
|
-
const outcome = syncSkillDirectory(sourcePath, targetPath, sourceFingerprint);
|
|
1208
|
-
if (outcome === "installed") {
|
|
1209
|
-
installed.push(packName);
|
|
1210
|
-
} else if (outcome === "refreshed") {
|
|
1211
|
-
refreshed.push(packName);
|
|
1212
|
-
} else {
|
|
1213
|
-
unchanged.push(packName);
|
|
1214
|
-
}
|
|
1215
|
-
}
|
|
1216
|
-
const legacyCleanup = cleanupLegacyAliases(target.dir);
|
|
1217
|
-
removedLegacyAliases.push(...legacyCleanup.removed);
|
|
1218
|
-
preservedLegacyAliases.push(...legacyCleanup.preserved);
|
|
1219
|
-
targetResults.push({
|
|
1220
|
-
agents: target.agents,
|
|
1221
|
-
targetDir: target.dir,
|
|
1222
|
-
installed,
|
|
1223
|
-
refreshed,
|
|
1224
|
-
unchanged,
|
|
1225
|
-
removedLegacyAliases,
|
|
1226
|
-
preservedLegacyAliases,
|
|
1227
|
-
success: true
|
|
1228
|
-
});
|
|
1229
|
-
} catch (error) {
|
|
1230
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
1231
|
-
targetResults.push({
|
|
1232
|
-
agents: target.agents,
|
|
1233
|
-
targetDir: target.dir,
|
|
1234
|
-
installed,
|
|
1235
|
-
refreshed,
|
|
1236
|
-
unchanged,
|
|
1237
|
-
removedLegacyAliases,
|
|
1238
|
-
preservedLegacyAliases,
|
|
1239
|
-
success: false,
|
|
1240
|
-
error: message
|
|
1241
|
-
});
|
|
1242
|
-
}
|
|
1243
|
-
}
|
|
1244
|
-
const result = {
|
|
1245
|
-
success: targetResults.every((entry) => entry.success),
|
|
1246
|
-
message: "",
|
|
1247
|
-
mode,
|
|
1248
|
-
targets: targetResults,
|
|
1249
|
-
installed: targetResults.flatMap((entry) => entry.installed),
|
|
1250
|
-
refreshed: targetResults.flatMap((entry) => entry.refreshed),
|
|
1251
|
-
unchanged: targetResults.flatMap((entry) => entry.unchanged),
|
|
1252
|
-
removedLegacyAliases: targetResults.flatMap((entry) => entry.removedLegacyAliases),
|
|
1253
|
-
preservedLegacyAliases: targetResults.flatMap((entry) => entry.preservedLegacyAliases)
|
|
1254
|
-
};
|
|
1255
|
-
result.message = buildSyncMessage(mode, result);
|
|
1256
|
-
return result;
|
|
1257
|
-
} catch (error) {
|
|
1258
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
1259
|
-
const result = {
|
|
1260
|
-
success: false,
|
|
1261
|
-
message: "",
|
|
1262
|
-
mode,
|
|
1263
|
-
targets: targetResults,
|
|
1264
|
-
installed: targetResults.flatMap((entry) => entry.installed),
|
|
1265
|
-
refreshed: targetResults.flatMap((entry) => entry.refreshed),
|
|
1266
|
-
unchanged: targetResults.flatMap((entry) => entry.unchanged),
|
|
1267
|
-
removedLegacyAliases: targetResults.flatMap((entry) => entry.removedLegacyAliases),
|
|
1268
|
-
preservedLegacyAliases: targetResults.flatMap((entry) => entry.preservedLegacyAliases)
|
|
1269
|
-
};
|
|
1270
|
-
result.message = `Failed to sync skills (${mode}): ${message}`;
|
|
1271
|
-
return result;
|
|
1272
|
-
}
|
|
1273
|
-
}
|
|
1274
|
-
function removeBundledSkills(mode) {
|
|
1275
|
-
const targets = getTargets(mode);
|
|
1276
|
-
const packNames = getCanonicalBundledSkillNames();
|
|
1277
|
-
const targetResults = [];
|
|
1278
|
-
for (const target of targets) {
|
|
1279
|
-
const removed = [];
|
|
1280
|
-
const missing = [];
|
|
1281
|
-
const removedLegacyAliases = [];
|
|
1282
|
-
const preservedLegacyAliases = [];
|
|
1283
|
-
try {
|
|
1284
|
-
for (const packName of packNames) {
|
|
1285
|
-
const targetPath = path4.join(target.dir, packName);
|
|
1286
|
-
if (fs5.existsSync(targetPath)) {
|
|
1287
|
-
fs5.rmSync(targetPath, { recursive: true, force: true });
|
|
1288
|
-
removed.push(packName);
|
|
1289
|
-
} else {
|
|
1290
|
-
missing.push(packName);
|
|
1291
|
-
}
|
|
1292
|
-
}
|
|
1293
|
-
const legacyCleanup = cleanupLegacyAliases(target.dir);
|
|
1294
|
-
removedLegacyAliases.push(...legacyCleanup.removed);
|
|
1295
|
-
preservedLegacyAliases.push(...legacyCleanup.preserved);
|
|
1296
|
-
targetResults.push({
|
|
1297
|
-
agents: target.agents,
|
|
1298
|
-
targetDir: target.dir,
|
|
1299
|
-
removed,
|
|
1300
|
-
missing,
|
|
1301
|
-
removedLegacyAliases,
|
|
1302
|
-
preservedLegacyAliases,
|
|
1303
|
-
success: true
|
|
1304
|
-
});
|
|
1305
|
-
} catch (error) {
|
|
1306
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
1307
|
-
targetResults.push({
|
|
1308
|
-
agents: target.agents,
|
|
1309
|
-
targetDir: target.dir,
|
|
1310
|
-
removed,
|
|
1311
|
-
missing,
|
|
1312
|
-
removedLegacyAliases,
|
|
1313
|
-
preservedLegacyAliases,
|
|
1314
|
-
success: false,
|
|
1315
|
-
error: message
|
|
1316
|
-
});
|
|
1317
|
-
}
|
|
1318
|
-
}
|
|
1319
|
-
const result = {
|
|
1320
|
-
success: targetResults.every((entry) => entry.success),
|
|
1321
|
-
message: "",
|
|
1322
|
-
mode,
|
|
1323
|
-
targets: targetResults,
|
|
1324
|
-
removed: targetResults.flatMap((entry) => entry.removed),
|
|
1325
|
-
missing: targetResults.flatMap((entry) => entry.missing),
|
|
1326
|
-
removedLegacyAliases: targetResults.flatMap((entry) => entry.removedLegacyAliases),
|
|
1327
|
-
preservedLegacyAliases: targetResults.flatMap((entry) => entry.preservedLegacyAliases)
|
|
1328
|
-
};
|
|
1329
|
-
result.message = buildRemovalMessage(mode, result);
|
|
1330
|
-
return result;
|
|
1331
|
-
}
|
|
1332
|
-
function hasBundledSkillArtifacts(mode) {
|
|
1333
|
-
const packNames = getCanonicalBundledSkillNames();
|
|
1334
|
-
const targets = getTargets(mode);
|
|
1335
|
-
return targets.some((target) => hasCanonicalBundledSkillInTarget(target.dir, packNames));
|
|
1336
|
-
}
|
|
1337
|
-
|
|
1338
904
|
// src/cli/commands/update.ts
|
|
1339
|
-
import * as
|
|
1340
|
-
import * as
|
|
1341
|
-
import * as
|
|
1342
|
-
var
|
|
905
|
+
import * as fs4 from "fs";
|
|
906
|
+
import * as path2 from "path";
|
|
907
|
+
import * as os2 from "os";
|
|
908
|
+
var PLUGIN_NAME = "opendevbrowser";
|
|
1343
909
|
function getCacheDir() {
|
|
1344
|
-
return process.env.OPENCODE_CACHE_DIR ||
|
|
910
|
+
return process.env.OPENCODE_CACHE_DIR || path2.join(os2.homedir(), ".cache", "opencode");
|
|
1345
911
|
}
|
|
1346
912
|
function rmdir(dirPath) {
|
|
1347
913
|
const cacheDir = getCacheDir();
|
|
1348
|
-
const resolvedCache =
|
|
1349
|
-
const resolvedPath =
|
|
1350
|
-
if (!resolvedPath.startsWith(resolvedCache +
|
|
914
|
+
const resolvedCache = path2.resolve(cacheDir);
|
|
915
|
+
const resolvedPath = path2.resolve(dirPath);
|
|
916
|
+
if (!resolvedPath.startsWith(resolvedCache + path2.sep) || resolvedPath === resolvedCache) {
|
|
1351
917
|
throw new Error(`Security: refusing to delete path outside cache directory: ${dirPath}`);
|
|
1352
918
|
}
|
|
1353
|
-
if (
|
|
1354
|
-
|
|
919
|
+
if (fs4.existsSync(dirPath)) {
|
|
920
|
+
fs4.rmSync(dirPath, { recursive: true, force: true });
|
|
1355
921
|
}
|
|
1356
922
|
}
|
|
1357
923
|
function runUpdate() {
|
|
1358
924
|
const cacheDir = getCacheDir();
|
|
1359
|
-
const nodeModulesDir =
|
|
1360
|
-
const pluginCacheDir =
|
|
925
|
+
const nodeModulesDir = path2.join(cacheDir, "node_modules");
|
|
926
|
+
const pluginCacheDir = path2.join(nodeModulesDir, PLUGIN_NAME);
|
|
1361
927
|
try {
|
|
1362
|
-
if (!
|
|
1363
|
-
if (
|
|
928
|
+
if (!fs4.existsSync(pluginCacheDir)) {
|
|
929
|
+
if (fs4.existsSync(nodeModulesDir)) {
|
|
1364
930
|
rmdir(nodeModulesDir);
|
|
1365
931
|
return {
|
|
1366
932
|
success: true,
|
|
@@ -1391,20 +957,29 @@ function runUpdate() {
|
|
|
1391
957
|
}
|
|
1392
958
|
|
|
1393
959
|
// src/cli/commands/uninstall.ts
|
|
1394
|
-
import * as
|
|
1395
|
-
import * as
|
|
1396
|
-
import * as
|
|
960
|
+
import * as fs5 from "fs";
|
|
961
|
+
import * as path3 from "path";
|
|
962
|
+
import * as os3 from "os";
|
|
963
|
+
function hasInstalledConfig(mode) {
|
|
964
|
+
const configPath = mode === "global" ? getGlobalConfigPath() : getLocalConfigPath();
|
|
965
|
+
try {
|
|
966
|
+
const { config } = readConfig(configPath);
|
|
967
|
+
return hasPlugin(config);
|
|
968
|
+
} catch {
|
|
969
|
+
return false;
|
|
970
|
+
}
|
|
971
|
+
}
|
|
1397
972
|
function getPluginConfigPath2(mode) {
|
|
1398
973
|
if (mode === "global") {
|
|
1399
|
-
const configDir = process.env.OPENCODE_CONFIG_DIR ||
|
|
1400
|
-
return
|
|
974
|
+
const configDir = process.env.OPENCODE_CONFIG_DIR || path3.join(os3.homedir(), ".config", "opencode");
|
|
975
|
+
return path3.join(configDir, "opendevbrowser.jsonc");
|
|
1401
976
|
}
|
|
1402
|
-
return
|
|
977
|
+
return path3.join(process.cwd(), "opendevbrowser.jsonc");
|
|
1403
978
|
}
|
|
1404
979
|
function removePluginConfigFile(mode) {
|
|
1405
980
|
const configPath = getPluginConfigPath2(mode);
|
|
1406
|
-
if (
|
|
1407
|
-
|
|
981
|
+
if (fs5.existsSync(configPath)) {
|
|
982
|
+
fs5.unlinkSync(configPath);
|
|
1408
983
|
return true;
|
|
1409
984
|
}
|
|
1410
985
|
return false;
|
|
@@ -1416,14 +991,14 @@ function runUninstall(mode, deleteConfigFile = false) {
|
|
|
1416
991
|
if (!hasPlugin(config)) {
|
|
1417
992
|
return {
|
|
1418
993
|
success: true,
|
|
1419
|
-
message: `
|
|
994
|
+
message: `No plugin config found in ${configPath}`,
|
|
1420
995
|
configPath,
|
|
1421
996
|
removed: false,
|
|
1422
997
|
configFileDeleted: false
|
|
1423
998
|
};
|
|
1424
999
|
}
|
|
1425
1000
|
const newContent = removePluginFromContent(content, "opendevbrowser");
|
|
1426
|
-
|
|
1001
|
+
fs5.writeFileSync(configPath, newContent, "utf-8");
|
|
1427
1002
|
let configFileDeleted = false;
|
|
1428
1003
|
if (deleteConfigFile) {
|
|
1429
1004
|
configFileDeleted = removePluginConfigFile(mode);
|
|
@@ -1447,19 +1022,10 @@ function runUninstall(mode, deleteConfigFile = false) {
|
|
|
1447
1022
|
}
|
|
1448
1023
|
}
|
|
1449
1024
|
function findInstalledConfigs() {
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
global = hasPlugin(globalConfig);
|
|
1455
|
-
} catch {
|
|
1456
|
-
}
|
|
1457
|
-
try {
|
|
1458
|
-
const { config: localConfig } = readConfig(getLocalConfigPath());
|
|
1459
|
-
local = hasPlugin(localConfig);
|
|
1460
|
-
} catch {
|
|
1461
|
-
}
|
|
1462
|
-
return { global, local };
|
|
1025
|
+
return {
|
|
1026
|
+
global: hasInstalledConfig("global") || hasManagedBundledSkillInstall("global") || hasBundledSkillArtifacts("global"),
|
|
1027
|
+
local: hasInstalledConfig("local") || hasManagedBundledSkillInstall("local") || hasBundledSkillArtifacts("local")
|
|
1028
|
+
};
|
|
1463
1029
|
}
|
|
1464
1030
|
|
|
1465
1031
|
// src/cli/commands/serve.ts
|
|
@@ -1549,8 +1115,8 @@ function parseRepeatedStringFlag(rawArgs, flag) {
|
|
|
1549
1115
|
}
|
|
1550
1116
|
|
|
1551
1117
|
// src/cli/commands/native.ts
|
|
1552
|
-
import * as
|
|
1553
|
-
import * as
|
|
1118
|
+
import * as fs6 from "fs";
|
|
1119
|
+
import * as path4 from "path";
|
|
1554
1120
|
import { execFileSync } from "child_process";
|
|
1555
1121
|
import { fileURLToPath } from "url";
|
|
1556
1122
|
var EXTENSION_ID_RE = /^[a-p]{32}$/;
|
|
@@ -1585,33 +1151,33 @@ var parseNativeArgs = (rawArgs) => {
|
|
|
1585
1151
|
};
|
|
1586
1152
|
var getManifestDir = () => {
|
|
1587
1153
|
if (process.platform === "darwin") {
|
|
1588
|
-
return
|
|
1154
|
+
return path4.join(process.env.HOME || "", "Library", "Application Support", "Google", "Chrome", "NativeMessagingHosts");
|
|
1589
1155
|
}
|
|
1590
1156
|
if (process.platform === "linux") {
|
|
1591
|
-
return
|
|
1157
|
+
return path4.join(process.env.HOME || "", ".config", "google-chrome", "NativeMessagingHosts");
|
|
1592
1158
|
}
|
|
1593
1159
|
if (process.platform === "win32") {
|
|
1594
|
-
const base = process.env.LOCALAPPDATA || (process.env.USERPROFILE ?
|
|
1160
|
+
const base = process.env.LOCALAPPDATA || (process.env.USERPROFILE ? path4.join(process.env.USERPROFILE, "AppData", "Local") : "");
|
|
1595
1161
|
if (!base) {
|
|
1596
1162
|
throw createUsageError("LOCALAPPDATA is not set. Unable to locate NativeMessagingHosts directory.");
|
|
1597
1163
|
}
|
|
1598
|
-
return
|
|
1164
|
+
return path4.join(base, "Google", "Chrome", "User Data", "NativeMessagingHosts");
|
|
1599
1165
|
}
|
|
1600
1166
|
throw createUsageError(`Native messaging is not supported on ${process.platform}.`);
|
|
1601
1167
|
};
|
|
1602
1168
|
var getScriptsDir = () => {
|
|
1603
1169
|
const __filename = fileURLToPath(import.meta.url);
|
|
1604
|
-
const startDir =
|
|
1170
|
+
const startDir = path4.dirname(__filename);
|
|
1605
1171
|
const rootsToScan = [startDir, process.cwd()];
|
|
1606
1172
|
for (const root of rootsToScan) {
|
|
1607
|
-
let current =
|
|
1173
|
+
let current = path4.resolve(root);
|
|
1608
1174
|
while (true) {
|
|
1609
|
-
const scriptsDir =
|
|
1610
|
-
const packageJsonPath =
|
|
1611
|
-
if (
|
|
1175
|
+
const scriptsDir = path4.join(current, "scripts", "native");
|
|
1176
|
+
const packageJsonPath = path4.join(current, "package.json");
|
|
1177
|
+
if (fs6.existsSync(scriptsDir) && fs6.existsSync(packageJsonPath)) {
|
|
1612
1178
|
return scriptsDir;
|
|
1613
1179
|
}
|
|
1614
|
-
const parent =
|
|
1180
|
+
const parent = path4.dirname(current);
|
|
1615
1181
|
if (parent === current) {
|
|
1616
1182
|
break;
|
|
1617
1183
|
}
|
|
@@ -1621,18 +1187,18 @@ var getScriptsDir = () => {
|
|
|
1621
1187
|
throw createUsageError("Unable to locate scripts/native directory.");
|
|
1622
1188
|
};
|
|
1623
1189
|
var getHostScriptPath = () => {
|
|
1624
|
-
return
|
|
1190
|
+
return path4.join(getScriptsDir(), "host.cjs");
|
|
1625
1191
|
};
|
|
1626
1192
|
var getManifestPath = () => {
|
|
1627
|
-
return
|
|
1193
|
+
return path4.join(getManifestDir(), "com.opendevbrowser.native.json");
|
|
1628
1194
|
};
|
|
1629
1195
|
var getWrapperPath = () => {
|
|
1630
1196
|
const wrapperName = process.platform === "win32" ? "com.opendevbrowser.native.cmd" : "com.opendevbrowser.native.sh";
|
|
1631
|
-
return
|
|
1197
|
+
return path4.join(getManifestDir(), wrapperName);
|
|
1632
1198
|
};
|
|
1633
1199
|
var readManifest = (manifestPath) => {
|
|
1634
1200
|
try {
|
|
1635
|
-
const raw =
|
|
1201
|
+
const raw = fs6.readFileSync(manifestPath, "utf8");
|
|
1636
1202
|
const data = JSON.parse(raw);
|
|
1637
1203
|
const origins = Array.isArray(data.allowed_origins) ? data.allowed_origins : [];
|
|
1638
1204
|
const match = origins.find((origin) => origin.startsWith("chrome-extension://"));
|
|
@@ -1669,9 +1235,9 @@ var readRegistryPath = () => {
|
|
|
1669
1235
|
};
|
|
1670
1236
|
var normalizePath = (value) => {
|
|
1671
1237
|
try {
|
|
1672
|
-
return
|
|
1238
|
+
return fs6.realpathSync(value);
|
|
1673
1239
|
} catch {
|
|
1674
|
-
return
|
|
1240
|
+
return path4.resolve(value);
|
|
1675
1241
|
}
|
|
1676
1242
|
};
|
|
1677
1243
|
var findExtensionIdInCommands = (preferences) => {
|
|
@@ -1732,8 +1298,8 @@ var getExtensionPathCandidates = () => {
|
|
|
1732
1298
|
if (primary) {
|
|
1733
1299
|
candidates.add(normalizePath(primary));
|
|
1734
1300
|
}
|
|
1735
|
-
const cwdExtension =
|
|
1736
|
-
if (
|
|
1301
|
+
const cwdExtension = path4.join(process.cwd(), "extension");
|
|
1302
|
+
if (fs6.existsSync(path4.join(cwdExtension, "manifest.json"))) {
|
|
1737
1303
|
candidates.add(normalizePath(cwdExtension));
|
|
1738
1304
|
}
|
|
1739
1305
|
if (candidates.size === 0) {
|
|
@@ -1818,13 +1384,13 @@ var getNativeStatusSnapshot = () => {
|
|
|
1818
1384
|
let manifestExists = false;
|
|
1819
1385
|
let wrapperExists = false;
|
|
1820
1386
|
let extensionIdValue = null;
|
|
1821
|
-
if (
|
|
1387
|
+
if (fs6.existsSync(manifestPath)) {
|
|
1822
1388
|
manifestExists = true;
|
|
1823
1389
|
installed = true;
|
|
1824
1390
|
const manifest = readManifest(manifestPath);
|
|
1825
1391
|
extensionIdValue = manifest.extensionId;
|
|
1826
1392
|
}
|
|
1827
|
-
if (
|
|
1393
|
+
if (fs6.existsSync(wrapperPath)) {
|
|
1828
1394
|
wrapperExists = true;
|
|
1829
1395
|
}
|
|
1830
1396
|
if (!manifestExists || !wrapperExists) {
|
|
@@ -1884,7 +1450,7 @@ function installNativeHost(extensionId) {
|
|
|
1884
1450
|
};
|
|
1885
1451
|
}
|
|
1886
1452
|
const hostScript = getHostScriptPath();
|
|
1887
|
-
if (!
|
|
1453
|
+
if (!fs6.existsSync(hostScript)) {
|
|
1888
1454
|
return {
|
|
1889
1455
|
success: false,
|
|
1890
1456
|
message: `Native host not found at ${hostScript}.`,
|
|
@@ -1893,7 +1459,7 @@ function installNativeHost(extensionId) {
|
|
|
1893
1459
|
}
|
|
1894
1460
|
const scriptsDir = getScriptsDir();
|
|
1895
1461
|
const manifestPath = getManifestPath();
|
|
1896
|
-
const installScript = process.platform === "win32" ?
|
|
1462
|
+
const installScript = process.platform === "win32" ? path4.join(scriptsDir, "install.ps1") : path4.join(scriptsDir, "install.sh");
|
|
1897
1463
|
try {
|
|
1898
1464
|
runScript(installScript, [normalized]);
|
|
1899
1465
|
return {
|
|
@@ -1913,7 +1479,7 @@ function installNativeHost(extensionId) {
|
|
|
1913
1479
|
async function runNativeCommand(args) {
|
|
1914
1480
|
const { subcommand, extensionId } = parseNativeArgs(args.rawArgs);
|
|
1915
1481
|
const scriptsDir = getScriptsDir();
|
|
1916
|
-
const uninstallScript = process.platform === "win32" ?
|
|
1482
|
+
const uninstallScript = process.platform === "win32" ? path4.join(scriptsDir, "uninstall.ps1") : path4.join(scriptsDir, "uninstall.sh");
|
|
1917
1483
|
if (subcommand === "install") {
|
|
1918
1484
|
return installNativeHost(extensionId);
|
|
1919
1485
|
}
|
|
@@ -2289,9 +1855,9 @@ ${nativeMessage}${fingerprintNote}${staleNote}` : `${baseMessage}${fingerprintNo
|
|
|
2289
1855
|
|
|
2290
1856
|
// src/cli/daemon-autostart.ts
|
|
2291
1857
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
2292
|
-
import { existsSync as
|
|
2293
|
-
import { homedir as
|
|
2294
|
-
import { dirname as
|
|
1858
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync2, unlinkSync as unlinkSync2, writeFileSync as writeFileSync4 } from "fs";
|
|
1859
|
+
import { homedir as homedir4, tmpdir } from "os";
|
|
1860
|
+
import { dirname as dirname3, isAbsolute, join as join5, relative, resolve as resolve3 } from "path";
|
|
2295
1861
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
2296
1862
|
var MAC_LABEL = "com.opendevbrowser.daemon";
|
|
2297
1863
|
var WIN_TASK_NAME = "OpenDevBrowser Daemon";
|
|
@@ -2301,9 +1867,9 @@ var defaultDeps = () => ({
|
|
|
2301
1867
|
argv1: process.argv[1] ?? "",
|
|
2302
1868
|
moduleUrl: import.meta.url,
|
|
2303
1869
|
uid: typeof process.getuid === "function" ? process.getuid() : 0,
|
|
2304
|
-
homedir:
|
|
2305
|
-
existsSync:
|
|
2306
|
-
mkdirSync:
|
|
1870
|
+
homedir: homedir4,
|
|
1871
|
+
existsSync: existsSync5,
|
|
1872
|
+
mkdirSync: mkdirSync2,
|
|
2307
1873
|
writeFileSync: writeFileSync4,
|
|
2308
1874
|
unlinkSync: unlinkSync2,
|
|
2309
1875
|
execFileSync: execFileSync2,
|
|
@@ -2315,14 +1881,14 @@ var formatCommand = (programArguments) => {
|
|
|
2315
1881
|
};
|
|
2316
1882
|
var resolveCliPathFromModule = (moduleUrl, exists) => {
|
|
2317
1883
|
const modulePath = fileURLToPath2(moduleUrl);
|
|
2318
|
-
const candidate =
|
|
1884
|
+
const candidate = resolve3(dirname3(modulePath), "..", "index.js");
|
|
2319
1885
|
if (!exists(candidate)) {
|
|
2320
1886
|
throw new Error(`CLI entrypoint not found at ${candidate}`);
|
|
2321
1887
|
}
|
|
2322
1888
|
return candidate;
|
|
2323
1889
|
};
|
|
2324
1890
|
var normalizeComparisonPath = (value, platform) => {
|
|
2325
|
-
const resolvedPath =
|
|
1891
|
+
const resolvedPath = resolve3(value);
|
|
2326
1892
|
return platform === "win32" ? resolvedPath.toLowerCase() : resolvedPath;
|
|
2327
1893
|
};
|
|
2328
1894
|
var isPathInsideRoot = (candidate, root, platform) => {
|
|
@@ -2357,7 +1923,7 @@ var resolveCliEntrypoint = (deps = {}) => {
|
|
|
2357
1923
|
let cliPath = null;
|
|
2358
1924
|
let source = "module";
|
|
2359
1925
|
if (resolved.argv1) {
|
|
2360
|
-
const candidate =
|
|
1926
|
+
const candidate = resolve3(resolved.argv1);
|
|
2361
1927
|
if (exists(candidate)) {
|
|
2362
1928
|
cliPath = candidate;
|
|
2363
1929
|
source = "argv1";
|
|
@@ -2372,13 +1938,13 @@ var resolveCliEntrypoint = (deps = {}) => {
|
|
|
2372
1938
|
const isTransient = isTransientCliPath(cliPath, resolved);
|
|
2373
1939
|
return { nodePath, cliPath, args, command, source, isTransient };
|
|
2374
1940
|
};
|
|
2375
|
-
var getLaunchAgentPath = (home =
|
|
2376
|
-
return
|
|
1941
|
+
var getLaunchAgentPath = (home = homedir4()) => {
|
|
1942
|
+
return join5(home, "Library", "LaunchAgents", `${MAC_LABEL}.plist`);
|
|
2377
1943
|
};
|
|
2378
1944
|
var buildLaunchAgentPlist = (entrypoint, options = {}) => {
|
|
2379
1945
|
const label = options.label ?? MAC_LABEL;
|
|
2380
|
-
const stdoutPath = options.stdoutPath ??
|
|
2381
|
-
const stderrPath = options.stderrPath ??
|
|
1946
|
+
const stdoutPath = options.stdoutPath ?? join5(homedir4(), "Library", "Logs", "opendevbrowser-daemon.log");
|
|
1947
|
+
const stderrPath = options.stderrPath ?? join5(homedir4(), "Library", "Logs", "opendevbrowser-daemon.err.log");
|
|
2382
1948
|
const programArgs = [entrypoint.nodePath, ...entrypoint.args].map((value) => ` <string>${value}</string>`).join("\n");
|
|
2383
1949
|
return [
|
|
2384
1950
|
'<?xml version="1.0" encoding="UTF-8"?>',
|
|
@@ -2583,10 +2149,10 @@ var installMacAutostart = (deps = {}) => {
|
|
|
2583
2149
|
assertPersistentEntrypoint(entrypoint);
|
|
2584
2150
|
const home = resolved.homedir();
|
|
2585
2151
|
const plistPath = getLaunchAgentPath(home);
|
|
2586
|
-
const stdoutPath =
|
|
2587
|
-
const stderrPath =
|
|
2588
|
-
const logsDir =
|
|
2589
|
-
resolved.mkdirSync(
|
|
2152
|
+
const stdoutPath = join5(home, "Library", "Logs", "opendevbrowser-daemon.log");
|
|
2153
|
+
const stderrPath = join5(home, "Library", "Logs", "opendevbrowser-daemon.err.log");
|
|
2154
|
+
const logsDir = dirname3(stdoutPath);
|
|
2155
|
+
resolved.mkdirSync(dirname3(plistPath), { recursive: true });
|
|
2590
2156
|
resolved.mkdirSync(logsDir, { recursive: true });
|
|
2591
2157
|
resolved.writeFileSync(
|
|
2592
2158
|
plistPath,
|
|
@@ -2963,7 +2529,7 @@ async function runDaemonCommand(args) {
|
|
|
2963
2529
|
}
|
|
2964
2530
|
|
|
2965
2531
|
// src/cli/commands/artifacts.ts
|
|
2966
|
-
import { join as
|
|
2532
|
+
import { join as join6, resolve as resolve4 } from "path";
|
|
2967
2533
|
import { tmpdir as tmpdir2 } from "os";
|
|
2968
2534
|
var PASSTHROUGH_BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
|
|
2969
2535
|
"--with-config",
|
|
@@ -3052,7 +2618,7 @@ var parseArtifactsArgs = (rawArgs) => {
|
|
|
3052
2618
|
};
|
|
3053
2619
|
async function runArtifactsCommand(args) {
|
|
3054
2620
|
const parsed = parseArtifactsArgs(args.rawArgs);
|
|
3055
|
-
const rootDir = parsed.outputDir ?
|
|
2621
|
+
const rootDir = parsed.outputDir ? resolve4(parsed.outputDir) : join6(tmpdir2(), "opendevbrowser");
|
|
3056
2622
|
const cleaned = await cleanupExpiredArtifacts(rootDir);
|
|
3057
2623
|
return {
|
|
3058
2624
|
success: true,
|
|
@@ -3163,34 +2729,34 @@ function formatAutostartReconciliationMessage(result) {
|
|
|
3163
2729
|
}
|
|
3164
2730
|
|
|
3165
2731
|
// src/cli/commands/run.ts
|
|
3166
|
-
import { readFileSync as
|
|
2732
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
3167
2733
|
|
|
3168
2734
|
// src/cli/output.ts
|
|
3169
2735
|
var normalizeExitCode = (code) => {
|
|
3170
2736
|
return Number.isInteger(code) ? Number(code) : 0;
|
|
3171
2737
|
};
|
|
3172
2738
|
var flushStream = (stream) => {
|
|
3173
|
-
return new Promise((
|
|
2739
|
+
return new Promise((resolve5) => {
|
|
3174
2740
|
if (!stream || typeof stream.write !== "function") {
|
|
3175
|
-
|
|
2741
|
+
resolve5();
|
|
3176
2742
|
return;
|
|
3177
2743
|
}
|
|
3178
2744
|
try {
|
|
3179
|
-
stream.write("", () =>
|
|
2745
|
+
stream.write("", () => resolve5());
|
|
3180
2746
|
} catch {
|
|
3181
|
-
|
|
2747
|
+
resolve5();
|
|
3182
2748
|
}
|
|
3183
2749
|
});
|
|
3184
2750
|
};
|
|
3185
2751
|
async function flushOutputAndExit(code, proc = process, timeoutMs = 250) {
|
|
3186
2752
|
const finalCode = normalizeExitCode(code);
|
|
3187
2753
|
proc.exitCode = finalCode;
|
|
3188
|
-
await new Promise((
|
|
2754
|
+
await new Promise((resolve5) => {
|
|
3189
2755
|
let settled = false;
|
|
3190
2756
|
const finish = () => {
|
|
3191
2757
|
if (settled) return;
|
|
3192
2758
|
settled = true;
|
|
3193
|
-
|
|
2759
|
+
resolve5();
|
|
3194
2760
|
};
|
|
3195
2761
|
const timer = setTimeout(finish, Math.max(0, timeoutMs));
|
|
3196
2762
|
timer.unref?.();
|
|
@@ -3312,13 +2878,13 @@ function parseRunArgs(rawArgs) {
|
|
|
3312
2878
|
return parsed;
|
|
3313
2879
|
}
|
|
3314
2880
|
function readScriptFromStdin() {
|
|
3315
|
-
return new Promise((
|
|
2881
|
+
return new Promise((resolve5, reject) => {
|
|
3316
2882
|
let data = "";
|
|
3317
2883
|
process.stdin.setEncoding("utf8");
|
|
3318
2884
|
process.stdin.on("data", (chunk) => {
|
|
3319
2885
|
data += chunk;
|
|
3320
2886
|
});
|
|
3321
|
-
process.stdin.on("end", () =>
|
|
2887
|
+
process.stdin.on("end", () => resolve5(data));
|
|
3322
2888
|
process.stdin.on("error", reject);
|
|
3323
2889
|
});
|
|
3324
2890
|
}
|
|
@@ -3327,7 +2893,7 @@ async function runScriptCommand(args) {
|
|
|
3327
2893
|
const outputOptions = { format: args.outputFormat, quiet: args.quiet };
|
|
3328
2894
|
let scriptRaw = "";
|
|
3329
2895
|
if (runArgs.scriptPath) {
|
|
3330
|
-
scriptRaw =
|
|
2896
|
+
scriptRaw = readFileSync2(runArgs.scriptPath, "utf-8");
|
|
3331
2897
|
} else if (!process.stdin.isTTY) {
|
|
3332
2898
|
scriptRaw = await readScriptFromStdin();
|
|
3333
2899
|
} else {
|
|
@@ -3552,16 +3118,16 @@ function promptYesNo(question, defaultYes) {
|
|
|
3552
3118
|
return Promise.resolve(false);
|
|
3553
3119
|
}
|
|
3554
3120
|
const suffix = defaultYes ? " [Y/n] " : " [y/N] ";
|
|
3555
|
-
return new Promise((
|
|
3121
|
+
return new Promise((resolve5) => {
|
|
3556
3122
|
process.stdout.write(`${question}${suffix}`);
|
|
3557
3123
|
process.stdin.setEncoding("utf8");
|
|
3558
3124
|
process.stdin.once("data", (data) => {
|
|
3559
3125
|
const input = data.toString().trim().toLowerCase();
|
|
3560
3126
|
if (!input) {
|
|
3561
|
-
|
|
3127
|
+
resolve5(defaultYes);
|
|
3562
3128
|
return;
|
|
3563
3129
|
}
|
|
3564
|
-
|
|
3130
|
+
resolve5(input === "y" || input === "yes");
|
|
3565
3131
|
});
|
|
3566
3132
|
});
|
|
3567
3133
|
}
|
|
@@ -4519,7 +4085,7 @@ async function runAnnotate(args) {
|
|
|
4519
4085
|
}
|
|
4520
4086
|
|
|
4521
4087
|
// src/cli/commands/canvas.ts
|
|
4522
|
-
import { readFileSync as
|
|
4088
|
+
import { readFileSync as readFileSync3 } from "fs";
|
|
4523
4089
|
var DEFAULT_FEEDBACK_STREAM_TIMEOUT_MS = 3e4;
|
|
4524
4090
|
var isRecord = (value) => {
|
|
4525
4091
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -4720,7 +4286,7 @@ var resolveCanvasParams = (canvasArgs) => {
|
|
|
4720
4286
|
if (hasParamsFile) {
|
|
4721
4287
|
let raw = "";
|
|
4722
4288
|
try {
|
|
4723
|
-
raw =
|
|
4289
|
+
raw = readFileSync3(canvasArgs.paramsFile ?? "", "utf8");
|
|
4724
4290
|
} catch (error) {
|
|
4725
4291
|
const message = error instanceof Error ? error.message : "Unable to read file";
|
|
4726
4292
|
throw createUsageError(`Invalid --params-file: ${message}`);
|
|
@@ -4789,7 +4355,7 @@ async function runCanvas(args) {
|
|
|
4789
4355
|
}
|
|
4790
4356
|
|
|
4791
4357
|
// src/cli/commands/rpc.ts
|
|
4792
|
-
import { readFileSync as
|
|
4358
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
4793
4359
|
var requireValue4 = (value, flag) => {
|
|
4794
4360
|
if (!value) throw createUsageError(`Missing value for ${flag}`);
|
|
4795
4361
|
return value;
|
|
@@ -4869,7 +4435,7 @@ var resolveRpcParams = (rpcArgs) => {
|
|
|
4869
4435
|
if (hasParamsFile) {
|
|
4870
4436
|
let raw = "";
|
|
4871
4437
|
try {
|
|
4872
|
-
raw =
|
|
4438
|
+
raw = readFileSync4(rpcArgs.paramsFile ?? "", "utf8");
|
|
4873
4439
|
} catch (error) {
|
|
4874
4440
|
const message = error instanceof Error ? error.message : "Unable to read file";
|
|
4875
4441
|
throw createUsageError(`Invalid --params-file: ${message}`);
|
|
@@ -6249,11 +5815,11 @@ function parseScreenshotArgs(rawArgs) {
|
|
|
6249
5815
|
return parsed;
|
|
6250
5816
|
}
|
|
6251
5817
|
async function runScreenshot(args) {
|
|
6252
|
-
const { sessionId, targetId, path:
|
|
5818
|
+
const { sessionId, targetId, path: path5, ref, fullPage, timeoutMs } = parseScreenshotArgs(args.rawArgs);
|
|
6253
5819
|
if (!sessionId) throw createUsageError("Missing --session-id");
|
|
6254
5820
|
const params = {
|
|
6255
5821
|
sessionId,
|
|
6256
|
-
...typeof
|
|
5822
|
+
...typeof path5 === "string" ? { path: path5 } : {},
|
|
6257
5823
|
...typeof targetId === "string" ? { targetId } : {},
|
|
6258
5824
|
...typeof ref === "string" ? { ref } : {},
|
|
6259
5825
|
...fullPage === true ? { fullPage: true } : {}
|
|
@@ -6652,7 +6218,7 @@ async function runDesktopAccessibilitySnapshot(args) {
|
|
|
6652
6218
|
}
|
|
6653
6219
|
|
|
6654
6220
|
// src/cli/commands/session/cookie-import.ts
|
|
6655
|
-
import { readFileSync as
|
|
6221
|
+
import { readFileSync as readFileSync5 } from "fs";
|
|
6656
6222
|
var requireValue5 = (value, flag) => {
|
|
6657
6223
|
if (!value) {
|
|
6658
6224
|
throw createUsageError(`Missing value for ${flag}`);
|
|
@@ -6767,7 +6333,7 @@ var resolveCookies = (parsed) => {
|
|
|
6767
6333
|
}
|
|
6768
6334
|
let raw = "";
|
|
6769
6335
|
try {
|
|
6770
|
-
raw =
|
|
6336
|
+
raw = readFileSync5(parsed.cookiesFile ?? "", "utf8");
|
|
6771
6337
|
} catch (error) {
|
|
6772
6338
|
const message = error instanceof Error ? error.message : "Unable to read file";
|
|
6773
6339
|
throw createUsageError(`Invalid --cookies-file: ${message}`);
|
|
@@ -7803,7 +7369,7 @@ async function runInspiredesignCommand(args) {
|
|
|
7803
7369
|
// package.json
|
|
7804
7370
|
var package_default = {
|
|
7805
7371
|
name: "opendevbrowser",
|
|
7806
|
-
version: "0.0.
|
|
7372
|
+
version: "0.0.22",
|
|
7807
7373
|
description: "Browser automation runtime with snapshot-refs-actions, browser replay screencasts, public read-only desktop observation, and browser-scoped computer-use orchestration",
|
|
7808
7374
|
type: "module",
|
|
7809
7375
|
main: "dist/index.js",
|
|
@@ -7814,6 +7380,7 @@ var package_default = {
|
|
|
7814
7380
|
files: [
|
|
7815
7381
|
"dist",
|
|
7816
7382
|
"skills",
|
|
7383
|
+
"scripts/postinstall-sync-skills.mjs",
|
|
7817
7384
|
"scripts/native",
|
|
7818
7385
|
"extension/canvas.html",
|
|
7819
7386
|
"extension/manifest.json",
|
|
@@ -7848,8 +7415,8 @@ var package_default = {
|
|
|
7848
7415
|
node: ">=18"
|
|
7849
7416
|
},
|
|
7850
7417
|
scripts: {
|
|
7851
|
-
build: "node scripts/run-package-tool.mjs tsup src/index.ts src/cli/index.ts src/skills/skill-loader.ts --format esm --clean --sourcemap && node scripts/run-package-tool.mjs tsc --emitDeclarationOnly --declaration --declarationMap -p tsconfig.json && node scripts/postbuild-dist.mjs",
|
|
7852
|
-
dev: "tsup src/index.ts src/cli/index.ts src/skills/skill-loader.ts --format esm --dts --watch",
|
|
7418
|
+
build: "node scripts/run-package-tool.mjs tsup src/index.ts src/cli/index.ts src/cli/installers/postinstall-skill-sync.ts src/skills/skill-loader.ts --format esm --clean --sourcemap && node scripts/run-package-tool.mjs tsc --emitDeclarationOnly --declaration --declarationMap -p tsconfig.json && node scripts/postbuild-dist.mjs",
|
|
7419
|
+
dev: "tsup src/index.ts src/cli/index.ts src/cli/installers/postinstall-skill-sync.ts src/skills/skill-loader.ts --format esm --dts --watch",
|
|
7853
7420
|
lint: 'node scripts/run-package-tool.mjs eslint "src/**/*.ts" "tests/**/*.ts"',
|
|
7854
7421
|
typecheck: "node scripts/run-package-tool.mjs tsc --noEmit -p tsconfig.json",
|
|
7855
7422
|
test: "node scripts/run-vitest-coverage.mjs",
|
|
@@ -7864,7 +7431,8 @@ var package_default = {
|
|
|
7864
7431
|
"extension:pack": "cd extension && zip -r ../opendevbrowser-extension.zip manifest.json popup.html canvas.html dist/ icons/",
|
|
7865
7432
|
"extension:store": "node scripts/chrome-store-publish.mjs",
|
|
7866
7433
|
"version:check": "node scripts/verify-versions.mjs",
|
|
7867
|
-
prepack: "npm run version:check && npm run build && npm run extension:build"
|
|
7434
|
+
prepack: "npm run version:check && npm run build && npm run extension:build",
|
|
7435
|
+
postinstall: "node scripts/postinstall-sync-skills.mjs"
|
|
7868
7436
|
},
|
|
7869
7437
|
dependencies: {
|
|
7870
7438
|
"@opencode-ai/plugin": "^1.2.25",
|
|
@@ -7892,8 +7460,10 @@ var package_default = {
|
|
|
7892
7460
|
}
|
|
7893
7461
|
};
|
|
7894
7462
|
|
|
7895
|
-
// src/cli/
|
|
7896
|
-
|
|
7463
|
+
// src/cli/update-skill-modes.ts
|
|
7464
|
+
function shouldRefreshManagedSkills(mode) {
|
|
7465
|
+
return hasManagedBundledSkillInstall(mode) || hasBundledSkillArtifacts(mode);
|
|
7466
|
+
}
|
|
7897
7467
|
function resolveUpdateSkillModes(args) {
|
|
7898
7468
|
if (args.rawArgs.includes("--no-skills")) {
|
|
7899
7469
|
return [];
|
|
@@ -7907,22 +7477,102 @@ function resolveUpdateSkillModes(args) {
|
|
|
7907
7477
|
if (args.mode) {
|
|
7908
7478
|
return [args.mode];
|
|
7909
7479
|
}
|
|
7910
|
-
const installed = findInstalledConfigs();
|
|
7911
7480
|
const modes = [];
|
|
7912
|
-
if (
|
|
7481
|
+
if (shouldRefreshManagedSkills("global")) {
|
|
7913
7482
|
modes.push("global");
|
|
7914
7483
|
}
|
|
7915
|
-
if (
|
|
7484
|
+
if (shouldRefreshManagedSkills("local")) {
|
|
7916
7485
|
modes.push("local");
|
|
7917
7486
|
}
|
|
7918
7487
|
return modes;
|
|
7919
7488
|
}
|
|
7489
|
+
|
|
7490
|
+
// src/cli/skill-lifecycle.ts
|
|
7491
|
+
function shouldSkipSkills(args) {
|
|
7492
|
+
return args.rawArgs.includes("--no-skills");
|
|
7493
|
+
}
|
|
7494
|
+
function getUpdateTargets(args, mode, deps) {
|
|
7495
|
+
if (deps.hasInstalledConfig(mode)) {
|
|
7496
|
+
return deps.getBundledSkillTargets(mode);
|
|
7497
|
+
}
|
|
7498
|
+
return deps.getBundledSkillLifecycleTargets(mode, {
|
|
7499
|
+
includeLegacyArtifacts: deps.hasBundledSkillArtifacts(mode)
|
|
7500
|
+
});
|
|
7501
|
+
}
|
|
7502
|
+
function collectUpdateSkillResults(args, deps, modes) {
|
|
7503
|
+
return modes.flatMap((mode) => {
|
|
7504
|
+
const targets = getUpdateTargets(args, mode, deps);
|
|
7505
|
+
return targets.length > 0 ? [deps.syncBundledSkillsForTargets(mode, targets)] : [];
|
|
7506
|
+
});
|
|
7507
|
+
}
|
|
7508
|
+
function getResolvedUpdateSkillModes(args, result, deps) {
|
|
7509
|
+
return result.success ? deps.resolveUpdateSkillModes(args) : [];
|
|
7510
|
+
}
|
|
7511
|
+
function buildUpdateSkillMessage(args, result, skillResults) {
|
|
7512
|
+
if (!result.success) {
|
|
7513
|
+
return "";
|
|
7514
|
+
}
|
|
7515
|
+
if (shouldSkipSkills(args)) {
|
|
7516
|
+
return "Managed skill refresh skipped (--no-skills).";
|
|
7517
|
+
}
|
|
7518
|
+
if (skillResults.length === 0) {
|
|
7519
|
+
return "No managed skill packs required refresh.";
|
|
7520
|
+
}
|
|
7521
|
+
return skillResults.map((entry) => entry.message).join("\n");
|
|
7522
|
+
}
|
|
7523
|
+
function buildUpdateCommandResult(args, result, deps) {
|
|
7524
|
+
const skillModes = getResolvedUpdateSkillModes(args, result, deps);
|
|
7525
|
+
const skillResults = result.success && !shouldSkipSkills(args) ? collectUpdateSkillResults(args, deps, skillModes) : [];
|
|
7526
|
+
const message = [result.message, buildUpdateSkillMessage(args, result, skillResults)].filter(Boolean).join("\n");
|
|
7527
|
+
return {
|
|
7528
|
+
success: result.success && skillResults.every((entry) => entry.success),
|
|
7529
|
+
message,
|
|
7530
|
+
data: {
|
|
7531
|
+
cacheCleared: result.cleared,
|
|
7532
|
+
skillModes,
|
|
7533
|
+
skills: skillResults
|
|
7534
|
+
}
|
|
7535
|
+
};
|
|
7536
|
+
}
|
|
7537
|
+
function buildUninstallSkillMessage(args, result, skillsResult) {
|
|
7538
|
+
if (!result.success) {
|
|
7539
|
+
return "";
|
|
7540
|
+
}
|
|
7541
|
+
if (shouldSkipSkills(args)) {
|
|
7542
|
+
return "Managed skill cleanup skipped (--no-skills).";
|
|
7543
|
+
}
|
|
7544
|
+
return skillsResult?.message ?? "No managed skill packs required cleanup.";
|
|
7545
|
+
}
|
|
7546
|
+
function getUninstallTargets(args, mode, result, deps) {
|
|
7547
|
+
if (!result.success || shouldSkipSkills(args)) {
|
|
7548
|
+
return [];
|
|
7549
|
+
}
|
|
7550
|
+
return deps.getBundledSkillLifecycleTargets(mode, {
|
|
7551
|
+
includeLegacyArtifacts: result.removed || deps.hasBundledSkillArtifacts(mode)
|
|
7552
|
+
});
|
|
7553
|
+
}
|
|
7554
|
+
function buildUninstallCommandResult(args, mode, result, deps) {
|
|
7555
|
+
const targets = getUninstallTargets(args, mode, result, deps);
|
|
7556
|
+
const skillsResult = result.success && !shouldSkipSkills(args) ? targets.length > 0 ? deps.removeBundledSkillsForTargets(mode, targets) : createNoOpSkillRemovalResult(mode) : void 0;
|
|
7557
|
+
const skillMessage = buildUninstallSkillMessage(args, result, skillsResult);
|
|
7558
|
+
return {
|
|
7559
|
+
success: result.success && (skillsResult?.success ?? true),
|
|
7560
|
+
message: [result.message, skillMessage].filter(Boolean).join("\n"),
|
|
7561
|
+
data: {
|
|
7562
|
+
config: result,
|
|
7563
|
+
skills: skillsResult
|
|
7564
|
+
}
|
|
7565
|
+
};
|
|
7566
|
+
}
|
|
7567
|
+
|
|
7568
|
+
// src/cli/index.ts
|
|
7569
|
+
var VERSION = typeof package_default.version === "string" ? package_default.version : "0.0.0";
|
|
7920
7570
|
async function promptInstallMode() {
|
|
7921
7571
|
if (!process.stdin.isTTY) {
|
|
7922
7572
|
console.log("Non-interactive mode detected. Using global install.");
|
|
7923
7573
|
return "global";
|
|
7924
7574
|
}
|
|
7925
|
-
return new Promise((
|
|
7575
|
+
return new Promise((resolve5) => {
|
|
7926
7576
|
console.log("\nWhere would you like to install opendevbrowser?\n");
|
|
7927
7577
|
console.log(" 1. Global (~/.config/opencode/opencode.json)");
|
|
7928
7578
|
console.log(" 2. Local (./opencode.json in this project)\n");
|
|
@@ -7942,23 +7592,23 @@ async function promptInstallMode() {
|
|
|
7942
7592
|
resolved = true;
|
|
7943
7593
|
const input = data.toString().trim();
|
|
7944
7594
|
if (input === "2") {
|
|
7945
|
-
|
|
7595
|
+
resolve5("local");
|
|
7946
7596
|
} else {
|
|
7947
|
-
|
|
7597
|
+
resolve5("global");
|
|
7948
7598
|
}
|
|
7949
7599
|
});
|
|
7950
7600
|
process.stdin.once("close", () => {
|
|
7951
7601
|
cleanup();
|
|
7952
7602
|
if (resolved) return;
|
|
7953
7603
|
resolved = true;
|
|
7954
|
-
|
|
7604
|
+
resolve5("global");
|
|
7955
7605
|
});
|
|
7956
7606
|
timeoutId = setTimeout(() => {
|
|
7957
7607
|
timeoutId = null;
|
|
7958
7608
|
if (resolved) return;
|
|
7959
7609
|
resolved = true;
|
|
7960
7610
|
console.log("\nTimeout - using global install.");
|
|
7961
|
-
|
|
7611
|
+
resolve5("global");
|
|
7962
7612
|
}, 3e4);
|
|
7963
7613
|
});
|
|
7964
7614
|
}
|
|
@@ -7978,7 +7628,7 @@ async function promptUninstallMode() {
|
|
|
7978
7628
|
console.log("Plugin found in both global and local configs. Use --global or --local flag.");
|
|
7979
7629
|
return null;
|
|
7980
7630
|
}
|
|
7981
|
-
return new Promise((
|
|
7631
|
+
return new Promise((resolve5) => {
|
|
7982
7632
|
console.log("\nopendevbrowser is installed in multiple locations:\n");
|
|
7983
7633
|
console.log(" 1. Global (~/.config/opencode/opencode.json)");
|
|
7984
7634
|
console.log(" 2. Local (./opencode.json)");
|
|
@@ -7988,15 +7638,15 @@ async function promptUninstallMode() {
|
|
|
7988
7638
|
process.stdin.once("data", (data) => {
|
|
7989
7639
|
const input = data.toString().trim();
|
|
7990
7640
|
if (input === "1") {
|
|
7991
|
-
|
|
7641
|
+
resolve5("global");
|
|
7992
7642
|
} else if (input === "2") {
|
|
7993
|
-
|
|
7643
|
+
resolve5("local");
|
|
7994
7644
|
} else {
|
|
7995
|
-
|
|
7645
|
+
resolve5(null);
|
|
7996
7646
|
}
|
|
7997
7647
|
});
|
|
7998
7648
|
process.stdin.once("close", () => {
|
|
7999
|
-
|
|
7649
|
+
resolve5(null);
|
|
8000
7650
|
});
|
|
8001
7651
|
});
|
|
8002
7652
|
}
|
|
@@ -8054,22 +7704,14 @@ async function main() {
|
|
|
8054
7704
|
registerCommand({
|
|
8055
7705
|
name: "update",
|
|
8056
7706
|
description: "Clear cached plugin and refresh managed skill packs",
|
|
8057
|
-
run: () => {
|
|
8058
|
-
|
|
8059
|
-
|
|
8060
|
-
|
|
8061
|
-
|
|
8062
|
-
|
|
8063
|
-
|
|
8064
|
-
|
|
8065
|
-
message,
|
|
8066
|
-
data: {
|
|
8067
|
-
cacheCleared: result2.cleared,
|
|
8068
|
-
skillModes,
|
|
8069
|
-
skills: skillResults
|
|
8070
|
-
}
|
|
8071
|
-
};
|
|
8072
|
-
}
|
|
7707
|
+
run: () => buildUpdateCommandResult(args, runUpdate(), {
|
|
7708
|
+
resolveUpdateSkillModes,
|
|
7709
|
+
hasInstalledConfig,
|
|
7710
|
+
hasBundledSkillArtifacts,
|
|
7711
|
+
getBundledSkillTargets,
|
|
7712
|
+
getBundledSkillLifecycleTargets,
|
|
7713
|
+
syncBundledSkillsForTargets
|
|
7714
|
+
})
|
|
8073
7715
|
});
|
|
8074
7716
|
registerCommand({
|
|
8075
7717
|
name: "uninstall",
|
|
@@ -8085,18 +7727,11 @@ async function main() {
|
|
|
8085
7727
|
if (!mode) {
|
|
8086
7728
|
return { success: false, message: "Error: Please specify --global or --local for uninstall.", exitCode: EXIT_USAGE };
|
|
8087
7729
|
}
|
|
8088
|
-
|
|
8089
|
-
|
|
8090
|
-
|
|
8091
|
-
|
|
8092
|
-
|
|
8093
|
-
success: result2.success && (skillsResult?.success ?? true),
|
|
8094
|
-
message: [result2.message, skillMessage].filter(Boolean).join("\n"),
|
|
8095
|
-
data: {
|
|
8096
|
-
config: result2,
|
|
8097
|
-
skills: skillsResult
|
|
8098
|
-
}
|
|
8099
|
-
};
|
|
7730
|
+
return buildUninstallCommandResult(args, mode, runUninstall(mode), {
|
|
7731
|
+
hasBundledSkillArtifacts,
|
|
7732
|
+
getBundledSkillLifecycleTargets,
|
|
7733
|
+
removeBundledSkillsForTargets
|
|
7734
|
+
});
|
|
8100
7735
|
}
|
|
8101
7736
|
});
|
|
8102
7737
|
registerCommand({
|