Vai al contenuto principale

RPC (Remote Procedure Call)

Nell’SDK ufficiale le funzionalità più recenti sono supportate tramite generazione automatica di codice a partire da api.schema.json. Nella versione Laravel implementiamo le stesse cose facendo riferimento alle versioni generate degli altri linguaggi.

ServerRpc

Classe RPC associata al Client.

Connessione, modelli, strumenti e account

Con ping() e connect() verifichi e avvii la connessione, mentre con registerExtensionLaunchProvider() registri il provider di avvio delle estensioni. L’elenco dei modelli, le unità di prezzo e il catalogo integrato si ottengono da models(), mentre l’elenco degli strumenti disponibili da tools(). account() gestisce quota, stato di autenticazione, elenco degli utenti connessi, login e logout, mentre accounts() si occupa del recupero dei token di Microsoft Entra ID.

MCP, connettori e secret

mcp() fornisce elenco, aggiunta, aggiornamento ed eliminazione delle configurazioni MCP, abilitazione, rilevamento, ricerca nel registry, pianificazione e applicazione delle installazioni. Con connectors() puoi verificare le funzionalità, gli account e il catalogo dei connettori. Le operazioni sui connettori lato server riguardano principalmente il recupero e l’aggiornamento degli elenchi per account. secrets()->addFilterValues(), sperimentale, registra nel filtro di redazione della CLI i secret dinamici generati dal tuo host. La CLI maschera quindi questi valori nei log e nelle esportazioni della sessione.
Questa RPC non recupera token OAuth. L’SDK non persiste i valori né li scrive in log aggiuntivi. Registra valori che il tuo host ha già ottenuto.

Skills, Plugins, Agents, Instructions ed Extensions

Da ciascun gruppo puoi eseguire l’esplorazione, il recupero dei percorsi disponibili, la modifica delle impostazioni e il ricaricamento. commands() fornisce l’elenco dei comandi integrati e hooks() l’esplorazione degli hook prima dell’avvio della sessione. Skills e Plugins supportano abilitazione, disabilitazione e gestione delle installazioni, mentre Agents consente anche di ottenere informazioni sugli agenti integrati. Extensions esplora, abilita e disabilita le estensioni persistite.

Catalogo e installazione

Con catalog() esegui ricerca, recupero dei consigli sui prodotti ufficiali, selezione dei candidati e recupero dei feed; con le API di Skills, Plugins e MCP verifichi i piani di installazione, li applichi, interroghi lo stato o annulli le operazioni. Pianificazione e applicazione sono operazioni separate. Per esempi concreti di installazione consulta le rispettive sezioni più avanti.

Sessioni, host e ambiente di esecuzione

sessions() gestisce la ricerca delle sessioni persistite, la lettura degli eventi, la verifica delle dimensioni, l’eliminazione e la pulizia, e il fork. Sono disponibili anche la creazione e il caricamento di Workspace e il controllo remoto. host() avvia l’host, pubblica, elenca e ritira la pubblicazione delle sessioni, gestisce l’autenticazione, modifica la policy di ammissione delle sessioni e lo distrugge. Queste RPC host sono alla base dell’API host AHP (Agent Host Protocol) di alto livello dell’SDK, mentre runtime() gestisce il ciclo di vita del runtime.

Attività dell’agente cloud (experimental)

cloudTasks() crea, elimina e recupera le attività dell’agente di coding cloud, ottiene log e replay delle sessioni, modifica lo stato di condivisione e risolve la sessione da aprire a partire da un ID attività. Ogni metodo accetta il tipo Params corrispondente o un array e restituisce un DTO tipizzato. Quando ok nel risultato della creazione è false, controlla reason e message per il motivo del rifiuto da parte del servizio, e statusCode, errorMessage ed errorPayloadJson per le informazioni sull’errore della richiesta HTTP eseguita.

Git, ambienti, sandbox e policy

