patchcord 0.5.1 → 0.5.3
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/.claude-plugin/plugin.json +1 -1
- package/package.json +1 -1
- package/scripts/subscribe.mjs +11 -0
- package/skills/subscribe/SKILL.md +50 -17
package/package.json
CHANGED
package/scripts/subscribe.mjs
CHANGED
|
@@ -17,6 +17,17 @@ const JWT_REFRESH_SAFETY_MARGIN_SEC = 120;
|
|
|
17
17
|
const HEARTBEAT_INTERVAL_MS = 25_000;
|
|
18
18
|
const RECONNECT_BACKOFF_MS = [1000, 2000, 4000, 8000, 15_000, 30_000];
|
|
19
19
|
|
|
20
|
+
// Guarantee a terminal stderr line on any unhandled failure so the agent
|
|
21
|
+
// reading Monitor's output file always sees WHY the process died.
|
|
22
|
+
process.on("uncaughtException", (err) => {
|
|
23
|
+
process.stderr.write(`subscribe: fatal: uncaught: ${err?.stack || err?.message || err}\n`);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
});
|
|
26
|
+
process.on("unhandledRejection", (err) => {
|
|
27
|
+
process.stderr.write(`subscribe: fatal: unhandled rejection: ${err?.stack || err?.message || err}\n`);
|
|
28
|
+
process.exit(1);
|
|
29
|
+
});
|
|
30
|
+
|
|
20
31
|
function die(msg, code = 1) {
|
|
21
32
|
process.stderr.write(msg + "\n");
|
|
22
33
|
process.exit(code);
|
|
@@ -68,13 +68,19 @@ then the script is at
|
|
|
68
68
|
description: "patchcord realtime listener (<agent>@<ns>)",
|
|
69
69
|
persistent: true,
|
|
70
70
|
timeout_ms: 3600000,
|
|
71
|
-
command: "exec node \"<absolute-path-to-subscribe.mjs>\"
|
|
71
|
+
command: "exec node \"<absolute-path-to-subscribe.mjs>\""
|
|
72
72
|
)
|
|
73
73
|
```
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
Monitor
|
|
74
|
+
No `2>&1`, no grep filter. By construction the script only writes
|
|
75
|
+
`PATCHCORD: ...` lines to stdout. Everything else — `connected`,
|
|
76
|
+
`token refreshed`, startup diagnostics, errors — goes to stderr,
|
|
77
|
+
which Monitor captures into its output file but does NOT fire as
|
|
78
|
+
notifications. So there's nothing to filter and no way to get the
|
|
79
|
+
filter wrong.
|
|
80
|
+
|
|
81
|
+
Crash detection is handled automatically by Monitor itself: when the
|
|
82
|
+
process exits, Monitor emits a built-in "stream ended" task
|
|
83
|
+
notification with the output file path and exit code.
|
|
78
84
|
|
|
79
85
|
6. **Tell the user one short line:**
|
|
80
86
|
"Patchcord listener active — I'll pick up new messages as they arrive."
|
|
@@ -97,18 +103,45 @@ There is no `/patchcord:unsubscribe` command. Tell the user either:
|
|
|
97
103
|
- Run `kill $(cat /tmp/patchcord_subscribe_<namespace>_<agent>.pid)` in
|
|
98
104
|
a terminal.
|
|
99
105
|
|
|
100
|
-
# If
|
|
106
|
+
# If the Monitor stream ends — STRICT PROTOCOL
|
|
107
|
+
|
|
108
|
+
The stream-end task notification includes the path to Monitor's output
|
|
109
|
+
file. Do exactly this, in this order:
|
|
110
|
+
|
|
111
|
+
1. Read that output file using the Read tool.
|
|
112
|
+
2. Look at the last ~15 lines for a line matching one of the known
|
|
113
|
+
failure strings below. There will always be at least one terminal
|
|
114
|
+
error line — the script's error handlers guarantee it.
|
|
115
|
+
3. Report the specific cause to the user in one short sentence.
|
|
116
|
+
4. STOP.
|
|
117
|
+
|
|
118
|
+
**Forbidden on failure — do not do any of these:**
|
|
119
|
+
- Do NOT run `pgrep`, `ps`, `kill`, `pkill`, `killall`, or any command
|
|
120
|
+
that targets PIDs or process names.
|
|
121
|
+
- Do NOT modify, delete, or write to the pidfile yourself. The script
|
|
122
|
+
manages it; it's already cleaned up by the time Monitor emits the
|
|
123
|
+
stream-end event.
|
|
124
|
+
- Do NOT spawn another Monitor or another `node subscribe.mjs`. One
|
|
125
|
+
failure means something is wrong with the config or environment;
|
|
126
|
+
respawning will not fix it and will make things worse.
|
|
127
|
+
- Do NOT search for orphaned processes or try to "clean up" state.
|
|
101
128
|
|
|
102
|
-
|
|
103
|
-
— do not loop or retry:
|
|
129
|
+
Concrete failure strings you may see and what they mean:
|
|
104
130
|
|
|
105
131
|
- `no .mcp.json in <cwd>` — session is not in a patchcord project dir.
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
132
|
+
Tell the user which directory to `cd` into.
|
|
133
|
+
- `ticket: token rejected (HTTP 401|403)` — bearer in `.mcp.json` is
|
|
134
|
+
bad; regenerate from the dashboard.
|
|
135
|
+
- `ticket: server not configured for realtime` — the patchcord server
|
|
136
|
+
hasn't had `SUPABASE_JWT_SECRET` / `SUPABASE_ANON_KEY` set. This is
|
|
137
|
+
a cloud-only feature.
|
|
138
|
+
- `ticket: namespace not owned — regenerate your token` — the token's
|
|
139
|
+
namespace lost its owner row; regenerate from the dashboard.
|
|
140
|
+
- `already running (pid N)` (exit code 2) — pidfile guard tripped,
|
|
141
|
+
another listener is active. Report and stop. Do NOT kill the other
|
|
142
|
+
listener to make room.
|
|
143
|
+
- `subscribe: fatal: ...` — unhandled error. Show the user the line
|
|
144
|
+
verbatim, stop.
|
|
145
|
+
|
|
146
|
+
If the process exited cleanly (exit 0) with no error line, the user
|
|
147
|
+
closed the session or killed the process. Nothing to do.
|