@yodaos-pkg/ink 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.ts CHANGED
@@ -60,6 +60,8 @@ export interface CreateInkViewOptions {
60
60
  clearOnDestroy?: boolean;
61
61
  /** Callback fired after Ink reports a new measured content size. */
62
62
  onContentSizeChanged?: InkContentSizeChangedHandler | null;
63
+ /** Optional host-provided capability implementations bridged into the Ink runtime. */
64
+ hostCapabilities?: InkHostCapabilities | null;
63
65
  /** Optional wasm bootstrap overrides. */
64
66
  wasm?: InitInkOptions;
65
67
  }
@@ -273,6 +275,243 @@ export type InkClosedHandler = (context: InkClosedContext) => void;
273
275
  /** Callback invoked after the runtime reports a new measured content size. */
274
276
  export type InkContentSizeChangedHandler = (contentSize: InkContentSize) => void;
275
277
 
278
+ /**
279
+ * Host-provided backend configuration returned from
280
+ * `hostCapabilities.languageModel.getConfig()`.
281
+ *
282
+ * The browser host owns this transport-level configuration. Ink uses it when
283
+ * `LanguageModel.create()` needs a default endpoint, protocol style, headers,
284
+ * or fallback model selection.
285
+ */
286
+ export interface InkHostLanguageModelConfig {
287
+ /** Absolute request URL used for language-model inference requests. */
288
+ endpoint: string;
289
+ /** Optional fallback model used when the Ink app does not pass an explicit `model`. */
290
+ defaultModel?: string | null;
291
+ /** Provider protocol shape, for example `openai-chat-completions`. */
292
+ apiStyle: string;
293
+ /** Static host-owned headers merged into every inference request. */
294
+ headers?: Record<string, string>;
295
+ /** Whether Ink should also merge vendor headers resolved through OpenService. */
296
+ shareVendorHeaders?: boolean;
297
+ /** Optional environment key used when resolving shared vendor headers. */
298
+ vendorHeadersEnv?: string | null;
299
+ }
300
+
301
+ /**
302
+ * Normalized speech-synthesis request forwarded to `hostCapabilities.speech.speak()`.
303
+ *
304
+ * This matches the runtime-side speech synthesis request after the SDK has
305
+ * converted Rust IPC payloads into a browser-friendly camelCase object.
306
+ */
307
+ export interface InkHostSpeechSynthesisRequest {
308
+ /** Text content to speak. */
309
+ text: string;
310
+ /** Preferred BCP-47 language tag, such as `en-US`. */
311
+ lang: string;
312
+ /** Voice pitch multiplier where `1` is the host default. */
313
+ pitch: number;
314
+ /** Speech rate multiplier where `1` is the host default. */
315
+ rate: number;
316
+ /** Optional host-specific voice identifier. */
317
+ voice?: string | null;
318
+ /** Output volume in the inclusive range `0..1`. */
319
+ volume: number;
320
+ }
321
+
322
+ /**
323
+ * Start request forwarded to `hostCapabilities.speech.startRecognition()`.
324
+ *
325
+ * The browser host should treat `targetId` and `sessionId` as stable routing
326
+ * identifiers and echo them back in later `speech.*` events dispatched through
327
+ * `hostCapabilitiesTarget`.
328
+ */
329
+ export interface InkHostSpeechRecognitionRequest {
330
+ /** Runtime-generated event target identifier for the concrete recognition object. */
331
+ targetId: string;
332
+ /** Runtime-generated identifier for the recognition session being started. */
333
+ sessionId: string;
334
+ /** Optional BCP-47 language tag requested by the Ink app. */
335
+ lang?: string | null;
336
+ /** Whether the host should keep listening after a final result. */
337
+ continuous: boolean;
338
+ /** Whether interim recognition results should be surfaced before finalization. */
339
+ interimResults: boolean;
340
+ /** Maximum number of alternatives requested for each recognition result. */
341
+ maxAlternatives: number;
342
+ }
343
+
344
+ /**
345
+ * Control request forwarded to `hostCapabilities.speech.stopRecognition()` and
346
+ * `hostCapabilities.speech.abortRecognition()`.
347
+ */
348
+ export interface InkHostSpeechRecognitionControlRequest {
349
+ /** Runtime-generated event target identifier for the concrete recognition object. */
350
+ targetId: string;
351
+ /** Identifier of the active recognition session being controlled. */
352
+ sessionId: string;
353
+ }
354
+
355
+ /**
356
+ * Start request shared by orientation and motion sensor capabilities.
357
+ *
358
+ * Hosts should echo `targetId` and `sessionId` back in later sensor events such
359
+ * as `*.activate`, `*.reading`, and `*.error`.
360
+ */
361
+ export interface InkHostSensorStartRequest {
362
+ /** Runtime-generated event target identifier for the concrete sensor object. */
363
+ targetId: string;
364
+ /** Identifier of the sensor sampling session being started. */
365
+ sessionId: string;
366
+ /** Optional preferred sampling frequency in hertz. */
367
+ frequency?: number | null;
368
+ }
369
+
370
+ /**
371
+ * Stop request shared by orientation and motion sensor capabilities.
372
+ */
373
+ export interface InkHostSensorControlRequest {
374
+ /** Runtime-generated event target identifier for the concrete sensor object. */
375
+ targetId: string;
376
+ /** Identifier of the sensor sampling session being stopped. */
377
+ sessionId: string;
378
+ }
379
+
380
+ /**
381
+ * Host-controlled audio recording options passed into
382
+ * `hostCapabilities.media.startAudioRecording()`.
383
+ */
384
+ export interface InkHostAudioRecordingOptions {
385
+ /** Requested sample rate in hertz. */
386
+ sampleRate?: number;
387
+ /** Requested number of audio channels. */
388
+ numberOfChannels?: number;
389
+ /** Requested sample or container format, for example `pcm`. */
390
+ format?: string;
391
+ }
392
+
393
+ /**
394
+ * Start request forwarded to `hostCapabilities.media.startAudioRecording()`.
395
+ */
396
+ export interface InkHostStartAudioRecordingRequest {
397
+ /** Runtime-generated identifier for the recorder target receiving follow-up events. */
398
+ targetId: string;
399
+ /** Host recording options requested by the Ink app. */
400
+ options: InkHostAudioRecordingOptions;
401
+ }
402
+
403
+ /**
404
+ * Photo capture options forwarded to `hostCapabilities.media.takePhoto()`.
405
+ */
406
+ export interface InkHostTakePhotoOptions {
407
+ /** Requested quality hint, typically `high`, `normal`, or `low`. */
408
+ quality: string;
409
+ }
410
+
411
+ /**
412
+ * Host photo result returned from `hostCapabilities.media.takePhoto()`.
413
+ */
414
+ export interface InkHostTakePhotoResult {
415
+ /** Binary encoded image payload returned by the host camera implementation. */
416
+ data: Uint8Array | ArrayBuffer | ArrayBufferView;
417
+ /** MIME type describing the encoded image bytes, for example `image/jpeg`. */
418
+ mimeType: string;
419
+ }
420
+
421
+ /**
422
+ * Shared environment request used by OpenService and LanguageModel helpers.
423
+ */
424
+ export interface InkHostEnvRequest {
425
+ /** Optional environment selector used to resolve host-specific configuration. */
426
+ env?: string | null;
427
+ }
428
+
429
+ /**
430
+ * Browser-host capability registry consumed by `InkView.setHostCapabilities()`.
431
+ *
432
+ * Each capability group is optional. When a method is omitted, requests for
433
+ * that method fail fast with a host-side "not configured" error.
434
+ *
435
+ * Request/response hooks:
436
+ * - synchronous or asynchronous return values are both supported
437
+ * - long-lived asynchronous updates should be pushed separately through
438
+ * `view.hostCapabilitiesTarget` or `view.getHostCapabilitiesTarget()`
439
+ * - session-scoped events should preserve the `targetId` and `sessionId`
440
+ * supplied in the originating request
441
+ */
442
+ export interface InkHostCapabilities {
443
+ /** Host implementations for speech synthesis and speech recognition entry points. */
444
+ speech?: {
445
+ /** Speaks text through a host-provided speech synthesis backend. */
446
+ speak?(request: InkHostSpeechSynthesisRequest): void | Promise<void>;
447
+ /** Starts a host-provided speech recognition session. */
448
+ startRecognition?(request: InkHostSpeechRecognitionRequest): void | Promise<void>;
449
+ /** Requests graceful completion of an active recognition session. */
450
+ stopRecognition?(request: InkHostSpeechRecognitionControlRequest): void | Promise<void>;
451
+ /** Requests immediate termination of an active recognition session. */
452
+ abortRecognition?(request: InkHostSpeechRecognitionControlRequest): void | Promise<void>;
453
+ };
454
+ /** Host implementation of the AbsoluteOrientationSensor-compatible start/stop flow. */
455
+ absoluteOrientation?: {
456
+ /** Starts an absolute-orientation session and later emits `absoluteOrientation.*` events. */
457
+ start?(request: InkHostSensorStartRequest): void | Promise<void>;
458
+ /** Stops a previously started absolute-orientation session. */
459
+ stop?(request: InkHostSensorControlRequest): void | Promise<void>;
460
+ };
461
+ /** Host implementation of the Accelerometer-compatible start/stop flow. */
462
+ accelerometer?: {
463
+ /** Starts an accelerometer session and later emits `accelerometer.*` events. */
464
+ start?(request: InkHostSensorStartRequest): void | Promise<void>;
465
+ /** Stops a previously started accelerometer session. */
466
+ stop?(request: InkHostSensorControlRequest): void | Promise<void>;
467
+ };
468
+ /** Host implementation of the Gyroscope-compatible start/stop flow. */
469
+ gyroscope?: {
470
+ /** Starts a gyroscope session and later emits `gyroscope.*` events. */
471
+ start?(request: InkHostSensorStartRequest): void | Promise<void>;
472
+ /** Stops a previously started gyroscope session. */
473
+ stop?(request: InkHostSensorControlRequest): void | Promise<void>;
474
+ };
475
+ /** Host implementation of the Magnetometer-compatible start/stop flow. */
476
+ magnetometer?: {
477
+ /** Starts a magnetometer session and later emits `magnetometer.*` events. */
478
+ start?(request: InkHostSensorStartRequest): void | Promise<void>;
479
+ /** Stops a previously started magnetometer session. */
480
+ stop?(request: InkHostSensorControlRequest): void | Promise<void>;
481
+ };
482
+ /** Host implementations for recording audio and capturing still photos. */
483
+ media?: {
484
+ /** Starts audio recording and later emits `media.audioRecording*` events. */
485
+ startAudioRecording?(request: InkHostStartAudioRecordingRequest): void | Promise<void>;
486
+ /** Stops the currently active audio recording session. */
487
+ stopAudioRecording?(request: Record<string, never>): void | Promise<void>;
488
+ /** Pauses the currently active audio recording session. */
489
+ pauseAudioRecording?(request: Record<string, never>): void | Promise<void>;
490
+ /** Resumes a previously paused audio recording session. */
491
+ resumeAudioRecording?(request: Record<string, never>): void | Promise<void>;
492
+ /** Captures one photo and returns encoded image bytes plus their MIME type. */
493
+ takePhoto?(
494
+ request: InkHostTakePhotoOptions,
495
+ ): InkHostTakePhotoResult | Promise<InkHostTakePhotoResult>;
496
+ };
497
+ /** Host implementations for OpenService-backed configuration lookups. */
498
+ openService?: {
499
+ /** Resolves the OpenService manifest visible to the Ink runtime. */
500
+ getManifest?(request: InkHostEnvRequest): unknown | Promise<unknown>;
501
+ /** Resolves host-owned vendor headers that Ink may merge into outbound requests. */
502
+ getVendorHeaders?(
503
+ request: InkHostEnvRequest,
504
+ ): Record<string, string> | Promise<Record<string, string>>;
505
+ };
506
+ /** Host implementation for default LanguageModel backend discovery. */
507
+ languageModel?: {
508
+ /** Returns the transport configuration used when Ink initializes `LanguageModel.create()`. */
509
+ getConfig?(
510
+ request: InkHostEnvRequest,
511
+ ): InkHostLanguageModelConfig | Promise<InkHostLanguageModelConfig>;
512
+ };
513
+ }
514
+
276
515
  /**
277
516
  * Initializes the browser SDK and ensures the wasm runtime is ready to create
278
517
  * views. Most applications can use {@link InkView.create} or
@@ -474,6 +713,15 @@ export declare class InkView {
474
713
  */
