@fungi.computer/tourtois 0.0.0-stage → 0.0.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.
Files changed (135) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +127 -2
  3. package/dist/AgentMcpServers.d.ts +34 -0
  4. package/dist/AgentMcpServers.js +124 -0
  5. package/dist/AppAccessConsent.d.ts +23 -0
  6. package/dist/AppAccessConsent.js +122 -0
  7. package/dist/AppCallPermissions.d.ts +9 -0
  8. package/dist/AppCallPermissions.js +21 -0
  9. package/dist/AppDesktopSettings.d.ts +11 -0
  10. package/dist/AppDesktopSettings.js +102 -0
  11. package/dist/AppPane.d.ts +37 -0
  12. package/dist/AppPane.js +184 -0
  13. package/dist/AppWorkbench.d.ts +44 -0
  14. package/dist/AppWorkbench.js +575 -0
  15. package/dist/AvatarPicker.d.ts +7 -0
  16. package/dist/AvatarPicker.js +78 -0
  17. package/dist/AvatarPreview.d.ts +10 -0
  18. package/dist/AvatarPreview.js +6 -0
  19. package/dist/DesktopMenuBar.d.ts +18 -0
  20. package/dist/DesktopMenuBar.js +23 -0
  21. package/dist/FocusedAppMenus.d.ts +2 -0
  22. package/dist/FocusedAppMenus.js +10 -0
  23. package/dist/Keys.d.ts +131 -0
  24. package/dist/Keys.js +201 -0
  25. package/dist/MushroomMark.d.ts +2 -0
  26. package/dist/MushroomMark.js +5 -0
  27. package/dist/SettingsHome.d.ts +18 -0
  28. package/dist/SettingsHome.js +48 -0
  29. package/dist/SettingsNavigation.d.ts +17 -0
  30. package/dist/SettingsNavigation.js +153 -0
  31. package/dist/SystemSettings.d.ts +24 -0
  32. package/dist/SystemSettings.js +177 -0
  33. package/dist/TeamDesktop.d.ts +36 -0
  34. package/dist/TeamDesktop.js +39 -0
  35. package/dist/WorkbenchAppBar.d.ts +5 -0
  36. package/dist/WorkbenchAppBar.js +12 -0
  37. package/dist/app-authority.d.ts +150 -0
  38. package/dist/app-authority.js +41 -0
  39. package/dist/app-directory-reconciliation.d.ts +14 -0
  40. package/dist/app-directory-reconciliation.js +72 -0
  41. package/dist/app-directory.d.ts +206 -0
  42. package/dist/app-directory.js +21 -0
  43. package/dist/app-icon.d.ts +9 -0
  44. package/dist/app-icon.js +27 -0
  45. package/dist/app-launch.d.ts +53 -0
  46. package/dist/app-launch.js +204 -0
  47. package/dist/app-menus.d.ts +6 -0
  48. package/dist/app-menus.js +81 -0
  49. package/dist/app-open-url.d.ts +8 -0
  50. package/dist/app-open-url.js +63 -0
  51. package/dist/app-surface.d.ts +62 -0
  52. package/dist/app-surface.js +10 -0
  53. package/dist/app-windows.d.ts +107 -0
  54. package/dist/app-windows.js +21 -0
  55. package/dist/chrome.css +153 -0
  56. package/dist/command-dialogs.d.ts +42 -0
  57. package/dist/command-dialogs.js +194 -0
  58. package/dist/desktop/Desktop.d.ts +34 -0
  59. package/dist/desktop/Desktop.js +275 -0
  60. package/dist/desktop/consent.d.ts +4 -0
  61. package/dist/desktop/consent.js +64 -0
  62. package/dist/desktop/gill-frame.d.ts +14 -0
  63. package/dist/desktop/gill-frame.js +41 -0
  64. package/dist/desktop/gill-param-picker.d.ts +15 -0
  65. package/dist/desktop/gill-param-picker.js +145 -0
  66. package/dist/desktop/launcher-gill.d.ts +20 -0
  67. package/dist/desktop/launcher-gill.js +49 -0
  68. package/dist/desktop/own-launchers.d.ts +9 -0
  69. package/dist/desktop/own-launchers.js +9 -0
  70. package/dist/desktop/row-gill.d.ts +24 -0
  71. package/dist/desktop/row-gill.js +136 -0
  72. package/dist/desktop-api.d.ts +63 -0
  73. package/dist/desktop-api.js +31 -0
  74. package/dist/desktop-client.d.ts +19 -0
  75. package/dist/desktop-client.js +127 -0
  76. package/dist/desktop-layout.d.ts +117 -0
  77. package/dist/desktop-layout.js +305 -0
  78. package/dist/desktop-visibility.d.ts +8 -0
  79. package/dist/desktop-visibility.js +5 -0
  80. package/dist/layers.d.ts +5 -0
  81. package/dist/layers.js +31 -0
  82. package/dist/main.d.ts +2 -0
  83. package/dist/main.js +17 -0
  84. package/dist/member-avatar-cache.d.ts +15 -0
  85. package/dist/member-avatar-cache.js +69 -0
  86. package/dist/member-avatar.d.ts +39 -0
  87. package/dist/member-avatar.js +88 -0
  88. package/dist/menu-bar.d.ts +5 -0
  89. package/dist/menu-bar.js +5 -0
  90. package/dist/model.d.ts +6 -0
  91. package/dist/model.js +13 -0
  92. package/dist/oyster-platform-controls.d.ts +4 -0
  93. package/dist/oyster-platform-controls.js +107 -0
  94. package/dist/platform-controls.d.ts +84 -0
  95. package/dist/platform-controls.js +266 -0
  96. package/dist/queries.d.ts +7 -0
  97. package/dist/queries.js +7 -0
  98. package/dist/session-registry.d.ts +16 -0
  99. package/dist/session-registry.js +69 -0
  100. package/dist/session-selection.d.ts +6 -0
  101. package/dist/session-selection.js +22 -0
  102. package/dist/settings-leave-guard.d.ts +5 -0
  103. package/dist/settings-leave-guard.js +9 -0
  104. package/dist/settings-navigation.css +129 -0
  105. package/dist/settings-routes.d.ts +118 -0
  106. package/dist/settings-routes.js +216 -0
  107. package/dist/settings-sections.d.ts +74 -0
  108. package/dist/settings-sections.js +17 -0
  109. package/dist/shell-commands.d.ts +15 -0
  110. package/dist/shell-commands.js +95 -0
  111. package/dist/shell-host.d.ts +52 -0
  112. package/dist/shell-host.js +224 -0
  113. package/dist/shell-module.d.ts +12 -0
  114. package/dist/shell-module.js +17 -0
  115. package/dist/shell-release.d.ts +3 -0
  116. package/dist/shell-release.js +4 -0
  117. package/dist/shell.css +858 -0
  118. package/dist/shell.d.ts +6 -0
  119. package/dist/shell.js +83 -0
  120. package/dist/spa.css +11 -0
  121. package/dist/status-bar.d.ts +9 -0
  122. package/dist/status-bar.js +51 -0
  123. package/dist/team-directory.d.ts +3 -0
  124. package/dist/team-directory.js +6 -0
  125. package/dist/use-window-motion.d.ts +3 -0
  126. package/dist/use-window-motion.js +37 -0
  127. package/dist/useAppOpenUrlHandoff.d.ts +11 -0
  128. package/dist/useAppOpenUrlHandoff.js +62 -0
  129. package/dist/useAppWindowManager.d.ts +323 -0
  130. package/dist/useAppWindowManager.js +47 -0
  131. package/dist/useDirectoryCommands.d.ts +12 -0
  132. package/dist/useDirectoryCommands.js +80 -0
  133. package/dist/workbench.d.ts +3 -0
  134. package/dist/workbench.js +2 -0
  135. package/package.json +222 -3
