feat: add CopilotService gRPC service for extension framework#7172
feat: add CopilotService gRPC service for extension framework#7172wbreza wants to merge 10 commits intoAzure:mainfrom
Conversation
6477432 to
f4f408a
Compare
49702ee to
49a3df1
Compare
Add a new CopilotService gRPC service that exposes Copilot agent capabilities to extensions through 8 RPCs: - CreateSession: Create agent sessions with full configuration (model, reasoning effort, system message, mode, headless) - ResumeSession: Resume existing sessions by ID - ListSessions: List available sessions for a working directory - Initialize: Non-interactive first-run configuration - SendMessage: Send prompts and block until completion - GetUsageMetrics: Cumulative usage metrics across calls - GetFileChanges: Track files created/modified/deleted - StopSession: Clean up session resources Core agent changes: - Add WithHeadless option for silent operation via gRPC - Add HeadlessCollector as display replacement for headless mode - Add cumulative usage metrics tracking (GetCumulativeUsage) - Auto-approve permissions in headless mode - Add GetFileChanges() to watch.Watcher interface Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…C API Add azd demo copilot command that implements an interactive chat loop showcasing the full CopilotService gRPC integration: - CreateSession with configurable model, reasoning, system message, mode - Initialize to display resolved model/reasoning configuration - SendMessage in an interactive chat loop with per-turn usage metrics - GetUsageMetrics for cumulative session stats on exit - GetFileChanges for file change summary (created/modified/deleted) - StopSession for cleanup - ListSessions + ResumeSession via --resume flag Flags: --model, --reasoning-effort, --system-message, --mode, --resume Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…early The CopilotService.CreateSession gRPC handler was only creating the CopilotAgent struct without starting the underlying Copilot SDK client. This caused startup errors (auth, binary download, runtime crashes) to surface only on the first SendMessage call, making debugging confusing. Changes: - Add CopilotAgent.EnsureStarted() public method for eager client startup - Call EnsureStarted() in both CreateSession and ResumeSession handlers - Fix double 'failed to create session' error wrapping in ensureSession Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ssion Rework the CopilotService gRPC API based on design review: API changes (8 RPCs → 6): - Remove CreateSession, ResumeSession — session lifecycle is now implicit - SendMessage handles session creation/resumption inline via optional session_id field. First call creates a session, subsequent calls reuse it. Passing an SDK session_id resumes that session. - SendMessage response now includes per-turn file changes - Initialize is session-independent — just warms up client and resolves config Architecture changes: - CopilotAgent now owns file change accumulation (watcher per SendMessage, changes appended to agent cache) - New PrintSessionMetrics() prints usage + file changes (replaces auto-print) - Remove auto-printing of usage/file changes from SendMessage — callers decide when to display (init calls PrintSessionMetrics at the end) - gRPC service is thin routing layer — maps session IDs to agents Demo extension updated to use new API — SendMessage with inline config, Initialize for warmup, GetUsageMetrics/GetFileChanges at end. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Remove per-turn usage metrics display — shown only at end via GetUsageMetrics - Remove headless=true — agent output (thinking, tools, responses) should be visible in the demo chat experience Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Agent changes: - Remove stored sessionCtx from CopilotAgent — use atomic.Pointer for active context, updated per SendMessage call (SDK callbacks read it) - Use context.WithoutCancel in ensureSession so SDK client/session outlive individual gRPC request contexts (fixes CLI process crash on 2nd message) - Improve Stop() — clear cleanup tasks (idempotent), return first error - Skip plugin management in headless mode - Plugin detection fallback: when 'copilot plugin list' reports no plugins but they exist on disk, scan directory directly (CLI version mismatch workaround) - PrintSessionMetrics now prints file changes before usage metrics Demo extension: - Remove per-turn usage display and headless mode - Remove turn number prefixes from prompt - Remove 'Sending to agent' message Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…e tests Extract Agent and AgentFactory interfaces from the concrete CopilotAgent and CopilotAgentFactory types, enabling unit testing of the gRPC service layer without a real Copilot SDK runtime. Interface changes: - Agent interface: Initialize, SendMessage, SendMessageWithRetry, ListSessions, GetUsage, GetFileChanges, SessionID, Stop - AgentFactory interface: Create(ctx, opts...) (Agent, error) - Rename GetCumulativeUsage → GetUsage, GetAccumulatedFileChanges → GetFileChanges Tests (12 test cases): - SendMessage: new session, reuse session, resume SDK session, empty prompt - GetUsageMetrics: valid session, unknown session, empty session_id - GetFileChanges: valid session with changes - StopSession: valid cleanup, unknown session - Initialize: delegates to agent - SendMessage with file changes in response Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
4ef0eac to
6b9695f
Compare
Replace separate GetUsage/GetFileChanges/PrintSessionMetrics with a unified AgentMetrics type: - AgentMetrics.String() prints file changes then usage metrics - UsageMetrics.Format() renamed to String() (implements fmt.Stringer) - watch.FileChanges named slice type with String() for formatted display - watch.FileChange.String() for individual file change display - Agent interface: GetMetrics() replaces GetUsage/GetFileChanges/PrintSessionMetrics - AgentFactory returns AgentFactory interface, not concrete type - All callers updated: init.go, error middleware, gRPC service, tests - watch.PrintChangedFiles deprecated in favor of GetFileChanges().String() Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
b52a76d to
4631416
Compare
There was a problem hiding this comment.
Pull request overview
Adds a new CopilotService gRPC surface to the azd extension framework and wires it through the CLI/agent layers so extensions can create/resume sessions, send messages, and retrieve cached usage + file-change metrics. This includes new proto + generated bindings, server/client wiring, agent “headless” execution support, and a demo extension command.
Changes:
- Introduces
CopilotServicegRPC API (copilot.proto) with generated Go bindings and azd client/server registration. - Enhances the Copilot agent with headless collection, cumulative metrics (usage + file changes), and factory interfaces for testability.
- Adds file-change collection utilities in
pkg/watchplus unit tests, and a demo extension command (azd demo copilot) exercising the API.
Reviewed changes
Copilot reviewed 24 out of 24 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| cli/azd/grpc/proto/copilot.proto | Defines the new CopilotService RPCs and message types. |
| cli/azd/pkg/azdext/copilot.pb.go | Generated protobuf types for CopilotService. |
| cli/azd/pkg/azdext/copilot_grpc.pb.go | Generated gRPC client/server stubs for CopilotService. |
| cli/azd/pkg/azdext/azd_client.go | Adds lazy Copilot() client accessor. |
| cli/azd/internal/grpcserver/server.go | Registers CopilotService on the gRPC server. |
| cli/azd/internal/grpcserver/server_test.go | Updates server tests to include CopilotService. |
| cli/azd/internal/grpcserver/prompt_service_test.go | Updates test server setup to include CopilotService. |
| cli/azd/internal/grpcserver/copilot_service.go | Implements the CopilotService RPC handlers and session routing. |
| cli/azd/internal/grpcserver/copilot_service_test.go | Adds unit tests for CopilotService behavior. |
| cli/azd/internal/agent/types.go | Adds Agent/AgentFactory interfaces and AgentMetrics (usage + file changes); renames UsageMetrics formatting to String(). |
| cli/azd/internal/agent/types_test.go | Updates tests to use UsageMetrics.String(). |
| cli/azd/internal/agent/headless_collector.go | Adds headless event collector for gRPC/headless sessions. |
| cli/azd/internal/agent/headless_collector_test.go | Adds tests for headless collector behavior. |
| cli/azd/internal/agent/copilot_agent_factory.go | Returns AgentFactory and Agent interfaces for decoupling/tests. |
| cli/azd/internal/agent/copilot_agent.go | Adds headless mode, cumulative metrics, file-change tracking, and context persistence tweaks. |
| cli/azd/internal/agent/copilot/cli.go | Adds plugin detection fallback by scanning plugin directories on disk. |
| cli/azd/pkg/watch/watch.go | Adds GetFileChanges() API + formatting and change-type enum. |
| cli/azd/pkg/watch/watch_test.go | Adds tests for new watch file-change tracking. |
| cli/azd/extensions/microsoft.azd.demo/internal/cmd/root.go | Registers the new demo copilot command. |
| cli/azd/extensions/microsoft.azd.demo/internal/cmd/copilot.go | Implements interactive Copilot demo command using gRPC API. |
| cli/azd/extensions/microsoft.azd.demo/extension.yaml | Documents the new demo command. |
| cli/azd/cmd/middleware/error.go | Switches agent factory type + uses UsageMetrics.String(). |
| cli/azd/cmd/init.go | Prints combined session metrics (usage + file changes) after copilot run. |
| cli/azd/cmd/container.go | Registers CopilotService in IoC container. |
… safety Watch tests: - Replace time.Sleep with require.Eventually for deterministic polling - Sort FileChanges by path for stable output Agent (copilot_agent.go): - Fix watcher leak: use per-turn context.WithCancel, cancel in defer - Log NewWatcher errors instead of ignoring - Add sync.Mutex to guard cumulative metrics and file changes - GetMetrics() acquires lock for thread-safe reads gRPC service (copilot_service.go): - Stop newly-created agent if SendMessage fails (prevents process leak) - Log Stop() errors in StopSession instead of silently dropping Proto: - Update headless field comment to not imply a proto3 default Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Azure Dev CLI Install InstructionsInstall scriptsMacOS/Linux
bash: pwsh: WindowsPowerShell install MSI install Standalone Binary
MSI
Documentationlearn.microsoft.com documentationtitle: Azure Developer CLI reference
|
Summary
Adds a new CopilotService gRPC service to the azd extension framework, enabling extensions to interact with Copilot agent capabilities programmatically. Includes a demo extension command showcasing the full API.
CopilotService gRPC API (6 RPCs)
Design Decisions
Core Agent Enhancements
Demo Extension
Testing