@kingcrab/pi-imessage 1.0.0 → 1.1.1
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 +38 -46
- package/dist/agent/chats.js +21 -0
- package/dist/agent/commands.js +66 -38
- package/dist/agent/direct-send.js +1 -0
- package/dist/agent/error-log.js +37 -0
- package/dist/agent/health.js +1 -0
- package/dist/agent/progress.js +43 -5
- package/dist/agent/replies.js +1 -0
- package/dist/agent/run.js +2 -1
- package/dist/agent/scheduling.js +8 -7
- package/dist/extensions/browser.js +1 -1
- package/dist/extensions/memory.js +1 -1
- package/dist/extensions/message.js +1 -1
- package/dist/extensions/read-image.js +1 -1
- package/dist/extensions/restart.js +100 -0
- package/dist/extensions/schedules.js +1 -0
- package/dist/extensions/subagent.js +1 -1
- package/dist/extensions/web.js +4 -3
- package/dist/extensions/workspace.js +1 -1
- package/dist/main.js +25 -4
- package/dist/web/app.js +198 -55
- package/dist/web/page.js +3 -2
- package/dist/web/schedules.js +4 -15
- package/dist/web/server.js +48 -3
- package/dist/web/style.css +40 -0
- package/dist/web/tasks.js +183 -41
- package/docs/adr/0048-quiet-attachment-reads.md +11 -0
- package/docs/adr/0049-per-chat-progress-notices.md +21 -0
- package/docs/adr/0052-host-owned-self-restart.md +53 -0
- package/docs/adr/0053-service-log-errors.md +44 -0
- package/docs/adr/README.md +7 -2
- package/docs/api.md +16 -4
- package/ops/README.md +24 -41
- package/package.json +5 -5
package/ops/README.md
CHANGED
|
@@ -186,6 +186,13 @@ text). Never reset cursors, delete state or replay uncertain sends. Do not use
|
|
|
186
186
|
|
|
187
187
|
### 3. Run one private controller
|
|
188
188
|
|
|
189
|
+
From a chat, the assistant calls `restart_service` with the full commit hash of
|
|
190
|
+
the prepared release directory (ADR 0052). The host writes the controller
|
|
191
|
+
directory below itself and opens the controller only after that tool call has
|
|
192
|
+
settled; the call returns the directory and the next call verifies (step 4).
|
|
193
|
+
The manual procedure below is for operators and for a cold start when no
|
|
194
|
+
service is running.
|
|
195
|
+
|
|
189
196
|
In a `mktemp -d /tmp/pi-imessage-restart.XXXXXX` directory with `umask 077`:
|
|
190
197
|
|
|
191
198
|
- `environment.sh`: shell-quoted exports of the running process's `WORKING_DIR`,
|
|
@@ -196,44 +203,11 @@ In a `mktemp -d /tmp/pi-imessage-restart.XXXXXX` directory with `umask 077`:
|
|
|
196
203
|
- `control.sh`: shell-quoted `OLD_PID`, `OLD_STARTED` (exact `ps -o lstart=`),
|
|
197
204
|
`EXPECTED_COMMAND`, `REPO` (the release directory), `NODE`, `WORKING_DIR`,
|
|
198
205
|
`WEB_PORT` and `LOG_FILE`.
|
|
199
|
-
- `restart.command`:
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
umask 077
|
|
205
|
-
DEPLOY_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
206
|
-
source "$DEPLOY_DIR/environment.sh"
|
|
207
|
-
source "$DEPLOY_DIR/control.sh"
|
|
208
|
-
: "${OLD_PID:?}" "${OLD_STARTED:?}" "${EXPECTED_COMMAND:?}"
|
|
209
|
-
: "${REPO:?}" "${NODE:?}" "${WORKING_DIR:?}" "${WEB_PORT:?}" "${LOG_FILE:?}"
|
|
210
|
-
cd "$REPO"
|
|
211
|
-
exec 3>>"$DEPLOY_DIR/controller.log"
|
|
212
|
-
[ "$(ps -p "$OLD_PID" -o lstart=)" = "$OLD_STARTED" ]
|
|
213
|
-
[ "$(ps -p "$OLD_PID" -o command=)" = "$EXPECTED_COMMAND" ]
|
|
214
|
-
printf '%s stopping pid=%s\n' "$(date -u +%FT%TZ)" "$OLD_PID" >&3
|
|
215
|
-
kill -TERM "$OLD_PID"
|
|
216
|
-
deadline=$((SECONDS + 30))
|
|
217
|
-
while kill -0 "$OLD_PID" 2>/dev/null; do
|
|
218
|
-
if (( SECONDS >= deadline )); then
|
|
219
|
-
echo 'Shutdown timeout; no force-kill and no second process started' >&3
|
|
220
|
-
exit 1
|
|
221
|
-
fi
|
|
222
|
-
sleep 0.1
|
|
223
|
-
done
|
|
224
|
-
[ ! -e "$WORKING_DIR/durable/owner.lock" ]
|
|
225
|
-
port_status=0
|
|
226
|
-
lsof -nP -iTCP:"$WEB_PORT" -sTCP:LISTEN -t > /dev/null || port_status=$?
|
|
227
|
-
case "$port_status" in
|
|
228
|
-
0) echo 'Port still occupied; refusing startup' >&3; exit 1 ;;
|
|
229
|
-
1) ;; # No listener.
|
|
230
|
-
*) echo 'Cannot verify port ownership; refusing startup' >&3; exit 1 ;;
|
|
231
|
-
esac
|
|
232
|
-
printf '%s old process exited; ownership released\n' "$(date -u +%FT%TZ)" >&3
|
|
233
|
-
printf '%s\n' "$$" > "$DEPLOY_DIR/new.pid"
|
|
234
|
-
exec 3>&-
|
|
235
|
-
exec "$NODE" --use-env-proxy --experimental-strip-types src/cli.ts serve >> "$LOG_FILE" 2>&1
|
|
236
|
-
```
|
|
206
|
+
- `restart.command`: a copy of [`ops/restart.command`](restart.command) from the
|
|
207
|
+
release directory. It checks the old PID's start time and command, sends
|
|
208
|
+
SIGTERM, waits up to 30 s, refuses to start while the lock or port is held,
|
|
209
|
+
writes `controller.log` and `new.pid`, deletes `environment.sh` and then
|
|
210
|
+
`exec`s the new service process.
|
|
237
211
|
|
|
238
212
|
Launch it once with `chmod 700` and `open -a Terminal "$DEPLOY_DIR/restart.command"`
|
|
239
213
|
(`osascript` `do script` times out on claw). The separate Terminal keeps the
|
|
@@ -241,10 +215,17 @@ controller alive when the initiating agent's own turn is interrupted. For a
|
|
|
241
215
|
launchd controller, use that job's lifecycle instead; never `launchctl kickstart -k`
|
|
242
216
|
from inside the service.
|
|
243
217
|
|
|
218
|
+
A chat that writes its own controller through `bash` instead of
|
|
219
|
+
`restart_service` must end that call right after `open`: no `sleep`, polling or
|
|
220
|
+
verification in the same call. Tools are replay-safe by default (ADR 0041), so a
|
|
221
|
+
call still running when the controller stops the service reruns on every start,
|
|
222
|
+
launches another controller and loops (#39). Verify in a later call.
|
|
223
|
+
|
|
244
224
|
### 4. Verify
|
|
245
225
|
|
|
246
|
-
|
|
247
|
-
launch the controller twice before the first outcome is
|
|
226
|
+
In a new tool call, read `controller.log`, `new.pid`, the service log and the
|
|
227
|
+
listener first. Never launch the controller twice before the first outcome is
|
|
228
|
+
known. Require:
|
|
248
229
|
|
|
249
230
|
1. Old PID gone; exactly one new process and listener, cwd in the release
|
|
250
231
|
directory.
|
|
@@ -252,7 +233,9 @@ launch the controller twice before the first outcome is known. Require:
|
|
|
252
233
|
`Messaging ready` and `Application started`; no startup error.
|
|
253
234
|
3. Root and changed endpoints return 200; check UI changes in a browser.
|
|
254
235
|
4. Interrupted work continues; scheduler deadlines are unchanged; receipt
|
|
255
|
-
counts change only by new sends and sends interrupted by the stop.
|
|
236
|
+
counts change only by new sends and sends interrupted by the stop. After
|
|
237
|
+
`restart_service`, the old log shows `Restart requested` with the
|
|
238
|
+
controller directory.
|
|
256
239
|
|
|
257
240
|
On a timeout, lock, occupied port or startup failure, stop and report it. Do not
|
|
258
241
|
force-kill, steal the lock, reinstall dependencies or restore a workspace snapshot.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kingcrab/pi-imessage",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "A minimal, self-managing iMessage bot powered by Pi Durable",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -34,10 +34,10 @@
|
|
|
34
34
|
"test": "vitest run"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@earendil-works/chord": "1.0
|
|
38
|
-
"@earendil-works/pi-ai": "1.0
|
|
39
|
-
"@earendil-works/pi-coding-agent": "1.0
|
|
40
|
-
"@earendil-works/pi-durable": "1.0
|
|
37
|
+
"@earendil-works/chord": "1.4.0",
|
|
38
|
+
"@earendil-works/pi-ai": "1.4.0",
|
|
39
|
+
"@earendil-works/pi-coding-agent": "1.4.0",
|
|
40
|
+
"@earendil-works/pi-durable": "1.4.0",
|
|
41
41
|
"better-sqlite3": "13.0.3",
|
|
42
42
|
"defuddle": "0.19.4",
|
|
43
43
|
"sharp": "0.35.5",
|