@kubohiroya/turbowarp-teachable-machine 3.5.1 → 3.5.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.
@@ -47,6 +47,644 @@ function requireComputeMode(value) {
47
47
  if (!mode) throw new TypeError(`TM: Unknown compute mode: ${String(value)}`);
48
48
  return mode;
49
49
  }
50
+ //#endregion
51
+ //#region node_modules/.pnpm/@kubohiroya+turbowarp-extension-data-editor@0.2.1_react@18.3.1/node_modules/@kubohiroya/turbowarp-extension-data-editor/dist/fixed-input-schema.js
52
+ var numberToken = /^-?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?$/u;
53
+ var invalidNumber = Object.freeze({
54
+ kind: "invalid",
55
+ code: "fixed-number-input-invalid"
56
+ });
57
+ /**
58
+ * Parse a NEW numeric draft according to NP-finite-new-input-v1.
59
+ * Never apply this to opening/no-op raw values or use it as an owner validator.
60
+ * Keep the validated token so negative zero, precision and exponent spelling survive.
61
+ */
62
+ function parseFixedNumberInput(input) {
63
+ if (typeof input === "number") {
64
+ if (!Number.isFinite(input)) return invalidNumber;
65
+ return Object.freeze({
66
+ kind: "valid",
67
+ token: Object.is(input, -0) ? "-0" : String(input),
68
+ value: input
69
+ });
70
+ }
71
+ if (typeof input !== "string") return invalidNumber;
72
+ const token = input.trim();
73
+ if (!numberToken.test(token)) return invalidNumber;
74
+ const value = Number(token);
75
+ return Number.isFinite(value) ? Object.freeze({
76
+ kind: "valid",
77
+ token,
78
+ value
79
+ }) : invalidNumber;
80
+ }
81
+ var block_editor_fixed_inputs_schema_default = {
82
+ $schema: "https://json-schema.org/draft/2020-12/schema",
83
+ $id: "https://kubohiroya.github.io/turbowarp-teachable-machine/schemas/block-editor-fixed-inputs.schema.json",
84
+ title: "turbowarp-teachable-machine fixed input registration schema",
85
+ $defs: {
86
+ "setRecognitionMode": {
87
+ "type": "object",
88
+ "properties": { "MODE": {
89
+ "type": "string",
90
+ "enum": [
91
+ "pose",
92
+ "image",
93
+ "audio"
94
+ ]
95
+ } }
96
+ },
97
+ "setComputeMode": {
98
+ "type": "object",
99
+ "properties": { "MODE": {
100
+ "type": "string",
101
+ "enum": [
102
+ "auto",
103
+ "webgpu",
104
+ "webgl",
105
+ "wasm",
106
+ "cpu"
107
+ ]
108
+ } }
109
+ },
110
+ "setPreviewOpacity": {
111
+ "type": "object",
112
+ "properties": { "OPACITY": {
113
+ "type": "number",
114
+ "$comment": "New finite numeric input uses NP-finite-new-input-v1. Existing raw is preserved on no-op; runtime clamp/floor is not applied to stored raw."
115
+ } }
116
+ },
117
+ "setPreviewPosition": {
118
+ "type": "object",
119
+ "properties": { "POSITION": {
120
+ "type": "string",
121
+ "enum": [
122
+ "top-left",
123
+ "top-right",
124
+ "bottom-left",
125
+ "bottom-right",
126
+ "center",
127
+ "full-stage"
128
+ ]
129
+ } }
130
+ },
131
+ "setPreviewMirroring": {
132
+ "type": "object",
133
+ "properties": { "MIRRORING": {
134
+ "type": "string",
135
+ "enum": ["mirrored", "unmirrored"]
136
+ } }
137
+ },
138
+ "setPoseOverlayVisibility": {
139
+ "type": "object",
140
+ "properties": { "VISIBILITY": {
141
+ "type": "string",
142
+ "enum": ["on", "off"]
143
+ } }
144
+ },
145
+ "setPoseJointStyle": {
146
+ "type": "object",
147
+ "properties": {
148
+ "PART": {
149
+ "type": "string",
150
+ "enum": [
151
+ "nose",
152
+ "leftEye",
153
+ "rightEye",
154
+ "leftEar",
155
+ "rightEar",
156
+ "leftShoulder",
157
+ "rightShoulder",
158
+ "leftElbow",
159
+ "rightElbow",
160
+ "leftWrist",
161
+ "rightWrist",
162
+ "leftHip",
163
+ "rightHip",
164
+ "leftKnee",
165
+ "rightKnee",
166
+ "leftAnkle",
167
+ "rightAnkle"
168
+ ]
169
+ },
170
+ "OPACITY": {
171
+ "type": "number",
172
+ "$comment": "New finite numeric input uses NP-finite-new-input-v1. Existing raw is preserved on no-op; runtime clamp/floor is not applied to stored raw."
173
+ },
174
+ "RADIUS": {
175
+ "type": "number",
176
+ "$comment": "New finite numeric input uses NP-finite-new-input-v1. Existing raw is preserved on no-op; runtime clamp/floor is not applied to stored raw."
177
+ }
178
+ }
179
+ },
180
+ "setPoseBoneStyle": {
181
+ "type": "object",
182
+ "properties": {
183
+ "OPACITY": {
184
+ "type": "number",
185
+ "$comment": "New finite numeric input uses NP-finite-new-input-v1. Existing raw is preserved on no-op; runtime clamp/floor is not applied to stored raw."
186
+ },
187
+ "WIDTH": {
188
+ "type": "number",
189
+ "$comment": "New finite numeric input uses NP-finite-new-input-v1. Existing raw is preserved on no-op; runtime clamp/floor is not applied to stored raw."
190
+ }
191
+ }
192
+ },
193
+ "setPoseOverlayMinimumConfidence": {
194
+ "type": "object",
195
+ "properties": { "CONFIDENCE": {
196
+ "type": "number",
197
+ "$comment": "New finite numeric input uses NP-finite-new-input-v1. Existing raw is preserved on no-op; runtime clamp/floor is not applied to stored raw."
198
+ } }
199
+ },
200
+ "setPoseConfidenceScaling": {
201
+ "type": "object",
202
+ "properties": {
203
+ "PROPERTY": {
204
+ "type": "string",
205
+ "enum": [
206
+ "joint-opacity",
207
+ "joint-radius",
208
+ "bone-opacity",
209
+ "bone-width"
210
+ ]
211
+ },
212
+ "STATE": {
213
+ "type": "string",
214
+ "enum": ["on", "off"]
215
+ }
216
+ }
217
+ },
218
+ "setAccumulatedPoseParameters": {
219
+ "type": "object",
220
+ "properties": {
221
+ "ACCUMULATION": {
222
+ "type": "number",
223
+ "$comment": "New finite numeric input uses NP-finite-new-input-v1. Existing raw is preserved on no-op; runtime clamp/floor is not applied to stored raw."
224
+ },
225
+ "DECAY": {
226
+ "type": "number",
227
+ "$comment": "New finite numeric input uses NP-finite-new-input-v1. Existing raw is preserved on no-op; runtime clamp/floor is not applied to stored raw."
228
+ }
229
+ }
230
+ },
231
+ "setAccumulatedPoseThreshold": {
232
+ "type": "object",
233
+ "properties": { "THRESHOLD": {
234
+ "type": "number",
235
+ "$comment": "New finite numeric input uses NP-finite-new-input-v1. Existing raw is preserved on no-op; runtime clamp/floor is not applied to stored raw."
236
+ } }
237
+ },
238
+ "isPoseWithThreshold": {
239
+ "type": "object",
240
+ "properties": { "THRESHOLD": {
241
+ "type": "number",
242
+ "$comment": "New finite numeric input uses NP-finite-new-input-v1. Existing raw is preserved on no-op; runtime clamp/floor is not applied to stored raw."
243
+ } }
244
+ }
245
+ }
246
+ };
247
+ //#endregion
248
+ //#region src/fixed-input-schema.ts
249
+ /** Owner canonical fragments, distinct from older SOURCE/editor schemas. */
250
+ function fixedInputBundle(opcode, argument) {
251
+ const source = {
252
+ repository: "turbowarp-teachable-machine",
253
+ path: "schemas/block-editor-fixed-inputs.schema.json",
254
+ symbol: `#/$defs/${opcode}/properties/${argument}`
255
+ };
256
+ const fragment = block_editor_fixed_inputs_schema_default.$defs[opcode].properties[argument];
257
+ return {
258
+ identity: {
259
+ ownerId: "turbowarp-teachable-machine",
260
+ contractId: "fixed-inputs",
261
+ revision: "1",
262
+ variantId: `${opcode}.${argument}`
263
+ },
264
+ dialect: "2020-12",
265
+ root: {
266
+ retrievalUri: block_editor_fixed_inputs_schema_default.$id,
267
+ document: fragment,
268
+ artifact: {
269
+ role: "canonical-schema",
270
+ source
271
+ }
272
+ },
273
+ resources: [],
274
+ provenance: {
275
+ canonicalSources: [source, {
276
+ repository: "turbowarp-teachable-machine",
277
+ path: "src/extension.ts",
278
+ symbol: opcode
279
+ }],
280
+ generatedFiles: [],
281
+ referenceSchemas: [],
282
+ generationSources: []
283
+ }
284
+ };
285
+ }
286
+ block_editor_fixed_inputs_schema_default.$defs;
287
+ //#endregion
288
+ //#region src/fixed-input-editors.ts
289
+ var existingNumber = (value) => {
290
+ if (typeof value !== "number" && typeof value !== "string" || typeof value === "string" && value.trim() === "") throw new TypeError("Expected a numeric literal.");
291
+ const number = Number(value);
292
+ if (!Number.isFinite(number)) throw new TypeError("Expected a finite number.");
293
+ return number;
294
+ };
295
+ var newNumber = (value) => {
296
+ const parsed = parseFixedNumberInput(value);
297
+ if (parsed.kind !== "valid") throw new TypeError("Invalid new numeric input.");
298
+ return parsed.token;
299
+ };
300
+ var aliases = {
301
+ "setRecognitionMode.MODE": {
302
+ "pose": "pose",
303
+ "poses": "pose",
304
+ "body": "pose",
305
+ "image": "image",
306
+ "images": "image",
307
+ "object": "image",
308
+ "card": "image",
309
+ "marker": "image",
310
+ "audio": "audio",
311
+ "sound": "audio",
312
+ "voice": "audio",
313
+ "microphone": "audio",
314
+ "mic": "audio",
315
+ "ポーズ": "pose",
316
+ "姿勢": "pose",
317
+ "画像": "image",
318
+ "物体": "image",
319
+ "カード": "image",
320
+ "記号": "image",
321
+ "音声": "audio",
322
+ "音": "audio",
323
+ "声": "audio",
324
+ "マイク": "audio"
325
+ },
326
+ "setPreviewPosition.POSITION": {
327
+ "左上": "top-left",
328
+ "右上": "top-right",
329
+ "左下": "bottom-left",
330
+ "右下": "bottom-right",
331
+ "中央": "center",
332
+ "ステージ全体": "full-stage",
333
+ "top-left": "top-left",
334
+ "top-right": "top-right",
335
+ "bottom-left": "bottom-left",
336
+ "bottom-right": "bottom-right",
337
+ "center": "center",
338
+ "full-stage": "full-stage"
339
+ },
340
+ "setPreviewMirroring.MIRRORING": {
341
+ "mirrored": "mirrored",
342
+ "unmirrored": "unmirrored",
343
+ "mirror": "mirrored",
344
+ "normal": "unmirrored",
345
+ "左右反転": "mirrored",
346
+ "そのまま": "unmirrored"
347
+ },
348
+ "setPoseOverlayVisibility.VISIBILITY": {
349
+ "on": "on",
350
+ "off": "off",
351
+ "show": "on",
352
+ "hide": "off",
353
+ "true": "on",
354
+ "false": "off",
355
+ "表示": "on",
356
+ "非表示": "off"
357
+ },
358
+ "setPoseConfidenceScaling.STATE": {
359
+ "on": "on",
360
+ "off": "off",
361
+ "show": "on",
362
+ "hide": "off",
363
+ "true": "on",
364
+ "false": "off",
365
+ "表示": "on",
366
+ "非表示": "off"
367
+ },
368
+ "setComputeMode.MODE": {
369
+ "auto": "auto",
370
+ "automatic": "auto",
371
+ "default": "auto",
372
+ "fastest": "auto",
373
+ "自動": "auto",
374
+ "おまかせ": "auto",
375
+ "webgpu": "webgpu",
376
+ "gpu": "webgpu",
377
+ "webgl": "webgl",
378
+ "wasm": "wasm",
379
+ "webassembly": "wasm",
380
+ "simd": "wasm",
381
+ "cpu": "cpu",
382
+ "javascript": "cpu"
383
+ }
384
+ };
385
+ function binding(opcode, argument, values) {
386
+ return {
387
+ argument,
388
+ schemaBundle: fixedInputBundle(opcode, argument),
389
+ control: values ? {
390
+ kind: "enum",
391
+ choices: values.map((value) => ({ value }))
392
+ } : { kind: "number" },
393
+ read(value) {
394
+ if (!values) return existingNumber(value);
395
+ if (typeof value !== "string") throw new TypeError("Expected a string.");
396
+ return projectEnum(opcode, argument, value);
397
+ },
398
+ encode(value) {
399
+ if (!values) return newNumber(value);
400
+ if (typeof value !== "string" || !values.includes(value)) throw new TypeError("Invalid selection.");
401
+ return value;
402
+ },
403
+ validateCandidate(value) {
404
+ try {
405
+ if (!values) existingNumber(value);
406
+ else if (typeof value !== "string" || !values.includes(value)) throw new TypeError("Invalid selection.");
407
+ return [];
408
+ } catch {
409
+ return [{ message: "Invalid fixed input." }];
410
+ }
411
+ }
412
+ };
413
+ }
414
+ function projectEnum(opcode, argument, value) {
415
+ const key = `${opcode}.${argument}`;
416
+ const token = argument === "POSITION" ? value : value.trim().toLowerCase();
417
+ return aliases[key]?.[token] ?? value;
418
+ }
419
+ var fixedInputEditors = [
420
+ {
421
+ apiVersion: 1,
422
+ extensionId: "kubohiroyatm",
423
+ editorId: "fixed-setRecognitionMode",
424
+ opcodes: ["kubohiroyatm_setRecognitionMode"],
425
+ contractId: "turbowarp-teachable-machine/setRecognitionMode",
426
+ contractRevision: "1",
427
+ validationContext: () => ({
428
+ consumerId: "turbowarp-teachable-machine",
429
+ nowMs: 0,
430
+ settings: null
431
+ }),
432
+ bindings: [binding("setRecognitionMode", "MODE", [
433
+ "pose",
434
+ "image",
435
+ "audio"
436
+ ])]
437
+ },
438
+ {
439
+ apiVersion: 1,
440
+ extensionId: "kubohiroyatm",
441
+ editorId: "fixed-setComputeMode",
442
+ opcodes: ["kubohiroyatm_setComputeMode"],
443
+ contractId: "turbowarp-teachable-machine/setComputeMode",
444
+ contractRevision: "1",
445
+ validationContext: () => ({
446
+ consumerId: "turbowarp-teachable-machine",
447
+ nowMs: 0,
448
+ settings: null
449
+ }),
450
+ bindings: [binding("setComputeMode", "MODE", [
451
+ "auto",
452
+ "webgpu",
453
+ "webgl",
454
+ "wasm",
455
+ "cpu"
456
+ ])]
457
+ },
458
+ {
459
+ apiVersion: 1,
460
+ extensionId: "kubohiroyatm",
461
+ editorId: "fixed-setPreviewOpacity",
462
+ opcodes: ["kubohiroyatm_setPreviewOpacity"],
463
+ contractId: "turbowarp-teachable-machine/setPreviewOpacity",
464
+ contractRevision: "1",
465
+ validationContext: () => ({
466
+ consumerId: "turbowarp-teachable-machine",
467
+ nowMs: 0,
468
+ settings: null
469
+ }),
470
+ bindings: [binding("setPreviewOpacity", "OPACITY")]
471
+ },
472
+ {
473
+ apiVersion: 1,
474
+ extensionId: "kubohiroyatm",
475
+ editorId: "fixed-setPreviewPosition",
476
+ opcodes: ["kubohiroyatm_setPreviewPosition"],
477
+ contractId: "turbowarp-teachable-machine/setPreviewPosition",
478
+ contractRevision: "1",
479
+ validationContext: () => ({
480
+ consumerId: "turbowarp-teachable-machine",
481
+ nowMs: 0,
482
+ settings: null
483
+ }),
484
+ bindings: [binding("setPreviewPosition", "POSITION", [
485
+ "top-left",
486
+ "top-right",
487
+ "bottom-left",
488
+ "bottom-right",
489
+ "center",
490
+ "full-stage"
491
+ ])]
492
+ },
493
+ {
494
+ apiVersion: 1,
495
+ extensionId: "kubohiroyatm",
496
+ editorId: "fixed-setPreviewMirroring",
497
+ opcodes: ["kubohiroyatm_setPreviewMirroring"],
498
+ contractId: "turbowarp-teachable-machine/setPreviewMirroring",
499
+ contractRevision: "1",
500
+ validationContext: () => ({
501
+ consumerId: "turbowarp-teachable-machine",
502
+ nowMs: 0,
503
+ settings: null
504
+ }),
505
+ bindings: [binding("setPreviewMirroring", "MIRRORING", ["mirrored", "unmirrored"])]
506
+ },
507
+ {
508
+ apiVersion: 1,
509
+ extensionId: "kubohiroyatm",
510
+ editorId: "fixed-setPoseOverlayVisibility",
511
+ opcodes: ["kubohiroyatm_setPoseOverlayVisibility"],
512
+ contractId: "turbowarp-teachable-machine/setPoseOverlayVisibility",
513
+ contractRevision: "1",
514
+ validationContext: () => ({
515
+ consumerId: "turbowarp-teachable-machine",
516
+ nowMs: 0,
517
+ settings: null
518
+ }),
519
+ bindings: [binding("setPoseOverlayVisibility", "VISIBILITY", ["on", "off"])]
520
+ },
521
+ {
522
+ apiVersion: 1,
523
+ extensionId: "kubohiroyatm",
524
+ editorId: "fixed-setPoseJointStyle",
525
+ opcodes: ["kubohiroyatm_setPoseJointStyle"],
526
+ contractId: "turbowarp-teachable-machine/setPoseJointStyle",
527
+ contractRevision: "1",
528
+ validationContext: () => ({
529
+ consumerId: "turbowarp-teachable-machine",
530
+ nowMs: 0,
531
+ settings: null
532
+ }),
533
+ bindings: [
534
+ binding("setPoseJointStyle", "PART", [
535
+ "nose",
536
+ "leftEye",
537
+ "rightEye",
538
+ "leftEar",
539
+ "rightEar",
540
+ "leftShoulder",
541
+ "rightShoulder",
542
+ "leftElbow",
543
+ "rightElbow",
544
+ "leftWrist",
545
+ "rightWrist",
546
+ "leftHip",
547
+ "rightHip",
548
+ "leftKnee",
549
+ "rightKnee",
550
+ "leftAnkle",
551
+ "rightAnkle"
552
+ ]),
553
+ binding("setPoseJointStyle", "OPACITY"),
554
+ binding("setPoseJointStyle", "RADIUS")
555
+ ]
556
+ },
557
+ {
558
+ apiVersion: 1,
559
+ extensionId: "kubohiroyatm",
560
+ editorId: "fixed-setPoseBoneStyle",
561
+ opcodes: ["kubohiroyatm_setPoseBoneStyle"],
562
+ contractId: "turbowarp-teachable-machine/setPoseBoneStyle",
563
+ contractRevision: "1",
564
+ validationContext: () => ({
565
+ consumerId: "turbowarp-teachable-machine",
566
+ nowMs: 0,
567
+ settings: null
568
+ }),
569
+ bindings: [binding("setPoseBoneStyle", "OPACITY"), binding("setPoseBoneStyle", "WIDTH")]
570
+ },
571
+ {
572
+ apiVersion: 1,
573
+ extensionId: "kubohiroyatm",
574
+ editorId: "fixed-setPoseOverlayMinimumConfidence",
575
+ opcodes: ["kubohiroyatm_setPoseOverlayMinimumConfidence"],
576
+ contractId: "turbowarp-teachable-machine/setPoseOverlayMinimumConfidence",
577
+ contractRevision: "1",
578
+ validationContext: () => ({
579
+ consumerId: "turbowarp-teachable-machine",
580
+ nowMs: 0,
581
+ settings: null
582
+ }),
583
+ bindings: [binding("setPoseOverlayMinimumConfidence", "CONFIDENCE")]
584
+ },
585
+ {
586
+ apiVersion: 1,
587
+ extensionId: "kubohiroyatm",
588
+ editorId: "fixed-setPoseConfidenceScaling",
589
+ opcodes: ["kubohiroyatm_setPoseConfidenceScaling"],
590
+ contractId: "turbowarp-teachable-machine/setPoseConfidenceScaling",
591
+ contractRevision: "1",
592
+ validationContext: () => ({
593
+ consumerId: "turbowarp-teachable-machine",
594
+ nowMs: 0,
595
+ settings: null
596
+ }),
597
+ bindings: [binding("setPoseConfidenceScaling", "PROPERTY", [
598
+ "joint-opacity",
599
+ "joint-radius",
600
+ "bone-opacity",
601
+ "bone-width"
602
+ ]), binding("setPoseConfidenceScaling", "STATE", ["on", "off"])]
603
+ },
604
+ {
605
+ apiVersion: 1,
606
+ extensionId: "kubohiroyatm",
607
+ editorId: "fixed-setAccumulatedPoseParameters",
608
+ opcodes: ["kubohiroyatm_setAccumulatedPoseParameters"],
609
+ contractId: "turbowarp-teachable-machine/setAccumulatedPoseParameters",
610
+ contractRevision: "1",
611
+ validationContext: () => ({
612
+ consumerId: "turbowarp-teachable-machine",
613
+ nowMs: 0,
614
+ settings: null
615
+ }),
616
+ bindings: [binding("setAccumulatedPoseParameters", "ACCUMULATION"), binding("setAccumulatedPoseParameters", "DECAY")]
617
+ },
618
+ {
619
+ apiVersion: 1,
620
+ extensionId: "kubohiroyatm",
621
+ editorId: "fixed-setAccumulatedPoseThreshold",
622
+ opcodes: ["kubohiroyatm_setAccumulatedPoseThreshold"],
623
+ contractId: "turbowarp-teachable-machine/setAccumulatedPoseThreshold",
624
+ contractRevision: "1",
625
+ validationContext: () => ({
626
+ consumerId: "turbowarp-teachable-machine",
627
+ nowMs: 0,
628
+ settings: null
629
+ }),
630
+ bindings: [binding("setAccumulatedPoseThreshold", "THRESHOLD")]
631
+ },
632
+ {
633
+ apiVersion: 1,
634
+ extensionId: "kubohiroyatm",
635
+ editorId: "fixed-isPoseWithThreshold",
636
+ opcodes: ["kubohiroyatm_isPoseWithThreshold"],
637
+ contractId: "turbowarp-teachable-machine/isPoseWithThreshold",
638
+ contractRevision: "1",
639
+ validationContext: () => ({
640
+ consumerId: "turbowarp-teachable-machine",
641
+ nowMs: 0,
642
+ settings: null
643
+ }),
644
+ bindings: [binding("isPoseWithThreshold", "THRESHOLD")]
645
+ }
646
+ ];
647
+ /** Register only currently declared opcodes; release obsolete feature-flag scopes. */
648
+ function fixedInputRegistration(scratch) {
649
+ const host = typeof scratch === "object" && scratch !== null ? scratch : {};
650
+ let active;
651
+ let activeOpcodes = "";
652
+ const removers = [];
653
+ let disposed = false;
654
+ const dispose = () => {
655
+ host.vm?.runtime?.off?.("RUNTIME_DISPOSED", shutdown);
656
+ for (const remove of removers.splice(0).reverse()) remove();
657
+ active = void 0;
658
+ activeOpcodes = "";
659
+ };
660
+ const shutdown = () => {
661
+ disposed = true;
662
+ dispose();
663
+ };
664
+ return {
665
+ ensure(opcodes) {
666
+ const api = host.gui?.blockEditors;
667
+ const signature = [...new Set(opcodes)].sort().join("\0");
668
+ if (disposed || api === active && signature === activeOpcodes) return;
669
+ dispose();
670
+ if (api?.apiVersion !== 1 || typeof api.registerFixedInputEditor !== "function") return;
671
+ try {
672
+ for (const definition of fixedInputEditors) if (definition.opcodes.every((opcode) => opcodes.includes(opcode))) {
673
+ const remove = api.registerFixedInputEditor.call(api, definition);
674
+ if (typeof remove !== "function") throw new TypeError("Invalid fixed registration cleanup.");
675
+ removers.push(remove);
676
+ }
677
+ active = api;
678
+ activeOpcodes = signature;
679
+ host.vm?.runtime?.on?.("RUNTIME_DISPOSED", shutdown);
680
+ } catch (error) {
681
+ dispose();
682
+ throw error;
683
+ }
684
+ },
685
+ dispose: shutdown
686
+ };
687
+ }
50
688
  var block_definitions_default = {
51
689
  extensionName: "Teachable Machine",
52
690
  blocks: [
@@ -549,7 +1187,7 @@ function confidenceMultiplier(value) {
549
1187
  }
550
1188
  var package_default = {
551
1189
  name: "@kubohiroya/turbowarp-teachable-machine",
552
- version: "3.5.1",
1190
+ version: "3.5.2",
553
1191
  description: "A TurboWarp extension for recognition using Teachable Machine pose, image, and audio models.",
554
1192
  author: "Hiroya Kubo <hiroya@cuc.ac.jp>",
555
1193
  license: "MPL-2.0",
@@ -581,7 +1219,9 @@ var package_default = {
581
1219
  "dist/",
582
1220
  "README.md",
583
1221
  "LICENSE",
584
- "THIRD_PARTY_NOTICES.md"
1222
+ "THIRD_PARTY_NOTICES.md",
1223
+ "schemas/",
1224
+ "docs/fixed-input-editors.ja.md"
585
1225
  ],
586
1226
  unpkg: "./dist/tm.js",
587
1227
  jsdelivr: "./dist/tm.js",
@@ -617,8 +1257,8 @@ var package_default = {
617
1257
  "prepack": "npm run build && npm run release:consistency:check"
618
1258
  },
619
1259
  devDependencies: {
620
- "@kubohiroya/turbowarp-camera-source": "0.13.0",
621
- "@kubohiroya/vite-plugin-turbowarp-extension": "0.4.0",
1260
+ "@kubohiroya/turbowarp-camera-source": "0.17.1",
1261
+ "@kubohiroya/vite-plugin-turbowarp-extension": "0.6.1",
622
1262
  "@teachablemachine/image": "0.8.5",
623
1263
  "@teachablemachine/pose": "0.8.6",
624
1264
  "@tensorflow-models/posenet": "2.2.2",
@@ -629,7 +1269,8 @@ var package_default = {
629
1269
  "@types/node": "^22.20.1",
630
1270
  "typescript": "^5.9.3",
631
1271
  "vite": "^8.2.2",
632
- "vitest": "^4.0.14"
1272
+ "vitest": "^4.0.14",
1273
+ "@kubohiroya/turbowarp-extension-data-editor": "0.2.1"
633
1274
  },
634
1275
  keywords: [
635
1276
  "turbowarp",
@@ -640,7 +1281,13 @@ var package_default = {
640
1281
  "audio",
641
1282
  "camera",
642
1283
  "teachable-machine"
643
- ]
1284
+ ],
1285
+ gitHead: "97ef12018789316d6170a7aab29d7c5b0a4c90f4",
1286
+ "x-turbowarp-source": {
1287
+ "revision": "97ef12018789316d6170a7aab29d7c5b0a4c90f4",
1288
+ "revisionRole": "base-commit",
1289
+ "sourceState": "local-release-overlay"
1290
+ }
644
1291
  };
645
1292
  //#endregion
646
1293
  //#region src/extension.ts
@@ -1017,7 +1664,10 @@ var TMExtension = class {
1017
1664
  this.visibilityChangeListener = () => this.handleDocumentVisibilityChange();
1018
1665
  if (this.featureFlags.temporalPoseScoring && typeof document !== "undefined") document.addEventListener("visibilitychange", this.visibilityChangeListener);
1019
1666
  }
1667
+ fixedEditors = fixedInputRegistration(typeof Scratch === "undefined" ? void 0 : Scratch);
1020
1668
  getInfo() {
1669
+ const visibleOpcodes = block_definitions_default.blocks.filter((block) => !block.featureFlag || this.featureFlags[block.featureFlag]).map((block) => `${EXTENSION_ID}_${block.opcode}`);
1670
+ this.fixedEditors.ensure(visibleOpcodes);
1021
1671
  return {
1022
1672
  id: EXTENSION_ID,
1023
1673
  name: Scratch.translate(block_definitions_default.extensionName),
@@ -2089,6 +2739,7 @@ var TMExtension = class {
2089
2739
  else if (typeof Scratch !== "undefined") Scratch.vm?.runtime?.emit(ACCUMULATED_POSE_CHANGED_EVENT, payload);
2090
2740
  }
2091
2741
  dispose() {
2742
+ this.fixedEditors.dispose();
2092
2743
  this.stopCamera();
2093
2744
  if (this.featureFlags.temporalPoseScoring && typeof document !== "undefined") document.removeEventListener("visibilitychange", this.visibilityChangeListener);
2094
2745
  this.onAccumulatedPoseChanged = null;