@@ -0,0 +1,69 @@
1
+ import { latestSession } from "./session-selection.js";
2
+ import { requestIds } from "./team-directory.js";
3
+ import { useCallback, useEffect, useRef, useState } from "react";
4
+ /**
5
+ * Own one Team's client/session generation from effect setup through cleanup.
6
+ * The render waits for setup so React StrictMode can rehearse and replace the
7
+ * generation without handing a child a client that cleanup already closed.
8
+ */
9
+ export function useSessionRegistry(teamId, createClient) {
10
+ const registryRef = useRef();
11
+ const [, rerenderAfterSetup] = useState(0);
12
+ useEffect(() => {
13
+ const registry = {
14
+ teamId,
15
+ clients: new Map(),
16
+ sessions: new Map(),
17
+ pendingCreates: new Map(),
18
+ };
19
+ registryRef.current = registry;
20
+ rerenderAfterSetup((version) => version + 1);
21
+ return () => {
22
+ void Promise.allSettled([...registry.clients.values()].map((client) => client.close()));
23
+ if (registryRef.current === registry)
24
+ registryRef.current = undefined;
25
+ };
26
+ }, [createClient, teamId]);
27
+ const clientFor = useCallback((agentId) => {
28
+ const registry = registryRef.current;
29
+ if (registry?.teamId !== teamId)
30
+ throw new Error("Tourtois Team client registry is unavailable");
31
+ let client = registry.clients.get(agentId);
32
+ if (!client) {
33
+ client = createClient(agentId);
34
+ registry.clients.set(agentId, client);
35
+ }
36
+ return { client, registry };
37
+ }, [createClient, teamId]);
38
+ const sessionFor = useCallback((agentId, sessionId) => {
39
+ const { client, registry } = clientFor(agentId);
40
+ const key = `${agentId}\u0000${sessionId}`;
41
+ const existing = registry.sessions.get(key);
42
+ if (existing)
43
+ return existing;
44
+ const session = client.session(sessionId);
45
+ registry.sessions.set(key, session);
46
+ return session;
47
+ }, [clientFor]);
48
+ const selectSession = useCallback(async (agentId) => {
49
+ const { client, registry } = clientFor(agentId);
50
+ const latest = await latestSession(client);
51
+ if (registryRef.current !== registry)
52
+ throw new Error("Chat selection changed");
53
+ let sessionId = latest;
54
+ if (sessionId === null) {
55
+ const requestId = registry.pendingCreates.get(agentId) ?? requestIds.request.generate();
56
+ registry.pendingCreates.set(agentId, requestId);
57
+ sessionId = await client.createSession(requestId);
58
+ }
59
+ if (registryRef.current !== registry)
60
+ throw new Error("Chat selection changed");
61
+ registry.pendingCreates.delete(agentId);
62
+ return sessionId;
63
+ }, [clientFor]);
64
+ return {
65
+ ready: registryRef.current?.teamId === teamId,
66
+ sessionFor,
67
+ selectSession,
68
+ };
69
+ }
@@ -0,0 +1,6 @@
1
+ import type { ShiitakeAgent } from "@fungi.computer/shiitake/client";
2
+ /**
3
+ * Retained inbox startup: latest update wins; merely opening never touches
4
+ * recency. An unreadable Session carries no recency and is never selected.
5
+ */
6
+ export declare function latestSession(client: Pick<ShiitakeAgent, "listSessions">): Promise<string | null>;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Retained inbox startup: latest update wins; merely opening never touches
3
+ * recency. An unreadable Session carries no recency and is never selected.
4
+ */
5
+ export async function latestSession(client) {
6
+ let latest;
7
+ let after;
8
+ do {
9
+ const page = await client.listSessions(after);
10
+ for (const session of page.sessions) {
11
+ if (session.state === "unavailable")
12
+ continue;
13
+ if (!latest ||
14
+ session.lastActivityAt > latest.lastActivityAt ||
15
+ (session.lastActivityAt === latest.lastActivityAt &&
16
+ session.sessionId < latest.sessionId))
17
+ latest = session;
18
+ }
19
+ after = page.next;
20
+ } while (after !== undefined);
21
+ return latest?.sessionId ?? null;
22
+ }
@@ -0,0 +1,5 @@
1
+ export type SettingsLeaveState = "clean" | "dirty" | "pending" | "uncertain";
2
+ export type SettingsLeaveGuard = () => SettingsLeaveState;
3
+ /** Registers readers, not copies of form or request state. */
4
+ export declare const SettingsLeaveContext: import("react").Context<(guard: SettingsLeaveGuard) => () => void>;
5
+ export declare function useSettingsLeaveGuard(read: SettingsLeaveGuard): void;
@@ -0,0 +1,9 @@
1
+ import { createContext, useContext, useEffect, useRef } from "react";
2
+ /** Registers readers, not copies of form or request state. */
3
+ export const SettingsLeaveContext = createContext(() => () => undefined);
4
+ export function useSettingsLeaveGuard(read) {
5
+ const register = useContext(SettingsLeaveContext);
6
+ const latest = useRef(read);
7
+ latest.current = read;
8
+ useEffect(() => register(() => latest.current()), [register]);
9
+ }
@@ -0,0 +1,129 @@
1
+ .tourtois-settings-nav-group {
2
+ display: flex;
3
+ flex-direction: column;
4
+ gap: var(--spacing-xs);
5
+ }
6
+
7
+ .tourtois-settings-mobile-select {
8
+ display: none;
9
+ }
10
+
11
+ @media (max-width: 480px) {
12
+ .tourtois-system-settings .tourtois-settings-layout {
13
+ display: flex;
14
+ flex-direction: column;
15
+ }
16
+
17
+ /* These scoped rules outrank shell.css's desktop defaults even when the
18
+ bundler places this imported sheet before those defaults. */
19
+ .tourtois-settings-layout .tourtois-settings-nav {
20
+ display: none;
21
+ }
22
+
23
+ .tourtois-settings-mobile-select {
24
+ display: block;
25
+ min-width: 0;
26
+ padding: var(--spacing-sm);
27
+ border-bottom: var(--border) solid var(--stipe-hairline);
28
+ }
29
+
30
+ .tourtois-settings-mobile-select .select {
31
+ min-width: 0;
32
+ max-width: 100%;
33
+ }
34
+
35
+ .tourtois-settings-layout .tourtois-settings-content {
36
+ flex: 1;
37
+ min-height: 0;
38
+ padding: var(--spacing-sm);
39
+ }
40
+ }
41
+
42
+ .tourtois-connectors {
43
+ display: flex;
44
+ flex-direction: column;
45
+ gap: var(--spacing-sm);
46
+ }
47
+
48
+ @media (max-width: 640px) {
49
+ .tourtois-github-connection-row {
50
+ grid-template-columns: auto minmax(0, 1fr);
51
+ }
52
+
53
+ .tourtois-github-connection-controls {
54
+ grid-column: 2;
55
+ grid-row: 2;
56
+ }
57
+ }
58
+
59
+ .tourtois-connector-panel {
60
+ display: flex;
61
+ flex-direction: column;
62
+ gap: var(--spacing-sm);
63
+ }
64
+ .tourtois-connector-row {
65
+ grid-column: 1 / -1;
66
+ min-width: 0;
67
+ width: 100%;
68
+ }
69
+ .tourtois-connector-row-controls {
70
+ display: flex;
71
+ align-items: center;
72
+ justify-content: flex-end;
73
+ gap: var(--spacing-xs);
74
+ width: 10rem;
75
+ max-width: 100%;
76
+ min-width: 0;
77
+ }
78
+ .tourtois-connector-row[data-computer="true"] .tourtois-connector-row-controls {
79
+ width: 20rem;
80
+ }
81
+ .tourtois-connector-select-slot {
82
+ flex: 1;
83
+ min-width: 0;
84
+ }
85
+ .tourtois-connector-row-details {
86
+ grid-column: 1 / -1;
87
+ min-width: 0;
88
+ }
89
+ .tourtois-connector-row[data-stacked="true"] .tourtois-connector-row-controls {
90
+ width: 100%;
91
+ }
92
+
93
+ /* Websites: each saved site is a summary line that opens into a short,
94
+ readable install guide. The guide is Caps Prose; the code is a Caps
95
+ CopyField block, so this file only lays the pieces out. */
96
+ .tourtois-website-summary {
97
+ display: flex;
98
+ flex-wrap: wrap;
99
+ align-items: center;
100
+ gap: var(--spacing-sm);
101
+ min-width: 0;
102
+ }
103
+ .tourtois-website-hosts {
104
+ color: var(--stipe-fg-muted);
105
+ overflow-wrap: anywhere;
106
+ }
107
+ .tourtois-website-guide {
108
+ display: grid;
109
+ gap: var(--spacing-md);
110
+ min-width: 0;
111
+ border-top: var(--border) solid var(--stipe-hairline);
112
+ padding-top: var(--spacing-md);
113
+ }
114
+ .tourtois-website-doc {
115
+ max-width: 44rem;
116
+ min-width: 0;
117
+ }
118
+ .tourtois-website-doc > :first-child {
119
+ margin-top: 0;
120
+ }
121
+ .tourtois-website-note {
122
+ color: var(--stipe-fg-muted);
123
+ }
124
+
125
+ /* The Settings panel owns scrolling; its GitHub contents retain their natural
126
+ height rather than shrinking the form and feedback inside the flex column. */
127
+ .tourtois-github-settings > * {
128
+ flex-shrink: 0;
129
+ }
@@ -0,0 +1,118 @@
1
+ import type { RouterCore } from "@tanstack/router-core";
2
+ import * as z from "zod";
3
+ import type { WhistleJsonValue } from "@fungi.computer/whistle";
4
+ /** Host requests name a settings destination, never a browser URL. */
5
+ export declare const settingsLocationSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
6
+ category: z.ZodLiteral<"home">;
7
+ }, z.core.$strict>, z.ZodObject<{
8
+ category: z.ZodLiteral<"apps">;
9
+ appKey: z.ZodNullable<z.ZodString>;
10
+ section: z.ZodEnum<{
11
+ desktop: "desktop";
12
+ permissions: "permissions";
13
+ advanced: "advanced";
14
+ }>;
15
+ }, z.core.$strict>, z.ZodObject<{
16
+ category: z.ZodLiteral<"avatar">;
17
+ }, z.core.$strict>, z.ZodObject<{
18
+ category: z.ZodLiteral<"connectors">;
19
+ target: z.ZodDiscriminatedUnion<[z.ZodObject<{
20
+ kind: z.ZodLiteral<"list">;
21
+ }, z.core.$strict>, z.ZodObject<{
22
+ kind: z.ZodLiteral<"new">;
23
+ }, z.core.$strict>, z.ZodObject<{
24
+ kind: z.ZodLiteral<"connector">;
25
+ connectorId: z.ZodString;
26
+ }, z.core.$strict>, z.ZodObject<{
27
+ kind: z.ZodLiteral<"agent">;
28
+ agentId: z.ZodNullable<z.ZodString>;
29
+ }, z.core.$strict>], "kind">;
30
+ }, z.core.$strict>, z.ZodObject<{
31
+ category: z.ZodLiteral<"computers">;
32
+ }, z.core.$strict>, z.ZodObject<{
33
+ category: z.ZodLiteral<"keys">;
34
+ }, z.core.$strict>, z.ZodObject<{
35
+ category: z.ZodLiteral<"defaults">;
36
+ }, z.core.$strict>, z.ZodObject<{
37
+ category: z.ZodLiteral<"channels">;
38
+ }, z.core.$strict>, z.ZodObject<{
39
+ category: z.ZodLiteral<"selling">;
40
+ appId: z.ZodNullable<z.ZodString>;
41
+ }, z.core.$strict>], "category">;
42
+ export type SettingsLocation = z.output<typeof settingsLocationSchema>;
43
+ export declare const parseSettingsLocation: (value: WhistleJsonValue) => SettingsLocation;
44
+ /** One host's dialog history; settings never replace the Team's browser URL. */
45
+ export declare function createSettingsRouter(): RouterCore<import("@tanstack/router-core").Route<import("@tanstack/react-router").Register, any, "/", "/", string, "__root__", undefined, {}, {}, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, {}, undefined, readonly [import("@tanstack/react-router").Route<unknown, import("@tanstack/react-router").RootRoute<import("@tanstack/react-router").Register, undefined, {}, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, "/selling", "/selling", string, "/selling", undefined, import("@tanstack/react-router").ResolveParams<"/selling">, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, {}, () => {
46
+ category: "selling";
47
+ appId: null;
48
+ }, unknown, unknown, unknown, unknown, undefined>, import("@tanstack/react-router").Route<unknown, import("@tanstack/react-router").RootRoute<import("@tanstack/react-router").Register, undefined, {}, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, "/selling/apps/$appId", "/selling/apps/$appId", string, "/selling/apps/$appId", undefined, {
49
+ appId: string;
50
+ }, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, {}, ({ params }: import("@tanstack/react-router").LoaderFnContext<unknown, import("@tanstack/react-router").RootRoute<import("@tanstack/react-router").Register, undefined, {}, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, "/selling/apps/$appId", {
51
+ appId: string;
52
+ }, {}, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, unknown, undefined>) => {
53
+ category: "selling";
54
+ appId: string;
55
+ }, unknown, unknown, unknown, unknown, undefined>, import("@tanstack/react-router").Route<unknown, import("@tanstack/react-router").RootRoute<import("@tanstack/react-router").Register, undefined, {}, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, "/closed", "/closed", string, "/closed", undefined, import("@tanstack/react-router").ResolveParams<"/closed">, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, {}, () => null, unknown, unknown, unknown, unknown, undefined>, import("@tanstack/react-router").Route<unknown, import("@tanstack/react-router").RootRoute<import("@tanstack/react-router").Register, undefined, {}, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, "/", "/", string, "/", undefined, import("@tanstack/react-router").ResolveParams<"/">, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, {}, () => {
56
+ category: "home";
57
+ }, unknown, unknown, unknown, unknown, undefined>, import("@tanstack/react-router").Route<unknown, import("@tanstack/react-router").RootRoute<import("@tanstack/react-router").Register, undefined, {}, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, "/apps", "/apps", string, "/apps", undefined, import("@tanstack/react-router").ResolveParams<"/apps">, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, {}, () => {
58
+ category: "apps";
59
+ appKey: null;
60
+ section: "permissions";
61
+ }, unknown, unknown, unknown, unknown, undefined>, import("@tanstack/react-router").Route<unknown, import("@tanstack/react-router").RootRoute<import("@tanstack/react-router").Register, undefined, {}, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, "/apps/$appKey/$section", "/apps/$appKey/$section", string, "/apps/$appKey/$section", undefined, {
62
+ appKey: string;
63
+ section: "desktop" | "permissions" | "advanced";
64
+ }, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, {}, ({ params }: import("@tanstack/react-router").LoaderFnContext<unknown, import("@tanstack/react-router").RootRoute<import("@tanstack/react-router").Register, undefined, {}, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, "/apps/$appKey/$section", {
65
+ appKey: string;
66
+ section: "desktop" | "permissions" | "advanced";
67
+ }, {}, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, unknown, undefined>) => {
68
+ appKey: string;
69
+ section: "desktop" | "permissions" | "advanced";
70
+ category: "apps";
71
+ }, unknown, unknown, unknown, unknown, undefined>, import("@tanstack/react-router").Route<unknown, import("@tanstack/react-router").RootRoute<import("@tanstack/react-router").Register, undefined, {}, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, "/avatar", "/avatar", string, "/avatar", undefined, import("@tanstack/react-router").ResolveParams<"/avatar">, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, {}, () => {
72
+ category: "avatar";
73
+ }, unknown, unknown, unknown, unknown, undefined>, import("@tanstack/react-router").Route<unknown, import("@tanstack/react-router").RootRoute<import("@tanstack/react-router").Register, undefined, {}, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, "/defaults", "/defaults", string, "/defaults", undefined, import("@tanstack/react-router").ResolveParams<"/defaults">, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, {}, () => {
74
+ category: "defaults";
75
+ }, unknown, unknown, unknown, unknown, undefined>, import("@tanstack/react-router").Route<unknown, import("@tanstack/react-router").RootRoute<import("@tanstack/react-router").Register, undefined, {}, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, "/connectors", "/connectors", string, "/connectors", undefined, import("@tanstack/react-router").ResolveParams<"/connectors">, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, {}, () => {
76
+ category: "connectors";
77
+ target: {
78
+ kind: "list";
79
+ };
80
+ }, unknown, unknown, unknown, unknown, undefined>, import("@tanstack/react-router").Route<unknown, import("@tanstack/react-router").RootRoute<import("@tanstack/react-router").Register, undefined, {}, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, "/connectors/new", "/connectors/new", string, "/connectors/new", undefined, import("@tanstack/react-router").ResolveParams<"/connectors/new">, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, {}, () => {
81
+ category: "connectors";
82
+ target: {
83
+ kind: "new";
84
+ };
85
+ }, unknown, unknown, unknown, unknown, undefined>, import("@tanstack/react-router").Route<unknown, import("@tanstack/react-router").RootRoute<import("@tanstack/react-router").Register, undefined, {}, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, "/connectors/$connectorId", "/connectors/$connectorId", string, "/connectors/$connectorId", undefined, {
86
+ connectorId: string;
87
+ }, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, {}, ({ params }: import("@tanstack/react-router").LoaderFnContext<unknown, import("@tanstack/react-router").RootRoute<import("@tanstack/react-router").Register, undefined, {}, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, "/connectors/$connectorId", {
88
+ connectorId: string;
89
+ }, {}, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, unknown, undefined>) => {
90
+ category: "connectors";
91
+ target: {
92
+ kind: "connector";
93
+ connectorId: string;
94
+ };
95
+ }, unknown, unknown, unknown, unknown, undefined>, import("@tanstack/react-router").Route<unknown, import("@tanstack/react-router").RootRoute<import("@tanstack/react-router").Register, undefined, {}, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, "/connectors/agents", "/connectors/agents", string, "/connectors/agents", undefined, import("@tanstack/react-router").ResolveParams<"/connectors/agents">, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, {}, () => {
96
+ category: "connectors";
97
+ target: {
98
+ kind: "agent";
99
+ agentId: null;
100
+ };
101
+ }, unknown, unknown, unknown, unknown, undefined>, import("@tanstack/react-router").Route<unknown, import("@tanstack/react-router").RootRoute<import("@tanstack/react-router").Register, undefined, {}, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, "/connectors/agents/$agentId", "/connectors/agents/$agentId", string, "/connectors/agents/$agentId", undefined, {
102
+ agentId: string;
103
+ }, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, {}, ({ params }: import("@tanstack/react-router").LoaderFnContext<unknown, import("@tanstack/react-router").RootRoute<import("@tanstack/react-router").Register, undefined, {}, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, "/connectors/agents/$agentId", {
104
+ agentId: string;
105
+ }, {}, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, unknown, undefined>) => {
106
+ category: "connectors";
107
+ target: {
108
+ kind: "agent";
109
+ agentId: string;
110
+ };
111
+ }, unknown, unknown, unknown, unknown, undefined>, import("@tanstack/react-router").Route<unknown, import("@tanstack/react-router").RootRoute<import("@tanstack/react-router").Register, undefined, {}, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, "/computers", "/computers", string, "/computers", undefined, import("@tanstack/react-router").ResolveParams<"/computers">, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, {}, () => {
112
+ category: "computers";
113
+ }, unknown, unknown, unknown, unknown, undefined>, import("@tanstack/react-router").Route<unknown, import("@tanstack/react-router").RootRoute<import("@tanstack/react-router").Register, undefined, {}, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, "/keys", "/keys", string, "/keys", undefined, import("@tanstack/react-router").ResolveParams<"/keys">, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, {}, () => {
114
+ category: "keys";
115
+ }, unknown, unknown, unknown, unknown, undefined>, import("@tanstack/react-router").Route<unknown, import("@tanstack/react-router").RootRoute<import("@tanstack/react-router").Register, undefined, {}, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, "/channels", "/channels", string, "/channels", undefined, import("@tanstack/react-router").ResolveParams<"/channels">, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, import("@tanstack/react-router").AnyContext, {}, () => {
116
+ category: "channels";
117
+ }, unknown, unknown, unknown, unknown, undefined>], unknown, unknown, unknown, undefined>, "never", false, import("@tanstack/history").RouterHistory, Record<string, any>>;
118
+ export declare function navigateSettings(router: ReturnType<typeof createSettingsRouter>, location: SettingsLocation | null): Promise<void>;
@@ -0,0 +1,216 @@
1
+ import { createRootRoute, createRoute, createRouter, } from "@tanstack/react-router";
2
+ import { createMemoryHistory } from "@tanstack/history";
3
+ import * as z from "zod";
4
+ const appKey = z.string().min(1).max(256);
5
+ const connectorId = z.string().min(1).max(260);
6
+ const section = z.enum(["permissions", "desktop", "advanced"]);
7
+ /** Host requests name a settings destination, never a browser URL. */
8
+ export const settingsLocationSchema = z.discriminatedUnion("category", [
9
+ z.strictObject({ category: z.literal("home") }),
10
+ z.strictObject({
11
+ category: z.literal("apps"),
12
+ appKey: appKey.nullable(),
13
+ section,
14
+ }),
15
+ z.strictObject({ category: z.literal("avatar") }),
16
+ z.strictObject({
17
+ category: z.literal("connectors"),
18
+ target: z.discriminatedUnion("kind", [
19
+ z.strictObject({ kind: z.literal("list") }),
20
+ z.strictObject({ kind: z.literal("new") }),
21
+ z.strictObject({ kind: z.literal("connector"), connectorId }),
22
+ z.strictObject({ kind: z.literal("agent"), agentId: appKey.nullable() }),
23
+ ]),
24
+ }),
25
+ z.strictObject({ category: z.literal("computers") }),
26
+ z.strictObject({ category: z.literal("keys") }),
27
+ z.strictObject({ category: z.literal("defaults") }),
28
+ z.strictObject({ category: z.literal("channels") }),
29
+ z.strictObject({ category: z.literal("selling"), appId: appKey.nullable() }),
30
+ ]);
31
+ export const parseSettingsLocation = (value) => settingsLocationSchema.parse(value);
32
+ /** One host's dialog history; settings never replace the Team's browser URL. */
33
+ export function createSettingsRouter() {
34
+ // The dialog retains its editors while the router selects their destination.
35
+ const root = createRootRoute({ component: () => null });
36
+ const closed = createRoute({
37
+ getParentRoute: () => root,
38
+ path: "/closed",
39
+ loader: () => null,
40
+ });
41
+ const home = createRoute({
42
+ getParentRoute: () => root,
43
+ path: "/",
44
+ loader: () => ({ category: "home" }),
45
+ });
46
+ const apps = createRoute({
47
+ getParentRoute: () => root,
48
+ path: "/apps",
49
+ loader: () => ({
50
+ category: "apps",
51
+ appKey: null,
52
+ section: "permissions",
53
+ }),
54
+ });
55
+ const app = createRoute({
56
+ getParentRoute: () => root,
57
+ path: "/apps/$appKey/$section",
58
+ params: { parse: (params) => z.object({ appKey, section }).parse(params) },
59
+ loader: ({ params }) => ({ category: "apps", ...params }),
60
+ });
61
+ const avatar = createRoute({
62
+ getParentRoute: () => root,
63
+ path: "/avatar",
64
+ loader: () => ({ category: "avatar" }),
65
+ });
66
+ const defaults = createRoute({
67
+ getParentRoute: () => root,
68
+ path: "/defaults",
69
+ loader: () => ({ category: "defaults" }),
70
+ });
71
+ const connectors = createRoute({
72
+ getParentRoute: () => root,
73
+ path: "/connectors",
74
+ loader: () => ({
75
+ category: "connectors",
76
+ target: { kind: "list" },
77
+ }),
78
+ });
79
+ const connectorNew = createRoute({
80
+ getParentRoute: () => root,
81
+ path: "/connectors/new",
82
+ loader: () => ({
83
+ category: "connectors",
84
+ target: { kind: "new" },
85
+ }),
86
+ });
87
+ const connector = createRoute({
88
+ getParentRoute: () => root,
89
+ path: "/connectors/$connectorId",
90
+ params: {
91
+ parse: (params) => z.object({ connectorId }).parse(params),
92
+ },
93
+ loader: ({ params }) => ({
94
+ category: "connectors",
95
+ target: { kind: "connector", connectorId: params.connectorId },
96
+ }),
97
+ });
98
+ const connectorAgents = createRoute({
99
+ getParentRoute: () => root,
100
+ path: "/connectors/agents",
101
+ loader: () => ({
102
+ category: "connectors",
103
+ target: { kind: "agent", agentId: null },
104
+ }),
105
+ });
106
+ const connectorAgent = createRoute({
107
+ getParentRoute: () => root,
108
+ path: "/connectors/agents/$agentId",
109
+ params: { parse: (params) => z.object({ agentId: appKey }).parse(params) },
110
+ loader: ({ params }) => ({
111
+ category: "connectors",
112
+ target: { kind: "agent", agentId: params.agentId },
113
+ }),
114
+ });
115
+ const computers = createRoute({
116
+ getParentRoute: () => root,
117
+ path: "/computers",
118
+ loader: () => ({ category: "computers" }),
119
+ });
120
+ const keys = createRoute({
121
+ getParentRoute: () => root,
122
+ path: "/keys",
123
+ loader: () => ({ category: "keys" }),
124
+ });
125
+ const channels = createRoute({
126
+ getParentRoute: () => root,
127
+ path: "/channels",
128
+ loader: () => ({ category: "channels" }),
129
+ });
130
+ const selling = createRoute({
131
+ getParentRoute: () => root,
132
+ path: "/selling",
133
+ loader: () => ({ category: "selling", appId: null }),
134
+ });
135
+ const sellApp = createRoute({
136
+ getParentRoute: () => root,
137
+ path: "/selling/apps/$appId",
138
+ params: { parse: (params) => z.object({ appId: appKey }).parse(params) },
139
+ loader: ({ params }) => ({ category: "selling", appId: params.appId }),
140
+ });
141
+ const routeTree = root.addChildren([
142
+ selling,
143
+ sellApp,
144
+ closed,
145
+ home,
146
+ apps,
147
+ app,
148
+ avatar,
149
+ defaults,
150
+ connectors,
151
+ connectorNew,
152
+ connector,
153
+ connectorAgents,
154
+ connectorAgent,
155
+ computers,
156
+ keys,
157
+ channels,
158
+ ]);
159
+ const router = createRouter({
160
+ routeTree,
161
+ history: createMemoryHistory({ initialEntries: ["/closed"] }),
162
+ defaultPendingMs: 0,
163
+ defaultPendingMinMs: 0,
164
+ });
165
+ return router;
166
+ }
167
+ export function navigateSettings(router, location) {
168
+ if (location === null)
169
+ return router.navigate({ to: "/closed" });
170
+ switch (location.category) {
171
+ case "selling":
172
+ return location.appId === null
173
+ ? router.navigate({ to: "/selling" })
174
+ : router.navigate({
175
+ to: "/selling/apps/$appId",
176
+ params: { appId: location.appId },
177
+ });
178
+ case "home":
179
+ return router.navigate({ to: "/" });
180
+ case "avatar":
181
+ return router.navigate({ to: "/avatar" });
182
+ case "defaults":
183
+ return router.navigate({ to: "/defaults" });
184
+ case "channels":
185
+ return router.navigate({ to: "/channels" });
186
+ case "connectors": {
187
+ const target = location.target;
188
+ if (target.kind === "list")
189
+ return router.navigate({ to: "/connectors" });
190
+ if (target.kind === "new")
191
+ return router.navigate({ to: "/connectors/new" });
192
+ if (target.kind === "connector")
193
+ return router.navigate({
194
+ to: "/connectors/$connectorId",
195
+ params: { connectorId: target.connectorId },
196
+ });
197
+ return target.agentId === null
198
+ ? router.navigate({ to: "/connectors/agents" })
199
+ : router.navigate({
200
+ to: "/connectors/agents/$agentId",
201
+ params: { agentId: target.agentId },
202
+ });
203
+ }
204
+ case "computers":
205
+ return router.navigate({ to: "/computers" });
206
+ case "keys":
207
+ return router.navigate({ to: "/keys" });
208
+ case "apps":
209
+ return location.appKey === null
210
+ ? router.navigate({ to: "/apps" })
211
+ : router.navigate({
212
+ to: "/apps/$appKey/$section",
213
+ params: { appKey: location.appKey, section: location.section },
214
+ });
215
+ }
216
+ }