Documentation
¶
Overview ¶
Package copilotcli is the GitHub Copilot CLI provider: CopilotCLIExecutor drives the Copilot command line as a turn executor for one session CSF owns. Each turn is one Copilot process, started through the ipc/proc capability on the session's identifier, which Copilot creates on the first turn and resumes with its history on every later one.
Every non-ephemeral record Copilot writes is reported to a structured log under the turn's trace, in the record shape the Claude Code turn executor writes. The two records the harness reads back are reported in Claude Code's stream-json shape, with Copilot's own record kept under "copilot": an assistant message becomes an "assistant" event whose tool calls carry the Claude Code tool names, and the turn's result becomes a "result" event carrying the token and cache usage Copilot wrote to its usage file. So a run's log reads the same whichever executor ran the turn.
It is unrelated to ipc/model/copilot, the Copilot Workbench client.
Index ¶
- Constants
- Variables
- type CopilotCLIExecutor
- func (executor *CopilotCLIExecutor) Close(ctx context.Context) error
- func (executor *CopilotCLIExecutor) Interrupt(ctx context.Context) error
- func (executor *CopilotCLIExecutor) Propose(ctx context.Context, turn *Turn) (*model.Proposal[Event], error)
- func (executor *CopilotCLIExecutor) Session() uuid.UUID
- type CopilotCLIExecutorOption
- func WithArguments(arguments ...string) CopilotCLIExecutorOption
- func WithDirectory(directory string) CopilotCLIExecutorOption
- func WithEnvironment(variables ...string) CopilotCLIExecutorOption
- func WithExecutable(executable string) CopilotCLIExecutorOption
- func WithLaunchPrefix(prefix ...string) CopilotCLIExecutorOption
- func WithLogger(logger *slog.Logger) CopilotCLIExecutorOption
- func WithUsageFile(path string) CopilotCLIExecutorOption
- type Event
- type ToolGrants
- type Turn
- type TurnError
Constants ¶
const ( // EventTypeAssistant is an assistant message, in Claude Code's shape. EventTypeAssistant = "assistant" // EventTypeResult is the event that ends a turn. EventTypeResult = "result" // EventTypeUser names the prompt the executor was given, in the report // only, and a tool's result, both in Claude Code's stream-json user // message shape. EventTypeUser = "user" )
Copilot record types the executor reads, and the Claude Code stream-json types and fields it reports them as.
const DefaultExecutable = "copilot"
DefaultExecutable is the Copilot command line, resolved on PATH.
const PinnedVersion = "1.0.90"
PinnedVersion is the Copilot CLI version the harness's Copilot sessions were measured on: its flags, record shapes, hook payloads and usage file.
const ProviderName = "copilotcli"
ProviderName names the Copilot CLI provider in turn reports and proposals.
Variables ¶
var ( // ErrNoLauncher reports an executor constructed without the process // capability. ErrNoLauncher = errors.New("copilotcli executor: a process launcher is required") // ErrNoSession reports an executor constructed without a session // identifier. ErrNoSession = errors.New("copilotcli executor: a nonzero session identifier is required") // ErrInvalidOption reports a nil option or an option value the executor // cannot use. ErrInvalidOption = errors.New("copilotcli executor: invalid option") // ErrNoPrompt reports a nil turn or a turn with an empty prompt. ErrNoPrompt = errors.New("copilotcli executor: a turn needs a prompt") // ErrMalformedEvent reports an output line that is not a Copilot JSON // record. ErrMalformedEvent = errors.New("copilotcli executor: Copilot wrote a line that is not a JSON record") // ErrTurnIncomplete reports a Copilot process that exited without the // result record that ends a turn. ErrTurnIncomplete = errors.New("copilotcli executor: Copilot exited before reporting the turn's result") // ErrTurnFailed reports a result record with a nonzero exit code. ErrTurnFailed = errors.New("copilotcli executor: Copilot reported a failed turn") // ErrSessionMismatch reports a result for another session than the one // the executor runs. ErrSessionMismatch = errors.New("copilotcli executor: Copilot reported another session") // ErrInterrupted reports a turn whose process Interrupt stopped. ErrInterrupted = errors.New("copilotcli executor: the turn was interrupted") // ErrClosed reports a turn or an interrupt on a closed executor, and a // turn Close stopped. ErrClosed = errors.New("copilotcli executor: the executor is closed") )
var ErrUntranslatableTool = errors.New("copilotcli executor: the tool rule has no Copilot equivalent")
ErrUntranslatableTool reports a Claude Code tool rule that has no Copilot equivalent. A recipe carrying one cannot run on Copilot: dropping the rule would narrow the session and widening it would break the allowlist.
Functions ¶
This section is empty.
Types ¶
type CopilotCLIExecutor ¶
type CopilotCLIExecutor struct {
// contains filtered or unexported fields
}
CopilotCLIExecutor runs the turns of one Copilot session, one process per turn. Turns never overlap: Propose waits for the previous turn to finish. Interrupt stops the running turn's process; Close stops it, waits for the turn to return and refuses every later one. The executor starts no goroutine of its own: each turn's process runs, and is reaped, inside the Propose that started it.
func NewCopilotCLIExecutor ¶
func NewCopilotCLIExecutor(launcher proc.ILauncher, session uuid.UUID, options ...CopilotCLIExecutorOption) (*CopilotCLIExecutor, error)
NewCopilotCLIExecutor builds the Copilot turn executor for session. The launcher is the process capability every turn's Copilot process is started through; the caller owns it.
func (*CopilotCLIExecutor) Close ¶
func (executor *CopilotCLIExecutor) Close(ctx context.Context) error
Close stops the running turn, if any, waits for it to return and refuses every later turn. ctx bounds the wait. It is idempotent.
func (*CopilotCLIExecutor) Interrupt ¶
func (executor *CopilotCLIExecutor) Interrupt(ctx context.Context) error
Interrupt stops the running turn's process; the turn returns ErrInterrupted. Between turns there is nothing to stop.
func (*CopilotCLIExecutor) Propose ¶
func (executor *CopilotCLIExecutor) Propose(ctx context.Context, turn *Turn) (*model.Proposal[Event], error)
Propose runs one turn: it starts Copilot on the session with the prompt and returns every record reported for it, in order, ending with the result. ctx bounds the turn's process. A turn that does not reach a successful result returns a *TurnError carrying the records reported before the failure.
func (*CopilotCLIExecutor) Session ¶
func (executor *CopilotCLIExecutor) Session() uuid.UUID
Session is the session identifier CSF gave this executor.
type CopilotCLIExecutorOption ¶
type CopilotCLIExecutorOption func(executor *CopilotCLIExecutor) error
CopilotCLIExecutorOption configures a CopilotCLIExecutor.
func WithArguments ¶
func WithArguments(arguments ...string) CopilotCLIExecutorOption
WithArguments appends arguments to every Copilot invocation, after the flags the executor owns, which may not be repeated.
func WithDirectory ¶
func WithDirectory(directory string) CopilotCLIExecutorOption
WithDirectory runs Copilot in directory instead of the caller's working directory.
func WithEnvironment ¶
func WithEnvironment(variables ...string) CopilotCLIExecutorOption
WithEnvironment appends variables, as NAME=value, to the environment every Copilot process inherits.
func WithExecutable ¶
func WithExecutable(executable string) CopilotCLIExecutorOption
WithExecutable runs Copilot from executable, a path or a name on PATH, instead of DefaultExecutable.
func WithLaunchPrefix ¶
func WithLaunchPrefix(prefix ...string) CopilotCLIExecutorOption
WithLaunchPrefix wraps every Copilot process: the process started is prefix[0], with prefix[1:] ahead of the Copilot executable and its arguments. The session sandbox puts its launcher here.
func WithLogger ¶
func WithLogger(logger *slog.Logger) CopilotCLIExecutorOption
WithLogger reports every turn and record to logger instead of slog.Default().
func WithUsageFile ¶
func WithUsageFile(path string) CopilotCLIExecutorOption
WithUsageFile has every turn write Copilot's usage statistics to path, replaced each turn, and report the tokens and cache usage it holds on the turn's result. Without it the result carries no token counts: Copilot's stream reports none.
type Event ¶
type Event struct {
Type string
Raw json.RawMessage
}
Event is one record the executor reported for a turn: Type is its type and Raw the record as reported.
type ToolGrants ¶
ToolGrants is a recipe's tool rules as Copilot takes them: the tools the model is shown (--available-tools) and the permissions it holds without asking (--allow-tool). Nothing else is available, and a permission not granted is denied, since nobody answers a prompt. AllPaths is set when the shell is granted: Copilot also denies a shell command naming a path outside the working directory, which Claude Code's shell rules never do, and a session that may run the shell can reach any path through it anyway.
func TranslateToolRules ¶
func TranslateToolRules(rules []string) (ToolGrants, error)
TranslateToolRules translates Claude Code tool rules into Copilot's grants: "Bash" grants the shell, "Bash(pattern)" the shell for commands matching the pattern, "mcp__server__tool" one MCP tool, and Read, Write, Edit, MultiEdit, Glob and Grep their Copilot tools. Any other rule is ErrUntranslatableTool.
type Turn ¶
type Turn struct {
Prompt string
}
Turn is what one Copilot turn decides on: the prompt, passed to Copilot unchanged.