@datalayer/core 1.2.14 → 1.2.15

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.
@@ -2,6 +2,7 @@ export * from './useAuthorization';
2
2
  export * from './useBackdrop';
3
3
  export * from './useBackdropJupyterLab';
4
4
  export * from './useCache';
5
+ export * from './libraryApp';
5
6
  export * from './useContainsFocus';
6
7
  export * from './useContents';
7
8
  export * from './useDatalayer';
@@ -6,6 +6,7 @@ export * from './useAuthorization.js';
6
6
  export * from './useBackdrop.js';
7
7
  export * from './useBackdropJupyterLab.js';
8
8
  export * from './useCache.js';
9
+ export * from './libraryApp.js';
9
10
  export * from './useContainsFocus.js';
10
11
  export * from './useContents.js';
11
12
  export * from './useDatalayer.js';
@@ -0,0 +1,37 @@
1
+ /**
2
+ * What the Library says of a published application beyond any item's fields:
3
+ * its face, its kind and whether it runs live.
4
+ *
5
+ * Spacer keeps them beside the app's item, from its Appspec, and the Library
6
+ * projection carries them: `face_s` (the JSON of its `id`, `emoji`, `avatar`
7
+ * and `banner`, each only when set), `app_kind_s` and `runs_live_b` — an app
8
+ * that runs live can be tried before it is cloned: not a decision, and naming
9
+ * the agent it runs on.
10
+ *
11
+ * @module hooks/libraryApp
12
+ */
13
+ /** The kinds of application. */
14
+ export declare const LIBRARY_APP_KINDS: readonly ["decision", "chat", "widget", "worker"];
15
+ export type LibraryAppKind = (typeof LIBRARY_APP_KINDS)[number];
16
+ /** An application's face, as its Appspec says it: each only when set. */
17
+ export type LibraryAppFace = {
18
+ /** The Appspec's id: what seeds its banner, and the agent it runs as. */
19
+ id?: string;
20
+ emoji?: string;
21
+ /** The drawing chosen, by name, from the profile's set. */
22
+ avatar?: string;
23
+ /** The banner chosen, by name, from the profile's set. */
24
+ banner?: string;
25
+ };
26
+ export type LibraryAppFields = {
27
+ /** None when the Library answered without one. */
28
+ face?: LibraryAppFace;
29
+ /** None when the Library answered without one. */
30
+ appKind?: LibraryAppKind;
31
+ /** Whether it can be tried before it is cloned. */
32
+ runsLive: boolean;
33
+ };
34
+ /** The face `face_s` carries; a value that is not a face's JSON is refused. */
35
+ export declare function libraryAppFaceOf(value: unknown): LibraryAppFace | undefined;
36
+ /** The face, kind and liveness of an app as the Library answers it. */
37
+ export declare function libraryAppFieldsOf(raw: Record<string, unknown>): LibraryAppFields;
@@ -0,0 +1,59 @@
1
+ /*
2
+ * Copyright (c) 2023-2025 Datalayer, Inc.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+ /**
6
+ * What the Library says of a published application beyond any item's fields:
7
+ * its face, its kind and whether it runs live.
8
+ *
9
+ * Spacer keeps them beside the app's item, from its Appspec, and the Library
10
+ * projection carries them: `face_s` (the JSON of its `id`, `emoji`, `avatar`
11
+ * and `banner`, each only when set), `app_kind_s` and `runs_live_b` — an app
12
+ * that runs live can be tried before it is cloned: not a decision, and naming
13
+ * the agent it runs on.
14
+ *
15
+ * @module hooks/libraryApp
16
+ */
17
+ /** The kinds of application. */
18
+ export const LIBRARY_APP_KINDS = [
19
+ 'decision',
20
+ 'chat',
21
+ 'widget',
22
+ 'worker',
23
+ ];
24
+ const FACE_KEYS = ['id', 'emoji', 'avatar', 'banner'];
25
+ /** The face `face_s` carries; a value that is not a face's JSON is refused. */
26
+ export function libraryAppFaceOf(value) {
27
+ if (value === undefined || value === null || value === '') {
28
+ return undefined;
29
+ }
30
+ if (typeof value !== 'string') {
31
+ throw new Error(`An app's face is not a string: ${String(value)}`);
32
+ }
33
+ const parsed = JSON.parse(value);
34
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
35
+ throw new Error(`An app's face is not an object: ${value}`);
36
+ }
37
+ const face = {};
38
+ for (const key of FACE_KEYS) {
39
+ const field = parsed[key];
40
+ if (typeof field === 'string' && field) {
41
+ face[key] = field;
42
+ }
43
+ }
44
+ return face;
45
+ }
46
+ /** The face, kind and liveness of an app as the Library answers it. */
47
+ export function libraryAppFieldsOf(raw) {
48
+ const kind = raw.app_kind_s;
49
+ if (kind !== undefined &&
50
+ !LIBRARY_APP_KINDS.includes(kind)) {
51
+ throw new Error(`An app's kind is not one of ${LIBRARY_APP_KINDS}: ${String(kind)}`);
52
+ }
53
+ const face = libraryAppFaceOf(raw.face_s);
54
+ return {
55
+ ...(face ? { face } : {}),
56
+ ...(kind ? { appKind: kind } : {}),
57
+ runsLive: raw.runs_live_b === true,
58
+ };
59
+ }
@@ -39,6 +39,7 @@
39
39
  import { useQuery, useQueries, useMutation, useQueryClient, } from '@tanstack/react-query';
40
40
  import { BOOTSTRAP_USER_ONBOARDING, asContact, asInvite, asOrganization, asSecret, asTeam, asToken, asUser, } from '../models/index.js';
41
41
  import { asSpace } from './cacheConverters.js';
42
+ import { libraryAppFieldsOf } from './libraryApp.js';
42
43
  import { useCoreStore, useIAMStore, profileStore } from '../state/index.js';
43
44
  import { asDisplayName, namesAsInitials, asArray } from '../utils/index.js';
44
45
  import { useDatalayer } from './useDatalayer.js';
@@ -880,10 +881,13 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
880
881
  /**
881
882
  * A published agentic UI application: what it answers, and its definition
882
883
  * as the library hands it over — `model_s`, the string the Studio reads
883
- * the definition from, left unparsed because the Studio owns its shape.
884
+ * the definition from, left unparsed because the Studio owns its shape —
885
+ * and its face, its kind and whether it runs live (`libraryAppFieldsOf`),
886
+ * so its card draws it and the gallery opens one that runs live.
884
887
  */
885
888
  const toApp = (raw) => {
886
889
  return {
890
+ ...libraryAppFieldsOf(raw),
887
891
  id: raw.uid,
888
892
  type: 'app',
889
893
  name: raw.name_t,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datalayer/core",
3
- "version": "1.2.14",
3
+ "version": "1.2.15",
4
4
  "type": "module",
5
5
  "workspaces": [
6
6
  ".",