@brainervirus/workit-cli 1.0.2 → 1.0.4
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/dist/index.js +95 -31
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -43028,10 +43028,12 @@ import {
|
|
|
43028
43028
|
copyFileSync as copyFileSync2,
|
|
43029
43029
|
cpSync as cpSync3,
|
|
43030
43030
|
existsSync as existsSync10,
|
|
43031
|
+
lstatSync as lstatSync2,
|
|
43031
43032
|
mkdirSync as mkdirSync5,
|
|
43032
43033
|
mkdtempSync,
|
|
43033
43034
|
readFileSync as readFileSync10,
|
|
43034
43035
|
readdirSync as readdirSync4,
|
|
43036
|
+
realpathSync as realpathSync2,
|
|
43035
43037
|
renameSync,
|
|
43036
43038
|
rmSync as rmSync2,
|
|
43037
43039
|
statSync as statSync4,
|
|
@@ -43135,6 +43137,7 @@ var readSetupState = (dir = resolveConfigDir()) => ({
|
|
|
43135
43137
|
|
|
43136
43138
|
// packages/workit-core/src/core/registration.ts
|
|
43137
43139
|
import path7 from "node:path";
|
|
43140
|
+
var OPENCODE_NPM_PIN = "@brainervirus/workit-opencode";
|
|
43138
43141
|
var isRecord = (v) => v !== null && typeof v === "object" && !Array.isArray(v);
|
|
43139
43142
|
var named = (s, name) => s === name || s.startsWith(`${name}@`);
|
|
43140
43143
|
function isWorkitPlugin(value) {
|
|
@@ -43257,7 +43260,16 @@ function cursorHooksEntry(_packageDir) {
|
|
|
43257
43260
|
|
|
43258
43261
|
// packages/workit-core/src/core/doctor.ts
|
|
43259
43262
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
43260
|
-
import {
|
|
43263
|
+
import {
|
|
43264
|
+
existsSync as existsSync9,
|
|
43265
|
+
lstatSync,
|
|
43266
|
+
mkdirSync as mkdirSync4,
|
|
43267
|
+
readFileSync as readFileSync9,
|
|
43268
|
+
readlinkSync,
|
|
43269
|
+
statSync as statSync3,
|
|
43270
|
+
unlinkSync,
|
|
43271
|
+
writeFileSync as writeFileSync6
|
|
43272
|
+
} from "node:fs";
|
|
43261
43273
|
import os5 from "node:os";
|
|
43262
43274
|
import path11 from "node:path";
|
|
43263
43275
|
|
|
@@ -52358,11 +52370,19 @@ var checkUtility = (res) => {
|
|
|
52358
52370
|
detail: "git (and flock where required) on PATH"
|
|
52359
52371
|
};
|
|
52360
52372
|
};
|
|
52373
|
+
var isFragileCachePin = (entry) => {
|
|
52374
|
+
const n = entry.replaceAll("\\", "/").toLowerCase();
|
|
52375
|
+
if (!n.startsWith("file:"))
|
|
52376
|
+
return false;
|
|
52377
|
+
return n.includes("/caches/pnpm/dlx/") || n.includes("/_npx/") || n.includes("/.pacquet/") || n.includes("/library/caches/pnpm/");
|
|
52378
|
+
};
|
|
52361
52379
|
var staleEntry = (entry) => {
|
|
52362
52380
|
if (!entry)
|
|
52363
52381
|
return "stale";
|
|
52364
52382
|
if (entry.includes("git+file"))
|
|
52365
52383
|
return "stale";
|
|
52384
|
+
if (isFragileCachePin(entry))
|
|
52385
|
+
return "fragile-cache";
|
|
52366
52386
|
if (entry.startsWith("file:")) {
|
|
52367
52387
|
const target = entry.replace(/^file:\/\//, "").replace(/^file:/, "");
|
|
52368
52388
|
return existsSync9(target) ? "ok" : "missing-file";
|
|
@@ -52391,7 +52411,7 @@ var checkStalePin = (res) => {
|
|
|
52391
52411
|
id: "stale_pin",
|
|
52392
52412
|
status: "fail",
|
|
52393
52413
|
detail: "no workit plugin registered in the opencode config",
|
|
52394
|
-
fix:
|
|
52414
|
+
fix: 'Run `workit init` and select OpenCode — pin "@brainervirus/workit-opencode"'
|
|
52395
52415
|
};
|
|
52396
52416
|
}
|
|
52397
52417
|
const first = staleEntry(entries[0]);
|
|
@@ -52400,7 +52420,15 @@ var checkStalePin = (res) => {
|
|
|
52400
52420
|
id: "stale_pin",
|
|
52401
52421
|
status: "fail",
|
|
52402
52422
|
detail: `stale workit pin: ${entries[0]}`,
|
|
52403
|
-
fix: "
|
|
52423
|
+
fix: "Run `workit init` (or install-opencode-plugin.sh for a checkout) — replace git+file pins"
|
|
52424
|
+
};
|
|
52425
|
+
}
|
|
52426
|
+
if (first === "fragile-cache") {
|
|
52427
|
+
return {
|
|
52428
|
+
id: "stale_pin",
|
|
52429
|
+
status: "fail",
|
|
52430
|
+
detail: `workit pin points at a package-manager cache path: ${entries[0]}`,
|
|
52431
|
+
fix: 'Run `workit init` and select OpenCode — pin should be "@brainervirus/workit-opencode"'
|
|
52404
52432
|
};
|
|
52405
52433
|
}
|
|
52406
52434
|
if (first === "missing-file") {
|
|
@@ -52408,7 +52436,7 @@ var checkStalePin = (res) => {
|
|
|
52408
52436
|
id: "stale_pin",
|
|
52409
52437
|
status: "fail",
|
|
52410
52438
|
detail: `workit pin points at a missing file: ${entries[0]}`,
|
|
52411
|
-
fix: "
|
|
52439
|
+
fix: "Run `workit init` (or restore the checkout and re-run install-opencode-plugin.sh)"
|
|
52412
52440
|
};
|
|
52413
52441
|
}
|
|
52414
52442
|
return { id: "stale_pin", status: "pass", detail: "opencode pin resolves" };
|
|
@@ -52458,6 +52486,22 @@ var checkStaleInstall = (res) => {
|
|
|
52458
52486
|
detail: "cursor plugin not inspected on the opencode host"
|
|
52459
52487
|
};
|
|
52460
52488
|
}
|
|
52489
|
+
if (existsSync9(res.cursorPluginDir) && lstatSync(res.cursorPluginDir).isSymbolicLink()) {
|
|
52490
|
+
let target = "";
|
|
52491
|
+
try {
|
|
52492
|
+
target = readlinkSync(res.cursorPluginDir);
|
|
52493
|
+
} catch {
|
|
52494
|
+
target = "(unreadable)";
|
|
52495
|
+
}
|
|
52496
|
+
const n = target.replaceAll("\\", "/").toLowerCase();
|
|
52497
|
+
const fragile = n.includes("/caches/pnpm/dlx/") || n.includes("/_npx/") || n.includes("/.pacquet/") || n.includes("/library/caches/pnpm/");
|
|
52498
|
+
return {
|
|
52499
|
+
id: "stale_install",
|
|
52500
|
+
status: "fail",
|
|
52501
|
+
detail: fragile ? `stale_install: cursor plugin dir is a symlink into a package-manager cache (${target})` : `stale_install: cursor plugin dir is a symlink (${target}) — expected a real directory copy`,
|
|
52502
|
+
fix: "Run `workit init` and select Cursor — install must copy into ~/.cursor/plugins/local/workit"
|
|
52503
|
+
};
|
|
52504
|
+
}
|
|
52461
52505
|
const canonicalMcp = cursorMcpServerEntry("").args.find((a) => a.startsWith("--package="));
|
|
52462
52506
|
const mcpSelectors = pluginMcpSelectors(res);
|
|
52463
52507
|
const legacyPin = (mcpSelectors ?? []).find((s) => s !== canonicalMcp && s.includes("@brainervirus/workit-cursor@"));
|
|
@@ -52657,7 +52701,9 @@ var checkCredentialMetadata = (res) => {
|
|
|
52657
52701
|
tokenPaths.push(path11.join(res.configDir, "youtrack.token"));
|
|
52658
52702
|
}
|
|
52659
52703
|
const vcsJson = readJson(path11.join(res.configDir, "vcs.json"));
|
|
52660
|
-
|
|
52704
|
+
const active = typeof vcsJson?.provider === "string" ? vcsJson.provider.trim().toLowerCase() : null;
|
|
52705
|
+
const vcsKeys = active === "gitlab" || active === "github" ? [active] : ["gitlab", "github"];
|
|
52706
|
+
for (const key of vcsKeys) {
|
|
52661
52707
|
const provider = vcsJson?.[key];
|
|
52662
52708
|
if (provider && typeof provider === "object") {
|
|
52663
52709
|
const tf = provider.tokenFile;
|
|
@@ -53517,7 +53563,15 @@ function adapterRoot(platform, res) {
|
|
|
53517
53563
|
}
|
|
53518
53564
|
return null;
|
|
53519
53565
|
}
|
|
53520
|
-
var
|
|
53566
|
+
var isDevOpenCodeAdapterRoot = (root, dev) => {
|
|
53567
|
+
if (dev)
|
|
53568
|
+
return true;
|
|
53569
|
+
const norm = root.replaceAll("\\", "/");
|
|
53570
|
+
return /\/packages\/workit-opencode\/?$/.test(norm);
|
|
53571
|
+
};
|
|
53572
|
+
var resolveOpenCodePin = (root, opts = {}) => {
|
|
53573
|
+
if (!isDevOpenCodeAdapterRoot(root, opts.dev))
|
|
53574
|
+
return OPENCODE_NPM_PIN;
|
|
53521
53575
|
for (const rel of ["src/plugin.ts", "dist/plugin.js"]) {
|
|
53522
53576
|
const entry = path12.join(root, rel);
|
|
53523
53577
|
if (existsSync10(entry))
|
|
@@ -53525,8 +53579,9 @@ var opencodePin = (root) => {
|
|
|
53525
53579
|
}
|
|
53526
53580
|
return null;
|
|
53527
53581
|
};
|
|
53582
|
+
var opencodePin = (root, res) => resolveOpenCodePin(root, { dev: res.dev });
|
|
53528
53583
|
function applyOpenCode(root, res) {
|
|
53529
|
-
const pin = opencodePin(root);
|
|
53584
|
+
const pin = opencodePin(root, res);
|
|
53530
53585
|
if (!pin) {
|
|
53531
53586
|
return {
|
|
53532
53587
|
platform: "opencode",
|
|
@@ -53613,30 +53668,35 @@ var preservedCursorRules = (src, dest) => {
|
|
|
53613
53668
|
return preserved;
|
|
53614
53669
|
};
|
|
53615
53670
|
function copyPluginDir(src, dest) {
|
|
53671
|
+
const realSrc = realpathSync2(src);
|
|
53616
53672
|
const marker = path12.join(dest, ".workit-root");
|
|
53617
|
-
const
|
|
53673
|
+
const destIsLink = existsSync10(dest) && lstatSync2(dest).isSymbolicLink();
|
|
53674
|
+
const synced = !destIsLink && readFileSafe(marker)?.trim() === realSrc && samePluginContent(realSrc, dest);
|
|
53618
53675
|
if (synced)
|
|
53619
53676
|
return "Skipped";
|
|
53620
53677
|
const hadDir = existsSync10(dest);
|
|
53621
|
-
const rules = preservedCursorRules(
|
|
53678
|
+
const rules = preservedCursorRules(realSrc, dest);
|
|
53622
53679
|
const parent = path12.dirname(dest);
|
|
53623
53680
|
mkdirSync5(parent, { recursive: true });
|
|
53624
53681
|
const swap = mkdtempSync(path12.join(parent, `.${path12.basename(dest)}.swap-`));
|
|
53625
53682
|
const stage = path12.join(swap, "stage");
|
|
53626
53683
|
const backup = path12.join(swap, "backup");
|
|
53627
53684
|
try {
|
|
53628
|
-
cpSync3(
|
|
53685
|
+
cpSync3(realSrc, stage, {
|
|
53629
53686
|
recursive: true,
|
|
53630
|
-
filter: (entry) => !path12.relative(
|
|
53687
|
+
filter: (entry) => !path12.relative(realSrc, entry).split(path12.sep).includes("node_modules")
|
|
53631
53688
|
});
|
|
53632
53689
|
for (const [name, content] of rules) {
|
|
53633
53690
|
mkdirSync5(path12.join(stage, "rules"), { recursive: true });
|
|
53634
53691
|
writeFileSync7(path12.join(stage, "rules", name), content);
|
|
53635
53692
|
}
|
|
53636
|
-
writeFileSync7(path12.join(stage, ".workit-root"),
|
|
53693
|
+
writeFileSync7(path12.join(stage, ".workit-root"), realSrc + `
|
|
53637
53694
|
`, "utf8");
|
|
53638
|
-
if (!samePluginContent(
|
|
53695
|
+
if (!samePluginContent(realSrc, stage))
|
|
53639
53696
|
throw new Error("staged adapter content is incomplete");
|
|
53697
|
+
if (lstatSync2(stage).isSymbolicLink()) {
|
|
53698
|
+
throw new Error("staged adapter resolved to a symlink — refusing fragile cache install");
|
|
53699
|
+
}
|
|
53640
53700
|
if (hadDir)
|
|
53641
53701
|
renameSync(dest, backup);
|
|
53642
53702
|
try {
|
|
@@ -54394,7 +54454,7 @@ import os8 from "node:os";
|
|
|
54394
54454
|
import path15 from "node:path";
|
|
54395
54455
|
|
|
54396
54456
|
// packages/workit-core/src/core/uninstall.ts
|
|
54397
|
-
import { existsSync as existsSync12, readFileSync as readFileSync11, realpathSync as
|
|
54457
|
+
import { existsSync as existsSync12, readFileSync as readFileSync11, realpathSync as realpathSync3, rmSync as rmSync3, writeFileSync as writeFileSync8 } from "node:fs";
|
|
54398
54458
|
import os7 from "node:os";
|
|
54399
54459
|
import path14 from "node:path";
|
|
54400
54460
|
var resolveUninstallPaths = (options = {}) => {
|
|
@@ -54593,7 +54653,7 @@ var canonicalRemoveDirAllowed = (actionPath, res) => {
|
|
|
54593
54653
|
return false;
|
|
54594
54654
|
}
|
|
54595
54655
|
try {
|
|
54596
|
-
return
|
|
54656
|
+
return realpathSync3(actionPath) === realpathSync3(expected);
|
|
54597
54657
|
} catch {
|
|
54598
54658
|
return true;
|
|
54599
54659
|
}
|
|
@@ -54790,9 +54850,10 @@ function SearchSelect({
|
|
|
54790
54850
|
onQueryChange
|
|
54791
54851
|
}) {
|
|
54792
54852
|
const [query, setQuery] = import_react65.useState("");
|
|
54793
|
-
const filtered = import_react65.useMemo(() => filterOptions(options, query), [options, query]);
|
|
54853
|
+
const filtered = import_react65.useMemo(() => filterOptions(options, query, Infinity), [options, query]);
|
|
54794
54854
|
const [rawIndex, setRawIndex] = import_react65.useState(() => Math.max(0, options.findIndex((option) => option.value === value)));
|
|
54795
54855
|
const index = Math.min(rawIndex, Math.max(0, filtered.length - 1));
|
|
54856
|
+
const offset = Math.max(0, index - VISIBLE_ROWS + 1);
|
|
54796
54857
|
use_input_default((input, key) => {
|
|
54797
54858
|
const type = (next) => {
|
|
54798
54859
|
onQueryChange?.(next);
|
|
@@ -54824,10 +54885,10 @@ function SearchSelect({
|
|
|
54824
54885
|
filtered.length === 0 ? /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
54825
54886
|
dimColor: true,
|
|
54826
54887
|
children: "No matches"
|
|
54827
|
-
}, undefined, false, undefined, this) : filtered.map((option, i) => /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
54828
|
-
color: i === index ? "cyan" : "dim",
|
|
54888
|
+
}, undefined, false, undefined, this) : filtered.slice(offset, offset + VISIBLE_ROWS).map((option, i) => /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
54889
|
+
color: i + offset === index ? "cyan" : "dim",
|
|
54829
54890
|
children: [
|
|
54830
|
-
i === index ? "❯ " : " ",
|
|
54891
|
+
i + offset === index ? "❯ " : " ",
|
|
54831
54892
|
option.label
|
|
54832
54893
|
]
|
|
54833
54894
|
}, option.value, true, undefined, this))
|
|
@@ -55834,23 +55895,26 @@ function Screen({
|
|
|
55834
55895
|
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
55835
55896
|
dimColor: true,
|
|
55836
55897
|
children: [
|
|
55837
|
-
"
|
|
55898
|
+
"Apply gitignore + hygiene in ",
|
|
55838
55899
|
resolveBasePath(draft.values),
|
|
55839
|
-
" (
|
|
55900
|
+
"? (Existing files are never overwritten.)"
|
|
55840
55901
|
]
|
|
55841
55902
|
}, undefined, true, undefined, this),
|
|
55842
55903
|
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(ConfirmInput, {
|
|
55843
|
-
defaultChoice: "
|
|
55904
|
+
defaultChoice: "cancel",
|
|
55844
55905
|
submitOnEnter: false,
|
|
55845
55906
|
onConfirm: () => {
|
|
55846
55907
|
dispatch({ type: "set", field: "applyProject", value: true });
|
|
55847
55908
|
dispatch({ type: "next" });
|
|
55848
55909
|
},
|
|
55849
|
-
onCancel: () => {
|
|
55910
|
+
onCancel: () => {
|
|
55911
|
+
dispatch({ type: "set", field: "applyProject", value: false });
|
|
55912
|
+
dispatch({ type: "next" });
|
|
55913
|
+
}
|
|
55850
55914
|
}, undefined, false, undefined, this),
|
|
55851
55915
|
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
55852
55916
|
dimColor: true,
|
|
55853
|
-
children: "y to
|
|
55917
|
+
children: "y to add project files · n to skip · b Back · Esc Cancel"
|
|
55854
55918
|
}, undefined, false, undefined, this)
|
|
55855
55919
|
]
|
|
55856
55920
|
}, undefined, true, undefined, this);
|
|
@@ -56426,7 +56490,7 @@ import { createInterface as createInterface2 } from "node:readline/promises";
|
|
|
56426
56490
|
|
|
56427
56491
|
// packages/workit-core/src/core.ts
|
|
56428
56492
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
56429
|
-
import { existsSync as existsSync16, realpathSync as
|
|
56493
|
+
import { existsSync as existsSync16, realpathSync as realpathSync8 } from "node:fs";
|
|
56430
56494
|
import path22 from "node:path";
|
|
56431
56495
|
|
|
56432
56496
|
// packages/workit-core/src/core/task-store.ts
|
|
@@ -59140,7 +59204,7 @@ async function runAuthorizedExternalAction(input, effect) {
|
|
|
59140
59204
|
};
|
|
59141
59205
|
}
|
|
59142
59206
|
// packages/workit-core/src/core/task-engine.ts
|
|
59143
|
-
import { realpathSync as
|
|
59207
|
+
import { realpathSync as realpathSync7 } from "node:fs";
|
|
59144
59208
|
|
|
59145
59209
|
// packages/workit-core/src/core/policy-resolver.ts
|
|
59146
59210
|
var resolverInputSchema = object({
|
|
@@ -59984,7 +60048,7 @@ class WorkitCore {
|
|
|
59984
60048
|
}
|
|
59985
60049
|
contextRootError() {
|
|
59986
60050
|
try {
|
|
59987
|
-
if (
|
|
60051
|
+
if (realpathSync7(this.context.root) !== this.store.root)
|
|
59988
60052
|
return failure("invalid_input", "operation context root does not match the task store root");
|
|
59989
60053
|
} catch {
|
|
59990
60054
|
return failure("invalid_input", "operation context root cannot be resolved");
|
|
@@ -61213,7 +61277,7 @@ class WorkitCore {
|
|
|
61213
61277
|
if (view.task.workspaceId !== view.workspace.id)
|
|
61214
61278
|
return failure("invalid_input", "task and workspace bindings are invalid");
|
|
61215
61279
|
try {
|
|
61216
|
-
if (
|
|
61280
|
+
if (realpathSync7(view.workspace.root) !== this.store.root)
|
|
61217
61281
|
return failure("invalid_input", "task view root does not match the task store");
|
|
61218
61282
|
} catch {
|
|
61219
61283
|
return failure("invalid_input", "task view root cannot be resolved");
|
|
@@ -61482,7 +61546,7 @@ function resolveGitRevision(root, value) {
|
|
|
61482
61546
|
}
|
|
61483
61547
|
}
|
|
61484
61548
|
function resolveInside(root, candidate) {
|
|
61485
|
-
const base =
|
|
61549
|
+
const base = realpathSync8(root);
|
|
61486
61550
|
const target = path22.resolve(base, candidate);
|
|
61487
61551
|
if (target !== base && !target.startsWith(base + path22.sep)) {
|
|
61488
61552
|
throw new Error("path must stay inside repository root");
|
|
@@ -61490,14 +61554,14 @@ function resolveInside(root, candidate) {
|
|
|
61490
61554
|
let ancestor = target;
|
|
61491
61555
|
while (!existsSync16(ancestor))
|
|
61492
61556
|
ancestor = path22.dirname(ancestor);
|
|
61493
|
-
const canonicalAncestor =
|
|
61557
|
+
const canonicalAncestor = realpathSync8(ancestor);
|
|
61494
61558
|
if (canonicalAncestor !== base && !canonicalAncestor.startsWith(base + path22.sep)) {
|
|
61495
61559
|
throw new Error("path must stay inside repository root");
|
|
61496
61560
|
}
|
|
61497
61561
|
return target;
|
|
61498
61562
|
}
|
|
61499
61563
|
function run(root, executable, args, env = {}) {
|
|
61500
|
-
const cwd =
|
|
61564
|
+
const cwd = realpathSync8(root);
|
|
61501
61565
|
const result = spawnSync4(executable, args, {
|
|
61502
61566
|
cwd,
|
|
61503
61567
|
encoding: "utf8",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brainervirus/workit-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Workit CLI — setup wizard, doctor, and task control for agentic coding workflows",
|
|
6
6
|
"keywords": [
|
|
@@ -37,9 +37,9 @@
|
|
|
37
37
|
"typecheck": "tsc --noEmit"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@brainervirus/workit-core": "^1.0.
|
|
41
|
-
"@brainervirus/workit-cursor": "^1.0.
|
|
42
|
-
"@brainervirus/workit-opencode": "^1.0.
|
|
40
|
+
"@brainervirus/workit-core": "^1.0.4",
|
|
41
|
+
"@brainervirus/workit-cursor": "^1.0.4",
|
|
42
|
+
"@brainervirus/workit-opencode": "^1.0.4",
|
|
43
43
|
"@inkjs/ui": "2.0.0",
|
|
44
44
|
"ink": "7.1.1",
|
|
45
45
|
"react": "19.2.8"
|