@brainervirus/workit-opencode 0.8.7 → 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 +167 -12
- package/package.json +2 -2
package/dist/plugin.js
CHANGED
|
@@ -1596,7 +1596,11 @@ var checkLauncher = (res) => {
|
|
|
1596
1596
|
detail: "no dev checkout found (WORKFLOW_TOOLKIT_DEV) — skipping non-Cursor launcher checks"
|
|
1597
1597
|
};
|
|
1598
1598
|
}
|
|
1599
|
-
return {
|
|
1599
|
+
return {
|
|
1600
|
+
id: "launcher",
|
|
1601
|
+
status: "pass",
|
|
1602
|
+
detail: `${res.host} launcher/hook entries present`
|
|
1603
|
+
};
|
|
1600
1604
|
};
|
|
1601
1605
|
var checkUtility = (res) => {
|
|
1602
1606
|
const git = commandOnPath("git", res.env);
|
|
@@ -1616,7 +1620,11 @@ var checkUtility = (res) => {
|
|
|
1616
1620
|
fix: "Install util-linux (flock)"
|
|
1617
1621
|
};
|
|
1618
1622
|
}
|
|
1619
|
-
return {
|
|
1623
|
+
return {
|
|
1624
|
+
id: "utility",
|
|
1625
|
+
status: "pass",
|
|
1626
|
+
detail: "git (and flock where required) on PATH"
|
|
1627
|
+
};
|
|
1620
1628
|
};
|
|
1621
1629
|
var staleEntry = (entry) => {
|
|
1622
1630
|
if (!entry)
|
|
@@ -1638,7 +1646,11 @@ var checkStalePin = (res) => {
|
|
|
1638
1646
|
};
|
|
1639
1647
|
}
|
|
1640
1648
|
if (!existsSync7(res.opencodeConfig)) {
|
|
1641
|
-
return {
|
|
1649
|
+
return {
|
|
1650
|
+
id: "stale_pin",
|
|
1651
|
+
status: "pass",
|
|
1652
|
+
detail: "no opencode config — not registered"
|
|
1653
|
+
};
|
|
1642
1654
|
}
|
|
1643
1655
|
const cfg = readJson(res.opencodeConfig);
|
|
1644
1656
|
const entries = pluginEntries(cfg);
|
|
@@ -1669,6 +1681,118 @@ var checkStalePin = (res) => {
|
|
|
1669
1681
|
}
|
|
1670
1682
|
return { id: "stale_pin", status: "pass", detail: "opencode pin resolves" };
|
|
1671
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
|
+
};
|
|
1672
1796
|
var checkDuplicateRegistration = (res) => {
|
|
1673
1797
|
const problems = [];
|
|
1674
1798
|
const opencodeHost = res.host !== "cursor";
|
|
@@ -1704,7 +1828,11 @@ var checkDuplicateRegistration = (res) => {
|
|
|
1704
1828
|
}
|
|
1705
1829
|
}
|
|
1706
1830
|
if (problems.length === 0) {
|
|
1707
|
-
return {
|
|
1831
|
+
return {
|
|
1832
|
+
id: "duplicate_registration",
|
|
1833
|
+
status: "pass",
|
|
1834
|
+
detail: "no duplicate registrations"
|
|
1835
|
+
};
|
|
1708
1836
|
}
|
|
1709
1837
|
return {
|
|
1710
1838
|
id: "duplicate_registration",
|
|
@@ -1730,7 +1858,11 @@ var checkMalformedConfig = (res) => {
|
|
|
1730
1858
|
files.push(res.cursorMcp);
|
|
1731
1859
|
const bad = files.filter((p) => !parsesAsConfigObject(p));
|
|
1732
1860
|
if (bad.length === 0)
|
|
1733
|
-
return {
|
|
1861
|
+
return {
|
|
1862
|
+
id: "malformed_config",
|
|
1863
|
+
status: "pass",
|
|
1864
|
+
detail: "config files parse"
|
|
1865
|
+
};
|
|
1734
1866
|
return {
|
|
1735
1867
|
id: "malformed_config",
|
|
1736
1868
|
status: "fail",
|
|
@@ -1741,10 +1873,18 @@ var checkMalformedConfig = (res) => {
|
|
|
1741
1873
|
var checkWorkspaceMismatch = (res) => {
|
|
1742
1874
|
const file = path10.join(res.configDir, "workspaces.json");
|
|
1743
1875
|
if (!existsSync7(file))
|
|
1744
|
-
return {
|
|
1876
|
+
return {
|
|
1877
|
+
id: "workspace_mismatch",
|
|
1878
|
+
status: "pass",
|
|
1879
|
+
detail: "no workspaces configured"
|
|
1880
|
+
};
|
|
1745
1881
|
const ws = readJson(file);
|
|
1746
1882
|
if (!Array.isArray(ws?.workspaces)) {
|
|
1747
|
-
return {
|
|
1883
|
+
return {
|
|
1884
|
+
id: "workspace_mismatch",
|
|
1885
|
+
status: "pass",
|
|
1886
|
+
detail: "no workspaces configured"
|
|
1887
|
+
};
|
|
1748
1888
|
}
|
|
1749
1889
|
const match = resolveWorkspaceFrom(res.cwd, res.configDir);
|
|
1750
1890
|
if (match)
|
|
@@ -1786,7 +1926,11 @@ var checkCredentialMetadata = (res) => {
|
|
|
1786
1926
|
}
|
|
1787
1927
|
}
|
|
1788
1928
|
if (tokenPaths.length === 0) {
|
|
1789
|
-
return {
|
|
1929
|
+
return {
|
|
1930
|
+
id: "credential_metadata",
|
|
1931
|
+
status: "pass",
|
|
1932
|
+
detail: "no credentials configured"
|
|
1933
|
+
};
|
|
1790
1934
|
}
|
|
1791
1935
|
const problems = [];
|
|
1792
1936
|
for (const raw of tokenPaths) {
|
|
@@ -1824,7 +1968,11 @@ var checkLogWritable = (res) => {
|
|
|
1824
1968
|
mkdirSync3(logsDir, { recursive: true, mode: 448 });
|
|
1825
1969
|
writeFileSync6(probe, `{"probe":true}
|
|
1826
1970
|
`, { mode: 384 });
|
|
1827
|
-
return {
|
|
1971
|
+
return {
|
|
1972
|
+
id: "log_writable",
|
|
1973
|
+
status: "pass",
|
|
1974
|
+
detail: "log directory writable"
|
|
1975
|
+
};
|
|
1828
1976
|
} catch (err) {
|
|
1829
1977
|
return {
|
|
1830
1978
|
id: "log_writable",
|
|
@@ -1845,6 +1993,7 @@ var RUN_CHECKS = [
|
|
|
1845
1993
|
checkLauncher,
|
|
1846
1994
|
checkUtility,
|
|
1847
1995
|
checkStalePin,
|
|
1996
|
+
checkStaleInstall,
|
|
1848
1997
|
checkDuplicateRegistration,
|
|
1849
1998
|
checkMalformedConfig,
|
|
1850
1999
|
checkWorkspaceMismatch,
|
|
@@ -1857,21 +2006,27 @@ var INSTALLER_REQUIRED = new Set([
|
|
|
1857
2006
|
"launcher",
|
|
1858
2007
|
"utility",
|
|
1859
2008
|
"stale_pin",
|
|
2009
|
+
"stale_install",
|
|
1860
2010
|
"duplicate_registration",
|
|
1861
2011
|
"malformed_config"
|
|
1862
2012
|
]);
|
|
1863
2013
|
var runDoctor = (options = {}) => {
|
|
1864
2014
|
const res = resolve(options);
|
|
1865
2015
|
const raw = RUN_CHECKS.map((fn) => fn(res));
|
|
1866
|
-
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;
|
|
1867
2021
|
const failed = checks.filter((c) => c.status === "fail").length;
|
|
1868
2022
|
const warned = checks.filter((c) => c.status === "warn").length;
|
|
1869
2023
|
const passed = checks.filter((c) => c.status === "pass").length;
|
|
1870
2024
|
const exitCode = failed > 0 ? 1 : 0;
|
|
2025
|
+
const offline = !raw.some((c) => ("registryProbed" in c) && c.registryProbed);
|
|
1871
2026
|
const report = {
|
|
1872
2027
|
ok: failed === 0,
|
|
1873
2028
|
exitCode,
|
|
1874
|
-
offline
|
|
2029
|
+
offline,
|
|
1875
2030
|
host: res.host,
|
|
1876
2031
|
checked_at: new Date().toISOString(),
|
|
1877
2032
|
summary: { passed, warned, failed, total: checks.length },
|
|
@@ -1881,7 +2036,7 @@ var runDoctor = (options = {}) => {
|
|
|
1881
2036
|
getDiagnosticLogger()?.info(EVENT.doctor, {
|
|
1882
2037
|
host: res.host,
|
|
1883
2038
|
exit_code: exitCode,
|
|
1884
|
-
offline
|
|
2039
|
+
offline,
|
|
1885
2040
|
failed: checks.filter((c) => c.status === "fail").map((c) => c.id),
|
|
1886
2041
|
total: checks.length
|
|
1887
2042
|
});
|
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"
|