@a5c-ai/babysitter-breakpoints 0.0.27

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.
@@ -0,0 +1,35 @@
1
+ ---
2
+ name: babysitter-breakpoint
3
+ description: Use the breakpoint API to communicate with users during babysitter runs (post breakpoints, poll for release, fetch feedback, and read context files). Trigger whenever a babysitter workflow needs approval, input, or status updates via breakpoints.
4
+ ---
5
+
6
+ # babysitter-breakpoint
7
+
8
+ Use this skill to handle all user communication via the `breakpoints` CLI. Do
9
+ not prompt the user directly. Always post a breakpoint and poll until it is
10
+ released, then fetch feedback and continue.
11
+
12
+ ## Workflow
13
+
14
+ 1. Create a breakpoint with the required payload and `payload.context.files`.
15
+ 2. Poll `breakpoints breakpoint wait <id> --interval 3` until `released`.
16
+ 3. Apply feedback from the printed details and continue.
17
+
18
+ ## Payload structure
19
+
20
+ Always include a `context.files` array for referenced files:
21
+
22
+ ```json
23
+ {
24
+ "context": {
25
+ "runId": "run-...",
26
+ "files": [
27
+ { "path": ".a5c/runs/<runId>/artifacts/process.md", "format": "markdown" },
28
+ { "path": ".a5c/runs/<runId>/inputs.json", "format": "code", "language": "json" },
29
+ { "path": ".a5c/runs/<runId>/code/main.js", "format": "code", "language": "javascript" }
30
+ ]
31
+ }
32
+ }
33
+ ```
34
+
35
+ See `references/breakpoint-api.md` for curl examples and endpoints.
@@ -0,0 +1,57 @@
1
+ # Breakpoint CLI + API
2
+
3
+ Use the `breakpoints` CLI to communicate with the user. The CLI wraps the local
4
+ API. Never prompt directly.
5
+
6
+ ## Base URL
7
+ - Default: `http://localhost:3000`
8
+ - Override with `BREAKPOINT_API_URL` if set.
9
+
10
+ ## Auth
11
+ - Agent token: `AGENT_TOKEN`
12
+ - Human token: `HUMAN_TOKEN`
13
+ - Use `Authorization: Bearer <token>` when set.
14
+
15
+ ## Create a breakpoint (agent)
16
+ ```bash
17
+ breakpoints breakpoint create \
18
+ --question "Approve process + inputs + main.js?" \
19
+ --run-id run-... \
20
+ --title "Approval needed" \
21
+ --file ".a5c/runs/<runId>/artifacts/process.md,markdown" \
22
+ --file ".a5c/runs/<runId>/inputs.json,code,json" \
23
+ --file ".a5c/runs/<runId>/code/main.js,code,javascript"
24
+ ```
25
+
26
+ ## Poll for status
27
+ ```bash
28
+ breakpoints breakpoint status <id>
29
+ ```
30
+
31
+ ## Fetch full details (including feedback)
32
+ ```bash
33
+ breakpoints breakpoint show <id>
34
+ ```
35
+
36
+ ## Wait for release (prints details)
37
+ ```bash
38
+ breakpoints breakpoint wait <id> --interval 3
39
+ ```
40
+
41
+ ## Fetch context file content (API)
42
+ ```bash
43
+ curl -s "$BREAKPOINT_API_URL/api/breakpoints/<id>/context?path=path/to/file"
44
+ ```
45
+
46
+ ## Release with feedback (human)
47
+ ```bash
48
+ curl -s -X POST "$BREAKPOINT_API_URL/api/breakpoints/<id>/feedback" \
49
+ -H "Content-Type: application/json" \
50
+ -H "Authorization: Bearer $HUMAN_TOKEN" \
51
+ -d '{"author":"reviewer","comment":"approved","release":true}'
52
+ ```
53
+
54
+ ## Notes
55
+ - Poll every 2-10 seconds.
56
+ - Continue orchestration only after `status` becomes `released` and feedback is retrieved.
57
+ - Context files must be listed in the breakpoint payload and use allowlisted extensions.
package/README.md ADDED
@@ -0,0 +1,154 @@
1
+ # Breakpoint Manager
2
+
3
+ Lightweight breakpoint manager with API, queue worker, and web UI.
4
+
5
+ This package now lives at `packages/breakpoints`.
6
+
7
+ ## Requirements
8
+ - Node.js 18+
9
+
10
+ ## Setup
11
+ ```bash
12
+ cd packages/breakpoints
13
+ npm install
14
+ npm run init:db
15
+ ```
16
+
17
+ ## Run (dev)
18
+ ```bash
19
+ cd packages/breakpoints
20
+ npm run dev
21
+ ```
22
+
23
+ ## Run (installed CLI)
24
+ ```bash
25
+ breakpoints start
26
+ ```
27
+
28
+ Or run separately:
29
+ ```bash
30
+ npm run start:api
31
+ npm run start:worker
32
+ ```
33
+
34
+ ## CLI Examples
35
+ Start the full system (API + web UI + worker):
36
+ ```bash
37
+ breakpoints start
38
+ ```
39
+
40
+ Create a breakpoint (agent):
41
+ ```bash
42
+ breakpoints breakpoint create --question "Need approval?" --title "Approval"
43
+ ```
44
+
45
+ Check status:
46
+ ```bash
47
+ breakpoints breakpoint status <id>
48
+ ```
49
+
50
+ Wait for release:
51
+ ```bash
52
+ breakpoints breakpoint wait <id> --interval 3
53
+ ```
54
+
55
+ Install the babysitter-breakpoint skill:
56
+ ```bash
57
+ breakpoints install-skill --target codex --scope global
58
+ ```
59
+
60
+ ## Configuration
61
+ Environment variables:
62
+ - `PORT` (default 3185)
63
+ - `WEB_PORT` (default 3184)
64
+ - `DB_PATH` (default `~/.a5c/breakpoints/db/breakpoints.db`)
65
+ - `REPO_ROOT` (default package root / current working directory)
66
+ - `AGENT_TOKEN` (optional)
67
+ - `HUMAN_TOKEN` (optional)
68
+ - `WORKER_POLL_MS` (default 2000)
69
+ - `WORKER_BATCH_SIZE` (default 10)
70
+
71
+ ## API Examples
72
+ Create breakpoint (agent):
73
+ ```bash
74
+ curl -X POST http://localhost:3185/api/breakpoints \
75
+ -H "Content-Type: application/json" \
76
+ -H "Authorization: Bearer $AGENT_TOKEN" \
77
+ -d '{"agentId":"agent-1","title":"Need review","payload":{"summary":"check this"},"tags":["review"],"ttlSeconds":3600}'
78
+ ```
79
+
80
+ Check status:
81
+ ```bash
82
+ curl http://localhost:3185/api/breakpoints/<id>/status
83
+ ```
84
+
85
+ Release with feedback (human):
86
+ ```bash
87
+ curl -X POST http://localhost:3185/api/breakpoints/<id>/feedback \
88
+ -H "Content-Type: application/json" \
89
+ -H "Authorization: Bearer $HUMAN_TOKEN" \
90
+ -d '{"author":"reviewer","comment":"Looks good","release":true}'
91
+ ```
92
+
93
+ ## Breakpoint Context Payload
94
+ To enable context rendering in the UI, include a `context.files` array in the
95
+ breakpoint payload:
96
+ ```json
97
+ {
98
+ "context": {
99
+ "runId": "run-...",
100
+ "files": [
101
+ { "path": "docs/plan.md", "format": "markdown" },
102
+ { "path": "api/routes.js", "format": "code", "language": "javascript" }
103
+ ]
104
+ }
105
+ }
106
+ ```
107
+
108
+ The API serves file content via:
109
+ ```
110
+ GET /api/breakpoints/:id/context?path=path/to/file
111
+ ```
112
+ Only allowlisted extensions are served, and the file must be listed in the
113
+ breakpoint payload.
114
+
115
+ ## Web UI
116
+ Open `http://localhost:3184` and provide the human token in the UI.
117
+
118
+ ## Install the babysitter-breakpoint skill
119
+ ```bash
120
+ breakpoints install-skill
121
+ ```
122
+ Defaults to global Codex install. Options:
123
+ ```bash
124
+ breakpoints install-skill --target codex --scope global
125
+ breakpoints install-skill --target codex --scope local
126
+ breakpoints install-skill --target claude --scope global
127
+ breakpoints install-skill --target claude --scope local
128
+ breakpoints install-skill --target cursor --scope global
129
+ breakpoints install-skill --target cursor --scope local
130
+ ```
131
+ Global targets use `CODEX_HOME` or `~/.codex` for Codex, and `~/.claude` or `~/.cursor` for Claude/Cursor. Local installs write to `.codex/skills`, `.claude/skills`, or `.cursor/skills` under the package root. Restart the app after install.
132
+
133
+ When installed from npm, the skill is bundled at `.codex/skills/babysitter-breakpoint/` inside the package and copied to the target location by `breakpoints install-skill`.
134
+
135
+ ## Breakpoint CLI (agent-friendly)
136
+ Create a breakpoint:
137
+ ```bash
138
+ breakpoints breakpoint create \
139
+ --question "Approve process + inputs + main.js?" \
140
+ --run-id run-123 \
141
+ --title "Approval needed" \
142
+ --file ".a5c/runs/run-123/artifacts/process.md,markdown" \
143
+ --file ".a5c/runs/run-123/inputs.json,code,json" \
144
+ --file ".a5c/runs/run-123/code/main.js,code,javascript"
145
+ ```
146
+
147
+ Wait for release (prints full details when released):
148
+ ```bash
149
+ breakpoints breakpoint wait <id> --interval 3
150
+ ```
151
+
152
+ ## Notes
153
+ - Tags are stored as JSON in SQLite; tag filtering uses a simple string match.
154
+ - The queue worker processes TTL expiration jobs; notification jobs are stubbed.
package/api/db.js ADDED
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+
3
+ const fs = require("fs");
4
+ const path = require("path");
5
+ const os = require("os");
6
+ const sqlite3 = require("sqlite3");
7
+
8
+ function defaultDbPath() {
9
+ const home = os.homedir();
10
+ return path.join(home, ".a5c", "breakpoints", "db", "breakpoints.db");
11
+ }
12
+
13
+ function expandHome(value) {
14
+ if (!value) return value;
15
+ if (value === "~") return os.homedir();
16
+ if (value.startsWith(`~${path.sep}`)) {
17
+ return path.join(os.homedir(), value.slice(2));
18
+ }
19
+ if (value.startsWith("~/")) {
20
+ return path.join(os.homedir(), value.slice(2));
21
+ }
22
+ return value;
23
+ }
24
+
25
+ function resolveDbPath(value) {
26
+ const expanded = expandHome(value);
27
+ if (!expanded) return expanded;
28
+ const normalized = path.normalize(expanded);
29
+ if (normalized.endsWith(path.sep)) {
30
+ return path.join(normalized, "breakpoints.db");
31
+ }
32
+ if (!path.extname(normalized)) {
33
+ return path.join(normalized, "breakpoints.db");
34
+ }
35
+ return normalized;
36
+ }
37
+
38
+ const DB_PATH = resolveDbPath(process.env.DB_PATH || defaultDbPath());
39
+
40
+ function openDb() {
41
+ fs.mkdirSync(path.dirname(DB_PATH), { recursive: true });
42
+ return new sqlite3.Database(DB_PATH);
43
+ }
44
+
45
+ function run(db, sql, params = []) {
46
+ return new Promise((resolve, reject) => {
47
+ db.run(sql, params, function onRun(err) {
48
+ if (err) return reject(err);
49
+ resolve(this);
50
+ });
51
+ });
52
+ }
53
+
54
+ function get(db, sql, params = []) {
55
+ return new Promise((resolve, reject) => {
56
+ db.get(sql, params, (err, row) => {
57
+ if (err) return reject(err);
58
+ resolve(row);
59
+ });
60
+ });
61
+ }
62
+
63
+ function all(db, sql, params = []) {
64
+ return new Promise((resolve, reject) => {
65
+ db.all(sql, params, (err, rows) => {
66
+ if (err) return reject(err);
67
+ resolve(rows);
68
+ });
69
+ });
70
+ }
71
+
72
+ async function initDb(db) {
73
+ const schemaPath = path.join(__dirname, "..", "db", "schema.sql");
74
+ const schema = fs.readFileSync(schemaPath, "utf8");
75
+ fs.mkdirSync(path.dirname(DB_PATH), { recursive: true });
76
+ await run(db, "PRAGMA foreign_keys = ON;");
77
+ const statements = schema
78
+ .split(";")
79
+ .map((statement) => statement.trim())
80
+ .filter((statement) => statement.length);
81
+ for (const statement of statements) {
82
+ await run(db, statement);
83
+ }
84
+ }
85
+
86
+ module.exports = {
87
+ DB_PATH,
88
+ openDb,
89
+ run,
90
+ get,
91
+ all,
92
+ initDb,
93
+ };