Da git() ottieni informazioni su branch, directory di lavoro e Git remote, mentre da gitHubRepository() e gitHubOwners() puoi esplorare repository e proprietari GitHub. environments() gestisce gli ambienti Mission Control, sandbox() e sandboxProxyCa() il supporto sandbox e la Proxy CA, contentExclusion() la verifica delle policy di esclusione, e managedSettings() e userSettings() le impostazioni. Usa settings() per rimuovere singole chiavi da un file di impostazioni e mascherare i valori da visualizzare. gitHubRepository()->getById() risolve owner e nome a partire da un ID di repository GitHub, e lookupBranchPullRequest() cerca nei repository indicati, in ordine di priorità, una pull request dell’head owner e del branch indicati. Entrambi ricevono authInfo così com’è. Il risultato di getById() contiene owner e nome in repository, oppure null se il repository non viene trovato. Lo status della ricerca di pull request è found, no-token, no-pr o lookup-failed. I valori sconosciuti vengono mantenuti come stringhe, quindi non generano eccezioni. pullRequest è un array associativo quando viene trovata una pull request, altrimenti null.
gitHubFetch() fornisce richieste autenticate all’API GitHub e operazioni con nome, mentre gitHubRelease() fornisce ricerca delle release, snapshot, download degli asset e verifica dell’avanzamento. In Fetch, sessionId seleziona l’autenticazione di una sessione. Se omesso, viene usata l’autenticazione del processo. Specifica authOwnerId per usare un binding di autenticazione gestito dall’host. In Release, authInfo seleziona credenziali gestite dal runtime, e le release pubbliche possono essere cercate e scaricate in modo anonimo. Elimina tu stesso il path scaricato dopo l’uso. allocateRequestId(), request() ed executeOperation() di Fetch e abandonRequest(), getSnapshot() e downloadAsset() di Release non possono essere chiamati dalle Extensions. L’SDK Laravel attualmente non espone l’RPC cancel di nessuno dei due gruppi, quindi non puoi annullare dall’SDK un’operazione in corso. abandonRequest() scarta un ID di richiesta Release non utilizzato e non interrompe un’operazione in corso.

Modelli locali, inferenza HTTP e file system

azureMl() fornisce catalogo, risoluzione e download dei modelli locali, oltre a verifica dello stato, annullamento ed eliminazione. llmInference() è un’API sperimentale che inoltra al lato client le richieste HTTP del livello modello. sessionFs() registra il provider di callback file system/SQLite della sessione.

Callback di rete (experimental)

network()->setProvider() comunica al runtime le callback di risoluzione del proxy e di autenticazione Kerberos registrate sul client. Normalmente l’opzione network del Client le registra automaticamente, quindi non è necessario chiamare direttamente questo RPC. I campi callback di NetworkSetProviderRequest indicano che l’handler corrispondente è registrato. L’RPC non restituisce alcun valore. Il runtime deve supportare l’RPC network.setProvider. In caso contrario, il client lancia all’avvio un’eccezione che ti invita ad aggiornare il runtime. Per i dettagli consulta Autenticazione.
scope è connection per impostazione predefinita. runtime copre anche le comunicazioni condivise in background, ma solo una connessione alla volta può registrarsi con questo scope.

RPC interni e sperimentali

I seguenti RPC sono contrassegnati come interni nell’SDK ufficiale, ma Laravel li espone come @experimental. Potrebbero cambiare o essere rimossi in futuro, e le restrizioni sul chiamante del runtime continuano ad applicarsi. Usali per creare, elencare e rimuovere voci del registro degli agenti, aprire un URL di autenticazione nel browser, ripulire output di grandi dimensioni scaduti degli strumenti e ottenere gli avvisi di concessione dei percorsi della sandbox. I risultati degli elenchi non includono le credenziali di connessione.

Esempio di chiamata di base

Anche le funzionalità già incluse nell’SDK sono state aggiunte nuovamente nella versione a generazione automatica del codice.

Esempi d’uso per funzionalità

Di seguito sono riassunti esempi di chiamata rappresentativi per le funzionalità descritte sopra.

Candidati Agent Plugin del catalog

