@fungi.computer/tourtois 0.4.0 → 0.5.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 +5 -2
- package/dist/AppWorkbench.js +2 -13
- package/dist/SystemSettings.js +9 -25
- package/dist/app-authority.d.ts +0 -2
- package/dist/desktop/Desktop.js +4 -4
- package/dist/desktop/launcher-gill.js +3 -3
- package/dist/oyster-platform-controls.js +75 -7
- package/dist/shell-module.d.ts +3 -2
- package/dist/shell-module.js +3 -2
- package/dist/shell.css +0 -16
- package/package.json +12 -12
package/README.md
CHANGED
|
@@ -83,8 +83,11 @@ methods. Tourtois's code loads as one lazy chunk behind that module, so no host
|
|
|
83
83
|
bundles it, and a fork mounts the same way.
|
|
84
84
|
|
|
85
85
|
Tourtois asks the host to mount each App in that App's own sandboxed frame,
|
|
86
|
-
under its own installation, Release and permissions.
|
|
87
|
-
|
|
86
|
+
under its own installation, Release and permissions. Tourtois imports no host
|
|
87
|
+
implementation package. Standalone App Permissions frame Oyster's own grants
|
|
88
|
+
page, also available without a shell; the changed Oyster and Tourtois ship
|
|
89
|
+
together. Other Settings sections still use their existing host-backed ports:
|
|
90
|
+
this repair does not frame Keys, MCP servers, Computers or the consent dialog.
|
|
88
91
|
|
|
89
92
|
## Agent tools
|
|
90
93
|
|
package/dist/AppWorkbench.js
CHANGED
|
@@ -2,6 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { desktopSettingsHandler } from "./desktop/consent.js";
|
|
3
3
|
import { AppError } from "@fungi.computer/agar";
|
|
4
4
|
import {} from "@fungi.computer/caps/blocks/app-bar";
|
|
5
|
+
import { ResizeHandle } from "@fungi.computer/caps/components/resize-handle";
|
|
5
6
|
import { toast, Toaster } from "@fungi.computer/caps/components/toaster";
|
|
6
7
|
import { WindowSnapPreview } from "@fungi.computer/caps/components/window";
|
|
7
8
|
import { MaosaicoRegion, useLayer, useMaosaicoLayout, } from "@fungi.computer/maosaico";
|
|
@@ -560,19 +561,7 @@ export function AppWorkbench({ paneLayerRef, phone, teamId, teamName, initialCom
|
|
|
560
561
|
width: layout.snapPreview.frame.width,
|
|
561
562
|
height: layout.snapPreview.frame.height,
|
|
562
563
|
...layout.stackingStyle,
|
|
563
|
-
} })), layout.divider ? (_jsx(
|
|
564
|
-
if (!layout.divider)
|
|
565
|
-
return;
|
|
566
|
-
const step = new Map([
|
|
567
|
-
["ArrowLeft", -32],
|
|
568
|
-
["ArrowRight", 32],
|
|
569
|
-
]).get(event.key) ?? 0;
|
|
570
|
-
if (step) {
|
|
571
|
-
event.preventDefault();
|
|
572
|
-
event.stopPropagation();
|
|
573
|
-
layout.resizeMain(layout.divider.position + step);
|
|
574
|
-
}
|
|
575
|
-
} })) : null] })] }), _jsx(ShellCommandDialogs, { host: appSurfaceHost, state: shellCommands, focusedWindow: activeWindow, directoryApps: directory.map((app) => ({
|
|
564
|
+
} })), layout.divider ? (_jsx(ResizeHandle, { ...layout.divider.props, className: "pointer-events-auto absolute top-1/2 -translate-x-1/2 -translate-y-1/2", "aria-label": "Main window width", orientation: "vertical", min: layout.divider.min, max: layout.divider.max, value: layout.divider.position, onValueChange: layout.resizeMain, style: { left: layout.divider.position, ...layout.stackingStyle } })) : null] })] }), _jsx(ShellCommandDialogs, { host: appSurfaceHost, state: shellCommands, focusedWindow: activeWindow, directoryApps: directory.map((app) => ({
|
|
576
565
|
commands: app.commands,
|
|
577
566
|
name: app.displayName ?? "App",
|
|
578
567
|
roles: app.roles,
|
package/dist/SystemSettings.js
CHANGED
|
@@ -15,6 +15,7 @@ import { ActionRow } from "@fungi.computer/caps/components/action-row";
|
|
|
15
15
|
import { DataList, DataRow } from "@fungi.computer/caps/components/data-list";
|
|
16
16
|
import { SettingsLeaveContext, } from "./settings-leave-guard.js";
|
|
17
17
|
import { Button } from "@fungi.computer/caps/components/button";
|
|
18
|
+
import { Tabs, TabsContent, TabsList, TabsTrigger, } from "@fungi.computer/caps/components/tabs";
|
|
18
19
|
import { WindowFrame, WindowHeader, WindowActions, } from "@fungi.computer/caps/components/window";
|
|
19
20
|
import { Dialog, DialogContent, DialogTitle, DialogDescription, } from "@fungi.computer/caps/components/dialog";
|
|
20
21
|
/** One system-settings surface. The menu only requests opening it. */
|
|
@@ -142,31 +143,14 @@ export function SystemSettings({ location: requestedLocation, sections: ceiling,
|
|
|
142
143
|
});
|
|
143
144
|
} }) }, addressKey(app.address)))) }), appCount === 0 ? (_jsx("p", { children: desktopOnly
|
|
144
145
|
? "No Apps installed yet."
|
|
145
|
-
: "No Apps in this Team yet." })) : null] })) : null, appsLoaded ? (
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
section: "permissions",
|
|
154
|
-
});
|
|
155
|
-
}, children: "Permissions" })) : null, _jsx(Button, { type: "button", size: "sm", variant: "ghost", className: desktop ? "bg-base-300 text-base-content" : undefined, "aria-pressed": desktop, onClick: () => {
|
|
156
|
-
onNavigate({
|
|
157
|
-
category: "apps",
|
|
158
|
-
appKey,
|
|
159
|
-
section: "desktop",
|
|
160
|
-
});
|
|
161
|
-
}, children: "Desktop" }), AppAdvanced !== undefined ? (_jsx(Button, { type: "button", size: "sm", variant: "ghost", className: advanced
|
|
162
|
-
? "bg-base-300 text-base-content"
|
|
163
|
-
: undefined, "aria-pressed": advanced, onClick: () => {
|
|
164
|
-
onNavigate({
|
|
165
|
-
category: "apps",
|
|
166
|
-
appKey,
|
|
167
|
-
section: "advanced",
|
|
168
|
-
});
|
|
169
|
-
}, children: "Advanced" })) : null] })) : null] }), _jsxs("div", { className: "tourtois-settings-app-content", children: [!selected ? (_jsx("p", { children: "Choose an app to manage its permissions and advanced settings." })) : null, _jsx("div", { className: "tourtois-settings-permissions", hidden: !selected || advanced || desktop, children: AppPermissions !== undefined ? (_jsx(AppPermissions, { selectedKey: appKey, onAccepted: onAccepted })) : null }), selected && desktop && desktopOnly ? (_jsx(AppCallPermissions, { calls: selected.calls, apps: apps })) : null, selected && desktop ? (_jsx(AppDesktopSettings, { app: selected, desktop: desktopSettings, consentReadyAt: desktopConsentReadyAt }, selected.surfaceId)) : null, AppAdvanced !== undefined ? (_jsx(AppAdvanced, { selectedKey: appKey, visible: advanced, onNavigate: onNavigate, onAccepted: onAccepted })) : null] })] })) : null] }) }), leaveError ? (_jsx("div", { className: "tourtois-settings-discard", role: "alert", children: leaveError })) : null, discard ? (_jsxs("div", { className: "tourtois-settings-discard", role: "alert", children: [_jsx("p", { children: "Discard unsaved changes?" }), _jsxs("div", { className: "tourtois-settings-actions", children: [_jsx(Button, { type: "button", size: "sm", variant: "ghost", onClick: () => {
|
|
146
|
+
: "No Apps in this Team yet." })) : null] })) : null, appsLoaded ? (_jsx("section", { className: "tourtois-settings-content", "aria-label": "App settings", hidden: !appSection || appKey === null, children: _jsxs(Tabs, { className: "flex min-h-0 flex-1 flex-col", value: advanced ? "advanced" : desktop ? "desktop" : "permissions", onValueChange: (section) => {
|
|
147
|
+
if (section === "permissions" ||
|
|
148
|
+
section === "desktop" ||
|
|
149
|
+
section === "advanced")
|
|
150
|
+
onNavigate({ category: "apps", appKey, section });
|
|
151
|
+
}, children: [_jsxs("div", { className: "tourtois-settings-app-header", children: [_jsxs(SectionHeading, { className: "tourtois-settings-app-heading", children: [selected ? (_jsx(AppIcon, { roles: selected.roles, icon: selected.icon })) : null, selected
|
|
152
|
+
? (selected.displayName ?? selected.appId)
|
|
153
|
+
: "Apps"] }), _jsxs(TabsList, { variant: "segmented", className: "ml-auto w-auto", hidden: !selected || (desktopOnly && AppAdvanced === undefined), "aria-label": "App settings sections", children: [!desktopOnly ? (_jsx(TabsTrigger, { value: "permissions", children: "Permissions" })) : null, _jsx(TabsTrigger, { value: "desktop", children: "Desktop" }), AppAdvanced !== undefined ? (_jsx(TabsTrigger, { value: "advanced", children: "Advanced" })) : null] })] }), _jsxs("div", { className: "tourtois-settings-app-content", children: [!selected ? (_jsx("p", { children: "Choose an app to manage its permissions and advanced settings." })) : null, AppPermissions !== undefined ? (_jsx(TabsContent, { value: "permissions", forceMount: true, className: "mt-0 flex min-h-0 flex-1 flex-col", children: _jsx("div", { className: "tourtois-settings-permissions", hidden: !selected, children: _jsx(AppPermissions, { selectedKey: appKey, onAccepted: onAccepted }) }) })) : null, _jsxs(TabsContent, { value: "desktop", forceMount: true, className: "mt-0 flex min-h-0 flex-1 flex-col", children: [selected && desktop && desktopOnly ? (_jsx(AppCallPermissions, { calls: selected.calls, apps: apps })) : null, selected && desktop ? (_jsx(AppDesktopSettings, { app: selected, desktop: desktopSettings, consentReadyAt: desktopConsentReadyAt }, selected.surfaceId)) : null] }), AppAdvanced !== undefined ? (_jsx(TabsContent, { value: "advanced", forceMount: true, className: "mt-0 flex min-h-0 flex-1 flex-col", children: _jsx(AppAdvanced, { selectedKey: appKey, visible: advanced, onNavigate: onNavigate, onAccepted: onAccepted }) })) : null] })] }) })) : null] }) }), leaveError ? (_jsx("div", { className: "tourtois-settings-discard", role: "alert", children: leaveError })) : null, discard ? (_jsxs("div", { className: "tourtois-settings-discard", role: "alert", children: [_jsx("p", { children: "Discard unsaved changes?" }), _jsxs("div", { className: "tourtois-settings-actions", children: [_jsx(Button, { type: "button", size: "sm", variant: "ghost", onClick: () => {
|
|
170
154
|
setDiscard(false);
|
|
171
155
|
}, children: "Keep editing" }), _jsx(Button, { type: "button", size: "sm", onClick: () => {
|
|
172
156
|
if (!canClose())
|
package/dist/app-authority.d.ts
CHANGED
|
@@ -52,7 +52,6 @@ export declare const appPermissionChangesSchema: z.ZodObject<{
|
|
|
52
52
|
marketplace: z.ZodOptional<z.ZodObject<{
|
|
53
53
|
browse: z.ZodBoolean;
|
|
54
54
|
purchase: z.ZodBoolean;
|
|
55
|
-
installFree: z.ZodBoolean;
|
|
56
55
|
}, z.core.$strict>>;
|
|
57
56
|
}, z.core.$strict>;
|
|
58
57
|
export type AppPermissionChanges = z.output<typeof appPermissionChangesSchema>;
|
|
@@ -109,7 +108,6 @@ export declare const appPermissionReceiptSchema: z.ZodObject<{
|
|
|
109
108
|
marketplacePermissions: z.ZodObject<{
|
|
110
109
|
browse: z.ZodBoolean;
|
|
111
110
|
purchase: z.ZodBoolean;
|
|
112
|
-
installFree: z.ZodBoolean;
|
|
113
111
|
}, z.core.$strict>;
|
|
114
112
|
}, z.core.$strip>;
|
|
115
113
|
export declare function appPermissionsMutationRequest(teamId: string, requestId: string, address: AppAddress, expectedAuthorityVersion: number, permissions: AppPermissionChanges): {
|
package/dist/desktop/Desktop.js
CHANGED
|
@@ -201,9 +201,9 @@ function ArrangedDesktop({ owner, ...props }) {
|
|
|
201
201
|
onSelect: () => undefined,
|
|
202
202
|
})),
|
|
203
203
|
];
|
|
204
|
-
return (_jsxs(_Fragment, { children: [snapshot.refreshFailure ? (_jsx("p", { role: "alert", children: snapshot.refreshFailure.message })) : null, editing ? (_jsxs("div", { className: "tourtois-desktop-controls", children: [_jsx(Button, { size: "sm", variant: "
|
|
204
|
+
return (_jsxs(_Fragment, { children: [snapshot.refreshFailure ? (_jsx("p", { role: "alert", children: snapshot.refreshFailure.message })) : null, editing ? (_jsxs("div", { className: "tourtois-desktop-controls", children: [_jsx(Button, { size: "sm", variant: "outline", onClick: () => {
|
|
205
205
|
onEditingChange(false);
|
|
206
|
-
}, children: "Done arranging" }), _jsx("div", { className: "tourtois-desktop-add-gill", children: _jsxs(Select, { "aria-label": "Add widget", value: "", disabled: saving, onChange: (event) => {
|
|
206
|
+
}, children: "Done arranging" }), _jsx("div", { className: "tourtois-desktop-add-gill", children: _jsxs(Select, { "aria-label": "Add widget", className: "select-sm", value: "", disabled: saving, onChange: (event) => {
|
|
207
207
|
const gill = catalog[Number(event.currentTarget.value)];
|
|
208
208
|
const size = gill?.sizes[0];
|
|
209
209
|
if (gill && size && (gill.params?.length ?? 0) > 0)
|
|
@@ -214,9 +214,9 @@ function ArrangedDesktop({ owner, ...props }) {
|
|
|
214
214
|
gillId: gill.gillId,
|
|
215
215
|
size,
|
|
216
216
|
});
|
|
217
|
-
}, children: [_jsx("option", { value: "", children: "Add widget\u2026" }), catalog.map((gill, index) => (_jsx("option", { value: index, children: gill.title }, `${gill.surfaceId}:${gill.gillId}`)))] }) }), _jsx(Button, { size: "sm", variant: "
|
|
217
|
+
}, children: [_jsx("option", { value: "", children: "Add widget\u2026" }), catalog.map((gill, index) => (_jsx("option", { value: index, children: gill.title }, `${gill.surfaceId}:${gill.gillId}`)))] }) }), _jsx(Button, { size: "sm", variant: "outline", disabled: saving, onClick: () => {
|
|
218
218
|
void save("layout.reset", {});
|
|
219
|
-
}, children: "Reset to Team default" }), snapshot.canWriteTeam ? (_jsx(Button, { size: "sm", variant: "
|
|
219
|
+
}, children: "Reset to Team default" }), snapshot.canWriteTeam ? (_jsx(Button, { size: "sm", variant: "outline", disabled: saving, onClick: () => {
|
|
220
220
|
void save("layout.set", { layout: snapshot.layout }, "team");
|
|
221
221
|
}, children: "Save as Team default" })) : null] })) : null, configuration ? (_jsx(GillParamPicker, { gill: configuration.gill, initialParams: snapshot.layout.items.find((item) => item.id === configuration.itemId)?.params, computers: props.computersForGill?.(configuration.gill.surfaceId) ?? [], transport: props.transport, editing: configuration.itemId !== undefined, onClose: () => {
|
|
222
222
|
setConfiguration(null);
|
|
@@ -27,9 +27,9 @@ export function LauncherGill({ items, size = "M", onAllApps, loading = false, un
|
|
|
27
27
|
onSelect: item.onSelect,
|
|
28
28
|
}));
|
|
29
29
|
const ready = !loading && !unavailable;
|
|
30
|
-
return (_jsxs(GillFrame, { title: "Launcher", size: size, onContentHeight: onContentHeight, editHandle: editHandle ?? (_jsx(
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
return (_jsxs(GillFrame, { title: "Launcher", size: size, onContentHeight: onContentHeight, editHandle: editHandle ?? (_jsx(Button, { size: "xs", variant: "outline", "aria-expanded": editing, onClick: () => {
|
|
31
|
+
setEditing(!editing);
|
|
32
|
+
}, children: editing ? "Done" : "Edit launcher" })), children: [loading ? _jsx("p", { role: "status", children: "Loading Apps\u2026" }) : null, unavailable ? (_jsxs("p", { role: "alert", children: ["App directory unavailable.", " ", onRetry ? (_jsx(Button, { size: "sm", variant: "ghost", onClick: onRetry, children: "Retry" })) : null] })) : null, ready ? (_jsxs(_Fragment, { children: [items.length === 0 ? (_jsx(EmptyState, { variant: "hint", title: "No Apps available", description: "Installed launchable Apps appear here." })) : null, items.length > 0 && shown.length === 0 ? (_jsx("p", { children: "No Apps shown. Edit the launcher to show them again." })) : null, _jsx(AppGrid, { "aria-label": "Team Apps", items: [
|
|
33
33
|
...tiles,
|
|
34
34
|
...warnings,
|
|
35
35
|
{
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
// Settings (the Hub) never calls
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// Standalone Oyster Settings chrome, loaded from the chosen shell Release.
|
|
3
|
+
// App Permissions frame Oyster's own grants page, never its implementation.
|
|
4
|
+
// Connectors, Keys and Computers retain their existing host-backed ports.
|
|
5
|
+
// A host with its own Settings (the Hub) never calls this entrypoint.
|
|
6
6
|
import "@fungi.computer/parakeet/styles.css";
|
|
7
7
|
import "./shell.css";
|
|
8
8
|
import { AppError } from "@fungi.computer/agar";
|
|
@@ -11,10 +11,12 @@ import { workbenchDirectorySchema } from "@fungi.computer/nacre/workbench-direct
|
|
|
11
11
|
import { QueryClientProvider } from "@tanstack/react-query";
|
|
12
12
|
import * as S from "effect/Schema";
|
|
13
13
|
import { z } from "zod";
|
|
14
|
+
import { useEffect, useRef, useState } from "react";
|
|
14
15
|
import { createRoot } from "react-dom/client";
|
|
15
16
|
import { agentMcpServersViewSchema, createPlatformControls, PlatformControlsView, } from "./platform-controls.js";
|
|
16
17
|
import { settingsLocationSchema } from "./settings-routes.js";
|
|
17
18
|
import { OysterComputers, createOysterComputersPort, } from "./OysterComputers.js";
|
|
19
|
+
import { useSettingsLeaveGuard, } from "./settings-leave-guard.js";
|
|
18
20
|
async function json(path) {
|
|
19
21
|
const response = await fetch(path, {
|
|
20
22
|
credentials: "same-origin",
|
|
@@ -111,6 +113,65 @@ function createOysterKeysPort(oysterKeysWire) {
|
|
|
111
113
|
};
|
|
112
114
|
}
|
|
113
115
|
const directory = async () => workbenchDirectorySchema.parse(await json("/api/workbench/directory"));
|
|
116
|
+
const permissionFrameMessage = z.strictObject({
|
|
117
|
+
type: z.literal("oyster.permissions"),
|
|
118
|
+
event: z.enum(["accepted", "state"]),
|
|
119
|
+
state: z.enum(["clean", "dirty", "pending", "uncertain"]),
|
|
120
|
+
});
|
|
121
|
+
function OysterPermissionsFrame({ installationId, onAccepted, }) {
|
|
122
|
+
const frame = useRef(null);
|
|
123
|
+
const sizeObserver = useRef(null);
|
|
124
|
+
const [height, setHeight] = useState(0);
|
|
125
|
+
const leave = useRef("clean");
|
|
126
|
+
const [refreshFailed, setRefreshFailed] = useState(false);
|
|
127
|
+
useSettingsLeaveGuard(() => leave.current);
|
|
128
|
+
useEffect(() => () => {
|
|
129
|
+
sizeObserver.current?.disconnect();
|
|
130
|
+
}, []);
|
|
131
|
+
useEffect(() => {
|
|
132
|
+
const receive = (event) => {
|
|
133
|
+
const source = frame.current?.contentWindow;
|
|
134
|
+
if (!source ||
|
|
135
|
+
event.source !== source ||
|
|
136
|
+
event.origin !== window.location.origin)
|
|
137
|
+
return;
|
|
138
|
+
const parsed = permissionFrameMessage.safeParse(event.data);
|
|
139
|
+
if (!parsed.success)
|
|
140
|
+
return;
|
|
141
|
+
leave.current = parsed.data.state;
|
|
142
|
+
if (parsed.data.event === "accepted") {
|
|
143
|
+
setRefreshFailed(false);
|
|
144
|
+
void onAccepted().catch((cause) => {
|
|
145
|
+
console.error("App permissions Settings refresh failed", cause);
|
|
146
|
+
setRefreshFailed(true);
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
window.addEventListener("message", receive);
|
|
151
|
+
return () => {
|
|
152
|
+
window.removeEventListener("message", receive);
|
|
153
|
+
};
|
|
154
|
+
}, [onAccepted]);
|
|
155
|
+
return (_jsxs(_Fragment, { children: [refreshFailed ? (_jsx("p", { role: "alert", children: "Permissions saved. Settings could not refresh. Close and reopen Settings to retry." })) : null, _jsx("iframe", { ref: frame, title: "App permissions", src: `/api/installations/${encodeURIComponent(installationId)}/grants`, className: "w-full shrink-0 border-0", style: { height }, onLoad: () => {
|
|
156
|
+
sizeObserver.current?.disconnect();
|
|
157
|
+
const body = frame.current?.contentDocument?.body;
|
|
158
|
+
if (!body)
|
|
159
|
+
return;
|
|
160
|
+
// The same-origin host page owns its markup. Observe its body rather
|
|
161
|
+
// than its editor internals; Settings remains the only scroll owner.
|
|
162
|
+
const resize = () => {
|
|
163
|
+
setHeight(Math.ceil(body.getBoundingClientRect().height));
|
|
164
|
+
};
|
|
165
|
+
sizeObserver.current = new ResizeObserver(resize);
|
|
166
|
+
sizeObserver.current.observe(body);
|
|
167
|
+
resize();
|
|
168
|
+
} })] }));
|
|
169
|
+
}
|
|
170
|
+
function OysterAppPermissions({ selectedKey, onAccepted, }) {
|
|
171
|
+
if (!selectedKey?.startsWith("installation:"))
|
|
172
|
+
return null;
|
|
173
|
+
return (_jsx(OysterPermissionsFrame, { installationId: selectedKey.slice("installation:".length), onAccepted: onAccepted }, selectedKey));
|
|
174
|
+
}
|
|
114
175
|
export const mountPlatformControls = (root, input) => {
|
|
115
176
|
const keys = createOysterKeysPort(input.keysWire);
|
|
116
177
|
const requestAppAccess = (target, request, dialog) => input.requestAppAccess(target, request, {
|
|
@@ -118,7 +179,7 @@ export const mountPlatformControls = (root, input) => {
|
|
|
118
179
|
customize: (installationId) => dialog.customize({
|
|
119
180
|
category: "apps",
|
|
120
181
|
appKey: installationId === null ? null : `installation:${installationId}`,
|
|
121
|
-
section: "
|
|
182
|
+
section: "permissions",
|
|
122
183
|
}),
|
|
123
184
|
});
|
|
124
185
|
const controls = createPlatformControls({
|
|
@@ -128,7 +189,14 @@ export const mountPlatformControls = (root, input) => {
|
|
|
128
189
|
const computers = () => (_jsx(OysterComputers, { teamId: input.teamId, port: computersPort, onChanged: controls.changed }));
|
|
129
190
|
const client = createQueryClient();
|
|
130
191
|
const settings = createRoot(root);
|
|
131
|
-
settings.render(_jsx(QueryClientProvider, { client: client, children: _jsx(PlatformControlsView, { teamId: input.teamId, controls: controls, data: {
|
|
192
|
+
settings.render(_jsx(QueryClientProvider, { client: client, children: _jsx(PlatformControlsView, { teamId: input.teamId, controls: controls, data: {
|
|
193
|
+
directory,
|
|
194
|
+
agentMcpServers,
|
|
195
|
+
computers,
|
|
196
|
+
keys,
|
|
197
|
+
requestAppAccess,
|
|
198
|
+
appPermissions: OysterAppPermissions,
|
|
199
|
+
} }) }));
|
|
132
200
|
return Promise.resolve({
|
|
133
201
|
controls: {
|
|
134
202
|
...controls,
|
package/dist/shell-module.d.ts
CHANGED
|
@@ -6,7 +6,8 @@ import type { MountPlatformControls, MountShell } from "@fungi.computer/nacre/sh
|
|
|
6
6
|
*/
|
|
7
7
|
export declare const mountShell: MountShell;
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
9
|
+
* Standalone Oyster Settings chrome, loaded as its own lazy chunk.
|
|
10
|
+
* App Permissions frame the host's page instead of importing host code;
|
|
11
|
+
* other sections retain their existing host-backed ports.
|
|
11
12
|
*/
|
|
12
13
|
export declare const mountPlatformControls: MountPlatformControls;
|
package/dist/shell-module.js
CHANGED
|
@@ -8,8 +8,9 @@ export const mountShell = async (root, input) => {
|
|
|
8
8
|
return shell.mountShell(root, input);
|
|
9
9
|
};
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
11
|
+
* Standalone Oyster Settings chrome, loaded as its own lazy chunk.
|
|
12
|
+
* App Permissions frame the host's page instead of importing host code;
|
|
13
|
+
* other sections retain their existing host-backed ports.
|
|
13
14
|
*/
|
|
14
15
|
export const mountPlatformControls = async (root, input) => {
|
|
15
16
|
const settings = await import("./oyster-platform-controls.js");
|
package/dist/shell.css
CHANGED
|
@@ -249,13 +249,6 @@
|
|
|
249
249
|
gap: var(--spacing-sm);
|
|
250
250
|
}
|
|
251
251
|
|
|
252
|
-
.tourtois-settings-app-tabs {
|
|
253
|
-
display: flex;
|
|
254
|
-
flex-wrap: wrap;
|
|
255
|
-
gap: var(--spacing-xs);
|
|
256
|
-
margin-left: auto;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
252
|
.tourtois-settings-app-header {
|
|
260
253
|
display: flex;
|
|
261
254
|
align-items: center;
|
|
@@ -532,15 +525,6 @@
|
|
|
532
525
|
color: var(--stipe-fg-muted);
|
|
533
526
|
font-size: var(--text-sm);
|
|
534
527
|
}
|
|
535
|
-
.tourtois-divider {
|
|
536
|
-
position: absolute;
|
|
537
|
-
top: 0;
|
|
538
|
-
bottom: 0;
|
|
539
|
-
width: 8px;
|
|
540
|
-
pointer-events: auto;
|
|
541
|
-
cursor: col-resize;
|
|
542
|
-
touch-action: none;
|
|
543
|
-
}
|
|
544
528
|
|
|
545
529
|
.tourtois-team-git {
|
|
546
530
|
display: flex;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fungi.computer/tourtois",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"author": "Levi <levi@technomancy.dev>",
|
|
5
5
|
"description": "Tourtois: the trusted desktop shell for Oyster and Fungi, with host-supplied Settings sections",
|
|
6
6
|
"type": "module",
|
|
@@ -73,18 +73,18 @@
|
|
|
73
73
|
"LICENSE"
|
|
74
74
|
],
|
|
75
75
|
"dependencies": {
|
|
76
|
-
"@fungi.computer/agar": "0.
|
|
76
|
+
"@fungi.computer/agar": "0.6.1",
|
|
77
77
|
"@fungi.computer/cairn": "0.1.0",
|
|
78
|
-
"@fungi.computer/caps": "0.
|
|
78
|
+
"@fungi.computer/caps": "0.6.0",
|
|
79
79
|
"@fungi.computer/ear-tag": "0.1.0",
|
|
80
80
|
"@fungi.computer/gills": "0.2.0",
|
|
81
81
|
"@fungi.computer/maosaico": "0.1.0",
|
|
82
|
-
"@fungi.computer/parakeet": "0.
|
|
83
|
-
"@fungi.computer/puffball": "0.
|
|
84
|
-
"@fungi.computer/shiitake": "0.
|
|
85
|
-
"@fungi.computer/sigils": "0.2.
|
|
82
|
+
"@fungi.computer/parakeet": "0.6.1",
|
|
83
|
+
"@fungi.computer/puffball": "0.4.0",
|
|
84
|
+
"@fungi.computer/shiitake": "0.8.0",
|
|
85
|
+
"@fungi.computer/sigils": "0.2.1",
|
|
86
86
|
"@fungi.computer/sprite": "0.2.0",
|
|
87
|
-
"@fungi.computer/sprite-zdog": "0.
|
|
87
|
+
"@fungi.computer/sprite-zdog": "0.3.0",
|
|
88
88
|
"@fungi.computer/whistle": "0.3.0",
|
|
89
89
|
"@tanstack/history": "1.162.1",
|
|
90
90
|
"@tanstack/react-form": "1.33.2",
|
|
@@ -96,16 +96,16 @@
|
|
|
96
96
|
"lucide-react": "0.460.0",
|
|
97
97
|
"react-dom": "18.3.1",
|
|
98
98
|
"zod": "4.4.3",
|
|
99
|
-
"@fungi.computer/nacre": "0.1.
|
|
99
|
+
"@fungi.computer/nacre": "0.1.2"
|
|
100
100
|
},
|
|
101
101
|
"peerDependencies": {
|
|
102
102
|
"react": "^18.3.1 || ^19.2.0"
|
|
103
103
|
},
|
|
104
104
|
"devDependencies": {
|
|
105
|
-
"@fungi.computer/oyster": "0.
|
|
105
|
+
"@fungi.computer/oyster": "0.8.0",
|
|
106
106
|
"@cloudflare/workers-types": "5.20260828.1",
|
|
107
|
-
"@fungi.computer/forage": "0.2.
|
|
108
|
-
"@fungi.computer/mycelium": "0.
|
|
107
|
+
"@fungi.computer/forage": "0.2.2",
|
|
108
|
+
"@fungi.computer/mycelium": "0.3.1",
|
|
109
109
|
"@ladle/react": "5.1.1",
|
|
110
110
|
"@types/react": "18.3.3",
|
|
111
111
|
"@vitejs/plugin-react": "6.1.1",
|