pi-simocracy 0.2.0 → 0.4.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 +89 -30
- package/package.json +2 -1
- package/src/auth/commands.ts +4 -4
- package/src/index.ts +361 -444
- package/src/openrouter.ts +0 -16
- package/src/png-to-ansi.ts +79 -0
- package/src/simocracy.ts +24 -90
- package/src/webp-to-rgba.ts +70 -0
- package/src/writes.ts +117 -53
- package/src/interview.ts +0 -516
- package/src/training/alignment.ts +0 -259
- package/src/training/apply.ts +0 -271
- package/src/training/baseline.ts +0 -159
- package/src/training/chat.ts +0 -131
- package/src/training/feedback.ts +0 -81
- package/src/training/index.ts +0 -142
- package/src/training/profile.ts +0 -229
- package/src/training/prompt-helpers.ts +0 -70
- package/src/training/prompts.ts +0 -131
- package/src/training/question-set.ts +0 -134
- package/src/training/storage.ts +0 -81
- package/src/training/types.ts +0 -121
package/README.md
CHANGED
|
@@ -1,18 +1,28 @@
|
|
|
1
1
|
# pi-simocracy
|
|
2
2
|
|
|
3
3
|
Load a [Simocracy](https://simocracy.org) sim into your [`pi`](https://github.com/mariozechner/pi-coding-agent) chat — see its
|
|
4
|
-
|
|
4
|
+
sprite render in the terminal and chat with the agent **as that sim**.
|
|
5
5
|
|
|
6
6
|
```
|
|
7
7
|
/sim mr meow
|
|
8
8
|
```
|
|
9
9
|
|
|
10
10
|
…fetches Mr Meow from Simocracy's ATProto indexer, renders his 32×32
|
|
11
|
-
sprite as colored ANSI half-blocks directly in the chat, and
|
|
12
|
-
his constitution + speaking style into pi's system prompt so pi
|
|
11
|
+
pixel-art sprite as colored ANSI half-blocks directly in the chat, and
|
|
12
|
+
pushes his constitution + speaking style into pi's system prompt so pi
|
|
13
13
|
roleplays as Mr Meow until you `/sim unload`.
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
<p align="center">
|
|
16
|
+
<img src="https://raw.githubusercontent.com/GainForest/pi-simocracy/main/demo/sim-load.gif" alt="Mr Meow (a pipoya pixel-art cat) loaded inline in pi's chat" width="760">
|
|
17
|
+
</p>
|
|
18
|
+
|
|
19
|
+
As of v0.4.0, codex pet sims (OpenAI hatch-pet skill output) render too —
|
|
20
|
+
load **Einstein** with `/sim einstein` and the WebP atlas decodes, the
|
|
21
|
+
idle frame crops, and the half-block ANSI render fires inline:
|
|
22
|
+
|
|
23
|
+
<p align="center">
|
|
24
|
+
<img src="https://raw.githubusercontent.com/GainForest/pi-simocracy/main/demo/codex-pet-load.gif" alt="Einstein (a codex pet sim with a WebP petSheet) loaded inline in pi's chat" width="760">
|
|
25
|
+
</p>
|
|
16
26
|
|
|
17
27
|
---
|
|
18
28
|
|
|
@@ -33,13 +43,17 @@ doesn't need it — it just rewrites pi's system prompt.
|
|
|
33
43
|
|
|
34
44
|
## Slash commands
|
|
35
45
|
|
|
36
|
-
| Command
|
|
37
|
-
|
|
38
|
-
| `/sim <name>`
|
|
39
|
-
| `/sim <at-uri>`
|
|
40
|
-
| `/sim status`
|
|
41
|
-
| `/sim unload`
|
|
42
|
-
| `/sim
|
|
46
|
+
| Command | What it does |
|
|
47
|
+
|-------------------|-------------------------------------------------------------|
|
|
48
|
+
| `/sim <name>` | Load a sim by name (fuzzy search). Multiple matches → picker. |
|
|
49
|
+
| `/sim <at-uri>` | Load a sim by AT-URI directly (no search). |
|
|
50
|
+
| `/sim status` | Show which sim is currently loaded. |
|
|
51
|
+
| `/sim unload` | Drop the persona and break character cleanly. |
|
|
52
|
+
| `/sim login [handle]` | Sign in to **ATProto / Bluesky** via loopback OAuth (NOT Anthropic — pi's built-in `/login` is what does that). Required before pi can update your sim. |
|
|
53
|
+
| `/sim logout` | Clear the local ATProto OAuth session. |
|
|
54
|
+
| `/sim whoami` | Show the signed-in handle / DID. |
|
|
55
|
+
| `/sim my [name]` | List / pick / fuzzy-load sims you own on your PDS. Single match auto-loads; ambiguous matches open a picker. Requires `/sim login`. |
|
|
56
|
+
| `/sim help` | Print usage. |
|
|
43
57
|
|
|
44
58
|
Examples:
|
|
45
59
|
|
|
@@ -47,20 +61,48 @@ Examples:
|
|
|
47
61
|
/sim mr meow
|
|
48
62
|
/sim Marie Curie
|
|
49
63
|
/sim at://did:plc:qc42fmqqlsmdq7jiypiiigww/org.simocracy.sim/3mfo6vwfaka24
|
|
64
|
+
/sim login alice.bsky.social
|
|
65
|
+
/sim my
|
|
50
66
|
/sim unload
|
|
51
67
|
```
|
|
52
68
|
|
|
53
69
|
---
|
|
54
70
|
|
|
71
|
+
## Editing a sim's constitution / speaking style
|
|
72
|
+
|
|
73
|
+
There is no slash-command pipeline for this. Once you've signed in via
|
|
74
|
+
`/sim login` and loaded a sim you own (`/sim my`, then pick), just
|
|
75
|
+
**describe the change you want to pi**:
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
> add a red line about animal welfare to the constitution
|
|
79
|
+
> rewrite the speaking style to drop the lenny faces and be more concise
|
|
80
|
+
> shorten the constitution to ~300 words and emphasise renewable energy
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Pi rewrites the constitution and/or speaking style itself, then calls
|
|
84
|
+
the `simocracy_update_sim` tool to persist the result. The tool refuses
|
|
85
|
+
to run if you're not signed in or you don't own the loaded sim. The
|
|
86
|
+
new persona takes effect on the next reply — no reload needed.
|
|
87
|
+
|
|
88
|
+
Writing goes directly to your PDS via
|
|
89
|
+
`com.atproto.repo.createRecord` / `putRecord` against the
|
|
90
|
+
`org.simocracy.agents` (constitution) and `org.simocracy.style`
|
|
91
|
+
(speaking style) collections — the same lexicons simocracy.org reads
|
|
92
|
+
back.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
55
96
|
## LLM-callable tools
|
|
56
97
|
|
|
57
98
|
The same actions are exposed to pi as tools, so the model can drive them itself:
|
|
58
99
|
|
|
59
|
-
| Tool
|
|
60
|
-
|
|
61
|
-
| `simocracy_load_sim`
|
|
62
|
-
| `simocracy_unload_sim`
|
|
63
|
-
| `simocracy_chat`
|
|
100
|
+
| Tool | Use when |
|
|
101
|
+
|-------------------------|-----------------------------------------------------------------|
|
|
102
|
+
| `simocracy_load_sim` | Load a sim into the current session (sets the persona). |
|
|
103
|
+
| `simocracy_unload_sim` | Stop roleplaying. |
|
|
104
|
+
| `simocracy_chat` | Send one message to a sim and get a quoted reply, **without** changing the active session persona. Useful for "ask Mr Meow what he thinks of this PR." Requires `OPENROUTER_API_KEY`. |
|
|
105
|
+
| `simocracy_update_sim` | Write a new constitution (`shortDescription` + `description`) and/or speaking `style` for the **loaded** sim to your PDS. Requires `/sim login` AND ownership of the loaded sim. |
|
|
64
106
|
|
|
65
107
|
---
|
|
66
108
|
|
|
@@ -77,11 +119,18 @@ The same actions are exposed to pi as tools, so the model can drive them itself:
|
|
|
77
119
|
- `org.simocracy.sim` — display name + sprite + avatar blob refs
|
|
78
120
|
- `org.simocracy.agents` — short description + full constitution
|
|
79
121
|
- `org.simocracy.style` — speaking style / mannerisms
|
|
80
|
-
4. **Render.** Fetch the sprite
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
122
|
+
4. **Render.** Fetch the sprite blob via `com.atproto.sync.getBlob`,
|
|
123
|
+
decode it, crop the front-facing idle frame, and emit as 24-bit ANSI
|
|
124
|
+
using the upper-half-block character `▀` so each terminal cell paints
|
|
125
|
+
two pixels. Two render paths depending on the sim's `spriteKind`:
|
|
126
|
+
- **`pipoya`** (legacy + default): 128×128 PNG, 4×4 of 32×32 walking
|
|
127
|
+
frames; decode with `pngjs`, take row 0 col 0 at native size.
|
|
128
|
+
- **`codexPet`** (OpenAI hatch-pet output): 1536×1872 atlas, 8×9 of
|
|
129
|
+
192×208 cells. PNG sheets decode through `pngjs`; WebP sheets
|
|
130
|
+
decode through `@jsquash/webp` (wasm, lazy-init). The idle cell
|
|
131
|
+
(row 0 col 0) is box-downscaled to ~32 wide so the inline render
|
|
132
|
+
stays comparable in height to a pipoya sprite.
|
|
133
|
+
Transparent regions show pi's background through.
|
|
85
134
|
5. **Inject.** A `before_agent_start` event handler appends the sim's
|
|
86
135
|
identity + constitution + speaking style to pi's system prompt **every
|
|
87
136
|
turn**. After `/sim unload`, a one-shot override fires on the next
|
|
@@ -97,12 +146,17 @@ keeps the terminal it's already running in.
|
|
|
97
146
|
|
|
98
147
|
```
|
|
99
148
|
src/
|
|
100
|
-
├── index.ts
|
|
101
|
-
├──
|
|
102
|
-
├──
|
|
103
|
-
|
|
149
|
+
├── index.ts # extension entry: slash command, tools, persona injection
|
|
150
|
+
├── persona.ts # buildSimPrompt(sim) — the system-prompt fragment
|
|
151
|
+
├── simocracy.ts # indexer + PDS client (read-only fetchers)
|
|
152
|
+
├── writes.ts # PDS writers + ownership / sign-in preconditions
|
|
153
|
+
├── png-to-ansi.ts # RGBA half-block ANSI renderer + downscalers
|
|
154
|
+
├── webp-to-rgba.ts # @jsquash/webp wrapper for codex pet WebP sheets
|
|
155
|
+
├── openrouter.ts # minimal OpenRouter client (only used by simocracy_chat)
|
|
156
|
+
└── auth/ # ATProto OAuth loopback flow + session storage
|
|
104
157
|
demo/
|
|
105
|
-
|
|
158
|
+
├── sim-load.tape # vhs tape — Mr Meow (pipoya)
|
|
159
|
+
└── codex-pet-load.tape # vhs tape — Einstein (codex pet)
|
|
106
160
|
```
|
|
107
161
|
|
|
108
162
|
---
|
|
@@ -118,11 +172,12 @@ pi -e $(pwd)/src/index.ts -ne -ns # load the extension directly
|
|
|
118
172
|
|
|
119
173
|
Then in `pi`: `/sim mr meow`.
|
|
120
174
|
|
|
121
|
-
To rebuild the demo
|
|
175
|
+
To rebuild the demo recordings:
|
|
122
176
|
|
|
123
177
|
```bash
|
|
124
178
|
brew install vhs # one-time
|
|
125
|
-
vhs demo/sim-load.tape #
|
|
179
|
+
vhs demo/sim-load.tape # Mr Meow (pipoya) — demo/sim-load.{webm,gif}
|
|
180
|
+
vhs demo/codex-pet-load.tape # Einstein (codex pet) — demo/codex-pet-load.{webm,gif}
|
|
126
181
|
```
|
|
127
182
|
|
|
128
183
|
---
|
|
@@ -137,7 +192,11 @@ These come bundled with `pi` itself, so installing pi-simocracy via
|
|
|
137
192
|
|
|
138
193
|
Direct npm dependencies (auto-installed):
|
|
139
194
|
|
|
140
|
-
- `pngjs` — PNG decoder for sprite blobs
|
|
195
|
+
- `pngjs` — PNG decoder for pipoya sprite blobs and codex pet PNG sheets
|
|
196
|
+
- `@jsquash/webp` — wasm WebP decoder for codex pet WebP sheets
|
|
197
|
+
(lazy-init, no native bindings)
|
|
198
|
+
- `@atproto/api` + `@atproto/oauth-client-node` — ATProto loopback OAuth
|
|
199
|
+
for `/sim login` and PDS writes via `simocracy_update_sim`
|
|
141
200
|
- `typebox` — tool parameter schemas
|
|
142
201
|
|
|
143
202
|
---
|
|
@@ -157,4 +216,4 @@ Direct npm dependencies (auto-installed):
|
|
|
157
216
|
|
|
158
217
|
## License
|
|
159
218
|
|
|
160
|
-
MIT — see [LICENSE](
|
|
219
|
+
MIT — see [LICENSE](https://github.com/GainForest/pi-simocracy/blob/main/LICENSE).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-simocracy",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Pi extension: load a Simocracy sim into your chat — see its pixel-art sprite render inline in the terminal and roleplay with it.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "David Dao <david@gainforest.earth> (https://github.com/daviddao)",
|
|
@@ -45,6 +45,7 @@
|
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"@atproto/api": "^0.19.11",
|
|
47
47
|
"@atproto/oauth-client-node": "^0.3.17",
|
|
48
|
+
"@jsquash/webp": "^1.5.0",
|
|
48
49
|
"pngjs": "^7.0.0",
|
|
49
50
|
"typebox": "^1.1.24"
|
|
50
51
|
},
|
package/src/auth/commands.ts
CHANGED
|
@@ -106,8 +106,8 @@ export async function runLogin(
|
|
|
106
106
|
|
|
107
107
|
ctx.ui.notify(
|
|
108
108
|
handleResolved
|
|
109
|
-
? `🔐 Signed in to ATProto as @${handleResolved} (${did}).
|
|
110
|
-
: `🔐 Signed in to ATProto as ${did}.
|
|
109
|
+
? `🔐 Signed in to ATProto as @${handleResolved} (${did}). Pi can now update the constitution / speaking style of any sim you own via the simocracy_update_sim tool — just load one of your sims with /sim my and ask pi for the change you want.`
|
|
110
|
+
: `🔐 Signed in to ATProto as ${did}. Pi can now update the constitution / speaking style of any sim you own via the simocracy_update_sim tool — just load one of your sims with /sim my and ask pi for the change you want.`,
|
|
111
111
|
"info",
|
|
112
112
|
);
|
|
113
113
|
} finally {
|
|
@@ -139,8 +139,8 @@ export async function runWhoami(ctx: ExtensionCommandContext): Promise<void> {
|
|
|
139
139
|
}
|
|
140
140
|
ctx.ui.notify(
|
|
141
141
|
auth.handle
|
|
142
|
-
? `Signed into ATProto as @${auth.handle} (${auth.did}) since ${auth.lastLogin}.
|
|
143
|
-
: `Signed into ATProto as ${auth.did} since ${auth.lastLogin}.
|
|
142
|
+
? `Signed into ATProto as @${auth.handle} (${auth.did}) since ${auth.lastLogin}. Pi can update the constitution / speaking style of any sim you own (loaded via /sim my) by calling the simocracy_update_sim tool.`
|
|
143
|
+
: `Signed into ATProto as ${auth.did} since ${auth.lastLogin}. Pi can update the constitution / speaking style of any sim you own (loaded via /sim my) by calling the simocracy_update_sim tool.`,
|
|
144
144
|
"info",
|
|
145
145
|
);
|
|
146
146
|
}
|