Skip to content
This repository was archived by the owner on Jun 3, 2026. It is now read-only.
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
2 changes: 2 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
],
"license": "MIT",
"main": "./dist/extension.js",
"enabledApiProposals": [
"chatOutputRenderer"
],
"engines": {
"vscode": "^1.104.0"
},
Expand Down Expand Up @@ -321,6 +324,20 @@
}
}
],
"chatOutputRenderers": [
{
"viewType": "seamless-agent.askUserResult",
"mimeTypes": [
"application/vnd.seamless-agent.ask-user-result"
]
},
{
"viewType": "seamless-agent.planReviewResult",
"mimeTypes": [
"application/vnd.seamless-agent.plan-review-result"
]
}
],
"commands": [
{
"command": "seamless-agent.cancelPendingPlans",
Expand Down
16 changes: 16 additions & 0 deletions package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,22 @@
"batch.deleteSelected": "Delete Selected",
"batch.selectedCount": "{0} selected",
"confirm.deleteSelected": "Are you sure you want to delete {0} selected items?",
"renderer.userResponse": "User Response",
"renderer.defaultAgentName": "Agent",
"renderer.userDismissed": "User dismissed this prompt",
"renderer.clickToExpand": "(click to expand)",
"renderer.userResponded": "User responded:",
"renderer.attachments": "Attachments:",
"renderer.renderErrorAskUser": "Unable to render ask_user result",
"renderer.renderErrorPlanReview": "Unable to render plan review result",
"renderer.error": "Error",
"renderer.planReview": "Plan Review",
"renderer.walkthrough": "Walkthrough",
"renderer.review": "Review",
"renderer.status": "Status:",
"renderer.changesRequested": "Changes Requested",
"renderer.viewPlan": "View Plan",
"renderer.revisionsRequired": "Revisions Required:",
"console.orTypeYourOwn": "Or type your own response below",
"response.selectedOptions": "Selected options:",
"response.additionalResponse": "Additional response:"
Expand Down
17 changes: 17 additions & 0 deletions package.nls.pt-br.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,23 @@
"batch.deleteSelected": "Excluir Selecionados",
"batch.selectedCount": "{0} selecionados",
"confirm.deleteSelected": "Tem certeza que deseja excluir {0} itens selecionados?",

"renderer.userResponse": "Resposta do Usuário",
"renderer.defaultAgentName": "Agente",
"renderer.userDismissed": "Usuário dispensou esta solicitação",
"renderer.clickToExpand": "(clique para expandir)",
"renderer.userResponded": "Usuário respondeu:",
"renderer.attachments": "Anexos:",
"renderer.renderErrorAskUser": "Não foi possível renderizar o resultado de ask_user",
"renderer.renderErrorPlanReview": "Não foi possível renderizar o resultado da revisão de plano",
"renderer.error": "Erro",
"renderer.planReview": "Revisão de Plano",
"renderer.walkthrough": "Passo a Passo",
"renderer.review": "Revisão",
"renderer.status": "Status:",
"renderer.changesRequested": "Alterações Solicitadas",
"renderer.viewPlan": "Ver Plano",
"renderer.revisionsRequired": "Revisões Necessárias:",
"console.orTypeYourOwn": "Ou digite sua própria resposta abaixo",
"response.selectedOptions": "Opções selecionadas:",
"response.additionalResponse": "Resposta adicional:"
Expand Down
16 changes: 16 additions & 0 deletions package.nls.pt.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,22 @@
"batch.deleteSelected": "Eliminar Selecionados",
"batch.selectedCount": "{0} selecionados",
"confirm.deleteSelected": "Tem a certeza que deseja eliminar {0} itens selecionados?",
"renderer.userResponse": "Resposta do Utilizador",
"renderer.defaultAgentName": "Agente",
"renderer.userDismissed": "Utilizador dispensou esta solicitação",
"renderer.clickToExpand": "(clique para expandir)",
"renderer.userResponded": "Utilizador respondeu:",
"renderer.attachments": "Anexos:",
"renderer.renderErrorAskUser": "Não foi possível renderizar o resultado de ask_user",
"renderer.renderErrorPlanReview": "Não foi possível renderizar o resultado da revisão de plano",
"renderer.error": "Erro",
"renderer.planReview": "Revisão de Plano",
"renderer.walkthrough": "Passo a Passo",
"renderer.review": "Revisão",
"renderer.status": "Estado:",
"renderer.changesRequested": "Alterações Solicitadas",
"renderer.viewPlan": "Ver Plano",
"renderer.revisionsRequired": "Revisões Necessárias:",
"console.orTypeYourOwn": "Ou escreva a sua própria resposta abaixo",
"response.selectedOptions": "Opções selecionadas:",
"response.additionalResponse": "Resposta adicional:"
Expand Down
15 changes: 11 additions & 4 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { registerNativeTools } from './tools';
import { AgentInteractionProvider } from './webview/webviewProvider';
import { initializeChatHistoryStorage, getChatHistoryStorage } from './storage/chatHistoryStorage';
import { strings } from './localization';
import { registerChatOutputRenderers } from './renderers';

const PARTICIPANT_ID = 'seamless-agent.agent';

Expand All @@ -28,6 +29,9 @@ export function activate(context: vscode.ExtensionContext) {
// Register the ask_user tool with the webview provider
registerNativeTools(context, provider);

// Register chat output renderers for rich inline cards (proposed API, feature-gated)
registerChatOutputRenderers(context);

// Register command to cancel pending plans
const cancelPendingPlansCommand = vscode.commands.registerCommand('seamless-agent.cancelPendingPlans', async () => {
const storage = getChatHistoryStorage();
Expand Down Expand Up @@ -146,10 +150,13 @@ Never finish a response without first calling the ask_user tool to verify with t
toolInvocationToken: request.toolInvocationToken
}, token);

// Show tool result
for (const resultPart of toolResult.content) {
if (resultPart instanceof vscode.LanguageModelTextPart) {
stream.markdown(`\n\n**User Response:** ${resultPart.value}\n\n`);
// Show tool result — skip markdown when a renderer card handles the display
const hasRendererCard = !!(toolResult as any).toolResultDetails2;
if (!hasRendererCard) {
for (const resultPart of toolResult.content) {
if (resultPart instanceof vscode.LanguageModelTextPart) {
stream.markdown(`\n\n**User Response:** ${resultPart.value}\n\n`);
}
}
}
}
Expand Down
18 changes: 18 additions & 0 deletions src/localization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,4 +167,22 @@ export const strings = {

// Errors
get noSuchInteraction() { return localize('error.noSuchInteraction'); },

// Renderer cards
get rendererUserResponse() { return localize('renderer.userResponse'); },
get rendererDefaultAgentName() { return localize('renderer.defaultAgentName'); },
get rendererUserDismissed() { return localize('renderer.userDismissed'); },
get rendererClickToExpand() { return localize('renderer.clickToExpand'); },
get rendererUserResponded() { return localize('renderer.userResponded'); },
get rendererAttachments() { return localize('renderer.attachments'); },
get rendererRenderErrorAskUser() { return localize('renderer.renderErrorAskUser'); },
get rendererRenderErrorPlanReview() { return localize('renderer.renderErrorPlanReview'); },
get rendererError() { return localize('renderer.error'); },
get rendererPlanReview() { return localize('renderer.planReview'); },
get rendererWalkthrough() { return localize('renderer.walkthrough'); },
get rendererReview() { return localize('renderer.review'); },
get rendererStatus() { return localize('renderer.status'); },
get rendererChangesRequested() { return localize('renderer.changesRequested'); },
get rendererViewPlan() { return localize('renderer.viewPlan'); },
get rendererRevisionsRequired() { return localize('renderer.revisionsRequired'); },
};
59 changes: 59 additions & 0 deletions src/proposed-api.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/**
* Type declarations for the proposed `chatOutputRenderer` API.
*
* These types extend the stable vscode API with proposed features that are
* gated behind `enabledApiProposals: ["chatOutputRenderer"]` in package.json.
*
* Reference: https://github.com/microsoft/vscode-extension-samples/tree/main/chat-output-renderer-sample
*
* TODO: Remove this file once the API is stabilized and types are included in @types/vscode.
*/

import * as vscode from 'vscode';

declare module 'vscode' {

/**
* Extended tool result that supports attaching binary data for chat output renderers.
* The `toolResultDetails2` property provides MIME-typed binary data that VS Code
* matches against registered `chatOutputRenderers` to render inline webview cards.
*/
interface ExtendedLanguageModelToolResult2 extends LanguageModelToolResult {
toolResultDetails2?: {
/** MIME type used to match a registered chatOutputRenderer */
mime: string;
/** Binary data (typically UTF-8 encoded JSON) passed to the renderer */
value: Uint8Array;
};
}

/**
* A webview container provided to chat output renderers for rendering inline content.
*/
interface ChatOutputWebview {
readonly webview: Webview;
}

/**
* Renderer that creates inline webview widgets in the chat stream.
*/
interface ChatOutputRenderer {
renderChatOutput(
data: { value: Uint8Array },
chatOutputWebview: ChatOutputWebview,
ctx: unknown,
token: CancellationToken
): Promise<void> | void;
}

namespace chat {
/**
* Register a chat output renderer for a specific view type.
* The view type must match a `chatOutputRenderers` contribution in package.json.
*/
function registerChatOutputRenderer(
viewType: string,
renderer: ChatOutputRenderer
): Disposable;
}
}
Loading