opencode-rules-md 0.8.5 → 0.8.6
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/cli.mjs +252 -261
- package/dist/src/cli/config.d.ts +11 -0
- package/dist/src/cli/config.d.ts.map +1 -1
- package/dist/src/cli/config.js +15 -0
- package/dist/src/cli/config.js.map +1 -1
- package/dist/src/cli/install.d.ts +35 -20
- package/dist/src/cli/install.d.ts.map +1 -1
- package/dist/src/cli/install.js +50 -131
- package/dist/src/cli/install.js.map +1 -1
- package/dist/src/cli/main.d.ts +5 -0
- package/dist/src/cli/main.d.ts.map +1 -1
- package/dist/src/cli/main.js +29 -26
- package/dist/src/cli/main.js.map +1 -1
- package/dist/src/cli/spawn.d.ts +29 -0
- package/dist/src/cli/spawn.d.ts.map +1 -0
- package/dist/src/cli/spawn.js +48 -0
- package/dist/src/cli/spawn.js.map +1 -0
- package/dist/src/cli/status.d.ts +15 -8
- package/dist/src/cli/status.d.ts.map +1 -1
- package/dist/src/cli/status.js +63 -31
- package/dist/src/cli/status.js.map +1 -1
- package/dist/src/cli/uninstall.d.ts +5 -2
- package/dist/src/cli/uninstall.d.ts.map +1 -1
- package/dist/src/cli/uninstall.js +78 -51
- package/dist/src/cli/uninstall.js.map +1 -1
- package/dist/src/cli/update.d.ts +50 -16
- package/dist/src/cli/update.d.ts.map +1 -1
- package/dist/src/cli/update.js +156 -124
- package/dist/src/cli/update.js.map +1 -1
- package/package.json +1 -1
- package/src/cli/config.ts +19 -0
- package/src/cli/install.ts +66 -174
- package/src/cli/main.ts +34 -25
- package/src/cli/spawn.ts +76 -0
- package/src/cli/status.ts +83 -37
- package/src/cli/uninstall.ts +88 -57
- package/src/cli/update.ts +182 -148
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spawn.d.ts","sourceRoot":"","sources":["../../../src/cli/spawn.ts"],"names":[],"mappings":"AAiBA,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B;AAED,MAAM,MAAM,OAAO,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,YAAY,KAAK,WAAW,CAAC;AAE9F,MAAM,WAAW,0BAA0B;IACzC,mFAAmF;IACnF,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,kFAAkF;IAClF,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,iFAAiF;IACjF,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B;AAED;;;;;;;;GAQG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,EAAE,EACd,IAAI,GAAE,0BAA+B,GACpC,OAAO,CAAC,WAAW,CAAC,CAKtB"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// src/cli/spawn.ts — thin wrapper around `opencode plugin`.
|
|
3
|
+
//
|
|
4
|
+
// Why a wrapper? Two reasons:
|
|
5
|
+
// 1. OpenCode owns the schema for `data['plugin']` (singular) and the cache
|
|
6
|
+
// layout under ~/.cache/opencode/packages/. Re-implementing that logic
|
|
7
|
+
// drift-prone (the bug we are fixing). Delegating to OpenCode's own CLI
|
|
8
|
+
// keeps us correct by construction.
|
|
9
|
+
// 2. Tests need a deterministic, non-blocking seam. Defaulting to
|
|
10
|
+
// spawnSync with `stdio: 'inherit'` lets the real CLI talk directly to
|
|
11
|
+
// the user's terminal; tests inject a stub that returns canned output.
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
import { createRequire } from 'node:module';
|
|
14
|
+
const require = createRequire(import.meta.url);
|
|
15
|
+
/**
|
|
16
|
+
* Run `opencode plugin <args...>` and return the exit status plus captured
|
|
17
|
+
* stdout/stderr (only populated when `stdio: 'pipe'`).
|
|
18
|
+
*
|
|
19
|
+
* The default implementation uses spawnSync so the call blocks until the
|
|
20
|
+
* child process exits. This keeps `omd install` simple — the user's shell
|
|
21
|
+
* stays put until registration completes, then returns control with a
|
|
22
|
+
* non-zero status on failure.
|
|
23
|
+
*/
|
|
24
|
+
export async function spawnOpencodePlugin(args, opts = {}) {
|
|
25
|
+
const env = opts.env ?? process.env;
|
|
26
|
+
const stdio = opts.stdio ?? 'inherit';
|
|
27
|
+
const spawnFn = opts.spawn ?? defaultSpawn;
|
|
28
|
+
return spawnFn('opencode', ['plugin', ...args], { env, stdio });
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Default spawn implementation backed by node:child_process.spawnSync.
|
|
32
|
+
*
|
|
33
|
+
* The require is loaded lazily so test doubles can replace the spawn
|
|
34
|
+
* function entirely without ever touching node:child_process.
|
|
35
|
+
*/
|
|
36
|
+
function defaultSpawn(command, args, options) {
|
|
37
|
+
const cp = require('node:child_process');
|
|
38
|
+
const result = cp.spawnSync(command, args, {
|
|
39
|
+
env: options.env,
|
|
40
|
+
stdio: options.stdio,
|
|
41
|
+
});
|
|
42
|
+
return {
|
|
43
|
+
status: result.status,
|
|
44
|
+
stdout: result.stdout?.toString() ?? '',
|
|
45
|
+
stderr: result.stderr?.toString() ?? '',
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=spawn.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spawn.js","sourceRoot":"","sources":["../../../src/cli/spawn.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,4DAA4D;AAC5D,EAAE;AACF,8BAA8B;AAC9B,8EAA8E;AAC9E,4EAA4E;AAC5E,6EAA6E;AAC7E,yCAAyC;AACzC,oEAAoE;AACpE,4EAA4E;AAC5E,4EAA4E;AAC5E,8EAA8E;AAE9E,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAwB/C;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,IAAc,EACd,OAAmC,EAAE;IAErC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;IACpC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,SAAS,CAAC;IACtC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,IAAI,YAAY,CAAC;IAC3C,OAAO,OAAO,CAAC,UAAU,EAAE,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;AAClE,CAAC;AAED;;;;;GAKG;AACH,SAAS,YAAY,CAAC,OAAe,EAAE,IAAc,EAAE,OAAqB;IAC1E,MAAM,EAAE,GAAG,OAAO,CAAC,oBAAoB,CAAwC,CAAC;IAChF,MAAM,MAAM,GAAG,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE;QACzC,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,KAAK,EAAE,OAAO,CAAC,KAAK;KACrB,CAAC,CAAC;IACH,OAAO;QACL,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;QACvC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;KACxC,CAAC;AACJ,CAAC"}
|
package/dist/src/cli/status.d.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { type CliFs } from './config.js';
|
|
2
|
+
export interface StatusOptions {
|
|
3
|
+
/** Override latest version for testing — skips the npm registry call */
|
|
4
|
+
latestVersion?: string | null;
|
|
5
|
+
}
|
|
2
6
|
export interface StatusEntry {
|
|
3
7
|
basename: string;
|
|
4
8
|
path: string;
|
|
@@ -27,16 +31,19 @@ export interface DoctorResult {
|
|
|
27
31
|
* Run the status command: read-only probe for both opencode.json and tui.json.
|
|
28
32
|
* Reports path, format, installed specifier, other plugins, and freshness.
|
|
29
33
|
*/
|
|
30
|
-
export declare const runStatus: (fs: CliFs, env: NodeJS.ProcessEnv, log: (s: string) => void) => Promise<StatusResult>;
|
|
34
|
+
export declare const runStatus: (fs: CliFs, env: NodeJS.ProcessEnv, log: (s: string) => void, opts?: StatusOptions) => Promise<StatusResult>;
|
|
31
35
|
/**
|
|
32
36
|
* Run the doctor command: health checks for the plugin environment.
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
37
|
+
*
|
|
38
|
+
* Checks:
|
|
39
|
+
* - Node >= 20: issue if below
|
|
40
|
+
* - Bun on PATH: issue if absent
|
|
41
|
+
* - Both configs readable and valid: issue if absent or malformed
|
|
42
|
+
* - Legacy `plugins` field present: warning (no-op for the runtime, but
|
|
43
|
+
* indicates a previous buggy install)
|
|
44
|
+
* - Rule dir existence: warning if absent
|
|
45
|
+
* - Config dir writable: issue if not writable
|
|
46
|
+
* - Package freshness: info line about update availability
|
|
40
47
|
*
|
|
41
48
|
* Exit 1 if any issues found.
|
|
42
49
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/cli/status.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/cli/status.ts"],"names":[],"mappings":"AAiBA,OAAO,EAIL,KAAK,KAAK,EAEX,MAAM,aAAa,CAAC;AAMrB,MAAM,WAAW,aAAa;IAC5B,wEAAwE;IACxE,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,WAAW,EAAE,CAAC;CACxB;AAID,MAAM,WAAW,aAAa;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAWD;;;GAGG;AACH,eAAO,MAAM,SAAS,GACpB,IAAI,KAAK,EACT,KAAK,MAAM,CAAC,UAAU,EACtB,KAAK,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,EACxB,OAAM,aAAkB,KACvB,OAAO,CAAC,YAAY,CAoDtB,CAAC;AAIF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,SAAS,GACpB,IAAI,KAAK,EACT,KAAK,MAAM,CAAC,UAAU,EACtB,KAAK,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,EACxB,OAAO,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,EAC1B,OAAM,aAAkB,KACvB,OAAO,CAAC,YAAY,CAqItB,CAAC"}
|
package/dist/src/cli/status.js
CHANGED
|
@@ -1,15 +1,22 @@
|
|
|
1
1
|
// ---------------------------------------------------------------------------
|
|
2
2
|
// src/cli/status.ts — `omd status` and `omd doctor` command implementations.
|
|
3
3
|
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
4
|
+
// Three correctness fixes vs. the previous implementation:
|
|
5
|
+
//
|
|
6
|
+
// 1. We read `data['plugin']` (singular) as the source of truth, with a
|
|
7
|
+
// backward-compat fallback to `data['plugins']`. The legacy plural
|
|
8
|
+
// field is no longer authoritative.
|
|
9
|
+
// 2. `runDoctor` warns when a legacy `plugins` field is present, so users
|
|
10
|
+
// upgrading from the buggy version are nudged to clean up.
|
|
11
|
+
// 3. The cache freshness check uses ~/.cache/opencode/packages/ (where
|
|
12
|
+
// OpenCode actually stores plugin installs) instead of the legacy
|
|
13
|
+
// ~/.cache/opencode/node_modules/ path.
|
|
7
14
|
// ---------------------------------------------------------------------------
|
|
8
|
-
import { join, dirname } from 'path';
|
|
15
|
+
import { join, dirname, extname } from 'path';
|
|
9
16
|
import { homedir } from 'os';
|
|
10
|
-
import {
|
|
11
|
-
import { loadGlobalConfig, matchesPlugin, normalizePlugin, } from './config.js';
|
|
17
|
+
import { loadGlobalConfig, matchesPlugin, readInstalledPlugins, } from './config.js';
|
|
12
18
|
import { fetchLatestVersion } from './registry.js';
|
|
19
|
+
import { resolveCachePaths } from './update.js';
|
|
13
20
|
// ─── Constants ───────────────────────────────────────────────────────────────
|
|
14
21
|
const RULE_DIR_NAME = 'opencode-rules-md';
|
|
15
22
|
const MIN_NODE_VERSION = 20;
|
|
@@ -19,26 +26,29 @@ const CONFIG_BASENAMES = ['opencode', 'tui'];
|
|
|
19
26
|
* Run the status command: read-only probe for both opencode.json and tui.json.
|
|
20
27
|
* Reports path, format, installed specifier, other plugins, and freshness.
|
|
21
28
|
*/
|
|
22
|
-
export const runStatus = async (fs, env, log) => {
|
|
29
|
+
export const runStatus = async (fs, env, log, opts = {}) => {
|
|
23
30
|
const configs = [];
|
|
24
|
-
const latest =
|
|
31
|
+
const latest = opts.latestVersion !== undefined
|
|
32
|
+
? opts.latestVersion
|
|
33
|
+
: await fetchLatestVersion();
|
|
25
34
|
for (const basename of CONFIG_BASENAMES) {
|
|
26
35
|
const loaded = loadGlobalConfig(fs, env, basename);
|
|
27
36
|
const format = extname(loaded.path); // '.json' or '.jsonc'
|
|
28
|
-
const plugins =
|
|
29
|
-
const match = plugins.find(p => matchesPlugin(p));
|
|
37
|
+
const plugins = readInstalledPlugins(loaded);
|
|
38
|
+
const match = plugins.find((p) => matchesPlugin(p)) ?? null;
|
|
30
39
|
const entry = {
|
|
31
40
|
basename,
|
|
32
41
|
path: loaded.path,
|
|
33
42
|
format,
|
|
34
|
-
installed: match
|
|
35
|
-
notInstalled: !loaded.exists
|
|
36
|
-
otherPlugins: plugins.filter(p => !matchesPlugin(p)),
|
|
43
|
+
installed: match,
|
|
44
|
+
notInstalled: !loaded.exists || match === null,
|
|
45
|
+
otherPlugins: plugins.filter((p) => !matchesPlugin(p)),
|
|
37
46
|
latest,
|
|
38
|
-
isLatest: match !==
|
|
47
|
+
isLatest: match !== null && latest !== null
|
|
48
|
+
? match === `opencode-rules-md@${latest}`
|
|
49
|
+
: null,
|
|
39
50
|
};
|
|
40
51
|
configs.push(entry);
|
|
41
|
-
// ── Print status lines ──────────────────────────────────────────────────
|
|
42
52
|
if (!loaded.exists) {
|
|
43
53
|
log(`omd: ${basename}.json — config not found at ${loaded.path}`);
|
|
44
54
|
continue;
|
|
@@ -53,7 +63,7 @@ export const runStatus = async (fs, env, log) => {
|
|
|
53
63
|
log(` opencode-rules-md: ${match}${isLatestLabel}`);
|
|
54
64
|
}
|
|
55
65
|
else {
|
|
56
|
-
log(
|
|
66
|
+
log(' opencode-rules-md: not installed');
|
|
57
67
|
}
|
|
58
68
|
if (entry.otherPlugins.length > 0) {
|
|
59
69
|
log(` other plugins: ${entry.otherPlugins.join(', ')}`);
|
|
@@ -64,13 +74,16 @@ export const runStatus = async (fs, env, log) => {
|
|
|
64
74
|
// ─── runDoctor ────────────────────────────────────────────────────────────────
|
|
65
75
|
/**
|
|
66
76
|
* Run the doctor command: health checks for the plugin environment.
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
77
|
+
*
|
|
78
|
+
* Checks:
|
|
79
|
+
* - Node >= 20: issue if below
|
|
80
|
+
* - Bun on PATH: issue if absent
|
|
81
|
+
* - Both configs readable and valid: issue if absent or malformed
|
|
82
|
+
* - Legacy `plugins` field present: warning (no-op for the runtime, but
|
|
83
|
+
* indicates a previous buggy install)
|
|
84
|
+
* - Rule dir existence: warning if absent
|
|
85
|
+
* - Config dir writable: issue if not writable
|
|
86
|
+
* - Package freshness: info line about update availability
|
|
74
87
|
*
|
|
75
88
|
* Exit 1 if any issues found.
|
|
76
89
|
*/
|
|
@@ -84,7 +97,7 @@ export const runDoctor = async (fs, env, log, error, opts = {}) => {
|
|
|
84
97
|
let hasBun = opts.hasBun;
|
|
85
98
|
if (hasBun === undefined) {
|
|
86
99
|
const pathEnv = (env.PATH ?? '').split(':');
|
|
87
|
-
hasBun = pathEnv.some(p => {
|
|
100
|
+
hasBun = pathEnv.some((p) => {
|
|
88
101
|
try {
|
|
89
102
|
const { existsSync } = require('node:fs');
|
|
90
103
|
return existsSync(p + '/bun');
|
|
@@ -123,23 +136,32 @@ export const runDoctor = async (fs, env, log, error, opts = {}) => {
|
|
|
123
136
|
continue;
|
|
124
137
|
}
|
|
125
138
|
log(` ${basename}${extname(loaded.path)}: ${loaded.path}`);
|
|
126
|
-
const plugins =
|
|
127
|
-
const match = plugins.find(p => matchesPlugin(p));
|
|
139
|
+
const plugins = readInstalledPlugins(loaded);
|
|
140
|
+
const match = plugins.find((p) => matchesPlugin(p)) ?? null;
|
|
128
141
|
if (match) {
|
|
129
|
-
info.push(`${basename}: opencode-rules-md
|
|
142
|
+
info.push(`${basename}: opencode-rules-md installed (${match})`);
|
|
130
143
|
log(` opencode-rules-md: ${match}`);
|
|
131
144
|
}
|
|
132
145
|
else {
|
|
133
146
|
warnings.push(`${basename}: plugin not installed`);
|
|
134
|
-
log(
|
|
147
|
+
log(' opencode-rules-md: not installed');
|
|
148
|
+
}
|
|
149
|
+
// ── Check legacy `plugins` field (backward-compat warning) ──────────────
|
|
150
|
+
if (loaded.data['plugins'] !== undefined && loaded.data['plugin'] === undefined) {
|
|
151
|
+
warnings.push(`${basename}: legacy "plugins" field present (should be "plugin") — run "omd uninstall && omd install" to migrate`);
|
|
152
|
+
log(` [WARN] ${basename}: legacy "plugins" field present (should be "plugin")`);
|
|
135
153
|
}
|
|
136
154
|
// ── Check plugin shape ────────────────────────────────────────────────────
|
|
137
|
-
|
|
138
|
-
|
|
155
|
+
const pluginField = loaded.data['plugin'] ?? loaded.data['plugins'];
|
|
156
|
+
if (pluginField !== undefined &&
|
|
157
|
+
!Array.isArray(pluginField) &&
|
|
158
|
+
typeof pluginField !== 'object' &&
|
|
159
|
+
typeof pluginField !== 'string') {
|
|
160
|
+
issues.push(`${basename}: plugin field has invalid type — expected array, object, or string`);
|
|
139
161
|
error(`[ISSUE] ${basename}: invalid plugin shape`);
|
|
140
162
|
}
|
|
141
163
|
else {
|
|
142
|
-
log(
|
|
164
|
+
log(' plugin field: valid');
|
|
143
165
|
}
|
|
144
166
|
}
|
|
145
167
|
// ── Check: rule dir existence (warning, not issue) ─────────────────────────
|
|
@@ -152,6 +174,16 @@ export const runDoctor = async (fs, env, log, error, opts = {}) => {
|
|
|
152
174
|
else {
|
|
153
175
|
log(` ${ruleBase}: exists`);
|
|
154
176
|
}
|
|
177
|
+
// ── Check: package cache directory ────────────────────────────────────────
|
|
178
|
+
log('Checking OpenCode package cache...');
|
|
179
|
+
const cachePaths = resolveCachePaths(env, fs);
|
|
180
|
+
if (cachePaths.length === 0) {
|
|
181
|
+
info.push('No opencode-rules-md cache found under ~/.cache/opencode/packages/');
|
|
182
|
+
log(' no cache entries match opencode-rules-md*');
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
log(` cache entries: ${cachePaths.join(', ')}`);
|
|
186
|
+
}
|
|
155
187
|
// ── Check: config dir writable ─────────────────────────────────────────────
|
|
156
188
|
const configDir = env.OPENCODE_CONFIG_DIR ?? join(homedir(), '.config', 'opencode');
|
|
157
189
|
log('Checking config directory write access...');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/cli/status.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,6EAA6E;AAC7E,EAAE;AACF,
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/cli/status.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { type CliFs } from './config.js';
|
|
2
2
|
export declare const CONFIG_BASENAMES: readonly ["opencode", "tui"];
|
|
3
3
|
export interface UninstallOptions {
|
|
4
|
+
/** Also remove ~/.cache/opencode/packages/opencode-rules-md*. */
|
|
4
5
|
purge?: boolean;
|
|
6
|
+
/** Run the full pipeline without writing to disk. */
|
|
5
7
|
dryRun?: boolean;
|
|
8
|
+
/** Reserved for future prompts — no-op today. */
|
|
6
9
|
yes?: boolean;
|
|
7
10
|
}
|
|
8
11
|
export interface UninstallResultPerFile {
|
|
@@ -19,9 +22,9 @@ export interface UninstallResult {
|
|
|
19
22
|
* Uninstall opencode-rules-md from both opencode.json and tui.json configs.
|
|
20
23
|
*
|
|
21
24
|
* Options:
|
|
22
|
-
* purge — also remove ~/.cache/opencode/
|
|
25
|
+
* purge — also remove ~/.cache/opencode/packages/opencode-rules-md*
|
|
23
26
|
* dryRun — run full pipeline without writing to disk
|
|
24
|
-
* yes —
|
|
27
|
+
* yes — reserved
|
|
25
28
|
*/
|
|
26
29
|
export declare const runUninstall: (opts: UninstallOptions | undefined, fs: CliFs, env: NodeJS.ProcessEnv) => UninstallResult;
|
|
27
30
|
//# sourceMappingURL=uninstall.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uninstall.d.ts","sourceRoot":"","sources":["../../../src/cli/uninstall.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"uninstall.d.ts","sourceRoot":"","sources":["../../../src/cli/uninstall.ts"],"names":[],"mappings":"AAoBA,OAAO,EAKL,KAAK,KAAK,EACX,MAAM,aAAa,CAAC;AAGrB,eAAO,MAAM,gBAAgB,8BAA+B,CAAC;AAE7D,MAAM,WAAW,gBAAgB;IAC/B,iEAAiE;IACjE,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,qDAAqD;IACrD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,iDAAiD;IACjD,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC;IACtC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,OAAO,GAAG,SAAS,CAAC;IAC5B,OAAO,EAAE,sBAAsB,EAAE,CAAC;IAClC,MAAM,EAAE,OAAO,CAAC;CACjB;AA6CD;;;;;;;GAOG;AACH,eAAO,MAAM,YAAY,GACvB,MAAM,gBAAgB,YAAK,EAC3B,IAAI,KAAK,EACT,KAAK,MAAM,CAAC,UAAU,KACrB,eAqEF,CAAC"}
|
|
@@ -1,21 +1,69 @@
|
|
|
1
1
|
// ---------------------------------------------------------------------------
|
|
2
2
|
// src/cli/uninstall.ts — `omd uninstall` command implementation.
|
|
3
3
|
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
4
|
+
// Removes opencode-rules-md from opencode.json and tui.json, and (with
|
|
5
|
+
// `--purge`) wipes the OpenCode package cache. Two important fixes vs.
|
|
6
|
+
// the previous implementation:
|
|
7
|
+
//
|
|
8
|
+
// 1. We read & write `data['plugin']` (singular), the field OpenCode
|
|
9
|
+
// actually honors. The previous code wrote `data['plugins']` (plural),
|
|
10
|
+
// which OpenCode silently ignored — so "uninstall" used to leave
|
|
11
|
+
// the plugin effectively installed.
|
|
12
|
+
// 2. We also strip a stale `data['plugins']` entry if it exists, so
|
|
13
|
+
// users who upgraded from a buggy `omd install` get their legacy
|
|
14
|
+
// field cleaned up too.
|
|
15
|
+
// 3. We purge ~/.cache/opencode/packages/opencode-rules-md* (the real
|
|
16
|
+
// cache OpenCode uses), not the old ~/.cache/opencode/node_modules
|
|
17
|
+
// path.
|
|
7
18
|
// ---------------------------------------------------------------------------
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
19
|
+
import { join } from 'path';
|
|
20
|
+
import { loadGlobalConfig, backupIfWritable, rotateBackups, writeAtomically, } from './config.js';
|
|
21
|
+
import { resolveCachePaths, purgeDirectory } from './update.js';
|
|
11
22
|
export const CONFIG_BASENAMES = ['opencode', 'tui'];
|
|
23
|
+
/**
|
|
24
|
+
* Strip `opencode-rules-md` entries from a config payload, cleaning both
|
|
25
|
+
* the modern `plugin` field (array or single string) and any legacy
|
|
26
|
+
* `plugins` field. Returns a tuple [newData, removedCount].
|
|
27
|
+
*
|
|
28
|
+
* `removedCount > 0` indicates the file actually needs to be rewritten.
|
|
29
|
+
*/
|
|
30
|
+
function stripFromData(data) {
|
|
31
|
+
let removed = 0;
|
|
32
|
+
const next = { ...data };
|
|
33
|
+
// Modern field: `plugin` (singular). Accept array or single string.
|
|
34
|
+
const currentRaw = next['plugin'] ?? next['plugins'];
|
|
35
|
+
if (currentRaw !== undefined) {
|
|
36
|
+
if (typeof currentRaw === 'string') {
|
|
37
|
+
if (currentRaw.startsWith('opencode-rules-md')) {
|
|
38
|
+
delete next['plugin'];
|
|
39
|
+
delete next['plugins'];
|
|
40
|
+
removed += 1;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
else if (Array.isArray(currentRaw)) {
|
|
44
|
+
const filtered = currentRaw.filter((p) => !(typeof p === 'string' && p.startsWith('opencode-rules-md')));
|
|
45
|
+
if (filtered.length !== currentRaw.length) {
|
|
46
|
+
removed += currentRaw.length - filtered.length;
|
|
47
|
+
if (filtered.length === 0) {
|
|
48
|
+
delete next['plugin'];
|
|
49
|
+
delete next['plugins'];
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
next['plugin'] = filtered;
|
|
53
|
+
delete next['plugins'];
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return { next, removed };
|
|
59
|
+
}
|
|
12
60
|
/**
|
|
13
61
|
* Uninstall opencode-rules-md from both opencode.json and tui.json configs.
|
|
14
62
|
*
|
|
15
63
|
* Options:
|
|
16
|
-
* purge — also remove ~/.cache/opencode/
|
|
64
|
+
* purge — also remove ~/.cache/opencode/packages/opencode-rules-md*
|
|
17
65
|
* dryRun — run full pipeline without writing to disk
|
|
18
|
-
* yes —
|
|
66
|
+
* yes — reserved
|
|
19
67
|
*/
|
|
20
68
|
export const runUninstall = (opts = {}, fs, env) => {
|
|
21
69
|
const results = [];
|
|
@@ -23,67 +71,46 @@ export const runUninstall = (opts = {}, fs, env) => {
|
|
|
23
71
|
let purged = false;
|
|
24
72
|
// ── Purge cache if requested ────────────────────────────────────────────
|
|
25
73
|
if (opts.purge) {
|
|
26
|
-
const
|
|
27
|
-
|
|
74
|
+
const cachePaths = resolveCachePaths(env, fs);
|
|
75
|
+
for (const cachePath of cachePaths) {
|
|
28
76
|
try {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
// Empty directory — remove it
|
|
33
|
-
fs.rmdirSync(cachePath);
|
|
34
|
-
}
|
|
35
|
-
else {
|
|
36
|
-
// Has contents — remove contents then the dir
|
|
37
|
-
for (const entry of entries) {
|
|
38
|
-
const entryPath = join(cachePath, entry);
|
|
39
|
-
if (fs.existsSync(entryPath)) {
|
|
40
|
-
try {
|
|
41
|
-
fs.unlinkSync(entryPath);
|
|
42
|
-
}
|
|
43
|
-
catch {
|
|
44
|
-
// ignore individual file failures
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
fs.rmdirSync(cachePath);
|
|
77
|
+
if (fs.existsSync(cachePath)) {
|
|
78
|
+
purgeDirectory(fs, cachePath);
|
|
79
|
+
purged = true;
|
|
49
80
|
}
|
|
50
|
-
purged = true;
|
|
51
81
|
}
|
|
52
82
|
catch {
|
|
53
|
-
// best-effort —
|
|
83
|
+
// best-effort — purge failure is non-fatal
|
|
54
84
|
}
|
|
55
85
|
}
|
|
56
86
|
}
|
|
57
87
|
// ── Remove plugin from both configs ─────────────────────────────────────
|
|
58
88
|
for (const basename of CONFIG_BASENAMES) {
|
|
59
89
|
const loaded = loadGlobalConfig(fs, env, basename);
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
90
|
+
if (!loaded.exists) {
|
|
91
|
+
results.push({ path: loaded.path, status: 'skipped', backup: null });
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
const { next, removed } = stripFromData(loaded.data);
|
|
95
|
+
if (removed === 0) {
|
|
65
96
|
results.push({ path: loaded.path, status: 'skipped', backup: null });
|
|
66
97
|
continue;
|
|
67
98
|
}
|
|
68
99
|
anyProcessed = true;
|
|
69
|
-
const
|
|
70
|
-
const newContent = JSON.stringify(newData, null, 2) + '\n';
|
|
100
|
+
const newContent = JSON.stringify(next, null, 2) + '\n';
|
|
71
101
|
if (opts.dryRun) {
|
|
72
102
|
results.push({ path: loaded.path, status: 'wrote', backup: null });
|
|
73
103
|
continue;
|
|
74
104
|
}
|
|
75
|
-
// Backup the existing file
|
|
76
|
-
|
|
77
|
-
if (
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
const name = dot >= 0 ? base.slice(0, dot) : base;
|
|
85
|
-
rotateBackups(fs, dir, name, 3);
|
|
86
|
-
}
|
|
105
|
+
// Backup the existing file before rewriting.
|
|
106
|
+
const backup = backupIfWritable(fs, loaded.path);
|
|
107
|
+
if (backup !== undefined) {
|
|
108
|
+
const segs = loaded.path.replace(/\\/g, '/').split('/');
|
|
109
|
+
const base = segs[segs.length - 1] ?? loaded.path;
|
|
110
|
+
const dot = base.lastIndexOf('.');
|
|
111
|
+
const name = dot >= 0 ? base.slice(0, dot) : base;
|
|
112
|
+
const dir = join(...segs.slice(0, -1));
|
|
113
|
+
rotateBackups(fs, dir, name, 3);
|
|
87
114
|
}
|
|
88
115
|
writeAtomically(fs, loaded.path, newContent);
|
|
89
116
|
results.push({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uninstall.js","sourceRoot":"","sources":["../../../src/cli/uninstall.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,iEAAiE;AACjE,EAAE;AACF,
|
|
1
|
+
{"version":3,"file":"uninstall.js","sourceRoot":"","sources":["../../../src/cli/uninstall.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,iEAAiE;AACjE,EAAE;AACF,uEAAuE;AACvE,uEAAuE;AACvE,+BAA+B;AAC/B,EAAE;AACF,uEAAuE;AACvE,4EAA4E;AAC5E,sEAAsE;AACtE,yCAAyC;AACzC,sEAAsE;AACtE,sEAAsE;AACtE,6BAA6B;AAC7B,wEAAwE;AACxE,wEAAwE;AACxE,aAAa;AACb,8EAA8E;AAE9E,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,EACb,eAAe,GAEhB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAEhE,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,UAAU,EAAE,KAAK,CAAU,CAAC;AAuB7D;;;;;;GAMG;AACH,SAAS,aAAa,CAAC,IAA6B;IAIlD,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,MAAM,IAAI,GAA4B,EAAE,GAAG,IAAI,EAAE,CAAC;IAElD,oEAAoE;IACpE,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC;IACrD,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,IAAI,OAAO,UAAU,KAAK,QAAQ,EAAE,CAAC;YACnC,IAAI,UAAU,CAAC,UAAU,CAAC,mBAAmB,CAAC,EAAE,CAAC;gBAC/C,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACtB,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC;gBACvB,OAAO,IAAI,CAAC,CAAC;YACf,CAAC;QACH,CAAC;aAAM,IAAI,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;YACrC,MAAM,QAAQ,GAAI,UAAwB,CAAC,MAAM,CAC/C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,UAAU,CAAC,mBAAmB,CAAC,CAAC,CACrE,CAAC;YACF,IAAI,QAAQ,CAAC,MAAM,KAAK,UAAU,CAAC,MAAM,EAAE,CAAC;gBAC1C,OAAO,IAAI,UAAU,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;gBAC/C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBAC1B,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAC;oBACtB,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC;gBACzB,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC;oBAC1B,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC;gBACzB,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAC3B,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,OAAyB,EAAE,EAC3B,EAAS,EACT,GAAsB,EACL,EAAE;IACnB,MAAM,OAAO,GAA6B,EAAE,CAAC;IAC7C,IAAI,YAAY,GAAG,KAAK,CAAC;IACzB,IAAI,MAAM,GAAG,KAAK,CAAC;IAEnB,2EAA2E;IAC3E,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,MAAM,UAAU,GAAG,iBAAiB,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QAC9C,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YACnC,IAAI,CAAC;gBACH,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;oBAC7B,cAAc,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;oBAC9B,MAAM,GAAG,IAAI,CAAC;gBAChB,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,2CAA2C;YAC7C,CAAC;QACH,CAAC;IACH,CAAC;IAED,2EAA2E;IAC3E,KAAK,MAAM,QAAQ,IAAI,gBAAgB,EAAE,CAAC;QACxC,MAAM,MAAM,GAAG,gBAAgB,CAAC,EAAE,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;QAEnD,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACnB,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;YACrE,SAAS;QACX,CAAC;QAED,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAErD,IAAI,OAAO,KAAK,CAAC,EAAE,CAAC;YAClB,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;YACrE,SAAS;QACX,CAAC;QAED,YAAY,GAAG,IAAI,CAAC;QAEpB,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC;QAExD,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;YACnE,SAAS;QACX,CAAC;QAED,6CAA6C;QAC7C,MAAM,MAAM,GAAG,gBAAgB,CAAC,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;QACjD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACxD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC;YAClD,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;YAClC,MAAM,IAAI,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAClD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YACvC,aAAa,CAAC,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAClC,CAAC;QAED,eAAe,CAAC,EAAE,EAAE,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QAC7C,OAAO,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,MAAM,EAAE,OAAO;YACf,MAAM,EAAE,MAAM,IAAI,IAAI;SACvB,CAAC,CAAC;IACL,CAAC;IAED,OAAO;QACL,MAAM,EAAE,YAAY,IAAI,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;QACpD,OAAO;QACP,MAAM;KACP,CAAC;AACJ,CAAC,CAAC"}
|
package/dist/src/cli/update.d.ts
CHANGED
|
@@ -1,31 +1,65 @@
|
|
|
1
|
-
import type
|
|
2
|
-
|
|
1
|
+
import { type CliFs } from './config.js';
|
|
2
|
+
import { spawnOpencodePlugin } from './spawn.js';
|
|
3
|
+
/** Package directory used by OpenCode to cache plugin installs. */
|
|
4
|
+
export declare const PACKAGES_DIR_BASENAME: readonly [".cache", "opencode", "packages"];
|
|
5
|
+
/** Exact cache directory name we look for (bare specifier, no version suffix). */
|
|
6
|
+
export declare const CACHE_DIR_BASENAME = "opencode-rules-md";
|
|
7
|
+
/**
|
|
8
|
+
* Resolve the user's home directory, honoring a custom HOME env var.
|
|
9
|
+
* Used by both resolveCachePaths and the config loader.
|
|
10
|
+
*/
|
|
11
|
+
export declare function resolveHome(env?: NodeJS.ProcessEnv): string;
|
|
12
|
+
/**
|
|
13
|
+
* Return the absolute path of the OpenCode packages cache directory.
|
|
14
|
+
*/
|
|
15
|
+
export declare function resolvePackagesDir(env?: NodeJS.ProcessEnv): string;
|
|
16
|
+
/**
|
|
17
|
+
* Return the cache directories that match the opencode-rules-md prefix.
|
|
18
|
+
*
|
|
19
|
+
* Real-world layout under ~/.cache/opencode/packages/ looks like:
|
|
20
|
+
* opencode-rules-md/
|
|
21
|
+
* opencode-rules-md@latest/
|
|
22
|
+
* some-other-plugin/
|
|
23
|
+
*
|
|
24
|
+
* We glob-match anything starting with `opencode-rules-md` (exact or with
|
|
25
|
+
* an `@<version>` suffix). When an injected fs is provided we list the
|
|
26
|
+
* directory and filter; without one we return the two most common shapes
|
|
27
|
+
* so callers can pre-check existence cheaply.
|
|
28
|
+
*/
|
|
29
|
+
export declare function resolveCachePaths(env?: NodeJS.ProcessEnv, fs?: CliFs): string[];
|
|
3
30
|
export interface UpdateOptions {
|
|
31
|
+
/** Injected latest version (test seam). Defaults to a real npm lookup. */
|
|
4
32
|
latestVersion?: string | null | undefined;
|
|
33
|
+
/** Print the plan without writing or spawning. */
|
|
5
34
|
dryRun?: boolean;
|
|
35
|
+
/** Injected spawn function (test seam). Defaults to spawnOpencodePlugin. */
|
|
36
|
+
spawn?: typeof spawnOpencodePlugin;
|
|
6
37
|
}
|
|
7
38
|
export interface UpdateResult {
|
|
8
39
|
status: 'stale' | 'current' | 'unreachable';
|
|
9
|
-
|
|
40
|
+
cachePaths: string[];
|
|
41
|
+
/** Re-install instruction; empty when status === 'current'. */
|
|
10
42
|
instruction: string;
|
|
11
43
|
}
|
|
12
44
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* resolveConfigDir fallback strategy.
|
|
45
|
+
* Extract the version portion of an `opencode-rules-md@<version>` specifier.
|
|
46
|
+
* Returns null when the specifier has no `@version` segment.
|
|
16
47
|
*/
|
|
17
|
-
export declare function
|
|
48
|
+
export declare function extractVersion(specifier: string): string | null;
|
|
18
49
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* 2. Compare to installed version in config
|
|
22
|
-
* 3. If stale: purge cache, print reinstall instruction
|
|
23
|
-
* 4. If current: print "already current"
|
|
24
|
-
* 5. If unreachable: noop
|
|
50
|
+
* Recursively delete a directory and all its contents using the injected fs.
|
|
51
|
+
* Best-effort — a failed purge is not fatal; we want the update to keep going.
|
|
25
52
|
*/
|
|
26
|
-
export declare
|
|
53
|
+
export declare function purgeDirectory(fs: CliFs, dirPath: string): void;
|
|
27
54
|
/**
|
|
28
|
-
*
|
|
55
|
+
* Run the update command.
|
|
56
|
+
*
|
|
57
|
+
* 1. Resolve the latest published version from npm (or use the injected mock).
|
|
58
|
+
* 2. Read the installed version from the user's opencode config.
|
|
59
|
+
* 3. If unreachable, log and return.
|
|
60
|
+
* 4. If current, log and return.
|
|
61
|
+
* 5. Otherwise: purge stale cache directories, then spawn
|
|
62
|
+
* `opencode plugin opencode-rules-md --global --force`.
|
|
29
63
|
*/
|
|
30
|
-
export declare
|
|
64
|
+
export declare const runUpdate: (fs: CliFs, env: NodeJS.ProcessEnv, log: (s: string) => void, _error: (s: string) => void, opts?: UpdateOptions) => Promise<UpdateResult>;
|
|
31
65
|
//# sourceMappingURL=update.d.ts.map
|