@a5c-ai/babysitter-openclaw 5.0.1-staging.f6432257 → 5.0.1-staging.ff2c19f9
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/bin/cli.cjs +41 -25
- package/bin/install-shared.cjs +219 -0
- package/bin/install.cjs +13 -353
- package/bin/uninstall.cjs +10 -157
- package/commands/doctor.md +5 -5
- package/commands/help.md +245 -244
- package/commands/observe.md +12 -12
- package/extensions/hooks/agent-end.ts +8 -117
- package/extensions/hooks/before-prompt-build.ts +9 -89
- package/extensions/hooks/session-end.ts +8 -70
- package/extensions/hooks/session-start.ts +8 -71
- package/hooks/babysitter-proxied-agent-end.js +24 -0
- package/hooks/babysitter-proxied-agent-end.sh +3 -0
- package/hooks/babysitter-proxied-before-prompt-build.js +24 -0
- package/hooks/babysitter-proxied-before-prompt-build.sh +3 -0
- package/hooks/babysitter-proxied-session-end.js +24 -0
- package/hooks/babysitter-proxied-session-end.sh +3 -0
- package/hooks/babysitter-proxied-session-start.js +24 -0
- package/hooks/babysitter-proxied-session-start.sh +7 -162
- package/hooks/babysitter-proxied-stop-hook.sh +2 -102
- package/hooks.json +1 -0
- package/openclaw.plugin.json +4 -4
- package/package.json +5 -4
- package/plugin.json +3 -2
- package/scripts/team-install.cjs +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 +1 -1
- package/hooks/babysitter-session-start.sh +0 -62
- package/hooks/babysitter-stop-hook.sh +0 -45
- package/hooks/proxied-hooks.json +0 -27
- package/scripts/setup.sh +0 -100
package/bin/cli.cjs
CHANGED
|
@@ -5,47 +5,51 @@ const path = require('path');
|
|
|
5
5
|
const { spawnSync } = require('child_process');
|
|
6
6
|
|
|
7
7
|
const PACKAGE_ROOT = path.resolve(__dirname, '..');
|
|
8
|
+
let shared;
|
|
9
|
+
try { shared = require('./install-shared'); } catch {}
|
|
8
10
|
|
|
9
11
|
function printUsage() {
|
|
10
12
|
console.error([
|
|
11
13
|
'Usage:',
|
|
12
14
|
' babysitter-openclaw install [--global]',
|
|
13
15
|
' babysitter-openclaw install --workspace [path]',
|
|
14
|
-
' babysitter-openclaw uninstall
|
|
15
|
-
' babysitter-openclaw uninstall --workspace [path]',
|
|
16
|
-
' babysitter-openclaw version',
|
|
17
|
-
' babysitter-openclaw help',
|
|
16
|
+
' babysitter-openclaw uninstall',
|
|
18
17
|
].join('\n'));
|
|
19
18
|
}
|
|
20
19
|
|
|
21
|
-
function
|
|
20
|
+
function parseInstallArgs(argv) {
|
|
21
|
+
let scope = 'global';
|
|
22
22
|
let workspace = null;
|
|
23
|
+
const passthrough = [];
|
|
23
24
|
|
|
24
25
|
for (let i = 0; i < argv.length; i += 1) {
|
|
25
26
|
const arg = argv[i];
|
|
27
|
+
if (arg === '--global') {
|
|
28
|
+
scope = 'global';
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
26
31
|
if (arg === '--workspace') {
|
|
32
|
+
scope = 'workspace';
|
|
27
33
|
const next = argv[i + 1];
|
|
28
|
-
workspace = next && !next.startsWith('-') ? path.resolve(next) : process.cwd();
|
|
29
34
|
if (next && !next.startsWith('-')) {
|
|
35
|
+
workspace = path.resolve(next);
|
|
30
36
|
i += 1;
|
|
37
|
+
} else {
|
|
38
|
+
workspace = process.cwd();
|
|
31
39
|
}
|
|
32
40
|
continue;
|
|
33
41
|
}
|
|
34
|
-
|
|
35
|
-
workspace = null;
|
|
36
|
-
continue;
|
|
37
|
-
}
|
|
38
|
-
throw new Error(`unknown argument: ${arg}`);
|
|
42
|
+
passthrough.push(arg);
|
|
39
43
|
}
|
|
40
44
|
|
|
41
|
-
return { workspace };
|
|
45
|
+
return { scope, workspace, passthrough };
|
|
42
46
|
}
|
|
43
47
|
|
|
44
|
-
function runNodeScript(scriptPath, args) {
|
|
48
|
+
function runNodeScript(scriptPath, args, extraEnv = {}) {
|
|
45
49
|
const result = spawnSync(process.execPath, [scriptPath, ...args], {
|
|
46
50
|
cwd: process.cwd(),
|
|
47
51
|
stdio: 'inherit',
|
|
48
|
-
env: process.env,
|
|
52
|
+
env: { ...process.env, ...extraEnv },
|
|
49
53
|
});
|
|
50
54
|
process.exitCode = result.status ?? 1;
|
|
51
55
|
}
|
|
@@ -58,23 +62,35 @@ function main() {
|
|
|
58
62
|
return;
|
|
59
63
|
}
|
|
60
64
|
|
|
61
|
-
if (command === '
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
+
if (command === 'install') {
|
|
66
|
+
if (shared && typeof shared.harnessCliRoute === 'function' && shared.harnessCliRoute(rest, PACKAGE_ROOT, runNodeScript)) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const parsed = parseInstallArgs(rest);
|
|
70
|
+
if (parsed.scope === 'workspace') {
|
|
71
|
+
const args = [];
|
|
72
|
+
if (parsed.workspace) {
|
|
73
|
+
args.push('--workspace', parsed.workspace);
|
|
74
|
+
}
|
|
75
|
+
args.push(...parsed.passthrough);
|
|
76
|
+
runNodeScript(
|
|
77
|
+
path.join(PACKAGE_ROOT, 'scripts', 'team-install.cjs'),
|
|
78
|
+
args,
|
|
79
|
+
{ PLUGIN_PACKAGE_ROOT: PACKAGE_ROOT },
|
|
80
|
+
);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
runNodeScript(path.join(PACKAGE_ROOT, 'bin', 'install.cjs'), parsed.passthrough);
|
|
65
84
|
return;
|
|
66
85
|
}
|
|
67
86
|
|
|
68
|
-
if (command
|
|
69
|
-
|
|
70
|
-
printUsage();
|
|
71
|
-
process.exitCode = 1;
|
|
87
|
+
if (command === 'uninstall') {
|
|
88
|
+
runNodeScript(path.join(PACKAGE_ROOT, 'bin', 'uninstall.cjs'), rest);
|
|
72
89
|
return;
|
|
73
90
|
}
|
|
74
91
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
runNodeScript(path.join(PACKAGE_ROOT, 'bin', `${command}.cjs`), args);
|
|
92
|
+
printUsage();
|
|
93
|
+
process.exitCode = 1;
|
|
78
94
|
}
|
|
79
95
|
|
|
80
96
|
main();
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const os = require('os');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const { spawnSync } = require('child_process');
|
|
7
|
+
|
|
8
|
+
const PLUGIN_NAME = "babysitter";
|
|
9
|
+
const PLUGIN_CATEGORY = 'Coding';
|
|
10
|
+
|
|
11
|
+
function getUserHome() {
|
|
12
|
+
return os.homedir();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function getHarnessHome() {
|
|
16
|
+
return path.join(os.homedir(), '.openclaw');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function getHomePluginRoot(scope) {
|
|
20
|
+
if (scope === 'workspace') return path.join(process.cwd(), '.a5c', 'plugins', PLUGIN_NAME);
|
|
21
|
+
return path.join(path.join(getHarnessHome(), 'plugins'), PLUGIN_NAME);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function getHomeMarketplacePath() {
|
|
25
|
+
return path.join(getHarnessHome(), 'plugins', 'marketplace.json');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function writeFileIfChanged(filePath, contents) {
|
|
29
|
+
try {
|
|
30
|
+
const existing = fs.readFileSync(filePath, 'utf8');
|
|
31
|
+
if (existing === contents) return false;
|
|
32
|
+
} catch {}
|
|
33
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
34
|
+
fs.writeFileSync(filePath, contents);
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function copyRecursive(src, dest) {
|
|
39
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
40
|
+
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
41
|
+
if (entry.name === 'node_modules' || entry.name === '.git') continue;
|
|
42
|
+
const s = path.join(src, entry.name);
|
|
43
|
+
const d = path.join(dest, entry.name);
|
|
44
|
+
if (entry.isDirectory()) {
|
|
45
|
+
copyRecursive(s, d);
|
|
46
|
+
} else {
|
|
47
|
+
fs.copyFileSync(s, d);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function copyPluginBundle(packageRoot, pluginRoot) {
|
|
53
|
+
const bundleEntries = fs.readdirSync(packageRoot).filter(
|
|
54
|
+
e => !['node_modules', '.git', 'test', 'dist'].includes(e)
|
|
55
|
+
);
|
|
56
|
+
fs.mkdirSync(pluginRoot, { recursive: true });
|
|
57
|
+
for (const entry of bundleEntries) {
|
|
58
|
+
const src = path.join(packageRoot, entry);
|
|
59
|
+
const dest = path.join(pluginRoot, entry);
|
|
60
|
+
const stat = fs.statSync(src);
|
|
61
|
+
if (stat.isDirectory()) {
|
|
62
|
+
copyRecursive(src, dest);
|
|
63
|
+
} else {
|
|
64
|
+
fs.copyFileSync(src, dest);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function readJson(filePath) {
|
|
70
|
+
try {
|
|
71
|
+
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
72
|
+
} catch {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function writeJson(filePath, value) {
|
|
78
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
79
|
+
fs.writeFileSync(filePath, JSON.stringify(value, null, 2) + '\n');
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function ensureExecutable(filePath) {
|
|
83
|
+
try {
|
|
84
|
+
fs.chmodSync(filePath, 0o755);
|
|
85
|
+
} catch {}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function normalizeMarketplaceSourcePath(source, marketplacePath) {
|
|
89
|
+
if (typeof source === 'string') {
|
|
90
|
+
return path.relative(path.dirname(marketplacePath), source).replace(/\\/g, '/');
|
|
91
|
+
}
|
|
92
|
+
return source;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function ensureMarketplaceEntry(marketplacePath, pluginRoot) {
|
|
96
|
+
let marketplace = readJson(marketplacePath) || {
|
|
97
|
+
name: "a5c.ai",
|
|
98
|
+
plugins: [],
|
|
99
|
+
};
|
|
100
|
+
if (!Array.isArray(marketplace.plugins)) marketplace.plugins = [];
|
|
101
|
+
const idx = marketplace.plugins.findIndex(p => p.name === PLUGIN_NAME);
|
|
102
|
+
const relSource = './' + normalizeMarketplaceSourcePath(pluginRoot, marketplacePath);
|
|
103
|
+
const entry = {
|
|
104
|
+
name: PLUGIN_NAME,
|
|
105
|
+
source: relSource,
|
|
106
|
+
description: "Orchestrate complex, multi-step workflows with event-sourced state management, hook-based extensibility, and human-in-the-loop approval",
|
|
107
|
+
version: "5.0.0",
|
|
108
|
+
author: { name: "a5c.ai" },
|
|
109
|
+
};
|
|
110
|
+
if (idx >= 0) marketplace.plugins[idx] = entry;
|
|
111
|
+
else marketplace.plugins.push(entry);
|
|
112
|
+
writeJson(marketplacePath, marketplace);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function removeMarketplaceEntry(marketplacePath) {
|
|
116
|
+
const marketplace = readJson(marketplacePath);
|
|
117
|
+
if (!marketplace || !Array.isArray(marketplace.plugins)) return;
|
|
118
|
+
marketplace.plugins = marketplace.plugins.filter(p => p.name !== PLUGIN_NAME);
|
|
119
|
+
writeJson(marketplacePath, marketplace);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function warnWindowsHooks() {
|
|
123
|
+
if (process.platform === 'win32') {
|
|
124
|
+
console.warn('[' + PLUGIN_NAME + '] Windows detected — shell hooks (.sh) require Git Bash or WSL.');
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function runPostInstall(pluginRoot) {
|
|
129
|
+
const postInstall = path.join(pluginRoot, 'scripts', 'post-install.js');
|
|
130
|
+
if (fs.existsSync(postInstall)) {
|
|
131
|
+
spawnSync(process.execPath, [postInstall], {
|
|
132
|
+
cwd: pluginRoot, stdio: 'inherit',
|
|
133
|
+
env: { ...process.env, PLUGIN_ROOT: pluginRoot },
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function getGlobalStateDir() {
|
|
139
|
+
return process.env.BABYSITTER_GLOBAL_STATE_DIR || path.join(getUserHome(), '.a5c');
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function resolveCliCommand(packageRoot) {
|
|
143
|
+
try {
|
|
144
|
+
const result = spawnSync('babysitter', ['--version'], { stdio: 'pipe', timeout: 10000 });
|
|
145
|
+
if (result.status === 0) return 'babysitter';
|
|
146
|
+
} catch {}
|
|
147
|
+
const versionsPath = path.join(packageRoot, 'versions.json');
|
|
148
|
+
const versions = readJson(versionsPath) || {};
|
|
149
|
+
const ver = versions.sdkVersion || 'latest';
|
|
150
|
+
return `npx -y @a5c-ai/babysitter-sdk@${ver}`;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function runCli(packageRoot, cliArgs, options = {}) {
|
|
154
|
+
const cmd = resolveCliCommand(packageRoot);
|
|
155
|
+
const parts = cmd.split(' ');
|
|
156
|
+
const result = spawnSync(parts[0], [...parts.slice(1), ...cliArgs], {
|
|
157
|
+
stdio: options.stdio || 'inherit',
|
|
158
|
+
timeout: options.timeout || 120000,
|
|
159
|
+
cwd: options.cwd || process.cwd(),
|
|
160
|
+
env: { ...process.env, ...options.env },
|
|
161
|
+
});
|
|
162
|
+
return result;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function ensureGlobalProcessLibrary(packageRoot) {
|
|
166
|
+
const stateDir = getGlobalStateDir();
|
|
167
|
+
const activeFile = path.join(stateDir, 'active', 'process-library.json');
|
|
168
|
+
let active = readJson(activeFile);
|
|
169
|
+
if (active && active.binding && active.binding.dir) {
|
|
170
|
+
return active;
|
|
171
|
+
}
|
|
172
|
+
const defaultSpec = readJson(path.join(stateDir, 'process-library-defaults.json'));
|
|
173
|
+
const cloneDir = defaultSpec && defaultSpec.cloneDir
|
|
174
|
+
? defaultSpec.cloneDir
|
|
175
|
+
: path.join(stateDir, 'process-library', PLUGIN_NAME + '-repo');
|
|
176
|
+
runCli(packageRoot, [
|
|
177
|
+
'process-library:clone',
|
|
178
|
+
'--dir', cloneDir,
|
|
179
|
+
'--state-dir', stateDir,
|
|
180
|
+
'--json',
|
|
181
|
+
], { stdio: 'pipe' });
|
|
182
|
+
runCli(packageRoot, [
|
|
183
|
+
'process-library:use',
|
|
184
|
+
'--dir', cloneDir,
|
|
185
|
+
'--state-dir', stateDir,
|
|
186
|
+
'--json',
|
|
187
|
+
], { stdio: 'pipe' });
|
|
188
|
+
active = readJson(activeFile);
|
|
189
|
+
return {
|
|
190
|
+
binding: active && active.binding ? active.binding : { dir: cloneDir },
|
|
191
|
+
defaultSpec: defaultSpec || { cloneDir },
|
|
192
|
+
stateFile: activeFile,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
module.exports = {
|
|
198
|
+
PLUGIN_NAME,
|
|
199
|
+
PLUGIN_CATEGORY,
|
|
200
|
+
getUserHome,
|
|
201
|
+
getHarnessHome,
|
|
202
|
+
getHomePluginRoot,
|
|
203
|
+
getHomeMarketplacePath,
|
|
204
|
+
writeFileIfChanged,
|
|
205
|
+
copyRecursive,
|
|
206
|
+
copyPluginBundle,
|
|
207
|
+
readJson,
|
|
208
|
+
writeJson,
|
|
209
|
+
ensureExecutable,
|
|
210
|
+
normalizeMarketplaceSourcePath,
|
|
211
|
+
ensureMarketplaceEntry,
|
|
212
|
+
removeMarketplaceEntry,
|
|
213
|
+
warnWindowsHooks,
|
|
214
|
+
runPostInstall,
|
|
215
|
+
getGlobalStateDir,
|
|
216
|
+
resolveCliCommand,
|
|
217
|
+
runCli,
|
|
218
|
+
ensureGlobalProcessLibrary,
|
|
219
|
+
};
|