@glassly/engine 0.3.4-dev.692 → 0.3.4-dev.696
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/build/generated/releaseMetadata.js +3 -3
- package/build/generated/releaseMetadata.js.map +1 -1
- package/build/index.d.ts +1 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js.map +1 -1
- package/build/runtime/bootstrap.d.ts +22 -0
- package/build/runtime/bootstrap.d.ts.map +1 -1
- package/build/runtime/bootstrap.js.map +1 -1
- package/build/runtime/webLoginSeam.d.ts +17 -0
- package/build/runtime/webLoginSeam.d.ts.map +1 -0
- package/build/runtime/webLoginSeam.js +53 -0
- package/build/runtime/webLoginSeam.js.map +1 -0
- package/build/services/CloudClientService.d.ts +2 -2
- package/build/services/LocalMiniappRuntime.d.ts +5 -0
- package/build/services/LocalMiniappRuntime.d.ts.map +1 -1
- package/build/services/LocalMiniappRuntime.js +23 -0
- package/build/services/LocalMiniappRuntime.js.map +1 -1
- package/package.json +7 -7
- package/src/generated/releaseMetadata.ts +3 -3
- package/src/index.ts +2 -0
- package/src/runtime/bootstrap.ts +18 -0
- package/src/runtime/webLoginSeam.ts +59 -0
- package/src/services/LocalMiniappRuntime.ts +23 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@glassly/engine",
|
|
3
|
-
"version": "0.3.4-dev.
|
|
3
|
+
"version": "0.3.4-dev.696",
|
|
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.
|
|
101
|
-
"@glassly/cloud-client": "0.3.4-dev.
|
|
102
|
-
"@glassly/cloud-protocol": "0.3.4-dev.
|
|
103
|
-
"@glassly/crust": "0.3.4-dev.
|
|
104
|
-
"@glassly/miniapp": "0.3.4-dev.
|
|
100
|
+
"@glassly/bluetooth-sdk": "0.3.4-dev.696",
|
|
101
|
+
"@glassly/cloud-client": "0.3.4-dev.696",
|
|
102
|
+
"@glassly/cloud-protocol": "0.3.4-dev.696",
|
|
103
|
+
"@glassly/crust": "0.3.4-dev.696",
|
|
104
|
+
"@glassly/miniapp": "0.3.4-dev.696",
|
|
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.
|
|
110
|
+
"@glassly/llm-providers": "0.3.4-dev.696",
|
|
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.
|
|
16
|
-
"releaseSetId": "glassly-0.3.4-dev.
|
|
17
|
-
"sourceCommit": "
|
|
15
|
+
"releaseIdentity": "0.3.4-dev.696",
|
|
16
|
+
"releaseSetId": "glassly-0.3.4-dev.696",
|
|
17
|
+
"sourceCommit": "6350b9aa9518c8af4da730f6d6c60312dc47e672",
|
|
18
18
|
"otaManifestUrl": null,
|
|
19
19
|
"otaManifestSha256": null
|
|
20
20
|
})
|
package/src/index.ts
CHANGED
package/src/runtime/bootstrap.ts
CHANGED
|
@@ -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
|
// ---------------------------------------------------------------------------
|