- Inicio
- Documentation
- Sesiones
- Ciclo de vida de la inyección TTSR
Ciclo de vida de la inyección TTSR
Este documento cubre la ruta de ejecución actual de las Time Traveling Stream Rules (TTSR), desde el descubrimiento de reglas hasta la interrupción del flujo, la inyección de reintentos, las notificaciones de extensiones y el manejo del estado de sesión.
Archivos de implementación
Sección titulada «Archivos de implementación»../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. Alimentación de descubrimiento y registro de reglas
Sección titulada «1. Alimentación de descubrimiento y registro de reglas»Al crear la sesión, createAgentSession() carga todas las reglas descubiertas y construye un 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);}Comportamiento de deduplicación previo al registro
Sección titulada «Comportamiento de deduplicación previo al registro»loadCapability("rules") deduplica por rule.name con semántica de primera coincidencia gana (mayor prioridad de proveedor primero). Los duplicados sombreados se eliminan antes del registro TTSR.
Comportamiento de TtsrManager.addRule()
Sección titulada «Comportamiento de TtsrManager.addRule()»El registro se omite cuando:
rule.ttsrTriggerestá ausente- una regla con el mismo
rule.nameya fue registrada en este manager - la expresión regular falla al compilar (
new RegExp(rule.ttsrTrigger)lanza una excepción)
Los triggers con expresiones regulares inválidas se registran como advertencias y se ignoran; el inicio de sesión continúa.
Advertencia sobre configuración
Sección titulada «Advertencia sobre configuración»TtsrSettings.enabled se carga en el manager pero actualmente no se verifica en el control de ejecución. Si existen reglas, la coincidencia se ejecuta de todos modos.
2. Ciclo de vida del monitor de flujo
Sección titulada «2. Ciclo de vida del monitor de flujo»La detección TTSR se ejecuta dentro de AgentSession.#handleAgentEvent.
Inicio de turno
Sección titulada «Inicio de turno»En turn_start, el buffer del flujo se reinicia:
ttsrManager.resetBuffer()
Durante el flujo (message_update)
Sección titulada «Durante el flujo (message_update)»Cuando llegan actualizaciones del asistente y existen reglas:
- se monitorean
text_deltaytoolcall_delta - se añade el delta al buffer del manager
- se llama a
check(buffer)
check() itera las reglas registradas y devuelve todas las reglas coincidentes que pasan la política de repetición (#canTrigger).
3. Decisión de activación y ruta de cancelación inmediata
Sección titulada «3. Decisión de activación y ruta de cancelación inmediata»Cuando una o más reglas coinciden:
markInjected(matches)registra los nombres de las reglas en el estado de inyección del manager.- las reglas coincidentes se ponen en cola en
#pendingTtsrInjections. #ttsrAbortPending = true.agent.abort()se llama inmediatamente.- el evento
ttsr_triggeredse emite de forma asíncrona (fire-and-forget). - el trabajo de reintento se programa mediante
setTimeout(..., 50).
La cancelación no se bloquea esperando los callbacks de extensiones.
4. Programación de reintentos, modo de contexto e inyección de recordatorio
Sección titulada «4. Programación de reintentos, modo de contexto e inyección de recordatorio»Después del timeout de 50ms:
#ttsrAbortPending = false- se lee
ttsrManager.getSettings().contextMode - si
contextMode === "discard", se descarta la salida parcial del asistente conagent.popMessage() - se construye el contenido de inyección a partir de las reglas pendientes usando la plantilla
ttsr-interrupt.md - se añade un mensaje sintético del usuario que contiene un bloque
<system-interrupt ...>por cada regla - se llama a
agent.continue()para reintentar la generación
El payload de la plantilla es:
<system-interrupt reason="rule_violation" rule="{{name}}" path="{{path}}">...{{content}}</system-interrupt>Las inyecciones pendientes se limpian después de la generación del contenido.
Comportamiento de contextMode sobre la salida parcial
Sección titulada «Comportamiento de contextMode sobre la salida parcial»discard: el mensaje parcial/cancelado del asistente se elimina antes del reintento.keep: la salida parcial del asistente permanece en el estado de la conversación; el recordatorio se añade después de ella.
5. Política de repetición y lógica de intervalo
Sección titulada «5. Política de repetición y lógica de intervalo»TtsrManager rastrea #messageCount y lastInjectedAt por regla.
repeatMode: "once"
Sección titulada «repeatMode: "once"»Una regla solo puede activarse una vez después de tener un registro de inyección.
repeatMode: "after-gap"
Sección titulada «repeatMode: "after-gap"»Una regla puede reactivarse solo cuando:
messageCount - lastInjectedAt >= repeatGap
messageCount se incrementa en turn_end, por lo que el intervalo se mide en turnos completados, no en fragmentos del flujo.
6. Emisión de eventos y superficies de extensiones/hooks
Sección titulada «6. Emisión de eventos y superficies de extensiones/hooks»Evento de sesión
Sección titulada «Evento de sesión»AgentSessionEvent incluye:
{ type: "ttsr_triggered"; rules: Rule[] }Ejecutor de extensiones
Sección titulada «Ejecutor de extensiones»#emitSessionEvent() enruta el evento a:
- listeners de extensiones (
ExtensionRunner.emit({ type: "ttsr_triggered", rules })) - suscriptores locales de sesión
Tipado de hooks y herramientas personalizadas
Sección titulada «Tipado de hooks y herramientas personalizadas»- la API de extensiones expone
on("ttsr_triggered", ...) - la API de hooks expone
on("ttsr_triggered", ...) - las herramientas personalizadas reciben
onSession({ reason: "ttsr_triggered", rules })
Diferencia de renderizado en modo interactivo
Sección titulada «Diferencia de renderizado en modo interactivo»El modo interactivo usa session.isTtsrAbortPending para suprimir la visualización de la razón de detención del asistente cancelado como un fallo visible durante la interrupción TTSR, y renderiza un TtsrNotificationComponent cuando llega el evento.
7. Persistencia y estado de reanudación (implementación actual)
Sección titulada «7. Persistencia y estado de reanudación (implementación actual)»SessionManager tiene soporte completo de esquema para la persistencia de reglas inyectadas:
- tipo de entrada:
ttsr_injection - API de adición:
appendTtsrInjection(ruleNames) - API de consulta:
getInjectedTtsrRules() - la reconstrucción de contexto incluye
SessionContext.injectedTtsrRules
TtsrManager también soporta restauración mediante restoreInjected(ruleNames).
Estado actual del cableado
Sección titulada «Estado actual del cableado»En la ruta de ejecución actual:
AgentSessionno añade entradasttsr_injectioncuando se activa TTSR.createAgentSession()no restauraexistingSession.injectedTtsrRulesde vuelta alttsrManager.
Efecto neto: la supresión de reglas inyectadas se aplica en memoria para el proceso activo, pero actualmente no se persiste/restaura entre recargas/reanudaciones de sesión a través de esta ruta.
8. Límites de condiciones de carrera y garantías de ordenamiento
Sección titulada «8. Límites de condiciones de carrera y garantías de ordenamiento»Cancelación vs callback de reintento
Sección titulada «Cancelación vs callback de reintento»- la cancelación es síncrona desde la perspectiva del handler TTSR (
agent.abort()se llama inmediatamente) - el reintento se difiere mediante temporizador (
50ms) - la notificación a extensiones es asíncrona e intencionalmente no se espera antes de la programación de cancelación/reintento
Múltiples coincidencias en la misma ventana de flujo
Sección titulada «Múltiples coincidencias en la misma ventana de flujo»check() devuelve todas las reglas elegibles que coinciden actualmente. Se inyectan como un lote en el siguiente mensaje de reintento.
Entre cancelación y continuación
Sección titulada «Entre cancelación y continuación»Durante la ventana del temporizador, el estado puede cambiar (interrupción del usuario, acciones de modo, eventos adicionales). La llamada de reintento es de mejor esfuerzo: agent.continue().catch(() => {}) absorbe los errores subsecuentes.
9. Resumen de casos límite
Sección titulada «9. Resumen de casos límite»- Expresión regular
ttsr_triggerinválida: se omite con advertencia; las demás reglas continúan. - Nombres de reglas duplicados en la capa de capacidades: los duplicados de menor prioridad se sombrean antes del registro.
- Nombres duplicados en la capa del manager: el segundo registro se ignora.
contextMode: "keep": la salida parcial que viola las reglas puede permanecer en el contexto antes del reintento con recordatorio.- El intervalo de repetición (repeat-after-gap) depende de los incrementos del contador de turnos en
turn_end; los fragmentos a mitad de turno no avanzan los contadores de intervalo.