@a5c-ai/babysitter-opencode 5.0.1-staging.d73033a7 → 5.0.1-staging.d8bdfcceaf4a
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 +19 -21
- 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/call.md +5 -1
- package/commands/cleanup.md +30 -8
- package/commands/doctor.md +7 -8
- package/commands/help.md +246 -244
- package/commands/observe.md +17 -12
- package/commands/yolo.md +11 -7
- package/hooks/babysitter-proxied-session-created.js +18 -212
- package/hooks/babysitter-proxied-session-created.sh +11 -0
- package/hooks/babysitter-proxied-shell-env.js +21 -145
- package/hooks/babysitter-proxied-shell-env.sh +3 -0
- package/hooks/babysitter-proxied-stop-hook.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 +14 -22
- package/package.json +21 -19
- package/plugin.json +6 -4
- 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/accomplish-status/SKILL.md +1 -1
- package/skills/babysit/SKILL.md +4 -3
- package/skills/call/SKILL.md +5 -1
- package/skills/cleanup/SKILL.md +30 -8
- package/skills/contrib/SKILL.md +25 -25
- package/skills/doctor/SKILL.md +7 -8
- package/skills/help/SKILL.md +4 -2
- package/skills/observe/SKILL.md +7 -2
- 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/skills/yolo/SKILL.md +5 -1
- package/versions.json +2 -2
- package/hooks/babysitter-proxied-session-idle.js +0 -173
- 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/scripts/sync-command-docs.cjs +0 -107
- package/scripts/sync-command-surfaces.js +0 -52
package/hooks/session-idle.js
DELETED
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Babysitter Session Idle Hook for OpenCode
|
|
4
|
-
*
|
|
5
|
-
* Fires when the OpenCode agent goes idle. Checks if the current babysitter
|
|
6
|
-
* run has pending effects that need attention. Since OpenCode does NOT have a
|
|
7
|
-
* blocking stop hook, this is fire-and-forget -- it outputs context about
|
|
8
|
-
* pending effects so the agent can decide whether to continue iterating.
|
|
9
|
-
*
|
|
10
|
-
* Delegates to `babysitter hook:run --hook-type stop` (which handles the
|
|
11
|
-
* run-state inspection and iteration tracking).
|
|
12
|
-
*
|
|
13
|
-
* OpenCode plugin protocol:
|
|
14
|
-
* - Receives event context as JSON via stdin
|
|
15
|
-
* - Outputs JSON to stdout
|
|
16
|
-
* - Exit 0 = success
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
"use strict";
|
|
20
|
-
|
|
21
|
-
const { execSync } = require("child_process");
|
|
22
|
-
const { readFileSync, mkdirSync, appendFileSync } = require("fs");
|
|
23
|
-
const os = require("os");
|
|
24
|
-
const path = require("path");
|
|
25
|
-
|
|
26
|
-
const PLUGIN_ROOT = process.env.OPENCODE_PLUGIN_ROOT || path.resolve(__dirname, "..");
|
|
27
|
-
const GLOBAL_ROOT = process.env.BABYSITTER_GLOBAL_STATE_DIR || path.join(os.homedir(), ".a5c");
|
|
28
|
-
const STATE_DIR = process.env.BABYSITTER_STATE_DIR || path.join(GLOBAL_ROOT, "state");
|
|
29
|
-
const LOG_DIR = process.env.BABYSITTER_LOG_DIR || path.join(GLOBAL_ROOT, "logs");
|
|
30
|
-
const LOG_FILE = path.join(LOG_DIR, "babysitter-session-idle-hook.log");
|
|
31
|
-
|
|
32
|
-
function ensureDir(dir) {
|
|
33
|
-
try { mkdirSync(dir, { recursive: true }); } catch { /* best-effort */ }
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function blog(msg) {
|
|
37
|
-
ensureDir(LOG_DIR);
|
|
38
|
-
const ts = new Date().toISOString();
|
|
39
|
-
try {
|
|
40
|
-
appendFileSync(LOG_FILE, `[INFO] ${ts} ${msg}\n`);
|
|
41
|
-
} catch { /* best-effort */ }
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function getSdkVersion() {
|
|
45
|
-
try {
|
|
46
|
-
const versions = JSON.parse(readFileSync(path.join(PLUGIN_ROOT, "versions.json"), "utf8"));
|
|
47
|
-
return versions.sdkVersion || "latest";
|
|
48
|
-
} catch {
|
|
49
|
-
return "latest";
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function runBabysitterHook(hookType, inputJson) {
|
|
54
|
-
const sdkVersion = getSdkVersion();
|
|
55
|
-
const args = [
|
|
56
|
-
"hook:run",
|
|
57
|
-
"--hook-type", hookType,
|
|
58
|
-
"--harness", "opencode",
|
|
59
|
-
"--plugin-root", PLUGIN_ROOT,
|
|
60
|
-
"--state-dir", STATE_DIR,
|
|
61
|
-
"--json",
|
|
62
|
-
];
|
|
63
|
-
|
|
64
|
-
try {
|
|
65
|
-
const result = execSync(`babysitter ${args.join(" ")}`, {
|
|
66
|
-
input: inputJson,
|
|
67
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
68
|
-
timeout: 30000,
|
|
69
|
-
env: { ...process.env, BABYSITTER_STATE_DIR: STATE_DIR },
|
|
70
|
-
});
|
|
71
|
-
return result.toString("utf8").trim();
|
|
72
|
-
} catch {
|
|
73
|
-
try {
|
|
74
|
-
const result = execSync(`npx -y "@a5c-ai/babysitter-sdk@${sdkVersion}" ${args.join(" ")}`, {
|
|
75
|
-
input: inputJson,
|
|
76
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
77
|
-
timeout: 60000,
|
|
78
|
-
env: { ...process.env, BABYSITTER_STATE_DIR: STATE_DIR },
|
|
79
|
-
});
|
|
80
|
-
return result.toString("utf8").trim();
|
|
81
|
-
} catch (err) {
|
|
82
|
-
blog(`Hook execution failed: ${err.message}`);
|
|
83
|
-
return "{}";
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
function main() {
|
|
89
|
-
blog("session-idle hook invoked");
|
|
90
|
-
|
|
91
|
-
const sessionId = process.env.BABYSITTER_SESSION_ID
|
|
92
|
-
|| process.env.OPENCODE_SESSION_ID
|
|
93
|
-
|| "";
|
|
94
|
-
|
|
95
|
-
if (!sessionId) {
|
|
96
|
-
blog("No session ID -- nothing to check");
|
|
97
|
-
process.stdout.write("{}\n");
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const hookInput = JSON.stringify({
|
|
102
|
-
session_id: sessionId,
|
|
103
|
-
cwd: process.cwd(),
|
|
104
|
-
harness: "opencode",
|
|
105
|
-
plugin_root: PLUGIN_ROOT,
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
blog(`Checking run status for session ${sessionId}`);
|
|
109
|
-
|
|
110
|
-
// Delegate to the stop hook handler, which inspects run state
|
|
111
|
-
// and returns block/allow decisions
|
|
112
|
-
const result = runBabysitterHook("stop", hookInput);
|
|
113
|
-
|
|
114
|
-
blog(`Hook result: ${result}`);
|
|
115
|
-
|
|
116
|
-
try {
|
|
117
|
-
const parsed = JSON.parse(result);
|
|
118
|
-
process.stdout.write(JSON.stringify(parsed) + "\n");
|
|
119
|
-
} catch {
|
|
120
|
-
process.stdout.write("{}\n");
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
main();
|
package/hooks/shell-env.js
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Babysitter Shell Environment Hook for OpenCode
|
|
4
|
-
*
|
|
5
|
-
* Fires when OpenCode initializes a shell environment. Injects babysitter
|
|
6
|
-
* environment variables (BABYSITTER_SESSION_ID, BABYSITTER_STATE_DIR, etc.)
|
|
7
|
-
* so that subprocesses and other hooks can discover the active session.
|
|
8
|
-
*
|
|
9
|
-
* This is critical for OpenCode because it does NOT natively inject
|
|
10
|
-
* distinctive env vars into plugins -- the babysitter plugin must self-inject
|
|
11
|
-
* them via this hook.
|
|
12
|
-
*
|
|
13
|
-
* OpenCode plugin protocol:
|
|
14
|
-
* - Outputs env var assignments as JSON: { "env": { "KEY": "VALUE" } }
|
|
15
|
-
* - Exit 0 = success
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
"use strict";
|
|
19
|
-
|
|
20
|
-
const { readFileSync, mkdirSync, appendFileSync, existsSync } = require("fs");
|
|
21
|
-
const os = require("os");
|
|
22
|
-
const path = require("path");
|
|
23
|
-
const crypto = require("crypto");
|
|
24
|
-
|
|
25
|
-
const PLUGIN_ROOT = process.env.OPENCODE_PLUGIN_ROOT || path.resolve(__dirname, "..");
|
|
26
|
-
const GLOBAL_ROOT = process.env.BABYSITTER_GLOBAL_STATE_DIR || path.join(os.homedir(), ".a5c");
|
|
27
|
-
const STATE_DIR = process.env.BABYSITTER_STATE_DIR || path.join(GLOBAL_ROOT, "state");
|
|
28
|
-
const RUNS_DIR = process.env.BABYSITTER_RUNS_DIR || path.join(GLOBAL_ROOT, "runs");
|
|
29
|
-
const LOG_DIR = process.env.BABYSITTER_LOG_DIR || path.join(GLOBAL_ROOT, "logs");
|
|
30
|
-
const LOG_FILE = path.join(LOG_DIR, "babysitter-shell-env-hook.log");
|
|
31
|
-
|
|
32
|
-
function ensureDir(dir) {
|
|
33
|
-
try { mkdirSync(dir, { recursive: true }); } catch { /* best-effort */ }
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function blog(msg) {
|
|
37
|
-
ensureDir(LOG_DIR);
|
|
38
|
-
const ts = new Date().toISOString();
|
|
39
|
-
try {
|
|
40
|
-
appendFileSync(LOG_FILE, `[INFO] ${ts} ${msg}\n`);
|
|
41
|
-
} catch { /* best-effort */ }
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function getSdkVersion() {
|
|
45
|
-
try {
|
|
46
|
-
const versions = JSON.parse(readFileSync(path.join(PLUGIN_ROOT, "versions.json"), "utf8"));
|
|
47
|
-
return versions.sdkVersion || "latest";
|
|
48
|
-
} catch {
|
|
49
|
-
return "latest";
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function main() {
|
|
54
|
-
blog("shell-env hook invoked");
|
|
55
|
-
|
|
56
|
-
// Resolve or generate session ID
|
|
57
|
-
const sessionId = process.env.BABYSITTER_SESSION_ID
|
|
58
|
-
|| process.env.OPENCODE_SESSION_ID
|
|
59
|
-
|| crypto.randomUUID();
|
|
60
|
-
|
|
61
|
-
const sdkVersion = getSdkVersion();
|
|
62
|
-
|
|
63
|
-
// Build env vars to inject
|
|
64
|
-
const env = {
|
|
65
|
-
BABYSITTER_SESSION_ID: sessionId,
|
|
66
|
-
OPENCODE_SESSION_ID: sessionId,
|
|
67
|
-
BABYSITTER_STATE_DIR: STATE_DIR,
|
|
68
|
-
BABYSITTER_RUNS_DIR: RUNS_DIR,
|
|
69
|
-
OPENCODE_PLUGIN_ROOT: PLUGIN_ROOT,
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
// Add SDK version for downstream hooks
|
|
73
|
-
if (sdkVersion && sdkVersion !== "latest") {
|
|
74
|
-
env.BABYSITTER_SDK_VERSION = sdkVersion;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// Add global state dir if defined
|
|
78
|
-
const globalStateDir = process.env.BABYSITTER_GLOBAL_STATE_DIR;
|
|
79
|
-
if (globalStateDir) {
|
|
80
|
-
env.BABYSITTER_GLOBAL_STATE_DIR = globalStateDir;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
blog(`Injecting env: ${JSON.stringify(env)}`);
|
|
84
|
-
|
|
85
|
-
process.stdout.write(JSON.stringify({ env }) + "\n");
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
main();
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Babysitter Tool Execute After Hook for OpenCode
|
|
4
|
-
*
|
|
5
|
-
* Fires after a tool execution in OpenCode. Delegates to
|
|
6
|
-
* `babysitter hook:run --hook-type post-tool-use` for post-tool-use awareness.
|
|
7
|
-
*
|
|
8
|
-
* This hook can be used to:
|
|
9
|
-
* - Log tool execution results for babysitter run observability
|
|
10
|
-
* - Trigger babysitter effects based on tool outputs
|
|
11
|
-
* - Update session state after tool executions
|
|
12
|
-
*
|
|
13
|
-
* OpenCode plugin protocol:
|
|
14
|
-
* - Receives tool result context as JSON via stdin
|
|
15
|
-
* - Outputs JSON to stdout
|
|
16
|
-
* - Exit 0 = success
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
"use strict";
|
|
20
|
-
|
|
21
|
-
const { execSync } = require("child_process");
|
|
22
|
-
const { readFileSync, mkdirSync, appendFileSync } = require("fs");
|
|
23
|
-
const os = require("os");
|
|
24
|
-
const path = require("path");
|
|
25
|
-
|
|
26
|
-
const PLUGIN_ROOT = process.env.OPENCODE_PLUGIN_ROOT || path.resolve(__dirname, "..");
|
|
27
|
-
const GLOBAL_ROOT = process.env.BABYSITTER_GLOBAL_STATE_DIR || path.join(os.homedir(), ".a5c");
|
|
28
|
-
const STATE_DIR = process.env.BABYSITTER_STATE_DIR || path.join(GLOBAL_ROOT, "state");
|
|
29
|
-
const LOG_DIR = process.env.BABYSITTER_LOG_DIR || path.join(GLOBAL_ROOT, "logs");
|
|
30
|
-
const LOG_FILE = path.join(LOG_DIR, "babysitter-tool-after-hook.log");
|
|
31
|
-
|
|
32
|
-
function ensureDir(dir) {
|
|
33
|
-
try { mkdirSync(dir, { recursive: true }); } catch { /* best-effort */ }
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function blog(msg) {
|
|
37
|
-
ensureDir(LOG_DIR);
|
|
38
|
-
const ts = new Date().toISOString();
|
|
39
|
-
try {
|
|
40
|
-
appendFileSync(LOG_FILE, `[INFO] ${ts} ${msg}\n`);
|
|
41
|
-
} catch { /* best-effort */ }
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function getSdkVersion() {
|
|
45
|
-
try {
|
|
46
|
-
const versions = JSON.parse(readFileSync(path.join(PLUGIN_ROOT, "versions.json"), "utf8"));
|
|
47
|
-
return versions.sdkVersion || "latest";
|
|
48
|
-
} catch {
|
|
49
|
-
return "latest";
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function main() {
|
|
54
|
-
const sessionId = process.env.BABYSITTER_SESSION_ID
|
|
55
|
-
|| process.env.OPENCODE_SESSION_ID
|
|
56
|
-
|| "";
|
|
57
|
-
|
|
58
|
-
if (!sessionId) {
|
|
59
|
-
process.stdout.write("{}\n");
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// Read stdin for tool result context
|
|
64
|
-
let inputData = "";
|
|
65
|
-
try {
|
|
66
|
-
inputData = require("fs").readFileSync(0, "utf8");
|
|
67
|
-
} catch {
|
|
68
|
-
// No stdin available
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
blog(`tool-execute-after: session=${sessionId}`);
|
|
72
|
-
|
|
73
|
-
const hookInput = JSON.stringify({
|
|
74
|
-
session_id: sessionId,
|
|
75
|
-
cwd: process.cwd(),
|
|
76
|
-
harness: "opencode",
|
|
77
|
-
plugin_root: PLUGIN_ROOT,
|
|
78
|
-
tool_result: inputData ? JSON.parse(inputData) : {},
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
const sdkVersion = getSdkVersion();
|
|
82
|
-
const args = [
|
|
83
|
-
"hook:run",
|
|
84
|
-
"--hook-type", "post-tool-use",
|
|
85
|
-
"--harness", "opencode",
|
|
86
|
-
"--plugin-root", PLUGIN_ROOT,
|
|
87
|
-
"--state-dir", STATE_DIR,
|
|
88
|
-
"--json",
|
|
89
|
-
];
|
|
90
|
-
|
|
91
|
-
try {
|
|
92
|
-
const result = execSync(`babysitter ${args.join(" ")}`, {
|
|
93
|
-
input: hookInput,
|
|
94
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
95
|
-
timeout: 10000,
|
|
96
|
-
env: { ...process.env, BABYSITTER_STATE_DIR: STATE_DIR },
|
|
97
|
-
});
|
|
98
|
-
const output = result.toString("utf8").trim();
|
|
99
|
-
blog(`Hook result: ${output}`);
|
|
100
|
-
process.stdout.write((output || "{}") + "\n");
|
|
101
|
-
} catch {
|
|
102
|
-
blog("Post-tool-use hook failed -- non-blocking");
|
|
103
|
-
process.stdout.write("{}\n");
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
main();
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Babysitter Tool Execute Before Hook for OpenCode
|
|
4
|
-
*
|
|
5
|
-
* Fires before a tool execution in OpenCode. Delegates to
|
|
6
|
-
* `babysitter hook:run --hook-type pre-tool-use` for pre-tool-use awareness.
|
|
7
|
-
*
|
|
8
|
-
* This hook can be used to:
|
|
9
|
-
* - Log tool invocations for babysitter run observability
|
|
10
|
-
* - Block certain tool calls during specific orchestration phases
|
|
11
|
-
* - Inject babysitter context into tool arguments
|
|
12
|
-
*
|
|
13
|
-
* OpenCode plugin protocol:
|
|
14
|
-
* - Receives tool context as JSON via stdin
|
|
15
|
-
* - Outputs JSON to stdout (empty = allow, { block: true } = block)
|
|
16
|
-
* - Exit 0 = success
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
"use strict";
|
|
20
|
-
|
|
21
|
-
const { execSync } = require("child_process");
|
|
22
|
-
const { readFileSync, mkdirSync, appendFileSync } = require("fs");
|
|
23
|
-
const os = require("os");
|
|
24
|
-
const path = require("path");
|
|
25
|
-
|
|
26
|
-
const PLUGIN_ROOT = process.env.OPENCODE_PLUGIN_ROOT || path.resolve(__dirname, "..");
|
|
27
|
-
const GLOBAL_ROOT = process.env.BABYSITTER_GLOBAL_STATE_DIR || path.join(os.homedir(), ".a5c");
|
|
28
|
-
const STATE_DIR = process.env.BABYSITTER_STATE_DIR || path.join(GLOBAL_ROOT, "state");
|
|
29
|
-
const LOG_DIR = process.env.BABYSITTER_LOG_DIR || path.join(GLOBAL_ROOT, "logs");
|
|
30
|
-
const LOG_FILE = path.join(LOG_DIR, "babysitter-tool-before-hook.log");
|
|
31
|
-
|
|
32
|
-
function ensureDir(dir) {
|
|
33
|
-
try { mkdirSync(dir, { recursive: true }); } catch { /* best-effort */ }
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function blog(msg) {
|
|
37
|
-
ensureDir(LOG_DIR);
|
|
38
|
-
const ts = new Date().toISOString();
|
|
39
|
-
try {
|
|
40
|
-
appendFileSync(LOG_FILE, `[INFO] ${ts} ${msg}\n`);
|
|
41
|
-
} catch { /* best-effort */ }
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function getSdkVersion() {
|
|
45
|
-
try {
|
|
46
|
-
const versions = JSON.parse(readFileSync(path.join(PLUGIN_ROOT, "versions.json"), "utf8"));
|
|
47
|
-
return versions.sdkVersion || "latest";
|
|
48
|
-
} catch {
|
|
49
|
-
return "latest";
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function main() {
|
|
54
|
-
const sessionId = process.env.BABYSITTER_SESSION_ID
|
|
55
|
-
|| process.env.OPENCODE_SESSION_ID
|
|
56
|
-
|| "";
|
|
57
|
-
|
|
58
|
-
if (!sessionId) {
|
|
59
|
-
// No session -- pass through without intervention
|
|
60
|
-
process.stdout.write("{}\n");
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Read stdin for tool context
|
|
65
|
-
let inputData = "";
|
|
66
|
-
try {
|
|
67
|
-
inputData = require("fs").readFileSync(0, "utf8");
|
|
68
|
-
} catch {
|
|
69
|
-
// No stdin available
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
blog(`tool-execute-before: session=${sessionId}`);
|
|
73
|
-
|
|
74
|
-
const hookInput = JSON.stringify({
|
|
75
|
-
session_id: sessionId,
|
|
76
|
-
cwd: process.cwd(),
|
|
77
|
-
harness: "opencode",
|
|
78
|
-
plugin_root: PLUGIN_ROOT,
|
|
79
|
-
tool_context: inputData ? JSON.parse(inputData) : {},
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
const sdkVersion = getSdkVersion();
|
|
83
|
-
const args = [
|
|
84
|
-
"hook:run",
|
|
85
|
-
"--hook-type", "pre-tool-use",
|
|
86
|
-
"--harness", "opencode",
|
|
87
|
-
"--plugin-root", PLUGIN_ROOT,
|
|
88
|
-
"--state-dir", STATE_DIR,
|
|
89
|
-
"--json",
|
|
90
|
-
];
|
|
91
|
-
|
|
92
|
-
try {
|
|
93
|
-
const result = execSync(`babysitter ${args.join(" ")}`, {
|
|
94
|
-
input: hookInput,
|
|
95
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
96
|
-
timeout: 10000,
|
|
97
|
-
env: { ...process.env, BABYSITTER_STATE_DIR: STATE_DIR },
|
|
98
|
-
});
|
|
99
|
-
const output = result.toString("utf8").trim();
|
|
100
|
-
blog(`Hook result: ${output}`);
|
|
101
|
-
process.stdout.write((output || "{}") + "\n");
|
|
102
|
-
} catch {
|
|
103
|
-
// On failure, allow the tool execution to proceed
|
|
104
|
-
blog("Pre-tool-use hook failed -- allowing execution");
|
|
105
|
-
process.stdout.write("{}\n");
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
main();
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const path = require('path');
|
|
4
|
-
const {
|
|
5
|
-
listMarkdownBasenames,
|
|
6
|
-
reportCheckResult,
|
|
7
|
-
syncCommandMirrors,
|
|
8
|
-
syncSkillsFromCommands,
|
|
9
|
-
writeFileIfChanged,
|
|
10
|
-
} = require('../../../scripts/plugin-command-sync-lib.cjs');
|
|
11
|
-
|
|
12
|
-
const PACKAGE_ROOT = path.resolve(__dirname, '..');
|
|
13
|
-
const REPO_ROOT = path.resolve(PACKAGE_ROOT, '..', '..');
|
|
14
|
-
const ROOT_COMMANDS = path.join(REPO_ROOT, 'plugins', 'babysitter', 'commands');
|
|
15
|
-
const COMMANDS_ROOT = path.join(PACKAGE_ROOT, 'commands');
|
|
16
|
-
const SKILLS_ROOT = path.join(PACKAGE_ROOT, 'skills');
|
|
17
|
-
const LABEL = 'babysitter-opencode sync';
|
|
18
|
-
|
|
19
|
-
const BABYSIT_SKILL = `---
|
|
20
|
-
name: babysit
|
|
21
|
-
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.)
|
|
22
|
-
---
|
|
23
|
-
|
|
24
|
-
# babysit
|
|
25
|
-
|
|
26
|
-
Orchestrate \`.a5c/runs/<runId>/\` through iterative execution.
|
|
27
|
-
|
|
28
|
-
## Dependencies
|
|
29
|
-
|
|
30
|
-
### Babysitter SDK and CLI
|
|
31
|
-
|
|
32
|
-
Read the SDK version from \`versions.json\` to ensure version compatibility:
|
|
33
|
-
|
|
34
|
-
\`\`\`bash
|
|
35
|
-
SDK_VERSION=$(node -e "try{const fs=require('fs');const probes=['./plugins/babysitter-opencode/versions.json','./node_modules/@a5c-ai/babysitter-opencode/versions.json'];for(const probe of probes){if(fs.existsSync(probe)){console.log(JSON.parse(fs.readFileSync(probe,'utf8')).sdkVersion||'latest');process.exit(0)}}console.log('latest')}catch{console.log('latest')}")
|
|
36
|
-
|
|
37
|
-
npm i -g @a5c-ai/babysitter-sdk@$SDK_VERSION
|
|
38
|
-
CLI="npx -y @a5c-ai/babysitter-sdk@$SDK_VERSION"
|
|
39
|
-
\`\`\`
|
|
40
|
-
|
|
41
|
-
## Instructions
|
|
42
|
-
|
|
43
|
-
Run the following command to get full orchestration instructions:
|
|
44
|
-
|
|
45
|
-
\`\`\`bash
|
|
46
|
-
babysitter instructions:babysit-skill --harness opencode --interactive
|
|
47
|
-
\`\`\`
|
|
48
|
-
|
|
49
|
-
For non-interactive mode:
|
|
50
|
-
|
|
51
|
-
\`\`\`bash
|
|
52
|
-
babysitter instructions:babysit-skill --harness opencode --no-interactive
|
|
53
|
-
\`\`\`
|
|
54
|
-
|
|
55
|
-
Follow the instructions returned by the command above to orchestrate the run.
|
|
56
|
-
`;
|
|
57
|
-
|
|
58
|
-
function getCommandNames() {
|
|
59
|
-
return listMarkdownBasenames(ROOT_COMMANDS);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function main() {
|
|
63
|
-
const check = process.argv.includes('--check');
|
|
64
|
-
const commandNames = getCommandNames();
|
|
65
|
-
const mirrorResult = syncCommandMirrors({
|
|
66
|
-
label: LABEL,
|
|
67
|
-
sourceRoot: ROOT_COMMANDS,
|
|
68
|
-
targetRoot: COMMANDS_ROOT,
|
|
69
|
-
names: commandNames,
|
|
70
|
-
check,
|
|
71
|
-
cwd: PACKAGE_ROOT,
|
|
72
|
-
});
|
|
73
|
-
const skillsResult = syncSkillsFromCommands({
|
|
74
|
-
label: LABEL,
|
|
75
|
-
sourceRoot: COMMANDS_ROOT,
|
|
76
|
-
skillsRoot: SKILLS_ROOT,
|
|
77
|
-
names: commandNames,
|
|
78
|
-
check,
|
|
79
|
-
cwd: PACKAGE_ROOT,
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
const babysitSkillPath = path.join(SKILLS_ROOT, 'babysit', 'SKILL.md');
|
|
83
|
-
if (check) {
|
|
84
|
-
const fs = require('fs');
|
|
85
|
-
const stale = [...mirrorResult.stale, ...skillsResult.stale];
|
|
86
|
-
const current = fs.existsSync(babysitSkillPath)
|
|
87
|
-
? fs.readFileSync(babysitSkillPath, 'utf8')
|
|
88
|
-
: null;
|
|
89
|
-
if (current !== BABYSIT_SKILL) {
|
|
90
|
-
stale.push(path.relative(PACKAGE_ROOT, babysitSkillPath));
|
|
91
|
-
}
|
|
92
|
-
reportCheckResult(LABEL, stale);
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
const babysitUpdated = writeFileIfChanged(babysitSkillPath, BABYSIT_SKILL) ? 1 : 0;
|
|
97
|
-
const updated = mirrorResult.updated + skillsResult.updated + babysitUpdated;
|
|
98
|
-
|
|
99
|
-
if (updated === 0) {
|
|
100
|
-
console.log(`[${LABEL}] no OpenCode command or skill changes were needed.`);
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
console.log(`[${LABEL}] updated ${updated} OpenCode command/skill file(s).`);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
main();
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Sync command surfaces from the canonical babysitter plugin.
|
|
4
|
-
*
|
|
5
|
-
* Copies command .md files from the cursor/codex plugins or generates
|
|
6
|
-
* them from the SDK CLI command definitions. Used during build/deploy
|
|
7
|
-
* to keep command surfaces in sync across harness plugins.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
"use strict";
|
|
11
|
-
|
|
12
|
-
const fs = require("fs");
|
|
13
|
-
const path = require("path");
|
|
14
|
-
|
|
15
|
-
const PLUGIN_ROOT = path.resolve(__dirname, "..");
|
|
16
|
-
const COMMANDS_DIR = path.join(PLUGIN_ROOT, "commands");
|
|
17
|
-
|
|
18
|
-
// Check mode
|
|
19
|
-
const checkOnly = process.argv.includes("--check");
|
|
20
|
-
|
|
21
|
-
function main() {
|
|
22
|
-
// Verify commands directory exists and has files
|
|
23
|
-
if (!fs.existsSync(COMMANDS_DIR)) {
|
|
24
|
-
console.error("ERROR: commands/ directory not found");
|
|
25
|
-
process.exit(1);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const files = fs.readdirSync(COMMANDS_DIR).filter(f => f.endsWith(".md"));
|
|
29
|
-
if (files.length === 0) {
|
|
30
|
-
console.error("ERROR: No command .md files found in commands/");
|
|
31
|
-
process.exit(1);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
console.log(`Found ${files.length} command files:`);
|
|
35
|
-
for (const file of files) {
|
|
36
|
-
const content = fs.readFileSync(path.join(COMMANDS_DIR, file), "utf8");
|
|
37
|
-
const hasHeader = content.startsWith("---");
|
|
38
|
-
const status = hasHeader ? "OK" : "MISSING FRONTMATTER";
|
|
39
|
-
console.log(` ${file} [${status}]`);
|
|
40
|
-
if (checkOnly && !hasHeader) {
|
|
41
|
-
process.exit(1);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
if (checkOnly) {
|
|
46
|
-
console.log("\nAll command files are valid.");
|
|
47
|
-
} else {
|
|
48
|
-
console.log("\nCommand surfaces synced.");
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
main();
|