@a5c-ai/babysitter-opencode 5.0.1-staging.e4f17eff → 5.0.1-staging.ef4e872c
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/README.md +2 -2
- package/bin/cli.cjs +1 -191
- package/bin/cli.js +90 -49
- package/bin/install-shared.cjs +1 -478
- package/bin/install-shared.js +615 -0
- package/bin/install.cjs +1 -143
- package/bin/install.js +18 -98
- package/bin/uninstall.cjs +1 -87
- package/bin/uninstall.js +12 -34
- package/commands/doctor.md +5 -5
- package/commands/help.md +245 -244
- package/commands/observe.md +12 -12
- package/hooks/babysitter-proxied-session-created.js +18 -212
- package/hooks/babysitter-proxied-session-created.sh +11 -0
- package/hooks/babysitter-proxied-session-idle.js +18 -167
- package/hooks/babysitter-proxied-session-idle.sh +3 -0
- package/hooks/babysitter-proxied-shell-env.js +21 -145
- package/hooks/babysitter-proxied-shell-env.sh +3 -0
- package/hooks/babysitter-proxied-tool-execute-after.js +20 -160
- package/hooks/babysitter-proxied-tool-execute-after.sh +3 -0
- package/hooks/babysitter-proxied-tool-execute-before.js +20 -162
- package/hooks/babysitter-proxied-tool-execute-before.sh +3 -0
- package/hooks/hooks.json +18 -18
- package/package.json +22 -18
- package/plugin.json +6 -4
- package/scripts/team-install.js +23 -0
- package/skills/contrib/SKILL.md +25 -25
- package/skills/doctor/SKILL.md +5 -5
- package/skills/help/SKILL.md +3 -2
- package/skills/observe/SKILL.md +1 -1
- package/skills/plugins/SKILL.md +243 -243
- package/skills/project-install/SKILL.md +3 -3
- package/skills/resume/SKILL.md +1 -1
- package/skills/retrospect/SKILL.md +48 -48
- package/skills/user-install/SKILL.md +3 -3
- package/versions.json +2 -2
- package/hooks/hooks.json.legacy +0 -46
- package/hooks/proxied-hooks.json +0 -47
- package/hooks/session-created.js +0 -182
- package/hooks/session-idle.js +0 -124
- package/hooks/shell-env.js +0 -88
- package/hooks/tool-execute-after.js +0 -107
- package/hooks/tool-execute-before.js +0 -109
package/bin/install-shared.cjs
CHANGED
|
@@ -1,480 +1,3 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
1
|
'use strict';
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
* Shared installation utilities for babysitter-opencode plugin.
|
|
6
|
-
*
|
|
7
|
-
* Handles plugin bundle copying, OpenCode config registration,
|
|
8
|
-
* marketplace entry management, and process library bootstrapping.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
const fs = require('fs');
|
|
12
|
-
const os = require('os');
|
|
13
|
-
const path = require('path');
|
|
14
|
-
const { spawnSync } = require('child_process');
|
|
15
|
-
|
|
16
|
-
const PLUGIN_NAME = 'babysitter';
|
|
17
|
-
|
|
18
|
-
const PLUGIN_BUNDLE_ENTRIES = [
|
|
19
|
-
'plugin.json',
|
|
20
|
-
'versions.json',
|
|
21
|
-
'hooks',
|
|
22
|
-
'skills',
|
|
23
|
-
'commands',
|
|
24
|
-
];
|
|
25
|
-
|
|
26
|
-
const HOOK_SCRIPT_NAMES = [
|
|
27
|
-
'session-created.js',
|
|
28
|
-
'session-idle.js',
|
|
29
|
-
'shell-env.js',
|
|
30
|
-
'tool-execute-before.js',
|
|
31
|
-
'tool-execute-after.js',
|
|
32
|
-
];
|
|
33
|
-
|
|
34
|
-
const DEFAULT_MARKETPLACE = {
|
|
35
|
-
name: 'local-plugins',
|
|
36
|
-
interface: {
|
|
37
|
-
displayName: 'Local Plugins',
|
|
38
|
-
},
|
|
39
|
-
plugins: [],
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
// ---------------------------------------------------------------------------
|
|
43
|
-
// Path helpers
|
|
44
|
-
// ---------------------------------------------------------------------------
|
|
45
|
-
|
|
46
|
-
function getUserHome() {
|
|
47
|
-
if (process.env.USERPROFILE) return path.resolve(process.env.USERPROFILE);
|
|
48
|
-
if (process.env.HOME) return path.resolve(process.env.HOME);
|
|
49
|
-
return os.homedir();
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function getGlobalStateDir() {
|
|
53
|
-
if (process.env.BABYSITTER_GLOBAL_STATE_DIR) {
|
|
54
|
-
return path.resolve(process.env.BABYSITTER_GLOBAL_STATE_DIR);
|
|
55
|
-
}
|
|
56
|
-
return path.join(getUserHome(), '.a5c');
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Resolve the OpenCode config root.
|
|
61
|
-
* OpenCode uses `.opencode/` in the workspace directory by default.
|
|
62
|
-
* Respect OPENCODE_HOME env var if set.
|
|
63
|
-
*/
|
|
64
|
-
function getOpenCodeHome(workspace) {
|
|
65
|
-
if (process.env.OPENCODE_HOME) return path.resolve(process.env.OPENCODE_HOME);
|
|
66
|
-
return path.join(workspace || process.cwd(), '.opencode');
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function getHomePluginRoot(workspace) {
|
|
70
|
-
if (process.env.BABYSITTER_OPENCODE_PLUGIN_DIR) {
|
|
71
|
-
return path.resolve(process.env.BABYSITTER_OPENCODE_PLUGIN_DIR, PLUGIN_NAME);
|
|
72
|
-
}
|
|
73
|
-
return path.join(getOpenCodeHome(workspace), 'plugins', PLUGIN_NAME);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function getHomeMarketplacePath(workspace) {
|
|
77
|
-
if (process.env.BABYSITTER_OPENCODE_MARKETPLACE_PATH) {
|
|
78
|
-
return path.resolve(process.env.BABYSITTER_OPENCODE_MARKETPLACE_PATH);
|
|
79
|
-
}
|
|
80
|
-
return path.join(getUserHome(), '.agents', 'plugins', 'marketplace.json');
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// ---------------------------------------------------------------------------
|
|
84
|
-
// File utilities
|
|
85
|
-
// ---------------------------------------------------------------------------
|
|
86
|
-
|
|
87
|
-
function writeFileIfChanged(filePath, contents) {
|
|
88
|
-
if (fs.existsSync(filePath)) {
|
|
89
|
-
const current = fs.readFileSync(filePath, 'utf8');
|
|
90
|
-
if (current === contents) return false;
|
|
91
|
-
}
|
|
92
|
-
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
93
|
-
fs.writeFileSync(filePath, contents, 'utf8');
|
|
94
|
-
return true;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
function readJson(filePath) {
|
|
98
|
-
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
function writeJson(filePath, value) {
|
|
102
|
-
writeFileIfChanged(filePath, `${JSON.stringify(value, null, 2)}\n`);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
function copyRecursive(src, dest) {
|
|
106
|
-
const stat = fs.statSync(src);
|
|
107
|
-
if (stat.isDirectory()) {
|
|
108
|
-
fs.mkdirSync(dest, { recursive: true });
|
|
109
|
-
for (const entry of fs.readdirSync(src)) {
|
|
110
|
-
if (['node_modules', '.git', 'test', '.a5c'].includes(entry)) continue;
|
|
111
|
-
copyRecursive(path.join(src, entry), path.join(dest, entry));
|
|
112
|
-
}
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// Strip BOM from SKILL.md files
|
|
117
|
-
if (path.basename(src) === 'SKILL.md') {
|
|
118
|
-
const file = fs.readFileSync(src);
|
|
119
|
-
const hasBom = file.length >= 3 && file[0] === 0xef && file[1] === 0xbb && file[2] === 0xbf;
|
|
120
|
-
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
121
|
-
fs.writeFileSync(dest, hasBom ? file.subarray(3) : file);
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
126
|
-
fs.copyFileSync(src, dest);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// ---------------------------------------------------------------------------
|
|
130
|
-
// Plugin bundle
|
|
131
|
-
// ---------------------------------------------------------------------------
|
|
132
|
-
|
|
133
|
-
function copyPluginBundle(packageRoot, pluginRoot) {
|
|
134
|
-
if (path.resolve(packageRoot) === path.resolve(pluginRoot)) {
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
fs.rmSync(pluginRoot, { recursive: true, force: true });
|
|
138
|
-
fs.mkdirSync(pluginRoot, { recursive: true });
|
|
139
|
-
for (const entry of PLUGIN_BUNDLE_ENTRIES) {
|
|
140
|
-
const src = path.join(packageRoot, entry);
|
|
141
|
-
if (fs.existsSync(src)) {
|
|
142
|
-
copyRecursive(src, path.join(pluginRoot, entry));
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// ---------------------------------------------------------------------------
|
|
148
|
-
// OpenCode index.js entry point generation
|
|
149
|
-
// ---------------------------------------------------------------------------
|
|
150
|
-
|
|
151
|
-
function writeIndexJs(pluginRoot) {
|
|
152
|
-
const indexContent = `#!/usr/bin/env node
|
|
153
|
-
/**
|
|
154
|
-
* Babysitter plugin entry point for OpenCode.
|
|
155
|
-
*
|
|
156
|
-
* OpenCode discovers plugins by looking for JS/TS modules in
|
|
157
|
-
* .opencode/plugins/. This file registers the babysitter hooks
|
|
158
|
-
* with the OpenCode plugin system.
|
|
159
|
-
*/
|
|
160
|
-
|
|
161
|
-
"use strict";
|
|
162
|
-
|
|
163
|
-
const path = require("path");
|
|
164
|
-
|
|
165
|
-
const PLUGIN_DIR = __dirname;
|
|
166
|
-
|
|
167
|
-
module.exports = {
|
|
168
|
-
name: "babysitter",
|
|
169
|
-
version: require(path.join(PLUGIN_DIR, "plugin.json")).version,
|
|
170
|
-
|
|
171
|
-
hooks: {
|
|
172
|
-
"session.created": require(path.join(PLUGIN_DIR, "hooks", "session-created.js")),
|
|
173
|
-
"session.idle": require(path.join(PLUGIN_DIR, "hooks", "session-idle.js")),
|
|
174
|
-
"shell.env": require(path.join(PLUGIN_DIR, "hooks", "shell-env.js")),
|
|
175
|
-
"tool.execute.before": require(path.join(PLUGIN_DIR, "hooks", "tool-execute-before.js")),
|
|
176
|
-
"tool.execute.after": require(path.join(PLUGIN_DIR, "hooks", "tool-execute-after.js")),
|
|
177
|
-
},
|
|
178
|
-
};
|
|
179
|
-
`;
|
|
180
|
-
fs.writeFileSync(path.join(pluginRoot, 'index.js'), indexContent, 'utf8');
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
// ---------------------------------------------------------------------------
|
|
184
|
-
// OpenCode hooks.json config registration
|
|
185
|
-
// ---------------------------------------------------------------------------
|
|
186
|
-
|
|
187
|
-
function mergeHooksConfig(packageRoot, openCodeHome) {
|
|
188
|
-
const hooksJsonPath = path.join(packageRoot, 'hooks', 'hooks.json');
|
|
189
|
-
if (!fs.existsSync(hooksJsonPath)) return;
|
|
190
|
-
const managedConfig = readJson(hooksJsonPath);
|
|
191
|
-
const managedHooks = managedConfig.hooks || {};
|
|
192
|
-
const hooksConfigPath = path.join(openCodeHome, 'hooks.json');
|
|
193
|
-
const existing = fs.existsSync(hooksConfigPath)
|
|
194
|
-
? readJson(hooksConfigPath)
|
|
195
|
-
: { version: 1, hooks: {} };
|
|
196
|
-
existing.version = existing.version || 1;
|
|
197
|
-
if (!existing.hooks || typeof existing.hooks !== 'object') {
|
|
198
|
-
existing.hooks = {};
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
for (const [eventName, entries] of Object.entries(managedHooks)) {
|
|
202
|
-
const existingEntries = Array.isArray(existing.hooks[eventName]) ? existing.hooks[eventName] : [];
|
|
203
|
-
const filteredEntries = existingEntries.filter((entry) => {
|
|
204
|
-
const script = String(entry.script || entry.command || entry.bash || '');
|
|
205
|
-
return !HOOK_SCRIPT_NAMES.some((name) => script.includes(name));
|
|
206
|
-
});
|
|
207
|
-
existing.hooks[eventName] = [...filteredEntries, ...entries];
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
writeJson(hooksConfigPath, existing);
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
function removeManagedHooks(openCodeHome) {
|
|
214
|
-
const hooksConfigPath = path.join(openCodeHome, 'hooks.json');
|
|
215
|
-
if (!fs.existsSync(hooksConfigPath)) return;
|
|
216
|
-
|
|
217
|
-
let hooksConfig;
|
|
218
|
-
try {
|
|
219
|
-
hooksConfig = readJson(hooksConfigPath);
|
|
220
|
-
} catch {
|
|
221
|
-
return;
|
|
222
|
-
}
|
|
223
|
-
if (!hooksConfig.hooks || typeof hooksConfig.hooks !== 'object') return;
|
|
224
|
-
|
|
225
|
-
for (const eventName of Object.keys(hooksConfig.hooks)) {
|
|
226
|
-
const eventHooks = Array.isArray(hooksConfig.hooks[eventName]) ? hooksConfig.hooks[eventName] : [];
|
|
227
|
-
const filtered = eventHooks.filter((entry) => {
|
|
228
|
-
const script = String(entry.script || entry.command || entry.bash || '');
|
|
229
|
-
return !HOOK_SCRIPT_NAMES.some((name) => script.includes(name));
|
|
230
|
-
});
|
|
231
|
-
if (filtered.length > 0) {
|
|
232
|
-
hooksConfig.hooks[eventName] = filtered;
|
|
233
|
-
} else {
|
|
234
|
-
delete hooksConfig.hooks[eventName];
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
if (Object.keys(hooksConfig.hooks).length === 0) {
|
|
238
|
-
fs.rmSync(hooksConfigPath, { force: true });
|
|
239
|
-
} else {
|
|
240
|
-
writeJson(hooksConfigPath, hooksConfig);
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
// ---------------------------------------------------------------------------
|
|
245
|
-
// Marketplace
|
|
246
|
-
// ---------------------------------------------------------------------------
|
|
247
|
-
|
|
248
|
-
function normalizeMarketplaceName(name) {
|
|
249
|
-
const raw = String(name || '').trim();
|
|
250
|
-
const sanitized = raw
|
|
251
|
-
.replace(/[^A-Za-z0-9_-]+/g, '-')
|
|
252
|
-
.replace(/^-+|-+$/g, '');
|
|
253
|
-
return sanitized || DEFAULT_MARKETPLACE.name;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
function normalizeMarketplaceSourcePath(marketplacePath, pluginSourcePath) {
|
|
257
|
-
let next = pluginSourcePath;
|
|
258
|
-
if (path.isAbsolute(next)) {
|
|
259
|
-
next = path.relative(path.dirname(marketplacePath), next);
|
|
260
|
-
}
|
|
261
|
-
next = String(next || '').replace(/\\/g, '/');
|
|
262
|
-
if (!next.startsWith('./') && !next.startsWith('../')) {
|
|
263
|
-
next = `./${next}`;
|
|
264
|
-
}
|
|
265
|
-
return next;
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
function ensureMarketplaceEntry(marketplacePath, pluginSourcePath) {
|
|
269
|
-
const marketplace = fs.existsSync(marketplacePath)
|
|
270
|
-
? readJson(marketplacePath)
|
|
271
|
-
: { ...DEFAULT_MARKETPLACE, plugins: [] };
|
|
272
|
-
marketplace.name = normalizeMarketplaceName(marketplace.name);
|
|
273
|
-
marketplace.interface = marketplace.interface || {};
|
|
274
|
-
marketplace.interface.displayName =
|
|
275
|
-
marketplace.interface.displayName || DEFAULT_MARKETPLACE.interface.displayName;
|
|
276
|
-
const nextEntry = {
|
|
277
|
-
name: PLUGIN_NAME,
|
|
278
|
-
source: {
|
|
279
|
-
source: 'local',
|
|
280
|
-
path: normalizeMarketplaceSourcePath(marketplacePath, pluginSourcePath),
|
|
281
|
-
},
|
|
282
|
-
policy: {
|
|
283
|
-
installation: 'AVAILABLE',
|
|
284
|
-
authentication: 'ON_INSTALL',
|
|
285
|
-
},
|
|
286
|
-
category: 'Coding',
|
|
287
|
-
};
|
|
288
|
-
const existingIndex = Array.isArray(marketplace.plugins)
|
|
289
|
-
? marketplace.plugins.findIndex((entry) => entry && entry.name === PLUGIN_NAME)
|
|
290
|
-
: -1;
|
|
291
|
-
if (!Array.isArray(marketplace.plugins)) {
|
|
292
|
-
marketplace.plugins = [nextEntry];
|
|
293
|
-
} else if (existingIndex >= 0) {
|
|
294
|
-
marketplace.plugins[existingIndex] = nextEntry;
|
|
295
|
-
} else {
|
|
296
|
-
marketplace.plugins.push(nextEntry);
|
|
297
|
-
}
|
|
298
|
-
writeJson(marketplacePath, marketplace);
|
|
299
|
-
return nextEntry;
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
function removeMarketplaceEntry(marketplacePath) {
|
|
303
|
-
if (!fs.existsSync(marketplacePath)) return;
|
|
304
|
-
const marketplace = readJson(marketplacePath);
|
|
305
|
-
if (!Array.isArray(marketplace.plugins)) return;
|
|
306
|
-
marketplace.plugins = marketplace.plugins.filter((entry) => entry && entry.name !== PLUGIN_NAME);
|
|
307
|
-
writeJson(marketplacePath, marketplace);
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
// ---------------------------------------------------------------------------
|
|
311
|
-
// Babysitter SDK CLI helpers
|
|
312
|
-
// ---------------------------------------------------------------------------
|
|
313
|
-
|
|
314
|
-
function resolveBabysitterCommand(packageRoot) {
|
|
315
|
-
if (process.env.BABYSITTER_SDK_CLI) {
|
|
316
|
-
return {
|
|
317
|
-
command: process.execPath,
|
|
318
|
-
argsPrefix: [path.resolve(process.env.BABYSITTER_SDK_CLI)],
|
|
319
|
-
};
|
|
320
|
-
}
|
|
321
|
-
try {
|
|
322
|
-
return {
|
|
323
|
-
command: process.execPath,
|
|
324
|
-
argsPrefix: [
|
|
325
|
-
require.resolve('@a5c-ai/babysitter-sdk/dist/cli/main.js', {
|
|
326
|
-
paths: [packageRoot],
|
|
327
|
-
}),
|
|
328
|
-
],
|
|
329
|
-
};
|
|
330
|
-
} catch {
|
|
331
|
-
return {
|
|
332
|
-
command: 'babysitter',
|
|
333
|
-
argsPrefix: [],
|
|
334
|
-
};
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
function runBabysitterCli(packageRoot, cliArgs, options = {}) {
|
|
339
|
-
const resolved = resolveBabysitterCommand(packageRoot);
|
|
340
|
-
const result = spawnSync(resolved.command, [...resolved.argsPrefix, ...cliArgs], {
|
|
341
|
-
cwd: options.cwd || process.cwd(),
|
|
342
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
343
|
-
encoding: 'utf8',
|
|
344
|
-
env: {
|
|
345
|
-
...process.env,
|
|
346
|
-
...(options.env || {}),
|
|
347
|
-
},
|
|
348
|
-
});
|
|
349
|
-
if (result.status !== 0) {
|
|
350
|
-
const stderr = (result.stderr || '').trim();
|
|
351
|
-
const stdout = (result.stdout || '').trim();
|
|
352
|
-
throw new Error(
|
|
353
|
-
`babysitter ${cliArgs.join(' ')} failed` +
|
|
354
|
-
(stderr ? `: ${stderr}` : stdout ? `: ${stdout}` : ''),
|
|
355
|
-
);
|
|
356
|
-
}
|
|
357
|
-
return result.stdout;
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
function ensureGlobalProcessLibrary(packageRoot) {
|
|
361
|
-
return JSON.parse(
|
|
362
|
-
runBabysitterCli(
|
|
363
|
-
packageRoot,
|
|
364
|
-
['process-library:active', '--state-dir', getGlobalStateDir(), '--json'],
|
|
365
|
-
{ cwd: packageRoot },
|
|
366
|
-
),
|
|
367
|
-
);
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
// ---------------------------------------------------------------------------
|
|
371
|
-
// Accomplish AI detection and paths
|
|
372
|
-
// ---------------------------------------------------------------------------
|
|
373
|
-
|
|
374
|
-
/**
|
|
375
|
-
* Returns the Accomplish user data directory for the current platform.
|
|
376
|
-
* If OPENCODE_CONFIG_DIR is set, returns its parent (the Accomplish data dir).
|
|
377
|
-
* Otherwise falls back to platform-specific defaults.
|
|
378
|
-
*/
|
|
379
|
-
function getAccomplishDataDir() {
|
|
380
|
-
if (process.env.OPENCODE_CONFIG_DIR) {
|
|
381
|
-
return path.resolve(process.env.OPENCODE_CONFIG_DIR, '..');
|
|
382
|
-
}
|
|
383
|
-
const home = getUserHome();
|
|
384
|
-
switch (process.platform) {
|
|
385
|
-
case 'darwin':
|
|
386
|
-
return path.join(home, 'Library', 'Application Support', 'Accomplish');
|
|
387
|
-
case 'win32': {
|
|
388
|
-
const appData = process.env.APPDATA || process.env.LOCALAPPDATA;
|
|
389
|
-
return appData
|
|
390
|
-
? path.join(appData, 'Accomplish')
|
|
391
|
-
: path.join(home, 'AppData', 'Roaming', 'Accomplish');
|
|
392
|
-
}
|
|
393
|
-
default:
|
|
394
|
-
return path.join(home, '.config', 'Accomplish');
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
/**
|
|
399
|
-
* Returns true if Accomplish AI appears to be installed or is running.
|
|
400
|
-
* Checks for:
|
|
401
|
-
* - ACCOMPLISH_TASK_ID env var (running inside Accomplish)
|
|
402
|
-
* - Accomplish data dir with an opencode/ subdirectory on disk
|
|
403
|
-
*/
|
|
404
|
-
function isAccomplishInstalled() {
|
|
405
|
-
if (process.env.ACCOMPLISH_TASK_ID) return true;
|
|
406
|
-
try {
|
|
407
|
-
const dataDir = getAccomplishDataDir();
|
|
408
|
-
const openCodeDir = path.join(dataDir, 'opencode');
|
|
409
|
-
return fs.existsSync(openCodeDir);
|
|
410
|
-
} catch {
|
|
411
|
-
return false;
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
/**
|
|
416
|
-
* Returns the OpenCode home directory inside the Accomplish data dir.
|
|
417
|
-
*/
|
|
418
|
-
function getAccomplishOpenCodeHome() {
|
|
419
|
-
return path.join(getAccomplishDataDir(), 'opencode');
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
/**
|
|
423
|
-
* Install the babysitter plugin into Accomplish's OpenCode directory.
|
|
424
|
-
* Mirrors the standard OpenCode install: copies bundle, writes index.js,
|
|
425
|
-
* installs skills and hooks.
|
|
426
|
-
*/
|
|
427
|
-
function installAccomplishSurface(packageRoot, accomplishOpenCodeHome) {
|
|
428
|
-
const pluginRoot = path.join(accomplishOpenCodeHome, 'plugins', PLUGIN_NAME);
|
|
429
|
-
|
|
430
|
-
// Copy plugin bundle
|
|
431
|
-
copyPluginBundle(packageRoot, pluginRoot);
|
|
432
|
-
|
|
433
|
-
// Create index.js entry point
|
|
434
|
-
writeIndexJs(pluginRoot);
|
|
435
|
-
|
|
436
|
-
// Install skills and hooks config
|
|
437
|
-
installOpenCodeSurface(packageRoot, accomplishOpenCodeHome);
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
// ---------------------------------------------------------------------------
|
|
441
|
-
// OpenCode surface installation
|
|
442
|
-
// ---------------------------------------------------------------------------
|
|
443
|
-
|
|
444
|
-
function installOpenCodeSurface(packageRoot, openCodeHome) {
|
|
445
|
-
// Copy skills into .opencode/skills/
|
|
446
|
-
const sourceSkills = path.join(packageRoot, 'skills');
|
|
447
|
-
if (fs.existsSync(sourceSkills)) {
|
|
448
|
-
const targetSkills = path.join(openCodeHome, 'skills');
|
|
449
|
-
fs.mkdirSync(targetSkills, { recursive: true });
|
|
450
|
-
for (const entry of fs.readdirSync(sourceSkills, { withFileTypes: true })) {
|
|
451
|
-
if (!entry.isDirectory()) continue;
|
|
452
|
-
copyRecursive(
|
|
453
|
-
path.join(sourceSkills, entry.name),
|
|
454
|
-
path.join(targetSkills, entry.name),
|
|
455
|
-
);
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
// Merge hooks config
|
|
460
|
-
mergeHooksConfig(packageRoot, openCodeHome);
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
module.exports = {
|
|
464
|
-
copyPluginBundle,
|
|
465
|
-
copyRecursive,
|
|
466
|
-
ensureGlobalProcessLibrary,
|
|
467
|
-
ensureMarketplaceEntry,
|
|
468
|
-
getAccomplishDataDir,
|
|
469
|
-
getAccomplishOpenCodeHome,
|
|
470
|
-
getHomeMarketplacePath,
|
|
471
|
-
getHomePluginRoot,
|
|
472
|
-
getOpenCodeHome,
|
|
473
|
-
installAccomplishSurface,
|
|
474
|
-
installOpenCodeSurface,
|
|
475
|
-
isAccomplishInstalled,
|
|
476
|
-
removeManagedHooks,
|
|
477
|
-
removeMarketplaceEntry,
|
|
478
|
-
writeIndexJs,
|
|
479
|
-
writeJson,
|
|
480
|
-
};
|
|
3
|
+
module.exports = require('./install-shared.js');
|