@zihanw/pi-forge 0.2.0 → 0.3.0
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 +154 -104
- package/README.zh-CN.md +151 -103
- package/examples/default-prompt-stack.json +52 -93
- package/examples/reviewer-prompt-stack.json +115 -0
- package/examples/sillytavern-dm-writer-prompt-stack.json +190 -0
- package/package.json +3 -8
- package/src/compiler.ts +546 -175
- package/src/index.ts +320 -660
- package/src/loader.ts +141 -56
- package/src/payload-capture.ts +85 -0
- package/src/policy.ts +42 -0
- package/src/regex.ts +500 -0
- package/src/sillytavern-importer.ts +404 -19
- package/src/stack-migration.ts +159 -0
- package/src/storage.ts +28 -0
- package/src/types.ts +80 -38
- package/src/web-editor/index.ts +2 -0
- package/src/web-editor/page.ts +2844 -0
- package/src/web-editor/server.ts +289 -0
- package/src/web-editor/types.ts +84 -0
- package/src/web-host.ts +229 -0
- package/src/web-editor.ts +0 -1491
package/README.md
CHANGED
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
[English](README.md) | [简体中文](README.zh-CN.md)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
**pi-forge** lets you customize how Pi thinks and behaves. It gives you prompt stacks — JSON files that can replace, append to, or prepend Pi's default system prompt while controlling the AI's personality, visible tools, conversation history layout, template variables, and prompt transforms.
|
|
6
8
|
|
|
7
9
|
Think of it as a character sheet for your AI agent.
|
|
8
10
|
|
|
@@ -11,7 +13,9 @@ Think of it as a character sheet for your AI agent.
|
|
|
11
13
|
- **Give Pi a personality** — turn it into a creative writer, a roleplay partner, a strict code reviewer, or anything in between.
|
|
12
14
|
- **Switch contexts instantly** — one command to swap between "coding mode", "writing mode", and "translation mode".
|
|
13
15
|
- **Control what the AI sees** — choose which tools, skills, and project context appear in each prompt.
|
|
14
|
-
- **
|
|
16
|
+
- **Limit tools and skills per stack** — enforce active tool policy and filter skill visibility for focused modes.
|
|
17
|
+
- **Use template variables** — define static values such as `{{char}}` / `{{user}}`, and use ST-style turn/session variable macros inside prompt text.
|
|
18
|
+
- **Transform outgoing and finalized text** — run deterministic regex replacements on selected history, compiled prompt text, or finalized assistant messages.
|
|
15
19
|
- **Import SillyTavern presets** — bring your existing ST character presets into Pi with one command.
|
|
16
20
|
- **Debug your prompts** — intercept and inspect exactly what gets sent to the model.
|
|
17
21
|
|
|
@@ -25,43 +29,17 @@ pi install npm:@zihanw/pi-forge
|
|
|
25
29
|
|
|
26
30
|
### Your first prompt stack
|
|
27
31
|
|
|
28
|
-
Create `.pi/prompt-stacks/default.json
|
|
32
|
+
Create `.pi/forge/prompt-stacks/default.json` from [examples/default-prompt-stack.json](examples/default-prompt-stack.json).
|
|
29
33
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
"autoActivate": true,
|
|
36
|
-
"mode": "replace",
|
|
37
|
-
"items": [
|
|
38
|
-
{
|
|
39
|
-
"kind": "block",
|
|
40
|
-
"id": "role",
|
|
41
|
-
"name": "Main Role",
|
|
42
|
-
"enabled": true,
|
|
43
|
-
"role": "system",
|
|
44
|
-
"content": "You are a friendly and concise coding assistant. Prefer short answers with code examples."
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
"kind": "slot",
|
|
48
|
-
"id": "tools",
|
|
49
|
-
"name": "Available Tools",
|
|
50
|
-
"enabled": true,
|
|
51
|
-
"role": "system",
|
|
52
|
-
"slot": "tools"
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
"kind": "slot",
|
|
56
|
-
"id": "chat-history",
|
|
57
|
-
"name": "Chat History",
|
|
58
|
-
"enabled": true,
|
|
59
|
-
"slot": "chat-history"
|
|
60
|
-
}
|
|
61
|
-
]
|
|
62
|
-
}
|
|
34
|
+
The default example mirrors Pi's own prompt builder from `@earendil-works/pi-coding-agent/dist/core/system-prompt.js`, but splits it into movable pi-forge slots: role, tools, guidelines, Pi docs guidance, appended system prompt text, project context, skills, date/cwd, and chat history.
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
mkdir -p .pi/forge/prompt-stacks
|
|
38
|
+
$EDITOR .pi/forge/prompt-stacks/default.json
|
|
63
39
|
```
|
|
64
40
|
|
|
41
|
+
Paste the example JSON into that file. If you are working inside this repository, you can copy it directly with `cp examples/default-prompt-stack.json .pi/forge/prompt-stacks/default.json`.
|
|
42
|
+
|
|
65
43
|
That's it. Restart Pi or run `/preset reload`. If no stack is already selected, `default.json` auto-activates. If you previously chose another stack or `/preset use none`, run `/preset use default`.
|
|
66
44
|
|
|
67
45
|
### Visual editor
|
|
@@ -72,13 +50,15 @@ Prefer clicking over typing JSON? pi-forge has a built-in web editor:
|
|
|
72
50
|
/preset ui
|
|
73
51
|
```
|
|
74
52
|
|
|
75
|
-
Drag, drop, edit, validate,
|
|
53
|
+
Drag, drop, edit, validate, inspect full previews and captured payloads, manage variables/context/regex rules in tabs, switch dark mode, recover through raw stack JSON, import, export, fork, and delete stacks — all in your browser. Stack metadata is collapsible so the active editor stays in view.
|
|
76
54
|
|
|
77
55
|
Import accepts native pi-forge stack JSON and SillyTavern preset JSON. SillyTavern presets are converted to prompt stacks automatically; if a preset contains multiple `character_id` configs, the editor asks which one to use.
|
|
78
56
|
|
|
79
|
-
The editor runs on `127.0.0.1
|
|
57
|
+
The editor runs on an available `127.0.0.1` port with a session token, so multiple Pi instances can run editors at the same time. If Pi reinitializes the extension after session navigation or a new session, `/preset ui` reuses the existing editor URL for the same project instead of orphaning the old server. Writes require a trusted project and stay inside prompt-stack storage. New stacks are written to `.pi/forge/prompt-stacks`; existing legacy stacks under `.pi/prompt-stacks` remain readable and editable. Successful save, import, fork, and delete actions reload into the current Pi session. Use `/preset ui restart` or `/preset ui stop` when needed.
|
|
58
|
+
|
|
59
|
+
To copy old stacks into the new location, run `/preset migrate-stacks`. Add `--dry-run` to preview, `--overwrite` to replace existing target files, and `--delete-legacy` to remove old files after successful copy.
|
|
80
60
|
|
|
81
|
-
To
|
|
61
|
+
To prefer a specific port, create `.pi/forge/config.json`. If that port is busy, pi-forge falls back to another available port and shows the actual URL:
|
|
82
62
|
|
|
83
63
|
```json
|
|
84
64
|
{
|
|
@@ -102,11 +82,11 @@ Useful pattern:
|
|
|
102
82
|
|
|
103
83
|
This keeps the latest request clear and avoids duplicating it.
|
|
104
84
|
|
|
105
|
-
For a
|
|
85
|
+
For a baseline stack to fork before turning Pi into a character, start from [examples/default-prompt-stack.json](examples/default-prompt-stack.json).
|
|
106
86
|
|
|
107
87
|
### 🧑💻 Focused code review
|
|
108
88
|
|
|
109
|
-
Create a `reviewer.json` stack with a strict review block: "prioritize correctness, regressions, security, and missing tests." Keep the `tools`, `project-context`, `variables`, and `chat-history` slots enabled so Pi can still inspect the repo and
|
|
89
|
+
Create a `reviewer.json` stack with a strict review block: "prioritize correctness, regressions, security, and missing tests." Keep the `tools`, `project-context`, `variables`, and `chat-history` slots enabled so Pi can still inspect the repo and see any template variables you expose.
|
|
110
90
|
|
|
111
91
|
Use `mode: "append"` if you want to keep Pi's normal coding behavior and only add the sharper review lens.
|
|
112
92
|
|
|
@@ -119,7 +99,7 @@ Create a small `translator.json` stack with one system block for tone and target
|
|
|
119
99
|
Create separate stacks for different tasks:
|
|
120
100
|
|
|
121
101
|
```
|
|
122
|
-
.pi/prompt-stacks/
|
|
102
|
+
.pi/forge/prompt-stacks/
|
|
123
103
|
coder.json # strict coding assistant
|
|
124
104
|
writer.json # creative writing partner
|
|
125
105
|
translator.json # bilingual translator
|
|
@@ -127,29 +107,35 @@ Create separate stacks for different tasks:
|
|
|
127
107
|
|
|
128
108
|
Switch with `/preset use coder`, `/preset use writer`, etc.
|
|
129
109
|
|
|
130
|
-
###
|
|
110
|
+
### 🧪 Presets that show off pi-forge
|
|
131
111
|
|
|
132
|
-
|
|
112
|
+
- **Pi mirror** — start from [examples/default-prompt-stack.json](examples/default-prompt-stack.json). It preserves normal Pi behavior while making every runtime section movable and inspectable.
|
|
113
|
+
- **Focused reviewer** — see [examples/reviewer-prompt-stack.json](examples/reviewer-prompt-stack.json). It denies file-writing tools, wraps prior chat history as background, removes the latest user message from history, then reinserts `{{lastUserMessage}}` as the explicit review target.
|
|
114
|
+
- **Read-only scout** — use `tools.allow` for `read`, `grep`, `find`, and `ls`; omit editing tools; cap `chat-history` with `maxChars`. Good for exploration turns where the model should report findings without changing files.
|
|
115
|
+
- **Surgical patcher** — keep the Pi mirror, require `read`, `edit`, and `bash`, strip assistant thinking from inserted history, and move `project-context` near the final user turn. Good for focused implementation passes.
|
|
116
|
+
- **SillyTavern DM writer** — see [examples/sillytavern-dm-writer-prompt-stack.json](examples/sillytavern-dm-writer-prompt-stack.json). It defines a Dungeon Master character with `{{char}}` / `{{user}}`, wraps prior adventure history, reinserts `{{lastUserMessage}}` as the current player action, and uses regex cleanup for OOC notes, secret-roll markers, dice notation, and `Player:` prefixes.
|
|
117
|
+
- **Payload lab** — include `active-model`, `date-cwd`, and variables slots, then add `compiled` regex rules for deterministic redaction or formatting. Pair it with `/payload next` or the web editor's capture view to audit exactly what changed.
|
|
118
|
+
- **Docs-only Pi expert** — allow only read/search tools, enable the `pi-docs` slot, and keep project context. Useful when you want answers grounded in the installed Pi docs instead of general memory.
|
|
119
|
+
|
|
120
|
+
### 🔧 Template variables
|
|
133
121
|
|
|
134
122
|
```json
|
|
135
|
-
"
|
|
136
|
-
"
|
|
137
|
-
|
|
138
|
-
"type": "string",
|
|
139
|
-
"scope": "session",
|
|
140
|
-
"description": "What we're working on",
|
|
141
|
-
"agentWritable": true
|
|
142
|
-
}
|
|
143
|
-
}
|
|
123
|
+
"variables": {
|
|
124
|
+
"char": "Konata",
|
|
125
|
+
"user": "User"
|
|
144
126
|
}
|
|
145
127
|
```
|
|
146
128
|
|
|
147
|
-
|
|
129
|
+
Use static variables for stable prompt constants, and ST-style macros for local prompt-time mutation:
|
|
148
130
|
|
|
149
131
|
```
|
|
150
|
-
|
|
132
|
+
{{setvar::mood::focused}}
|
|
133
|
+
{{getvar::mood}}
|
|
134
|
+
{{setsessionvar::topic::compiler cleanup}}
|
|
151
135
|
```
|
|
152
136
|
|
|
137
|
+
For durable project memory, use normal files in the repo rather than pi-forge prompt variables.
|
|
138
|
+
|
|
153
139
|
### 📦 SillyTavern migration
|
|
154
140
|
|
|
155
141
|
Bring your ST presets into Pi:
|
|
@@ -160,6 +146,8 @@ Bring your ST presets into Pi:
|
|
|
160
146
|
|
|
161
147
|
pi-forge converts the preset to a prompt stack and generates a migration report showing what was handled and what needs manual tweaking.
|
|
162
148
|
|
|
149
|
+
Deterministic SillyTavern `promptOnly` regex scripts are converted to pi-forge `regex.rules` as history-stage rules when they can be represented safely, including full-match token conversion, trim strings, depth fields, and clear user/assistant placements. Display-only, mixed prompt/display, DOM/browser, CSS/HTML decoration, JavaScript, unsupported placements, and invalid regex scripts stay report-only for manual review.
|
|
150
|
+
|
|
163
151
|
### 🔍 Prompt debugging
|
|
164
152
|
|
|
165
153
|
See exactly what gets sent to the model:
|
|
@@ -168,6 +156,8 @@ See exactly what gets sent to the model:
|
|
|
168
156
|
/payload next save=.pi/forge/payloads/last.json
|
|
169
157
|
```
|
|
170
158
|
|
|
159
|
+
Or open `/preset ui`, click **Arm payload**, send the next Pi prompt, and inspect the redacted provider payload in the browser.
|
|
160
|
+
|
|
171
161
|
Or preview your compiled prompt without sending anything:
|
|
172
162
|
|
|
173
163
|
```
|
|
@@ -188,6 +178,9 @@ Items are arranged in order. When the stack is active, pi-forge:
|
|
|
188
178
|
1. Builds a system prompt from your `system`-role blocks and slots, then applies it with the stack's `mode`.
|
|
189
179
|
2. Inserts `user`/`assistant` blocks and slots around the conversation history.
|
|
190
180
|
3. Expands `{{macros}}` like `{{lastUserMessage}}`, `{{date}}`, and custom variables.
|
|
181
|
+
4. Applies stack tool policy to Pi's active tool set and filters pi-forge-rendered tool/skill slots.
|
|
182
|
+
5. Applies enabled outgoing regex rules for the `history` and `compiled` stages.
|
|
183
|
+
6. Optionally applies destructive `finalize` regex rules when an assistant message finishes.
|
|
191
184
|
|
|
192
185
|
### Slots at a glance
|
|
193
186
|
|
|
@@ -198,7 +191,7 @@ Items are arranged in order. When the stack is active, pi-forge:
|
|
|
198
191
|
| `tool-guidelines` | Tool usage instructions |
|
|
199
192
|
| `skills` | Loaded Pi skills |
|
|
200
193
|
| `project-context` | Project instructions and context files |
|
|
201
|
-
| `variables` |
|
|
194
|
+
| `variables` | Static/session/turn template variables |
|
|
202
195
|
| `date` / `cwd` / `date-cwd` | Current date and working directory |
|
|
203
196
|
| `active-model` | Which model is being used |
|
|
204
197
|
| `append-system-prompt` | User's appended system prompt text |
|
|
@@ -224,26 +217,16 @@ Items are arranged in order. When the stack is active, pi-forge:
|
|
|
224
217
|
| `/preset status` | Show the active stack and diagnostics summary |
|
|
225
218
|
| `/preset diagnostics` | Show runtime diagnostics |
|
|
226
219
|
| `/preset reload` | Reload stacks from disk |
|
|
220
|
+
| `/preset migrate-stacks [--dry-run] [--overwrite] [--delete-legacy]` | Copy legacy `.pi/prompt-stacks` files into `.pi/forge/prompt-stacks` |
|
|
227
221
|
| `/preset ui [stop\|restart]` | Open, stop, or restart the web editor |
|
|
228
222
|
|
|
229
|
-
### State management
|
|
230
|
-
|
|
231
|
-
| Command | What it does |
|
|
232
|
-
|---------|-------------|
|
|
233
|
-
| `/state list` | Show all session state |
|
|
234
|
-
| `/state status` | Show state definitions and current values |
|
|
235
|
-
| `/state set <name> <value>` | Set a state variable |
|
|
236
|
-
| `/state get <name>` | Read a state variable |
|
|
237
|
-
| `/state clear [name]` | Clear state (all or by name) |
|
|
238
|
-
| `/preset vars ...` | Legacy variable commands kept for older stacks |
|
|
239
|
-
|
|
240
223
|
### Import & debug
|
|
241
224
|
|
|
242
225
|
| Command | What it does |
|
|
243
226
|
|---------|-------------|
|
|
244
227
|
| `/preset import-silly <path>` | Import a SillyTavern preset |
|
|
245
228
|
| `/intercept` | Show the next provider payload |
|
|
246
|
-
| `/payload next [save=<path>]` | Show and
|
|
229
|
+
| `/payload next [save=<path>]` | Show, save, and expose the next payload to the web editor |
|
|
247
230
|
|
|
248
231
|
## Common macros
|
|
249
232
|
|
|
@@ -313,71 +296,138 @@ Valid roles: `system`, `user`, `assistant`, `custom`.
|
|
|
313
296
|
|
|
314
297
|
```json
|
|
315
298
|
"options": {
|
|
316
|
-
"includeLastUserMessage": false
|
|
299
|
+
"includeLastUserMessage": false,
|
|
300
|
+
"stripAssistantThinking": true,
|
|
301
|
+
"includeSummaries": true,
|
|
302
|
+
"toolMode": "keep",
|
|
303
|
+
"roles": ["user", "assistant"],
|
|
304
|
+
"maxMessages": 40,
|
|
305
|
+
"maxChars": 20000
|
|
317
306
|
}
|
|
318
307
|
```
|
|
319
308
|
|
|
320
309
|
Set to `false` when you use `{{lastUserMessage}}` after the history — prevents the user's message from appearing twice.
|
|
321
310
|
|
|
322
|
-
|
|
311
|
+
Set `stripAssistantThinking` to `true` to remove prior assistant thinking blocks from inserted chat history. Visible assistant text, tool calls, and tool result messages are preserved. This only affects history inserted by that slot and does not alter the current agent loop or stored transcript.
|
|
312
|
+
|
|
313
|
+
Use `includeSummaries: false` to omit Pi branch/compaction summary messages, `roles` to keep only specific message roles, `toolMode: "drop"` to remove prior tool-call/tool-result history, and `maxMessages` / `maxChars` to keep only recent history. When filters or limits can break tool-call pairs, pi-forge removes dangling tool calls/results instead of sending inconsistent tool history.
|
|
314
|
+
|
|
315
|
+
### Structured slot format options
|
|
316
|
+
|
|
317
|
+
Structured runtime slots default to XML-style wrappers. Add `"format": "plain"` to `tools`, `tool-guidelines`, `skills`, `project-context`, or `variables` slots for compact newline-separated output.
|
|
323
318
|
|
|
324
319
|
```json
|
|
325
320
|
{
|
|
326
321
|
"kind": "slot",
|
|
327
|
-
"id": "
|
|
322
|
+
"id": "tools",
|
|
328
323
|
"enabled": true,
|
|
329
|
-
"role": "
|
|
330
|
-
"slot": "
|
|
324
|
+
"role": "system",
|
|
325
|
+
"slot": "tools",
|
|
331
326
|
"options": {
|
|
332
|
-
"
|
|
333
|
-
"includeNamespaces": ["user.*", "agent.*"],
|
|
334
|
-
"includeMetadata": true,
|
|
335
|
-
"format": "xml",
|
|
336
|
-
"maxValueChars": 1200
|
|
327
|
+
"format": "plain"
|
|
337
328
|
}
|
|
338
329
|
}
|
|
339
330
|
```
|
|
340
331
|
|
|
341
|
-
|
|
332
|
+
The default Pi mirror uses a few extra slot options:
|
|
342
333
|
|
|
343
334
|
```json
|
|
344
|
-
|
|
335
|
+
{
|
|
336
|
+
"slot": "tools",
|
|
337
|
+
"options": {
|
|
338
|
+
"format": "plain",
|
|
339
|
+
"onlyWithSnippets": true
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
`tools.onlyWithSnippets` matches Pi's default "Available tools" section by hiding tools that do not provide prompt snippets. `tool-guidelines.heading`, `tool-guidelines.includePiDefaultGuidelines`, and `tool-guidelines.piStyle` make the guidelines slot match Pi's default heading and bullets. `skills.requireReadTool` hides skills unless the read tool is active, matching Pi's default behavior.
|
|
345
|
+
|
|
346
|
+
### Tool and skill policy
|
|
347
|
+
|
|
348
|
+
Prompt stacks can constrain tools and skills with stack-level `allow` or `deny` lists. Patterns are exact by default and support `*` wildcards.
|
|
349
|
+
|
|
350
|
+
```json
|
|
351
|
+
{
|
|
352
|
+
"tools": {
|
|
353
|
+
"allow": ["read", "bash"]
|
|
354
|
+
},
|
|
355
|
+
"skills": {
|
|
356
|
+
"deny": ["browser-danger"]
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
Use `allow` when only matching tools or skills should remain active. Use `deny` when everything except matching tools or skills should remain active. A single resource policy cannot contain both non-empty lists; mixed `allow` and `deny` entries are validation errors.
|
|
362
|
+
|
|
363
|
+
Tool policy is enforced through Pi's active tool list while the stack is active. pi-forge remembers the previous active tools and restores them when prompt stacks are disabled or switched to an unrestricted stack.
|
|
364
|
+
|
|
365
|
+
Skill policy filters skills rendered by pi-forge's `skills` slot. If a stack uses `mode: "append"` or `"prepend"`, Pi's base prompt may already contain unfiltered skills; use `mode: "replace"` when skill visibility must be controlled.
|
|
366
|
+
|
|
367
|
+
### Regex transforms
|
|
368
|
+
|
|
369
|
+
Prompt stacks can run deterministic regex replacements on model-bound prompt text and, optionally, finalized assistant messages. Outgoing rules support `history` and `compiled` stages. Destructive final-message cleanup uses `effect: "finalize"` at `stage: "compiled"` with the `messages` target. True display-only streaming transforms and provider-payload rewrites are not active yet.
|
|
370
|
+
|
|
371
|
+
```json
|
|
372
|
+
"regex": {
|
|
345
373
|
"schemaVersion": 1,
|
|
346
|
-
"
|
|
347
|
-
|
|
348
|
-
"
|
|
349
|
-
"
|
|
350
|
-
"
|
|
351
|
-
"
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
"
|
|
355
|
-
"
|
|
356
|
-
"
|
|
357
|
-
"userWritable": true
|
|
374
|
+
"rules": [
|
|
375
|
+
{
|
|
376
|
+
"id": "trim-ooc",
|
|
377
|
+
"enabled": true,
|
|
378
|
+
"stage": "history",
|
|
379
|
+
"effect": "outgoing",
|
|
380
|
+
"pattern": "\\(OOC:[^)]+\\)",
|
|
381
|
+
"flags": "gi",
|
|
382
|
+
"replace": "",
|
|
383
|
+
"roles": ["assistant"],
|
|
384
|
+
"maxMessages": 20
|
|
358
385
|
}
|
|
359
|
-
|
|
386
|
+
]
|
|
360
387
|
}
|
|
361
388
|
```
|
|
362
389
|
|
|
363
|
-
|
|
390
|
+
Use `stage: "history"` to transform messages inserted by the `chat-history` slot. Use `stage: "compiled"` with optional `targets: ["system"]`, `["messages"]`, or both to transform the final compiled prompt. Message rules can filter by `roles`, `maxMessages`, `maxChars`, `minDepth`, and `maxDepth`, where depth `0` is the latest message. Replacements use JavaScript syntax (`$&` for the full match, `$1` for captures; `$0` is also accepted as a full-match alias, and `$$` escapes a literal `$`). `trimStrings` removes literal strings from expanded replacement matches/captures, matching SillyTavern's Trim Out behavior. Supported regex flags are `g`, `i`, `m`, `s`, and `u`.
|
|
364
391
|
|
|
365
|
-
|
|
392
|
+
To clean a completed assistant message after streaming, use `effect: "finalize"`:
|
|
366
393
|
|
|
367
|
-
|
|
394
|
+
```json
|
|
395
|
+
{
|
|
396
|
+
"id": "finalize-ooc",
|
|
397
|
+
"enabled": true,
|
|
398
|
+
"stage": "compiled",
|
|
399
|
+
"effect": "finalize",
|
|
400
|
+
"targets": ["messages"],
|
|
401
|
+
"roles": ["assistant"],
|
|
402
|
+
"pattern": "\\s*\\(OOC:[^)]+\\)",
|
|
403
|
+
"flags": "gi",
|
|
404
|
+
"replace": ""
|
|
405
|
+
}
|
|
406
|
+
```
|
|
368
407
|
|
|
369
|
-
|
|
408
|
+
Warning: `finalize` runs at `message_end`, after raw output may already have streamed in the TUI. It returns a cleaned replacement message to Pi, so the original model output is not preserved in the stored transcript.
|
|
370
409
|
|
|
371
|
-
|
|
410
|
+
`effect: "outgoing"` changes model input. `effect: "finalize"` changes finalized assistant transcript content. `effect: "display"` and `"both"` validate with warnings but are ignored at runtime until true display transforms are implemented.
|
|
372
411
|
|
|
373
|
-
-
|
|
374
|
-
- Open questions (`agent.openQuestions`)
|
|
375
|
-
- Story state (`agent.storyState`)
|
|
376
|
-
- User-requested notes (`agent.notes`)
|
|
412
|
+
SillyTavern imports convert deterministic prompt-only `{{match}}` / `$0` full-match replacements to JavaScript `$&` (both `$0` and `$&` work in pi-forge), preserve original regex metadata in `source.sillytavern`, and run as history-stage rules so depth stays chat-relative. Display-only/browser/unsupported-placement scripts stay report-only. The web editor has a structured Regex dialog for these rule fields and preserves advanced unknown fields for raw JSON editing.
|
|
377
413
|
|
|
378
|
-
###
|
|
414
|
+
### Variables slot options
|
|
379
415
|
|
|
380
|
-
|
|
416
|
+
```json
|
|
417
|
+
{
|
|
418
|
+
"kind": "slot",
|
|
419
|
+
"id": "variables",
|
|
420
|
+
"enabled": true,
|
|
421
|
+
"role": "user",
|
|
422
|
+
"slot": "variables",
|
|
423
|
+
"options": {
|
|
424
|
+
"includeStatic": true,
|
|
425
|
+
"includeSession": true,
|
|
426
|
+
"includeTurn": false,
|
|
427
|
+
"format": "xml"
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
```
|
|
381
431
|
|
|
382
432
|
## Package setup for development
|
|
383
433
|
|