opendevbrowser 0.0.20 → 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 +18 -8
- package/dist/chunk-3ILXPKSJ.js +86 -0
- package/dist/chunk-3ILXPKSJ.js.map +1 -0
- package/dist/{chunk-LMNFPJRI.js → chunk-OGE5KJ4X.js} +18 -12
- package/dist/{chunk-LMNFPJRI.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/{chunk-C6QUKABT.js → chunk-ZE2E7ZGH.js} +243 -37
- package/dist/chunk-ZE2E7ZGH.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/help.d.ts.map +1 -1
- package/dist/cli/index.js +296 -617
- 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.map +1 -1
- package/dist/index.js +9 -8
- package/dist/index.js.map +1 -1
- package/dist/inspiredesign/handoff.d.ts +34 -0
- package/dist/inspiredesign/handoff.d.ts.map +1 -0
- package/dist/opendevbrowser.js +9 -8
- package/dist/opendevbrowser.js.map +1 -1
- package/dist/providers/inspiredesign-contract.d.ts +33 -0
- package/dist/providers/inspiredesign-contract.d.ts.map +1 -1
- package/dist/providers/renderer.d.ts +3 -1
- package/dist/providers/renderer.d.ts.map +1 -1
- package/dist/providers/workflow-handoff.d.ts +14 -0
- package/dist/providers/workflow-handoff.d.ts.map +1 -0
- package/dist/providers/workflows.d.ts.map +1 -1
- package/dist/{providers-3VBLTNAX.js → providers-ZIVHHH4F.js} +2 -2
- 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/skills/opendevbrowser-product-presentation-asset/SKILL.md +2 -2
- package/dist/chunk-3VA6XR25.js.map +0 -1
- package/dist/chunk-C6QUKABT.js.map +0 -1
- /package/dist/{providers-3VBLTNAX.js.map → providers-ZIVHHH4F.js.map} +0 -0
package/dist/cli/index.js
CHANGED
|
@@ -31,22 +31,39 @@ 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";
|
|
42
57
|
import "../chunk-Y2KL55OG.js";
|
|
43
58
|
import {
|
|
59
|
+
INSPIREDESIGN_HANDOFF_COMMANDS,
|
|
60
|
+
INSPIREDESIGN_HANDOFF_GUIDANCE,
|
|
44
61
|
cleanupExpiredArtifacts,
|
|
45
62
|
isChallengeAutomationMode,
|
|
46
63
|
setDefaultLogSink,
|
|
47
64
|
stderrSink,
|
|
48
65
|
summarizePrimaryProviderIssue
|
|
49
|
-
} from "../chunk-
|
|
66
|
+
} from "../chunk-ZE2E7ZGH.js";
|
|
50
67
|
import "../chunk-FUSXMW3G.js";
|
|
51
68
|
|
|
52
69
|
// src/cli/args.ts
|
|
@@ -449,7 +466,7 @@ var HELP_CAPABILITY_ENTRIES = [
|
|
|
449
466
|
description: "Control the bounded browser-scoped computer-use challenge lane with --challenge-automation-mode; the optional helper is not a desktop agent.",
|
|
450
467
|
details: [
|
|
451
468
|
{ label: "flag:", value: "--challenge-automation-mode off|browser|browser_with_helper" },
|
|
452
|
-
{ label: "works:", value: "research run, shopping run, product-video run, macro-resolve --execute" },
|
|
469
|
+
{ label: "works:", value: "research run, shopping run, product-video run, inspiredesign run, macro-resolve --execute" },
|
|
453
470
|
{ label: "entry:", value: onboarding_metadata_default.quickStartCommands.computerUseEntry },
|
|
454
471
|
{ label: "proof:", value: "review, session-inspector, workflow fallback metadata" }
|
|
455
472
|
]
|
|
@@ -486,6 +503,16 @@ var HELP_ONBOARDING_ENTRIES = [
|
|
|
486
503
|
description: "Start deal hunting with explicit providers in managed mode and only trust regional comparisons when the result reports `region_authoritative=true`.",
|
|
487
504
|
details: [{ label: "cli:", value: onboarding_metadata_default.quickStartCommands.validatedShopping }]
|
|
488
505
|
},
|
|
506
|
+
{
|
|
507
|
+
label: "inspiredesign_followthrough",
|
|
508
|
+
description: "After inspiredesign finishes, continue in Canvas with the emitted request template and load the canvas-contract design-agent lane before patching.",
|
|
509
|
+
details: [
|
|
510
|
+
{ label: "quick:", value: INSPIREDESIGN_HANDOFF_COMMANDS.loadBestPractices },
|
|
511
|
+
{ label: "design:", value: INSPIREDESIGN_HANDOFF_COMMANDS.loadDesignAgent },
|
|
512
|
+
{ label: "prep:", value: INSPIREDESIGN_HANDOFF_GUIDANCE.prepareCanvasPlanRequest },
|
|
513
|
+
{ label: "run:", value: INSPIREDESIGN_HANDOFF_COMMANDS.continueInCanvas }
|
|
514
|
+
]
|
|
515
|
+
},
|
|
489
516
|
{
|
|
490
517
|
label: "computer_use_entry",
|
|
491
518
|
description: "Enter browser-scoped computer use from a workflow run, not from a separate desktop command family.",
|
|
@@ -515,6 +542,7 @@ var HELP_ONBOARDING_ENTRIES = [
|
|
|
515
542
|
];
|
|
516
543
|
var HELP_REFERENCE_ENTRIES = [
|
|
517
544
|
{ label: "src/cli/onboarding-metadata.json", description: "Canonical first-contact onboarding metadata shared by help, nudges, and proof lanes." },
|
|
545
|
+
{ label: "src/inspiredesign/handoff.ts", description: "Shared inspiredesign follow-through commands, artifact names, and Canvas continuation guidance." },
|
|
518
546
|
{ label: "src/public-surface/source.ts", description: "Authoritative command, usage, flag, and tool surface metadata." },
|
|
519
547
|
{ label: "src/public-surface/generated-manifest.ts", description: "Checked-in generated public-surface snapshot consumed by help and parity tests." },
|
|
520
548
|
{ label: "src/public-surface/generated-manifest.json", description: "Checked-in generated public-surface snapshot consumed by inventory scripts." },
|
|
@@ -693,86 +721,12 @@ function getCommand(name) {
|
|
|
693
721
|
}
|
|
694
722
|
|
|
695
723
|
// src/cli/installers/global.ts
|
|
696
|
-
import * as
|
|
724
|
+
import * as fs2 from "fs";
|
|
697
725
|
|
|
698
|
-
// src/cli/
|
|
726
|
+
// src/cli/templates/config.ts
|
|
699
727
|
import * as fs from "fs";
|
|
700
728
|
import * as path from "path";
|
|
701
729
|
import * as os from "os";
|
|
702
|
-
import { parse as parseJsonc, modify, applyEdits } from "jsonc-parser";
|
|
703
|
-
var PLUGIN_NAME = "opendevbrowser";
|
|
704
|
-
var SCHEMA_URL = "https://opencode.ai/config.json";
|
|
705
|
-
function getGlobalConfigPath() {
|
|
706
|
-
const configDir = process.env.OPENCODE_CONFIG_DIR || path.join(os.homedir(), ".config", "opencode");
|
|
707
|
-
return path.join(configDir, "opencode.json");
|
|
708
|
-
}
|
|
709
|
-
function getLocalConfigPath() {
|
|
710
|
-
return path.join(process.cwd(), "opencode.json");
|
|
711
|
-
}
|
|
712
|
-
function ensureDir(dirPath) {
|
|
713
|
-
if (!fs.existsSync(dirPath)) {
|
|
714
|
-
fs.mkdirSync(dirPath, { recursive: true });
|
|
715
|
-
}
|
|
716
|
-
}
|
|
717
|
-
function readConfig(configPath) {
|
|
718
|
-
if (!fs.existsSync(configPath)) {
|
|
719
|
-
return { content: "", config: {} };
|
|
720
|
-
}
|
|
721
|
-
const content = fs.readFileSync(configPath, "utf-8");
|
|
722
|
-
const errors = [];
|
|
723
|
-
const parsed = parseJsonc(content, errors, { allowTrailingComma: true });
|
|
724
|
-
if (errors.length > 0) {
|
|
725
|
-
const firstError = errors[0];
|
|
726
|
-
throw new Error(`Invalid JSONC at ${configPath}: parse error at offset ${firstError?.offset ?? 0}`);
|
|
727
|
-
}
|
|
728
|
-
return { content, config: parsed ?? {} };
|
|
729
|
-
}
|
|
730
|
-
function hasPlugin(config, pluginName = PLUGIN_NAME) {
|
|
731
|
-
return config.plugin?.includes(pluginName) ?? false;
|
|
732
|
-
}
|
|
733
|
-
function createConfigWithPlugin(pluginName = PLUGIN_NAME) {
|
|
734
|
-
return {
|
|
735
|
-
$schema: SCHEMA_URL,
|
|
736
|
-
plugin: [pluginName]
|
|
737
|
-
};
|
|
738
|
-
}
|
|
739
|
-
function updateConfigContent(content, pluginName = PLUGIN_NAME) {
|
|
740
|
-
if (!content.trim()) {
|
|
741
|
-
return JSON.stringify(createConfigWithPlugin(pluginName), null, 2) + "\n";
|
|
742
|
-
}
|
|
743
|
-
const parsed = parseJsonc(content, [], { allowTrailingComma: true }) ?? {};
|
|
744
|
-
if (parsed.plugin?.includes(pluginName)) {
|
|
745
|
-
return content;
|
|
746
|
-
}
|
|
747
|
-
let result = content;
|
|
748
|
-
if (!parsed.$schema) {
|
|
749
|
-
const edits2 = modify(result, ["$schema"], SCHEMA_URL, { formattingOptions: { tabSize: 2, insertSpaces: true } });
|
|
750
|
-
result = applyEdits(result, edits2);
|
|
751
|
-
}
|
|
752
|
-
const newPlugins = parsed.plugin ? [...parsed.plugin, pluginName] : [pluginName];
|
|
753
|
-
const edits = modify(result, ["plugin"], newPlugins, { formattingOptions: { tabSize: 2, insertSpaces: true } });
|
|
754
|
-
result = applyEdits(result, edits);
|
|
755
|
-
return result;
|
|
756
|
-
}
|
|
757
|
-
function removePluginFromContent(content, pluginName = PLUGIN_NAME) {
|
|
758
|
-
if (!content.trim()) {
|
|
759
|
-
return content;
|
|
760
|
-
}
|
|
761
|
-
const parsed = parseJsonc(content, [], { allowTrailingComma: true }) ?? {};
|
|
762
|
-
if (!parsed.plugin?.includes(pluginName)) {
|
|
763
|
-
return content;
|
|
764
|
-
}
|
|
765
|
-
const newPlugins = parsed.plugin.filter((p) => p !== pluginName);
|
|
766
|
-
const edits = modify(content, ["plugin"], newPlugins.length > 0 ? newPlugins : void 0, {
|
|
767
|
-
formattingOptions: { tabSize: 2, insertSpaces: true }
|
|
768
|
-
});
|
|
769
|
-
return applyEdits(content, edits);
|
|
770
|
-
}
|
|
771
|
-
|
|
772
|
-
// src/cli/templates/config.ts
|
|
773
|
-
import * as fs2 from "fs";
|
|
774
|
-
import * as path2 from "path";
|
|
775
|
-
import * as os2 from "os";
|
|
776
730
|
function buildConfigTemplate(relayToken, daemonToken) {
|
|
777
731
|
return `{
|
|
778
732
|
// OpenDevBrowser Plugin Configuration
|
|
@@ -849,19 +803,19 @@ function buildConfigTemplate(relayToken, daemonToken) {
|
|
|
849
803
|
}
|
|
850
804
|
function getPluginConfigPath(mode) {
|
|
851
805
|
if (mode === "global") {
|
|
852
|
-
const configDir = process.env.OPENCODE_CONFIG_DIR ||
|
|
853
|
-
return
|
|
806
|
+
const configDir = process.env.OPENCODE_CONFIG_DIR || path.join(os.homedir(), ".config", "opencode");
|
|
807
|
+
return path.join(configDir, "opendevbrowser.jsonc");
|
|
854
808
|
}
|
|
855
|
-
return
|
|
809
|
+
return path.join(process.cwd(), "opendevbrowser.jsonc");
|
|
856
810
|
}
|
|
857
811
|
function createPluginConfig(mode) {
|
|
858
812
|
const configPath = getPluginConfigPath(mode);
|
|
859
|
-
if (
|
|
813
|
+
if (fs.existsSync(configPath)) {
|
|
860
814
|
return { created: false, path: configPath };
|
|
861
815
|
}
|
|
862
|
-
const dir =
|
|
863
|
-
if (!
|
|
864
|
-
|
|
816
|
+
const dir = path.dirname(configPath);
|
|
817
|
+
if (!fs.existsSync(dir)) {
|
|
818
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
865
819
|
}
|
|
866
820
|
const relayToken = generateSecureToken();
|
|
867
821
|
const daemonToken = generateSecureToken();
|
|
@@ -885,7 +839,7 @@ function installGlobal(withConfig = false) {
|
|
|
885
839
|
}
|
|
886
840
|
const newContent = updateConfigContent(content, "opendevbrowser");
|
|
887
841
|
ensureDir(configPath.replace(/[/\\][^/\\]+$/, ""));
|
|
888
|
-
|
|
842
|
+
fs2.writeFileSync(configPath, newContent, "utf-8");
|
|
889
843
|
if (withConfig) {
|
|
890
844
|
createPluginConfig("global");
|
|
891
845
|
}
|
|
@@ -909,7 +863,7 @@ function installGlobal(withConfig = false) {
|
|
|
909
863
|
}
|
|
910
864
|
|
|
911
865
|
// src/cli/installers/local.ts
|
|
912
|
-
import * as
|
|
866
|
+
import * as fs3 from "fs";
|
|
913
867
|
function installLocal(withConfig = false) {
|
|
914
868
|
const configPath = getLocalConfigPath();
|
|
915
869
|
try {
|
|
@@ -924,7 +878,7 @@ function installLocal(withConfig = false) {
|
|
|
924
878
|
};
|
|
925
879
|
}
|
|
926
880
|
const newContent = updateConfigContent(content, "opendevbrowser");
|
|
927
|
-
|
|
881
|
+
fs3.writeFileSync(configPath, newContent, "utf-8");
|
|
928
882
|
if (withConfig) {
|
|
929
883
|
createPluginConfig("local");
|
|
930
884
|
}
|
|
@@ -947,407 +901,32 @@ function installLocal(withConfig = false) {
|
|
|
947
901
|
}
|
|
948
902
|
}
|
|
949
903
|
|
|
950
|
-
// src/cli/installers/skills.ts
|
|
951
|
-
import * as crypto from "crypto";
|
|
952
|
-
import * as fs5 from "fs";
|
|
953
|
-
import * as path4 from "path";
|
|
954
|
-
|
|
955
|
-
// src/cli/utils/skills.ts
|
|
956
|
-
import * as path3 from "path";
|
|
957
|
-
import * as os3 from "os";
|
|
958
|
-
var SKILL_DIR_NAME = "skill";
|
|
959
|
-
var SKILLS_DIR_NAME = "skills";
|
|
960
|
-
function getGlobalSkillDir() {
|
|
961
|
-
const configDir = process.env.OPENCODE_CONFIG_DIR || path3.join(os3.homedir(), ".config", "opencode");
|
|
962
|
-
return path3.join(configDir, SKILL_DIR_NAME);
|
|
963
|
-
}
|
|
964
|
-
function getLocalSkillDir() {
|
|
965
|
-
return path3.join(process.cwd(), ".opencode", SKILL_DIR_NAME);
|
|
966
|
-
}
|
|
967
|
-
function getCodexHomeDir() {
|
|
968
|
-
return process.env.CODEX_HOME || path3.join(os3.homedir(), ".codex");
|
|
969
|
-
}
|
|
970
|
-
function getClaudeCodeHomeDir() {
|
|
971
|
-
return process.env.CLAUDECODE_HOME || path3.join(os3.homedir(), ".claude");
|
|
972
|
-
}
|
|
973
|
-
function getAmpHomeDir() {
|
|
974
|
-
return process.env.AMP_CLI_HOME || path3.join(os3.homedir(), ".amp");
|
|
975
|
-
}
|
|
976
|
-
function dedupeTargets(targets) {
|
|
977
|
-
const deduped = /* @__PURE__ */ new Map();
|
|
978
|
-
for (const target of targets) {
|
|
979
|
-
const key = path3.resolve(target.dir);
|
|
980
|
-
const existing = deduped.get(key);
|
|
981
|
-
if (existing) {
|
|
982
|
-
if (!existing.agents.includes(target.agent)) {
|
|
983
|
-
existing.agents.push(target.agent);
|
|
984
|
-
}
|
|
985
|
-
continue;
|
|
986
|
-
}
|
|
987
|
-
deduped.set(key, { agents: [target.agent], dir: target.dir });
|
|
988
|
-
}
|
|
989
|
-
return Array.from(deduped.values());
|
|
990
|
-
}
|
|
991
|
-
function getGlobalSkillTargets() {
|
|
992
|
-
const claudeSkillsDir = path3.join(getClaudeCodeHomeDir(), SKILLS_DIR_NAME);
|
|
993
|
-
const ampSkillsDir = path3.join(getAmpHomeDir(), SKILLS_DIR_NAME);
|
|
994
|
-
return dedupeTargets([
|
|
995
|
-
{ agent: "opencode", dir: getGlobalSkillDir() },
|
|
996
|
-
{ agent: "codex", dir: path3.join(getCodexHomeDir(), SKILLS_DIR_NAME) },
|
|
997
|
-
{ agent: "claudecode", dir: claudeSkillsDir },
|
|
998
|
-
{ agent: "ampcli", dir: ampSkillsDir }
|
|
999
|
-
]);
|
|
1000
|
-
}
|
|
1001
|
-
function getLocalSkillTargets() {
|
|
1002
|
-
const localClaudeSkillsDir = path3.join(process.cwd(), ".claude", SKILLS_DIR_NAME);
|
|
1003
|
-
const localAmpSkillsDir = path3.join(process.cwd(), ".amp", SKILLS_DIR_NAME);
|
|
1004
|
-
return dedupeTargets([
|
|
1005
|
-
{ agent: "opencode", dir: getLocalSkillDir() },
|
|
1006
|
-
{ agent: "codex", dir: path3.join(process.cwd(), ".codex", SKILLS_DIR_NAME) },
|
|
1007
|
-
{ agent: "claudecode", dir: localClaudeSkillsDir },
|
|
1008
|
-
{ agent: "ampcli", dir: localAmpSkillsDir }
|
|
1009
|
-
]);
|
|
1010
|
-
}
|
|
1011
|
-
|
|
1012
|
-
// src/cli/installers/skills.ts
|
|
1013
|
-
var LEGACY_ALIAS_DIRS = [
|
|
1014
|
-
{ name: "research", canonical: "opendevbrowser-research" },
|
|
1015
|
-
{ name: "shopping", canonical: "opendevbrowser-shopping" }
|
|
1016
|
-
];
|
|
1017
|
-
function getTargets(mode) {
|
|
1018
|
-
return mode === "global" ? getGlobalSkillTargets() : getLocalSkillTargets();
|
|
1019
|
-
}
|
|
1020
|
-
function getCanonicalBundledSkillNames() {
|
|
1021
|
-
return listBundledSkillDirectories().map((entry) => entry.name);
|
|
1022
|
-
}
|
|
1023
|
-
function hasCanonicalBundledSkillInTarget(targetDir, packNames) {
|
|
1024
|
-
return packNames.some((packName) => fs5.existsSync(path4.join(targetDir, packName)));
|
|
1025
|
-
}
|
|
1026
|
-
function formatSummary(parts, totalTargets, failures) {
|
|
1027
|
-
const summary = parts.length > 0 ? parts.join(", ") : "no lifecycle changes";
|
|
1028
|
-
const failureSummary = failures > 0 ? `, ${failures} failed` : "";
|
|
1029
|
-
return `${summary} across ${totalTargets} targets${failureSummary}`;
|
|
1030
|
-
}
|
|
1031
|
-
function hashDirectoryTree(dirPath) {
|
|
1032
|
-
const hash = crypto.createHash("sha256");
|
|
1033
|
-
const visit = (currentPath, relativePath) => {
|
|
1034
|
-
const entries = fs5.readdirSync(currentPath, { withFileTypes: true }).sort((left, right) => left.name.localeCompare(right.name));
|
|
1035
|
-
for (const entry of entries) {
|
|
1036
|
-
const absolutePath = path4.join(currentPath, entry.name);
|
|
1037
|
-
const entryRelativePath = relativePath ? path4.posix.join(relativePath, entry.name) : entry.name;
|
|
1038
|
-
if (entry.isDirectory()) {
|
|
1039
|
-
hash.update(`D:${entryRelativePath}\0`);
|
|
1040
|
-
visit(absolutePath, entryRelativePath);
|
|
1041
|
-
continue;
|
|
1042
|
-
}
|
|
1043
|
-
if (entry.isFile()) {
|
|
1044
|
-
hash.update(`F:${entryRelativePath}\0`);
|
|
1045
|
-
hash.update(fs5.readFileSync(absolutePath));
|
|
1046
|
-
hash.update("\0");
|
|
1047
|
-
continue;
|
|
1048
|
-
}
|
|
1049
|
-
if (entry.isSymbolicLink()) {
|
|
1050
|
-
hash.update(`L:${entryRelativePath}\0${fs5.readlinkSync(absolutePath)}\0`);
|
|
1051
|
-
}
|
|
1052
|
-
}
|
|
1053
|
-
};
|
|
1054
|
-
visit(dirPath, "");
|
|
1055
|
-
return hash.digest("hex");
|
|
1056
|
-
}
|
|
1057
|
-
function syncSkillDirectory(sourcePath, targetPath, sourceFingerprint) {
|
|
1058
|
-
if (!fs5.existsSync(targetPath)) {
|
|
1059
|
-
fs5.cpSync(sourcePath, targetPath, { recursive: true });
|
|
1060
|
-
return "installed";
|
|
1061
|
-
}
|
|
1062
|
-
const targetFingerprint = hashDirectoryTree(targetPath);
|
|
1063
|
-
if (targetFingerprint === sourceFingerprint) {
|
|
1064
|
-
return "unchanged";
|
|
1065
|
-
}
|
|
1066
|
-
const parentDir = path4.dirname(targetPath);
|
|
1067
|
-
const targetName = path4.basename(targetPath);
|
|
1068
|
-
const stagingRoot = fs5.mkdtempSync(path4.join(parentDir, `.${targetName}-sync-`));
|
|
1069
|
-
const stagedPath = path4.join(stagingRoot, targetName);
|
|
1070
|
-
const backupPath = path4.join(stagingRoot, `${targetName}-backup`);
|
|
1071
|
-
try {
|
|
1072
|
-
fs5.cpSync(sourcePath, stagedPath, { recursive: true });
|
|
1073
|
-
fs5.renameSync(targetPath, backupPath);
|
|
1074
|
-
try {
|
|
1075
|
-
fs5.renameSync(stagedPath, targetPath);
|
|
1076
|
-
} catch (error) {
|
|
1077
|
-
if (fs5.existsSync(backupPath) && !fs5.existsSync(targetPath)) {
|
|
1078
|
-
fs5.renameSync(backupPath, targetPath);
|
|
1079
|
-
}
|
|
1080
|
-
throw error;
|
|
1081
|
-
}
|
|
1082
|
-
fs5.rmSync(backupPath, { recursive: true, force: true });
|
|
1083
|
-
return "refreshed";
|
|
1084
|
-
} finally {
|
|
1085
|
-
if (fs5.existsSync(stagedPath)) {
|
|
1086
|
-
fs5.rmSync(stagedPath, { recursive: true, force: true });
|
|
1087
|
-
}
|
|
1088
|
-
if (fs5.existsSync(backupPath)) {
|
|
1089
|
-
fs5.rmSync(backupPath, { recursive: true, force: true });
|
|
1090
|
-
}
|
|
1091
|
-
fs5.rmSync(stagingRoot, { recursive: true, force: true });
|
|
1092
|
-
}
|
|
1093
|
-
}
|
|
1094
|
-
function cleanupLegacyAlias(targetDir, aliasName) {
|
|
1095
|
-
const aliasPath = path4.join(targetDir, aliasName);
|
|
1096
|
-
if (!fs5.existsSync(aliasPath)) {
|
|
1097
|
-
return { removed: [], preserved: [] };
|
|
1098
|
-
}
|
|
1099
|
-
let stats;
|
|
1100
|
-
try {
|
|
1101
|
-
stats = fs5.statSync(aliasPath);
|
|
1102
|
-
} catch {
|
|
1103
|
-
return {
|
|
1104
|
-
removed: [],
|
|
1105
|
-
preserved: [{ targetDir, name: aliasName, reason: "unknown_layout" }]
|
|
1106
|
-
};
|
|
1107
|
-
}
|
|
1108
|
-
if (!stats.isDirectory()) {
|
|
1109
|
-
return {
|
|
1110
|
-
removed: [],
|
|
1111
|
-
preserved: [{ targetDir, name: aliasName, reason: "unknown_layout" }]
|
|
1112
|
-
};
|
|
1113
|
-
}
|
|
1114
|
-
if (fs5.existsSync(path4.join(aliasPath, "SKILL.md"))) {
|
|
1115
|
-
return {
|
|
1116
|
-
removed: [],
|
|
1117
|
-
preserved: [{ targetDir, name: aliasName, reason: "contains_skill_md" }]
|
|
1118
|
-
};
|
|
1119
|
-
}
|
|
1120
|
-
const entries = fs5.readdirSync(aliasPath);
|
|
1121
|
-
if (entries.length === 0) {
|
|
1122
|
-
fs5.rmSync(aliasPath, { recursive: true, force: true });
|
|
1123
|
-
return { removed: [aliasName], preserved: [] };
|
|
1124
|
-
}
|
|
1125
|
-
return {
|
|
1126
|
-
removed: [],
|
|
1127
|
-
preserved: [{ targetDir, name: aliasName, reason: "non_empty" }]
|
|
1128
|
-
};
|
|
1129
|
-
}
|
|
1130
|
-
function cleanupLegacyAliases(targetDir) {
|
|
1131
|
-
const removed = [];
|
|
1132
|
-
const preserved = [];
|
|
1133
|
-
for (const alias of LEGACY_ALIAS_DIRS) {
|
|
1134
|
-
const result = cleanupLegacyAlias(targetDir, alias.name);
|
|
1135
|
-
removed.push(...result.removed);
|
|
1136
|
-
preserved.push(...result.preserved);
|
|
1137
|
-
}
|
|
1138
|
-
return { removed, preserved };
|
|
1139
|
-
}
|
|
1140
|
-
function buildSyncMessage(mode, result) {
|
|
1141
|
-
return `Skills ${mode} sync: ${formatSummary(
|
|
1142
|
-
[
|
|
1143
|
-
result.installed.length > 0 ? `${result.installed.length} installed` : "",
|
|
1144
|
-
result.refreshed.length > 0 ? `${result.refreshed.length} refreshed` : "",
|
|
1145
|
-
result.unchanged.length > 0 ? `${result.unchanged.length} unchanged` : "",
|
|
1146
|
-
result.removedLegacyAliases.length > 0 ? `${result.removedLegacyAliases.length} legacy aliases removed` : "",
|
|
1147
|
-
result.preservedLegacyAliases.length > 0 ? `${result.preservedLegacyAliases.length} legacy aliases preserved` : ""
|
|
1148
|
-
].filter(Boolean),
|
|
1149
|
-
result.targets.length,
|
|
1150
|
-
result.targets.filter((entry) => !entry.success).length
|
|
1151
|
-
)}`;
|
|
1152
|
-
}
|
|
1153
|
-
function buildRemovalMessage(mode, result) {
|
|
1154
|
-
return `Skills ${mode} removal: ${formatSummary(
|
|
1155
|
-
[
|
|
1156
|
-
result.removed.length > 0 ? `${result.removed.length} removed` : "",
|
|
1157
|
-
result.missing.length > 0 ? `${result.missing.length} already absent` : "",
|
|
1158
|
-
result.removedLegacyAliases.length > 0 ? `${result.removedLegacyAliases.length} legacy aliases removed` : "",
|
|
1159
|
-
result.preservedLegacyAliases.length > 0 ? `${result.preservedLegacyAliases.length} legacy aliases preserved` : ""
|
|
1160
|
-
].filter(Boolean),
|
|
1161
|
-
result.targets.length,
|
|
1162
|
-
result.targets.filter((entry) => !entry.success).length
|
|
1163
|
-
)}`;
|
|
1164
|
-
}
|
|
1165
|
-
function syncBundledSkills(mode) {
|
|
1166
|
-
const targets = getTargets(mode);
|
|
1167
|
-
const targetResults = [];
|
|
1168
|
-
try {
|
|
1169
|
-
const sourceDir = getBundledSkillsDir();
|
|
1170
|
-
const packNames = getCanonicalBundledSkillNames();
|
|
1171
|
-
const bundledFingerprints = /* @__PURE__ */ new Map();
|
|
1172
|
-
for (const packName of packNames) {
|
|
1173
|
-
const sourcePath = path4.join(sourceDir, packName);
|
|
1174
|
-
if (!fs5.existsSync(sourcePath)) {
|
|
1175
|
-
throw new Error(`Bundled skill directory missing: ${packName}`);
|
|
1176
|
-
}
|
|
1177
|
-
bundledFingerprints.set(packName, hashDirectoryTree(sourcePath));
|
|
1178
|
-
}
|
|
1179
|
-
for (const target of targets) {
|
|
1180
|
-
const installed = [];
|
|
1181
|
-
const refreshed = [];
|
|
1182
|
-
const unchanged = [];
|
|
1183
|
-
const removedLegacyAliases = [];
|
|
1184
|
-
const preservedLegacyAliases = [];
|
|
1185
|
-
try {
|
|
1186
|
-
ensureDir(target.dir);
|
|
1187
|
-
for (const packName of packNames) {
|
|
1188
|
-
const sourcePath = path4.join(sourceDir, packName);
|
|
1189
|
-
const targetPath = path4.join(target.dir, packName);
|
|
1190
|
-
const sourceFingerprint = bundledFingerprints.get(packName);
|
|
1191
|
-
if (!sourceFingerprint) {
|
|
1192
|
-
throw new Error(`Bundled fingerprint missing: ${packName}`);
|
|
1193
|
-
}
|
|
1194
|
-
const outcome = syncSkillDirectory(sourcePath, targetPath, sourceFingerprint);
|
|
1195
|
-
if (outcome === "installed") {
|
|
1196
|
-
installed.push(packName);
|
|
1197
|
-
} else if (outcome === "refreshed") {
|
|
1198
|
-
refreshed.push(packName);
|
|
1199
|
-
} else {
|
|
1200
|
-
unchanged.push(packName);
|
|
1201
|
-
}
|
|
1202
|
-
}
|
|
1203
|
-
const legacyCleanup = cleanupLegacyAliases(target.dir);
|
|
1204
|
-
removedLegacyAliases.push(...legacyCleanup.removed);
|
|
1205
|
-
preservedLegacyAliases.push(...legacyCleanup.preserved);
|
|
1206
|
-
targetResults.push({
|
|
1207
|
-
agents: target.agents,
|
|
1208
|
-
targetDir: target.dir,
|
|
1209
|
-
installed,
|
|
1210
|
-
refreshed,
|
|
1211
|
-
unchanged,
|
|
1212
|
-
removedLegacyAliases,
|
|
1213
|
-
preservedLegacyAliases,
|
|
1214
|
-
success: true
|
|
1215
|
-
});
|
|
1216
|
-
} catch (error) {
|
|
1217
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
1218
|
-
targetResults.push({
|
|
1219
|
-
agents: target.agents,
|
|
1220
|
-
targetDir: target.dir,
|
|
1221
|
-
installed,
|
|
1222
|
-
refreshed,
|
|
1223
|
-
unchanged,
|
|
1224
|
-
removedLegacyAliases,
|
|
1225
|
-
preservedLegacyAliases,
|
|
1226
|
-
success: false,
|
|
1227
|
-
error: message
|
|
1228
|
-
});
|
|
1229
|
-
}
|
|
1230
|
-
}
|
|
1231
|
-
const result = {
|
|
1232
|
-
success: targetResults.every((entry) => entry.success),
|
|
1233
|
-
message: "",
|
|
1234
|
-
mode,
|
|
1235
|
-
targets: targetResults,
|
|
1236
|
-
installed: targetResults.flatMap((entry) => entry.installed),
|
|
1237
|
-
refreshed: targetResults.flatMap((entry) => entry.refreshed),
|
|
1238
|
-
unchanged: targetResults.flatMap((entry) => entry.unchanged),
|
|
1239
|
-
removedLegacyAliases: targetResults.flatMap((entry) => entry.removedLegacyAliases),
|
|
1240
|
-
preservedLegacyAliases: targetResults.flatMap((entry) => entry.preservedLegacyAliases)
|
|
1241
|
-
};
|
|
1242
|
-
result.message = buildSyncMessage(mode, result);
|
|
1243
|
-
return result;
|
|
1244
|
-
} catch (error) {
|
|
1245
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
1246
|
-
const result = {
|
|
1247
|
-
success: false,
|
|
1248
|
-
message: "",
|
|
1249
|
-
mode,
|
|
1250
|
-
targets: targetResults,
|
|
1251
|
-
installed: targetResults.flatMap((entry) => entry.installed),
|
|
1252
|
-
refreshed: targetResults.flatMap((entry) => entry.refreshed),
|
|
1253
|
-
unchanged: targetResults.flatMap((entry) => entry.unchanged),
|
|
1254
|
-
removedLegacyAliases: targetResults.flatMap((entry) => entry.removedLegacyAliases),
|
|
1255
|
-
preservedLegacyAliases: targetResults.flatMap((entry) => entry.preservedLegacyAliases)
|
|
1256
|
-
};
|
|
1257
|
-
result.message = `Failed to sync skills (${mode}): ${message}`;
|
|
1258
|
-
return result;
|
|
1259
|
-
}
|
|
1260
|
-
}
|
|
1261
|
-
function removeBundledSkills(mode) {
|
|
1262
|
-
const targets = getTargets(mode);
|
|
1263
|
-
const packNames = getCanonicalBundledSkillNames();
|
|
1264
|
-
const targetResults = [];
|
|
1265
|
-
for (const target of targets) {
|
|
1266
|
-
const removed = [];
|
|
1267
|
-
const missing = [];
|
|
1268
|
-
const removedLegacyAliases = [];
|
|
1269
|
-
const preservedLegacyAliases = [];
|
|
1270
|
-
try {
|
|
1271
|
-
for (const packName of packNames) {
|
|
1272
|
-
const targetPath = path4.join(target.dir, packName);
|
|
1273
|
-
if (fs5.existsSync(targetPath)) {
|
|
1274
|
-
fs5.rmSync(targetPath, { recursive: true, force: true });
|
|
1275
|
-
removed.push(packName);
|
|
1276
|
-
} else {
|
|
1277
|
-
missing.push(packName);
|
|
1278
|
-
}
|
|
1279
|
-
}
|
|
1280
|
-
const legacyCleanup = cleanupLegacyAliases(target.dir);
|
|
1281
|
-
removedLegacyAliases.push(...legacyCleanup.removed);
|
|
1282
|
-
preservedLegacyAliases.push(...legacyCleanup.preserved);
|
|
1283
|
-
targetResults.push({
|
|
1284
|
-
agents: target.agents,
|
|
1285
|
-
targetDir: target.dir,
|
|
1286
|
-
removed,
|
|
1287
|
-
missing,
|
|
1288
|
-
removedLegacyAliases,
|
|
1289
|
-
preservedLegacyAliases,
|
|
1290
|
-
success: true
|
|
1291
|
-
});
|
|
1292
|
-
} catch (error) {
|
|
1293
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
1294
|
-
targetResults.push({
|
|
1295
|
-
agents: target.agents,
|
|
1296
|
-
targetDir: target.dir,
|
|
1297
|
-
removed,
|
|
1298
|
-
missing,
|
|
1299
|
-
removedLegacyAliases,
|
|
1300
|
-
preservedLegacyAliases,
|
|
1301
|
-
success: false,
|
|
1302
|
-
error: message
|
|
1303
|
-
});
|
|
1304
|
-
}
|
|
1305
|
-
}
|
|
1306
|
-
const result = {
|
|
1307
|
-
success: targetResults.every((entry) => entry.success),
|
|
1308
|
-
message: "",
|
|
1309
|
-
mode,
|
|
1310
|
-
targets: targetResults,
|
|
1311
|
-
removed: targetResults.flatMap((entry) => entry.removed),
|
|
1312
|
-
missing: targetResults.flatMap((entry) => entry.missing),
|
|
1313
|
-
removedLegacyAliases: targetResults.flatMap((entry) => entry.removedLegacyAliases),
|
|
1314
|
-
preservedLegacyAliases: targetResults.flatMap((entry) => entry.preservedLegacyAliases)
|
|
1315
|
-
};
|
|
1316
|
-
result.message = buildRemovalMessage(mode, result);
|
|
1317
|
-
return result;
|
|
1318
|
-
}
|
|
1319
|
-
function hasBundledSkillArtifacts(mode) {
|
|
1320
|
-
const packNames = getCanonicalBundledSkillNames();
|
|
1321
|
-
const targets = getTargets(mode);
|
|
1322
|
-
return targets.some((target) => hasCanonicalBundledSkillInTarget(target.dir, packNames));
|
|
1323
|
-
}
|
|
1324
|
-
|
|
1325
904
|
// src/cli/commands/update.ts
|
|
1326
|
-
import * as
|
|
1327
|
-
import * as
|
|
1328
|
-
import * as
|
|
1329
|
-
var
|
|
905
|
+
import * as fs4 from "fs";
|
|
906
|
+
import * as path2 from "path";
|
|
907
|
+
import * as os2 from "os";
|
|
908
|
+
var PLUGIN_NAME = "opendevbrowser";
|
|
1330
909
|
function getCacheDir() {
|
|
1331
|
-
return process.env.OPENCODE_CACHE_DIR ||
|
|
910
|
+
return process.env.OPENCODE_CACHE_DIR || path2.join(os2.homedir(), ".cache", "opencode");
|
|
1332
911
|
}
|
|
1333
912
|
function rmdir(dirPath) {
|
|
1334
913
|
const cacheDir = getCacheDir();
|
|
1335
|
-
const resolvedCache =
|
|
1336
|
-
const resolvedPath =
|
|
1337
|
-
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) {
|
|
1338
917
|
throw new Error(`Security: refusing to delete path outside cache directory: ${dirPath}`);
|
|
1339
918
|
}
|
|
1340
|
-
if (
|
|
1341
|
-
|
|
919
|
+
if (fs4.existsSync(dirPath)) {
|
|
920
|
+
fs4.rmSync(dirPath, { recursive: true, force: true });
|
|
1342
921
|
}
|
|
1343
922
|
}
|
|
1344
923
|
function runUpdate() {
|
|
1345
924
|
const cacheDir = getCacheDir();
|
|
1346
|
-
const nodeModulesDir =
|
|
1347
|
-
const pluginCacheDir =
|
|
925
|
+
const nodeModulesDir = path2.join(cacheDir, "node_modules");
|
|
926
|
+
const pluginCacheDir = path2.join(nodeModulesDir, PLUGIN_NAME);
|
|
1348
927
|
try {
|
|
1349
|
-
if (!
|
|
1350
|
-
if (
|
|
928
|
+
if (!fs4.existsSync(pluginCacheDir)) {
|
|
929
|
+
if (fs4.existsSync(nodeModulesDir)) {
|
|
1351
930
|
rmdir(nodeModulesDir);
|
|
1352
931
|
return {
|
|
1353
932
|
success: true,
|
|
@@ -1378,20 +957,29 @@ function runUpdate() {
|
|
|
1378
957
|
}
|
|
1379
958
|
|
|
1380
959
|
// src/cli/commands/uninstall.ts
|
|
1381
|
-
import * as
|
|
1382
|
-
import * as
|
|
1383
|
-
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
|
+
}
|
|
1384
972
|
function getPluginConfigPath2(mode) {
|
|
1385
973
|
if (mode === "global") {
|
|
1386
|
-
const configDir = process.env.OPENCODE_CONFIG_DIR ||
|
|
1387
|
-
return
|
|
974
|
+
const configDir = process.env.OPENCODE_CONFIG_DIR || path3.join(os3.homedir(), ".config", "opencode");
|
|
975
|
+
return path3.join(configDir, "opendevbrowser.jsonc");
|
|
1388
976
|
}
|
|
1389
|
-
return
|
|
977
|
+
return path3.join(process.cwd(), "opendevbrowser.jsonc");
|
|
1390
978
|
}
|
|
1391
979
|
function removePluginConfigFile(mode) {
|
|
1392
980
|
const configPath = getPluginConfigPath2(mode);
|
|
1393
|
-
if (
|
|
1394
|
-
|
|
981
|
+
if (fs5.existsSync(configPath)) {
|
|
982
|
+
fs5.unlinkSync(configPath);
|
|
1395
983
|
return true;
|
|
1396
984
|
}
|
|
1397
985
|
return false;
|
|
@@ -1403,14 +991,14 @@ function runUninstall(mode, deleteConfigFile = false) {
|
|
|
1403
991
|
if (!hasPlugin(config)) {
|
|
1404
992
|
return {
|
|
1405
993
|
success: true,
|
|
1406
|
-
message: `
|
|
994
|
+
message: `No plugin config found in ${configPath}`,
|
|
1407
995
|
configPath,
|
|
1408
996
|
removed: false,
|
|
1409
997
|
configFileDeleted: false
|
|
1410
998
|
};
|
|
1411
999
|
}
|
|
1412
1000
|
const newContent = removePluginFromContent(content, "opendevbrowser");
|
|
1413
|
-
|
|
1001
|
+
fs5.writeFileSync(configPath, newContent, "utf-8");
|
|
1414
1002
|
let configFileDeleted = false;
|
|
1415
1003
|
if (deleteConfigFile) {
|
|
1416
1004
|
configFileDeleted = removePluginConfigFile(mode);
|
|
@@ -1434,19 +1022,10 @@ function runUninstall(mode, deleteConfigFile = false) {
|
|
|
1434
1022
|
}
|
|
1435
1023
|
}
|
|
1436
1024
|
function findInstalledConfigs() {
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
global = hasPlugin(globalConfig);
|
|
1442
|
-
} catch {
|
|
1443
|
-
}
|
|
1444
|
-
try {
|
|
1445
|
-
const { config: localConfig } = readConfig(getLocalConfigPath());
|
|
1446
|
-
local = hasPlugin(localConfig);
|
|
1447
|
-
} catch {
|
|
1448
|
-
}
|
|
1449
|
-
return { global, local };
|
|
1025
|
+
return {
|
|
1026
|
+
global: hasInstalledConfig("global") || hasManagedBundledSkillInstall("global") || hasBundledSkillArtifacts("global"),
|
|
1027
|
+
local: hasInstalledConfig("local") || hasManagedBundledSkillInstall("local") || hasBundledSkillArtifacts("local")
|
|
1028
|
+
};
|
|
1450
1029
|
}
|
|
1451
1030
|
|
|
1452
1031
|
// src/cli/commands/serve.ts
|
|
@@ -1536,8 +1115,8 @@ function parseRepeatedStringFlag(rawArgs, flag) {
|
|
|
1536
1115
|
}
|
|
1537
1116
|
|
|
1538
1117
|
// src/cli/commands/native.ts
|
|
1539
|
-
import * as
|
|
1540
|
-
import * as
|
|
1118
|
+
import * as fs6 from "fs";
|
|
1119
|
+
import * as path4 from "path";
|
|
1541
1120
|
import { execFileSync } from "child_process";
|
|
1542
1121
|
import { fileURLToPath } from "url";
|
|
1543
1122
|
var EXTENSION_ID_RE = /^[a-p]{32}$/;
|
|
@@ -1572,33 +1151,33 @@ var parseNativeArgs = (rawArgs) => {
|
|
|
1572
1151
|
};
|
|
1573
1152
|
var getManifestDir = () => {
|
|
1574
1153
|
if (process.platform === "darwin") {
|
|
1575
|
-
return
|
|
1154
|
+
return path4.join(process.env.HOME || "", "Library", "Application Support", "Google", "Chrome", "NativeMessagingHosts");
|
|
1576
1155
|
}
|
|
1577
1156
|
if (process.platform === "linux") {
|
|
1578
|
-
return
|
|
1157
|
+
return path4.join(process.env.HOME || "", ".config", "google-chrome", "NativeMessagingHosts");
|
|
1579
1158
|
}
|
|
1580
1159
|
if (process.platform === "win32") {
|
|
1581
|
-
const base = process.env.LOCALAPPDATA || (process.env.USERPROFILE ?
|
|
1160
|
+
const base = process.env.LOCALAPPDATA || (process.env.USERPROFILE ? path4.join(process.env.USERPROFILE, "AppData", "Local") : "");
|
|
1582
1161
|
if (!base) {
|
|
1583
1162
|
throw createUsageError("LOCALAPPDATA is not set. Unable to locate NativeMessagingHosts directory.");
|
|
1584
1163
|
}
|
|
1585
|
-
return
|
|
1164
|
+
return path4.join(base, "Google", "Chrome", "User Data", "NativeMessagingHosts");
|
|
1586
1165
|
}
|
|
1587
1166
|
throw createUsageError(`Native messaging is not supported on ${process.platform}.`);
|
|
1588
1167
|
};
|
|
1589
1168
|
var getScriptsDir = () => {
|
|
1590
1169
|
const __filename = fileURLToPath(import.meta.url);
|
|
1591
|
-
const startDir =
|
|
1170
|
+
const startDir = path4.dirname(__filename);
|
|
1592
1171
|
const rootsToScan = [startDir, process.cwd()];
|
|
1593
1172
|
for (const root of rootsToScan) {
|
|
1594
|
-
let current =
|
|
1173
|
+
let current = path4.resolve(root);
|
|
1595
1174
|
while (true) {
|
|
1596
|
-
const scriptsDir =
|
|
1597
|
-
const packageJsonPath =
|
|
1598
|
-
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)) {
|
|
1599
1178
|
return scriptsDir;
|
|
1600
1179
|
}
|
|
1601
|
-
const parent =
|
|
1180
|
+
const parent = path4.dirname(current);
|
|
1602
1181
|
if (parent === current) {
|
|
1603
1182
|
break;
|
|
1604
1183
|
}
|
|
@@ -1608,18 +1187,18 @@ var getScriptsDir = () => {
|
|
|
1608
1187
|
throw createUsageError("Unable to locate scripts/native directory.");
|
|
1609
1188
|
};
|
|
1610
1189
|
var getHostScriptPath = () => {
|
|
1611
|
-
return
|
|
1190
|
+
return path4.join(getScriptsDir(), "host.cjs");
|
|
1612
1191
|
};
|
|
1613
1192
|
var getManifestPath = () => {
|
|
1614
|
-
return
|
|
1193
|
+
return path4.join(getManifestDir(), "com.opendevbrowser.native.json");
|
|
1615
1194
|
};
|
|
1616
1195
|
var getWrapperPath = () => {
|
|
1617
1196
|
const wrapperName = process.platform === "win32" ? "com.opendevbrowser.native.cmd" : "com.opendevbrowser.native.sh";
|
|
1618
|
-
return
|
|
1197
|
+
return path4.join(getManifestDir(), wrapperName);
|
|
1619
1198
|
};
|
|
1620
1199
|
var readManifest = (manifestPath) => {
|
|
1621
1200
|
try {
|
|
1622
|
-
const raw =
|
|
1201
|
+
const raw = fs6.readFileSync(manifestPath, "utf8");
|
|
1623
1202
|
const data = JSON.parse(raw);
|
|
1624
1203
|
const origins = Array.isArray(data.allowed_origins) ? data.allowed_origins : [];
|
|
1625
1204
|
const match = origins.find((origin) => origin.startsWith("chrome-extension://"));
|
|
@@ -1656,9 +1235,9 @@ var readRegistryPath = () => {
|
|
|
1656
1235
|
};
|
|
1657
1236
|
var normalizePath = (value) => {
|
|
1658
1237
|
try {
|
|
1659
|
-
return
|
|
1238
|
+
return fs6.realpathSync(value);
|
|
1660
1239
|
} catch {
|
|
1661
|
-
return
|
|
1240
|
+
return path4.resolve(value);
|
|
1662
1241
|
}
|
|
1663
1242
|
};
|
|
1664
1243
|
var findExtensionIdInCommands = (preferences) => {
|
|
@@ -1719,8 +1298,8 @@ var getExtensionPathCandidates = () => {
|
|
|
1719
1298
|
if (primary) {
|
|
1720
1299
|
candidates.add(normalizePath(primary));
|
|
1721
1300
|
}
|
|
1722
|
-
const cwdExtension =
|
|
1723
|
-
if (
|
|
1301
|
+
const cwdExtension = path4.join(process.cwd(), "extension");
|
|
1302
|
+
if (fs6.existsSync(path4.join(cwdExtension, "manifest.json"))) {
|
|
1724
1303
|
candidates.add(normalizePath(cwdExtension));
|
|
1725
1304
|
}
|
|
1726
1305
|
if (candidates.size === 0) {
|
|
@@ -1805,13 +1384,13 @@ var getNativeStatusSnapshot = () => {
|
|
|
1805
1384
|
let manifestExists = false;
|
|
1806
1385
|
let wrapperExists = false;
|
|
1807
1386
|
let extensionIdValue = null;
|
|
1808
|
-
if (
|
|
1387
|
+
if (fs6.existsSync(manifestPath)) {
|
|
1809
1388
|
manifestExists = true;
|
|
1810
1389
|
installed = true;
|
|
1811
1390
|
const manifest = readManifest(manifestPath);
|
|
1812
1391
|
extensionIdValue = manifest.extensionId;
|
|
1813
1392
|
}
|
|
1814
|
-
if (
|
|
1393
|
+
if (fs6.existsSync(wrapperPath)) {
|
|
1815
1394
|
wrapperExists = true;
|
|
1816
1395
|
}
|
|
1817
1396
|
if (!manifestExists || !wrapperExists) {
|
|
@@ -1871,7 +1450,7 @@ function installNativeHost(extensionId) {
|
|
|
1871
1450
|
};
|
|
1872
1451
|
}
|
|
1873
1452
|
const hostScript = getHostScriptPath();
|
|
1874
|
-
if (!
|
|
1453
|
+
if (!fs6.existsSync(hostScript)) {
|
|
1875
1454
|
return {
|
|
1876
1455
|
success: false,
|
|
1877
1456
|
message: `Native host not found at ${hostScript}.`,
|
|
@@ -1880,7 +1459,7 @@ function installNativeHost(extensionId) {
|
|
|
1880
1459
|
}
|
|
1881
1460
|
const scriptsDir = getScriptsDir();
|
|
1882
1461
|
const manifestPath = getManifestPath();
|
|
1883
|
-
const installScript = process.platform === "win32" ?
|
|
1462
|
+
const installScript = process.platform === "win32" ? path4.join(scriptsDir, "install.ps1") : path4.join(scriptsDir, "install.sh");
|
|
1884
1463
|
try {
|
|
1885
1464
|
runScript(installScript, [normalized]);
|
|
1886
1465
|
return {
|
|
@@ -1900,7 +1479,7 @@ function installNativeHost(extensionId) {
|
|
|
1900
1479
|
async function runNativeCommand(args) {
|
|
1901
1480
|
const { subcommand, extensionId } = parseNativeArgs(args.rawArgs);
|
|
1902
1481
|
const scriptsDir = getScriptsDir();
|
|
1903
|
-
const uninstallScript = process.platform === "win32" ?
|
|
1482
|
+
const uninstallScript = process.platform === "win32" ? path4.join(scriptsDir, "uninstall.ps1") : path4.join(scriptsDir, "uninstall.sh");
|
|
1904
1483
|
if (subcommand === "install") {
|
|
1905
1484
|
return installNativeHost(extensionId);
|
|
1906
1485
|
}
|
|
@@ -2276,9 +1855,9 @@ ${nativeMessage}${fingerprintNote}${staleNote}` : `${baseMessage}${fingerprintNo
|
|
|
2276
1855
|
|
|
2277
1856
|
// src/cli/daemon-autostart.ts
|
|
2278
1857
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
2279
|
-
import { existsSync as
|
|
2280
|
-
import { homedir as
|
|
2281
|
-
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";
|
|
2282
1861
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
2283
1862
|
var MAC_LABEL = "com.opendevbrowser.daemon";
|
|
2284
1863
|
var WIN_TASK_NAME = "OpenDevBrowser Daemon";
|
|
@@ -2288,9 +1867,9 @@ var defaultDeps = () => ({
|
|
|
2288
1867
|
argv1: process.argv[1] ?? "",
|
|
2289
1868
|
moduleUrl: import.meta.url,
|
|
2290
1869
|
uid: typeof process.getuid === "function" ? process.getuid() : 0,
|
|
2291
|
-
homedir:
|
|
2292
|
-
existsSync:
|
|
2293
|
-
mkdirSync:
|
|
1870
|
+
homedir: homedir4,
|
|
1871
|
+
existsSync: existsSync5,
|
|
1872
|
+
mkdirSync: mkdirSync2,
|
|
2294
1873
|
writeFileSync: writeFileSync4,
|
|
2295
1874
|
unlinkSync: unlinkSync2,
|
|
2296
1875
|
execFileSync: execFileSync2,
|
|
@@ -2302,14 +1881,14 @@ var formatCommand = (programArguments) => {
|
|
|
2302
1881
|
};
|
|
2303
1882
|
var resolveCliPathFromModule = (moduleUrl, exists) => {
|
|
2304
1883
|
const modulePath = fileURLToPath2(moduleUrl);
|
|
2305
|
-
const candidate =
|
|
1884
|
+
const candidate = resolve3(dirname3(modulePath), "..", "index.js");
|
|
2306
1885
|
if (!exists(candidate)) {
|
|
2307
1886
|
throw new Error(`CLI entrypoint not found at ${candidate}`);
|
|
2308
1887
|
}
|
|
2309
1888
|
return candidate;
|
|
2310
1889
|
};
|
|
2311
1890
|
var normalizeComparisonPath = (value, platform) => {
|
|
2312
|
-
const resolvedPath =
|
|
1891
|
+
const resolvedPath = resolve3(value);
|
|
2313
1892
|
return platform === "win32" ? resolvedPath.toLowerCase() : resolvedPath;
|
|
2314
1893
|
};
|
|
2315
1894
|
var isPathInsideRoot = (candidate, root, platform) => {
|
|
@@ -2344,7 +1923,7 @@ var resolveCliEntrypoint = (deps = {}) => {
|
|
|
2344
1923
|
let cliPath = null;
|
|
2345
1924
|
let source = "module";
|
|
2346
1925
|
if (resolved.argv1) {
|
|
2347
|
-
const candidate =
|
|
1926
|
+
const candidate = resolve3(resolved.argv1);
|
|
2348
1927
|
if (exists(candidate)) {
|
|
2349
1928
|
cliPath = candidate;
|
|
2350
1929
|
source = "argv1";
|
|
@@ -2359,13 +1938,13 @@ var resolveCliEntrypoint = (deps = {}) => {
|
|
|
2359
1938
|
const isTransient = isTransientCliPath(cliPath, resolved);
|
|
2360
1939
|
return { nodePath, cliPath, args, command, source, isTransient };
|
|
2361
1940
|
};
|
|
2362
|
-
var getLaunchAgentPath = (home =
|
|
2363
|
-
return
|
|
1941
|
+
var getLaunchAgentPath = (home = homedir4()) => {
|
|
1942
|
+
return join5(home, "Library", "LaunchAgents", `${MAC_LABEL}.plist`);
|
|
2364
1943
|
};
|
|
2365
1944
|
var buildLaunchAgentPlist = (entrypoint, options = {}) => {
|
|
2366
1945
|
const label = options.label ?? MAC_LABEL;
|
|
2367
|
-
const stdoutPath = options.stdoutPath ??
|
|
2368
|
-
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");
|
|
2369
1948
|
const programArgs = [entrypoint.nodePath, ...entrypoint.args].map((value) => ` <string>${value}</string>`).join("\n");
|
|
2370
1949
|
return [
|
|
2371
1950
|
'<?xml version="1.0" encoding="UTF-8"?>',
|
|
@@ -2570,10 +2149,10 @@ var installMacAutostart = (deps = {}) => {
|
|
|
2570
2149
|
assertPersistentEntrypoint(entrypoint);
|
|
2571
2150
|
const home = resolved.homedir();
|
|
2572
2151
|
const plistPath = getLaunchAgentPath(home);
|
|
2573
|
-
const stdoutPath =
|
|
2574
|
-
const stderrPath =
|
|
2575
|
-
const logsDir =
|
|
2576
|
-
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 });
|
|
2577
2156
|
resolved.mkdirSync(logsDir, { recursive: true });
|
|
2578
2157
|
resolved.writeFileSync(
|
|
2579
2158
|
plistPath,
|
|
@@ -2950,7 +2529,7 @@ async function runDaemonCommand(args) {
|
|
|
2950
2529
|
}
|
|
2951
2530
|
|
|
2952
2531
|
// src/cli/commands/artifacts.ts
|
|
2953
|
-
import { join as
|
|
2532
|
+
import { join as join6, resolve as resolve4 } from "path";
|
|
2954
2533
|
import { tmpdir as tmpdir2 } from "os";
|
|
2955
2534
|
var PASSTHROUGH_BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
|
|
2956
2535
|
"--with-config",
|
|
@@ -3039,7 +2618,7 @@ var parseArtifactsArgs = (rawArgs) => {
|
|
|
3039
2618
|
};
|
|
3040
2619
|
async function runArtifactsCommand(args) {
|
|
3041
2620
|
const parsed = parseArtifactsArgs(args.rawArgs);
|
|
3042
|
-
const rootDir = parsed.outputDir ?
|
|
2621
|
+
const rootDir = parsed.outputDir ? resolve4(parsed.outputDir) : join6(tmpdir2(), "opendevbrowser");
|
|
3043
2622
|
const cleaned = await cleanupExpiredArtifacts(rootDir);
|
|
3044
2623
|
return {
|
|
3045
2624
|
success: true,
|
|
@@ -3150,34 +2729,34 @@ function formatAutostartReconciliationMessage(result) {
|
|
|
3150
2729
|
}
|
|
3151
2730
|
|
|
3152
2731
|
// src/cli/commands/run.ts
|
|
3153
|
-
import { readFileSync as
|
|
2732
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
3154
2733
|
|
|
3155
2734
|
// src/cli/output.ts
|
|
3156
2735
|
var normalizeExitCode = (code) => {
|
|
3157
2736
|
return Number.isInteger(code) ? Number(code) : 0;
|
|
3158
2737
|
};
|
|
3159
2738
|
var flushStream = (stream) => {
|
|
3160
|
-
return new Promise((
|
|
2739
|
+
return new Promise((resolve5) => {
|
|
3161
2740
|
if (!stream || typeof stream.write !== "function") {
|
|
3162
|
-
|
|
2741
|
+
resolve5();
|
|
3163
2742
|
return;
|
|
3164
2743
|
}
|
|
3165
2744
|
try {
|
|
3166
|
-
stream.write("", () =>
|
|
2745
|
+
stream.write("", () => resolve5());
|
|
3167
2746
|
} catch {
|
|
3168
|
-
|
|
2747
|
+
resolve5();
|
|
3169
2748
|
}
|
|
3170
2749
|
});
|
|
3171
2750
|
};
|
|
3172
2751
|
async function flushOutputAndExit(code, proc = process, timeoutMs = 250) {
|
|
3173
2752
|
const finalCode = normalizeExitCode(code);
|
|
3174
2753
|
proc.exitCode = finalCode;
|
|
3175
|
-
await new Promise((
|
|
2754
|
+
await new Promise((resolve5) => {
|
|
3176
2755
|
let settled = false;
|
|
3177
2756
|
const finish = () => {
|
|
3178
2757
|
if (settled) return;
|
|
3179
2758
|
settled = true;
|
|
3180
|
-
|
|
2759
|
+
resolve5();
|
|
3181
2760
|
};
|
|
3182
2761
|
const timer = setTimeout(finish, Math.max(0, timeoutMs));
|
|
3183
2762
|
timer.unref?.();
|
|
@@ -3299,13 +2878,13 @@ function parseRunArgs(rawArgs) {
|
|
|
3299
2878
|
return parsed;
|
|
3300
2879
|
}
|
|
3301
2880
|
function readScriptFromStdin() {
|
|
3302
|
-
return new Promise((
|
|
2881
|
+
return new Promise((resolve5, reject) => {
|
|
3303
2882
|
let data = "";
|
|
3304
2883
|
process.stdin.setEncoding("utf8");
|
|
3305
2884
|
process.stdin.on("data", (chunk) => {
|
|
3306
2885
|
data += chunk;
|
|
3307
2886
|
});
|
|
3308
|
-
process.stdin.on("end", () =>
|
|
2887
|
+
process.stdin.on("end", () => resolve5(data));
|
|
3309
2888
|
process.stdin.on("error", reject);
|
|
3310
2889
|
});
|
|
3311
2890
|
}
|
|
@@ -3314,7 +2893,7 @@ async function runScriptCommand(args) {
|
|
|
3314
2893
|
const outputOptions = { format: args.outputFormat, quiet: args.quiet };
|
|
3315
2894
|
let scriptRaw = "";
|
|
3316
2895
|
if (runArgs.scriptPath) {
|
|
3317
|
-
scriptRaw =
|
|
2896
|
+
scriptRaw = readFileSync2(runArgs.scriptPath, "utf-8");
|
|
3318
2897
|
} else if (!process.stdin.isTTY) {
|
|
3319
2898
|
scriptRaw = await readScriptFromStdin();
|
|
3320
2899
|
} else {
|
|
@@ -3539,16 +3118,16 @@ function promptYesNo(question, defaultYes) {
|
|
|
3539
3118
|
return Promise.resolve(false);
|
|
3540
3119
|
}
|
|
3541
3120
|
const suffix = defaultYes ? " [Y/n] " : " [y/N] ";
|
|
3542
|
-
return new Promise((
|
|
3121
|
+
return new Promise((resolve5) => {
|
|
3543
3122
|
process.stdout.write(`${question}${suffix}`);
|
|
3544
3123
|
process.stdin.setEncoding("utf8");
|
|
3545
3124
|
process.stdin.once("data", (data) => {
|
|
3546
3125
|
const input = data.toString().trim().toLowerCase();
|
|
3547
3126
|
if (!input) {
|
|
3548
|
-
|
|
3127
|
+
resolve5(defaultYes);
|
|
3549
3128
|
return;
|
|
3550
3129
|
}
|
|
3551
|
-
|
|
3130
|
+
resolve5(input === "y" || input === "yes");
|
|
3552
3131
|
});
|
|
3553
3132
|
});
|
|
3554
3133
|
}
|
|
@@ -3696,6 +3275,10 @@ var readFailures = (data) => {
|
|
|
3696
3275
|
const failures = meta.failures;
|
|
3697
3276
|
return Array.isArray(failures) ? failures.filter((entry) => Boolean(entry) && typeof entry === "object") : [];
|
|
3698
3277
|
};
|
|
3278
|
+
var readFollowthroughSummary = (data) => {
|
|
3279
|
+
const record = asRecord(data);
|
|
3280
|
+
return readNonEmptyString(record?.followthroughSummary) ?? readNonEmptyString(readMeta(data)?.followthroughSummary);
|
|
3281
|
+
};
|
|
3699
3282
|
var readSuggestedSteps = (data) => {
|
|
3700
3283
|
const steps = asRecord(data)?.suggestedSteps;
|
|
3701
3284
|
return Array.isArray(steps) ? steps.flatMap((step) => {
|
|
@@ -3737,6 +3320,13 @@ var buildWorkflowCompletionMessage = (workflowLabel, data) => {
|
|
|
3737
3320
|
inferred.guidance?.recommendedNextCommands[0] ?? null
|
|
3738
3321
|
);
|
|
3739
3322
|
}
|
|
3323
|
+
const followthroughSummary = readFollowthroughSummary(data);
|
|
3324
|
+
if (followthroughSummary) {
|
|
3325
|
+
return buildNextStepMessage(
|
|
3326
|
+
`${workflowLabel} completed. ${followthroughSummary}`,
|
|
3327
|
+
readSuggestedNextAction(data) ?? readSuggestedStepReason(data)
|
|
3328
|
+
);
|
|
3329
|
+
}
|
|
3740
3330
|
return `${workflowLabel} completed.`;
|
|
3741
3331
|
};
|
|
3742
3332
|
|
|
@@ -4495,7 +4085,7 @@ async function runAnnotate(args) {
|
|
|
4495
4085
|
}
|
|
4496
4086
|
|
|
4497
4087
|
// src/cli/commands/canvas.ts
|
|
4498
|
-
import { readFileSync as
|
|
4088
|
+
import { readFileSync as readFileSync3 } from "fs";
|
|
4499
4089
|
var DEFAULT_FEEDBACK_STREAM_TIMEOUT_MS = 3e4;
|
|
4500
4090
|
var isRecord = (value) => {
|
|
4501
4091
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -4696,7 +4286,7 @@ var resolveCanvasParams = (canvasArgs) => {
|
|
|
4696
4286
|
if (hasParamsFile) {
|
|
4697
4287
|
let raw = "";
|
|
4698
4288
|
try {
|
|
4699
|
-
raw =
|
|
4289
|
+
raw = readFileSync3(canvasArgs.paramsFile ?? "", "utf8");
|
|
4700
4290
|
} catch (error) {
|
|
4701
4291
|
const message = error instanceof Error ? error.message : "Unable to read file";
|
|
4702
4292
|
throw createUsageError(`Invalid --params-file: ${message}`);
|
|
@@ -4765,7 +4355,7 @@ async function runCanvas(args) {
|
|
|
4765
4355
|
}
|
|
4766
4356
|
|
|
4767
4357
|
// src/cli/commands/rpc.ts
|
|
4768
|
-
import { readFileSync as
|
|
4358
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
4769
4359
|
var requireValue4 = (value, flag) => {
|
|
4770
4360
|
if (!value) throw createUsageError(`Missing value for ${flag}`);
|
|
4771
4361
|
return value;
|
|
@@ -4845,7 +4435,7 @@ var resolveRpcParams = (rpcArgs) => {
|
|
|
4845
4435
|
if (hasParamsFile) {
|
|
4846
4436
|
let raw = "";
|
|
4847
4437
|
try {
|
|
4848
|
-
raw =
|
|
4438
|
+
raw = readFileSync4(rpcArgs.paramsFile ?? "", "utf8");
|
|
4849
4439
|
} catch (error) {
|
|
4850
4440
|
const message = error instanceof Error ? error.message : "Unable to read file";
|
|
4851
4441
|
throw createUsageError(`Invalid --params-file: ${message}`);
|
|
@@ -6225,11 +5815,11 @@ function parseScreenshotArgs(rawArgs) {
|
|
|
6225
5815
|
return parsed;
|
|
6226
5816
|
}
|
|
6227
5817
|
async function runScreenshot(args) {
|
|
6228
|
-
const { sessionId, targetId, path:
|
|
5818
|
+
const { sessionId, targetId, path: path5, ref, fullPage, timeoutMs } = parseScreenshotArgs(args.rawArgs);
|
|
6229
5819
|
if (!sessionId) throw createUsageError("Missing --session-id");
|
|
6230
5820
|
const params = {
|
|
6231
5821
|
sessionId,
|
|
6232
|
-
...typeof
|
|
5822
|
+
...typeof path5 === "string" ? { path: path5 } : {},
|
|
6233
5823
|
...typeof targetId === "string" ? { targetId } : {},
|
|
6234
5824
|
...typeof ref === "string" ? { ref } : {},
|
|
6235
5825
|
...fullPage === true ? { fullPage: true } : {}
|
|
@@ -6628,7 +6218,7 @@ async function runDesktopAccessibilitySnapshot(args) {
|
|
|
6628
6218
|
}
|
|
6629
6219
|
|
|
6630
6220
|
// src/cli/commands/session/cookie-import.ts
|
|
6631
|
-
import { readFileSync as
|
|
6221
|
+
import { readFileSync as readFileSync5 } from "fs";
|
|
6632
6222
|
var requireValue5 = (value, flag) => {
|
|
6633
6223
|
if (!value) {
|
|
6634
6224
|
throw createUsageError(`Missing value for ${flag}`);
|
|
@@ -6743,7 +6333,7 @@ var resolveCookies = (parsed) => {
|
|
|
6743
6333
|
}
|
|
6744
6334
|
let raw = "";
|
|
6745
6335
|
try {
|
|
6746
|
-
raw =
|
|
6336
|
+
raw = readFileSync5(parsed.cookiesFile ?? "", "utf8");
|
|
6747
6337
|
} catch (error) {
|
|
6748
6338
|
const message = error instanceof Error ? error.message : "Unable to read file";
|
|
6749
6339
|
throw createUsageError(`Invalid --cookies-file: ${message}`);
|
|
@@ -6874,6 +6464,26 @@ var requireValue7 = (value, flag) => {
|
|
|
6874
6464
|
}
|
|
6875
6465
|
return value;
|
|
6876
6466
|
};
|
|
6467
|
+
var asRecord2 = (value) => {
|
|
6468
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
6469
|
+
return null;
|
|
6470
|
+
}
|
|
6471
|
+
return value;
|
|
6472
|
+
};
|
|
6473
|
+
var hasExecutionBlocker = (result) => {
|
|
6474
|
+
const execution = asRecord2(asRecord2(result)?.execution);
|
|
6475
|
+
const meta = asRecord2(execution?.meta);
|
|
6476
|
+
return asRecord2(meta?.blocker) !== null;
|
|
6477
|
+
};
|
|
6478
|
+
var buildMacroResolveMessage = (execute, result) => {
|
|
6479
|
+
if (!execute) {
|
|
6480
|
+
return "Macro resolved.";
|
|
6481
|
+
}
|
|
6482
|
+
if (hasExecutionBlocker(result)) {
|
|
6483
|
+
return "Macro resolved, but execution is blocked and needs follow-up.";
|
|
6484
|
+
}
|
|
6485
|
+
return "Macro resolved and executed.";
|
|
6486
|
+
};
|
|
6877
6487
|
var parseMacroResolveArgs = (rawArgs) => {
|
|
6878
6488
|
const parsed = {};
|
|
6879
6489
|
for (let index = 0; index < rawArgs.length; index += 1) {
|
|
@@ -6952,7 +6562,7 @@ async function runMacroResolve(args) {
|
|
|
6952
6562
|
}) : await callDaemon("macro.resolve", params);
|
|
6953
6563
|
return {
|
|
6954
6564
|
success: true,
|
|
6955
|
-
message: parsed.execute
|
|
6565
|
+
message: buildMacroResolveMessage(parsed.execute ?? false, result),
|
|
6956
6566
|
data: result
|
|
6957
6567
|
};
|
|
6958
6568
|
}
|
|
@@ -7759,7 +7369,7 @@ async function runInspiredesignCommand(args) {
|
|
|
7759
7369
|
// package.json
|
|
7760
7370
|
var package_default = {
|
|
7761
7371
|
name: "opendevbrowser",
|
|
7762
|
-
version: "0.0.
|
|
7372
|
+
version: "0.0.22",
|
|
7763
7373
|
description: "Browser automation runtime with snapshot-refs-actions, browser replay screencasts, public read-only desktop observation, and browser-scoped computer-use orchestration",
|
|
7764
7374
|
type: "module",
|
|
7765
7375
|
main: "dist/index.js",
|
|
@@ -7770,6 +7380,7 @@ var package_default = {
|
|
|
7770
7380
|
files: [
|
|
7771
7381
|
"dist",
|
|
7772
7382
|
"skills",
|
|
7383
|
+
"scripts/postinstall-sync-skills.mjs",
|
|
7773
7384
|
"scripts/native",
|
|
7774
7385
|
"extension/canvas.html",
|
|
7775
7386
|
"extension/manifest.json",
|
|
@@ -7804,8 +7415,8 @@ var package_default = {
|
|
|
7804
7415
|
node: ">=18"
|
|
7805
7416
|
},
|
|
7806
7417
|
scripts: {
|
|
7807
|
-
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",
|
|
7808
|
-
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",
|
|
7809
7420
|
lint: 'node scripts/run-package-tool.mjs eslint "src/**/*.ts" "tests/**/*.ts"',
|
|
7810
7421
|
typecheck: "node scripts/run-package-tool.mjs tsc --noEmit -p tsconfig.json",
|
|
7811
7422
|
test: "node scripts/run-vitest-coverage.mjs",
|
|
@@ -7820,7 +7431,8 @@ var package_default = {
|
|
|
7820
7431
|
"extension:pack": "cd extension && zip -r ../opendevbrowser-extension.zip manifest.json popup.html canvas.html dist/ icons/",
|
|
7821
7432
|
"extension:store": "node scripts/chrome-store-publish.mjs",
|
|
7822
7433
|
"version:check": "node scripts/verify-versions.mjs",
|
|
7823
|
-
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"
|
|
7824
7436
|
},
|
|
7825
7437
|
dependencies: {
|
|
7826
7438
|
"@opencode-ai/plugin": "^1.2.25",
|
|
@@ -7848,8 +7460,10 @@ var package_default = {
|
|
|
7848
7460
|
}
|
|
7849
7461
|
};
|
|
7850
7462
|
|
|
7851
|
-
// src/cli/
|
|
7852
|
-
|
|
7463
|
+
// src/cli/update-skill-modes.ts
|
|
7464
|
+
function shouldRefreshManagedSkills(mode) {
|
|
7465
|
+
return hasManagedBundledSkillInstall(mode) || hasBundledSkillArtifacts(mode);
|
|
7466
|
+
}
|
|
7853
7467
|
function resolveUpdateSkillModes(args) {
|
|
7854
7468
|
if (args.rawArgs.includes("--no-skills")) {
|
|
7855
7469
|
return [];
|
|
@@ -7863,22 +7477,102 @@ function resolveUpdateSkillModes(args) {
|
|
|
7863
7477
|
if (args.mode) {
|
|
7864
7478
|
return [args.mode];
|
|
7865
7479
|
}
|
|
7866
|
-
const installed = findInstalledConfigs();
|
|
7867
7480
|
const modes = [];
|
|
7868
|
-
if (
|
|
7481
|
+
if (shouldRefreshManagedSkills("global")) {
|
|
7869
7482
|
modes.push("global");
|
|
7870
7483
|
}
|
|
7871
|
-
if (
|
|
7484
|
+
if (shouldRefreshManagedSkills("local")) {
|
|
7872
7485
|
modes.push("local");
|
|
7873
7486
|
}
|
|
7874
7487
|
return modes;
|
|
7875
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";
|
|
7876
7570
|
async function promptInstallMode() {
|
|
7877
7571
|
if (!process.stdin.isTTY) {
|
|
7878
7572
|
console.log("Non-interactive mode detected. Using global install.");
|
|
7879
7573
|
return "global";
|
|
7880
7574
|
}
|
|
7881
|
-
return new Promise((
|
|
7575
|
+
return new Promise((resolve5) => {
|
|
7882
7576
|
console.log("\nWhere would you like to install opendevbrowser?\n");
|
|
7883
7577
|
console.log(" 1. Global (~/.config/opencode/opencode.json)");
|
|
7884
7578
|
console.log(" 2. Local (./opencode.json in this project)\n");
|
|
@@ -7898,23 +7592,23 @@ async function promptInstallMode() {
|
|
|
7898
7592
|
resolved = true;
|
|
7899
7593
|
const input = data.toString().trim();
|
|
7900
7594
|
if (input === "2") {
|
|
7901
|
-
|
|
7595
|
+
resolve5("local");
|
|
7902
7596
|
} else {
|
|
7903
|
-
|
|
7597
|
+
resolve5("global");
|
|
7904
7598
|
}
|
|
7905
7599
|
});
|
|
7906
7600
|
process.stdin.once("close", () => {
|
|
7907
7601
|
cleanup();
|
|
7908
7602
|
if (resolved) return;
|
|
7909
7603
|
resolved = true;
|
|
7910
|
-
|
|
7604
|
+
resolve5("global");
|
|
7911
7605
|
});
|
|
7912
7606
|
timeoutId = setTimeout(() => {
|
|
7913
7607
|
timeoutId = null;
|
|
7914
7608
|
if (resolved) return;
|
|
7915
7609
|
resolved = true;
|
|
7916
7610
|
console.log("\nTimeout - using global install.");
|
|
7917
|
-
|
|
7611
|
+
resolve5("global");
|
|
7918
7612
|
}, 3e4);
|
|
7919
7613
|
});
|
|
7920
7614
|
}
|
|
@@ -7934,7 +7628,7 @@ async function promptUninstallMode() {
|
|
|
7934
7628
|
console.log("Plugin found in both global and local configs. Use --global or --local flag.");
|
|
7935
7629
|
return null;
|
|
7936
7630
|
}
|
|
7937
|
-
return new Promise((
|
|
7631
|
+
return new Promise((resolve5) => {
|
|
7938
7632
|
console.log("\nopendevbrowser is installed in multiple locations:\n");
|
|
7939
7633
|
console.log(" 1. Global (~/.config/opencode/opencode.json)");
|
|
7940
7634
|
console.log(" 2. Local (./opencode.json)");
|
|
@@ -7944,15 +7638,15 @@ async function promptUninstallMode() {
|
|
|
7944
7638
|
process.stdin.once("data", (data) => {
|
|
7945
7639
|
const input = data.toString().trim();
|
|
7946
7640
|
if (input === "1") {
|
|
7947
|
-
|
|
7641
|
+
resolve5("global");
|
|
7948
7642
|
} else if (input === "2") {
|
|
7949
|
-
|
|
7643
|
+
resolve5("local");
|
|
7950
7644
|
} else {
|
|
7951
|
-
|
|
7645
|
+
resolve5(null);
|
|
7952
7646
|
}
|
|
7953
7647
|
});
|
|
7954
7648
|
process.stdin.once("close", () => {
|
|
7955
|
-
|
|
7649
|
+
resolve5(null);
|
|
7956
7650
|
});
|
|
7957
7651
|
});
|
|
7958
7652
|
}
|
|
@@ -8010,22 +7704,14 @@ async function main() {
|
|
|
8010
7704
|
registerCommand({
|
|
8011
7705
|
name: "update",
|
|
8012
7706
|
description: "Clear cached plugin and refresh managed skill packs",
|
|
8013
|
-
run: () => {
|
|
8014
|
-
|
|
8015
|
-
|
|
8016
|
-
|
|
8017
|
-
|
|
8018
|
-
|
|
8019
|
-
|
|
8020
|
-
|
|
8021
|
-
message,
|
|
8022
|
-
data: {
|
|
8023
|
-
cacheCleared: result2.cleared,
|
|
8024
|
-
skillModes,
|
|
8025
|
-
skills: skillResults
|
|
8026
|
-
}
|
|
8027
|
-
};
|
|
8028
|
-
}
|
|
7707
|
+
run: () => buildUpdateCommandResult(args, runUpdate(), {
|
|
7708
|
+
resolveUpdateSkillModes,
|
|
7709
|
+
hasInstalledConfig,
|
|
7710
|
+
hasBundledSkillArtifacts,
|
|
7711
|
+
getBundledSkillTargets,
|
|
7712
|
+
getBundledSkillLifecycleTargets,
|
|
7713
|
+
syncBundledSkillsForTargets
|
|
7714
|
+
})
|
|
8029
7715
|
});
|
|
8030
7716
|
registerCommand({
|
|
8031
7717
|
name: "uninstall",
|
|
@@ -8041,18 +7727,11 @@ async function main() {
|
|
|
8041
7727
|
if (!mode) {
|
|
8042
7728
|
return { success: false, message: "Error: Please specify --global or --local for uninstall.", exitCode: EXIT_USAGE };
|
|
8043
7729
|
}
|
|
8044
|
-
|
|
8045
|
-
|
|
8046
|
-
|
|
8047
|
-
|
|
8048
|
-
|
|
8049
|
-
success: result2.success && (skillsResult?.success ?? true),
|
|
8050
|
-
message: [result2.message, skillMessage].filter(Boolean).join("\n"),
|
|
8051
|
-
data: {
|
|
8052
|
-
config: result2,
|
|
8053
|
-
skills: skillsResult
|
|
8054
|
-
}
|
|
8055
|
-
};
|
|
7730
|
+
return buildUninstallCommandResult(args, mode, runUninstall(mode), {
|
|
7731
|
+
hasBundledSkillArtifacts,
|
|
7732
|
+
getBundledSkillLifecycleTargets,
|
|
7733
|
+
removeBundledSkillsForTargets
|
|
7734
|
+
});
|
|
8056
7735
|
}
|
|
8057
7736
|
});
|
|
8058
7737
|
registerCommand({
|