@datagusto/cli 0.0.0-stage → 0.2.0
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/LICENSE +21 -0
- package/README.md +186 -2
- package/bin/run.js +5 -0
- package/dist/adapters/claude-code.d.ts +48 -0
- package/dist/adapters/claude-code.js +526 -0
- package/dist/adapters/claude-code.js.map +1 -0
- package/dist/adapters/claude-settings.d.ts +29 -0
- package/dist/adapters/claude-settings.js +115 -0
- package/dist/adapters/claude-settings.js.map +1 -0
- package/dist/adapters/index.d.ts +10 -0
- package/dist/adapters/index.js +37 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/kiro-agent.d.ts +29 -0
- package/dist/adapters/kiro-agent.js +124 -0
- package/dist/adapters/kiro-agent.js.map +1 -0
- package/dist/adapters/kiro.d.ts +24 -0
- package/dist/adapters/kiro.js +752 -0
- package/dist/adapters/kiro.js.map +1 -0
- package/dist/adapters/types.d.ts +81 -0
- package/dist/adapters/types.js +14 -0
- package/dist/adapters/types.js.map +1 -0
- package/dist/api/client.d.ts +36 -0
- package/dist/api/client.js +85 -0
- package/dist/api/client.js.map +1 -0
- package/dist/api/errors.d.ts +4 -0
- package/dist/api/errors.js +25 -0
- package/dist/api/errors.js.map +1 -0
- package/dist/commands/remove.d.ts +13 -0
- package/dist/commands/remove.js +59 -0
- package/dist/commands/remove.js.map +1 -0
- package/dist/commands/setup.d.ts +16 -0
- package/dist/commands/setup.js +114 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/status.d.ts +7 -0
- package/dist/commands/status.js +53 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/display.d.ts +2 -0
- package/dist/display.js +12 -0
- package/dist/display.js.map +1 -0
- package/dist/fs/atomic.d.ts +23 -0
- package/dist/fs/atomic.js +65 -0
- package/dist/fs/atomic.js.map +1 -0
- package/dist/key-input.d.ts +24 -0
- package/dist/key-input.js +96 -0
- package/dist/key-input.js.map +1 -0
- package/dist/platform.d.ts +24 -0
- package/dist/platform.js +61 -0
- package/dist/platform.js.map +1 -0
- package/dist/state/installs.d.ts +24 -0
- package/dist/state/installs.js +110 -0
- package/dist/state/installs.js.map +1 -0
- package/dist/vendor.d.ts +16 -0
- package/dist/vendor.js +60 -0
- package/dist/vendor.js.map +1 -0
- package/package.json +57 -4
- package/vendor/claude_code/.claude-plugin/plugin.json +55 -0
- package/vendor/claude_code/README.md +267 -0
- package/vendor/claude_code/dist/api-client.js +82 -0
- package/vendor/claude_code/dist/builtin-tools.generated.js +33 -0
- package/vendor/claude_code/dist/extractors.js +201 -0
- package/vendor/claude_code/dist/index.js +695 -0
- package/vendor/claude_code/dist/monitoring.js +66 -0
- package/vendor/claude_code/dist/state.js +71 -0
- package/vendor/claude_code/dist/types.js +5 -0
- package/vendor/claude_code/hooks/hooks.json +25 -0
- package/vendor/claude_code/package.json +26 -0
- package/vendor/kiro/.kiro/agents/kiro_default.json +20 -0
- package/vendor/kiro/.kiro/hooks/datagusto-post-tool-use.json +10 -0
- package/vendor/kiro/.kiro/hooks/datagusto-pre-tool-use.json +10 -0
- package/vendor/kiro/.kiro/hooks/datagusto-session-start.json +10 -0
- package/vendor/kiro/.kiro/hooks/datagusto-stop.json +10 -0
- package/vendor/kiro/.kiro/hooks/datagusto-user-prompt-submit.json +10 -0
- package/vendor/kiro/dist/api-client.js +82 -0
- package/vendor/kiro/dist/builtin-tools.generated.js +87 -0
- package/vendor/kiro/dist/engine.js +65 -0
- package/vendor/kiro/dist/extractors.js +201 -0
- package/vendor/kiro/dist/index.js +735 -0
- package/vendor/kiro/dist/monitoring.js +66 -0
- package/vendor/kiro/dist/state.js +71 -0
- package/vendor/kiro/dist/types.js +5 -0
- package/vendor/kiro/package.json +25 -0
- package/vendor/manifest.json +42 -0
|
@@ -0,0 +1,526 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// dg CLI - Claude Code adapter
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
//
|
|
5
|
+
// Installs the bundled claude_code plugin as hooks in the user's settings:
|
|
6
|
+
//
|
|
7
|
+
// ~/.datagusto/claude-code/
|
|
8
|
+
// dist/, hooks/hooks.json, .claude-plugin/, package.json
|
|
9
|
+
// claude-code.json serverUrl + apiKey, mode 0600
|
|
10
|
+
// .datagusto-install.json ownership marker + file hashes
|
|
11
|
+
// ~/.claude/settings.json the plugin's hooks, pointing at that folder
|
|
12
|
+
//
|
|
13
|
+
// settings.json hooks work on every Claude Code version that has hooks, so
|
|
14
|
+
// there is one install method. The plugin's own loadConfig() reads
|
|
15
|
+
// claude-code.json from the plugin root, so the plugin runtime is unchanged
|
|
16
|
+
// (ADR-0003 TR-2, TR-8). The folder lives outside ~/.claude so no Claude Code
|
|
17
|
+
// version also loads it as a plugin, which would run every hook twice.
|
|
18
|
+
//
|
|
19
|
+
// settings.json belongs to the user (TR-5): only entries whose command points
|
|
20
|
+
// into our folder are added or removed (see claude-settings.ts). Only events
|
|
21
|
+
// the installed Claude Code knows are written, because before 2.1.122 one bad
|
|
22
|
+
// hooks entry could invalidate the whole settings file.
|
|
23
|
+
//
|
|
24
|
+
// The plugin folder is built in a staging dir next to the target and renamed
|
|
25
|
+
// into place, and restored if the settings edit then fails, so a failed setup
|
|
26
|
+
// leaves the previous install (or nothing) behind. The marker is how clear()
|
|
27
|
+
// and a re-run tell our folder from one the user made; a folder without it is
|
|
28
|
+
// never touched.
|
|
29
|
+
import { execFile } from "node:child_process";
|
|
30
|
+
import { randomBytes } from "node:crypto";
|
|
31
|
+
import { access, constants, copyFile, lstat, mkdir, readFile, rename, rm, stat } from "node:fs/promises";
|
|
32
|
+
import { dirname, join } from "node:path";
|
|
33
|
+
import { promisify } from "node:util";
|
|
34
|
+
import { DatagustoApiClient } from "../api/client.js";
|
|
35
|
+
import { explainApiError } from "../api/errors.js";
|
|
36
|
+
import { tildify } from "../display.js";
|
|
37
|
+
import { ensureDir, renameWithRetry, writeFileAtomic } from "../fs/atomic.js";
|
|
38
|
+
import { hasUnixPermissions, hookCommandPath, isWindows, onPath } from "../platform.js";
|
|
39
|
+
import { changedFiles, loadVendoredPlugin } from "../vendor.js";
|
|
40
|
+
import { addHooks, eventsWithHooks, readSettings, removeHooks, writeSettings, } from "./claude-settings.js";
|
|
41
|
+
import { AdapterError, } from "./types.js";
|
|
42
|
+
const PLUGIN_DIR_NAME = "claude-code";
|
|
43
|
+
/** Where dg builds before the settings.json method put the plugin. */
|
|
44
|
+
const LEGACY_SKILLS_DIR_NAME = "datagusto-safety";
|
|
45
|
+
const VENDOR_NAME = "claude_code";
|
|
46
|
+
const CONFIG_FILE = "claude-code.json";
|
|
47
|
+
const MARKER_FILE = ".datagusto-install.json";
|
|
48
|
+
const INSTALLED_BY = "@datagusto/cli";
|
|
49
|
+
const PLUGIN_ROOT_VAR = "${CLAUDE_PLUGIN_ROOT}";
|
|
50
|
+
/** Oldest Claude Code dg will set up: has SessionStart + UserPromptSubmit. */
|
|
51
|
+
export const MIN_HOOKS_VERSION = "1.0.62";
|
|
52
|
+
/**
|
|
53
|
+
* First Claude Code release with each hook event, from its CHANGELOG.md.
|
|
54
|
+
* PostToolUseFailure's first changelog mention is 2.1.119, so that is used as
|
|
55
|
+
* a safe lower bound. Events not listed are never written to settings.json.
|
|
56
|
+
*/
|
|
57
|
+
export const HOOK_EVENT_SINCE = {
|
|
58
|
+
PreToolUse: "1.0.38",
|
|
59
|
+
PostToolUse: "1.0.38",
|
|
60
|
+
UserPromptSubmit: "1.0.54",
|
|
61
|
+
SessionStart: "1.0.62",
|
|
62
|
+
SessionEnd: "1.0.85",
|
|
63
|
+
PermissionRequest: "2.0.45",
|
|
64
|
+
PostToolUseFailure: "2.1.119",
|
|
65
|
+
};
|
|
66
|
+
export class ClaudeCodeAdapter {
|
|
67
|
+
name = "claude-code";
|
|
68
|
+
displayName = "Claude Code";
|
|
69
|
+
whoami;
|
|
70
|
+
claudeVersion;
|
|
71
|
+
constructor(deps = {}) {
|
|
72
|
+
this.whoami = deps.whoami ?? ((serverUrl, apiKey) => new DatagustoApiClient({ serverUrl, apiKey }).whoami());
|
|
73
|
+
this.claudeVersion = deps.claudeVersion ?? runClaudeVersion;
|
|
74
|
+
}
|
|
75
|
+
pluginDir(ctx) {
|
|
76
|
+
return join(ctx.homeDir, ".datagusto", PLUGIN_DIR_NAME);
|
|
77
|
+
}
|
|
78
|
+
async installedServerUrl(ctx) {
|
|
79
|
+
const dir = this.pluginDir(ctx);
|
|
80
|
+
if ((await ownership(dir)).state !== "ours")
|
|
81
|
+
return undefined;
|
|
82
|
+
const config = await readJsonObject(join(dir, CONFIG_FILE));
|
|
83
|
+
return typeof config.serverUrl === "string" && config.serverUrl ? config.serverUrl : undefined;
|
|
84
|
+
}
|
|
85
|
+
/** ~/.claude/skills/datagusto-safety, removed on setup if dg created it. */
|
|
86
|
+
legacySkillsDir(ctx) {
|
|
87
|
+
return join(ctx.homeDir, ".claude", "skills", LEGACY_SKILLS_DIR_NAME);
|
|
88
|
+
}
|
|
89
|
+
settingsPath(ctx) {
|
|
90
|
+
return join(ctx.homeDir, ".claude", "settings.json");
|
|
91
|
+
}
|
|
92
|
+
async detect(ctx) {
|
|
93
|
+
if ((await isDir(join(ctx.homeDir, ".claude"))) || (await onPath("claude", ctx.env, ctx.platform))) {
|
|
94
|
+
return { found: true };
|
|
95
|
+
}
|
|
96
|
+
const install = isWindows(ctx.platform)
|
|
97
|
+
? "`irm https://claude.ai/install.ps1 | iex` in PowerShell"
|
|
98
|
+
: "`curl -fsSL https://claude.ai/install.sh | bash`";
|
|
99
|
+
return {
|
|
100
|
+
found: false,
|
|
101
|
+
detail: "Claude Code doesn't look installed: there's no `claude` command on your PATH and no ~/.claude folder. " +
|
|
102
|
+
`Install it with ${install}, start \`claude\` once to sign in, then run this again.`,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
async plan(ctx, _conn) {
|
|
106
|
+
const version = await this.supportedVersion(ctx);
|
|
107
|
+
const dir = this.pluginDir(ctx);
|
|
108
|
+
const owner = await ownership(dir);
|
|
109
|
+
if (owner.state === "foreign")
|
|
110
|
+
throw foreignDirError(dir, ctx.homeDir);
|
|
111
|
+
const plugin = await loadVendoredPlugin(ctx.vendorDir, VENDOR_NAME);
|
|
112
|
+
const update = owner.state === "ours";
|
|
113
|
+
// Read now so a broken settings.json stops setup before anything is written.
|
|
114
|
+
await readSettings(this.settingsPath(ctx));
|
|
115
|
+
const hooks = settingsHooks(await readVendoredHooks(join(ctx.vendorDir, VENDOR_NAME)), dir, version, ctx.platform);
|
|
116
|
+
const changes = [
|
|
117
|
+
{
|
|
118
|
+
kind: "copy-dir",
|
|
119
|
+
path: dir,
|
|
120
|
+
description: `${update ? "Update" : "Install"} the Datagusto safety plugin v${plugin.pluginVersion}`,
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
kind: update ? "update-file" : "create-file",
|
|
124
|
+
path: join(dir, CONFIG_FILE),
|
|
125
|
+
description: "Save the server URL and API key (readable only by you)",
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
kind: "merge-json",
|
|
129
|
+
path: this.settingsPath(ctx),
|
|
130
|
+
description: `Add the plugin's ${Object.keys(hooks).length} hooks (your other settings are left as they are)`,
|
|
131
|
+
},
|
|
132
|
+
];
|
|
133
|
+
if ((await ownership(this.legacySkillsDir(ctx))).state === "ours") {
|
|
134
|
+
changes.push({
|
|
135
|
+
kind: "remove",
|
|
136
|
+
path: this.legacySkillsDir(ctx),
|
|
137
|
+
description: "Remove the copy an earlier dg installed",
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
return { agent: this.name, changes };
|
|
141
|
+
}
|
|
142
|
+
async apply(ctx, _plan, conn) {
|
|
143
|
+
const version = await this.supportedVersion(ctx);
|
|
144
|
+
const dir = this.pluginDir(ctx);
|
|
145
|
+
const legacyDir = this.legacySkillsDir(ctx);
|
|
146
|
+
const src = join(ctx.vendorDir, VENDOR_NAME);
|
|
147
|
+
const plugin = await loadVendoredPlugin(ctx.vendorDir, VENDOR_NAME);
|
|
148
|
+
const damaged = await changedFiles(src, plugin.files);
|
|
149
|
+
if (damaged.length > 0) {
|
|
150
|
+
throw new AdapterError(`The plugin files bundled with dg are damaged (${damaged.join(", ")}). ` +
|
|
151
|
+
"Reinstall the CLI: npm install -g @datagusto/cli");
|
|
152
|
+
}
|
|
153
|
+
const owner = await ownership(dir);
|
|
154
|
+
if (owner.state === "foreign")
|
|
155
|
+
throw foreignDirError(dir, ctx.homeDir);
|
|
156
|
+
const legacyOwner = await ownership(legacyDir);
|
|
157
|
+
// Work out the new settings.json before touching disk.
|
|
158
|
+
const hooks = settingsHooks(await readVendoredHooks(src), dir, version, ctx.platform);
|
|
159
|
+
const settings = await readSettings(this.settingsPath(ctx));
|
|
160
|
+
removeHooks(settings, pointsInto(ctx.platform, dir, legacyDir));
|
|
161
|
+
addHooks(settings, hooks);
|
|
162
|
+
// A re-run keeps any other options the user put in claude-code.json
|
|
163
|
+
// (verbose, monitorOnly, …).
|
|
164
|
+
const previousFrom = owner.state === "ours" ? dir : legacyOwner.state === "ours" ? legacyDir : undefined;
|
|
165
|
+
const previous = previousFrom ? await readJsonObject(join(previousFrom, CONFIG_FILE)) : {};
|
|
166
|
+
const config = { ...previous, serverUrl: conn.serverUrl, apiKey: conn.apiKey };
|
|
167
|
+
const marker = {
|
|
168
|
+
installedBy: INSTALLED_BY,
|
|
169
|
+
cliVersion: ctx.cliVersion,
|
|
170
|
+
pluginVersion: plugin.pluginVersion,
|
|
171
|
+
hookEvents: Object.keys(hooks),
|
|
172
|
+
files: plugin.files,
|
|
173
|
+
};
|
|
174
|
+
const parent = dirname(dir);
|
|
175
|
+
await ensureDir(parent, 0o700); // ~/.datagusto is ours
|
|
176
|
+
const staging = join(parent, `.${PLUGIN_DIR_NAME}.${randomBytes(4).toString("hex")}.staging`);
|
|
177
|
+
try {
|
|
178
|
+
await mkdir(staging, { mode: 0o755 });
|
|
179
|
+
for (const rel of Object.keys(plugin.files)) {
|
|
180
|
+
const to = join(staging, ...rel.split("/"));
|
|
181
|
+
await mkdir(dirname(to), { recursive: true });
|
|
182
|
+
await copyFile(join(src, ...rel.split("/")), to);
|
|
183
|
+
}
|
|
184
|
+
await writeFileAtomic(join(staging, CONFIG_FILE), JSON.stringify(config, null, 2) + "\n", { mode: 0o600 });
|
|
185
|
+
await writeFileAtomic(join(staging, MARKER_FILE), JSON.stringify(marker, null, 2) + "\n");
|
|
186
|
+
const swap = await swapIntoPlace(staging, dir);
|
|
187
|
+
try {
|
|
188
|
+
await writeSettings(settings);
|
|
189
|
+
}
|
|
190
|
+
catch (err) {
|
|
191
|
+
await swap.rollback();
|
|
192
|
+
throw err;
|
|
193
|
+
}
|
|
194
|
+
await swap.commit();
|
|
195
|
+
}
|
|
196
|
+
finally {
|
|
197
|
+
await rm(staging, { recursive: true, force: true });
|
|
198
|
+
}
|
|
199
|
+
// An earlier dg installed a plugin copy that Claude Code 2.1.157+ loads by
|
|
200
|
+
// itself; left in place, every hook would run twice.
|
|
201
|
+
if (legacyOwner.state === "ours")
|
|
202
|
+
await rm(legacyDir, { recursive: true, force: true });
|
|
203
|
+
return {
|
|
204
|
+
agent: this.name,
|
|
205
|
+
workspace: null,
|
|
206
|
+
agentId: conn.agentId,
|
|
207
|
+
paths: [dir, this.settingsPath(ctx)],
|
|
208
|
+
installedAt: new Date().toISOString(),
|
|
209
|
+
cliVersion: ctx.cliVersion,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
async clear(ctx, record) {
|
|
213
|
+
const result = { removed: [], edited: [], skipped: [] };
|
|
214
|
+
const settingsPath = this.settingsPath(ctx);
|
|
215
|
+
const dirs = record.paths.filter((p) => p !== settingsPath);
|
|
216
|
+
// Hooks first: hooks pointing at a deleted folder would error on every call.
|
|
217
|
+
if (record.paths.includes(settingsPath)) {
|
|
218
|
+
try {
|
|
219
|
+
if (await this.removeSettingsHooks(ctx, dirs))
|
|
220
|
+
result.edited.push(settingsPath);
|
|
221
|
+
}
|
|
222
|
+
catch (err) {
|
|
223
|
+
if (!(err instanceof AdapterError))
|
|
224
|
+
throw err;
|
|
225
|
+
result.skipped.push(settingsPath);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
for (const path of dirs) {
|
|
229
|
+
const owner = await ownership(path);
|
|
230
|
+
if (owner.state === "ours") {
|
|
231
|
+
await rm(path, { recursive: true, force: true });
|
|
232
|
+
result.removed.push(path);
|
|
233
|
+
}
|
|
234
|
+
else if (owner.state === "foreign") {
|
|
235
|
+
result.skipped.push(path);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return result;
|
|
239
|
+
}
|
|
240
|
+
async doctor(ctx, record) {
|
|
241
|
+
const report = { agent: this.name, checks: [] };
|
|
242
|
+
const add = (check) => report.checks.push(check);
|
|
243
|
+
const dir = record.paths[0] ?? this.pluginDir(ctx);
|
|
244
|
+
const shown = tildify(dir, ctx.homeDir);
|
|
245
|
+
const owner = await ownership(dir);
|
|
246
|
+
add(await this.checkClaudeVersion(ctx, owner.state === "ours" ? owner.marker.hookEvents : undefined));
|
|
247
|
+
if (dir !== this.pluginDir(ctx)) {
|
|
248
|
+
add({
|
|
249
|
+
name: "Plugin files",
|
|
250
|
+
status: "fail",
|
|
251
|
+
detail: `${shown} was installed by an earlier dg. Run \`dg setup claude-code\` again to move it.`,
|
|
252
|
+
});
|
|
253
|
+
return report;
|
|
254
|
+
}
|
|
255
|
+
if (owner.state !== "ours") {
|
|
256
|
+
add({
|
|
257
|
+
name: "Plugin files",
|
|
258
|
+
status: "fail",
|
|
259
|
+
detail: owner.state === "missing"
|
|
260
|
+
? `${shown} is gone. Run \`dg setup claude-code\` again to reinstall it.`
|
|
261
|
+
: `${shown} is no longer the folder dg installed. Run \`dg setup claude-code\` again after moving it away.`,
|
|
262
|
+
});
|
|
263
|
+
return report;
|
|
264
|
+
}
|
|
265
|
+
const changed = await changedFiles(dir, owner.marker.files);
|
|
266
|
+
add(changed.length === 0
|
|
267
|
+
? { name: "Plugin files", status: "ok", detail: `${shown} (v${owner.marker.pluginVersion})` }
|
|
268
|
+
: {
|
|
269
|
+
name: "Plugin files",
|
|
270
|
+
status: "fail",
|
|
271
|
+
detail: `Changed or missing: ${changed.join(", ")}. Run \`dg setup claude-code\` again to repair them.`,
|
|
272
|
+
});
|
|
273
|
+
add(await this.checkSettingsHooks(ctx, dir, owner.marker.hookEvents ?? []));
|
|
274
|
+
try {
|
|
275
|
+
const bundled = await loadVendoredPlugin(ctx.vendorDir, VENDOR_NAME);
|
|
276
|
+
if (!sameFiles(bundled.files, owner.marker.files)) {
|
|
277
|
+
add({
|
|
278
|
+
name: "Plugin version",
|
|
279
|
+
status: "warn",
|
|
280
|
+
detail: `This dg bundles plugin v${bundled.pluginVersion}, but v${owner.marker.pluginVersion} is installed. ` +
|
|
281
|
+
"Run `dg setup claude-code` again to update it.",
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
catch {
|
|
286
|
+
// A broken CLI package is setup's problem; status still reports the rest.
|
|
287
|
+
}
|
|
288
|
+
const configPath = join(dir, CONFIG_FILE);
|
|
289
|
+
const config = await readJsonObject(configPath);
|
|
290
|
+
const serverUrl = typeof config.serverUrl === "string" ? config.serverUrl : "";
|
|
291
|
+
const apiKey = typeof config.apiKey === "string" ? config.apiKey : "";
|
|
292
|
+
if (!serverUrl || !apiKey) {
|
|
293
|
+
add({
|
|
294
|
+
name: "Config",
|
|
295
|
+
status: "fail",
|
|
296
|
+
detail: `${tildify(configPath, ctx.homeDir)} has no server URL or API key. Run \`dg setup claude-code\` again.`,
|
|
297
|
+
});
|
|
298
|
+
return report;
|
|
299
|
+
}
|
|
300
|
+
// Windows has no mode bits to check: the user profile's access rules keep the file private.
|
|
301
|
+
const fileMode = hasUnixPermissions(ctx.platform) ? (await stat(configPath)).mode & 0o777 : 0o600;
|
|
302
|
+
add(fileMode & 0o077
|
|
303
|
+
? {
|
|
304
|
+
name: "Config",
|
|
305
|
+
status: "warn",
|
|
306
|
+
detail: `${tildify(configPath, ctx.homeDir)} holds your API key but other users can read it. Run: chmod 600 ${configPath}`,
|
|
307
|
+
}
|
|
308
|
+
: { name: "Config", status: "ok", detail: serverUrl });
|
|
309
|
+
const who = await this.whoami(serverUrl, apiKey);
|
|
310
|
+
if (!who.ok) {
|
|
311
|
+
add({ name: "API key", status: "fail", detail: explainApiError(who, serverUrl) });
|
|
312
|
+
return report;
|
|
313
|
+
}
|
|
314
|
+
report.agentName = who.data.name;
|
|
315
|
+
add(who.data.agent_id === record.agentId
|
|
316
|
+
? { name: "API key", status: "ok", detail: `agent "${who.data.name}"` }
|
|
317
|
+
: {
|
|
318
|
+
name: "API key",
|
|
319
|
+
status: "warn",
|
|
320
|
+
detail: `The key now belongs to agent "${who.data.name}", not the one it was set up with. ` +
|
|
321
|
+
"Run `dg setup claude-code` again if that's not what you want.",
|
|
322
|
+
});
|
|
323
|
+
return report;
|
|
324
|
+
}
|
|
325
|
+
// -- Internal ---------------------------------------------------------------
|
|
326
|
+
/** Parsed `claude --version` (undefined if it can't be run); throws if too old. */
|
|
327
|
+
async supportedVersion(ctx) {
|
|
328
|
+
const version = parseVersion(await this.claudeVersion(ctx.env));
|
|
329
|
+
if (version && compareVersions(version, MIN_HOOKS_VERSION) < 0) {
|
|
330
|
+
throw new AdapterError(`Claude Code ${version} is too old for the Datagusto plugin. Update Claude Code, then run this again.`);
|
|
331
|
+
}
|
|
332
|
+
return version;
|
|
333
|
+
}
|
|
334
|
+
/** Drop hooks pointing into `dirs` from settings.json; true if any went. */
|
|
335
|
+
async removeSettingsHooks(ctx, dirs) {
|
|
336
|
+
const settings = await readSettings(this.settingsPath(ctx));
|
|
337
|
+
if (!settings.exists || removeHooks(settings, pointsInto(ctx.platform, ...dirs)) === 0)
|
|
338
|
+
return false;
|
|
339
|
+
await writeSettings(settings);
|
|
340
|
+
return true;
|
|
341
|
+
}
|
|
342
|
+
async checkClaudeVersion(ctx, installedEvents) {
|
|
343
|
+
const version = parseVersion(await this.claudeVersion(ctx.env));
|
|
344
|
+
const name = "Claude Code";
|
|
345
|
+
if (!version) {
|
|
346
|
+
return { name, status: "warn", detail: "Couldn't run `claude --version` to check which version is installed." };
|
|
347
|
+
}
|
|
348
|
+
if (compareVersions(version, MIN_HOOKS_VERSION) < 0) {
|
|
349
|
+
return { name, status: "fail", detail: `Claude Code ${version} is too old for the plugin. Update Claude Code.` };
|
|
350
|
+
}
|
|
351
|
+
// Claude Code was upgraded since setup: it now has events setup left out.
|
|
352
|
+
const newer = installedEvents
|
|
353
|
+
? Object.keys(HOOK_EVENT_SINCE).filter((e) => compareVersions(version, HOOK_EVENT_SINCE[e]) >= 0 && !installedEvents.includes(e))
|
|
354
|
+
: [];
|
|
355
|
+
if (newer.length > 0) {
|
|
356
|
+
return {
|
|
357
|
+
name,
|
|
358
|
+
status: "warn",
|
|
359
|
+
detail: `Claude Code ${version} has hook events that weren't available when this was set up (${newer.join(", ")}). ` +
|
|
360
|
+
"Run `dg setup claude-code` again to add them.",
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
return { name, status: "ok", detail: version };
|
|
364
|
+
}
|
|
365
|
+
async checkSettingsHooks(ctx, dir, expected) {
|
|
366
|
+
const name = "Hooks";
|
|
367
|
+
let settings;
|
|
368
|
+
try {
|
|
369
|
+
settings = await readSettings(this.settingsPath(ctx));
|
|
370
|
+
}
|
|
371
|
+
catch (err) {
|
|
372
|
+
if (!(err instanceof AdapterError))
|
|
373
|
+
throw err;
|
|
374
|
+
return { name, status: "fail", detail: `${err.message.split(",")[0]}, so Claude Code may be ignoring it.` };
|
|
375
|
+
}
|
|
376
|
+
const present = eventsWithHooks(settings, pointsInto(ctx.platform, dir));
|
|
377
|
+
const missing = expected.filter((e) => !present.includes(e));
|
|
378
|
+
return missing.length === 0
|
|
379
|
+
? { name, status: "ok", detail: `${present.length} events in ~/.claude/settings.json` }
|
|
380
|
+
: {
|
|
381
|
+
name,
|
|
382
|
+
status: "fail",
|
|
383
|
+
detail: `Missing from ~/.claude/settings.json: ${missing.join(", ")}. Run \`dg setup claude-code\` again.`,
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
// -- Internal helpers ---------------------------------------------------------
|
|
388
|
+
/** Matches hook commands that run a script inside one of `dirs`. */
|
|
389
|
+
function pointsInto(platform, ...dirs) {
|
|
390
|
+
const prefixes = dirs.map((d) => `${hookCommandPath(d, platform)}/`);
|
|
391
|
+
return (command) => prefixes.some((p) => command.includes(p));
|
|
392
|
+
}
|
|
393
|
+
async function readVendoredHooks(pluginSrc) {
|
|
394
|
+
const parsed = JSON.parse(await readFile(join(pluginSrc, "hooks", "hooks.json"), "utf8"));
|
|
395
|
+
return parsed.hooks;
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
398
|
+
* The plugin's hooks.json rewritten for settings.json: ${CLAUDE_PLUGIN_ROOT}
|
|
399
|
+
* becomes the absolute plugin folder (only plugins get that variable), and
|
|
400
|
+
* events `version` doesn't know are left out.
|
|
401
|
+
*/
|
|
402
|
+
export function settingsHooks(pluginHooks, pluginDir, version, platform) {
|
|
403
|
+
const dir = hookCommandPath(pluginDir, platform);
|
|
404
|
+
if (/["$`\\]/.test(dir)) {
|
|
405
|
+
throw new AdapterError(`Your home folder path (${dir}) has characters dg can't safely put in a hook command ` +
|
|
406
|
+
'(a double quote, $, backtick or backslash).');
|
|
407
|
+
}
|
|
408
|
+
const out = {};
|
|
409
|
+
for (const [event, groups] of Object.entries(pluginHooks)) {
|
|
410
|
+
const since = HOOK_EVENT_SINCE[event];
|
|
411
|
+
// An unknown version (`claude` isn't on PATH) is assumed to be current.
|
|
412
|
+
if (!since || (version && compareVersions(version, since) < 0))
|
|
413
|
+
continue;
|
|
414
|
+
out[event] = groups.map((g) => ({
|
|
415
|
+
...g,
|
|
416
|
+
hooks: g.hooks.map((h) => (typeof h.command === "string" ? { ...h, command: h.command.split(PLUGIN_ROOT_VAR).join(dir) } : h)),
|
|
417
|
+
}));
|
|
418
|
+
}
|
|
419
|
+
return out;
|
|
420
|
+
}
|
|
421
|
+
function foreignDirError(dir, homeDir) {
|
|
422
|
+
return new AdapterError(`${tildify(dir, homeDir)} already exists and wasn't created by dg, so it was left alone. ` +
|
|
423
|
+
"Move or delete it, then run this again.");
|
|
424
|
+
}
|
|
425
|
+
async function ownership(dir) {
|
|
426
|
+
let info;
|
|
427
|
+
try {
|
|
428
|
+
info = await lstat(dir);
|
|
429
|
+
}
|
|
430
|
+
catch (err) {
|
|
431
|
+
if (err.code === "ENOENT")
|
|
432
|
+
return { state: "missing" };
|
|
433
|
+
throw err;
|
|
434
|
+
}
|
|
435
|
+
if (!info.isDirectory())
|
|
436
|
+
return { state: "foreign" };
|
|
437
|
+
const marker = await readJsonObject(join(dir, MARKER_FILE));
|
|
438
|
+
if (marker.installedBy !== INSTALLED_BY || typeof marker.files !== "object" || marker.files === null) {
|
|
439
|
+
return { state: "foreign" };
|
|
440
|
+
}
|
|
441
|
+
return { state: "ours", marker: marker };
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* Rename `staging` to `target`. The old `target` is kept aside until
|
|
445
|
+
* commit(), so rollback() can put it back.
|
|
446
|
+
*/
|
|
447
|
+
async function swapIntoPlace(staging, target) {
|
|
448
|
+
let backup;
|
|
449
|
+
if (await exists(target)) {
|
|
450
|
+
backup = `${staging}.old`;
|
|
451
|
+
await renameWithRetry(target, backup);
|
|
452
|
+
}
|
|
453
|
+
try {
|
|
454
|
+
await renameWithRetry(staging, target);
|
|
455
|
+
}
|
|
456
|
+
catch (err) {
|
|
457
|
+
if (backup)
|
|
458
|
+
await rename(backup, target);
|
|
459
|
+
throw err;
|
|
460
|
+
}
|
|
461
|
+
return {
|
|
462
|
+
commit: async () => {
|
|
463
|
+
if (backup)
|
|
464
|
+
await rm(backup, { recursive: true, force: true });
|
|
465
|
+
},
|
|
466
|
+
rollback: async () => {
|
|
467
|
+
await rm(target, { recursive: true, force: true });
|
|
468
|
+
if (backup)
|
|
469
|
+
await rename(backup, target);
|
|
470
|
+
},
|
|
471
|
+
};
|
|
472
|
+
}
|
|
473
|
+
async function readJsonObject(path) {
|
|
474
|
+
try {
|
|
475
|
+
const v = JSON.parse(await readFile(path, "utf8"));
|
|
476
|
+
return typeof v === "object" && v !== null && !Array.isArray(v) ? v : {};
|
|
477
|
+
}
|
|
478
|
+
catch {
|
|
479
|
+
return {};
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
function sameFiles(a, b) {
|
|
483
|
+
const keys = Object.keys(a);
|
|
484
|
+
return keys.length === Object.keys(b).length && keys.every((k) => a[k] === b[k]);
|
|
485
|
+
}
|
|
486
|
+
function parseVersion(output) {
|
|
487
|
+
return output?.match(/(\d+)\.(\d+)\.(\d+)/)?.[0];
|
|
488
|
+
}
|
|
489
|
+
export function compareVersions(a, b) {
|
|
490
|
+
const pa = a.split(".").map(Number);
|
|
491
|
+
const pb = b.split(".").map(Number);
|
|
492
|
+
for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
|
|
493
|
+
const d = (pa[i] ?? 0) - (pb[i] ?? 0);
|
|
494
|
+
if (d !== 0)
|
|
495
|
+
return Math.sign(d);
|
|
496
|
+
}
|
|
497
|
+
return 0;
|
|
498
|
+
}
|
|
499
|
+
async function exists(path) {
|
|
500
|
+
try {
|
|
501
|
+
await lstat(path);
|
|
502
|
+
return true;
|
|
503
|
+
}
|
|
504
|
+
catch {
|
|
505
|
+
return false;
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
async function isDir(path) {
|
|
509
|
+
try {
|
|
510
|
+
return (await stat(path)).isDirectory();
|
|
511
|
+
}
|
|
512
|
+
catch {
|
|
513
|
+
return false;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
async function runClaudeVersion(env) {
|
|
517
|
+
try {
|
|
518
|
+
// On Windows `claude` may be an npm .cmd shim, which only runs through a shell.
|
|
519
|
+
const { stdout } = await promisify(execFile)("claude", ["--version"], { env, timeout: 10_000, shell: isWindows() });
|
|
520
|
+
return stdout;
|
|
521
|
+
}
|
|
522
|
+
catch {
|
|
523
|
+
return undefined;
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
//# sourceMappingURL=claude-code.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-code.js","sourceRoot":"","sources":["../../src/adapters/claude-code.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** `hooks` in settings.json: event → matcher groups. */
|
|
2
|
+
export type HooksConfig = Record<string, MatcherGroup[]>;
|
|
3
|
+
export interface MatcherGroup {
|
|
4
|
+
matcher?: string;
|
|
5
|
+
hooks: HookHandler[];
|
|
6
|
+
[key: string]: unknown;
|
|
7
|
+
}
|
|
8
|
+
export interface HookHandler {
|
|
9
|
+
type: string;
|
|
10
|
+
command?: string;
|
|
11
|
+
[key: string]: unknown;
|
|
12
|
+
}
|
|
13
|
+
export interface SettingsFile {
|
|
14
|
+
/** The path as given, e.g. ~/.claude/settings.json. */
|
|
15
|
+
path: string;
|
|
16
|
+
/** Where writes go: the symlink target if `path` is a symlink. */
|
|
17
|
+
realPath: string;
|
|
18
|
+
exists: boolean;
|
|
19
|
+
mode: number;
|
|
20
|
+
data: Record<string, unknown>;
|
|
21
|
+
}
|
|
22
|
+
export declare function readSettings(path: string): Promise<SettingsFile>;
|
|
23
|
+
export declare function writeSettings(file: SettingsFile): Promise<void>;
|
|
24
|
+
/** Remove every handler whose command `isOurs`; returns how many went. */
|
|
25
|
+
export declare function removeHooks(file: SettingsFile, isOurs: (command: string) => boolean): number;
|
|
26
|
+
/** Append `add`'s matcher groups after whatever each event already has. */
|
|
27
|
+
export declare function addHooks(file: SettingsFile, add: HooksConfig): void;
|
|
28
|
+
/** Events that have at least one handler whose command `isOurs`. */
|
|
29
|
+
export declare function eventsWithHooks(file: SettingsFile, isOurs: (command: string) => boolean): string[];
|