docs: update docs

This commit is contained in:
can1357
2026-04-30 06:44:16 +02:00
parent 5003996a01
commit 9865a4ce6c
54 changed files with 2145 additions and 1959 deletions
+33 -27
View File
@@ -17,14 +17,15 @@ This document covers the current Time Traveling Stream Rules (TTSR) runtime path
## 1. Discovery feed and rule registration
At session creation, `createAgentSession()` loads all discovered rules and constructs a `TtsrManager`:
At session creation, `createAgentSession()` loads discovered rules and constructs a `TtsrManager`:
```ts
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);
if (rule.condition?.length && ttsrManager.addRule(rule)) continue;
// non-TTSR rules continue through normal rule handling
}
```
@@ -36,15 +37,15 @@ for (const rule of rulesResult.items) {
Registration is skipped when:
- `rule.ttsrTrigger` is absent
- `rule.condition` is absent or all condition regexes fail to compile
- a rule with the same `rule.name` was already registered in this manager
- the regex fails to compile (`new RegExp(rule.ttsrTrigger)` throws)
- the rule scope excludes all monitored streams
Invalid regex triggers are logged as warnings and ignored; session startup continues.
Invalid regex conditions and unreachable scopes are logged as warnings and ignored; session startup continues.
### Setting caveat
`TtsrSettings.enabled` is loaded into the manager but is not currently checked in runtime gating. If rules exist, matching still runs.
`TtsrSettings.enabled` is loaded into the manager but is not currently checked in runtime gating. If TTSR rules exist, matching still runs.
## 2. Streaming monitor lifecycle
@@ -60,22 +61,21 @@ On `turn_start`, the stream buffer is reset:
When assistant updates arrive and rules exist:
- monitor `text_delta` and `toolcall_delta`
- append delta into manager buffer
- call `check(buffer)`
- monitor `text_delta`, `thinking_delta`, and `toolcall_delta`
- append delta into a source/tool scoped manager buffer
- call `checkDelta(delta, matchContext)`
`check()` iterates registered rules and returns all matching rules that pass repeat policy (`#canTrigger`).
`checkDelta()` iterates registered rules and returns all matching rules that pass scope, global-path, condition, and repeat policy checks.
## 3. Trigger decision and immediate abort path
When one or more rules match:
When one or more rules match and at least one matched rule allows interruption:
1. `markInjected(matches)` records rule names in manager injection state.
2. matched rules are queued in `#pendingTtsrInjections`.
3. `#ttsrAbortPending = true`.
4. `agent.abort()` is called immediately.
5. `ttsr_triggered` event is emitted asynchronously (fire-and-forget).
6. retry work is scheduled via `setTimeout(..., 50)`.
1. Matched rules are deduplicated into `#pendingTtsrInjections`.
2. `#ttsrAbortPending = true` and a TTSR resume gate is created.
3. `agent.abort()` is called immediately.
4. `ttsr_triggered` event is emitted asynchronously (fire-and-forget).
5. retry work is scheduled via the post-prompt task scheduler with a 50ms delay.
Abort is not blocked on extension callbacks.
@@ -85,10 +85,10 @@ After the 50ms timeout:
1. `#ttsrAbortPending = false`
2. read `ttsrManager.getSettings().contextMode`
3. if `contextMode === "discard"`, drop partial assistant output with `agent.popMessage()`
3. if `contextMode === "discard"`, drop the targeted partial assistant output with `agent.replaceMessages(...slice(0, targetAssistantIndex))`
4. build injection content from pending rules using `ttsr-interrupt.md` template
5. append a synthetic user message containing one `<system-interrupt ...>` block per rule
6. call `agent.continue()` to retry generation
5. append and persist a hidden `custom_message`/runtime custom message with `customType: "ttsr-injection"` and `details.rules`
6. mark those rule names injected, persist a `ttsr_injection` entry, and call `agent.continue()` to retry generation
Template payload is:
@@ -106,6 +106,10 @@ Pending injections are cleared after content generation.
- `discard`: partial/aborted assistant message is removed before retry.
- `keep`: partial assistant output remains in conversation state; reminder is appended after it.
### Non-interrupting matches
If matched rules do not permit interruption (`interruptMode: "never"`, or source-specific `prose-only`/`tool-only` mismatch), they are still queued. After a successful non-error, non-aborted assistant message, `AgentSession` injects the hidden `ttsr-injection` custom message as a follow-up and schedules continuation.
## 5. Repeat policy and gap logic
`TtsrManager` tracks `#messageCount` and per-rule `lastInjectedAt`.
@@ -151,23 +155,24 @@ Interactive mode uses `session.isTtsrAbortPending` to suppress showing the abort
## 7. Persistence and resume state (current implementation)
`SessionManager` has full schema support for injected-rule persistence:
`SessionManager` persists injected-rule state:
- entry type: `ttsr_injection`
- append API: `appendTtsrInjection(ruleNames)`
- query API: `getInjectedTtsrRules()`
- context reconstruction includes `SessionContext.injectedTtsrRules`
`TtsrManager` also supports restoration via `restoreInjected(ruleNames)`.
`TtsrManager` supports restoration via `restoreInjected(ruleNames)`.
### Current wiring status
In the current runtime path:
- `AgentSession` does not append `ttsr_injection` entries when TTSR triggers.
- `createAgentSession()` does not restore `existingSession.injectedTtsrRules` back into `ttsrManager`.
- interrupted injections append a hidden `custom_message` with `customType: "ttsr-injection"` and append a `ttsr_injection` entry via `appendTtsrInjection(...)`
- deferred non-interrupting injections are marked/persisted when their queued custom message reaches `message_end`
- `createAgentSession()` restores `existingSession.injectedTtsrRules` into `ttsrManager`
Net effect: injected-rule suppression is enforced in-memory for the live process, but is not currently persisted/restored across session reload/resume by this path.
Net effect: injected-rule suppression is persisted/restored across session reload/resume for the current branch path.
## 8. Race boundaries and ordering guarantees
@@ -179,7 +184,7 @@ Net effect: injected-rule suppression is enforced in-memory for the live process
### Multiple matches in same stream window
`check()` returns all currently matching eligible rules. They are injected as a batch on the next retry message.
`checkDelta()` returns all currently matching eligible rules for that scoped buffer. Pending injections are deduplicated by rule name before injection.
### Between abort and continue
@@ -187,8 +192,9 @@ During the timer window, state can change (user interruption, mode actions, addi
## 9. Edge cases summary
- Invalid `ttsr_trigger` regex: skipped with warning; other rules continue.
- Invalid `condition` regex: skipped with warning; other conditions/rules continue.
- Duplicate rule names at capability layer: lower-priority duplicates are shadowed before registration.
- Duplicate names at manager layer: second registration is ignored.
- `contextMode: "keep"`: partial violating output can remain in context before reminder retry.
- `interruptMode: "never"` queues a deferred hidden injection after a successful assistant message rather than aborting mid-stream.
- Repeat-after-gap depends on turn count increments at `turn_end`; mid-turn chunks do not advance gap counters.