feat: Port R101 setWorkingVisible API and R104 Azure Cognitive Services…

SF-Task: S01/T01
This commit is contained in:
Mikael Hugo 2026-04-30 22:28:01 +02:00
parent 2bc8d0cdd3
commit 8418e88730
5 changed files with 38 additions and 0 deletions

View file

@ -135,6 +135,24 @@ function buildDefaultBaseUrl(resourceName: string): string {
return `https://${resourceName}.openai.azure.com/openai/v1`;
}
function isCognitiveServicesDomain(url: string): boolean {
try {
const hostname = new URL(url).hostname;
return hostname.endsWith(".cognitiveservices.azure.com");
} catch {
return false;
}
}
function normalizeCognitiveServicesUrl(url: string): string {
// Azure Cognitive Services endpoints use /openai/deployments/{deployment}/chat/completions
// We need to normalize to the OpenAI-compatible base path
if (url.includes("/openai/deployments/")) {
return url.split("/openai/deployments/")[0]!;
}
return url;
}
function resolveAzureConfig(
model: Model<"azure-openai-responses">,
options?: AzureOpenAIResponsesOptions,
@ -160,6 +178,11 @@ function resolveAzureConfig(
);
}
// Normalize Cognitive Services endpoints (e.g., .cognitiveservices.azure.com)
if (isCognitiveServicesDomain(resolvedBaseUrl)) {
resolvedBaseUrl = normalizeCognitiveServicesUrl(resolvedBaseUrl);
}
return {
baseUrl: normalizeAzureBaseUrl(resolvedBaseUrl),
apiVersion,

View file

@ -166,6 +166,7 @@ const noOpUIContext: ExtensionUIContext = {
onTerminalInput: () => () => {},
setStatus: () => {},
setWorkingMessage: () => {},
setWorkingVisible: () => {},
setWidget: () => {},
setFooter: () => {},
setHeader: () => {},

View file

@ -131,6 +131,9 @@ export interface ExtensionUIContext {
/** Set the working/loading message shown during streaming. Call with no argument to restore default. */
setWorkingMessage(message?: string): void;
/** Show or hide the built-in working/loading indicator. */
setWorkingVisible(visible: boolean): void;
/** Set a widget to display above or below the editor. Accepts string array or component factory. */
setWidget(key: string, content: string[] | undefined, options?: ExtensionWidgetOptions): void;
setWidget(

View file

@ -22,6 +22,11 @@ export function createExtensionUIContext(host: any): ExtensionUIContext {
host.pendingWorkingMessage = message;
}
},
setWorkingVisible: (visible) => {
if (host.loadingAnimation) {
host.loadingAnimation.setVisible(visible);
}
},
setWidget: (key, content, options) => host.setExtensionWidget(key, content, options),
setFooter: (factory) => host.setExtensionFooter(factory),
setHeader: (factory) => host.setExtensionHeader(factory),

View file

@ -290,6 +290,12 @@ export async function runRpcMode(session: AgentSession): Promise<never> {
});
},
setWorkingVisible(visible: boolean): void {
void withEmbeddedUiContext((ui) => {
ui.setWorkingVisible(visible);
});
},
setWidget(key: string, content: unknown, options?: ExtensionWidgetOptions): void {
widgetState.set(key, { content, options });
if (content === undefined || Array.isArray(content)) {