Richiedendo agent-plugin-discovery in catalog.search e specificando plugin nei kinds di ricerca, puoi ottenere candidati Agent Plugin. Per ricevere application/vnd.anthropic.claude-plugin+json e application/agent-plugin+json, oltre al formato standard application/vnd.github.copilot-plugin, richiedi agent-plugin-formats in aggiunta ad agent-plugin-discovery. agent-plugin-confirmed-installation è la capability che restituisce l’installabilità e un piano da revisionare; anch’essa va richiesta insieme ad agent-plugin-discovery. Se consentita, i candidati includono installability, il cui valore è uno tra installable, install-data-unavailable, feature-disabled e not-installable-kind. installPlan è incluso solo quando installability è installable. Il piano è un dato di verifica: questa RPC catalog non esegue mai l’installazione. I sources del piano includono, in ordine di priorità, i candidati materialization, marketplace e repository. Per Marketplace vengono registrati nome e repository, per un Repository diretto il repository e un percorso facoltativo. Nei piani con sola materialization pluginName viene omesso e components è vuoto. Verifica il nome e il contenuto effettivamente installato nella revisione restituita da plugins.planInstall(). Per un candidato selezionato puoi creare con plugins.planInstall() un piano verificato privo di effetti collaterali. plugins.applyInstall() chiede all’utente una conferma esplicita e, se concessa, applica il piano. Dopo l’applicazione il plugin viene registrato in stato disabilitato. Il campo mcpServers della revisione mostra il nome del server, il transport e, per i server remoti, l’host dichiarati dai file verificati. Questo non costituisce una garanzia di sicurezza: l’utente deve verificarne il contenuto prima di dare la conferma esplicita. La description di un plugin installato deriva dal manifest. verifiedSource indica il repository GitHub e il commit fissato ed è presente solo nelle installazioni dirette fissate a un commit. iconUrl è contenuto esterno non attendibile: non inviare credenziali di autenticazione o credenziali GitHub durante il recupero. Le credenziali stesse non vengono mai restituite come motivo di rifiuto. Per un network-failure nel risultato dell’installazione puoi controllare CatalogNetworkFailureReason, lo statusCode HTTP, un retryAfterSeconds facoltativo e un message visualizzabile in sicurezza.
Per pianificare da un materialisation reference di Agent Finder usa catalog.planInstallFromReference(). Il valore outcome->kind del risultato è uno tra plugin-install-planned, skill-install-planned e refused. Passa i piani dei plugin a plugins.applyInstall() e quelli delle skill a skills.applyInstall().

contentExclusion

Prima di creare una sessione puoi validare il JSON della policy di esclusione dei contenuti.
policiesJson viene passato alla CLI come stringa JSON non analizzata. Se l’analisi del JSON o la validazione dello schema falliscono, si verifica un errore RPC dalla CLI (JsonRpcException). Questa è una RPC con ambito server che valida la policy stessa. Per verificare i percorsi all’interno della directory di lavoro della sessione rispetto alla policy di esclusione effettiva, usa contentExclusion()->checkPaths() con ambito sessione.

managedSettings (experimental: impostazioni gestite)

Esegue lettura delle impostazioni gestite, risoluzione delle policy, recupero dello schema, validazione, anteprima della composizione e invalidazione della cache.

settings (experimental: operazioni sui file di impostazioni)

Rimuovi una chiave specifica da un file di impostazioni e maschera i valori segreti per la visualizzazione. removeRawKey() rimuove le chiavi così come sono, incluse quelle che non sono percorsi di impostazione canonici, come le chiavi che non è stato possibile caricare. Se il file non può essere analizzato, la CLI non lo sovrascrive e status è invalid. redactValueForDisplay() sostituisce i valori segreti con segnaposto in base alla posizione nell’albero delle impostazioni indicata da basePath, così puoi mostrare il valore agli utenti o scriverlo nei log.

Ciclo di vita di Runtime e Host (experimental)

host.unpublishSession() ritira la application publication da un host in esecuzione di tua proprietà. Il ritiro della pubblicazione non elimina né interrompe la cronologia della sessione originale, i worktree o il lavoro in corso. Se la sessione non è già pubblicata, unpublished è false; le publication diverse da application generano un errore.
host.dispose() distrugge il listener dell’host specificando hostId.
host.setSessionCreationPolicy() attiva o disattiva l’accettazione di nuove sessioni remote da parte di un host in esecuzione. La modifica non disconnette i client esistenti e si applica solo alle ammissioni successive.
Nei runtime stdio avviati dall’SDK, Client::stop() chiama runtime.shutdown dopo aver disconnesso le sessioni e prima di chiudere la connessione JSON-RPC e il processo. La disconnessione delle sessioni (session.detach) condivide un’unica scadenza complessiva di 10 secondi per tutte le sessioni. Una disconnessione che supera la scadenza viene inclusa come errore nel valore di ritorno e l’arresto prosegue. Attende inoltre fino a 10 secondi il completamento della pulizia del runtime e, in caso di errore, include l’errore nel valore di ritorno proseguendo con il resto dell’arresto. Per le connessioni a runtime esterni, come con cli_url, questa RPC non viene chiamata per non terminare il runtime condiviso. Se la CLI non riesce a identificare la richiesta corrispondente e restituisce un errore JSON-RPC con id: null, tutte le richieste in corso falliscono con una JsonRpcException. L’eccezione include un messaggio diagnostico da cui sono rimossi i valori tra virgolette e la cui lunghezza è limitata. La connessione resta aperta. Poiché la CLI potrebbe aver già elaborato la richiesta, non ritentare automaticamente senza aver verificato che sia sicuro farlo. L’SDK rifiuta prima dell’invio le richieste in uscita annidate oltre 127 livelli, che la CLI non può leggere, e sostituisce con un errore JSON-RPC le risposte degli handler annidate troppo in profondità.

