@brainervirus/workit-cli 2.0.1 → 2.1.0
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 +36 -7
- package/dist/index.js +2405 -343
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -49793,13 +49793,6 @@ var workspaceConfigSchema = object({
|
|
|
49793
49793
|
profiles: record(nonBlank, workspaceProfileSchema).optional(),
|
|
49794
49794
|
releaseTracks: record(nonBlank, releaseTrackSchema).optional()
|
|
49795
49795
|
}).passthrough().superRefine((workspace, context) => {
|
|
49796
|
-
if (workspace.youtrack && workspace.vcs?.provider !== "gitlab") {
|
|
49797
|
-
context.addIssue({
|
|
49798
|
-
code: "custom",
|
|
49799
|
-
path: ["youtrack"],
|
|
49800
|
-
message: `YouTrack issue linking requires the gitlab provider, got ${workspace.vcs?.provider ?? "unset"}`
|
|
49801
|
-
});
|
|
49802
|
-
}
|
|
49803
49796
|
if (workspace.issues && workspace.vcs?.provider !== "github") {
|
|
49804
49797
|
context.addIssue({
|
|
49805
49798
|
code: "custom",
|
|
@@ -49992,13 +49985,10 @@ var selectWorkspaceMatch = (matches, cwd, workspaceName) => {
|
|
|
49992
49985
|
}
|
|
49993
49986
|
return mostSpecific[0];
|
|
49994
49987
|
};
|
|
49995
|
-
var
|
|
49996
|
-
const result = readWorkspacesResult(dir);
|
|
49997
|
-
if (result.status === "malformed" || result.status === "invalid")
|
|
49998
|
-
throw new Error(result.error);
|
|
49988
|
+
var resolveWorkspaceFromEntries = (cwd, entries, workspaceName) => {
|
|
49999
49989
|
const targets = [cwd, realpathOf(cwd)].map((p) => p.replaceAll("\\", "/"));
|
|
50000
49990
|
const matches = [];
|
|
50001
|
-
for (const ws of
|
|
49991
|
+
for (const ws of entries) {
|
|
50002
49992
|
const glob = ws.glob.replaceAll("\\", "/");
|
|
50003
49993
|
const canonical = canonicalGlob(glob);
|
|
50004
49994
|
let matched = false;
|
|
@@ -50013,6 +50003,12 @@ var resolveWorkspaceFrom = (cwd, dir, workspaceName) => {
|
|
|
50013
50003
|
}
|
|
50014
50004
|
return selectWorkspaceMatch(matches, cwd, workspaceName) ?? null;
|
|
50015
50005
|
};
|
|
50006
|
+
var resolveWorkspaceFrom = (cwd, dir, workspaceName) => {
|
|
50007
|
+
const result = readWorkspacesResult(dir);
|
|
50008
|
+
if (result.status === "malformed" || result.status === "invalid")
|
|
50009
|
+
throw new Error(result.error);
|
|
50010
|
+
return resolveWorkspaceFromEntries(cwd, result.entries, workspaceName);
|
|
50011
|
+
};
|
|
50016
50012
|
var runtimeWorkspacePolicySchema = (kind) => {
|
|
50017
50013
|
const key = kind === "branch" ? "branchPolicy" : kind === "commit" ? "commitPolicy" : "vcs";
|
|
50018
50014
|
const policySchema = kind === "branch" ? workspaceBranchPolicySchema : kind === "commit" ? workspaceCommitPolicySchema : object({
|
|
@@ -50096,6 +50092,48 @@ var resolveRuntimeWorkspacePolicy = (cwd, kind, requestedProfile) => {
|
|
|
50096
50092
|
source: profilePolicy ? `profile:${profileName}` : workspacePolicy ? `workspace:${candidate.name}` : "user-default"
|
|
50097
50093
|
};
|
|
50098
50094
|
};
|
|
50095
|
+
var resolveWorkspaceProfile = (workspace, requestedProfile) => {
|
|
50096
|
+
const profileName = requestedProfile ?? workspace.defaultProfile ?? null;
|
|
50097
|
+
const profile = profileName ? workspace.profiles?.[profileName] : undefined;
|
|
50098
|
+
if (profileName && !profile) {
|
|
50099
|
+
return {
|
|
50100
|
+
status: "invalid",
|
|
50101
|
+
error: `workspace ${JSON.stringify(workspace.name)} has no profile ${JSON.stringify(profileName)}`
|
|
50102
|
+
};
|
|
50103
|
+
}
|
|
50104
|
+
const effectiveWorkspace = profile ? {
|
|
50105
|
+
...workspace,
|
|
50106
|
+
...profile.branchPolicy ? { branchPolicy: profile.branchPolicy } : {},
|
|
50107
|
+
...profile.commitPolicy ? { commitPolicy: profile.commitPolicy } : {}
|
|
50108
|
+
} : workspace;
|
|
50109
|
+
return {
|
|
50110
|
+
status: "resolved",
|
|
50111
|
+
profileName,
|
|
50112
|
+
workspace: effectiveWorkspace,
|
|
50113
|
+
provenance: {
|
|
50114
|
+
branchPolicy: profile?.branchPolicy ? `profile:${profileName}` : workspace.branchPolicy ? `workspace:${workspace.name}` : "user-default",
|
|
50115
|
+
commitPolicy: profile?.commitPolicy ? `profile:${profileName}` : workspace.commitPolicy ? `workspace:${workspace.name}` : "user-default"
|
|
50116
|
+
}
|
|
50117
|
+
};
|
|
50118
|
+
};
|
|
50119
|
+
var resolveWorkspacePolicy = (config, workspace, profileName) => {
|
|
50120
|
+
const selected = workspace ? resolveWorkspaceProfile(workspace, profileName) : {
|
|
50121
|
+
status: "resolved",
|
|
50122
|
+
profileName: null,
|
|
50123
|
+
workspace: null,
|
|
50124
|
+
provenance: { branchPolicy: "user-default", commitPolicy: "user-default" }
|
|
50125
|
+
};
|
|
50126
|
+
if (selected.status === "invalid")
|
|
50127
|
+
return selected;
|
|
50128
|
+
return {
|
|
50129
|
+
status: "resolved",
|
|
50130
|
+
workspace: selected.workspace,
|
|
50131
|
+
profileName: selected.profileName,
|
|
50132
|
+
branchPolicy: resolveBranchPolicy(config, selected.workspace),
|
|
50133
|
+
commitPolicy: resolveCommitPolicy(config, selected.workspace),
|
|
50134
|
+
provenance: selected.provenance
|
|
50135
|
+
};
|
|
50136
|
+
};
|
|
50099
50137
|
|
|
50100
50138
|
// packages/workit-core/src/core/gitignore.ts
|
|
50101
50139
|
var GITIGNORE_ENTRIES = [
|
|
@@ -50607,20 +50645,20 @@ function writeFileAtomic(file, content, mode) {
|
|
|
50607
50645
|
import {
|
|
50608
50646
|
copyFileSync as copyFileSync2,
|
|
50609
50647
|
cpSync as cpSync3,
|
|
50610
|
-
existsSync as
|
|
50648
|
+
existsSync as existsSync11,
|
|
50611
50649
|
lstatSync as lstatSync4,
|
|
50612
50650
|
mkdirSync as mkdirSync5,
|
|
50613
50651
|
mkdtempSync,
|
|
50614
|
-
readFileSync as
|
|
50615
|
-
readdirSync as
|
|
50652
|
+
readFileSync as readFileSync12,
|
|
50653
|
+
readdirSync as readdirSync5,
|
|
50616
50654
|
realpathSync as realpathSync2,
|
|
50617
50655
|
renameSync as renameSync2,
|
|
50618
50656
|
rmSync,
|
|
50619
|
-
statSync as
|
|
50657
|
+
statSync as statSync4,
|
|
50620
50658
|
writeFileSync as writeFileSync5
|
|
50621
50659
|
} from "node:fs";
|
|
50622
|
-
import
|
|
50623
|
-
import
|
|
50660
|
+
import os7 from "node:os";
|
|
50661
|
+
import path14 from "node:path";
|
|
50624
50662
|
import { isDeepStrictEqual as isDeepStrictEqual2 } from "node:util";
|
|
50625
50663
|
|
|
50626
50664
|
// packages/workit-core/src/core/branch-policy.ts
|
|
@@ -50729,7 +50767,7 @@ var named = (s, name) => s === name || s.startsWith(`${name}@`);
|
|
|
50729
50767
|
function isWorkitPlugin(value) {
|
|
50730
50768
|
const s = String(value).replaceAll("\\", "/");
|
|
50731
50769
|
const url = s.startsWith("file://") || s.startsWith("git+file://");
|
|
50732
|
-
const pkgPath =
|
|
50770
|
+
const pkgPath = /\/(?:packages\/workit-(?:opencode|cursor)|node_modules\/@brainervirus\/workit-(?:opencode|cursor))(?:\/|$)/.test(s);
|
|
50733
50771
|
return named(s, "workflow-toolkit") || named(s, "workflow-toolkit-opencode") || named(s, "local/workflow-toolkit") || named(s, "workit") || named(s, "local/workit") || named(s, "@brainervirus/workit-opencode") || named(s, "@brainervirus/workit-cursor") || url && pkgPath || s.startsWith("git+file://") && s.includes("workflow-toolkit");
|
|
50734
50772
|
}
|
|
50735
50773
|
function mergeOpenCodePlugins(plugin, pin) {
|
|
@@ -53344,9 +53382,10 @@ var parsesAsConfigObject = (p) => {
|
|
|
53344
53382
|
}
|
|
53345
53383
|
};
|
|
53346
53384
|
var pluginEntries = (cfg) => {
|
|
53347
|
-
const
|
|
53348
|
-
|
|
53349
|
-
|
|
53385
|
+
const entries = [cfg?.plugins, cfg?.plugin].flatMap((value) => Array.isArray(value) ? value : typeof value === "string" ? [value] : []);
|
|
53386
|
+
return [
|
|
53387
|
+
...new Set(entries.filter((entry) => typeof entry === "string" && isWorkitPlugin(entry)))
|
|
53388
|
+
];
|
|
53350
53389
|
};
|
|
53351
53390
|
var commandOnPath = (name, env) => {
|
|
53352
53391
|
const dirs = (env.PATH ?? process.env.PATH ?? "").split(path12.delimiter);
|
|
@@ -54603,6 +54642,351 @@ var runDoctor = (options = {}) => {
|
|
|
54603
54642
|
return report;
|
|
54604
54643
|
};
|
|
54605
54644
|
|
|
54645
|
+
// packages/workit-core/src/core/host-install.ts
|
|
54646
|
+
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
54647
|
+
import { accessSync, constants as constants2, existsSync as existsSync10, readFileSync as readFileSync11, readdirSync as readdirSync4, statSync as statSync3 } from "node:fs";
|
|
54648
|
+
import os6 from "node:os";
|
|
54649
|
+
import path13 from "node:path";
|
|
54650
|
+
function hostCommand(name, args, options = {}) {
|
|
54651
|
+
const executable = findHostExecutable(name, options);
|
|
54652
|
+
if (!executable)
|
|
54653
|
+
throw new Error(`${name} executable was not found on PATH or supported user bin directories`);
|
|
54654
|
+
if (process.platform === "win32" && /\.(?:cmd|bat)$/i.test(executable)) {
|
|
54655
|
+
const node = findHostExecutable("node", options);
|
|
54656
|
+
if (!node)
|
|
54657
|
+
throw new Error(`Node.js is required to run the ${name} Windows shim`);
|
|
54658
|
+
const script = resolveWindowsShimScript(executable);
|
|
54659
|
+
if (!script)
|
|
54660
|
+
throw new Error(`could not resolve the ${name} Windows shim to a JavaScript entrypoint`);
|
|
54661
|
+
return { command: node, args: [script, ...args], cwd: options.cwd, purpose: `${name} CLI` };
|
|
54662
|
+
}
|
|
54663
|
+
return { command: executable, args, cwd: options.cwd, purpose: `${name} CLI` };
|
|
54664
|
+
}
|
|
54665
|
+
function resolveWindowsShimEntry(contents, shim, exists = existsSync10) {
|
|
54666
|
+
const root = path13.win32.dirname(shim);
|
|
54667
|
+
const matches = contents.matchAll(/(["']?)([^\r\n"']*node_modules[\\/][^\r\n"']+?\.js)\1/gi);
|
|
54668
|
+
for (const match of matches) {
|
|
54669
|
+
const raw = match[2].replace(/%~?dp0%?/gi, root);
|
|
54670
|
+
const candidate = path13.win32.isAbsolute(raw) ? raw : path13.win32.resolve(root, raw);
|
|
54671
|
+
if (exists(candidate))
|
|
54672
|
+
return candidate;
|
|
54673
|
+
}
|
|
54674
|
+
return null;
|
|
54675
|
+
}
|
|
54676
|
+
var resolveWindowsShimScript = (shim) => {
|
|
54677
|
+
try {
|
|
54678
|
+
const contents = readFileSync11(shim, "utf8");
|
|
54679
|
+
return resolveWindowsShimEntry(contents, shim);
|
|
54680
|
+
} catch {
|
|
54681
|
+
return null;
|
|
54682
|
+
}
|
|
54683
|
+
};
|
|
54684
|
+
var MARKETPLACE = "https://github.com/BrainerVirus/workit.git";
|
|
54685
|
+
var CODEX_MARKETPLACE_NAME = "workflow-toolkit";
|
|
54686
|
+
var validPackageVersion = (value) => value === "latest" || /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(value);
|
|
54687
|
+
var nodePrerequisite = (options) => {
|
|
54688
|
+
const node = findHostExecutable("node", options);
|
|
54689
|
+
if (!node)
|
|
54690
|
+
throw new Error("Workit host packages require Node.js 24+; install Node.js and retry");
|
|
54691
|
+
return {
|
|
54692
|
+
command: node,
|
|
54693
|
+
args: [
|
|
54694
|
+
"-e",
|
|
54695
|
+
'const v=Number(process.versions.node.split(".")[0]);if(v<24){console.error(`Workit host packages require Node.js 24+ (found ${process.versions.node})`);process.exit(1)}'
|
|
54696
|
+
],
|
|
54697
|
+
cwd: options.cwd,
|
|
54698
|
+
purpose: "Check the Node.js 24+ package runtime requirement"
|
|
54699
|
+
};
|
|
54700
|
+
};
|
|
54701
|
+
function findHostExecutable(name, options = {}) {
|
|
54702
|
+
const env = options.env ?? process.env;
|
|
54703
|
+
const home = options.home ?? env.HOME ?? os6.homedir();
|
|
54704
|
+
const suffixes = process.platform === "win32" ? ["", ".exe", ".cmd", ".bat"] : [""];
|
|
54705
|
+
const dirs = (env.PATH ?? "").split(path13.delimiter).filter(Boolean);
|
|
54706
|
+
dirs.push(path13.join(home, ".local", "bin"), path13.join(home, ".asdf", "shims"));
|
|
54707
|
+
for (const [base, tail] of [
|
|
54708
|
+
[path13.join(home, ".local", "share", "fnm", "node-versions"), path13.join("installation", "bin")],
|
|
54709
|
+
[path13.join(home, ".nvm", "versions", "node"), "bin"]
|
|
54710
|
+
]) {
|
|
54711
|
+
try {
|
|
54712
|
+
for (const entry of readdirSync4(base, { withFileTypes: true })) {
|
|
54713
|
+
if (entry.isDirectory())
|
|
54714
|
+
dirs.push(path13.join(base, entry.name, tail));
|
|
54715
|
+
}
|
|
54716
|
+
} catch {}
|
|
54717
|
+
}
|
|
54718
|
+
for (const dir of dirs) {
|
|
54719
|
+
for (const suffix of suffixes) {
|
|
54720
|
+
const candidate = path13.join(dir, `${name}${suffix}`);
|
|
54721
|
+
try {
|
|
54722
|
+
if (statSync3(candidate).isFile()) {
|
|
54723
|
+
if (process.platform === "win32")
|
|
54724
|
+
return candidate;
|
|
54725
|
+
accessSync(candidate, constants2.X_OK);
|
|
54726
|
+
return candidate;
|
|
54727
|
+
}
|
|
54728
|
+
} catch {}
|
|
54729
|
+
}
|
|
54730
|
+
}
|
|
54731
|
+
return null;
|
|
54732
|
+
}
|
|
54733
|
+
var isPiWorkitInstalled = (home, env = process.env) => {
|
|
54734
|
+
const settings = path13.join(env.PI_CODING_AGENT_DIR ?? path13.join(home, ".pi", "agent"), "settings.json");
|
|
54735
|
+
try {
|
|
54736
|
+
const document2 = JSON.parse(readFileSync11(settings, "utf8"));
|
|
54737
|
+
return (document2.packages ?? []).some((entry) => {
|
|
54738
|
+
const source = entry && typeof entry === "object" && !Array.isArray(entry) ? entry.source : entry;
|
|
54739
|
+
const value = String(source).replaceAll("\\", "/").replace(/\/+$/, "");
|
|
54740
|
+
return /^npm:@brainervirus\/workit-pi(?:@[^/]+)?$/.test(value) || value === "@brainervirus/workit-pi" || /(?:^|\/)packages\/workit-pi$/.test(value);
|
|
54741
|
+
});
|
|
54742
|
+
} catch {
|
|
54743
|
+
return false;
|
|
54744
|
+
}
|
|
54745
|
+
};
|
|
54746
|
+
var isCanonicalCodexPackage = (root) => {
|
|
54747
|
+
for (const file of [
|
|
54748
|
+
path13.join(root, ".codex-plugin", "plugin.json"),
|
|
54749
|
+
path13.join(root, "package.json")
|
|
54750
|
+
]) {
|
|
54751
|
+
try {
|
|
54752
|
+
const manifest = JSON.parse(readFileSync11(file, "utf8"));
|
|
54753
|
+
const repository = typeof manifest.repository === "string" ? manifest.repository : manifest.repository?.url;
|
|
54754
|
+
if ((manifest.name === "workit" || manifest.name === "@brainervirus/workit-codex") && repository?.replace(/\.git$/, "").toLowerCase() === "https://github.com/brainervirus/workit")
|
|
54755
|
+
return true;
|
|
54756
|
+
} catch {}
|
|
54757
|
+
}
|
|
54758
|
+
return false;
|
|
54759
|
+
};
|
|
54760
|
+
var isCodexWorkitInstalled = (home, env = process.env) => {
|
|
54761
|
+
const codexHome = env.CODEX_HOME ?? path13.join(home, ".codex");
|
|
54762
|
+
const isPackageOrVersionDirectory = (root) => {
|
|
54763
|
+
if (isCanonicalCodexPackage(root))
|
|
54764
|
+
return true;
|
|
54765
|
+
try {
|
|
54766
|
+
return readdirSync4(root, { withFileTypes: true }).some((entry) => entry.isDirectory() && isCanonicalCodexPackage(path13.join(root, entry.name)));
|
|
54767
|
+
} catch {
|
|
54768
|
+
return false;
|
|
54769
|
+
}
|
|
54770
|
+
};
|
|
54771
|
+
if (isPackageOrVersionDirectory(path13.join(codexHome, "plugins", "workit")))
|
|
54772
|
+
return true;
|
|
54773
|
+
const root = path13.join(codexHome, "plugins", "cache");
|
|
54774
|
+
try {
|
|
54775
|
+
for (const marketplace of readdirSync4(root, { withFileTypes: true })) {
|
|
54776
|
+
if (!marketplace.isDirectory())
|
|
54777
|
+
continue;
|
|
54778
|
+
if (isPackageOrVersionDirectory(path13.join(root, marketplace.name, "workit")))
|
|
54779
|
+
return true;
|
|
54780
|
+
}
|
|
54781
|
+
} catch {
|
|
54782
|
+
return false;
|
|
54783
|
+
}
|
|
54784
|
+
return false;
|
|
54785
|
+
};
|
|
54786
|
+
function installedHostApp(host, home, env = process.env, platform = process.platform, exists = existsSync10) {
|
|
54787
|
+
const candidates = [];
|
|
54788
|
+
const pathApi = platform === "win32" ? path13.win32 : path13;
|
|
54789
|
+
if (platform === "darwin") {
|
|
54790
|
+
const app = host === "cursor" ? "Cursor.app" : host === "codex" ? "Codex.app" : host === "opencode" ? "OpenCode.app" : "";
|
|
54791
|
+
if (app)
|
|
54792
|
+
candidates.push(`/Applications/${app}`, pathApi.join(home, "Applications", app));
|
|
54793
|
+
} else if (platform === "win32") {
|
|
54794
|
+
const local = env.LOCALAPPDATA ?? pathApi.join(home, "AppData", "Local");
|
|
54795
|
+
if (host === "cursor")
|
|
54796
|
+
candidates.push(pathApi.join(local, "Programs", "Cursor", "Cursor.exe"));
|
|
54797
|
+
if (host === "codex")
|
|
54798
|
+
candidates.push(pathApi.join(local, "Programs", "Codex", "Codex.exe"));
|
|
54799
|
+
if (host === "opencode")
|
|
54800
|
+
candidates.push(pathApi.join(local, "Programs", "OpenCode", "OpenCode.exe"));
|
|
54801
|
+
}
|
|
54802
|
+
return candidates.some(exists);
|
|
54803
|
+
}
|
|
54804
|
+
function planHostInstall(host, options = {}) {
|
|
54805
|
+
const env = options.env ?? process.env;
|
|
54806
|
+
const home = options.home ?? env.HOME ?? os6.homedir();
|
|
54807
|
+
const cwd = options.cwd ?? process.cwd();
|
|
54808
|
+
const version = options.packageVersion ?? "latest";
|
|
54809
|
+
if (!validPackageVersion(version))
|
|
54810
|
+
throw new Error(`unsupported package version selector: ${version}`);
|
|
54811
|
+
if (options.alreadyInstalled && options.mode !== "upgrade")
|
|
54812
|
+
return [];
|
|
54813
|
+
const upgrading = options.mode === "upgrade";
|
|
54814
|
+
if (host === "codex") {
|
|
54815
|
+
if (!upgrading && isCodexWorkitInstalled(home, env))
|
|
54816
|
+
return [];
|
|
54817
|
+
const base = hostCommand("codex", [], { home, cwd, env });
|
|
54818
|
+
return [
|
|
54819
|
+
nodePrerequisite({ home, cwd, env }),
|
|
54820
|
+
{
|
|
54821
|
+
...base,
|
|
54822
|
+
args: [...base.args, "plugin", "marketplace", "list"],
|
|
54823
|
+
purpose: "Check whether the Workit marketplace is already registered"
|
|
54824
|
+
},
|
|
54825
|
+
{
|
|
54826
|
+
...base,
|
|
54827
|
+
args: [
|
|
54828
|
+
...base.args,
|
|
54829
|
+
"plugin",
|
|
54830
|
+
"marketplace",
|
|
54831
|
+
upgrading ? "upgrade" : "add",
|
|
54832
|
+
...upgrading ? [CODEX_MARKETPLACE_NAME] : [MARKETPLACE]
|
|
54833
|
+
],
|
|
54834
|
+
purpose: upgrading ? "Refresh the Workit Codex marketplace" : "Register the Workit Codex marketplace",
|
|
54835
|
+
...upgrading ? {} : { skipWhenOutputIncludes: CODEX_MARKETPLACE_NAME }
|
|
54836
|
+
},
|
|
54837
|
+
{
|
|
54838
|
+
...base,
|
|
54839
|
+
args: [...base.args, "plugin", "add", `workit@${CODEX_MARKETPLACE_NAME}`],
|
|
54840
|
+
purpose: upgrading ? "Refresh the Workit Codex plugin" : "Install the Workit Codex plugin"
|
|
54841
|
+
}
|
|
54842
|
+
];
|
|
54843
|
+
}
|
|
54844
|
+
if (host === "pi") {
|
|
54845
|
+
if (!upgrading && isPiWorkitInstalled(home, env))
|
|
54846
|
+
return [];
|
|
54847
|
+
const base = hostCommand("pi", [], { home, cwd, env });
|
|
54848
|
+
return [
|
|
54849
|
+
nodePrerequisite({ home, cwd, env }),
|
|
54850
|
+
{
|
|
54851
|
+
...base,
|
|
54852
|
+
args: upgrading ? [...base.args, "update", "--extension", "npm:@brainervirus/workit-pi"] : [...base.args, "install", `npm:@brainervirus/workit-pi@${version}`],
|
|
54853
|
+
purpose: upgrading ? "Update the Workit Pi package" : "Install the Workit Pi package in personal Pi settings"
|
|
54854
|
+
}
|
|
54855
|
+
];
|
|
54856
|
+
}
|
|
54857
|
+
if (host === "cursor") {
|
|
54858
|
+
const node = findHostExecutable("node", { home, env });
|
|
54859
|
+
if (!node)
|
|
54860
|
+
throw new Error("Workit host packages require Node.js 24+; install Node.js and retry");
|
|
54861
|
+
const npm = findHostExecutable("npm", { home, env });
|
|
54862
|
+
const npmCli = npm ? findNpmCli(npm) : null;
|
|
54863
|
+
if (!npmCli)
|
|
54864
|
+
throw new Error("npm CLI could not be resolved; install Node.js 24+ and npm, then retry");
|
|
54865
|
+
const stage = path13.join(home, ".cursor", "plugins", "local", ".workit-package-bootstrap");
|
|
54866
|
+
const target = options.targetDir ?? path13.join(home, ".cursor", "plugins", "local", "workit");
|
|
54867
|
+
return [
|
|
54868
|
+
nodePrerequisite({ home, cwd, env }),
|
|
54869
|
+
{
|
|
54870
|
+
command: node,
|
|
54871
|
+
args: [
|
|
54872
|
+
npmCli,
|
|
54873
|
+
"install",
|
|
54874
|
+
"--prefix",
|
|
54875
|
+
stage,
|
|
54876
|
+
"--no-save",
|
|
54877
|
+
"--package-lock=false",
|
|
54878
|
+
`@brainervirus/workit-cursor@${version}`
|
|
54879
|
+
],
|
|
54880
|
+
cwd,
|
|
54881
|
+
purpose: upgrading ? "Download the current Workit Cursor adapter for the managed local plugin directory" : "Download the Workit Cursor adapter package for the managed local plugin directory",
|
|
54882
|
+
packageRoot: path13.join(stage, "node_modules", "@brainervirus", "workit-cursor"),
|
|
54883
|
+
packageTarget: target
|
|
54884
|
+
}
|
|
54885
|
+
];
|
|
54886
|
+
}
|
|
54887
|
+
if (host === "opencode") {
|
|
54888
|
+
if (upgrading)
|
|
54889
|
+
throw new Error("OpenCode CLI cannot target the Workit server plugin for a scoped update; upgrade is unsupported and the current registration was preserved");
|
|
54890
|
+
return [];
|
|
54891
|
+
}
|
|
54892
|
+
return [];
|
|
54893
|
+
}
|
|
54894
|
+
function runHostInstall(commands, runner, context = {}) {
|
|
54895
|
+
const results = [];
|
|
54896
|
+
let packageRoot;
|
|
54897
|
+
let outputHistory = "";
|
|
54898
|
+
for (const command of commands) {
|
|
54899
|
+
if (command.skipWhenOutputIncludes && outputHistory.includes(command.skipWhenOutputIncludes)) {
|
|
54900
|
+
results.push({
|
|
54901
|
+
command,
|
|
54902
|
+
result: { exitCode: 0, stdout: "", stderr: "already registered; skipped" }
|
|
54903
|
+
});
|
|
54904
|
+
continue;
|
|
54905
|
+
}
|
|
54906
|
+
const result = runner ? runner(command) : runHostCommand(command, context);
|
|
54907
|
+
results.push({ command, result });
|
|
54908
|
+
if (result.exitCode !== 0)
|
|
54909
|
+
return { ok: false, results };
|
|
54910
|
+
outputHistory += `
|
|
54911
|
+
${result.stdout}
|
|
54912
|
+
${result.stderr}`;
|
|
54913
|
+
if (command.packageRoot && command.packageTarget) {
|
|
54914
|
+
try {
|
|
54915
|
+
if (!existsSync10(command.packageRoot)) {
|
|
54916
|
+
return {
|
|
54917
|
+
ok: false,
|
|
54918
|
+
results: [
|
|
54919
|
+
{
|
|
54920
|
+
command,
|
|
54921
|
+
result: {
|
|
54922
|
+
...result,
|
|
54923
|
+
exitCode: 1,
|
|
54924
|
+
stderr: "npm completed without producing the expected Cursor package"
|
|
54925
|
+
}
|
|
54926
|
+
}
|
|
54927
|
+
]
|
|
54928
|
+
};
|
|
54929
|
+
} else {
|
|
54930
|
+
packageRoot = command.packageRoot;
|
|
54931
|
+
}
|
|
54932
|
+
} catch (error) {
|
|
54933
|
+
return {
|
|
54934
|
+
ok: false,
|
|
54935
|
+
results: [
|
|
54936
|
+
{
|
|
54937
|
+
command,
|
|
54938
|
+
result: {
|
|
54939
|
+
...result,
|
|
54940
|
+
exitCode: 1,
|
|
54941
|
+
stderr: error instanceof Error ? error.message : String(error)
|
|
54942
|
+
}
|
|
54943
|
+
}
|
|
54944
|
+
]
|
|
54945
|
+
};
|
|
54946
|
+
}
|
|
54947
|
+
}
|
|
54948
|
+
}
|
|
54949
|
+
return { ok: true, results, packageRoot };
|
|
54950
|
+
}
|
|
54951
|
+
function runHostCommand(step, context = {}) {
|
|
54952
|
+
if (process.platform === "win32" && /\.(?:cmd|bat)$/i.test(step.command)) {
|
|
54953
|
+
return {
|
|
54954
|
+
exitCode: 1,
|
|
54955
|
+
stdout: "",
|
|
54956
|
+
stderr: `Cannot safely execute batch shim ${step.command}; resolve its Node.js CLI entrypoint and retry`
|
|
54957
|
+
};
|
|
54958
|
+
}
|
|
54959
|
+
const result = spawnSync3(step.command, step.args, {
|
|
54960
|
+
cwd: step.cwd,
|
|
54961
|
+
env: (() => {
|
|
54962
|
+
const home = context.home ?? context.env?.HOME ?? os6.homedir();
|
|
54963
|
+
const env = { ...process.env, ...context.env, HOME: home };
|
|
54964
|
+
env.CODEX_HOME = context.env?.CODEX_HOME ?? path13.join(home, ".codex");
|
|
54965
|
+
env.PI_CODING_AGENT_DIR = context.env?.PI_CODING_AGENT_DIR ?? path13.join(home, ".pi", "agent");
|
|
54966
|
+
env.XDG_CONFIG_HOME = context.env?.XDG_CONFIG_HOME ?? path13.join(home, ".config");
|
|
54967
|
+
return env;
|
|
54968
|
+
})(),
|
|
54969
|
+
encoding: "utf8",
|
|
54970
|
+
timeout: 60000,
|
|
54971
|
+
windowsHide: true,
|
|
54972
|
+
shell: false
|
|
54973
|
+
});
|
|
54974
|
+
return {
|
|
54975
|
+
exitCode: result.status ?? (result.error ? 1 : 1),
|
|
54976
|
+
stdout: result.stdout ?? "",
|
|
54977
|
+
stderr: result.stderr ?? result.error?.message ?? ""
|
|
54978
|
+
};
|
|
54979
|
+
}
|
|
54980
|
+
var findNpmCli = (npm) => {
|
|
54981
|
+
const dir = path13.dirname(npm);
|
|
54982
|
+
const candidates = [
|
|
54983
|
+
path13.join(dir, "node_modules", "npm", "bin", "npm-cli.js"),
|
|
54984
|
+
path13.join(dir, "..", "node_modules", "npm", "bin", "npm-cli.js"),
|
|
54985
|
+
path13.join(dir, "..", "lib", "node_modules", "npm", "bin", "npm-cli.js")
|
|
54986
|
+
];
|
|
54987
|
+
return candidates.find((candidate) => existsSync10(candidate)) ?? null;
|
|
54988
|
+
};
|
|
54989
|
+
|
|
54606
54990
|
// packages/workit-core/src/core/setup.ts
|
|
54607
54991
|
var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE";
|
|
54608
54992
|
function parseList(raw) {
|
|
@@ -54682,7 +55066,7 @@ var resolveTokenPath = (configured, fallback, override) => {
|
|
|
54682
55066
|
};
|
|
54683
55067
|
var readConfigRecord = (file) => {
|
|
54684
55068
|
try {
|
|
54685
|
-
const value = JSON.parse(
|
|
55069
|
+
const value = JSON.parse(readFileSync12(file, "utf8"));
|
|
54686
55070
|
return isRecord2(value) ? value : null;
|
|
54687
55071
|
} catch {
|
|
54688
55072
|
return null;
|
|
@@ -54703,11 +55087,12 @@ function buildSetupPreview(values, opts = {}) {
|
|
|
54703
55087
|
const current = readConfigFromDir(state.configDir);
|
|
54704
55088
|
mutations.push({
|
|
54705
55089
|
type: "merge-json",
|
|
54706
|
-
path:
|
|
55090
|
+
path: path14.join(state.configDir, "config.json"),
|
|
54707
55091
|
value: {
|
|
54708
55092
|
locale: values.locale,
|
|
54709
55093
|
localeOptions: current.localeOptions,
|
|
54710
55094
|
timezone: values.timezone,
|
|
55095
|
+
...values.commitPolicy === undefined ? {} : { commitPolicy: values.commitPolicy },
|
|
54711
55096
|
branchPolicy: mergePreset(values.branchPreset, {
|
|
54712
55097
|
allowed: values.branchPreset === "custom" ? parseList(values.branchAllowed) : undefined,
|
|
54713
55098
|
protectedNames: values.branchPreset === "custom" ? parseList(values.branchProtected) : undefined
|
|
@@ -54729,17 +55114,17 @@ function buildSetupPreview(values, opts = {}) {
|
|
|
54729
55114
|
if (blocked.length === 0) {
|
|
54730
55115
|
mutations.push({
|
|
54731
55116
|
type: "update-workspaces",
|
|
54732
|
-
path:
|
|
55117
|
+
path: path14.join(state.configDir, "workspaces.json"),
|
|
54733
55118
|
entries: values.workspaces,
|
|
54734
55119
|
expectedRevision: diskWorkspaceResult.revision
|
|
54735
55120
|
});
|
|
54736
55121
|
}
|
|
54737
55122
|
}
|
|
54738
55123
|
if (values.baseUrl.trim()) {
|
|
54739
|
-
const ytPath =
|
|
55124
|
+
const ytPath = path14.join(state.configDir, "youtrack.json");
|
|
54740
55125
|
const ytExisting = readConfigRecord(ytPath);
|
|
54741
55126
|
const ytConfigured = configuredTokenPath(ytExisting, "tokenFile");
|
|
54742
|
-
const tokenPath = resolveTokenPath(ytConfigured,
|
|
55127
|
+
const tokenPath = resolveTokenPath(ytConfigured, path14.join(state.configDir, "youtrack.token"), values.tokenPaths?.youtrack);
|
|
54743
55128
|
const draft = youtrackDraft(values, tokenPath);
|
|
54744
55129
|
if (ytConfigured !== null && tokenPath !== ytConfigured) {
|
|
54745
55130
|
delete draft.tokenFile;
|
|
@@ -54755,7 +55140,7 @@ function buildSetupPreview(values, opts = {}) {
|
|
|
54755
55140
|
path: ytPath,
|
|
54756
55141
|
value: draft
|
|
54757
55142
|
});
|
|
54758
|
-
if (
|
|
55143
|
+
if (existsSync11(tokenPath))
|
|
54759
55144
|
preserved.push(tokenPath);
|
|
54760
55145
|
else
|
|
54761
55146
|
mutations.push({
|
|
@@ -54767,7 +55152,7 @@ function buildSetupPreview(values, opts = {}) {
|
|
|
54767
55152
|
});
|
|
54768
55153
|
}
|
|
54769
55154
|
if (values.vcsProvider !== "skip") {
|
|
54770
|
-
const vcsPath =
|
|
55155
|
+
const vcsPath = path14.join(state.configDir, "vcs.json");
|
|
54771
55156
|
mutations.push({
|
|
54772
55157
|
type: "merge-json",
|
|
54773
55158
|
path: vcsPath,
|
|
@@ -54781,16 +55166,45 @@ function buildSetupPreview(values, opts = {}) {
|
|
|
54781
55166
|
if (platform === "opencode") {
|
|
54782
55167
|
mutations.push({ type: "register-platform", platform, path: paths.opencodeConfig });
|
|
54783
55168
|
} else if (platform === "cursor") {
|
|
55169
|
+
const cursorRoot = adapterRoot("cursor", {
|
|
55170
|
+
...paths,
|
|
55171
|
+
dev: opts.dev ?? env.WORKFLOW_TOOLKIT_DEV ?? null
|
|
55172
|
+
});
|
|
55173
|
+
if (cursorRoot === null) {
|
|
55174
|
+
const commands = planHostInstall("cursor", {
|
|
55175
|
+
home: paths.home,
|
|
55176
|
+
cwd: paths.cwd,
|
|
55177
|
+
env,
|
|
55178
|
+
packageVersion: "latest",
|
|
55179
|
+
targetDir: paths.cursorPluginDir
|
|
55180
|
+
});
|
|
55181
|
+
mutations.push({
|
|
55182
|
+
type: "install-host",
|
|
55183
|
+
platform: "cursor",
|
|
55184
|
+
path: path14.join(paths.home, ".cursor", "plugins", "local", ".workit-package-bootstrap"),
|
|
55185
|
+
commands
|
|
55186
|
+
});
|
|
55187
|
+
}
|
|
54784
55188
|
mutations.push({ type: "install-adapter", platform, path: paths.cursorPluginDir });
|
|
54785
55189
|
mutations.push({ type: "register-platform", platform, path: paths.cursorSettings });
|
|
54786
55190
|
mutations.push({ type: "register-platform", platform, path: paths.cursorMcp });
|
|
55191
|
+
} else if (platform === "codex" || platform === "pi") {
|
|
55192
|
+
const commands = planHostInstall(platform, { home: paths.home, cwd: paths.cwd, env });
|
|
55193
|
+
if (commands.length > 0) {
|
|
55194
|
+
mutations.push({
|
|
55195
|
+
type: "install-host",
|
|
55196
|
+
platform,
|
|
55197
|
+
path: platform === "codex" ? path14.join(env.CODEX_HOME ?? path14.join(paths.home, ".codex"), "plugins", "cache", "workflow-toolkit", "workit") : path14.join(env.PI_CODING_AGENT_DIR ?? path14.join(paths.home, ".pi", "agent"), "settings.json"),
|
|
55198
|
+
commands
|
|
55199
|
+
});
|
|
55200
|
+
}
|
|
54787
55201
|
}
|
|
54788
55202
|
}
|
|
54789
55203
|
}
|
|
54790
55204
|
if (values.applyProject) {
|
|
54791
|
-
const root =
|
|
54792
|
-
const gitignorePath =
|
|
54793
|
-
const existing =
|
|
55205
|
+
const root = path14.resolve(opts.cwd ?? process.cwd());
|
|
55206
|
+
const gitignorePath = path14.join(root, ".gitignore");
|
|
55207
|
+
const existing = existsSync11(gitignorePath) ? readFileSync12(gitignorePath, "utf8") : "";
|
|
54794
55208
|
const existingLines = new Set(existing.split(`
|
|
54795
55209
|
`).map((l) => l.trim()).filter(Boolean));
|
|
54796
55210
|
const entries = GITIGNORE_ENTRIES.filter((e) => e.trim() !== "" && !existingLines.has(e.trim()));
|
|
@@ -54812,16 +55226,16 @@ function buildSetupPreview(values, opts = {}) {
|
|
|
54812
55226
|
}
|
|
54813
55227
|
var resolveSetupPaths = (options, configDir) => {
|
|
54814
55228
|
const env = options.env ?? process.env;
|
|
54815
|
-
const home = options.home ?? env.HOME ??
|
|
55229
|
+
const home = options.home ?? env.HOME ?? os7.homedir();
|
|
54816
55230
|
return {
|
|
54817
55231
|
home,
|
|
54818
55232
|
configDir,
|
|
54819
55233
|
cwd: options.cwd ?? process.cwd(),
|
|
54820
55234
|
env,
|
|
54821
|
-
opencodeConfig: options.opencodeConfig ??
|
|
54822
|
-
cursorSettings: options.cursorSettings ??
|
|
54823
|
-
cursorMcp: options.cursorMcp ??
|
|
54824
|
-
cursorPluginDir: options.cursorPluginDir ??
|
|
55235
|
+
opencodeConfig: options.opencodeConfig ?? path14.join(home, ".config", "opencode", "opencode.json"),
|
|
55236
|
+
cursorSettings: options.cursorSettings ?? path14.join(home, ".cursor", "settings.json"),
|
|
55237
|
+
cursorMcp: options.cursorMcp ?? path14.join(home, ".cursor", "mcp.json"),
|
|
55238
|
+
cursorPluginDir: options.cursorPluginDir ?? path14.join(home, ".cursor", "plugins", "local", "workit")
|
|
54825
55239
|
};
|
|
54826
55240
|
};
|
|
54827
55241
|
function resolveApply(preview, options) {
|
|
@@ -54835,9 +55249,9 @@ var isRecord2 = (v) => v !== null && typeof v === "object" && !Array.isArray(v);
|
|
|
54835
55249
|
var readExisting = (p) => {
|
|
54836
55250
|
let raw;
|
|
54837
55251
|
try {
|
|
54838
|
-
raw =
|
|
55252
|
+
raw = readFileSync12(p, "utf8");
|
|
54839
55253
|
} catch {
|
|
54840
|
-
if (
|
|
55254
|
+
if (existsSync11(p))
|
|
54841
55255
|
return { kind: "malformed", error: `${p} is not readable` };
|
|
54842
55256
|
return { kind: "missing" };
|
|
54843
55257
|
}
|
|
@@ -54861,7 +55275,7 @@ function deepMerge(base, patch) {
|
|
|
54861
55275
|
}
|
|
54862
55276
|
var readFileSafe = (p) => {
|
|
54863
55277
|
try {
|
|
54864
|
-
return
|
|
55278
|
+
return readFileSync12(p, "utf8");
|
|
54865
55279
|
} catch {
|
|
54866
55280
|
return null;
|
|
54867
55281
|
}
|
|
@@ -54877,7 +55291,7 @@ var workspaceEntriesAlreadyMatch = (contents, file, entries) => {
|
|
|
54877
55291
|
}
|
|
54878
55292
|
};
|
|
54879
55293
|
function applyMutation(m) {
|
|
54880
|
-
const dir =
|
|
55294
|
+
const dir = path14.dirname(m.path);
|
|
54881
55295
|
switch (m.type) {
|
|
54882
55296
|
case "create-file": {
|
|
54883
55297
|
mkdirSync5(dir, { recursive: true });
|
|
@@ -55026,7 +55440,7 @@ function applyMutation(m) {
|
|
|
55026
55440
|
detail: "already configured"
|
|
55027
55441
|
};
|
|
55028
55442
|
}
|
|
55029
|
-
mkdirSync5(
|
|
55443
|
+
mkdirSync5(path14.dirname(m.path), { recursive: true });
|
|
55030
55444
|
writeFileSync5(m.path, JSON.stringify(merged, null, 2) + `
|
|
55031
55445
|
`, "utf8");
|
|
55032
55446
|
return existing.kind === "record" ? { platform: "core", file: m.path, status: "Configured" } : { platform: "core", file: m.path, status: "Installed" };
|
|
@@ -55035,28 +55449,33 @@ function applyMutation(m) {
|
|
|
55035
55449
|
}
|
|
55036
55450
|
var isAdapter = (root, platform) => {
|
|
55037
55451
|
try {
|
|
55038
|
-
const pkg = JSON.parse(
|
|
55452
|
+
const pkg = JSON.parse(readFileSync12(path14.join(root, "package.json"), "utf8"));
|
|
55039
55453
|
return pkg.name === `@brainervirus/workit-${platform}`;
|
|
55040
55454
|
} catch {
|
|
55041
55455
|
return false;
|
|
55042
55456
|
}
|
|
55043
55457
|
};
|
|
55044
|
-
function adapterRoot(platform, res) {
|
|
55458
|
+
function adapterRoot(platform, res, preferInstalledAdapter = false) {
|
|
55045
55459
|
const candidates = [];
|
|
55460
|
+
const stagedCursor = path14.join(res.home, ".cursor", "plugins", "local", ".workit-package-bootstrap", "node_modules", "@brainervirus", "workit-cursor");
|
|
55461
|
+
if (platform === "cursor" && preferInstalledAdapter)
|
|
55462
|
+
candidates.push(stagedCursor);
|
|
55046
55463
|
if (res.dev) {
|
|
55047
|
-
candidates.push(
|
|
55464
|
+
candidates.push(path14.join(res.dev, "packages", `workit-${platform}`));
|
|
55048
55465
|
} else {
|
|
55049
|
-
candidates.push(
|
|
55050
|
-
let dir =
|
|
55466
|
+
candidates.push(path14.join(packageRoot(), "..", `workit-${platform}`));
|
|
55467
|
+
let dir = path14.resolve(res.cwd);
|
|
55051
55468
|
while (true) {
|
|
55052
|
-
candidates.push(
|
|
55053
|
-
const parent =
|
|
55469
|
+
candidates.push(path14.join(dir, "packages", `workit-${platform}`));
|
|
55470
|
+
const parent = path14.dirname(dir);
|
|
55054
55471
|
if (parent === dir)
|
|
55055
55472
|
break;
|
|
55056
55473
|
dir = parent;
|
|
55057
55474
|
}
|
|
55058
55475
|
}
|
|
55059
|
-
candidates.push(
|
|
55476
|
+
candidates.push(path14.join(res.home, ".local", "share", "workit", "packages", `workit-${platform}`));
|
|
55477
|
+
if (platform === "cursor")
|
|
55478
|
+
candidates.push(stagedCursor);
|
|
55060
55479
|
for (const candidate of candidates) {
|
|
55061
55480
|
if (isAdapter(candidate, platform))
|
|
55062
55481
|
return candidate;
|
|
@@ -55073,16 +55492,16 @@ var resolveOpenCodePin = (root, opts = {}) => {
|
|
|
55073
55492
|
if (!isDevOpenCodeAdapterRoot(root, opts.dev))
|
|
55074
55493
|
return OPENCODE_NPM_PIN;
|
|
55075
55494
|
for (const rel of ["src/plugin.ts", "dist/plugin.js"]) {
|
|
55076
|
-
const entry =
|
|
55077
|
-
if (
|
|
55495
|
+
const entry = path14.join(root, rel);
|
|
55496
|
+
if (existsSync11(entry))
|
|
55078
55497
|
return `file://${entry}`;
|
|
55079
55498
|
}
|
|
55080
55499
|
return null;
|
|
55081
55500
|
};
|
|
55082
55501
|
var opencodePin = (root, res) => resolveOpenCodePin(root, { dev: res.dev });
|
|
55083
55502
|
function applyOpenCode(root, res) {
|
|
55084
|
-
const
|
|
55085
|
-
if (!
|
|
55503
|
+
const resolvedPin = opencodePin(root, res);
|
|
55504
|
+
if (!resolvedPin) {
|
|
55086
55505
|
return {
|
|
55087
55506
|
platform: "opencode",
|
|
55088
55507
|
file: res.opencodeConfig,
|
|
@@ -55090,7 +55509,7 @@ function applyOpenCode(root, res) {
|
|
|
55090
55509
|
detail: "workit-opencode package has no loadable plugin entry (src/plugin.ts or dist/plugin.js)"
|
|
55091
55510
|
};
|
|
55092
55511
|
}
|
|
55093
|
-
mkdirSync5(
|
|
55512
|
+
mkdirSync5(path14.dirname(res.opencodeConfig), { recursive: true });
|
|
55094
55513
|
const existing = readExisting(res.opencodeConfig);
|
|
55095
55514
|
if (existing.kind === "malformed") {
|
|
55096
55515
|
return {
|
|
@@ -55100,7 +55519,17 @@ function applyOpenCode(root, res) {
|
|
|
55100
55519
|
detail: `cannot merge into malformed config: ${existing.error} — repair or remove the file`
|
|
55101
55520
|
};
|
|
55102
55521
|
}
|
|
55103
|
-
const
|
|
55522
|
+
const configuredPlugins = existing.kind === "record" ? Array.isArray(existing.value.plugins) ? existing.value.plugins : typeof existing.value.plugins === "string" ? [existing.value.plugins] : typeof existing.value.plugin === "string" ? [existing.value.plugin] : Array.isArray(existing.value.plugin) ? existing.value.plugin : [] : [];
|
|
55523
|
+
const configuredPin = configuredPlugins.find((entry) => typeof entry === "string" && isWorkitPlugin(entry));
|
|
55524
|
+
const pin = configuredPin ?? resolvedPin;
|
|
55525
|
+
const base = existing.kind === "record" ? existing.value : {};
|
|
55526
|
+
const merged = existing.kind === "record" && Object.hasOwn(existing.value, "plugins") ? (() => {
|
|
55527
|
+
const plugins = mergeOpenCodePlugins(existing.value.plugins, pin);
|
|
55528
|
+
return {
|
|
55529
|
+
config: { ...existing.value, plugins: plugins.config },
|
|
55530
|
+
changed: plugins.changed.length > 0 ? ["plugins"] : []
|
|
55531
|
+
};
|
|
55532
|
+
})() : mergeOpenCodeConfig(base, pin);
|
|
55104
55533
|
if (merged.changed.length === 0) {
|
|
55105
55534
|
return {
|
|
55106
55535
|
platform: "opencode",
|
|
@@ -55125,22 +55554,22 @@ function applyOpenCode(root, res) {
|
|
|
55125
55554
|
}
|
|
55126
55555
|
var samePluginContent = (src, dest, relative = "") => {
|
|
55127
55556
|
try {
|
|
55128
|
-
for (const entry of
|
|
55557
|
+
for (const entry of readdirSync5(src, { withFileTypes: true })) {
|
|
55129
55558
|
if (entry.name === "node_modules")
|
|
55130
55559
|
continue;
|
|
55131
|
-
const source =
|
|
55132
|
-
const installed =
|
|
55560
|
+
const source = path14.join(src, entry.name);
|
|
55561
|
+
const installed = path14.join(dest, entry.name);
|
|
55133
55562
|
if (entry.isDirectory()) {
|
|
55134
|
-
if (!
|
|
55563
|
+
if (!statSync4(installed).isDirectory() || !samePluginContent(source, installed, path14.join(relative, entry.name)))
|
|
55135
55564
|
return false;
|
|
55136
|
-
} else if (!
|
|
55565
|
+
} else if (!readFileSync12(source).equals(readFileSync12(installed))) {
|
|
55137
55566
|
return false;
|
|
55138
55567
|
}
|
|
55139
55568
|
}
|
|
55140
|
-
for (const entry of
|
|
55141
|
-
if (
|
|
55569
|
+
for (const entry of readdirSync5(dest, { withFileTypes: true })) {
|
|
55570
|
+
if (existsSync11(path14.join(src, entry.name)))
|
|
55142
55571
|
continue;
|
|
55143
|
-
const rel =
|
|
55572
|
+
const rel = path14.join(relative, entry.name);
|
|
55144
55573
|
if (rel === ".workit-root")
|
|
55145
55574
|
continue;
|
|
55146
55575
|
if (relative === "rules" && entry.isFile() && entry.name.endsWith(".mdc"))
|
|
@@ -55154,43 +55583,43 @@ var samePluginContent = (src, dest, relative = "") => {
|
|
|
55154
55583
|
};
|
|
55155
55584
|
var preservedCursorRules = (src, dest) => {
|
|
55156
55585
|
const preserved = new Map;
|
|
55157
|
-
const sourceRules =
|
|
55158
|
-
const installedRules =
|
|
55586
|
+
const sourceRules = path14.join(src, "rules");
|
|
55587
|
+
const installedRules = path14.join(dest, "rules");
|
|
55159
55588
|
try {
|
|
55160
|
-
for (const entry of
|
|
55589
|
+
for (const entry of readdirSync5(installedRules, { withFileTypes: true })) {
|
|
55161
55590
|
if (!entry.isFile() || !entry.name.endsWith(".mdc"))
|
|
55162
55591
|
continue;
|
|
55163
|
-
if (
|
|
55592
|
+
if (existsSync11(path14.join(sourceRules, entry.name)))
|
|
55164
55593
|
continue;
|
|
55165
|
-
preserved.set(entry.name,
|
|
55594
|
+
preserved.set(entry.name, readFileSync12(path14.join(installedRules, entry.name)));
|
|
55166
55595
|
}
|
|
55167
55596
|
} catch {}
|
|
55168
55597
|
return preserved;
|
|
55169
55598
|
};
|
|
55170
55599
|
function copyPluginDir(src, dest) {
|
|
55171
55600
|
const realSrc = realpathSync2(src);
|
|
55172
|
-
const marker =
|
|
55173
|
-
const destIsLink =
|
|
55601
|
+
const marker = path14.join(dest, ".workit-root");
|
|
55602
|
+
const destIsLink = existsSync11(dest) && lstatSync4(dest).isSymbolicLink();
|
|
55174
55603
|
const synced = !destIsLink && readFileSafe(marker)?.trim() === realSrc && samePluginContent(realSrc, dest);
|
|
55175
55604
|
if (synced)
|
|
55176
55605
|
return "Skipped";
|
|
55177
|
-
const hadDir =
|
|
55606
|
+
const hadDir = existsSync11(dest);
|
|
55178
55607
|
const rules = preservedCursorRules(realSrc, dest);
|
|
55179
|
-
const parent =
|
|
55608
|
+
const parent = path14.dirname(dest);
|
|
55180
55609
|
mkdirSync5(parent, { recursive: true });
|
|
55181
|
-
const swap = mkdtempSync(
|
|
55182
|
-
const stage =
|
|
55183
|
-
const backup =
|
|
55610
|
+
const swap = mkdtempSync(path14.join(parent, `.${path14.basename(dest)}.swap-`));
|
|
55611
|
+
const stage = path14.join(swap, "stage");
|
|
55612
|
+
const backup = path14.join(swap, "backup");
|
|
55184
55613
|
try {
|
|
55185
55614
|
cpSync3(realSrc, stage, {
|
|
55186
55615
|
recursive: true,
|
|
55187
|
-
filter: (entry) => !
|
|
55616
|
+
filter: (entry) => !path14.relative(realSrc, entry).split(path14.sep).includes("node_modules")
|
|
55188
55617
|
});
|
|
55189
55618
|
for (const [name, content] of rules) {
|
|
55190
|
-
mkdirSync5(
|
|
55191
|
-
writeFileSync5(
|
|
55619
|
+
mkdirSync5(path14.join(stage, "rules"), { recursive: true });
|
|
55620
|
+
writeFileSync5(path14.join(stage, "rules", name), content);
|
|
55192
55621
|
}
|
|
55193
|
-
writeFileSync5(
|
|
55622
|
+
writeFileSync5(path14.join(stage, ".workit-root"), realSrc + `
|
|
55194
55623
|
`, "utf8");
|
|
55195
55624
|
if (!samePluginContent(realSrc, stage))
|
|
55196
55625
|
throw new Error("staged adapter content is incomplete");
|
|
@@ -55202,7 +55631,7 @@ function copyPluginDir(src, dest) {
|
|
|
55202
55631
|
try {
|
|
55203
55632
|
renameSync2(stage, dest);
|
|
55204
55633
|
} catch (error) {
|
|
55205
|
-
if (hadDir && !
|
|
55634
|
+
if (hadDir && !existsSync11(dest))
|
|
55206
55635
|
renameSync2(backup, dest);
|
|
55207
55636
|
throw error;
|
|
55208
55637
|
}
|
|
@@ -55213,26 +55642,26 @@ function copyPluginDir(src, dest) {
|
|
|
55213
55642
|
return hadDir ? "Configured" : "Installed";
|
|
55214
55643
|
}
|
|
55215
55644
|
var removeLegacyCursorDir = (res) => {
|
|
55216
|
-
const legacy =
|
|
55217
|
-
if (legacy === res.cursorPluginDir || !
|
|
55645
|
+
const legacy = path14.join(res.home, ".cursor", "plugins", "local", "workflow-toolkit");
|
|
55646
|
+
if (legacy === res.cursorPluginDir || !existsSync11(legacy))
|
|
55218
55647
|
return;
|
|
55219
|
-
const legacyRules =
|
|
55220
|
-
if (
|
|
55648
|
+
const legacyRules = path14.join(legacy, "rules");
|
|
55649
|
+
if (existsSync11(legacyRules)) {
|
|
55221
55650
|
try {
|
|
55222
|
-
mkdirSync5(
|
|
55223
|
-
for (const entry of
|
|
55651
|
+
mkdirSync5(path14.join(res.cursorPluginDir, "rules"), { recursive: true });
|
|
55652
|
+
for (const entry of readdirSync5(legacyRules, { withFileTypes: true })) {
|
|
55224
55653
|
if (!entry.isFile() || !entry.name.endsWith(".mdc"))
|
|
55225
55654
|
continue;
|
|
55226
|
-
const target =
|
|
55227
|
-
if (!
|
|
55228
|
-
copyFileSync2(
|
|
55655
|
+
const target = path14.join(res.cursorPluginDir, "rules", entry.name);
|
|
55656
|
+
if (!existsSync11(target))
|
|
55657
|
+
copyFileSync2(path14.join(legacyRules, entry.name), target);
|
|
55229
55658
|
}
|
|
55230
55659
|
} catch {}
|
|
55231
55660
|
}
|
|
55232
55661
|
rmSync(legacy, { recursive: true, force: true });
|
|
55233
55662
|
};
|
|
55234
55663
|
function applyCursorSettings(root, res) {
|
|
55235
|
-
mkdirSync5(
|
|
55664
|
+
mkdirSync5(path14.dirname(res.cursorSettings), { recursive: true });
|
|
55236
55665
|
const settingsExisting = readExisting(res.cursorSettings);
|
|
55237
55666
|
if (settingsExisting.kind === "malformed") {
|
|
55238
55667
|
return {
|
|
@@ -55260,7 +55689,7 @@ function applyCursorSettings(root, res) {
|
|
|
55260
55689
|
};
|
|
55261
55690
|
}
|
|
55262
55691
|
function applyCursorMcp(root, res) {
|
|
55263
|
-
mkdirSync5(
|
|
55692
|
+
mkdirSync5(path14.dirname(res.cursorMcp), { recursive: true });
|
|
55264
55693
|
const mcpExisting = readExisting(res.cursorMcp);
|
|
55265
55694
|
if (mcpExisting.kind === "malformed") {
|
|
55266
55695
|
return {
|
|
@@ -55270,7 +55699,18 @@ function applyCursorMcp(root, res) {
|
|
|
55270
55699
|
detail: `cannot merge into malformed config: ${mcpExisting.error} — repair or remove the file`
|
|
55271
55700
|
};
|
|
55272
55701
|
}
|
|
55273
|
-
const
|
|
55702
|
+
const mcpBase = mcpExisting.kind === "record" ? mcpExisting.value : {};
|
|
55703
|
+
const server = cursorMcpServerEntry(res.cursorPluginDir);
|
|
55704
|
+
const servers = isRecord2(mcpBase.mcpServers) ? mcpBase.mcpServers : {};
|
|
55705
|
+
const current = isRecord2(servers.workit) ? servers.workit : {};
|
|
55706
|
+
const previousArgs = Array.isArray(current.args) ? current.args.map(String) : [];
|
|
55707
|
+
const previousPackage = previousArgs.find((arg) => arg.startsWith("--package=@brainervirus/workit-cursor@") && arg !== `--package=${CURSOR_RUNTIME_PACKAGE}`);
|
|
55708
|
+
if (previousPackage) {
|
|
55709
|
+
const index = server.args.findIndex((arg) => arg.startsWith("--package="));
|
|
55710
|
+
if (index >= 0)
|
|
55711
|
+
server.args[index] = previousPackage;
|
|
55712
|
+
}
|
|
55713
|
+
const mcp = mergeCursorMcp(mcpBase, "workit", server);
|
|
55274
55714
|
if (mcp.changed.length === 0) {
|
|
55275
55715
|
return {
|
|
55276
55716
|
platform: "cursor",
|
|
@@ -55288,9 +55728,9 @@ function applyCursorMcp(root, res) {
|
|
|
55288
55728
|
};
|
|
55289
55729
|
}
|
|
55290
55730
|
function verifyPlatform(platform, res) {
|
|
55291
|
-
if (platform === "opencode" && !
|
|
55731
|
+
if (platform === "opencode" && !existsSync11(res.opencodeConfig))
|
|
55292
55732
|
return null;
|
|
55293
|
-
if (platform === "cursor" && !
|
|
55733
|
+
if (platform === "cursor" && !existsSync11(res.cursorSettings) && !existsSync11(res.cursorMcp)) {
|
|
55294
55734
|
return null;
|
|
55295
55735
|
}
|
|
55296
55736
|
return runDoctor({
|
|
@@ -55355,6 +55795,51 @@ function applySetupPreview(preview, options = {}) {
|
|
|
55355
55795
|
const rootFor = new Map;
|
|
55356
55796
|
let cursorCopyOk = false;
|
|
55357
55797
|
for (const mutation of preview.mutations) {
|
|
55798
|
+
if (mutation.type === "install-host") {
|
|
55799
|
+
const expectedPath = mutation.platform === "cursor" ? path14.join(res.home, ".cursor", "plugins", "local", ".workit-package-bootstrap") : mutation.platform === "codex" ? path14.join(res.env.CODEX_HOME ?? path14.join(res.home, ".codex"), "plugins", "cache", "workflow-toolkit", "workit") : mutation.platform === "pi" ? path14.join(res.env.PI_CODING_AGENT_DIR ?? path14.join(res.home, ".pi", "agent"), "settings.json") : "";
|
|
55800
|
+
if (mutation.path !== expectedPath) {
|
|
55801
|
+
entries.push({
|
|
55802
|
+
platform: mutation.platform,
|
|
55803
|
+
file: mutation.path,
|
|
55804
|
+
status: "Failed",
|
|
55805
|
+
detail: `preview/apply path mismatch: apply resolved ${expectedPath}, the previewed host install was ${mutation.path} — rebuild the preview with the same options`
|
|
55806
|
+
});
|
|
55807
|
+
continue;
|
|
55808
|
+
}
|
|
55809
|
+
const run = options.runHostCommand ?? ((step) => runHostCommand(step, { home: res.home, env: res.env }));
|
|
55810
|
+
const installed = runHostInstall(mutation.commands, run);
|
|
55811
|
+
for (const { command, result } of installed.results) {
|
|
55812
|
+
entries.push({
|
|
55813
|
+
platform: mutation.platform,
|
|
55814
|
+
file: command.command,
|
|
55815
|
+
status: result.exitCode === 0 ? "Installed" : "Failed",
|
|
55816
|
+
detail: result.exitCode === 0 ? `${command.purpose} (${command.args.join(" ")})` : `${command.purpose} failed (${command.args.join(" ")}): ${result.stderr || `exit ${result.exitCode}`}`
|
|
55817
|
+
});
|
|
55818
|
+
}
|
|
55819
|
+
if (!installed.ok && installed.results.length === 0) {
|
|
55820
|
+
entries.push({
|
|
55821
|
+
platform: mutation.platform,
|
|
55822
|
+
file: mutation.platform,
|
|
55823
|
+
status: "Failed",
|
|
55824
|
+
detail: "host installation did not run"
|
|
55825
|
+
});
|
|
55826
|
+
}
|
|
55827
|
+
if (!installed.ok)
|
|
55828
|
+
continue;
|
|
55829
|
+
if (mutation.platform === "cursor" && installed.packageRoot) {
|
|
55830
|
+
rootFor.set("cursor", installed.packageRoot);
|
|
55831
|
+
}
|
|
55832
|
+
const verified = mutation.platform === "codex" ? isCodexWorkitInstalled(res.home, res.env) : mutation.platform === "pi" ? isPiWorkitInstalled(res.home, res.env) : true;
|
|
55833
|
+
if (!verified) {
|
|
55834
|
+
entries.push({
|
|
55835
|
+
platform: mutation.platform,
|
|
55836
|
+
file: mutation.platform,
|
|
55837
|
+
status: "Failed",
|
|
55838
|
+
detail: "the host command succeeded, but Workit registration was not found; inspect the host's native package list and retry"
|
|
55839
|
+
});
|
|
55840
|
+
}
|
|
55841
|
+
continue;
|
|
55842
|
+
}
|
|
55358
55843
|
if (mutation.type !== "register-platform" && mutation.type !== "install-adapter") {
|
|
55359
55844
|
entries.push(applyMutation(mutation));
|
|
55360
55845
|
continue;
|
|
@@ -55372,7 +55857,7 @@ function applySetupPreview(preview, options = {}) {
|
|
|
55372
55857
|
}
|
|
55373
55858
|
let root = rootFor.get(platform);
|
|
55374
55859
|
if (root === undefined) {
|
|
55375
|
-
root = adapterRoot(platform, res);
|
|
55860
|
+
root = adapterRoot(platform, res, options.preferInstalledAdapter);
|
|
55376
55861
|
rootFor.set(platform, root);
|
|
55377
55862
|
}
|
|
55378
55863
|
if (root === null) {
|
|
@@ -55468,7 +55953,7 @@ var setupCompletionGuidance = () => [
|
|
|
55468
55953
|
];
|
|
55469
55954
|
function applyWorkspaceBranchPolicy(opts) {
|
|
55470
55955
|
const { workspace_root, env = process.env } = opts;
|
|
55471
|
-
const dir =
|
|
55956
|
+
const dir = path14.join(env.WORKFLOW_TOOLKIT_CONFIG ?? configDir());
|
|
55472
55957
|
const {
|
|
55473
55958
|
status,
|
|
55474
55959
|
path: wsPath,
|
|
@@ -55480,7 +55965,7 @@ function applyWorkspaceBranchPolicy(opts) {
|
|
|
55480
55965
|
if (status === "malformed" || status === "invalid")
|
|
55481
55966
|
return { ok: false, error: workspacesError ?? `invalid workspaces.json: ${wsPath}` };
|
|
55482
55967
|
const detection = detectBranchPolicy(workspace_root);
|
|
55483
|
-
const name = String(env.WORKFLOW_BP_NAME ??
|
|
55968
|
+
const name = String(env.WORKFLOW_BP_NAME ?? path14.basename(workspace_root));
|
|
55484
55969
|
const integration = env.WORKFLOW_BP_INTEGRATION ?? detection.integration;
|
|
55485
55970
|
const policy = {
|
|
55486
55971
|
preset: detection.preset,
|
|
@@ -55529,7 +56014,7 @@ function applyWorkspaceBranchPolicy(opts) {
|
|
|
55529
56014
|
ok: false,
|
|
55530
56015
|
error: `workspaces.json changed while applying the branch policy: ${wsPath}`
|
|
55531
56016
|
};
|
|
55532
|
-
mkdirSync5(
|
|
56017
|
+
mkdirSync5(path14.dirname(wsPath), { recursive: true });
|
|
55533
56018
|
const tmp = `${wsPath}.${process.pid}.tmp`;
|
|
55534
56019
|
try {
|
|
55535
56020
|
writeFileSync5(tmp, JSON.stringify({ ...document2, workspaces: next }, null, 2) + `
|
|
@@ -55588,6 +56073,201 @@ function validateBaseUrl(url) {
|
|
|
55588
56073
|
return "base URL must use https";
|
|
55589
56074
|
return null;
|
|
55590
56075
|
}
|
|
56076
|
+
function workspaceEditorValue(workspace, field) {
|
|
56077
|
+
const [section, key, leaf] = field.split(".");
|
|
56078
|
+
if (section === "defaultProfile")
|
|
56079
|
+
return workspace.defaultProfile ?? "";
|
|
56080
|
+
if (section === "vcs") {
|
|
56081
|
+
if (key === "account")
|
|
56082
|
+
return workspace.vcs?.account ?? "";
|
|
56083
|
+
return workspace.vcs?.defaultTargetBranch ?? "";
|
|
56084
|
+
}
|
|
56085
|
+
if (section === "youtrack")
|
|
56086
|
+
return key === "baseUrl" ? workspace.youtrack?.baseUrl ?? "" : workspace.youtrack?.link_issues === undefined ? "inherit" : String(workspace.youtrack.link_issues);
|
|
56087
|
+
if (section === "issues")
|
|
56088
|
+
return workspace.issues?.link_on_pr === undefined ? "inherit" : String(workspace.issues.link_on_pr);
|
|
56089
|
+
if (section === "branchPolicy") {
|
|
56090
|
+
const value = workspace.branchPolicy;
|
|
56091
|
+
if (key === "preset")
|
|
56092
|
+
return value?.preset ?? "inherit";
|
|
56093
|
+
if (key === "allowed")
|
|
56094
|
+
return value?.allowed?.join(", ") ?? "";
|
|
56095
|
+
if (key === "protected")
|
|
56096
|
+
return value?.protected?.join(", ") ?? "";
|
|
56097
|
+
if (key === "developBranch")
|
|
56098
|
+
return value?.developBranch ?? "";
|
|
56099
|
+
if (key === "integration")
|
|
56100
|
+
return value?.integration ?? "merge";
|
|
56101
|
+
if (key === "prefixes")
|
|
56102
|
+
return value?.prefixes?.[leaf] ?? "";
|
|
56103
|
+
}
|
|
56104
|
+
if (section === "commitPolicy") {
|
|
56105
|
+
if (key === "preset")
|
|
56106
|
+
return workspace.commitPolicy?.preset ?? "inherit";
|
|
56107
|
+
if (key === "pattern")
|
|
56108
|
+
return workspace.commitPolicy?.pattern ?? "";
|
|
56109
|
+
}
|
|
56110
|
+
return "";
|
|
56111
|
+
}
|
|
56112
|
+
function setWorkspaceEditorValue(workspace, field, value, defaults = {}) {
|
|
56113
|
+
const [section, key, leaf] = field.split(".");
|
|
56114
|
+
const list = value.split(",").map((item) => item.trim()).filter(Boolean);
|
|
56115
|
+
if (section === "defaultProfile")
|
|
56116
|
+
return { ...workspace, defaultProfile: value.trim() || undefined };
|
|
56117
|
+
if (section === "vcs")
|
|
56118
|
+
return workspace.vcs ? { ...workspace, vcs: { ...workspace.vcs, [key]: value.trim() || undefined } } : workspace;
|
|
56119
|
+
if (section === "youtrack") {
|
|
56120
|
+
const current = workspace.youtrack ?? {};
|
|
56121
|
+
if (key === "baseUrl")
|
|
56122
|
+
return { ...workspace, youtrack: { ...current, baseUrl: value.trim() || undefined } };
|
|
56123
|
+
if (!value || value === "inherit") {
|
|
56124
|
+
const { link_issues: _discard, ...rest } = current;
|
|
56125
|
+
return { ...workspace, youtrack: Object.keys(rest).length ? rest : undefined };
|
|
56126
|
+
}
|
|
56127
|
+
return { ...workspace, youtrack: { ...current, link_issues: value === "true" } };
|
|
56128
|
+
}
|
|
56129
|
+
if (section === "issues") {
|
|
56130
|
+
const current = workspace.issues ?? { provider: "github" };
|
|
56131
|
+
if (!value || value === "inherit") {
|
|
56132
|
+
const { link_on_pr: _discard, ...rest } = current;
|
|
56133
|
+
return { ...workspace, issues: Object.keys(rest).length ? rest : undefined };
|
|
56134
|
+
}
|
|
56135
|
+
return {
|
|
56136
|
+
...workspace,
|
|
56137
|
+
issues: { ...current, provider: "github", link_on_pr: value === "true" }
|
|
56138
|
+
};
|
|
56139
|
+
}
|
|
56140
|
+
if (section === "branchPolicy") {
|
|
56141
|
+
if (key === "preset" && (!value.trim() || value === "inherit")) {
|
|
56142
|
+
const { branchPolicy: _discard, ...rest } = workspace;
|
|
56143
|
+
return rest;
|
|
56144
|
+
}
|
|
56145
|
+
const current = workspace.branchPolicy ?? { preset: defaults.branchPreset ?? "gitflow" };
|
|
56146
|
+
const branchPolicy = key === "preset" ? { ...current, preset: value || "gitflow" } : key === "allowed" ? { ...current, allowed: list } : key === "protected" ? { ...current, protected: list } : key === "developBranch" ? { ...current, developBranch: value.trim() || undefined } : key === "integration" ? { ...current, integration: value === "pr" ? "pr" : "merge" } : key === "prefixes" ? {
|
|
56147
|
+
...current,
|
|
56148
|
+
prefixes: {
|
|
56149
|
+
feature: "feature/",
|
|
56150
|
+
bugfix: "bugfix/",
|
|
56151
|
+
release: "release/",
|
|
56152
|
+
hotfix: "hotfix/",
|
|
56153
|
+
...current.prefixes,
|
|
56154
|
+
[leaf]: value.trim()
|
|
56155
|
+
}
|
|
56156
|
+
} : current;
|
|
56157
|
+
return { ...workspace, branchPolicy };
|
|
56158
|
+
}
|
|
56159
|
+
if (section === "commitPolicy") {
|
|
56160
|
+
if (key === "preset" && (!value.trim() || value === "inherit")) {
|
|
56161
|
+
const { commitPolicy: _discard, ...rest } = workspace;
|
|
56162
|
+
return rest;
|
|
56163
|
+
}
|
|
56164
|
+
const current = workspace.commitPolicy ?? { preset: defaults.commitPreset ?? "conventional" };
|
|
56165
|
+
return {
|
|
56166
|
+
...workspace,
|
|
56167
|
+
commitPolicy: key === "pattern" ? { ...current, pattern: value || undefined } : { ...current, preset: value }
|
|
56168
|
+
};
|
|
56169
|
+
}
|
|
56170
|
+
return workspace;
|
|
56171
|
+
}
|
|
56172
|
+
var splitList = (value) => value.split(",").map((item) => item.trim()).filter(Boolean);
|
|
56173
|
+
var emptyTrack = () => ({
|
|
56174
|
+
strategy: "gitflow",
|
|
56175
|
+
productionBranch: "main",
|
|
56176
|
+
integrationBranch: "develop",
|
|
56177
|
+
naming: { feature: "feature/{name}", release: "release/{version}", hotfix: "hotfix/{name}" },
|
|
56178
|
+
baseBranch: "develop",
|
|
56179
|
+
mergeBackBranches: ["develop"],
|
|
56180
|
+
pullRequestTarget: "develop",
|
|
56181
|
+
tagNamespace: "",
|
|
56182
|
+
versionSource: { kind: "git-tag" },
|
|
56183
|
+
requiredChecks: []
|
|
56184
|
+
});
|
|
56185
|
+
function profileEditorValue(profile, field) {
|
|
56186
|
+
const [section, key, leaf] = field.split(".");
|
|
56187
|
+
if (section === "branchPolicy") {
|
|
56188
|
+
const value = profile?.branchPolicy;
|
|
56189
|
+
if (key === "prefixes")
|
|
56190
|
+
return value?.prefixes?.[leaf] ?? "";
|
|
56191
|
+
if (key === "allowed" || key === "protected")
|
|
56192
|
+
return value?.[key]?.join(", ") ?? "";
|
|
56193
|
+
return String(value?.[key] ?? "");
|
|
56194
|
+
}
|
|
56195
|
+
return String(profile?.commitPolicy?.[key] ?? "");
|
|
56196
|
+
}
|
|
56197
|
+
function setProfileEditorValue(profile, field, value, defaults = {}) {
|
|
56198
|
+
const [section, key, leaf] = field.split(".");
|
|
56199
|
+
if (section === "branchPolicy") {
|
|
56200
|
+
if (key === "preset" && (!value.trim() || value === "inherit")) {
|
|
56201
|
+
const { branchPolicy: _discard, ...rest } = profile;
|
|
56202
|
+
return rest;
|
|
56203
|
+
}
|
|
56204
|
+
const current = profile.branchPolicy ?? { preset: defaults.branchPreset ?? "gitflow" };
|
|
56205
|
+
let branchPolicy;
|
|
56206
|
+
if (key === "preset")
|
|
56207
|
+
branchPolicy = { ...current, preset: value || "gitflow" };
|
|
56208
|
+
else if (key === "allowed" || key === "protected")
|
|
56209
|
+
branchPolicy = { ...current, [key]: splitList(value) };
|
|
56210
|
+
else if (key === "prefixes")
|
|
56211
|
+
branchPolicy = {
|
|
56212
|
+
...current,
|
|
56213
|
+
prefixes: {
|
|
56214
|
+
feature: "feature/",
|
|
56215
|
+
bugfix: "bugfix/",
|
|
56216
|
+
release: "release/",
|
|
56217
|
+
hotfix: "hotfix/",
|
|
56218
|
+
...current.prefixes,
|
|
56219
|
+
[leaf]: value
|
|
56220
|
+
}
|
|
56221
|
+
};
|
|
56222
|
+
else if (key === "developBranch")
|
|
56223
|
+
branchPolicy = { ...current, developBranch: value || undefined };
|
|
56224
|
+
else
|
|
56225
|
+
branchPolicy = { ...current, integration: value === "pr" ? "pr" : "merge" };
|
|
56226
|
+
return { ...profile, branchPolicy };
|
|
56227
|
+
}
|
|
56228
|
+
const current = profile.commitPolicy ?? { preset: defaults.commitPreset ?? "conventional" };
|
|
56229
|
+
if (key === "preset" && (!value.trim() || value === "inherit")) {
|
|
56230
|
+
const { commitPolicy: _discard, ...rest } = profile;
|
|
56231
|
+
return rest;
|
|
56232
|
+
}
|
|
56233
|
+
return {
|
|
56234
|
+
...profile,
|
|
56235
|
+
commitPolicy: key === "pattern" ? { ...current, pattern: value || undefined } : { ...current, preset: value || "conventional" }
|
|
56236
|
+
};
|
|
56237
|
+
}
|
|
56238
|
+
function trackEditorValue(track, field) {
|
|
56239
|
+
if (field.startsWith("naming."))
|
|
56240
|
+
return track.naming[field.slice(7)];
|
|
56241
|
+
if (field === "mergeBackBranches" || field === "requiredChecks")
|
|
56242
|
+
return track[field].join(", ");
|
|
56243
|
+
if (field.startsWith("versionSource.")) {
|
|
56244
|
+
const key = field.slice(14);
|
|
56245
|
+
if (key === "kind")
|
|
56246
|
+
return track.versionSource.kind;
|
|
56247
|
+
if (key === "path")
|
|
56248
|
+
return track.versionSource.kind === "package-json" ? track.versionSource.path : "";
|
|
56249
|
+
return track.versionSource.kind === "package-json" ? track.versionSource.field : "";
|
|
56250
|
+
}
|
|
56251
|
+
return String(track[field] ?? "");
|
|
56252
|
+
}
|
|
56253
|
+
function setTrackEditorValue(track, field, value) {
|
|
56254
|
+
if (field.startsWith("naming."))
|
|
56255
|
+
return { ...track, naming: { ...track.naming, [field.slice(7)]: value } };
|
|
56256
|
+
if (field === "mergeBackBranches" || field === "requiredChecks")
|
|
56257
|
+
return { ...track, [field]: splitList(value) };
|
|
56258
|
+
if (field.startsWith("versionSource.")) {
|
|
56259
|
+
const key = field.slice(14);
|
|
56260
|
+
const kind = key === "kind" ? value : track.versionSource.kind;
|
|
56261
|
+
const versionSource = kind === "package-json" ? {
|
|
56262
|
+
kind,
|
|
56263
|
+
path: key === "path" ? value : track.versionSource.kind === kind ? track.versionSource.path : "package.json",
|
|
56264
|
+
field: key === "field" ? value : track.versionSource.kind === kind ? track.versionSource.field : "version"
|
|
56265
|
+
} : kind === "manual" ? { kind } : { kind: "git-tag" };
|
|
56266
|
+
return { ...track, versionSource };
|
|
56267
|
+
}
|
|
56268
|
+
return { ...track, [field]: value };
|
|
56269
|
+
}
|
|
56270
|
+
var createReleaseTrack = emptyTrack;
|
|
55591
56271
|
function loadWorkspaces() {
|
|
55592
56272
|
return loadWorkspacesFrom(configDir());
|
|
55593
56273
|
}
|
|
@@ -55605,8 +56285,8 @@ function applyWizardBranchPolicy(branchPolicy, workspace_root, env = process.env
|
|
|
55605
56285
|
}
|
|
55606
56286
|
|
|
55607
56287
|
// packages/workit-cli/src/wizard-state.ts
|
|
55608
|
-
import { existsSync as
|
|
55609
|
-
import
|
|
56288
|
+
import { existsSync as existsSync12, statSync as statSync5 } from "node:fs";
|
|
56289
|
+
import path15 from "node:path";
|
|
55610
56290
|
import { isDeepStrictEqual as isDeepStrictEqual3 } from "node:util";
|
|
55611
56291
|
var NEXT = {
|
|
55612
56292
|
platforms: "locale",
|
|
@@ -55625,6 +56305,10 @@ var NEXT = {
|
|
|
55625
56305
|
workspaceName: "workspaceGlob",
|
|
55626
56306
|
workspaceGlob: "workspaceProvider",
|
|
55627
56307
|
workspaceProvider: null,
|
|
56308
|
+
workspaceAdvanced: null,
|
|
56309
|
+
workspaceAdvancedValue: null,
|
|
56310
|
+
globalCommitPolicy: null,
|
|
56311
|
+
globalCommitPattern: null,
|
|
55628
56312
|
branchPolicy: "project",
|
|
55629
56313
|
branchPolicyDevelop: "branchPolicy",
|
|
55630
56314
|
project: "summary",
|
|
@@ -55648,6 +56332,10 @@ var PREV = {
|
|
|
55648
56332
|
workspaceName: "workspaces",
|
|
55649
56333
|
workspaceGlob: "workspaceName",
|
|
55650
56334
|
workspaceProvider: "workspaceGlob",
|
|
56335
|
+
workspaceAdvanced: "workspaces",
|
|
56336
|
+
workspaceAdvancedValue: "workspaceAdvanced",
|
|
56337
|
+
globalCommitPolicy: "workspaces",
|
|
56338
|
+
globalCommitPattern: "globalCommitPolicy",
|
|
55651
56339
|
branchPolicy: "workspaces",
|
|
55652
56340
|
branchPolicyDevelop: "branchPolicy",
|
|
55653
56341
|
project: "branchPolicy",
|
|
@@ -55662,7 +56350,7 @@ function resolveBasePath(values, env = process.env) {
|
|
|
55662
56350
|
}
|
|
55663
56351
|
var isDirectory = (p) => {
|
|
55664
56352
|
try {
|
|
55665
|
-
return
|
|
56353
|
+
return statSync5(p).isDirectory();
|
|
55666
56354
|
} catch {
|
|
55667
56355
|
return false;
|
|
55668
56356
|
}
|
|
@@ -55671,9 +56359,9 @@ var basePathMessage = (value) => {
|
|
|
55671
56359
|
const p = value.trim();
|
|
55672
56360
|
if (!p)
|
|
55673
56361
|
return "workspace root path is required";
|
|
55674
|
-
return !
|
|
56362
|
+
return !path15.isAbsolute(p) || !isDirectory(p) ? `invalid workspace root "${p}" — enter an existing absolute directory` : null;
|
|
55675
56363
|
};
|
|
55676
|
-
var skipsBranchPolicy = (screen, basePath) => (screen === "branchPolicy" || screen === "branchPolicyDevelop") && !
|
|
56364
|
+
var skipsBranchPolicy = (screen, basePath) => (screen === "branchPolicy" || screen === "branchPolicyDevelop") && !existsSync12(path15.join(basePath, ".git"));
|
|
55677
56365
|
function nextScreen(screen, preset, tracker, basePath) {
|
|
55678
56366
|
let next = NEXT[screen];
|
|
55679
56367
|
while (next && (skipsCustomBranch(next, preset) || skipsBranchPolicy(next, basePath) || skipsYoutrack(next, tracker) || skipsBasePath(next, basePath)))
|
|
@@ -55756,6 +56444,7 @@ function createInitialDraft(config = readConfig(), opts = {}) {
|
|
|
55756
56444
|
branchPreset: config.branchPolicy.preset,
|
|
55757
56445
|
branchAllowed: policy.allowed.join(", "),
|
|
55758
56446
|
branchProtected: policy.protected.join(", "),
|
|
56447
|
+
commitPolicy: { ...config.commitPolicy },
|
|
55759
56448
|
baseUrl: "",
|
|
55760
56449
|
basePath: process.env.WORKFLOW_WORKSPACE_ROOT ?? "",
|
|
55761
56450
|
issueTracker: "youtrack",
|
|
@@ -55793,23 +56482,17 @@ function reducer3(draft, action) {
|
|
|
55793
56482
|
const next = decodeIssueTracker(action.value, draft.values.issueTracker);
|
|
55794
56483
|
if (next === draft.values.issueTracker)
|
|
55795
56484
|
return draft;
|
|
55796
|
-
const stripIssues = (workspace) => {
|
|
55797
|
-
const rest = { ...workspace };
|
|
55798
|
-
delete rest.issues;
|
|
55799
|
-
return rest;
|
|
55800
|
-
};
|
|
55801
|
-
const needsStrip = next !== "github" && (draft.values.workspaces.some((w) => w.issues !== undefined) || draft.workspaceDraft?.issues !== undefined);
|
|
55802
56485
|
const errors = { ...draft.errors };
|
|
55803
56486
|
delete errors.baseUrl;
|
|
55804
56487
|
return {
|
|
55805
56488
|
...draft,
|
|
55806
56489
|
errors,
|
|
55807
|
-
workspaceDraft:
|
|
56490
|
+
workspaceDraft: draft.workspaceDraft,
|
|
55808
56491
|
values: {
|
|
55809
56492
|
...draft.values,
|
|
55810
56493
|
issueTracker: next,
|
|
55811
56494
|
baseUrl: next === "youtrack" ? draft.values.baseUrl : "",
|
|
55812
|
-
workspaces:
|
|
56495
|
+
workspaces: draft.values.workspaces
|
|
55813
56496
|
}
|
|
55814
56497
|
};
|
|
55815
56498
|
}
|
|
@@ -55939,6 +56622,18 @@ function reducer3(draft, action) {
|
|
|
55939
56622
|
errors: {}
|
|
55940
56623
|
};
|
|
55941
56624
|
}
|
|
56625
|
+
case "workspaceAdvancedOpen": {
|
|
56626
|
+
const entry = draft.values.workspaces[action.index];
|
|
56627
|
+
if (!entry)
|
|
56628
|
+
return draft;
|
|
56629
|
+
return {
|
|
56630
|
+
...draft,
|
|
56631
|
+
screen: "workspaceAdvanced",
|
|
56632
|
+
workspaceIndex: action.index,
|
|
56633
|
+
workspaceDraft: entry.vcs ? { ...entry, vcs: { ...entry.vcs } } : { ...entry },
|
|
56634
|
+
workspaceEditorField: undefined
|
|
56635
|
+
};
|
|
56636
|
+
}
|
|
55942
56637
|
case "workspaceRemove":
|
|
55943
56638
|
return {
|
|
55944
56639
|
...draft,
|
|
@@ -55962,34 +56657,165 @@ function reducer3(draft, action) {
|
|
|
55962
56657
|
...draft,
|
|
55963
56658
|
workspaceDraft: {
|
|
55964
56659
|
...base,
|
|
55965
|
-
vcs: provider === "skip" ? undefined : {
|
|
56660
|
+
vcs: provider === "skip" ? undefined : { ...vcs, provider }
|
|
55966
56661
|
}
|
|
55967
56662
|
};
|
|
55968
56663
|
}
|
|
55969
|
-
case "
|
|
55970
|
-
|
|
55971
|
-
|
|
56664
|
+
case "workspaceAdvancedSelect":
|
|
56665
|
+
return { ...draft, screen: "workspaceAdvancedValue", workspaceEditorField: action.field };
|
|
56666
|
+
case "workspaceAdvancedSet": {
|
|
56667
|
+
if (!draft.workspaceDraft)
|
|
55972
56668
|
return draft;
|
|
55973
|
-
const entry = wd.vcs ? { ...wd, vcs: { ...wd.vcs } } : { ...wd, vcs: undefined };
|
|
55974
|
-
const workspaces = draft.workspaceIndex === null ? [...draft.values.workspaces, entry] : draft.values.workspaces.map((w, i) => i === draft.workspaceIndex ? entry : w);
|
|
55975
56669
|
return {
|
|
55976
56670
|
...draft,
|
|
55977
|
-
|
|
55978
|
-
|
|
55979
|
-
|
|
55980
|
-
|
|
55981
|
-
|
|
56671
|
+
workspaceDraft: setWorkspaceEditorValue(draft.workspaceDraft, action.field, action.value, {
|
|
56672
|
+
branchPreset: draft.values.branchPreset,
|
|
56673
|
+
commitPreset: draft.values.commitPolicy.preset
|
|
56674
|
+
}),
|
|
56675
|
+
screen: "workspaceAdvanced"
|
|
55982
56676
|
};
|
|
55983
56677
|
}
|
|
55984
|
-
|
|
55985
|
-
}
|
|
55986
|
-
|
|
55987
|
-
|
|
55988
|
-
|
|
55989
|
-
|
|
55990
|
-
|
|
55991
|
-
|
|
55992
|
-
|
|
56678
|
+
case "globalCommitOpen":
|
|
56679
|
+
return { ...draft, screen: "globalCommitPolicy" };
|
|
56680
|
+
case "globalCommitEditPattern":
|
|
56681
|
+
return { ...draft, screen: "globalCommitPattern" };
|
|
56682
|
+
case "globalCommitPreset": {
|
|
56683
|
+
const valid = [
|
|
56684
|
+
"conventional",
|
|
56685
|
+
"gitmoji",
|
|
56686
|
+
"ticket-prefix",
|
|
56687
|
+
"freeform",
|
|
56688
|
+
"custom",
|
|
56689
|
+
"auto"
|
|
56690
|
+
];
|
|
56691
|
+
if (!valid.includes(action.value))
|
|
56692
|
+
return draft;
|
|
56693
|
+
return {
|
|
56694
|
+
...draft,
|
|
56695
|
+
values: {
|
|
56696
|
+
...draft.values,
|
|
56697
|
+
commitPolicy: {
|
|
56698
|
+
...draft.values.commitPolicy,
|
|
56699
|
+
preset: action.value
|
|
56700
|
+
}
|
|
56701
|
+
}
|
|
56702
|
+
};
|
|
56703
|
+
}
|
|
56704
|
+
case "globalCommitPattern":
|
|
56705
|
+
return {
|
|
56706
|
+
...draft,
|
|
56707
|
+
values: {
|
|
56708
|
+
...draft.values,
|
|
56709
|
+
commitPolicy: { ...draft.values.commitPolicy, pattern: action.value || undefined }
|
|
56710
|
+
}
|
|
56711
|
+
};
|
|
56712
|
+
case "globalCommitPatternDone":
|
|
56713
|
+
return { ...draft, screen: "globalCommitPolicy" };
|
|
56714
|
+
case "workspaceProfileCreate": {
|
|
56715
|
+
const name = action.name.trim();
|
|
56716
|
+
if (!draft.workspaceDraft || !name || draft.workspaceDraft.profiles?.[name])
|
|
56717
|
+
return draft;
|
|
56718
|
+
const profiles = {
|
|
56719
|
+
...draft.workspaceDraft.profiles,
|
|
56720
|
+
[name]: { commitPolicy: { preset: "conventional" } }
|
|
56721
|
+
};
|
|
56722
|
+
return { ...draft, workspaceDraft: { ...draft.workspaceDraft, profiles } };
|
|
56723
|
+
}
|
|
56724
|
+
case "workspaceProfileDelete": {
|
|
56725
|
+
if (!draft.workspaceDraft?.profiles?.[action.name])
|
|
56726
|
+
return draft;
|
|
56727
|
+
const profiles = { ...draft.workspaceDraft.profiles };
|
|
56728
|
+
delete profiles[action.name];
|
|
56729
|
+
return {
|
|
56730
|
+
...draft,
|
|
56731
|
+
workspaceDraft: {
|
|
56732
|
+
...draft.workspaceDraft,
|
|
56733
|
+
profiles,
|
|
56734
|
+
defaultProfile: draft.workspaceDraft.defaultProfile === action.name ? undefined : draft.workspaceDraft.defaultProfile
|
|
56735
|
+
}
|
|
56736
|
+
};
|
|
56737
|
+
}
|
|
56738
|
+
case "workspaceProfileDefault": {
|
|
56739
|
+
if (!draft.workspaceDraft?.profiles?.[action.name])
|
|
56740
|
+
return draft;
|
|
56741
|
+
return { ...draft, workspaceDraft: { ...draft.workspaceDraft, defaultProfile: action.name } };
|
|
56742
|
+
}
|
|
56743
|
+
case "workspaceProfileSet": {
|
|
56744
|
+
const profile = draft.workspaceDraft?.profiles?.[action.name];
|
|
56745
|
+
if (!draft.workspaceDraft || !profile)
|
|
56746
|
+
return draft;
|
|
56747
|
+
return {
|
|
56748
|
+
...draft,
|
|
56749
|
+
workspaceDraft: {
|
|
56750
|
+
...draft.workspaceDraft,
|
|
56751
|
+
profiles: {
|
|
56752
|
+
...draft.workspaceDraft.profiles,
|
|
56753
|
+
[action.name]: setProfileEditorValue(profile, action.field, action.value, {
|
|
56754
|
+
branchPreset: draft.values.branchPreset,
|
|
56755
|
+
commitPreset: draft.values.commitPolicy.preset
|
|
56756
|
+
})
|
|
56757
|
+
}
|
|
56758
|
+
}
|
|
56759
|
+
};
|
|
56760
|
+
}
|
|
56761
|
+
case "workspaceTrackCreate": {
|
|
56762
|
+
const name = action.name.trim();
|
|
56763
|
+
if (!draft.workspaceDraft || !name || draft.workspaceDraft.releaseTracks?.[name])
|
|
56764
|
+
return draft;
|
|
56765
|
+
return {
|
|
56766
|
+
...draft,
|
|
56767
|
+
workspaceDraft: {
|
|
56768
|
+
...draft.workspaceDraft,
|
|
56769
|
+
releaseTracks: { ...draft.workspaceDraft.releaseTracks, [name]: createReleaseTrack() }
|
|
56770
|
+
}
|
|
56771
|
+
};
|
|
56772
|
+
}
|
|
56773
|
+
case "workspaceTrackDelete": {
|
|
56774
|
+
if (!draft.workspaceDraft?.releaseTracks?.[action.name])
|
|
56775
|
+
return draft;
|
|
56776
|
+
const releaseTracks = { ...draft.workspaceDraft.releaseTracks };
|
|
56777
|
+
delete releaseTracks[action.name];
|
|
56778
|
+
return { ...draft, workspaceDraft: { ...draft.workspaceDraft, releaseTracks } };
|
|
56779
|
+
}
|
|
56780
|
+
case "workspaceTrackSet": {
|
|
56781
|
+
const track = draft.workspaceDraft?.releaseTracks?.[action.name];
|
|
56782
|
+
if (!draft.workspaceDraft || !track)
|
|
56783
|
+
return draft;
|
|
56784
|
+
return {
|
|
56785
|
+
...draft,
|
|
56786
|
+
workspaceDraft: {
|
|
56787
|
+
...draft.workspaceDraft,
|
|
56788
|
+
releaseTracks: {
|
|
56789
|
+
...draft.workspaceDraft.releaseTracks,
|
|
56790
|
+
[action.name]: setTrackEditorValue(track, action.field, action.value)
|
|
56791
|
+
}
|
|
56792
|
+
}
|
|
56793
|
+
};
|
|
56794
|
+
}
|
|
56795
|
+
case "workspaceSave": {
|
|
56796
|
+
const wd = draft.workspaceDraft;
|
|
56797
|
+
if (!wd || !wd.name.trim() || !wd.glob.trim())
|
|
56798
|
+
return draft;
|
|
56799
|
+
const entry = wd.vcs ? { ...wd, vcs: { ...wd.vcs } } : { ...wd, vcs: undefined };
|
|
56800
|
+
const workspaces = draft.workspaceIndex === null ? [...draft.values.workspaces, entry] : draft.values.workspaces.map((w, i) => i === draft.workspaceIndex ? entry : w);
|
|
56801
|
+
return {
|
|
56802
|
+
...draft,
|
|
56803
|
+
screen: "workspaces",
|
|
56804
|
+
workspaceDraft: null,
|
|
56805
|
+
workspaceIndex: null,
|
|
56806
|
+
values: { ...draft.values, workspaces },
|
|
56807
|
+
errors: {}
|
|
56808
|
+
};
|
|
56809
|
+
}
|
|
56810
|
+
}
|
|
56811
|
+
}
|
|
56812
|
+
function defaultWorkspaceProvider(vcs, tracker) {
|
|
56813
|
+
if (tracker === "github")
|
|
56814
|
+
return "github";
|
|
56815
|
+
if (tracker === "gitlab")
|
|
56816
|
+
return "gitlab";
|
|
56817
|
+
return vcs === "gitlab" || vcs === "github" ? vcs : null;
|
|
56818
|
+
}
|
|
55993
56819
|
function workspaceVcs(vcs, tracker) {
|
|
55994
56820
|
const provider = defaultWorkspaceProvider(vcs, tracker);
|
|
55995
56821
|
return provider ? { provider } : undefined;
|
|
@@ -56018,32 +56844,30 @@ function workspaceDraftText(draft, field, value) {
|
|
|
56018
56844
|
}
|
|
56019
56845
|
|
|
56020
56846
|
// packages/workit-core/src/core/detect-hosts.ts
|
|
56021
|
-
import
|
|
56022
|
-
import os8 from "node:os";
|
|
56023
|
-
import path16 from "node:path";
|
|
56847
|
+
import os9 from "node:os";
|
|
56024
56848
|
|
|
56025
56849
|
// packages/workit-core/src/core/uninstall.ts
|
|
56026
|
-
import { existsSync as
|
|
56027
|
-
import
|
|
56028
|
-
import
|
|
56850
|
+
import { existsSync as existsSync13, readFileSync as readFileSync13, realpathSync as realpathSync3, rmSync as rmSync2, writeFileSync as writeFileSync6 } from "node:fs";
|
|
56851
|
+
import os8 from "node:os";
|
|
56852
|
+
import path16 from "node:path";
|
|
56029
56853
|
var resolveUninstallPaths = (options = {}) => {
|
|
56030
|
-
const home = options.home ?? options.env?.HOME ??
|
|
56854
|
+
const home = options.home ?? options.env?.HOME ?? os8.homedir();
|
|
56031
56855
|
return {
|
|
56032
|
-
opencodeConfig: options.opencodeConfig ??
|
|
56033
|
-
cursorSettings: options.cursorSettings ??
|
|
56034
|
-
cursorMcp: options.cursorMcp ??
|
|
56035
|
-
cursorPluginDir: options.cursorPluginDir ??
|
|
56036
|
-
codexPluginDir:
|
|
56037
|
-
piConfig:
|
|
56856
|
+
opencodeConfig: options.opencodeConfig ?? path16.join(home, ".config", "opencode", "opencode.json"),
|
|
56857
|
+
cursorSettings: options.cursorSettings ?? path16.join(home, ".cursor", "settings.json"),
|
|
56858
|
+
cursorMcp: options.cursorMcp ?? path16.join(home, ".cursor", "mcp.json"),
|
|
56859
|
+
cursorPluginDir: options.cursorPluginDir ?? path16.join(home, ".cursor", "plugins", "local", "workit"),
|
|
56860
|
+
codexPluginDir: path16.join(home, ".codex", "plugins", "workit"),
|
|
56861
|
+
piConfig: path16.join(home, ".pi", "config.json")
|
|
56038
56862
|
};
|
|
56039
56863
|
};
|
|
56040
56864
|
var isRecord3 = (v) => v !== null && typeof v === "object" && !Array.isArray(v);
|
|
56041
56865
|
var readJsonRecord = (file) => {
|
|
56042
56866
|
let raw;
|
|
56043
56867
|
try {
|
|
56044
|
-
raw =
|
|
56868
|
+
raw = readFileSync13(file, "utf8");
|
|
56045
56869
|
} catch {
|
|
56046
|
-
if (
|
|
56870
|
+
if (existsSync13(file))
|
|
56047
56871
|
return { kind: "malformed", error: `${file} is not readable` };
|
|
56048
56872
|
return { kind: "missing" };
|
|
56049
56873
|
}
|
|
@@ -56055,8 +56879,8 @@ var readJsonRecord = (file) => {
|
|
|
56055
56879
|
}
|
|
56056
56880
|
};
|
|
56057
56881
|
var stripTrailingSep = (p) => {
|
|
56058
|
-
const j =
|
|
56059
|
-
return
|
|
56882
|
+
const j = path16.join(p);
|
|
56883
|
+
return path16.dirname(j) === j ? j : j.replace(/[\\/]+$/, "");
|
|
56060
56884
|
};
|
|
56061
56885
|
var CURSOR_LEGACY_IDENTITIES = ["workflow-toolkit", "local/workflow-toolkit"];
|
|
56062
56886
|
function cleanCursorSettings(settings, pluginDir) {
|
|
@@ -56167,7 +56991,7 @@ function planUninstall(paths = {}) {
|
|
|
56167
56991
|
const mcpExisting = readJsonRecord(res.cursorMcp);
|
|
56168
56992
|
const settingsDirty = settingsExisting.kind === "malformed" || settingsExisting.kind === "record" && cleanCursorSettings(settingsExisting.value, res.cursorPluginDir).changed;
|
|
56169
56993
|
const mcpDirty = mcpExisting.kind === "malformed" || mcpExisting.kind === "record" && cleanCursorMcp(mcpExisting.value).changed;
|
|
56170
|
-
const dirExists =
|
|
56994
|
+
const dirExists = existsSync13(res.cursorPluginDir);
|
|
56171
56995
|
const actions = [];
|
|
56172
56996
|
if (settingsDirty) {
|
|
56173
56997
|
actions.push({
|
|
@@ -56195,7 +57019,7 @@ function planUninstall(paths = {}) {
|
|
|
56195
57019
|
installed: settingsDirty || mcpDirty || dirExists,
|
|
56196
57020
|
actions
|
|
56197
57021
|
};
|
|
56198
|
-
const codexInstalled =
|
|
57022
|
+
const codexInstalled = existsSync13(res.codexPluginDir);
|
|
56199
57023
|
const codex = {
|
|
56200
57024
|
host: "codex",
|
|
56201
57025
|
installed: codexInstalled,
|
|
@@ -56217,8 +57041,8 @@ function planUninstall(paths = {}) {
|
|
|
56217
57041
|
return { hosts: [opencode, cursor, codex, pi] };
|
|
56218
57042
|
}
|
|
56219
57043
|
var canonicalRemoveDirAllowed = (actionPath, res) => {
|
|
56220
|
-
const expected =
|
|
56221
|
-
if (!(actionPath === expected &&
|
|
57044
|
+
const expected = path16.resolve(res.cursorPluginDir);
|
|
57045
|
+
if (!(actionPath === expected && path16.basename(expected) === "workit" && path16.basename(path16.dirname(expected)) === "local" && path16.basename(path16.dirname(path16.dirname(expected))) === "plugins")) {
|
|
56222
57046
|
return false;
|
|
56223
57047
|
}
|
|
56224
57048
|
try {
|
|
@@ -56242,7 +57066,7 @@ var applyEditJsonRemove = (target, cleaner) => {
|
|
|
56242
57066
|
`;
|
|
56243
57067
|
let current;
|
|
56244
57068
|
try {
|
|
56245
|
-
current =
|
|
57069
|
+
current = readFileSync13(target, "utf8");
|
|
56246
57070
|
} catch (error) {
|
|
56247
57071
|
return {
|
|
56248
57072
|
status: "failed",
|
|
@@ -56270,12 +57094,12 @@ function applyUninstall(plan, paths = {}) {
|
|
|
56270
57094
|
let status;
|
|
56271
57095
|
let detail;
|
|
56272
57096
|
if (action.kind === "remove-dir") {
|
|
56273
|
-
const resolved =
|
|
56274
|
-
const allowed = canonicalRemoveDirAllowed(resolved, res) || resolved ===
|
|
57097
|
+
const resolved = path16.resolve(action.path);
|
|
57098
|
+
const allowed = canonicalRemoveDirAllowed(resolved, res) || resolved === path16.resolve(res.codexPluginDir) && path16.basename(resolved) === "workit" && path16.basename(path16.dirname(resolved)) === "plugins";
|
|
56275
57099
|
if (!allowed) {
|
|
56276
57100
|
status = "failed";
|
|
56277
57101
|
detail = `refusing to remove non-canonical plugin directory: ${resolved}`;
|
|
56278
|
-
} else if (!
|
|
57102
|
+
} else if (!existsSync13(resolved)) {
|
|
56279
57103
|
status = "skipped";
|
|
56280
57104
|
detail = "directory already absent";
|
|
56281
57105
|
} else {
|
|
@@ -56306,13 +57130,7 @@ function applyUninstall(plan, paths = {}) {
|
|
|
56306
57130
|
|
|
56307
57131
|
// packages/workit-core/src/core/detect-hosts.ts
|
|
56308
57132
|
var HOSTS = ["opencode", "cursor", "codex", "pi"];
|
|
56309
|
-
var
|
|
56310
|
-
opencode: [path16.join(".config", "opencode")],
|
|
56311
|
-
cursor: [".cursor"],
|
|
56312
|
-
codex: [".codex"],
|
|
56313
|
-
pi: [".pi"]
|
|
56314
|
-
};
|
|
56315
|
-
var WIZARD_HOSTS = ["opencode", "cursor"];
|
|
57133
|
+
var WIZARD_HOSTS = [...HOSTS];
|
|
56316
57134
|
function preselectedPlatforms(detection) {
|
|
56317
57135
|
return WIZARD_HOSTS.filter((host) => detection[host].detected);
|
|
56318
57136
|
}
|
|
@@ -56326,52 +57144,19 @@ function emptyDetection() {
|
|
|
56326
57144
|
}
|
|
56327
57145
|
function detectHosts(options = {}) {
|
|
56328
57146
|
const env = options.env ?? process.env;
|
|
56329
|
-
const home = options.home ?? env.HOME ??
|
|
56330
|
-
const plan = planUninstall(options);
|
|
57147
|
+
const home = options.home ?? env.HOME ?? os9.homedir();
|
|
57148
|
+
const plan = planUninstall({ ...options, home, env });
|
|
56331
57149
|
const configuredByHost = new Map(plan.hosts.map((h) => [h.host, h.installed]));
|
|
56332
57150
|
const found = emptyDetection();
|
|
56333
57151
|
for (const host of HOSTS) {
|
|
56334
|
-
const detected =
|
|
57152
|
+
const detected = findHostExecutable(host, { home, env }) !== null || installedHostApp(host, home, env);
|
|
56335
57153
|
found[host] = {
|
|
56336
57154
|
detected,
|
|
56337
|
-
configured:
|
|
57155
|
+
configured: host === "codex" ? isCodexWorkitInstalled(home, env) || (configuredByHost.get(host) ?? false) : host === "pi" ? isPiWorkitInstalled(home, env) || (configuredByHost.get(host) ?? false) : configuredByHost.get(host) ?? false
|
|
56338
57156
|
};
|
|
56339
57157
|
}
|
|
56340
57158
|
return found;
|
|
56341
57159
|
}
|
|
56342
|
-
function cliFound(name, env, home) {
|
|
56343
|
-
if (commandOnPath(name, env))
|
|
56344
|
-
return true;
|
|
56345
|
-
const extra = managerBinDirs(home);
|
|
56346
|
-
if (extra.length === 0)
|
|
56347
|
-
return false;
|
|
56348
|
-
return commandOnPath(name, {
|
|
56349
|
-
...env,
|
|
56350
|
-
PATH: [...(env.PATH ?? "").split(path16.delimiter), ...extra].join(path16.delimiter)
|
|
56351
|
-
});
|
|
56352
|
-
}
|
|
56353
|
-
var managerBinDirs = (home) => {
|
|
56354
|
-
const dirs = [path16.join(home, ".local", "bin"), path16.join(home, ".asdf", "shims")];
|
|
56355
|
-
const versioned = [
|
|
56356
|
-
[path16.join(home, ".local", "share", "fnm", "node-versions"), path16.join("installation", "bin")],
|
|
56357
|
-
[path16.join(home, ".nvm", "versions", "node"), "bin"]
|
|
56358
|
-
];
|
|
56359
|
-
for (const [base, tail] of versioned) {
|
|
56360
|
-
let entries;
|
|
56361
|
-
try {
|
|
56362
|
-
entries = readdirSync5(base, { withFileTypes: true });
|
|
56363
|
-
} catch {
|
|
56364
|
-
continue;
|
|
56365
|
-
}
|
|
56366
|
-
for (const entry of entries) {
|
|
56367
|
-
try {
|
|
56368
|
-
if (entry.isDirectory())
|
|
56369
|
-
dirs.push(path16.join(base, entry.name, tail));
|
|
56370
|
-
} catch {}
|
|
56371
|
-
}
|
|
56372
|
-
}
|
|
56373
|
-
return dirs;
|
|
56374
|
-
};
|
|
56375
57160
|
|
|
56376
57161
|
// packages/workit-cli/src/search-select.tsx
|
|
56377
57162
|
var import_react65 = __toESM(require_react(), 1);
|
|
@@ -56469,22 +57254,10 @@ function SearchSelect({
|
|
|
56469
57254
|
var jsx_dev_runtime2 = __toESM(require_jsx_dev_runtime(), 1);
|
|
56470
57255
|
var PLATFORM_LABELS = [
|
|
56471
57256
|
{ label: "OpenCode", value: "opencode" },
|
|
56472
|
-
{ label: "Cursor", value: "cursor" }
|
|
57257
|
+
{ label: "Cursor", value: "cursor" },
|
|
57258
|
+
{ label: "Codex", value: "codex" },
|
|
57259
|
+
{ label: "Pi", value: "pi" }
|
|
56473
57260
|
];
|
|
56474
|
-
function platformOptions(detection) {
|
|
56475
|
-
return PLATFORM_LABELS.map(({ label, value }) => {
|
|
56476
|
-
const found = detection[value];
|
|
56477
|
-
const tag = found.configured ? " · already configured" : found.detected ? " · detected" : "";
|
|
56478
|
-
return { label: `${label}${tag}`, value };
|
|
56479
|
-
});
|
|
56480
|
-
}
|
|
56481
|
-
function externalHostGuidance(detection) {
|
|
56482
|
-
return ["codex", "pi"].map((host) => {
|
|
56483
|
-
const found = detection[host];
|
|
56484
|
-
const status = found.configured ? "already configured" : found.detected ? "detected" : "not detected";
|
|
56485
|
-
return host === "codex" ? `Codex · ${status} — plugin/hooks setup: https://github.com/BrainerVirus/workit#readme (Codex CLI / desktop)` : `Pi · ${status} — install separately: pi install @brainervirus/workit-pi`;
|
|
56486
|
-
});
|
|
56487
|
-
}
|
|
56488
57261
|
var BRANCH_PRESETS = [
|
|
56489
57262
|
{ label: "GitFlow", value: "gitflow" },
|
|
56490
57263
|
{ label: "GitHub Flow", value: "github-flow" },
|
|
@@ -56522,6 +57295,99 @@ var ISSUE_TRACKERS = [
|
|
|
56522
57295
|
{ label: "GitLab Issues", value: "gitlab" },
|
|
56523
57296
|
{ label: "None", value: "none" }
|
|
56524
57297
|
];
|
|
57298
|
+
var WORKSPACE_ADVANCED_FIELDS = [
|
|
57299
|
+
{ label: "Hosting provider account", value: "vcs.account" },
|
|
57300
|
+
{ label: "Default target branch", value: "vcs.defaultTargetBranch" },
|
|
57301
|
+
{ label: "Workspace YouTrack URL", value: "youtrack.baseUrl" },
|
|
57302
|
+
{ label: "Link issues in YouTrack", value: "youtrack.link_issues" },
|
|
57303
|
+
{ label: "Link GitHub issues on pull requests", value: "issues.link_on_pr" },
|
|
57304
|
+
{ label: "Branch preset", value: "branchPolicy.preset" },
|
|
57305
|
+
{ label: "Allowed branch patterns", value: "branchPolicy.allowed" },
|
|
57306
|
+
{ label: "Protected branches", value: "branchPolicy.protected" },
|
|
57307
|
+
{ label: "Develop branch", value: "branchPolicy.developBranch" },
|
|
57308
|
+
{ label: "Integration method (pr or merge)", value: "branchPolicy.integration" },
|
|
57309
|
+
{ label: "Feature prefix", value: "branchPolicy.prefixes.feature" },
|
|
57310
|
+
{ label: "Bugfix prefix", value: "branchPolicy.prefixes.bugfix" },
|
|
57311
|
+
{ label: "Release prefix", value: "branchPolicy.prefixes.release" },
|
|
57312
|
+
{ label: "Hotfix prefix", value: "branchPolicy.prefixes.hotfix" },
|
|
57313
|
+
{ label: "Commit policy preset", value: "commitPolicy.preset" },
|
|
57314
|
+
{ label: "Custom commit pattern", value: "commitPolicy.pattern" },
|
|
57315
|
+
{ label: "Default profile name", value: "defaultProfile" }
|
|
57316
|
+
];
|
|
57317
|
+
var PROFILE_FIELDS = [
|
|
57318
|
+
{ label: "Branch preset", value: "branchPolicy.preset" },
|
|
57319
|
+
{ label: "Allowed patterns", value: "branchPolicy.allowed" },
|
|
57320
|
+
{ label: "Protected branches", value: "branchPolicy.protected" },
|
|
57321
|
+
{ label: "Develop branch", value: "branchPolicy.developBranch" },
|
|
57322
|
+
{ label: "Integration (pr or merge)", value: "branchPolicy.integration" },
|
|
57323
|
+
{ label: "Feature prefix", value: "branchPolicy.prefixes.feature" },
|
|
57324
|
+
{ label: "Bugfix prefix", value: "branchPolicy.prefixes.bugfix" },
|
|
57325
|
+
{ label: "Release prefix", value: "branchPolicy.prefixes.release" },
|
|
57326
|
+
{ label: "Hotfix prefix", value: "branchPolicy.prefixes.hotfix" },
|
|
57327
|
+
{ label: "Commit preset", value: "commitPolicy.preset" },
|
|
57328
|
+
{ label: "Commit pattern", value: "commitPolicy.pattern" }
|
|
57329
|
+
];
|
|
57330
|
+
var TRACK_FIELDS = [
|
|
57331
|
+
{ label: "Strategy", value: "strategy" },
|
|
57332
|
+
{ label: "Production branch", value: "productionBranch" },
|
|
57333
|
+
{ label: "Integration branch", value: "integrationBranch" },
|
|
57334
|
+
{ label: "Feature branch naming", value: "naming.feature" },
|
|
57335
|
+
{ label: "Release branch naming", value: "naming.release" },
|
|
57336
|
+
{ label: "Hotfix branch naming", value: "naming.hotfix" },
|
|
57337
|
+
{ label: "Base branch", value: "baseBranch" },
|
|
57338
|
+
{ label: "Merge-back branches", value: "mergeBackBranches" },
|
|
57339
|
+
{ label: "Pull request target", value: "pullRequestTarget" },
|
|
57340
|
+
{ label: "Tag namespace", value: "tagNamespace" },
|
|
57341
|
+
{ label: "Version source (manual, git-tag, package-json)", value: "versionSource.kind" },
|
|
57342
|
+
{ label: "Package.json path", value: "versionSource.path" },
|
|
57343
|
+
{ label: "Package version field", value: "versionSource.field" },
|
|
57344
|
+
{ label: "Required checks", value: "requiredChecks" }
|
|
57345
|
+
];
|
|
57346
|
+
var enumFieldOptions = (field) => {
|
|
57347
|
+
if (field === "commitPolicy.preset")
|
|
57348
|
+
return [{ label: "Inherit global", value: "inherit" }, ...commitPresetOptions];
|
|
57349
|
+
if (field === "branchPolicy.preset")
|
|
57350
|
+
return [
|
|
57351
|
+
{ label: "Inherit global", value: "inherit" },
|
|
57352
|
+
{ label: "GitFlow", value: "gitflow" },
|
|
57353
|
+
{ label: "GitHub Flow", value: "github-flow" },
|
|
57354
|
+
{ label: "Trunk-based", value: "trunk-based" },
|
|
57355
|
+
{ label: "Custom", value: "custom" }
|
|
57356
|
+
];
|
|
57357
|
+
if (field === "strategy")
|
|
57358
|
+
return [
|
|
57359
|
+
{ label: "GitFlow", value: "gitflow" },
|
|
57360
|
+
{ label: "GitHub Flow", value: "github-flow" },
|
|
57361
|
+
{ label: "Trunk-based", value: "trunk-based" },
|
|
57362
|
+
{ label: "Custom", value: "custom" }
|
|
57363
|
+
];
|
|
57364
|
+
if (field.endsWith(".integration"))
|
|
57365
|
+
return [
|
|
57366
|
+
{ label: "Pull requests", value: "pr" },
|
|
57367
|
+
{ label: "Merge commits", value: "merge" }
|
|
57368
|
+
];
|
|
57369
|
+
if (field === "versionSource.kind")
|
|
57370
|
+
return [
|
|
57371
|
+
{ label: "Package.json", value: "package-json" },
|
|
57372
|
+
{ label: "Git tag", value: "git-tag" },
|
|
57373
|
+
{ label: "Manual", value: "manual" }
|
|
57374
|
+
];
|
|
57375
|
+
if (field === "youtrack.link_issues" || field === "issues.link_on_pr")
|
|
57376
|
+
return [
|
|
57377
|
+
{ label: "Inherit global behavior", value: "inherit" },
|
|
57378
|
+
{ label: "Enabled", value: "true" },
|
|
57379
|
+
{ label: "Disabled", value: "false" }
|
|
57380
|
+
];
|
|
57381
|
+
return null;
|
|
57382
|
+
};
|
|
57383
|
+
var commitPresetOptions = [
|
|
57384
|
+
{ label: "Conventional commits", value: "conventional" },
|
|
57385
|
+
{ label: "Gitmoji", value: "gitmoji" },
|
|
57386
|
+
{ label: "Ticket prefix", value: "ticket-prefix" },
|
|
57387
|
+
{ label: "Freeform", value: "freeform" },
|
|
57388
|
+
{ label: "Custom pattern", value: "custom" },
|
|
57389
|
+
{ label: "Auto-detect", value: "auto" }
|
|
57390
|
+
];
|
|
56525
57391
|
var TIMEZONE_FALLBACK = [
|
|
56526
57392
|
"UTC",
|
|
56527
57393
|
"America/New_York",
|
|
@@ -56560,6 +57426,8 @@ var TEXT_SCREENS = new Set([
|
|
|
56560
57426
|
"basePath",
|
|
56561
57427
|
"workspaceName",
|
|
56562
57428
|
"workspaceGlob",
|
|
57429
|
+
"workspaceAdvancedValue",
|
|
57430
|
+
"globalCommitPattern",
|
|
56563
57431
|
"branchPolicyDevelop"
|
|
56564
57432
|
]);
|
|
56565
57433
|
var SEARCH_SCREENS = new Set(["locale", "timezone"]);
|
|
@@ -56604,6 +57472,479 @@ function SelectList({
|
|
|
56604
57472
|
}, option.value, true, undefined, this))
|
|
56605
57473
|
}, undefined, false, undefined, this);
|
|
56606
57474
|
}
|
|
57475
|
+
function HostPicker({
|
|
57476
|
+
detection,
|
|
57477
|
+
selected,
|
|
57478
|
+
onChange,
|
|
57479
|
+
onSubmit
|
|
57480
|
+
}) {
|
|
57481
|
+
const available = PLATFORM_LABELS.filter(({ value }) => detection[value].detected).map(({ value }) => value);
|
|
57482
|
+
const options = [
|
|
57483
|
+
{ label: "Select all available", value: "__all" },
|
|
57484
|
+
{ label: "Clear all", value: "__none" },
|
|
57485
|
+
...PLATFORM_LABELS.map(({ label, value }) => ({ label, value }))
|
|
57486
|
+
];
|
|
57487
|
+
const [index, setIndex] = import_react66.useState(0);
|
|
57488
|
+
const indexRef = import_react66.useRef(index);
|
|
57489
|
+
const [chosen, setChosen] = import_react66.useState(selected);
|
|
57490
|
+
const chosenRef = import_react66.useRef(chosen);
|
|
57491
|
+
import_react66.useEffect(() => {
|
|
57492
|
+
indexRef.current = index;
|
|
57493
|
+
}, [index]);
|
|
57494
|
+
import_react66.useEffect(() => {
|
|
57495
|
+
chosenRef.current = chosen;
|
|
57496
|
+
}, [chosen]);
|
|
57497
|
+
const update = (next) => {
|
|
57498
|
+
chosenRef.current = next;
|
|
57499
|
+
setChosen(next);
|
|
57500
|
+
onChange(next);
|
|
57501
|
+
};
|
|
57502
|
+
use_input_default((input, key) => {
|
|
57503
|
+
if (key.upArrow || key.downArrow) {
|
|
57504
|
+
const next = Math.max(0, Math.min(options.length - 1, indexRef.current + (key.downArrow ? 1 : -1)));
|
|
57505
|
+
indexRef.current = next;
|
|
57506
|
+
setIndex(next);
|
|
57507
|
+
return;
|
|
57508
|
+
}
|
|
57509
|
+
if (input === " ") {
|
|
57510
|
+
const option = options[indexRef.current];
|
|
57511
|
+
if (option.value === "__all")
|
|
57512
|
+
update([...available]);
|
|
57513
|
+
else if (option.value === "__none")
|
|
57514
|
+
update([]);
|
|
57515
|
+
else if (detection[option.value].detected) {
|
|
57516
|
+
const next = chosenRef.current.includes(option.value) ? chosenRef.current.filter((host) => host !== option.value) : [...chosenRef.current, option.value];
|
|
57517
|
+
update(next);
|
|
57518
|
+
}
|
|
57519
|
+
} else if (key.return) {
|
|
57520
|
+
const option = options[indexRef.current];
|
|
57521
|
+
if (option.value === "__all")
|
|
57522
|
+
update([...available]);
|
|
57523
|
+
else if (option.value === "__none")
|
|
57524
|
+
update([]);
|
|
57525
|
+
onSubmit(chosenRef.current);
|
|
57526
|
+
}
|
|
57527
|
+
});
|
|
57528
|
+
return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
|
|
57529
|
+
flexDirection: "column",
|
|
57530
|
+
gap: 0,
|
|
57531
|
+
children: options.map((option, row) => {
|
|
57532
|
+
const host = option.value === "__all" || option.value === "__none" ? null : option.value;
|
|
57533
|
+
const detected = host === null || detection[host].detected;
|
|
57534
|
+
const checked = host !== null && chosen.includes(host);
|
|
57535
|
+
const label = host === null ? option.label : `${checked ? "[✓]" : "[ ]"} ${option.label}${detection[host].configured ? " · already configured" : detection[host].detected ? " · detected" : " · unavailable"}`;
|
|
57536
|
+
return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
57537
|
+
color: row === index ? "cyan" : undefined,
|
|
57538
|
+
dimColor: !detected,
|
|
57539
|
+
children: [
|
|
57540
|
+
row === index ? "❯ " : " ",
|
|
57541
|
+
label
|
|
57542
|
+
]
|
|
57543
|
+
}, option.value, true, undefined, this);
|
|
57544
|
+
})
|
|
57545
|
+
}, undefined, false, undefined, this);
|
|
57546
|
+
}
|
|
57547
|
+
function WorkspaceCollectionEditor({
|
|
57548
|
+
draft,
|
|
57549
|
+
dispatch
|
|
57550
|
+
}) {
|
|
57551
|
+
const [mode, setMode] = import_react66.useState("main");
|
|
57552
|
+
const [name, setName] = import_react66.useState("");
|
|
57553
|
+
const [field, setField] = import_react66.useState(null);
|
|
57554
|
+
const [nameError, setNameError] = import_react66.useState("");
|
|
57555
|
+
const workspace = draft.workspaceDraft;
|
|
57556
|
+
const profileNames = Object.keys(workspace?.profiles ?? {});
|
|
57557
|
+
const trackNames = Object.keys(workspace?.releaseTracks ?? {});
|
|
57558
|
+
if (!workspace)
|
|
57559
|
+
return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
57560
|
+
color: "red",
|
|
57561
|
+
children: "Workspace draft is unavailable."
|
|
57562
|
+
}, undefined, false, undefined, this);
|
|
57563
|
+
if (mode === "profiles") {
|
|
57564
|
+
const options = [
|
|
57565
|
+
...profileNames.flatMap((profile) => [
|
|
57566
|
+
{ label: `Edit profile ${profile}`, value: `edit:${profile}` },
|
|
57567
|
+
{ label: `Set ${profile} as default`, value: `default:${profile}` },
|
|
57568
|
+
{ label: `Delete profile ${profile}`, value: `delete:${profile}` }
|
|
57569
|
+
]),
|
|
57570
|
+
{ label: "Create profile", value: "create" },
|
|
57571
|
+
{ label: "Back to advanced settings", value: "back" }
|
|
57572
|
+
];
|
|
57573
|
+
return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
|
|
57574
|
+
flexDirection: "column",
|
|
57575
|
+
gap: 1,
|
|
57576
|
+
children: [
|
|
57577
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
57578
|
+
bold: true,
|
|
57579
|
+
children: [
|
|
57580
|
+
"Profiles · default: ",
|
|
57581
|
+
workspace.defaultProfile ?? "none"
|
|
57582
|
+
]
|
|
57583
|
+
}, undefined, true, undefined, this),
|
|
57584
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
57585
|
+
dimColor: true,
|
|
57586
|
+
children: "Profiles can override branch rules and commit conventions."
|
|
57587
|
+
}, undefined, false, undefined, this),
|
|
57588
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(SelectList, {
|
|
57589
|
+
options,
|
|
57590
|
+
value: "back",
|
|
57591
|
+
onSelect: (value) => {
|
|
57592
|
+
const profileName = value.slice(value.indexOf(":") + 1);
|
|
57593
|
+
if (value === "create") {
|
|
57594
|
+
setNameError("");
|
|
57595
|
+
setName("");
|
|
57596
|
+
setMode("profileName");
|
|
57597
|
+
} else if (value.startsWith("edit:")) {
|
|
57598
|
+
setName(profileName);
|
|
57599
|
+
setMode("profileEdit");
|
|
57600
|
+
} else if (value.startsWith("default:"))
|
|
57601
|
+
dispatch({ type: "workspaceProfileDefault", name: profileName });
|
|
57602
|
+
else if (value.startsWith("delete:"))
|
|
57603
|
+
dispatch({ type: "workspaceProfileDelete", name: profileName });
|
|
57604
|
+
else
|
|
57605
|
+
setMode("main");
|
|
57606
|
+
}
|
|
57607
|
+
}, undefined, false, undefined, this)
|
|
57608
|
+
]
|
|
57609
|
+
}, undefined, true, undefined, this);
|
|
57610
|
+
}
|
|
57611
|
+
if (mode === "profileName")
|
|
57612
|
+
return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
|
|
57613
|
+
flexDirection: "column",
|
|
57614
|
+
gap: 1,
|
|
57615
|
+
children: [
|
|
57616
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
57617
|
+
bold: true,
|
|
57618
|
+
children: "Create profile"
|
|
57619
|
+
}, undefined, false, undefined, this),
|
|
57620
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
57621
|
+
dimColor: true,
|
|
57622
|
+
children: "Profile name:"
|
|
57623
|
+
}, undefined, false, undefined, this),
|
|
57624
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(TextInput, {
|
|
57625
|
+
onSubmit: (value) => {
|
|
57626
|
+
const next = value.trim();
|
|
57627
|
+
if (!next) {
|
|
57628
|
+
setNameError("Enter a profile name.");
|
|
57629
|
+
return;
|
|
57630
|
+
}
|
|
57631
|
+
if (workspace.profiles?.[next]) {
|
|
57632
|
+
setNameError(`Profile ${next} already exists. Choose a different name or edit it from the list.`);
|
|
57633
|
+
return;
|
|
57634
|
+
}
|
|
57635
|
+
dispatch({ type: "workspaceProfileCreate", name: next });
|
|
57636
|
+
setName(next);
|
|
57637
|
+
setMode("profileEdit");
|
|
57638
|
+
}
|
|
57639
|
+
}, undefined, false, undefined, this),
|
|
57640
|
+
nameError && /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
57641
|
+
color: "red",
|
|
57642
|
+
children: nameError
|
|
57643
|
+
}, undefined, false, undefined, this),
|
|
57644
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
57645
|
+
dimColor: true,
|
|
57646
|
+
children: "Enter to create · Esc Back"
|
|
57647
|
+
}, undefined, false, undefined, this)
|
|
57648
|
+
]
|
|
57649
|
+
}, undefined, true, undefined, this);
|
|
57650
|
+
if (mode === "profileEdit" || mode === "profileValue") {
|
|
57651
|
+
const selected = workspace.profiles?.[name];
|
|
57652
|
+
if (mode === "profileValue" && field) {
|
|
57653
|
+
const item = PROFILE_FIELDS.find((entry) => entry.value === field);
|
|
57654
|
+
const choices = enumFieldOptions(field);
|
|
57655
|
+
return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
|
|
57656
|
+
flexDirection: "column",
|
|
57657
|
+
gap: 1,
|
|
57658
|
+
children: [
|
|
57659
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
57660
|
+
bold: true,
|
|
57661
|
+
children: [
|
|
57662
|
+
"Profile ",
|
|
57663
|
+
name,
|
|
57664
|
+
" · ",
|
|
57665
|
+
item?.label
|
|
57666
|
+
]
|
|
57667
|
+
}, undefined, true, undefined, this),
|
|
57668
|
+
choices ? /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(SelectList, {
|
|
57669
|
+
options: choices,
|
|
57670
|
+
value: selected ? profileEditorValue(selected, field) : choices[0].value,
|
|
57671
|
+
onSelect: (value) => {
|
|
57672
|
+
dispatch({
|
|
57673
|
+
type: "workspaceProfileSet",
|
|
57674
|
+
name,
|
|
57675
|
+
field,
|
|
57676
|
+
value
|
|
57677
|
+
});
|
|
57678
|
+
setMode("profileEdit");
|
|
57679
|
+
}
|
|
57680
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(TextInput, {
|
|
57681
|
+
defaultValue: selected ? profileEditorValue(selected, field) : "",
|
|
57682
|
+
onSubmit: (value) => {
|
|
57683
|
+
dispatch({
|
|
57684
|
+
type: "workspaceProfileSet",
|
|
57685
|
+
name,
|
|
57686
|
+
field,
|
|
57687
|
+
value
|
|
57688
|
+
});
|
|
57689
|
+
setMode("profileEdit");
|
|
57690
|
+
}
|
|
57691
|
+
}, undefined, false, undefined, this),
|
|
57692
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
57693
|
+
dimColor: true,
|
|
57694
|
+
children: "Enter to save · Esc Back"
|
|
57695
|
+
}, undefined, false, undefined, this)
|
|
57696
|
+
]
|
|
57697
|
+
}, undefined, true, undefined, this);
|
|
57698
|
+
}
|
|
57699
|
+
const options = [
|
|
57700
|
+
...PROFILE_FIELDS,
|
|
57701
|
+
{ label: "Done editing", value: "done" }
|
|
57702
|
+
];
|
|
57703
|
+
return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
|
|
57704
|
+
flexDirection: "column",
|
|
57705
|
+
gap: 1,
|
|
57706
|
+
children: [
|
|
57707
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
57708
|
+
bold: true,
|
|
57709
|
+
children: [
|
|
57710
|
+
"Edit profile · ",
|
|
57711
|
+
name
|
|
57712
|
+
]
|
|
57713
|
+
}, undefined, true, undefined, this),
|
|
57714
|
+
PROFILE_FIELDS.map((item) => /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
57715
|
+
dimColor: true,
|
|
57716
|
+
children: [
|
|
57717
|
+
item.label,
|
|
57718
|
+
": ",
|
|
57719
|
+
selected ? profileEditorValue(selected, item.value) || "unset" : ""
|
|
57720
|
+
]
|
|
57721
|
+
}, item.value, true, undefined, this)),
|
|
57722
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(SelectList, {
|
|
57723
|
+
options,
|
|
57724
|
+
value: "done",
|
|
57725
|
+
onSelect: (value) => {
|
|
57726
|
+
if (value === "done")
|
|
57727
|
+
setMode("profiles");
|
|
57728
|
+
else {
|
|
57729
|
+
setField(value);
|
|
57730
|
+
setMode("profileValue");
|
|
57731
|
+
}
|
|
57732
|
+
}
|
|
57733
|
+
}, undefined, false, undefined, this)
|
|
57734
|
+
]
|
|
57735
|
+
}, undefined, true, undefined, this);
|
|
57736
|
+
}
|
|
57737
|
+
if (mode === "tracks") {
|
|
57738
|
+
const options = [
|
|
57739
|
+
...trackNames.flatMap((track) => [
|
|
57740
|
+
{ label: `Edit release track ${track}`, value: `edit:${track}` },
|
|
57741
|
+
{ label: `Delete release track ${track}`, value: `delete:${track}` }
|
|
57742
|
+
]),
|
|
57743
|
+
{ label: "Create release track", value: "create" },
|
|
57744
|
+
{ label: "Back to advanced settings", value: "back" }
|
|
57745
|
+
];
|
|
57746
|
+
return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
|
|
57747
|
+
flexDirection: "column",
|
|
57748
|
+
gap: 1,
|
|
57749
|
+
children: [
|
|
57750
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
57751
|
+
bold: true,
|
|
57752
|
+
children: "Named release tracks"
|
|
57753
|
+
}, undefined, false, undefined, this),
|
|
57754
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
57755
|
+
dimColor: true,
|
|
57756
|
+
children: "Each track has its own branches, naming, version source, and checks."
|
|
57757
|
+
}, undefined, false, undefined, this),
|
|
57758
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(SelectList, {
|
|
57759
|
+
options,
|
|
57760
|
+
value: "back",
|
|
57761
|
+
onSelect: (value) => {
|
|
57762
|
+
const trackName = value.slice(value.indexOf(":") + 1);
|
|
57763
|
+
if (value === "create") {
|
|
57764
|
+
setNameError("");
|
|
57765
|
+
setName("");
|
|
57766
|
+
setMode("trackName");
|
|
57767
|
+
} else if (value.startsWith("edit:")) {
|
|
57768
|
+
setName(trackName);
|
|
57769
|
+
setMode("trackEdit");
|
|
57770
|
+
} else if (value.startsWith("delete:"))
|
|
57771
|
+
dispatch({ type: "workspaceTrackDelete", name: trackName });
|
|
57772
|
+
else
|
|
57773
|
+
setMode("main");
|
|
57774
|
+
}
|
|
57775
|
+
}, undefined, false, undefined, this)
|
|
57776
|
+
]
|
|
57777
|
+
}, undefined, true, undefined, this);
|
|
57778
|
+
}
|
|
57779
|
+
if (mode === "trackName")
|
|
57780
|
+
return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
|
|
57781
|
+
flexDirection: "column",
|
|
57782
|
+
gap: 1,
|
|
57783
|
+
children: [
|
|
57784
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
57785
|
+
bold: true,
|
|
57786
|
+
children: "Create release track"
|
|
57787
|
+
}, undefined, false, undefined, this),
|
|
57788
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
57789
|
+
dimColor: true,
|
|
57790
|
+
children: "Track name:"
|
|
57791
|
+
}, undefined, false, undefined, this),
|
|
57792
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(TextInput, {
|
|
57793
|
+
onSubmit: (value) => {
|
|
57794
|
+
const next = value.trim();
|
|
57795
|
+
if (!next) {
|
|
57796
|
+
setNameError("Enter a release-track name.");
|
|
57797
|
+
return;
|
|
57798
|
+
}
|
|
57799
|
+
if (workspace.releaseTracks?.[next]) {
|
|
57800
|
+
setNameError(`Release track ${next} already exists. Choose a different name or edit it from the list.`);
|
|
57801
|
+
return;
|
|
57802
|
+
}
|
|
57803
|
+
dispatch({ type: "workspaceTrackCreate", name: next });
|
|
57804
|
+
setName(next);
|
|
57805
|
+
setMode("trackEdit");
|
|
57806
|
+
}
|
|
57807
|
+
}, undefined, false, undefined, this),
|
|
57808
|
+
nameError && /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
57809
|
+
color: "red",
|
|
57810
|
+
children: nameError
|
|
57811
|
+
}, undefined, false, undefined, this),
|
|
57812
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
57813
|
+
dimColor: true,
|
|
57814
|
+
children: "Enter to create · Esc Back"
|
|
57815
|
+
}, undefined, false, undefined, this)
|
|
57816
|
+
]
|
|
57817
|
+
}, undefined, true, undefined, this);
|
|
57818
|
+
if (mode === "trackEdit" || mode === "trackValue") {
|
|
57819
|
+
const selected = workspace.releaseTracks?.[name];
|
|
57820
|
+
if (mode === "trackValue" && field) {
|
|
57821
|
+
const item = TRACK_FIELDS.find((entry) => entry.value === field);
|
|
57822
|
+
const choices = enumFieldOptions(field);
|
|
57823
|
+
return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
|
|
57824
|
+
flexDirection: "column",
|
|
57825
|
+
gap: 1,
|
|
57826
|
+
children: [
|
|
57827
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
57828
|
+
bold: true,
|
|
57829
|
+
children: [
|
|
57830
|
+
"Release track ",
|
|
57831
|
+
name,
|
|
57832
|
+
" · ",
|
|
57833
|
+
item?.label
|
|
57834
|
+
]
|
|
57835
|
+
}, undefined, true, undefined, this),
|
|
57836
|
+
choices ? /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(SelectList, {
|
|
57837
|
+
options: choices,
|
|
57838
|
+
value: selected ? trackEditorValue(selected, field) : choices[0].value,
|
|
57839
|
+
onSelect: (value) => {
|
|
57840
|
+
dispatch({
|
|
57841
|
+
type: "workspaceTrackSet",
|
|
57842
|
+
name,
|
|
57843
|
+
field,
|
|
57844
|
+
value
|
|
57845
|
+
});
|
|
57846
|
+
setMode("trackEdit");
|
|
57847
|
+
}
|
|
57848
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(TextInput, {
|
|
57849
|
+
defaultValue: selected ? trackEditorValue(selected, field) : "",
|
|
57850
|
+
onSubmit: (value) => {
|
|
57851
|
+
dispatch({
|
|
57852
|
+
type: "workspaceTrackSet",
|
|
57853
|
+
name,
|
|
57854
|
+
field,
|
|
57855
|
+
value
|
|
57856
|
+
});
|
|
57857
|
+
setMode("trackEdit");
|
|
57858
|
+
}
|
|
57859
|
+
}, undefined, false, undefined, this),
|
|
57860
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
57861
|
+
dimColor: true,
|
|
57862
|
+
children: "Lists use comma-separated values · Enter to save · Esc Back"
|
|
57863
|
+
}, undefined, false, undefined, this)
|
|
57864
|
+
]
|
|
57865
|
+
}, undefined, true, undefined, this);
|
|
57866
|
+
}
|
|
57867
|
+
const options = [...TRACK_FIELDS, { label: "Done editing", value: "done" }];
|
|
57868
|
+
return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
|
|
57869
|
+
flexDirection: "column",
|
|
57870
|
+
gap: 1,
|
|
57871
|
+
children: [
|
|
57872
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
57873
|
+
bold: true,
|
|
57874
|
+
children: [
|
|
57875
|
+
"Edit release track · ",
|
|
57876
|
+
name
|
|
57877
|
+
]
|
|
57878
|
+
}, undefined, true, undefined, this),
|
|
57879
|
+
TRACK_FIELDS.map((item) => /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
57880
|
+
dimColor: true,
|
|
57881
|
+
children: [
|
|
57882
|
+
item.label,
|
|
57883
|
+
": ",
|
|
57884
|
+
selected ? trackEditorValue(selected, item.value) || "unset" : ""
|
|
57885
|
+
]
|
|
57886
|
+
}, item.value, true, undefined, this)),
|
|
57887
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(SelectList, {
|
|
57888
|
+
options,
|
|
57889
|
+
value: "done",
|
|
57890
|
+
onSelect: (value) => {
|
|
57891
|
+
if (value === "done")
|
|
57892
|
+
setMode("tracks");
|
|
57893
|
+
else {
|
|
57894
|
+
setField(value);
|
|
57895
|
+
setMode("trackValue");
|
|
57896
|
+
}
|
|
57897
|
+
}
|
|
57898
|
+
}, undefined, false, undefined, this)
|
|
57899
|
+
]
|
|
57900
|
+
}, undefined, true, undefined, this);
|
|
57901
|
+
}
|
|
57902
|
+
const options = [
|
|
57903
|
+
...WORKSPACE_ADVANCED_FIELDS,
|
|
57904
|
+
{ label: "Manage profiles", value: "profiles" },
|
|
57905
|
+
{ label: "Manage release tracks", value: "tracks" },
|
|
57906
|
+
{ label: "Save workspace settings", value: "save" }
|
|
57907
|
+
];
|
|
57908
|
+
return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
|
|
57909
|
+
flexDirection: "column",
|
|
57910
|
+
gap: 1,
|
|
57911
|
+
children: [
|
|
57912
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
57913
|
+
bold: true,
|
|
57914
|
+
children: [
|
|
57915
|
+
"Advanced workspace settings · ",
|
|
57916
|
+
workspace.name
|
|
57917
|
+
]
|
|
57918
|
+
}, undefined, true, undefined, this),
|
|
57919
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
57920
|
+
dimColor: true,
|
|
57921
|
+
children: "Choose a setting to edit. Lists use comma-separated values; blank clears an override."
|
|
57922
|
+
}, undefined, false, undefined, this),
|
|
57923
|
+
[...WORKSPACE_ADVANCED_FIELDS].map(({ label, value }) => /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
57924
|
+
dimColor: true,
|
|
57925
|
+
children: [
|
|
57926
|
+
label,
|
|
57927
|
+
": ",
|
|
57928
|
+
workspaceEditorValue(workspace, value) || "inherited / unset"
|
|
57929
|
+
]
|
|
57930
|
+
}, value, true, undefined, this)),
|
|
57931
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(SelectList, {
|
|
57932
|
+
options,
|
|
57933
|
+
value: "save",
|
|
57934
|
+
onSelect: (value) => {
|
|
57935
|
+
if (value === "save")
|
|
57936
|
+
dispatch({ type: "workspaceSave" });
|
|
57937
|
+
else if (value === "profiles")
|
|
57938
|
+
setMode("profiles");
|
|
57939
|
+
else if (value === "tracks")
|
|
57940
|
+
setMode("tracks");
|
|
57941
|
+
else
|
|
57942
|
+
dispatch({ type: "workspaceAdvancedSelect", field: value });
|
|
57943
|
+
}
|
|
57944
|
+
}, undefined, false, undefined, this)
|
|
57945
|
+
]
|
|
57946
|
+
}, undefined, true, undefined, this);
|
|
57947
|
+
}
|
|
56607
57948
|
function effectivePolicy(values) {
|
|
56608
57949
|
return mergePreset(values.branchPreset, {
|
|
56609
57950
|
allowed: parseList(values.branchAllowed),
|
|
@@ -56815,6 +58156,8 @@ function describeMutation(m) {
|
|
|
56815
58156
|
return `+ register ${m.platform}: ${m.path}`;
|
|
56816
58157
|
case "install-adapter":
|
|
56817
58158
|
return `+ copy adapter ${m.platform}: ${m.path}`;
|
|
58159
|
+
case "install-host":
|
|
58160
|
+
return `+ install ${m.platform}: ${m.commands.map((command) => command.command).join(", ")}`;
|
|
56818
58161
|
case "set-token-path":
|
|
56819
58162
|
return `+ change ${m.key} in ${m.path} → ${m.value}`;
|
|
56820
58163
|
}
|
|
@@ -56870,28 +58213,21 @@ function Screen({
|
|
|
56870
58213
|
children: "Step 1 — Platforms"
|
|
56871
58214
|
}, undefined, false, undefined, this),
|
|
56872
58215
|
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
56873
|
-
children: "
|
|
58216
|
+
children: "Choose the detected tools where Workit should be configured."
|
|
56874
58217
|
}, undefined, false, undefined, this),
|
|
56875
58218
|
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
56876
58219
|
dimColor: true,
|
|
56877
|
-
children: "
|
|
58220
|
+
children: "Use Space to toggle, or choose Select all available / Clear all."
|
|
56878
58221
|
}, undefined, false, undefined, this),
|
|
56879
|
-
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(
|
|
56880
|
-
|
|
56881
|
-
|
|
58222
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(HostPicker, {
|
|
58223
|
+
detection,
|
|
58224
|
+
selected: draft.values.platforms,
|
|
56882
58225
|
onChange: (values) => dispatch({ type: "set", field: "platforms", value: values }),
|
|
56883
58226
|
onSubmit: (values) => {
|
|
56884
58227
|
dispatch({ type: "set", field: "platforms", value: values });
|
|
56885
58228
|
dispatch({ type: "next" });
|
|
56886
58229
|
}
|
|
56887
58230
|
}, undefined, false, undefined, this),
|
|
56888
|
-
externalHostGuidance(detection).map((guidance) => /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
56889
|
-
children: guidance
|
|
56890
|
-
}, guidance, false, undefined, this)),
|
|
56891
|
-
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
56892
|
-
dimColor: true,
|
|
56893
|
-
children: "For legacy installations, use `workit cutover` to preview migration."
|
|
56894
|
-
}, undefined, false, undefined, this),
|
|
56895
58231
|
draft.errors.platforms && /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
56896
58232
|
color: "red",
|
|
56897
58233
|
children: draft.errors.platforms
|
|
@@ -57260,7 +58596,12 @@ function Screen({
|
|
|
57260
58596
|
})),
|
|
57261
58597
|
{ label: "Add workspace", value: "add" },
|
|
57262
58598
|
{ label: `Use current project (${base})`, value: "current" },
|
|
57263
|
-
{ label: "Done", value: "done" }
|
|
58599
|
+
{ label: "Done", value: "done" },
|
|
58600
|
+
{ label: "Advanced global commit policy", value: "global-commit" },
|
|
58601
|
+
...draft.values.workspaces.map((w, i) => ({
|
|
58602
|
+
label: `Advanced settings for ${w.name}`,
|
|
58603
|
+
value: `advanced:${i}`
|
|
58604
|
+
}))
|
|
57264
58605
|
];
|
|
57265
58606
|
return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
|
|
57266
58607
|
flexDirection: "column",
|
|
@@ -57300,6 +58641,10 @@ function Screen({
|
|
|
57300
58641
|
dispatch({ type: "workspaceEdit", index: Number(value.slice(5)) });
|
|
57301
58642
|
else if (value.startsWith("remove:"))
|
|
57302
58643
|
dispatch({ type: "workspaceRemove", index: Number(value.slice(7)) });
|
|
58644
|
+
else if (value.startsWith("advanced:"))
|
|
58645
|
+
dispatch({ type: "workspaceAdvancedOpen", index: Number(value.slice(9)) });
|
|
58646
|
+
else if (value === "global-commit")
|
|
58647
|
+
dispatch({ type: "globalCommitOpen" });
|
|
57303
58648
|
else if (value === "add")
|
|
57304
58649
|
dispatch({ type: "workspaceAdd" });
|
|
57305
58650
|
else if (value === "current")
|
|
@@ -57334,93 +58679,222 @@ function Screen({
|
|
|
57334
58679
|
onChange: (value) => dispatch({ type: "workspaceDraftName", value }),
|
|
57335
58680
|
onSubmit: () => dispatch({ type: "next" })
|
|
57336
58681
|
}, undefined, false, undefined, this),
|
|
57337
|
-
draft.errors.workspaceName && /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
57338
|
-
color: "red",
|
|
57339
|
-
children: draft.errors.workspaceName
|
|
58682
|
+
draft.errors.workspaceName && /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
58683
|
+
color: "red",
|
|
58684
|
+
children: draft.errors.workspaceName
|
|
58685
|
+
}, undefined, false, undefined, this),
|
|
58686
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
58687
|
+
dimColor: true,
|
|
58688
|
+
children: "Enter to continue · Esc Back"
|
|
58689
|
+
}, undefined, false, undefined, this)
|
|
58690
|
+
]
|
|
58691
|
+
}, undefined, true, undefined, this);
|
|
58692
|
+
case "workspaceGlob": {
|
|
58693
|
+
const glob = draft.workspaceDraft?.glob ?? "";
|
|
58694
|
+
return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
|
|
58695
|
+
flexDirection: "column",
|
|
58696
|
+
gap: 1,
|
|
58697
|
+
children: [
|
|
58698
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
58699
|
+
bold: true,
|
|
58700
|
+
children: "Step 5 — Workspaces · Pattern"
|
|
58701
|
+
}, undefined, false, undefined, this),
|
|
58702
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
58703
|
+
dimColor: true,
|
|
58704
|
+
children: "Workspace pattern (glob, e.g. /work/**):"
|
|
58705
|
+
}, undefined, false, undefined, this),
|
|
58706
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(TextInput, {
|
|
58707
|
+
placeholder: SCREEN_PLACEHOLDERS.workspaceGlob,
|
|
58708
|
+
defaultValue: glob,
|
|
58709
|
+
onChange: (value) => dispatch({ type: "workspaceDraftGlob", value }),
|
|
58710
|
+
onSubmit: () => dispatch({ type: "next" })
|
|
58711
|
+
}, undefined, false, undefined, this),
|
|
58712
|
+
glob.trim() !== "" && /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
|
|
58713
|
+
flexDirection: "column",
|
|
58714
|
+
gap: 0,
|
|
58715
|
+
children: [
|
|
58716
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
58717
|
+
bold: true,
|
|
58718
|
+
children: "Match preview (shared matcher):"
|
|
58719
|
+
}, undefined, false, undefined, this),
|
|
58720
|
+
workspacePreviewTargets(resolveBasePath(draft.values)).map((target) => {
|
|
58721
|
+
const matches = matchWorkspace(glob, target);
|
|
58722
|
+
return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
58723
|
+
color: matches ? "green" : "red",
|
|
58724
|
+
children: [
|
|
58725
|
+
matches ? "✓ matches" : "✗ no match",
|
|
58726
|
+
" ",
|
|
58727
|
+
target
|
|
58728
|
+
]
|
|
58729
|
+
}, target, true, undefined, this);
|
|
58730
|
+
})
|
|
58731
|
+
]
|
|
58732
|
+
}, undefined, true, undefined, this),
|
|
58733
|
+
draft.errors.workspaceGlob && /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
58734
|
+
color: "red",
|
|
58735
|
+
children: draft.errors.workspaceGlob
|
|
58736
|
+
}, undefined, false, undefined, this),
|
|
58737
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
58738
|
+
dimColor: true,
|
|
58739
|
+
children: "Enter to continue · Esc Back"
|
|
58740
|
+
}, undefined, false, undefined, this)
|
|
58741
|
+
]
|
|
58742
|
+
}, undefined, true, undefined, this);
|
|
58743
|
+
}
|
|
58744
|
+
case "workspaceProvider":
|
|
58745
|
+
return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
|
|
58746
|
+
flexDirection: "column",
|
|
58747
|
+
gap: 1,
|
|
58748
|
+
children: [
|
|
58749
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
58750
|
+
bold: true,
|
|
58751
|
+
children: "Step 5 — Workspaces · Provider"
|
|
58752
|
+
}, undefined, false, undefined, this),
|
|
58753
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
58754
|
+
dimColor: true,
|
|
58755
|
+
children: "Version control provider for this workspace:"
|
|
58756
|
+
}, undefined, false, undefined, this),
|
|
58757
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(SelectList, {
|
|
58758
|
+
options: VCS_PROVIDERS,
|
|
58759
|
+
value: draft.workspaceDraft?.vcs?.provider ?? "skip",
|
|
58760
|
+
onChange: (value) => dispatch({ type: "workspaceDraftProvider", value }),
|
|
58761
|
+
onSelect: (value) => {
|
|
58762
|
+
dispatch({ type: "workspaceDraftProvider", value });
|
|
58763
|
+
dispatch({ type: "workspaceSave" });
|
|
58764
|
+
}
|
|
58765
|
+
}, undefined, false, undefined, this),
|
|
58766
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
58767
|
+
dimColor: true,
|
|
58768
|
+
children: "Enter to save · b Back · Esc Cancel"
|
|
58769
|
+
}, undefined, false, undefined, this)
|
|
58770
|
+
]
|
|
58771
|
+
}, undefined, true, undefined, this);
|
|
58772
|
+
case "workspaceAdvanced": {
|
|
58773
|
+
return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(WorkspaceCollectionEditor, {
|
|
58774
|
+
draft,
|
|
58775
|
+
dispatch
|
|
58776
|
+
}, undefined, false, undefined, this);
|
|
58777
|
+
}
|
|
58778
|
+
case "workspaceAdvancedValue": {
|
|
58779
|
+
const field = draft.workspaceEditorField;
|
|
58780
|
+
const current = draft.workspaceDraft && field ? workspaceEditorValue(draft.workspaceDraft, field) : "";
|
|
58781
|
+
const label = WORKSPACE_ADVANCED_FIELDS.find((entry) => entry.value === field)?.label ?? "Setting";
|
|
58782
|
+
const choices = field ? enumFieldOptions(field) : null;
|
|
58783
|
+
const profileChoices = field === "defaultProfile" ? [
|
|
58784
|
+
{ label: "Inherit / no default profile", value: "" },
|
|
58785
|
+
...Object.keys(draft.workspaceDraft?.profiles ?? {}).map((name) => ({
|
|
58786
|
+
label: name,
|
|
58787
|
+
value: name
|
|
58788
|
+
}))
|
|
58789
|
+
] : null;
|
|
58790
|
+
return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
|
|
58791
|
+
flexDirection: "column",
|
|
58792
|
+
gap: 1,
|
|
58793
|
+
children: [
|
|
58794
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
58795
|
+
bold: true,
|
|
58796
|
+
children: [
|
|
58797
|
+
"Advanced workspace settings · ",
|
|
58798
|
+
label
|
|
58799
|
+
]
|
|
58800
|
+
}, undefined, true, undefined, this),
|
|
58801
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
58802
|
+
dimColor: true,
|
|
58803
|
+
children: "Leave empty to clear this override. Use comma-separated values for lists."
|
|
58804
|
+
}, undefined, false, undefined, this),
|
|
58805
|
+
profileChoices ? /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(SelectList, {
|
|
58806
|
+
options: profileChoices,
|
|
58807
|
+
value: current,
|
|
58808
|
+
onSelect: (value) => field && dispatch({ type: "workspaceAdvancedSet", field, value })
|
|
58809
|
+
}, undefined, false, undefined, this) : choices ? /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(SelectList, {
|
|
58810
|
+
options: choices,
|
|
58811
|
+
value: current || choices[0].value,
|
|
58812
|
+
onSelect: (value) => field && dispatch({ type: "workspaceAdvancedSet", field, value })
|
|
58813
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(TextInput, {
|
|
58814
|
+
defaultValue: current,
|
|
58815
|
+
onSubmit: (value) => field && dispatch({ type: "workspaceAdvancedSet", field, value })
|
|
58816
|
+
}, undefined, false, undefined, this),
|
|
58817
|
+
field?.endsWith("integration") && /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
58818
|
+
dimColor: true,
|
|
58819
|
+
children: "Enter pr or merge."
|
|
57340
58820
|
}, undefined, false, undefined, this),
|
|
57341
58821
|
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
57342
58822
|
dimColor: true,
|
|
57343
|
-
children: "Enter to
|
|
58823
|
+
children: "Enter to save · Esc Back"
|
|
57344
58824
|
}, undefined, false, undefined, this)
|
|
57345
58825
|
]
|
|
57346
58826
|
}, undefined, true, undefined, this);
|
|
57347
|
-
|
|
57348
|
-
|
|
58827
|
+
}
|
|
58828
|
+
case "globalCommitPolicy": {
|
|
58829
|
+
const options = [
|
|
58830
|
+
{ label: "Conventional commits", value: "conventional" },
|
|
58831
|
+
{ label: "Gitmoji", value: "gitmoji" },
|
|
58832
|
+
{ label: "Ticket prefix", value: "ticket-prefix" },
|
|
58833
|
+
{ label: "Freeform", value: "freeform" },
|
|
58834
|
+
{ label: "Custom pattern", value: "custom" },
|
|
58835
|
+
{ label: "Auto-detect", value: "auto" },
|
|
58836
|
+
{ label: "Edit custom pattern…", value: "pattern" },
|
|
58837
|
+
{ label: "Done", value: "done" }
|
|
58838
|
+
];
|
|
57349
58839
|
return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
|
|
57350
58840
|
flexDirection: "column",
|
|
57351
58841
|
gap: 1,
|
|
57352
58842
|
children: [
|
|
57353
58843
|
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
57354
58844
|
bold: true,
|
|
57355
|
-
children: "
|
|
58845
|
+
children: "Advanced global commit policy"
|
|
57356
58846
|
}, undefined, false, undefined, this),
|
|
57357
58847
|
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
57358
58848
|
dimColor: true,
|
|
57359
|
-
children: "
|
|
57360
|
-
}, undefined, false, undefined, this),
|
|
57361
|
-
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(TextInput, {
|
|
57362
|
-
placeholder: SCREEN_PLACEHOLDERS.workspaceGlob,
|
|
57363
|
-
defaultValue: glob,
|
|
57364
|
-
onChange: (value) => dispatch({ type: "workspaceDraftGlob", value }),
|
|
57365
|
-
onSubmit: () => dispatch({ type: "next" })
|
|
58849
|
+
children: "Default convention used when a workspace has no commit override."
|
|
57366
58850
|
}, undefined, false, undefined, this),
|
|
57367
|
-
|
|
57368
|
-
|
|
57369
|
-
gap: 0,
|
|
58851
|
+
draft.values.commitPolicy.pattern && /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
58852
|
+
dimColor: true,
|
|
57370
58853
|
children: [
|
|
57371
|
-
|
|
57372
|
-
|
|
57373
|
-
children: "Match preview (shared matcher):"
|
|
57374
|
-
}, undefined, false, undefined, this),
|
|
57375
|
-
workspacePreviewTargets(resolveBasePath(draft.values)).map((target) => {
|
|
57376
|
-
const matches = matchWorkspace(glob, target);
|
|
57377
|
-
return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
57378
|
-
color: matches ? "green" : "red",
|
|
57379
|
-
children: [
|
|
57380
|
-
matches ? "✓ matches" : "✗ no match",
|
|
57381
|
-
" ",
|
|
57382
|
-
target
|
|
57383
|
-
]
|
|
57384
|
-
}, target, true, undefined, this);
|
|
57385
|
-
})
|
|
58854
|
+
"Custom pattern: ",
|
|
58855
|
+
draft.values.commitPolicy.pattern
|
|
57386
58856
|
]
|
|
57387
58857
|
}, undefined, true, undefined, this),
|
|
57388
|
-
|
|
57389
|
-
|
|
57390
|
-
|
|
58858
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(SelectList, {
|
|
58859
|
+
options,
|
|
58860
|
+
value: draft.values.commitPolicy.preset,
|
|
58861
|
+
onSelect: (value) => {
|
|
58862
|
+
if (value === "pattern")
|
|
58863
|
+
dispatch({ type: "globalCommitEditPattern" });
|
|
58864
|
+
else if (value === "done")
|
|
58865
|
+
dispatch({ type: "back" });
|
|
58866
|
+
else
|
|
58867
|
+
dispatch({ type: "globalCommitPreset", value });
|
|
58868
|
+
}
|
|
57391
58869
|
}, undefined, false, undefined, this),
|
|
57392
58870
|
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
57393
58871
|
dimColor: true,
|
|
57394
|
-
children: "Enter to
|
|
58872
|
+
children: "Enter to select · b Back"
|
|
57395
58873
|
}, undefined, false, undefined, this)
|
|
57396
58874
|
]
|
|
57397
58875
|
}, undefined, true, undefined, this);
|
|
57398
58876
|
}
|
|
57399
|
-
case "
|
|
58877
|
+
case "globalCommitPattern":
|
|
57400
58878
|
return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
|
|
57401
58879
|
flexDirection: "column",
|
|
57402
58880
|
gap: 1,
|
|
57403
58881
|
children: [
|
|
57404
58882
|
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
57405
58883
|
bold: true,
|
|
57406
|
-
children: "
|
|
58884
|
+
children: "Advanced global commit policy · Custom pattern"
|
|
57407
58885
|
}, undefined, false, undefined, this),
|
|
57408
58886
|
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
57409
58887
|
dimColor: true,
|
|
57410
|
-
children: "
|
|
58888
|
+
children: "Regular expression matched against the commit subject line."
|
|
57411
58889
|
}, undefined, false, undefined, this),
|
|
57412
|
-
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(
|
|
57413
|
-
|
|
57414
|
-
|
|
57415
|
-
|
|
57416
|
-
onSelect: (value) => {
|
|
57417
|
-
dispatch({ type: "workspaceDraftProvider", value });
|
|
57418
|
-
dispatch({ type: "workspaceSave" });
|
|
57419
|
-
}
|
|
58890
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(TextInput, {
|
|
58891
|
+
defaultValue: draft.values.commitPolicy.pattern ?? "",
|
|
58892
|
+
onChange: (value) => dispatch({ type: "globalCommitPattern", value }),
|
|
58893
|
+
onSubmit: () => dispatch({ type: "globalCommitPatternDone" })
|
|
57420
58894
|
}, undefined, false, undefined, this),
|
|
57421
58895
|
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
57422
58896
|
dimColor: true,
|
|
57423
|
-
children: "Enter to save ·
|
|
58897
|
+
children: "Enter to save · Esc Back"
|
|
57424
58898
|
}, undefined, false, undefined, this)
|
|
57425
58899
|
]
|
|
57426
58900
|
}, undefined, true, undefined, this);
|
|
@@ -57494,6 +58968,36 @@ function Screen({
|
|
|
57494
58968
|
case "summary": {
|
|
57495
58969
|
const policy = effectivePolicy(draft.values);
|
|
57496
58970
|
const preview = buildSetupPreview(draft.values, { cwd: resolveBasePath(draft.values) });
|
|
58971
|
+
const policyPreview = (() => {
|
|
58972
|
+
try {
|
|
58973
|
+
const current = readConfig();
|
|
58974
|
+
const config = {
|
|
58975
|
+
...current,
|
|
58976
|
+
branchPolicy: mergePreset(draft.values.branchPreset, {
|
|
58977
|
+
allowed: parseList(draft.values.branchAllowed),
|
|
58978
|
+
protectedNames: parseList(draft.values.branchProtected)
|
|
58979
|
+
}, current),
|
|
58980
|
+
commitPolicy: draft.values.commitPolicy
|
|
58981
|
+
};
|
|
58982
|
+
const checkout = resolveBasePath(draft.values);
|
|
58983
|
+
const workspace = resolveWorkspaceFromEntries(checkout, draft.values.workspaces);
|
|
58984
|
+
const resolved = resolveWorkspacePolicy(config, workspace);
|
|
58985
|
+
if (resolved.status === "invalid")
|
|
58986
|
+
return { error: resolved.error };
|
|
58987
|
+
return {
|
|
58988
|
+
error: null,
|
|
58989
|
+
workspace: workspace?.name ?? null,
|
|
58990
|
+
branchSource: resolved.provenance.branchPolicy,
|
|
58991
|
+
commitSource: resolved.provenance.commitPolicy,
|
|
58992
|
+
target: resolved.branchPolicy.defaultTargetBranch,
|
|
58993
|
+
branchPreset: resolved.branchPolicy.preset,
|
|
58994
|
+
commitPreset: resolved.commitPolicy.preset
|
|
58995
|
+
};
|
|
58996
|
+
} catch (error) {
|
|
58997
|
+
return { error: error instanceof Error ? error.message : String(error) };
|
|
58998
|
+
}
|
|
58999
|
+
})();
|
|
59000
|
+
const canApply = preview.ok && policyPreview.error === null;
|
|
57497
59001
|
return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
|
|
57498
59002
|
flexDirection: "column",
|
|
57499
59003
|
gap: 1,
|
|
@@ -57544,6 +59048,52 @@ function Screen({
|
|
|
57544
59048
|
policy.protected.join(", ")
|
|
57545
59049
|
]
|
|
57546
59050
|
}, undefined, true, undefined, this),
|
|
59051
|
+
policyPreview.error === null ? /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
|
|
59052
|
+
flexDirection: "column",
|
|
59053
|
+
gap: 0,
|
|
59054
|
+
children: [
|
|
59055
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
59056
|
+
children: [
|
|
59057
|
+
"Sample checkout: ",
|
|
59058
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
59059
|
+
color: "green",
|
|
59060
|
+
children: resolveBasePath(draft.values)
|
|
59061
|
+
}, undefined, false, undefined, this),
|
|
59062
|
+
policyPreview.workspace ? ` · workspace ${policyPreview.workspace}` : " · no matching workspace"
|
|
59063
|
+
]
|
|
59064
|
+
}, undefined, true, undefined, this),
|
|
59065
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
59066
|
+
children: [
|
|
59067
|
+
"Effective branch policy: ",
|
|
59068
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
59069
|
+
color: "green",
|
|
59070
|
+
children: policyPreview.branchPreset
|
|
59071
|
+
}, undefined, false, undefined, this),
|
|
59072
|
+
" · target ",
|
|
59073
|
+
policyPreview.target,
|
|
59074
|
+
" · source ",
|
|
59075
|
+
policyPreview.branchSource
|
|
59076
|
+
]
|
|
59077
|
+
}, undefined, true, undefined, this),
|
|
59078
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
59079
|
+
children: [
|
|
59080
|
+
"Effective commit policy: ",
|
|
59081
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
59082
|
+
color: "green",
|
|
59083
|
+
children: policyPreview.commitPreset
|
|
59084
|
+
}, undefined, false, undefined, this),
|
|
59085
|
+
" · source ",
|
|
59086
|
+
policyPreview.commitSource
|
|
59087
|
+
]
|
|
59088
|
+
}, undefined, true, undefined, this)
|
|
59089
|
+
]
|
|
59090
|
+
}, undefined, true, undefined, this) : /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
59091
|
+
color: "red",
|
|
59092
|
+
children: [
|
|
59093
|
+
"Policy preview failed: ",
|
|
59094
|
+
policyPreview.error
|
|
59095
|
+
]
|
|
59096
|
+
}, undefined, true, undefined, this),
|
|
57547
59097
|
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
57548
59098
|
children: [
|
|
57549
59099
|
"YouTrack base URL:",
|
|
@@ -57592,7 +59142,7 @@ function Screen({
|
|
|
57592
59142
|
}, o.envKey, true, undefined, this))
|
|
57593
59143
|
]
|
|
57594
59144
|
}, undefined, true, undefined, this),
|
|
57595
|
-
|
|
59145
|
+
canApply ? /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
|
|
57596
59146
|
flexDirection: "column",
|
|
57597
59147
|
gap: 0,
|
|
57598
59148
|
children: [
|
|
@@ -57600,9 +59150,9 @@ function Screen({
|
|
|
57600
59150
|
bold: true,
|
|
57601
59151
|
children: "Will apply:"
|
|
57602
59152
|
}, undefined, false, undefined, this),
|
|
57603
|
-
preview.mutations.map((m) => /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
59153
|
+
preview.mutations.map((m, index) => /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
57604
59154
|
children: describeMutation(m)
|
|
57605
|
-
}, `${m.type}:${
|
|
59155
|
+
}, `${m.type}:${index}`, false, undefined, this)),
|
|
57606
59156
|
preview.preserved.map((p) => /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
57607
59157
|
color: "green",
|
|
57608
59158
|
children: [
|
|
@@ -57631,7 +59181,7 @@ function Screen({
|
|
|
57631
59181
|
}, undefined, false, undefined, this)
|
|
57632
59182
|
]
|
|
57633
59183
|
}, undefined, true, undefined, this),
|
|
57634
|
-
|
|
59184
|
+
canApply && /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(ConfirmInput, {
|
|
57635
59185
|
defaultChoice: "confirm",
|
|
57636
59186
|
submitOnEnter: false,
|
|
57637
59187
|
onConfirm: () => dispatch({ type: "apply" }),
|
|
@@ -57639,7 +59189,7 @@ function Screen({
|
|
|
57639
59189
|
}, undefined, false, undefined, this),
|
|
57640
59190
|
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
57641
59191
|
dimColor: true,
|
|
57642
|
-
children:
|
|
59192
|
+
children: canApply ? "y to apply · b Back · Esc Cancel" : "b Back · Esc Cancel"
|
|
57643
59193
|
}, undefined, false, undefined, this)
|
|
57644
59194
|
]
|
|
57645
59195
|
}, undefined, true, undefined, this);
|
|
@@ -57658,7 +59208,7 @@ function Screen({
|
|
|
57658
59208
|
|
|
57659
59209
|
// packages/workit-core/src/core/logger.ts
|
|
57660
59210
|
import { appendFileSync, mkdirSync as mkdirSync6, readdirSync as readdirSync6, unlinkSync as unlinkSync4 } from "node:fs";
|
|
57661
|
-
import
|
|
59211
|
+
import os10 from "node:os";
|
|
57662
59212
|
import path17 from "node:path";
|
|
57663
59213
|
var REDACTED = "[REDACTED]";
|
|
57664
59214
|
var DEFAULT_MAX_RATE = 20;
|
|
@@ -57713,10 +59263,10 @@ var resolveStateDir = () => {
|
|
|
57713
59263
|
const override = process.env.WORKFLOW_TOOLKIT_STATE;
|
|
57714
59264
|
if (override)
|
|
57715
59265
|
return override;
|
|
57716
|
-
const home =
|
|
59266
|
+
const home = os10.homedir();
|
|
57717
59267
|
if (process.env.XDG_STATE_HOME)
|
|
57718
59268
|
return path17.join(process.env.XDG_STATE_HOME, "workit");
|
|
57719
|
-
switch (
|
|
59269
|
+
switch (os10.platform()) {
|
|
57720
59270
|
case "darwin":
|
|
57721
59271
|
return path17.join(home, "Library", "Application Support", "workit");
|
|
57722
59272
|
case "win32":
|
|
@@ -57725,7 +59275,7 @@ var resolveStateDir = () => {
|
|
|
57725
59275
|
return path17.join(process.env.HOME ?? home, ".local", "state", "workit");
|
|
57726
59276
|
}
|
|
57727
59277
|
};
|
|
57728
|
-
var homePattern = new RegExp(`${escapeRegExp2(
|
|
59278
|
+
var homePattern = new RegExp(`${escapeRegExp2(os10.homedir())}(?=[/\\\\]|$)|\\$HOME(?=[/\\\\]|$)`, "g");
|
|
57729
59279
|
var applyPatterns = (value) => {
|
|
57730
59280
|
let out = value;
|
|
57731
59281
|
out = out.replace(SECRET_VALUE, REDACTED);
|
|
@@ -58115,11 +59665,11 @@ async function runCutoverCommand(argv, deps = {}) {
|
|
|
58115
59665
|
}
|
|
58116
59666
|
|
|
58117
59667
|
// packages/workit-cli/src/task.ts
|
|
58118
|
-
import { readFileSync as
|
|
59668
|
+
import { readFileSync as readFileSync20 } from "node:fs";
|
|
58119
59669
|
import { createInterface as createInterface2 } from "node:readline/promises";
|
|
58120
59670
|
|
|
58121
59671
|
// packages/workit-core/src/core.ts
|
|
58122
|
-
import { spawnSync as
|
|
59672
|
+
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
58123
59673
|
import { existsSync as existsSync17, realpathSync as realpathSync10 } from "node:fs";
|
|
58124
59674
|
import path27 from "node:path";
|
|
58125
59675
|
|
|
@@ -59792,7 +61342,7 @@ function assertProductWriteAllowed(input) {
|
|
|
59792
61342
|
// packages/workit-core/src/core/task-evaluation.ts
|
|
59793
61343
|
import { createHash as createHash10 } from "node:crypto";
|
|
59794
61344
|
import * as fs10 from "node:fs";
|
|
59795
|
-
import { spawnSync as
|
|
61345
|
+
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
59796
61346
|
import path25 from "node:path";
|
|
59797
61347
|
|
|
59798
61348
|
// packages/workit-core/src/core/authority.ts
|
|
@@ -59802,11 +61352,11 @@ import path24 from "node:path";
|
|
|
59802
61352
|
|
|
59803
61353
|
// packages/workit-core/src/core/auto-approval.ts
|
|
59804
61354
|
import { createHash as createHash8 } from "node:crypto";
|
|
59805
|
-
import { readFileSync as
|
|
61355
|
+
import { readFileSync as readFileSync16, realpathSync as realpathSync5 } from "node:fs";
|
|
59806
61356
|
import path23 from "node:path";
|
|
59807
61357
|
|
|
59808
61358
|
// packages/workit-core/src/core/branch.ts
|
|
59809
|
-
import { existsSync as existsSync15, mkdirSync as mkdirSync8, readFileSync as
|
|
61359
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync8, readFileSync as readFileSync15, writeFileSync as writeFileSync8 } from "node:fs";
|
|
59810
61360
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
59811
61361
|
import { createHash as createHash7 } from "node:crypto";
|
|
59812
61362
|
import path22 from "node:path";
|
|
@@ -59911,11 +61461,11 @@ var gitContext = (workspaceRoot, paths = []) => {
|
|
|
59911
61461
|
// packages/workit-core/src/core/vcs-config.ts
|
|
59912
61462
|
import fs8 from "node:fs";
|
|
59913
61463
|
import path21 from "node:path";
|
|
59914
|
-
import { spawnSync as
|
|
61464
|
+
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
59915
61465
|
var vcsConfigPath = () => process.env.WORKFLOW_VCS_CONFIG ?? path21.join(configDir(), "vcs.json");
|
|
59916
61466
|
var vcsCwd = (cwd) => cwd ?? process.env.WORKFLOW_WORKSPACE_ROOT ?? process.cwd();
|
|
59917
61467
|
var remoteProvider = (cwd) => {
|
|
59918
|
-
const r =
|
|
61468
|
+
const r = spawnSync4("git", ["remote", "get-url", "origin"], { cwd, encoding: "utf8" });
|
|
59919
61469
|
if (r.status !== 0)
|
|
59920
61470
|
return null;
|
|
59921
61471
|
const url = (r.stdout ?? "").trim();
|
|
@@ -59952,7 +61502,7 @@ var remoteEndpoint = (remote) => {
|
|
|
59952
61502
|
var configuredSshEndpoint = (host) => {
|
|
59953
61503
|
if (host.startsWith("-"))
|
|
59954
61504
|
return null;
|
|
59955
|
-
const resolved =
|
|
61505
|
+
const resolved = spawnSync4("ssh", ["-G", host], {
|
|
59956
61506
|
encoding: "utf8",
|
|
59957
61507
|
timeout: 5000,
|
|
59958
61508
|
maxBuffer: 1024 * 1024,
|
|
@@ -60031,8 +61581,8 @@ function vcsConfig(mode, cwd) {
|
|
|
60031
61581
|
const hasWorkspacePolicy = typeof wp.preset === "string" && Object.hasOwn(PRESETS, wp.preset);
|
|
60032
61582
|
const policyDefault = resolveBranchPolicyFor(root).defaultTargetBranch;
|
|
60033
61583
|
const defaultTarget = String(wsVcs.defaultTargetBranch ?? (hasWorkspacePolicy ? policyDefault : cfg.defaultTargetBranch ?? policyDefault) ?? "develop");
|
|
60034
|
-
const linkIssues =
|
|
60035
|
-
const youtrackBaseUrl =
|
|
61584
|
+
const linkIssues = typeof wsYt.link_issues === "boolean" ? wsYt.link_issues : null;
|
|
61585
|
+
const youtrackBaseUrl = typeof wsYt.baseUrl === "string" ? wsYt.baseUrl : null;
|
|
60036
61586
|
let issuesProvider = null;
|
|
60037
61587
|
let linkOnPr = null;
|
|
60038
61588
|
if (provider === "github" && typeof wsIssues.provider === "string" && wsIssues.provider.toLowerCase() === "github") {
|
|
@@ -60103,7 +61653,7 @@ function vcsCliIdentity(cwd) {
|
|
|
60103
61653
|
PATH: process.env.PATH ?? "",
|
|
60104
61654
|
...provider === "github" ? { GH_HOST: host } : { GITLAB_HOST: host }
|
|
60105
61655
|
};
|
|
60106
|
-
const result =
|
|
61656
|
+
const result = spawnSync4(bin, ["api", "user"], {
|
|
60107
61657
|
cwd: root,
|
|
60108
61658
|
encoding: "utf8",
|
|
60109
61659
|
env
|
|
@@ -60145,7 +61695,7 @@ function mergedPrStyle(limit = 6, cwd) {
|
|
|
60145
61695
|
`).filter((l) => l.startsWith("## ")).map((l) => l.trim()),
|
|
60146
61696
|
descriptionPreview: desc.slice(0, 600)
|
|
60147
61697
|
});
|
|
60148
|
-
const remoteResult =
|
|
61698
|
+
const remoteResult = spawnSync4("git", ["remote", "get-url", "--push", "--all", "origin"], {
|
|
60149
61699
|
cwd,
|
|
60150
61700
|
encoding: "utf8"
|
|
60151
61701
|
});
|
|
@@ -60161,7 +61711,7 @@ function mergedPrStyle(limit = 6, cwd) {
|
|
|
60161
61711
|
if (!hostingApiHostMatches(remote, host))
|
|
60162
61712
|
return { ok: false, error: "PR style target does not match the provider host" };
|
|
60163
61713
|
if (provider === "gitlab") {
|
|
60164
|
-
const run = (args) =>
|
|
61714
|
+
const run = (args) => spawnSync4("glab", ["api", ...args], {
|
|
60165
61715
|
cwd,
|
|
60166
61716
|
encoding: "utf8",
|
|
60167
61717
|
env
|
|
@@ -60181,7 +61731,7 @@ function mergedPrStyle(limit = 6, cwd) {
|
|
|
60181
61731
|
});
|
|
60182
61732
|
}
|
|
60183
61733
|
} else if (provider === "github") {
|
|
60184
|
-
const r =
|
|
61734
|
+
const r = spawnSync4("gh", [
|
|
60185
61735
|
"pr",
|
|
60186
61736
|
"list",
|
|
60187
61737
|
"--repo",
|
|
@@ -60454,7 +62004,7 @@ var branchSetup = ({
|
|
|
60454
62004
|
};
|
|
60455
62005
|
const readManifest = () => {
|
|
60456
62006
|
try {
|
|
60457
|
-
return JSON.parse(
|
|
62007
|
+
return JSON.parse(readFileSync15(manifestPath, "utf8"));
|
|
60458
62008
|
} catch {
|
|
60459
62009
|
return {};
|
|
60460
62010
|
}
|
|
@@ -60650,7 +62200,7 @@ var OPERATION_CLASS = {
|
|
|
60650
62200
|
var operationAutoClass = (operation) => typeof operation === "string" ? OPERATION_CLASS[operation] ?? null : null;
|
|
60651
62201
|
var digestOf = (configDirPath) => {
|
|
60652
62202
|
try {
|
|
60653
|
-
const raw =
|
|
62203
|
+
const raw = readFileSync16(`${configDirPath}/workspaces.json`, "utf8");
|
|
60654
62204
|
return createHash8("sha256").update(raw).digest("hex");
|
|
60655
62205
|
} catch {
|
|
60656
62206
|
return null;
|
|
@@ -61458,7 +63008,7 @@ var compareCodeUnits2 = (left, right) => {
|
|
|
61458
63008
|
return left.length - right.length;
|
|
61459
63009
|
};
|
|
61460
63010
|
var gitPaths = (root) => {
|
|
61461
|
-
const result =
|
|
63011
|
+
const result = spawnSync5("git", ["ls-files", "-z", "--cached", "--others", "--exclude-standard"], {
|
|
61462
63012
|
cwd: root,
|
|
61463
63013
|
encoding: "buffer"
|
|
61464
63014
|
});
|
|
@@ -61471,7 +63021,7 @@ var gitPaths = (root) => {
|
|
|
61471
63021
|
};
|
|
61472
63022
|
}
|
|
61473
63023
|
const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path25.sep).join("/")) : [];
|
|
61474
|
-
const stagedDeleted =
|
|
63024
|
+
const stagedDeleted = spawnSync5("git", ["diff", "--cached", "--name-only", "--diff-filter=D", "-z"], { cwd: root, encoding: "buffer" });
|
|
61475
63025
|
if (stagedDeleted.status !== 0) {
|
|
61476
63026
|
const stderr = stagedDeleted.stderr?.toString("utf8") ?? "";
|
|
61477
63027
|
if (!/not a git repository/i.test(stderr))
|
|
@@ -61602,7 +63152,7 @@ function captureCandidate(root, scope, environment = []) {
|
|
|
61602
63152
|
const values = supplied.sort((left, right) => compareCodeUnits2(left.name, right.name)).map(({ name, value }) => ({ name, value, refs: [] }));
|
|
61603
63153
|
if (values.some(({ value }) => value === null))
|
|
61604
63154
|
completeness = "uncertain";
|
|
61605
|
-
const headResult =
|
|
63155
|
+
const headResult = spawnSync5("git", ["rev-parse", "HEAD"], { cwd: checkout, encoding: "utf8" });
|
|
61606
63156
|
if (headResult.status !== 0 && !/not a git repository/i.test(headResult.stderr ?? ""))
|
|
61607
63157
|
completeness = "uncertain";
|
|
61608
63158
|
const head = headResult.status === 0 ? headResult.stdout.trim() : null;
|
|
@@ -61990,6 +63540,13 @@ var compactText = (value, limit) => value === null ? null : value.replace(privat
|
|
|
61990
63540
|
return `${match.slice(0, space)} <redacted>`;
|
|
61991
63541
|
}).slice(0, limit);
|
|
61992
63542
|
var compactBytes = (value) => new TextEncoder().encode(value).byteLength;
|
|
63543
|
+
var compactTimestamp = (value) => `${value.slice(0, 19)}.${value.slice(20, -1).padEnd(9, "0")}`;
|
|
63544
|
+
var compactDecisionChoice = (entry) => {
|
|
63545
|
+
const stated = entry.data.binding.statedChoice?.text;
|
|
63546
|
+
const approved = entry.data.response === "approved" ? entry.data.binding.approvedContent : "";
|
|
63547
|
+
const source = stated?.trim() || approved.trim() || null;
|
|
63548
|
+
return compactText(source, COMPACT_TEXT_BYTES);
|
|
63549
|
+
};
|
|
61993
63550
|
var compactReference = (ref) => {
|
|
61994
63551
|
if (ref.kind === "file")
|
|
61995
63552
|
return {
|
|
@@ -62005,11 +63562,18 @@ var compactReference = (ref) => {
|
|
|
62005
63562
|
return { kind: ref.kind };
|
|
62006
63563
|
};
|
|
62007
63564
|
function compactTaskContext(view) {
|
|
62008
|
-
const decisions = view.task.decisions.slice().sort((left, right) =>
|
|
63565
|
+
const decisions = view.task.decisions.slice().sort((left, right) => {
|
|
63566
|
+
const leftAt = compactTimestamp(left.recordedAt);
|
|
63567
|
+
const rightAt = compactTimestamp(right.recordedAt);
|
|
63568
|
+
if (leftAt !== rightAt)
|
|
63569
|
+
return leftAt > rightAt ? -1 : 1;
|
|
63570
|
+
return left.id < right.id ? -1 : left.id > right.id ? 1 : 0;
|
|
63571
|
+
}).slice(0, COMPACT_MAX_ITEMS).map((entry) => ({
|
|
62009
63572
|
id: entry.id,
|
|
62010
63573
|
purpose: entry.data.purpose,
|
|
62011
63574
|
status: entry.data.response,
|
|
62012
63575
|
digest: entry.data.digest,
|
|
63576
|
+
choice: compactDecisionChoice(entry) || `task.inspect taskId=${view.task.id} view=full; decision=${entry.id}`,
|
|
62013
63577
|
references: entry.data.binding.contentRefs.slice(0, 1).map(compactReference)
|
|
62014
63578
|
}));
|
|
62015
63579
|
const methods = view.task.policy ? selectMethods(view.task.policy, view.capabilities).map((method) => ({
|
|
@@ -65076,7 +66640,7 @@ function resolveInside(root, candidate) {
|
|
|
65076
66640
|
}
|
|
65077
66641
|
function run2(root, executable, args, env = {}) {
|
|
65078
66642
|
const cwd = realpathSync10(root);
|
|
65079
|
-
const result =
|
|
66643
|
+
const result = spawnSync6(executable, args, {
|
|
65080
66644
|
cwd,
|
|
65081
66645
|
encoding: "utf8",
|
|
65082
66646
|
env: { ...process.env, ...env }
|
|
@@ -65092,7 +66656,7 @@ function run2(root, executable, args, env = {}) {
|
|
|
65092
66656
|
// packages/workit-core/src/core/pr-create.ts
|
|
65093
66657
|
import fs11 from "node:fs";
|
|
65094
66658
|
import path28 from "node:path";
|
|
65095
|
-
import { spawnSync as
|
|
66659
|
+
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
65096
66660
|
import { pathToFileURL } from "node:url";
|
|
65097
66661
|
var remoteRepoPath = (remote) => {
|
|
65098
66662
|
const raw = remote.trim();
|
|
@@ -65194,11 +66758,11 @@ function whichOnPath(tool) {
|
|
|
65194
66758
|
}
|
|
65195
66759
|
var hostingCliAvailable = (provider) => whichOnPath(provider === "gitlab" ? "glab" : "gh") !== null;
|
|
65196
66760
|
function repoRoot2(cwd) {
|
|
65197
|
-
const result =
|
|
66761
|
+
const result = spawnSync7("git", ["rev-parse", "--show-toplevel"], { cwd, encoding: "utf8" });
|
|
65198
66762
|
return result.status === 0 ? (result.stdout ?? "").trim() : cwd;
|
|
65199
66763
|
}
|
|
65200
66764
|
var pushRemote = (cwd) => {
|
|
65201
|
-
const result =
|
|
66765
|
+
const result = spawnSync7("git", ["remote", "get-url", "--push", "--all", "origin"], {
|
|
65202
66766
|
cwd,
|
|
65203
66767
|
encoding: "utf8"
|
|
65204
66768
|
});
|
|
@@ -65258,7 +66822,7 @@ var pushTargetIsStable = (cwd, remote) => {
|
|
|
65258
66822
|
const target = safePushUrl(remote);
|
|
65259
66823
|
if (!target)
|
|
65260
66824
|
return false;
|
|
65261
|
-
const result =
|
|
66825
|
+
const result = spawnSync7("git", ["config", "--get-regexp", "^url\\..*\\.(insteadof|pushinsteadof)$"], { cwd, encoding: "utf8" });
|
|
65262
66826
|
if (result.status !== 0 && result.status !== 1)
|
|
65263
66827
|
return false;
|
|
65264
66828
|
const prefixes = (result.stdout ?? "").split(/\r?\n/u).map((line) => line.trim().slice(line.trim().indexOf(" ") + 1)).filter(Boolean);
|
|
@@ -65306,12 +66870,12 @@ function prCreate(env, cwd) {
|
|
|
65306
66870
|
const resolvedDefault = String(cfg.defaultTargetBranch ?? policy.defaultTargetBranch ?? "develop");
|
|
65307
66871
|
const target = targetOverride || resolvedDefault;
|
|
65308
66872
|
const title = String(env.WF_PR_TITLE ?? "");
|
|
65309
|
-
const br =
|
|
66873
|
+
const br = spawnSync7("git", ["rev-parse", "--abbrev-ref", "HEAD"], {
|
|
65310
66874
|
cwd: root,
|
|
65311
66875
|
encoding: "utf8"
|
|
65312
66876
|
});
|
|
65313
66877
|
const branch = br.status === 0 ? (br.stdout ?? "").trim() : "";
|
|
65314
|
-
const sourceResult = branch ?
|
|
66878
|
+
const sourceResult = branch ? spawnSync7("git", ["rev-parse", "--verify", `refs/heads/${branch}`], {
|
|
65315
66879
|
cwd: root,
|
|
65316
66880
|
encoding: "utf8"
|
|
65317
66881
|
}) : null;
|
|
@@ -65320,7 +66884,7 @@ function prCreate(env, cwd) {
|
|
|
65320
66884
|
return { error: "approved PR source branch and commit are incomplete" };
|
|
65321
66885
|
if (env.WORKIT_EXPECTED_SOURCE_BRANCH && env.WORKIT_EXPECTED_SOURCE_BRANCH !== branch || env.WORKIT_EXPECTED_SOURCE_COMMIT && env.WORKIT_EXPECTED_SOURCE_COMMIT !== sourceCommit)
|
|
65322
66886
|
return { error: "approved PR source branch or commit changed before execution" };
|
|
65323
|
-
const mergeBaseResult = policy.integration === "merge" ?
|
|
66887
|
+
const mergeBaseResult = policy.integration === "merge" ? spawnSync7("git", ["rev-parse", "--verify", `refs/heads/${target}`], {
|
|
65324
66888
|
cwd: root,
|
|
65325
66889
|
encoding: "utf8"
|
|
65326
66890
|
}) : null;
|
|
@@ -65336,7 +66900,7 @@ function prCreate(env, cwd) {
|
|
|
65336
66900
|
targetBranch: target,
|
|
65337
66901
|
stderr: "source or target branch commit could not be resolved"
|
|
65338
66902
|
};
|
|
65339
|
-
const merge =
|
|
66903
|
+
const merge = spawnSync7("git", ["merge", "--no-ff", sourceCommit, "-m", title], {
|
|
65340
66904
|
cwd: root,
|
|
65341
66905
|
encoding: "utf8"
|
|
65342
66906
|
});
|
|
@@ -65347,16 +66911,16 @@ function prCreate(env, cwd) {
|
|
|
65347
66911
|
targetBranch: target,
|
|
65348
66912
|
stderr: (merge.stderr ?? "").slice(0, 800)
|
|
65349
66913
|
};
|
|
65350
|
-
const mergedCommit =
|
|
66914
|
+
const mergedCommit = spawnSync7("git", ["rev-parse", "HEAD"], {
|
|
65351
66915
|
cwd: root,
|
|
65352
66916
|
encoding: "utf8"
|
|
65353
66917
|
});
|
|
65354
66918
|
if (mergedCommit.status !== 0)
|
|
65355
66919
|
return { error: "merge commit could not be resolved", mode: "merge" };
|
|
65356
|
-
const updateTarget =
|
|
66920
|
+
const updateTarget = spawnSync7("git", ["update-ref", `refs/heads/${target}`, mergedCommit.stdout.trim(), mergeBaseCommit], { cwd: root, encoding: "utf8" });
|
|
65357
66921
|
if (updateTarget.status !== 0)
|
|
65358
66922
|
return { error: "merge target branch changed before update", mode: "merge" };
|
|
65359
|
-
const push =
|
|
66923
|
+
const push = spawnSync7("git", ["push", targetUrl, `${mergedCommit.stdout.trim()}:refs/heads/${target}`], { cwd: root, encoding: "utf8", env: { ...process.env, PATH: process.env.PATH ?? "" } });
|
|
65360
66924
|
if (push.status !== 0)
|
|
65361
66925
|
return {
|
|
65362
66926
|
error: "push failed",
|
|
@@ -65373,7 +66937,7 @@ function prCreate(env, cwd) {
|
|
|
65373
66937
|
output: (push.stdout ?? "").trim()
|
|
65374
66938
|
};
|
|
65375
66939
|
};
|
|
65376
|
-
const co =
|
|
66940
|
+
const co = spawnSync7("git", ["checkout", "--detach", mergeBaseCommit], {
|
|
65377
66941
|
cwd: root,
|
|
65378
66942
|
encoding: "utf8"
|
|
65379
66943
|
});
|
|
@@ -65385,7 +66949,7 @@ function prCreate(env, cwd) {
|
|
|
65385
66949
|
stderr: (co.stderr ?? "").slice(0, 800)
|
|
65386
66950
|
};
|
|
65387
66951
|
const result = finish();
|
|
65388
|
-
|
|
66952
|
+
spawnSync7("git", ["checkout", branch], { cwd: root, encoding: "utf8" });
|
|
65389
66953
|
return result;
|
|
65390
66954
|
}
|
|
65391
66955
|
const pr = cfg.pr ?? {};
|
|
@@ -65411,7 +66975,7 @@ function prCreate(env, cwd) {
|
|
|
65411
66975
|
const push = pr.pushBranch !== false;
|
|
65412
66976
|
const skipConfirm = pr.confirmSkip !== false;
|
|
65413
66977
|
const remoteBranchTip = () => {
|
|
65414
|
-
const read =
|
|
66978
|
+
const read = spawnSync7("git", ["ls-remote", targetUrl, `refs/heads/${branch}`], {
|
|
65415
66979
|
cwd: root,
|
|
65416
66980
|
encoding: "utf8",
|
|
65417
66981
|
env: { ...process.env, PATH: process.env.PATH ?? "" }
|
|
@@ -65427,7 +66991,7 @@ function prCreate(env, cwd) {
|
|
|
65427
66991
|
stderr: branch ? "source branch commit could not be resolved" : "empty current branch (detached HEAD or unborn HEAD)"
|
|
65428
66992
|
};
|
|
65429
66993
|
if (push) {
|
|
65430
|
-
const pushed =
|
|
66994
|
+
const pushed = spawnSync7("git", ["push", "-u", targetUrl, `${sourceCommit}:refs/heads/${branch}`], { cwd: root, encoding: "utf8", env: { ...process.env, PATH: process.env.PATH ?? "" } });
|
|
65431
66995
|
if (pushed.status !== 0)
|
|
65432
66996
|
return { error: "push failed", provider, stderr: (pushed.stderr ?? "").slice(0, 800) };
|
|
65433
66997
|
}
|
|
@@ -65472,12 +67036,12 @@ function prCreate(env, cwd) {
|
|
|
65472
67036
|
cmd.push("--draft");
|
|
65473
67037
|
cmdEnv = { ...process.env, PATH: process.env.PATH ?? "", GH_HOST: identity.host };
|
|
65474
67038
|
}
|
|
65475
|
-
const result =
|
|
67039
|
+
const result = spawnSync7(cmd[0], cmd.slice(1), { cwd: root, encoding: "utf8", env: cmdEnv });
|
|
65476
67040
|
if (result.status !== 0) {
|
|
65477
67041
|
const err = (result.stderr ?? result.stdout ?? "").trim();
|
|
65478
67042
|
let hint = null;
|
|
65479
67043
|
if (provider === "gitlab" && (err.includes("409") || err.toLowerCase().includes("already exists"))) {
|
|
65480
|
-
const list =
|
|
67044
|
+
const list = spawnSync7("glab", ["mr", "list", `--source-branch=${branch}`, "--output=json"], {
|
|
65481
67045
|
cwd: root,
|
|
65482
67046
|
encoding: "utf8",
|
|
65483
67047
|
env: cmdEnv
|
|
@@ -65536,7 +67100,7 @@ function mergePr(cwd, opts) {
|
|
|
65536
67100
|
return { error: "approved hosting account changed before execution" };
|
|
65537
67101
|
if (!/^[a-f0-9]{40,64}$/i.test(opts.sourceCommit))
|
|
65538
67102
|
return { error: "approved merge source commit is invalid" };
|
|
65539
|
-
const currentCommit =
|
|
67103
|
+
const currentCommit = spawnSync7("git", ["rev-parse", "--verify", `refs/heads/${opts.source}`], {
|
|
65540
67104
|
cwd: root,
|
|
65541
67105
|
encoding: "utf8"
|
|
65542
67106
|
});
|
|
@@ -65550,7 +67114,7 @@ function mergePr(cwd, opts) {
|
|
|
65550
67114
|
return { error: `workflow CLI missing (required for ${provider})` };
|
|
65551
67115
|
const owner = repoPath.split("/")[0];
|
|
65552
67116
|
const endpoint = provider === "github" ? `repos/${repository.replace(/^[^/]+\//u, "")}/pulls?state=open&head=${encodeURIComponent(`${owner}:${opts.source}`)}&base=${encodeURIComponent(opts.target)}&per_page=100` : `projects/${encodeURIComponent(repoPath)}/merge_requests?state=opened&source_branch=${encodeURIComponent(opts.source)}&target_branch=${encodeURIComponent(opts.target)}&per_page=100`;
|
|
65553
|
-
const listOpen = () =>
|
|
67117
|
+
const listOpen = () => spawnSync7(provider === "github" ? "gh" : "glab", ["api", endpoint], {
|
|
65554
67118
|
cwd: root,
|
|
65555
67119
|
encoding: "utf8",
|
|
65556
67120
|
env: {
|
|
@@ -65610,7 +67174,7 @@ function mergePr(cwd, opts) {
|
|
|
65610
67174
|
cmd.push("--delete-branch");
|
|
65611
67175
|
cmdEnv = { ...process.env, PATH: process.env.PATH ?? "", GH_HOST: identity.host };
|
|
65612
67176
|
}
|
|
65613
|
-
const result =
|
|
67177
|
+
const result = spawnSync7(cmd[0], cmd.slice(1), { cwd: root, encoding: "utf8", env: cmdEnv });
|
|
65614
67178
|
if (result.status !== 0)
|
|
65615
67179
|
return {
|
|
65616
67180
|
error: "merge failed",
|
|
@@ -65627,8 +67191,8 @@ function mergePr(cwd, opts) {
|
|
|
65627
67191
|
}
|
|
65628
67192
|
|
|
65629
67193
|
// packages/workit-core/src/core/repo-context.ts
|
|
65630
|
-
import { spawnSync as
|
|
65631
|
-
import { existsSync as existsSync18, readFileSync as
|
|
67194
|
+
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
67195
|
+
import { existsSync as existsSync18, readFileSync as readFileSync19, readdirSync as readdirSync9 } from "node:fs";
|
|
65632
67196
|
import path29 from "node:path";
|
|
65633
67197
|
var isSafeContextRange = (value) => value.length <= 4096 && (() => {
|
|
65634
67198
|
try {
|
|
@@ -65656,7 +67220,7 @@ var invalidRange = (cwd) => ({
|
|
|
65656
67220
|
cwd
|
|
65657
67221
|
});
|
|
65658
67222
|
var runGit = (cwd, args) => {
|
|
65659
|
-
const result =
|
|
67223
|
+
const result = spawnSync8("git", args, { cwd, encoding: "utf8" });
|
|
65660
67224
|
return {
|
|
65661
67225
|
stdout: (result.stdout ?? "").trimEnd(),
|
|
65662
67226
|
stderr: (result.stderr ?? "").trimEnd(),
|
|
@@ -65798,7 +67362,7 @@ var packageScripts = (cwd, keys) => {
|
|
|
65798
67362
|
if (!existsSync18(pkgPath))
|
|
65799
67363
|
return [];
|
|
65800
67364
|
try {
|
|
65801
|
-
const pkg = JSON.parse(
|
|
67365
|
+
const pkg = JSON.parse(readFileSync19(pkgPath, "utf8"));
|
|
65802
67366
|
return keys.filter((k) => pkg.scripts && typeof pkg.scripts[k] === "string").map((k) => `${k}: ${pkg.scripts?.[k]}`);
|
|
65803
67367
|
} catch {
|
|
65804
67368
|
return [];
|
|
@@ -65832,7 +67396,7 @@ var documentationFiles = (cwd) => {
|
|
|
65832
67396
|
var readTrimmed = (file, maxLines) => {
|
|
65833
67397
|
if (!existsSync18(file))
|
|
65834
67398
|
return "";
|
|
65835
|
-
const lines =
|
|
67399
|
+
const lines = readFileSync19(file, "utf8").split(`
|
|
65836
67400
|
`);
|
|
65837
67401
|
return lines.slice(0, maxLines).join(`
|
|
65838
67402
|
`);
|
|
@@ -66020,7 +67584,7 @@ function docsRefreshContext(root, range) {
|
|
|
66020
67584
|
const pkgPath = path29.join(cwd, "package.json");
|
|
66021
67585
|
if (existsSync18(pkgPath)) {
|
|
66022
67586
|
try {
|
|
66023
|
-
const pkg = JSON.parse(
|
|
67587
|
+
const pkg = JSON.parse(readFileSync19(pkgPath, "utf8"));
|
|
66024
67588
|
stdout += JSON.stringify({ name: pkg.name, version: pkg.version, scripts: pkg.scripts }, null, 2) + `
|
|
66025
67589
|
`;
|
|
66026
67590
|
} catch {}
|
|
@@ -66097,7 +67661,7 @@ function releaseNotesContext(root, rangeOrTag) {
|
|
|
66097
67661
|
}
|
|
66098
67662
|
|
|
66099
67663
|
// packages/workit-core/src/core/tracker-issues.ts
|
|
66100
|
-
import { spawnSync as
|
|
67664
|
+
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
66101
67665
|
var repoPathFromRemote = (remote) => {
|
|
66102
67666
|
let rest = (remote || "").trim().replace(/\/+$/, "");
|
|
66103
67667
|
if (!rest)
|
|
@@ -66118,7 +67682,7 @@ var defaultCli = (bin, available) => {
|
|
|
66118
67682
|
if (!available)
|
|
66119
67683
|
return null;
|
|
66120
67684
|
return (args, root) => {
|
|
66121
|
-
const out =
|
|
67685
|
+
const out = spawnSync9(bin, args, {
|
|
66122
67686
|
cwd: root,
|
|
66123
67687
|
encoding: "utf8",
|
|
66124
67688
|
env: { ...process.env, PATH: process.env.PATH ?? "" }
|
|
@@ -66851,7 +68415,7 @@ async function logTimeUpdate(input, operation = defaultOperations) {
|
|
|
66851
68415
|
// packages/workit-core/src/core/external-action-effects.ts
|
|
66852
68416
|
import fs13 from "node:fs";
|
|
66853
68417
|
import path31 from "node:path";
|
|
66854
|
-
import { spawnSync as
|
|
68418
|
+
import { spawnSync as spawnSync10 } from "node:child_process";
|
|
66855
68419
|
var run3 = (root, args) => {
|
|
66856
68420
|
return run2(root, "git", args);
|
|
66857
68421
|
};
|
|
@@ -67251,7 +68815,7 @@ var hostingProvider = (root, remote) => {
|
|
|
67251
68815
|
};
|
|
67252
68816
|
var remoteBranchTip = (root, provider, host, repo, branch) => {
|
|
67253
68817
|
const endpoint = provider === "github" ? `repos/${repo}/git/ref/heads/${branch.split("/").map(encodeURIComponent).join("/")}` : `projects/${encodeURIComponent(repo)}/repository/branches/${encodeURIComponent(branch)}`;
|
|
67254
|
-
const response =
|
|
68818
|
+
const response = spawnSync10(provider === "github" ? "gh" : "glab", ["api", endpoint], {
|
|
67255
68819
|
cwd: root,
|
|
67256
68820
|
encoding: "utf8",
|
|
67257
68821
|
env: hostingCliEnv(provider, host)
|
|
@@ -67259,7 +68823,7 @@ var remoteBranchTip = (root, provider, host, repo, branch) => {
|
|
|
67259
68823
|
if (response.status !== 0) {
|
|
67260
68824
|
if (/\b404\b/.test(response.stderr ?? "")) {
|
|
67261
68825
|
const project = provider === "github" ? `repos/${repo}` : `projects/${encodeURIComponent(repo)}`;
|
|
67262
|
-
const visible =
|
|
68826
|
+
const visible = spawnSync10(provider === "github" ? "gh" : "glab", ["api", project], {
|
|
67263
68827
|
cwd: root,
|
|
67264
68828
|
encoding: "utf8",
|
|
67265
68829
|
env: hostingCliEnv(provider, host)
|
|
@@ -67315,7 +68879,7 @@ var mergedBranch = (root, branch) => {
|
|
|
67315
68879
|
outcome: "not_started"
|
|
67316
68880
|
});
|
|
67317
68881
|
const endpoint = provider === "github" ? `repos/${repo}/pulls?state=closed&head=${encodeURIComponent(`${repo.split("/")[0]}:${branch}`)}&per_page=100` : `projects/${encodeURIComponent(repo)}/merge_requests?state=merged&source_branch=${encodeURIComponent(branch)}&per_page=100`;
|
|
67318
|
-
const response =
|
|
68882
|
+
const response = spawnSync10(provider === "github" ? "gh" : "glab", ["api", endpoint], {
|
|
67319
68883
|
cwd: root,
|
|
67320
68884
|
encoding: "utf8",
|
|
67321
68885
|
env: hostingCliEnv(provider, auth.host)
|
|
@@ -67377,7 +68941,7 @@ var readHostingAction = async (root, resolved, actionRef) => {
|
|
|
67377
68941
|
return unknownHostingEvidence(operation);
|
|
67378
68942
|
const endpoint = cfg.provider === "github" ? `repos/${repo}/pulls?state=all&head=${encodeURIComponent(`${repo.split("/")[0]}:${branch}`)}&base=${encodeURIComponent(target)}&per_page=100&page=1` : `projects/${encodeURIComponent(repo)}/merge_requests?state=all&source_branch=${encodeURIComponent(branch)}&target_branch=${encodeURIComponent(target)}&per_page=100&page=1`;
|
|
67379
68943
|
const cli = cfg.provider === "github" ? "gh" : "glab";
|
|
67380
|
-
const response =
|
|
68944
|
+
const response = spawnSync10(cli, ["api", endpoint], {
|
|
67381
68945
|
cwd: root,
|
|
67382
68946
|
encoding: "utf8",
|
|
67383
68947
|
env: hostingCliEnv(cfg.provider, auth.host)
|
|
@@ -68464,7 +70028,7 @@ async function payloadValue(raw, deps) {
|
|
|
68464
70028
|
return { ok: true, value: {} };
|
|
68465
70029
|
let source;
|
|
68466
70030
|
try {
|
|
68467
|
-
source = raw === "-" ? await readInput(deps.stdin ?? process.stdin) : raw.startsWith("@") ? decodeUtf8(
|
|
70031
|
+
source = raw === "-" ? await readInput(deps.stdin ?? process.stdin) : raw.startsWith("@") ? decodeUtf8(readFileSync20(raw.slice(1))) : raw;
|
|
68468
70032
|
} catch (error) {
|
|
68469
70033
|
return {
|
|
68470
70034
|
ok: false,
|
|
@@ -69177,6 +70741,498 @@ async function runActionCommand(argv, deps = {}) {
|
|
|
69177
70741
|
return result.ok ? 0 : 1;
|
|
69178
70742
|
}
|
|
69179
70743
|
|
|
70744
|
+
// packages/workit-cli/src/upgrade.ts
|
|
70745
|
+
import { spawnSync as spawnSync11 } from "node:child_process";
|
|
70746
|
+
import {
|
|
70747
|
+
existsSync as existsSync19,
|
|
70748
|
+
readFileSync as readFileSync21,
|
|
70749
|
+
mkdirSync as mkdirSync9,
|
|
70750
|
+
copyFileSync as copyFileSync3,
|
|
70751
|
+
chmodSync,
|
|
70752
|
+
cpSync as cpSync4,
|
|
70753
|
+
lstatSync as lstatSync8
|
|
70754
|
+
} from "node:fs";
|
|
70755
|
+
import path32 from "node:path";
|
|
70756
|
+
import os11 from "node:os";
|
|
70757
|
+
import { createHash as createHash11 } from "node:crypto";
|
|
70758
|
+
var HOSTS2 = ["opencode", "cursor", "codex", "pi"];
|
|
70759
|
+
var upgradePaths = (deps) => {
|
|
70760
|
+
const home = deps.home ?? deps.env?.HOME ?? os11.homedir();
|
|
70761
|
+
const env = {
|
|
70762
|
+
...process.env,
|
|
70763
|
+
...deps.home || deps.env?.HOME ? {
|
|
70764
|
+
HOME: home,
|
|
70765
|
+
CODEX_HOME: path32.join(home, ".codex"),
|
|
70766
|
+
PI_CODING_AGENT_DIR: path32.join(home, ".pi/agent"),
|
|
70767
|
+
XDG_CONFIG_HOME: path32.join(home, ".config"),
|
|
70768
|
+
WORKFLOW_TOOLKIT_CONFIG: undefined,
|
|
70769
|
+
WORKFLOW_TOOLKIT_CONFIG_DIR: undefined
|
|
70770
|
+
} : {},
|
|
70771
|
+
...deps.env,
|
|
70772
|
+
HOME: home
|
|
70773
|
+
};
|
|
70774
|
+
const xdg = env.XDG_CONFIG_HOME || path32.join(home, ".config");
|
|
70775
|
+
return {
|
|
70776
|
+
home,
|
|
70777
|
+
env,
|
|
70778
|
+
configDir: env.WORKFLOW_TOOLKIT_CONFIG ?? env.WORKFLOW_TOOLKIT_CONFIG_DIR ?? path32.join(xdg, "workit"),
|
|
70779
|
+
opencodeConfig: path32.join(xdg, "opencode/opencode.json"),
|
|
70780
|
+
piSettings: path32.join(env.PI_CODING_AGENT_DIR ?? path32.join(home, ".pi/agent"), "settings.json"),
|
|
70781
|
+
codexConfig: path32.join(env.CODEX_HOME ?? path32.join(home, ".codex"), "config.toml")
|
|
70782
|
+
};
|
|
70783
|
+
};
|
|
70784
|
+
var object2 = (file) => {
|
|
70785
|
+
if (!existsSync19(file))
|
|
70786
|
+
return null;
|
|
70787
|
+
let data;
|
|
70788
|
+
try {
|
|
70789
|
+
data = JSON.parse(readFileSync21(file, "utf8"));
|
|
70790
|
+
} catch {
|
|
70791
|
+
throw new Error(`${file} is not valid JSON; use the native host to inspect JSONC settings`);
|
|
70792
|
+
}
|
|
70793
|
+
if (!data || typeof data !== "object" || Array.isArray(data))
|
|
70794
|
+
throw new Error(`${file} is not a configuration object`);
|
|
70795
|
+
return data;
|
|
70796
|
+
};
|
|
70797
|
+
var digest2 = (file) => existsSync19(file) ? createHash11("sha256").update(readFileSync21(file)).digest("hex") : "missing";
|
|
70798
|
+
var runner = (deps) => deps.run ?? ((command, args) => {
|
|
70799
|
+
const { home, env } = upgradePaths(deps);
|
|
70800
|
+
let step;
|
|
70801
|
+
try {
|
|
70802
|
+
step = hostCommand(command, args, { home, env });
|
|
70803
|
+
} catch {
|
|
70804
|
+
return { status: 1, stdout: "" };
|
|
70805
|
+
}
|
|
70806
|
+
const result = runHostCommand(step, { home, env });
|
|
70807
|
+
return { status: result.exitCode, stdout: result.stdout };
|
|
70808
|
+
});
|
|
70809
|
+
var classify = (host, selector) => ({
|
|
70810
|
+
host,
|
|
70811
|
+
selector,
|
|
70812
|
+
kind: selector === `@brainervirus/workit-${host}` || selector === `@brainervirus/workit-${host}@latest` || selector === `npm:@brainervirus/workit-${host}` || selector === `npm:@brainervirus/workit-${host}@latest` ? "floating" : new RegExp(`^(?:npm:)?@brainervirus/workit-${host}@[^/]+$`).test(selector) ? "pinned" : "local"
|
|
70813
|
+
});
|
|
70814
|
+
var sources = (paths, run, hosts) => {
|
|
70815
|
+
const { home, opencodeConfig, piSettings } = paths;
|
|
70816
|
+
const result = [];
|
|
70817
|
+
if (hosts.includes("opencode") && existsSync19(opencodeConfig + "c"))
|
|
70818
|
+
throw new Error("OpenCode JSONC config is present; inspect effective native configuration before updating");
|
|
70819
|
+
const oc = hosts.includes("opencode") ? object2(opencodeConfig) : null;
|
|
70820
|
+
if (oc && [oc.plugins, oc.plugin].some((value) => value !== undefined && !Array.isArray(value)))
|
|
70821
|
+
throw new Error("OpenCode plugin registrations must be arrays");
|
|
70822
|
+
const plugins = [...oc?.plugins ?? [], ...oc?.plugin ?? []];
|
|
70823
|
+
for (const pin of plugins)
|
|
70824
|
+
if (typeof pin === "string" && isWorkitPlugin(pin))
|
|
70825
|
+
result.push(classify("opencode", pin));
|
|
70826
|
+
const cursor = hosts.includes("cursor") ? object2(path32.join(home, ".cursor/plugins/local/workit/package.json")) : null;
|
|
70827
|
+
if (cursor?.name === "@brainervirus/workit-cursor") {
|
|
70828
|
+
const mcp = object2(path32.join(home, ".cursor/mcp.json"));
|
|
70829
|
+
const args = mcp?.mcpServers?.workit?.args ?? [];
|
|
70830
|
+
const selector = args.find((arg) => typeof arg === "string" && arg.startsWith("--package="));
|
|
70831
|
+
result.push(classify("cursor", typeof selector === "string" ? selector.slice(10) : "local"));
|
|
70832
|
+
}
|
|
70833
|
+
const pi = hosts.includes("pi") ? object2(piSettings) : null;
|
|
70834
|
+
if (pi?.packages !== undefined && !Array.isArray(pi.packages))
|
|
70835
|
+
throw new Error("Pi package registrations must be an array");
|
|
70836
|
+
for (const entry of pi?.packages ?? []) {
|
|
70837
|
+
const source = typeof entry === "string" ? entry : entry?.source;
|
|
70838
|
+
if (typeof source !== "string")
|
|
70839
|
+
continue;
|
|
70840
|
+
const npm = /^(?:npm:)?@brainervirus\/workit-pi(?:@[^/]+)?$/.test(source);
|
|
70841
|
+
const local = path32.isAbsolute(source) && source.replaceAll("\\", "/").endsWith("/packages/workit-pi") && object2(path32.join(source, "package.json"))?.name === "@brainervirus/workit-pi";
|
|
70842
|
+
if (npm || local)
|
|
70843
|
+
result.push(classify("pi", source));
|
|
70844
|
+
}
|
|
70845
|
+
const listing = hosts.includes("codex") ? run("codex", ["plugin", "list", "--json"]) : { status: 1, stdout: "" };
|
|
70846
|
+
if (hosts.includes("codex") && listing.status !== 0) {
|
|
70847
|
+
let available = false;
|
|
70848
|
+
try {
|
|
70849
|
+
hostCommand("codex", [], { home, env: paths.env });
|
|
70850
|
+
available = true;
|
|
70851
|
+
} catch {}
|
|
70852
|
+
if (available || existsSync19(paths.codexConfig))
|
|
70853
|
+
throw new Error("Codex plugin inventory failed; inspect the native host before upgrading");
|
|
70854
|
+
}
|
|
70855
|
+
if (listing.status === 0) {
|
|
70856
|
+
let installed;
|
|
70857
|
+
try {
|
|
70858
|
+
installed = JSON.parse(listing.stdout).installed ?? [];
|
|
70859
|
+
} catch {
|
|
70860
|
+
throw new Error("Codex plugin inventory could not be parsed");
|
|
70861
|
+
}
|
|
70862
|
+
if (!Array.isArray(installed))
|
|
70863
|
+
throw new Error("Codex plugin inventory is malformed");
|
|
70864
|
+
for (const plugin of installed) {
|
|
70865
|
+
if (plugin.name !== "workit")
|
|
70866
|
+
continue;
|
|
70867
|
+
const source = plugin.source;
|
|
70868
|
+
const npm = plugin.marketplaceName === "workflow-toolkit" && source?.source === "npm" && source?.package === "@brainervirus/workit-codex";
|
|
70869
|
+
result.push({
|
|
70870
|
+
...classify("codex", npm ? `${source.package}${source.version ? `@${source.version}` : ""}` : "local"),
|
|
70871
|
+
installedVersion: plugin.version
|
|
70872
|
+
});
|
|
70873
|
+
}
|
|
70874
|
+
}
|
|
70875
|
+
for (const source of result) {
|
|
70876
|
+
if (source.host === "cursor")
|
|
70877
|
+
source.installedVersion = cursor?.version;
|
|
70878
|
+
if (source.host === "pi" && source.kind === "floating") {
|
|
70879
|
+
const inventory = run("pi", ["list"]);
|
|
70880
|
+
if (inventory.status === 0)
|
|
70881
|
+
source.installedVersion = piInstalledVersion(inventory.stdout, source.selector);
|
|
70882
|
+
}
|
|
70883
|
+
}
|
|
70884
|
+
return result;
|
|
70885
|
+
};
|
|
70886
|
+
var piInstalledVersion = (listing, selector) => {
|
|
70887
|
+
const lines = listing.split(/\r?\n/).map((line) => line.trim());
|
|
70888
|
+
const index = lines.indexOf(selector);
|
|
70889
|
+
if (index < 0 || !lines[index + 1] || !path32.isAbsolute(lines[index + 1]))
|
|
70890
|
+
return;
|
|
70891
|
+
const pkg = object2(path32.join(lines[index + 1], "package.json"));
|
|
70892
|
+
return pkg?.name === "@brainervirus/workit-pi" ? pkg.version : undefined;
|
|
70893
|
+
};
|
|
70894
|
+
var versionAtLeast = (installed, latest) => {
|
|
70895
|
+
if (!/^\d+\.\d+\.\d+$/.test(installed))
|
|
70896
|
+
return false;
|
|
70897
|
+
const current = installed.split(".").map(Number);
|
|
70898
|
+
const target = latest.split(".").map(Number);
|
|
70899
|
+
for (let index = 0;index < 3; index++) {
|
|
70900
|
+
if (current[index] !== target[index])
|
|
70901
|
+
return current[index] > target[index];
|
|
70902
|
+
}
|
|
70903
|
+
return true;
|
|
70904
|
+
};
|
|
70905
|
+
function previewUpgrade(hosts = HOSTS2, deps = {}) {
|
|
70906
|
+
const paths = upgradePaths(deps);
|
|
70907
|
+
const { home, configDir } = paths;
|
|
70908
|
+
const run = runner(deps);
|
|
70909
|
+
const state = readSetupState(configDir);
|
|
70910
|
+
const plan = {
|
|
70911
|
+
ok: true,
|
|
70912
|
+
blocked: [],
|
|
70913
|
+
skipped: [],
|
|
70914
|
+
entries: [],
|
|
70915
|
+
configDigests: {},
|
|
70916
|
+
migrations: []
|
|
70917
|
+
};
|
|
70918
|
+
for (const file of [state.config, state.workspaces, state.youtrack, state.vcs]) {
|
|
70919
|
+
if (file.status === "malformed")
|
|
70920
|
+
plan.blocked.push(file.error ?? file.file);
|
|
70921
|
+
plan.configDigests[file.file] = digest2(file.file);
|
|
70922
|
+
}
|
|
70923
|
+
for (const file of [
|
|
70924
|
+
paths.opencodeConfig,
|
|
70925
|
+
paths.opencodeConfig + "c",
|
|
70926
|
+
path32.join(home, ".cursor/settings.json"),
|
|
70927
|
+
path32.join(home, ".cursor/mcp.json"),
|
|
70928
|
+
path32.join(home, ".cursor/plugins/local/workit/package.json"),
|
|
70929
|
+
paths.codexConfig,
|
|
70930
|
+
paths.piSettings
|
|
70931
|
+
])
|
|
70932
|
+
plan.configDigests[file] = digest2(file);
|
|
70933
|
+
try {
|
|
70934
|
+
const config = object2(state.config.file);
|
|
70935
|
+
if (config && Object.hasOwn(config, "trustedPaths"))
|
|
70936
|
+
plan.migrations.push({
|
|
70937
|
+
id: "2.0-remove-ignored-trusted-paths",
|
|
70938
|
+
file: state.config.file,
|
|
70939
|
+
description: "Remove ignored Workit trustedPaths; native host permissions remain unchanged"
|
|
70940
|
+
});
|
|
70941
|
+
const installedSources = sources(paths, run, hosts);
|
|
70942
|
+
for (const host of ["opencode", "pi"]) {
|
|
70943
|
+
if (new Set(installedSources.filter((source) => source.host === host).map((source) => source.selector)).size > 1)
|
|
70944
|
+
plan.blocked.push(`${host}: conflicting Workit registrations; reconcile them in the native host before upgrading`);
|
|
70945
|
+
}
|
|
70946
|
+
for (const source of installedSources.filter((source, index, list) => list.findIndex((entry) => entry.host === source.host && entry.selector === source.selector) === index)) {
|
|
70947
|
+
if (source.kind !== "floating") {
|
|
70948
|
+
plan.skipped.push({
|
|
70949
|
+
host: source.host,
|
|
70950
|
+
reason: `${source.kind} source preserved; change its source explicitly to upgrade`
|
|
70951
|
+
});
|
|
70952
|
+
continue;
|
|
70953
|
+
}
|
|
70954
|
+
if (source.host === "opencode") {
|
|
70955
|
+
plan.skipped.push({
|
|
70956
|
+
host: source.host,
|
|
70957
|
+
reason: "OpenCode server plugin preserved: scoped native updates are unavailable in qualified 2.0.21; Workit never updates unrelated plugins"
|
|
70958
|
+
});
|
|
70959
|
+
continue;
|
|
70960
|
+
}
|
|
70961
|
+
const latest = run("npm", ["view", `@brainervirus/workit-${source.host}`, "version"]);
|
|
70962
|
+
if (latest.status !== 0 || !/^\d+\.\d+\.\d+$/.test(latest.stdout.trim())) {
|
|
70963
|
+
plan.blocked.push(`${source.host}: registry version unavailable; existing installation preserved`);
|
|
70964
|
+
continue;
|
|
70965
|
+
}
|
|
70966
|
+
if (source.installedVersion && versionAtLeast(source.installedVersion, latest.stdout.trim())) {
|
|
70967
|
+
plan.skipped.push({
|
|
70968
|
+
host: source.host,
|
|
70969
|
+
reason: `already current (${source.installedVersion})`
|
|
70970
|
+
});
|
|
70971
|
+
continue;
|
|
70972
|
+
}
|
|
70973
|
+
const commands = source.host === "pi" ? [{ command: "pi", args: ["update", "--extension", source.selector] }] : source.host === "codex" ? [{ command: "codex", args: ["plugin", "add", "workit@workflow-toolkit", "--json"] }] : planHostInstall("cursor", {
|
|
70974
|
+
home,
|
|
70975
|
+
env: deps.env,
|
|
70976
|
+
cwd: home,
|
|
70977
|
+
packageVersion: latest.stdout.trim(),
|
|
70978
|
+
targetDir: path32.join(home, ".cursor/plugins/local/workit")
|
|
70979
|
+
});
|
|
70980
|
+
plan.entries.push({
|
|
70981
|
+
host: source.host,
|
|
70982
|
+
selector: source.selector,
|
|
70983
|
+
latest: latest.stdout.trim(),
|
|
70984
|
+
commands
|
|
70985
|
+
});
|
|
70986
|
+
}
|
|
70987
|
+
} catch (error) {
|
|
70988
|
+
plan.blocked.push(error instanceof Error ? error.message : "installed source could not be read");
|
|
70989
|
+
}
|
|
70990
|
+
plan.ok = plan.blocked.length === 0;
|
|
70991
|
+
return plan;
|
|
70992
|
+
}
|
|
70993
|
+
function applyUpgrade(plan, deps = {}) {
|
|
70994
|
+
if (!plan.ok)
|
|
70995
|
+
return { ok: false, error: plan.blocked.join("; ") };
|
|
70996
|
+
if (!plan.entries.length && !plan.migrations.length && !plan.cli)
|
|
70997
|
+
return { ok: true };
|
|
70998
|
+
for (const [file, expected] of Object.entries(plan.configDigests))
|
|
70999
|
+
if (digest2(file) !== expected)
|
|
71000
|
+
return { ok: false, error: `configuration changed; preview again: ${file}` };
|
|
71001
|
+
const { home, env, configDir } = upgradePaths(deps);
|
|
71002
|
+
const active = deps.activeHosts?.() ?? runningHosts(deps);
|
|
71003
|
+
if (plan.entries.some((entry) => active.includes(entry.host)))
|
|
71004
|
+
return {
|
|
71005
|
+
ok: false,
|
|
71006
|
+
error: "Stop the selected running hosts before upgrading their loaded plugins"
|
|
71007
|
+
};
|
|
71008
|
+
const backup = path32.join(home, ".local/state/workit/upgrades", new Date().toISOString().replaceAll(":", "-"));
|
|
71009
|
+
mkdirSync9(backup, { recursive: true, mode: 448 });
|
|
71010
|
+
for (const file of Object.keys(plan.configDigests))
|
|
71011
|
+
if (existsSync19(file)) {
|
|
71012
|
+
const target = path32.join(backup, createHash11("sha256").update(file).digest("hex").slice(0, 12) + "-" + path32.basename(file));
|
|
71013
|
+
copyFileSync3(file, target);
|
|
71014
|
+
chmodSync(target, 384);
|
|
71015
|
+
}
|
|
71016
|
+
for (const migration of plan.migrations) {
|
|
71017
|
+
const value = object2(migration.file);
|
|
71018
|
+
if (migration.id !== "2.0-remove-ignored-trusted-paths" || !value)
|
|
71019
|
+
return {
|
|
71020
|
+
ok: false,
|
|
71021
|
+
backup,
|
|
71022
|
+
error: "Unknown configuration migration; upgrade the CLI before applying"
|
|
71023
|
+
};
|
|
71024
|
+
delete value.trustedPaths;
|
|
71025
|
+
writeFileAtomic(migration.file, JSON.stringify(value, null, 2) + `
|
|
71026
|
+
`, 384);
|
|
71027
|
+
}
|
|
71028
|
+
const run = runner(deps);
|
|
71029
|
+
const cursorRoot = path32.join(home, ".cursor/plugins/local/workit");
|
|
71030
|
+
if (plan.entries.some((entry) => entry.host === "cursor") && existsSync19(cursorRoot))
|
|
71031
|
+
cpSync4(cursorRoot, path32.join(backup, "cursor-package"), { recursive: true });
|
|
71032
|
+
for (const entry of plan.entries) {
|
|
71033
|
+
if (entry.host === "opencode")
|
|
71034
|
+
return {
|
|
71035
|
+
ok: false,
|
|
71036
|
+
backup,
|
|
71037
|
+
error: "Scoped OpenCode server-plugin updates are unsupported; registration preserved"
|
|
71038
|
+
};
|
|
71039
|
+
if (entry.host === "cursor") {
|
|
71040
|
+
const preview = {
|
|
71041
|
+
ok: true,
|
|
71042
|
+
blocked: [],
|
|
71043
|
+
preserved: [],
|
|
71044
|
+
overrides: [],
|
|
71045
|
+
platforms: ["cursor"],
|
|
71046
|
+
state: readSetupState(configDir),
|
|
71047
|
+
mutations: [
|
|
71048
|
+
{
|
|
71049
|
+
type: "install-host",
|
|
71050
|
+
platform: "cursor",
|
|
71051
|
+
path: path32.join(home, ".cursor/plugins/local/.workit-package-bootstrap"),
|
|
71052
|
+
commands: entry.commands.map((command) => ({
|
|
71053
|
+
...command,
|
|
71054
|
+
purpose: command.purpose ?? "Upgrade Cursor"
|
|
71055
|
+
}))
|
|
71056
|
+
},
|
|
71057
|
+
{
|
|
71058
|
+
type: "install-adapter",
|
|
71059
|
+
platform: "cursor",
|
|
71060
|
+
path: path32.join(home, ".cursor/plugins/local/workit")
|
|
71061
|
+
}
|
|
71062
|
+
]
|
|
71063
|
+
};
|
|
71064
|
+
const result = applySetupPreview(preview, {
|
|
71065
|
+
home,
|
|
71066
|
+
env,
|
|
71067
|
+
cwd: home,
|
|
71068
|
+
preferInstalledAdapter: true,
|
|
71069
|
+
runHostCommand: (command) => {
|
|
71070
|
+
const outcome = run(command.command, command.args);
|
|
71071
|
+
return { exitCode: outcome.status ?? 1, stdout: outcome.stdout, stderr: "" };
|
|
71072
|
+
}
|
|
71073
|
+
});
|
|
71074
|
+
const pkg = object2(path32.join(home, ".cursor/plugins/local/workit/package.json"));
|
|
71075
|
+
if (!result.ok || pkg?.version !== entry.latest)
|
|
71076
|
+
return {
|
|
71077
|
+
ok: false,
|
|
71078
|
+
backup,
|
|
71079
|
+
error: "Cursor update did not verify the requested package version; inspect the installer before retrying"
|
|
71080
|
+
};
|
|
71081
|
+
continue;
|
|
71082
|
+
}
|
|
71083
|
+
for (const command of entry.commands)
|
|
71084
|
+
if (run(command.command, command.args).status !== 0)
|
|
71085
|
+
return {
|
|
71086
|
+
ok: false,
|
|
71087
|
+
backup,
|
|
71088
|
+
error: `${entry.host}: update failed; inspect the native host before retrying`
|
|
71089
|
+
};
|
|
71090
|
+
const verify = entry.host === "codex" ? run("codex", ["plugin", "list", "--json"]) : run("pi", ["list"]);
|
|
71091
|
+
if (verify.status !== 0)
|
|
71092
|
+
return { ok: false, backup, error: `${entry.host}: update verification failed` };
|
|
71093
|
+
if (entry.host === "codex") {
|
|
71094
|
+
let installed = [];
|
|
71095
|
+
try {
|
|
71096
|
+
installed = JSON.parse(verify.stdout).installed ?? [];
|
|
71097
|
+
} catch {}
|
|
71098
|
+
if (!installed.some((plugin) => plugin.name === "workit" && plugin.marketplaceName === "workflow-toolkit" && plugin.version === entry.latest))
|
|
71099
|
+
return { ok: false, backup, error: "Codex did not report the requested Workit version" };
|
|
71100
|
+
}
|
|
71101
|
+
if (entry.host === "pi" && piInstalledVersion(verify.stdout, entry.selector) !== entry.latest)
|
|
71102
|
+
return { ok: false, backup, error: "Pi did not report the requested Workit package version" };
|
|
71103
|
+
}
|
|
71104
|
+
if (plan.cli) {
|
|
71105
|
+
const currentRoot = run("npm", ["root", "--global"]);
|
|
71106
|
+
if (currentRoot.status !== 0 || currentRoot.stdout.trim() !== plan.cli.root)
|
|
71107
|
+
return { ok: false, backup, error: "Global npm location changed; preview again" };
|
|
71108
|
+
const cliBackup = path32.join(backup, "cli-package");
|
|
71109
|
+
cpSync4(path32.join(plan.cli.root, "@brainervirus/workit-cli"), cliBackup, { recursive: true });
|
|
71110
|
+
if (run("npm", ["install", "--global", `@brainervirus/workit-cli@${plan.cli.latest}`]).status !== 0)
|
|
71111
|
+
return {
|
|
71112
|
+
ok: false,
|
|
71113
|
+
backup,
|
|
71114
|
+
error: `CLI update failed; preserved package at ${cliBackup}; use npm to repair or run node ${path32.join(cliBackup, "dist/index.js")}`
|
|
71115
|
+
};
|
|
71116
|
+
const installed = object2(path32.join(plan.cli.root, "@brainervirus/workit-cli/package.json"));
|
|
71117
|
+
if (installed?.name !== "@brainervirus/workit-cli" || installed.version !== plan.cli.latest)
|
|
71118
|
+
return {
|
|
71119
|
+
ok: false,
|
|
71120
|
+
backup,
|
|
71121
|
+
error: `CLI update did not verify the requested version; preserved package at ${cliBackup}`
|
|
71122
|
+
};
|
|
71123
|
+
}
|
|
71124
|
+
return { ok: true, backup };
|
|
71125
|
+
}
|
|
71126
|
+
async function runUpgradeCommand(argv, deps = {}) {
|
|
71127
|
+
const out = deps.out ?? process.stdout;
|
|
71128
|
+
const flags = new Set(argv);
|
|
71129
|
+
const unknown = argv.filter((arg) => !["--apply", "--confirm", "--json", "--cli"].includes(arg) && !arg.startsWith("--hosts="));
|
|
71130
|
+
const hostFlag = argv.find((arg) => arg.startsWith("--hosts="))?.slice(8);
|
|
71131
|
+
const raw = hostFlag === "none" ? [] : hostFlag?.split(",") ?? HOSTS2;
|
|
71132
|
+
if (unknown.length || raw.some((host) => !HOSTS2.includes(host))) {
|
|
71133
|
+
out.write(`Usage: workit upgrade [--hosts=opencode,cursor,codex,pi|none] [--cli] [--apply --confirm] [--json]
|
|
71134
|
+
`);
|
|
71135
|
+
return 2;
|
|
71136
|
+
}
|
|
71137
|
+
const plan = previewUpgrade(raw, deps);
|
|
71138
|
+
if (flags.has("--cli")) {
|
|
71139
|
+
const run = runner(deps);
|
|
71140
|
+
const root = run("npm", ["root", "--global"]);
|
|
71141
|
+
if (root.status !== 0 || !path32.isAbsolute(root.stdout.trim())) {
|
|
71142
|
+
plan.blocked.push("Global npm location could not be verified");
|
|
71143
|
+
} else {
|
|
71144
|
+
const packageFile = path32.join(root.stdout.trim(), "@brainervirus/workit-cli/package.json");
|
|
71145
|
+
const pkg = object2(packageFile);
|
|
71146
|
+
if (pkg?.name !== "@brainervirus/workit-cli" || lstatSync8(path32.dirname(packageFile)).isSymbolicLink()) {
|
|
71147
|
+
plan.skipped.push({
|
|
71148
|
+
host: "cli",
|
|
71149
|
+
reason: "No managed global CLI install (local links preserved); use npx @brainervirus/workit-cli@latest"
|
|
71150
|
+
});
|
|
71151
|
+
} else {
|
|
71152
|
+
const latest = run("npm", ["view", "@brainervirus/workit-cli", "version"]);
|
|
71153
|
+
if (latest.status !== 0 || !/^\d+\.\d+\.\d+$/.test(latest.stdout.trim()))
|
|
71154
|
+
plan.blocked.push("CLI registry version unavailable; existing installation preserved");
|
|
71155
|
+
else if (!versionAtLeast(pkg.version, latest.stdout.trim())) {
|
|
71156
|
+
plan.cli = { latest: latest.stdout.trim(), root: root.stdout.trim() };
|
|
71157
|
+
plan.configDigests[packageFile] = digest2(packageFile);
|
|
71158
|
+
} else
|
|
71159
|
+
plan.skipped.push({ host: "cli", reason: `already current (${pkg.version})` });
|
|
71160
|
+
}
|
|
71161
|
+
}
|
|
71162
|
+
plan.ok = plan.blocked.length === 0;
|
|
71163
|
+
}
|
|
71164
|
+
if (!flags.has("--apply")) {
|
|
71165
|
+
out.write(JSON.stringify(plan, null, 2) + `
|
|
71166
|
+
`);
|
|
71167
|
+
return plan.ok ? 0 : 1;
|
|
71168
|
+
}
|
|
71169
|
+
if (!flags.has("--confirm")) {
|
|
71170
|
+
out.write(`Apply requires --confirm after reviewing the upgrade preview.
|
|
71171
|
+
`);
|
|
71172
|
+
return 2;
|
|
71173
|
+
}
|
|
71174
|
+
const result = applyUpgrade(plan, deps);
|
|
71175
|
+
out.write(JSON.stringify(result, null, 2) + `
|
|
71176
|
+
`);
|
|
71177
|
+
return result.ok ? 0 : 1;
|
|
71178
|
+
}
|
|
71179
|
+
async function runLaunchCommand(argv, deps = {}) {
|
|
71180
|
+
const [host, ...args] = argv;
|
|
71181
|
+
if (!HOSTS2.includes(host)) {
|
|
71182
|
+
(deps.out ?? process.stdout).write(`Usage: workit launch <opencode|cursor|codex|pi> [--auto-upgrade] [-- host arguments]
|
|
71183
|
+
`);
|
|
71184
|
+
return 2;
|
|
71185
|
+
}
|
|
71186
|
+
const auto = args[0] === "--auto-upgrade";
|
|
71187
|
+
const rest = auto ? args.slice(1) : args;
|
|
71188
|
+
const hostArgs = rest[0] === "--" ? rest.slice(1) : rest;
|
|
71189
|
+
const { home, env } = upgradePaths(deps);
|
|
71190
|
+
let launch;
|
|
71191
|
+
if (!deps.run) {
|
|
71192
|
+
try {
|
|
71193
|
+
launch = hostCommand(host, hostArgs, { home, env });
|
|
71194
|
+
} catch (error) {
|
|
71195
|
+
(deps.out ?? process.stderr).write(`${error instanceof Error ? error.message : "Host executable unavailable"}
|
|
71196
|
+
`);
|
|
71197
|
+
return 1;
|
|
71198
|
+
}
|
|
71199
|
+
}
|
|
71200
|
+
if (auto) {
|
|
71201
|
+
const plan = previewUpgrade([host], deps);
|
|
71202
|
+
if (plan.ok) {
|
|
71203
|
+
for (const skipped of plan.skipped)
|
|
71204
|
+
(deps.out ?? process.stderr).write(`${skipped.host}: ${skipped.reason}
|
|
71205
|
+
`);
|
|
71206
|
+
const result = applyUpgrade(plan, deps);
|
|
71207
|
+
if (!result.ok) {
|
|
71208
|
+
(deps.out ?? process.stdout).write(`${result.error}
|
|
71209
|
+
`);
|
|
71210
|
+
return 1;
|
|
71211
|
+
}
|
|
71212
|
+
} else if (plan.blocked.every((reason) => reason.includes("registry version unavailable"))) {
|
|
71213
|
+
(deps.out ?? process.stderr).write(`Upgrade unavailable: ${plan.blocked.join("; ")}. Starting the unchanged host.
|
|
71214
|
+
`);
|
|
71215
|
+
} else {
|
|
71216
|
+
(deps.out ?? process.stderr).write(`Upgrade blocked: ${plan.blocked.join("; ")}
|
|
71217
|
+
`);
|
|
71218
|
+
return 1;
|
|
71219
|
+
}
|
|
71220
|
+
}
|
|
71221
|
+
if (deps.run)
|
|
71222
|
+
return deps.run(host, hostArgs).status ?? 1;
|
|
71223
|
+
return spawnSync11(launch.command, launch.args, {
|
|
71224
|
+
stdio: "inherit",
|
|
71225
|
+
env
|
|
71226
|
+
}).status ?? 1;
|
|
71227
|
+
}
|
|
71228
|
+
var runningHosts = (deps) => {
|
|
71229
|
+
const run = runner(deps);
|
|
71230
|
+
const list = process.platform === "win32" ? run("tasklist", ["/fo", "csv", "/nh"]) : run("ps", ["-eo", "comm="]);
|
|
71231
|
+
if (list.status !== 0)
|
|
71232
|
+
return HOSTS2;
|
|
71233
|
+
return HOSTS2.filter((host) => new RegExp(`(?:^|[\\/",\\s])${host}(?:\\.exe)?(?:[",\\s]|$)`, "im").test(list.stdout));
|
|
71234
|
+
};
|
|
71235
|
+
|
|
69180
71236
|
// packages/workit-cli/src/index.tsx
|
|
69181
71237
|
var jsx_dev_runtime3 = __toESM(require_jsx_dev_runtime(), 1);
|
|
69182
71238
|
var logger = createLogger({
|
|
@@ -69201,6 +71257,8 @@ var HELP = `workit — workflow rails for agentic coding
|
|
|
69201
71257
|
|
|
69202
71258
|
Usage:
|
|
69203
71259
|
workit init Run the interactive setup wizard
|
|
71260
|
+
workit upgrade Preview upgrades (--apply --confirm; --hosts=a,b; --cli for the CLI)
|
|
71261
|
+
workit launch <host> [--auto-upgrade] [-- args] Upgrade before host startup
|
|
69204
71262
|
workit doctor Verify the offline installation health (add --json for a machine-readable report)
|
|
69205
71263
|
workit uninstall Remove workit host registrations interactively (~/.config/workit is kept)
|
|
69206
71264
|
workit cutover Preview or apply an explicit v1 cutover (apply requires --confirm)
|
|
@@ -69209,7 +71267,7 @@ ${COMMAND_DESCRIPTIONS.map(([cmd, desc]) => ` ${cmd.padEnd(helpColumn)}${desc}`
|
|
|
69209
71267
|
action payloads: ${externalActionHelp}
|
|
69210
71268
|
workit Show this help
|
|
69211
71269
|
|
|
69212
|
-
Run \`npx workit init\` to configure platforms, YouTrack, VCS and project hygiene.
|
|
71270
|
+
Run \`npx @brainervirus/workit-cli init\` to configure platforms, YouTrack, VCS and project hygiene.
|
|
69213
71271
|
`;
|
|
69214
71272
|
function printApplySummary(result) {
|
|
69215
71273
|
for (const entry of result.entries) {
|
|
@@ -69423,7 +71481,11 @@ if (__require.main == __require.module) {
|
|
|
69423
71481
|
logger.error(EVENT.uncaughtFailure, { phase: "uncaughtException", ...errorDetail(err) });
|
|
69424
71482
|
process.exit(1);
|
|
69425
71483
|
});
|
|
69426
|
-
if (subcommand === "
|
|
71484
|
+
if (subcommand === "upgrade") {
|
|
71485
|
+
process.exit(await runUpgradeCommand(args.slice(1)));
|
|
71486
|
+
} else if (subcommand === "launch") {
|
|
71487
|
+
process.exit(await runLaunchCommand(args.slice(1)));
|
|
71488
|
+
} else if (subcommand === "init") {
|
|
69427
71489
|
await runInit();
|
|
69428
71490
|
} else if (subcommand === "doctor") {
|
|
69429
71491
|
runDoctorCommand(args);
|