475
714
  notifyUserInteraction(): this;
476
715
 
716
+ /** Registers host-provided implementations for browser-side IPC-backed capabilities. */
717
+ setHostCapabilities(capabilities: InkHostCapabilities | null): this;
718
+
719
+ /** Returns the EventTarget used to push asynchronous host capability events back into Ink. */
720
+ getHostCapabilitiesTarget(): EventTarget;
721
+
722
+ /** Property-style access to the host capability EventTarget. */
723
+ readonly hostCapabilitiesTarget: EventTarget;
724
+
477
725
  /** Forwards a pointer-like event directly into the current Ink view. */
478
726
  dispatchPointer(
479
727
  eventType: string,
package/index.js CHANGED
@@ -412,32 +412,440 @@ function isResizeOptions(value) {
412
412
  return value != null && typeof value === 'object' && !Array.isArray(value);
413
413
  }
414
414
 
415
- function normalizeHostLanguageModelConfig(config) {
416
- if (config == null) {
417
- return null;
415
+ function normalizeStringMap(value, optionName) {
416
+ if (value == null) {
417
+ return {};
418
+ }
419
+ if (typeof value !== 'object' || Array.isArray(value)) {
420
+ throw new TypeError(`\`${optionName}\` must be a plain object when provided.`);
418
421
  }
419
- if (typeof config !== 'object') {
420
- throw new TypeError('`config` must be an object or null.');
422
+ return Object.fromEntries(
423
+ Object.entries(value).map(([key, entryValue]) => [String(key), String(entryValue)]),
424
+ );
425
+ }
426
+
427
+ function normalizeHostLanguageModelConfig(config) {
428
+ if (config == null || typeof config !== 'object' || Array.isArray(config)) {
429
+ throw new TypeError('`languageModel.getConfig()` must resolve to a config object.');
421
430
  }
422
431
 
423
- const headers =
424
- config.headers && typeof config.headers === 'object' && !Array.isArray(config.headers)
425
- ? Object.fromEntries(
426
- Object.entries(config.headers).map(([key, value]) => [String(key), String(value)]),
427
- )
428
- : {};
432
+ const endpoint = String(config.endpoint || '').trim();
433
+ const apiStyle = String(config.apiStyle || '').trim();
434
+ if (!endpoint) {
435
+ throw new TypeError('`languageModel.getConfig()` must provide a non-empty `endpoint`.');
436
+ }
437
+ if (!apiStyle) {
438
+ throw new TypeError('`languageModel.getConfig()` must provide a non-empty `apiStyle`.');
439
+ }
429
440
 
430
441
  return {
431
- endpoint: String(config.endpoint || '').trim(),
432
- defaultModel: config.defaultModel == null ? null : String(config.defaultModel).trim(),
433
- apiStyle: String(config.apiStyle || '').trim(),
434
- headers,
442
+ endpoint,
443
+ defaultModel: config.defaultModel == null ? null : String(config.defaultModel).trim() || null,
444
+ apiStyle,
445
+ headers: normalizeStringMap(config.headers, 'languageModel.headers'),
435
446
  shareVendorHeaders: Boolean(config.shareVendorHeaders),
436
447
  vendorHeadersEnv:
437
- config.vendorHeadersEnv == null ? null : String(config.vendorHeadersEnv).trim(),
448
+ config.vendorHeadersEnv == null ? null : String(config.vendorHeadersEnv).trim() || null,
438
449
  };
439
450
  }
440
451
 
452
+ function ensureHostCapabilitiesObject(value) {
453
+ if (value == null) {
454
+ return null;
455
+ }
456
+ if (typeof value !== 'object' || Array.isArray(value)) {
457
+ throw new TypeError('`hostCapabilities` must be an object or null.');
458
+ }
459
+ return value;
460
+ }
461
+
462
+ function parseHostCapabilityRequest(requestJson, capability, method) {
463
+ if (typeof requestJson !== 'string') {
464
+ throw new TypeError(`Host capability ${capability}.${method} requires a JSON request string.`);
465
+ }
466
+ try {
467
+ return JSON.parse(requestJson);
468
+ } catch {
469
+ throw new Error(`Host capability ${capability}.${method} received invalid request JSON.`);
470
+ }
471
+ }
472
+
473
+ function serializeIpcResponseData(responseData) {
474
+ const json = JSON.stringify(responseData);
475
+ if (typeof json !== 'string') {
476
+ throw new TypeError('Host capability handler must return JSON-serializable response data.');
477
+ }
478
+ return json;
479
+ }
480
+
481
+ function createSuccessResponseData() {
482
+ return { type: 'Success' };
483
+ }
484
+
485
+ function serializeSuccessResponse() {
486
+ return serializeIpcResponseData(createSuccessResponseData());
487
+ }
488
+
489
+ function serializeOpenServiceManifestResponse(result) {
490
+ return serializeIpcResponseData({
491
+ type: 'OpenService',
492
+ data: {
493
+ type: 'Manifest',
494
+ data: result,
495
+ },
496
+ });
497
+ }
498
+
499
+ function serializeOpenServiceVendorHeadersResponse(result) {
500
+ return serializeIpcResponseData({
501
+ type: 'OpenService',
502
+ data: {
503
+ type: 'VendorHeaders',
504
+ data: normalizeStringMap(result, 'openService.getVendorHeaders() result'),
505
+ },
506
+ });
507
+ }
508
+
509
+ function normalizePhotoResult(result) {
510
+ if (result == null || typeof result !== 'object' || Array.isArray(result)) {
511
+ throw new TypeError(
512
+ '`media.takePhoto()` must resolve to an object with `data` and `mimeType`.',
513
+ );
514
+ }
515
+ const mimeType = String(result.mimeType || '').trim();
516
+ if (!mimeType) {
517
+ throw new TypeError('`media.takePhoto()` must provide a non-empty `mimeType`.');
518
+ }
519
+ const data = cloneUint8Array(result.data ?? result.bytes ?? result.buffer);
520
+ if (!data) {
521
+ throw new TypeError(
522
+ '`media.takePhoto()` must provide binary `data` as Uint8Array, ArrayBuffer, or TypedArray.',
523
+ );
524
+ }
525
+ return { data, mimeType };
526
+ }
527
+
528
+ function serializeTakePhotoResponse(result) {
529
+ const photo = normalizePhotoResult(result);
530
+ return serializeIpcResponseData({
531
+ type: 'Media',
532
+ data: {
533
+ type: 'TakePhotoResult',
534
+ data: [Array.from(photo.data), photo.mimeType],
535
+ },
536
+ });
537
+ }
538
+
539
+ function serializeLanguageModelConfigResponse(result) {
540
+ return serializeIpcResponseData({
541
+ type: 'LanguageModel',
542
+ data: {
543
+ type: 'Config',
544
+ data: normalizeHostLanguageModelConfig(result),
545
+ },
546
+ });
547
+ }
548
+
549
+ const HOST_CAPABILITY_SERIALIZERS = {
550
+ speech: {
551
+ speak: () => serializeSuccessResponse(),
552
+ startRecognition: () => serializeSuccessResponse(),
553
+ stopRecognition: () => serializeSuccessResponse(),
554
+ abortRecognition: () => serializeSuccessResponse(),
555
+ },
556
+ absoluteOrientation: {
557
+ start: () => serializeSuccessResponse(),
558
+ stop: () => serializeSuccessResponse(),
559
+ },
560
+ accelerometer: {
561
+ start: () => serializeSuccessResponse(),
562
+ stop: () => serializeSuccessResponse(),
563
+ },
564
+ gyroscope: {
565
+ start: () => serializeSuccessResponse(),
566
+ stop: () => serializeSuccessResponse(),
567
+ },
568
+ magnetometer: {
569
+ start: () => serializeSuccessResponse(),
570
+ stop: () => serializeSuccessResponse(),
571
+ },
572
+ media: {
573
+ startAudioRecording: () => serializeSuccessResponse(),
574
+ stopAudioRecording: () => serializeSuccessResponse(),
575
+ pauseAudioRecording: () => serializeSuccessResponse(),
576
+ resumeAudioRecording: () => serializeSuccessResponse(),
577
+ takePhoto: (result) => serializeTakePhotoResponse(result),
578
+ },
579
+ openService: {
580
+ getManifest: (result) => serializeOpenServiceManifestResponse(result),
581
+ getVendorHeaders: (result) => serializeOpenServiceVendorHeadersResponse(result),
582
+ },
583
+ languageModel: {
584
+ getConfig: (result) => serializeLanguageModelConfigResponse(result),
585
+ },
586
+ };
587
+
588
+ function normalizeHostCapabilities(capabilities) {
589
+ const normalizedCapabilities = ensureHostCapabilitiesObject(capabilities);
590
+ if (!normalizedCapabilities) {
591
+ return null;
592
+ }
593
+
594
+ return {
595
+ async handleRequest(capability, method, requestJson) {
596
+ const serializer = HOST_CAPABILITY_SERIALIZERS[capability]?.[method];
597
+ const hook = normalizedCapabilities?.[capability]?.[method];
598
+ if (typeof serializer !== 'function' || typeof hook !== 'function') {
599
+ throw new Error(
600
+ `Host capability ${String(capability)}.${String(method)} is not configured on Web host`,
601
+ );
602
+ }
603
+ const request = parseHostCapabilityRequest(requestJson, capability, method);
604
+ const result = await hook(request);
605
+ return serializer(result);
606
+ },
607
+ };
608
+ }
609
+
610
+ function createIpcEvent(type, target, detail) {
611
+ return {
612
+ type,
613
+ target: target || null,
614
+ bubbles: false,
615
+ cancelable: false,
616
+ default_prevented: false,
617
+ propagation_stopped: false,
618
+ detail,
619
+ };
620
+ }
621
+
622
+ function requireDetailObject(detail, eventType) {
623
+ if (detail == null || typeof detail !== 'object' || Array.isArray(detail)) {
624
+ throw new TypeError(
625
+ `Host capability event \`${eventType}\` requires an object detail payload.`,
626
+ );
627
+ }
628
+ return detail;
629
+ }
630
+
631
+ function requireStringField(value, fieldName, eventType) {
632
+ if (typeof value !== 'string' || !value.trim()) {
633
+ throw new TypeError(
634
+ `Host capability event \`${eventType}\` requires a non-empty \`${fieldName}\`.`,
635
+ );
636
+ }
637
+ return value.trim();
638
+ }
639
+
640
+ function buildSpeechSessionEvent(eventType, variant, detail) {
641
+ const payload = requireDetailObject(detail, eventType);
642
+ const targetId = requireStringField(payload.targetId, 'targetId', eventType);
643
+ const sessionId = requireStringField(payload.sessionId, 'sessionId', eventType);
644
+ return createIpcEvent(eventType, targetId, {
645
+ type: 'Speech',
646
+ data: {
647
+ type: variant,
648
+ data: { sessionId },
649
+ },
650
+ });
651
+ }
652
+
653
+ function buildSpeechResultEvent(eventType, detail) {
654
+ const payload = requireDetailObject(detail, eventType);
655
+ const targetId = requireStringField(payload.targetId, 'targetId', eventType);
656
+ const sessionId = requireStringField(payload.sessionId, 'sessionId', eventType);
657
+ const alternatives = Array.isArray(payload.alternatives)
658
+ ? payload.alternatives.map((alternative) => ({
659
+ transcript: String(alternative?.transcript || ''),
660
+ confidence: Number(alternative?.confidence || 0),
661
+ }))
662
+ : [];
663
+ return createIpcEvent(eventType, targetId, {
664
+ type: 'Speech',
665
+ data: {
666
+ type: 'Result',
667
+ data: {
668
+ sessionId,
669
+ resultIndex: Math.max(0, Math.trunc(Number(payload.resultIndex) || 0)),
670
+ isFinal: Boolean(payload.isFinal),
671
+ alternatives,
672
+ },
673
+ },
674
+ });
675
+ }
676
+
677
+ function buildSpeechErrorEvent(eventType, detail) {
678
+ const payload = requireDetailObject(detail, eventType);
679
+ const targetId = requireStringField(payload.targetId, 'targetId', eventType);
680
+ const sessionId = requireStringField(payload.sessionId, 'sessionId', eventType);
681
+ return createIpcEvent(eventType, targetId, {
682
+ type: 'Speech',
683
+ data: {
684
+ type: 'Error',
685
+ data: {
686
+ sessionId,
687
+ error: String(payload.error || ''),
688
+ message: String(payload.message || ''),
689
+ },
690
+ },
691
+ });
692
+ }
693
+
694
+ function buildSensorSessionEvent(category, eventType, variant, detail) {
695
+ const payload = requireDetailObject(detail, eventType);
696
+ const targetId = requireStringField(payload.targetId, 'targetId', eventType);
697
+ const sessionId = requireStringField(payload.sessionId, 'sessionId', eventType);
698
+ return createIpcEvent(eventType, targetId, {
699
+ type: category,
700
+ data: {
701
+ type: variant,
702
+ data: { sessionId },
703
+ },
704
+ });
705
+ }
706
+
707
+ function buildSensorReadingEvent(category, eventType, detail, valueFields) {
708
+ const payload = requireDetailObject(detail, eventType);
709
+ const targetId = requireStringField(payload.targetId, 'targetId', eventType);
710
+ const sessionId = requireStringField(payload.sessionId, 'sessionId', eventType);
711
+ const data = {
712
+ sessionId,
713
+ timestamp: Number(payload.timestamp || 0),
714
+ };
715
+ for (const fieldName of valueFields) {
716
+ data[fieldName] = Number(payload[fieldName] || 0);
717
+ }
718
+ return createIpcEvent(eventType, targetId, {
719
+ type: category,
720
+ data: {
721
+ type: 'Reading',
722
+ data,
723
+ },
724
+ });
725
+ }
726
+
727
+ function buildSensorErrorEvent(category, eventType, detail) {
728
+ const payload = requireDetailObject(detail, eventType);
729
+ const targetId = requireStringField(payload.targetId, 'targetId', eventType);
730
+ const sessionId = requireStringField(payload.sessionId, 'sessionId', eventType);
731
+ return createIpcEvent(eventType, targetId, {
732
+ type: category,
733
+ data: {
734
+ type: 'Error',
735
+ data: {
736
+ sessionId,
737
+ error: String(payload.error || ''),
738
+ message: String(payload.message || ''),
739
+ },
740
+ },
741
+ });
742
+ }
743
+
744
+ function buildMediaRecordingEvent(eventType, variant, detail, data) {
745
+ const payload = requireDetailObject(detail, eventType);
746
+ const targetId = requireStringField(payload.targetId, 'targetId', eventType);
747
+ return createIpcEvent(eventType, targetId, {
748
+ type: 'Media',
749
+ data:
750
+ data == null
751
+ ? { type: variant }
752
+ : {
753
+ type: variant,
754
+ data,
755
+ },
756
+ });
757
+ }
758
+
759
+ const HOST_CAPABILITY_EVENT_BUILDERS = {
760
+ 'speech.start': (detail) => buildSpeechSessionEvent('speech.start', 'Start', detail),
761
+ 'speech.audiostart': (detail) =>
762
+ buildSpeechSessionEvent('speech.audiostart', 'AudioStart', detail),
763
+ 'speech.soundstart': (detail) =>
764
+ buildSpeechSessionEvent('speech.soundstart', 'SoundStart', detail),
765
+ 'speech.speechstart': (detail) =>
766
+ buildSpeechSessionEvent('speech.speechstart', 'SpeechStart', detail),
767
+ 'speech.result': (detail) => buildSpeechResultEvent('speech.result', detail),
768
+ 'speech.nomatch': (detail) => buildSpeechSessionEvent('speech.nomatch', 'NoMatch', detail),
769
+ 'speech.error': (detail) => buildSpeechErrorEvent('speech.error', detail),
770
+ 'speech.speechend': (detail) => buildSpeechSessionEvent('speech.speechend', 'SpeechEnd', detail),
771
+ 'speech.soundend': (detail) => buildSpeechSessionEvent('speech.soundend', 'SoundEnd', detail),
772
+ 'speech.audioend': (detail) => buildSpeechSessionEvent('speech.audioend', 'AudioEnd', detail),
773
+ 'speech.end': (detail) => buildSpeechSessionEvent('speech.end', 'End', detail),
774
+ 'absoluteOrientation.activate': (detail) =>
775
+ buildSensorSessionEvent(
776
+ 'AbsoluteOrientation',
777
+ 'absoluteOrientation.activate',
778
+ 'Activate',
779
+ detail,
780
+ ),
781
+ 'absoluteOrientation.reading': (detail) =>
782
+ buildSensorReadingEvent('AbsoluteOrientation', 'absoluteOrientation.reading', detail, [
783
+ 'x',
784
+ 'y',
785
+ 'z',
786
+ 'w',
787
+ ]),
788
+ 'absoluteOrientation.error': (detail) =>
789
+ buildSensorErrorEvent('AbsoluteOrientation', 'absoluteOrientation.error', detail),
790
+ 'accelerometer.activate': (detail) =>
791
+ buildSensorSessionEvent('Accelerometer', 'accelerometer.activate', 'Activate', detail),
792
+ 'accelerometer.reading': (detail) =>
793
+ buildSensorReadingEvent('Accelerometer', 'accelerometer.reading', detail, ['x', 'y', 'z']),
794
+ 'accelerometer.error': (detail) =>
795
+ buildSensorErrorEvent('Accelerometer', 'accelerometer.error', detail),
796
+ 'gyroscope.activate': (detail) =>
797
+ buildSensorSessionEvent('Gyroscope', 'gyroscope.activate', 'Activate', detail),
798
+ 'gyroscope.reading': (detail) =>
799
+ buildSensorReadingEvent('Gyroscope', 'gyroscope.reading', detail, ['x', 'y', 'z']),
800
+ 'gyroscope.error': (detail) => buildSensorErrorEvent('Gyroscope', 'gyroscope.error', detail),
801
+ 'magnetometer.activate': (detail) =>
802
+ buildSensorSessionEvent('Magnetometer', 'magnetometer.activate', 'Activate', detail),
803
+ 'magnetometer.reading': (detail) =>
804
+ buildSensorReadingEvent('Magnetometer', 'magnetometer.reading', detail, ['x', 'y', 'z']),
805
+ 'magnetometer.error': (detail) =>
806
+ buildSensorErrorEvent('Magnetometer', 'magnetometer.error', detail),
807
+ 'media.audioRecordingStarted': (detail) =>
808
+ buildMediaRecordingEvent('media', 'AudioRecordingStarted', detail),
809
+ 'media.audioRecordingStopped': (detail) => {
810
+ const payload = requireDetailObject(detail, 'media.audioRecordingStopped');
811
+ return buildMediaRecordingEvent(
812
+ 'media',
813
+ 'AudioRecordingStopped',
814
+ payload,
815
+ String(payload.path || ''),
816
+ );
817
+ },
818
+ 'media.audioRecordingPaused': (detail) =>
819
+ buildMediaRecordingEvent('media', 'AudioRecordingPaused', detail),
820
+ 'media.audioRecordingResumed': (detail) =>
821
+ buildMediaRecordingEvent('media', 'AudioRecordingResumed', detail),
822
+ 'media.audioFrameRecorded': (detail) => {
823
+ const payload = requireDetailObject(detail, 'media.audioFrameRecorded');
824
+ const bytes = cloneUint8Array(payload.data ?? payload.bytes ?? payload.buffer);
825
+ if (!bytes) {
826
+ throw new TypeError(
827
+ 'Host capability event `media.audioFrameRecorded` requires binary `data`.',
828
+ );
829
+ }
830
+ return buildMediaRecordingEvent('media', 'AudioFrameRecorded', payload, Array.from(bytes));
831
+ },
832
+ 'media.audioRecordingError': (detail) => {
833
+ const payload = requireDetailObject(detail, 'media.audioRecordingError');
834
+ return buildMediaRecordingEvent(
835
+ 'media',
836
+ 'AudioRecordingError',
837
+ payload,
838
+ String(payload.message || ''),
839
+ );
840
+ },
841
+ 'media.audioRecordingInterruptionBegin': (detail) =>
842
+ buildMediaRecordingEvent('media', 'AudioRecordingInterruptionBegin', detail),
843
+ 'media.audioRecordingInterruptionEnd': (detail) =>
844
+ buildMediaRecordingEvent('media', 'AudioRecordingInterruptionEnd', detail),
845
+ };
846
+
847
+ const HOST_CAPABILITY_EVENT_TYPES = Object.keys(HOST_CAPABILITY_EVENT_BUILDERS);
848
+
441
849
  class InkHostMessageStream {
442
850
  #rawStream;
443
851
  #requestRender;
@@ -553,6 +961,7 @@ export class InkView {
553
961
  #scaleFactor;
554
962
  #surfaceBinding;
555
963
  #onContentSizeChanged;
964
+ #hostCapabilitiesTarget;
556
965
 
557
966
  constructor(rawView, options = {}) {
558
967
  this.#rawView = rawView;
@@ -575,7 +984,10 @@ export class InkView {
575
984
  this.#scaleFactor = normalizeScaleFactor(options.scaleFactor);
576
985
  this.#surfaceBinding = null;
577
986
  this.#onContentSizeChanged = null;
987
+ this.#hostCapabilitiesTarget = new EventTarget();
988
+ this.#bindHostCapabilityEvents();
578
989
  this.onContentSizeChanged = options.onContentSizeChanged || null;
990
+ this.setHostCapabilities(options.hostCapabilities || null);
579
991
  }
580
992
 
581
993
  #clearSurfaceContents() {
@@ -890,6 +1302,27 @@ export class InkView {
890
1302
  return true;
891
1303
  }
892
1304
 
1305
+ #bindHostCapabilityEvents() {
1306
+ for (const eventType of HOST_CAPABILITY_EVENT_TYPES) {
1307
+ this.#hostCapabilitiesTarget.addEventListener(eventType, (event) => {
1308
+ if (this.#destroyed || typeof this.#rawView.dispatchHostCapabilityEvent !== 'function') {
1309
+ return;
1310
+ }
1311
+ const buildIpcEvent = HOST_CAPABILITY_EVENT_BUILDERS[eventType];
1312
+ if (typeof buildIpcEvent !== 'function') {
1313
+ return;
1314
+ }
1315
+ try {
1316
+ const ipcEvent = buildIpcEvent(event?.detail);
1317
+ this.#rawView.dispatchHostCapabilityEvent(JSON.stringify(ipcEvent));
1318
+ this.requestRender();
1319
+ } catch (error) {
1320
+ console.error(`InkView failed to bridge host capability event \`${eventType}\`.`, error);
1321
+ }
1322
+ });
1323
+ }
1324
+ }
1325
+
893
1326
  attachSurface(surface) {
894
1327
  const normalizedSurface = normalizeSurfaceDescriptor(surface);
895
1328
  if (!normalizedSurface) {
@@ -937,6 +1370,9 @@ export class InkView {
937
1370
  if (typeof this.#rawView.clearSurface === 'function') {
938
1371
  this.#rawView.clearSurface();
939
1372
  }
1373
+ if (typeof this.#rawView.setHostCapabilities === 'function') {
1374
+ this.#rawView.setHostCapabilities(null);
1375
+ }
940
1376
  this.#surfaceBinding = null;
941
1377
  this.#surface = null;
942
1378
  this.#canvas = null;
@@ -1247,17 +1683,22 @@ export class InkView {
1247
1683
  return this;
1248
1684
  }
1249
1685
 
1250
- setHostLanguageModelConfig(config) {
1251
- if (typeof this.#rawView.setLanguageModelConfig !== 'function') {
1252
- return this;
1686
+ setHostCapabilities(capabilities) {
1687
+ const normalizedCapabilities = normalizeHostCapabilities(capabilities);
1688
+ if (typeof this.#rawView.setHostCapabilities === 'function') {
1689
+ this.#rawView.setHostCapabilities(normalizedCapabilities);
1253
1690
  }
1254
- const normalizedConfig = normalizeHostLanguageModelConfig(config);
1255
- this.#rawView.setLanguageModelConfig(
1256
- normalizedConfig == null ? null : JSON.stringify(normalizedConfig),
1257
- );
1258
1691
  return this;
1259
1692
  }
1260
1693
 
1694
+ getHostCapabilitiesTarget() {
1695
+ return this.#hostCapabilitiesTarget;
1696
+ }
1697
+
1698
+ get hostCapabilitiesTarget() {
1699
+ return this.#hostCapabilitiesTarget;
1700
+ }
1701
+
1261
1702
  dispatchPointer(eventType, x, y, id = 0, button = 0, deltaX = 0, deltaY = 0) {
1262
1703
  this.#rawView.dispatchPointer(eventType, x, y, id, button, deltaX, deltaY);
1263
1704
  this.requestRender();
package/package.json CHANGED
@@ -10,7 +10,7 @@
10
10
  "access": "public",
11
11
  "registry": "https://registry.npmjs.com/"
12
12
  },
13
- "version": "0.10.0",
13
+ "version": "0.11.0",
14
14
  "type": "module",
15
15
  "main": "index.js",
16
16
  "types": "index.d.ts",
package/pkg/ink_web.d.ts CHANGED
@@ -24,6 +24,7 @@ export class InkWebView {
24
24
  currentContentHeight(): number;
25
25
  currentContentWidth(): number;
26
26
  destroy(): void;
27
+ dispatchHostCapabilityEvent(event_json: string): void;
27
28
  dispatchInput(event_type: string, code: string, timestamp: number): void;
28
29
  dispatchMessageEvent(payload_json: string, origin: string, last_event_id: string): void;
29
30
  dispatchPointer(event_type: string, x: number, y: number, id: number, button: number, delta_x: number, delta_y: number): void;
@@ -36,15 +37,15 @@ export class InkWebView {
36
37
  openBundle(app_id: string, files: Map<any, any>, initial_page?: string | null, query_json?: string | null): void;
37
38
  render(): boolean;
38
39
  resolveCloseRequested(allow: boolean): void;
40
+ setHostCapabilities(capabilities: any): void;
39
41
  setInteractive(interactive: boolean): void;
40
- setLanguageModelConfig(config_json?: string | null): void;
41
42
  setLayoutMode(layout_mode: string): void;
42
43
  setViewport(width: number, height: number, scale_factor: number, reset_scroll?: boolean | null): void;
43
44
  }
44
45
 
45
46
  export function get_version(): string;
46
47
 
47
- export function main(): void;
48
+ export function start(): void;
48
49
 
49
50
  export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
50
51
 
@@ -67,6 +68,7 @@ export interface InitOutput {
67
68
  readonly inkwebview_currentContentHeight: (a: number) => number;
68
69
  readonly inkwebview_currentContentWidth: (a: number) => number;
69
70
  readonly inkwebview_destroy: (a: number) => void;
71
+ readonly inkwebview_dispatchHostCapabilityEvent: (a: number, b: number, c: number, d: number) => void;
70
72
  readonly inkwebview_dispatchInput: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
71
73
  readonly inkwebview_dispatchMessageEvent: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => void;
72
74
  readonly inkwebview_dispatchPointer: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number) => void;
@@ -79,16 +81,16 @@ export interface InitOutput {
79
81
  readonly inkwebview_openBundle: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number) => void;
80
82
  readonly inkwebview_render: (a: number, b: number) => void;
81
83
  readonly inkwebview_resolveCloseRequested: (a: number, b: number) => void;
84
+ readonly inkwebview_setHostCapabilities: (a: number, b: number, c: number) => void;
82
85
  readonly inkwebview_setInteractive: (a: number, b: number) => void;
83
- readonly inkwebview_setLanguageModelConfig: (a: number, b: number, c: number, d: number) => void;
84
86
  readonly inkwebview_setLayoutMode: (a: number, b: number, c: number) => void;
85
87
  readonly inkwebview_setViewport: (a: number, b: number, c: number, d: number, e: number) => void;
86
- readonly main: () => void;
87
- readonly __wasm_bindgen_func_elem_9822: (a: number, b: number) => void;
88
- readonly __wasm_bindgen_func_elem_14048: (a: number, b: number) => void;
89
- readonly __wasm_bindgen_func_elem_9965: (a: number, b: number, c: number) => void;
90
- readonly __wasm_bindgen_func_elem_14049: (a: number, b: number, c: number) => void;
91
- readonly __wasm_bindgen_func_elem_9963: (a: number, b: number) => void;
88
+ readonly start: () => void;
89
+ readonly __wasm_bindgen_func_elem_10696: (a: number, b: number) => void;
90
+ readonly __wasm_bindgen_func_elem_14706: (a: number, b: number) => void;
91
+ readonly __wasm_bindgen_func_elem_10674: (a: number, b: number, c: number) => void;
92
+ readonly __wasm_bindgen_func_elem_14707: (a: number, b: number, c: number) => void;
93
+ readonly __wasm_bindgen_func_elem_10675: (a: number, b: number) => void;
92
94
  readonly __wbindgen_export: (a: number, b: number) => number;
93
95
  readonly __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
94
96
  readonly __wbindgen_export3: (a: number) => void;
package/pkg/ink_web.js CHANGED
@@ -164,6 +164,24 @@ export class InkWebView {
164
164
  destroy() {
165
165
  wasm.inkwebview_destroy(this.__wbg_ptr);
166
166
  }
167
+ /**
168
+ * @param {string} event_json
169
+ */
170
+ dispatchHostCapabilityEvent(event_json) {
171
+ try {
172
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
173
+ const ptr0 = passStringToWasm0(event_json, wasm.__wbindgen_export, wasm.__wbindgen_export2);
174
+ const len0 = WASM_VECTOR_LEN;
175
+ wasm.inkwebview_dispatchHostCapabilityEvent(retptr, this.__wbg_ptr, ptr0, len0);
176
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
177
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
178
+ if (r1) {
179
+ throw takeObject(r0);
180
+ }
181
+ } finally {
182
+ wasm.__wbindgen_add_to_stack_pointer(16);
183
+ }
184
+ }
167
185
  /**
168
186
  * @param {string} event_type
169
187
  * @param {string} code
@@ -346,20 +364,12 @@ export class InkWebView {
346
364
  wasm.inkwebview_resolveCloseRequested(this.__wbg_ptr, allow);
347
365
  }
348
366
  /**
349
- * @param {boolean} interactive
350
- */
351
- setInteractive(interactive) {
352
- wasm.inkwebview_setInteractive(this.__wbg_ptr, interactive);
353
- }
354
- /**
355
- * @param {string | null} [config_json]
367
+ * @param {any} capabilities
356
368
  */
357
- setLanguageModelConfig(config_json) {
369
+ setHostCapabilities(capabilities) {
358
370
  try {
359
371
  const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
360
- var ptr0 = isLikeNone(config_json) ? 0 : passStringToWasm0(config_json, wasm.__wbindgen_export, wasm.__wbindgen_export2);
361
- var len0 = WASM_VECTOR_LEN;
362
- wasm.inkwebview_setLanguageModelConfig(retptr, this.__wbg_ptr, ptr0, len0);
372
+ wasm.inkwebview_setHostCapabilities(retptr, this.__wbg_ptr, addHeapObject(capabilities));
363
373
  var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
364
374
  var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
365
375
  if (r1) {
@@ -369,6 +379,12 @@ export class InkWebView {
369
379
  wasm.__wbindgen_add_to_stack_pointer(16);
370
380
  }
371
381
  }
382
+ /**
383
+ * @param {boolean} interactive
384
+ */
385
+ setInteractive(interactive) {
386
+ wasm.inkwebview_setInteractive(this.__wbg_ptr, interactive);
387
+ }
372
388
  /**
373
389
  * @param {string} layout_mode
374
390
  */
@@ -409,8 +425,8 @@ export function get_version() {
409
425
  }
410
426
  }
411
427
 
412
- export function main() {
413
- wasm.main();
428
+ export function start() {
429
+ wasm.start();
414
430
  }
415
431
  import * as import1 from "../env.js"
416
432
  import * as import2 from "../env.js"
@@ -1217,28 +1233,28 @@ function __wbg_get_imports() {
1217
1233
  return ret;
1218
1234
  },
1219
1235
  __wbindgen_cast_0000000000000001: function(arg0, arg1) {
1220
- // Cast intrinsic for `Closure(Closure { dtor_idx: 2633, function: Function { arguments: [NamedExternref("CloseEvent")], shim_idx: 2621, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
1221
- const ret = makeMutClosure(arg0, arg1, wasm.__wasm_bindgen_func_elem_9822, __wasm_bindgen_func_elem_9965);
1236
+ // Cast intrinsic for `Closure(Closure { dtor_idx: 2675, function: Function { arguments: [NamedExternref("CloseEvent")], shim_idx: 2678, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
1237
+ const ret = makeMutClosure(arg0, arg1, wasm.__wasm_bindgen_func_elem_10696, __wasm_bindgen_func_elem_10674);
1222
1238
  return addHeapObject(ret);
1223
1239
  },
1224
1240
  __wbindgen_cast_0000000000000002: function(arg0, arg1) {
1225
- // Cast intrinsic for `Closure(Closure { dtor_idx: 2633, function: Function { arguments: [NamedExternref("Event")], shim_idx: 2621, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
1226
- const ret = makeMutClosure(arg0, arg1, wasm.__wasm_bindgen_func_elem_9822, __wasm_bindgen_func_elem_9965);
1241
+ // Cast intrinsic for `Closure(Closure { dtor_idx: 2675, function: Function { arguments: [NamedExternref("Event")], shim_idx: 2678, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
1242
+ const ret = makeMutClosure(arg0, arg1, wasm.__wasm_bindgen_func_elem_10696, __wasm_bindgen_func_elem_10674);
1227
1243
  return addHeapObject(ret);
1228
1244
  },
1229
1245
  __wbindgen_cast_0000000000000003: function(arg0, arg1) {
1230
- // Cast intrinsic for `Closure(Closure { dtor_idx: 2633, function: Function { arguments: [NamedExternref("MessageEvent")], shim_idx: 2621, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
1231
- const ret = makeMutClosure(arg0, arg1, wasm.__wasm_bindgen_func_elem_9822, __wasm_bindgen_func_elem_9965);
1246
+ // Cast intrinsic for `Closure(Closure { dtor_idx: 2675, function: Function { arguments: [NamedExternref("MessageEvent")], shim_idx: 2678, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
1247
+ const ret = makeMutClosure(arg0, arg1, wasm.__wasm_bindgen_func_elem_10696, __wasm_bindgen_func_elem_10674);
1232
1248
  return addHeapObject(ret);
1233
1249
  },
1234
1250
  __wbindgen_cast_0000000000000004: function(arg0, arg1) {
1235
- // Cast intrinsic for `Closure(Closure { dtor_idx: 2633, function: Function { arguments: [], shim_idx: 2634, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
1236
- const ret = makeMutClosure(arg0, arg1, wasm.__wasm_bindgen_func_elem_9822, __wasm_bindgen_func_elem_9963);
1251
+ // Cast intrinsic for `Closure(Closure { dtor_idx: 2675, function: Function { arguments: [], shim_idx: 2676, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
1252
+ const ret = makeMutClosure(arg0, arg1, wasm.__wasm_bindgen_func_elem_10696, __wasm_bindgen_func_elem_10675);
1237
1253
  return addHeapObject(ret);
1238
1254
  },
1239
1255
  __wbindgen_cast_0000000000000005: function(arg0, arg1) {
1240
- // Cast intrinsic for `Closure(Closure { dtor_idx: 3529, function: Function { arguments: [Externref], shim_idx: 3530, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
1241
- const ret = makeMutClosure(arg0, arg1, wasm.__wasm_bindgen_func_elem_14048, __wasm_bindgen_func_elem_14049);
1256
+ // Cast intrinsic for `Closure(Closure { dtor_idx: 3626, function: Function { arguments: [Externref], shim_idx: 3627, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
1257
+ const ret = makeMutClosure(arg0, arg1, wasm.__wasm_bindgen_func_elem_14706, __wasm_bindgen_func_elem_14707);
1242
1258
  return addHeapObject(ret);
1243
1259
  },
1244
1260
  __wbindgen_cast_0000000000000006: function(arg0) {
@@ -1295,16 +1311,16 @@ function __wbg_get_imports() {
1295
1311
  };
1296
1312
  }
1297
1313
 
1298
- function __wasm_bindgen_func_elem_9963(arg0, arg1) {
1299
- wasm.__wasm_bindgen_func_elem_9963(arg0, arg1);
1314
+ function __wasm_bindgen_func_elem_10675(arg0, arg1) {
1315
+ wasm.__wasm_bindgen_func_elem_10675(arg0, arg1);
1300
1316
  }
1301
1317
 
1302
- function __wasm_bindgen_func_elem_9965(arg0, arg1, arg2) {
1303
- wasm.__wasm_bindgen_func_elem_9965(arg0, arg1, addHeapObject(arg2));
1318
+ function __wasm_bindgen_func_elem_10674(arg0, arg1, arg2) {
1319
+ wasm.__wasm_bindgen_func_elem_10674(arg0, arg1, addHeapObject(arg2));
1304
1320
  }
1305
1321
 
1306
- function __wasm_bindgen_func_elem_14049(arg0, arg1, arg2) {
1307
- wasm.__wasm_bindgen_func_elem_14049(arg0, arg1, addHeapObject(arg2));
1322
+ function __wasm_bindgen_func_elem_14707(arg0, arg1, arg2) {
1323
+ wasm.__wasm_bindgen_func_elem_14707(arg0, arg1, addHeapObject(arg2));
1308
1324
  }
1309
1325
 
1310
1326
 
Binary file
@@ -18,6 +18,7 @@ export const inkwebview_currentClosedSource: (a: number, b: number) => void;
18
18
  export const inkwebview_currentContentHeight: (a: number) => number;
19
19
  export const inkwebview_currentContentWidth: (a: number) => number;
20
20
  export const inkwebview_destroy: (a: number) => void;
21
+ export const inkwebview_dispatchHostCapabilityEvent: (a: number, b: number, c: number, d: number) => void;
21
22
  export const inkwebview_dispatchInput: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
22
23
  export const inkwebview_dispatchMessageEvent: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => void;
23
24
  export const inkwebview_dispatchPointer: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number) => void;
@@ -30,16 +31,16 @@ export const inkwebview_open: (a: number, b: number, c: number, d: number, e: nu
30
31
  export const inkwebview_openBundle: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number) => void;
31
32
  export const inkwebview_render: (a: number, b: number) => void;
32
33
  export const inkwebview_resolveCloseRequested: (a: number, b: number) => void;
34
+ export const inkwebview_setHostCapabilities: (a: number, b: number, c: number) => void;
33
35
  export const inkwebview_setInteractive: (a: number, b: number) => void;
34
- export const inkwebview_setLanguageModelConfig: (a: number, b: number, c: number, d: number) => void;
35
36
  export const inkwebview_setLayoutMode: (a: number, b: number, c: number) => void;
36
37
  export const inkwebview_setViewport: (a: number, b: number, c: number, d: number, e: number) => void;
37
- export const main: () => void;
38
- export const __wasm_bindgen_func_elem_9822: (a: number, b: number) => void;
39
- export const __wasm_bindgen_func_elem_14048: (a: number, b: number) => void;
40
- export const __wasm_bindgen_func_elem_9965: (a: number, b: number, c: number) => void;
41
- export const __wasm_bindgen_func_elem_14049: (a: number, b: number, c: number) => void;
42
- export const __wasm_bindgen_func_elem_9963: (a: number, b: number) => void;
38
+ export const start: () => void;
39
+ export const __wasm_bindgen_func_elem_10696: (a: number, b: number) => void;
40
+ export const __wasm_bindgen_func_elem_14706: (a: number, b: number) => void;
41
+ export const __wasm_bindgen_func_elem_10674: (a: number, b: number, c: number) => void;
42
+ export const __wasm_bindgen_func_elem_14707: (a: number, b: number, c: number) => void;
43
+ export const __wasm_bindgen_func_elem_10675: (a: number, b: number) => void;
43
44
  export const __wbindgen_export: (a: number, b: number) => number;
44
45
  export const __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
45
46
  export const __wbindgen_export3: (a: number) => void;