@brainervirus/workit-opencode 0.8.6 → 0.8.8
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/plugin.js +183 -22
- package/package.json +2 -2
package/dist/plugin.js
CHANGED
|
@@ -1132,10 +1132,22 @@ function isWorkitPlugin(value) {
|
|
|
1132
1132
|
const pkgPath = s.includes("/packages/workit-opencode/") || s.includes("/packages/workit-cursor/") || s.includes("/node_modules/@brainervirus/workit-opencode/") || s.includes("/node_modules/@brainervirus/workit-cursor/");
|
|
1133
1133
|
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");
|
|
1134
1134
|
}
|
|
1135
|
-
var CURSOR_RUNTIME_PACKAGE = "@brainervirus/workit-cursor@
|
|
1135
|
+
var CURSOR_RUNTIME_PACKAGE = "@brainervirus/workit-cursor@latest";
|
|
1136
|
+
function cursorMcpServerEntry(_packageDir) {
|
|
1137
|
+
return {
|
|
1138
|
+
command: "npx",
|
|
1139
|
+
args: [
|
|
1140
|
+
"-y",
|
|
1141
|
+
"--prefer-online",
|
|
1142
|
+
`--package=${CURSOR_RUNTIME_PACKAGE}`,
|
|
1143
|
+
"workit-cursor-mcp",
|
|
1144
|
+
"${workspaceFolder}"
|
|
1145
|
+
]
|
|
1146
|
+
};
|
|
1147
|
+
}
|
|
1136
1148
|
function cursorHooksEntry(_packageDir) {
|
|
1137
1149
|
return {
|
|
1138
|
-
command: `npx -y --package=${CURSOR_RUNTIME_PACKAGE} workit-cursor-session-start`,
|
|
1150
|
+
command: `npx -y --prefer-online --package=${CURSOR_RUNTIME_PACKAGE} workit-cursor-session-start`,
|
|
1139
1151
|
args: []
|
|
1140
1152
|
};
|
|
1141
1153
|
}
|
|
@@ -1505,12 +1517,9 @@ var registeredCursorLauncher = (res) => {
|
|
|
1505
1517
|
return "invalid";
|
|
1506
1518
|
}
|
|
1507
1519
|
const executable = path10.basename(command).toLowerCase();
|
|
1520
|
+
const canonical = cursorMcpServerEntry("").args;
|
|
1508
1521
|
if (executable === "npx" || executable === "npx.exe" || executable === "npx.cmd") {
|
|
1509
|
-
if (args
|
|
1510
|
-
return "invalid";
|
|
1511
|
-
if (args[1] !== `--package=${CURSOR_RUNTIME_PACKAGE}`)
|
|
1512
|
-
return "invalid";
|
|
1513
|
-
if (args[2] !== "workit-cursor-mcp")
|
|
1522
|
+
if (args.length !== canonical.length || args.some((a, i) => a !== canonical[i]))
|
|
1514
1523
|
return "invalid";
|
|
1515
1524
|
return { kind: "npx" };
|
|
1516
1525
|
}
|
|
@@ -1587,7 +1596,11 @@ var checkLauncher = (res) => {
|
|
|
1587
1596
|
detail: "no dev checkout found (WORKFLOW_TOOLKIT_DEV) — skipping non-Cursor launcher checks"
|
|
1588
1597
|
};
|
|
1589
1598
|
}
|
|
1590
|
-
return {
|
|
1599
|
+
return {
|
|
1600
|
+
id: "launcher",
|
|
1601
|
+
status: "pass",
|
|
1602
|
+
detail: `${res.host} launcher/hook entries present`
|
|
1603
|
+
};
|
|
1591
1604
|
};
|
|
1592
1605
|
var checkUtility = (res) => {
|
|
1593
1606
|
const git = commandOnPath("git", res.env);
|
|
@@ -1607,7 +1620,11 @@ var checkUtility = (res) => {
|
|
|
1607
1620
|
fix: "Install util-linux (flock)"
|
|
1608
1621
|
};
|
|
1609
1622
|
}
|
|
1610
|
-
return {
|
|
1623
|
+
return {
|
|
1624
|
+
id: "utility",
|
|
1625
|
+
status: "pass",
|
|
1626
|
+
detail: "git (and flock where required) on PATH"
|
|
1627
|
+
};
|
|
1611
1628
|
};
|
|
1612
1629
|
var staleEntry = (entry) => {
|
|
1613
1630
|
if (!entry)
|
|
@@ -1629,7 +1646,11 @@ var checkStalePin = (res) => {
|
|
|
1629
1646
|
};
|
|
1630
1647
|
}
|
|
1631
1648
|
if (!existsSync7(res.opencodeConfig)) {
|
|
1632
|
-
return {
|
|
1649
|
+
return {
|
|
1650
|
+
id: "stale_pin",
|
|
1651
|
+
status: "pass",
|
|
1652
|
+
detail: "no opencode config — not registered"
|
|
1653
|
+
};
|
|
1633
1654
|
}
|
|
1634
1655
|
const cfg = readJson(res.opencodeConfig);
|
|
1635
1656
|
const entries = pluginEntries(cfg);
|
|
@@ -1660,6 +1681,118 @@ var checkStalePin = (res) => {
|
|
|
1660
1681
|
}
|
|
1661
1682
|
return { id: "stale_pin", status: "pass", detail: "opencode pin resolves" };
|
|
1662
1683
|
};
|
|
1684
|
+
var pluginMcpSelectors = (res) => {
|
|
1685
|
+
const p = path10.join(res.cursorPluginDir, "mcp.json");
|
|
1686
|
+
if (!existsSync7(p))
|
|
1687
|
+
return null;
|
|
1688
|
+
const cfg = readJson(p);
|
|
1689
|
+
const server = cfg?.mcpServers?.workit;
|
|
1690
|
+
if (!server || typeof server !== "object" || Array.isArray(server))
|
|
1691
|
+
return null;
|
|
1692
|
+
const args = server.args;
|
|
1693
|
+
if (!Array.isArray(args))
|
|
1694
|
+
return null;
|
|
1695
|
+
return args.map(String).filter((a) => a.startsWith("--package="));
|
|
1696
|
+
};
|
|
1697
|
+
var registryLatestVersion = (res) => {
|
|
1698
|
+
const seam = res.env.WORKIT_DOCTOR_STALE_REGISTRY_VERSION;
|
|
1699
|
+
if (typeof seam === "string" && seam) {
|
|
1700
|
+
return /^\d+(?:\.\d+){1,2}$/.test(seam) ? seam : null;
|
|
1701
|
+
}
|
|
1702
|
+
const cmd = res.env.WORKIT_DOCTOR_STALE_REGISTRY_CMD ?? (commandOnPath("npm", res.env) ? "npm" : null);
|
|
1703
|
+
if (!cmd)
|
|
1704
|
+
return null;
|
|
1705
|
+
try {
|
|
1706
|
+
const r = spawnSync2(cmd, ["view", CURSOR_RUNTIME_PACKAGE, "version"], {
|
|
1707
|
+
encoding: "utf8",
|
|
1708
|
+
timeout: 20000,
|
|
1709
|
+
env: res.env
|
|
1710
|
+
});
|
|
1711
|
+
const v = (r.stdout ?? "").trim().split(/\s+/)[0];
|
|
1712
|
+
return r.status === 0 && /^\d+(?:\.\d+){1,2}$/.test(v) ? v : null;
|
|
1713
|
+
} catch {
|
|
1714
|
+
return null;
|
|
1715
|
+
}
|
|
1716
|
+
};
|
|
1717
|
+
var installedPluginVersion = (res) => {
|
|
1718
|
+
const pkg = readJson(path10.join(res.cursorPluginDir, "package.json"));
|
|
1719
|
+
return typeof pkg?.version === "string" && pkg.version ? pkg.version : null;
|
|
1720
|
+
};
|
|
1721
|
+
var checkStaleInstall = (res) => {
|
|
1722
|
+
if (res.host !== "cursor" && res.host !== "cli") {
|
|
1723
|
+
return {
|
|
1724
|
+
id: "stale_install",
|
|
1725
|
+
status: "pass",
|
|
1726
|
+
detail: "cursor plugin not inspected on the opencode host"
|
|
1727
|
+
};
|
|
1728
|
+
}
|
|
1729
|
+
const canonicalMcp = cursorMcpServerEntry("").args.find((a) => a.startsWith("--package="));
|
|
1730
|
+
const mcpSelectors = pluginMcpSelectors(res);
|
|
1731
|
+
const legacyPin = (mcpSelectors ?? []).find((s) => s !== canonicalMcp && s.includes("@brainervirus/workit-cursor@"));
|
|
1732
|
+
if (legacyPin) {
|
|
1733
|
+
return {
|
|
1734
|
+
id: "stale_install",
|
|
1735
|
+
status: "fail",
|
|
1736
|
+
detail: `stale_install: plugin mcp.json pins a legacy selector ${legacyPin} (canonical: ${canonicalMcp})`,
|
|
1737
|
+
fix: "Re-run install-cursor-plugin.sh — it rewrites the workit MCP entry to the canonical @latest selector"
|
|
1738
|
+
};
|
|
1739
|
+
}
|
|
1740
|
+
const hooksFile = path10.join(res.cursorPluginDir, "hooks", "hooks-cursor.json");
|
|
1741
|
+
const hookCmd = readJson(hooksFile)?.hooks?.sessionStart?.[0]?.command ?? null;
|
|
1742
|
+
const canonicalHook = canonicalCursorHook;
|
|
1743
|
+
const staleHook = hookCmd !== null && hookCmd !== canonicalHook && !hookCmd.startsWith("node ") && hookCmd.includes("@brainervirus/workit-cursor@");
|
|
1744
|
+
if (staleHook) {
|
|
1745
|
+
return {
|
|
1746
|
+
id: "stale_install",
|
|
1747
|
+
status: "fail",
|
|
1748
|
+
detail: `stale_install: sessionStart hook runs a legacy selector (canonical: ${canonicalHook})`,
|
|
1749
|
+
fix: "Re-run install-cursor-plugin.sh — it rewrites the sessionStart hook to the canonical @latest selector"
|
|
1750
|
+
};
|
|
1751
|
+
}
|
|
1752
|
+
const installed = installedPluginVersion(res);
|
|
1753
|
+
const source = res.dev ? readJson(path10.join(res.dev, "packages/workit-cursor/package.json"))?.version ?? null : readJson(path10.join(packageRoot(), "package.json"))?.version ?? null;
|
|
1754
|
+
const localDist = mcpSelectors === null && hookCmd !== null && hookCmd.startsWith("node ");
|
|
1755
|
+
if (localDist && installed !== null && source !== null && !semverAtLeast(installed, source)) {
|
|
1756
|
+
return {
|
|
1757
|
+
id: "stale_install",
|
|
1758
|
+
status: "fail",
|
|
1759
|
+
detail: `stale_install: installed workit-cursor ${installed} is behind the current runtime ${source}`,
|
|
1760
|
+
fix: "Re-run install-cursor-plugin.sh — it refreshes the plugin directory and rewrites the workit MCP/hook entries"
|
|
1761
|
+
};
|
|
1762
|
+
}
|
|
1763
|
+
if (installed !== null && localDist) {
|
|
1764
|
+
const expected = registryLatestVersion(res);
|
|
1765
|
+
if (expected === null) {
|
|
1766
|
+
return {
|
|
1767
|
+
id: "registry_unreachable",
|
|
1768
|
+
status: "warn",
|
|
1769
|
+
registryProbed: true,
|
|
1770
|
+
detail: "registry_unreachable: cannot compare installed workit-cursor against the published runtime",
|
|
1771
|
+
fix: "Retry when the npm registry is reachable, or re-run install-cursor-plugin.sh to refresh the install"
|
|
1772
|
+
};
|
|
1773
|
+
}
|
|
1774
|
+
if (!semverAtLeast(installed, expected)) {
|
|
1775
|
+
return {
|
|
1776
|
+
id: "stale_install",
|
|
1777
|
+
status: "fail",
|
|
1778
|
+
registryProbed: true,
|
|
1779
|
+
detail: `stale_install: local-dist workit-cursor ${installed} is behind the published runtime ${expected}`,
|
|
1780
|
+
fix: "Re-run install-cursor-plugin.sh — it refreshes the plugin directory with the current build"
|
|
1781
|
+
};
|
|
1782
|
+
}
|
|
1783
|
+
return {
|
|
1784
|
+
id: "stale_install",
|
|
1785
|
+
status: "pass",
|
|
1786
|
+
registryProbed: true,
|
|
1787
|
+
detail: `installed local-dist workit-cursor ${installed} matches the published runtime ${expected}`
|
|
1788
|
+
};
|
|
1789
|
+
}
|
|
1790
|
+
return {
|
|
1791
|
+
id: "stale_install",
|
|
1792
|
+
status: "pass",
|
|
1793
|
+
detail: installed === null ? "installed workit-cursor selectors are canonical" : `installed workit-cursor ${installed} is metadata on the canonical @latest install (fresh at launch)`
|
|
1794
|
+
};
|
|
1795
|
+
};
|
|
1663
1796
|
var checkDuplicateRegistration = (res) => {
|
|
1664
1797
|
const problems = [];
|
|
1665
1798
|
const opencodeHost = res.host !== "cursor";
|
|
@@ -1695,7 +1828,11 @@ var checkDuplicateRegistration = (res) => {
|
|
|
1695
1828
|
}
|
|
1696
1829
|
}
|
|
1697
1830
|
if (problems.length === 0) {
|
|
1698
|
-
return {
|
|
1831
|
+
return {
|
|
1832
|
+
id: "duplicate_registration",
|
|
1833
|
+
status: "pass",
|
|
1834
|
+
detail: "no duplicate registrations"
|
|
1835
|
+
};
|
|
1699
1836
|
}
|
|
1700
1837
|
return {
|
|
1701
1838
|
id: "duplicate_registration",
|
|
@@ -1721,7 +1858,11 @@ var checkMalformedConfig = (res) => {
|
|
|
1721
1858
|
files.push(res.cursorMcp);
|
|
1722
1859
|
const bad = files.filter((p) => !parsesAsConfigObject(p));
|
|
1723
1860
|
if (bad.length === 0)
|
|
1724
|
-
return {
|
|
1861
|
+
return {
|
|
1862
|
+
id: "malformed_config",
|
|
1863
|
+
status: "pass",
|
|
1864
|
+
detail: "config files parse"
|
|
1865
|
+
};
|
|
1725
1866
|
return {
|
|
1726
1867
|
id: "malformed_config",
|
|
1727
1868
|
status: "fail",
|
|
@@ -1732,10 +1873,18 @@ var checkMalformedConfig = (res) => {
|
|
|
1732
1873
|
var checkWorkspaceMismatch = (res) => {
|
|
1733
1874
|
const file = path10.join(res.configDir, "workspaces.json");
|
|
1734
1875
|
if (!existsSync7(file))
|
|
1735
|
-
return {
|
|
1876
|
+
return {
|
|
1877
|
+
id: "workspace_mismatch",
|
|
1878
|
+
status: "pass",
|
|
1879
|
+
detail: "no workspaces configured"
|
|
1880
|
+
};
|
|
1736
1881
|
const ws = readJson(file);
|
|
1737
1882
|
if (!Array.isArray(ws?.workspaces)) {
|
|
1738
|
-
return {
|
|
1883
|
+
return {
|
|
1884
|
+
id: "workspace_mismatch",
|
|
1885
|
+
status: "pass",
|
|
1886
|
+
detail: "no workspaces configured"
|
|
1887
|
+
};
|
|
1739
1888
|
}
|
|
1740
1889
|
const match = resolveWorkspaceFrom(res.cwd, res.configDir);
|
|
1741
1890
|
if (match)
|
|
@@ -1777,7 +1926,11 @@ var checkCredentialMetadata = (res) => {
|
|
|
1777
1926
|
}
|
|
1778
1927
|
}
|
|
1779
1928
|
if (tokenPaths.length === 0) {
|
|
1780
|
-
return {
|
|
1929
|
+
return {
|
|
1930
|
+
id: "credential_metadata",
|
|
1931
|
+
status: "pass",
|
|
1932
|
+
detail: "no credentials configured"
|
|
1933
|
+
};
|
|
1781
1934
|
}
|
|
1782
1935
|
const problems = [];
|
|
1783
1936
|
for (const raw of tokenPaths) {
|
|
@@ -1815,7 +1968,11 @@ var checkLogWritable = (res) => {
|
|
|
1815
1968
|
mkdirSync3(logsDir, { recursive: true, mode: 448 });
|
|
1816
1969
|
writeFileSync6(probe, `{"probe":true}
|
|
1817
1970
|
`, { mode: 384 });
|
|
1818
|
-
return {
|
|
1971
|
+
return {
|
|
1972
|
+
id: "log_writable",
|
|
1973
|
+
status: "pass",
|
|
1974
|
+
detail: "log directory writable"
|
|
1975
|
+
};
|
|
1819
1976
|
} catch (err) {
|
|
1820
1977
|
return {
|
|
1821
1978
|
id: "log_writable",
|
|
@@ -1836,6 +1993,7 @@ var RUN_CHECKS = [
|
|
|
1836
1993
|
checkLauncher,
|
|
1837
1994
|
checkUtility,
|
|
1838
1995
|
checkStalePin,
|
|
1996
|
+
checkStaleInstall,
|
|
1839
1997
|
checkDuplicateRegistration,
|
|
1840
1998
|
checkMalformedConfig,
|
|
1841
1999
|
checkWorkspaceMismatch,
|
|
@@ -1848,21 +2006,27 @@ var INSTALLER_REQUIRED = new Set([
|
|
|
1848
2006
|
"launcher",
|
|
1849
2007
|
"utility",
|
|
1850
2008
|
"stale_pin",
|
|
2009
|
+
"stale_install",
|
|
1851
2010
|
"duplicate_registration",
|
|
1852
2011
|
"malformed_config"
|
|
1853
2012
|
]);
|
|
1854
2013
|
var runDoctor = (options = {}) => {
|
|
1855
2014
|
const res = resolve(options);
|
|
1856
2015
|
const raw = RUN_CHECKS.map((fn) => fn(res));
|
|
1857
|
-
const checks = res.installer ? raw.map((c) => c.status === "fail" && !INSTALLER_REQUIRED.has(c.id) ? {
|
|
2016
|
+
const checks = res.installer ? raw.map((c) => c.status === "fail" && !INSTALLER_REQUIRED.has(c.id) ? {
|
|
2017
|
+
...c,
|
|
2018
|
+
status: "warn",
|
|
2019
|
+
detail: `${c.detail} (not enforced by installer)`
|
|
2020
|
+
} : c) : raw;
|
|
1858
2021
|
const failed = checks.filter((c) => c.status === "fail").length;
|
|
1859
2022
|
const warned = checks.filter((c) => c.status === "warn").length;
|
|
1860
2023
|
const passed = checks.filter((c) => c.status === "pass").length;
|
|
1861
2024
|
const exitCode = failed > 0 ? 1 : 0;
|
|
2025
|
+
const offline = !raw.some((c) => ("registryProbed" in c) && c.registryProbed);
|
|
1862
2026
|
const report = {
|
|
1863
2027
|
ok: failed === 0,
|
|
1864
2028
|
exitCode,
|
|
1865
|
-
offline
|
|
2029
|
+
offline,
|
|
1866
2030
|
host: res.host,
|
|
1867
2031
|
checked_at: new Date().toISOString(),
|
|
1868
2032
|
summary: { passed, warned, failed, total: checks.length },
|
|
@@ -1872,7 +2036,7 @@ var runDoctor = (options = {}) => {
|
|
|
1872
2036
|
getDiagnosticLogger()?.info(EVENT.doctor, {
|
|
1873
2037
|
host: res.host,
|
|
1874
2038
|
exit_code: exitCode,
|
|
1875
|
-
offline
|
|
2039
|
+
offline,
|
|
1876
2040
|
failed: checks.filter((c) => c.status === "fail").map((c) => c.id),
|
|
1877
2041
|
total: checks.length
|
|
1878
2042
|
});
|
|
@@ -5376,9 +5540,6 @@ var resetForSpecDrift = (state) => ({
|
|
|
5376
5540
|
var resetForPlanDrift = (state) => ({
|
|
5377
5541
|
...state,
|
|
5378
5542
|
plan: { ...state.plan, status: "draft", evidence: null, approved_digest: null },
|
|
5379
|
-
menu: { presented: false, chosen: "", evidence: null },
|
|
5380
|
-
execution: { status: "pending", mode: null, evidence: null },
|
|
5381
|
-
handoff_destination: false,
|
|
5382
5543
|
updated_at: Date.now()
|
|
5383
5544
|
});
|
|
5384
5545
|
var driftCodeFor = (root2, relPath, storedDigest) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brainervirus/workit-opencode",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.8",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Workit OpenCode plugin (thin wrapper over @brainervirus/workit-core)",
|
|
6
6
|
"keywords": [
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"typecheck": "tsc --noEmit"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@brainervirus/workit-core": "^0.8.
|
|
37
|
+
"@brainervirus/workit-core": "^0.8.8"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@opencode-ai/plugin": "1.17.7"
|