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