glitchlings 0.2.5__cp312-cp312-win_amd64.whl → 0.9.3__cp312-cp312-win_amd64.whl
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.
- glitchlings/__init__.py +36 -17
- glitchlings/__main__.py +0 -1
- glitchlings/_zoo_rust/__init__.py +12 -0
- glitchlings/_zoo_rust.cp312-win_amd64.pyd +0 -0
- glitchlings/assets/__init__.py +180 -0
- glitchlings/assets/apostrofae_pairs.json +32 -0
- glitchlings/assets/ekkokin_homophones.json +2014 -0
- glitchlings/assets/hokey_assets.json +193 -0
- glitchlings/assets/lexemes/academic.json +1049 -0
- glitchlings/assets/lexemes/colors.json +1333 -0
- glitchlings/assets/lexemes/corporate.json +716 -0
- glitchlings/assets/lexemes/cyberpunk.json +22 -0
- glitchlings/assets/lexemes/lovecraftian.json +23 -0
- glitchlings/assets/lexemes/synonyms.json +3354 -0
- glitchlings/assets/mim1c_homoglyphs.json.gz.b64 +1064 -0
- glitchlings/assets/pipeline_assets.json +29 -0
- glitchlings/attack/__init__.py +53 -0
- glitchlings/attack/compose.py +299 -0
- glitchlings/attack/core.py +465 -0
- glitchlings/attack/encode.py +114 -0
- glitchlings/attack/metrics.py +104 -0
- glitchlings/attack/metrics_dispatch.py +70 -0
- glitchlings/attack/tokenization.py +157 -0
- glitchlings/auggie.py +283 -0
- glitchlings/compat/__init__.py +9 -0
- glitchlings/compat/loaders.py +355 -0
- glitchlings/compat/types.py +41 -0
- glitchlings/conf/__init__.py +41 -0
- glitchlings/conf/loaders.py +331 -0
- glitchlings/conf/schema.py +156 -0
- glitchlings/conf/types.py +72 -0
- glitchlings/config.toml +2 -0
- glitchlings/constants.py +59 -0
- glitchlings/dev/__init__.py +3 -0
- glitchlings/dev/docs.py +45 -0
- glitchlings/dlc/__init__.py +17 -3
- glitchlings/dlc/_shared.py +296 -0
- glitchlings/dlc/gutenberg.py +400 -0
- glitchlings/dlc/huggingface.py +37 -65
- glitchlings/dlc/prime.py +55 -114
- glitchlings/dlc/pytorch.py +98 -0
- glitchlings/dlc/pytorch_lightning.py +173 -0
- glitchlings/internal/__init__.py +16 -0
- glitchlings/internal/rust.py +159 -0
- glitchlings/internal/rust_ffi.py +432 -0
- glitchlings/main.py +123 -32
- glitchlings/runtime_config.py +24 -0
- glitchlings/util/__init__.py +29 -176
- glitchlings/util/adapters.py +65 -0
- glitchlings/util/keyboards.py +311 -0
- glitchlings/util/transcripts.py +108 -0
- glitchlings/zoo/__init__.py +47 -24
- glitchlings/zoo/assets/__init__.py +29 -0
- glitchlings/zoo/core.py +301 -167
- glitchlings/zoo/core_execution.py +98 -0
- glitchlings/zoo/core_planning.py +451 -0
- glitchlings/zoo/corrupt_dispatch.py +295 -0
- glitchlings/zoo/ekkokin.py +118 -0
- glitchlings/zoo/hokey.py +137 -0
- glitchlings/zoo/jargoyle.py +179 -274
- glitchlings/zoo/mim1c.py +106 -68
- glitchlings/zoo/pedant/__init__.py +107 -0
- glitchlings/zoo/pedant/core.py +105 -0
- glitchlings/zoo/pedant/forms.py +74 -0
- glitchlings/zoo/pedant/stones.py +74 -0
- glitchlings/zoo/redactyl.py +44 -175
- glitchlings/zoo/rng.py +259 -0
- glitchlings/zoo/rushmore.py +359 -116
- glitchlings/zoo/scannequin.py +18 -125
- glitchlings/zoo/transforms.py +386 -0
- glitchlings/zoo/typogre.py +76 -162
- glitchlings/zoo/validation.py +477 -0
- glitchlings/zoo/zeedub.py +33 -86
- glitchlings-0.9.3.dist-info/METADATA +334 -0
- glitchlings-0.9.3.dist-info/RECORD +80 -0
- {glitchlings-0.2.5.dist-info → glitchlings-0.9.3.dist-info}/entry_points.txt +1 -0
- glitchlings/zoo/_ocr_confusions.py +0 -34
- glitchlings/zoo/_rate.py +0 -21
- glitchlings/zoo/reduple.py +0 -169
- glitchlings-0.2.5.dist-info/METADATA +0 -490
- glitchlings-0.2.5.dist-info/RECORD +0 -27
- /glitchlings/{zoo → assets}/ocr_confusions.tsv +0 -0
- {glitchlings-0.2.5.dist-info → glitchlings-0.9.3.dist-info}/WHEEL +0 -0
- {glitchlings-0.2.5.dist-info → glitchlings-0.9.3.dist-info}/licenses/LICENSE +0 -0
- {glitchlings-0.2.5.dist-info → glitchlings-0.9.3.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
"""Keyboard layout neighbor maps for typo simulation.
|
|
2
|
+
|
|
3
|
+
This module centralizes keyboard layout data that was previously stored
|
|
4
|
+
directly in :mod:`glitchlings.util.__init__`. It defines adjacency maps
|
|
5
|
+
for various keyboard layouts used by typo-generating glitchlings.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from collections.abc import Iterable
|
|
11
|
+
|
|
12
|
+
from glitchlings.zoo.transforms import (
|
|
13
|
+
KeyNeighborMap,
|
|
14
|
+
build_keyboard_neighbor_map,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
__all__ = [
|
|
18
|
+
"KeyboardLayouts",
|
|
19
|
+
"KeyNeighbors",
|
|
20
|
+
"KEYNEIGHBORS",
|
|
21
|
+
"ShiftMap",
|
|
22
|
+
"ShiftMaps",
|
|
23
|
+
"SHIFT_MAPS",
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
KeyboardLayouts = dict[str, KeyNeighborMap]
|
|
27
|
+
ShiftMap = dict[str, str]
|
|
28
|
+
ShiftMaps = dict[str, ShiftMap]
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
_KEYNEIGHBORS: KeyboardLayouts = {
|
|
32
|
+
"CURATOR_QWERTY": {
|
|
33
|
+
"a": [*"qwsz"],
|
|
34
|
+
"b": [*"vghn "],
|
|
35
|
+
"c": [*"xdfv "],
|
|
36
|
+
"d": [*"serfcx"],
|
|
37
|
+
"e": [*"wsdrf34"],
|
|
38
|
+
"f": [*"drtgvc"],
|
|
39
|
+
"g": [*"ftyhbv"],
|
|
40
|
+
"h": [*"gyujnb"],
|
|
41
|
+
"i": [*"ujko89"],
|
|
42
|
+
"j": [*"huikmn"],
|
|
43
|
+
"k": [*"jilom,"],
|
|
44
|
+
"l": [*"kop;.,"],
|
|
45
|
+
"m": [*"njk, "],
|
|
46
|
+
"n": [*"bhjm "],
|
|
47
|
+
"o": [*"iklp90"],
|
|
48
|
+
"p": [*"o0-[;l"],
|
|
49
|
+
"q": [*"was 12"],
|
|
50
|
+
"r": [*"edft45"],
|
|
51
|
+
"s": [*"awedxz"],
|
|
52
|
+
"t": [*"r56ygf"],
|
|
53
|
+
"u": [*"y78ijh"],
|
|
54
|
+
"v": [*"cfgb "],
|
|
55
|
+
"w": [*"q23esa"],
|
|
56
|
+
"x": [*"zsdc "],
|
|
57
|
+
"y": [*"t67uhg"],
|
|
58
|
+
"z": [*"asx"],
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _register_layout(name: str, rows: Iterable[str]) -> None:
|
|
64
|
+
_KEYNEIGHBORS[name] = build_keyboard_neighbor_map(rows)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
_register_layout(
|
|
68
|
+
"DVORAK",
|
|
69
|
+
(
|
|
70
|
+
"`1234567890[]\\",
|
|
71
|
+
" ',.pyfgcrl/=\\",
|
|
72
|
+
" aoeuidhtns-",
|
|
73
|
+
" ;qjkxbmwvz",
|
|
74
|
+
),
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
_register_layout(
|
|
78
|
+
"COLEMAK",
|
|
79
|
+
(
|
|
80
|
+
"`1234567890-=",
|
|
81
|
+
" qwfpgjluy;[]\\",
|
|
82
|
+
" arstdhneio'",
|
|
83
|
+
" zxcvbkm,./",
|
|
84
|
+
),
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
_register_layout(
|
|
88
|
+
"QWERTY",
|
|
89
|
+
(
|
|
90
|
+
"`1234567890-=",
|
|
91
|
+
" qwertyuiop[]\\",
|
|
92
|
+
" asdfghjkl;'",
|
|
93
|
+
" zxcvbnm,./",
|
|
94
|
+
),
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
_register_layout(
|
|
98
|
+
"AZERTY",
|
|
99
|
+
(
|
|
100
|
+
"²&é\"'(-è_çà)=",
|
|
101
|
+
" azertyuiop^$",
|
|
102
|
+
" qsdfghjklmù*",
|
|
103
|
+
" <wxcvbn,;:!",
|
|
104
|
+
),
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
_register_layout(
|
|
108
|
+
"QWERTZ",
|
|
109
|
+
(
|
|
110
|
+
"^1234567890ß´",
|
|
111
|
+
" qwertzuiopü+",
|
|
112
|
+
" asdfghjklöä#",
|
|
113
|
+
" yxcvbnm,.-",
|
|
114
|
+
),
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
_register_layout(
|
|
118
|
+
"SPANISH_QWERTY",
|
|
119
|
+
(
|
|
120
|
+
"º1234567890'¡",
|
|
121
|
+
" qwertyuiop´+",
|
|
122
|
+
" asdfghjklñ´",
|
|
123
|
+
" <zxcvbnm,.-",
|
|
124
|
+
),
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
_register_layout(
|
|
128
|
+
"SWEDISH_QWERTY",
|
|
129
|
+
(
|
|
130
|
+
"§1234567890+´",
|
|
131
|
+
" qwertyuiopå¨",
|
|
132
|
+
" asdfghjklöä'",
|
|
133
|
+
" <zxcvbnm,.-",
|
|
134
|
+
),
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
class KeyNeighbors:
|
|
139
|
+
"""Attribute-based access to keyboard layout neighbor maps."""
|
|
140
|
+
|
|
141
|
+
def __init__(self) -> None:
|
|
142
|
+
for layout_name, layout in _KEYNEIGHBORS.items():
|
|
143
|
+
setattr(self, layout_name, layout)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
KEYNEIGHBORS: KeyNeighbors = KeyNeighbors()
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def _uppercase_keys(layout: str) -> ShiftMap:
|
|
150
|
+
mapping: ShiftMap = {}
|
|
151
|
+
for key in _KEYNEIGHBORS.get(layout, {}):
|
|
152
|
+
if key.isalpha():
|
|
153
|
+
mapping[key] = key.upper()
|
|
154
|
+
return mapping
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def _with_letters(base: ShiftMap, layout: str) -> ShiftMap:
|
|
158
|
+
mapping = dict(base)
|
|
159
|
+
mapping.update(_uppercase_keys(layout))
|
|
160
|
+
return mapping
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def _qwerty_symbols() -> ShiftMap:
|
|
164
|
+
return {
|
|
165
|
+
"`": "~",
|
|
166
|
+
"1": "!",
|
|
167
|
+
"2": "@",
|
|
168
|
+
"3": "#",
|
|
169
|
+
"4": "$",
|
|
170
|
+
"5": "%",
|
|
171
|
+
"6": "^",
|
|
172
|
+
"7": "&",
|
|
173
|
+
"8": "*",
|
|
174
|
+
"9": "(",
|
|
175
|
+
"0": ")",
|
|
176
|
+
"-": "_",
|
|
177
|
+
"=": "+",
|
|
178
|
+
"[": "{",
|
|
179
|
+
"]": "}",
|
|
180
|
+
"\\": "|",
|
|
181
|
+
";": ":",
|
|
182
|
+
"'": '"',
|
|
183
|
+
",": "<",
|
|
184
|
+
".": ">",
|
|
185
|
+
"/": "?",
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def _azerty_symbols() -> ShiftMap:
|
|
190
|
+
return {
|
|
191
|
+
"&": "1",
|
|
192
|
+
"\u00e9": "2",
|
|
193
|
+
'"': "3",
|
|
194
|
+
"'": "4",
|
|
195
|
+
"(": "5",
|
|
196
|
+
"-": "6",
|
|
197
|
+
"\u00e8": "7",
|
|
198
|
+
"_": "8",
|
|
199
|
+
"\u00e7": "9",
|
|
200
|
+
"\u00e0": "0",
|
|
201
|
+
")": "\u00b0",
|
|
202
|
+
"=": "+",
|
|
203
|
+
"^": "\u00a8",
|
|
204
|
+
"$": "\u00a3",
|
|
205
|
+
"*": "\u00b5",
|
|
206
|
+
"\u00f9": "%",
|
|
207
|
+
"<": ">",
|
|
208
|
+
",": "?",
|
|
209
|
+
";": ".",
|
|
210
|
+
":": "/",
|
|
211
|
+
"!": "\u00a7",
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def _qwertz_symbols() -> ShiftMap:
|
|
216
|
+
return {
|
|
217
|
+
"^": "\u00b0",
|
|
218
|
+
"1": "!",
|
|
219
|
+
"2": '"',
|
|
220
|
+
"3": "\u00a7",
|
|
221
|
+
"4": "$",
|
|
222
|
+
"5": "%",
|
|
223
|
+
"6": "&",
|
|
224
|
+
"7": "/",
|
|
225
|
+
"8": "(",
|
|
226
|
+
"9": ")",
|
|
227
|
+
"0": "=",
|
|
228
|
+
"\u00df": "?",
|
|
229
|
+
"\u00b4": "`",
|
|
230
|
+
"+": "*",
|
|
231
|
+
"#": "'",
|
|
232
|
+
"-": "_",
|
|
233
|
+
",": ";",
|
|
234
|
+
".": ":",
|
|
235
|
+
"\u00e4": "\u00c4",
|
|
236
|
+
"\u00f6": "\u00d6",
|
|
237
|
+
"\u00fc": "\u00dc",
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def _spanish_symbols() -> ShiftMap:
|
|
242
|
+
return {
|
|
243
|
+
"\u00ba": "\u00aa",
|
|
244
|
+
"1": "!",
|
|
245
|
+
"2": '"',
|
|
246
|
+
"3": "\u00b7",
|
|
247
|
+
"4": "$",
|
|
248
|
+
"5": "%",
|
|
249
|
+
"6": "&",
|
|
250
|
+
"7": "/",
|
|
251
|
+
"8": "(",
|
|
252
|
+
"9": ")",
|
|
253
|
+
"0": "=",
|
|
254
|
+
"'": "?",
|
|
255
|
+
"\u00a1": "\u00bf",
|
|
256
|
+
"+": "*",
|
|
257
|
+
"\u00b4": "\u00a8",
|
|
258
|
+
"-": "_",
|
|
259
|
+
",": ";",
|
|
260
|
+
".": ":",
|
|
261
|
+
"<": ">",
|
|
262
|
+
"\u00f1": "\u00d1",
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def _swedish_symbols() -> ShiftMap:
|
|
267
|
+
return {
|
|
268
|
+
"\u00a7": "\u00bd",
|
|
269
|
+
"1": "!",
|
|
270
|
+
"2": '"',
|
|
271
|
+
"3": "#",
|
|
272
|
+
"4": "\u00a4",
|
|
273
|
+
"5": "%",
|
|
274
|
+
"6": "&",
|
|
275
|
+
"7": "/",
|
|
276
|
+
"8": "(",
|
|
277
|
+
"9": ")",
|
|
278
|
+
"0": "=",
|
|
279
|
+
"+": "?",
|
|
280
|
+
"\u00b4": "\u00a8",
|
|
281
|
+
"-": "_",
|
|
282
|
+
",": ";",
|
|
283
|
+
".": ":",
|
|
284
|
+
"<": ">",
|
|
285
|
+
"\u00e5": "\u00c5",
|
|
286
|
+
"\u00e4": "\u00c4",
|
|
287
|
+
"\u00f6": "\u00d6",
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
_SHIFT_MAPS: ShiftMaps = {
|
|
292
|
+
"CURATOR_QWERTY": _with_letters(_qwerty_symbols(), "CURATOR_QWERTY"),
|
|
293
|
+
"QWERTY": _with_letters(_qwerty_symbols(), "QWERTY"),
|
|
294
|
+
"COLEMAK": _with_letters(_qwerty_symbols(), "COLEMAK"),
|
|
295
|
+
"DVORAK": _with_letters(_qwerty_symbols(), "DVORAK"),
|
|
296
|
+
"AZERTY": _with_letters(_azerty_symbols(), "AZERTY"),
|
|
297
|
+
"QWERTZ": _with_letters(_qwertz_symbols(), "QWERTZ"),
|
|
298
|
+
"SPANISH_QWERTY": _with_letters(_spanish_symbols(), "SPANISH_QWERTY"),
|
|
299
|
+
"SWEDISH_QWERTY": _with_letters(_swedish_symbols(), "SWEDISH_QWERTY"),
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
class ShiftMapsAccessor:
|
|
304
|
+
"""Attribute-based access to per-layout shift maps."""
|
|
305
|
+
|
|
306
|
+
def __init__(self) -> None:
|
|
307
|
+
for layout_name, mapping in _SHIFT_MAPS.items():
|
|
308
|
+
setattr(self, layout_name, mapping)
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
SHIFT_MAPS: ShiftMapsAccessor = ShiftMapsAccessor()
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"""Shared transcript type helpers used across attack and DLC modules."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any, Literal, Sequence, TypeGuard, Union
|
|
6
|
+
|
|
7
|
+
TranscriptTurn = dict[str, Any]
|
|
8
|
+
Transcript = list[TranscriptTurn]
|
|
9
|
+
|
|
10
|
+
# Type alias for transcript target specifications.
|
|
11
|
+
# - "last": corrupt only the last turn (default behavior)
|
|
12
|
+
# - "all": corrupt all turns
|
|
13
|
+
# - "assistant": corrupt only turns with role="assistant"
|
|
14
|
+
# - "user": corrupt only turns with role="user"
|
|
15
|
+
# - int: corrupt a specific index (negative indexing supported)
|
|
16
|
+
# - Sequence[int]: corrupt specific indices
|
|
17
|
+
TranscriptTarget = Union[Literal["last", "all", "assistant", "user"], int, Sequence[int]]
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def is_transcript(
|
|
21
|
+
value: Any,
|
|
22
|
+
*,
|
|
23
|
+
allow_empty: bool = True,
|
|
24
|
+
require_all_content: bool = False,
|
|
25
|
+
) -> TypeGuard[Transcript]:
|
|
26
|
+
"""Return True when ``value`` appears to be a chat transcript mapping list."""
|
|
27
|
+
if not isinstance(value, list):
|
|
28
|
+
return False
|
|
29
|
+
|
|
30
|
+
if not value:
|
|
31
|
+
return allow_empty
|
|
32
|
+
|
|
33
|
+
if not all(isinstance(turn, dict) for turn in value):
|
|
34
|
+
return False
|
|
35
|
+
|
|
36
|
+
if require_all_content:
|
|
37
|
+
return all("content" in turn for turn in value)
|
|
38
|
+
|
|
39
|
+
return "content" in value[-1]
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def resolve_transcript_indices(
|
|
43
|
+
transcript: Transcript,
|
|
44
|
+
target: TranscriptTarget,
|
|
45
|
+
) -> list[int]:
|
|
46
|
+
"""Resolve a transcript target specification to concrete indices.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
transcript: The transcript to resolve indices for.
|
|
50
|
+
target: The target specification indicating which turns to corrupt.
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
A list of valid indices into the transcript, sorted in ascending order.
|
|
54
|
+
|
|
55
|
+
Raises:
|
|
56
|
+
ValueError: If the target specification is invalid or references
|
|
57
|
+
indices outside the transcript bounds.
|
|
58
|
+
"""
|
|
59
|
+
if not transcript:
|
|
60
|
+
return []
|
|
61
|
+
|
|
62
|
+
length = len(transcript)
|
|
63
|
+
|
|
64
|
+
if target == "last":
|
|
65
|
+
return [length - 1]
|
|
66
|
+
|
|
67
|
+
if target == "all":
|
|
68
|
+
return list(range(length))
|
|
69
|
+
|
|
70
|
+
if target == "assistant":
|
|
71
|
+
return [i for i, turn in enumerate(transcript) if turn.get("role") == "assistant"]
|
|
72
|
+
|
|
73
|
+
if target == "user":
|
|
74
|
+
return [i for i, turn in enumerate(transcript) if turn.get("role") == "user"]
|
|
75
|
+
|
|
76
|
+
if isinstance(target, int):
|
|
77
|
+
# Normalize negative indices
|
|
78
|
+
normalized = target if target >= 0 else length + target
|
|
79
|
+
if not 0 <= normalized < length:
|
|
80
|
+
raise ValueError(f"Transcript index {target} out of bounds for length {length}")
|
|
81
|
+
return [normalized]
|
|
82
|
+
|
|
83
|
+
# Handle sequence of indices
|
|
84
|
+
if isinstance(target, Sequence) and not isinstance(target, str):
|
|
85
|
+
indices: list[int] = []
|
|
86
|
+
for idx in target:
|
|
87
|
+
if not isinstance(idx, int):
|
|
88
|
+
raise ValueError(f"Transcript indices must be integers, got {type(idx).__name__}")
|
|
89
|
+
normalized = idx if idx >= 0 else length + idx
|
|
90
|
+
if not 0 <= normalized < length:
|
|
91
|
+
raise ValueError(f"Transcript index {idx} out of bounds for length {length}")
|
|
92
|
+
indices.append(normalized)
|
|
93
|
+
# Deduplicate and sort
|
|
94
|
+
return sorted(set(indices))
|
|
95
|
+
|
|
96
|
+
raise ValueError(
|
|
97
|
+
f"Invalid transcript target: {target!r}. "
|
|
98
|
+
"Expected 'last', 'all', 'assistant', 'user', int, or sequence of ints."
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
__all__ = [
|
|
103
|
+
"Transcript",
|
|
104
|
+
"TranscriptTarget",
|
|
105
|
+
"TranscriptTurn",
|
|
106
|
+
"is_transcript",
|
|
107
|
+
"resolve_transcript_indices",
|
|
108
|
+
]
|
glitchlings/zoo/__init__.py
CHANGED
|
@@ -3,15 +3,17 @@ from __future__ import annotations
|
|
|
3
3
|
import ast
|
|
4
4
|
from typing import Any
|
|
5
5
|
|
|
6
|
-
from .
|
|
6
|
+
from .core import Gaggle, Glitchling, plan_glitchlings
|
|
7
|
+
from .ekkokin import Ekkokin, ekkokin
|
|
8
|
+
from .hokey import Hokey, hokey
|
|
9
|
+
from .jargoyle import Jargoyle, jargoyle
|
|
7
10
|
from .mim1c import Mim1c, mim1c
|
|
8
|
-
from .
|
|
9
|
-
from .reduple import Reduple, reduple
|
|
10
|
-
from .rushmore import Rushmore, rushmore
|
|
11
|
+
from .pedant import Pedant, pedant
|
|
11
12
|
from .redactyl import Redactyl, redactyl
|
|
13
|
+
from .rushmore import Rushmore, RushmoreMode, rushmore
|
|
12
14
|
from .scannequin import Scannequin, scannequin
|
|
15
|
+
from .typogre import Typogre, typogre
|
|
13
16
|
from .zeedub import Zeedub, zeedub
|
|
14
|
-
from .core import Glitchling, Gaggle
|
|
15
17
|
|
|
16
18
|
__all__ = [
|
|
17
19
|
"Typogre",
|
|
@@ -20,9 +22,12 @@ __all__ = [
|
|
|
20
22
|
"mim1c",
|
|
21
23
|
"Jargoyle",
|
|
22
24
|
"jargoyle",
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
+
"Ekkokin",
|
|
26
|
+
"ekkokin",
|
|
27
|
+
"Hokey",
|
|
28
|
+
"hokey",
|
|
25
29
|
"Rushmore",
|
|
30
|
+
"RushmoreMode",
|
|
26
31
|
"rushmore",
|
|
27
32
|
"Redactyl",
|
|
28
33
|
"redactyl",
|
|
@@ -30,20 +35,30 @@ __all__ = [
|
|
|
30
35
|
"scannequin",
|
|
31
36
|
"Zeedub",
|
|
32
37
|
"zeedub",
|
|
38
|
+
"Pedant",
|
|
39
|
+
"pedant",
|
|
33
40
|
"Glitchling",
|
|
34
41
|
"Gaggle",
|
|
42
|
+
"plan_glitchlings",
|
|
35
43
|
"summon",
|
|
36
44
|
"BUILTIN_GLITCHLINGS",
|
|
37
45
|
"DEFAULT_GLITCHLING_NAMES",
|
|
38
46
|
"parse_glitchling_spec",
|
|
47
|
+
"get_glitchling_class",
|
|
39
48
|
]
|
|
40
49
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
50
|
+
_BUILTIN_GLITCHLING_LIST: list[Glitchling] = [
|
|
51
|
+
typogre,
|
|
52
|
+
hokey,
|
|
53
|
+
mim1c,
|
|
54
|
+
ekkokin,
|
|
55
|
+
pedant,
|
|
56
|
+
jargoyle,
|
|
57
|
+
rushmore,
|
|
58
|
+
redactyl,
|
|
59
|
+
scannequin,
|
|
60
|
+
zeedub,
|
|
61
|
+
]
|
|
47
62
|
|
|
48
63
|
BUILTIN_GLITCHLINGS: dict[str, Glitchling] = {
|
|
49
64
|
glitchling.name.lower(): glitchling for glitchling in _BUILTIN_GLITCHLING_LIST
|
|
@@ -51,22 +66,22 @@ BUILTIN_GLITCHLINGS: dict[str, Glitchling] = {
|
|
|
51
66
|
|
|
52
67
|
_BUILTIN_GLITCHLING_TYPES: dict[str, type[Glitchling]] = {
|
|
53
68
|
typogre.name.lower(): Typogre,
|
|
69
|
+
ekkokin.name.lower(): Ekkokin,
|
|
70
|
+
hokey.name.lower(): Hokey,
|
|
54
71
|
mim1c.name.lower(): Mim1c,
|
|
55
|
-
|
|
72
|
+
pedant.name.lower(): Pedant,
|
|
73
|
+
jargoyle.name.lower(): Jargoyle,
|
|
56
74
|
rushmore.name.lower(): Rushmore,
|
|
57
75
|
redactyl.name.lower(): Redactyl,
|
|
58
76
|
scannequin.name.lower(): Scannequin,
|
|
59
77
|
zeedub.name.lower(): Zeedub,
|
|
60
78
|
}
|
|
61
|
-
if _HAS_JARGOYLE:
|
|
62
|
-
_BUILTIN_GLITCHLING_TYPES[jargoyle.name.lower()] = Jargoyle
|
|
63
79
|
|
|
64
80
|
DEFAULT_GLITCHLING_NAMES: list[str] = list(BUILTIN_GLITCHLINGS.keys())
|
|
65
81
|
|
|
66
82
|
|
|
67
83
|
def parse_glitchling_spec(specification: str) -> Glitchling:
|
|
68
84
|
"""Return a glitchling instance configured according to ``specification``."""
|
|
69
|
-
|
|
70
85
|
text = specification.strip()
|
|
71
86
|
if not text:
|
|
72
87
|
raise ValueError("Glitchling specification cannot be empty.")
|
|
@@ -93,14 +108,10 @@ def parse_glitchling_spec(specification: str) -> Glitchling:
|
|
|
93
108
|
try:
|
|
94
109
|
call_expr = ast.parse(f"_({arg_source})", mode="eval").body
|
|
95
110
|
except SyntaxError as exc:
|
|
96
|
-
raise ValueError(
|
|
97
|
-
f"Invalid parameter syntax for glitchling '{name}': {exc.msg}"
|
|
98
|
-
) from exc
|
|
111
|
+
raise ValueError(f"Invalid parameter syntax for glitchling '{name}': {exc.msg}") from exc
|
|
99
112
|
|
|
100
113
|
if not isinstance(call_expr, ast.Call) or call_expr.args:
|
|
101
|
-
raise ValueError(
|
|
102
|
-
f"Glitchling '{name}' parameters must be provided as keyword arguments."
|
|
103
|
-
)
|
|
114
|
+
raise ValueError(f"Glitchling '{name}' parameters must be provided as keyword arguments.")
|
|
104
115
|
|
|
105
116
|
kwargs: dict[str, Any] = {}
|
|
106
117
|
for keyword in call_expr.keywords:
|
|
@@ -121,9 +132,21 @@ def parse_glitchling_spec(specification: str) -> Glitchling:
|
|
|
121
132
|
raise ValueError(f"Failed to instantiate glitchling '{name}': {exc}") from exc
|
|
122
133
|
|
|
123
134
|
|
|
135
|
+
def get_glitchling_class(name: str) -> type[Glitchling]:
|
|
136
|
+
"""Look up the glitchling class registered under ``name``."""
|
|
137
|
+
key = name.strip().lower()
|
|
138
|
+
if not key:
|
|
139
|
+
raise ValueError("Glitchling name cannot be empty.")
|
|
140
|
+
|
|
141
|
+
glitchling_type = _BUILTIN_GLITCHLING_TYPES.get(key)
|
|
142
|
+
if glitchling_type is None:
|
|
143
|
+
raise ValueError(f"Glitchling '{name}' not found.")
|
|
144
|
+
|
|
145
|
+
return glitchling_type
|
|
146
|
+
|
|
147
|
+
|
|
124
148
|
def summon(glitchlings: list[str | Glitchling], seed: int = 151) -> Gaggle:
|
|
125
149
|
"""Summon glitchlings by name (using defaults) or instance (to change parameters)."""
|
|
126
|
-
|
|
127
150
|
summoned: list[Glitchling] = []
|
|
128
151
|
for entry in glitchlings:
|
|
129
152
|
if isinstance(entry, Glitchling):
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""Compatibility shim for the relocated asset helpers."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from glitchlings.assets import (
|
|
6
|
+
PIPELINE_ASSET_SPECS,
|
|
7
|
+
PIPELINE_ASSETS,
|
|
8
|
+
AssetKind,
|
|
9
|
+
PipelineAsset,
|
|
10
|
+
hash_asset,
|
|
11
|
+
load_homophone_groups,
|
|
12
|
+
load_json,
|
|
13
|
+
open_binary,
|
|
14
|
+
open_text,
|
|
15
|
+
read_text,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
__all__ = [
|
|
19
|
+
"AssetKind",
|
|
20
|
+
"PipelineAsset",
|
|
21
|
+
"PIPELINE_ASSETS",
|
|
22
|
+
"PIPELINE_ASSET_SPECS",
|
|
23
|
+
"hash_asset",
|
|
24
|
+
"load_homophone_groups",
|
|
25
|
+
"load_json",
|
|
26
|
+
"open_binary",
|
|
27
|
+
"open_text",
|
|
28
|
+
"read_text",
|
|
29
|
+
]
|