@glassly/engine 0.3.4-dev.692 → 0.3.4-dev.694

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glassly/engine",
3
- "version": "0.3.4-dev.692",
3
+ "version": "0.3.4-dev.694",
4
4
  "description": "Glassly Engine — miniapp registry, WebView bridge, and miniapp store",
5
5
  "main": "build/index.js",
6
6
  "react-native": "src/index.ts",
@@ -97,17 +97,17 @@
97
97
  "registry": "https://registry.npmjs.org/"
98
98
  },
99
99
  "dependencies": {
100
- "@glassly/bluetooth-sdk": "0.3.4-dev.692",
101
- "@glassly/cloud-client": "0.3.4-dev.692",
102
- "@glassly/cloud-protocol": "0.3.4-dev.692",
103
- "@glassly/crust": "0.3.4-dev.692",
104
- "@glassly/miniapp": "0.3.4-dev.692",
100
+ "@glassly/bluetooth-sdk": "0.3.4-dev.694",
101
+ "@glassly/cloud-client": "0.3.4-dev.694",
102
+ "@glassly/cloud-protocol": "0.3.4-dev.694",
103
+ "@glassly/crust": "0.3.4-dev.694",
104
+ "@glassly/miniapp": "0.3.4-dev.694",
105
105
  "buffer": "^6.0.3",
106
106
  "events": "^3.3.0",
107
107
  "react-native-marked": "8.1.1",
108
108
  "semver": "^7.7.4",
109
109
  "typesafe-ts": "^1.7.1",
110
- "@glassly/llm-providers": "0.3.4-dev.692",
110
+ "@glassly/llm-providers": "0.3.4-dev.694",
111
111
  "@huggingface/jinja": "^0.5.9",
112
112
  "jsonrepair": "^3.12.0"
113
113
  },
