- Home
- Documentation
- Sessioni
- Operazioni di sessione: export, dump, share, fork, resume/continue
Operazioni di sessione: export, dump, share, fork, resume/continue
Questo documento descrive il comportamento visibile dall’operatore per le operazioni di esportazione/condivisione/fork/ripristino della sessione così come sono attualmente implementate.
File di implementazione
Sezione intitolata “File di implementazione”../src/modes/controllers/command-controller.ts../src/session/agent-session.ts../src/session/session-manager.ts../src/export/html/index.ts../src/export/custom-share.ts../src/main.ts
Matrice delle operazioni
Sezione intitolata “Matrice delle operazioni”| Operazione | Percorso di accesso | Mutazione della sessione | Creazione/cambio file di sessione | Artefatto di output |
|---|---|---|---|---|
/dump | Comando slash interattivo | No | No | Testo negli appunti |
/export [path] | Comando slash interattivo | No | No | File HTML |
--export <session.jsonl> [outputPath] | Percorso rapido di avvio CLI | Nessuna mutazione di sessione a runtime | Nessuna sessione attiva; legge il file di destinazione | File HTML |
/share | Comando slash interattivo | No | No | HTML temporaneo + URL di condivisione/gist |
/fork | Comando slash interattivo | Sì (l’identità della sessione attiva cambia) | Crea un nuovo file di sessione e passa la sessione corrente a quest’ultimo (solo in modalità persistente) | Copia la directory degli artefatti nel nuovo namespace di sessione, se presente |
/resume | Comando slash interattivo | Sì (lo stato in-memory attivo viene sostituito) | Passa al file di sessione esistente selezionato | Nessuno |
--resume | Avvio CLI (selettore) | Sì dopo la creazione della sessione | Apre il file di sessione esistente selezionato | Nessuno |
--resume <id|path> | Avvio CLI | Sì dopo la creazione della sessione | Apre la sessione esistente; nel caso cross-project può effettuare il fork nel progetto corrente | Nessuno |
--continue | Avvio CLI | Sì dopo la creazione della sessione | Apre il breadcrumb del terminale o la sessione più recente; ne crea una nuova se non ne esiste nessuna | Nessuno |
Esportazione e dump
Sezione intitolata “Esportazione e dump”/export [outputPath] (interattivo)
Sezione intitolata “/export [outputPath] (interattivo)”Flusso:
InputControllerinstrada/export...versoCommandController.handleExportCommand.- Il comando divide per spazi bianchi e utilizza solo il primo argomento dopo
/exportcomeoutputPath. AgentSession.exportToHtml()chiamaexportSessionToHtml(sessionManager, state, { outputPath, themeName }).- In caso di successo, l’interfaccia utente mostra il percorso e apre il file nel browser.
Dettagli del comportamento:
- Gli argomenti
--copy,clipboardecopyvengono esplicitamente rifiutati con un avviso che invita a utilizzare/dump. - L’esportazione incorpora l’intestazione/le voci/la foglia della sessione più il
systemPromptcorrente e le descrizioni degli strumenti dallo stato dell’agente. - Nessuna voce di sessione viene aggiunta durante l’esportazione.
Avvertenza:
- L’analisi degli argomenti è basata sugli spazi bianchi (
text.split(/\s+/)), pertanto i percorsi tra virgolette con spazi non vengono preservati come percorso singolo in questo percorso di comando.
--export <inputSessionFile> [outputPath] (CLI)
Sezione intitolata “--export <inputSessionFile> [outputPath] (CLI)”Flusso in main.ts:
- Gestito anticipatamente (prima dell’avvio interattivo/della sessione).
- Chiama
exportFromFile(inputPath, outputPath?). SessionManager.open(inputPath)carica le voci, quindi l’HTML viene generato e scritto.- Il processo stampa
Exported to: ...ed esce.
Dettagli del comportamento:
- Un file di input mancante viene segnalato come
File not found: <path>. - Questo percorso non crea un
AgentSessione non muta alcuna sessione in esecuzione.
/dump (esportazione interattiva negli appunti)
Sezione intitolata “/dump (esportazione interattiva negli appunti)”Flusso:
CommandController.handleDumpCommand()chiamasession.formatSessionAsText().- Se la stringa è vuota, riporta
No messages to dump yet. - Altrimenti copia negli appunti tramite
copyToClipboardnativo.
Il contenuto del dump include:
- Prompt di sistema
- Modello attivo/livello di riflessione
- Definizioni degli strumenti e parametri
- Messaggi utente/assistente
- Blocchi di riflessione e chiamate agli strumenti
- Risultati degli strumenti e blocchi di esecuzione (ad eccezione delle voci bash/python con
excludeFromContext) - Voci personalizzate/hook/menzione di file/riepilogo branch/riepilogo di compattazione
Nessuna modifica alla persistenza della sessione viene effettuata dal dump.
Condivisione
Sezione intitolata “Condivisione”/share è solo interattivo e inizia sempre esportando la sessione corrente in un file HTML temporaneo.
Fase 1: esportazione temporanea
Sezione intitolata “Fase 1: esportazione temporanea”- Percorso del file temporaneo:
${os.tmpdir()}/${Snowflake.next()}.html - Utilizza
session.exportToHtml(tmpFile) - Se l’esportazione fallisce (in particolare per le sessioni in-memory), la condivisione termina con un errore.
Fase 2: gestore di condivisione personalizzato (se presente)
Sezione intitolata “Fase 2: gestore di condivisione personalizzato (se presente)”loadCustomShare() verifica ~/.xcsh/agent per il primo candidato esistente:
share.tsshare.jsshare.mjs
Requisiti:
- Il modulo deve esportare come default una funzione
(htmlPath) => Promise<CustomShareResult | string | undefined>.
Se presente e valido:
- L’interfaccia utente entra nello stato di caricamento
Sharing.... - Interpretazione del risultato del gestore:
- stringa => trattata come URL, mostrata e aperta
- oggetto =>
urle/omessagemostrati;urlaperto undefined/falsy =>Session sharedgenerico
- Il file temporaneo viene rimosso al termine.
Comportamento di fallback critico:
- Se il gestore personalizzato esiste ma il caricamento fallisce, il comando genera un errore e termina.
- Se il gestore personalizzato viene eseguito e genera un’eccezione, il comando genera un errore e termina.
- In entrambi i casi di errore, non viene eseguito il fallback al gist di GitHub.
- Il fallback al gist avviene solo quando non esiste nessuno script di condivisione personalizzato.
Fase 3: fallback predefinito al gist
Sezione intitolata “Fase 3: fallback predefinito al gist”Solo quando non viene trovato nessun gestore di condivisione personalizzato:
- Valida
gh auth status. - Mostra il loader
Creating gist.... - Esegue
gh gist create --public=false <tmpFile>. - Analizza l’URL del gist, ricava l’id del gist, costruisce l’URL di anteprima
https://gistpreview.github.io/?<id>. - Mostra sia l’URL di anteprima che quello del gist; apre l’anteprima.
Semantica di annullamento/interruzione nella condivisione:
- Il loader dispone di un hook
onAbortche ripristina l’interfaccia utente dell’editor e riportaShare cancelled. - Il comando sottostante
gh gist createnon riceve un segnale di interruzione in questo percorso di codice; l’annullamento è a livello di interfaccia utente e viene verificato dopo il ritorno del comando.
/fork crea una nuova sessione da quella corrente e cambia l’identità della sessione attiva.
Precondizioni e controlli immediati
Sezione intitolata “Precondizioni e controlli immediati”- Se l’agente sta eseguendo lo streaming,
/forkviene rifiutato con un avviso. - Gli indicatori di stato/caricamento dell’interfaccia utente vengono azzerati prima dell’operazione.
Flusso a livello di sessione
Sezione intitolata “Flusso a livello di sessione”AgentSession.fork():
- Emette
session_before_switchconreason: "fork"(annullabile). - Svuota le scritture in sospeso.
- Chiama
SessionManager.fork(). - Copia la directory degli artefatti dal namespace della vecchia sessione a quello nuovo (best-effort; i fallimenti di copia non ENOENT vengono registrati, non sono fatali).
- Aggiorna
agent.sessionId. - Emette
session_switchconreason: "fork".
Comportamento di SessionManager.fork():
- Richiede la modalità persistente e un file di sessione esistente.
- Crea un nuovo id di sessione e un nuovo percorso file JSONL.
- Riscrive l’intestazione con:
- nuovo
id - nuovo timestamp
cwdinvariatoparentSessionimpostato sull’id della sessione precedente
- nuovo
- Mantiene invariate tutte le voci non di intestazione nel nuovo file.
Comportamento non persistente
Sezione intitolata “Comportamento non persistente”- Il gestore di sessione in-memory restituisce
undefineddafork(). AgentSession.fork()restituiscefalse.- L’interfaccia utente riporta
Fork failed (session not persisted or cancelled).
Ripristino e continuazione
Sezione intitolata “Ripristino e continuazione”/resume interattivo
Sezione intitolata “/resume interattivo”Flusso:
- Apre il selettore di sessione popolato tramite
SessionManager.list(currentCwd, currentSessionDir). - Alla selezione,
SelectorController.handleResumeSession(sessionPath)chiamasession.switchSession(sessionPath). - L’interfaccia utente cancella/ricostruisce la chat e i todo, quindi riporta
Resumed session.
Note:
- Questo selettore elenca solo le sessioni nell’ambito della directory di sessione corrente.
- Non utilizza la ricerca globale cross-project.
CLI --resume
Sezione intitolata “CLI --resume”--resume (nessun valore)
Sezione intitolata “--resume (nessun valore)”main.tselenca le sessioni per cwd/sessionDir correnti e apre il selettore.- Il percorso selezionato viene aperto con
SessionManager.open(selectedPath)prima della creazione della sessione.
--resume <value>
Sezione intitolata “--resume <value>”Ordine di risoluzione di createSessionManager():
- Se il valore sembra un percorso (
/,\o.jsonl), apertura diretta. - Altrimenti trattato come prefisso id:
- ricerca nell’ambito corrente (
SessionManager.list(cwd, sessionDir)) - se non trovato e nessuna
sessionDiresplicita, ricerca globale (SessionManager.listAll())
- ricerca nell’ambito corrente (
Comportamento in caso di corrispondenza id cross-project:
- Se il cwd della sessione trovata differisce dal cwd corrente, la CLI chiede:
Session found in different project ... Fork into current directory? [y/N]
- In caso affermativo:
SessionManager.forkFrom(match.path, cwd, sessionDir)crea un nuovo file forked locale. - In caso negativo/TTY non predefinito: il comando genera un errore.
CLI --continue
Sezione intitolata “CLI --continue”SessionManager.continueRecent(cwd, sessionDir):
- Risolve la directory di sessione per il cwd corrente.
- Legge prima il breadcrumb con scope al terminale.
- Ricorre al file di sessione modificato più di recente.
- Apre la sessione trovata; se non ne esiste nessuna, crea una nuova sessione.
Questo è un comportamento solo di avvio; non esiste un comando slash interattivo /continue.
Come il cambio di sessione muta effettivamente lo stato a runtime
Sezione intitolata “Come il cambio di sessione muta effettivamente lo stato a runtime”AgentSession.switchSession(sessionPath) esegue la transizione a runtime utilizzata dalle operazioni di tipo resume:
- Emette
session_before_switchconreason: "resume"etargetSessionFile(annullabile). - Disconnette la sottoscrizione agli eventi dell’agente e interrompe il lavoro in corso.
- Cancella i messaggi di steering/follow-up/next-turn in coda.
- Svuota le scritture del gestore di sessione corrente.
sessionManager.setSessionFile(sessionPath)e aggiornaagent.sessionId.- Costruisce il contesto di sessione dalle voci caricate.
- Emette
session_switchconreason: "resume". - Sostituisce i messaggi dell’agente dal contesto.
- Ripristina il modello (se disponibile nel registro corrente).
- Ripristina o inizializza il livello di riflessione.
- Riconnette la sottoscrizione agli eventi dell’agente.
Nessun nuovo file di sessione viene creato da switchSession() stesso.
Emissioni di eventi e punti di annullamento
Sezione intitolata “Emissioni di eventi e punti di annullamento”Hook del ciclo di vita switch/fork
Sezione intitolata “Hook del ciclo di vita switch/fork”Per newSession, fork e switchSession:
- Evento precedente:
session_before_switch- motivazioni:
new,fork,resume - annullabile restituendo
{ cancel: true }
- motivazioni:
- Evento successivo:
session_switch- stesso insieme di motivazioni
- include
previousSessionFile
ExtensionRunner.emit() termina anticipatamente al primo risultato di un evento precedente che annulla.
Comportamento onSession degli strumenti personalizzati
Sezione intitolata “Comportamento onSession degli strumenti personalizzati”L’SDK collega gli eventi di sessione delle estensioni ai callback onSession degli strumenti personalizzati:
session_switch->onSession({ reason: "switch", previousSessionFile })session_branch->reason: "branch"session_start->reason: "start"session_tree->reason: "tree"session_shutdown->reason: "shutdown"
Questi callback sono osservativi; non annullano switch/fork.
Altre superfici di annullamento rilevanti per questo documento
Sezione intitolata “Altre superfici di annullamento rilevanti per questo documento”/forkviene bloccato durante lo streaming (l’utente deve attendere/interrompere la risposta corrente prima).- Il selettore
/resumepuò essere annullato dall’utente chiudendo il selettore. --resume <id>cross-project può essere annullato rifiutando il prompt di fork./sharedispone di un percorso di interruzione nell’interfaccia utente (Share cancelled) per il flusso gist; non implementa la semantica di kill del processo pergh gist createin questo percorso di codice.
Comportamento della sessione non persistente (in-memory)
Sezione intitolata “Comportamento della sessione non persistente (in-memory)”Quando il gestore di sessione viene creato con SessionManager.inMemory() (--no-session):
- Il percorso del file di sessione è assente.
/exporte/sharefalliscono conCannot export in-memory session to HTML(propagato all’interfaccia utente degli errori di comando)./forkfallisce perchéSessionManager.fork()richiede la persistenza./dumpfunziona ancora perché serializza lo stato dell’agente in-memory.- La semantica di resume/continue da CLI viene ignorata se
--no-sessionè impostato, poiché la creazione del gestore restituisce immediatamente in-memory.
Avvertenze note sull’implementazione (nel codice corrente)
Sezione intitolata “Avvertenze note sull’implementazione (nel codice corrente)”SelectorController.handleResumeSession()non verifica il risultato booleano disession.switchSession(...); un cambio annullato da un hook può comunque procedere attraverso il percorso di ridisegno/stato “Resumed session” dell’interfaccia utente.- I fallimenti di condivisione personalizzata in
/sharenon degradano al fallback gist predefinito; terminano il comando con un errore. - La tokenizzazione degli argomenti di
/exportè semplicistica e non preserva i percorsi tra virgolette con spazi.