@a5c-ai/babysitter-hermes 5.0.1-staging.5c9708469
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 +46 -0
- package/bin/cli.js +96 -0
- package/bin/install-shared.js +219 -0
- package/bin/install.js +30 -0
- package/bin/uninstall.js +24 -0
- package/hooks/babysitter-proxied-on-event.sh +3 -0
- package/hooks.json +15 -0
- package/package.json +38 -0
- package/scripts/create-release-tag.mjs +18 -0
- package/scripts/publish-from-tag.mjs +41 -0
- package/scripts/team-install.js +23 -0
- package/skills/assimilate/SKILL.md +38 -0
- package/skills/babysit/SKILL.md +45 -0
- package/skills/call/SKILL.md +8 -0
- package/skills/cleanup/SKILL.md +43 -0
- package/skills/contrib/SKILL.md +34 -0
- package/skills/doctor/SKILL.md +512 -0
- package/skills/forever/SKILL.md +8 -0
- package/skills/help/SKILL.md +246 -0
- package/skills/observe/SKILL.md +13 -0
- package/skills/plan/SKILL.md +8 -0
- package/skills/plugins/SKILL.md +257 -0
- package/skills/project-install/SKILL.md +18 -0
- package/skills/resume/SKILL.md +9 -0
- package/skills/retrospect/SKILL.md +56 -0
- package/skills/user-install/SKILL.md +18 -0
- package/skills/yolo/SKILL.md +8 -0
package/README.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# babysitter
|
|
2
|
+
|
|
3
|
+
Orchestrate complex, multi-step workflows with event-sourced state management, hook-based extensibility, and human-in-the-loop approval
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
Install the Babysitter SDK CLI:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install -g @a5c-ai/babysitter-sdk
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Installation — Hermes
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install -g @a5c-ai/babysitter-hermes
|
|
17
|
+
babysitter-hermes install --global
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Restart Hermes to pick up the installed plugin.
|
|
21
|
+
|
|
22
|
+
## What's Included
|
|
23
|
+
|
|
24
|
+
- **Skills**: babysit
|
|
25
|
+
- **Hooks**: PostToolUse
|
|
26
|
+
- **Commands**: (directory)
|
|
27
|
+
|
|
28
|
+
- **CLI**: Install/uninstall scripts for global and workspace setup
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
## Verification
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
babysitter harness:discover --json | grep hermes
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Integration Model
|
|
39
|
+
|
|
40
|
+
The plugin provides:
|
|
41
|
+
|
|
42
|
+
- Core orchestration skill for multi-step workflow management
|
|
43
|
+
- Lifecycle hooks for session state, orchestration loops, and token compression
|
|
44
|
+
- Command wrappers for plan, resume, doctor, and other operations
|
|
45
|
+
|
|
46
|
+
The process library is fetched and bound through the SDK CLI.
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const { spawnSync } = require('child_process');
|
|
6
|
+
|
|
7
|
+
const PACKAGE_ROOT = path.resolve(__dirname, '..');
|
|
8
|
+
let shared;
|
|
9
|
+
try { shared = require('./install-shared'); } catch {}
|
|
10
|
+
|
|
11
|
+
function printUsage() {
|
|
12
|
+
console.error([
|
|
13
|
+
'Usage:',
|
|
14
|
+
' babysitter-hermes install [--global]',
|
|
15
|
+
' babysitter-hermes install --workspace [path]',
|
|
16
|
+
' babysitter-hermes uninstall',
|
|
17
|
+
].join('\n'));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function parseInstallArgs(argv) {
|
|
21
|
+
let scope = 'global';
|
|
22
|
+
let workspace = null;
|
|
23
|
+
const passthrough = [];
|
|
24
|
+
|
|
25
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
26
|
+
const arg = argv[i];
|
|
27
|
+
if (arg === '--global') {
|
|
28
|
+
scope = 'global';
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
if (arg === '--workspace') {
|
|
32
|
+
scope = 'workspace';
|
|
33
|
+
const next = argv[i + 1];
|
|
34
|
+
if (next && !next.startsWith('-')) {
|
|
35
|
+
workspace = path.resolve(next);
|
|
36
|
+
i += 1;
|
|
37
|
+
} else {
|
|
38
|
+
workspace = process.cwd();
|
|
39
|
+
}
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
passthrough.push(arg);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return { scope, workspace, passthrough };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function runNodeScript(scriptPath, args, extraEnv = {}) {
|
|
49
|
+
const result = spawnSync(process.execPath, [scriptPath, ...args], {
|
|
50
|
+
cwd: process.cwd(),
|
|
51
|
+
stdio: 'inherit',
|
|
52
|
+
env: { ...process.env, ...extraEnv },
|
|
53
|
+
});
|
|
54
|
+
process.exitCode = result.status ?? 1;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function main() {
|
|
58
|
+
const [command, ...rest] = process.argv.slice(2);
|
|
59
|
+
if (!command || command === '--help' || command === '-h' || command === 'help') {
|
|
60
|
+
printUsage();
|
|
61
|
+
process.exitCode = command ? 0 : 1;
|
|
62
|
+
return;
|
|
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.js'),
|
|
78
|
+
args,
|
|
79
|
+
{ PLUGIN_PACKAGE_ROOT: PACKAGE_ROOT },
|
|
80
|
+
);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
runNodeScript(path.join(PACKAGE_ROOT, 'bin', 'install.js'), parsed.passthrough);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (command === 'uninstall') {
|
|
88
|
+
runNodeScript(path.join(PACKAGE_ROOT, 'bin', 'uninstall.js'), rest);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
printUsage();
|
|
93
|
+
process.exitCode = 1;
|
|
94
|
+
}
|
|
95
|
+
|
|
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(), ".hermes");
|
|
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(os.homedir(), ".agents/plugins"), PLUGIN_NAME);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function getHomeMarketplacePath() {
|
|
25
|
+
return path.join(os.homedir(), ".agents/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.1-staging.5c9708469",
|
|
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
|
+
};
|
package/bin/install.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const shared = require('./install-shared');
|
|
6
|
+
|
|
7
|
+
const PACKAGE_ROOT = path.resolve(__dirname, '..');
|
|
8
|
+
|
|
9
|
+
function main() {
|
|
10
|
+
const pluginRoot = shared.getHomePluginRoot();
|
|
11
|
+
const marketplacePath = shared.getHomeMarketplacePath();
|
|
12
|
+
|
|
13
|
+
console.log(`[${shared.PLUGIN_NAME}] Installing plugin to ${pluginRoot}`);
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
shared.copyPluginBundle(PACKAGE_ROOT, pluginRoot);
|
|
17
|
+
shared.ensureMarketplaceEntry(marketplacePath, pluginRoot);
|
|
18
|
+
if (typeof shared.harnessInstall === 'function') {
|
|
19
|
+
shared.harnessInstall(PACKAGE_ROOT, pluginRoot);
|
|
20
|
+
}
|
|
21
|
+
shared.runPostInstall && shared.runPostInstall(pluginRoot);
|
|
22
|
+
console.log(`[${shared.PLUGIN_NAME}] Installation complete!`);
|
|
23
|
+
console.log(`[${shared.PLUGIN_NAME}] Restart your IDE/CLI to pick up the plugin.`);
|
|
24
|
+
} catch (err) {
|
|
25
|
+
console.error(`[${shared.PLUGIN_NAME}] Failed to install: ${err.message}`);
|
|
26
|
+
process.exitCode = 1;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
main();
|
package/bin/uninstall.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const shared = require('./install-shared');
|
|
6
|
+
|
|
7
|
+
function main() {
|
|
8
|
+
const pluginRoot = shared.getHomePluginRoot();
|
|
9
|
+
|
|
10
|
+
if (!fs.existsSync(pluginRoot)) {
|
|
11
|
+
console.log(`[${shared.PLUGIN_NAME}] Plugin not installed at ${pluginRoot}`);
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
fs.rmSync(pluginRoot, { recursive: true, force: true });
|
|
17
|
+
console.log(`[${shared.PLUGIN_NAME}] Uninstalled from ${pluginRoot}`);
|
|
18
|
+
} catch (err) {
|
|
19
|
+
console.error(`[${shared.PLUGIN_NAME}] Failed to uninstall: ${err.message}`);
|
|
20
|
+
process.exitCode = 1;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
main();
|
package/hooks.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"hooks": {
|
|
3
|
+
"onEvent": [
|
|
4
|
+
{
|
|
5
|
+
"matcher": ".*",
|
|
6
|
+
"hooks": [
|
|
7
|
+
{
|
|
8
|
+
"type": "command",
|
|
9
|
+
"command": "npx -y -p @a5c-ai/hooks-mux-cli -c \"a5c-hooks-mux invoke --adapter hermes --handler 'bash ./hooks/babysitter-proxied-on-event.sh' --json\""
|
|
10
|
+
}
|
|
11
|
+
]
|
|
12
|
+
}
|
|
13
|
+
]
|
|
14
|
+
}
|
|
15
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@a5c-ai/babysitter-hermes",
|
|
3
|
+
"version": "5.0.1-staging.5c9708469",
|
|
4
|
+
"description": "Orchestrate complex, multi-step workflows with event-sourced state management, hook-based extensibility, and human-in-the-loop approval",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"test": "npm run validate:ci",
|
|
7
|
+
"test:integration": "node test/integration.test.js",
|
|
8
|
+
"test:packaged-install": "node test/packaged-install.test.js",
|
|
9
|
+
"validate:ci": "npm run test:integration && npm run test:packaged-install",
|
|
10
|
+
"team:install": "node scripts/team-install.js"
|
|
11
|
+
},
|
|
12
|
+
"bin": {
|
|
13
|
+
"babysitter-hermes": "bin/cli.js"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"hooks/",
|
|
17
|
+
"hooks.json",
|
|
18
|
+
"skills/",
|
|
19
|
+
"bin/",
|
|
20
|
+
"scripts/",
|
|
21
|
+
"README.md"
|
|
22
|
+
],
|
|
23
|
+
"keywords": [
|
|
24
|
+
"babysitter",
|
|
25
|
+
"hermes",
|
|
26
|
+
"orchestration"
|
|
27
|
+
],
|
|
28
|
+
"author": "a5c.ai",
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "git+https://github.com/a5c-ai/babysitter-hermes.git"
|
|
33
|
+
},
|
|
34
|
+
"homepage": "https://github.com/a5c-ai/babysitter-hermes#readme",
|
|
35
|
+
"bugs": {
|
|
36
|
+
"url": "https://github.com/a5c-ai/babysitter-hermes/issues"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawnSync } from 'node:child_process';
|
|
3
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
4
|
+
|
|
5
|
+
function run(command, args) {
|
|
6
|
+
const result = spawnSync(command, args, { encoding: 'utf8', stdio: 'inherit' });
|
|
7
|
+
if (result.status !== 0) process.exit(result.status || 1);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const branch = process.env.GITHUB_REF_NAME || 'develop';
|
|
11
|
+
const sha = (process.env.GITHUB_SHA || '').slice(0, 12);
|
|
12
|
+
const version = existsSync('package.json') ? JSON.parse(readFileSync('package.json', 'utf8')).version : JSON.parse(readFileSync('versions.json', 'utf8')).sdkVersion;
|
|
13
|
+
const normalized = String(version).replace(/[^0-9A-Za-z._-]/g, '-');
|
|
14
|
+
const tag = 'release/' + branch + '/v' + normalized + '-' + sha;
|
|
15
|
+
run('git', ['config', 'user.name', 'github-actions[bot]']);
|
|
16
|
+
run('git', ['config', 'user.email', 'github-actions[bot]@users.noreply.github.com']);
|
|
17
|
+
run('git', ['tag', tag]);
|
|
18
|
+
run('git', ['push', 'origin', tag]);
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawnSync } from 'node:child_process';
|
|
3
|
+
import { readFileSync } from 'node:fs';
|
|
4
|
+
|
|
5
|
+
function run(command, args, options = {}) {
|
|
6
|
+
const result = spawnSync(command, args, { stdio: options.stdio || 'inherit', encoding: options.encoding });
|
|
7
|
+
if (result.status !== 0 && !options.allowFailure) process.exit(result.status || 1);
|
|
8
|
+
return result;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function npmView(packageSpec) {
|
|
12
|
+
return run('npm', ['view', packageSpec, 'version'], { allowFailure: true, stdio: 'pipe', encoding: 'utf8' }).status === 0;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const pkg = JSON.parse(readFileSync('package.json', 'utf8'));
|
|
16
|
+
const ref = process.env.GITHUB_REF_NAME || '';
|
|
17
|
+
const branch = ref.split('/')[1] || 'develop';
|
|
18
|
+
const tag = branch === 'main' ? 'latest' : branch;
|
|
19
|
+
|
|
20
|
+
if (!process.env.NODE_AUTH_TOKEN) {
|
|
21
|
+
console.log('NODE_AUTH_TOKEN is not configured; skipping npm publish.');
|
|
22
|
+
process.exit(0);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (npmView(pkg.name + '@' + pkg.version)) {
|
|
26
|
+
console.log(pkg.name + '@' + pkg.version + ' already exists; ensuring dist-tag ' + tag + '.');
|
|
27
|
+
run('npm', ['dist-tag', 'add', pkg.name + '@' + pkg.version, tag], { allowFailure: true });
|
|
28
|
+
process.exit(0);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
for (const field of ['dependencies', 'peerDependencies', 'optionalDependencies']) {
|
|
32
|
+
for (const [name, version] of Object.entries(pkg[field] || {})) {
|
|
33
|
+
if (!name.startsWith('@a5c-ai/') || version.startsWith('^') || version.startsWith('~') || version === '*' || version.startsWith('workspace:')) continue;
|
|
34
|
+
if (!npmView(name + '@' + version)) {
|
|
35
|
+
console.log('Required internal dependency ' + name + '@' + version + ' is not published yet; skipping npm publish.');
|
|
36
|
+
process.exit(0);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
run('npm', ['publish', '--access', 'public', '--tag', tag]);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
var path = require('path');
|
|
5
|
+
var shared = require('../bin/install-shared');
|
|
6
|
+
|
|
7
|
+
var workspace = process.cwd();
|
|
8
|
+
for (var i = 0; i < process.argv.length; i++) {
|
|
9
|
+
if (process.argv[i] === '--workspace' && process.argv[i + 1]) {
|
|
10
|
+
workspace = path.resolve(process.argv[i + 1]);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
var src = process.env.PLUGIN_PACKAGE_ROOT || path.resolve(__dirname, '..');
|
|
15
|
+
var dest = shared.getHomePluginRoot('workspace');
|
|
16
|
+
console.log('[babysitter] Team install to ' + dest);
|
|
17
|
+
|
|
18
|
+
shared.copyPluginBundle(src, dest);
|
|
19
|
+
if (typeof shared.harnessTeamInstall === 'function') {
|
|
20
|
+
shared.harnessTeamInstall(src, dest, workspace);
|
|
21
|
+
}
|
|
22
|
+
shared.runPostInstall(dest);
|
|
23
|
+
console.log('[babysitter] Team install complete.');
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: assimilate
|
|
3
|
+
description: Assimilate an external methodology, harness, or specification into babysitter process definitions with skills and agents.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# assimilate
|
|
7
|
+
|
|
8
|
+
Invoke the babysitter:babysit skill (using the Skill tool) and follow its instructions (SKILL.md).
|
|
9
|
+
|
|
10
|
+
Use the assimilation domain processes from the active process library to convert external sources into well-defined babysitter process definitions with accompanying skills/ and agents/ directories.
|
|
11
|
+
|
|
12
|
+
If the workspace does not already have an active process-library binding, initialize it first through the shared global SDK binding:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
babysitter process-library:active --json
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Run the process after formalizing it.
|
|
19
|
+
|
|
20
|
+
Available assimilation workflows:
|
|
21
|
+
- **methodology-assimilation** (`specializations/meta/assimilation/workflows/methodology-assimilation`) - Learns an external methodology from its repo and converts procedural instructions, commands, and manual flows into babysitter processes with refactored skills and agents. Supports output as methodology or specialization.
|
|
22
|
+
- **harness integration** (`specializations/meta/assimilation/harness/*`) - Integrates babysitter SDK with a specific AI coding harness (generic, codex, opencode, gemini-cli, openclaw, antigravity).
|
|
23
|
+
|
|
24
|
+
During the interview phase, determine which assimilation workflow to use based on the user's target:
|
|
25
|
+
- If the target is a **repo URL or methodology name** then use the methodology-assimilation workflow.
|
|
26
|
+
- If the target is a **harness name** (e.g. codex, opencode, antigravity) then use the matching harness process.
|
|
27
|
+
- If the target is a **specification or other source** then adapt the methodology-assimilation workflow for the spec format.
|
|
28
|
+
- If unclear, ask the user to clarify the assimilation target and type.
|
|
29
|
+
|
|
30
|
+
## After Assimilation: Contribute Back
|
|
31
|
+
|
|
32
|
+
After successfully assimilating a methodology or harness integration, prompt the user to share it with the community. The assimilated process definitions, skills, and agents could benefit other babysitter users:
|
|
33
|
+
|
|
34
|
+
- **Completed a methodology assimilation**: `/babysitter:contrib library contribution: assimilated [methodology-name] into babysitter process definitions`
|
|
35
|
+
- **Completed a harness integration**: `/babysitter:contrib library contribution: [harness-name] harness integration`
|
|
36
|
+
- **Hit issues during assimilation** (e.g. unsupported patterns, missing SDK features): `/babysitter:contrib bug report: assimilation of [target] failed because [description]` or `/babysitter:contrib feature request: [what the SDK needs to support]`
|
|
37
|
+
|
|
38
|
+
Even just reporting that an assimilation didn't work well helps improve babysitter for everyone.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: babysit
|
|
3
|
+
description: Orchestrate via @babysitter. Use this skill when asked to babysit a run, orchestrate a process or whenever it is called explicitly. (babysit, babysitter, orchestrate, orchestrate a run, workflow, etc.)
|
|
4
|
+
allowed-tools: Read, Grep, Write, Task, Bash, Edit, Grep, Glob, WebFetch, WebSearch, Search, AskUserQuestion, TodoWrite, TodoRead, Skill, BashOutput, KillShell, MultiEdit, LS
|
|
5
|
+
version: 0.1.3
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# babysit
|
|
9
|
+
|
|
10
|
+
Orchestrate `.a5c/runs/<runId>/` through iterative execution.
|
|
11
|
+
|
|
12
|
+
## Dependencies
|
|
13
|
+
|
|
14
|
+
### Babysitter SDK and CLI
|
|
15
|
+
|
|
16
|
+
Read the SDK version from `versions.json` to ensure version compatibility:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
SDK_VERSION=$(node -e "try{console.log(JSON.parse(require('fs').readFileSync('${CLAUDE_PLUGIN_ROOT}/versions.json','utf8')).sdkVersion||'latest')}catch{console.log('latest')}")
|
|
20
|
+
npm i -g @a5c-ai/babysitter-sdk@$SDK_VERSION
|
|
21
|
+
|
|
22
|
+
CLI="npx -y @a5c-ai/babysitter-sdk@$SDK_VERSION"
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
If `babysitter` is already installed globally at the correct version, you may use `CLI="babysitter"` instead.
|
|
26
|
+
|
|
27
|
+
### jq
|
|
28
|
+
|
|
29
|
+
Make sure `jq` is installed and available in the path. If not, install it.
|
|
30
|
+
|
|
31
|
+
## Instructions
|
|
32
|
+
|
|
33
|
+
Run the following command to get full orchestration instructions:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
$CLI instructions:babysit-skill --harness claude-code --interactive
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
For non-interactive mode (running with `-p` flag or no AskUserQuestion tool):
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
$CLI instructions:babysit-skill --harness claude-code --no-interactive
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Follow the instructions returned by the command above to orchestrate the run.
|