@glassly/engine 0.3.5-dev.768 → 0.3.5-dev.770
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/services/LocalMiniappRuntime.d.ts +4 -2
- package/build/services/LocalMiniappRuntime.d.ts.map +1 -1
- package/build/services/LocalMiniappRuntime.js +30 -9
- package/build/services/LocalMiniappRuntime.js.map +1 -1
- package/build/services/manifestActions.d.ts +1 -1
- package/build/services/manifestActions.d.ts.map +1 -1
- package/build/services/manifestActions.js +3 -2
- package/build/services/manifestActions.js.map +1 -1
- package/build/services/widgetPlacements.d.ts +8 -7
- package/build/services/widgetPlacements.d.ts.map +1 -1
- package/build/services/widgetPlacements.js +7 -6
- package/build/services/widgetPlacements.js.map +1 -1
- package/build/types/applet.d.ts +3 -1
- package/build/types/applet.d.ts.map +1 -1
- package/build/types/applet.js.map +1 -1
- package/package.json +7 -7
- package/src/generated/releaseMetadata.ts +3 -3
- package/src/services/LocalMiniappRuntime.ts +35 -9
- package/src/services/manifestActions.ts +10 -3
- package/src/services/widgetPlacements.ts +23 -9
- package/src/types/applet.ts +3 -1
|
@@ -32,7 +32,7 @@ export declare function normalizeManifestActions(raw: unknown): DeclaredAction[]
|
|
|
32
32
|
* Normalize manifest widgets for installed and dev-sideloaded bundles: an
|
|
33
33
|
* entry without an id, a name or a usable size is dropped, repeats of a
|
|
34
34
|
* size are folded, and a default size the widget does not offer becomes
|
|
35
|
-
* its first size.
|
|
35
|
+
* its first size. Only `expandable: true` makes a widget expandable.
|
|
36
36
|
*/
|
|
37
37
|
export declare function normalizeManifestWidgets(raw: unknown): DeclaredWidget[];
|
|
38
38
|
//# sourceMappingURL=manifestActions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifestActions.d.ts","sourceRoot":"","sources":["../../src/services/manifestActions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,cAAc,EAAE,cAAc,EAAqB,MAAM,iBAAiB,CAAA;AAEvF,gGAAgG;AAChG,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,cAAc,EAAE,CAAA;IAC1B,aAAa,CAAC,EAAE;QAAC,YAAY,EAAE,OAAO,CAAA;KAAC,CAAA;CACxC;AAED,8EAA8E;AAC9E,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,MAAM,CAAA;IACf,EAAE,EAAE,MAAM,CAAA;IACV,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACpC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACvC;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,aAAa,EAAE,EACrB,iBAAiB,EAAE,MAAM,EACzB,cAAc,EAAE,OAAO,GACtB,aAAa,EAAE,CAkBjB;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,OAAO,GAAG,cAAc,EAAE,CA0BvE;AAKD;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,OAAO,GAAG,cAAc,EAAE,
|
|
1
|
+
{"version":3,"file":"manifestActions.d.ts","sourceRoot":"","sources":["../../src/services/manifestActions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,cAAc,EAAE,cAAc,EAAqB,MAAM,iBAAiB,CAAA;AAEvF,gGAAgG;AAChG,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,cAAc,EAAE,CAAA;IAC1B,aAAa,CAAC,EAAE;QAAC,YAAY,EAAE,OAAO,CAAA;KAAC,CAAA;CACxC;AAED,8EAA8E;AAC9E,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,MAAM,CAAA;IACf,EAAE,EAAE,MAAM,CAAA;IACV,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACpC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACvC;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,aAAa,EAAE,EACrB,iBAAiB,EAAE,MAAM,EACzB,cAAc,EAAE,OAAO,GACtB,aAAa,EAAE,CAkBjB;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,OAAO,GAAG,cAAc,EAAE,CA0BvE;AAKD;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,OAAO,GAAG,cAAc,EAAE,CAwBvE"}
|
|
@@ -51,13 +51,13 @@ export function normalizeManifestActions(raw) {
|
|
|
51
51
|
}
|
|
52
52
|
return out;
|
|
53
53
|
}
|
|
54
|
-
const WIDGET_SIZES = ["XS", "SM", "MD", "LG"];
|
|
54
|
+
const WIDGET_SIZES = ["XS", "XSM", "SM", "MD", "LG"];
|
|
55
55
|
const isWidgetSize = (value) => WIDGET_SIZES.includes(value);
|
|
56
56
|
/**
|
|
57
57
|
* Normalize manifest widgets for installed and dev-sideloaded bundles: an
|
|
58
58
|
* entry without an id, a name or a usable size is dropped, repeats of a
|
|
59
59
|
* size are folded, and a default size the widget does not offer becomes
|
|
60
|
-
* its first size.
|
|
60
|
+
* its first size. Only `expandable: true` makes a widget expandable.
|
|
61
61
|
*/
|
|
62
62
|
export function normalizeManifestWidgets(raw) {
|
|
63
63
|
if (!Array.isArray(raw))
|
|
@@ -76,6 +76,7 @@ export function normalizeManifestWidgets(raw) {
|
|
|
76
76
|
name: w.name,
|
|
77
77
|
sizes,
|
|
78
78
|
defaultSize: isWidgetSize(w.defaultSize) && sizes.includes(w.defaultSize) ? w.defaultSize : sizes[0],
|
|
79
|
+
expandable: w.expandable === true,
|
|
79
80
|
});
|
|
80
81
|
}
|
|
81
82
|
return out;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifestActions.js","sourceRoot":"","sources":["../../src/services/manifestActions.ts"],"names":[],"mappings":"AAoBA;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAC/B,IAAqB,EACrB,iBAAyB,EACzB,cAAuB;IAEvB,MAAM,IAAI,GAAoB,EAAE,CAAA;IAChC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,CAAC,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,WAAW,KAAK,iBAAiB,IAAI,GAAG,CAAC,WAAW,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAAE,SAAQ;QAC7G,IAAI,GAAG,CAAC,aAAa,EAAE,YAAY,KAAK,KAAK;YAAE,SAAQ;QACvD,KAAK,MAAM,MAAM,IAAI,GAAG,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC;YACvC,IAAI,MAAM,CAAC,UAAU,KAAK,QAAQ,IAAI,CAAC,cAAc;gBAAE,SAAQ;YAC/D,IAAI,CAAC,IAAI,CAAC;gBACR,WAAW,EAAE,GAAG,CAAC,WAAW;gBAC5B,OAAO,EAAE,GAAG,CAAC,IAAI;gBACjB,EAAE,EAAE,MAAM,CAAC,EAAE;gBACb,WAAW,EAAE,MAAM,CAAC,WAAW;gBAC/B,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,EAAC,UAAU,EAAE,MAAM,CAAC,UAAU,EAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC7D,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,EAAC,YAAY,EAAE,MAAM,CAAC,YAAY,EAAC,CAAC,CAAC,CAAC,EAAE,CAAC;aACpE,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,wBAAwB,CAAC,GAAY;IACnD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,CAAA;IAClC,MAAM,GAAG,GAAqB,EAAE,CAAA;IAChC,KAAK,MAAM,CAAC,IAAI,GAMd,EAAE,CAAC;QACH,IAAI,CAAC,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,WAAW,KAAK,QAAQ,EAAE,CAAC;YACvE,GAAG,CAAC,IAAI,CAAC;gBACP,EAAE,EAAE,CAAC,CAAC,EAAE;gBACR,WAAW,EAAE,CAAC,CAAC,WAAW;gBAC1B,GAAG,CAAC,CAAC,CAAC,UAAU,IAAI,OAAO,CAAC,CAAC,UAAU,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC;oBAClF,CAAC,CAAC,EAAC,UAAU,EAAE,CAAC,CAAC,UAAqC,EAAC;oBACvD,CAAC,CAAC,EAAE,CAAC;gBACP,GAAG,CAAC,CAAC,CAAC,YAAY,IAAI,OAAO,CAAC,CAAC,YAAY,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC;oBACxF,CAAC,CAAC,EAAC,YAAY,EAAE,CAAC,CAAC,YAAuC,EAAC;oBAC3D,CAAC,CAAC,EAAE,CAAC;gBACP,yEAAyE;gBACzE,GAAG,CAAC,CAAC,CAAC,UAAU,KAAK,QAAQ,IAAI,CAAC,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAC,UAAU,EAAE,CAAC,CAAC,UAAU,EAAC,CAAC,CAAC,CAAC,EAAE,CAAC;aAC9F,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,MAAM,YAAY,GAAkC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"manifestActions.js","sourceRoot":"","sources":["../../src/services/manifestActions.ts"],"names":[],"mappings":"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","sourcesContent":["import type {DeclaredAction, DeclaredWidget, DeclaredWidgetSize} from \"../types/applet\"\n\n/** The subset of ClientApp that action-listing needs (structural, no cycle on applet types). */\nexport interface ActionListApp {\n packageName: string\n name: string\n actions?: DeclaredAction[]\n compatibility?: {isCompatible: boolean}\n}\n\n/** One row of `session.actions.list` — a flat, MCP-tool-shaped descriptor. */\nexport interface ActionListRow {\n packageName: string\n appName: string\n id: string\n description: string\n parameters?: Record<string, unknown>\n outputSchema?: Record<string, unknown>\n}\n\n/**\n * Project the installed-app set into the caller's invokable-action rows:\n * excludes the caller's own actions, incompatible apps, and placeholder\n * packages; `visibility: \"system\"` actions only surface for system callers.\n */\nexport function visibleActionRows(\n apps: ActionListApp[],\n callerPackageName: string,\n callerIsSystem: boolean,\n): ActionListRow[] {\n const rows: ActionListRow[] = []\n for (const app of apps) {\n if (!app.packageName || app.packageName === callerPackageName || app.packageName.includes(\"@empty\")) continue\n if (app.compatibility?.isCompatible === false) continue\n for (const action of app.actions ?? []) {\n if (action.visibility === \"system\" && !callerIsSystem) continue\n rows.push({\n packageName: app.packageName,\n appName: app.name,\n id: action.id,\n description: action.description,\n ...(action.parameters ? {parameters: action.parameters} : {}),\n ...(action.outputSchema ? {outputSchema: action.outputSchema} : {}),\n })\n }\n }\n return rows\n}\n\n/**\n * Normalize manifest actions defensively for installed and dev-sideloaded\n * bundles. Input and output schemas are passed through as opaque JSON Schema.\n */\nexport function normalizeManifestActions(raw: unknown): DeclaredAction[] {\n if (!Array.isArray(raw)) return []\n const out: DeclaredAction[] = []\n for (const a of raw as Array<{\n id?: unknown\n description?: unknown\n parameters?: unknown\n outputSchema?: unknown\n visibility?: unknown\n }>) {\n if (a && typeof a.id === \"string\" && typeof a.description === \"string\") {\n out.push({\n id: a.id,\n description: a.description,\n ...(a.parameters && typeof a.parameters === \"object\" && !Array.isArray(a.parameters)\n ? {parameters: a.parameters as Record<string, unknown>}\n : {}),\n ...(a.outputSchema && typeof a.outputSchema === \"object\" && !Array.isArray(a.outputSchema)\n ? {outputSchema: a.outputSchema as Record<string, unknown>}\n : {}),\n // Unknown/absent values fall back to the default (\"public\") by omission.\n ...(a.visibility === \"system\" || a.visibility === \"public\" ? {visibility: a.visibility} : {}),\n })\n }\n }\n return out\n}\n\nconst WIDGET_SIZES: readonly DeclaredWidgetSize[] = [\"XS\", \"XSM\", \"SM\", \"MD\", \"LG\"]\nconst isWidgetSize = (value: unknown): value is DeclaredWidgetSize => (WIDGET_SIZES as readonly unknown[]).includes(value)\n\n/**\n * Normalize manifest widgets for installed and dev-sideloaded bundles: an\n * entry without an id, a name or a usable size is dropped, repeats of a\n * size are folded, and a default size the widget does not offer becomes\n * its first size. Only `expandable: true` makes a widget expandable.\n */\nexport function normalizeManifestWidgets(raw: unknown): DeclaredWidget[] {\n if (!Array.isArray(raw)) return []\n const out: DeclaredWidget[] = []\n const seen = new Set<string>()\n for (const w of raw as Array<{\n id?: unknown\n name?: unknown\n sizes?: unknown\n defaultSize?: unknown\n expandable?: unknown\n }>) {\n if (!w || typeof w.id !== \"string\" || !w.id || typeof w.name !== \"string\" || !w.name || seen.has(w.id)) continue\n const sizes = Array.isArray(w.sizes) ? Array.from(new Set(w.sizes.filter(isWidgetSize))) : []\n if (sizes.length === 0) continue\n seen.add(w.id)\n out.push({\n id: w.id,\n name: w.name,\n sizes,\n defaultSize: isWidgetSize(w.defaultSize) && sizes.includes(w.defaultSize) ? w.defaultSize : sizes[0],\n expandable: w.expandable === true,\n })\n }\n return out\n}\n"]}
|
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
* Who placed which widget where: the pure bookkeeping behind the runtime's
|
|
3
3
|
* widget routing. A placement is one host's box for one provider widget;
|
|
4
4
|
* a provider is placed while any host holds one of its widgets. Frames are
|
|
5
|
-
* kept per widget so a host that places one again gets the last
|
|
6
|
-
* at once.
|
|
5
|
+
* kept per widget and view so a host that places one again gets the last
|
|
6
|
+
* card and expanded frames at once.
|
|
7
7
|
*/
|
|
8
|
+
export type WidgetView = "card" | "expanded";
|
|
8
9
|
export interface WidgetBox {
|
|
9
|
-
size: "XS" | "SM" | "MD" | "LG";
|
|
10
|
+
size: "XS" | "XSM" | "SM" | "MD" | "LG";
|
|
10
11
|
width: number;
|
|
11
12
|
height: number;
|
|
12
13
|
}
|
|
@@ -19,8 +20,8 @@ export interface Placement {
|
|
|
19
20
|
export interface WidgetPlacements {
|
|
20
21
|
/** Keyed by `${host}|${provider}/${widgetId}`. */
|
|
21
22
|
placements: ReadonlyMap<string, Placement>;
|
|
22
|
-
/** The latest frame per `${provider}/${widgetId}
|
|
23
|
-
frames: ReadonlyMap<string, unknown[]
|
|
23
|
+
/** The latest frame per `${provider}/${widgetId}` and view. */
|
|
24
|
+
frames: ReadonlyMap<string, Readonly<Partial<Record<WidgetView, unknown[]>>>>;
|
|
24
25
|
}
|
|
25
26
|
export declare const widgetKey: (providerPackageName: string, widgetId: string) => string;
|
|
26
27
|
export declare function emptyWidgetPlacements(): WidgetPlacements;
|
|
@@ -30,8 +31,8 @@ export declare function unplaceWidget(state: WidgetPlacements, hostPackageName:
|
|
|
30
31
|
export declare function dropHost(state: WidgetPlacements, hostPackageName: string): WidgetPlacements;
|
|
31
32
|
/** A provider went away: drop its placements, keep its frames for the placeholder. */
|
|
32
33
|
export declare function dropProvider(state: WidgetPlacements, providerPackageName: string): WidgetPlacements;
|
|
33
|
-
export declare function setFrame(state: WidgetPlacements, providerPackageName: string, widgetId: string, elements: unknown[]): WidgetPlacements;
|
|
34
|
-
export declare function frameOf(state: WidgetPlacements, providerPackageName: string, widgetId: string): unknown[] | null;
|
|
34
|
+
export declare function setFrame(state: WidgetPlacements, providerPackageName: string, widgetId: string, elements: unknown[], view?: WidgetView): WidgetPlacements;
|
|
35
|
+
export declare function frameOf(state: WidgetPlacements, providerPackageName: string, widgetId: string, view?: WidgetView): unknown[] | null;
|
|
35
36
|
export declare function placementOf(state: WidgetPlacements, hostPackageName: string, providerPackageName: string, widgetId: string): Placement | null;
|
|
36
37
|
/** Hosts holding this widget, each once. */
|
|
37
38
|
export declare function hostsOf(state: WidgetPlacements, providerPackageName: string, widgetId: string): string[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"widgetPlacements.d.ts","sourceRoot":"","sources":["../../src/services/widgetPlacements.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"widgetPlacements.d.ts","sourceRoot":"","sources":["../../src/services/widgetPlacements.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,UAAU,CAAA;AAE5C,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,IAAI,GAAG,KAAK,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;IACvC,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,SAAS;IACxB,eAAe,EAAE,MAAM,CAAA;IACvB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,QAAQ,EAAE,MAAM,CAAA;IAChB,GAAG,EAAE,SAAS,CAAA;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,kDAAkD;IAClD,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;IAC1C,+DAA+D;IAC/D,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;CAC9E;AAED,eAAO,MAAM,SAAS,GAAI,qBAAqB,MAAM,EAAE,UAAU,MAAM,KAAG,MAA8C,CAAA;AAIxH,wBAAgB,qBAAqB,IAAI,gBAAgB,CAExD;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,SAAS,GAAG,gBAAgB,CAI3F;AAED,wBAAgB,aAAa,CAC3B,KAAK,EAAE,gBAAgB,EACvB,eAAe,EAAE,MAAM,EACvB,mBAAmB,EAAE,MAAM,EAC3B,QAAQ,EAAE,MAAM,GACf,gBAAgB,CAMlB;AAED,mDAAmD;AACnD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,GAAG,gBAAgB,CAM3F;AAED,sFAAsF;AACtF,wBAAgB,YAAY,CAAC,KAAK,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,GAAG,gBAAgB,CAMnG;AAED,wBAAgB,QAAQ,CACtB,KAAK,EAAE,gBAAgB,EACvB,mBAAmB,EAAE,MAAM,EAC3B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,OAAO,EAAE,EACnB,IAAI,GAAE,UAAmB,GACxB,gBAAgB,CAKlB;AAED,wBAAgB,OAAO,CACrB,KAAK,EAAE,gBAAgB,EACvB,mBAAmB,EAAE,MAAM,EAC3B,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,UAAmB,GACxB,OAAO,EAAE,GAAG,IAAI,CAElB;AAED,wBAAgB,WAAW,CACzB,KAAK,EAAE,gBAAgB,EACvB,eAAe,EAAE,MAAM,EACvB,mBAAmB,EAAE,MAAM,EAC3B,QAAQ,EAAE,MAAM,GACf,SAAS,GAAG,IAAI,CAElB;AAED,4CAA4C;AAC5C,wBAAgB,OAAO,CAAC,KAAK,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAQxG;AAED,iDAAiD;AACjD,wBAAgB,eAAe,CAAC,KAAK,EAAE,gBAAgB,GAAG,GAAG,CAAC,MAAM,CAAC,CAIpE;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,GAAG,OAAO,CAK9F;AAED,0EAA0E;AAC1E,wBAAgB,YAAY,CAAC,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,GAAG,SAAS,EAAE,CAE1F"}
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Who placed which widget where: the pure bookkeeping behind the runtime's
|
|
3
3
|
* widget routing. A placement is one host's box for one provider widget;
|
|
4
4
|
* a provider is placed while any host holds one of its widgets. Frames are
|
|
5
|
-
* kept per widget so a host that places one again gets the last
|
|
6
|
-
* at once.
|
|
5
|
+
* kept per widget and view so a host that places one again gets the last
|
|
6
|
+
* card and expanded frames at once.
|
|
7
7
|
*/
|
|
8
8
|
export const widgetKey = (providerPackageName, widgetId) => `${providerPackageName}/${widgetId}`;
|
|
9
9
|
const placementKey = (hostPackageName, providerPackageName, widgetId) => `${hostPackageName}|${widgetKey(providerPackageName, widgetId)}`;
|
|
@@ -41,13 +41,14 @@ export function dropProvider(state, providerPackageName) {
|
|
|
41
41
|
}
|
|
42
42
|
return placements.size === state.placements.size ? state : { ...state, placements };
|
|
43
43
|
}
|
|
44
|
-
export function setFrame(state, providerPackageName, widgetId, elements) {
|
|
44
|
+
export function setFrame(state, providerPackageName, widgetId, elements, view = "card") {
|
|
45
|
+
const key = widgetKey(providerPackageName, widgetId);
|
|
45
46
|
const frames = new Map(state.frames);
|
|
46
|
-
frames.set(
|
|
47
|
+
frames.set(key, { ...state.frames.get(key), [view]: elements });
|
|
47
48
|
return { ...state, frames };
|
|
48
49
|
}
|
|
49
|
-
export function frameOf(state, providerPackageName, widgetId) {
|
|
50
|
-
return state.frames.get(widgetKey(providerPackageName, widgetId)) ?? null;
|
|
50
|
+
export function frameOf(state, providerPackageName, widgetId, view = "card") {
|
|
51
|
+
return state.frames.get(widgetKey(providerPackageName, widgetId))?.[view] ?? null;
|
|
51
52
|
}
|
|
52
53
|
export function placementOf(state, hostPackageName, providerPackageName, widgetId) {
|
|
53
54
|
return state.placements.get(placementKey(hostPackageName, providerPackageName, widgetId)) ?? null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"widgetPlacements.js","sourceRoot":"","sources":["../../src/services/widgetPlacements.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;
|
|
1
|
+
{"version":3,"file":"widgetPlacements.js","sourceRoot":"","sources":["../../src/services/widgetPlacements.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Who placed which widget where: the pure bookkeeping behind the runtime's\n * widget routing. A placement is one host's box for one provider widget;\n * a provider is placed while any host holds one of its widgets. Frames are\n * kept per widget and view so a host that places one again gets the last\n * card and expanded frames at once.\n */\n\nexport type WidgetView = \"card\" | \"expanded\"\n\nexport interface WidgetBox {\n size: \"XS\" | \"XSM\" | \"SM\" | \"MD\" | \"LG\"\n width: number\n height: number\n}\n\nexport interface Placement {\n hostPackageName: string\n providerPackageName: string\n widgetId: string\n box: WidgetBox\n}\n\nexport interface WidgetPlacements {\n /** Keyed by `${host}|${provider}/${widgetId}`. */\n placements: ReadonlyMap<string, Placement>\n /** The latest frame per `${provider}/${widgetId}` and view. */\n frames: ReadonlyMap<string, Readonly<Partial<Record<WidgetView, unknown[]>>>>\n}\n\nexport const widgetKey = (providerPackageName: string, widgetId: string): string => `${providerPackageName}/${widgetId}`\nconst placementKey = (hostPackageName: string, providerPackageName: string, widgetId: string): string =>\n `${hostPackageName}|${widgetKey(providerPackageName, widgetId)}`\n\nexport function emptyWidgetPlacements(): WidgetPlacements {\n return {placements: new Map(), frames: new Map()}\n}\n\nexport function placeWidget(state: WidgetPlacements, placement: Placement): WidgetPlacements {\n const placements = new Map(state.placements)\n placements.set(placementKey(placement.hostPackageName, placement.providerPackageName, placement.widgetId), placement)\n return {...state, placements}\n}\n\nexport function unplaceWidget(\n state: WidgetPlacements,\n hostPackageName: string,\n providerPackageName: string,\n widgetId: string,\n): WidgetPlacements {\n const key = placementKey(hostPackageName, providerPackageName, widgetId)\n if (!state.placements.has(key)) return state\n const placements = new Map(state.placements)\n placements.delete(key)\n return {...state, placements}\n}\n\n/** A host went away: drop everything it placed. */\nexport function dropHost(state: WidgetPlacements, hostPackageName: string): WidgetPlacements {\n const placements = new Map(state.placements)\n for (const [key, placement] of state.placements) {\n if (placement.hostPackageName === hostPackageName) placements.delete(key)\n }\n return placements.size === state.placements.size ? state : {...state, placements}\n}\n\n/** A provider went away: drop its placements, keep its frames for the placeholder. */\nexport function dropProvider(state: WidgetPlacements, providerPackageName: string): WidgetPlacements {\n const placements = new Map(state.placements)\n for (const [key, placement] of state.placements) {\n if (placement.providerPackageName === providerPackageName) placements.delete(key)\n }\n return placements.size === state.placements.size ? state : {...state, placements}\n}\n\nexport function setFrame(\n state: WidgetPlacements,\n providerPackageName: string,\n widgetId: string,\n elements: unknown[],\n view: WidgetView = \"card\",\n): WidgetPlacements {\n const key = widgetKey(providerPackageName, widgetId)\n const frames = new Map(state.frames)\n frames.set(key, {...state.frames.get(key), [view]: elements})\n return {...state, frames}\n}\n\nexport function frameOf(\n state: WidgetPlacements,\n providerPackageName: string,\n widgetId: string,\n view: WidgetView = \"card\",\n): unknown[] | null {\n return state.frames.get(widgetKey(providerPackageName, widgetId))?.[view] ?? null\n}\n\nexport function placementOf(\n state: WidgetPlacements,\n hostPackageName: string,\n providerPackageName: string,\n widgetId: string,\n): Placement | null {\n return state.placements.get(placementKey(hostPackageName, providerPackageName, widgetId)) ?? null\n}\n\n/** Hosts holding this widget, each once. */\nexport function hostsOf(state: WidgetPlacements, providerPackageName: string, widgetId: string): string[] {\n const hosts = new Set<string>()\n for (const placement of state.placements.values()) {\n if (placement.providerPackageName === providerPackageName && placement.widgetId === widgetId) {\n hosts.add(placement.hostPackageName)\n }\n }\n return Array.from(hosts)\n}\n\n/** Providers with at least one widget placed. */\nexport function placedProviders(state: WidgetPlacements): Set<string> {\n const providers = new Set<string>()\n for (const placement of state.placements.values()) providers.add(placement.providerPackageName)\n return providers\n}\n\nexport function isProviderPlaced(state: WidgetPlacements, providerPackageName: string): boolean {\n for (const placement of state.placements.values()) {\n if (placement.providerPackageName === providerPackageName) return true\n }\n return false\n}\n\n/** The placements a host holds on a provider, for re-delivering boxes. */\nexport function placementsBy(state: WidgetPlacements, hostPackageName: string): Placement[] {\n return Array.from(state.placements.values()).filter((placement) => placement.hostPackageName === hostPackageName)\n}\n"]}
|
package/build/types/applet.d.ts
CHANGED
|
@@ -81,13 +81,15 @@ export interface DeclaredAction {
|
|
|
81
81
|
*/
|
|
82
82
|
visibility?: "public" | "system";
|
|
83
83
|
}
|
|
84
|
-
export type DeclaredWidgetSize = "XS" | "SM" | "MD" | "LG";
|
|
84
|
+
export type DeclaredWidgetSize = "XS" | "XSM" | "SM" | "MD" | "LG";
|
|
85
85
|
/** A dashboard widget a miniapp declares in `miniapp.json` and serves through `session.widgets`. */
|
|
86
86
|
export interface DeclaredWidget {
|
|
87
87
|
id: string;
|
|
88
88
|
name: string;
|
|
89
89
|
sizes: DeclaredWidgetSize[];
|
|
90
90
|
defaultSize: DeclaredWidgetSize;
|
|
91
|
+
/** A tap on the selected widget expands it to the full screen instead of activating the card. */
|
|
92
|
+
expandable: boolean;
|
|
91
93
|
}
|
|
92
94
|
export interface ClientApp extends AppletInterface {
|
|
93
95
|
offline: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"applet.d.ts","sourceRoot":"","sources":["../../src/types/applet.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,sBAAsB,EAAC,MAAM,2BAA2B,CAAA;AACrE,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,OAAO,CAAA;AACpC;;GAEG;AAEH,OAAO,EAAC,mBAAmB,EAAC,MAAM,YAAY,CAAA;AAE9C,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,4BAA4B,CAAA;AAEnE;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,YAAY,GAAG,WAAW,CAAA;AAEhE;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG,KAAK,GAAG,sBAAsB,CAAA;AAE9D;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,iBAAiB,CAAA;IACvB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;IACf,aAAa,CAAC,EAAE,SAAS,CAAA;IACzB,IAAI,EAAE,UAAU,CAAA;IAChB,WAAW,EAAE,gBAAgB,EAAE,CAAA;IAC/B,OAAO,EAAE,OAAO,CAAA;IAChB;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,OAAO,EAAE,OAAO,CAAA;IAChB,oBAAoB,EAAE,mBAAmB,EAAE,CAAA;IAC3C,iDAAiD;IACjD,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,uFAAuF;IACvF,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED;;;;;;;;GAQG;AACH;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAA;IACV,WAAW,EAAE,MAAM,CAAA;IACnB,4DAA4D;IAC5D,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACpC,iEAAiE;IACjE,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACtC;;;OAGG;IACH,UAAU,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAA;CACjC;AAED,MAAM,MAAM,kBAAkB,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"applet.d.ts","sourceRoot":"","sources":["../../src/types/applet.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"applet.js","sourceRoot":"","sources":["../../src/types/applet.ts"],"names":[],"mappings":"","sourcesContent":["import type {ManifestPermissionType} from \"@glassly/miniapp/manifest\"\nimport type {ReactNode} from \"react\"\n/**\n * App and miniapp types owned by @glassly/engine.\n */\n\nimport {HardwareRequirement} from \"./hardware\"\n\nimport type {CompatibilityResult} from \"../utils/hardware/hardware\"\n\n/**\n * App execution model types\n */\nexport type AppletType = \"standard\" | \"background\" | \"dashboard\"\n\n/**\n * Permission types that apps can request: the manifest vocabulary from the\n * SDK (the single source the CLI validator reads too) plus the host-only ALL.\n */\nexport type AppPermissionType = \"ALL\" | ManifestPermissionType\n\n/**\n * Permission object with type and description\n */\nexport interface AppletPermission {\n type: AppPermissionType\n description?: string\n required?: boolean\n}\n\n/**\n * Minimal app interface for client home screen display\n * Optimized for fast rendering - only essential fields\n *\n * This is the client-facing interface used by mobile apps.\n * Internal cloud services use AppI from models (more fields).\n */\nexport interface AppletInterface {\n packageName: string\n name: string\n webviewUrl: string\n logoUrl: string\n iconComponent?: ReactNode\n type: AppletType\n permissions: AppletPermission[]\n running: boolean\n /**\n * True while this app's UI WebView is mounted in the Compositor overlay.\n * At most one app is foregrounded at a time. Distinct from `running`:\n * a foregrounded app is always running, but a running app may be\n * backgrounded (JSContext alive, WebView torn down). Normalized to a\n * concrete boolean by the apps store's projectApps; literal call sites\n * may omit it.\n */\n foregrounded?: boolean\n healthy: boolean\n hardwareRequirements: HardwareRequirement[]\n /** ISO date string when the app was installed */\n installedDate?: string\n /** ISO date string when the app was last run. Undefined if never run (app is \"new\") */\n lastActiveAt?: string\n}\n\n/**\n * Runtime applet shape used by the engine apps store and OEM hosts.\n *\n * Extends AppletInterface with the host-side fields the manager / OEM tracks\n * outside the manifest: offline routing, hardware compatibility result,\n * loading/hidden/local flags, lifecycle hooks, screenshot, and the\n * dev-miniapp escape hatches (`devUrl` / `isMiniappDev`) that surface a\n * `glassly dev` snapshot.\n */\n/**\n * A manifest-declared action a miniapp exposes for other miniapps to invoke\n * via `session.actions`. Populated from `miniapp.json`'s `actions` field.\n * Shape maps 1:1 onto an MCP tool (id→name, description, parameters→inputSchema).\n */\nexport interface DeclaredAction {\n id: string\n description: string\n /** JSON-Schema input descriptor (MCP-compatible subset). */\n parameters?: Record<string, unknown>\n /** JSON-Schema descriptor for the action's structured result. */\n outputSchema?: Record<string, unknown>\n /**\n * Who may invoke the action: \"public\" (default — any installed miniapp) or\n * \"system\" (system miniapps such as the AI assistant only).\n */\n visibility?: \"public\" | \"system\"\n}\n\nexport type DeclaredWidgetSize = \"XS\" | \"SM\" | \"MD\" | \"LG\"\n\n/** A dashboard widget a miniapp declares in `miniapp.json` and serves through `session.widgets`. */\nexport interface DeclaredWidget {\n id: string\n name: string\n sizes: DeclaredWidgetSize[]\n defaultSize: DeclaredWidgetSize\n}\n\nexport interface ClientApp extends AppletInterface {\n offline: boolean\n offlineRoute: string\n compatibility?: CompatibilityResult\n loading: boolean\n local: boolean\n hidden: boolean\n /**\n * Always On miniapp: the host starts it at launch and it only stops from\n * the app switcher's Always On pill; its card cannot be swiped away and\n * the capsule close minimizes it. Manifest `alwaysOn` gives the default;\n * the wearer's choice persists beside the hidden flag.\n */\n alwaysOn?: boolean\n /** Running, but paused while the paired glasses are disconnected (MiniappPauseCoordinator). */\n paused?: boolean\n onStart?: () => void\n onStop?: () => void\n screenshot?: string\n runtimePermissions?: string[]\n declaredPermissions?: string[]\n version?: string\n /** Manifest `description`: the paragraph the store and the info page show. */\n description?: string\n /** Manifest `tagline`: one line under the name. */\n tagline?: string\n /** Manifest `tags`: lowercase store tag slugs. */\n tags?: string[]\n needsPcm?: boolean\n needsTranscript?: boolean\n devUrl?: string\n devPort?: number\n isMiniappDev?: boolean\n /** Manifest-declared actions (for session.miniapps.list + invoke gating). */\n actions?: DeclaredAction[]\n /** Manifest-declared dashboard widgets. */\n widgets?: DeclaredWidget[]\n /**\n * Running only because a host placed one of its widgets: no card in the\n * app switcher, no frame of its own on the glasses. Opening the app from\n * the home screen promotes it to a normal run.\n */\n widgetOnly?: boolean\n}\n"]}
|
|
1
|
+
{"version":3,"file":"applet.js","sourceRoot":"","sources":["../../src/types/applet.ts"],"names":[],"mappings":"","sourcesContent":["import type {ManifestPermissionType} from \"@glassly/miniapp/manifest\"\nimport type {ReactNode} from \"react\"\n/**\n * App and miniapp types owned by @glassly/engine.\n */\n\nimport {HardwareRequirement} from \"./hardware\"\n\nimport type {CompatibilityResult} from \"../utils/hardware/hardware\"\n\n/**\n * App execution model types\n */\nexport type AppletType = \"standard\" | \"background\" | \"dashboard\"\n\n/**\n * Permission types that apps can request: the manifest vocabulary from the\n * SDK (the single source the CLI validator reads too) plus the host-only ALL.\n */\nexport type AppPermissionType = \"ALL\" | ManifestPermissionType\n\n/**\n * Permission object with type and description\n */\nexport interface AppletPermission {\n type: AppPermissionType\n description?: string\n required?: boolean\n}\n\n/**\n * Minimal app interface for client home screen display\n * Optimized for fast rendering - only essential fields\n *\n * This is the client-facing interface used by mobile apps.\n * Internal cloud services use AppI from models (more fields).\n */\nexport interface AppletInterface {\n packageName: string\n name: string\n webviewUrl: string\n logoUrl: string\n iconComponent?: ReactNode\n type: AppletType\n permissions: AppletPermission[]\n running: boolean\n /**\n * True while this app's UI WebView is mounted in the Compositor overlay.\n * At most one app is foregrounded at a time. Distinct from `running`:\n * a foregrounded app is always running, but a running app may be\n * backgrounded (JSContext alive, WebView torn down). Normalized to a\n * concrete boolean by the apps store's projectApps; literal call sites\n * may omit it.\n */\n foregrounded?: boolean\n healthy: boolean\n hardwareRequirements: HardwareRequirement[]\n /** ISO date string when the app was installed */\n installedDate?: string\n /** ISO date string when the app was last run. Undefined if never run (app is \"new\") */\n lastActiveAt?: string\n}\n\n/**\n * Runtime applet shape used by the engine apps store and OEM hosts.\n *\n * Extends AppletInterface with the host-side fields the manager / OEM tracks\n * outside the manifest: offline routing, hardware compatibility result,\n * loading/hidden/local flags, lifecycle hooks, screenshot, and the\n * dev-miniapp escape hatches (`devUrl` / `isMiniappDev`) that surface a\n * `glassly dev` snapshot.\n */\n/**\n * A manifest-declared action a miniapp exposes for other miniapps to invoke\n * via `session.actions`. Populated from `miniapp.json`'s `actions` field.\n * Shape maps 1:1 onto an MCP tool (id→name, description, parameters→inputSchema).\n */\nexport interface DeclaredAction {\n id: string\n description: string\n /** JSON-Schema input descriptor (MCP-compatible subset). */\n parameters?: Record<string, unknown>\n /** JSON-Schema descriptor for the action's structured result. */\n outputSchema?: Record<string, unknown>\n /**\n * Who may invoke the action: \"public\" (default — any installed miniapp) or\n * \"system\" (system miniapps such as the AI assistant only).\n */\n visibility?: \"public\" | \"system\"\n}\n\nexport type DeclaredWidgetSize = \"XS\" | \"XSM\" | \"SM\" | \"MD\" | \"LG\"\n\n/** A dashboard widget a miniapp declares in `miniapp.json` and serves through `session.widgets`. */\nexport interface DeclaredWidget {\n id: string\n name: string\n sizes: DeclaredWidgetSize[]\n defaultSize: DeclaredWidgetSize\n /** A tap on the selected widget expands it to the full screen instead of activating the card. */\n expandable: boolean\n}\n\nexport interface ClientApp extends AppletInterface {\n offline: boolean\n offlineRoute: string\n compatibility?: CompatibilityResult\n loading: boolean\n local: boolean\n hidden: boolean\n /**\n * Always On miniapp: the host starts it at launch and it only stops from\n * the app switcher's Always On pill; its card cannot be swiped away and\n * the capsule close minimizes it. Manifest `alwaysOn` gives the default;\n * the wearer's choice persists beside the hidden flag.\n */\n alwaysOn?: boolean\n /** Running, but paused while the paired glasses are disconnected (MiniappPauseCoordinator). */\n paused?: boolean\n onStart?: () => void\n onStop?: () => void\n screenshot?: string\n runtimePermissions?: string[]\n declaredPermissions?: string[]\n version?: string\n /** Manifest `description`: the paragraph the store and the info page show. */\n description?: string\n /** Manifest `tagline`: one line under the name. */\n tagline?: string\n /** Manifest `tags`: lowercase store tag slugs. */\n tags?: string[]\n needsPcm?: boolean\n needsTranscript?: boolean\n devUrl?: string\n devPort?: number\n isMiniappDev?: boolean\n /** Manifest-declared actions (for session.miniapps.list + invoke gating). */\n actions?: DeclaredAction[]\n /** Manifest-declared dashboard widgets. */\n widgets?: DeclaredWidget[]\n /**\n * Running only because a host placed one of its widgets: no card in the\n * app switcher, no frame of its own on the glasses. Opening the app from\n * the home screen promotes it to a normal run.\n */\n widgetOnly?: boolean\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@glassly/engine",
|
|
3
|
-
"version": "0.3.5-dev.
|
|
3
|
+
"version": "0.3.5-dev.770",
|
|
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.5-dev.
|
|
101
|
-
"@glassly/cloud-client": "0.3.5-dev.
|
|
102
|
-
"@glassly/cloud-protocol": "0.3.5-dev.
|
|
103
|
-
"@glassly/crust": "0.3.5-dev.
|
|
104
|
-
"@glassly/miniapp": "0.3.5-dev.
|
|
100
|
+
"@glassly/bluetooth-sdk": "0.3.5-dev.770",
|
|
101
|
+
"@glassly/cloud-client": "0.3.5-dev.770",
|
|
102
|
+
"@glassly/cloud-protocol": "0.3.5-dev.770",
|
|
103
|
+
"@glassly/crust": "0.3.5-dev.770",
|
|
104
|
+
"@glassly/miniapp": "0.3.5-dev.770",
|
|
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.5-dev.
|
|
110
|
+
"@glassly/llm-providers": "0.3.5-dev.770",
|
|
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.5",
|
|
15
|
-
"releaseIdentity": "0.3.5-dev.
|
|
16
|
-
"releaseSetId": "glassly-0.3.5-dev.
|
|
17
|
-
"sourceCommit": "
|
|
15
|
+
"releaseIdentity": "0.3.5-dev.770",
|
|
16
|
+
"releaseSetId": "glassly-0.3.5-dev.770",
|
|
17
|
+
"sourceCommit": "ef87aadc6750acdb633e753a9d5fd5e2de85f1fd",
|
|
18
18
|
"otaManifestUrl": null,
|
|
19
19
|
"otaManifestSha256": null
|
|
20
20
|
})
|
|
@@ -109,6 +109,7 @@ import {
|
|
|
109
109
|
unplaceWidget,
|
|
110
110
|
type WidgetBox,
|
|
111
111
|
type WidgetPlacements,
|
|
112
|
+
type WidgetView,
|
|
112
113
|
} from "./widgetPlacements"
|
|
113
114
|
import {
|
|
114
115
|
activeDashboard,
|
|
@@ -6298,6 +6299,8 @@ class LocalMiniappRuntime {
|
|
|
6298
6299
|
private widgetCallSeq = 0
|
|
6299
6300
|
/** Elements per widget frame; a card is small, and the link is slow. */
|
|
6300
6301
|
private static readonly WIDGET_FRAME_ELEMENT_CAP = 64
|
|
6302
|
+
/** Elements per expanded widget frame: the full screen, on the same link. */
|
|
6303
|
+
private static readonly WIDGET_EXPANDED_FRAME_ELEMENT_CAP = 128
|
|
6301
6304
|
|
|
6302
6305
|
private requireWidgetHost(packageName: string, requestId: string | undefined, op: string): boolean {
|
|
6303
6306
|
return this.requirePermission(packageName, requestId, "HOST_WIDGETS", `to ${op} widgets`)
|
|
@@ -6346,6 +6349,7 @@ class LocalMiniappRuntime {
|
|
|
6346
6349
|
name: widget.name,
|
|
6347
6350
|
sizes: widget.sizes,
|
|
6348
6351
|
defaultSize: widget.defaultSize,
|
|
6352
|
+
expandable: widget.expandable,
|
|
6349
6353
|
running: app.running,
|
|
6350
6354
|
compatible: app.compatibility?.isCompatible !== false,
|
|
6351
6355
|
})
|
|
@@ -6357,7 +6361,8 @@ class LocalMiniappRuntime {
|
|
|
6357
6361
|
private parseWidgetBox(raw: unknown): WidgetBox | null {
|
|
6358
6362
|
const box = raw as {size?: unknown; width?: unknown; height?: unknown} | null
|
|
6359
6363
|
if (!box || typeof box !== "object") return null
|
|
6360
|
-
if (box.size !== "XS" && box.size !== "SM" && box.size !== "MD" && box.size !== "LG")
|
|
6364
|
+
if (box.size !== "XS" && box.size !== "XSM" && box.size !== "SM" && box.size !== "MD" && box.size !== "LG")
|
|
6365
|
+
return null
|
|
6361
6366
|
const width = Number(box.width)
|
|
6362
6367
|
const height = Number(box.height)
|
|
6363
6368
|
if (!(width > 0) || !(height > 0)) return null
|
|
@@ -6383,7 +6388,7 @@ class LocalMiniappRuntime {
|
|
|
6383
6388
|
/**
|
|
6384
6389
|
* session.widgets.place: record the host's box, wake the provider in widget
|
|
6385
6390
|
* mode when it is not running, hand it the box, and answer with the last
|
|
6386
|
-
*
|
|
6391
|
+
* card and expanded frames the provider pushed for the widget.
|
|
6387
6392
|
*/
|
|
6388
6393
|
private async handleWidgetPlace(
|
|
6389
6394
|
hostPackageName: string,
|
|
@@ -6432,7 +6437,10 @@ class LocalMiniappRuntime {
|
|
|
6432
6437
|
if (placementOf(this.widgetPlacements, hostPackageName, provider, widgetId) && this.connectedApps.has(provider)) {
|
|
6433
6438
|
this.sendWidgetCall(provider, widgetId, {kind: "box", box})
|
|
6434
6439
|
}
|
|
6435
|
-
this.sendResult(hostPackageName, requestId, true, {
|
|
6440
|
+
this.sendResult(hostPackageName, requestId, true, {
|
|
6441
|
+
frame: widgetFrameOf(this.widgetPlacements, provider, widgetId),
|
|
6442
|
+
expandedFrame: widgetFrameOf(this.widgetPlacements, provider, widgetId, "expanded"),
|
|
6443
|
+
})
|
|
6436
6444
|
}
|
|
6437
6445
|
|
|
6438
6446
|
private async handleWidgetUnplace(
|
|
@@ -6550,20 +6558,38 @@ class LocalMiniappRuntime {
|
|
|
6550
6558
|
}
|
|
6551
6559
|
}
|
|
6552
6560
|
|
|
6553
|
-
/** Provider → host, one-shot: cache the frame and push it to every host holding the widget. */
|
|
6561
|
+
/** Provider → host, one-shot: cache the frame for its view and push it to every host holding the widget. */
|
|
6554
6562
|
private handleWidgetUpdate(providerPackageName: string, payload: Record<string, unknown>): void {
|
|
6555
6563
|
const widgetId = payload.widgetId as string | undefined
|
|
6556
6564
|
const elements = payload.elements
|
|
6557
6565
|
if (!widgetId || !Array.isArray(elements)) return
|
|
6558
6566
|
const app = this.interopApps().find((a) => a.packageName === providerPackageName)
|
|
6559
|
-
|
|
6560
|
-
if (
|
|
6561
|
-
|
|
6567
|
+
const widget = app ? this.declaredWidget(app, widgetId) : undefined
|
|
6568
|
+
if (!widget) return
|
|
6569
|
+
const view: WidgetView = payload.view === "expanded" ? "expanded" : "card"
|
|
6570
|
+
if (view === "expanded" && !widget.expandable) {
|
|
6571
|
+
console.warn(
|
|
6572
|
+
`${LOG_TAG}: dropping expanded frame from ${providerPackageName}/${widgetId}: not declared expandable`,
|
|
6573
|
+
)
|
|
6562
6574
|
return
|
|
6563
6575
|
}
|
|
6564
|
-
|
|
6576
|
+
const cap =
|
|
6577
|
+
view === "expanded"
|
|
6578
|
+
? LocalMiniappRuntime.WIDGET_EXPANDED_FRAME_ELEMENT_CAP
|
|
6579
|
+
: LocalMiniappRuntime.WIDGET_FRAME_ELEMENT_CAP
|
|
6580
|
+
if (elements.length > cap || this.actionPayloadTooLarge(elements)) {
|
|
6581
|
+
console.warn(`${LOG_TAG}: dropping oversized ${view} widget frame from ${providerPackageName}/${widgetId}`)
|
|
6582
|
+
return
|
|
6583
|
+
}
|
|
6584
|
+
this.widgetPlacements = setWidgetFrame(this.widgetPlacements, providerPackageName, widgetId, elements, view)
|
|
6565
6585
|
for (const host of widgetHostsOf(this.widgetPlacements, providerPackageName, widgetId)) {
|
|
6566
|
-
this.sendToMiniapp(host, {
|
|
6586
|
+
this.sendToMiniapp(host, {
|
|
6587
|
+
type: MiniappResponseType.WIDGET_FRAME,
|
|
6588
|
+
packageName: providerPackageName,
|
|
6589
|
+
widgetId,
|
|
6590
|
+
elements,
|
|
6591
|
+
...(view === "expanded" ? {view} : {}),
|
|
6592
|
+
})
|
|
6567
6593
|
}
|
|
6568
6594
|
}
|
|
6569
6595
|
|
|
@@ -79,20 +79,26 @@ export function normalizeManifestActions(raw: unknown): DeclaredAction[] {
|
|
|
79
79
|
return out
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
const WIDGET_SIZES: readonly DeclaredWidgetSize[] = ["XS", "SM", "MD", "LG"]
|
|
82
|
+
const WIDGET_SIZES: readonly DeclaredWidgetSize[] = ["XS", "XSM", "SM", "MD", "LG"]
|
|
83
83
|
const isWidgetSize = (value: unknown): value is DeclaredWidgetSize => (WIDGET_SIZES as readonly unknown[]).includes(value)
|
|
84
84
|
|
|
85
85
|
/**
|
|
86
86
|
* Normalize manifest widgets for installed and dev-sideloaded bundles: an
|
|
87
87
|
* entry without an id, a name or a usable size is dropped, repeats of a
|
|
88
88
|
* size are folded, and a default size the widget does not offer becomes
|
|
89
|
-
* its first size.
|
|
89
|
+
* its first size. Only `expandable: true` makes a widget expandable.
|
|
90
90
|
*/
|
|
91
91
|
export function normalizeManifestWidgets(raw: unknown): DeclaredWidget[] {
|
|
92
92
|
if (!Array.isArray(raw)) return []
|
|
93
93
|
const out: DeclaredWidget[] = []
|
|
94
94
|
const seen = new Set<string>()
|
|
95
|
-
for (const w of raw as Array<{
|
|
95
|
+
for (const w of raw as Array<{
|
|
96
|
+
id?: unknown
|
|
97
|
+
name?: unknown
|
|
98
|
+
sizes?: unknown
|
|
99
|
+
defaultSize?: unknown
|
|
100
|
+
expandable?: unknown
|
|
101
|
+
}>) {
|
|
96
102
|
if (!w || typeof w.id !== "string" || !w.id || typeof w.name !== "string" || !w.name || seen.has(w.id)) continue
|
|
97
103
|
const sizes = Array.isArray(w.sizes) ? Array.from(new Set(w.sizes.filter(isWidgetSize))) : []
|
|
98
104
|
if (sizes.length === 0) continue
|
|
@@ -102,6 +108,7 @@ export function normalizeManifestWidgets(raw: unknown): DeclaredWidget[] {
|
|
|
102
108
|
name: w.name,
|
|
103
109
|
sizes,
|
|
104
110
|
defaultSize: isWidgetSize(w.defaultSize) && sizes.includes(w.defaultSize) ? w.defaultSize : sizes[0],
|
|
111
|
+
expandable: w.expandable === true,
|
|
105
112
|
})
|
|
106
113
|
}
|
|
107
114
|
return out
|
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
* Who placed which widget where: the pure bookkeeping behind the runtime's
|
|
3
3
|
* widget routing. A placement is one host's box for one provider widget;
|
|
4
4
|
* a provider is placed while any host holds one of its widgets. Frames are
|
|
5
|
-
* kept per widget so a host that places one again gets the last
|
|
6
|
-
* at once.
|
|
5
|
+
* kept per widget and view so a host that places one again gets the last
|
|
6
|
+
* card and expanded frames at once.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
export type WidgetView = "card" | "expanded"
|
|
10
|
+
|
|
9
11
|
export interface WidgetBox {
|
|
10
|
-
size: "XS" | "SM" | "MD" | "LG"
|
|
12
|
+
size: "XS" | "XSM" | "SM" | "MD" | "LG"
|
|
11
13
|
width: number
|
|
12
14
|
height: number
|
|
13
15
|
}
|
|
@@ -22,8 +24,8 @@ export interface Placement {
|
|
|
22
24
|
export interface WidgetPlacements {
|
|
23
25
|
/** Keyed by `${host}|${provider}/${widgetId}`. */
|
|
24
26
|
placements: ReadonlyMap<string, Placement>
|
|
25
|
-
/** The latest frame per `${provider}/${widgetId}
|
|
26
|
-
frames: ReadonlyMap<string, unknown[]
|
|
27
|
+
/** The latest frame per `${provider}/${widgetId}` and view. */
|
|
28
|
+
frames: ReadonlyMap<string, Readonly<Partial<Record<WidgetView, unknown[]>>>>
|
|
27
29
|
}
|
|
28
30
|
|
|
29
31
|
export const widgetKey = (providerPackageName: string, widgetId: string): string => `${providerPackageName}/${widgetId}`
|
|
@@ -71,14 +73,26 @@ export function dropProvider(state: WidgetPlacements, providerPackageName: strin
|
|
|
71
73
|
return placements.size === state.placements.size ? state : {...state, placements}
|
|
72
74
|
}
|
|
73
75
|
|
|
74
|
-
export function setFrame(
|
|
76
|
+
export function setFrame(
|
|
77
|
+
state: WidgetPlacements,
|
|
78
|
+
providerPackageName: string,
|
|
79
|
+
widgetId: string,
|
|
80
|
+
elements: unknown[],
|
|
81
|
+
view: WidgetView = "card",
|
|
82
|
+
): WidgetPlacements {
|
|
83
|
+
const key = widgetKey(providerPackageName, widgetId)
|
|
75
84
|
const frames = new Map(state.frames)
|
|
76
|
-
frames.set(
|
|
85
|
+
frames.set(key, {...state.frames.get(key), [view]: elements})
|
|
77
86
|
return {...state, frames}
|
|
78
87
|
}
|
|
79
88
|
|
|
80
|
-
export function frameOf(
|
|
81
|
-
|
|
89
|
+
export function frameOf(
|
|
90
|
+
state: WidgetPlacements,
|
|
91
|
+
providerPackageName: string,
|
|
92
|
+
widgetId: string,
|
|
93
|
+
view: WidgetView = "card",
|
|
94
|
+
): unknown[] | null {
|
|
95
|
+
return state.frames.get(widgetKey(providerPackageName, widgetId))?.[view] ?? null
|
|
82
96
|
}
|
|
83
97
|
|
|
84
98
|
export function placementOf(
|
package/src/types/applet.ts
CHANGED
|
@@ -89,7 +89,7 @@ export interface DeclaredAction {
|
|
|
89
89
|
visibility?: "public" | "system"
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
export type DeclaredWidgetSize = "XS" | "SM" | "MD" | "LG"
|
|
92
|
+
export type DeclaredWidgetSize = "XS" | "XSM" | "SM" | "MD" | "LG"
|
|
93
93
|
|
|
94
94
|
/** A dashboard widget a miniapp declares in `miniapp.json` and serves through `session.widgets`. */
|
|
95
95
|
export interface DeclaredWidget {
|
|
@@ -97,6 +97,8 @@ export interface DeclaredWidget {
|
|
|
97
97
|
name: string
|
|
98
98
|
sizes: DeclaredWidgetSize[]
|
|
99
99
|
defaultSize: DeclaredWidgetSize
|
|
100
|
+
/** A tap on the selected widget expands it to the full screen instead of activating the card. */
|
|
101
|
+
expandable: boolean
|
|
100
102
|
}
|
|
101
103
|
|
|
102
104
|
export interface ClientApp extends AppletInterface {
|