risupack 0.1.4 → 0.2.2
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
CHANGED
|
@@ -1,63 +1,97 @@
|
|
|
1
1
|
# risupack
|
|
2
2
|
|
|
3
|
-
A
|
|
3
|
+
A command-line tool and TypeScript library for building RisuAI CharX modules, unpacking CharX and RisuM files, bundling Lua, and inspecting RisuSave databases.
|
|
4
|
+
|
|
5
|
+
## Requirements
|
|
6
|
+
|
|
7
|
+
- Node.js 20 or later
|
|
4
8
|
|
|
5
9
|
## Installation
|
|
6
10
|
|
|
11
|
+
Install risupack in the project that contains the module sources.
|
|
12
|
+
|
|
7
13
|
```sh
|
|
8
14
|
npm install --save-dev risupack
|
|
9
15
|
```
|
|
10
16
|
|
|
11
|
-
|
|
17
|
+
Run the local installation with `npx risupack`.
|
|
18
|
+
|
|
19
|
+
## New modules
|
|
20
|
+
|
|
21
|
+
A module without character prompts needs only a manifest.
|
|
22
|
+
|
|
23
|
+
```text
|
|
24
|
+
sample-module/
|
|
25
|
+
└── charx.json
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
```json
|
|
29
|
+
{
|
|
30
|
+
"description": "Sample module",
|
|
31
|
+
"name": "Sample Module",
|
|
32
|
+
"namespace": "sample-module",
|
|
33
|
+
"version": "1.0.0"
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Build the CharX from the manifest.
|
|
12
38
|
|
|
13
39
|
```sh
|
|
14
|
-
risupack build-charx
|
|
15
|
-
risupack bundle-lua <entry.lua> <output.lua>
|
|
16
|
-
risupack inspect-risusave <database.bin> [namespace-or-name]
|
|
17
|
-
risupack unpack-charx <input.charx> [output-directory]
|
|
18
|
-
risupack unpack-risum <input.risum> [output-directory]
|
|
40
|
+
npx risupack build-charx sample-module/charx.json
|
|
19
41
|
```
|
|
20
42
|
|
|
21
|
-
|
|
43
|
+
Without `output`, the command writes `../dist/<name>.charx` relative to the manifest directory.
|
|
44
|
+
|
|
45
|
+
Add lorebooks, regexes, triggers, CSS, toggles, assets, or character prompts only when the module needs them. Reference each source from `charx.json`.
|
|
46
|
+
|
|
47
|
+
## Existing modules
|
|
48
|
+
|
|
49
|
+
Unpack an existing CharX into editable sources.
|
|
22
50
|
|
|
23
51
|
```sh
|
|
24
|
-
|
|
52
|
+
npx risupack unpack-charx character.charx character
|
|
25
53
|
```
|
|
26
54
|
|
|
27
|
-
|
|
55
|
+
Both unpack commands require an absent or empty output directory. When the output argument is omitted, each command uses the input filename without its extension.
|
|
28
56
|
|
|
29
|
-
|
|
57
|
+
Edit the generated sources and rebuild from the generated manifest.
|
|
30
58
|
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
59
|
+
```sh
|
|
60
|
+
npx risupack build-charx character/charx.json
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Use `unpack-risum` for a standalone RisuM file.
|
|
64
|
+
|
|
65
|
+
```sh
|
|
66
|
+
npx risupack unpack-risum module.risum module
|
|
37
67
|
```
|
|
38
68
|
|
|
39
|
-
|
|
69
|
+
The generated `charx.json` can be passed to `build-charx` to package the recovered module as a CharX.
|
|
40
70
|
|
|
41
|
-
|
|
71
|
+
## Source layout
|
|
72
|
+
|
|
73
|
+
All manifest paths, including `output` and `bundleOutput`, are relative to `charx.json`. A generated source directory can contain the following files when the module uses the corresponding features.
|
|
42
74
|
|
|
43
75
|
```text
|
|
44
|
-
<
|
|
76
|
+
<module>/
|
|
77
|
+
├── alternate_greetings/
|
|
45
78
|
├── assets/
|
|
46
79
|
├── lorebooks/
|
|
47
80
|
├── regex/
|
|
48
|
-
├── styles/
|
|
49
81
|
├── triggers/
|
|
82
|
+
├── card.json
|
|
50
83
|
├── charx.json
|
|
84
|
+
├── description.md
|
|
85
|
+
├── first_mes.md
|
|
86
|
+
├── style.html
|
|
51
87
|
└── toggles.txt
|
|
52
88
|
```
|
|
53
89
|
|
|
54
|
-
|
|
90
|
+
The builder accepts other layouts. Update the paths in `charx.json` after moving a source file.
|
|
55
91
|
|
|
56
|
-
## Manifest
|
|
92
|
+
## Manifest
|
|
57
93
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
Use the following manifest structure.
|
|
94
|
+
`name` is the only field enforced as required. Set a stable `namespace` for module identity and lookup.
|
|
61
95
|
|
|
62
96
|
```json
|
|
63
97
|
{
|
|
@@ -68,120 +102,158 @@ Use the following manifest structure.
|
|
|
68
102
|
"name": "background"
|
|
69
103
|
}
|
|
70
104
|
],
|
|
71
|
-
"
|
|
105
|
+
"creator": "Creator",
|
|
72
106
|
"description": "Module description",
|
|
107
|
+
"folders": ["Internal"],
|
|
73
108
|
"hideIcon": false,
|
|
74
109
|
"icon": "assets/icon.png",
|
|
110
|
+
"license": "AGPL-3.0-only",
|
|
75
111
|
"lorebook": [
|
|
76
112
|
{
|
|
77
113
|
"alwaysActive": false,
|
|
78
|
-
"comment": "
|
|
114
|
+
"comment": "Sample",
|
|
79
115
|
"file": "lorebooks/sample.md",
|
|
80
|
-
"folder": "
|
|
116
|
+
"folder": "Internal",
|
|
81
117
|
"insertOrder": 100,
|
|
82
|
-
"key": "",
|
|
118
|
+
"key": "sample",
|
|
83
119
|
"mode": "normal",
|
|
84
120
|
"secondaryKey": "",
|
|
85
121
|
"selective": false,
|
|
86
122
|
"useRegex": false
|
|
87
123
|
}
|
|
88
124
|
],
|
|
89
|
-
"lowLevelAccess":
|
|
125
|
+
"lowLevelAccess": false,
|
|
90
126
|
"name": "Sample Module",
|
|
91
|
-
"namespace": "sample",
|
|
127
|
+
"namespace": "sample-module",
|
|
128
|
+
"output": "../dist/sample-module.charx",
|
|
92
129
|
"regex": ["regex/display.md"],
|
|
130
|
+
"tags": ["utility"],
|
|
93
131
|
"toggles": "toggles.txt",
|
|
94
132
|
"triggers": [
|
|
95
133
|
{
|
|
96
134
|
"bundle": true,
|
|
97
|
-
"
|
|
98
|
-
"
|
|
135
|
+
"comment": "Start",
|
|
136
|
+
"lowLevelAccess": false,
|
|
137
|
+
"lua": "triggers/main.lua",
|
|
138
|
+
"type": "start"
|
|
99
139
|
}
|
|
100
140
|
],
|
|
101
141
|
"version": "1.0.0"
|
|
102
142
|
}
|
|
103
143
|
```
|
|
104
144
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
- `
|
|
108
|
-
- `
|
|
109
|
-
- `
|
|
110
|
-
- `
|
|
111
|
-
- `
|
|
112
|
-
- `
|
|
113
|
-
- `
|
|
114
|
-
- `
|
|
115
|
-
- `
|
|
116
|
-
- `
|
|
117
|
-
- `
|
|
118
|
-
- `
|
|
119
|
-
- `
|
|
120
|
-
- `
|
|
121
|
-
- `
|
|
122
|
-
- `
|
|
123
|
-
- `
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
`CSS`, `toggles`, and lorebook sources accept a path string, a file object, or inline content.
|
|
145
|
+
- `CSS`: CSS or HTML source inserted into the RisuAI background HTML field
|
|
146
|
+
- `assets`: Additional files packaged as RisuAI assets
|
|
147
|
+
- `card`: Optional character card sources
|
|
148
|
+
- `creator`: Creator name
|
|
149
|
+
- `description`: Package description stored as creator notes
|
|
150
|
+
- `folders`: Lorebook folders to create even when no entry references them
|
|
151
|
+
- `hideIcon`: Whether RisuAI hides the module icon in chat, defaulting to `false`
|
|
152
|
+
- `icon`: Main module icon; omission creates a transparent placeholder icon
|
|
153
|
+
- `license`: Package license identifier or text
|
|
154
|
+
- `lorebook`: Lorebook entries
|
|
155
|
+
- `lowLevelAccess`: Module-level low-level access, defaulting to `false`
|
|
156
|
+
- `name`: Required non-empty module name
|
|
157
|
+
- `namespace`: Module namespace
|
|
158
|
+
- `output`: Default CharX output path
|
|
159
|
+
- `regex`: Regex entries in execution order
|
|
160
|
+
- `tags`: Package tags, defaulting to an empty array
|
|
161
|
+
- `toggles`: Module toggle source
|
|
162
|
+
- `triggers`: Trigger entries
|
|
163
|
+
- `version`: Package version
|
|
164
|
+
|
|
165
|
+
## Text sources
|
|
166
|
+
|
|
167
|
+
CSS, toggles, lorebook contents, and external character text fields accept a path string or an object containing `file` or `content`.
|
|
130
168
|
|
|
131
169
|
```json
|
|
132
170
|
{
|
|
133
|
-
"CSS": "
|
|
134
|
-
"toggles": { "file": "toggles.txt" },
|
|
171
|
+
"CSS": "style.html",
|
|
135
172
|
"lorebook": [
|
|
136
173
|
{
|
|
137
|
-
"comment": "
|
|
174
|
+
"comment": "Inline",
|
|
138
175
|
"content": "Inline lorebook content"
|
|
139
176
|
}
|
|
140
|
-
]
|
|
177
|
+
],
|
|
178
|
+
"toggles": {
|
|
179
|
+
"file": "toggles.txt"
|
|
180
|
+
}
|
|
141
181
|
}
|
|
142
182
|
```
|
|
143
183
|
|
|
144
|
-
|
|
184
|
+
`content` takes precedence when an object contains both `content` and `file`. Bundled Lua lorebooks require `file`.
|
|
145
185
|
|
|
146
|
-
##
|
|
186
|
+
## Character sources
|
|
147
187
|
|
|
148
|
-
|
|
149
|
-
- `content`: Inline lorebook source.
|
|
150
|
-
- `comment`: Lorebook name. Defaults to the source file basename.
|
|
151
|
-
- `alwaysActive`: Enables constant activation. Defaults to `false`.
|
|
152
|
-
- `activationPercent`: RisuAI activation percentage.
|
|
153
|
-
- `folder`: Display folder name. The builder creates referenced folders automatically.
|
|
154
|
-
- `insertOrder`: Lorebook insertion order. Defaults to `100`.
|
|
155
|
-
- `key`: Comma-separated primary activation keys. Defaults to an empty string.
|
|
156
|
-
- `secondaryKey`: Comma-separated secondary activation keys. Defaults to an empty string.
|
|
157
|
-
- `selective`: Enables secondary-key matching. Defaults to `false`.
|
|
158
|
-
- `mode`: RisuAI lorebook mode. Defaults to `normal`.
|
|
159
|
-
- `useRegex`: Treats activation keys as regular expressions when `true`. Defaults to `false`.
|
|
160
|
-
- `extentions`: RisuAI-specific lorebook extension values. Use this exact spelling.
|
|
161
|
-
- `bundle`: Bundles the Lua source and its `require()` dependencies when `true`. Defaults to `false`.
|
|
162
|
-
- `bundleOutput`: Optional path for retaining the bundled Lua artifact.
|
|
188
|
+
Omit `card` when the module has no character-specific prompts or settings.
|
|
163
189
|
|
|
164
|
-
|
|
190
|
+
Use a card source object to keep the character description and greetings in separate Markdown files.
|
|
191
|
+
|
|
192
|
+
```json
|
|
193
|
+
{
|
|
194
|
+
"card": {
|
|
195
|
+
"alternate_greetings": ["alternate_greetings/1.md", "alternate_greetings/2.md"],
|
|
196
|
+
"description": "description.md",
|
|
197
|
+
"file": "card.json",
|
|
198
|
+
"first_mes": "first_mes.md"
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
- `alternate_greetings`: Alternate greeting sources in display order
|
|
204
|
+
- `description`: Character description source
|
|
205
|
+
- `file`: Optional JSON source for other character card fields
|
|
206
|
+
- `first_mes`: First message source
|
|
165
207
|
|
|
166
|
-
|
|
208
|
+
When `file` is omitted, the builder starts from an empty character card. A referenced `card.json` may contain `{}` when all required character content is stored in the external text files. Put other Character Card fields under `data`.
|
|
167
209
|
|
|
168
|
-
|
|
169
|
-
- `bundle`: Bundles the entry file and its `require()` dependencies. Defaults to `true`.
|
|
170
|
-
- `bundleOutput`: Optional path for retaining the bundled Lua artifact.
|
|
171
|
-
- `comment`: Trigger name. Defaults to an empty string.
|
|
172
|
-
- `lowLevelAccess`: Enables low-level access for the trigger.
|
|
210
|
+
The unpack commands create character sources only when the packaged card contains character-specific values.
|
|
173
211
|
|
|
174
|
-
|
|
212
|
+
## Lorebooks
|
|
213
|
+
|
|
214
|
+
Each lorebook entry accepts the following fields.
|
|
215
|
+
|
|
216
|
+
- `activationPercent`: RisuAI activation percentage
|
|
217
|
+
- `alwaysActive`: Constant activation, defaulting to `false`
|
|
218
|
+
- `bookVersion`: Lorebook format version, defaulting to `2`
|
|
219
|
+
- `bundle`: Whether to bundle a Lua source and its `require()` dependencies, defaulting to `false`
|
|
220
|
+
- `bundleOutput`: Optional path that retains the bundled Lua output
|
|
221
|
+
- `comment`: Lorebook name, defaulting to the source filename
|
|
222
|
+
- `content`: Inline lorebook content
|
|
223
|
+
- `extentions`: RisuAI-specific lorebook extension values; retain this spelling
|
|
224
|
+
- `file`: Lorebook source path, required unless `content` is present
|
|
225
|
+
- `folder`: RisuAI lorebook folder name
|
|
226
|
+
- `insertOrder`: Insertion order, defaulting to `100`
|
|
227
|
+
- `key`: Comma-separated primary activation keys, defaulting to an empty string
|
|
228
|
+
- `mode`: RisuAI lorebook mode, defaulting to `normal`
|
|
229
|
+
- `secondaryKey`: Comma-separated secondary activation keys, defaulting to an empty string
|
|
230
|
+
- `selective`: Secondary-key matching, defaulting to `false`
|
|
231
|
+
- `useRegex`: Regular expression matching for activation keys, defaulting to `false`
|
|
232
|
+
|
|
233
|
+
Set `bundle` to `true` when the packaged lorebook must contain bundled Lua instead of the Lua entry source.
|
|
234
|
+
|
|
235
|
+
```json
|
|
236
|
+
{
|
|
237
|
+
"lorebook": [
|
|
238
|
+
{
|
|
239
|
+
"alwaysActive": false,
|
|
240
|
+
"bundle": true,
|
|
241
|
+
"comment": "Renderer",
|
|
242
|
+
"file": "lorebooks/renderer.lua",
|
|
243
|
+
"insertOrder": 200
|
|
244
|
+
}
|
|
245
|
+
]
|
|
246
|
+
}
|
|
247
|
+
```
|
|
175
248
|
|
|
176
|
-
|
|
249
|
+
Omit `bundleOutput` during normal builds. The builder removes its temporary bundle after packaging.
|
|
177
250
|
|
|
178
|
-
##
|
|
251
|
+
## Regexes
|
|
179
252
|
|
|
180
|
-
Store one regex entry in each Markdown file.
|
|
253
|
+
Store one file-based regex entry in each Markdown file.
|
|
181
254
|
|
|
182
255
|
```md
|
|
183
256
|
---
|
|
184
|
-
ableFlag: true
|
|
185
257
|
comment: Display
|
|
186
258
|
flag: gs
|
|
187
259
|
type: editdisplay
|
|
@@ -193,19 +265,18 @@ OUT:
|
|
|
193
265
|
replacement
|
|
194
266
|
```
|
|
195
267
|
|
|
196
|
-
|
|
268
|
+
The frontmatter accepts `comment`, `flag`, and `type`. The generated RisuAI `ableFlag` value is `true` when `flag` is present and `false` when `flag` is absent. Leave the content after `OUT:` empty for an empty replacement.
|
|
197
269
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
Regex entries accept a file path, a file object, or an inline object.
|
|
270
|
+
Manifest entries accept a path, an object containing `file`, or inline regex data.
|
|
201
271
|
|
|
202
272
|
```json
|
|
203
273
|
{
|
|
204
274
|
"regex": [
|
|
205
275
|
"regex/display.md",
|
|
206
|
-
{ "file": "regex/request.md" },
|
|
207
276
|
{
|
|
208
|
-
"
|
|
277
|
+
"file": "regex/request.md"
|
|
278
|
+
},
|
|
279
|
+
{
|
|
209
280
|
"comment": "Inline",
|
|
210
281
|
"flag": "gs",
|
|
211
282
|
"in": "input pattern",
|
|
@@ -216,28 +287,127 @@ Regex entries accept a file path, a file object, or an inline object.
|
|
|
216
287
|
}
|
|
217
288
|
```
|
|
218
289
|
|
|
219
|
-
Inline
|
|
290
|
+
Inline entries require string values for `in` and `out`. The presence of `flag` also controls `ableFlag` for inline entries. `comment` defaults to an empty string, and `type` defaults to `editdisplay`.
|
|
220
291
|
|
|
221
|
-
##
|
|
292
|
+
## Lua triggers
|
|
293
|
+
|
|
294
|
+
Set `lua` to an unbundled Lua entry file.
|
|
295
|
+
|
|
296
|
+
```json
|
|
297
|
+
{
|
|
298
|
+
"triggers": [
|
|
299
|
+
{
|
|
300
|
+
"bundle": true,
|
|
301
|
+
"comment": "Start",
|
|
302
|
+
"conditions": [],
|
|
303
|
+
"lowLevelAccess": false,
|
|
304
|
+
"lua": "triggers/main.lua",
|
|
305
|
+
"type": "start"
|
|
306
|
+
}
|
|
307
|
+
]
|
|
308
|
+
}
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
- `bundle`: Whether to bundle `require()` dependencies, defaulting to `true`
|
|
312
|
+
- `bundleOutput`: Optional path that retains the bundled Lua output
|
|
313
|
+
- `comment`: Trigger name, defaulting to an empty string
|
|
314
|
+
- `conditions`: RisuAI trigger conditions, defaulting to an empty array
|
|
315
|
+
- `lowLevelAccess`: Trigger-level low-level access
|
|
316
|
+
- `lua`: Lua entry file
|
|
317
|
+
- `type`: RisuAI trigger type, defaulting to `start`
|
|
318
|
+
|
|
319
|
+
The bundler resolves `require("lib.example")` as `lib/example.lua` relative to the Lua entry file's directory. Omit `bundleOutput` during normal builds to use a temporary bundle.
|
|
320
|
+
|
|
321
|
+
A trigger without `lua` must provide a RisuAI `effect` array directly. This form preserves triggers that cannot be represented as one Lua effect.
|
|
322
|
+
|
|
323
|
+
## CSS and toggles
|
|
324
|
+
|
|
325
|
+
risupack copies CSS and toggle sources into the package without changing their contents.
|
|
326
|
+
|
|
327
|
+
Wrap custom styles in a `<style>` element.
|
|
222
328
|
|
|
223
|
-
|
|
329
|
+
```html
|
|
330
|
+
<style>
|
|
331
|
+
.sample-panel {
|
|
332
|
+
color: white;
|
|
333
|
+
}
|
|
334
|
+
</style>
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
Write one toggle definition per line.
|
|
224
338
|
|
|
225
|
-
|
|
339
|
+
```text
|
|
340
|
+
enabled=Enable feature
|
|
341
|
+
theme=Theme=select=Light,Dark
|
|
342
|
+
label=Label=text
|
|
343
|
+
```
|
|
226
344
|
|
|
227
|
-
|
|
345
|
+
Checkbox values omit the type. Select values use `select` followed by comma-separated options. Text values use `text`.
|
|
228
346
|
|
|
229
347
|
## Assets
|
|
230
348
|
|
|
231
|
-
List additional packaged files in
|
|
349
|
+
List additional packaged files in `assets`.
|
|
232
350
|
|
|
233
|
-
- `
|
|
234
|
-
- `
|
|
235
|
-
- `
|
|
351
|
+
- `extension`: Packaged extension without a leading dot; defaults to the lowercase source extension and accepts ASCII letters and digits
|
|
352
|
+
- `file`: Required asset source path
|
|
353
|
+
- `name`: RisuAI asset name, defaulting to the source filename without its extension
|
|
236
354
|
|
|
237
|
-
|
|
355
|
+
The builder sanitizes unsupported archive filename characters and adds numeric suffixes for collisions.
|
|
356
|
+
|
|
357
|
+
## Reproducible builds
|
|
358
|
+
|
|
359
|
+
Set `SOURCE_DATE_EPOCH` to a Unix timestamp to fix timestamps in the generated card and ZIP entries.
|
|
360
|
+
|
|
361
|
+
```sh
|
|
362
|
+
SOURCE_DATE_EPOCH=1700000000 npx risupack build-charx module/charx.json
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
Identical inputs and a fixed source date produce byte-identical CharX files.
|
|
366
|
+
|
|
367
|
+
## CharX contents
|
|
368
|
+
|
|
369
|
+
A built CharX contains the generated card, encoded module, assets, and asset metadata.
|
|
370
|
+
|
|
371
|
+
```text
|
|
372
|
+
module.charx
|
|
373
|
+
├── assets/
|
|
374
|
+
├── x_meta/
|
|
375
|
+
├── card.json
|
|
376
|
+
└── module.risum
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
The archive always contains `card.json`, `module.risum`, and a main icon. The source manifest does not require a `card` or `icon` field.
|
|
380
|
+
|
|
381
|
+
## Utility commands
|
|
382
|
+
|
|
383
|
+
Bundle a standalone Lua entry file.
|
|
384
|
+
|
|
385
|
+
```sh
|
|
386
|
+
npx risupack bundle-lua triggers/main.lua dist/main.lua
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
The command writes one Lua file containing resolved `require()` dependencies and the entry code.
|
|
390
|
+
|
|
391
|
+
Inspect the module records stored in a RisuSave database.
|
|
392
|
+
|
|
393
|
+
```sh
|
|
394
|
+
npx risupack inspect-risusave database.bin
|
|
395
|
+
npx risupack inspect-risusave database.bin module-namespace
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
The optional query matches a module namespace, name, or ID. The command writes the matching records as JSON to standard output.
|
|
238
399
|
|
|
239
400
|
## Programmatic API
|
|
240
401
|
|
|
402
|
+
Import commands from the package root.
|
|
403
|
+
|
|
404
|
+
```ts
|
|
405
|
+
import { buildCharX, unpackCharX } from "risupack";
|
|
406
|
+
|
|
407
|
+
buildCharX("module/charx.json", "dist/module.charx");
|
|
408
|
+
unpackCharX("dist/module.charx", "module-unpacked");
|
|
409
|
+
```
|
|
410
|
+
|
|
241
411
|
The package exports `buildCharX()`, `bundleLua()`, `createExpandedModuleSources()`, `decodeModule()`, `parseModuleBlock()`, `parseZIP()`, `unpackCharX()`, and `unpackRisuM()`.
|
|
242
412
|
|
|
243
413
|
## License
|
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as unpackCharX, c as bundleLua, o as parseModuleBlock, s as buildCharX, t as unpackRisuM } from "./unpack-risum-
|
|
2
|
+
import { a as unpackCharX, c as bundleLua, o as parseModuleBlock, s as buildCharX, t as unpackRisuM } from "./unpack-risum-tckgp4pg.js";
|
|
3
3
|
import { readFileSync } from "node:fs";
|
|
4
4
|
import { join, parse } from "node:path";
|
|
5
5
|
//#region src/cli.ts
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as unpackCharX, c as bundleLua, i as parseZIP, n as createExpandedModuleSources, o as parseModuleBlock, r as decodeModule, s as buildCharX, t as unpackRisuM } from "./unpack-risum-
|
|
1
|
+
import { a as unpackCharX, c as bundleLua, i as parseZIP, n as createExpandedModuleSources, o as parseModuleBlock, r as decodeModule, s as buildCharX, t as unpackRisuM } from "./unpack-risum-tckgp4pg.js";
|
|
2
2
|
export { buildCharX, bundleLua, createExpandedModuleSources, decodeModule, parseModuleBlock, parseZIP, unpackCharX, unpackRisuM };
|
|
@@ -159,6 +159,20 @@ function readSource(manifestDirectory, source, label) {
|
|
|
159
159
|
assert$2(typeof source.file === "string", `${label}.file must be a string`);
|
|
160
160
|
return fs.readFileSync(path.resolve(manifestDirectory, source.file), "utf8");
|
|
161
161
|
}
|
|
162
|
+
function readCard(manifest, manifestDirectory) {
|
|
163
|
+
if (!manifest.card) return;
|
|
164
|
+
if (typeof manifest.card === "string") return JSON.parse(readSource(manifestDirectory, manifest.card, "card"));
|
|
165
|
+
const card = "content" in manifest.card || "file" in manifest.card ? JSON.parse(readSource(manifestDirectory, manifest.card, "card")) : {};
|
|
166
|
+
const data = card.data ?? {};
|
|
167
|
+
if (manifest.card.alternate_greetings !== void 0) {
|
|
168
|
+
assert$2(Array.isArray(manifest.card.alternate_greetings), "card.alternate_greetings must be an array");
|
|
169
|
+
data.alternate_greetings = manifest.card.alternate_greetings.map((source, index) => readSource(manifestDirectory, source, `card.alternate_greetings[${index}]`));
|
|
170
|
+
}
|
|
171
|
+
if (manifest.card.description !== void 0) data.description = readSource(manifestDirectory, manifest.card.description, "card.description");
|
|
172
|
+
if (manifest.card.first_mes !== void 0) data.first_mes = readSource(manifestDirectory, manifest.card.first_mes, "card.first_mes");
|
|
173
|
+
card.data = data;
|
|
174
|
+
return card;
|
|
175
|
+
}
|
|
162
176
|
function sanitizeArchiveName(name) {
|
|
163
177
|
return Array.from(name, (character) => character.charCodeAt(0) < 32 ? "_" : character).join("").replace(/[<>:"/\\|?*]/g, "_").trim().slice(0, 100) || "asset";
|
|
164
178
|
}
|
|
@@ -205,7 +219,7 @@ function parseRegexDocument(content, fileName) {
|
|
|
205
219
|
const { body, metadata } = parseFrontmatter(content, fileName);
|
|
206
220
|
const parsed = parseRegexBody(body, fileName);
|
|
207
221
|
return {
|
|
208
|
-
ableFlag: metadata.
|
|
222
|
+
ableFlag: metadata.flag !== void 0,
|
|
209
223
|
comment: metadata.comment ?? "",
|
|
210
224
|
flag: metadata.flag,
|
|
211
225
|
in: parsed.in,
|
|
@@ -223,7 +237,7 @@ function buildRegexScripts(manifestDirectory, regexGroups = []) {
|
|
|
223
237
|
if (group.in !== void 0 || group.out !== void 0) {
|
|
224
238
|
assert$2(typeof group.in === "string" && typeof group.out === "string", "Inline regex entries require in and out");
|
|
225
239
|
scripts.push({
|
|
226
|
-
ableFlag: group.
|
|
240
|
+
ableFlag: group.flag !== void 0,
|
|
227
241
|
comment: group.comment ?? "",
|
|
228
242
|
flag: group.flag,
|
|
229
243
|
in: group.in,
|
|
@@ -564,7 +578,7 @@ function buildCharX(manifestPath, outputArgument) {
|
|
|
564
578
|
const regex = buildRegexScripts(manifestDirectory, manifest.regex);
|
|
565
579
|
const trigger = buildTriggers(manifest, manifestDirectory);
|
|
566
580
|
const { cardAssets, files: assetFiles } = createAssetFiles(manifest, manifestDirectory);
|
|
567
|
-
const card = createCard(manifest, lorebook, cardAssets,
|
|
581
|
+
const card = createCard(manifest, lorebook, cardAssets, readCard(manifest, manifestDirectory));
|
|
568
582
|
const module = {
|
|
569
583
|
description: `Module for ${manifest.name}`,
|
|
570
584
|
id: createUUID(`${manifest.namespace ?? manifest.name}:module`),
|
|
@@ -710,11 +724,96 @@ function takeSourcePath(directory, label, extension, takenPaths) {
|
|
|
710
724
|
return candidate;
|
|
711
725
|
}
|
|
712
726
|
function createRegexDocument(regex) {
|
|
713
|
-
const frontmatter = [`
|
|
727
|
+
const frontmatter = [`comment: ${regex.comment ?? ""}`];
|
|
714
728
|
if (regex.flag !== void 0) frontmatter.push(`flag: ${regex.flag}`);
|
|
715
729
|
frontmatter.push(`type: ${regex.type ?? "editdisplay"}`);
|
|
716
730
|
return `---\n${frontmatter.join("\n")}\n---\n\nIN:\n${regex.in ?? ""}\nOUT:\n${regex.out ?? ""}\n`;
|
|
717
731
|
}
|
|
732
|
+
function createCardSources(card, files) {
|
|
733
|
+
const sourceCard = JSON.parse(JSON.stringify(card));
|
|
734
|
+
const data = sourceCard.data ?? {};
|
|
735
|
+
const risuai = data.extensions?.risuai;
|
|
736
|
+
const alternateGreetings = data.alternate_greetings ?? [];
|
|
737
|
+
assert$1(Array.isArray(alternateGreetings), "card.data.alternate_greetings must be an array");
|
|
738
|
+
for (let index = 0; index < alternateGreetings.length; index += 1) {
|
|
739
|
+
const greeting = alternateGreetings[index];
|
|
740
|
+
assert$1(typeof greeting === "string", `card.data.alternate_greetings[${index}] must be a string`);
|
|
741
|
+
}
|
|
742
|
+
const description = data.description ?? "";
|
|
743
|
+
const firstMessage = data.first_mes ?? "";
|
|
744
|
+
assert$1(typeof description === "string", "card.data.description must be a string");
|
|
745
|
+
assert$1(typeof firstMessage === "string", "card.data.first_mes must be a string");
|
|
746
|
+
delete data.alternate_greetings;
|
|
747
|
+
delete data.assets;
|
|
748
|
+
delete data.character_book;
|
|
749
|
+
delete data.character_version;
|
|
750
|
+
delete data.creator;
|
|
751
|
+
delete data.creator_notes;
|
|
752
|
+
delete data.description;
|
|
753
|
+
delete data.first_mes;
|
|
754
|
+
delete data.modification_date;
|
|
755
|
+
delete data.name;
|
|
756
|
+
delete data.tags;
|
|
757
|
+
if (risuai) {
|
|
758
|
+
delete risuai.backgroundHTML;
|
|
759
|
+
delete risuai.hideChatIcon;
|
|
760
|
+
delete risuai.license;
|
|
761
|
+
delete risuai.lowLevelAccess;
|
|
762
|
+
delete risuai.moduleNamespace;
|
|
763
|
+
delete risuai.toggles;
|
|
764
|
+
for (const [key, value] of Object.entries({
|
|
765
|
+
additionalText: "",
|
|
766
|
+
bias: [],
|
|
767
|
+
defaultVariables: "",
|
|
768
|
+
inlayViewScreen: false,
|
|
769
|
+
largePortrait: false,
|
|
770
|
+
lorePlus: false,
|
|
771
|
+
prebuiltAssetCommand: "",
|
|
772
|
+
prebuiltAssetExclude: [],
|
|
773
|
+
prebuiltAssetStyle: "",
|
|
774
|
+
sdData: [],
|
|
775
|
+
utilityBot: false,
|
|
776
|
+
viewScreen: "none",
|
|
777
|
+
virtualscript: "",
|
|
778
|
+
vits: {}
|
|
779
|
+
})) if (JSON.stringify(sortKeysDeep(risuai[key])) === JSON.stringify(sortKeysDeep(value))) delete risuai[key];
|
|
780
|
+
if (Object.keys(risuai).length === 0) delete data.extensions.risuai;
|
|
781
|
+
}
|
|
782
|
+
if (data.extensions) {
|
|
783
|
+
delete data.extensions.moduleNoneImage;
|
|
784
|
+
if (Object.keys(data.extensions).length === 0) delete data.extensions;
|
|
785
|
+
}
|
|
786
|
+
for (const [key, value] of Object.entries({
|
|
787
|
+
creation_date: 0,
|
|
788
|
+
group_only_greetings: [],
|
|
789
|
+
mes_example: "",
|
|
790
|
+
nickname: "",
|
|
791
|
+
personality: "",
|
|
792
|
+
post_history_instructions: "",
|
|
793
|
+
scenario: "",
|
|
794
|
+
source: [],
|
|
795
|
+
system_prompt: ""
|
|
796
|
+
})) if (JSON.stringify(sortKeysDeep(data[key])) === JSON.stringify(sortKeysDeep(value))) delete data[key];
|
|
797
|
+
if (Object.keys(data).length === 0) delete sourceCard.data;
|
|
798
|
+
else sourceCard.data = data;
|
|
799
|
+
if (sourceCard.spec === "chara_card_v3") delete sourceCard.spec;
|
|
800
|
+
if (sourceCard.spec_version === "3.0") delete sourceCard.spec_version;
|
|
801
|
+
if (!(alternateGreetings.length > 0 || description !== "" || firstMessage !== "" || Object.keys(sourceCard).length > 0)) return;
|
|
802
|
+
const alternateGreetingFiles = alternateGreetings.map((greeting, index) => {
|
|
803
|
+
const file = `alternate_greetings/${index + 1}.md`;
|
|
804
|
+
files.set(file, Buffer.from(greeting, "utf8"));
|
|
805
|
+
return file;
|
|
806
|
+
});
|
|
807
|
+
files.set("description.md", Buffer.from(description, "utf8"));
|
|
808
|
+
files.set("first_mes.md", Buffer.from(firstMessage, "utf8"));
|
|
809
|
+
files.set("card.json", Buffer.from(`${JSON.stringify(sortKeysDeep(sourceCard), null, 2)}\n`, "utf8"));
|
|
810
|
+
return {
|
|
811
|
+
alternate_greetings: alternateGreetingFiles,
|
|
812
|
+
description: "description.md",
|
|
813
|
+
file: "card.json",
|
|
814
|
+
first_mes: "first_mes.md"
|
|
815
|
+
};
|
|
816
|
+
}
|
|
718
817
|
function createExpandedModuleSources(card, decodedModule) {
|
|
719
818
|
const moduleData = decodedModule.module;
|
|
720
819
|
const files = /* @__PURE__ */ new Map();
|
|
@@ -774,7 +873,7 @@ function createExpandedModuleSources(card, decodedModule) {
|
|
|
774
873
|
}
|
|
775
874
|
const risuai = card.data?.extensions?.risuai ?? {};
|
|
776
875
|
const manifest = {
|
|
777
|
-
card:
|
|
876
|
+
card: createCardSources(card, files),
|
|
778
877
|
creator: card.data?.creator,
|
|
779
878
|
description: card.data?.creator_notes ?? moduleData.description ?? "",
|
|
780
879
|
folders,
|
|
@@ -912,11 +1011,11 @@ function unpackCharX(inputPath, outputPath) {
|
|
|
912
1011
|
decodedModule = decodeModule(moduleEntry.data, map);
|
|
913
1012
|
}
|
|
914
1013
|
const expandedSources = decodedModule ? createExpandedModuleSources(card, decodedModule) : /* @__PURE__ */ new Map();
|
|
915
|
-
for (const name of expandedSources.keys()) assert$1(!extracted.has(name), `Generated module source conflicts with an archive entry: ${name}`);
|
|
1014
|
+
for (const name of expandedSources.keys()) assert$1(name === "card.json" || !extracted.has(name), `Generated module source conflicts with an archive entry: ${name}`);
|
|
916
1015
|
assertEmptyOutputDirectory$1(resolvedOutputPath);
|
|
917
1016
|
fs.mkdirSync(resolvedOutputPath, { recursive: true });
|
|
918
1017
|
for (const [name, entry] of extracted) {
|
|
919
|
-
if (name === "module.risum") continue;
|
|
1018
|
+
if (name === "module.risum" || decodedModule && name === "card.json" || expandedSources.has(name)) continue;
|
|
920
1019
|
const destination = path.join(resolvedOutputPath, ...name.split("/"));
|
|
921
1020
|
if (entry.directory) {
|
|
922
1021
|
fs.mkdirSync(destination, { recursive: true });
|
|
@@ -1055,4 +1154,4 @@ function unpackRisuM(inputPath, outputPath) {
|
|
|
1055
1154
|
//#endregion
|
|
1056
1155
|
export { unpackCharX as a, bundleLua as c, parseZIP as i, createExpandedModuleSources as n, parseModuleBlock as o, decodeModule as r, buildCharX as s, unpackRisuM as t };
|
|
1057
1156
|
|
|
1058
|
-
//# sourceMappingURL=unpack-risum-
|
|
1157
|
+
//# sourceMappingURL=unpack-risum-tckgp4pg.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unpack-risum-tckgp4pg.js","names":[],"sources":["../src/bundle.ts","../src/build-charx.ts","../src/inspect-risusave.ts","../src/unpack-charx.ts","../src/unpack-risum.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\n\nconst REQUIRE_PATTERN = /require\\s*\\(?[\"']([^\"']+)[\"']\\)?/g;\n\ninterface BundleState {\n entryPath: string;\n hoistedComments: string[];\n includedModules: Set<string>;\n preloads: string[];\n totalInputBytes: number;\n}\n\nfunction formatBytes(bytes: number): string {\n if (bytes === 0) {\n return \"0 B\";\n }\n\n const base = 1024;\n const sizes = [\"B\", \"KB\", \"MB\"];\n const index = Math.floor(Math.log(bytes) / Math.log(base));\n return `${Number.parseFloat((bytes / Math.pow(base, index)).toFixed(2))} ${sizes[index]}`;\n}\n\nfunction resolveModulePath(moduleName: string): string {\n return `${moduleName.replace(/\\./g, \"/\")}.lua`;\n}\n\nfunction minifyLua(content: string, hoistedComments: string[]): string {\n const tokenPattern =\n /(--\\[(=*)\\[[\\s\\S]*?\\]\\2\\])|(--.*)|(\\[(=*)\\[[\\s\\S]*?\\]\\5\\])|(\"([^\"\\\\]|\\\\.)*\")|('([^'\\\\]|\\\\.)*')/g;\n\n return content\n .replace(\n tokenPattern,\n (match: string, longComment?: string, _equals?: string, shortComment?: string) => {\n if (!longComment && !shortComment) {\n return match;\n }\n if (shortComment?.startsWith(\"--!\") || (longComment && /^--\\[(=*)\\[!/.test(match))) {\n hoistedComments.push(match);\n }\n return \" \";\n },\n )\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter((line) => line.length > 0)\n .join(\"\\n\");\n}\n\nfunction processModule(moduleName: string, state: BundleState): void {\n if (state.includedModules.has(moduleName)) {\n return;\n }\n\n const rootDirectory = path.dirname(path.resolve(state.entryPath));\n const modulePath = path.join(rootDirectory, resolveModulePath(moduleName));\n if (!fs.existsSync(modulePath)) {\n console.warn(`Warning: Module '${moduleName}' not found`);\n return;\n }\n\n const rawContent = fs.readFileSync(modulePath, \"utf8\");\n state.includedModules.add(moduleName);\n state.totalInputBytes += fs.statSync(modulePath).size;\n\n for (const match of rawContent.matchAll(new RegExp(REQUIRE_PATTERN.source, \"g\"))) {\n const dependency = match[1];\n if (dependency) {\n processModule(dependency, state);\n }\n }\n\n const minifiedContent = minifyLua(rawContent, state.hoistedComments);\n state.preloads.push(`package.preload[\"${moduleName}\"]=function(...)${minifiedContent} end`);\n}\n\nfunction bundleLua(entryPath: string, outputArgument: string): string {\n const resolvedEntryPath = path.resolve(entryPath);\n if (!fs.existsSync(resolvedEntryPath)) {\n throw new Error(`Entry file not found: ${entryPath}`);\n }\n\n let outputPath = path.resolve(outputArgument);\n if (fs.existsSync(outputPath) && fs.statSync(outputPath).isDirectory()) {\n outputPath = path.join(outputPath, path.basename(resolvedEntryPath));\n }\n if (path.extname(outputPath) !== \".lua\") {\n outputPath += \".lua\";\n }\n\n const state: BundleState = {\n entryPath: resolvedEntryPath,\n hoistedComments: [],\n includedModules: new Set(),\n preloads: [],\n totalInputBytes: fs.statSync(resolvedEntryPath).size,\n };\n const mainContent = fs.readFileSync(resolvedEntryPath, \"utf8\");\n\n for (const match of mainContent.matchAll(new RegExp(REQUIRE_PATTERN.source, \"g\"))) {\n const moduleName = match[1];\n if (moduleName) {\n processModule(moduleName, state);\n }\n }\n\n const mainMinified = minifyLua(mainContent, state.hoistedComments);\n const hoisted = state.hoistedComments.length > 0 ? `${state.hoistedComments.join(\"\\n\")}\\n` : \"\";\n const output = `${hoisted}${state.preloads.join(\"\\n\")}\\n${mainMinified}`;\n\n fs.mkdirSync(path.dirname(outputPath), { recursive: true });\n fs.writeFileSync(outputPath, output, \"utf8\");\n\n const outputBytes = fs.statSync(outputPath).size;\n const reduction = ((state.totalInputBytes - outputBytes) / state.totalInputBytes) * 100;\n console.log(\n `Bundled ${path.relative(process.cwd(), resolvedEntryPath)} to ${path.relative(process.cwd(), outputPath)}`,\n );\n console.log(\n `${state.includedModules.size} modules, ${formatBytes(state.totalInputBytes)} to ${formatBytes(outputBytes)}, ${reduction.toFixed(2)}% reduction`,\n );\n return outputPath;\n}\n\nexport { bundleLua };\n","import crypto from \"node:crypto\";\nimport fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport zlib from \"node:zlib\";\n\nimport { bundleLua } from \"./bundle.js\";\n\nconst DEFAULT_ICON = Buffer.from(\n \"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M/wHwAEAQH/69v17QAAAABJRU5ErkJggg==\",\n \"base64\",\n);\nconst RPACK_MAP_PATH = path.join(\n path.dirname(fileURLToPath(import.meta.url)),\n \"..\",\n \"vendor\",\n \"rpack\",\n \"rpack_map.bin\",\n);\n\nconst CRC32_TABLE = (() => {\n const table = new Uint32Array(256);\n for (let index = 0; index < table.length; index += 1) {\n let value = index;\n for (let bit = 0; bit < 8; bit += 1) {\n if ((value & 1) !== 0) {\n value = 0xedb88320 ^ (value >>> 1);\n } else {\n value >>>= 1;\n }\n }\n table[index] = value >>> 0;\n }\n return table;\n})();\n\nfunction assert(condition: unknown, message: string): asserts condition {\n if (!condition) {\n throw new Error(message);\n }\n}\n\nfunction calculateCRC32(data) {\n let value = 0xffffffff;\n for (const byte of data) {\n value = CRC32_TABLE[(value ^ byte) & 0xff] ^ (value >>> 8);\n }\n return (value ^ 0xffffffff) >>> 0;\n}\n\nfunction createUUID(seed) {\n const bytes = crypto.createHash(\"sha256\").update(seed).digest().subarray(0, 16);\n bytes[6] = (bytes[6] & 0x0f) | 0x50;\n bytes[8] = (bytes[8] & 0x3f) | 0x80;\n const hex = bytes.toString(\"hex\");\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n}\n\nfunction detectImageType(data) {\n if (data.subarray(0, 8).equals(Buffer.from(\"89504e470d0a1a0a\", \"hex\"))) {\n return \"PNG\";\n }\n if (data.subarray(0, 3).equals(Buffer.from(\"ffd8ff\", \"hex\"))) {\n return \"JPEG\";\n }\n if (\n data.subarray(0, 6).toString(\"ascii\") === \"GIF87a\" ||\n data.subarray(0, 6).toString(\"ascii\") === \"GIF89a\"\n ) {\n return \"GIF\";\n }\n if (\n data.subarray(0, 4).toString(\"ascii\") === \"RIFF\" &&\n data.subarray(8, 12).toString(\"ascii\") === \"WEBP\"\n ) {\n return \"WEBP\";\n }\n return \"Unknown\";\n}\n\nfunction getAssetCategory(extension) {\n const audio = new Set([\"flac\", \"mp3\", \"ogg\", \"wav\"]);\n const code = new Set([\"js\", \"lua\", \"ts\"]);\n const fonts = new Set([\"otf\", \"ttf\", \"woff\", \"woff2\"]);\n const images = new Set([\"avif\", \"gif\", \"jpeg\", \"jpg\", \"png\", \"webp\"]);\n const models = new Set([\"mmd\", \"obj\"]);\n const video = new Set([\"avi\", \"mkv\", \"mov\", \"mp4\", \"webm\"]);\n\n if (audio.has(extension)) {\n return \"audio\";\n }\n if (code.has(extension)) {\n return \"code\";\n }\n if (fonts.has(extension)) {\n return \"fonts\";\n }\n if (images.has(extension)) {\n return \"image\";\n }\n if (models.has(extension)) {\n return \"model\";\n }\n if (extension === \"onnx\" || extension === \"safetensors\" || extension === \"cpkt\") {\n return \"ai\";\n }\n if (video.has(extension)) {\n return \"video\";\n }\n return \"other\";\n}\n\nfunction readSource(manifestDirectory, source, label) {\n if (typeof source === \"string\") {\n return fs.readFileSync(path.resolve(manifestDirectory, source), \"utf8\");\n }\n assert(source && typeof source === \"object\", `${label} must be a file path or source object`);\n if (typeof source.content === \"string\") {\n return source.content;\n }\n assert(typeof source.file === \"string\", `${label}.file must be a string`);\n return fs.readFileSync(path.resolve(manifestDirectory, source.file), \"utf8\");\n}\n\nfunction readCard(manifest, manifestDirectory) {\n if (!manifest.card) {\n return undefined;\n }\n\n if (typeof manifest.card === \"string\") {\n return JSON.parse(readSource(manifestDirectory, manifest.card, \"card\"));\n }\n\n const baseSourcePresent = \"content\" in manifest.card || \"file\" in manifest.card;\n const card = baseSourcePresent\n ? JSON.parse(readSource(manifestDirectory, manifest.card, \"card\"))\n : {};\n const data = card.data ?? {};\n if (manifest.card.alternate_greetings !== undefined) {\n assert(\n Array.isArray(manifest.card.alternate_greetings),\n \"card.alternate_greetings must be an array\",\n );\n data.alternate_greetings = manifest.card.alternate_greetings.map((source, index) =>\n readSource(manifestDirectory, source, `card.alternate_greetings[${index}]`),\n );\n }\n if (manifest.card.description !== undefined) {\n data.description = readSource(manifestDirectory, manifest.card.description, \"card.description\");\n }\n if (manifest.card.first_mes !== undefined) {\n data.first_mes = readSource(manifestDirectory, manifest.card.first_mes, \"card.first_mes\");\n }\n card.data = data;\n return card;\n}\n\nfunction sanitizeArchiveName(name: string): string {\n const sanitized = Array.from(name, (character) =>\n character.charCodeAt(0) < 32 ? \"_\" : character,\n )\n .join(\"\")\n .replace(/[<>:\"/\\\\|?*]/g, \"_\")\n .trim();\n return sanitized.slice(0, 100) || \"asset\";\n}\n\nfunction sortKeysDeep(value) {\n if (Array.isArray(value)) {\n return value.map(sortKeysDeep);\n }\n if (value && typeof value === \"object\" && !Buffer.isBuffer(value)) {\n const sorted = {};\n for (const key of Object.keys(value).sort()) {\n if (value[key] !== undefined) {\n sorted[key] = sortKeysDeep(value[key]);\n }\n }\n return sorted;\n }\n return value;\n}\n\nfunction parseFrontmatter(content, fileName) {\n const normalized = content.replace(/\\r\\n/g, \"\\n\");\n assert(normalized.startsWith(\"---\\n\"), `Missing frontmatter in ${fileName}`);\n const end = normalized.indexOf(\"\\n---\\n\", 4);\n assert(end !== -1, `Unclosed frontmatter in ${fileName}`);\n const metadata: Record<string, string | boolean> = {};\n for (const line of normalized.slice(4, end).split(\"\\n\")) {\n if (line.trim() === \"\") {\n continue;\n }\n const separator = line.indexOf(\":\");\n assert(separator !== -1, `Invalid frontmatter line in ${fileName}: ${line}`);\n const key = line.slice(0, separator).trim();\n const rawValue = line.slice(separator + 1).trim();\n assert(key !== \"\", `Empty frontmatter key in ${fileName}`);\n if (rawValue === \"true\") {\n metadata[key] = true;\n } else if (rawValue === \"false\") {\n metadata[key] = false;\n } else {\n metadata[key] = rawValue;\n }\n }\n return {\n body: normalized.slice(end + 5),\n metadata,\n };\n}\n\nfunction parseRegexBody(content, fileName) {\n const normalized = content.replace(/^\\n+/, \"\").replace(/\\n$/, \"\");\n const match = normalized.match(/^IN:\\s*\\n([\\s\\S]*?)\\nOUT:\\s*(?:\\n([\\s\\S]*))?$/);\n assert(match, `Invalid regex body in ${fileName}`);\n return {\n in: match[1],\n out: match[2] ?? \"\",\n };\n}\n\nfunction parseRegexDocument(content, fileName) {\n const { body, metadata } = parseFrontmatter(content, fileName);\n const parsed = parseRegexBody(body, fileName);\n return {\n ableFlag: metadata.flag !== undefined,\n comment: metadata.comment ?? \"\",\n flag: metadata.flag,\n in: parsed.in,\n out: parsed.out,\n type: metadata.type ?? \"editdisplay\",\n };\n}\n\nfunction buildRegexScripts(manifestDirectory, regexGroups: any[] = []) {\n const scripts: any[] = [];\n for (const group of regexGroups) {\n if (typeof group === \"string\") {\n scripts.push(\n parseRegexDocument(readSource(manifestDirectory, group, `regex ${group}`), group),\n );\n continue;\n }\n if (group.in !== undefined || group.out !== undefined) {\n assert(\n typeof group.in === \"string\" && typeof group.out === \"string\",\n \"Inline regex entries require in and out\",\n );\n scripts.push({\n ableFlag: group.flag !== undefined,\n comment: group.comment ?? \"\",\n flag: group.flag,\n in: group.in,\n out: group.out,\n type: group.type ?? \"editdisplay\",\n });\n continue;\n }\n\n assert(\n typeof group.file === \"string\",\n \"Regex entries require a file path, or inline in and out fields\",\n );\n scripts.push(\n parseRegexDocument(\n readSource(manifestDirectory, group.file, `regex ${group.file}`),\n group.file,\n ),\n );\n }\n return scripts;\n}\n\nfunction buildLorebook(manifest, manifestDirectory) {\n const folderKeys = new Map<string, string>();\n const folderNames = new Set<string>(manifest.folders ?? []);\n for (const entry of manifest.lorebook ?? []) {\n if (entry.folder) {\n folderNames.add(entry.folder);\n }\n }\n for (const name of folderNames) {\n folderKeys.set(\n name,\n `\\uf000folder:${createUUID(`${manifest.namespace ?? manifest.name}:folder:${name}`)}`,\n );\n }\n\n const temporaryDirectory = fs.mkdtempSync(path.join(os.tmpdir(), \"risums-charx-lorebook-\"));\n try {\n const lorebook = (manifest.lorebook ?? []).map((entry, index) => {\n let content;\n if (entry.bundle) {\n assert(\n typeof entry.file === \"string\",\n `Bundled lorebook ${entry.comment ?? index + 1} requires a file`,\n );\n const entryPath = path.resolve(manifestDirectory, entry.file);\n const outputPath = entry.bundleOutput\n ? path.resolve(manifestDirectory, entry.bundleOutput)\n : path.join(temporaryDirectory, `lorebook-${index}.lua`);\n content = readBundledLua(entryPath, outputPath);\n } else {\n content = readSource(\n manifestDirectory,\n entry,\n `lorebook ${entry.comment ?? entry.file ?? \"\"}`,\n );\n }\n return {\n activationPercent: entry.activationPercent,\n alwaysActive: entry.alwaysActive ?? false,\n bookVersion: entry.bookVersion ?? 2,\n comment: entry.comment ?? path.basename(entry.file ?? \"Lorebook\"),\n content,\n extentions: entry.extentions,\n folder: entry.folder ? folderKeys.get(entry.folder) : undefined,\n insertorder: entry.insertOrder ?? 100,\n key: entry.key ?? \"\",\n mode: entry.mode ?? \"normal\",\n secondkey: entry.secondaryKey ?? \"\",\n selective: entry.selective ?? false,\n useRegex: entry.useRegex ?? false,\n };\n });\n\n for (const name of folderNames) {\n lorebook.push({\n alwaysActive: false,\n bookVersion: 2,\n comment: name,\n content: \"\",\n insertorder: 100,\n key: folderKeys.get(name),\n mode: \"folder\",\n secondkey: \"\",\n selective: false,\n useRegex: false,\n });\n }\n return lorebook;\n } finally {\n fs.rmSync(temporaryDirectory, { force: true, recursive: true });\n }\n}\n\nfunction readBundledLua(entryPath: string, outputPath: string): string {\n bundleLua(entryPath, outputPath);\n return fs.readFileSync(outputPath, \"utf8\");\n}\n\nfunction buildTriggers(manifest, manifestDirectory) {\n const temporaryDirectory = fs.mkdtempSync(path.join(os.tmpdir(), \"risums-charx-\"));\n try {\n return (manifest.triggers ?? []).map((trigger, index) => {\n let effect = trigger.effect;\n if (trigger.lua) {\n const entryPath = path.resolve(manifestDirectory, trigger.lua);\n let code;\n if (trigger.bundle ?? true) {\n const outputPath = trigger.bundleOutput\n ? path.resolve(manifestDirectory, trigger.bundleOutput)\n : path.join(temporaryDirectory, `trigger-${index}.lua`);\n code = readBundledLua(entryPath, outputPath);\n } else {\n code = fs.readFileSync(entryPath, \"utf8\");\n }\n effect = [{ code, type: \"triggerlua\" }];\n }\n assert(Array.isArray(effect), `Trigger ${index + 1} requires lua or effect`);\n return {\n comment: trigger.comment ?? \"\",\n conditions: trigger.conditions ?? [],\n effect,\n lowLevelAccess: trigger.lowLevelAccess,\n type: trigger.type ?? \"start\",\n };\n });\n } finally {\n fs.rmSync(temporaryDirectory, { force: true, recursive: true });\n }\n}\n\nfunction createRisuM(module, encodeMap) {\n const payload = Buffer.from(\n JSON.stringify(sortKeysDeep({ module, type: \"risuModule\" }), null, 2),\n \"utf8\",\n );\n const encoded = Buffer.allocUnsafe(payload.length);\n for (let index = 0; index < payload.length; index += 1) {\n encoded[index] = encodeMap[payload[index]];\n }\n const header = Buffer.alloc(6);\n header.writeUInt8(111, 0);\n header.writeUInt8(0, 1);\n header.writeUInt32LE(encoded.length, 2);\n return Buffer.concat([header, encoded, Buffer.from([0])]);\n}\n\nfunction createAssetFiles(manifest, manifestDirectory) {\n const cardAssets: any[] = [];\n const files: Array<{ data: Buffer; name: string }> = [];\n const takenNames = new Set<string>();\n\n function addAsset({ data, extension, name, type }) {\n const category = getAssetCategory(extension);\n const baseDirectory = `assets/${type === \"icon\" ? \"icon\" : \"other\"}/${category}`;\n const baseName = sanitizeArchiveName(name);\n let archiveName = baseName;\n let suffix = 0;\n while (takenNames.has(archiveName)) {\n suffix += 1;\n archiveName = `${baseName}_${suffix}`;\n }\n const archivePath = `${baseDirectory}/${archiveName}.${extension}`;\n takenNames.add(archiveName);\n cardAssets.push({\n ext: extension,\n name,\n type,\n uri: `embeded://${archivePath}`,\n });\n files.push({ data, name: archivePath });\n files.push({\n data: Buffer.from(JSON.stringify({ type: detectImageType(data) }, null, 2)),\n name: `x_meta/${archiveName}.json`,\n });\n }\n\n if (manifest.icon) {\n const iconPath = path.resolve(manifestDirectory, manifest.icon);\n const extension = path.extname(iconPath).slice(1).toLowerCase() || \"png\";\n addAsset({ data: fs.readFileSync(iconPath), extension, name: \"main\", type: \"icon\" });\n } else {\n addAsset({ data: DEFAULT_ICON, extension: \"png\", name: \"main\", type: \"icon\" });\n }\n\n for (const asset of manifest.assets ?? []) {\n assert(typeof asset.file === \"string\", \"Asset file must be a string\");\n const assetPath = path.resolve(manifestDirectory, asset.file);\n const extension = (asset.extension ?? path.extname(assetPath).slice(1)).toLowerCase();\n assert(extension !== \"\", `Cannot determine extension for ${asset.file}`);\n assert(/^[a-z0-9]+$/.test(extension), `Invalid extension for ${asset.file}: ${extension}`);\n addAsset({\n data: fs.readFileSync(assetPath),\n extension,\n name: asset.name ?? path.basename(assetPath, path.extname(assetPath)),\n type: \"x-risu-asset\",\n });\n }\n return { cardAssets, files };\n}\n\nfunction createCard(manifest, lorebook, cardAssets, sourceCard?: Record<string, any>) {\n const sourceData = sourceCard?.data ?? {};\n const sourceExtensions = sourceData.extensions ?? {};\n const sourceRisuAI = sourceExtensions.risuai ?? {};\n const entries = lorebook.map((entry) => ({\n case_sensitive: entry.extentions?.risu_case_sensitive ?? false,\n comment: entry.comment,\n constant: entry.alwaysActive,\n content: entry.content,\n enabled: true,\n extensions: {\n ...entry.extentions,\n risu_activationPercent: entry.activationPercent,\n risu_loreCache: entry.loreCache,\n },\n folder: entry.folder,\n insertion_order: entry.insertorder,\n keys: entry.key.split(\",\").map((key) => key.trim()),\n mode: entry.mode,\n name: entry.comment,\n secondary_keys: entry.selective\n ? entry.secondkey.split(\",\").map((key) => key.trim())\n : undefined,\n selective: entry.selective,\n use_regex: entry.useRegex,\n }));\n return {\n ...sourceCard,\n data: {\n ...sourceData,\n alternate_greetings: sourceData.alternate_greetings ?? [],\n assets: cardAssets,\n character_book: {\n entries,\n extensions: { risu_fullWordMatching: false },\n },\n character_version: manifest.version ?? sourceData.character_version ?? \"\",\n creation_date: sourceData.creation_date ?? 0,\n creator: manifest.creator ?? sourceData.creator ?? \"\",\n creator_notes: manifest.description ?? sourceData.creator_notes ?? \"\",\n description: sourceData.description ?? \"\",\n extensions: {\n ...sourceExtensions,\n moduleNoneImage: manifest.icon ? undefined : true,\n risuai: {\n ...sourceRisuAI,\n additionalText: sourceRisuAI.additionalText ?? \"\",\n backgroundHTML: manifest.CSS\n ? readSource(path.dirname(manifest.__path), manifest.CSS, \"CSS\")\n : \"\",\n bias: sourceRisuAI.bias ?? [],\n defaultVariables: sourceRisuAI.defaultVariables ?? \"\",\n hideChatIcon: manifest.hideIcon ?? false,\n inlayViewScreen: sourceRisuAI.inlayViewScreen ?? false,\n largePortrait: sourceRisuAI.largePortrait ?? false,\n license: manifest.license ?? \"\",\n lorePlus: sourceRisuAI.lorePlus ?? false,\n lowLevelAccess: manifest.lowLevelAccess ?? false,\n moduleNamespace: manifest.namespace,\n newGenData: sourceRisuAI.newGenData,\n prebuiltAssetCommand: sourceRisuAI.prebuiltAssetCommand ?? \"\",\n prebuiltAssetExclude: sourceRisuAI.prebuiltAssetExclude ?? [],\n prebuiltAssetStyle: sourceRisuAI.prebuiltAssetStyle ?? \"\",\n sdData: sourceRisuAI.sdData ?? [],\n toggles: manifest.toggles\n ? readSource(path.dirname(manifest.__path), manifest.toggles, \"toggles\")\n : \"\",\n utilityBot: sourceRisuAI.utilityBot ?? false,\n viewScreen: \"none\",\n virtualscript: sourceRisuAI.virtualscript ?? \"\",\n vits: sourceRisuAI.vits ?? {},\n },\n },\n first_mes: sourceData.first_mes ?? \"\",\n group_only_greetings: sourceData.group_only_greetings ?? [],\n mes_example: sourceData.mes_example ?? \"\",\n modification_date: process.env.SOURCE_DATE_EPOCH\n ? Number(process.env.SOURCE_DATE_EPOCH)\n : Math.floor(Date.now() / 1000),\n name: manifest.name,\n nickname: sourceData.nickname ?? \"\",\n personality: sourceData.personality ?? \"\",\n post_history_instructions: sourceData.post_history_instructions ?? \"\",\n scenario: sourceData.scenario ?? \"\",\n source: sourceData.source ?? [],\n system_prompt: sourceData.system_prompt ?? \"\",\n tags: manifest.tags ?? sourceData.tags ?? [],\n },\n spec: sourceCard?.spec ?? \"chara_card_v3\",\n spec_version: sourceCard?.spec_version ?? \"3.0\",\n };\n}\n\nfunction getDOSDateTime(date) {\n const year = Math.max(1980, date.getUTCFullYear());\n return {\n date: ((year - 1980) << 9) | ((date.getUTCMonth() + 1) << 5) | date.getUTCDate(),\n time:\n (date.getUTCHours() << 11) |\n (date.getUTCMinutes() << 5) |\n Math.floor(date.getUTCSeconds() / 2),\n };\n}\n\nfunction createZIP(files, timestamp) {\n assert(files.length <= 0xffff, \"ZIP contains too many files\");\n const centralRecords: Buffer[] = [];\n const localRecords: Buffer[] = [];\n let offset = 0;\n const { date, time } = getDOSDateTime(timestamp);\n\n for (const file of files) {\n const data = Buffer.from(file.data);\n const compressed = zlib.deflateRawSync(data, { level: 6 });\n const fileName = Buffer.from(file.name.replace(/\\\\/g, \"/\"), \"utf8\");\n const CRC32 = calculateCRC32(data);\n assert(\n data.length <= 0xffffffff && compressed.length <= 0xffffffff,\n `${file.name} exceeds ZIP32 limits`,\n );\n\n const localHeader = Buffer.alloc(30);\n localHeader.writeUInt32LE(0x04034b50, 0);\n localHeader.writeUInt16LE(20, 4);\n localHeader.writeUInt16LE(0x0800, 6);\n localHeader.writeUInt16LE(8, 8);\n localHeader.writeUInt16LE(time, 10);\n localHeader.writeUInt16LE(date, 12);\n localHeader.writeUInt32LE(CRC32, 14);\n localHeader.writeUInt32LE(compressed.length, 18);\n localHeader.writeUInt32LE(data.length, 22);\n localHeader.writeUInt16LE(fileName.length, 26);\n localHeader.writeUInt16LE(0, 28);\n localRecords.push(localHeader, fileName, compressed);\n\n const centralHeader = Buffer.alloc(46);\n centralHeader.writeUInt32LE(0x02014b50, 0);\n centralHeader.writeUInt16LE(20, 4);\n centralHeader.writeUInt16LE(20, 6);\n centralHeader.writeUInt16LE(0x0800, 8);\n centralHeader.writeUInt16LE(8, 10);\n centralHeader.writeUInt16LE(time, 12);\n centralHeader.writeUInt16LE(date, 14);\n centralHeader.writeUInt32LE(CRC32, 16);\n centralHeader.writeUInt32LE(compressed.length, 20);\n centralHeader.writeUInt32LE(data.length, 24);\n centralHeader.writeUInt16LE(fileName.length, 28);\n centralHeader.writeUInt16LE(0, 30);\n centralHeader.writeUInt16LE(0, 32);\n centralHeader.writeUInt16LE(0, 34);\n centralHeader.writeUInt16LE(0, 36);\n centralHeader.writeUInt32LE(0, 38);\n centralHeader.writeUInt32LE(offset, 42);\n centralRecords.push(centralHeader, fileName);\n offset += localHeader.length + fileName.length + compressed.length;\n }\n\n const centralDirectory = Buffer.concat(centralRecords);\n const end = Buffer.alloc(22);\n end.writeUInt32LE(0x06054b50, 0);\n end.writeUInt16LE(0, 4);\n end.writeUInt16LE(0, 6);\n end.writeUInt16LE(files.length, 8);\n end.writeUInt16LE(files.length, 10);\n end.writeUInt32LE(centralDirectory.length, 12);\n end.writeUInt32LE(offset, 16);\n end.writeUInt16LE(0, 20);\n return Buffer.concat([...localRecords, centralDirectory, end]);\n}\n\nfunction buildCharX(manifestPath: string, outputArgument?: string): string {\n const resolvedManifestPath = path.resolve(manifestPath);\n const manifestDirectory = path.dirname(resolvedManifestPath);\n const manifest = JSON.parse(fs.readFileSync(resolvedManifestPath, \"utf8\"));\n manifest.__path = resolvedManifestPath;\n assert(typeof manifest.name === \"string\" && manifest.name !== \"\", \"Manifest name is required\");\n\n const lorebook = buildLorebook(manifest, manifestDirectory);\n const regex = buildRegexScripts(manifestDirectory, manifest.regex);\n const trigger = buildTriggers(manifest, manifestDirectory);\n const { cardAssets, files: assetFiles } = createAssetFiles(manifest, manifestDirectory);\n const sourceCard = readCard(manifest, manifestDirectory);\n const card = createCard(manifest, lorebook, cardAssets, sourceCard);\n const module = {\n description: `Module for ${manifest.name}`,\n id: createUUID(`${manifest.namespace ?? manifest.name}:module`),\n lorebook,\n name: `${manifest.name} Module`,\n regex,\n trigger,\n };\n\n const map = fs.readFileSync(RPACK_MAP_PATH);\n assert(map.length >= 256, `Invalid RPack map: ${RPACK_MAP_PATH}`);\n const files = [\n ...assetFiles,\n { data: Buffer.from(JSON.stringify(sortKeysDeep(card), null, 2)), name: \"card.json\" },\n { data: createRisuM(sortKeysDeep(module), map.subarray(0, 256)), name: \"module.risum\" },\n ].sort((left, right) => left.name.localeCompare(right.name));\n\n const outputPath = outputArgument\n ? path.resolve(outputArgument)\n : path.resolve(\n manifestDirectory,\n manifest.output ?? `../dist/${sanitizeArchiveName(manifest.name)}.charx`,\n );\n fs.mkdirSync(path.dirname(outputPath), { recursive: true });\n const timestamp = process.env.SOURCE_DATE_EPOCH\n ? new Date(Number(process.env.SOURCE_DATE_EPOCH) * 1000)\n : new Date();\n fs.writeFileSync(outputPath, createZIP(files, timestamp));\n console.log(`Built ${path.relative(process.cwd(), outputPath)} (${files.length} files)`);\n return outputPath;\n}\n\nexport { buildCharX };\n","import zlib from \"node:zlib\";\n\nconst MAGIC = Buffer.from(\"RISUSAVE\\0\");\nconst MODULE_BLOCK_TYPE = 5;\n\ninterface ModuleRecord {\n id?: unknown;\n name?: unknown;\n namespace?: unknown;\n [key: string]: unknown;\n}\n\nfunction parseModuleBlock(database: Buffer): ModuleRecord[] {\n if (!database.subarray(0, MAGIC.length).equals(MAGIC)) {\n throw new Error(\"Invalid RISUSAVE header\");\n }\n\n let offset = MAGIC.length;\n while (offset < database.length) {\n if (offset + 3 > database.length) {\n throw new Error(`Truncated block header at byte ${offset}`);\n }\n const type = database[offset];\n const compressed = database[offset + 1] === 1;\n const nameLength = database[offset + 2];\n offset += 3;\n\n if (offset + nameLength + 4 > database.length) {\n throw new Error(`Truncated block name at byte ${offset}`);\n }\n const name = database.subarray(offset, offset + nameLength).toString(\"utf8\");\n offset += nameLength;\n const contentLength = database.readUInt32LE(offset);\n offset += 4;\n\n if (offset + contentLength > database.length) {\n throw new Error(`Truncated ${name} block at byte ${offset}`);\n }\n let content = database.subarray(offset, offset + contentLength);\n offset += contentLength;\n\n if (type !== MODULE_BLOCK_TYPE) {\n continue;\n }\n if (compressed) {\n content = zlib.gunzipSync(content);\n }\n return JSON.parse(content.toString(\"utf8\")) as ModuleRecord[];\n }\n throw new Error(\"RISUSAVE module block not found\");\n}\n\nexport { parseModuleBlock };\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport zlib from \"node:zlib\";\n\nconst RPACK_MAP_PATH = path.join(\n path.dirname(fileURLToPath(import.meta.url)),\n \"..\",\n \"vendor\",\n \"rpack\",\n \"rpack_map.bin\",\n);\n\nconst CRC32_TABLE = (() => {\n const table = new Uint32Array(256);\n for (let index = 0; index < table.length; index += 1) {\n let value = index;\n for (let bit = 0; bit < 8; bit += 1) {\n if ((value & 1) !== 0) {\n value = 0xedb88320 ^ (value >>> 1);\n } else {\n value >>>= 1;\n }\n }\n table[index] = value >>> 0;\n }\n return table;\n})();\n\nfunction assert(condition: unknown, message: string): asserts condition {\n if (!condition) {\n throw new Error(message);\n }\n}\n\nfunction calculateCRC32(data) {\n let value = 0xffffffff;\n for (const byte of data) {\n value = CRC32_TABLE[(value ^ byte) & 0xff] ^ (value >>> 8);\n }\n return (value ^ 0xffffffff) >>> 0;\n}\n\nfunction decodeModule(data: Buffer, map: Buffer): Record<string, any> {\n assert(data.length >= 7, \"module.risum is truncated\");\n assert(data.readUInt8(0) === 111, \"Invalid module.risum magic number\");\n assert(data.readUInt8(1) === 0, `Unsupported module.risum version: ${data.readUInt8(1)}`);\n\n const encodedLength = data.readUInt32LE(2);\n assert(encodedLength <= data.length - 6, \"module.risum payload is truncated\");\n assert(map.length >= 256, `Invalid RPack map: ${RPACK_MAP_PATH}`);\n\n let decodeMap;\n if (map.length >= 512) {\n decodeMap = map.subarray(256, 512);\n } else {\n decodeMap = Buffer.alloc(256);\n const seen = new Set();\n for (let index = 0; index < 256; index += 1) {\n const encoded = map[index];\n assert(!seen.has(encoded), \"RPack encode map is not a permutation\");\n seen.add(encoded);\n decodeMap[encoded] = index;\n }\n }\n\n const encoded = data.subarray(6, 6 + encodedLength);\n const decoded = Buffer.allocUnsafe(encoded.length);\n for (let index = 0; index < encoded.length; index += 1) {\n decoded[index] = decodeMap[encoded[index]];\n }\n\n const parsed = JSON.parse(decoded.toString(\"utf8\"));\n assert(\n parsed && parsed.type === \"risuModule\" && parsed.module,\n \"module.risum does not contain a Risu module\",\n );\n return parsed;\n}\n\nfunction findEndOfCentralDirectory(archive) {\n const minimumOffset = Math.max(0, archive.length - 0xffff - 22);\n for (let offset = archive.length - 22; offset >= minimumOffset; offset -= 1) {\n if (archive.readUInt32LE(offset) === 0x06054b50) {\n const commentLength = archive.readUInt16LE(offset + 20);\n if (offset + 22 + commentLength === archive.length) {\n return offset;\n }\n }\n }\n throw new Error(\"ZIP end record not found\");\n}\n\nfunction normalizeEntryName(name) {\n assert(name !== \"\", \"ZIP entry has an empty name\");\n assert(!name.includes(\"\\0\"), `ZIP entry contains a null byte: ${JSON.stringify(name)}`);\n\n const normalized = name.replace(/\\\\/g, \"/\");\n assert(!normalized.startsWith(\"/\"), `ZIP entry uses an absolute path: ${name}`);\n assert(!/^[a-zA-Z]:/.test(normalized), `ZIP entry uses an absolute path: ${name}`);\n\n const parts = normalized.split(\"/\");\n assert(!parts.includes(\"..\"), `ZIP entry escapes the output directory: ${name}`);\n return parts.filter((part) => part !== \"\" && part !== \".\").join(\"/\");\n}\n\nfunction sanitizeSourceName(name: string, fallback: string): string {\n const sanitized = Array.from(name, (character) =>\n character.charCodeAt(0) < 32 ? \"_\" : character,\n )\n .join(\"\")\n .replace(/[<>:\"/\\\\|?*]/g, \"_\")\n .replace(/[. ]+$/g, \"\")\n .trim();\n return sanitized || fallback;\n}\n\nfunction sortKeysDeep(value) {\n if (Array.isArray(value)) {\n return value.map(sortKeysDeep);\n }\n if (value && typeof value === \"object\" && !Buffer.isBuffer(value)) {\n const sorted = {};\n for (const key of Object.keys(value).sort()) {\n if (value[key] !== undefined) {\n sorted[key] = sortKeysDeep(value[key]);\n }\n }\n return sorted;\n }\n return value;\n}\n\nfunction takeSourcePath(directory, label, extension, takenPaths) {\n const baseName = sanitizeSourceName(label, \"untitled\");\n const suffix = baseName.toLowerCase().endsWith(extension) ? \"\" : extension;\n let candidate = `${directory}/${baseName}${suffix}`;\n let collision = 1;\n while (takenPaths.has(candidate)) {\n collision += 1;\n candidate = `${directory}/${baseName}_${collision}${suffix}`;\n }\n takenPaths.add(candidate);\n return candidate;\n}\n\nfunction createRegexDocument(regex) {\n const frontmatter = [`comment: ${regex.comment ?? \"\"}`];\n if (regex.flag !== undefined) {\n frontmatter.push(`flag: ${regex.flag}`);\n }\n frontmatter.push(`type: ${regex.type ?? \"editdisplay\"}`);\n return `---\\n${frontmatter.join(\"\\n\")}\\n---\\n\\nIN:\\n${regex.in ?? \"\"}\\nOUT:\\n${regex.out ?? \"\"}\\n`;\n}\n\nfunction createCardSources(card, files) {\n const sourceCard = JSON.parse(JSON.stringify(card));\n const data = sourceCard.data ?? {};\n const risuai = data.extensions?.risuai;\n\n const alternateGreetings = data.alternate_greetings ?? [];\n assert(Array.isArray(alternateGreetings), \"card.data.alternate_greetings must be an array\");\n for (let index = 0; index < alternateGreetings.length; index += 1) {\n const greeting = alternateGreetings[index];\n assert(\n typeof greeting === \"string\",\n `card.data.alternate_greetings[${index}] must be a string`,\n );\n }\n\n const description = data.description ?? \"\";\n const firstMessage = data.first_mes ?? \"\";\n assert(typeof description === \"string\", \"card.data.description must be a string\");\n assert(typeof firstMessage === \"string\", \"card.data.first_mes must be a string\");\n\n delete data.alternate_greetings;\n delete data.assets;\n delete data.character_book;\n delete data.character_version;\n delete data.creator;\n delete data.creator_notes;\n delete data.description;\n delete data.first_mes;\n delete data.modification_date;\n delete data.name;\n delete data.tags;\n\n if (risuai) {\n delete risuai.backgroundHTML;\n delete risuai.hideChatIcon;\n delete risuai.license;\n delete risuai.lowLevelAccess;\n delete risuai.moduleNamespace;\n delete risuai.toggles;\n const defaults = {\n additionalText: \"\",\n bias: [],\n defaultVariables: \"\",\n inlayViewScreen: false,\n largePortrait: false,\n lorePlus: false,\n prebuiltAssetCommand: \"\",\n prebuiltAssetExclude: [],\n prebuiltAssetStyle: \"\",\n sdData: [],\n utilityBot: false,\n viewScreen: \"none\",\n virtualscript: \"\",\n vits: {},\n };\n for (const [key, value] of Object.entries(defaults)) {\n if (JSON.stringify(sortKeysDeep(risuai[key])) === JSON.stringify(sortKeysDeep(value))) {\n delete risuai[key];\n }\n }\n if (Object.keys(risuai).length === 0) {\n delete data.extensions.risuai;\n }\n }\n if (data.extensions) {\n delete data.extensions.moduleNoneImage;\n if (Object.keys(data.extensions).length === 0) {\n delete data.extensions;\n }\n }\n\n const dataDefaults = {\n creation_date: 0,\n group_only_greetings: [],\n mes_example: \"\",\n nickname: \"\",\n personality: \"\",\n post_history_instructions: \"\",\n scenario: \"\",\n source: [],\n system_prompt: \"\",\n };\n for (const [key, value] of Object.entries(dataDefaults)) {\n if (JSON.stringify(sortKeysDeep(data[key])) === JSON.stringify(sortKeysDeep(value))) {\n delete data[key];\n }\n }\n\n if (Object.keys(data).length === 0) {\n delete sourceCard.data;\n } else {\n sourceCard.data = data;\n }\n if (sourceCard.spec === \"chara_card_v3\") {\n delete sourceCard.spec;\n }\n if (sourceCard.spec_version === \"3.0\") {\n delete sourceCard.spec_version;\n }\n\n const cardRequired =\n alternateGreetings.length > 0 ||\n description !== \"\" ||\n firstMessage !== \"\" ||\n Object.keys(sourceCard).length > 0;\n if (!cardRequired) {\n return undefined;\n }\n\n const alternateGreetingFiles = alternateGreetings.map((greeting, index) => {\n const file = `alternate_greetings/${index + 1}.md`;\n files.set(file, Buffer.from(greeting, \"utf8\"));\n return file;\n });\n files.set(\"description.md\", Buffer.from(description, \"utf8\"));\n files.set(\"first_mes.md\", Buffer.from(firstMessage, \"utf8\"));\n files.set(\n \"card.json\",\n Buffer.from(`${JSON.stringify(sortKeysDeep(sourceCard), null, 2)}\\n`, \"utf8\"),\n );\n return {\n alternate_greetings: alternateGreetingFiles,\n description: \"description.md\",\n file: \"card.json\",\n first_mes: \"first_mes.md\",\n };\n}\n\nfunction createExpandedModuleSources(\n card: Record<string, any>,\n decodedModule: Record<string, any>,\n): Map<string, Buffer> {\n const moduleData = decodedModule.module;\n const files = new Map<string, Buffer>();\n const folderNames = new Map<any, any>();\n const folders: any[] = [];\n const takenPaths = new Set<string>();\n\n for (const entry of moduleData.lorebook ?? []) {\n if (entry.mode !== \"folder\") {\n continue;\n }\n folderNames.set(entry.key, entry.comment);\n folders.push(entry.comment);\n }\n\n const lorebook: any[] = [];\n for (const entry of moduleData.lorebook ?? []) {\n if (entry.mode === \"folder\") {\n continue;\n }\n const file = takeSourcePath(\"lorebooks\", entry.comment, \".md\", takenPaths);\n files.set(file, Buffer.from(entry.content ?? \"\", \"utf8\"));\n lorebook.push({\n activationPercent: entry.activationPercent,\n alwaysActive: entry.alwaysActive ?? false,\n bookVersion: entry.bookVersion ?? 2,\n comment: entry.comment ?? \"\",\n extentions: entry.extentions,\n file,\n folder: folderNames.get(entry.folder),\n insertOrder: entry.insertorder ?? 100,\n key: entry.key ?? \"\",\n mode: entry.mode ?? \"normal\",\n secondaryKey: entry.secondkey ?? \"\",\n selective: entry.selective ?? false,\n useRegex: entry.useRegex ?? false,\n });\n }\n\n const regex: string[] = [];\n for (const entry of moduleData.regex ?? []) {\n const file = takeSourcePath(\"regex\", entry.comment, \".md\", takenPaths);\n files.set(file, Buffer.from(createRegexDocument(entry), \"utf8\"));\n regex.push(file);\n }\n\n const triggers: any[] = [];\n for (let index = 0; index < (moduleData.trigger ?? []).length; index += 1) {\n const trigger = moduleData.trigger[index];\n const luaEffect =\n trigger.effect?.length === 1 && trigger.effect[0].type === \"triggerlua\"\n ? trigger.effect[0]\n : undefined;\n if (!luaEffect || typeof luaEffect.code !== \"string\") {\n triggers.push(trigger);\n continue;\n }\n\n const label = trigger.comment || `trigger-${index + 1}`;\n const luaPath = takeSourcePath(\"triggers\", label, \".lua\", takenPaths);\n files.set(luaPath, Buffer.from(luaEffect.code, \"utf8\"));\n triggers.push({\n bundle: false,\n comment: trigger.comment ?? \"\",\n conditions: trigger.conditions ?? [],\n lowLevelAccess: trigger.lowLevelAccess,\n lua: luaPath,\n type: trigger.type ?? \"start\",\n });\n }\n\n const risuai = card.data?.extensions?.risuai ?? {};\n const manifest: Record<string, any> = {\n card: createCardSources(card, files),\n creator: card.data?.creator,\n description: card.data?.creator_notes ?? moduleData.description ?? \"\",\n folders,\n hideIcon: risuai.hideChatIcon ?? moduleData.hideIcon ?? false,\n lorebook,\n lowLevelAccess: risuai.lowLevelAccess ?? moduleData.lowLevelAccess ?? false,\n name: card.data?.name ?? moduleData.name,\n namespace: risuai.moduleNamespace ?? moduleData.namespace,\n regex,\n tags: card.data?.tags,\n triggers,\n version: card.data?.character_version ?? \"\",\n };\n\n const CSS = risuai.backgroundHTML ?? moduleData.backgroundEmbedding;\n if (CSS) {\n manifest.CSS = \"style.html\";\n files.set(\"style.html\", Buffer.from(CSS, \"utf8\"));\n }\n const toggles = risuai.toggles ?? moduleData.customModuleToggle;\n if (toggles) {\n manifest.toggles = \"toggles.txt\";\n files.set(\"toggles.txt\", Buffer.from(toggles, \"utf8\"));\n }\n\n const mainIcon = card.data?.assets?.find(\n (asset) => asset.type === \"icon\" && asset.name === \"main\",\n );\n if (mainIcon?.uri?.startsWith(\"embeded://\")) {\n manifest.icon = mainIcon.uri.slice(\"embeded://\".length);\n }\n\n const assets: any[] = [];\n for (const asset of card.data?.assets ?? []) {\n if (asset === mainIcon || !asset.uri?.startsWith(\"embeded://\")) {\n continue;\n }\n assets.push({\n extension: asset.ext,\n file: asset.uri.slice(\"embeded://\".length),\n name: asset.name,\n });\n }\n if (assets.length > 0) {\n manifest.assets = assets;\n }\n\n files.set(\n \"charx.json\",\n Buffer.from(`${JSON.stringify(sortKeysDeep(manifest), null, 2)}\\n`, \"utf8\"),\n );\n return files;\n}\n\nfunction parseZIP(archive: Buffer) {\n const endOffset = findEndOfCentralDirectory(archive);\n const diskNumber = archive.readUInt16LE(endOffset + 4);\n const centralDisk = archive.readUInt16LE(endOffset + 6);\n const diskEntries = archive.readUInt16LE(endOffset + 8);\n const totalEntries = archive.readUInt16LE(endOffset + 10);\n const centralSize = archive.readUInt32LE(endOffset + 12);\n const centralOffset = archive.readUInt32LE(endOffset + 16);\n\n assert(diskNumber === 0 && centralDisk === 0, \"Multi-disk ZIP archives are not supported\");\n assert(diskEntries === totalEntries, \"Inconsistent ZIP entry count\");\n assert(\n totalEntries !== 0xffff && centralSize !== 0xffffffff && centralOffset !== 0xffffffff,\n \"ZIP64 is not supported\",\n );\n\n const zipOffset = endOffset - centralSize - centralOffset;\n assert(zipOffset >= 0, \"Invalid ZIP central directory offset\");\n\n const entries: any[] = [];\n const names = new Set();\n let offset = zipOffset + centralOffset;\n for (let index = 0; index < totalEntries; index += 1) {\n assert(offset + 46 <= archive.length, \"ZIP central directory is truncated\");\n assert(\n archive.readUInt32LE(offset) === 0x02014b50,\n `Invalid ZIP central record at byte ${offset}`,\n );\n\n const flags = archive.readUInt16LE(offset + 8);\n const method = archive.readUInt16LE(offset + 10);\n const expectedCRC32 = archive.readUInt32LE(offset + 16);\n const compressedSize = archive.readUInt32LE(offset + 20);\n const uncompressedSize = archive.readUInt32LE(offset + 24);\n const nameLength = archive.readUInt16LE(offset + 28);\n const extraLength = archive.readUInt16LE(offset + 30);\n const commentLength = archive.readUInt16LE(offset + 32);\n const diskStart = archive.readUInt16LE(offset + 34);\n const localOffset = archive.readUInt32LE(offset + 42);\n const recordLength = 46 + nameLength + extraLength + commentLength;\n\n assert(offset + recordLength <= archive.length, \"ZIP central record is truncated\");\n assert((flags & 1) === 0, \"Encrypted ZIP entries are not supported\");\n assert(method === 0 || method === 8, `Unsupported ZIP compression method: ${method}`);\n assert(diskStart === 0, \"Multi-disk ZIP entries are not supported\");\n assert(\n compressedSize !== 0xffffffff &&\n uncompressedSize !== 0xffffffff &&\n localOffset !== 0xffffffff,\n \"ZIP64 entries are not supported\",\n );\n\n const rawName = archive.subarray(offset + 46, offset + 46 + nameLength);\n const decodedName = rawName.toString(\"utf8\");\n const directory = decodedName.endsWith(\"/\") || decodedName.endsWith(\"\\\\\");\n const name = normalizeEntryName(decodedName);\n assert(name !== \"\", \"ZIP entry resolves to an empty path\");\n assert(!names.has(name), `Duplicate ZIP entry: ${name}`);\n names.add(name);\n\n entries.push({\n compressedSize,\n directory,\n expectedCRC32,\n localOffset: zipOffset + localOffset,\n method,\n name,\n uncompressedSize,\n });\n offset += recordLength;\n }\n\n assert(offset === endOffset, \"ZIP central directory size does not match its records\");\n return entries;\n}\n\nfunction readEntry(archive, entry) {\n const offset = entry.localOffset;\n assert(offset + 30 <= archive.length, `ZIP local record is truncated: ${entry.name}`);\n assert(archive.readUInt32LE(offset) === 0x04034b50, `Invalid ZIP local record: ${entry.name}`);\n\n const nameLength = archive.readUInt16LE(offset + 26);\n const extraLength = archive.readUInt16LE(offset + 28);\n const dataOffset = offset + 30 + nameLength + extraLength;\n const dataEnd = dataOffset + entry.compressedSize;\n assert(dataEnd <= archive.length, `ZIP entry data is truncated: ${entry.name}`);\n\n const compressed = archive.subarray(dataOffset, dataEnd);\n const data = entry.method === 0 ? Buffer.from(compressed) : zlib.inflateRawSync(compressed);\n assert(data.length === entry.uncompressedSize, `ZIP entry size mismatch: ${entry.name}`);\n assert(\n calculateCRC32(data) === entry.expectedCRC32,\n `ZIP entry checksum mismatch: ${entry.name}`,\n );\n assert(!entry.directory || data.length === 0, `ZIP directory entry contains data: ${entry.name}`);\n return data;\n}\n\nfunction assertEmptyOutputDirectory(outputDirectory) {\n if (!fs.existsSync(outputDirectory)) {\n return;\n }\n assert(\n fs.statSync(outputDirectory).isDirectory(),\n `Output path is not a directory: ${outputDirectory}`,\n );\n assert(\n fs.readdirSync(outputDirectory).length === 0,\n `Output directory is not empty: ${outputDirectory}`,\n );\n}\n\nfunction unpackCharX(inputPath: string, outputPath: string): string {\n const resolvedInputPath = path.resolve(inputPath);\n const resolvedOutputPath = path.resolve(outputPath);\n const archive = fs.readFileSync(resolvedInputPath);\n const entries = parseZIP(archive);\n const extracted = new Map<string, { data: Buffer; directory: boolean }>();\n\n for (const entry of entries) {\n extracted.set(entry.name, {\n data: readEntry(archive, entry),\n directory: entry.directory,\n });\n }\n\n const cardEntry = extracted.get(\"card.json\");\n assert(cardEntry, \"CharX archive does not contain card.json\");\n assert(!cardEntry.directory, \"card.json is a directory\");\n const card = JSON.parse(cardEntry.data.toString(\"utf8\"));\n\n let decodedModule;\n if (extracted.has(\"module.risum\")) {\n const moduleEntry = extracted.get(\"module.risum\");\n assert(moduleEntry, \"CharX archive does not contain module.risum\");\n assert(!moduleEntry.directory, \"module.risum is a directory\");\n const map = fs.readFileSync(RPACK_MAP_PATH);\n decodedModule = decodeModule(moduleEntry.data, map);\n }\n\n const expandedSources = decodedModule\n ? createExpandedModuleSources(card, decodedModule)\n : new Map();\n for (const name of expandedSources.keys()) {\n assert(\n name === \"card.json\" || !extracted.has(name),\n `Generated module source conflicts with an archive entry: ${name}`,\n );\n }\n\n assertEmptyOutputDirectory(resolvedOutputPath);\n fs.mkdirSync(resolvedOutputPath, { recursive: true });\n\n for (const [name, entry] of extracted) {\n if (\n name === \"module.risum\" ||\n (decodedModule && name === \"card.json\") ||\n expandedSources.has(name)\n ) {\n continue;\n }\n const destination = path.join(resolvedOutputPath, ...name.split(\"/\"));\n if (entry.directory) {\n fs.mkdirSync(destination, { recursive: true });\n continue;\n }\n fs.mkdirSync(path.dirname(destination), { recursive: true });\n fs.writeFileSync(destination, entry.data);\n }\n\n for (const [name, data] of expandedSources) {\n const destination = path.join(resolvedOutputPath, ...name.split(\"/\"));\n fs.mkdirSync(path.dirname(destination), { recursive: true });\n fs.writeFileSync(destination, data);\n }\n\n const relativeOutput = path.relative(process.cwd(), resolvedOutputPath) || \".\";\n console.log(\n `Unpacked ${entries.length - (decodedModule ? 1 : 0)} archive files to ${relativeOutput}`,\n );\n return resolvedOutputPath;\n}\n\nexport { createExpandedModuleSources, decodeModule, parseZIP, unpackCharX };\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { createExpandedModuleSources } from \"./unpack-charx.js\";\n\nconst RPACK_MAP_PATH = path.join(\n path.dirname(fileURLToPath(import.meta.url)),\n \"..\",\n \"vendor\",\n \"rpack\",\n \"rpack_map.bin\",\n);\n\nfunction assert(condition: unknown, message: string): asserts condition {\n if (!condition) {\n throw new Error(message);\n }\n}\n\nfunction assertEmptyOutputDirectory(outputDirectory) {\n if (!fs.existsSync(outputDirectory)) {\n return;\n }\n assert(\n fs.statSync(outputDirectory).isDirectory(),\n `Output path is not a directory: ${outputDirectory}`,\n );\n assert(\n fs.readdirSync(outputDirectory).length === 0,\n `Output directory is not empty: ${outputDirectory}`,\n );\n}\n\nfunction decodeRPack(data, decodeMap) {\n for (let index = 0; index < data.length; index += 1) {\n data[index] = decodeMap[data[index]];\n }\n return data;\n}\n\nfunction readExactly(fileDescriptor, length, position, label) {\n const data = Buffer.allocUnsafe(length);\n let read = 0;\n while (read < length) {\n const count = fs.readSync(fileDescriptor, data, read, length - read, position + read);\n assert(count > 0, `${label} is truncated at byte ${position + read}`);\n read += count;\n }\n return data;\n}\n\nfunction sanitizeAssetName(name: string, fallback: string): string {\n const sanitized = Array.from(name, (character) =>\n character.charCodeAt(0) < 32 ? \"_\" : character,\n )\n .join(\"\")\n .replace(/[<>:\"/\\\\|?*]/g, \"_\")\n .replace(/[. ]+$/g, \"\")\n .trim();\n return sanitized.slice(0, 180) || fallback;\n}\n\nfunction detectAssetExtension(data, fallback) {\n if (data.subarray(0, 8).equals(Buffer.from(\"89504e470d0a1a0a\", \"hex\"))) {\n return \"png\";\n }\n if (data.subarray(0, 3).equals(Buffer.from(\"ffd8ff\", \"hex\"))) {\n return \"jpg\";\n }\n if (\n data.subarray(0, 6).toString(\"ascii\") === \"GIF87a\" ||\n data.subarray(0, 6).toString(\"ascii\") === \"GIF89a\"\n ) {\n return \"gif\";\n }\n if (\n data.subarray(0, 4).toString(\"ascii\") === \"RIFF\" &&\n data.subarray(8, 12).toString(\"ascii\") === \"WEBP\"\n ) {\n return \"webp\";\n }\n if (data.subarray(4, 12).toString(\"ascii\").includes(\"ftypavif\")) {\n return \"avif\";\n }\n return /^[a-z0-9]+$/i.test(fallback ?? \"\") ? fallback.toLowerCase() : \"bin\";\n}\n\nfunction takeAssetPath(asset, data, index, takenPaths) {\n const extension = detectAssetExtension(data, asset[2]);\n const baseName = sanitizeAssetName(asset[0] ?? \"\", `asset_${index + 1}`);\n let candidate = `assets/${baseName}.${extension}`;\n let collision = 1;\n while (takenPaths.has(candidate)) {\n collision += 1;\n candidate = `assets/${baseName}_${collision}.${extension}`;\n }\n takenPaths.add(candidate);\n return candidate;\n}\n\nfunction writeSources(outputDirectory, decodedModule, assetSources) {\n const card = {\n data: {\n name: decodedModule.module.name,\n },\n };\n const sources = createExpandedModuleSources(card, decodedModule);\n const manifestSource = sources.get(\"charx.json\");\n assert(manifestSource, \"Expanded module sources do not contain charx.json\");\n const manifest = JSON.parse(manifestSource.toString(\"utf8\"));\n manifest.assets = assetSources;\n sources.set(\"charx.json\", Buffer.from(`${JSON.stringify(manifest, null, 2)}\\n`, \"utf8\"));\n\n for (const [name, data] of sources) {\n const destination = path.join(outputDirectory, ...name.split(\"/\"));\n fs.mkdirSync(path.dirname(destination), { recursive: true });\n fs.writeFileSync(destination, data);\n }\n}\n\nfunction unpackRisuM(inputPath: string, outputPath: string): string {\n const resolvedInputPath = path.resolve(inputPath);\n const resolvedOutputPath = path.resolve(outputPath);\n assertEmptyOutputDirectory(resolvedOutputPath);\n\n const map = fs.readFileSync(RPACK_MAP_PATH);\n assert(map.length >= 512, `Invalid RPack map: ${RPACK_MAP_PATH}`);\n const decodeMap = map.subarray(256, 512);\n const fileDescriptor = fs.openSync(resolvedInputPath, \"r\");\n\n try {\n const fileSize = fs.fstatSync(fileDescriptor).size;\n const header = readExactly(fileDescriptor, 6, 0, \"RISUM header\");\n assert(header.readUInt8(0) === 111, \"Invalid RISUM magic number\");\n assert(header.readUInt8(1) === 0, `Unsupported RISUM version: ${header.readUInt8(1)}`);\n\n const payloadLength = header.readUInt32LE(2);\n const payload = readExactly(fileDescriptor, payloadLength, 6, \"RISUM module payload\");\n const decodedModule = JSON.parse(decodeRPack(payload, decodeMap).toString(\"utf8\"));\n assert(\n decodedModule?.type === \"risuModule\" && decodedModule.module,\n \"RISUM does not contain a Risu module\",\n );\n\n const assetMetadata = decodedModule.module.assets ?? [];\n const assetSources: any[] = [];\n const takenPaths = new Set<string>();\n let assetIndex = 0;\n let position = 6 + payloadLength;\n\n fs.mkdirSync(path.join(resolvedOutputPath, \"assets\"), { recursive: true });\n while (position < fileSize) {\n const marker = readExactly(fileDescriptor, 1, position, \"RISUM asset marker\").readUInt8(0);\n position += 1;\n if (marker === 0) {\n break;\n }\n assert(marker === 1, `Invalid RISUM asset marker at byte ${position - 1}: ${marker}`);\n assert(\n assetIndex < assetMetadata.length,\n \"RISUM contains more asset blocks than asset metadata entries\",\n );\n\n const lengthData = readExactly(fileDescriptor, 4, position, \"RISUM asset length\");\n const assetLength = lengthData.readUInt32LE(0);\n position += 4;\n const encodedAsset = readExactly(\n fileDescriptor,\n assetLength,\n position,\n `RISUM asset ${assetIndex + 1}`,\n );\n position += assetLength;\n\n const metadata = assetMetadata[assetIndex];\n assert(metadata, `RISUM asset ${assetIndex + 1} has no metadata`);\n const decodedAsset = decodeRPack(encodedAsset, decodeMap);\n const sourcePath = takeAssetPath(metadata, decodedAsset, assetIndex, takenPaths);\n const destination = path.join(resolvedOutputPath, ...sourcePath.split(\"/\"));\n fs.writeFileSync(destination, decodedAsset);\n assetSources.push({\n extension: path.extname(sourcePath).slice(1),\n file: sourcePath,\n name: metadata[0],\n });\n assetIndex += 1;\n\n if (assetIndex % 500 === 0) {\n console.log(`Extracted ${assetIndex} / ${assetMetadata.length} assets`);\n }\n }\n\n assert(\n assetIndex === assetMetadata.length,\n `RISUM contains ${assetIndex} asset blocks but declares ${assetMetadata.length}`,\n );\n assert(\n position === fileSize,\n `RISUM contains ${fileSize - position} trailing bytes after the end marker`,\n );\n writeSources(resolvedOutputPath, decodedModule, assetSources);\n\n const relativeOutput = path.relative(process.cwd(), resolvedOutputPath) || \".\";\n console.log(`Unpacked ${assetIndex} assets and module sources to ${relativeOutput}`);\n return resolvedOutputPath;\n } finally {\n fs.closeSync(fileDescriptor);\n }\n}\n\nexport { unpackRisuM };\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "risupack",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Command-line tools for packing and unpacking RisuAI modules",
|
|
5
5
|
"license": "AGPL-3.0-only",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/enzi221/risupack.git"
|
|
9
|
+
},
|
|
6
10
|
"bin": {
|
|
7
11
|
"risupack": "dist/cli.js"
|
|
8
12
|
},
|
|
@@ -21,7 +25,8 @@
|
|
|
21
25
|
"build": "vp build && tsc --project tsconfig.build.json",
|
|
22
26
|
"check": "tsc --noEmit",
|
|
23
27
|
"prepack": "npm run check && npm run build",
|
|
24
|
-
"prepare": "vp config"
|
|
28
|
+
"prepare": "vp config",
|
|
29
|
+
"test": "vp test"
|
|
25
30
|
},
|
|
26
31
|
"devDependencies": {
|
|
27
32
|
"@types/node": "^24.3.0",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"unpack-risum-CyOf_v7e.js","names":[],"sources":["../src/bundle.ts","../src/build-charx.ts","../src/inspect-risusave.ts","../src/unpack-charx.ts","../src/unpack-risum.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\n\nconst REQUIRE_PATTERN = /require\\s*\\(?[\"']([^\"']+)[\"']\\)?/g;\n\ninterface BundleState {\n entryPath: string;\n hoistedComments: string[];\n includedModules: Set<string>;\n preloads: string[];\n totalInputBytes: number;\n}\n\nfunction formatBytes(bytes: number): string {\n if (bytes === 0) {\n return \"0 B\";\n }\n\n const base = 1024;\n const sizes = [\"B\", \"KB\", \"MB\"];\n const index = Math.floor(Math.log(bytes) / Math.log(base));\n return `${Number.parseFloat((bytes / Math.pow(base, index)).toFixed(2))} ${sizes[index]}`;\n}\n\nfunction resolveModulePath(moduleName: string): string {\n return `${moduleName.replace(/\\./g, \"/\")}.lua`;\n}\n\nfunction minifyLua(content: string, hoistedComments: string[]): string {\n const tokenPattern =\n /(--\\[(=*)\\[[\\s\\S]*?\\]\\2\\])|(--.*)|(\\[(=*)\\[[\\s\\S]*?\\]\\5\\])|(\"([^\"\\\\]|\\\\.)*\")|('([^'\\\\]|\\\\.)*')/g;\n\n return content\n .replace(\n tokenPattern,\n (match: string, longComment?: string, _equals?: string, shortComment?: string) => {\n if (!longComment && !shortComment) {\n return match;\n }\n if (shortComment?.startsWith(\"--!\") || (longComment && /^--\\[(=*)\\[!/.test(match))) {\n hoistedComments.push(match);\n }\n return \" \";\n },\n )\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter((line) => line.length > 0)\n .join(\"\\n\");\n}\n\nfunction processModule(moduleName: string, state: BundleState): void {\n if (state.includedModules.has(moduleName)) {\n return;\n }\n\n const rootDirectory = path.dirname(path.resolve(state.entryPath));\n const modulePath = path.join(rootDirectory, resolveModulePath(moduleName));\n if (!fs.existsSync(modulePath)) {\n console.warn(`Warning: Module '${moduleName}' not found`);\n return;\n }\n\n const rawContent = fs.readFileSync(modulePath, \"utf8\");\n state.includedModules.add(moduleName);\n state.totalInputBytes += fs.statSync(modulePath).size;\n\n for (const match of rawContent.matchAll(new RegExp(REQUIRE_PATTERN.source, \"g\"))) {\n const dependency = match[1];\n if (dependency) {\n processModule(dependency, state);\n }\n }\n\n const minifiedContent = minifyLua(rawContent, state.hoistedComments);\n state.preloads.push(`package.preload[\"${moduleName}\"]=function(...)${minifiedContent} end`);\n}\n\nfunction bundleLua(entryPath: string, outputArgument: string): string {\n const resolvedEntryPath = path.resolve(entryPath);\n if (!fs.existsSync(resolvedEntryPath)) {\n throw new Error(`Entry file not found: ${entryPath}`);\n }\n\n let outputPath = path.resolve(outputArgument);\n if (fs.existsSync(outputPath) && fs.statSync(outputPath).isDirectory()) {\n outputPath = path.join(outputPath, path.basename(resolvedEntryPath));\n }\n if (path.extname(outputPath) !== \".lua\") {\n outputPath += \".lua\";\n }\n\n const state: BundleState = {\n entryPath: resolvedEntryPath,\n hoistedComments: [],\n includedModules: new Set(),\n preloads: [],\n totalInputBytes: fs.statSync(resolvedEntryPath).size,\n };\n const mainContent = fs.readFileSync(resolvedEntryPath, \"utf8\");\n\n for (const match of mainContent.matchAll(new RegExp(REQUIRE_PATTERN.source, \"g\"))) {\n const moduleName = match[1];\n if (moduleName) {\n processModule(moduleName, state);\n }\n }\n\n const mainMinified = minifyLua(mainContent, state.hoistedComments);\n const hoisted = state.hoistedComments.length > 0 ? `${state.hoistedComments.join(\"\\n\")}\\n` : \"\";\n const output = `${hoisted}${state.preloads.join(\"\\n\")}\\n${mainMinified}`;\n\n fs.mkdirSync(path.dirname(outputPath), { recursive: true });\n fs.writeFileSync(outputPath, output, \"utf8\");\n\n const outputBytes = fs.statSync(outputPath).size;\n const reduction = ((state.totalInputBytes - outputBytes) / state.totalInputBytes) * 100;\n console.log(\n `Bundled ${path.relative(process.cwd(), resolvedEntryPath)} to ${path.relative(process.cwd(), outputPath)}`,\n );\n console.log(\n `${state.includedModules.size} modules, ${formatBytes(state.totalInputBytes)} to ${formatBytes(outputBytes)}, ${reduction.toFixed(2)}% reduction`,\n );\n return outputPath;\n}\n\nexport { bundleLua };\n","import crypto from \"node:crypto\";\nimport fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport zlib from \"node:zlib\";\n\nimport { bundleLua } from \"./bundle.js\";\n\nconst DEFAULT_ICON = Buffer.from(\n \"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M/wHwAEAQH/69v17QAAAABJRU5ErkJggg==\",\n \"base64\",\n);\nconst RPACK_MAP_PATH = path.join(\n path.dirname(fileURLToPath(import.meta.url)),\n \"..\",\n \"vendor\",\n \"rpack\",\n \"rpack_map.bin\",\n);\n\nconst CRC32_TABLE = (() => {\n const table = new Uint32Array(256);\n for (let index = 0; index < table.length; index += 1) {\n let value = index;\n for (let bit = 0; bit < 8; bit += 1) {\n if ((value & 1) !== 0) {\n value = 0xedb88320 ^ (value >>> 1);\n } else {\n value >>>= 1;\n }\n }\n table[index] = value >>> 0;\n }\n return table;\n})();\n\nfunction assert(condition: unknown, message: string): asserts condition {\n if (!condition) {\n throw new Error(message);\n }\n}\n\nfunction calculateCRC32(data) {\n let value = 0xffffffff;\n for (const byte of data) {\n value = CRC32_TABLE[(value ^ byte) & 0xff] ^ (value >>> 8);\n }\n return (value ^ 0xffffffff) >>> 0;\n}\n\nfunction createUUID(seed) {\n const bytes = crypto.createHash(\"sha256\").update(seed).digest().subarray(0, 16);\n bytes[6] = (bytes[6] & 0x0f) | 0x50;\n bytes[8] = (bytes[8] & 0x3f) | 0x80;\n const hex = bytes.toString(\"hex\");\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n}\n\nfunction detectImageType(data) {\n if (data.subarray(0, 8).equals(Buffer.from(\"89504e470d0a1a0a\", \"hex\"))) {\n return \"PNG\";\n }\n if (data.subarray(0, 3).equals(Buffer.from(\"ffd8ff\", \"hex\"))) {\n return \"JPEG\";\n }\n if (\n data.subarray(0, 6).toString(\"ascii\") === \"GIF87a\" ||\n data.subarray(0, 6).toString(\"ascii\") === \"GIF89a\"\n ) {\n return \"GIF\";\n }\n if (\n data.subarray(0, 4).toString(\"ascii\") === \"RIFF\" &&\n data.subarray(8, 12).toString(\"ascii\") === \"WEBP\"\n ) {\n return \"WEBP\";\n }\n return \"Unknown\";\n}\n\nfunction getAssetCategory(extension) {\n const audio = new Set([\"flac\", \"mp3\", \"ogg\", \"wav\"]);\n const code = new Set([\"js\", \"lua\", \"ts\"]);\n const fonts = new Set([\"otf\", \"ttf\", \"woff\", \"woff2\"]);\n const images = new Set([\"avif\", \"gif\", \"jpeg\", \"jpg\", \"png\", \"webp\"]);\n const models = new Set([\"mmd\", \"obj\"]);\n const video = new Set([\"avi\", \"mkv\", \"mov\", \"mp4\", \"webm\"]);\n\n if (audio.has(extension)) {\n return \"audio\";\n }\n if (code.has(extension)) {\n return \"code\";\n }\n if (fonts.has(extension)) {\n return \"fonts\";\n }\n if (images.has(extension)) {\n return \"image\";\n }\n if (models.has(extension)) {\n return \"model\";\n }\n if (extension === \"onnx\" || extension === \"safetensors\" || extension === \"cpkt\") {\n return \"ai\";\n }\n if (video.has(extension)) {\n return \"video\";\n }\n return \"other\";\n}\n\nfunction readSource(manifestDirectory, source, label) {\n if (typeof source === \"string\") {\n return fs.readFileSync(path.resolve(manifestDirectory, source), \"utf8\");\n }\n assert(source && typeof source === \"object\", `${label} must be a file path or source object`);\n if (typeof source.content === \"string\") {\n return source.content;\n }\n assert(typeof source.file === \"string\", `${label}.file must be a string`);\n return fs.readFileSync(path.resolve(manifestDirectory, source.file), \"utf8\");\n}\n\nfunction sanitizeArchiveName(name: string): string {\n const sanitized = Array.from(name, (character) =>\n character.charCodeAt(0) < 32 ? \"_\" : character,\n )\n .join(\"\")\n .replace(/[<>:\"/\\\\|?*]/g, \"_\")\n .trim();\n return sanitized.slice(0, 100) || \"asset\";\n}\n\nfunction sortKeysDeep(value) {\n if (Array.isArray(value)) {\n return value.map(sortKeysDeep);\n }\n if (value && typeof value === \"object\" && !Buffer.isBuffer(value)) {\n const sorted = {};\n for (const key of Object.keys(value).sort()) {\n if (value[key] !== undefined) {\n sorted[key] = sortKeysDeep(value[key]);\n }\n }\n return sorted;\n }\n return value;\n}\n\nfunction parseFrontmatter(content, fileName) {\n const normalized = content.replace(/\\r\\n/g, \"\\n\");\n assert(normalized.startsWith(\"---\\n\"), `Missing frontmatter in ${fileName}`);\n const end = normalized.indexOf(\"\\n---\\n\", 4);\n assert(end !== -1, `Unclosed frontmatter in ${fileName}`);\n const metadata: Record<string, string | boolean> = {};\n for (const line of normalized.slice(4, end).split(\"\\n\")) {\n if (line.trim() === \"\") {\n continue;\n }\n const separator = line.indexOf(\":\");\n assert(separator !== -1, `Invalid frontmatter line in ${fileName}: ${line}`);\n const key = line.slice(0, separator).trim();\n const rawValue = line.slice(separator + 1).trim();\n assert(key !== \"\", `Empty frontmatter key in ${fileName}`);\n if (rawValue === \"true\") {\n metadata[key] = true;\n } else if (rawValue === \"false\") {\n metadata[key] = false;\n } else {\n metadata[key] = rawValue;\n }\n }\n return {\n body: normalized.slice(end + 5),\n metadata,\n };\n}\n\nfunction parseRegexBody(content, fileName) {\n const normalized = content.replace(/^\\n+/, \"\").replace(/\\n$/, \"\");\n const match = normalized.match(/^IN:\\s*\\n([\\s\\S]*?)\\nOUT:\\s*(?:\\n([\\s\\S]*))?$/);\n assert(match, `Invalid regex body in ${fileName}`);\n return {\n in: match[1],\n out: match[2] ?? \"\",\n };\n}\n\nfunction parseRegexDocument(content, fileName) {\n const { body, metadata } = parseFrontmatter(content, fileName);\n const parsed = parseRegexBody(body, fileName);\n return {\n ableFlag: metadata.ableFlag ?? true,\n comment: metadata.comment ?? \"\",\n flag: metadata.flag,\n in: parsed.in,\n out: parsed.out,\n type: metadata.type ?? \"editdisplay\",\n };\n}\n\nfunction buildRegexScripts(manifestDirectory, regexGroups: any[] = []) {\n const scripts: any[] = [];\n for (const group of regexGroups) {\n if (typeof group === \"string\") {\n scripts.push(\n parseRegexDocument(readSource(manifestDirectory, group, `regex ${group}`), group),\n );\n continue;\n }\n if (group.in !== undefined || group.out !== undefined) {\n assert(\n typeof group.in === \"string\" && typeof group.out === \"string\",\n \"Inline regex entries require in and out\",\n );\n scripts.push({\n ableFlag: group.ableFlag ?? true,\n comment: group.comment ?? \"\",\n flag: group.flag,\n in: group.in,\n out: group.out,\n type: group.type ?? \"editdisplay\",\n });\n continue;\n }\n\n assert(\n typeof group.file === \"string\",\n \"Regex entries require a file path, or inline in and out fields\",\n );\n scripts.push(\n parseRegexDocument(\n readSource(manifestDirectory, group.file, `regex ${group.file}`),\n group.file,\n ),\n );\n }\n return scripts;\n}\n\nfunction buildLorebook(manifest, manifestDirectory) {\n const folderKeys = new Map<string, string>();\n const folderNames = new Set<string>(manifest.folders ?? []);\n for (const entry of manifest.lorebook ?? []) {\n if (entry.folder) {\n folderNames.add(entry.folder);\n }\n }\n for (const name of folderNames) {\n folderKeys.set(\n name,\n `\\uf000folder:${createUUID(`${manifest.namespace ?? manifest.name}:folder:${name}`)}`,\n );\n }\n\n const temporaryDirectory = fs.mkdtempSync(path.join(os.tmpdir(), \"risums-charx-lorebook-\"));\n try {\n const lorebook = (manifest.lorebook ?? []).map((entry, index) => {\n let content;\n if (entry.bundle) {\n assert(\n typeof entry.file === \"string\",\n `Bundled lorebook ${entry.comment ?? index + 1} requires a file`,\n );\n const entryPath = path.resolve(manifestDirectory, entry.file);\n const outputPath = entry.bundleOutput\n ? path.resolve(manifestDirectory, entry.bundleOutput)\n : path.join(temporaryDirectory, `lorebook-${index}.lua`);\n content = readBundledLua(entryPath, outputPath);\n } else {\n content = readSource(\n manifestDirectory,\n entry,\n `lorebook ${entry.comment ?? entry.file ?? \"\"}`,\n );\n }\n return {\n activationPercent: entry.activationPercent,\n alwaysActive: entry.alwaysActive ?? false,\n bookVersion: entry.bookVersion ?? 2,\n comment: entry.comment ?? path.basename(entry.file ?? \"Lorebook\"),\n content,\n extentions: entry.extentions,\n folder: entry.folder ? folderKeys.get(entry.folder) : undefined,\n insertorder: entry.insertOrder ?? 100,\n key: entry.key ?? \"\",\n mode: entry.mode ?? \"normal\",\n secondkey: entry.secondaryKey ?? \"\",\n selective: entry.selective ?? false,\n useRegex: entry.useRegex ?? false,\n };\n });\n\n for (const name of folderNames) {\n lorebook.push({\n alwaysActive: false,\n bookVersion: 2,\n comment: name,\n content: \"\",\n insertorder: 100,\n key: folderKeys.get(name),\n mode: \"folder\",\n secondkey: \"\",\n selective: false,\n useRegex: false,\n });\n }\n return lorebook;\n } finally {\n fs.rmSync(temporaryDirectory, { force: true, recursive: true });\n }\n}\n\nfunction readBundledLua(entryPath: string, outputPath: string): string {\n bundleLua(entryPath, outputPath);\n return fs.readFileSync(outputPath, \"utf8\");\n}\n\nfunction buildTriggers(manifest, manifestDirectory) {\n const temporaryDirectory = fs.mkdtempSync(path.join(os.tmpdir(), \"risums-charx-\"));\n try {\n return (manifest.triggers ?? []).map((trigger, index) => {\n let effect = trigger.effect;\n if (trigger.lua) {\n const entryPath = path.resolve(manifestDirectory, trigger.lua);\n let code;\n if (trigger.bundle ?? true) {\n const outputPath = trigger.bundleOutput\n ? path.resolve(manifestDirectory, trigger.bundleOutput)\n : path.join(temporaryDirectory, `trigger-${index}.lua`);\n code = readBundledLua(entryPath, outputPath);\n } else {\n code = fs.readFileSync(entryPath, \"utf8\");\n }\n effect = [{ code, type: \"triggerlua\" }];\n }\n assert(Array.isArray(effect), `Trigger ${index + 1} requires lua or effect`);\n return {\n comment: trigger.comment ?? \"\",\n conditions: trigger.conditions ?? [],\n effect,\n lowLevelAccess: trigger.lowLevelAccess,\n type: trigger.type ?? \"start\",\n };\n });\n } finally {\n fs.rmSync(temporaryDirectory, { force: true, recursive: true });\n }\n}\n\nfunction createRisuM(module, encodeMap) {\n const payload = Buffer.from(\n JSON.stringify(sortKeysDeep({ module, type: \"risuModule\" }), null, 2),\n \"utf8\",\n );\n const encoded = Buffer.allocUnsafe(payload.length);\n for (let index = 0; index < payload.length; index += 1) {\n encoded[index] = encodeMap[payload[index]];\n }\n const header = Buffer.alloc(6);\n header.writeUInt8(111, 0);\n header.writeUInt8(0, 1);\n header.writeUInt32LE(encoded.length, 2);\n return Buffer.concat([header, encoded, Buffer.from([0])]);\n}\n\nfunction createAssetFiles(manifest, manifestDirectory) {\n const cardAssets: any[] = [];\n const files: Array<{ data: Buffer; name: string }> = [];\n const takenNames = new Set<string>();\n\n function addAsset({ data, extension, name, type }) {\n const category = getAssetCategory(extension);\n const baseDirectory = `assets/${type === \"icon\" ? \"icon\" : \"other\"}/${category}`;\n const baseName = sanitizeArchiveName(name);\n let archiveName = baseName;\n let suffix = 0;\n while (takenNames.has(archiveName)) {\n suffix += 1;\n archiveName = `${baseName}_${suffix}`;\n }\n const archivePath = `${baseDirectory}/${archiveName}.${extension}`;\n takenNames.add(archiveName);\n cardAssets.push({\n ext: extension,\n name,\n type,\n uri: `embeded://${archivePath}`,\n });\n files.push({ data, name: archivePath });\n files.push({\n data: Buffer.from(JSON.stringify({ type: detectImageType(data) }, null, 2)),\n name: `x_meta/${archiveName}.json`,\n });\n }\n\n if (manifest.icon) {\n const iconPath = path.resolve(manifestDirectory, manifest.icon);\n const extension = path.extname(iconPath).slice(1).toLowerCase() || \"png\";\n addAsset({ data: fs.readFileSync(iconPath), extension, name: \"main\", type: \"icon\" });\n } else {\n addAsset({ data: DEFAULT_ICON, extension: \"png\", name: \"main\", type: \"icon\" });\n }\n\n for (const asset of manifest.assets ?? []) {\n assert(typeof asset.file === \"string\", \"Asset file must be a string\");\n const assetPath = path.resolve(manifestDirectory, asset.file);\n const extension = (asset.extension ?? path.extname(assetPath).slice(1)).toLowerCase();\n assert(extension !== \"\", `Cannot determine extension for ${asset.file}`);\n assert(/^[a-z0-9]+$/.test(extension), `Invalid extension for ${asset.file}: ${extension}`);\n addAsset({\n data: fs.readFileSync(assetPath),\n extension,\n name: asset.name ?? path.basename(assetPath, path.extname(assetPath)),\n type: \"x-risu-asset\",\n });\n }\n return { cardAssets, files };\n}\n\nfunction createCard(manifest, lorebook, cardAssets, sourceCard?: Record<string, any>) {\n const sourceData = sourceCard?.data ?? {};\n const sourceExtensions = sourceData.extensions ?? {};\n const sourceRisuAI = sourceExtensions.risuai ?? {};\n const entries = lorebook.map((entry) => ({\n case_sensitive: entry.extentions?.risu_case_sensitive ?? false,\n comment: entry.comment,\n constant: entry.alwaysActive,\n content: entry.content,\n enabled: true,\n extensions: {\n ...entry.extentions,\n risu_activationPercent: entry.activationPercent,\n risu_loreCache: entry.loreCache,\n },\n folder: entry.folder,\n insertion_order: entry.insertorder,\n keys: entry.key.split(\",\").map((key) => key.trim()),\n mode: entry.mode,\n name: entry.comment,\n secondary_keys: entry.selective\n ? entry.secondkey.split(\",\").map((key) => key.trim())\n : undefined,\n selective: entry.selective,\n use_regex: entry.useRegex,\n }));\n return {\n ...sourceCard,\n data: {\n ...sourceData,\n alternate_greetings: sourceData.alternate_greetings ?? [],\n assets: cardAssets,\n character_book: {\n entries,\n extensions: { risu_fullWordMatching: false },\n },\n character_version: manifest.version ?? sourceData.character_version ?? \"\",\n creation_date: sourceData.creation_date ?? 0,\n creator: manifest.creator ?? sourceData.creator ?? \"\",\n creator_notes: manifest.description ?? sourceData.creator_notes ?? \"\",\n description: sourceData.description ?? \"\",\n extensions: {\n ...sourceExtensions,\n moduleNoneImage: manifest.icon ? undefined : true,\n risuai: {\n ...sourceRisuAI,\n additionalText: sourceRisuAI.additionalText ?? \"\",\n backgroundHTML: manifest.CSS\n ? readSource(path.dirname(manifest.__path), manifest.CSS, \"CSS\")\n : \"\",\n bias: sourceRisuAI.bias ?? [],\n defaultVariables: sourceRisuAI.defaultVariables ?? \"\",\n hideChatIcon: manifest.hideIcon ?? false,\n inlayViewScreen: sourceRisuAI.inlayViewScreen ?? false,\n largePortrait: sourceRisuAI.largePortrait ?? false,\n license: manifest.license ?? \"\",\n lorePlus: sourceRisuAI.lorePlus ?? false,\n lowLevelAccess: manifest.lowLevelAccess ?? false,\n moduleNamespace: manifest.namespace,\n newGenData: sourceRisuAI.newGenData,\n prebuiltAssetCommand: sourceRisuAI.prebuiltAssetCommand ?? \"\",\n prebuiltAssetExclude: sourceRisuAI.prebuiltAssetExclude ?? [],\n prebuiltAssetStyle: sourceRisuAI.prebuiltAssetStyle ?? \"\",\n sdData: sourceRisuAI.sdData ?? [],\n toggles: manifest.toggles\n ? readSource(path.dirname(manifest.__path), manifest.toggles, \"toggles\")\n : \"\",\n utilityBot: sourceRisuAI.utilityBot ?? false,\n viewScreen: \"none\",\n virtualscript: sourceRisuAI.virtualscript ?? \"\",\n vits: sourceRisuAI.vits ?? {},\n },\n },\n first_mes: sourceData.first_mes ?? \"\",\n group_only_greetings: sourceData.group_only_greetings ?? [],\n mes_example: sourceData.mes_example ?? \"\",\n modification_date: process.env.SOURCE_DATE_EPOCH\n ? Number(process.env.SOURCE_DATE_EPOCH)\n : Math.floor(Date.now() / 1000),\n name: manifest.name,\n nickname: sourceData.nickname ?? \"\",\n personality: sourceData.personality ?? \"\",\n post_history_instructions: sourceData.post_history_instructions ?? \"\",\n scenario: sourceData.scenario ?? \"\",\n source: sourceData.source ?? [],\n system_prompt: sourceData.system_prompt ?? \"\",\n tags: manifest.tags ?? sourceData.tags ?? [],\n },\n spec: sourceCard?.spec ?? \"chara_card_v3\",\n spec_version: sourceCard?.spec_version ?? \"3.0\",\n };\n}\n\nfunction getDOSDateTime(date) {\n const year = Math.max(1980, date.getUTCFullYear());\n return {\n date: ((year - 1980) << 9) | ((date.getUTCMonth() + 1) << 5) | date.getUTCDate(),\n time:\n (date.getUTCHours() << 11) |\n (date.getUTCMinutes() << 5) |\n Math.floor(date.getUTCSeconds() / 2),\n };\n}\n\nfunction createZIP(files, timestamp) {\n assert(files.length <= 0xffff, \"ZIP contains too many files\");\n const centralRecords: Buffer[] = [];\n const localRecords: Buffer[] = [];\n let offset = 0;\n const { date, time } = getDOSDateTime(timestamp);\n\n for (const file of files) {\n const data = Buffer.from(file.data);\n const compressed = zlib.deflateRawSync(data, { level: 6 });\n const fileName = Buffer.from(file.name.replace(/\\\\/g, \"/\"), \"utf8\");\n const CRC32 = calculateCRC32(data);\n assert(\n data.length <= 0xffffffff && compressed.length <= 0xffffffff,\n `${file.name} exceeds ZIP32 limits`,\n );\n\n const localHeader = Buffer.alloc(30);\n localHeader.writeUInt32LE(0x04034b50, 0);\n localHeader.writeUInt16LE(20, 4);\n localHeader.writeUInt16LE(0x0800, 6);\n localHeader.writeUInt16LE(8, 8);\n localHeader.writeUInt16LE(time, 10);\n localHeader.writeUInt16LE(date, 12);\n localHeader.writeUInt32LE(CRC32, 14);\n localHeader.writeUInt32LE(compressed.length, 18);\n localHeader.writeUInt32LE(data.length, 22);\n localHeader.writeUInt16LE(fileName.length, 26);\n localHeader.writeUInt16LE(0, 28);\n localRecords.push(localHeader, fileName, compressed);\n\n const centralHeader = Buffer.alloc(46);\n centralHeader.writeUInt32LE(0x02014b50, 0);\n centralHeader.writeUInt16LE(20, 4);\n centralHeader.writeUInt16LE(20, 6);\n centralHeader.writeUInt16LE(0x0800, 8);\n centralHeader.writeUInt16LE(8, 10);\n centralHeader.writeUInt16LE(time, 12);\n centralHeader.writeUInt16LE(date, 14);\n centralHeader.writeUInt32LE(CRC32, 16);\n centralHeader.writeUInt32LE(compressed.length, 20);\n centralHeader.writeUInt32LE(data.length, 24);\n centralHeader.writeUInt16LE(fileName.length, 28);\n centralHeader.writeUInt16LE(0, 30);\n centralHeader.writeUInt16LE(0, 32);\n centralHeader.writeUInt16LE(0, 34);\n centralHeader.writeUInt16LE(0, 36);\n centralHeader.writeUInt32LE(0, 38);\n centralHeader.writeUInt32LE(offset, 42);\n centralRecords.push(centralHeader, fileName);\n offset += localHeader.length + fileName.length + compressed.length;\n }\n\n const centralDirectory = Buffer.concat(centralRecords);\n const end = Buffer.alloc(22);\n end.writeUInt32LE(0x06054b50, 0);\n end.writeUInt16LE(0, 4);\n end.writeUInt16LE(0, 6);\n end.writeUInt16LE(files.length, 8);\n end.writeUInt16LE(files.length, 10);\n end.writeUInt32LE(centralDirectory.length, 12);\n end.writeUInt32LE(offset, 16);\n end.writeUInt16LE(0, 20);\n return Buffer.concat([...localRecords, centralDirectory, end]);\n}\n\nfunction buildCharX(manifestPath: string, outputArgument?: string): string {\n const resolvedManifestPath = path.resolve(manifestPath);\n const manifestDirectory = path.dirname(resolvedManifestPath);\n const manifest = JSON.parse(fs.readFileSync(resolvedManifestPath, \"utf8\"));\n manifest.__path = resolvedManifestPath;\n assert(typeof manifest.name === \"string\" && manifest.name !== \"\", \"Manifest name is required\");\n\n const lorebook = buildLorebook(manifest, manifestDirectory);\n const regex = buildRegexScripts(manifestDirectory, manifest.regex);\n const trigger = buildTriggers(manifest, manifestDirectory);\n const { cardAssets, files: assetFiles } = createAssetFiles(manifest, manifestDirectory);\n const sourceCard = manifest.card\n ? JSON.parse(readSource(manifestDirectory, manifest.card, \"card\"))\n : undefined;\n const card = createCard(manifest, lorebook, cardAssets, sourceCard);\n const module = {\n description: `Module for ${manifest.name}`,\n id: createUUID(`${manifest.namespace ?? manifest.name}:module`),\n lorebook,\n name: `${manifest.name} Module`,\n regex,\n trigger,\n };\n\n const map = fs.readFileSync(RPACK_MAP_PATH);\n assert(map.length >= 256, `Invalid RPack map: ${RPACK_MAP_PATH}`);\n const files = [\n ...assetFiles,\n { data: Buffer.from(JSON.stringify(sortKeysDeep(card), null, 2)), name: \"card.json\" },\n { data: createRisuM(sortKeysDeep(module), map.subarray(0, 256)), name: \"module.risum\" },\n ].sort((left, right) => left.name.localeCompare(right.name));\n\n const outputPath = outputArgument\n ? path.resolve(outputArgument)\n : path.resolve(\n manifestDirectory,\n manifest.output ?? `../dist/${sanitizeArchiveName(manifest.name)}.charx`,\n );\n fs.mkdirSync(path.dirname(outputPath), { recursive: true });\n const timestamp = process.env.SOURCE_DATE_EPOCH\n ? new Date(Number(process.env.SOURCE_DATE_EPOCH) * 1000)\n : new Date();\n fs.writeFileSync(outputPath, createZIP(files, timestamp));\n console.log(`Built ${path.relative(process.cwd(), outputPath)} (${files.length} files)`);\n return outputPath;\n}\n\nexport { buildCharX };\n","import zlib from \"node:zlib\";\n\nconst MAGIC = Buffer.from(\"RISUSAVE\\0\");\nconst MODULE_BLOCK_TYPE = 5;\n\ninterface ModuleRecord {\n id?: unknown;\n name?: unknown;\n namespace?: unknown;\n [key: string]: unknown;\n}\n\nfunction parseModuleBlock(database: Buffer): ModuleRecord[] {\n if (!database.subarray(0, MAGIC.length).equals(MAGIC)) {\n throw new Error(\"Invalid RISUSAVE header\");\n }\n\n let offset = MAGIC.length;\n while (offset < database.length) {\n if (offset + 3 > database.length) {\n throw new Error(`Truncated block header at byte ${offset}`);\n }\n const type = database[offset];\n const compressed = database[offset + 1] === 1;\n const nameLength = database[offset + 2];\n offset += 3;\n\n if (offset + nameLength + 4 > database.length) {\n throw new Error(`Truncated block name at byte ${offset}`);\n }\n const name = database.subarray(offset, offset + nameLength).toString(\"utf8\");\n offset += nameLength;\n const contentLength = database.readUInt32LE(offset);\n offset += 4;\n\n if (offset + contentLength > database.length) {\n throw new Error(`Truncated ${name} block at byte ${offset}`);\n }\n let content = database.subarray(offset, offset + contentLength);\n offset += contentLength;\n\n if (type !== MODULE_BLOCK_TYPE) {\n continue;\n }\n if (compressed) {\n content = zlib.gunzipSync(content);\n }\n return JSON.parse(content.toString(\"utf8\")) as ModuleRecord[];\n }\n throw new Error(\"RISUSAVE module block not found\");\n}\n\nexport { parseModuleBlock };\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport zlib from \"node:zlib\";\n\nconst RPACK_MAP_PATH = path.join(\n path.dirname(fileURLToPath(import.meta.url)),\n \"..\",\n \"vendor\",\n \"rpack\",\n \"rpack_map.bin\",\n);\n\nconst CRC32_TABLE = (() => {\n const table = new Uint32Array(256);\n for (let index = 0; index < table.length; index += 1) {\n let value = index;\n for (let bit = 0; bit < 8; bit += 1) {\n if ((value & 1) !== 0) {\n value = 0xedb88320 ^ (value >>> 1);\n } else {\n value >>>= 1;\n }\n }\n table[index] = value >>> 0;\n }\n return table;\n})();\n\nfunction assert(condition: unknown, message: string): asserts condition {\n if (!condition) {\n throw new Error(message);\n }\n}\n\nfunction calculateCRC32(data) {\n let value = 0xffffffff;\n for (const byte of data) {\n value = CRC32_TABLE[(value ^ byte) & 0xff] ^ (value >>> 8);\n }\n return (value ^ 0xffffffff) >>> 0;\n}\n\nfunction decodeModule(data: Buffer, map: Buffer): Record<string, any> {\n assert(data.length >= 7, \"module.risum is truncated\");\n assert(data.readUInt8(0) === 111, \"Invalid module.risum magic number\");\n assert(data.readUInt8(1) === 0, `Unsupported module.risum version: ${data.readUInt8(1)}`);\n\n const encodedLength = data.readUInt32LE(2);\n assert(encodedLength <= data.length - 6, \"module.risum payload is truncated\");\n assert(map.length >= 256, `Invalid RPack map: ${RPACK_MAP_PATH}`);\n\n let decodeMap;\n if (map.length >= 512) {\n decodeMap = map.subarray(256, 512);\n } else {\n decodeMap = Buffer.alloc(256);\n const seen = new Set();\n for (let index = 0; index < 256; index += 1) {\n const encoded = map[index];\n assert(!seen.has(encoded), \"RPack encode map is not a permutation\");\n seen.add(encoded);\n decodeMap[encoded] = index;\n }\n }\n\n const encoded = data.subarray(6, 6 + encodedLength);\n const decoded = Buffer.allocUnsafe(encoded.length);\n for (let index = 0; index < encoded.length; index += 1) {\n decoded[index] = decodeMap[encoded[index]];\n }\n\n const parsed = JSON.parse(decoded.toString(\"utf8\"));\n assert(\n parsed && parsed.type === \"risuModule\" && parsed.module,\n \"module.risum does not contain a Risu module\",\n );\n return parsed;\n}\n\nfunction findEndOfCentralDirectory(archive) {\n const minimumOffset = Math.max(0, archive.length - 0xffff - 22);\n for (let offset = archive.length - 22; offset >= minimumOffset; offset -= 1) {\n if (archive.readUInt32LE(offset) === 0x06054b50) {\n const commentLength = archive.readUInt16LE(offset + 20);\n if (offset + 22 + commentLength === archive.length) {\n return offset;\n }\n }\n }\n throw new Error(\"ZIP end record not found\");\n}\n\nfunction normalizeEntryName(name) {\n assert(name !== \"\", \"ZIP entry has an empty name\");\n assert(!name.includes(\"\\0\"), `ZIP entry contains a null byte: ${JSON.stringify(name)}`);\n\n const normalized = name.replace(/\\\\/g, \"/\");\n assert(!normalized.startsWith(\"/\"), `ZIP entry uses an absolute path: ${name}`);\n assert(!/^[a-zA-Z]:/.test(normalized), `ZIP entry uses an absolute path: ${name}`);\n\n const parts = normalized.split(\"/\");\n assert(!parts.includes(\"..\"), `ZIP entry escapes the output directory: ${name}`);\n return parts.filter((part) => part !== \"\" && part !== \".\").join(\"/\");\n}\n\nfunction sanitizeSourceName(name: string, fallback: string): string {\n const sanitized = Array.from(name, (character) =>\n character.charCodeAt(0) < 32 ? \"_\" : character,\n )\n .join(\"\")\n .replace(/[<>:\"/\\\\|?*]/g, \"_\")\n .replace(/[. ]+$/g, \"\")\n .trim();\n return sanitized || fallback;\n}\n\nfunction sortKeysDeep(value) {\n if (Array.isArray(value)) {\n return value.map(sortKeysDeep);\n }\n if (value && typeof value === \"object\" && !Buffer.isBuffer(value)) {\n const sorted = {};\n for (const key of Object.keys(value).sort()) {\n if (value[key] !== undefined) {\n sorted[key] = sortKeysDeep(value[key]);\n }\n }\n return sorted;\n }\n return value;\n}\n\nfunction takeSourcePath(directory, label, extension, takenPaths) {\n const baseName = sanitizeSourceName(label, \"untitled\");\n const suffix = baseName.toLowerCase().endsWith(extension) ? \"\" : extension;\n let candidate = `${directory}/${baseName}${suffix}`;\n let collision = 1;\n while (takenPaths.has(candidate)) {\n collision += 1;\n candidate = `${directory}/${baseName}_${collision}${suffix}`;\n }\n takenPaths.add(candidate);\n return candidate;\n}\n\nfunction createRegexDocument(regex) {\n const frontmatter = [`ableFlag: ${regex.ableFlag ?? true}`, `comment: ${regex.comment ?? \"\"}`];\n if (regex.flag !== undefined) {\n frontmatter.push(`flag: ${regex.flag}`);\n }\n frontmatter.push(`type: ${regex.type ?? \"editdisplay\"}`);\n return `---\\n${frontmatter.join(\"\\n\")}\\n---\\n\\nIN:\\n${regex.in ?? \"\"}\\nOUT:\\n${regex.out ?? \"\"}\\n`;\n}\n\nfunction createExpandedModuleSources(\n card: Record<string, any>,\n decodedModule: Record<string, any>,\n): Map<string, Buffer> {\n const moduleData = decodedModule.module;\n const files = new Map<string, Buffer>();\n const folderNames = new Map<any, any>();\n const folders: any[] = [];\n const takenPaths = new Set<string>();\n\n for (const entry of moduleData.lorebook ?? []) {\n if (entry.mode !== \"folder\") {\n continue;\n }\n folderNames.set(entry.key, entry.comment);\n folders.push(entry.comment);\n }\n\n const lorebook: any[] = [];\n for (const entry of moduleData.lorebook ?? []) {\n if (entry.mode === \"folder\") {\n continue;\n }\n const file = takeSourcePath(\"lorebooks\", entry.comment, \".md\", takenPaths);\n files.set(file, Buffer.from(entry.content ?? \"\", \"utf8\"));\n lorebook.push({\n activationPercent: entry.activationPercent,\n alwaysActive: entry.alwaysActive ?? false,\n bookVersion: entry.bookVersion ?? 2,\n comment: entry.comment ?? \"\",\n extentions: entry.extentions,\n file,\n folder: folderNames.get(entry.folder),\n insertOrder: entry.insertorder ?? 100,\n key: entry.key ?? \"\",\n mode: entry.mode ?? \"normal\",\n secondaryKey: entry.secondkey ?? \"\",\n selective: entry.selective ?? false,\n useRegex: entry.useRegex ?? false,\n });\n }\n\n const regex: string[] = [];\n for (const entry of moduleData.regex ?? []) {\n const file = takeSourcePath(\"regex\", entry.comment, \".md\", takenPaths);\n files.set(file, Buffer.from(createRegexDocument(entry), \"utf8\"));\n regex.push(file);\n }\n\n const triggers: any[] = [];\n for (let index = 0; index < (moduleData.trigger ?? []).length; index += 1) {\n const trigger = moduleData.trigger[index];\n const luaEffect =\n trigger.effect?.length === 1 && trigger.effect[0].type === \"triggerlua\"\n ? trigger.effect[0]\n : undefined;\n if (!luaEffect || typeof luaEffect.code !== \"string\") {\n triggers.push(trigger);\n continue;\n }\n\n const label = trigger.comment || `trigger-${index + 1}`;\n const luaPath = takeSourcePath(\"triggers\", label, \".lua\", takenPaths);\n files.set(luaPath, Buffer.from(luaEffect.code, \"utf8\"));\n triggers.push({\n bundle: false,\n comment: trigger.comment ?? \"\",\n conditions: trigger.conditions ?? [],\n lowLevelAccess: trigger.lowLevelAccess,\n lua: luaPath,\n type: trigger.type ?? \"start\",\n });\n }\n\n const risuai = card.data?.extensions?.risuai ?? {};\n const manifest: Record<string, any> = {\n card: \"card.json\",\n creator: card.data?.creator,\n description: card.data?.creator_notes ?? moduleData.description ?? \"\",\n folders,\n hideIcon: risuai.hideChatIcon ?? moduleData.hideIcon ?? false,\n lorebook,\n lowLevelAccess: risuai.lowLevelAccess ?? moduleData.lowLevelAccess ?? false,\n name: card.data?.name ?? moduleData.name,\n namespace: risuai.moduleNamespace ?? moduleData.namespace,\n regex,\n tags: card.data?.tags,\n triggers,\n version: card.data?.character_version ?? \"\",\n };\n\n const CSS = risuai.backgroundHTML ?? moduleData.backgroundEmbedding;\n if (CSS) {\n manifest.CSS = \"style.html\";\n files.set(\"style.html\", Buffer.from(CSS, \"utf8\"));\n }\n const toggles = risuai.toggles ?? moduleData.customModuleToggle;\n if (toggles) {\n manifest.toggles = \"toggles.txt\";\n files.set(\"toggles.txt\", Buffer.from(toggles, \"utf8\"));\n }\n\n const mainIcon = card.data?.assets?.find(\n (asset) => asset.type === \"icon\" && asset.name === \"main\",\n );\n if (mainIcon?.uri?.startsWith(\"embeded://\")) {\n manifest.icon = mainIcon.uri.slice(\"embeded://\".length);\n }\n\n const assets: any[] = [];\n for (const asset of card.data?.assets ?? []) {\n if (asset === mainIcon || !asset.uri?.startsWith(\"embeded://\")) {\n continue;\n }\n assets.push({\n extension: asset.ext,\n file: asset.uri.slice(\"embeded://\".length),\n name: asset.name,\n });\n }\n if (assets.length > 0) {\n manifest.assets = assets;\n }\n\n files.set(\n \"charx.json\",\n Buffer.from(`${JSON.stringify(sortKeysDeep(manifest), null, 2)}\\n`, \"utf8\"),\n );\n return files;\n}\n\nfunction parseZIP(archive: Buffer) {\n const endOffset = findEndOfCentralDirectory(archive);\n const diskNumber = archive.readUInt16LE(endOffset + 4);\n const centralDisk = archive.readUInt16LE(endOffset + 6);\n const diskEntries = archive.readUInt16LE(endOffset + 8);\n const totalEntries = archive.readUInt16LE(endOffset + 10);\n const centralSize = archive.readUInt32LE(endOffset + 12);\n const centralOffset = archive.readUInt32LE(endOffset + 16);\n\n assert(diskNumber === 0 && centralDisk === 0, \"Multi-disk ZIP archives are not supported\");\n assert(diskEntries === totalEntries, \"Inconsistent ZIP entry count\");\n assert(\n totalEntries !== 0xffff && centralSize !== 0xffffffff && centralOffset !== 0xffffffff,\n \"ZIP64 is not supported\",\n );\n\n const zipOffset = endOffset - centralSize - centralOffset;\n assert(zipOffset >= 0, \"Invalid ZIP central directory offset\");\n\n const entries: any[] = [];\n const names = new Set();\n let offset = zipOffset + centralOffset;\n for (let index = 0; index < totalEntries; index += 1) {\n assert(offset + 46 <= archive.length, \"ZIP central directory is truncated\");\n assert(\n archive.readUInt32LE(offset) === 0x02014b50,\n `Invalid ZIP central record at byte ${offset}`,\n );\n\n const flags = archive.readUInt16LE(offset + 8);\n const method = archive.readUInt16LE(offset + 10);\n const expectedCRC32 = archive.readUInt32LE(offset + 16);\n const compressedSize = archive.readUInt32LE(offset + 20);\n const uncompressedSize = archive.readUInt32LE(offset + 24);\n const nameLength = archive.readUInt16LE(offset + 28);\n const extraLength = archive.readUInt16LE(offset + 30);\n const commentLength = archive.readUInt16LE(offset + 32);\n const diskStart = archive.readUInt16LE(offset + 34);\n const localOffset = archive.readUInt32LE(offset + 42);\n const recordLength = 46 + nameLength + extraLength + commentLength;\n\n assert(offset + recordLength <= archive.length, \"ZIP central record is truncated\");\n assert((flags & 1) === 0, \"Encrypted ZIP entries are not supported\");\n assert(method === 0 || method === 8, `Unsupported ZIP compression method: ${method}`);\n assert(diskStart === 0, \"Multi-disk ZIP entries are not supported\");\n assert(\n compressedSize !== 0xffffffff &&\n uncompressedSize !== 0xffffffff &&\n localOffset !== 0xffffffff,\n \"ZIP64 entries are not supported\",\n );\n\n const rawName = archive.subarray(offset + 46, offset + 46 + nameLength);\n const decodedName = rawName.toString(\"utf8\");\n const directory = decodedName.endsWith(\"/\") || decodedName.endsWith(\"\\\\\");\n const name = normalizeEntryName(decodedName);\n assert(name !== \"\", \"ZIP entry resolves to an empty path\");\n assert(!names.has(name), `Duplicate ZIP entry: ${name}`);\n names.add(name);\n\n entries.push({\n compressedSize,\n directory,\n expectedCRC32,\n localOffset: zipOffset + localOffset,\n method,\n name,\n uncompressedSize,\n });\n offset += recordLength;\n }\n\n assert(offset === endOffset, \"ZIP central directory size does not match its records\");\n return entries;\n}\n\nfunction readEntry(archive, entry) {\n const offset = entry.localOffset;\n assert(offset + 30 <= archive.length, `ZIP local record is truncated: ${entry.name}`);\n assert(archive.readUInt32LE(offset) === 0x04034b50, `Invalid ZIP local record: ${entry.name}`);\n\n const nameLength = archive.readUInt16LE(offset + 26);\n const extraLength = archive.readUInt16LE(offset + 28);\n const dataOffset = offset + 30 + nameLength + extraLength;\n const dataEnd = dataOffset + entry.compressedSize;\n assert(dataEnd <= archive.length, `ZIP entry data is truncated: ${entry.name}`);\n\n const compressed = archive.subarray(dataOffset, dataEnd);\n const data = entry.method === 0 ? Buffer.from(compressed) : zlib.inflateRawSync(compressed);\n assert(data.length === entry.uncompressedSize, `ZIP entry size mismatch: ${entry.name}`);\n assert(\n calculateCRC32(data) === entry.expectedCRC32,\n `ZIP entry checksum mismatch: ${entry.name}`,\n );\n assert(!entry.directory || data.length === 0, `ZIP directory entry contains data: ${entry.name}`);\n return data;\n}\n\nfunction assertEmptyOutputDirectory(outputDirectory) {\n if (!fs.existsSync(outputDirectory)) {\n return;\n }\n assert(\n fs.statSync(outputDirectory).isDirectory(),\n `Output path is not a directory: ${outputDirectory}`,\n );\n assert(\n fs.readdirSync(outputDirectory).length === 0,\n `Output directory is not empty: ${outputDirectory}`,\n );\n}\n\nfunction unpackCharX(inputPath: string, outputPath: string): string {\n const resolvedInputPath = path.resolve(inputPath);\n const resolvedOutputPath = path.resolve(outputPath);\n const archive = fs.readFileSync(resolvedInputPath);\n const entries = parseZIP(archive);\n const extracted = new Map<string, { data: Buffer; directory: boolean }>();\n\n for (const entry of entries) {\n extracted.set(entry.name, {\n data: readEntry(archive, entry),\n directory: entry.directory,\n });\n }\n\n const cardEntry = extracted.get(\"card.json\");\n assert(cardEntry, \"CharX archive does not contain card.json\");\n assert(!cardEntry.directory, \"card.json is a directory\");\n const card = JSON.parse(cardEntry.data.toString(\"utf8\"));\n\n let decodedModule;\n if (extracted.has(\"module.risum\")) {\n const moduleEntry = extracted.get(\"module.risum\");\n assert(moduleEntry, \"CharX archive does not contain module.risum\");\n assert(!moduleEntry.directory, \"module.risum is a directory\");\n const map = fs.readFileSync(RPACK_MAP_PATH);\n decodedModule = decodeModule(moduleEntry.data, map);\n }\n\n const expandedSources = decodedModule\n ? createExpandedModuleSources(card, decodedModule)\n : new Map();\n for (const name of expandedSources.keys()) {\n assert(\n !extracted.has(name),\n `Generated module source conflicts with an archive entry: ${name}`,\n );\n }\n\n assertEmptyOutputDirectory(resolvedOutputPath);\n fs.mkdirSync(resolvedOutputPath, { recursive: true });\n\n for (const [name, entry] of extracted) {\n if (name === \"module.risum\") {\n continue;\n }\n const destination = path.join(resolvedOutputPath, ...name.split(\"/\"));\n if (entry.directory) {\n fs.mkdirSync(destination, { recursive: true });\n continue;\n }\n fs.mkdirSync(path.dirname(destination), { recursive: true });\n fs.writeFileSync(destination, entry.data);\n }\n\n for (const [name, data] of expandedSources) {\n const destination = path.join(resolvedOutputPath, ...name.split(\"/\"));\n fs.mkdirSync(path.dirname(destination), { recursive: true });\n fs.writeFileSync(destination, data);\n }\n\n const relativeOutput = path.relative(process.cwd(), resolvedOutputPath) || \".\";\n console.log(\n `Unpacked ${entries.length - (decodedModule ? 1 : 0)} archive files to ${relativeOutput}`,\n );\n return resolvedOutputPath;\n}\n\nexport { createExpandedModuleSources, decodeModule, parseZIP, unpackCharX };\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { createExpandedModuleSources } from \"./unpack-charx.js\";\n\nconst RPACK_MAP_PATH = path.join(\n path.dirname(fileURLToPath(import.meta.url)),\n \"..\",\n \"vendor\",\n \"rpack\",\n \"rpack_map.bin\",\n);\n\nfunction assert(condition: unknown, message: string): asserts condition {\n if (!condition) {\n throw new Error(message);\n }\n}\n\nfunction assertEmptyOutputDirectory(outputDirectory) {\n if (!fs.existsSync(outputDirectory)) {\n return;\n }\n assert(\n fs.statSync(outputDirectory).isDirectory(),\n `Output path is not a directory: ${outputDirectory}`,\n );\n assert(\n fs.readdirSync(outputDirectory).length === 0,\n `Output directory is not empty: ${outputDirectory}`,\n );\n}\n\nfunction decodeRPack(data, decodeMap) {\n for (let index = 0; index < data.length; index += 1) {\n data[index] = decodeMap[data[index]];\n }\n return data;\n}\n\nfunction readExactly(fileDescriptor, length, position, label) {\n const data = Buffer.allocUnsafe(length);\n let read = 0;\n while (read < length) {\n const count = fs.readSync(fileDescriptor, data, read, length - read, position + read);\n assert(count > 0, `${label} is truncated at byte ${position + read}`);\n read += count;\n }\n return data;\n}\n\nfunction sanitizeAssetName(name: string, fallback: string): string {\n const sanitized = Array.from(name, (character) =>\n character.charCodeAt(0) < 32 ? \"_\" : character,\n )\n .join(\"\")\n .replace(/[<>:\"/\\\\|?*]/g, \"_\")\n .replace(/[. ]+$/g, \"\")\n .trim();\n return sanitized.slice(0, 180) || fallback;\n}\n\nfunction detectAssetExtension(data, fallback) {\n if (data.subarray(0, 8).equals(Buffer.from(\"89504e470d0a1a0a\", \"hex\"))) {\n return \"png\";\n }\n if (data.subarray(0, 3).equals(Buffer.from(\"ffd8ff\", \"hex\"))) {\n return \"jpg\";\n }\n if (\n data.subarray(0, 6).toString(\"ascii\") === \"GIF87a\" ||\n data.subarray(0, 6).toString(\"ascii\") === \"GIF89a\"\n ) {\n return \"gif\";\n }\n if (\n data.subarray(0, 4).toString(\"ascii\") === \"RIFF\" &&\n data.subarray(8, 12).toString(\"ascii\") === \"WEBP\"\n ) {\n return \"webp\";\n }\n if (data.subarray(4, 12).toString(\"ascii\").includes(\"ftypavif\")) {\n return \"avif\";\n }\n return /^[a-z0-9]+$/i.test(fallback ?? \"\") ? fallback.toLowerCase() : \"bin\";\n}\n\nfunction takeAssetPath(asset, data, index, takenPaths) {\n const extension = detectAssetExtension(data, asset[2]);\n const baseName = sanitizeAssetName(asset[0] ?? \"\", `asset_${index + 1}`);\n let candidate = `assets/${baseName}.${extension}`;\n let collision = 1;\n while (takenPaths.has(candidate)) {\n collision += 1;\n candidate = `assets/${baseName}_${collision}.${extension}`;\n }\n takenPaths.add(candidate);\n return candidate;\n}\n\nfunction writeSources(outputDirectory, decodedModule, assetSources) {\n const card = {\n data: {\n name: decodedModule.module.name,\n },\n };\n const sources = createExpandedModuleSources(card, decodedModule);\n const manifestSource = sources.get(\"charx.json\");\n assert(manifestSource, \"Expanded module sources do not contain charx.json\");\n const manifest = JSON.parse(manifestSource.toString(\"utf8\"));\n manifest.assets = assetSources;\n sources.set(\"charx.json\", Buffer.from(`${JSON.stringify(manifest, null, 2)}\\n`, \"utf8\"));\n\n for (const [name, data] of sources) {\n const destination = path.join(outputDirectory, ...name.split(\"/\"));\n fs.mkdirSync(path.dirname(destination), { recursive: true });\n fs.writeFileSync(destination, data);\n }\n}\n\nfunction unpackRisuM(inputPath: string, outputPath: string): string {\n const resolvedInputPath = path.resolve(inputPath);\n const resolvedOutputPath = path.resolve(outputPath);\n assertEmptyOutputDirectory(resolvedOutputPath);\n\n const map = fs.readFileSync(RPACK_MAP_PATH);\n assert(map.length >= 512, `Invalid RPack map: ${RPACK_MAP_PATH}`);\n const decodeMap = map.subarray(256, 512);\n const fileDescriptor = fs.openSync(resolvedInputPath, \"r\");\n\n try {\n const fileSize = fs.fstatSync(fileDescriptor).size;\n const header = readExactly(fileDescriptor, 6, 0, \"RISUM header\");\n assert(header.readUInt8(0) === 111, \"Invalid RISUM magic number\");\n assert(header.readUInt8(1) === 0, `Unsupported RISUM version: ${header.readUInt8(1)}`);\n\n const payloadLength = header.readUInt32LE(2);\n const payload = readExactly(fileDescriptor, payloadLength, 6, \"RISUM module payload\");\n const decodedModule = JSON.parse(decodeRPack(payload, decodeMap).toString(\"utf8\"));\n assert(\n decodedModule?.type === \"risuModule\" && decodedModule.module,\n \"RISUM does not contain a Risu module\",\n );\n\n const assetMetadata = decodedModule.module.assets ?? [];\n const assetSources: any[] = [];\n const takenPaths = new Set<string>();\n let assetIndex = 0;\n let position = 6 + payloadLength;\n\n fs.mkdirSync(path.join(resolvedOutputPath, \"assets\"), { recursive: true });\n while (position < fileSize) {\n const marker = readExactly(fileDescriptor, 1, position, \"RISUM asset marker\").readUInt8(0);\n position += 1;\n if (marker === 0) {\n break;\n }\n assert(marker === 1, `Invalid RISUM asset marker at byte ${position - 1}: ${marker}`);\n assert(\n assetIndex < assetMetadata.length,\n \"RISUM contains more asset blocks than asset metadata entries\",\n );\n\n const lengthData = readExactly(fileDescriptor, 4, position, \"RISUM asset length\");\n const assetLength = lengthData.readUInt32LE(0);\n position += 4;\n const encodedAsset = readExactly(\n fileDescriptor,\n assetLength,\n position,\n `RISUM asset ${assetIndex + 1}`,\n );\n position += assetLength;\n\n const metadata = assetMetadata[assetIndex];\n assert(metadata, `RISUM asset ${assetIndex + 1} has no metadata`);\n const decodedAsset = decodeRPack(encodedAsset, decodeMap);\n const sourcePath = takeAssetPath(metadata, decodedAsset, assetIndex, takenPaths);\n const destination = path.join(resolvedOutputPath, ...sourcePath.split(\"/\"));\n fs.writeFileSync(destination, decodedAsset);\n assetSources.push({\n extension: path.extname(sourcePath).slice(1),\n file: sourcePath,\n name: metadata[0],\n });\n assetIndex += 1;\n\n if (assetIndex % 500 === 0) {\n console.log(`Extracted ${assetIndex} / ${assetMetadata.length} assets`);\n }\n }\n\n assert(\n assetIndex === assetMetadata.length,\n `RISUM contains ${assetIndex} asset blocks but declares ${assetMetadata.length}`,\n );\n assert(\n position === fileSize,\n `RISUM contains ${fileSize - position} trailing bytes after the end marker`,\n );\n writeSources(resolvedOutputPath, decodedModule, assetSources);\n\n const relativeOutput = path.relative(process.cwd(), resolvedOutputPath) || \".\";\n console.log(`Unpacked ${assetIndex} assets and module sources to ${relativeOutput}`);\n return resolvedOutputPath;\n } finally {\n fs.closeSync(fileDescriptor);\n }\n}\n\nexport { unpackRisuM };\n"],"mappings":"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"}
|