Skip to content

Function Host Debugger View#4883

Open
nturinski wants to merge 55 commits intomainfrom
nat/debuggerView
Open

Function Host Debugger View#4883
nturinski wants to merge 55 commits intomainfrom
nat/debuggerView

Conversation

@nturinski
Copy link
Member

This PR adds a Function Host Debug view to the Azure Functions extension. The view appears in the Run and Debug panel and lists running Function Host tasks along with their recent error output.

A new tree view provider backs this view and supplies nodes for active hosts and error entries. The view includes commands to refresh the data, clear recorded errors, view or copy recent logs, and send an error to Copilot. These commands are available from the view toolbar and node context menus.

The PR also introduces a setting to always show the Function Host Debug view, regardless of context.

Supporting changes include exporting shared utilities for identifying host error logs and cleaning log output, extending command handling to accept argument arrays, and updating the Functions task provider to allow additional CLI arguments in task definitions.

No host running (only visible if always show setting is enabled)
image

Function host running with no errors
image

Function host running with an error
image

Location of Ask Copilot context menu
image

nturinski and others added 30 commits October 24, 2025 10:55
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link
Contributor

Copilot AI commented Jan 15, 2026

@nturinski I've opened a new pull request, #4886, to work on those changes. Once the pull request is ready, I'll request review from you.

nturinski and others added 2 commits January 14, 2026 16:03
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link
Contributor

Copilot AI commented Jan 15, 2026

@nturinski I've opened a new pull request, #4887, to work on those changes. Once the pull request is ready, I'll request review from you.

Copilot AI and others added 2 commits January 14, 2026 16:15
…4885)

* Initial plan

* Add JSDoc documentation for IStartFuncProcessResult interface

Co-authored-by: nturinski <5290572+nturinski@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: nturinski <5290572+nturinski@users.noreply.github.com>
* Initial plan

* Add AbortController to prevent infinite stream iteration

Co-authored-by: nturinski <5290572+nturinski@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: nturinski <5290572+nturinski@users.noreply.github.com>
Copy link
Contributor

Copilot AI commented Jan 15, 2026

@nturinski I've opened a new pull request, #4888, to work on those changes. Once the pull request is ready, I'll request review from you.

nturinski and others added 2 commits January 14, 2026 16:35
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Removed exhaustive check for FuncHostDebugNode.
const funcCliPath = await getFuncCliPath(context, folder);
const args = (definition?.args || []) as string[];
if (args.length > 0) {
command = `${command} ${args.join(' ')}`;
Copy link
Contributor

Choose a reason for hiding this comment

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

Since the VSCode Task API accepts argument lists, why not use that?

Comment on lines +20 to +29
const candidates: Array<{ command: string; args: unknown[] }> = [
// Newer VS Code variants
{ command: 'workbench.action.chat.open', args: [trimmed] },
{ command: 'workbench.action.chat.open', args: [{ query: trimmed }] },
// Older / alternate variants
{ command: 'workbench.action.openChat', args: [trimmed] },
// Copilot extensions (IDs vary by version)
{ command: 'github.copilot.openChat', args: [trimmed] },
{ command: 'github.copilot-chat.openChat', args: [trimmed] },
];
Copy link
Contributor

Choose a reason for hiding this comment

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

Does the minimum VSCode version we have in this extension exclude any of these?

@MicroFish91
Copy link
Contributor

Very cool, I have it as a todo to review this either tomorrow or early next week!

return tasks;
}

async function updateFuncHostDebugContext(): Promise<void> {
Copy link
Contributor

@MicroFish91 MicroFish91 Jan 28, 2026

Choose a reason for hiding this comment

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

I'm running into an issue on error where the Function Host Debug view is not showing up. Well, at least that's what it appeared like initially. In reality, after I set some breakpoints, I realized that it actually is getting shown, but then immediately gets hidden.

I think for some reason this update function is called to show the view, and then for some reason gets called again and causes the view to hide.

My repro steps were: (1) create a DTS project via createNewProject, (2) hit F5, and (3) answer skip for now so nothing gets set for both connections. This causes this func CLI error which I was expecting to show up:

Image

I should be in office tomorrow so if you're not able to repro maybe we can investigate on my machine, lmk!

Nathan Turinski and others added 2 commits March 11, 2026 17:06
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@nturinski
Copy link
Member Author

@copilot Do another PR review

Copy link
Contributor

Copilot AI commented Mar 12, 2026

@nturinski I've opened a new pull request, #4928, to work on those changes. Once the pull request is ready, I'll request review from you.

const taskDirectory = taskExecution.options?.cwd?.replace('${workspaceFolder}', (t.taskExecution.task?.scope as vscode.WorkspaceFolder).uri?.path);
buildPath = buildPath?.replace('${workspaceFolder}', (t.taskExecution.task?.scope as vscode.WorkspaceFolder).uri?.path);
return taskDirectory && buildPath && normalizePath(taskDirectory) === normalizePath(buildPath);
const resolvedBuildPath = buildPath?.replace('${workspaceFolder}', (t.taskExecution.task?.scope as vscode.WorkspaceFolder).uri?.path);
Copy link
Member

Choose a reason for hiding this comment

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

task.scope can be a TaskScope enum value (just a number), not only a WorkspaceFolder. Casting it here without checking means .uri?.path evaluates to undefined, and String.replace() will happily coerce that to the literal string "undefined" — so you'd end up with paths like /some/path/undefined/sub instead of the original unresolved string.

We already do the right typeof check in registerFunctionHostDebugView.ts, so maybe something like:

const workspacePath = typeof t.taskExecution.task?.scope === 'object'
    ? (t.taskExecution.task.scope as vscode.WorkspaceFolder).uri?.path
    : undefined;
const taskDirectory = workspacePath
    ? taskExecution.options?.cwd?.replace('${workspaceFolder}', workspacePath)
    : taskExecution.options?.cwd;
const resolvedBuildPath = workspacePath
    ? buildPath?.replace('${workspaceFolder}', workspacePath)
    : buildPath;

Comment on lines +109 to +113
const funcTaskStartedEmitter = new vscode.EventEmitter<{ scope: vscode.WorkspaceFolder | vscode.TaskScope, execution?: vscode.ShellExecution }>();
export const onFuncTaskStarted = funcTaskStartedEmitter.event;

const runningFuncTasksChangedEmitter = new vscode.EventEmitter<void>();
export const onRunningFuncTasksChanged = runningFuncTasksChangedEmitter.event;
Copy link
Member

Choose a reason for hiding this comment

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

these emitters are never disposed

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, the issue is that we need to create them when the extension is activated, and if we dispose them after a function host task is terminated, they never get instantiated again.

I went ahead and disposed them on deactivation, which I think should happen anyway, but just to be explicit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants