patchcord 0.6.37 → 0.6.38
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/check-inbox.sh +35 -6
package/package.json
CHANGED
package/scripts/check-inbox.sh
CHANGED
|
@@ -75,7 +75,22 @@ fi
|
|
|
75
75
|
# Check inbox — one lightweight HTTP call
|
|
76
76
|
MACHINE_NAME=$(hostname -s 2>/dev/null || echo "unknown")
|
|
77
77
|
INSTALL_PATH=$(dirname "$MCP_JSON")
|
|
78
|
-
|
|
78
|
+
|
|
79
|
+
# PER-INVOCATION response file. This was a FIXED path (/tmp/patchcord_inbox.json)
|
|
80
|
+
# shared by every agent on the machine, and a host running several seats stops
|
|
81
|
+
# them at overlapping times: one hook's curl truncates and rewrites the file
|
|
82
|
+
# another hook is reading, and either one's `rm -f` deletes it underneath the
|
|
83
|
+
# other. The reader then hands a half-written body to jq, which is exactly the
|
|
84
|
+
# "Invalid numeric literal at line 1, column N" this produced on the Mac mini.
|
|
85
|
+
# A shared mutable temp path between concurrent agents is not a race that
|
|
86
|
+
# happens rarely; it is one that happens whenever the machine is busy.
|
|
87
|
+
RESP_FILE=$(mktemp "${TMPDIR:-/tmp}/patchcord_inbox.XXXXXX" 2>/dev/null || echo "")
|
|
88
|
+
[ -z "$RESP_FILE" ] && exit 0
|
|
89
|
+
# Remove it on ANY exit path, including the early returns below, so a crash
|
|
90
|
+
# cannot leave per-invocation files accumulating in /tmp.
|
|
91
|
+
trap 'rm -f "$RESP_FILE"' EXIT
|
|
92
|
+
|
|
93
|
+
HTTP_CODE=$(curl -s -o "$RESP_FILE" -w "%{http_code}" --max-time 5 \
|
|
79
94
|
-H "Authorization: Bearer ${TOKEN}" \
|
|
80
95
|
-H "x-patchcord-machine: ${MACHINE_NAME}" \
|
|
81
96
|
-H "x-patchcord-install-path: ${INSTALL_PATH}" \
|
|
@@ -86,18 +101,25 @@ if [ "$HTTP_CODE" = "401" ] || [ "$HTTP_CODE" = "403" ]; then
|
|
|
86
101
|
"decision": "block",
|
|
87
102
|
"reason": "PATCHCORD AUTH FAILED: token rejected by server (HTTP '"$HTTP_CODE"'). Check your token in .mcp.json — it may be wrong, expired, or not yet registered on the server."
|
|
88
103
|
}'
|
|
89
|
-
rm -f /tmp/patchcord_inbox.json
|
|
90
104
|
exit 0
|
|
91
105
|
fi
|
|
92
106
|
|
|
93
107
|
if [ "$HTTP_CODE" = "000" ]; then
|
|
94
108
|
# Server unreachable — skip silently
|
|
95
|
-
rm -f /tmp/patchcord_inbox.json
|
|
96
109
|
exit 0
|
|
97
110
|
fi
|
|
98
111
|
|
|
99
|
-
RESPONSE=$(cat
|
|
100
|
-
|
|
112
|
+
RESPONSE=$(cat "$RESP_FILE" 2>/dev/null || echo "")
|
|
113
|
+
|
|
114
|
+
# "COULD NOT TELL" IS NOT "NOTHING PENDING". Below, an unparseable body used to
|
|
115
|
+
# fall through jq's `// 0` default to COUNT=0, which takes the same exit path as
|
|
116
|
+
# a genuinely empty inbox AND clears the streak state. So a corrupted response
|
|
117
|
+
# told the agent it had no messages, silently, with no way to tell the two apart
|
|
118
|
+
# — the same absence-reads-as-a-value shape that cost this project a night.
|
|
119
|
+
# Refuse to answer instead: leave the streak state alone and say nothing.
|
|
120
|
+
if ! printf '%s' "$RESPONSE" | jq -e 'type == "object"' >/dev/null 2>&1; then
|
|
121
|
+
exit 0
|
|
122
|
+
fi
|
|
101
123
|
|
|
102
124
|
# ── Auto-apply custom skill from web console ──────────────────
|
|
103
125
|
# Writes to .claude/skills/patchcord-custom/SKILL.md — Claude Code
|
|
@@ -142,7 +164,14 @@ if [ "$COUNT" -eq 0 ]; then
|
|
|
142
164
|
exit 0
|
|
143
165
|
fi
|
|
144
166
|
|
|
145
|
-
|
|
167
|
+
# PER-IDENTITY lock. This was a single global path, so on a host running several
|
|
168
|
+
# seats one agent's notification suppressed EVERY other agent's for 5s — an
|
|
169
|
+
# agent with real pending messages could be silenced by an unrelated seat that
|
|
170
|
+
# happened to stop first. The dedupe is meant to stop ONE identity being told
|
|
171
|
+
# twice by the Stop and Notification hooks, never to stop a second identity
|
|
172
|
+
# being told at all.
|
|
173
|
+
NOTIFY_LOCK=$(pc_state_path "patchcord_notify_lock" "$NAMESPACE" "$AGENT_ID" 2>/dev/null || echo "")
|
|
174
|
+
[ -z "$NOTIFY_LOCK" ] && NOTIFY_LOCK="${TMPDIR:-/tmp}/patchcord_notify_lock_$(printf '%s' "${NAMESPACE}/${AGENT_ID}" | tr -c 'a-zA-Z0-9' '_')"
|
|
146
175
|
LOCK_AGE=5
|
|
147
176
|
if [ -f "$NOTIFY_LOCK" ]; then
|
|
148
177
|
LOCK_MTIME=$(stat -c %Y "$NOTIFY_LOCK" 2>/dev/null || stat -f %m "$NOTIFY_LOCK" 2>/dev/null || echo "0")
|