@a5c-ai/babysitter-opencode 0.1.3 → 0.1.4-staging.6342f2b1
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 +49 -3
- package/bin/install-shared.cjs +74 -0
- package/bin/install.cjs +78 -29
- package/commands/doctor.md +9 -9
- package/hooks/session-created.js +2 -1
- package/hooks/session-idle.js +2 -1
- package/hooks/shell-env.js +2 -1
- package/hooks/tool-execute-after.js +2 -1
- package/hooks/tool-execute-before.js +2 -1
- package/package.json +2 -2
- package/skills/accomplish-status/SKILL.md +114 -0
- package/skills/doctor/SKILL.md +9 -9
- package/versions.json +1 -1
package/README.md
CHANGED
|
@@ -25,6 +25,9 @@ plugins/babysitter-opencode/
|
|
|
25
25
|
tool-execute-after.js Post-tool-use hook
|
|
26
26
|
skills/
|
|
27
27
|
babysit/SKILL.md Core orchestration skill
|
|
28
|
+
accomplish-status/SKILL.md Run status reporting for Accomplish
|
|
29
|
+
accomplish-skills/
|
|
30
|
+
babysitter/SKILL.md Bundled skill in Accomplish format
|
|
28
31
|
plugin.json Plugin manifest
|
|
29
32
|
versions.json SDK version tracking
|
|
30
33
|
```
|
|
@@ -36,7 +39,7 @@ plugins/babysitter-opencode/
|
|
|
36
39
|
Install the Babysitter SDK CLI:
|
|
37
40
|
|
|
38
41
|
```bash
|
|
39
|
-
npm install -g @a5c-ai/babysitter
|
|
42
|
+
npm install -g @a5c-ai/babysitter-sdk
|
|
40
43
|
```
|
|
41
44
|
|
|
42
45
|
### Method 1: npm global install (recommended)
|
|
@@ -54,10 +57,10 @@ To install into a specific workspace:
|
|
|
54
57
|
babysitter-opencode install --workspace /path/to/project
|
|
55
58
|
```
|
|
56
59
|
|
|
57
|
-
### Method 2: Babysitter
|
|
60
|
+
### Method 2: Babysitter harness install
|
|
58
61
|
|
|
59
62
|
```bash
|
|
60
|
-
babysitter
|
|
63
|
+
babysitter harness:install-plugin opencode
|
|
61
64
|
```
|
|
62
65
|
|
|
63
66
|
### Method 3: Manual copy
|
|
@@ -83,11 +86,34 @@ Or from a specific workspace:
|
|
|
83
86
|
babysitter-opencode uninstall --workspace /path/to/project
|
|
84
87
|
```
|
|
85
88
|
|
|
89
|
+
### Method 4: Accomplish AI (auto-detected)
|
|
90
|
+
|
|
91
|
+
When [Accomplish](https://github.com/accomplish-ai/accomplish) is installed,
|
|
92
|
+
the installer automatically detects it and copies the plugin into Accomplish's
|
|
93
|
+
OpenCode config directory (`<userDataPath>/opencode/plugins/babysitter/`).
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
# Auto-detects Accomplish during standard install
|
|
97
|
+
npm install -g @a5c-ai/babysitter-opencode
|
|
98
|
+
|
|
99
|
+
# Or target Accomplish explicitly
|
|
100
|
+
babysitter-opencode install --accomplish
|
|
101
|
+
|
|
102
|
+
# Install to both standalone OpenCode and Accomplish
|
|
103
|
+
babysitter-opencode install --global --accomplish
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Accomplish stores OpenCode config at platform-specific locations:
|
|
107
|
+
- **macOS**: `~/Library/Application Support/Accomplish/opencode/`
|
|
108
|
+
- **Windows**: `%APPDATA%/Accomplish/opencode/`
|
|
109
|
+
- **Linux**: `~/.config/Accomplish/opencode/`
|
|
110
|
+
|
|
86
111
|
## CLI Reference
|
|
87
112
|
|
|
88
113
|
```
|
|
89
114
|
babysitter-opencode install [--global] Install plugin globally
|
|
90
115
|
babysitter-opencode install --workspace [path] Install into workspace
|
|
116
|
+
babysitter-opencode install --accomplish Install into Accomplish data dir
|
|
91
117
|
babysitter-opencode uninstall [--global] Uninstall plugin globally
|
|
92
118
|
babysitter-opencode uninstall --workspace [path] Uninstall from workspace
|
|
93
119
|
babysitter-opencode sync Sync command surfaces
|
|
@@ -127,6 +153,24 @@ natively provide them:
|
|
|
127
153
|
- `BABYSITTER_RUNS_DIR` -- Runs directory path
|
|
128
154
|
- `OPENCODE_PLUGIN_ROOT` -- Plugin root directory
|
|
129
155
|
|
|
156
|
+
### Accomplish Integration
|
|
157
|
+
|
|
158
|
+
When running inside [Accomplish](https://github.com/accomplish-ai/accomplish), OpenCode is spawned as a subprocess with
|
|
159
|
+
additional environment variables. The babysitter adapter detects these
|
|
160
|
+
automatically:
|
|
161
|
+
|
|
162
|
+
- `ACCOMPLISH_TASK_ID` -- Accomplish task identifier (primary correlation key)
|
|
163
|
+
- `OPENCODE_CONFIG_DIR` -- Path to Accomplish's OpenCode config directory
|
|
164
|
+
- `OPENCODE_CONFIG` -- Path to the generated `opencode.json`
|
|
165
|
+
|
|
166
|
+
The adapter writes `accomplishTaskId` into session state metadata for
|
|
167
|
+
correlation. The `accomplish-status` skill writes run status JSON to
|
|
168
|
+
`<OPENCODE_CONFIG_DIR>/run-status/<runId>.json` for file-based IPC.
|
|
169
|
+
|
|
170
|
+
Breakpoints are resolved conversationally: when a breakpoint is pending, the
|
|
171
|
+
agent uses Accomplish's `ask-user-question` MCP tool to prompt the user, then
|
|
172
|
+
posts the result via `babysitter task:post`.
|
|
173
|
+
|
|
130
174
|
### Configuration Environment Variables
|
|
131
175
|
|
|
132
176
|
| Variable | Default | Description |
|
|
@@ -137,6 +181,8 @@ natively provide them:
|
|
|
137
181
|
| `BABYSITTER_OPENCODE_MARKETPLACE_PATH` | `~/.agents/plugins/marketplace.json` | Marketplace file |
|
|
138
182
|
| `BABYSITTER_SDK_CLI` | (auto-detected) | Path to SDK CLI entry |
|
|
139
183
|
| `BABYSITTER_GLOBAL_STATE_DIR` | `~/.a5c` | Global state directory |
|
|
184
|
+
| `ACCOMPLISH_TASK_ID` | -- | Set by Accomplish when spawning OpenCode |
|
|
185
|
+
| `OPENCODE_CONFIG_DIR` | -- | Accomplish's OpenCode config directory |
|
|
140
186
|
|
|
141
187
|
## Verification
|
|
142
188
|
|
package/bin/install-shared.cjs
CHANGED
|
@@ -367,6 +367,76 @@ function ensureGlobalProcessLibrary(packageRoot) {
|
|
|
367
367
|
);
|
|
368
368
|
}
|
|
369
369
|
|
|
370
|
+
// ---------------------------------------------------------------------------
|
|
371
|
+
// Accomplish AI detection and paths
|
|
372
|
+
// ---------------------------------------------------------------------------
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Returns the Accomplish user data directory for the current platform.
|
|
376
|
+
* If OPENCODE_CONFIG_DIR is set, returns its parent (the Accomplish data dir).
|
|
377
|
+
* Otherwise falls back to platform-specific defaults.
|
|
378
|
+
*/
|
|
379
|
+
function getAccomplishDataDir() {
|
|
380
|
+
if (process.env.OPENCODE_CONFIG_DIR) {
|
|
381
|
+
return path.resolve(process.env.OPENCODE_CONFIG_DIR, '..');
|
|
382
|
+
}
|
|
383
|
+
const home = getUserHome();
|
|
384
|
+
switch (process.platform) {
|
|
385
|
+
case 'darwin':
|
|
386
|
+
return path.join(home, 'Library', 'Application Support', 'Accomplish');
|
|
387
|
+
case 'win32': {
|
|
388
|
+
const appData = process.env.APPDATA || process.env.LOCALAPPDATA;
|
|
389
|
+
return appData
|
|
390
|
+
? path.join(appData, 'Accomplish')
|
|
391
|
+
: path.join(home, 'AppData', 'Roaming', 'Accomplish');
|
|
392
|
+
}
|
|
393
|
+
default:
|
|
394
|
+
return path.join(home, '.config', 'Accomplish');
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* Returns true if Accomplish AI appears to be installed or is running.
|
|
400
|
+
* Checks for:
|
|
401
|
+
* - ACCOMPLISH_TASK_ID env var (running inside Accomplish)
|
|
402
|
+
* - Accomplish data dir with an opencode/ subdirectory on disk
|
|
403
|
+
*/
|
|
404
|
+
function isAccomplishInstalled() {
|
|
405
|
+
if (process.env.ACCOMPLISH_TASK_ID) return true;
|
|
406
|
+
try {
|
|
407
|
+
const dataDir = getAccomplishDataDir();
|
|
408
|
+
const openCodeDir = path.join(dataDir, 'opencode');
|
|
409
|
+
return fs.existsSync(openCodeDir);
|
|
410
|
+
} catch {
|
|
411
|
+
return false;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* Returns the OpenCode home directory inside the Accomplish data dir.
|
|
417
|
+
*/
|
|
418
|
+
function getAccomplishOpenCodeHome() {
|
|
419
|
+
return path.join(getAccomplishDataDir(), 'opencode');
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Install the babysitter plugin into Accomplish's OpenCode directory.
|
|
424
|
+
* Mirrors the standard OpenCode install: copies bundle, writes index.js,
|
|
425
|
+
* installs skills and hooks.
|
|
426
|
+
*/
|
|
427
|
+
function installAccomplishSurface(packageRoot, accomplishOpenCodeHome) {
|
|
428
|
+
const pluginRoot = path.join(accomplishOpenCodeHome, 'plugins', PLUGIN_NAME);
|
|
429
|
+
|
|
430
|
+
// Copy plugin bundle
|
|
431
|
+
copyPluginBundle(packageRoot, pluginRoot);
|
|
432
|
+
|
|
433
|
+
// Create index.js entry point
|
|
434
|
+
writeIndexJs(pluginRoot);
|
|
435
|
+
|
|
436
|
+
// Install skills and hooks config
|
|
437
|
+
installOpenCodeSurface(packageRoot, accomplishOpenCodeHome);
|
|
438
|
+
}
|
|
439
|
+
|
|
370
440
|
// ---------------------------------------------------------------------------
|
|
371
441
|
// OpenCode surface installation
|
|
372
442
|
// ---------------------------------------------------------------------------
|
|
@@ -395,10 +465,14 @@ module.exports = {
|
|
|
395
465
|
copyRecursive,
|
|
396
466
|
ensureGlobalProcessLibrary,
|
|
397
467
|
ensureMarketplaceEntry,
|
|
468
|
+
getAccomplishDataDir,
|
|
469
|
+
getAccomplishOpenCodeHome,
|
|
398
470
|
getHomeMarketplacePath,
|
|
399
471
|
getHomePluginRoot,
|
|
400
472
|
getOpenCodeHome,
|
|
473
|
+
installAccomplishSurface,
|
|
401
474
|
installOpenCodeSurface,
|
|
475
|
+
isAccomplishInstalled,
|
|
402
476
|
removeManagedHooks,
|
|
403
477
|
removeMarketplaceEntry,
|
|
404
478
|
writeIndexJs,
|
package/bin/install.cjs
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* node install.cjs # Install into cwd workspace
|
|
15
15
|
* node install.cjs --workspace /path # Install into specified workspace
|
|
16
16
|
* node install.cjs --global # Global install (user home)
|
|
17
|
+
* node install.cjs --accomplish # Install only to Accomplish AI data dir
|
|
17
18
|
*/
|
|
18
19
|
|
|
19
20
|
const path = require('path');
|
|
@@ -21,10 +22,13 @@ const {
|
|
|
21
22
|
copyPluginBundle,
|
|
22
23
|
ensureGlobalProcessLibrary,
|
|
23
24
|
ensureMarketplaceEntry,
|
|
25
|
+
getAccomplishOpenCodeHome,
|
|
24
26
|
getHomeMarketplacePath,
|
|
25
27
|
getHomePluginRoot,
|
|
26
28
|
getOpenCodeHome,
|
|
29
|
+
installAccomplishSurface,
|
|
27
30
|
installOpenCodeSurface,
|
|
31
|
+
isAccomplishInstalled,
|
|
28
32
|
writeIndexJs,
|
|
29
33
|
} = require('./install-shared.cjs');
|
|
30
34
|
|
|
@@ -32,6 +36,7 @@ const PACKAGE_ROOT = path.resolve(__dirname, '..');
|
|
|
32
36
|
|
|
33
37
|
function parseArgs(argv) {
|
|
34
38
|
let workspace = process.env.OPENCODE_WORKSPACE || process.cwd();
|
|
39
|
+
let accomplish = false;
|
|
35
40
|
for (let i = 2; i < argv.length; i += 1) {
|
|
36
41
|
const arg = argv[i];
|
|
37
42
|
if (arg === '--workspace') {
|
|
@@ -43,47 +48,91 @@ function parseArgs(argv) {
|
|
|
43
48
|
workspace = null;
|
|
44
49
|
continue;
|
|
45
50
|
}
|
|
51
|
+
if (arg === '--accomplish') {
|
|
52
|
+
accomplish = true;
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
46
55
|
throw new Error(`unknown argument: ${arg}`);
|
|
47
56
|
}
|
|
48
|
-
return { workspace };
|
|
57
|
+
return { workspace, accomplish };
|
|
49
58
|
}
|
|
50
59
|
|
|
51
|
-
function
|
|
52
|
-
const { workspace } = parseArgs(process.argv);
|
|
60
|
+
function installStandardOpenCode(workspace) {
|
|
53
61
|
const openCodeHome = getOpenCodeHome(workspace);
|
|
54
62
|
const pluginRoot = getHomePluginRoot(workspace);
|
|
55
63
|
const marketplacePath = getHomeMarketplacePath(workspace);
|
|
56
64
|
|
|
57
65
|
console.log(`[babysitter] Installing OpenCode plugin to ${pluginRoot}`);
|
|
58
66
|
|
|
67
|
+
// 1. Copy plugin bundle
|
|
68
|
+
copyPluginBundle(PACKAGE_ROOT, pluginRoot);
|
|
69
|
+
console.log('[babysitter] Copied plugin bundle');
|
|
70
|
+
|
|
71
|
+
// 2. Write index.js entry point for OpenCode plugin discovery
|
|
72
|
+
writeIndexJs(pluginRoot);
|
|
73
|
+
console.log('[babysitter] Created index.js entry point');
|
|
74
|
+
|
|
75
|
+
// 3. Register in marketplace
|
|
76
|
+
ensureMarketplaceEntry(marketplacePath, pluginRoot);
|
|
77
|
+
console.log(`[babysitter] Marketplace: ${marketplacePath}`);
|
|
78
|
+
|
|
79
|
+
// 4. Install OpenCode surfaces (skills, hooks config)
|
|
80
|
+
installOpenCodeSurface(PACKAGE_ROOT, openCodeHome);
|
|
81
|
+
console.log('[babysitter] Installed hooks and skills');
|
|
82
|
+
|
|
83
|
+
// 5. Bootstrap global process library
|
|
84
|
+
try {
|
|
85
|
+
const active = ensureGlobalProcessLibrary(PACKAGE_ROOT);
|
|
86
|
+
console.log(`[babysitter] Process library: ${active.binding?.dir || '(default)'}`);
|
|
87
|
+
if (active.defaultSpec?.cloneDir) {
|
|
88
|
+
console.log(`[babysitter] Process library clone: ${active.defaultSpec.cloneDir}`);
|
|
89
|
+
}
|
|
90
|
+
console.log(`[babysitter] Process library state: ${active.stateFile}`);
|
|
91
|
+
} catch (err) {
|
|
92
|
+
console.warn(`[babysitter] Warning: Could not bootstrap process library: ${err.message}`);
|
|
93
|
+
console.warn('[babysitter] Run "babysitter process-library:clone" manually if needed.');
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function installToAccomplish() {
|
|
98
|
+
const accomplishHome = getAccomplishOpenCodeHome();
|
|
99
|
+
console.log(`[babysitter] Installing plugin to Accomplish AI: ${accomplishHome}`);
|
|
100
|
+
|
|
101
|
+
installAccomplishSurface(PACKAGE_ROOT, accomplishHome);
|
|
102
|
+
|
|
103
|
+
console.log('[babysitter] Copied plugin bundle to Accomplish');
|
|
104
|
+
console.log('[babysitter] Created index.js entry point for Accomplish');
|
|
105
|
+
console.log('[babysitter] Installed hooks and skills for Accomplish');
|
|
106
|
+
console.log('[babysitter] Accomplish AI installation complete.');
|
|
107
|
+
console.log('[babysitter] Restart Accomplish to pick up the installed plugin.');
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function main() {
|
|
111
|
+
const { workspace, accomplish } = parseArgs(process.argv);
|
|
112
|
+
|
|
59
113
|
try {
|
|
60
|
-
//
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
const active = ensureGlobalProcessLibrary(PACKAGE_ROOT);
|
|
79
|
-
console.log(`[babysitter] Process library: ${active.binding?.dir || '(default)'}`);
|
|
80
|
-
if (active.defaultSpec?.cloneDir) {
|
|
81
|
-
console.log(`[babysitter] Process library clone: ${active.defaultSpec.cloneDir}`);
|
|
114
|
+
// If --accomplish is used without --global/--workspace, install only to Accomplish
|
|
115
|
+
if (accomplish && workspace !== null) {
|
|
116
|
+
installToAccomplish();
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Standard OpenCode install
|
|
121
|
+
installStandardOpenCode(workspace);
|
|
122
|
+
|
|
123
|
+
// Auto-detect Accomplish and install there too (unless --accomplish was explicit)
|
|
124
|
+
if (!accomplish) {
|
|
125
|
+
try {
|
|
126
|
+
if (isAccomplishInstalled()) {
|
|
127
|
+
console.log('[babysitter] Detected Accomplish AI installation.');
|
|
128
|
+
installToAccomplish();
|
|
129
|
+
}
|
|
130
|
+
} catch (err) {
|
|
131
|
+
console.warn(`[babysitter] Warning: Accomplish AI detection failed: ${err.message}`);
|
|
82
132
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
console.warn('[babysitter] Run "babysitter process-library:clone" manually if needed.');
|
|
133
|
+
} else {
|
|
134
|
+
// --accomplish combined with --global: install to both
|
|
135
|
+
installToAccomplish();
|
|
87
136
|
}
|
|
88
137
|
|
|
89
138
|
console.log('[babysitter] Installation complete!');
|
package/commands/doctor.md
CHANGED
|
@@ -177,13 +177,13 @@ Mark as PASS if no issues. Mark as WARN if runaway loops or stale sessions detec
|
|
|
177
177
|
**Goal:** Analyze babysitter log files for errors, warnings, and stop hook decisions.
|
|
178
178
|
|
|
179
179
|
Read the last 50 lines of each of these log files (if they exist):
|
|
180
|
-
- `$
|
|
181
|
-
- `$
|
|
182
|
-
- `$
|
|
183
|
-
- `$
|
|
184
|
-
- `$
|
|
185
|
-
- `$
|
|
186
|
-
- `$HOME/.a5c/logs/` and relevant
|
|
180
|
+
- `${BABYSITTER_LOG_DIR:-$HOME/.a5c/logs}/hooks.log`
|
|
181
|
+
- `${BABYSITTER_LOG_DIR:-$HOME/.a5c/logs}/babysitter-stop-hook.log`
|
|
182
|
+
- `${BABYSITTER_LOG_DIR:-$HOME/.a5c/logs}/babysitter-stop-hook-stderr.log`
|
|
183
|
+
- `${BABYSITTER_LOG_DIR:-$HOME/.a5c/logs}/babysitter-session-start-hook.log`
|
|
184
|
+
- `${BABYSITTER_LOG_DIR:-$HOME/.a5c/logs}/babysitter-session-start-hook-stderr.log`
|
|
185
|
+
- `${BABYSITTER_LOG_DIR:-$HOME/.a5c/logs}/babysitter.log`
|
|
186
|
+
- `${BABYSITTER_LOG_DIR:-$HOME/.a5c/logs}/` and relevant run/session specific logs there
|
|
187
187
|
|
|
188
188
|
|
|
189
189
|
For each log file:
|
|
@@ -285,7 +285,7 @@ The hooks delegate to the `babysitter` CLI. Check if it is available:
|
|
|
285
285
|
Check whether the stop hook has actually been invoked during this run's lifetime:
|
|
286
286
|
|
|
287
287
|
**From log files:**
|
|
288
|
-
- Read `$
|
|
288
|
+
- Read `${BABYSITTER_LOG_DIR:-$HOME/.a5c/logs}/babysitter-stop-hook.log` (if it exists).
|
|
289
289
|
- Count the number of "Hook script invoked" lines. This is the total invocation count.
|
|
290
290
|
- Count the number of "CLI exit code=" lines and extract exit codes.
|
|
291
291
|
- If the log file does not exist or has zero invocations, the stop hook has NOT been running.
|
|
@@ -297,7 +297,7 @@ Check whether the stop hook has actually been invoked during this run's lifetime
|
|
|
297
297
|
- If no STOP_HOOK_INVOKED events exist in the journal, note that the stop hook has not recorded any decisions for this run.
|
|
298
298
|
|
|
299
299
|
**From stderr:**
|
|
300
|
-
- Read `$
|
|
300
|
+
- Read `${BABYSITTER_LOG_DIR:-$HOME/.a5c/logs}/babysitter-stop-hook-stderr.log`.
|
|
301
301
|
- If it contains error output, display it and diagnose:
|
|
302
302
|
- "command not found" or exit code 127 → CLI not installed (see 10c)
|
|
303
303
|
- "MODULE_NOT_FOUND" or "Cannot find module" → SDK package corrupted or not built
|
package/hooks/session-created.js
CHANGED
|
@@ -16,12 +16,13 @@
|
|
|
16
16
|
|
|
17
17
|
const { execSync, execFileSync } = require("child_process");
|
|
18
18
|
const { readFileSync, mkdirSync, appendFileSync, existsSync, writeFileSync } = require("fs");
|
|
19
|
+
const os = require("os");
|
|
19
20
|
const path = require("path");
|
|
20
21
|
const crypto = require("crypto");
|
|
21
22
|
|
|
22
23
|
const PLUGIN_ROOT = process.env.OPENCODE_PLUGIN_ROOT || path.resolve(__dirname, "..");
|
|
23
24
|
const STATE_DIR = process.env.BABYSITTER_STATE_DIR || path.join(process.cwd(), ".a5c");
|
|
24
|
-
const LOG_DIR = process.env.BABYSITTER_LOG_DIR || path.join(
|
|
25
|
+
const LOG_DIR = process.env.BABYSITTER_LOG_DIR || path.join(os.homedir(), ".a5c", "logs");
|
|
25
26
|
const LOG_FILE = path.join(LOG_DIR, "babysitter-session-created-hook.log");
|
|
26
27
|
|
|
27
28
|
// ---------------------------------------------------------------------------
|
package/hooks/session-idle.js
CHANGED
|
@@ -20,11 +20,12 @@
|
|
|
20
20
|
|
|
21
21
|
const { execSync } = require("child_process");
|
|
22
22
|
const { readFileSync, mkdirSync, appendFileSync } = require("fs");
|
|
23
|
+
const os = require("os");
|
|
23
24
|
const path = require("path");
|
|
24
25
|
|
|
25
26
|
const PLUGIN_ROOT = process.env.OPENCODE_PLUGIN_ROOT || path.resolve(__dirname, "..");
|
|
26
27
|
const STATE_DIR = process.env.BABYSITTER_STATE_DIR || path.join(process.cwd(), ".a5c");
|
|
27
|
-
const LOG_DIR = process.env.BABYSITTER_LOG_DIR || path.join(
|
|
28
|
+
const LOG_DIR = process.env.BABYSITTER_LOG_DIR || path.join(os.homedir(), ".a5c", "logs");
|
|
28
29
|
const LOG_FILE = path.join(LOG_DIR, "babysitter-session-idle-hook.log");
|
|
29
30
|
|
|
30
31
|
function ensureDir(dir) {
|
package/hooks/shell-env.js
CHANGED
|
@@ -18,13 +18,14 @@
|
|
|
18
18
|
"use strict";
|
|
19
19
|
|
|
20
20
|
const { readFileSync, mkdirSync, appendFileSync, existsSync } = require("fs");
|
|
21
|
+
const os = require("os");
|
|
21
22
|
const path = require("path");
|
|
22
23
|
const crypto = require("crypto");
|
|
23
24
|
|
|
24
25
|
const PLUGIN_ROOT = process.env.OPENCODE_PLUGIN_ROOT || path.resolve(__dirname, "..");
|
|
25
26
|
const STATE_DIR = process.env.BABYSITTER_STATE_DIR || path.join(process.cwd(), ".a5c");
|
|
26
27
|
const RUNS_DIR = process.env.BABYSITTER_RUNS_DIR || path.join(STATE_DIR, "runs");
|
|
27
|
-
const LOG_DIR = process.env.BABYSITTER_LOG_DIR || path.join(
|
|
28
|
+
const LOG_DIR = process.env.BABYSITTER_LOG_DIR || path.join(os.homedir(), ".a5c", "logs");
|
|
28
29
|
const LOG_FILE = path.join(LOG_DIR, "babysitter-shell-env-hook.log");
|
|
29
30
|
|
|
30
31
|
function ensureDir(dir) {
|
|
@@ -20,11 +20,12 @@
|
|
|
20
20
|
|
|
21
21
|
const { execSync } = require("child_process");
|
|
22
22
|
const { readFileSync, mkdirSync, appendFileSync } = require("fs");
|
|
23
|
+
const os = require("os");
|
|
23
24
|
const path = require("path");
|
|
24
25
|
|
|
25
26
|
const PLUGIN_ROOT = process.env.OPENCODE_PLUGIN_ROOT || path.resolve(__dirname, "..");
|
|
26
27
|
const STATE_DIR = process.env.BABYSITTER_STATE_DIR || path.join(process.cwd(), ".a5c");
|
|
27
|
-
const LOG_DIR = process.env.BABYSITTER_LOG_DIR || path.join(
|
|
28
|
+
const LOG_DIR = process.env.BABYSITTER_LOG_DIR || path.join(os.homedir(), ".a5c", "logs");
|
|
28
29
|
const LOG_FILE = path.join(LOG_DIR, "babysitter-tool-after-hook.log");
|
|
29
30
|
|
|
30
31
|
function ensureDir(dir) {
|
|
@@ -20,11 +20,12 @@
|
|
|
20
20
|
|
|
21
21
|
const { execSync } = require("child_process");
|
|
22
22
|
const { readFileSync, mkdirSync, appendFileSync } = require("fs");
|
|
23
|
+
const os = require("os");
|
|
23
24
|
const path = require("path");
|
|
24
25
|
|
|
25
26
|
const PLUGIN_ROOT = process.env.OPENCODE_PLUGIN_ROOT || path.resolve(__dirname, "..");
|
|
26
27
|
const STATE_DIR = process.env.BABYSITTER_STATE_DIR || path.join(process.cwd(), ".a5c");
|
|
27
|
-
const LOG_DIR = process.env.BABYSITTER_LOG_DIR || path.join(
|
|
28
|
+
const LOG_DIR = process.env.BABYSITTER_LOG_DIR || path.join(os.homedir(), ".a5c", "logs");
|
|
28
29
|
const LOG_FILE = path.join(LOG_DIR, "babysitter-tool-before-hook.log");
|
|
29
30
|
|
|
30
31
|
function ensureDir(dir) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@a5c-ai/babysitter-opencode",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4-staging.6342f2b1",
|
|
4
4
|
"description": "Babysitter orchestration plugin for OpenCode with SDK-managed process-library bootstrapping and in-turn iteration model",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "node test/integration.test.js",
|
|
@@ -41,6 +41,6 @@
|
|
|
41
41
|
},
|
|
42
42
|
"homepage": "https://github.com/a5c-ai/babysitter/tree/main/plugins/babysitter-opencode#readme",
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@a5c-ai/babysitter-sdk": "0.0.
|
|
44
|
+
"@a5c-ai/babysitter-sdk": "0.0.188-staging.6342f2b1"
|
|
45
45
|
}
|
|
46
46
|
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: accomplish-status
|
|
3
|
+
description: Report babysitter orchestration run status to Accomplish AI desktop app via file-based IPC
|
|
4
|
+
command: /accomplish-status
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# accomplish-status
|
|
8
|
+
|
|
9
|
+
Report babysitter run status to the [Accomplish AI](https://github.com/accomplish-ai/accomplish) desktop app via file-based IPC.
|
|
10
|
+
|
|
11
|
+
## Overview
|
|
12
|
+
|
|
13
|
+
This skill writes run status JSON to a well-known directory. External consumers (such as a future Accomplish daemon integration or other tooling) can watch this directory for changes to track orchestration progress, pending breakpoints, and completion state.
|
|
14
|
+
|
|
15
|
+
## Status File Location
|
|
16
|
+
|
|
17
|
+
Status files are written to:
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
<OPENCODE_CONFIG_DIR>/run-status/<runId>.json
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Where `OPENCODE_CONFIG_DIR` is resolved from the `OPENCODE_CONFIG_DIR` environment variable (typically `~/.config/opencode` or platform equivalent).
|
|
24
|
+
|
|
25
|
+
## Dependencies
|
|
26
|
+
|
|
27
|
+
### Babysitter SDK and CLI
|
|
28
|
+
|
|
29
|
+
Read the SDK version from `versions.json` to ensure version compatibility:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
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')}")
|
|
33
|
+
CLI="npx -y @a5c-ai/babysitter-sdk@$SDK_VERSION"
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Instructions
|
|
37
|
+
|
|
38
|
+
### 1. Resolve the status directory
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
STATUS_DIR="${OPENCODE_CONFIG_DIR:-$HOME/.config/opencode}/run-status"
|
|
42
|
+
mkdir -p "$STATUS_DIR"
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### 2. Get run status from babysitter
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
babysitter run:status .a5c/runs/<runId> --json
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### 3. Write the status file
|
|
52
|
+
|
|
53
|
+
Transform the run status output into the Accomplish status format and write it to `$STATUS_DIR/<runId>.json`.
|
|
54
|
+
|
|
55
|
+
Use the `ACCOMPLISH_TASK_ID` environment variable to correlate the babysitter run with the originating Accomplish task. This variable is set automatically by Accomplish when it spawns the agent session.
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
ACCOMPLISH_TASK_ID="${ACCOMPLISH_TASK_ID:-}"
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### 4. Status file format
|
|
62
|
+
|
|
63
|
+
Write the following JSON structure to `$STATUS_DIR/<runId>.json`:
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"runId": "abc123-def456",
|
|
68
|
+
"processId": "my-process",
|
|
69
|
+
"status": "running",
|
|
70
|
+
"currentPhase": "execute",
|
|
71
|
+
"phases": [
|
|
72
|
+
{ "name": "plan", "status": "completed" },
|
|
73
|
+
{ "name": "execute", "status": "running" },
|
|
74
|
+
{ "name": "verify", "status": "pending" }
|
|
75
|
+
],
|
|
76
|
+
"pendingEffects": [
|
|
77
|
+
{
|
|
78
|
+
"effectId": "eff-001",
|
|
79
|
+
"kind": "breakpoint",
|
|
80
|
+
"title": "Approve implementation plan"
|
|
81
|
+
}
|
|
82
|
+
],
|
|
83
|
+
"accomplishTaskId": "accomplish-task-789",
|
|
84
|
+
"lastUpdatedAt": "2026-04-04T12:00:00.000Z"
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
#### Field reference
|
|
89
|
+
|
|
90
|
+
| Field | Type | Description |
|
|
91
|
+
|-------|------|-------------|
|
|
92
|
+
| `runId` | string | Babysitter run identifier |
|
|
93
|
+
| `processId` | string | Process definition identifier |
|
|
94
|
+
| `status` | enum | One of: `created`, `running`, `waiting`, `completed`, `failed` |
|
|
95
|
+
| `currentPhase` | string | Name of the currently active phase |
|
|
96
|
+
| `phases` | array | Ordered list of phases with individual status (`pending`, `running`, `completed`, `failed`) |
|
|
97
|
+
| `pendingEffects` | array | Currently pending effects (tasks, breakpoints, sleeps) awaiting resolution |
|
|
98
|
+
| `accomplishTaskId` | string | Correlation ID from `ACCOMPLISH_TASK_ID` env var; links this run to the Accomplish UI task |
|
|
99
|
+
| `lastUpdatedAt` | string | ISO 8601 timestamp of the last status update |
|
|
100
|
+
|
|
101
|
+
### 5. When to update
|
|
102
|
+
|
|
103
|
+
Write or update the status file:
|
|
104
|
+
|
|
105
|
+
- Immediately after `babysitter run:create` (status: `created`)
|
|
106
|
+
- After each `babysitter run:iterate` call (status: `running` or `waiting`)
|
|
107
|
+
- When breakpoints are requested (status: `waiting`, include breakpoint in `pendingEffects`)
|
|
108
|
+
- After `babysitter task:post` resolves an effect (status: `running`)
|
|
109
|
+
- On run completion (status: `completed`)
|
|
110
|
+
- On run failure (status: `failed`)
|
|
111
|
+
|
|
112
|
+
### 6. Cleanup
|
|
113
|
+
|
|
114
|
+
When a run reaches a terminal state (`completed` or `failed`), the status file may be left in place for external consumers to read the final state. Stale status files can be cleaned up manually or by external tooling.
|
package/skills/doctor/SKILL.md
CHANGED
|
@@ -178,13 +178,13 @@ Mark as PASS if no issues. Mark as WARN if runaway loops or stale sessions detec
|
|
|
178
178
|
**Goal:** Analyze babysitter log files for errors, warnings, and stop hook decisions.
|
|
179
179
|
|
|
180
180
|
Read the last 50 lines of each of these log files (if they exist):
|
|
181
|
-
- `$
|
|
182
|
-
- `$
|
|
183
|
-
- `$
|
|
184
|
-
- `$
|
|
185
|
-
- `$
|
|
186
|
-
- `$
|
|
187
|
-
- `$HOME/.a5c/logs/` and relevant
|
|
181
|
+
- `${BABYSITTER_LOG_DIR:-$HOME/.a5c/logs}/hooks.log`
|
|
182
|
+
- `${BABYSITTER_LOG_DIR:-$HOME/.a5c/logs}/babysitter-stop-hook.log`
|
|
183
|
+
- `${BABYSITTER_LOG_DIR:-$HOME/.a5c/logs}/babysitter-stop-hook-stderr.log`
|
|
184
|
+
- `${BABYSITTER_LOG_DIR:-$HOME/.a5c/logs}/babysitter-session-start-hook.log`
|
|
185
|
+
- `${BABYSITTER_LOG_DIR:-$HOME/.a5c/logs}/babysitter-session-start-hook-stderr.log`
|
|
186
|
+
- `${BABYSITTER_LOG_DIR:-$HOME/.a5c/logs}/babysitter.log`
|
|
187
|
+
- `${BABYSITTER_LOG_DIR:-$HOME/.a5c/logs}/` and relevant run/session specific logs there
|
|
188
188
|
|
|
189
189
|
|
|
190
190
|
For each log file:
|
|
@@ -286,7 +286,7 @@ The hooks delegate to the `babysitter` CLI. Check if it is available:
|
|
|
286
286
|
Check whether the stop hook has actually been invoked during this run's lifetime:
|
|
287
287
|
|
|
288
288
|
**From log files:**
|
|
289
|
-
- Read `$
|
|
289
|
+
- Read `${BABYSITTER_LOG_DIR:-$HOME/.a5c/logs}/babysitter-stop-hook.log` (if it exists).
|
|
290
290
|
- Count the number of "Hook script invoked" lines. This is the total invocation count.
|
|
291
291
|
- Count the number of "CLI exit code=" lines and extract exit codes.
|
|
292
292
|
- If the log file does not exist or has zero invocations, the stop hook has NOT been running.
|
|
@@ -298,7 +298,7 @@ Check whether the stop hook has actually been invoked during this run's lifetime
|
|
|
298
298
|
- If no STOP_HOOK_INVOKED events exist in the journal, note that the stop hook has not recorded any decisions for this run.
|
|
299
299
|
|
|
300
300
|
**From stderr:**
|
|
301
|
-
- Read `$
|
|
301
|
+
- Read `${BABYSITTER_LOG_DIR:-$HOME/.a5c/logs}/babysitter-stop-hook-stderr.log`.
|
|
302
302
|
- If it contains error output, display it and diagnose:
|
|
303
303
|
- "command not found" or exit code 127 → CLI not installed (see 10c)
|
|
304
304
|
- "MODULE_NOT_FOUND" or "Cannot find module" → SDK package corrupted or not built
|
package/versions.json
CHANGED