@fungi.computer/tourtois 0.0.1 → 0.2.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.
Files changed (54) hide show
  1. package/README.md +19 -0
  2. package/dist/AppAccessConsent.d.ts +6 -1
  3. package/dist/AppAccessConsent.js +4 -5
  4. package/dist/AppDesktopSettings.d.ts +2 -2
  5. package/dist/AppPane.d.ts +11 -4
  6. package/dist/AppPane.js +86 -11
  7. package/dist/AppWorkbench.d.ts +1 -1
  8. package/dist/AppWorkbench.js +10 -5
  9. package/dist/AvatarPreview.d.ts +8 -1
  10. package/dist/AvatarPreview.js +9 -1
  11. package/dist/Keys.d.ts +42 -121
  12. package/dist/Keys.js +200 -157
  13. package/dist/OysterComputers.d.ts +22 -0
  14. package/dist/OysterComputers.js +177 -0
  15. package/dist/SettingsHome.js +4 -4
  16. package/dist/SettingsNavigation.d.ts +1 -1
  17. package/dist/SettingsNavigation.js +1 -1
  18. package/dist/SystemSettings.d.ts +2 -2
  19. package/dist/SystemSettings.js +1 -1
  20. package/dist/TeamDesktop.d.ts +1 -1
  21. package/dist/app-authority.d.ts +47 -47
  22. package/dist/app-authority.js +1 -1
  23. package/dist/app-directory-reconciliation.js +7 -2
  24. package/dist/app-directory.d.ts +6 -5
  25. package/dist/app-directory.js +4 -1
  26. package/dist/app-launch.d.ts +1 -1
  27. package/dist/app-launch.js +6 -3
  28. package/dist/app-menus.d.ts +1 -1
  29. package/dist/app-surface.d.ts +2 -1
  30. package/dist/app-windows.d.ts +32 -2
  31. package/dist/app-windows.js +1 -1
  32. package/dist/command-dialogs.d.ts +1 -1
  33. package/dist/command-dialogs.js +4 -4
  34. package/dist/desktop/Desktop.d.ts +1 -1
  35. package/dist/desktop/consent.d.ts +1 -1
  36. package/dist/desktop/consent.js +1 -1
  37. package/dist/desktop/launcher-gill.js +1 -1
  38. package/dist/desktop/row-gill.d.ts +1 -1
  39. package/dist/oyster-platform-controls.d.ts +1 -1
  40. package/dist/oyster-platform-controls.js +64 -23
  41. package/dist/platform-controls.d.ts +6 -5
  42. package/dist/platform-controls.js +3 -3
  43. package/dist/queries.d.ts +4 -0
  44. package/dist/queries.js +4 -0
  45. package/dist/shell-commands.d.ts +1 -1
  46. package/dist/shell-commands.js +4 -4
  47. package/dist/shell-host.d.ts +7 -9
  48. package/dist/shell-host.js +102 -12
  49. package/dist/shell-module.d.ts +1 -1
  50. package/dist/shell.d.ts +1 -1
  51. package/dist/shell.js +5 -9
  52. package/dist/useAppWindowManager.d.ts +32 -1
  53. package/dist/useAppWindowManager.js +3 -0
  54. package/package.json +40 -19
