- Início
- Documentation
- Sessões
- Ciclo de Vida da Injeção TTSR
Ciclo de Vida da Injeção TTSR
Este documento abrange o caminho de execução atual do Time Traveling Stream Rules (TTSR), desde a descoberta de regras até a interrupção de stream, injeção de retry, notificações de extensões e gerenciamento de estado de sessão.
Arquivos de implementação
Seção intitulada “Arquivos de implementação”../src/sdk.ts../src/export/ttsr.ts../src/session/agent-session.ts../src/session/session-manager.ts../src/prompts/system/ttsr-interrupt.md../src/capability/index.ts../src/extensibility/extensions/types.ts../src/extensibility/hooks/types.ts../src/extensibility/custom-tools/types.ts../src/modes/controllers/event-controller.ts
1. Feed de descoberta e registro de regras
Seção intitulada “1. Feed de descoberta e registro de regras”Na criação da sessão, createAgentSession() carrega todas as regras descobertas e constrói um TtsrManager:
const ttsrSettings = settings.getGroup("ttsr");const ttsrManager = new TtsrManager(ttsrSettings);const rulesResult = await loadCapability<Rule>(ruleCapability.id, { cwd });for (const rule of rulesResult.items) { if (rule.ttsrTrigger) ttsrManager.addRule(rule);}Comportamento de deduplicação pré-registro
Seção intitulada “Comportamento de deduplicação pré-registro”loadCapability("rules") deduplica por rule.name com semântica de primeira ocorrência vence (prioridade maior do provedor primeiro). Duplicatas sombreadas são removidas antes do registro TTSR.
Comportamento de TtsrManager.addRule()
Seção intitulada “Comportamento de TtsrManager.addRule()”O registro é ignorado quando:
rule.ttsrTriggerestá ausente- uma regra com o mesmo
rule.namejá foi registrada neste gerenciador - a regex falha ao compilar (
new RegExp(rule.ttsrTrigger)lança exceção)
Triggers com regex inválida são registrados como warnings e ignorados; a inicialização da sessão continua.
Ressalva sobre configuração
Seção intitulada “Ressalva sobre configuração”TtsrSettings.enabled é carregado no gerenciador, mas atualmente não é verificado no controle de execução em tempo de runtime. Se existirem regras, a verificação de correspondência ainda será executada.
2. Ciclo de vida do monitor de streaming
Seção intitulada “2. Ciclo de vida do monitor de streaming”A detecção TTSR é executada dentro de AgentSession.#handleAgentEvent.
Início do turno
Seção intitulada “Início do turno”No turn_start, o buffer de stream é resetado:
ttsrManager.resetBuffer()
Durante o stream (message_update)
Seção intitulada “Durante o stream (message_update)”Quando atualizações do assistente chegam e existem regras:
- monitora
text_deltaetoolcall_delta - anexa o delta ao buffer do gerenciador
- chama
check(buffer)
check() itera as regras registradas e retorna todas as regras correspondentes que passam pela política de repetição (#canTrigger).
3. Decisão de trigger e caminho de abort imediato
Seção intitulada “3. Decisão de trigger e caminho de abort imediato”Quando uma ou mais regras correspondem:
markInjected(matches)registra os nomes das regras no estado de injeção do gerenciador.- as regras correspondentes são enfileiradas em
#pendingTtsrInjections. #ttsrAbortPending = true.agent.abort()é chamado imediatamente.- o evento
ttsr_triggeredé emitido de forma assíncrona (fire-and-forget). - o trabalho de retry é agendado via
setTimeout(..., 50).
O abort não é bloqueado por callbacks de extensões.
4. Agendamento de retry, modo de contexto e injeção de lembrete
Seção intitulada “4. Agendamento de retry, modo de contexto e injeção de lembrete”Após o timeout de 50ms:
#ttsrAbortPending = false- lê
ttsrManager.getSettings().contextMode - se
contextMode === "discard", descarta a saída parcial do assistente comagent.popMessage() - constrói o conteúdo de injeção a partir das regras pendentes usando o template
ttsr-interrupt.md - anexa uma mensagem de usuário sintética contendo um bloco
<system-interrupt ...>por regra - chama
agent.continue()para tentar novamente a geração
O payload do template é:
<system-interrupt reason="rule_violation" rule="{{name}}" path="{{path}}">...{{content}}</system-interrupt>As injeções pendentes são limpas após a geração do conteúdo.
Comportamento do contextMode na saída parcial
Seção intitulada “Comportamento do contextMode na saída parcial”discard: a mensagem parcial/abortada do assistente é removida antes do retry.keep: a saída parcial do assistente permanece no estado da conversa; o lembrete é anexado após ela.
5. Política de repetição e lógica de intervalo
Seção intitulada “5. Política de repetição e lógica de intervalo”TtsrManager rastreia #messageCount e lastInjectedAt por regra.
repeatMode: "once"
Seção intitulada “repeatMode: "once"”Uma regra pode ser acionada apenas uma vez após ter um registro de injeção.
repeatMode: "after-gap"
Seção intitulada “repeatMode: "after-gap"”Uma regra pode ser reacionada apenas quando:
messageCount - lastInjectedAt >= repeatGap
messageCount é incrementado no turn_end, então o intervalo é medido em turnos completos, não em chunks de stream.
6. Emissão de eventos e superfícies de extensão/hook
Seção intitulada “6. Emissão de eventos e superfícies de extensão/hook”Evento de sessão
Seção intitulada “Evento de sessão”AgentSessionEvent inclui:
{ type: "ttsr_triggered"; rules: Rule[] }Runner de extensão
Seção intitulada “Runner de extensão”#emitSessionEvent() encaminha o evento para:
- listeners de extensão (
ExtensionRunner.emit({ type: "ttsr_triggered", rules })) - assinantes locais da sessão
Tipagem de hook e custom-tool
Seção intitulada “Tipagem de hook e custom-tool”- a API de extensão expõe
on("ttsr_triggered", ...) - a API de hook expõe
on("ttsr_triggered", ...) - custom tools recebem
onSession({ reason: "ttsr_triggered", rules })
Diferença de renderização no modo interativo
Seção intitulada “Diferença de renderização no modo interativo”O modo interativo usa session.isTtsrAbortPending para suprimir a exibição do motivo de parada do assistente abortado como uma falha visível durante a interrupção TTSR, e renderiza um TtsrNotificationComponent quando o evento chega.
7. Persistência e estado de retomada (implementação atual)
Seção intitulada “7. Persistência e estado de retomada (implementação atual)”SessionManager possui suporte completo de schema para persistência de regras injetadas:
- tipo de entrada:
ttsr_injection - API de anexação:
appendTtsrInjection(ruleNames) - API de consulta:
getInjectedTtsrRules() - a reconstrução de contexto inclui
SessionContext.injectedTtsrRules
TtsrManager também suporta restauração via restoreInjected(ruleNames).
Status atual da integração
Seção intitulada “Status atual da integração”No caminho de execução atual:
AgentSessionnão anexa entradasttsr_injectionquando o TTSR é acionado.createAgentSession()não restauraexistingSession.injectedTtsrRulesde volta nottsrManager.
Efeito líquido: a supressão de regras injetadas é aplicada em memória para o processo ativo, mas atualmente não é persistida/restaurada entre recarregamento/retomada de sessão por este caminho.
8. Limites de race condition e garantias de ordenação
Seção intitulada “8. Limites de race condition e garantias de ordenação”Abort vs callback de retry
Seção intitulada “Abort vs callback de retry”- o abort é síncrono da perspectiva do handler TTSR (
agent.abort()é chamado imediatamente) - o retry é adiado por timer (
50ms) - a notificação de extensão é assíncrona e intencionalmente não aguardada antes do agendamento de abort/retry
Múltiplas correspondências na mesma janela de stream
Seção intitulada “Múltiplas correspondências na mesma janela de stream”check() retorna todas as regras elegíveis que correspondem atualmente. Elas são injetadas como um lote na próxima mensagem de retry.
Entre abort e continue
Seção intitulada “Entre abort e continue”Durante a janela do timer, o estado pode mudar (interrupção do usuário, ações de modo, eventos adicionais). A chamada de retry é de melhor esforço: agent.continue().catch(() => {}) engole erros subsequentes.
9. Resumo de casos extremos
Seção intitulada “9. Resumo de casos extremos”- Regex
ttsr_triggerinválida: ignorada com warning; outras regras continuam. - Nomes de regras duplicados na camada de capability: duplicatas de menor prioridade são sombreadas antes do registro.
- Nomes duplicados na camada do gerenciador: o segundo registro é ignorado.
contextMode: "keep": a saída parcial violadora pode permanecer no contexto antes do retry com lembrete.- Repeat-after-gap depende dos incrementos de contagem de turnos no
turn_end; chunks no meio do turno não avançam os contadores de intervalo.