@fungi.computer/tourtois 0.1.0 → 0.2.1
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/README.md +19 -0
- package/dist/AppAccessConsent.d.ts +6 -1
- package/dist/AppAccessConsent.js +4 -5
- package/dist/AppDesktopSettings.d.ts +2 -2
- package/dist/AppPane.d.ts +11 -4
- package/dist/AppPane.js +50 -10
- package/dist/AppWorkbench.d.ts +1 -1
- package/dist/AppWorkbench.js +10 -5
- package/dist/AvatarPreview.d.ts +8 -1
- package/dist/AvatarPreview.js +9 -1
- package/dist/Keys.d.ts +42 -121
- package/dist/Keys.js +200 -157
- package/dist/OysterComputers.d.ts +22 -0
- package/dist/OysterComputers.js +177 -0
- package/dist/SettingsNavigation.d.ts +1 -1
- package/dist/SettingsNavigation.js +1 -1
- package/dist/SystemSettings.d.ts +2 -2
- package/dist/SystemSettings.js +1 -1
- package/dist/TeamDesktop.d.ts +1 -1
- package/dist/app-authority.d.ts +37 -37
- package/dist/app-authority.js +1 -1
- package/dist/app-directory-reconciliation.js +7 -2
- package/dist/app-directory.d.ts +6 -5
- package/dist/app-directory.js +4 -1
- package/dist/app-launch.d.ts +1 -1
- package/dist/app-launch.js +6 -3
- package/dist/app-menus.d.ts +1 -1
- package/dist/app-surface.d.ts +2 -1
- package/dist/app-windows.d.ts +5 -2
- package/dist/app-windows.js +1 -1
- package/dist/command-dialogs.d.ts +1 -1
- package/dist/command-dialogs.js +4 -4
- package/dist/desktop/Desktop.d.ts +1 -1
- package/dist/desktop/consent.d.ts +1 -1
- package/dist/desktop/consent.js +1 -1
- package/dist/desktop/row-gill.d.ts +1 -1
- package/dist/oyster-platform-controls.d.ts +1 -1
- package/dist/oyster-platform-controls.js +64 -23
- package/dist/platform-controls.d.ts +6 -5
- package/dist/platform-controls.js +3 -3
- package/dist/queries.d.ts +4 -0
- package/dist/queries.js +4 -0
- package/dist/shell-commands.d.ts +1 -1
- package/dist/shell-commands.js +4 -4
- package/dist/shell-host.d.ts +7 -9
- package/dist/shell-host.js +36 -10
- package/dist/shell-module.d.ts +1 -1
- package/dist/shell.d.ts +1 -1
- package/dist/shell.js +5 -9
- package/dist/useAppWindowManager.d.ts +4 -1
- package/dist/useAppWindowManager.js +3 -0
- package/package.json +39 -18
package/dist/SystemSettings.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type AppDesktopSettingsApp } from "./AppDesktopSettings.js";
|
|
2
|
-
import { type AppDirectoryEntry } from "@fungi.computer/
|
|
3
|
-
import type { WorkbenchDesktopSettings } from "@fungi.computer/
|
|
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. */
|
package/dist/SystemSettings.js
CHANGED
|
@@ -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/
|
|
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";
|
package/dist/TeamDesktop.d.ts
CHANGED
|
@@ -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/
|
|
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";
|
package/dist/app-authority.d.ts
CHANGED
|
@@ -1,47 +1,47 @@
|
|
|
1
1
|
import * as z from "zod";
|
|
2
|
-
import { type AppAddress } from "@fungi.computer/
|
|
2
|
+
import { type AppAddress } from "@fungi.computer/nacre/app-directory";
|
|
3
3
|
export declare const appPermissionChangesSchema: z.ZodObject<{
|
|
4
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
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
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">>;
|
|
@@ -63,42 +63,42 @@ export declare const appPermissionReceiptSchema: z.ZodObject<{
|
|
|
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
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
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">;
|
|
@@ -140,10 +140,10 @@ export declare const appMutationResponseSchema: z.ZodObject<{
|
|
|
140
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
149
|
}, z.core.$strict>>>;
|
package/dist/app-authority.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as z from "zod";
|
|
2
|
-
import { appAuthorityEnforcementSchema, appComputerPermissionSchema, appAgentPermissionSchema, appGenerationPermissionsSchema, appMarketplacePermissionsSchema, } from "@fungi.computer/
|
|
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
|
|
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
|
}
|
package/dist/app-directory.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type WorkbenchDirectory } from "@fungi.computer/
|
|
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/
|
|
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/
|
|
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;
|
package/dist/app-directory.js
CHANGED
|
@@ -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/
|
|
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,
|
package/dist/app-launch.d.ts
CHANGED
|
@@ -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/
|
|
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. */
|
package/dist/app-launch.js
CHANGED
|
@@ -114,10 +114,13 @@ export function sameOfferedComputers(left, right) {
|
|
|
114
114
|
}));
|
|
115
115
|
}
|
|
116
116
|
function computersForApp(app, computers) {
|
|
117
|
-
//
|
|
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
|
-
|
|
120
|
-
|
|
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 [];
|
package/dist/app-menus.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AppSurfaceCommandHost } from "@fungi.computer/
|
|
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;
|
package/dist/app-surface.d.ts
CHANGED
|
@@ -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. */
|
package/dist/app-windows.d.ts
CHANGED
|
@@ -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/
|
|
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,7 +92,7 @@ export declare const hasVisibleAppWindows: (projection: Readonly<{
|
|
|
92
92
|
}>[];
|
|
93
93
|
}>;
|
|
94
94
|
container: HTMLElement;
|
|
95
|
-
status: import("@fungi.computer/
|
|
95
|
+
status: import("@fungi.computer/nacre/window-manager").WindowStatus;
|
|
96
96
|
generation: number;
|
|
97
97
|
error?: unknown;
|
|
98
98
|
cleanupError?: unknown;
|
|
@@ -110,6 +110,7 @@ export declare const hasVisibleAppWindows: (projection: Readonly<{
|
|
|
110
110
|
primary?: readonly Readonly<{
|
|
111
111
|
id: string;
|
|
112
112
|
label: string;
|
|
113
|
+
icon?: "play";
|
|
113
114
|
variant?: "primary" | "outline" | "ghost";
|
|
114
115
|
tone?: "destructive";
|
|
115
116
|
disabled?: boolean;
|
|
@@ -117,6 +118,7 @@ export declare const hasVisibleAppWindows: (projection: Readonly<{
|
|
|
117
118
|
menu?: readonly Readonly<{
|
|
118
119
|
id: string;
|
|
119
120
|
label: string;
|
|
121
|
+
icon?: "play";
|
|
120
122
|
variant?: "primary" | "outline" | "ghost";
|
|
121
123
|
tone?: "destructive";
|
|
122
124
|
disabled?: boolean;
|
|
@@ -124,6 +126,7 @@ export declare const hasVisibleAppWindows: (projection: Readonly<{
|
|
|
124
126
|
status?: readonly Readonly<{
|
|
125
127
|
id: string;
|
|
126
128
|
label: string;
|
|
129
|
+
presentation?: "bead";
|
|
127
130
|
tone?: "neutral" | "info" | "warning" | "success" | "error";
|
|
128
131
|
}>[];
|
|
129
132
|
}> | null;
|
package/dist/app-windows.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createWindowManager, hasVisibleWindows, } from "@fungi.computer/
|
|
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/
|
|
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;
|
package/dist/command-dialogs.js
CHANGED
|
@@ -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/
|
|
7
|
-
import { leaderKeyMatches, leaderKeys, parseChord, } from "@fungi.computer/
|
|
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(
|
|
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/
|
|
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/
|
|
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;
|
package/dist/desktop/consent.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AppError } from "@fungi.computer/agar";
|
|
2
|
-
import { desktopGillAdditionSchema, desktopGillSelectionSchema, } from "@fungi.computer/
|
|
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 = () => {
|
|
@@ -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/
|
|
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/
|
|
3
|
+
import type { MountPlatformControls } from "@fungi.computer/nacre/shell-module";
|
|
4
4
|
export declare const mountPlatformControls: MountPlatformControls;
|
|
@@ -7,12 +7,14 @@ import "@fungi.computer/parakeet/styles.css";
|
|
|
7
7
|
import "./shell.css";
|
|
8
8
|
import { AppError } from "@fungi.computer/agar";
|
|
9
9
|
import { createQueryClient } from "@fungi.computer/agar/query";
|
|
10
|
-
import { workbenchDirectorySchema } from "@fungi.computer/
|
|
10
|
+
import { workbenchDirectorySchema } from "@fungi.computer/nacre/workbench-directory";
|
|
11
11
|
import { QueryClientProvider } from "@tanstack/react-query";
|
|
12
12
|
import * as S from "effect/Schema";
|
|
13
|
+
import { z } from "zod";
|
|
13
14
|
import { createRoot } from "react-dom/client";
|
|
14
|
-
import { agentMcpServersViewSchema, createPlatformControls,
|
|
15
|
+
import { agentMcpServersViewSchema, createPlatformControls, PlatformControlsView, } from "./platform-controls.js";
|
|
15
16
|
import { settingsLocationSchema } from "./settings-routes.js";
|
|
17
|
+
import { OysterComputers, createOysterComputersPort, } from "./OysterComputers.js";
|
|
16
18
|
async function json(path) {
|
|
17
19
|
const response = await fetch(path, {
|
|
18
20
|
credentials: "same-origin",
|
|
@@ -61,33 +63,72 @@ const agentMcpServers = {
|
|
|
61
63
|
},
|
|
62
64
|
};
|
|
63
65
|
/** Owner-direct Keys custody; a plaintext secret comes back only once, on issue. */
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
66
|
+
function createOysterKeysPort(oysterKeysWire) {
|
|
67
|
+
const oysterKeysView = z.strictObject({
|
|
68
|
+
keys: z.array(oysterKeysWire.summary),
|
|
69
|
+
});
|
|
70
|
+
const oysterKeyIssue = z.strictObject({
|
|
71
|
+
plaintext: z.string().min(1),
|
|
72
|
+
key: oysterKeysWire.summary,
|
|
73
|
+
});
|
|
74
|
+
const oysterKeyMutation = z.strictObject({ key: oysterKeysWire.summary });
|
|
75
|
+
return {
|
|
76
|
+
scope: "oyster",
|
|
77
|
+
expiry: "optional",
|
|
78
|
+
options: (apps) => {
|
|
79
|
+
const targets = apps.map((app) => ({
|
|
80
|
+
id: app.installationId,
|
|
81
|
+
name: app.displayName,
|
|
82
|
+
}));
|
|
83
|
+
return Promise.resolve([
|
|
84
|
+
{ capability: "apps.read", label: "Read Apps", targets },
|
|
85
|
+
{
|
|
86
|
+
capability: "apps.use",
|
|
87
|
+
label: "Use Apps and run Workflows",
|
|
88
|
+
targets,
|
|
89
|
+
},
|
|
90
|
+
{ capability: "computer.use", label: "Use the Computer" },
|
|
91
|
+
]);
|
|
92
|
+
},
|
|
93
|
+
list: async () => oysterKeysView.parse(await json("/api/keys")),
|
|
94
|
+
issue: async (draft) => {
|
|
95
|
+
const response = await ownerRequest("/api/keys", {
|
|
96
|
+
method: "POST",
|
|
97
|
+
headers: { "Content-Type": "application/json" },
|
|
98
|
+
body: JSON.stringify(oysterKeysWire.issue.parse(draft)),
|
|
99
|
+
}, "The key request was refused");
|
|
100
|
+
return oysterKeyIssue.parse(await response.json());
|
|
101
|
+
},
|
|
102
|
+
revoke: async (keyId, requestId) => {
|
|
103
|
+
const response = await ownerRequest("/api/keys/revoke", {
|
|
104
|
+
method: "POST",
|
|
105
|
+
headers: { "Content-Type": "application/json" },
|
|
106
|
+
body: JSON.stringify(oysterKeysWire.revoke.parse({ keyId, requestId })),
|
|
107
|
+
}, "The key request was refused");
|
|
108
|
+
const result = oysterKeyMutation.parse(await response.json());
|
|
109
|
+
return { key: result.key, notice: "Key revoked.", retry: false };
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
}
|
|
83
113
|
const directory = async () => workbenchDirectorySchema.parse(await json("/api/workbench/directory"));
|
|
84
114
|
export const mountPlatformControls = (root, input) => {
|
|
115
|
+
const keys = createOysterKeysPort(input.keysWire);
|
|
116
|
+
const requestAppAccess = (target, request, dialog) => input.requestAppAccess(target, request, {
|
|
117
|
+
ask: dialog.ask,
|
|
118
|
+
customize: (installationId) => dialog.customize({
|
|
119
|
+
category: "apps",
|
|
120
|
+
appKey: installationId === null ? null : `installation:${installationId}`,
|
|
121
|
+
section: "desktop",
|
|
122
|
+
}),
|
|
123
|
+
});
|
|
85
124
|
const controls = createPlatformControls({
|
|
86
|
-
sections: ["home", "apps", "connectors", "keys"],
|
|
125
|
+
sections: ["home", "apps", "connectors", "computers", "keys"],
|
|
87
126
|
});
|
|
127
|
+
const computersPort = createOysterComputersPort(new URL(window.location.origin));
|
|
128
|
+
const computers = () => (_jsx(OysterComputers, { teamId: input.teamId, port: computersPort, onChanged: controls.changed }));
|
|
88
129
|
const client = createQueryClient();
|
|
89
130
|
const settings = createRoot(root);
|
|
90
|
-
settings.render(_jsx(QueryClientProvider, { client: client, children: _jsx(PlatformControlsView, { teamId: input.teamId, controls: controls, data: { directory, agentMcpServers, keys } }) }));
|
|
131
|
+
settings.render(_jsx(QueryClientProvider, { client: client, children: _jsx(PlatformControlsView, { teamId: input.teamId, controls: controls, data: { directory, agentMcpServers, computers, keys, requestAppAccess } }) }));
|
|
91
132
|
return Promise.resolve({
|
|
92
133
|
controls: {
|
|
93
134
|
...controls,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import
|
|
1
|
+
import type { WorkbenchHostControls } from "@fungi.computer/nacre/workbench";
|
|
2
|
+
import type { WorkbenchDirectory } from "@fungi.computer/nacre/workbench-directory";
|
|
3
|
+
import { type WorkbenchDesktopSettings, type WorkbenchDesktopRegistration } from "@fungi.computer/nacre/workbench";
|
|
3
4
|
import type { AppPermissionOutcome, AppPermissionRequest } from "@fungi.computer/agar";
|
|
4
5
|
import { type AppAccessRequest } from "./AppAccessConsent.js";
|
|
5
6
|
import { createSettingsRouter, type SettingsLocation } from "./settings-routes.js";
|
|
@@ -7,7 +8,7 @@ export { parseSettingsLocation } from "./settings-routes.js";
|
|
|
7
8
|
import type { SettingsSectionPorts } from "./settings-sections.js";
|
|
8
9
|
export type { SettingsSectionPorts, TeamAdministrationPort, } from "./settings-sections.js";
|
|
9
10
|
export { agentMcpServersViewSchema, type AgentMcpServerDraft, type AgentMcpServersPort, type AgentMcpServersView, } from "./AgentMcpServers.js";
|
|
10
|
-
export {
|
|
11
|
+
export { type KeyAppOption, type KeyGrantOption, type KeyGrantPreviewProps, type KeyTargetOption, type KeyChange, type KeyIssueDraft, type KeyIssueResult, type KeysPort, type KeysView, } from "./Keys.js";
|
|
11
12
|
/**
|
|
12
13
|
* Team administration a dashboard may ask for but never performs itself:
|
|
13
14
|
* System Settings (App permissions, forks, default Apps, Team Git, sprite)
|
|
@@ -36,7 +37,7 @@ export type PlatformControlsHost = PlatformControls & Readonly<{
|
|
|
36
37
|
desktopConsentReadyAt: () => number;
|
|
37
38
|
/** A child App can suggest Settings; only the member's Review opens them. */
|
|
38
39
|
suggestDesktopSettings: (target: AppAccessTarget) => void;
|
|
39
|
-
requestAppAccess:
|
|
40
|
+
requestAppAccess: WorkbenchHostControls["requestAppAccess"];
|
|
40
41
|
/** View wiring: current location, navigation and the consent handler. */
|
|
41
42
|
/** Settings the embedding host backs with real data and actions. */
|
|
42
43
|
sections?: readonly SettingsLocation["category"][] | undefined;
|
|
@@ -74,7 +75,7 @@ export type PlatformControlsData = SettingsSectionPorts & Readonly<{
|
|
|
74
75
|
* capabilities; the owner's click in this trusted shell is the only grant
|
|
75
76
|
* a host without a separate per-App ceiling needs.
|
|
76
77
|
*/
|
|
77
|
-
requestAppAccess?(target:
|
|
78
|
+
requestAppAccess?(target: Parameters<WorkbenchHostControls["requestAppAccess"]>[0], input: AppPermissionRequest, dialog: AppAccessDialog): Promise<AppPermissionOutcome>;
|
|
78
79
|
}>;
|
|
79
80
|
/** Tourtois owns the same Settings renderer on every embedding host. */
|
|
80
81
|
export declare function PlatformControlsView({ teamId, controls, data, }: {
|
|
@@ -2,8 +2,8 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
2
2
|
import { AppError } from "@fungi.computer/agar";
|
|
3
3
|
import { Button } from "@fungi.computer/caps/components/button";
|
|
4
4
|
import { toast } from "@fungi.computer/caps/components/toaster";
|
|
5
|
-
import { desktopGillAdditionSchema, desktopGillSelectionSchema, } from "@fungi.computer/
|
|
6
|
-
import { addressKey } from "@fungi.computer/
|
|
5
|
+
import { desktopGillAdditionSchema, desktopGillSelectionSchema, } from "@fungi.computer/nacre/workbench";
|
|
6
|
+
import { addressKey } from "@fungi.computer/nacre/app-directory";
|
|
7
7
|
import { tourtoisQueryKeys } from "./queries.js";
|
|
8
8
|
import { useQuery } from "@tanstack/react-query";
|
|
9
9
|
import { lazy, Suspense, useEffect, useState, useSyncExternalStore, } from "react";
|
|
@@ -13,7 +13,7 @@ import { createSettingsRouter, navigateSettings, settingsLocationSchema, } from
|
|
|
13
13
|
export { parseSettingsLocation } from "./settings-routes.js";
|
|
14
14
|
import { MemberAvatarSource } from "./member-avatar.js";
|
|
15
15
|
export { agentMcpServersViewSchema, } from "./AgentMcpServers.js";
|
|
16
|
-
export {
|
|
16
|
+
export {} from "./Keys.js";
|
|
17
17
|
/** One host's platform controls; render them with `PlatformControlsView`. */
|
|
18
18
|
export function createPlatformControls(options) {
|
|
19
19
|
const sections = options?.sections.slice();
|
package/dist/queries.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
/** Keep host and isolated-workbench reads in distinct cache entries. */
|
|
2
2
|
export declare const tourtoisQueryKeys: {
|
|
3
|
+
oysterComputers: (teamId: string) => readonly ["tourtois", "oyster-computers", string];
|
|
4
|
+
oysterComputerPage: (teamId: string, offset: number) => readonly ["tourtois", "oyster-computers", string, number];
|
|
5
|
+
oysterSelectedComputer: (teamId: string) => readonly ["tourtois", "oyster-selected-computer", string];
|
|
6
|
+
oysterInternetAccess: (teamId: string, computerId: string) => readonly ["tourtois", "oyster-internet-access", string, string];
|
|
3
7
|
hostSettings: (workspaceId: string) => readonly ["tourtois", "host-settings", string];
|
|
4
8
|
workbench: () => readonly ["tourtois", "workbench"];
|
|
5
9
|
workbenchComputers: (teamId: string) => readonly ["tourtois", "workbench-computers", string];
|