@a5c-ai/babysitter-codex 0.1.6-staging.f48a64a2 → 0.1.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/.app.json +3 -0
- package/.codex-plugin/plugin.json +47 -0
- package/README.md +41 -108
- package/assets/icon.svg +7 -0
- package/assets/logo.svg +8 -0
- package/bin/install-shared.js +509 -0
- package/bin/install.js +29 -433
- package/bin/uninstall.js +19 -120
- package/{.codex/hooks → hooks}/babysitter-session-start.sh +0 -0
- package/{.codex/hooks → hooks}/babysitter-stop-hook.sh +0 -0
- package/{.codex/hooks.json → hooks.json} +3 -3
- package/package.json +9 -5
- package/scripts/team-install.js +32 -424
- package/skills/babysit/SKILL.md +798 -0
- package/{.codex/skills → skills}/call/SKILL.md +1 -0
- package/{.codex/skills → skills}/yolo/SKILL.md +3 -0
- package/.codex/config.toml +0 -25
- package/.codex/skills/babysit/SKILL.md +0 -385
- package/SKILL.md +0 -385
- /package/{.codex/hooks → hooks}/user-prompt-submit.sh +0 -0
- /package/{.codex/skills → skills}/assimilate/SKILL.md +0 -0
- /package/{.codex/skills → skills}/doctor/SKILL.md +0 -0
- /package/{.codex/skills → skills}/forever/SKILL.md +0 -0
- /package/{.codex/skills → skills}/help/SKILL.md +0 -0
- /package/{.codex/skills → skills}/issue/SKILL.md +0 -0
- /package/{.codex/skills → skills}/model/SKILL.md +0 -0
- /package/{.codex/skills → skills}/observe/SKILL.md +0 -0
- /package/{.codex/skills → skills}/plan/SKILL.md +0 -0
- /package/{.codex/skills → skills}/project-install/SKILL.md +0 -0
- /package/{.codex/skills → skills}/resume/SKILL.md +0 -0
- /package/{.codex/skills → skills}/retrospect/SKILL.md +0 -0
- /package/{.codex/skills → skills}/team-install/SKILL.md +0 -0
- /package/{.codex/skills → skills}/user-install/SKILL.md +0 -0
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@a5c-ai/babysitter-codex",
|
|
3
|
-
"version": "0.1.6
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "Babysitter Codex skill bundle and integration package for OpenAI Codex CLI with SDK-managed process-library bootstrapping, 15 orchestration modes, and BOM-safe SKILL installation",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "node test/integration.test.js && node test/packaged-install.test.js",
|
|
7
7
|
"test:integration": "node test/integration.test.js",
|
|
8
8
|
"team:install": "node scripts/team-install.js",
|
|
9
|
-
"lint": "node -e \"const fs=require('fs'); const path=require('path'); const cp=require('child_process'); const walk=(dir)=>{for(const entry of fs.readdirSync(dir)){const file=path.join(dir, entry); const stat=fs.statSync(file); if(stat.isDirectory()) walk(file); else if(file.endsWith('.js')) cp.execFileSync(process.execPath,['--check',file],{stdio:'inherit'});}}; ['
|
|
9
|
+
"lint": "node -e \"const fs=require('fs'); const path=require('path'); const cp=require('child_process'); const walk=(dir)=>{for(const entry of fs.readdirSync(dir)){const file=path.join(dir, entry); const stat=fs.statSync(file); if(stat.isDirectory()) walk(file); else if(file.endsWith('.js')) cp.execFileSync(process.execPath,['--check',file],{stdio:'inherit'});}}; ['skills','bin','scripts','test'].forEach((dir)=>{if(fs.existsSync(dir)) walk(dir);});\"",
|
|
10
10
|
"deploy": "npm publish --access public",
|
|
11
11
|
"deploy:staging": "npm publish --access public --tag staging"
|
|
12
12
|
},
|
|
@@ -14,8 +14,12 @@
|
|
|
14
14
|
"babysitter-codex": "bin/cli.js"
|
|
15
15
|
},
|
|
16
16
|
"files": [
|
|
17
|
-
"
|
|
18
|
-
".
|
|
17
|
+
".codex-plugin/",
|
|
18
|
+
".app.json",
|
|
19
|
+
"assets/",
|
|
20
|
+
"hooks/",
|
|
21
|
+
"hooks.json",
|
|
22
|
+
"skills/",
|
|
19
23
|
"bin/",
|
|
20
24
|
"scripts/",
|
|
21
25
|
"babysitter.lock.json"
|
|
@@ -39,6 +43,6 @@
|
|
|
39
43
|
},
|
|
40
44
|
"homepage": "https://github.com/a5c-ai/babysitter/tree/main/plugins/babysitter-codex#readme",
|
|
41
45
|
"dependencies": {
|
|
42
|
-
"@a5c-ai/babysitter-sdk": "0.0.183
|
|
46
|
+
"@a5c-ai/babysitter-sdk": "0.0.183"
|
|
43
47
|
}
|
|
44
48
|
}
|
package/scripts/team-install.js
CHANGED
|
@@ -2,56 +2,16 @@
|
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
4
|
const fs = require('fs');
|
|
5
|
-
const os = require('os');
|
|
6
5
|
const path = require('path');
|
|
7
|
-
const {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
'issue',
|
|
17
|
-
'model',
|
|
18
|
-
'observe',
|
|
19
|
-
'plan',
|
|
20
|
-
'project-install',
|
|
21
|
-
'resume',
|
|
22
|
-
'retrospect',
|
|
23
|
-
'team-install',
|
|
24
|
-
'user-install',
|
|
25
|
-
'yolo',
|
|
26
|
-
];
|
|
27
|
-
const DEFAULT_PROCESS_LIBRARY_REPO = 'https://github.com/a5c-ai/babysitter.git';
|
|
28
|
-
const DEFAULT_PROCESS_LIBRARY_SUBPATH = 'library';
|
|
29
|
-
const DEFAULT_PROCESS_LIBRARY_REFERENCE_SUBPATH = 'library/reference';
|
|
30
|
-
const WORKSPACE_SKILL_ENTRIES = [
|
|
31
|
-
{ source: 'SKILL.md', target: 'SKILL.md' },
|
|
32
|
-
{ source: 'scripts', target: 'scripts' },
|
|
33
|
-
{ source: 'babysitter.lock.json', target: 'babysitter.lock.json' },
|
|
34
|
-
];
|
|
35
|
-
|
|
36
|
-
function listModeSkillEntries(packageRoot) {
|
|
37
|
-
const skillsDir = path.join(packageRoot, '.codex', 'skills');
|
|
38
|
-
return fs
|
|
39
|
-
.readdirSync(skillsDir, { withFileTypes: true })
|
|
40
|
-
.filter((entry) => entry.isDirectory() && entry.name !== SKILL_NAME)
|
|
41
|
-
.sort((a, b) => a.name.localeCompare(b.name))
|
|
42
|
-
.map((entry) => {
|
|
43
|
-
const skillName = entry.name;
|
|
44
|
-
const skillFile = path.join(skillsDir, skillName, 'SKILL.md');
|
|
45
|
-
if (!fs.existsSync(skillFile)) {
|
|
46
|
-
throw new Error(`missing mode skill template: ${skillFile}`);
|
|
47
|
-
}
|
|
48
|
-
return skillName;
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function readJson(filePath) {
|
|
53
|
-
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
54
|
-
}
|
|
6
|
+
const {
|
|
7
|
+
copyPluginBundle,
|
|
8
|
+
ensureGlobalProcessLibrary,
|
|
9
|
+
ensureMarketplaceEntry,
|
|
10
|
+
installCodexSurface,
|
|
11
|
+
mergeCodexConfigFile,
|
|
12
|
+
warnWindowsHooks,
|
|
13
|
+
writeJson,
|
|
14
|
+
} = require('../bin/install-shared');
|
|
55
15
|
|
|
56
16
|
function parseArgs(argv) {
|
|
57
17
|
const args = {
|
|
@@ -68,366 +28,21 @@ function parseArgs(argv) {
|
|
|
68
28
|
return args;
|
|
69
29
|
}
|
|
70
30
|
|
|
71
|
-
function getGlobalStateDir() {
|
|
72
|
-
if (process.env.BABYSITTER_GLOBAL_STATE_DIR) {
|
|
73
|
-
return path.resolve(process.env.BABYSITTER_GLOBAL_STATE_DIR);
|
|
74
|
-
}
|
|
75
|
-
return path.join(os.homedir(), '.a5c');
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
function splitProcessLibrarySubpath(value) {
|
|
79
|
-
return String(value)
|
|
80
|
-
.split(/[\\/]+/)
|
|
81
|
-
.map((part) => part.trim())
|
|
82
|
-
.filter(Boolean);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
function renderWorkspaceConfigToml() {
|
|
86
|
-
return [
|
|
87
|
-
'approval_policy = "on-request"',
|
|
88
|
-
'sandbox_mode = "workspace-write"',
|
|
89
|
-
'project_doc_max_bytes = 65536',
|
|
90
|
-
'',
|
|
91
|
-
'[sandbox_workspace_write]',
|
|
92
|
-
'writable_roots = [".a5c", ".codex"]',
|
|
93
|
-
'',
|
|
94
|
-
'[features]',
|
|
95
|
-
'codex_hooks = true',
|
|
96
|
-
'multi_agent = true',
|
|
97
|
-
'',
|
|
98
|
-
'[agents]',
|
|
99
|
-
'max_depth = 3',
|
|
100
|
-
'max_threads = 4',
|
|
101
|
-
'',
|
|
102
|
-
].join('\n');
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
function writeFileIfChanged(filePath, contents) {
|
|
106
|
-
if (fs.existsSync(filePath)) {
|
|
107
|
-
const current = fs.readFileSync(filePath, 'utf8');
|
|
108
|
-
if (current === contents) {
|
|
109
|
-
return false;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
113
|
-
fs.writeFileSync(filePath, contents, 'utf8');
|
|
114
|
-
return true;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
function copyRecursive(src, dest) {
|
|
118
|
-
const stat = fs.statSync(src);
|
|
119
|
-
if (stat.isDirectory()) {
|
|
120
|
-
fs.mkdirSync(dest, { recursive: true });
|
|
121
|
-
for (const entry of fs.readdirSync(src)) {
|
|
122
|
-
if (['node_modules', '.a5c', '.git', 'test', '.gitignore'].includes(entry)) continue;
|
|
123
|
-
copyRecursive(path.join(src, entry), path.join(dest, entry));
|
|
124
|
-
}
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
if (path.basename(src) === 'SKILL.md') {
|
|
129
|
-
const file = fs.readFileSync(src);
|
|
130
|
-
const hasBom = file.length >= 3 && file[0] === 0xef && file[1] === 0xbb && file[2] === 0xbf;
|
|
131
|
-
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
132
|
-
fs.writeFileSync(dest, hasBom ? file.subarray(3) : file);
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
137
|
-
fs.copyFileSync(src, dest);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
function installWorkspaceSkill(packageRoot, workspaceRoot, dryRun) {
|
|
141
|
-
const workspaceSkillsRoot = path.join(workspaceRoot, '.codex', 'skills');
|
|
142
|
-
const workspaceSkillRoot = path.join(workspaceRoot, '.codex', 'skills', SKILL_NAME);
|
|
143
|
-
const workspaceHookScriptsRoot = path.join(workspaceRoot, '.codex', 'hooks');
|
|
144
|
-
const modeSkillNames = listModeSkillEntries(packageRoot);
|
|
145
|
-
|
|
146
|
-
if (dryRun) {
|
|
147
|
-
return {
|
|
148
|
-
workspaceSkillsRoot,
|
|
149
|
-
workspaceSkillRoot,
|
|
150
|
-
workspaceHookScriptsRoot,
|
|
151
|
-
};
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
fs.rmSync(workspaceSkillRoot, { recursive: true, force: true });
|
|
155
|
-
fs.mkdirSync(workspaceSkillsRoot, { recursive: true });
|
|
156
|
-
fs.mkdirSync(workspaceSkillRoot, { recursive: true });
|
|
157
|
-
|
|
158
|
-
for (const entry of WORKSPACE_SKILL_ENTRIES) {
|
|
159
|
-
copyRecursive(
|
|
160
|
-
path.join(packageRoot, entry.source),
|
|
161
|
-
path.join(workspaceSkillRoot, entry.target),
|
|
162
|
-
);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
fs.mkdirSync(workspaceHookScriptsRoot, { recursive: true });
|
|
166
|
-
copyRecursive(path.join(packageRoot, '.codex', 'hooks'), workspaceHookScriptsRoot);
|
|
167
|
-
|
|
168
|
-
for (const skillName of modeSkillNames) {
|
|
169
|
-
copyRecursive(
|
|
170
|
-
path.join(packageRoot, '.codex', 'skills', skillName),
|
|
171
|
-
path.join(workspaceSkillsRoot, skillName),
|
|
172
|
-
);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
return {
|
|
176
|
-
workspaceSkillsRoot,
|
|
177
|
-
workspaceSkillRoot,
|
|
178
|
-
workspaceHookScriptsRoot,
|
|
179
|
-
};
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
function insertRootKey(content, key, line) {
|
|
183
|
-
const keyPattern = new RegExp(`^\\s*${key}\\s*=`, 'm');
|
|
184
|
-
if (keyPattern.test(content)) {
|
|
185
|
-
return content;
|
|
186
|
-
}
|
|
187
|
-
const sectionMatch = content.match(/^\[[^\]]+\]\s*$/m);
|
|
188
|
-
if (!sectionMatch || sectionMatch.index === undefined) {
|
|
189
|
-
return content.trim()
|
|
190
|
-
? `${content.trimEnd()}\n${line}\n`
|
|
191
|
-
: `${line}\n`;
|
|
192
|
-
}
|
|
193
|
-
const before = content.slice(0, sectionMatch.index).trimEnd();
|
|
194
|
-
const after = content.slice(sectionMatch.index);
|
|
195
|
-
return before
|
|
196
|
-
? `${before}\n${line}\n\n${after}`
|
|
197
|
-
: `${line}\n\n${after}`;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
function ensureSectionLine(content, sectionName, lineKey, line) {
|
|
201
|
-
const keyPattern = new RegExp(`^\\s*${lineKey}\\s*=`, 'm');
|
|
202
|
-
if (keyPattern.test(content)) {
|
|
203
|
-
return content;
|
|
204
|
-
}
|
|
205
|
-
const sectionHeader = `[${sectionName}]`;
|
|
206
|
-
const sectionPattern = new RegExp(`^\\[${sectionName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\]\\s*$`, 'm');
|
|
207
|
-
if (sectionPattern.test(content)) {
|
|
208
|
-
return content.replace(sectionPattern, `${sectionHeader}\n${line}`);
|
|
209
|
-
}
|
|
210
|
-
return content.trim()
|
|
211
|
-
? `${content.trimEnd()}\n\n${sectionHeader}\n${line}\n`
|
|
212
|
-
: `${sectionHeader}\n${line}\n`;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
function ensureWritableRoots(content) {
|
|
216
|
-
const sectionPattern = /^\[sandbox_workspace_write\]\s*$/m;
|
|
217
|
-
const rootsPattern = /^writable_roots\s*=\s*\[(.*?)\]\s*$/m;
|
|
218
|
-
const requiredRoots = ['.a5c', '.codex'];
|
|
219
|
-
|
|
220
|
-
if (!sectionPattern.test(content)) {
|
|
221
|
-
return content.trim()
|
|
222
|
-
? `${content.trimEnd()}\n\n[sandbox_workspace_write]\nwritable_roots = [".a5c", ".codex"]\n`
|
|
223
|
-
: '[sandbox_workspace_write]\nwritable_roots = [".a5c", ".codex"]\n';
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
if (!rootsPattern.test(content)) {
|
|
227
|
-
return content.replace(sectionPattern, '[sandbox_workspace_write]\nwritable_roots = [".a5c", ".codex"]');
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
return content.replace(rootsPattern, (_match, inner) => {
|
|
231
|
-
const values = inner
|
|
232
|
-
.split(',')
|
|
233
|
-
.map((part) => part.trim())
|
|
234
|
-
.filter(Boolean)
|
|
235
|
-
.map((part) => part.replace(/^"(.*)"$/, '$1'));
|
|
236
|
-
const merged = [...new Set([...values, ...requiredRoots])];
|
|
237
|
-
const rendered = merged.map((value) => `"${value}"`).join(', ');
|
|
238
|
-
return `writable_roots = [${rendered}]`;
|
|
239
|
-
});
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
function mergeWorkspaceConfig(existing) {
|
|
243
|
-
let content = existing.trim() ? existing : '';
|
|
244
|
-
content = insertRootKey(content, 'approval_policy', 'approval_policy = "on-request"');
|
|
245
|
-
content = insertRootKey(content, 'sandbox_mode', 'sandbox_mode = "workspace-write"');
|
|
246
|
-
content = insertRootKey(content, 'project_doc_max_bytes', 'project_doc_max_bytes = 65536');
|
|
247
|
-
content = ensureWritableRoots(content);
|
|
248
|
-
content = ensureSectionLine(content, 'features', 'codex_hooks', 'codex_hooks = true');
|
|
249
|
-
content = ensureSectionLine(content, 'features', 'multi_agent', 'multi_agent = true');
|
|
250
|
-
content = ensureSectionLine(content, 'agents', 'max_depth', 'max_depth = 3');
|
|
251
|
-
content = ensureSectionLine(content, 'agents', 'max_threads', 'max_threads = 4');
|
|
252
|
-
return `${content.trimEnd()}\n`;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
function resolveBabysitterCommand(packageRoot) {
|
|
256
|
-
if (process.env.BABYSITTER_SDK_CLI) {
|
|
257
|
-
return {
|
|
258
|
-
command: process.execPath,
|
|
259
|
-
argsPrefix: [path.resolve(process.env.BABYSITTER_SDK_CLI)],
|
|
260
|
-
};
|
|
261
|
-
}
|
|
262
|
-
try {
|
|
263
|
-
return {
|
|
264
|
-
command: process.execPath,
|
|
265
|
-
argsPrefix: [
|
|
266
|
-
require.resolve('@a5c-ai/babysitter-sdk/dist/cli/main.js', {
|
|
267
|
-
paths: [packageRoot],
|
|
268
|
-
}),
|
|
269
|
-
],
|
|
270
|
-
};
|
|
271
|
-
} catch {
|
|
272
|
-
return {
|
|
273
|
-
command: 'babysitter',
|
|
274
|
-
argsPrefix: [],
|
|
275
|
-
};
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
function runBabysitterCli(packageRoot, cliArgs, options = {}) {
|
|
280
|
-
const resolved = resolveBabysitterCommand(packageRoot);
|
|
281
|
-
const result = spawnSync(resolved.command, [...resolved.argsPrefix, ...cliArgs], {
|
|
282
|
-
cwd: options.cwd || process.cwd(),
|
|
283
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
284
|
-
encoding: 'utf8',
|
|
285
|
-
env: {
|
|
286
|
-
...process.env,
|
|
287
|
-
...(options.env || {}),
|
|
288
|
-
},
|
|
289
|
-
});
|
|
290
|
-
if (result.status !== 0) {
|
|
291
|
-
const stderr = (result.stderr || '').trim();
|
|
292
|
-
const stdout = (result.stdout || '').trim();
|
|
293
|
-
throw new Error(
|
|
294
|
-
`babysitter ${cliArgs.join(' ')} failed` +
|
|
295
|
-
(stderr ? `: ${stderr}` : stdout ? `: ${stdout}` : ''),
|
|
296
|
-
);
|
|
297
|
-
}
|
|
298
|
-
return result.stdout;
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
function resolveProcessLibrarySpec() {
|
|
302
|
-
const stateDir = getGlobalStateDir();
|
|
303
|
-
const repo = process.env.BABYSITTER_PROCESS_LIBRARY_REPO || DEFAULT_PROCESS_LIBRARY_REPO;
|
|
304
|
-
const ref = process.env.BABYSITTER_PROCESS_LIBRARY_REF || '';
|
|
305
|
-
const cloneDir = path.join(stateDir, 'process-library', 'babysitter-repo');
|
|
306
|
-
const processSubpath = process.env.BABYSITTER_PROCESS_LIBRARY_SUBPATH || DEFAULT_PROCESS_LIBRARY_SUBPATH;
|
|
307
|
-
const referenceSubpath = process.env.BABYSITTER_PROCESS_LIBRARY_REFERENCE_SUBPATH || DEFAULT_PROCESS_LIBRARY_REFERENCE_SUBPATH;
|
|
308
|
-
return {
|
|
309
|
-
repo,
|
|
310
|
-
ref: ref || undefined,
|
|
311
|
-
cloneDir,
|
|
312
|
-
processRoot: path.join(cloneDir, ...splitProcessLibrarySubpath(processSubpath)),
|
|
313
|
-
referenceRoot: path.join(cloneDir, ...splitProcessLibrarySubpath(referenceSubpath)),
|
|
314
|
-
stateDir,
|
|
315
|
-
};
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
function removeLegacyWorkspacePrompts(workspaceRoot) {
|
|
319
|
-
const promptsRoot = path.join(workspaceRoot, '.codex', 'prompts');
|
|
320
|
-
for (const promptFile of MODE_SKILL_NAMES.map((name) => `${name}.md`).concat('babysit.md')) {
|
|
321
|
-
const promptPath = path.join(promptsRoot, promptFile);
|
|
322
|
-
if (fs.existsSync(promptPath)) {
|
|
323
|
-
fs.rmSync(promptPath, { force: true });
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
if (fs.existsSync(promptsRoot)) {
|
|
327
|
-
try {
|
|
328
|
-
if (fs.readdirSync(promptsRoot).length === 0) {
|
|
329
|
-
fs.rmSync(promptsRoot, { recursive: true, force: true });
|
|
330
|
-
}
|
|
331
|
-
} catch {
|
|
332
|
-
// Best effort cleanup only.
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
function ensureActiveProcessLibrary(packageRoot, dryRun) {
|
|
338
|
-
const spec = resolveProcessLibrarySpec();
|
|
339
|
-
const activeArgs = ['process-library:active', '--state-dir', spec.stateDir, '--json'];
|
|
340
|
-
if (dryRun) {
|
|
341
|
-
return {
|
|
342
|
-
...spec,
|
|
343
|
-
plannedCommands: [
|
|
344
|
-
`babysitter ${activeArgs.join(' ')}`,
|
|
345
|
-
],
|
|
346
|
-
activeStateFile: path.join(spec.stateDir, 'active', 'process-library.json'),
|
|
347
|
-
binding: null,
|
|
348
|
-
};
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
const active = JSON.parse(runBabysitterCli(packageRoot, activeArgs, { cwd: packageRoot }));
|
|
352
|
-
return {
|
|
353
|
-
...spec,
|
|
354
|
-
plannedCommands: [],
|
|
355
|
-
activeStateFile: active.stateFile,
|
|
356
|
-
binding: active.binding || null,
|
|
357
|
-
};
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
function buildHooksConfig() {
|
|
361
|
-
return {
|
|
362
|
-
hooks: {
|
|
363
|
-
SessionStart: [
|
|
364
|
-
{
|
|
365
|
-
matcher: '*',
|
|
366
|
-
hooks: [
|
|
367
|
-
{
|
|
368
|
-
type: 'command',
|
|
369
|
-
command: '.codex/hooks/babysitter-session-start.sh',
|
|
370
|
-
},
|
|
371
|
-
],
|
|
372
|
-
},
|
|
373
|
-
],
|
|
374
|
-
UserPromptSubmit: [
|
|
375
|
-
{
|
|
376
|
-
matcher: '*',
|
|
377
|
-
hooks: [
|
|
378
|
-
{
|
|
379
|
-
type: 'command',
|
|
380
|
-
command: '.codex/hooks/user-prompt-submit.sh',
|
|
381
|
-
},
|
|
382
|
-
],
|
|
383
|
-
},
|
|
384
|
-
],
|
|
385
|
-
Stop: [
|
|
386
|
-
{
|
|
387
|
-
matcher: '*',
|
|
388
|
-
hooks: [
|
|
389
|
-
{
|
|
390
|
-
type: 'command',
|
|
391
|
-
command: '.codex/hooks/babysitter-stop-hook.sh',
|
|
392
|
-
},
|
|
393
|
-
],
|
|
394
|
-
},
|
|
395
|
-
],
|
|
396
|
-
},
|
|
397
|
-
};
|
|
398
|
-
}
|
|
399
|
-
|
|
400
31
|
function main() {
|
|
401
32
|
const args = parseArgs(process.argv);
|
|
402
33
|
const packageRoot = path.resolve(process.env.BABYSITTER_PACKAGE_ROOT || path.join(__dirname, '..'));
|
|
403
34
|
const workspaceRoot = args.workspace;
|
|
404
|
-
const
|
|
405
|
-
|
|
406
|
-
throw new Error(`missing lock file: ${lockPath}`);
|
|
407
|
-
}
|
|
408
|
-
const lock = readJson(lockPath);
|
|
409
|
-
const workspaceHooksConfigPath = path.join(workspaceRoot, '.codex', 'hooks.json');
|
|
35
|
+
const workspacePluginRoot = path.join(workspaceRoot, 'plugins', 'babysitter-codex');
|
|
36
|
+
const workspaceMarketplacePath = path.join(workspaceRoot, '.agents', 'plugins', 'marketplace.json');
|
|
410
37
|
const workspaceConfigPath = path.join(workspaceRoot, '.codex', 'config.toml');
|
|
411
|
-
|
|
412
|
-
const processLibrary = ensureActiveProcessLibrary(packageRoot, args.dryRun);
|
|
38
|
+
|
|
413
39
|
const installInfo = {
|
|
414
40
|
installedAt: new Date().toISOString(),
|
|
415
|
-
runtime: lock.runtime,
|
|
416
|
-
content: lock.content,
|
|
417
|
-
lockVersion: lock.version,
|
|
418
41
|
packageRoot,
|
|
419
42
|
workspaceRoot,
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
workspaceConfigPath,
|
|
423
|
-
workspaceHooksConfigPath,
|
|
424
|
-
hookScriptsRoot: workspaceHookScriptsRoot,
|
|
425
|
-
processLibraryRepo: processLibrary.repo,
|
|
426
|
-
...(processLibrary.ref ? { processLibraryRef: processLibrary.ref } : {}),
|
|
427
|
-
processLibraryCloneDir: processLibrary.cloneDir,
|
|
428
|
-
processLibraryRoot: processLibrary.processRoot,
|
|
429
|
-
processLibraryReferenceRoot: processLibrary.referenceRoot,
|
|
430
|
-
processLibraryStateFile: processLibrary.activeStateFile,
|
|
43
|
+
pluginRoot: workspacePluginRoot,
|
|
44
|
+
marketplacePath: workspaceMarketplacePath,
|
|
45
|
+
codexConfigPath: workspaceConfigPath,
|
|
431
46
|
};
|
|
432
47
|
|
|
433
48
|
if (args.dryRun) {
|
|
@@ -435,43 +50,36 @@ function main() {
|
|
|
435
50
|
ok: true,
|
|
436
51
|
dryRun: true,
|
|
437
52
|
installInfo,
|
|
438
|
-
processLibrary: {
|
|
439
|
-
repo: processLibrary.repo,
|
|
440
|
-
...(processLibrary.ref ? { ref: processLibrary.ref } : {}),
|
|
441
|
-
cloneDir: processLibrary.cloneDir,
|
|
442
|
-
processRoot: processLibrary.processRoot,
|
|
443
|
-
referenceRoot: processLibrary.referenceRoot,
|
|
444
|
-
stateFile: processLibrary.activeStateFile,
|
|
445
|
-
plannedCommands: processLibrary.plannedCommands,
|
|
446
|
-
},
|
|
447
53
|
}, null, 2));
|
|
448
54
|
return;
|
|
449
55
|
}
|
|
450
56
|
|
|
57
|
+
copyPluginBundle(packageRoot, workspacePluginRoot);
|
|
58
|
+
ensureMarketplaceEntry(workspaceMarketplacePath, workspacePluginRoot);
|
|
59
|
+
mergeCodexConfigFile(workspaceConfigPath);
|
|
60
|
+
installCodexSurface(packageRoot, path.join(workspaceRoot, '.codex'));
|
|
61
|
+
|
|
62
|
+
const active = ensureGlobalProcessLibrary(packageRoot);
|
|
63
|
+
installInfo.processLibraryStateFile = active.stateFile;
|
|
64
|
+
installInfo.processLibraryRoot = active.binding?.dir || '';
|
|
65
|
+
installInfo.processLibraryCloneDir = active.defaultSpec?.cloneDir || '';
|
|
66
|
+
|
|
451
67
|
const outDir = path.join(workspaceRoot, '.a5c', 'team');
|
|
452
68
|
fs.mkdirSync(outDir, { recursive: true });
|
|
453
|
-
|
|
454
|
-
fs.mkdirSync(path.dirname(workspaceHooksConfigPath), { recursive: true });
|
|
455
|
-
writeFileIfChanged(workspaceHooksConfigPath, `${JSON.stringify(buildHooksConfig(), null, 2)}\n`);
|
|
456
|
-
const existingWorkspaceConfig = fs.existsSync(workspaceConfigPath)
|
|
457
|
-
? fs.readFileSync(workspaceConfigPath, 'utf8')
|
|
458
|
-
: renderWorkspaceConfigToml();
|
|
459
|
-
writeFileIfChanged(workspaceConfigPath, mergeWorkspaceConfig(existingWorkspaceConfig));
|
|
460
|
-
fs.writeFileSync(path.join(outDir, 'install.json'), JSON.stringify(installInfo, null, 2), 'utf8');
|
|
69
|
+
writeJson(path.join(outDir, 'install.json'), installInfo);
|
|
461
70
|
|
|
462
71
|
const profilePath = path.join(outDir, 'profile.json');
|
|
463
72
|
if (!fs.existsSync(profilePath)) {
|
|
464
|
-
|
|
73
|
+
writeJson(profilePath, {
|
|
465
74
|
teamName: 'default',
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
workspaceConfigPath,
|
|
469
|
-
workspaceHooksConfigPath,
|
|
470
|
-
hookScriptsRoot: workspaceHookScriptsRoot,
|
|
75
|
+
pluginRoot: workspacePluginRoot,
|
|
76
|
+
marketplacePath: workspaceMarketplacePath,
|
|
77
|
+
codexConfigPath: workspaceConfigPath,
|
|
471
78
|
processLibraryLookupCommand: 'babysitter process-library:active --json',
|
|
472
|
-
}
|
|
79
|
+
});
|
|
473
80
|
}
|
|
474
81
|
|
|
82
|
+
warnWindowsHooks();
|
|
475
83
|
console.log('[team-install] complete');
|
|
476
84
|
}
|
|
477
85
|
|