Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 0 additions & 41 deletions apps/app/src/app/lib/den-session-events.ts

This file was deleted.

10 changes: 4 additions & 6 deletions apps/app/src/app/lib/den.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ export type { SharedDesktopConfig };
export { normalizeDesktopConfig };

import { isDesktopDeployment } from "./openwork-deployment";
import {
dispatchDenSettingsChanged,
} from "./den-session-events";
import { events } from "@/lib/event-bus";
import {
desktopFetch,
getDesktopBootstrapConfig as getDesktopBootstrapConfigFromShell,
Expand Down Expand Up @@ -630,7 +628,7 @@ export async function setDenBootstrapConfig(
applyDesktopBootstrapConfig(normalized);
}

dispatchDenSettingsChanged({
events.emit("openwork-den-settings-changed", {
settings: readDenSettings(),
});

Expand Down Expand Up @@ -747,7 +745,7 @@ export function writeDenSettings(next: DenSettings, options?: { persistBootstrap
}
}

dispatchDenSettingsChanged({
events.emit("openwork-den-settings-changed", {
settings: readDenSettings(),
});
}
Expand All @@ -767,7 +765,7 @@ export function clearDenSession(options?: { includeBaseUrls?: boolean }) {
window.localStorage.removeItem(STORAGE_ACTIVE_ORG_SLUG);
window.localStorage.removeItem(STORAGE_ACTIVE_ORG_NAME);

dispatchDenSettingsChanged({
events.emit("openwork-den-settings-changed", {
settings: readDenSettings(),
});
}
Expand Down
33 changes: 0 additions & 33 deletions apps/app/src/app/lib/provider-events.ts

This file was deleted.

12 changes: 4 additions & 8 deletions apps/app/src/components/model-select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import {
OPENWORK_MODEL_PREVIEWS,
OPENWORK_MODELS_PROVIDER_ID,
OPENWORK_MODELS_PROVIDER_NAME,
openWorkModelsPromoChangedEvent,
} from "@/react-app/domains/cloud/openwork-models-promo";
import { getConnectedProviderItems, useProviderListQuery } from "@/react-app/domains/connections/provider-list-query";
import {
Expand All @@ -43,8 +42,7 @@ import {
CommandList,
} from "@/components/ui/command";
import { isDesktopProviderBlocked } from "@/app/cloud/desktop-app-restrictions";
import { openModelPickerEvent } from "@/react-app/shell/new-providers-toast";
import { newProvidersEvent } from "@/app/lib/provider-events";
import { events } from "@/lib/event-bus";

function getProviderDisplayName(providerId: string) {
return providerId
Expand Down Expand Up @@ -75,8 +73,7 @@ function useModelOptions(open: boolean) {
const handler = () => {
void refetch();
};
window.addEventListener(newProvidersEvent, handler);
return () => window.removeEventListener(newProvidersEvent, handler);
return events.on("openwork-new-providers-available", handler);
}, [client, refetch]);

// Apply org-level restrictions (dev #1505) on top of the raw model list
Expand Down Expand Up @@ -216,8 +213,7 @@ export function ModelSelect({

React.useEffect(() => {
const handlePromoChanged = () => setPromoHidden(isOpenWorkModelsPromoHidden());
window.addEventListener(openWorkModelsPromoChangedEvent, handlePromoChanged);
return () => window.removeEventListener(openWorkModelsPromoChangedEvent, handlePromoChanged);
return events.on("openwork-openwork-models-promo-changed", handlePromoChanged);
}, []);

const focusSearchInput = React.useCallback(() => {
Expand Down Expand Up @@ -409,7 +405,7 @@ export function ModelSelect({
onClick={() => {
onOpenChange(false);
setSearch("");
window.dispatchEvent(new CustomEvent(openModelPickerEvent));
events.emit("openwork-open-model-picker");
}}
>
<Settings2 className="size-3.5" />
Expand Down
81 changes: 81 additions & 0 deletions apps/app/src/lib/event-bus.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import type { DenSettings, DenUser } from "@/app/lib/den";
import type { OpenTarget } from "@/react-app/domains/session/artifacts/open-target";

export function createEventBus<TEvents extends object>() {
const target = new EventTarget();

return {
on<TType extends keyof TEvents & string>(
type: TType,
listener: (event: CustomEvent<TEvents[TType]>) => void,
options?: AddEventListenerOptions,
) {
const wrapped: EventListenerObject = {
handleEvent(event: CustomEvent<TEvents[TType]>) {
listener(event);
},
};

target.addEventListener(type, wrapped, options);

return () => {
target.removeEventListener(type, wrapped, options);
};
},

emit<TType extends keyof TEvents & string>(
type: TType,
detail?: TEvents[TType],

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: emit makes payload optional for all events, so required event details are no longer enforced by TypeScript.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/app/src/lib/event-bus.ts, line 28:

<comment>`emit` makes payload optional for all events, so required event details are no longer enforced by TypeScript.</comment>

<file context>
@@ -0,0 +1,81 @@
+
+    emit<TType extends keyof TEvents & string>(
+      type: TType,
+      detail?: TEvents[TType],
+      options?: Omit<CustomEventInit<TEvents[TType]>, "detail">,
+    ) {
</file context>

options?: Omit<CustomEventInit<TEvents[TType]>, "detail">,
) {
return target.dispatchEvent(
new CustomEvent(type, {
...options,
detail,
}),
);
},
};
}

type NewProviderInfo = {
id: string;
name: string;
providerId: string;
firstModelId?: string;
firstModelName?: string;
};


interface AppEvents {
"openwork-den-session-updated": {
status?: "success" | "error" | "signed_out";
baseUrl?: string | null;
token?: string | null;
user?: DenUser | null;
email?: string | null;
message?: string | null;
};
"openwork-den-settings-changed": { settings: DenSettings };
"openwork-new-providers-available": {
providers: NewProviderInfo[];
newProviderCount?: number;
newModelCount?: number;
source: "cloud_sync" | "local_config" | "models_refresh" | "sign_in";
};
"openwork-openwork-models-promo-changed": undefined;
"openwork-open-model-picker": { newProviderIds?: string[]; initialTab?: "default" | "available" } | undefined;
"openwork-org-onboarding-visibility": { visible?: boolean };
"openwork-server-settings-changed": undefined;
"openwork:focusPrompt": undefined;
"openwork:flushPromptDraft": undefined;
"openwork:voice-transcript": { text: string };
"openwork-open-accessible-target": OpenTarget;
"openwork-hide-accessible-target": OpenTarget;
"openwork-close-right-pane": undefined;
}

export type InferAppEvent<TType extends keyof AppEvents & string> = CustomEvent<AppEvents[TType]>;
export type InferAppEventDetails<TType extends keyof AppEvents & string> = AppEvents[TType];

export const events = createEventBus<AppEvents>();
14 changes: 4 additions & 10 deletions apps/app/src/react-app/domains/cloud/den-auth-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,13 @@ import {
writeDenSettings,
type DenUser,
} from "../../../app/lib/den";
import {
denSessionUpdatedEvent,
dispatchDenSessionUpdated,
} from "../../../app/lib/den-session-events";
import {
deepLinkBridgeEvent,
drainPendingDeepLinks,
type DeepLinkBridgeDetail,
} from "../../../app/lib/deep-link-bridge";
import { parseDenAuthDeepLink } from "../../../app/lib/openwork-links";
import { events } from "@/lib/event-bus";

export type DenAuthStatus = "checking" | "signed_in" | "signed_out";

Expand Down Expand Up @@ -119,10 +116,7 @@ export function DenAuthProvider({ children }: DenAuthProviderProps) {
void refresh();
};

window.addEventListener(denSessionUpdatedEvent, handleSessionUpdated);
return () => {
window.removeEventListener(denSessionUpdatedEvent, handleSessionUpdated);
};
return events.on("openwork-den-session-updated", handleSessionUpdated);
}, [refresh]);

useEffect(() => {
Expand All @@ -149,7 +143,7 @@ export function DenAuthProvider({ children }: DenAuthProviderProps) {
activeOrgName: null,
});

dispatchDenSessionUpdated({
events.emit("openwork-den-session-updated", {
status: "success",
baseUrl: parsed.denBaseUrl,
token: result.token,
Expand All @@ -159,7 +153,7 @@ export function DenAuthProvider({ children }: DenAuthProviderProps) {
})
.catch((error) => {
handledGrantsRef.current.delete(parsed.grant);
dispatchDenSessionUpdated({
events.emit("openwork-den-session-updated", {
status: "error",
message:
error instanceof Error
Expand Down
16 changes: 5 additions & 11 deletions apps/app/src/react-app/domains/cloud/desktop-config-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,8 @@ import {
readDenSettings,
type DenDesktopConfig,
} from "../../../app/lib/den";
import {
denSessionUpdatedEvent,
denSettingsChangedEvent,
} from "../../../app/lib/den-session-events";
import { useDenAuth } from "./den-auth-provider";
import { events } from "@/lib/event-bus";

export type DesktopConfigStore = {
config: DenDesktopConfig;
Expand Down Expand Up @@ -252,21 +249,18 @@ export function DesktopConfigProvider({ children }: DesktopConfigProviderProps)
useEffect(() => {
if (typeof window === "undefined") return;

const handleSettingsChanged = () => {
bumpSettingsVersion();
};
const controller = new AbortController();

window.addEventListener(denSessionUpdatedEvent, handleSettingsChanged);
window.addEventListener(denSettingsChangedEvent, handleSettingsChanged);
events.on("openwork-den-session-updated", () => bumpSettingsVersion(), { signal: controller.signal });
events.on("openwork-den-settings-changed", () => bumpSettingsVersion(), { signal: controller.signal });

const interval = window.setInterval(() => {
if (!isSignedIn) return;
void desktopConfigHandler();
}, DESKTOP_CONFIG_REFRESH_MS);

return () => {
window.removeEventListener(denSessionUpdatedEvent, handleSettingsChanged);
window.removeEventListener(denSettingsChangedEvent, handleSettingsChanged);
controller.abort();
window.clearInterval(interval);
};
}, [desktopConfigHandler, isSignedIn]);
Expand Down
Loading
Loading