doc-detective 4.0.2-dev.1 → 4.0.2-dev.11
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/agents/adapters/claude-code.d.ts +77 -0
- package/dist/agents/adapters/claude-code.d.ts.map +1 -0
- package/dist/agents/adapters/claude-code.js +461 -0
- package/dist/agents/adapters/claude-code.js.map +1 -0
- package/dist/agents/adapters/codex.d.ts +64 -0
- package/dist/agents/adapters/codex.d.ts.map +1 -0
- package/dist/agents/adapters/codex.js +299 -0
- package/dist/agents/adapters/codex.js.map +1 -0
- package/dist/agents/adapters/copilot-cli.d.ts +29 -0
- package/dist/agents/adapters/copilot-cli.d.ts.map +1 -0
- package/dist/agents/adapters/copilot-cli.js +195 -0
- package/dist/agents/adapters/copilot-cli.js.map +1 -0
- package/dist/agents/adapters/gemini-cli.d.ts +29 -0
- package/dist/agents/adapters/gemini-cli.d.ts.map +1 -0
- package/dist/agents/adapters/gemini-cli.js +207 -0
- package/dist/agents/adapters/gemini-cli.js.map +1 -0
- package/dist/agents/adapters/opencode.d.ts +67 -0
- package/dist/agents/adapters/opencode.d.ts.map +1 -0
- package/dist/agents/adapters/opencode.js +341 -0
- package/dist/agents/adapters/opencode.js.map +1 -0
- package/dist/agents/adapters/qwen-code.d.ts +30 -0
- package/dist/agents/adapters/qwen-code.d.ts.map +1 -0
- package/dist/agents/adapters/qwen-code.js +212 -0
- package/dist/agents/adapters/qwen-code.js.map +1 -0
- package/dist/agents/command.d.ts +11 -0
- package/dist/agents/command.d.ts.map +1 -0
- package/dist/agents/command.js +41 -0
- package/dist/agents/command.js.map +1 -0
- package/dist/agents/fetcher.d.ts +30 -0
- package/dist/agents/fetcher.d.ts.map +1 -0
- package/dist/agents/fetcher.js +112 -0
- package/dist/agents/fetcher.js.map +1 -0
- package/dist/agents/prompts.d.ts +24 -0
- package/dist/agents/prompts.d.ts.map +1 -0
- package/dist/agents/prompts.js +74 -0
- package/dist/agents/prompts.js.map +1 -0
- package/dist/agents/registry.d.ts +4 -0
- package/dist/agents/registry.d.ts.map +1 -0
- package/dist/agents/registry.js +25 -0
- package/dist/agents/registry.js.map +1 -0
- package/dist/agents/runner.d.ts +13 -0
- package/dist/agents/runner.d.ts.map +1 -0
- package/dist/agents/runner.js +155 -0
- package/dist/agents/runner.js.map +1 -0
- package/dist/agents/spawn-helper.d.ts +33 -0
- package/dist/agents/spawn-helper.d.ts.map +1 -0
- package/dist/agents/spawn-helper.js +98 -0
- package/dist/agents/spawn-helper.js.map +1 -0
- package/dist/agents/types.d.ts +41 -0
- package/dist/agents/types.d.ts.map +1 -0
- package/dist/agents/types.js +2 -0
- package/dist/agents/types.js.map +1 -0
- package/dist/cli.js +42 -10
- package/dist/cli.js.map +1 -1
- package/dist/common/src/detectTests.d.ts.map +1 -1
- package/dist/common/src/detectTests.js +43 -12
- package/dist/common/src/detectTests.js.map +1 -1
- package/dist/common/src/fileTypes.d.ts.map +1 -1
- package/dist/common/src/fileTypes.js +10 -0
- package/dist/common/src/fileTypes.js.map +1 -1
- package/dist/common/src/schemas/schemas.json +594 -0
- package/dist/common/src/types/generated/checkLink_v3.d.ts +15 -0
- package/dist/common/src/types/generated/checkLink_v3.d.ts.map +1 -1
- package/dist/common/src/types/generated/config_v3.d.ts +4 -0
- package/dist/common/src/types/generated/config_v3.d.ts.map +1 -1
- package/dist/common/src/types/generated/resolvedTests_v3.d.ts +4 -0
- package/dist/common/src/types/generated/resolvedTests_v3.d.ts.map +1 -1
- package/dist/common/src/types/generated/step_v3.d.ts +15 -0
- package/dist/common/src/types/generated/step_v3.d.ts.map +1 -1
- package/dist/common/src/types/generated/test_v3.d.ts +30 -0
- package/dist/common/src/types/generated/test_v3.d.ts.map +1 -1
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +10 -0
- package/dist/core/config.js.map +1 -1
- package/dist/core/integrations/heretto.d.ts.map +1 -1
- package/dist/core/integrations/heretto.js +11 -3
- package/dist/core/integrations/heretto.js.map +1 -1
- package/dist/core/tests/checkLink.d.ts.map +1 -1
- package/dist/core/tests/checkLink.js +136 -29
- package/dist/core/tests/checkLink.js.map +1 -1
- package/dist/core/tests/loadCookie.d.ts.map +1 -1
- package/dist/core/tests/loadCookie.js +12 -2
- package/dist/core/tests/loadCookie.js.map +1 -1
- package/dist/core/tests/saveScreenshot.d.ts +15 -1
- package/dist/core/tests/saveScreenshot.d.ts.map +1 -1
- package/dist/core/tests/saveScreenshot.js +41 -17
- package/dist/core/tests/saveScreenshot.js.map +1 -1
- package/dist/index.cjs +816 -59
- package/dist/reporters/htmlReporter.d.ts +2 -0
- package/dist/reporters/htmlReporter.d.ts.map +1 -0
- package/dist/reporters/htmlReporter.js +1589 -0
- package/dist/reporters/htmlReporter.js.map +1 -0
- package/dist/utils.d.ts +2 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +43 -10
- package/dist/utils.js.map +1 -1
- package/package.json +3 -1
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import axios from "axios";
|
|
5
|
+
import { safeSpawn } from "../spawn-helper.js";
|
|
6
|
+
const EXTENSION_NAME = "doc-detective";
|
|
7
|
+
const GIT_SOURCE = "https://github.com/doc-detective/agent-tools.git";
|
|
8
|
+
const LATEST_MANIFEST_URL = "https://raw.githubusercontent.com/doc-detective/agent-tools/main/gemini-extension.json";
|
|
9
|
+
export function defaultGeminiCliDeps() {
|
|
10
|
+
return {
|
|
11
|
+
run: (cmd, args) => safeSpawn(cmd, args),
|
|
12
|
+
existsSync: fs.existsSync,
|
|
13
|
+
readFileSync: (p, enc = "utf8") => fs.readFileSync(p, enc),
|
|
14
|
+
homedir: os.homedir,
|
|
15
|
+
fetchLatestVersion: async () => {
|
|
16
|
+
const response = await axios.get(LATEST_MANIFEST_URL, {
|
|
17
|
+
timeout: 5000,
|
|
18
|
+
responseType: "json",
|
|
19
|
+
});
|
|
20
|
+
const version = response?.data?.version;
|
|
21
|
+
return typeof version === "string" ? version : undefined;
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export class GeminiCliAdapter {
|
|
26
|
+
id = "gemini";
|
|
27
|
+
displayName = "Gemini CLI";
|
|
28
|
+
deps;
|
|
29
|
+
constructor(deps = defaultGeminiCliDeps()) {
|
|
30
|
+
this.deps = deps;
|
|
31
|
+
}
|
|
32
|
+
supportsScopes() {
|
|
33
|
+
// Gemini's `extensions install` has no --scope flag; extensions live in ~/.gemini.
|
|
34
|
+
return ["global"];
|
|
35
|
+
}
|
|
36
|
+
async detect() {
|
|
37
|
+
const geminiHome = path.join(this.deps.homedir(), ".gemini");
|
|
38
|
+
let onPath = false;
|
|
39
|
+
let version;
|
|
40
|
+
try {
|
|
41
|
+
const result = await this.deps.run("gemini", ["--version"]);
|
|
42
|
+
if (result.exitCode === 0 && result.stdout.trim()) {
|
|
43
|
+
onPath = true;
|
|
44
|
+
version = result.stdout.trim();
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
// Binary absent — silent.
|
|
49
|
+
}
|
|
50
|
+
const configPaths = {};
|
|
51
|
+
if (this.deps.existsSync(geminiHome))
|
|
52
|
+
configPaths.global = geminiHome;
|
|
53
|
+
const present = onPath || !!configPaths.global;
|
|
54
|
+
const notes = [];
|
|
55
|
+
if (!onPath && configPaths.global) {
|
|
56
|
+
notes.push("`gemini` not on PATH; install requires the binary — see https://github.com/google-gemini/gemini-cli for install options.");
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
present,
|
|
60
|
+
onPath,
|
|
61
|
+
version,
|
|
62
|
+
configPaths,
|
|
63
|
+
notes: notes.length ? notes : undefined,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
async getInstallState(_scope) {
|
|
67
|
+
const base = await this.queryLocalInstallState();
|
|
68
|
+
if (!base.installed)
|
|
69
|
+
return base;
|
|
70
|
+
return this.enrichWithLatest(base);
|
|
71
|
+
}
|
|
72
|
+
manifestPath() {
|
|
73
|
+
return path.join(this.deps.homedir(), ".gemini", "extensions", EXTENSION_NAME, "gemini-extension.json");
|
|
74
|
+
}
|
|
75
|
+
async queryLocalInstallState() {
|
|
76
|
+
// Preferred: `gemini extensions list --output-format json`
|
|
77
|
+
try {
|
|
78
|
+
const result = await this.deps.run("gemini", ["extensions", "list", "--output-format", "json"]);
|
|
79
|
+
if (result.exitCode === 0 && result.stdout.trim()) {
|
|
80
|
+
try {
|
|
81
|
+
const parsed = JSON.parse(result.stdout);
|
|
82
|
+
if (Array.isArray(parsed)) {
|
|
83
|
+
const entry = parsed.find((e) => e && typeof e === "object" && e.name === EXTENSION_NAME);
|
|
84
|
+
if (entry) {
|
|
85
|
+
const version = typeof entry.version === "string" ? entry.version : undefined;
|
|
86
|
+
return { installed: true, installedVersion: version };
|
|
87
|
+
}
|
|
88
|
+
return { installed: false };
|
|
89
|
+
}
|
|
90
|
+
// Non-array (e.g. error object) — fall through to the filesystem fallback.
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
// Unparseable JSON — fall through.
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
// CLI not available — fall through.
|
|
99
|
+
}
|
|
100
|
+
// Fallback: read the extension manifest directly.
|
|
101
|
+
const manifestPath = this.manifestPath();
|
|
102
|
+
if (!this.deps.existsSync(manifestPath))
|
|
103
|
+
return { installed: false };
|
|
104
|
+
try {
|
|
105
|
+
const parsed = JSON.parse(this.deps.readFileSync(manifestPath, "utf8"));
|
|
106
|
+
return {
|
|
107
|
+
installed: true,
|
|
108
|
+
installedVersion: typeof parsed?.version === "string" ? parsed.version : undefined,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
return { installed: false };
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
async enrichWithLatest(state) {
|
|
116
|
+
let latestVersion;
|
|
117
|
+
try {
|
|
118
|
+
latestVersion = await this.deps.fetchLatestVersion();
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
latestVersion = undefined;
|
|
122
|
+
}
|
|
123
|
+
if (!latestVersion) {
|
|
124
|
+
return { ...state, latestVersion: undefined, upToDate: undefined };
|
|
125
|
+
}
|
|
126
|
+
const upToDate = state.installedVersion !== undefined
|
|
127
|
+
? state.installedVersion === latestVersion
|
|
128
|
+
: undefined;
|
|
129
|
+
return { ...state, latestVersion, upToDate };
|
|
130
|
+
}
|
|
131
|
+
async install(opts) {
|
|
132
|
+
const base = await this.queryLocalInstallState();
|
|
133
|
+
const enriched = base.installed ? await this.enrichWithLatest(base) : base;
|
|
134
|
+
const isInstalled = enriched.installed;
|
|
135
|
+
const isUpToDate = enriched.upToDate === true;
|
|
136
|
+
if (isInstalled && isUpToDate && !opts.force) {
|
|
137
|
+
return {
|
|
138
|
+
adapterId: this.id,
|
|
139
|
+
scope: opts.scope,
|
|
140
|
+
action: "already-up-to-date",
|
|
141
|
+
installedVersion: enriched.installedVersion,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
const commands = isInstalled
|
|
145
|
+
? [["gemini", "extensions", "update", EXTENSION_NAME]]
|
|
146
|
+
: [
|
|
147
|
+
[
|
|
148
|
+
"gemini", "extensions", "install", GIT_SOURCE,
|
|
149
|
+
"--auto-update", "--consent", "--skip-settings",
|
|
150
|
+
],
|
|
151
|
+
];
|
|
152
|
+
if (opts.dryRun) {
|
|
153
|
+
for (const cmd of commands) {
|
|
154
|
+
opts.logger(`[dry-run] would run: ${cmd.join(" ")}`, "info");
|
|
155
|
+
}
|
|
156
|
+
return {
|
|
157
|
+
adapterId: this.id,
|
|
158
|
+
scope: opts.scope,
|
|
159
|
+
action: "dry-run",
|
|
160
|
+
installedVersion: enriched.installedVersion,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
for (const [cmd, ...args] of commands) {
|
|
164
|
+
opts.logger(`Running: ${cmd} ${args.join(" ")}`, "debug");
|
|
165
|
+
let result;
|
|
166
|
+
try {
|
|
167
|
+
result = await this.deps.run(cmd, args);
|
|
168
|
+
}
|
|
169
|
+
catch (err) {
|
|
170
|
+
const code = err?.code;
|
|
171
|
+
if (code === "ENOENT") {
|
|
172
|
+
throw new Error("Gemini CLI is not installed or not on PATH. Run `npm install -g @google/gemini-cli` and re-run install-agents.");
|
|
173
|
+
}
|
|
174
|
+
throw err;
|
|
175
|
+
}
|
|
176
|
+
if (result.stdout)
|
|
177
|
+
opts.logger(result.stdout, "debug");
|
|
178
|
+
if (result.exitCode !== 0) {
|
|
179
|
+
throw new Error(`\`${cmd} ${args.join(" ")}\` exited with code ${result.exitCode}` +
|
|
180
|
+
(result.stderr ? `: ${result.stderr}` : ""));
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
// Re-read on-disk state post-install so the report reflects reality even
|
|
184
|
+
// when the network probe failed or this was a fresh install (where
|
|
185
|
+
// `enriched` was never enriched with latestVersion). Same pattern used by
|
|
186
|
+
// the Qwen and Copilot adapters.
|
|
187
|
+
const postInstall = await this.queryLocalInstallState();
|
|
188
|
+
const installedVersion = enriched.latestVersion ??
|
|
189
|
+
postInstall.installedVersion ??
|
|
190
|
+
enriched.installedVersion;
|
|
191
|
+
let action;
|
|
192
|
+
if (opts.force && isInstalled && isUpToDate)
|
|
193
|
+
action = "forced";
|
|
194
|
+
else if (isInstalled)
|
|
195
|
+
action = "updated";
|
|
196
|
+
else
|
|
197
|
+
action = "installed";
|
|
198
|
+
return {
|
|
199
|
+
adapterId: this.id,
|
|
200
|
+
scope: opts.scope,
|
|
201
|
+
action,
|
|
202
|
+
installedVersion,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
export const geminiCliAdapter = new GeminiCliAdapter();
|
|
207
|
+
//# sourceMappingURL=gemini-cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gemini-cli.js","sourceRoot":"","sources":["../../../src/agents/adapters/gemini-cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { AgentAdapter, DetectionResult, InstallOptions, InstallReport, InstallState, Scope } from "../types.js";
|
|
2
|
+
export interface RunResult {
|
|
3
|
+
stdout: string;
|
|
4
|
+
stderr: string;
|
|
5
|
+
exitCode: number;
|
|
6
|
+
}
|
|
7
|
+
export interface OpenCodeDeps {
|
|
8
|
+
run: (cmd: string, args: string[]) => Promise<RunResult>;
|
|
9
|
+
existsSync: (p: string) => boolean;
|
|
10
|
+
readFileSync: (p: string, encoding?: BufferEncoding) => string;
|
|
11
|
+
readdirSync?: (p: string) => string[];
|
|
12
|
+
mkdirSync?: (p: string, opts?: {
|
|
13
|
+
recursive?: boolean;
|
|
14
|
+
}) => void;
|
|
15
|
+
writeFileSync?: (p: string, data: string | Buffer) => void;
|
|
16
|
+
rmSync?: (p: string, opts?: {
|
|
17
|
+
recursive?: boolean;
|
|
18
|
+
force?: boolean;
|
|
19
|
+
}) => void;
|
|
20
|
+
homedir: () => string;
|
|
21
|
+
cwd: () => string;
|
|
22
|
+
fetchLatestVersion: () => Promise<string | undefined>;
|
|
23
|
+
fetchZip: (ref: string) => Promise<{
|
|
24
|
+
tempDir: string;
|
|
25
|
+
ref: string;
|
|
26
|
+
owned?: boolean;
|
|
27
|
+
}>;
|
|
28
|
+
}
|
|
29
|
+
export declare function defaultOpenCodeDeps(): OpenCodeDeps;
|
|
30
|
+
export declare class OpenCodeAdapter implements AgentAdapter {
|
|
31
|
+
readonly id = "opencode";
|
|
32
|
+
readonly displayName = "OpenCode";
|
|
33
|
+
private deps;
|
|
34
|
+
constructor(deps?: OpenCodeDeps);
|
|
35
|
+
supportsScopes(): Scope[];
|
|
36
|
+
detect(): Promise<DetectionResult>;
|
|
37
|
+
getInstallState(scope: Scope): Promise<InstallState>;
|
|
38
|
+
/**
|
|
39
|
+
* Resolve the scope root. Global scope prefers the XDG-style config dir
|
|
40
|
+
* (~/.config/opencode/) that OpenCode documents as primary. Project scope
|
|
41
|
+
* uses ./.opencode/ for committed, team-shared skills.
|
|
42
|
+
*/
|
|
43
|
+
private scopeRoot;
|
|
44
|
+
private canonicalSkillPath;
|
|
45
|
+
private queryLocalInstallState;
|
|
46
|
+
private enrichWithLatest;
|
|
47
|
+
install(opts: InstallOptions): Promise<InstallReport>;
|
|
48
|
+
private mkdirp;
|
|
49
|
+
/**
|
|
50
|
+
* Walk a directory tree and remove any file or directory whose basename
|
|
51
|
+
* starts with "doc-detective". Used before re-copying hooks/ or agents/ so
|
|
52
|
+
* we prune our own stale artifacts (files/dirs renamed or removed
|
|
53
|
+
* upstream) without touching unrelated user content living in the same
|
|
54
|
+
* directory.
|
|
55
|
+
*/
|
|
56
|
+
private pruneDocDetectiveFiles;
|
|
57
|
+
/**
|
|
58
|
+
* Recursive directory copy. Uses `this.deps.readdirSync` and
|
|
59
|
+
* `this.deps.writeFileSync` where the injected signatures match, but falls
|
|
60
|
+
* back to `fs.statSync` and buffer-returning `fs.readFileSync` directly —
|
|
61
|
+
* the `OpenCodeDeps.readFileSync` signature returns a string, so we can't
|
|
62
|
+
* use it here without losing binary content.
|
|
63
|
+
*/
|
|
64
|
+
private copyDir;
|
|
65
|
+
}
|
|
66
|
+
export declare const opencodeAdapter: AgentAdapter;
|
|
67
|
+
//# sourceMappingURL=opencode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opencode.d.ts","sourceRoot":"","sources":["../../../src/agents/adapters/opencode.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,YAAY,EACZ,eAAe,EACf,cAAc,EACd,aAAa,EACb,YAAY,EACZ,KAAK,EACN,MAAM,aAAa,CAAC;AAKrB,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;IACzD,UAAU,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC;IACnC,YAAY,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,cAAc,KAAK,MAAM,CAAC;IAC/D,WAAW,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,EAAE,CAAC;IACtC,SAAS,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC;IAChE,aAAa,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,KAAK,IAAI,CAAC;IAC3D,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC;IAC9E,OAAO,EAAE,MAAM,MAAM,CAAC;IACtB,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,kBAAkB,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACtD,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CACvF;AAMD,wBAAgB,mBAAmB,IAAI,YAAY,CAqBlD;AAED,qBAAa,eAAgB,YAAW,YAAY;IAClD,QAAQ,CAAC,EAAE,cAAc;IACzB,QAAQ,CAAC,WAAW,cAAc;IAClC,OAAO,CAAC,IAAI,CAAe;gBAEf,IAAI,GAAE,YAAoC;IAItD,cAAc,IAAI,KAAK,EAAE;IAInB,MAAM,IAAI,OAAO,CAAC,eAAe,CAAC;IAsClC,eAAe,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,YAAY,CAAC;IAM1D;;;;OAIG;IACH,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,sBAAsB;YAWhB,gBAAgB;IAiBxB,OAAO,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IAuK3D,OAAO,CAAC,MAAM;IAKd;;;;;;OAMG;IACH,OAAO,CAAC,sBAAsB;IAmB9B;;;;;;OAMG;IACH,OAAO,CAAC,OAAO;CAmBhB;AAED,eAAO,MAAM,eAAe,EAAE,YAAoC,CAAC"}
|
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import axios from "axios";
|
|
5
|
+
import { safeSpawn } from "../spawn-helper.js";
|
|
6
|
+
import { fetchAgentToolsZip } from "../fetcher.js";
|
|
7
|
+
import { parseMetadataVersion } from "./codex.js";
|
|
8
|
+
const CANONICAL_SKILL = "doc-detective-init";
|
|
9
|
+
const LATEST_SKILL_URL = "https://raw.githubusercontent.com/doc-detective/agent-tools/main/skills/doc-detective-init/SKILL.md";
|
|
10
|
+
export function defaultOpenCodeDeps() {
|
|
11
|
+
return {
|
|
12
|
+
run: (cmd, args) => safeSpawn(cmd, args),
|
|
13
|
+
existsSync: fs.existsSync,
|
|
14
|
+
readFileSync: (p, enc = "utf8") => fs.readFileSync(p, enc),
|
|
15
|
+
readdirSync: (p) => fs.readdirSync(p),
|
|
16
|
+
mkdirSync: (p, opts) => { fs.mkdirSync(p, opts); },
|
|
17
|
+
writeFileSync: (p, data) => fs.writeFileSync(p, typeof data === "string" ? data : Buffer.from(data)),
|
|
18
|
+
rmSync: (p, opts) => { fs.rmSync(p, opts); },
|
|
19
|
+
homedir: os.homedir,
|
|
20
|
+
cwd: () => process.cwd(),
|
|
21
|
+
fetchLatestVersion: async () => {
|
|
22
|
+
const response = await axios.get(LATEST_SKILL_URL, {
|
|
23
|
+
timeout: 5000,
|
|
24
|
+
responseType: "text",
|
|
25
|
+
});
|
|
26
|
+
return parseMetadataVersion(String(response?.data ?? ""));
|
|
27
|
+
},
|
|
28
|
+
fetchZip: (ref) => fetchAgentToolsZip(ref),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export class OpenCodeAdapter {
|
|
32
|
+
id = "opencode";
|
|
33
|
+
displayName = "OpenCode";
|
|
34
|
+
deps;
|
|
35
|
+
constructor(deps = defaultOpenCodeDeps()) {
|
|
36
|
+
this.deps = deps;
|
|
37
|
+
}
|
|
38
|
+
supportsScopes() {
|
|
39
|
+
return ["global", "project"];
|
|
40
|
+
}
|
|
41
|
+
async detect() {
|
|
42
|
+
const configDir = path.join(this.deps.homedir(), ".config", "opencode");
|
|
43
|
+
const installDir = path.join(this.deps.homedir(), ".opencode");
|
|
44
|
+
const projectDir = path.join(this.deps.cwd(), ".opencode");
|
|
45
|
+
let onPath = false;
|
|
46
|
+
let version;
|
|
47
|
+
try {
|
|
48
|
+
const result = await this.deps.run("opencode", ["--version"]);
|
|
49
|
+
if (result.exitCode === 0 && result.stdout.trim()) {
|
|
50
|
+
onPath = true;
|
|
51
|
+
version = result.stdout.trim();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
// Binary absent — silent.
|
|
56
|
+
}
|
|
57
|
+
const configPaths = {};
|
|
58
|
+
if (this.deps.existsSync(configDir))
|
|
59
|
+
configPaths.global = configDir;
|
|
60
|
+
else if (this.deps.existsSync(installDir))
|
|
61
|
+
configPaths.global = installDir;
|
|
62
|
+
if (this.deps.existsSync(projectDir))
|
|
63
|
+
configPaths.project = projectDir;
|
|
64
|
+
const present = onPath || !!configPaths.global || !!configPaths.project;
|
|
65
|
+
const notes = [];
|
|
66
|
+
if (!onPath && (configPaths.global || configPaths.project)) {
|
|
67
|
+
notes.push("`opencode` not on PATH; skills will be written to <scope>/skills/ and auto-discovered on next OpenCode launch.");
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
present,
|
|
71
|
+
onPath,
|
|
72
|
+
version,
|
|
73
|
+
configPaths,
|
|
74
|
+
notes: notes.length ? notes : undefined,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
async getInstallState(scope) {
|
|
78
|
+
const base = this.queryLocalInstallState(scope);
|
|
79
|
+
if (!base.installed)
|
|
80
|
+
return base;
|
|
81
|
+
return this.enrichWithLatest(base);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Resolve the scope root. Global scope prefers the XDG-style config dir
|
|
85
|
+
* (~/.config/opencode/) that OpenCode documents as primary. Project scope
|
|
86
|
+
* uses ./.opencode/ for committed, team-shared skills.
|
|
87
|
+
*/
|
|
88
|
+
scopeRoot(scope) {
|
|
89
|
+
return scope === "global"
|
|
90
|
+
? path.join(this.deps.homedir(), ".config", "opencode")
|
|
91
|
+
: path.join(this.deps.cwd(), ".opencode");
|
|
92
|
+
}
|
|
93
|
+
canonicalSkillPath(scope) {
|
|
94
|
+
return path.join(this.scopeRoot(scope), "skills", CANONICAL_SKILL, "SKILL.md");
|
|
95
|
+
}
|
|
96
|
+
queryLocalInstallState(scope) {
|
|
97
|
+
const canonical = this.canonicalSkillPath(scope);
|
|
98
|
+
if (!this.deps.existsSync(canonical))
|
|
99
|
+
return { installed: false };
|
|
100
|
+
try {
|
|
101
|
+
const raw = this.deps.readFileSync(canonical, "utf8");
|
|
102
|
+
return { installed: true, installedVersion: parseMetadataVersion(raw) };
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
return { installed: false };
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
async enrichWithLatest(state) {
|
|
109
|
+
let latestVersion;
|
|
110
|
+
try {
|
|
111
|
+
latestVersion = await this.deps.fetchLatestVersion();
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
latestVersion = undefined;
|
|
115
|
+
}
|
|
116
|
+
if (!latestVersion) {
|
|
117
|
+
return { ...state, latestVersion: undefined, upToDate: undefined };
|
|
118
|
+
}
|
|
119
|
+
const upToDate = state.installedVersion !== undefined
|
|
120
|
+
? state.installedVersion === latestVersion
|
|
121
|
+
: undefined;
|
|
122
|
+
return { ...state, latestVersion, upToDate };
|
|
123
|
+
}
|
|
124
|
+
async install(opts) {
|
|
125
|
+
const local = this.queryLocalInstallState(opts.scope);
|
|
126
|
+
const enriched = local.installed ? await this.enrichWithLatest(local) : local;
|
|
127
|
+
const isInstalled = enriched.installed;
|
|
128
|
+
const isUpToDate = enriched.upToDate === true;
|
|
129
|
+
// `upToDate === undefined` means the latest-version probe failed
|
|
130
|
+
// (offline, GitHub rate limit, etc.). Treat that as "keep what's on
|
|
131
|
+
// disk" instead of re-fetching and re-copying the entire zip every
|
|
132
|
+
// run. `--force` still works for explicit refresh.
|
|
133
|
+
const latestUnknown = isInstalled && enriched.upToDate === undefined;
|
|
134
|
+
if (isInstalled && !opts.force && (isUpToDate || latestUnknown)) {
|
|
135
|
+
if (latestUnknown) {
|
|
136
|
+
opts.logger("OpenCode is already installed, but the latest-version check failed; skipping reinstall. Use --force to reinstall anyway.", "info");
|
|
137
|
+
}
|
|
138
|
+
return {
|
|
139
|
+
adapterId: this.id,
|
|
140
|
+
scope: opts.scope,
|
|
141
|
+
action: "already-up-to-date",
|
|
142
|
+
installedVersion: enriched.installedVersion,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
const root = this.scopeRoot(opts.scope);
|
|
146
|
+
if (opts.dryRun) {
|
|
147
|
+
opts.logger(`[dry-run] would fetch doc-detective/agent-tools and copy into ${root}: ` +
|
|
148
|
+
`skills/doc-detective-*, plugins/opencode-plugin.mjs, hooks/, agents/`, "info");
|
|
149
|
+
return {
|
|
150
|
+
adapterId: this.id,
|
|
151
|
+
scope: opts.scope,
|
|
152
|
+
action: "dry-run",
|
|
153
|
+
installedVersion: enriched.installedVersion,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
const fetched = await this.deps.fetchZip("main");
|
|
157
|
+
try {
|
|
158
|
+
const pluginSrc = path.join(fetched.tempDir, "plugins", "doc-detective");
|
|
159
|
+
if (!this.deps.existsSync(pluginSrc)) {
|
|
160
|
+
throw new Error(`Fetched agent-tools archive has no plugins/doc-detective/ directory at ${pluginSrc}.`);
|
|
161
|
+
}
|
|
162
|
+
// Fall back to module-level fs.rmSync when no rmSync is injected —
|
|
163
|
+
// required for the atomic rename below to succeed when `dst` exists.
|
|
164
|
+
const rmSync = this.deps.rmSync ??
|
|
165
|
+
((p, opts) => fs.rmSync(p, opts));
|
|
166
|
+
// 1. Skills (doc-detective-* only) — fail loudly if missing, then
|
|
167
|
+
// atomic-overwrite each skill (copy to a tmp sibling, swap in).
|
|
168
|
+
const skillsSrc = path.join(pluginSrc, "skills");
|
|
169
|
+
const skillsDst = path.join(root, "skills");
|
|
170
|
+
if (!this.deps.existsSync(skillsSrc)) {
|
|
171
|
+
throw new Error(`Fetched agent-tools archive has no plugins/doc-detective/skills/ directory at ${skillsSrc}.`);
|
|
172
|
+
}
|
|
173
|
+
const names = (this.deps.readdirSync?.(skillsSrc) ?? []).filter((n) => n.startsWith("doc-detective-"));
|
|
174
|
+
if (names.length === 0) {
|
|
175
|
+
throw new Error("Fetched agent-tools archive has no OpenCode doc-detective-* skills to install.");
|
|
176
|
+
}
|
|
177
|
+
this.mkdirp(skillsDst);
|
|
178
|
+
for (const name of names) {
|
|
179
|
+
const src = path.join(skillsSrc, name);
|
|
180
|
+
const dst = path.join(skillsDst, name);
|
|
181
|
+
const tmpDst = `${dst}.install.tmp.${process.pid}.${Date.now()}`;
|
|
182
|
+
if (this.deps.existsSync(tmpDst)) {
|
|
183
|
+
rmSync(tmpDst, { recursive: true, force: true });
|
|
184
|
+
}
|
|
185
|
+
try {
|
|
186
|
+
this.copyDir(src, tmpDst);
|
|
187
|
+
}
|
|
188
|
+
catch (err) {
|
|
189
|
+
try {
|
|
190
|
+
rmSync(tmpDst, { recursive: true, force: true });
|
|
191
|
+
}
|
|
192
|
+
catch { }
|
|
193
|
+
throw err;
|
|
194
|
+
}
|
|
195
|
+
if (this.deps.existsSync(dst)) {
|
|
196
|
+
rmSync(dst, { recursive: true, force: true });
|
|
197
|
+
}
|
|
198
|
+
fs.renameSync(tmpDst, dst);
|
|
199
|
+
opts.logger(`Copied skill: ${name}`, "debug");
|
|
200
|
+
}
|
|
201
|
+
// 2. Plugin file — also required for OpenCode integration to work.
|
|
202
|
+
const pluginFileSrc = path.join(pluginSrc, "opencode-plugin.mjs");
|
|
203
|
+
if (!this.deps.existsSync(pluginFileSrc)) {
|
|
204
|
+
throw new Error(`Fetched agent-tools archive has no OpenCode plugin file at ${pluginFileSrc}.`);
|
|
205
|
+
}
|
|
206
|
+
const pluginFileDst = path.join(root, "plugins", "opencode-plugin.mjs");
|
|
207
|
+
this.mkdirp(path.dirname(pluginFileDst));
|
|
208
|
+
const buf = fs.readFileSync(pluginFileSrc);
|
|
209
|
+
if (this.deps.writeFileSync)
|
|
210
|
+
this.deps.writeFileSync(pluginFileDst, buf);
|
|
211
|
+
else
|
|
212
|
+
fs.writeFileSync(pluginFileDst, buf);
|
|
213
|
+
opts.logger("Copied plugin: opencode-plugin.mjs", "debug");
|
|
214
|
+
// 3. Hooks dir — copy additively. We can't safely wipe the whole dir
|
|
215
|
+
// because OpenCode users may keep their own hooks alongside ours.
|
|
216
|
+
// We prune only doc-detective-owned files: anything whose basename
|
|
217
|
+
// starts with "doc-detective" and lives under hooks/ gets removed
|
|
218
|
+
// first, so files renamed/removed upstream don't linger. Unrelated
|
|
219
|
+
// user content is preserved.
|
|
220
|
+
const hooksSrc = path.join(pluginSrc, "hooks");
|
|
221
|
+
const hooksDst = path.join(root, "hooks");
|
|
222
|
+
if (this.deps.existsSync(hooksSrc)) {
|
|
223
|
+
if (this.deps.existsSync(hooksDst)) {
|
|
224
|
+
this.pruneDocDetectiveFiles(hooksDst);
|
|
225
|
+
}
|
|
226
|
+
this.copyDir(hooksSrc, hooksDst);
|
|
227
|
+
opts.logger("Copied hooks/", "debug");
|
|
228
|
+
}
|
|
229
|
+
// 4. Agents dir — same additive-copy + targeted-prune pattern as hooks.
|
|
230
|
+
const agentsSrc = path.join(pluginSrc, "agents");
|
|
231
|
+
const agentsDst = path.join(root, "agents");
|
|
232
|
+
if (this.deps.existsSync(agentsSrc)) {
|
|
233
|
+
if (this.deps.existsSync(agentsDst)) {
|
|
234
|
+
this.pruneDocDetectiveFiles(agentsDst);
|
|
235
|
+
}
|
|
236
|
+
this.copyDir(agentsSrc, agentsDst);
|
|
237
|
+
opts.logger("Copied agents/", "debug");
|
|
238
|
+
}
|
|
239
|
+
const installedVersion = this.queryLocalInstallState(opts.scope).installedVersion ??
|
|
240
|
+
enriched.latestVersion;
|
|
241
|
+
let action;
|
|
242
|
+
if (opts.force && isInstalled && isUpToDate)
|
|
243
|
+
action = "forced";
|
|
244
|
+
else if (isInstalled)
|
|
245
|
+
action = "updated";
|
|
246
|
+
else
|
|
247
|
+
action = "installed";
|
|
248
|
+
return {
|
|
249
|
+
adapterId: this.id,
|
|
250
|
+
scope: opts.scope,
|
|
251
|
+
action,
|
|
252
|
+
installedVersion,
|
|
253
|
+
notes: [
|
|
254
|
+
"OpenCode auto-discovers skills and plugins at startup — restart OpenCode if it's currently running.",
|
|
255
|
+
],
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
catch (err) {
|
|
259
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
260
|
+
throw new Error(`Failed to install OpenCode tools from GitHub: ${reason}`);
|
|
261
|
+
}
|
|
262
|
+
finally {
|
|
263
|
+
// Only clean up the fetched tempDir when the fetcher reports ownership.
|
|
264
|
+
// Tests that inject a pre-populated source tree set `owned: false`.
|
|
265
|
+
if (fetched.owned) {
|
|
266
|
+
try {
|
|
267
|
+
this.deps.rmSync?.(fetched.tempDir, { recursive: true, force: true });
|
|
268
|
+
}
|
|
269
|
+
catch { }
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
mkdirp(p) {
|
|
274
|
+
if (this.deps.mkdirSync)
|
|
275
|
+
this.deps.mkdirSync(p, { recursive: true });
|
|
276
|
+
else
|
|
277
|
+
fs.mkdirSync(p, { recursive: true });
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Walk a directory tree and remove any file or directory whose basename
|
|
281
|
+
* starts with "doc-detective". Used before re-copying hooks/ or agents/ so
|
|
282
|
+
* we prune our own stale artifacts (files/dirs renamed or removed
|
|
283
|
+
* upstream) without touching unrelated user content living in the same
|
|
284
|
+
* directory.
|
|
285
|
+
*/
|
|
286
|
+
pruneDocDetectiveFiles(dir) {
|
|
287
|
+
const rmSync = this.deps.rmSync ??
|
|
288
|
+
((p, opts) => fs.rmSync(p, opts));
|
|
289
|
+
const entries = this.deps.readdirSync?.(dir) ?? [];
|
|
290
|
+
for (const name of entries) {
|
|
291
|
+
const full = path.join(dir, name);
|
|
292
|
+
if (name.startsWith("doc-detective")) {
|
|
293
|
+
rmSync(full, { recursive: true, force: true });
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
296
|
+
// Recurse into subdirectories to catch nested doc-detective-* files
|
|
297
|
+
// (e.g., hooks/scripts/doc-detective-before.js).
|
|
298
|
+
let isDir = false;
|
|
299
|
+
try {
|
|
300
|
+
isDir = fs.statSync(full).isDirectory();
|
|
301
|
+
}
|
|
302
|
+
catch { }
|
|
303
|
+
if (isDir)
|
|
304
|
+
this.pruneDocDetectiveFiles(full);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Recursive directory copy. Uses `this.deps.readdirSync` and
|
|
309
|
+
* `this.deps.writeFileSync` where the injected signatures match, but falls
|
|
310
|
+
* back to `fs.statSync` and buffer-returning `fs.readFileSync` directly —
|
|
311
|
+
* the `OpenCodeDeps.readFileSync` signature returns a string, so we can't
|
|
312
|
+
* use it here without losing binary content.
|
|
313
|
+
*/
|
|
314
|
+
copyDir(src, dst) {
|
|
315
|
+
this.mkdirp(dst);
|
|
316
|
+
const entries = this.deps.readdirSync?.(src) ?? [];
|
|
317
|
+
for (const entry of entries) {
|
|
318
|
+
const from = path.join(src, entry);
|
|
319
|
+
const to = path.join(dst, entry);
|
|
320
|
+
const stat = fs.statSync(from);
|
|
321
|
+
if (stat.isDirectory()) {
|
|
322
|
+
this.copyDir(from, to);
|
|
323
|
+
}
|
|
324
|
+
else {
|
|
325
|
+
const buf = fs.readFileSync(from);
|
|
326
|
+
if (this.deps.writeFileSync)
|
|
327
|
+
this.deps.writeFileSync(to, buf);
|
|
328
|
+
else
|
|
329
|
+
fs.writeFileSync(to, buf);
|
|
330
|
+
// Preserve executable bits from the source so shell-script hooks
|
|
331
|
+
// keep working after install.
|
|
332
|
+
try {
|
|
333
|
+
fs.chmodSync(to, stat.mode);
|
|
334
|
+
}
|
|
335
|
+
catch { }
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
export const opencodeAdapter = new OpenCodeAdapter();
|
|
341
|
+
//# sourceMappingURL=opencode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opencode.js","sourceRoot":"","sources":["../../../src/agents/adapters/opencode.ts"],"names":[],"mappings":"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"}
|