SessionRpc

Classe RPC associata alla Session. Sono possibili anche cose che le SDK precedenti non consentivano, come l’uso della modalità piano.

Modello, modalità, nome e piano

Con model() puoi verificare e cambiare il modello corrente e impostare reasoning effort, Auto tier e modelli consentiti. mode() gestisce la modalità, name() il nome della sessione e plan() la lettura e scrittura del testo del piano e dei todo SQLite.

Workspace, istruzioni e LSP

workspaces() fornisce elenco, lettura, scrittura, spostamento ed eliminazione di file e operazioni sulle directory. Con instructions() puoi recuperare, ricaricare ed esplorare le istruzioni, e con lsp() inizializzare la configurazione dei language server.

Obiettivo Autopilot

autopilotObjective()->getState() restituisce come oggetto tipizzato lo stato attuale dell’obiettivo Autopilot della sessione. Se non esiste alcun obiettivo, state è null. Questa API è diversa da workspaces()->autopilotObjectiveExists(), che verifica se un obiettivo è salvato nel workspace.
Con setStayInAutopilot() puoi sopprimere la richiesta di tornare alla modalità interattiva quando un objective viene completato o messo in pausa. L’impostazione è mantenuta nella memoria del client e il valore predefinito è true. Passa false in value per annullare la soppressione. Reimpostala dopo una riconnessione.

Agenti, Fleet e attività in background

Con agent() elenchi, selezioni e ricarichi gli agenti, e con fleet() avvii Fleet. tasks() gestisce la registrazione di agenti in background e attività di proprietà del client, il recupero e l’aggiornamento dell’avanzamento, la migrazione, l’invio di messaggi, l’annullamento e l’eliminazione.

MCP, Plugins, Extensions e Workflow

mcp() gestisce elenco, avvio, arresto e ricaricamento dei server, strumenti, prompt e risorse, OAuth, sampling e aggiornamento degli header dinamici. plugins() ed extensions() gestiscono lo stato all’interno della sessione e customizations() ricarica le personalizzazioni. Con workflow() esegui e interroghi i workflow, mentre con diagnostics() e connectors() ottieni informazioni diagnostiche e connettori.

Tools, Permissions, Commands e UI

tools() e permissions() gestiscono le risposte alle richieste in sospeso arrivate tramite eventi e le impostazioni. permissions()->clearResumeEscalation() annulla in memoria l’escalation dei permessi ripristinata dalla cronologia alla ripresa e restituisce un risultato di successo tipizzato. commands() fornisce elenco ed esecuzione dei comandi e risposta agli eventi, mentre ui() fornisce le risposte a richieste come input utente, elicitation e approvazione del piano. completions() recupera i suggerimenti di completamento.

Accounts, autenticazione e Providers

accounts() gestisce l’enumerazione di account, provider e account di accesso tramite enumerate(), get() e set(), e il login interattivo tramite begin(), advance() e cancel(). gitHubAuth() gestisce lo stato di autenticazione e le credenziali della sessione, provider() e providers() le destinazioni di connessione dei modelli e gli adapter dei provider, e connectors() le connessioni ai connettori della sessione.

Cronologia, coda, log e utilizzo

history() fornisce compattazione (incluse le impostazioni di compattazione), interruzione, riepilogo di passaggio di consegne e troncamento della conversazione, mentre queue() fornisce inserimento, spostamento, modifica, eliminazione e invio immediato degli elementi in sospeso. Con log(), eventLog(), usage(), quota() e limitPrediction() gestisci log, eventi, utilizzo e informazioni sui limiti. Con schedule() puoi verificare e interrompere i prompt pianificati.

