pi-studio 0.9.55 → 0.9.56
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/CHANGELOG.md +13 -0
- package/README.md +14 -2
- package/ROADMAP.md +16 -1
- package/client/studio-client.js +163 -43
- package/index.ts +734 -163
- package/package.json +1 -1
- package/shared/REPL_SESSION_RECORD_PROTOCOL.md +70 -0
- package/shared/repl-session-record.js +623 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-studio",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.56",
|
|
4
4
|
"description": "Two-pane browser workspace for pi with prompt/response editing, annotations, critiques, active quiz, prompt/response history, live previews, and tmux-backed REPL/literate REPL workflows",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Shared REPL session record protocol v1
|
|
2
|
+
|
|
3
|
+
This protocol lets independent `pi-repl` and `pi-studio` installations exchange a clean code/output record while using the same tmux REPL session. Neither package imports or requires the other. If the protocol is unavailable or invalid, each package keeps its existing standalone behavior and the raw tmux pane/history remains usable.
|
|
4
|
+
|
|
5
|
+
## Discovery and identity
|
|
6
|
+
|
|
7
|
+
Compatible clients inspect two tmux session options:
|
|
8
|
+
|
|
9
|
+
- `@pi_repl_record_id`: 32 lowercase hexadecimal characters
|
|
10
|
+
- `@pi_repl_record_version`: `1`
|
|
11
|
+
|
|
12
|
+
A client creating metadata uses tmux `set-option -o`, so concurrent first writers cannot replace an ID already chosen by another client. The option contains an opaque ID, never a filesystem path.
|
|
13
|
+
|
|
14
|
+
The record is bound to:
|
|
15
|
+
|
|
16
|
+
- the tmux session name
|
|
17
|
+
- `#{session_id}`
|
|
18
|
+
- `#{session_created}`
|
|
19
|
+
|
|
20
|
+
A client refuses a record whose stored identity does not match the live tmux session. Runtime metadata continues to use `@pi_repl_runtime`.
|
|
21
|
+
|
|
22
|
+
## Storage and permissions
|
|
23
|
+
|
|
24
|
+
The opaque ID maps to:
|
|
25
|
+
|
|
26
|
+
```text
|
|
27
|
+
<os temporary directory>/pi-repl-session-records-<uid>/<record-id>.json
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The root is a real, current-user-owned mode-`0700` directory. Record files are single-link regular, current-user-owned mode-`0600` files. Symlinked roots, records, lock paths, and hard-linked records are refused. Writes use a same-directory exclusive temporary file, file fsync, atomic rename, and best-effort directory fsync.
|
|
31
|
+
|
|
32
|
+
The record is a bounded JSON snapshot:
|
|
33
|
+
|
|
34
|
+
```json
|
|
35
|
+
{
|
|
36
|
+
"protocol": "pi-repl-session-record",
|
|
37
|
+
"version": 1,
|
|
38
|
+
"recordId": "…",
|
|
39
|
+
"session": {
|
|
40
|
+
"sessionName": "pi-repl-python",
|
|
41
|
+
"tmuxSessionId": "$1",
|
|
42
|
+
"tmuxSessionCreatedAt": 1700000000,
|
|
43
|
+
"runtime": "ipython"
|
|
44
|
+
},
|
|
45
|
+
"revision": 4,
|
|
46
|
+
"createdAt": 1700000000000,
|
|
47
|
+
"updatedAt": 1700000005000,
|
|
48
|
+
"clearedAt": null,
|
|
49
|
+
"droppedEntries": 0,
|
|
50
|
+
"entries": []
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Each entry has a stable `id`, optional `requestId`, timestamps, session/runtime identity, `origin` (`pi-repl` or `pi-studio`), a presentation `label`, `mode` (`raw`, `literate`, or `agent`), prose, code, cleaned output, status, and skipped/truncation metadata.
|
|
55
|
+
|
|
56
|
+
## Concurrency and bounds
|
|
57
|
+
|
|
58
|
+
Record updates take a short cross-process directory lock, read the latest snapshot, upsert by stable entry ID, and replace the snapshot atomically. A stale lock can be recovered. The implementation retains at most 300 entries, bounds individual prose/code/output fields, and caps the serialized record at 16 MiB by dropping the oldest entries first.
|
|
59
|
+
|
|
60
|
+
Attribution-sensitive sends also take a separate cross-client send lease. A compatible client holds it from the pre-send pane capture through the completion/output capture. The lease has an owner token, heartbeat, bounded wait, and stale recovery. If a caller times out or aborts after submission, the live client continues heartbeating the lease until the runtime completion marker appears or that exact tmux session lifetime ends; a caller timeout does not imply that submitted code stopped. This prevents `pi-repl` and `pi-studio` from concurrently claiming each other's output; it cannot prevent a person typing directly into an attached tmux pane.
|
|
61
|
+
|
|
62
|
+
## Clean record versus raw history
|
|
63
|
+
|
|
64
|
+
The clean record includes submissions whose semantic boundaries are known to a compatible client, plus explicit literate notes. Code typed directly into tmux is retained only in the raw pane/history mirror unless future runtime-specific instrumentation can establish reliable boundaries. Clients must not present raw `pipe-pane` output as reliably parsed code/output.
|
|
65
|
+
|
|
66
|
+
Canonical Markdown exports identify origin, mode, status, runtime, and timestamp and include this direct-input limitation.
|
|
67
|
+
|
|
68
|
+
## Compatibility
|
|
69
|
+
|
|
70
|
+
A client that sees an unsupported version leaves it untouched. Existing tmux sessions gain v1 metadata lazily when inspected or used. Studio may import legacy browser-local entries as `pi-studio` entries using their stable IDs, making retries idempotent.
|