@@ -12,9 +12,9 @@ export interface EngineReleaseMetadata {
12
12
  export const ENGINE_RELEASE_METADATA: Readonly<EngineReleaseMetadata> = Object.freeze({
13
13
  "schemaVersion": 1,
14
14
  "familyBaseVersion": "0.3.4",
15
- "releaseIdentity": "0.3.4-dev.692",
16
- "releaseSetId": "glassly-0.3.4-dev.692",
17
- "sourceCommit": "cdff0285d06e386961f1cd79f78ea78296ffe545",
15
+ "releaseIdentity": "0.3.4-dev.694",
16
+ "releaseSetId": "glassly-0.3.4-dev.694",
17
+ "sourceCommit": "2970c08c3e091a371fd3459c630eceb7811b1121",
18
18
  "otaManifestUrl": null,
19
19
  "otaManifestSha256": null
20
20
  })
package/src/index.ts CHANGED
@@ -35,6 +35,8 @@ export type {
35
35
  IslandUiSeams,
36
36
  ScanQrOptions,
37
37
  ScanQrResult,
38
+ WebLoginOptions,
39
+ WebLoginResult,
38
40
  SubjectTokenType,
39
41
  } from "./runtime/bootstrap"
40
42
 
@@ -66,6 +66,13 @@ export interface IslandUiSeams {
66
66
  * miniapps get NOT_IMPLEMENTED.
67
67
  */
68
68
  scanQr?: (options?: ScanQrOptions) => Promise<ScanQrResult>
69
+ /**
70
+ * `session.system.webLogin` — open a third-party sign-in page in an in-app
71
+ * browser sheet and hand back named cookies once it reaches the done URL.
72
+ * Same Modal rule as scanQr: must NOT clear miniapp foreground. Absent ⇒
73
+ * miniapps get NOT_IMPLEMENTED.
74
+ */
75
+ webLogin?: (options: WebLoginOptions) => Promise<WebLoginResult>
69
76
  }
70
77
 
71
78
  export interface ScanQrOptions {
@@ -75,6 +82,17 @@ export interface ScanQrOptions {
75
82
 
76
83
  export type ScanQrResult = {data: string} | {cancelled: true}
77
84
 
85
+ export interface WebLoginOptions {
86
+ url: string
87
+ doneUrlPrefix: string
88
+ cookies: string[]
89
+ title?: string
90
+ /** The requesting miniapp, shown on the sheet so the user knows who asked. */
91
+ packageName?: string
92
+ }
93
+
94
+ export type WebLoginResult = {status: "completed"; cookies: Record<string, string>; url: string} | {status: "cancelled"}
95
+
78
96
  export interface IslandConfigureOptions {
79
97
  /** REQUIRED — the only must-have seam. The host owns login; engine owns the rest. */
80
98
  auth: IslandAuth
@@ -0,0 +1,59 @@
1
+ import type {WebLoginOptions, WebLoginResult} from "./bootstrap"
2
+
3
+ export class WebLoginNotConfiguredError extends Error {
4
+ readonly code = "NOT_IMPLEMENTED"
5
+ constructor() {
6
+ super("In-app sign-in is not configured on this host. Reload the Glassly App and try again.")
7
+ this.name = "WebLoginNotConfiguredError"
8
+ }
9
+ }
10
+
11
+ export class WebLoginInvalidError extends Error {
12
+ readonly code = "INVALID_ARGS"
13
+ constructor(message: string) {
14
+ super(message)
15
+ this.name = "WebLoginInvalidError"
16
+ }
17
+ }
18
+
19
+ /** The host of an https URL, or null when it is anything else. */
20
+ function httpsHost(value: unknown): string | null {
21
+ if (typeof value !== "string") return null
22
+ const match = value.match(/^https:\/\/([^/?#]+)(?:[/?#]|$)/i)
23
+ return match ? match[1].toLowerCase() : null
24
+ }
25
+
26
+ /**
27
+ * Checks a WEB_LOGIN payload before it reaches the host sheet: both URLs
28
+ * https, at least one cookie name, and the cookie names sane. The done URL is
29
+ * where cookies are read from, so it must be an origin the miniapp named.
30
+ */
31
+ export function parseWebLoginOptions(payload: Record<string, unknown>, packageName?: string): WebLoginOptions {
32
+ const url = payload.url
33
+ const doneUrlPrefix = payload.doneUrlPrefix
34
+ if (!httpsHost(url)) throw new WebLoginInvalidError("webLogin: url must be an https URL")
35
+ if (!httpsHost(doneUrlPrefix)) throw new WebLoginInvalidError("webLogin: doneUrlPrefix must be an https URL")
36
+ const cookies = Array.isArray(payload.cookies)
37
+ ? payload.cookies.filter(
38
+ (name): name is string => typeof name === "string" && /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/.test(name),
39
+ )
40
+ : []
41
+ if (cookies.length === 0) throw new WebLoginInvalidError("webLogin: cookies must name at least one cookie")
42
+ return {
43
+ url: url as string,
44
+ doneUrlPrefix: doneUrlPrefix as string,
45
+ cookies,
46
+ title: typeof payload.title === "string" && payload.title.trim() ? payload.title.trim() : undefined,
47
+ packageName,
48
+ }
49
+ }
50
+
51
+ export async function invokeWebLoginSeam(
52
+ webLogin: ((options: WebLoginOptions) => Promise<WebLoginResult>) | undefined,
53
+ payload: Record<string, unknown>,
54
+ packageName?: string,
55
+ ): Promise<WebLoginResult> {
56
+ const options = parseWebLoginOptions(payload, packageName)
57
+ if (!webLogin) throw new WebLoginNotConfiguredError()
58
+ return webLogin(options)
59
+ }
@@ -142,6 +142,7 @@ import {
142
142
  } from "../runtime/config"
143
143
  import {getAnalytics, getUiSeams} from "../runtime/bootstrap"
144
144
  import {invokeScanQrSeam} from "../runtime/scanQrSeam"
145
+ import {invokeWebLoginSeam} from "../runtime/webLoginSeam"
145
146
  import {normalizeStreamAudioConfig, normalizeStreamVideoConfig} from "../runtime/streamConfig"
146
147
  import {visibleActionRows} from "./manifestActions"
147
148
  import {toLanguageHint} from "@glassly/cloud-protocol/languages"
@@ -1623,6 +1624,9 @@ class LocalMiniappRuntime {
1623
1624
  case MiniappRequestType.SCAN_QR:
1624
1625
  void this.handleScanQr(packageName, payload, requestId)
1625
1626
  break
1627
+ case MiniappRequestType.WEB_LOGIN:
1628
+ void this.handleWebLogin(packageName, payload, requestId)
1629
+ break
1626
1630
 
1627
1631
  // Persistent binary blob storage (session.blob)
1628
1632
  case MiniappRequestType.BLOB_CREATE:
@@ -4536,6 +4540,25 @@ class LocalMiniappRuntime {
4536
4540
  }
4537
4541
  }
4538
4542
 
4543
+ /**
4544
+ * session.system.webLogin — host in-app browser sheet. Same contract as
4545
+ * scanQr: the seam presents a Modal and never clears miniapp foreground.
4546
+ */
4547
+ private async handleWebLogin(packageName: string, payload: Record<string, unknown>, requestId?: string): Promise<void> {
4548
+ try {
4549
+ const result = await invokeWebLoginSeam(getUiSeams().webLogin, payload, packageName)
4550
+ this.sendResult(packageName, requestId, true, result)
4551
+ } catch (err) {
4552
+ if (!getUiSeams().webLogin) {
4553
+ console.warn(`${LOG_TAG}: webLogin seam missing — sign-in sheet is not registered`)
4554
+ }
4555
+ this.sendResult(packageName, requestId, false, undefined, {
4556
+ code: (err as {code?: string} | null | undefined)?.code || MiniappErrorCode.INTERNAL,
4557
+ message: err instanceof Error ? err.message : "Web sign-in failed",
4558
+ })
4559
+ }
4560
+ }
4561
+
4539
4562
  // ---------------------------------------------------------------------------
4540
4563
  // System utilities (share, open URL, clipboard, download)
4541
4564
  // ---------------------------------------------------------------------------