Ciclo di vita, remoto e integrazione con l’host

sendMessages() esegue più messaggi in un unico turno e suspend() e shutdown() arrestano la sessione. interruptMainTurn() controlla il turno principale e cancelAllBackgroundAgents() gli agenti in background, separatamente. remote() e visibility() gestiscono la pubblicazione remota e lo stato di condivisione, sandbox() la sandbox della sessione, managedSettings() le impostazioni gestite con ambito sessione, contentExclusion() la verifica dei percorsi, metadata() i metadati di proprietà del client e canvas() l’integrazione con Canvas.

debug (experimental)

Con debug()->collectLogs() puoi raccogliere il log degli eventi, i log di processo e i log della shell della sessione in un archivio .tgz o in una directory. Per impostazione predefinita le informazioni sensibili nei log vengono oscurate. Con additionalEntries puoi aggiungere file o directory e per redaction puoi specificare plain-text, events-jsonl o none. Specificando none non viene applicato alcun oscuramento, quindi presta attenzione al contenuto aggiunto.
Specificando DebugCollectLogsDestination::directory('/tmp/copilot-debug') puoi scrivere l’output in una directory di staging. Con include puoi indicare singolarmente i log e i percorsi di riferimento da raccogliere, e verificare il contenuto raccolto da entries e skippedEntries nel risultato. I percorsi della destinazione e delle voci aggiuntive sono percorsi lato server CLI. Nella configurazione standard, in cui la CLI viene avviata via stdio, si tratta dello stesso host dell’applicazione; se invece ti connetti via TCP a un server CLI su un altro host, specifica i percorsi lato server e non quelli della macchina chiamante.

contentExclusion (experimental)

Puoi verificare se percorsi assoluti locali all’interno della directory di lavoro della sessione sono soggetti alla policy di esclusione dei contenuti. Chiamalo prima di leggere o allegare il contenuto dei file.
checkPaths() accetta solo percorsi assoluti, che devono trovarsi all’interno della directory di lavoro della sessione. checks viene restituito nello stesso ordine dell’input e i percorsi duplicati vengono mantenuti così come sono. Se il percorso, il file system o la valutazione della policy non sono supportati o disponibili, vengono restituiti available: false e checks vuoto. In questo caso isExcluded() restituisce sempre true, quindi tratta tutti i percorsi come esclusi. Anche con available: true, i percorsi assenti dal risultato vengono considerati esclusi per sicurezza.

MCP Apps (experimental)

Da $session->rpc()->mcp()->apps() puoi chiamare le RPC per MCP Apps. In listTools() e callTool() il nome del server MCP chiamante originServerName è obbligatorio. Il risultato di callTool() viene restituito come risultato MCP in formato libero.
readResource() restituisce i dati della risorsa, ad esempio HTML. L’SDK non esegue il rendering nel browser né manipola iframe, quindi il rendering del contenuto ottenuto è responsabilità dell’applicazione chiamante.

Esempi d’uso per funzionalità

Di seguito sono riassunti esempi di chiamata rappresentativi per le funzionalità descritte sopra.

remote (experimental: supporto per le sessioni remote)

Per i dettagli consulta Remote Sessions.

sandbox (experimental: controllo della sandbox)

Nell’handler dei permessi, se è presente $request['sandboxPathGrant'], chiamalo con il requestId della richiesta in sospeso interessata. Poiché questa RPC risponde da sola alla richiesta di permesso, in caso di successo restituisci PermissionDecision::noResult() per non inviare la risposta normale.

metadata (experimental: informazioni sulla sessione)

Gestione delle sessioni locali (experimental)

Usa $session->rpc()->management() per configurare, elencare, creare, inviare messaggi e chiudere le sessioni locali che hanno aderito alla gestione nella stessa directory di configurazione. Registra una callback dell’host con setSessionCreationHandler() per ricevere l’RPC inverso da create(). La callback deve creare la sessione figlia con newSessionId, mantenerne le restrizioni su permessi e modello e restituire un SessionManagementCreateResult. Nell’esempio seguente, $sessionCreationHandler è una closure che riceve un SessionManagementCreateHostRequest, crea la sessione figlia sull’host e restituisce un SessionManagementCreateResult.
accepted di message() indica che il messaggio è stato accettato per la consegna, non che il destinatario abbia risposto o completato la sua attività. Dopo aver verificato separatamente che una sessione figlia ha terminato il lavoro, usa close() per chiudere solo le sessioni figlie che hai creato. La cronologia salvata non viene eliminata.

