@a5c-ai/babysitter-opencode 5.0.1-staging.e4f17eff → 5.0.1-staging.fcac7259
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 +2 -2
- 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 +13 -34
- package/commands/doctor.md +5 -5
- package/commands/help.md +245 -244
- package/commands/observe.md +12 -12
- package/hooks/babysitter-proxied-session-created.js +18 -212
- package/hooks/babysitter-proxied-session-created.sh +11 -0
- package/hooks/babysitter-proxied-session-idle.js +18 -167
- package/hooks/babysitter-proxied-session-idle.sh +3 -0
- package/hooks/babysitter-proxied-shell-env.js +21 -145
- package/hooks/babysitter-proxied-shell-env.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 +18 -18
- package/package.json +19 -19
- package/plugin.json +6 -4
- package/scripts/team-install.js +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/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
|
@@ -5,52 +5,52 @@ description: Analysis for a run and its results, process, suggestions for proces
|
|
|
5
5
|
|
|
6
6
|
# retrospect
|
|
7
7
|
|
|
8
|
-
Invoke the babysitter:babysit skill (using the Skill tool) and follow its instructions (SKILL.md).
|
|
9
|
-
|
|
10
|
-
create and run a retrospect process:
|
|
11
|
-
|
|
12
|
-
### Run Selection
|
|
13
|
-
|
|
14
|
-
- `--all` or "all runs": list all completed/failed runs and analyze collectively
|
|
15
|
-
- Multiple run IDs: analyze each specified run
|
|
16
|
-
- Single run ID or no ID: existing behavior (latest run)
|
|
17
|
-
- In interactive mode with no run specified: ask user whether to analyze latest, select specific runs, or all runs
|
|
18
|
-
|
|
19
|
-
### Cross-Run Analysis (multi-run mode)
|
|
20
|
-
|
|
21
|
-
When analyzing multiple runs, the retrospect process should additionally cover:
|
|
22
|
-
- Common failure patterns across runs
|
|
23
|
-
- Velocity trends (tasks/time across runs)
|
|
24
|
-
- Process evolution (how processes changed)
|
|
25
|
-
- Repeated breakpoint patterns
|
|
26
|
-
- Aggregate quality metrics
|
|
27
|
-
|
|
28
|
-
implementations notes (for the process):
|
|
29
|
-
- The process should analyze the run, the process that was followed, and provide suggestions for improvements, optimizations, and fixes.
|
|
30
|
-
- The process should such have many breakpoints where the user can steer the process, provide feedback, and make decisions about how to proceed with the retrospect.
|
|
31
|
-
- The process should be designed to be flexible and adaptable to different types of runs, projects, and goals, and should be able to provide insights and suggestions that are relevant and actionable for the user. (modification to the process, skills, etc.)
|
|
32
|
-
- The process should be designed to be iterative, allowing the user to go through multiple rounds of analysis and improvement, and should be able to track the changes and improvements made over time.
|
|
33
|
-
- The process should cover:
|
|
34
|
-
- Analysis of the run and its results, including what went well, what didn't go well, and what could be improved.
|
|
35
|
-
- Analysis of the process that was followed, including what steps were taken, what tools were used, and how effective they were.
|
|
36
|
-
- Suggestions for improvements, optimizations, and fixes for both the run and the process.
|
|
37
|
-
- Implementing the improvements, optimizations, and fixes, and tracking the changes made over time.
|
|
38
|
-
### Cleanup Suggestion
|
|
39
|
-
|
|
40
|
-
After retrospect analysis, suggest running `/babysitter:cleanup` to clean up old run data and reclaim disk space.
|
|
41
|
-
|
|
42
|
-
- Ending by explicitly prompting the user to contribute back -- even just reporting an issue is valuable, they don't need to implement the fix themselves. After analysis, display a clear call-to-action:
|
|
43
|
-
|
|
44
|
-
"You've identified [specific insight/improvement]. This could help other babysitter users too. Run `/babysitter:contrib` to share it upstream -- you can either report it as an issue or submit a PR with the fix."
|
|
45
|
-
|
|
46
|
-
Route to the specific contrib workflow based on what the user wants to do:
|
|
47
|
-
|
|
48
|
-
**Just reporting (no code changes needed):**
|
|
49
|
-
- Found a bug or weakness in a process -> `/babysitter:contrib bug report: [description of what went wrong]`
|
|
50
|
-
- Found missing or confusing documentation -> `/babysitter:contrib documentation question: [what was unclear]`
|
|
51
|
-
- Have an idea for improvement but don't want to implement it -> `/babysitter:contrib feature request: [description]`
|
|
52
|
-
|
|
53
|
-
**Contributing code changes:**
|
|
54
|
-
- Process/skill/agent improvements -> `/babysitter:contrib library contribution: [description]`
|
|
55
|
-
- Bug fixes in SDK or CLI -> `/babysitter:contrib bugfix: [description]`
|
|
8
|
+
Invoke the babysitter:babysit skill (using the Skill tool) and follow its instructions (SKILL.md).
|
|
9
|
+
|
|
10
|
+
create and run a retrospect process:
|
|
11
|
+
|
|
12
|
+
### Run Selection
|
|
13
|
+
|
|
14
|
+
- `--all` or "all runs": list all completed/failed runs and analyze collectively
|
|
15
|
+
- Multiple run IDs: analyze each specified run
|
|
16
|
+
- Single run ID or no ID: existing behavior (latest run)
|
|
17
|
+
- In interactive mode with no run specified: ask user whether to analyze latest, select specific runs, or all runs
|
|
18
|
+
|
|
19
|
+
### Cross-Run Analysis (multi-run mode)
|
|
20
|
+
|
|
21
|
+
When analyzing multiple runs, the retrospect process should additionally cover:
|
|
22
|
+
- Common failure patterns across runs
|
|
23
|
+
- Velocity trends (tasks/time across runs)
|
|
24
|
+
- Process evolution (how processes changed)
|
|
25
|
+
- Repeated breakpoint patterns
|
|
26
|
+
- Aggregate quality metrics
|
|
27
|
+
|
|
28
|
+
implementations notes (for the process):
|
|
29
|
+
- The process should analyze the run, the process that was followed, and provide suggestions for improvements, optimizations, and fixes.
|
|
30
|
+
- The process should such have many breakpoints where the user can steer the process, provide feedback, and make decisions about how to proceed with the retrospect.
|
|
31
|
+
- The process should be designed to be flexible and adaptable to different types of runs, projects, and goals, and should be able to provide insights and suggestions that are relevant and actionable for the user. (modification to the process, skills, etc.)
|
|
32
|
+
- The process should be designed to be iterative, allowing the user to go through multiple rounds of analysis and improvement, and should be able to track the changes and improvements made over time.
|
|
33
|
+
- The process should cover:
|
|
34
|
+
- Analysis of the run and its results, including what went well, what didn't go well, and what could be improved.
|
|
35
|
+
- Analysis of the process that was followed, including what steps were taken, what tools were used, and how effective they were.
|
|
36
|
+
- Suggestions for improvements, optimizations, and fixes for both the run and the process.
|
|
37
|
+
- Implementing the improvements, optimizations, and fixes, and tracking the changes made over time.
|
|
38
|
+
### Cleanup Suggestion
|
|
39
|
+
|
|
40
|
+
After retrospect analysis, suggest running `/babysitter:cleanup` to clean up old run data and reclaim disk space.
|
|
41
|
+
|
|
42
|
+
- Ending by explicitly prompting the user to contribute back -- even just reporting an issue is valuable, they don't need to implement the fix themselves. After analysis, display a clear call-to-action:
|
|
43
|
+
|
|
44
|
+
"You've identified [specific insight/improvement]. This could help other babysitter users too. Run `/babysitter:contrib` to share it upstream -- you can either report it as an issue or submit a PR with the fix."
|
|
45
|
+
|
|
46
|
+
Route to the specific contrib workflow based on what the user wants to do:
|
|
47
|
+
|
|
48
|
+
**Just reporting (no code changes needed):**
|
|
49
|
+
- Found a bug or weakness in a process -> `/babysitter:contrib bug report: [description of what went wrong]`
|
|
50
|
+
- Found missing or confusing documentation -> `/babysitter:contrib documentation question: [what was unclear]`
|
|
51
|
+
- Have an idea for improvement but don't want to implement it -> `/babysitter:contrib feature request: [description]`
|
|
52
|
+
|
|
53
|
+
**Contributing code changes:**
|
|
54
|
+
- Process/skill/agent improvements -> `/babysitter:contrib library contribution: [description]`
|
|
55
|
+
- Bug fixes in SDK or CLI -> `/babysitter:contrib bugfix: [description]`
|
|
56
56
|
- Plugin instruction improvements -> `/babysitter:contrib library contribution: improved [plugin-name] [install|configure|uninstall] instructions`
|
|
@@ -5,8 +5,8 @@ description: Set up babysitter for yourself. Guides you through onboarding — i
|
|
|
5
5
|
|
|
6
6
|
# user-install
|
|
7
7
|
|
|
8
|
-
Invoke the babysitter:babysit skill (using the Skill tool) and follow its instructions (SKILL.md).
|
|
9
|
-
|
|
8
|
+
Invoke the babysitter:babysit skill (using the Skill tool) and follow its instructions (SKILL.md).
|
|
9
|
+
|
|
10
10
|
Before using the process library, resolve the active library root through the SDK CLI. If no binding exists yet, initialize the shared global SDK binding with:
|
|
11
11
|
|
|
12
12
|
```bash
|
|
@@ -14,5 +14,5 @@ babysitter process-library:active --json
|
|
|
14
14
|
```
|
|
15
15
|
|
|
16
16
|
Then use the `cradle/user-install` process from the active process library.
|
|
17
|
-
|
|
17
|
+
|
|
18
18
|
When the run completes, end with a friendly message that includes a polite and humorous ask to star the repo on GitHub: https://github.com/a5c-ai/babysitter
|
package/versions.json
CHANGED
package/hooks/hooks.json.legacy
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 1,
|
|
3
|
-
"description": "Babysitter hook registration for OpenCode. Maps OpenCode plugin events to babysitter hook scripts.",
|
|
4
|
-
"hooks": {
|
|
5
|
-
"session.created": [
|
|
6
|
-
{
|
|
7
|
-
"type": "command",
|
|
8
|
-
"script": "hooks/session-created.js",
|
|
9
|
-
"description": "Initialize babysitter session state and inject context",
|
|
10
|
-
"timeoutMs": 30000
|
|
11
|
-
}
|
|
12
|
-
],
|
|
13
|
-
"session.idle": [
|
|
14
|
-
{
|
|
15
|
-
"type": "command",
|
|
16
|
-
"script": "hooks/session-idle.js",
|
|
17
|
-
"description": "Check for pending babysitter effects when agent goes idle",
|
|
18
|
-
"timeoutMs": 30000
|
|
19
|
-
}
|
|
20
|
-
],
|
|
21
|
-
"shell.env": [
|
|
22
|
-
{
|
|
23
|
-
"type": "command",
|
|
24
|
-
"script": "hooks/shell-env.js",
|
|
25
|
-
"description": "Inject BABYSITTER_SESSION_ID and other env vars into shell",
|
|
26
|
-
"timeoutMs": 5000
|
|
27
|
-
}
|
|
28
|
-
],
|
|
29
|
-
"tool.execute.before": [
|
|
30
|
-
{
|
|
31
|
-
"type": "command",
|
|
32
|
-
"script": "hooks/tool-execute-before.js",
|
|
33
|
-
"description": "Pre-tool-use hook for babysitter awareness",
|
|
34
|
-
"timeoutMs": 10000
|
|
35
|
-
}
|
|
36
|
-
],
|
|
37
|
-
"tool.execute.after": [
|
|
38
|
-
{
|
|
39
|
-
"type": "command",
|
|
40
|
-
"script": "hooks/tool-execute-after.js",
|
|
41
|
-
"description": "Post-tool-use hook for babysitter awareness",
|
|
42
|
-
"timeoutMs": 10000
|
|
43
|
-
}
|
|
44
|
-
]
|
|
45
|
-
}
|
|
46
|
-
}
|
package/hooks/proxied-hooks.json
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"_comment": "NOT ACTIVE — Alternative hooks.json using per-hook unified scripts with hooks-proxy support. To activate, replace hooks.json with this file.",
|
|
3
|
-
"version": 1,
|
|
4
|
-
"description": "Babysitter hook registration for OpenCode. Maps OpenCode plugin events to unified babysitter hook scripts with hooks-proxy support.",
|
|
5
|
-
"hooks": {
|
|
6
|
-
"session.created": [
|
|
7
|
-
{
|
|
8
|
-
"type": "command",
|
|
9
|
-
"script": "hooks/babysitter-proxied-session-created.js",
|
|
10
|
-
"description": "Initialize babysitter session state and inject context (proxied via a5c-hooks-proxy)",
|
|
11
|
-
"timeoutMs": 30000
|
|
12
|
-
}
|
|
13
|
-
],
|
|
14
|
-
"session.idle": [
|
|
15
|
-
{
|
|
16
|
-
"type": "command",
|
|
17
|
-
"script": "hooks/babysitter-proxied-session-idle.js",
|
|
18
|
-
"description": "Check for pending babysitter effects when agent goes idle (proxied via a5c-hooks-proxy)",
|
|
19
|
-
"timeoutMs": 30000
|
|
20
|
-
}
|
|
21
|
-
],
|
|
22
|
-
"shell.env": [
|
|
23
|
-
{
|
|
24
|
-
"type": "command",
|
|
25
|
-
"script": "hooks/babysitter-proxied-shell-env.js",
|
|
26
|
-
"description": "Inject BABYSITTER_SESSION_ID and other env vars into shell (proxied via a5c-hooks-proxy)",
|
|
27
|
-
"timeoutMs": 5000
|
|
28
|
-
}
|
|
29
|
-
],
|
|
30
|
-
"tool.execute.before": [
|
|
31
|
-
{
|
|
32
|
-
"type": "command",
|
|
33
|
-
"script": "hooks/babysitter-proxied-tool-execute-before.js",
|
|
34
|
-
"description": "Pre-tool-use hook for babysitter awareness (proxied via a5c-hooks-proxy)",
|
|
35
|
-
"timeoutMs": 10000
|
|
36
|
-
}
|
|
37
|
-
],
|
|
38
|
-
"tool.execute.after": [
|
|
39
|
-
{
|
|
40
|
-
"type": "command",
|
|
41
|
-
"script": "hooks/babysitter-proxied-tool-execute-after.js",
|
|
42
|
-
"description": "Post-tool-use hook for babysitter awareness (proxied via a5c-hooks-proxy)",
|
|
43
|
-
"timeoutMs": 10000
|
|
44
|
-
}
|
|
45
|
-
]
|
|
46
|
-
}
|
|
47
|
-
}
|
package/hooks/session-created.js
DELETED
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Babysitter Session Created Hook for OpenCode
|
|
4
|
-
*
|
|
5
|
-
* Fires when an OpenCode session is created. Ensures the babysitter SDK CLI
|
|
6
|
-
* is installed, then delegates to `babysitter hook:run --hook-type session-start`
|
|
7
|
-
* to create baseline session state.
|
|
8
|
-
*
|
|
9
|
-
* OpenCode plugin protocol:
|
|
10
|
-
* - Receives event context as JSON via process.argv or stdin
|
|
11
|
-
* - Outputs JSON to stdout
|
|
12
|
-
* - Exit 0 = success
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
"use strict";
|
|
16
|
-
|
|
17
|
-
const { execSync, execFileSync } = require("child_process");
|
|
18
|
-
const { readFileSync, mkdirSync, appendFileSync, existsSync, writeFileSync } = require("fs");
|
|
19
|
-
const os = require("os");
|
|
20
|
-
const path = require("path");
|
|
21
|
-
const crypto = require("crypto");
|
|
22
|
-
|
|
23
|
-
const PLUGIN_ROOT = process.env.OPENCODE_PLUGIN_ROOT || path.resolve(__dirname, "..");
|
|
24
|
-
const GLOBAL_ROOT = process.env.BABYSITTER_GLOBAL_STATE_DIR || path.join(os.homedir(), ".a5c");
|
|
25
|
-
const STATE_DIR = process.env.BABYSITTER_STATE_DIR || path.join(GLOBAL_ROOT, "state");
|
|
26
|
-
const LOG_DIR = process.env.BABYSITTER_LOG_DIR || path.join(GLOBAL_ROOT, "logs");
|
|
27
|
-
const LOG_FILE = path.join(LOG_DIR, "babysitter-session-created-hook.log");
|
|
28
|
-
|
|
29
|
-
// ---------------------------------------------------------------------------
|
|
30
|
-
// Logging
|
|
31
|
-
// ---------------------------------------------------------------------------
|
|
32
|
-
|
|
33
|
-
function ensureDir(dir) {
|
|
34
|
-
try { mkdirSync(dir, { recursive: true }); } catch { /* best-effort */ }
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function blog(msg) {
|
|
38
|
-
ensureDir(LOG_DIR);
|
|
39
|
-
const ts = new Date().toISOString();
|
|
40
|
-
try {
|
|
41
|
-
appendFileSync(LOG_FILE, `[INFO] ${ts} ${msg}\n`);
|
|
42
|
-
} catch { /* best-effort */ }
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// ---------------------------------------------------------------------------
|
|
46
|
-
// SDK version & install
|
|
47
|
-
// ---------------------------------------------------------------------------
|
|
48
|
-
|
|
49
|
-
function getSdkVersion() {
|
|
50
|
-
try {
|
|
51
|
-
const versions = JSON.parse(readFileSync(path.join(PLUGIN_ROOT, "versions.json"), "utf8"));
|
|
52
|
-
return versions.sdkVersion || "latest";
|
|
53
|
-
} catch {
|
|
54
|
-
return "latest";
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function hasBabysitterCli() {
|
|
59
|
-
try {
|
|
60
|
-
execSync("babysitter --version", { stdio: "pipe", timeout: 10000 });
|
|
61
|
-
return true;
|
|
62
|
-
} catch {
|
|
63
|
-
return false;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
function installSdk(version) {
|
|
68
|
-
const marker = path.join(PLUGIN_ROOT, ".babysitter-install-attempted");
|
|
69
|
-
if (existsSync(marker)) return;
|
|
70
|
-
|
|
71
|
-
try {
|
|
72
|
-
execSync(`npm i -g "@a5c-ai/babysitter-sdk@${version}" --loglevel=error`, {
|
|
73
|
-
stdio: "pipe",
|
|
74
|
-
timeout: 120000,
|
|
75
|
-
});
|
|
76
|
-
blog(`Installed SDK globally (${version})`);
|
|
77
|
-
} catch {
|
|
78
|
-
// Try user-local prefix
|
|
79
|
-
try {
|
|
80
|
-
const prefix = path.join(process.env.HOME || process.env.USERPROFILE || "~", ".local");
|
|
81
|
-
execSync(`npm i -g "@a5c-ai/babysitter-sdk@${version}" --prefix "${prefix}" --loglevel=error`, {
|
|
82
|
-
stdio: "pipe",
|
|
83
|
-
timeout: 120000,
|
|
84
|
-
});
|
|
85
|
-
blog(`Installed SDK to user prefix (${version})`);
|
|
86
|
-
} catch {
|
|
87
|
-
blog("SDK installation failed");
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
try { writeFileSync(marker, version); } catch { /* best-effort */ }
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// ---------------------------------------------------------------------------
|
|
95
|
-
// CLI execution helper
|
|
96
|
-
// ---------------------------------------------------------------------------
|
|
97
|
-
|
|
98
|
-
function runBabysitterHook(hookType, inputJson) {
|
|
99
|
-
const sdkVersion = getSdkVersion();
|
|
100
|
-
const args = [
|
|
101
|
-
"hook:run",
|
|
102
|
-
"--hook-type", hookType,
|
|
103
|
-
"--harness", "opencode",
|
|
104
|
-
"--plugin-root", PLUGIN_ROOT,
|
|
105
|
-
"--state-dir", STATE_DIR,
|
|
106
|
-
"--json",
|
|
107
|
-
];
|
|
108
|
-
|
|
109
|
-
try {
|
|
110
|
-
const result = execSync(`babysitter ${args.join(" ")}`, {
|
|
111
|
-
input: inputJson,
|
|
112
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
113
|
-
timeout: 30000,
|
|
114
|
-
env: { ...process.env, BABYSITTER_STATE_DIR: STATE_DIR },
|
|
115
|
-
});
|
|
116
|
-
return result.toString("utf8").trim();
|
|
117
|
-
} catch (err) {
|
|
118
|
-
// Fall back to npx
|
|
119
|
-
try {
|
|
120
|
-
const result = execSync(`npx -y "@a5c-ai/babysitter-sdk@${sdkVersion}" ${args.join(" ")}`, {
|
|
121
|
-
input: inputJson,
|
|
122
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
123
|
-
timeout: 60000,
|
|
124
|
-
env: { ...process.env, BABYSITTER_STATE_DIR: STATE_DIR },
|
|
125
|
-
});
|
|
126
|
-
return result.toString("utf8").trim();
|
|
127
|
-
} catch (npxErr) {
|
|
128
|
-
blog(`Hook execution failed: ${npxErr.message}`);
|
|
129
|
-
return "{}";
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// ---------------------------------------------------------------------------
|
|
135
|
-
// Main
|
|
136
|
-
// ---------------------------------------------------------------------------
|
|
137
|
-
|
|
138
|
-
function main() {
|
|
139
|
-
blog("session-created hook invoked");
|
|
140
|
-
blog(`PLUGIN_ROOT=${PLUGIN_ROOT}`);
|
|
141
|
-
|
|
142
|
-
// Generate a session ID if OpenCode doesn't provide one
|
|
143
|
-
const sessionId = process.env.OPENCODE_SESSION_ID
|
|
144
|
-
|| process.env.BABYSITTER_SESSION_ID
|
|
145
|
-
|| crypto.randomUUID();
|
|
146
|
-
|
|
147
|
-
// Set env var so downstream hooks can pick it up
|
|
148
|
-
process.env.BABYSITTER_SESSION_ID = sessionId;
|
|
149
|
-
|
|
150
|
-
const sdkVersion = getSdkVersion();
|
|
151
|
-
|
|
152
|
-
// Ensure SDK is installed
|
|
153
|
-
if (!hasBabysitterCli()) {
|
|
154
|
-
blog("SDK CLI not found, attempting install");
|
|
155
|
-
installSdk(sdkVersion);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// Build hook input
|
|
159
|
-
const hookInput = JSON.stringify({
|
|
160
|
-
session_id: sessionId,
|
|
161
|
-
cwd: process.cwd(),
|
|
162
|
-
harness: "opencode",
|
|
163
|
-
plugin_root: PLUGIN_ROOT,
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
blog(`Hook input: ${hookInput}`);
|
|
167
|
-
|
|
168
|
-
// Delegate to SDK hook handler
|
|
169
|
-
const result = runBabysitterHook("session-start", hookInput);
|
|
170
|
-
|
|
171
|
-
blog(`Hook result: ${result}`);
|
|
172
|
-
|
|
173
|
-
// Output result
|
|
174
|
-
try {
|
|
175
|
-
const parsed = JSON.parse(result);
|
|
176
|
-
process.stdout.write(JSON.stringify(parsed) + "\n");
|
|
177
|
-
} catch {
|
|
178
|
-
process.stdout.write("{}\n");
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
main();
|
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();
|