opendevbrowser 0.0.21 → 0.0.23
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 +13 -3
- package/dist/{chunk-4KVXCXV3.js → chunk-2MG7BRPF.js} +521 -84
- package/dist/{chunk-4KVXCXV3.js.map → chunk-2MG7BRPF.js.map} +1 -1
- package/dist/chunk-3ILXPKSJ.js +86 -0
- package/dist/chunk-3ILXPKSJ.js.map +1 -0
- package/dist/{chunk-ZE2E7ZGH.js → chunk-K2TEHJCV.js} +240 -33
- package/dist/chunk-K2TEHJCV.js.map +1 -0
- 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/macro-resolve.d.ts.map +1 -1
- package/dist/cli/commands/uninstall.d.ts +1 -0
- package/dist/cli/commands/uninstall.d.ts.map +1 -1
- package/dist/cli/daemon-commands.d.ts.map +1 -1
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/index.js +298 -618
- 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/cli/utils/workflow-message.d.ts +1 -0
- package/dist/cli/utils/workflow-message.d.ts.map +1 -1
- package/dist/index.js +25 -9
- package/dist/index.js.map +1 -1
- package/dist/opendevbrowser.js +25 -9
- package/dist/opendevbrowser.js.map +1 -1
- package/dist/providers/social/platform.d.ts.map +1 -1
- package/dist/providers/social/search-quality.d.ts.map +1 -1
- package/dist/providers/social/youtube.d.ts.map +1 -1
- package/dist/providers/workflow-handoff.d.ts +27 -3
- package/dist/providers/workflow-handoff.d.ts.map +1 -1
- package/dist/providers/workflows.d.ts +1 -0
- package/dist/providers/workflows.d.ts.map +1 -1
- package/dist/{providers-ZIVHHH4F.js → providers-6YVHKTOJ.js} +2 -2
- package/dist/public-surface/generated-manifest.d.ts +162 -4
- package/dist/public-surface/generated-manifest.d.ts.map +1 -1
- package/dist/public-surface/source.d.ts +12 -6
- package/dist/public-surface/source.d.ts.map +1 -1
- package/dist/skills/skill-loader.js +2 -1
- package/dist/tools/macro_resolve.d.ts.map +1 -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/chunk-ZE2E7ZGH.js.map +0 -1
- /package/dist/{providers-ZIVHHH4F.js.map → providers-6YVHKTOJ.js.map} +0 -0
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-2MG7BRPF.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";
|
|
@@ -48,7 +63,7 @@ import {
|
|
|
48
63
|
setDefaultLogSink,
|
|
49
64
|
stderrSink,
|
|
50
65
|
summarizePrimaryProviderIssue
|
|
51
|
-
} from "../chunk-
|
|
66
|
+
} from "../chunk-K2TEHJCV.js";
|
|
52
67
|
import "../chunk-FUSXMW3G.js";
|
|
53
68
|
|
|
54
69
|
// src/cli/args.ts
|
|
@@ -565,6 +580,9 @@ function assertCommandCoverage() {
|
|
|
565
580
|
if (!detail || !detail.description.trim() || !detail.usage.trim()) {
|
|
566
581
|
throw new Error(`Missing command help metadata: ${command}`);
|
|
567
582
|
}
|
|
583
|
+
if (detail.examples.length === 0) {
|
|
584
|
+
throw new Error(`Missing command example metadata: ${command}`);
|
|
585
|
+
}
|
|
568
586
|
for (const flag of detail.flags) {
|
|
569
587
|
if (!FLAG_SET.has(flag)) {
|
|
570
588
|
throw new Error(`Command help metadata references unknown flag ${flag} for ${command}`);
|
|
@@ -605,6 +623,9 @@ function assertToolCoverage() {
|
|
|
605
623
|
if (!entry.description.trim()) {
|
|
606
624
|
throw new Error(`Help tool is missing a description: ${entry.name}`);
|
|
607
625
|
}
|
|
626
|
+
if (!entry.example?.trim()) {
|
|
627
|
+
throw new Error(`Help tool is missing an example: ${entry.name}`);
|
|
628
|
+
}
|
|
608
629
|
if (seen.has(entry.name)) {
|
|
609
630
|
throw new Error(`Help tool appears multiple times: ${entry.name}`);
|
|
610
631
|
}
|
|
@@ -626,7 +647,9 @@ function formatCommandGroups() {
|
|
|
626
647
|
description: detail.description,
|
|
627
648
|
details: [
|
|
628
649
|
{ label: "usage:", value: detail.usage },
|
|
629
|
-
{ label: "flags:", value: formatFlags(detail.flags) }
|
|
650
|
+
{ label: "flags:", value: formatFlags(detail.flags) },
|
|
651
|
+
...detail.examples.map((example) => ({ label: "example:", value: example })),
|
|
652
|
+
...detail.notes.map((note) => ({ label: "note:", value: note }))
|
|
630
653
|
]
|
|
631
654
|
};
|
|
632
655
|
});
|
|
@@ -649,7 +672,11 @@ function formatToolEntries() {
|
|
|
649
672
|
return formatRows(HELP_TOOL_ENTRIES.map((entry) => ({
|
|
650
673
|
label: entry.name,
|
|
651
674
|
description: entry.description,
|
|
652
|
-
details:
|
|
675
|
+
details: [
|
|
676
|
+
...entry.cliEquivalent ? [{ label: "cli:", value: entry.cliEquivalent }] : [{ label: "scope:", value: "tool-only" }],
|
|
677
|
+
...entry.example ? [{ label: "example:", value: entry.example }] : [],
|
|
678
|
+
...(entry.notes ?? []).map((note) => ({ label: "note:", value: note }))
|
|
679
|
+
]
|
|
653
680
|
})));
|
|
654
681
|
}
|
|
655
682
|
function formatOnboardingEntries() {
|
|
@@ -706,86 +733,12 @@ function getCommand(name) {
|
|
|
706
733
|
}
|
|
707
734
|
|
|
708
735
|
// src/cli/installers/global.ts
|
|
709
|
-
import * as
|
|
736
|
+
import * as fs2 from "fs";
|
|
710
737
|
|
|
711
|
-
// src/cli/
|
|
738
|
+
// src/cli/templates/config.ts
|
|
712
739
|
import * as fs from "fs";
|
|
713
740
|
import * as path from "path";
|
|
714
741
|
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
742
|
function buildConfigTemplate(relayToken, daemonToken) {
|
|
790
743
|
return `{
|
|
791
744
|
// OpenDevBrowser Plugin Configuration
|
|
@@ -862,19 +815,19 @@ function buildConfigTemplate(relayToken, daemonToken) {
|
|
|
862
815
|
}
|
|
863
816
|
function getPluginConfigPath(mode) {
|
|
864
817
|
if (mode === "global") {
|
|
865
|
-
const configDir = process.env.OPENCODE_CONFIG_DIR ||
|
|
866
|
-
return
|
|
818
|
+
const configDir = process.env.OPENCODE_CONFIG_DIR || path.join(os.homedir(), ".config", "opencode");
|
|
819
|
+
return path.join(configDir, "opendevbrowser.jsonc");
|
|
867
820
|
}
|
|
868
|
-
return
|
|
821
|
+
return path.join(process.cwd(), "opendevbrowser.jsonc");
|
|
869
822
|
}
|
|
870
823
|
function createPluginConfig(mode) {
|
|
871
824
|
const configPath = getPluginConfigPath(mode);
|
|
872
|
-
if (
|
|
825
|
+
if (fs.existsSync(configPath)) {
|
|
873
826
|
return { created: false, path: configPath };
|
|
874
827
|
}
|
|
875
|
-
const dir =
|
|
876
|
-
if (!
|
|
877
|
-
|
|
828
|
+
const dir = path.dirname(configPath);
|
|
829
|
+
if (!fs.existsSync(dir)) {
|
|
830
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
878
831
|
}
|
|
879
832
|
const relayToken = generateSecureToken();
|
|
880
833
|
const daemonToken = generateSecureToken();
|
|
@@ -898,7 +851,7 @@ function installGlobal(withConfig = false) {
|
|
|
898
851
|
}
|
|
899
852
|
const newContent = updateConfigContent(content, "opendevbrowser");
|
|
900
853
|
ensureDir(configPath.replace(/[/\\][^/\\]+$/, ""));
|
|
901
|
-
|
|
854
|
+
fs2.writeFileSync(configPath, newContent, "utf-8");
|
|
902
855
|
if (withConfig) {
|
|
903
856
|
createPluginConfig("global");
|
|
904
857
|
}
|
|
@@ -922,7 +875,7 @@ function installGlobal(withConfig = false) {
|
|
|
922
875
|
}
|
|
923
876
|
|
|
924
877
|
// src/cli/installers/local.ts
|
|
925
|
-
import * as
|
|
878
|
+
import * as fs3 from "fs";
|
|
926
879
|
function installLocal(withConfig = false) {
|
|
927
880
|
const configPath = getLocalConfigPath();
|
|
928
881
|
try {
|
|
@@ -937,7 +890,7 @@ function installLocal(withConfig = false) {
|
|
|
937
890
|
};
|
|
938
891
|
}
|
|
939
892
|
const newContent = updateConfigContent(content, "opendevbrowser");
|
|
940
|
-
|
|
893
|
+
fs3.writeFileSync(configPath, newContent, "utf-8");
|
|
941
894
|
if (withConfig) {
|
|
942
895
|
createPluginConfig("local");
|
|
943
896
|
}
|
|
@@ -960,407 +913,32 @@ function installLocal(withConfig = false) {
|
|
|
960
913
|
}
|
|
961
914
|
}
|
|
962
915
|
|
|
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
916
|
// src/cli/commands/update.ts
|
|
1339
|
-
import * as
|
|
1340
|
-
import * as
|
|
1341
|
-
import * as
|
|
1342
|
-
var
|
|
917
|
+
import * as fs4 from "fs";
|
|
918
|
+
import * as path2 from "path";
|
|
919
|
+
import * as os2 from "os";
|
|
920
|
+
var PLUGIN_NAME = "opendevbrowser";
|
|
1343
921
|
function getCacheDir() {
|
|
1344
|
-
return process.env.OPENCODE_CACHE_DIR ||
|
|
922
|
+
return process.env.OPENCODE_CACHE_DIR || path2.join(os2.homedir(), ".cache", "opencode");
|
|
1345
923
|
}
|
|
1346
924
|
function rmdir(dirPath) {
|
|
1347
925
|
const cacheDir = getCacheDir();
|
|
1348
|
-
const resolvedCache =
|
|
1349
|
-
const resolvedPath =
|
|
1350
|
-
if (!resolvedPath.startsWith(resolvedCache +
|
|
926
|
+
const resolvedCache = path2.resolve(cacheDir);
|
|
927
|
+
const resolvedPath = path2.resolve(dirPath);
|
|
928
|
+
if (!resolvedPath.startsWith(resolvedCache + path2.sep) || resolvedPath === resolvedCache) {
|
|
1351
929
|
throw new Error(`Security: refusing to delete path outside cache directory: ${dirPath}`);
|
|
1352
930
|
}
|
|
1353
|
-
if (
|
|
1354
|
-
|
|
931
|
+
if (fs4.existsSync(dirPath)) {
|
|
932
|
+
fs4.rmSync(dirPath, { recursive: true, force: true });
|
|
1355
933
|
}
|
|
1356
934
|
}
|
|
1357
935
|
function runUpdate() {
|
|
1358
936
|
const cacheDir = getCacheDir();
|
|
1359
|
-
const nodeModulesDir =
|
|
1360
|
-
const pluginCacheDir =
|
|
937
|
+
const nodeModulesDir = path2.join(cacheDir, "node_modules");
|
|
938
|
+
const pluginCacheDir = path2.join(nodeModulesDir, PLUGIN_NAME);
|
|
1361
939
|
try {
|
|
1362
|
-
if (!
|
|
1363
|
-
if (
|
|
940
|
+
if (!fs4.existsSync(pluginCacheDir)) {
|
|
941
|
+
if (fs4.existsSync(nodeModulesDir)) {
|
|
1364
942
|
rmdir(nodeModulesDir);
|
|
1365
943
|
return {
|
|
1366
944
|
success: true,
|
|
@@ -1391,20 +969,29 @@ function runUpdate() {
|
|
|
1391
969
|
}
|
|
1392
970
|
|
|
1393
971
|
// src/cli/commands/uninstall.ts
|
|
1394
|
-
import * as
|
|
1395
|
-
import * as
|
|
1396
|
-
import * as
|
|
972
|
+
import * as fs5 from "fs";
|
|
973
|
+
import * as path3 from "path";
|
|
974
|
+
import * as os3 from "os";
|
|
975
|
+
function hasInstalledConfig(mode) {
|
|
976
|
+
const configPath = mode === "global" ? getGlobalConfigPath() : getLocalConfigPath();
|
|
977
|
+
try {
|
|
978
|
+
const { config } = readConfig(configPath);
|
|
979
|
+
return hasPlugin(config);
|
|
980
|
+
} catch {
|
|
981
|
+
return false;
|
|
982
|
+
}
|
|
983
|
+
}
|
|
1397
984
|
function getPluginConfigPath2(mode) {
|
|
1398
985
|
if (mode === "global") {
|
|
1399
|
-
const configDir = process.env.OPENCODE_CONFIG_DIR ||
|
|
1400
|
-
return
|
|
986
|
+
const configDir = process.env.OPENCODE_CONFIG_DIR || path3.join(os3.homedir(), ".config", "opencode");
|
|
987
|
+
return path3.join(configDir, "opendevbrowser.jsonc");
|
|
1401
988
|
}
|
|
1402
|
-
return
|
|
989
|
+
return path3.join(process.cwd(), "opendevbrowser.jsonc");
|
|
1403
990
|
}
|
|
1404
991
|
function removePluginConfigFile(mode) {
|
|
1405
992
|
const configPath = getPluginConfigPath2(mode);
|
|
1406
|
-
if (
|
|
1407
|
-
|
|
993
|
+
if (fs5.existsSync(configPath)) {
|
|
994
|
+
fs5.unlinkSync(configPath);
|
|
1408
995
|
return true;
|
|
1409
996
|
}
|
|
1410
997
|
return false;
|
|
@@ -1416,14 +1003,14 @@ function runUninstall(mode, deleteConfigFile = false) {
|
|
|
1416
1003
|
if (!hasPlugin(config)) {
|
|
1417
1004
|
return {
|
|
1418
1005
|
success: true,
|
|
1419
|
-
message: `
|
|
1006
|
+
message: `No plugin config found in ${configPath}`,
|
|
1420
1007
|
configPath,
|
|
1421
1008
|
removed: false,
|
|
1422
1009
|
configFileDeleted: false
|
|
1423
1010
|
};
|
|
1424
1011
|
}
|
|
1425
1012
|
const newContent = removePluginFromContent(content, "opendevbrowser");
|
|
1426
|
-
|
|
1013
|
+
fs5.writeFileSync(configPath, newContent, "utf-8");
|
|
1427
1014
|
let configFileDeleted = false;
|
|
1428
1015
|
if (deleteConfigFile) {
|
|
1429
1016
|
configFileDeleted = removePluginConfigFile(mode);
|
|
@@ -1447,19 +1034,10 @@ function runUninstall(mode, deleteConfigFile = false) {
|
|
|
1447
1034
|
}
|
|
1448
1035
|
}
|
|
1449
1036
|
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 };
|
|
1037
|
+
return {
|
|
1038
|
+
global: hasInstalledConfig("global") || hasManagedBundledSkillInstall("global") || hasBundledSkillArtifacts("global"),
|
|
1039
|
+
local: hasInstalledConfig("local") || hasManagedBundledSkillInstall("local") || hasBundledSkillArtifacts("local")
|
|
1040
|
+
};
|
|
1463
1041
|
}
|
|
1464
1042
|
|
|
1465
1043
|
// src/cli/commands/serve.ts
|
|
@@ -1549,8 +1127,8 @@ function parseRepeatedStringFlag(rawArgs, flag) {
|
|
|
1549
1127
|
}
|
|
1550
1128
|
|
|
1551
1129
|
// src/cli/commands/native.ts
|
|
1552
|
-
import * as
|
|
1553
|
-
import * as
|
|
1130
|
+
import * as fs6 from "fs";
|
|
1131
|
+
import * as path4 from "path";
|
|
1554
1132
|
import { execFileSync } from "child_process";
|
|
1555
1133
|
import { fileURLToPath } from "url";
|
|
1556
1134
|
var EXTENSION_ID_RE = /^[a-p]{32}$/;
|
|
@@ -1585,33 +1163,33 @@ var parseNativeArgs = (rawArgs) => {
|
|
|
1585
1163
|
};
|
|
1586
1164
|
var getManifestDir = () => {
|
|
1587
1165
|
if (process.platform === "darwin") {
|
|
1588
|
-
return
|
|
1166
|
+
return path4.join(process.env.HOME || "", "Library", "Application Support", "Google", "Chrome", "NativeMessagingHosts");
|
|
1589
1167
|
}
|
|
1590
1168
|
if (process.platform === "linux") {
|
|
1591
|
-
return
|
|
1169
|
+
return path4.join(process.env.HOME || "", ".config", "google-chrome", "NativeMessagingHosts");
|
|
1592
1170
|
}
|
|
1593
1171
|
if (process.platform === "win32") {
|
|
1594
|
-
const base = process.env.LOCALAPPDATA || (process.env.USERPROFILE ?
|
|
1172
|
+
const base = process.env.LOCALAPPDATA || (process.env.USERPROFILE ? path4.join(process.env.USERPROFILE, "AppData", "Local") : "");
|
|
1595
1173
|
if (!base) {
|
|
1596
1174
|
throw createUsageError("LOCALAPPDATA is not set. Unable to locate NativeMessagingHosts directory.");
|
|
1597
1175
|
}
|
|
1598
|
-
return
|
|
1176
|
+
return path4.join(base, "Google", "Chrome", "User Data", "NativeMessagingHosts");
|
|
1599
1177
|
}
|
|
1600
1178
|
throw createUsageError(`Native messaging is not supported on ${process.platform}.`);
|
|
1601
1179
|
};
|
|
1602
1180
|
var getScriptsDir = () => {
|
|
1603
1181
|
const __filename = fileURLToPath(import.meta.url);
|
|
1604
|
-
const startDir =
|
|
1182
|
+
const startDir = path4.dirname(__filename);
|
|
1605
1183
|
const rootsToScan = [startDir, process.cwd()];
|
|
1606
1184
|
for (const root of rootsToScan) {
|
|
1607
|
-
let current =
|
|
1185
|
+
let current = path4.resolve(root);
|
|
1608
1186
|
while (true) {
|
|
1609
|
-
const scriptsDir =
|
|
1610
|
-
const packageJsonPath =
|
|
1611
|
-
if (
|
|
1187
|
+
const scriptsDir = path4.join(current, "scripts", "native");
|
|
1188
|
+
const packageJsonPath = path4.join(current, "package.json");
|
|
1189
|
+
if (fs6.existsSync(scriptsDir) && fs6.existsSync(packageJsonPath)) {
|
|
1612
1190
|
return scriptsDir;
|
|
1613
1191
|
}
|
|
1614
|
-
const parent =
|
|
1192
|
+
const parent = path4.dirname(current);
|
|
1615
1193
|
if (parent === current) {
|
|
1616
1194
|
break;
|
|
1617
1195
|
}
|
|
@@ -1621,18 +1199,18 @@ var getScriptsDir = () => {
|
|
|
1621
1199
|
throw createUsageError("Unable to locate scripts/native directory.");
|
|
1622
1200
|
};
|
|
1623
1201
|
var getHostScriptPath = () => {
|
|
1624
|
-
return
|
|
1202
|
+
return path4.join(getScriptsDir(), "host.cjs");
|
|
1625
1203
|
};
|
|
1626
1204
|
var getManifestPath = () => {
|
|
1627
|
-
return
|
|
1205
|
+
return path4.join(getManifestDir(), "com.opendevbrowser.native.json");
|
|
1628
1206
|
};
|
|
1629
1207
|
var getWrapperPath = () => {
|
|
1630
1208
|
const wrapperName = process.platform === "win32" ? "com.opendevbrowser.native.cmd" : "com.opendevbrowser.native.sh";
|
|
1631
|
-
return
|
|
1209
|
+
return path4.join(getManifestDir(), wrapperName);
|
|
1632
1210
|
};
|
|
1633
1211
|
var readManifest = (manifestPath) => {
|
|
1634
1212
|
try {
|
|
1635
|
-
const raw =
|
|
1213
|
+
const raw = fs6.readFileSync(manifestPath, "utf8");
|
|
1636
1214
|
const data = JSON.parse(raw);
|
|
1637
1215
|
const origins = Array.isArray(data.allowed_origins) ? data.allowed_origins : [];
|
|
1638
1216
|
const match = origins.find((origin) => origin.startsWith("chrome-extension://"));
|
|
@@ -1669,9 +1247,9 @@ var readRegistryPath = () => {
|
|
|
1669
1247
|
};
|
|
1670
1248
|
var normalizePath = (value) => {
|
|
1671
1249
|
try {
|
|
1672
|
-
return
|
|
1250
|
+
return fs6.realpathSync(value);
|
|
1673
1251
|
} catch {
|
|
1674
|
-
return
|
|
1252
|
+
return path4.resolve(value);
|
|
1675
1253
|
}
|
|
1676
1254
|
};
|
|
1677
1255
|
var findExtensionIdInCommands = (preferences) => {
|
|
@@ -1732,8 +1310,8 @@ var getExtensionPathCandidates = () => {
|
|
|
1732
1310
|
if (primary) {
|
|
1733
1311
|
candidates.add(normalizePath(primary));
|
|
1734
1312
|
}
|
|
1735
|
-
const cwdExtension =
|
|
1736
|
-
if (
|
|
1313
|
+
const cwdExtension = path4.join(process.cwd(), "extension");
|
|
1314
|
+
if (fs6.existsSync(path4.join(cwdExtension, "manifest.json"))) {
|
|
1737
1315
|
candidates.add(normalizePath(cwdExtension));
|
|
1738
1316
|
}
|
|
1739
1317
|
if (candidates.size === 0) {
|
|
@@ -1818,13 +1396,13 @@ var getNativeStatusSnapshot = () => {
|
|
|
1818
1396
|
let manifestExists = false;
|
|
1819
1397
|
let wrapperExists = false;
|
|
1820
1398
|
let extensionIdValue = null;
|
|
1821
|
-
if (
|
|
1399
|
+
if (fs6.existsSync(manifestPath)) {
|
|
1822
1400
|
manifestExists = true;
|
|
1823
1401
|
installed = true;
|
|
1824
1402
|
const manifest = readManifest(manifestPath);
|
|
1825
1403
|
extensionIdValue = manifest.extensionId;
|
|
1826
1404
|
}
|
|
1827
|
-
if (
|
|
1405
|
+
if (fs6.existsSync(wrapperPath)) {
|
|
1828
1406
|
wrapperExists = true;
|
|
1829
1407
|
}
|
|
1830
1408
|
if (!manifestExists || !wrapperExists) {
|
|
@@ -1884,7 +1462,7 @@ function installNativeHost(extensionId) {
|
|
|
1884
1462
|
};
|
|
1885
1463
|
}
|
|
1886
1464
|
const hostScript = getHostScriptPath();
|
|
1887
|
-
if (!
|
|
1465
|
+
if (!fs6.existsSync(hostScript)) {
|
|
1888
1466
|
return {
|
|
1889
1467
|
success: false,
|
|
1890
1468
|
message: `Native host not found at ${hostScript}.`,
|
|
@@ -1893,7 +1471,7 @@ function installNativeHost(extensionId) {
|
|
|
1893
1471
|
}
|
|
1894
1472
|
const scriptsDir = getScriptsDir();
|
|
1895
1473
|
const manifestPath = getManifestPath();
|
|
1896
|
-
const installScript = process.platform === "win32" ?
|
|
1474
|
+
const installScript = process.platform === "win32" ? path4.join(scriptsDir, "install.ps1") : path4.join(scriptsDir, "install.sh");
|
|
1897
1475
|
try {
|
|
1898
1476
|
runScript(installScript, [normalized]);
|
|
1899
1477
|
return {
|
|
@@ -1913,7 +1491,7 @@ function installNativeHost(extensionId) {
|
|
|
1913
1491
|
async function runNativeCommand(args) {
|
|
1914
1492
|
const { subcommand, extensionId } = parseNativeArgs(args.rawArgs);
|
|
1915
1493
|
const scriptsDir = getScriptsDir();
|
|
1916
|
-
const uninstallScript = process.platform === "win32" ?
|
|
1494
|
+
const uninstallScript = process.platform === "win32" ? path4.join(scriptsDir, "uninstall.ps1") : path4.join(scriptsDir, "uninstall.sh");
|
|
1917
1495
|
if (subcommand === "install") {
|
|
1918
1496
|
return installNativeHost(extensionId);
|
|
1919
1497
|
}
|
|
@@ -2289,9 +1867,9 @@ ${nativeMessage}${fingerprintNote}${staleNote}` : `${baseMessage}${fingerprintNo
|
|
|
2289
1867
|
|
|
2290
1868
|
// src/cli/daemon-autostart.ts
|
|
2291
1869
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
2292
|
-
import { existsSync as
|
|
2293
|
-
import { homedir as
|
|
2294
|
-
import { dirname as
|
|
1870
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync2, unlinkSync as unlinkSync2, writeFileSync as writeFileSync4 } from "fs";
|
|
1871
|
+
import { homedir as homedir4, tmpdir } from "os";
|
|
1872
|
+
import { dirname as dirname3, isAbsolute, join as join5, relative, resolve as resolve3 } from "path";
|
|
2295
1873
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
2296
1874
|
var MAC_LABEL = "com.opendevbrowser.daemon";
|
|
2297
1875
|
var WIN_TASK_NAME = "OpenDevBrowser Daemon";
|
|
@@ -2301,9 +1879,9 @@ var defaultDeps = () => ({
|
|
|
2301
1879
|
argv1: process.argv[1] ?? "",
|
|
2302
1880
|
moduleUrl: import.meta.url,
|
|
2303
1881
|
uid: typeof process.getuid === "function" ? process.getuid() : 0,
|
|
2304
|
-
homedir:
|
|
2305
|
-
existsSync:
|
|
2306
|
-
mkdirSync:
|
|
1882
|
+
homedir: homedir4,
|
|
1883
|
+
existsSync: existsSync5,
|
|
1884
|
+
mkdirSync: mkdirSync2,
|
|
2307
1885
|
writeFileSync: writeFileSync4,
|
|
2308
1886
|
unlinkSync: unlinkSync2,
|
|
2309
1887
|
execFileSync: execFileSync2,
|
|
@@ -2315,14 +1893,14 @@ var formatCommand = (programArguments) => {
|
|
|
2315
1893
|
};
|
|
2316
1894
|
var resolveCliPathFromModule = (moduleUrl, exists) => {
|
|
2317
1895
|
const modulePath = fileURLToPath2(moduleUrl);
|
|
2318
|
-
const candidate =
|
|
1896
|
+
const candidate = resolve3(dirname3(modulePath), "..", "index.js");
|
|
2319
1897
|
if (!exists(candidate)) {
|
|
2320
1898
|
throw new Error(`CLI entrypoint not found at ${candidate}`);
|
|
2321
1899
|
}
|
|
2322
1900
|
return candidate;
|
|
2323
1901
|
};
|
|
2324
1902
|
var normalizeComparisonPath = (value, platform) => {
|
|
2325
|
-
const resolvedPath =
|
|
1903
|
+
const resolvedPath = resolve3(value);
|
|
2326
1904
|
return platform === "win32" ? resolvedPath.toLowerCase() : resolvedPath;
|
|
2327
1905
|
};
|
|
2328
1906
|
var isPathInsideRoot = (candidate, root, platform) => {
|
|
@@ -2357,7 +1935,7 @@ var resolveCliEntrypoint = (deps = {}) => {
|
|
|
2357
1935
|
let cliPath = null;
|
|
2358
1936
|
let source = "module";
|
|
2359
1937
|
if (resolved.argv1) {
|
|
2360
|
-
const candidate =
|
|
1938
|
+
const candidate = resolve3(resolved.argv1);
|
|
2361
1939
|
if (exists(candidate)) {
|
|
2362
1940
|
cliPath = candidate;
|
|
2363
1941
|
source = "argv1";
|
|
@@ -2372,13 +1950,13 @@ var resolveCliEntrypoint = (deps = {}) => {
|
|
|
2372
1950
|
const isTransient = isTransientCliPath(cliPath, resolved);
|
|
2373
1951
|
return { nodePath, cliPath, args, command, source, isTransient };
|
|
2374
1952
|
};
|
|
2375
|
-
var getLaunchAgentPath = (home =
|
|
2376
|
-
return
|
|
1953
|
+
var getLaunchAgentPath = (home = homedir4()) => {
|
|
1954
|
+
return join5(home, "Library", "LaunchAgents", `${MAC_LABEL}.plist`);
|
|
2377
1955
|
};
|
|
2378
1956
|
var buildLaunchAgentPlist = (entrypoint, options = {}) => {
|
|
2379
1957
|
const label = options.label ?? MAC_LABEL;
|
|
2380
|
-
const stdoutPath = options.stdoutPath ??
|
|
2381
|
-
const stderrPath = options.stderrPath ??
|
|
1958
|
+
const stdoutPath = options.stdoutPath ?? join5(homedir4(), "Library", "Logs", "opendevbrowser-daemon.log");
|
|
1959
|
+
const stderrPath = options.stderrPath ?? join5(homedir4(), "Library", "Logs", "opendevbrowser-daemon.err.log");
|
|
2382
1960
|
const programArgs = [entrypoint.nodePath, ...entrypoint.args].map((value) => ` <string>${value}</string>`).join("\n");
|
|
2383
1961
|
return [
|
|
2384
1962
|
'<?xml version="1.0" encoding="UTF-8"?>',
|
|
@@ -2583,10 +2161,10 @@ var installMacAutostart = (deps = {}) => {
|
|
|
2583
2161
|
assertPersistentEntrypoint(entrypoint);
|
|
2584
2162
|
const home = resolved.homedir();
|
|
2585
2163
|
const plistPath = getLaunchAgentPath(home);
|
|
2586
|
-
const stdoutPath =
|
|
2587
|
-
const stderrPath =
|
|
2588
|
-
const logsDir =
|
|
2589
|
-
resolved.mkdirSync(
|
|
2164
|
+
const stdoutPath = join5(home, "Library", "Logs", "opendevbrowser-daemon.log");
|
|
2165
|
+
const stderrPath = join5(home, "Library", "Logs", "opendevbrowser-daemon.err.log");
|
|
2166
|
+
const logsDir = dirname3(stdoutPath);
|
|
2167
|
+
resolved.mkdirSync(dirname3(plistPath), { recursive: true });
|
|
2590
2168
|
resolved.mkdirSync(logsDir, { recursive: true });
|
|
2591
2169
|
resolved.writeFileSync(
|
|
2592
2170
|
plistPath,
|
|
@@ -2963,7 +2541,7 @@ async function runDaemonCommand(args) {
|
|
|
2963
2541
|
}
|
|
2964
2542
|
|
|
2965
2543
|
// src/cli/commands/artifacts.ts
|
|
2966
|
-
import { join as
|
|
2544
|
+
import { join as join6, resolve as resolve4 } from "path";
|
|
2967
2545
|
import { tmpdir as tmpdir2 } from "os";
|
|
2968
2546
|
var PASSTHROUGH_BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
|
|
2969
2547
|
"--with-config",
|
|
@@ -3052,7 +2630,7 @@ var parseArtifactsArgs = (rawArgs) => {
|
|
|
3052
2630
|
};
|
|
3053
2631
|
async function runArtifactsCommand(args) {
|
|
3054
2632
|
const parsed = parseArtifactsArgs(args.rawArgs);
|
|
3055
|
-
const rootDir = parsed.outputDir ?
|
|
2633
|
+
const rootDir = parsed.outputDir ? resolve4(parsed.outputDir) : join6(tmpdir2(), "opendevbrowser");
|
|
3056
2634
|
const cleaned = await cleanupExpiredArtifacts(rootDir);
|
|
3057
2635
|
return {
|
|
3058
2636
|
success: true,
|
|
@@ -3163,34 +2741,34 @@ function formatAutostartReconciliationMessage(result) {
|
|
|
3163
2741
|
}
|
|
3164
2742
|
|
|
3165
2743
|
// src/cli/commands/run.ts
|
|
3166
|
-
import { readFileSync as
|
|
2744
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
3167
2745
|
|
|
3168
2746
|
// src/cli/output.ts
|
|
3169
2747
|
var normalizeExitCode = (code) => {
|
|
3170
2748
|
return Number.isInteger(code) ? Number(code) : 0;
|
|
3171
2749
|
};
|
|
3172
2750
|
var flushStream = (stream) => {
|
|
3173
|
-
return new Promise((
|
|
2751
|
+
return new Promise((resolve5) => {
|
|
3174
2752
|
if (!stream || typeof stream.write !== "function") {
|
|
3175
|
-
|
|
2753
|
+
resolve5();
|
|
3176
2754
|
return;
|
|
3177
2755
|
}
|
|
3178
2756
|
try {
|
|
3179
|
-
stream.write("", () =>
|
|
2757
|
+
stream.write("", () => resolve5());
|
|
3180
2758
|
} catch {
|
|
3181
|
-
|
|
2759
|
+
resolve5();
|
|
3182
2760
|
}
|
|
3183
2761
|
});
|
|
3184
2762
|
};
|
|
3185
2763
|
async function flushOutputAndExit(code, proc = process, timeoutMs = 250) {
|
|
3186
2764
|
const finalCode = normalizeExitCode(code);
|
|
3187
2765
|
proc.exitCode = finalCode;
|
|
3188
|
-
await new Promise((
|
|
2766
|
+
await new Promise((resolve5) => {
|
|
3189
2767
|
let settled = false;
|
|
3190
2768
|
const finish = () => {
|
|
3191
2769
|
if (settled) return;
|
|
3192
2770
|
settled = true;
|
|
3193
|
-
|
|
2771
|
+
resolve5();
|
|
3194
2772
|
};
|
|
3195
2773
|
const timer = setTimeout(finish, Math.max(0, timeoutMs));
|
|
3196
2774
|
timer.unref?.();
|
|
@@ -3312,13 +2890,13 @@ function parseRunArgs(rawArgs) {
|
|
|
3312
2890
|
return parsed;
|
|
3313
2891
|
}
|
|
3314
2892
|
function readScriptFromStdin() {
|
|
3315
|
-
return new Promise((
|
|
2893
|
+
return new Promise((resolve5, reject) => {
|
|
3316
2894
|
let data = "";
|
|
3317
2895
|
process.stdin.setEncoding("utf8");
|
|
3318
2896
|
process.stdin.on("data", (chunk) => {
|
|
3319
2897
|
data += chunk;
|
|
3320
2898
|
});
|
|
3321
|
-
process.stdin.on("end", () =>
|
|
2899
|
+
process.stdin.on("end", () => resolve5(data));
|
|
3322
2900
|
process.stdin.on("error", reject);
|
|
3323
2901
|
});
|
|
3324
2902
|
}
|
|
@@ -3327,7 +2905,7 @@ async function runScriptCommand(args) {
|
|
|
3327
2905
|
const outputOptions = { format: args.outputFormat, quiet: args.quiet };
|
|
3328
2906
|
let scriptRaw = "";
|
|
3329
2907
|
if (runArgs.scriptPath) {
|
|
3330
|
-
scriptRaw =
|
|
2908
|
+
scriptRaw = readFileSync2(runArgs.scriptPath, "utf-8");
|
|
3331
2909
|
} else if (!process.stdin.isTTY) {
|
|
3332
2910
|
scriptRaw = await readScriptFromStdin();
|
|
3333
2911
|
} else {
|
|
@@ -3552,16 +3130,16 @@ function promptYesNo(question, defaultYes) {
|
|
|
3552
3130
|
return Promise.resolve(false);
|
|
3553
3131
|
}
|
|
3554
3132
|
const suffix = defaultYes ? " [Y/n] " : " [y/N] ";
|
|
3555
|
-
return new Promise((
|
|
3133
|
+
return new Promise((resolve5) => {
|
|
3556
3134
|
process.stdout.write(`${question}${suffix}`);
|
|
3557
3135
|
process.stdin.setEncoding("utf8");
|
|
3558
3136
|
process.stdin.once("data", (data) => {
|
|
3559
3137
|
const input = data.toString().trim().toLowerCase();
|
|
3560
3138
|
if (!input) {
|
|
3561
|
-
|
|
3139
|
+
resolve5(defaultYes);
|
|
3562
3140
|
return;
|
|
3563
3141
|
}
|
|
3564
|
-
|
|
3142
|
+
resolve5(input === "y" || input === "yes");
|
|
3565
3143
|
});
|
|
3566
3144
|
});
|
|
3567
3145
|
}
|
|
@@ -3681,6 +3259,12 @@ async function runSessionDisconnect(args) {
|
|
|
3681
3259
|
// src/cli/utils/workflow-message.ts
|
|
3682
3260
|
var asRecord = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
3683
3261
|
var readNonEmptyString = (value) => typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
|
|
3262
|
+
var UNRESOLVED_COMMAND_PLACEHOLDER_RE = /<[^>\n]+>/;
|
|
3263
|
+
var readRunnableStepCommand = (step) => {
|
|
3264
|
+
const command = readNonEmptyString(step.command);
|
|
3265
|
+
if (!command) return null;
|
|
3266
|
+
return UNRESOLVED_COMMAND_PLACEHOLDER_RE.test(command) ? null : command;
|
|
3267
|
+
};
|
|
3684
3268
|
var readMeta = (data) => {
|
|
3685
3269
|
return asRecord(asRecord(data)?.meta);
|
|
3686
3270
|
};
|
|
@@ -3728,6 +3312,17 @@ var readSuggestedNextAction = (data) => {
|
|
|
3728
3312
|
if (!record) return null;
|
|
3729
3313
|
return readNonEmptyString(record.suggestedNextAction) ?? readNonEmptyString(asRecord(record.sessionInspector)?.suggestedNextAction);
|
|
3730
3314
|
};
|
|
3315
|
+
var readSuggestedStepCommand = (data) => {
|
|
3316
|
+
let current = asRecord(data);
|
|
3317
|
+
while (current) {
|
|
3318
|
+
const command = readSuggestedSteps(current).map(readRunnableStepCommand).find((step) => Boolean(step));
|
|
3319
|
+
if (command) {
|
|
3320
|
+
return command;
|
|
3321
|
+
}
|
|
3322
|
+
current = asRecord(current.challengePlan);
|
|
3323
|
+
}
|
|
3324
|
+
return null;
|
|
3325
|
+
};
|
|
3731
3326
|
var readSuggestedStepReason = (data) => {
|
|
3732
3327
|
let current = asRecord(data);
|
|
3733
3328
|
while (current) {
|
|
@@ -3758,7 +3353,7 @@ var buildWorkflowCompletionMessage = (workflowLabel, data) => {
|
|
|
3758
3353
|
if (followthroughSummary) {
|
|
3759
3354
|
return buildNextStepMessage(
|
|
3760
3355
|
`${workflowLabel} completed. ${followthroughSummary}`,
|
|
3761
|
-
readSuggestedNextAction(data) ?? readSuggestedStepReason(data)
|
|
3356
|
+
readSuggestedNextAction(data) ?? readSuggestedStepCommand(data) ?? readSuggestedStepReason(data)
|
|
3762
3357
|
);
|
|
3763
3358
|
}
|
|
3764
3359
|
return `${workflowLabel} completed.`;
|
|
@@ -4519,7 +4114,7 @@ async function runAnnotate(args) {
|
|
|
4519
4114
|
}
|
|
4520
4115
|
|
|
4521
4116
|
// src/cli/commands/canvas.ts
|
|
4522
|
-
import { readFileSync as
|
|
4117
|
+
import { readFileSync as readFileSync3 } from "fs";
|
|
4523
4118
|
var DEFAULT_FEEDBACK_STREAM_TIMEOUT_MS = 3e4;
|
|
4524
4119
|
var isRecord = (value) => {
|
|
4525
4120
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -4720,7 +4315,7 @@ var resolveCanvasParams = (canvasArgs) => {
|
|
|
4720
4315
|
if (hasParamsFile) {
|
|
4721
4316
|
let raw = "";
|
|
4722
4317
|
try {
|
|
4723
|
-
raw =
|
|
4318
|
+
raw = readFileSync3(canvasArgs.paramsFile ?? "", "utf8");
|
|
4724
4319
|
} catch (error) {
|
|
4725
4320
|
const message = error instanceof Error ? error.message : "Unable to read file";
|
|
4726
4321
|
throw createUsageError(`Invalid --params-file: ${message}`);
|
|
@@ -4789,7 +4384,7 @@ async function runCanvas(args) {
|
|
|
4789
4384
|
}
|
|
4790
4385
|
|
|
4791
4386
|
// src/cli/commands/rpc.ts
|
|
4792
|
-
import { readFileSync as
|
|
4387
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
4793
4388
|
var requireValue4 = (value, flag) => {
|
|
4794
4389
|
if (!value) throw createUsageError(`Missing value for ${flag}`);
|
|
4795
4390
|
return value;
|
|
@@ -4869,7 +4464,7 @@ var resolveRpcParams = (rpcArgs) => {
|
|
|
4869
4464
|
if (hasParamsFile) {
|
|
4870
4465
|
let raw = "";
|
|
4871
4466
|
try {
|
|
4872
|
-
raw =
|
|
4467
|
+
raw = readFileSync4(rpcArgs.paramsFile ?? "", "utf8");
|
|
4873
4468
|
} catch (error) {
|
|
4874
4469
|
const message = error instanceof Error ? error.message : "Unable to read file";
|
|
4875
4470
|
throw createUsageError(`Invalid --params-file: ${message}`);
|
|
@@ -6249,11 +5844,11 @@ function parseScreenshotArgs(rawArgs) {
|
|
|
6249
5844
|
return parsed;
|
|
6250
5845
|
}
|
|
6251
5846
|
async function runScreenshot(args) {
|
|
6252
|
-
const { sessionId, targetId, path:
|
|
5847
|
+
const { sessionId, targetId, path: path5, ref, fullPage, timeoutMs } = parseScreenshotArgs(args.rawArgs);
|
|
6253
5848
|
if (!sessionId) throw createUsageError("Missing --session-id");
|
|
6254
5849
|
const params = {
|
|
6255
5850
|
sessionId,
|
|
6256
|
-
...typeof
|
|
5851
|
+
...typeof path5 === "string" ? { path: path5 } : {},
|
|
6257
5852
|
...typeof targetId === "string" ? { targetId } : {},
|
|
6258
5853
|
...typeof ref === "string" ? { ref } : {},
|
|
6259
5854
|
...fullPage === true ? { fullPage: true } : {}
|
|
@@ -6652,7 +6247,7 @@ async function runDesktopAccessibilitySnapshot(args) {
|
|
|
6652
6247
|
}
|
|
6653
6248
|
|
|
6654
6249
|
// src/cli/commands/session/cookie-import.ts
|
|
6655
|
-
import { readFileSync as
|
|
6250
|
+
import { readFileSync as readFileSync5 } from "fs";
|
|
6656
6251
|
var requireValue5 = (value, flag) => {
|
|
6657
6252
|
if (!value) {
|
|
6658
6253
|
throw createUsageError(`Missing value for ${flag}`);
|
|
@@ -6767,7 +6362,7 @@ var resolveCookies = (parsed) => {
|
|
|
6767
6362
|
}
|
|
6768
6363
|
let raw = "";
|
|
6769
6364
|
try {
|
|
6770
|
-
raw =
|
|
6365
|
+
raw = readFileSync5(parsed.cookiesFile ?? "", "utf8");
|
|
6771
6366
|
} catch (error) {
|
|
6772
6367
|
const message = error instanceof Error ? error.message : "Unable to read file";
|
|
6773
6368
|
throw createUsageError(`Invalid --cookies-file: ${message}`);
|
|
@@ -6904,12 +6499,28 @@ var asRecord2 = (value) => {
|
|
|
6904
6499
|
}
|
|
6905
6500
|
return value;
|
|
6906
6501
|
};
|
|
6502
|
+
var readNonEmptyString2 = (value) => typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
|
|
6907
6503
|
var hasExecutionBlocker = (result) => {
|
|
6908
6504
|
const execution = asRecord2(asRecord2(result)?.execution);
|
|
6909
6505
|
const meta = asRecord2(execution?.meta);
|
|
6910
6506
|
return asRecord2(meta?.blocker) !== null;
|
|
6911
6507
|
};
|
|
6508
|
+
var readMacroResolveSummary = (result) => readNonEmptyString2(asRecord2(result)?.followthroughSummary);
|
|
6509
|
+
var readMacroResolveNextStep = (result) => {
|
|
6510
|
+
const record = asRecord2(result);
|
|
6511
|
+
const explicit = readNonEmptyString2(record?.suggestedNextAction);
|
|
6512
|
+
if (explicit) {
|
|
6513
|
+
return explicit;
|
|
6514
|
+
}
|
|
6515
|
+
const [firstStep] = Array.isArray(record?.suggestedSteps) ? record.suggestedSteps.filter((step) => Boolean(step) && typeof step === "object") : [];
|
|
6516
|
+
return readNonEmptyString2(firstStep?.command) ?? readNonEmptyString2(firstStep?.reason);
|
|
6517
|
+
};
|
|
6912
6518
|
var buildMacroResolveMessage = (execute, result) => {
|
|
6519
|
+
const summary = readMacroResolveSummary(result);
|
|
6520
|
+
const nextStep = readMacroResolveNextStep(result);
|
|
6521
|
+
if (summary) {
|
|
6522
|
+
return nextStep ? `${summary} Next step: ${nextStep}` : summary;
|
|
6523
|
+
}
|
|
6913
6524
|
if (!execute) {
|
|
6914
6525
|
return "Macro resolved.";
|
|
6915
6526
|
}
|
|
@@ -7803,7 +7414,7 @@ async function runInspiredesignCommand(args) {
|
|
|
7803
7414
|
// package.json
|
|
7804
7415
|
var package_default = {
|
|
7805
7416
|
name: "opendevbrowser",
|
|
7806
|
-
version: "0.0.
|
|
7417
|
+
version: "0.0.23",
|
|
7807
7418
|
description: "Browser automation runtime with snapshot-refs-actions, browser replay screencasts, public read-only desktop observation, and browser-scoped computer-use orchestration",
|
|
7808
7419
|
type: "module",
|
|
7809
7420
|
main: "dist/index.js",
|
|
@@ -7814,6 +7425,7 @@ var package_default = {
|
|
|
7814
7425
|
files: [
|
|
7815
7426
|
"dist",
|
|
7816
7427
|
"skills",
|
|
7428
|
+
"scripts/postinstall-sync-skills.mjs",
|
|
7817
7429
|
"scripts/native",
|
|
7818
7430
|
"extension/canvas.html",
|
|
7819
7431
|
"extension/manifest.json",
|
|
@@ -7848,8 +7460,8 @@ var package_default = {
|
|
|
7848
7460
|
node: ">=18"
|
|
7849
7461
|
},
|
|
7850
7462
|
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",
|
|
7463
|
+
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",
|
|
7464
|
+
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
7465
|
lint: 'node scripts/run-package-tool.mjs eslint "src/**/*.ts" "tests/**/*.ts"',
|
|
7854
7466
|
typecheck: "node scripts/run-package-tool.mjs tsc --noEmit -p tsconfig.json",
|
|
7855
7467
|
test: "node scripts/run-vitest-coverage.mjs",
|
|
@@ -7864,7 +7476,8 @@ var package_default = {
|
|
|
7864
7476
|
"extension:pack": "cd extension && zip -r ../opendevbrowser-extension.zip manifest.json popup.html canvas.html dist/ icons/",
|
|
7865
7477
|
"extension:store": "node scripts/chrome-store-publish.mjs",
|
|
7866
7478
|
"version:check": "node scripts/verify-versions.mjs",
|
|
7867
|
-
prepack: "npm run version:check && npm run build && npm run extension:build"
|
|
7479
|
+
prepack: "npm run version:check && npm run build && npm run extension:build",
|
|
7480
|
+
postinstall: "node scripts/postinstall-sync-skills.mjs"
|
|
7868
7481
|
},
|
|
7869
7482
|
dependencies: {
|
|
7870
7483
|
"@opencode-ai/plugin": "^1.2.25",
|
|
@@ -7892,8 +7505,10 @@ var package_default = {
|
|
|
7892
7505
|
}
|
|
7893
7506
|
};
|
|
7894
7507
|
|
|
7895
|
-
// src/cli/
|
|
7896
|
-
|
|
7508
|
+
// src/cli/update-skill-modes.ts
|
|
7509
|
+
function shouldRefreshManagedSkills(mode) {
|
|
7510
|
+
return hasManagedBundledSkillInstall(mode) || hasBundledSkillArtifacts(mode);
|
|
7511
|
+
}
|
|
7897
7512
|
function resolveUpdateSkillModes(args) {
|
|
7898
7513
|
if (args.rawArgs.includes("--no-skills")) {
|
|
7899
7514
|
return [];
|
|
@@ -7907,22 +7522,102 @@ function resolveUpdateSkillModes(args) {
|
|
|
7907
7522
|
if (args.mode) {
|
|
7908
7523
|
return [args.mode];
|
|
7909
7524
|
}
|
|
7910
|
-
const installed = findInstalledConfigs();
|
|
7911
7525
|
const modes = [];
|
|
7912
|
-
if (
|
|
7526
|
+
if (shouldRefreshManagedSkills("global")) {
|
|
7913
7527
|
modes.push("global");
|
|
7914
7528
|
}
|
|
7915
|
-
if (
|
|
7529
|
+
if (shouldRefreshManagedSkills("local")) {
|
|
7916
7530
|
modes.push("local");
|
|
7917
7531
|
}
|
|
7918
7532
|
return modes;
|
|
7919
7533
|
}
|
|
7534
|
+
|
|
7535
|
+
// src/cli/skill-lifecycle.ts
|
|
7536
|
+
function shouldSkipSkills(args) {
|
|
7537
|
+
return args.rawArgs.includes("--no-skills");
|
|
7538
|
+
}
|
|
7539
|
+
function getUpdateTargets(args, mode, deps) {
|
|
7540
|
+
if (deps.hasInstalledConfig(mode)) {
|
|
7541
|
+
return deps.getBundledSkillTargets(mode);
|
|
7542
|
+
}
|
|
7543
|
+
return deps.getBundledSkillLifecycleTargets(mode, {
|
|
7544
|
+
includeLegacyArtifacts: deps.hasBundledSkillArtifacts(mode)
|
|
7545
|
+
});
|
|
7546
|
+
}
|
|
7547
|
+
function collectUpdateSkillResults(args, deps, modes) {
|
|
7548
|
+
return modes.flatMap((mode) => {
|
|
7549
|
+
const targets = getUpdateTargets(args, mode, deps);
|
|
7550
|
+
return targets.length > 0 ? [deps.syncBundledSkillsForTargets(mode, targets)] : [];
|
|
7551
|
+
});
|
|
7552
|
+
}
|
|
7553
|
+
function getResolvedUpdateSkillModes(args, result, deps) {
|
|
7554
|
+
return result.success ? deps.resolveUpdateSkillModes(args) : [];
|
|
7555
|
+
}
|
|
7556
|
+
function buildUpdateSkillMessage(args, result, skillResults) {
|
|
7557
|
+
if (!result.success) {
|
|
7558
|
+
return "";
|
|
7559
|
+
}
|
|
7560
|
+
if (shouldSkipSkills(args)) {
|
|
7561
|
+
return "Managed skill refresh skipped (--no-skills).";
|
|
7562
|
+
}
|
|
7563
|
+
if (skillResults.length === 0) {
|
|
7564
|
+
return "No managed skill packs required refresh.";
|
|
7565
|
+
}
|
|
7566
|
+
return skillResults.map((entry) => entry.message).join("\n");
|
|
7567
|
+
}
|
|
7568
|
+
function buildUpdateCommandResult(args, result, deps) {
|
|
7569
|
+
const skillModes = getResolvedUpdateSkillModes(args, result, deps);
|
|
7570
|
+
const skillResults = result.success && !shouldSkipSkills(args) ? collectUpdateSkillResults(args, deps, skillModes) : [];
|
|
7571
|
+
const message = [result.message, buildUpdateSkillMessage(args, result, skillResults)].filter(Boolean).join("\n");
|
|
7572
|
+
return {
|
|
7573
|
+
success: result.success && skillResults.every((entry) => entry.success),
|
|
7574
|
+
message,
|
|
7575
|
+
data: {
|
|
7576
|
+
cacheCleared: result.cleared,
|
|
7577
|
+
skillModes,
|
|
7578
|
+
skills: skillResults
|
|
7579
|
+
}
|
|
7580
|
+
};
|
|
7581
|
+
}
|
|
7582
|
+
function buildUninstallSkillMessage(args, result, skillsResult) {
|
|
7583
|
+
if (!result.success) {
|
|
7584
|
+
return "";
|
|
7585
|
+
}
|
|
7586
|
+
if (shouldSkipSkills(args)) {
|
|
7587
|
+
return "Managed skill cleanup skipped (--no-skills).";
|
|
7588
|
+
}
|
|
7589
|
+
return skillsResult?.message ?? "No managed skill packs required cleanup.";
|
|
7590
|
+
}
|
|
7591
|
+
function getUninstallTargets(args, mode, result, deps) {
|
|
7592
|
+
if (!result.success || shouldSkipSkills(args)) {
|
|
7593
|
+
return [];
|
|
7594
|
+
}
|
|
7595
|
+
return deps.getBundledSkillLifecycleTargets(mode, {
|
|
7596
|
+
includeLegacyArtifacts: result.removed || deps.hasBundledSkillArtifacts(mode)
|
|
7597
|
+
});
|
|
7598
|
+
}
|
|
7599
|
+
function buildUninstallCommandResult(args, mode, result, deps) {
|
|
7600
|
+
const targets = getUninstallTargets(args, mode, result, deps);
|
|
7601
|
+
const skillsResult = result.success && !shouldSkipSkills(args) ? targets.length > 0 ? deps.removeBundledSkillsForTargets(mode, targets) : createNoOpSkillRemovalResult(mode) : void 0;
|
|
7602
|
+
const skillMessage = buildUninstallSkillMessage(args, result, skillsResult);
|
|
7603
|
+
return {
|
|
7604
|
+
success: result.success && (skillsResult?.success ?? true),
|
|
7605
|
+
message: [result.message, skillMessage].filter(Boolean).join("\n"),
|
|
7606
|
+
data: {
|
|
7607
|
+
config: result,
|
|
7608
|
+
skills: skillsResult
|
|
7609
|
+
}
|
|
7610
|
+
};
|
|
7611
|
+
}
|
|
7612
|
+
|
|
7613
|
+
// src/cli/index.ts
|
|
7614
|
+
var VERSION = typeof package_default.version === "string" ? package_default.version : "0.0.0";
|
|
7920
7615
|
async function promptInstallMode() {
|
|
7921
7616
|
if (!process.stdin.isTTY) {
|
|
7922
7617
|
console.log("Non-interactive mode detected. Using global install.");
|
|
7923
7618
|
return "global";
|
|
7924
7619
|
}
|
|
7925
|
-
return new Promise((
|
|
7620
|
+
return new Promise((resolve5) => {
|
|
7926
7621
|
console.log("\nWhere would you like to install opendevbrowser?\n");
|
|
7927
7622
|
console.log(" 1. Global (~/.config/opencode/opencode.json)");
|
|
7928
7623
|
console.log(" 2. Local (./opencode.json in this project)\n");
|
|
@@ -7942,23 +7637,23 @@ async function promptInstallMode() {
|
|
|
7942
7637
|
resolved = true;
|
|
7943
7638
|
const input = data.toString().trim();
|
|
7944
7639
|
if (input === "2") {
|
|
7945
|
-
|
|
7640
|
+
resolve5("local");
|
|
7946
7641
|
} else {
|
|
7947
|
-
|
|
7642
|
+
resolve5("global");
|
|
7948
7643
|
}
|
|
7949
7644
|
});
|
|
7950
7645
|
process.stdin.once("close", () => {
|
|
7951
7646
|
cleanup();
|
|
7952
7647
|
if (resolved) return;
|
|
7953
7648
|
resolved = true;
|
|
7954
|
-
|
|
7649
|
+
resolve5("global");
|
|
7955
7650
|
});
|
|
7956
7651
|
timeoutId = setTimeout(() => {
|
|
7957
7652
|
timeoutId = null;
|
|
7958
7653
|
if (resolved) return;
|
|
7959
7654
|
resolved = true;
|
|
7960
7655
|
console.log("\nTimeout - using global install.");
|
|
7961
|
-
|
|
7656
|
+
resolve5("global");
|
|
7962
7657
|
}, 3e4);
|
|
7963
7658
|
});
|
|
7964
7659
|
}
|
|
@@ -7978,7 +7673,7 @@ async function promptUninstallMode() {
|
|
|
7978
7673
|
console.log("Plugin found in both global and local configs. Use --global or --local flag.");
|
|
7979
7674
|
return null;
|
|
7980
7675
|
}
|
|
7981
|
-
return new Promise((
|
|
7676
|
+
return new Promise((resolve5) => {
|
|
7982
7677
|
console.log("\nopendevbrowser is installed in multiple locations:\n");
|
|
7983
7678
|
console.log(" 1. Global (~/.config/opencode/opencode.json)");
|
|
7984
7679
|
console.log(" 2. Local (./opencode.json)");
|
|
@@ -7988,15 +7683,15 @@ async function promptUninstallMode() {
|
|
|
7988
7683
|
process.stdin.once("data", (data) => {
|
|
7989
7684
|
const input = data.toString().trim();
|
|
7990
7685
|
if (input === "1") {
|
|
7991
|
-
|
|
7686
|
+
resolve5("global");
|
|
7992
7687
|
} else if (input === "2") {
|
|
7993
|
-
|
|
7688
|
+
resolve5("local");
|
|
7994
7689
|
} else {
|
|
7995
|
-
|
|
7690
|
+
resolve5(null);
|
|
7996
7691
|
}
|
|
7997
7692
|
});
|
|
7998
7693
|
process.stdin.once("close", () => {
|
|
7999
|
-
|
|
7694
|
+
resolve5(null);
|
|
8000
7695
|
});
|
|
8001
7696
|
});
|
|
8002
7697
|
}
|
|
@@ -8054,22 +7749,14 @@ async function main() {
|
|
|
8054
7749
|
registerCommand({
|
|
8055
7750
|
name: "update",
|
|
8056
7751
|
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
|
-
}
|
|
7752
|
+
run: () => buildUpdateCommandResult(args, runUpdate(), {
|
|
7753
|
+
resolveUpdateSkillModes,
|
|
7754
|
+
hasInstalledConfig,
|
|
7755
|
+
hasBundledSkillArtifacts,
|
|
7756
|
+
getBundledSkillTargets,
|
|
7757
|
+
getBundledSkillLifecycleTargets,
|
|
7758
|
+
syncBundledSkillsForTargets
|
|
7759
|
+
})
|
|
8073
7760
|
});
|
|
8074
7761
|
registerCommand({
|
|
8075
7762
|
name: "uninstall",
|
|
@@ -8085,18 +7772,11 @@ async function main() {
|
|
|
8085
7772
|
if (!mode) {
|
|
8086
7773
|
return { success: false, message: "Error: Please specify --global or --local for uninstall.", exitCode: EXIT_USAGE };
|
|
8087
7774
|
}
|
|
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
|
-
};
|
|
7775
|
+
return buildUninstallCommandResult(args, mode, runUninstall(mode), {
|
|
7776
|
+
hasBundledSkillArtifacts,
|
|
7777
|
+
getBundledSkillLifecycleTargets,
|
|
7778
|
+
removeBundledSkillsForTargets
|
|
7779
|
+
});
|
|
8100
7780
|
}
|
|
8101
7781
|
});
|
|
8102
7782
|
registerCommand({
|