Session canvas

Le RPC Canvas si chiamano da $session->rpc()->canvas(). list() restituisce l’elenco in canvases di CanvasList e listOpen() in openCanvases di CanvasListOpenResult. open() restituisce OpenCanvasInstance, mentre l’invocazione di action restituisce CanvasActionInvokeResult. close() non ha valore di ritorno.
Il reverse-RPC del Canvas provider (canvas.open / canvas.close / canvas.action.invoke) viene gestito con canvasHandler di SessionConfig / ResumeSessionConfig. Il rendering del Canvas è responsabilità della UI dell’host.

workflow

Anche le API RPC sperimentali per workflow, connettori, diagnostica ecc. aggiunte nella serie Copilot CLI 1.0.89 sono disponibili da SessionRpc. Questi payload di protocollo variabili si passano come array compatibili con JSON e anche le risposte vengono restituite come array. A ogni chiamata viene aggiunto automaticamente il sessionId corrente.
workflow() chiama le RPC di basso livello fornite dalla CLI. Un’API di alto livello per registrare ed eseguire closure PHP come workflow, come nell’SDK Node.js, non è stata aggiunta in questa sincronizzazione. Questi nuovi gruppi RPC dipendono dalla versione della CLI e sono sperimentali, quindi usali solo con una CLI compatibile.

Tipi di callback SessionFS

Sono definiti tipi di callback (Request/Result) per le operazioni sul file system con ambito sessione. Sono i tipi di richiesta/risposta usati quando Copilot CLI effettua callback verso il client. SessionFsStatResult / SessionFsReaddirResult / SessionFsReaddirWithTypesResult hanno un error facoltativo (SessionFsError) usato in caso di errore.

Handler SessionFs

Il Client smista verso il provider della Session le richieste sessionFs.readFile / readFileBytes / writeFile / writeFileBytes e inoltre appendFile, exists, stat, mkdir, readdir, readdirWithTypes, rm, rename, sqliteQuery, sqliteTransaction e sqliteExists. Gli errori delle operazioni sui file vengono restituiti come error ENOENT (ENOENT o errno 2) / UNKNOWN. exists restituisce false in caso di eccezione e stat restituisce valori zero + error in caso di errore. Le operazioni non supportate dal provider producono un errore UNKNOWN (per SQLite, un errore JSON-RPC). Le eccezioni di sqliteQuery/sqliteExists vengono restituite come errori JSON-RPC, mentre gli errori di sqliteTransaction come error del risultato (con errorClass). Le interfacce lato provider (SessionFsFilesystemProvider, SessionFsSqliteCapableProvider, SessionFsSqliteProvider, SessionFsSqliteTransactionProvider) sono state aggiunte come interfacce separate per non rompere il tradizionale SessionFsProvider (2 metodi).

Tipi di callback SQLite

Per abilitare il supporto SQLite, passa SessionFsSetProviderCapabilities(sqlite: true) a capabilities di SessionFsSetProviderRequest.
Di norma non si chiama direttamente questa RPC: specificando l’opzione Client sessionFs (oppure session_fs in config/copilot.php), Client::start() invia sessionFs.setProvider una sola volta. La sessione richiede createSessionFsProvider (vedi SessionConfig). L’enum SessionFsSqliteQueryType (src/Enums/) rappresenta il tipo di query:
  • Exec: DDL/più statement (nessun risultato)
  • Query: SELECT (restituisce righe)
  • Run: INSERT/UPDATE/DELETE (restituisce rowsAffected)
Queste classi di tipo sono in src/Types/Rpc/.

Specifica degli argomenti come array

Sia gli argomenti sia i valori di ritorno usano classi dedicate, ma gli argomenti possono essere specificati anche come array.

Testing

Poiché non puoi usare il mock via Copilot::fake(), effettua il mock con Copilot::expects('client') o Copilot::expects('start').
Per le informazioni più recenti fai riferimento al repository GitHub.
Ultima modifica il 9 novembre 2026