@@ -18,19 +18,19 @@ function AvatarOverview({ onNavigate, }) {
18
18
  export function SettingsHome({ team, summary, sections, desktopOnly = false, onNavigate, }) {
19
19
  const offers = (category) => sections.includes(category);
20
20
  const close = team?.close;
21
- return (_jsxs("section", { className: "tourtois-settings-content", "aria-label": "Settings home", children: [_jsxs(DataList, { density: "compact", "aria-label": "Settings overview", children: [offers("channels") ? (_jsx(DataRow, { className: "p-0", children: _jsx(ActionRow, { "aria-label": "Website assistant", label: "Website assistant", description: "Set up chat on your WordPress site.", icon: _jsx(Sigil, { name: "connected" }), onClick: () => {
21
+ return (_jsxs("section", { className: "tourtois-settings-content", "aria-label": "Settings home", children: [_jsxs(DataList, { density: "compact", "aria-label": "Settings overview", children: [offers("channels") ? (_jsx(DataRow, { className: "p-0", children: _jsx(ActionRow, { "aria-label": "Website assistant", label: "Website assistant", description: "Set up chat on your WordPress site.", icon: _jsx(Sigil, { name: "internet" }), onClick: () => {
22
22
  onNavigate({ category: "channels" });
23
- } }) })) : null, offers("selling") ? (_jsx(DataRow, { className: "p-0", children: _jsx(ActionRow, { "aria-label": "Selling", label: "Selling", description: "Sell Apps on the Bazaar.", icon: _jsx(Sigil, { name: "installApps" }), onClick: () => {
23
+ } }) })) : null, offers("selling") ? (_jsx(DataRow, { className: "p-0", children: _jsx(ActionRow, { "aria-label": "Selling", label: "Selling", description: "Sell Apps on the Bazaar.", icon: _jsx(Sigil, { name: "sell" }), onClick: () => {
24
24
  onNavigate({ category: "selling", appId: null });
25
25
  } }) })) : null, offers("avatar") ? _jsx(AvatarOverview, { onNavigate: onNavigate }) : null, offers("defaults") ? (_jsx(DataRow, { className: "p-0", children: _jsx(ActionRow, { "aria-label": "Default apps", icon: _jsx(Sigil, { name: "installApps" }), label: "Default apps", description: "Apps for everyday tasks.", trailing: summary.defaultAppCount === null ? null : (_jsx(OverviewValue, { children: String(summary.defaultAppCount) +
26
26
  (summary.defaultAppCount === 1 ? " role" : " roles") })), onClick: () => {
27
27
  onNavigate({ category: "defaults" });
28
- } }) })) : null, team !== undefined ? (_jsx(DataRow, { className: "p-0", children: _jsx(ActionRow, { "aria-label": "Members and invites", icon: _jsx(Sigil, { name: "listAgents" }), label: "Members and invites", description: "People and invitations.", onClick: team.openMembers }) })) : null, offers("connectors") ? (_jsx(DataRow, { className: "p-0", children: _jsx(ActionRow, { "aria-label": "Connectors", icon: _jsx(Sigil, { name: "read" }), label: "Connectors", description: "What Agents can reach.", onClick: () => {
28
+ } }) })) : null, team !== undefined ? (_jsx(DataRow, { className: "p-0", children: _jsx(ActionRow, { "aria-label": "Members and invites", icon: _jsx(Sigil, { name: "members" }), label: "Members and invites", description: "People and invitations.", onClick: team.openMembers }) })) : null, offers("connectors") ? (_jsx(DataRow, { className: "p-0", children: _jsx(ActionRow, { "aria-label": "Connectors", icon: _jsx(Sigil, { name: "read" }), label: "Connectors", description: "What Agents can reach.", onClick: () => {
29
29
  onNavigate({
30
30
  category: "connectors",
31
31
  target: { kind: "list" },
32
32
  });
33
- } }) })) : null, offers("computers") ? (_jsx(DataRow, { className: "p-0", children: _jsx(ActionRow, { "aria-label": "Internet access", icon: _jsx(Sigil, { name: "connected" }), label: "Internet access", description: "Each Computer\u2019s outside access.", trailing: summary.computerCount === null ? null : (_jsx(OverviewValue, { children: String(summary.computerCount) +
33
+ } }) })) : null, offers("computers") ? (_jsx(DataRow, { className: "p-0", children: _jsx(ActionRow, { "aria-label": "Internet access", icon: _jsx(Sigil, { name: "internet" }), label: "Internet access", description: "Each Computer\u2019s outside access.", trailing: summary.computerCount === null ? null : (_jsx(OverviewValue, { children: String(summary.computerCount) +
34
34
  (summary.computerCount === 1
35
35
  ? " Computer"
36
36
  : " Computers") })), onClick: () => {
@@ -1,4 +1,4 @@
1
- import { type AppAddress } from "@fungi.computer/oyster/shell/app-directory";
1
+ import { type AppAddress } from "@fungi.computer/nacre/app-directory";
2
2
  import type { SettingsLocation } from "./settings-routes.js";
3
3
  export type NavigationApp = Readonly<{
4
4
  address: AppAddress;
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
2
2
  import { Button } from "@fungi.computer/caps/components/button";
3
3
  import { Select } from "@fungi.computer/caps/components/select";
4
4
  import { AppIcon } from "./app-icon.js";
5
- import { addressKey, } from "@fungi.computer/oyster/shell/app-directory";
5
+ import { addressKey, } from "@fungi.computer/nacre/app-directory";
6
6
  import { OwnSprite } from "./member-avatar.js";
7
7
  export function SettingsNavigation({ location, apps, sections, desktopOnly = false, onNavigate, }) {
8
8
  const groups = navigationGroups(apps, sections, desktopOnly);
@@ -1,6 +1,6 @@
1
1
  import { type AppDesktopSettingsApp } from "./AppDesktopSettings.js";
2
- import { type AppDirectoryEntry } from "@fungi.computer/oyster/shell/app-directory";
3
- import type { WorkbenchDesktopSettings } from "@fungi.computer/oyster/shell/workbench";
2
+ import { type AppDirectoryEntry } from "@fungi.computer/nacre/app-directory";
3
+ import type { WorkbenchDesktopSettings } from "@fungi.computer/nacre/workbench";
4
4
  import { type SettingsSectionPorts } from "./settings-sections.js";
5
5
  import type { SettingsLocation } from "./settings-routes.js";
6
6
  /** One system-settings surface. The menu only requests opening it. */
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { AppCallPermissions } from "./AppCallPermissions.js";
3
3
  import { SectionHeading } from "@fungi.computer/caps/blocks/section-heading";
4
4
  import { AppDesktopSettings, } from "./AppDesktopSettings.js";
5
- import { addressKey, } from "@fungi.computer/oyster/shell/app-directory";
5
+ import { addressKey, } from "@fungi.computer/nacre/app-directory";
6
6
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
7
7
  import { AgentMcpServers } from "./AgentMcpServers.js";
8
8
  import { Keys } from "./Keys.js";
@@ -3,7 +3,7 @@ import type { ComputerOption } from "./app-launch.js";
3
3
  import type { SettingsLocation } from "./settings-routes.js";
4
4
  import type { ReactNode } from "react";
5
5
  import type { AppBarItem } from "@fungi.computer/caps/blocks/app-bar";
6
- import type { WorkbenchDirectory } from "@fungi.computer/oyster/shell/workbench-directory";
6
+ import type { WorkbenchDirectory } from "@fungi.computer/nacre/workbench-directory";
7
7
  import type { PlatformControls } from "./platform-controls.js";
8
8
  import type { AppStorage } from "@fungi.computer/agar/storage";
9
9
  import type { DesktopGillTransport } from "./desktop/row-gill.js";
@@ -1,47 +1,47 @@
1
1
  import * as z from "zod";
2
- import { type AppAddress } from "@fungi.computer/oyster/shell/app-directory";
2
+ import { type AppAddress } from "@fungi.computer/nacre/app-directory";
3
3
  export declare const appPermissionChangesSchema: z.ZodObject<{
4
- computer: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
4
+ computer: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodLazy<z.ZodObject<{
5
5
  kind: z.ZodLiteral<"selected-computers">;
6
6
  computers: z.ZodArray<z.ZodObject<{
7
7
  computerId: z.ZodString;
8
8
  operations: z.ZodArray<z.ZodEnum<{
9
- "computer.list": "computer.list";
10
- "computer.readFile": "computer.readFile";
11
- "computer.writeFile": "computer.writeFile";
12
- "computer.execute": "computer.execute";
9
+ readonly "computer.list": "computer.list";
10
+ readonly "computer.readFile": "computer.readFile";
11
+ readonly "computer.writeFile": "computer.writeFile";
12
+ readonly "computer.execute": "computer.execute";
13
13
  }>>;
14
14
  }, z.core.$strict>>;
15
- }, z.core.$strict>, z.ZodObject<{
15
+ }, z.core.$strict>>, z.ZodLazy<z.ZodObject<{
16
16
  kind: z.ZodLiteral<"all-team-computers">;
17
17
  operations: z.ZodArray<z.ZodEnum<{
18
- "computer.list": "computer.list";
19
- "computer.readFile": "computer.readFile";
20
- "computer.writeFile": "computer.writeFile";
21
- "computer.execute": "computer.execute";
18
+ readonly "computer.list": "computer.list";
19
+ readonly "computer.readFile": "computer.readFile";
20
+ readonly "computer.writeFile": "computer.writeFile";
21
+ readonly "computer.execute": "computer.execute";
22
22
  }>>;
23
- }, z.core.$strict>], "kind">>;
23
+ }, z.core.$strict>>], "kind">>;
24
24
  agents: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
25
25
  kind: z.ZodLiteral<"all-team-agents">;
26
26
  directoryOperations: z.ZodArray<z.ZodEnum<{
27
- "agent.list": "agent.list";
27
+ readonly "agent.list": "agent.list";
28
28
  }>>;
29
29
  sessionOperations: z.ZodArray<z.ZodEnum<{
30
- "agent.read": "agent.read";
31
- "agent.send": "agent.send";
32
- "agent.manage": "agent.manage";
30
+ readonly "agent.read": "agent.read";
31
+ readonly "agent.send": "agent.send";
32
+ readonly "agent.manage": "agent.manage";
33
33
  }>>;
34
34
  }, z.core.$strict>, z.ZodObject<{
35
35
  kind: z.ZodLiteral<"selected-agents">;
36
36
  directoryOperations: z.ZodArray<z.ZodEnum<{
37
- "agent.list": "agent.list";
37
+ readonly "agent.list": "agent.list";
38
38
  }>>;
39
39
  agents: z.ZodArray<z.ZodObject<{
40
40
  agentId: z.ZodString;
41
41
  sessionOperations: z.ZodArray<z.ZodEnum<{
42
- "agent.read": "agent.read";
43
- "agent.send": "agent.send";
44
- "agent.manage": "agent.manage";
42
+ readonly "agent.read": "agent.read";
43
+ readonly "agent.send": "agent.send";
44
+ readonly "agent.manage": "agent.manage";
45
45
  }>>;
46
46
  }, z.core.$strict>>;
47
47
  }, z.core.$strict>], "kind">>;
@@ -58,47 +58,47 @@ export declare const appPermissionChangesSchema: z.ZodObject<{
58
58
  export type AppPermissionChanges = z.output<typeof appPermissionChangesSchema>;
59
59
  export declare const appPermissionReceiptSchema: z.ZodObject<{
60
60
  authorityVersion: z.ZodNumber;
61
- computerPermission: z.ZodNullable<z.ZodDiscriminatedUnion<[z.ZodObject<{
61
+ computerPermission: z.ZodNullable<z.ZodDiscriminatedUnion<[z.ZodLazy<z.ZodObject<{
62
62
  kind: z.ZodLiteral<"selected-computers">;
63
63
  computers: z.ZodArray<z.ZodObject<{
64
64
  computerId: z.ZodString;
65
65
  operations: z.ZodArray<z.ZodEnum<{
66
- "computer.list": "computer.list";
67
- "computer.readFile": "computer.readFile";
68
- "computer.writeFile": "computer.writeFile";
69
- "computer.execute": "computer.execute";
66
+ readonly "computer.list": "computer.list";
67
+ readonly "computer.readFile": "computer.readFile";
68
+ readonly "computer.writeFile": "computer.writeFile";
69
+ readonly "computer.execute": "computer.execute";
70
70
  }>>;
71
71
  }, z.core.$strict>>;
72
- }, z.core.$strict>, z.ZodObject<{
72
+ }, z.core.$strict>>, z.ZodLazy<z.ZodObject<{
73
73
  kind: z.ZodLiteral<"all-team-computers">;
74
74
  operations: z.ZodArray<z.ZodEnum<{
75
- "computer.list": "computer.list";
76
- "computer.readFile": "computer.readFile";
77
- "computer.writeFile": "computer.writeFile";
78
- "computer.execute": "computer.execute";
75
+ readonly "computer.list": "computer.list";
76
+ readonly "computer.readFile": "computer.readFile";
77
+ readonly "computer.writeFile": "computer.writeFile";
78
+ readonly "computer.execute": "computer.execute";
79
79
  }>>;
80
- }, z.core.$strict>], "kind">>;
80
+ }, z.core.$strict>>], "kind">>;
81
81
  agentPermission: z.ZodDiscriminatedUnion<[z.ZodObject<{
82
82
  kind: z.ZodLiteral<"all-team-agents">;
83
83
  directoryOperations: z.ZodArray<z.ZodEnum<{
84
- "agent.list": "agent.list";
84
+ readonly "agent.list": "agent.list";
85
85
  }>>;
86
86
  sessionOperations: z.ZodArray<z.ZodEnum<{
87
- "agent.read": "agent.read";
88
- "agent.send": "agent.send";
89
- "agent.manage": "agent.manage";
87
+ readonly "agent.read": "agent.read";
88
+ readonly "agent.send": "agent.send";
89
+ readonly "agent.manage": "agent.manage";
90
90
  }>>;
91
91
  }, z.core.$strict>, z.ZodObject<{
92
92
  kind: z.ZodLiteral<"selected-agents">;
93
93
  directoryOperations: z.ZodArray<z.ZodEnum<{
94
- "agent.list": "agent.list";
94
+ readonly "agent.list": "agent.list";
95
95
  }>>;
96
96
  agents: z.ZodArray<z.ZodObject<{
97
97
  agentId: z.ZodString;
98
98
  sessionOperations: z.ZodArray<z.ZodEnum<{
99
- "agent.read": "agent.read";
100
- "agent.send": "agent.send";
101
- "agent.manage": "agent.manage";
99
+ readonly "agent.read": "agent.read";
100
+ readonly "agent.send": "agent.send";
101
+ readonly "agent.manage": "agent.manage";
102
102
  }>>;
103
103
  }, z.core.$strict>>;
104
104
  }, z.core.$strict>], "kind">;
@@ -129,22 +129,22 @@ export type AppMutationRequest = ReturnType<typeof appPermissionsMutationRequest
129
129
  export declare const appMutationResponseSchema: z.ZodObject<{
130
130
  kind: z.ZodLiteral<"accepted">;
131
131
  receipt: z.ZodUnknown;
132
- enforcement: z.ZodNullable<z.ZodObject<{
132
+ enforcement: z.ZodNullable<z.ZodLazy<z.ZodObject<{
133
133
  requestId: z.ZodString;
134
- address: z.ZodUnion<readonly [z.ZodObject<{
134
+ address: z.ZodLazy<z.ZodUnion<readonly [z.ZodObject<{
135
135
  kind: z.ZodLiteral<"default">;
136
136
  appId: z.ZodString;
137
137
  }, z.core.$strict>, z.ZodObject<{
138
138
  kind: z.ZodLiteral<"installation">;
139
139
  installationId: z.ZodString;
140
- }, z.core.$strict>]>;
140
+ }, z.core.$strict>]>>;
141
141
  authorityVersion: z.ZodNumber;
142
142
  state: z.ZodEnum<{
143
- unaffected: "unaffected";
144
- pending: "pending";
145
- applied: "applied";
146
- expired: "expired";
143
+ readonly unaffected: "unaffected";
144
+ readonly pending: "pending";
145
+ readonly applied: "applied";
146
+ readonly expired: "expired";
147
147
  }>;
148
148
  outstanding: z.ZodNumber;
149
- }, z.core.$strict>>;
149
+ }, z.core.$strict>>>;
150
150
  }, z.core.$strict>;
@@ -1,5 +1,5 @@
1
1
  import * as z from "zod";
2
- import { appAuthorityEnforcementSchema, appComputerPermissionSchema, appAgentPermissionSchema, appGenerationPermissionsSchema, appMarketplacePermissionsSchema, } from "@fungi.computer/oyster/shell/app-directory";
2
+ import { appAuthorityEnforcementSchema, appComputerPermissionSchema, appAgentPermissionSchema, appGenerationPermissionsSchema, appMarketplacePermissionsSchema, } from "@fungi.computer/nacre/app-directory";
3
3
  export const appPermissionChangesSchema = z
4
4
  .strictObject({
5
5
  computer: appComputerPermissionSchema.optional(),
@@ -62,11 +62,16 @@ function appLaunchRequiresReplacement(current, next) {
62
62
  function appLaunchRequiresDirectoryUpdate(current, next) {
63
63
  return (next.appId !== current.appId ||
64
64
  next.surfaceId !== current.surfaceId ||
65
- stableLaunchHref(next.href, true) !== stableLaunchHref(current.href, true));
65
+ stableLaunchHref(next.href, true, next.releaseId !== current.releaseId) !==
66
+ stableLaunchHref(current.href, true, next.releaseId !== current.releaseId));
66
67
  }
67
- function stableLaunchHref(href, ignoreReleaseId = false) {
68
+ function stableLaunchHref(href, ignoreReleaseId = false, ignoreAuthorityVersion = false) {
68
69
  const url = new URL(href, "https://tourtois.invalid");
69
70
  if (ignoreReleaseId)
70
71
  url.searchParams.delete("releaseId");
72
+ // A promotion changes both selection facts. Leave the admitted mount alone
73
+ // until Reload; other authority/permission changes still reconcile normally.
74
+ if (ignoreAuthorityVersion)
75
+ url.searchParams.delete("authorityVersion");
71
76
  return url.pathname + url.search;
72
77
  }
@@ -1,4 +1,4 @@
1
- import { type WorkbenchDirectory } from "@fungi.computer/oyster/shell/workbench-directory";
1
+ import { type WorkbenchDirectory } from "@fungi.computer/nacre/workbench-directory";
2
2
  /** Shell composition keeps an unread directory distinct from an empty one. */
3
3
  export declare function useAppDirectory(teamId: string, directoryReader: () => Promise<WorkbenchDirectory>): {
4
4
  query: import("@tanstack/react-query").UseQueryResult<{
@@ -64,7 +64,7 @@ export declare function useAppDirectory(teamId: string, directoryReader: () => P
64
64
  }>) | undefined;
65
65
  }> | undefined;
66
66
  }>[];
67
- gills: import("@fungi.computer/oyster/shell/app-directory").AppDirectoryGill[];
67
+ gills: import("@fungi.computer/nacre/app-directory").AppDirectoryGill[];
68
68
  availability: "available" | "unavailable";
69
69
  surface: {
70
70
  stableRoute: string;
@@ -76,7 +76,7 @@ export declare function useAppDirectory(teamId: string, directoryReader: () => P
76
76
  readonly appId: string;
77
77
  readonly methods: readonly string[];
78
78
  }[] | undefined;
79
- computer?: {
79
+ computer?: "owner-fleet" | {
80
80
  computerId: string;
81
81
  name: string;
82
82
  } | undefined;
@@ -99,6 +99,7 @@ export declare function useAppDirectory(teamId: string, directoryReader: () => P
99
99
  computerId: string;
100
100
  name: string;
101
101
  } | undefined;
102
+ computerContext?: "owner-fleet" | undefined;
102
103
  needsUpdate?: {
103
104
  installationId: string | null;
104
105
  appId: string | null;
@@ -167,7 +168,7 @@ export declare function useAppDirectory(teamId: string, directoryReader: () => P
167
168
  }>) | undefined;
168
169
  }> | undefined;
169
170
  }>[];
170
- gills: import("@fungi.computer/oyster/shell/app-directory").AppDirectoryGill[];
171
+ gills: import("@fungi.computer/nacre/app-directory").AppDirectoryGill[];
171
172
  availability: "available" | "unavailable";
172
173
  surface: {
173
174
  stableRoute: string;
@@ -179,7 +180,7 @@ export declare function useAppDirectory(teamId: string, directoryReader: () => P
179
180
  readonly appId: string;
180
181
  readonly methods: readonly string[];
181
182
  }[] | undefined;
182
- computer?: {
183
+ computer?: "owner-fleet" | {
183
184
  computerId: string;
184
185
  name: string;
185
186
  } | undefined;
@@ -1,6 +1,6 @@
1
1
  import { tourtoisQueryKeys } from "./queries.js";
2
2
  import { useQuery } from "@tanstack/react-query";
3
- import { workbenchDirectorySchema, } from "@fungi.computer/oyster/shell/workbench-directory";
3
+ import { workbenchDirectorySchema, } from "@fungi.computer/nacre/workbench-directory";
4
4
  const noRoles = {};
5
5
  /** Shell composition keeps an unread directory distinct from an empty one. */
6
6
  export function useAppDirectory(teamId, directoryReader) {
@@ -11,6 +11,9 @@ export function useAppDirectory(teamId, directoryReader) {
11
11
  // The host's selection read can finish before Tourtois mounts. Keep the
12
12
  // result fresh for that handoff; explicit mutations still invalidate it.
13
13
  staleTime: 5_000,
14
+ // Quiet open Apps need release availability too, not just after a request
15
+ // is refused. React Query pauses this polling while the page is hidden.
16
+ refetchInterval: 15_000,
14
17
  });
15
18
  return {
16
19
  query,
@@ -2,7 +2,7 @@ import type { AppOpenInput } from "@fungi.computer/agar/apps";
2
2
  import type { WhistleSnapshot } from "@fungi.computer/whistle";
3
3
  import { type TourtoisAppSurfaceHost } from "./app-surface.js";
4
4
  import { createAppWindowManager, type AppLaunchDescriptor, type AppWindowManager, type AppWindowProjection } from "./app-windows.js";
5
- import type { WorkbenchDirectory } from "@fungi.computer/oyster/shell/workbench-directory";
5
+ import type { WorkbenchDirectory } from "@fungi.computer/nacre/workbench-directory";
6
6
  export type AppDirectoryApp = WorkbenchDirectory["apps"][number];
7
7
  export type AppDirectoryRoles = WorkbenchDirectory["roles"];
8
8
  /** The Team's effective App for a role when it can be launched now. */
@@ -114,10 +114,13 @@ export function sameOfferedComputers(left, right) {
114
114
  }));
115
115
  }
116
116
  function computersForApp(app, computers) {
117
- // A standalone host supplies its fixed context, not fabricated Team grants.
117
+ // Standalone context is fixed or owner-fleet, never fabricated Team grants.
118
118
  // Only an offered inventory entry can become a window's Computer choice.
119
- if (app.computer !== undefined)
120
- return computers.filter((computer) => computer.computerId === app.computer?.computerId);
119
+ const context = app.computer;
120
+ if (context === "owner-fleet")
121
+ return computers;
122
+ if (context !== undefined)
123
+ return computers.filter((computer) => computer.computerId === context.computerId);
121
124
  const permission = app.computerPermission;
122
125
  if (!permission)
123
126
  return [];
@@ -1,4 +1,4 @@
1
- import type { AppSurfaceCommandHost } from "@fungi.computer/oyster/shell/command-host";
1
+ import type { AppSurfaceCommandHost } from "@fungi.computer/nacre/command-host";
2
2
  /** Render the focused App's Whistle commands in the desktop's system bar. */
3
3
  export declare function AppMenus({ host, container: popover, }: Readonly<{
4
4
  host: Pick<AppSurfaceCommandHost, "subscribe" | "menu" | "execute"> | null;
@@ -4,8 +4,9 @@ import type { AgentSessionSelection, AppNavigationState, AppStatusItem, FileNavi
4
4
  import type { AppOpenInput, AppRoleChoice } from "@fungi.computer/agar/apps";
5
5
  import type { AppDeclaredCommand } from "@fungi.computer/puffball/app";
6
6
  import type { AppWindowMount } from "./app-windows.js";
7
+ import type { WindowEvents } from "@fungi.computer/nacre/window-manager";
7
8
  /** What one mounted App may raise toward the shell. */
8
- export type TourtoisAppMountEvents = Readonly<{
9
+ export type TourtoisAppMountEvents = Pick<WindowEvents, "onDeliveryPending"> & Readonly<{
9
10
  onComputerChoice?: () => Promise<void>;
10
11
  onAgentSessionSelection: (selection: AgentSessionSelection | null) => Promise<void>;
11
12
  /** A presentation-neutral file handoff to another App. */
@@ -1,5 +1,5 @@
1
1
  import type { AppOpenRequest } from "@fungi.computer/agar";
2
- import { type WindowHost, type WindowEvents, type WindowProjection, type WindowMount, type WindowManager, type WindowManagerOptions } from "@fungi.computer/oyster/shell/window-manager";
2
+ import { type WindowHost, type WindowEvents, type WindowProjection, type WindowMount, type WindowManager, type WindowManagerOptions } from "@fungi.computer/nacre/window-manager";
3
3
  export type AppLaunchDescriptor = Readonly<{
4
4
  windowId: string;
5
5
  /** Stable presentation identity across default inheritance/customization. */
@@ -92,13 +92,43 @@ export declare const hasVisibleAppWindows: (projection: Readonly<{
92
92
  }>[];
93
93
  }>;
94
94
  container: HTMLElement;
95
- status: import("@fungi.computer/oyster/shell/window-manager").WindowStatus;
95
+ status: import("@fungi.computer/nacre/window-manager").WindowStatus;
96
96
  generation: number;
97
97
  error?: unknown;
98
98
  cleanupError?: unknown;
99
99
  navigation: Readonly<{
100
100
  canGoBack: boolean;
101
101
  title?: string;
102
+ crumbs?: readonly Readonly<{
103
+ id: string;
104
+ label: string;
105
+ siblings?: readonly Readonly<{
106
+ id: string;
107
+ label: string;
108
+ }>[];
109
+ }>[];
110
+ primary?: readonly Readonly<{
111
+ id: string;
112
+ label: string;
113
+ icon?: "play";
114
+ variant?: "primary" | "outline" | "ghost";
115
+ tone?: "destructive";
116
+ disabled?: boolean;
117
+ }>[];
118
+ menu?: readonly Readonly<{
119
+ id: string;
120
+ label: string;
121
+ icon?: "play";
122
+ variant?: "primary" | "outline" | "ghost";
123
+ tone?: "destructive";
124
+ disabled?: boolean;
125
+ }>[];
126
+ status?: readonly Readonly<{
127
+ id: string;
128
+ label: string;
129
+ presentation?: "bead";
130
+ tone?: "neutral" | "info" | "warning" | "success" | "error";
131
+ }>[];
102
132
  }> | null;
103
133
  statusItems: readonly import("@fungi.computer/agar").AppStatusItem[];
104
134
  }>[];
@@ -1,4 +1,4 @@
1
- import { createWindowManager, hasVisibleWindows, } from "@fungi.computer/oyster/shell/window-manager";
1
+ import { createWindowManager, hasVisibleWindows, } from "@fungi.computer/nacre/window-manager";
2
2
  export const hasVisibleAppWindows = (hasVisibleWindows);
3
3
  /** DOM attachment and App identity belong to the browser host. */
4
4
  export function createAppWindowManager(options) {
@@ -1,7 +1,7 @@
1
1
  import { type ReactNode } from "react";
2
2
  import type { WhistleSnapshot } from "@fungi.computer/whistle";
3
3
  import type { AppDeclaredCommand } from "@fungi.computer/puffball/app";
4
- import { type AppSurfaceCommandHost } from "@fungi.computer/oyster/shell/command-host";
4
+ import { type AppSurfaceCommandHost } from "@fungi.computer/nacre/command-host";
5
5
  /** Current command view and the host-owned dialog visibility. */
6
6
  export type ShellCommandState = Readonly<{
7
7
  active: WhistleSnapshot;
@@ -3,8 +3,8 @@ import { useCallback, useLayoutEffect, useMemo } from "react";
3
3
  import { CommandMenu } from "@fungi.computer/caps/blocks/command-menu";
4
4
  import { Combobox } from "@fungi.computer/caps/components/combobox";
5
5
  import { Dialog, DialogContent, DialogDescription, DialogTitle, } from "@fungi.computer/caps/components/dialog";
6
- import { appDirectorySourceId, } from "@fungi.computer/oyster/shell/command-host";
7
- import { leaderKeyMatches, leaderKeys, parseChord, } from "@fungi.computer/oyster/shell/keys";
6
+ import { appDirectorySourceId, } from "@fungi.computer/nacre/command-host";
7
+ import { leaderKeyMatches, leaderKeys, parseChord, } from "@fungi.computer/nacre/keys";
8
8
  function isMac() {
9
9
  return /Mac|iPhone|iPad/u.test(navigator.userAgent);
10
10
  }
@@ -37,9 +37,9 @@ function commandKeycaps(commandId, active, mac, declared) {
37
37
  if (leader !== undefined)
38
38
  return [mac ? "⌘ K" : "Ctrl K", "then", chordKey(leader.key)];
39
39
  const binding = active.bindings.find((row) => row.commandId === commandId);
40
- const declaredBinding = declared?.projections?.bindings?.values.find((value) => value.startsWith("<leader> "));
40
+ const declaredBinding = declared?.projections?.bindings?.values.find((value) => value.startsWith("<leader>"));
41
41
  if (declaredBinding !== undefined)
42
- return [mac ? "⌘ K" : "Ctrl K", "then", chordKey(declaredBinding.slice(9))];
42
+ return [mac ? "⌘ K" : "Ctrl K", "then", chordKey(declaredBinding.slice(8))];
43
43
  if (binding === undefined)
44
44
  return [];
45
45
  const chord = parseChord(binding.binding, mac);
@@ -2,7 +2,7 @@ import type { AppOpenInput } from "@fungi.computer/agar/apps";
2
2
  import type { DesktopMethods } from "../desktop-api.js";
3
3
  import type { AppStorage } from "@fungi.computer/agar/storage";
4
4
  import type { AppBarItem } from "@fungi.computer/caps/blocks/app-bar";
5
- import type { WorkbenchDirectory } from "@fungi.computer/oyster/shell/workbench-directory";
5
+ import type { WorkbenchDirectory } from "@fungi.computer/nacre/workbench-directory";
6
6
  import { type DesktopLayoutClient } from "../desktop-client.js";
7
7
  import { type DesktopGillTransport } from "./row-gill.js";
8
8
  export type DesktopProps = {
@@ -1,4 +1,4 @@
1
- import { type WorkbenchDesktopSettings } from "@fungi.computer/oyster/shell/workbench";
1
+ import { type WorkbenchDesktopSettings } from "@fungi.computer/nacre/workbench";
2
2
  import type { DesktopLayoutClient } from "../desktop-client.js";
3
3
  /** Only the host's member-consent UI invokes this admitted dashboard callback. */
4
4
  export declare function desktopSettingsHandler(current: () => DesktopLayoutClient | null): WorkbenchDesktopSettings;
@@ -1,5 +1,5 @@
1
1
  import { AppError } from "@fungi.computer/agar";
2
- import { desktopGillAdditionSchema, desktopGillSelectionSchema, } from "@fungi.computer/oyster/shell/workbench";
2
+ import { desktopGillAdditionSchema, desktopGillSelectionSchema, } from "@fungi.computer/nacre/workbench";
3
3
  /** Only the host's member-consent UI invokes this admitted dashboard callback. */
4
4
  export function desktopSettingsHandler(current) {
5
5
  const owner = () => {
@@ -35,7 +35,7 @@ export function LauncherGill({ items, size = "M", onAllApps, loading = false, un
35
35
  {
36
36
  id: "all-apps",
37
37
  label: "All Apps ›",
38
- icon: _jsx(Sigil, { name: "installApps" }),
38
+ icon: _jsx(Sigil, { name: "allApps" }),
39
39
  onSelect: onAllApps,
40
40
  },
41
41
  ], size: "lg" }), editing ? (_jsx(DataList, { "aria-label": "Launcher preferences", children: items.map((item) => (_jsx(DataRow, { children: _jsxs("div", { className: "tourtois-launcher-preference", children: [_jsx("span", { "aria-hidden": "true", className: "grid size-6 place-items-center [&_svg]:size-full", children: item.icon ?? _jsx(Sigil, { name: "installApps" }) }), _jsx("div", { className: "tourtois-launcher-preference-identity", children: _jsx("span", { children: item.label }) }), _jsxs(Select, { "aria-label": `Launcher state for ${item.label}`, value: stateFor(item.id), onChange: (event) => {
@@ -1,7 +1,7 @@
1
1
  import type { AppBarItem } from "@fungi.computer/caps/blocks/app-bar";
2
2
  import { type ReactNode } from "react";
3
3
  import { type GillResponse } from "@fungi.computer/gills";
4
- import type { TeamWorkbenchHostHandle } from "@fungi.computer/oyster/shell/workbench";
4
+ import type { TeamWorkbenchHostHandle } from "@fungi.computer/nacre/workbench";
5
5
  import type { AppDeclaredGill, AppGillDesktopSize } from "@fungi.computer/gills";
6
6
  export type DesktopGillTransport = Pick<TeamWorkbenchHostHandle, "requestGill" | "watchGillChanges">;
7
7
  /** The host admits reads; opening a row navigates inside its App. */
@@ -1,4 +1,4 @@
1
1
  import "@fungi.computer/parakeet/styles.css";
2
2
  import "./shell.css";
3
- import type { MountPlatformControls } from "@fungi.computer/oyster/shell/shell-module";
3
+ import type { MountPlatformControls } from "@fungi.computer/nacre/shell-module";
4
4
  export declare const mountPlatformControls: MountPlatformControls;