feat: replace launcher panel with direct tab creation, use directory-based workspace IDs, and add backward-compatible schema fields

This commit is contained in:
Mohamed Boudra
2026-04-06 18:15:30 +07:00
parent 6e5cad812e
commit 7173342bcb
38 changed files with 1020 additions and 500 deletions
@@ -8,8 +8,8 @@ import {
import {
orderHeadForStreamRenderStrategy,
orderTailForStreamRenderStrategy,
resolveStreamRenderStrategy,
} from "./stream-strategy";
import { resolveStreamRenderStrategy } from "./stream-strategy-resolver";
export type StreamRenderSegments = {
historyVirtualized: StreamItem[];
@@ -1,2 +1,3 @@
export * from "./stream-strategy";
export * from "./stream-strategy-resolver";
export * from "./agent-stream-render-model";
@@ -56,8 +56,8 @@ describe("combined model selector helpers", () => {
expect(matchesSearch(rows[1]!, "gpt-5.4")).toBe(true);
});
it("builds an explicit trigger label for the selected provider and model", () => {
it("keeps the selected trigger label model-only", () => {
expect(resolveProviderLabel(providerDefinitions, "codex")).toBe("Codex");
expect(buildSelectedTriggerLabel("Codex", "GPT-5.4")).toBe("Codex: GPT-5.4");
expect(buildSelectedTriggerLabel("GPT-5.4")).toBe("GPT-5.4");
});
});
@@ -528,10 +528,6 @@ export function CombinedModelSelector({
);
const ProviderIcon = getProviderIcon(selectedProvider);
const selectedProviderLabel = useMemo(
() => resolveProviderLabel(providerDefinitions, selectedProvider),
[providerDefinitions, selectedProvider],
);
const selectedModelLabel = useMemo(() => {
if (!selectedModel) {
@@ -559,8 +555,8 @@ export function CombinedModelSelector({
return selectedModelLabel;
}
return buildSelectedTriggerLabel(selectedProviderLabel, selectedModelLabel);
}, [selectedModelLabel, selectedProviderLabel]);
return buildSelectedTriggerLabel(selectedModelLabel);
}, [selectedModelLabel]);
useEffect(() => {
if (isWeb) {
@@ -11,7 +11,7 @@ export function resolveProviderLabel(
return providerDefinitions.find((definition) => definition.id === providerId)?.label ?? providerId;
}
export function buildSelectedTriggerLabel(providerLabel: string, modelLabel: string): string {
export function buildSelectedTriggerLabel(modelLabel: string): string {
return modelLabel;
}
@@ -0,0 +1,14 @@
import type { ResolveStreamRenderStrategyInput, StreamStrategy } from "./stream-strategy";
import { createNativeStreamStrategy } from "./stream-strategy-native";
import { createWebStreamStrategy } from "./stream-strategy-web";
export function resolveStreamRenderStrategy(
input: ResolveStreamRenderStrategyInput,
): StreamStrategy {
if (input.platform === "web") {
return createWebStreamStrategy({
isMobileBreakpoint: input.isMobileBreakpoint,
});
}
return createNativeStreamStrategy();
}
@@ -6,8 +6,6 @@ import type {
BottomAnchorLocalRequest,
BottomAnchorRouteRequest,
} from "./use-bottom-anchor-controller";
import { createNativeStreamStrategy } from "./stream-strategy-native";
import { createWebStreamStrategy } from "./stream-strategy-web";
type EdgeSlot = "header" | "footer";
type NeighborRelation = "above" | "below";
@@ -183,17 +181,6 @@ export function createStreamStrategy(config: StreamStrategyConfig): StreamStrate
};
}
export function resolveStreamRenderStrategy(
input: ResolveStreamRenderStrategyInput,
): StreamStrategy {
if (input.platform === "web") {
return createWebStreamStrategy({
isMobileBreakpoint: input.isMobileBreakpoint,
});
}
return createNativeStreamStrategy();
}
export function resolveBottomAnchorTransportBehavior(input: {
strategy: StreamStrategy;
isViewportSettling: boolean;