wotann 0.5.39 → 0.5.41

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. package/dist/autopilot/completion-oracle.d.ts +71 -0
  2. package/dist/autopilot/completion-oracle.d.ts.map +1 -1
  3. package/dist/autopilot/completion-oracle.js +69 -2
  4. package/dist/autopilot/completion-oracle.js.map +1 -1
  5. package/dist/context/compaction-floor.d.ts +100 -0
  6. package/dist/context/compaction-floor.d.ts.map +1 -0
  7. package/dist/context/compaction-floor.js +94 -0
  8. package/dist/context/compaction-floor.js.map +1 -0
  9. package/dist/context/compaction.d.ts +27 -1
  10. package/dist/context/compaction.d.ts.map +1 -1
  11. package/dist/context/compaction.js +31 -0
  12. package/dist/context/compaction.js.map +1 -1
  13. package/dist/daemon/kairos-rpc.d.ts +1 -0
  14. package/dist/daemon/kairos-rpc.d.ts.map +1 -1
  15. package/dist/daemon/kairos-rpc.js +24 -0
  16. package/dist/daemon/kairos-rpc.js.map +1 -1
  17. package/dist/daemon/rpc-handlers/ports-rpc.d.ts +100 -0
  18. package/dist/daemon/rpc-handlers/ports-rpc.d.ts.map +1 -0
  19. package/dist/daemon/rpc-handlers/ports-rpc.js +278 -0
  20. package/dist/daemon/rpc-handlers/ports-rpc.js.map +1 -0
  21. package/dist/hooks/agentmemory-event-taxonomy.d.ts +144 -0
  22. package/dist/hooks/agentmemory-event-taxonomy.d.ts.map +1 -0
  23. package/dist/hooks/agentmemory-event-taxonomy.js +85 -0
  24. package/dist/hooks/agentmemory-event-taxonomy.js.map +1 -0
  25. package/dist/hooks/built-in.d.ts.map +1 -1
  26. package/dist/hooks/built-in.js +7 -3
  27. package/dist/hooks/built-in.js.map +1 -1
  28. package/dist/hooks/engine.d.ts +14 -0
  29. package/dist/hooks/engine.d.ts.map +1 -1
  30. package/dist/hooks/engine.js +62 -0
  31. package/dist/hooks/engine.js.map +1 -1
  32. package/dist/index.js +91 -2
  33. package/dist/index.js.map +1 -1
  34. package/dist/lib.d.ts +1 -1
  35. package/dist/lib.d.ts.map +1 -1
  36. package/dist/lib.js +1 -1
  37. package/dist/lib.js.map +1 -1
  38. package/dist/memory/injection-scanner.d.ts +78 -0
  39. package/dist/memory/injection-scanner.d.ts.map +1 -0
  40. package/dist/memory/injection-scanner.js +204 -0
  41. package/dist/memory/injection-scanner.js.map +1 -0
  42. package/dist/middleware/output-truncation.d.ts +18 -5
  43. package/dist/middleware/output-truncation.d.ts.map +1 -1
  44. package/dist/middleware/output-truncation.js +73 -1
  45. package/dist/middleware/output-truncation.js.map +1 -1
  46. package/dist/middleware/ttsr.d.ts +79 -3
  47. package/dist/middleware/ttsr.d.ts.map +1 -1
  48. package/dist/middleware/ttsr.js +136 -16
  49. package/dist/middleware/ttsr.js.map +1 -1
  50. package/dist/orchestration/autonomous.d.ts +182 -0
  51. package/dist/orchestration/autonomous.d.ts.map +1 -1
  52. package/dist/orchestration/autonomous.js +288 -1
  53. package/dist/orchestration/autonomous.js.map +1 -1
  54. package/dist/orchestration/ports-bridge.d.ts +325 -0
  55. package/dist/orchestration/ports-bridge.d.ts.map +1 -0
  56. package/dist/orchestration/ports-bridge.js +712 -0
  57. package/dist/orchestration/ports-bridge.js.map +1 -0
  58. package/dist/orchestration/textgrad-refinement.d.ts +123 -0
  59. package/dist/orchestration/textgrad-refinement.d.ts.map +1 -0
  60. package/dist/orchestration/textgrad-refinement.js +111 -0
  61. package/dist/orchestration/textgrad-refinement.js.map +1 -0
  62. package/dist/prompt/engine.d.ts +15 -0
  63. package/dist/prompt/engine.d.ts.map +1 -1
  64. package/dist/prompt/engine.js +20 -7
  65. package/dist/prompt/engine.js.map +1 -1
  66. package/dist/prompt/modules/capabilities.d.ts.map +1 -1
  67. package/dist/prompt/modules/capabilities.js +1 -0
  68. package/dist/prompt/modules/capabilities.js.map +1 -1
  69. package/dist/prompt/modules/caveman.d.ts.map +1 -1
  70. package/dist/prompt/modules/caveman.js +1 -0
  71. package/dist/prompt/modules/caveman.js.map +1 -1
  72. package/dist/prompt/modules/conventions.d.ts.map +1 -1
  73. package/dist/prompt/modules/conventions.js +1 -0
  74. package/dist/prompt/modules/conventions.js.map +1 -1
  75. package/dist/prompt/modules/identity.d.ts.map +1 -1
  76. package/dist/prompt/modules/identity.js +1 -0
  77. package/dist/prompt/modules/identity.js.map +1 -1
  78. package/dist/prompt/modules/index.d.ts +29 -0
  79. package/dist/prompt/modules/index.d.ts.map +1 -1
  80. package/dist/prompt/modules/index.js +51 -9
  81. package/dist/prompt/modules/index.js.map +1 -1
  82. package/dist/prompt/modules/llms-txt.d.ts.map +1 -1
  83. package/dist/prompt/modules/llms-txt.js +2 -4
  84. package/dist/prompt/modules/llms-txt.js.map +1 -1
  85. package/dist/prompt/modules/safety.d.ts.map +1 -1
  86. package/dist/prompt/modules/safety.js +1 -0
  87. package/dist/prompt/modules/safety.js.map +1 -1
  88. package/dist/prompt/modules/security.d.ts.map +1 -1
  89. package/dist/prompt/modules/security.js +1 -0
  90. package/dist/prompt/modules/security.js.map +1 -1
  91. package/dist/prompt/modules/skills.d.ts.map +1 -1
  92. package/dist/prompt/modules/skills.js +1 -0
  93. package/dist/prompt/modules/skills.js.map +1 -1
  94. package/dist/prompt/modules/tools.d.ts.map +1 -1
  95. package/dist/prompt/modules/tools.js +1 -0
  96. package/dist/prompt/modules/tools.js.map +1 -1
  97. package/dist/prompt/modules/user.d.ts.map +1 -1
  98. package/dist/prompt/modules/user.js +1 -0
  99. package/dist/prompt/modules/user.js.map +1 -1
  100. package/dist/providers/credential-pool.d.ts +45 -1
  101. package/dist/providers/credential-pool.d.ts.map +1 -1
  102. package/dist/providers/credential-pool.js +94 -1
  103. package/dist/providers/credential-pool.js.map +1 -1
  104. package/dist/providers/sticky-rotation-wire.d.ts +133 -0
  105. package/dist/providers/sticky-rotation-wire.d.ts.map +1 -0
  106. package/dist/providers/sticky-rotation-wire.js +185 -0
  107. package/dist/providers/sticky-rotation-wire.js.map +1 -0
  108. package/dist/runtime-hooks/ttsr-rule.d.ts +82 -0
  109. package/dist/runtime-hooks/ttsr-rule.d.ts.map +1 -0
  110. package/dist/runtime-hooks/ttsr-rule.js +207 -0
  111. package/dist/runtime-hooks/ttsr-rule.js.map +1 -0
  112. package/dist/runtime-hooks/ttsr-runner.d.ts +129 -0
  113. package/dist/runtime-hooks/ttsr-runner.d.ts.map +1 -0
  114. package/dist/runtime-hooks/ttsr-runner.js +193 -0
  115. package/dist/runtime-hooks/ttsr-runner.js.map +1 -0
  116. package/dist/runtime-hooks/ttsr-scope.d.ts +115 -0
  117. package/dist/runtime-hooks/ttsr-scope.d.ts.map +1 -0
  118. package/dist/runtime-hooks/ttsr-scope.js +378 -0
  119. package/dist/runtime-hooks/ttsr-scope.js.map +1 -0
  120. package/dist/sandbox/unified-exec.d.ts.map +1 -1
  121. package/dist/sandbox/unified-exec.js +6 -1
  122. package/dist/sandbox/unified-exec.js.map +1 -1
  123. package/dist/skills/cli-anything.d.ts.map +1 -1
  124. package/dist/skills/cli-anything.js +4 -1
  125. package/dist/skills/cli-anything.js.map +1 -1
  126. package/dist/skills/limits.d.ts +86 -0
  127. package/dist/skills/limits.d.ts.map +1 -0
  128. package/dist/skills/limits.js +140 -0
  129. package/dist/skills/limits.js.map +1 -0
  130. package/dist/skills/loader.d.ts +9 -0
  131. package/dist/skills/loader.d.ts.map +1 -1
  132. package/dist/skills/loader.js +29 -1
  133. package/dist/skills/loader.js.map +1 -1
  134. package/dist/storage/session-artifacts.d.ts +105 -0
  135. package/dist/storage/session-artifacts.d.ts.map +1 -0
  136. package/dist/storage/session-artifacts.js +198 -0
  137. package/dist/storage/session-artifacts.js.map +1 -0
  138. package/dist/tools/workspace-pack.d.ts +97 -0
  139. package/dist/tools/workspace-pack.d.ts.map +1 -0
  140. package/dist/tools/workspace-pack.js +228 -0
  141. package/dist/tools/workspace-pack.js.map +1 -0
  142. package/dist/tui/composer-history.d.ts +99 -0
  143. package/dist/tui/composer-history.d.ts.map +1 -0
  144. package/dist/tui/composer-history.js +169 -0
  145. package/dist/tui/composer-history.js.map +1 -0
  146. package/dist/ui/components/PromptInput.d.ts.map +1 -1
  147. package/dist/ui/components/PromptInput.js +80 -9
  148. package/dist/ui/components/PromptInput.js.map +1 -1
  149. package/package.json +1 -1
@@ -0,0 +1,129 @@
1
+ /**
2
+ * TTSR Runner - per-token rule evaluation.
3
+ *
4
+ * The Runner is the PURE LOGIC core of WOTANN's time-traveling
5
+ * streamed rules. It accepts streaming tokens labeled with a
6
+ * StreamContext, buffers them per stream kind, and emits a
7
+ * `TTSRTrigger` whenever a rule's regex matches its scoped buffer.
8
+ *
9
+ * It deliberately does NOT control the stream. It does not abort,
10
+ * does not retry, does not call the orchestrator. The middleware in
11
+ * `src/middleware/ttsr.ts` (which Anthropic / OpenAI / Ollama
12
+ * stream decoders consult) is responsible for converting a trigger
13
+ * into an actual abort + retry decision.
14
+ *
15
+ * That separation is critical: it lets the Runner be tested with
16
+ * zero provider mocking, and lets the orchestrator decide retry
17
+ * semantics (discard vs keep partial, retry once vs fall back to a
18
+ * smaller model, etc.) independently.
19
+ *
20
+ * See:
21
+ * - oh-my-pi packages/coding-agent/src/export/ttsr.ts (reference TtsrManager)
22
+ * - oh-my-pi packages/coding-agent/src/modes/controllers/event-controller.ts:631 (`ttsr_triggered` event consumer)
23
+ */
24
+ import type { TTSRRule } from "./ttsr-rule.js";
25
+ import { type StreamContext, type StreamKind } from "./ttsr-scope.js";
26
+ /**
27
+ * A trigger emitted by `observeToken` when a rule fires.
28
+ *
29
+ * The orchestrator turns this into:
30
+ * 1. stream.abort()
31
+ * 2. retry the model turn with `injectionBody` wrapped in
32
+ * `<system-reminder>...</system-reminder>` appended to the
33
+ * previous system prompt
34
+ * 3. on retry success, call `acknowledgeFired(rule.id)` so
35
+ * one-shot rules do not re-fire on the same session.
36
+ */
37
+ export interface TTSRTrigger {
38
+ readonly rule: TTSRRule;
39
+ readonly matchedAt: number;
40
+ readonly matchedText: string;
41
+ readonly context: StreamContext;
42
+ readonly bufferKey: string;
43
+ }
44
+ /**
45
+ * Snapshot used by tests and by the middleware for diagnostics.
46
+ */
47
+ export interface TTSRRunnerState {
48
+ readonly tokenCount: number;
49
+ readonly bufferKeys: readonly string[];
50
+ readonly firedRuleIds: readonly string[];
51
+ readonly registeredRuleIds: readonly string[];
52
+ }
53
+ export interface TTSRRunnerOptions {
54
+ readonly rules: readonly TTSRRule[];
55
+ /**
56
+ * Maximum buffer size per stream key. When exceeded, the buffer
57
+ * is sliced down to half-window. Default: 32 KiB. Setting to 0
58
+ * disables the cap (use with caution on long turns).
59
+ */
60
+ readonly maxBufferBytes?: number;
61
+ }
62
+ /**
63
+ * Runner instance.
64
+ *
65
+ * - Constructed with a frozen `rules` array (no hot reload by
66
+ * design - reload by building a new runner).
67
+ * - One instance per session. Reuse across turns is fine; reuse
68
+ * across sessions is NOT (fire records would leak).
69
+ */
70
+ export declare class TTSRRunner {
71
+ #private;
72
+ constructor(opts: TTSRRunnerOptions);
73
+ /**
74
+ * Feed one streamed token (or chunk) labeled with its stream
75
+ * context. Returns a `TTSRTrigger` when ANY rule fires, otherwise
76
+ * `null`.
77
+ *
78
+ * Multiple rules can match in principle; the first match wins to
79
+ * keep the orchestrator wire simple. Callers wanting all matches
80
+ * can call `observeAll` (below).
81
+ */
82
+ observeToken(token: string, ctx: StreamContext): TTSRTrigger | null;
83
+ /**
84
+ * Same as `observeToken` but returns every matching rule on the
85
+ * combined buffer. Useful when an orchestrator wants to inject
86
+ * multiple system reminders in one retry.
87
+ */
88
+ observeAll(token: string, ctx: StreamContext): readonly TTSRTrigger[];
89
+ /**
90
+ * Notify the runner that the orchestrator processed the trigger
91
+ * for `ruleId`. After this call, one-shot rules stop firing for
92
+ * the rest of the session.
93
+ *
94
+ * Non-one-shot rules are unaffected.
95
+ *
96
+ * Safe to call repeatedly with the same id (idempotent).
97
+ */
98
+ acknowledgeFired(ruleId: string): void;
99
+ /**
100
+ * Build the injection body the orchestrator should hand back to
101
+ * the model as a system reminder.
102
+ *
103
+ * Currently just `trigger.rule.body`, but kept as a method so we
104
+ * can later add metadata (matched text, file path, etc.) without
105
+ * changing the orchestrator wire.
106
+ */
107
+ getInjectionBody(trigger: TTSRTrigger): string;
108
+ /**
109
+ * Clear all per-turn buffers. Call between turns so cross-turn
110
+ * matches do not leak. Does NOT clear the one-shot fired set -
111
+ * one-shot is per-session.
112
+ */
113
+ resetBuffers(): void;
114
+ /**
115
+ * Clear EVERYTHING for a new session: buffers AND fired records.
116
+ * The runner becomes equivalent to a freshly constructed one.
117
+ */
118
+ reset(): void;
119
+ /** Inspect runner state. Used by middleware diagnostics + tests. */
120
+ getState(): TTSRRunnerState;
121
+ /** Has this rule already fired (and been acknowledged) this session? */
122
+ hasFired(ruleId: string): boolean;
123
+ /**
124
+ * Convenience: peek the buffer for a stream key. Returns empty
125
+ * string when nothing has been buffered yet. Read-only.
126
+ */
127
+ peekBuffer(kindOrKey: StreamKind | string, toolName?: string): string;
128
+ }
129
+ //# sourceMappingURL=ttsr-runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ttsr-runner.d.ts","sourceRoot":"","sources":["../../src/runtime-hooks/ttsr-runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAIL,KAAK,aAAa,EAClB,KAAK,UAAU,EAChB,MAAM,iBAAiB,CAAC;AAEzB;;;;;;;;;;GAUG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,QAAQ,CAAC,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAAC;CAC/C;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,CAAC;IACpC;;;;OAIG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;CAClC;AA0BD;;;;;;;GAOG;AACH,qBAAa,UAAU;;gBAOT,IAAI,EAAE,iBAAiB;IAYnC;;;;;;;;OAQG;IACH,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,GAAG,WAAW,GAAG,IAAI;IAKnE;;;;OAIG;IACH,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,GAAG,SAAS,WAAW,EAAE;IAoCrE;;;;;;;;OAQG;IACH,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAKtC;;;;;;;OAOG;IACH,gBAAgB,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM;IAI9C;;;;OAIG;IACH,YAAY,IAAI,IAAI;IAKpB;;;OAGG;IACH,KAAK,IAAI,IAAI;IAMb,oEAAoE;IACpE,QAAQ,IAAI,eAAe;IAS3B,wEAAwE;IACxE,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAIjC;;;OAGG;IACH,UAAU,CAAC,SAAS,EAAE,UAAU,GAAG,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM;CAWtE"}
@@ -0,0 +1,193 @@
1
+ /**
2
+ * TTSR Runner - per-token rule evaluation.
3
+ *
4
+ * The Runner is the PURE LOGIC core of WOTANN's time-traveling
5
+ * streamed rules. It accepts streaming tokens labeled with a
6
+ * StreamContext, buffers them per stream kind, and emits a
7
+ * `TTSRTrigger` whenever a rule's regex matches its scoped buffer.
8
+ *
9
+ * It deliberately does NOT control the stream. It does not abort,
10
+ * does not retry, does not call the orchestrator. The middleware in
11
+ * `src/middleware/ttsr.ts` (which Anthropic / OpenAI / Ollama
12
+ * stream decoders consult) is responsible for converting a trigger
13
+ * into an actual abort + retry decision.
14
+ *
15
+ * That separation is critical: it lets the Runner be tested with
16
+ * zero provider mocking, and lets the orchestrator decide retry
17
+ * semantics (discard vs keep partial, retry once vs fall back to a
18
+ * smaller model, etc.) independently.
19
+ *
20
+ * See:
21
+ * - oh-my-pi packages/coding-agent/src/export/ttsr.ts (reference TtsrManager)
22
+ * - oh-my-pi packages/coding-agent/src/modes/controllers/event-controller.ts:631 (`ttsr_triggered` event consumer)
23
+ */
24
+ import { matchScope, parseScope, } from "./ttsr-scope.js";
25
+ const DEFAULT_MAX_BUFFER_BYTES = 32 * 1024;
26
+ /**
27
+ * Determine the buffer key for a given stream context.
28
+ *
29
+ * - text -> "text"
30
+ * - thinking -> "thinking"
31
+ * - tool -> "tool:<name>" or just "tool" if unnamed
32
+ *
33
+ * Keeping buffers isolated per context prevents prose-side matches
34
+ * from bleeding into tool-call buffers and vice versa.
35
+ */
36
+ function bufferKeyFor(ctx) {
37
+ if (ctx.kind === "text")
38
+ return "text";
39
+ if (ctx.kind === "thinking")
40
+ return "thinking";
41
+ const tool = ctx.toolName?.trim().toLowerCase();
42
+ return tool ? `tool:${tool}` : "tool";
43
+ }
44
+ /**
45
+ * Runner instance.
46
+ *
47
+ * - Constructed with a frozen `rules` array (no hot reload by
48
+ * design - reload by building a new runner).
49
+ * - One instance per session. Reuse across turns is fine; reuse
50
+ * across sessions is NOT (fire records would leak).
51
+ */
52
+ export class TTSRRunner {
53
+ #compiled;
54
+ #buffers = new Map();
55
+ #fired = new Set();
56
+ #maxBufferBytes;
57
+ #tokenCount = 0;
58
+ constructor(opts) {
59
+ if (!opts || !Array.isArray(opts.rules)) {
60
+ throw new Error("TTSRRunner requires a rules array");
61
+ }
62
+ // Defensive copy + pre-parse the scope to avoid re-parsing per token.
63
+ this.#compiled = opts.rules.map((r) => ({ rule: r, scope: parseScope(r.scope) }));
64
+ this.#maxBufferBytes =
65
+ typeof opts.maxBufferBytes === "number" && opts.maxBufferBytes >= 0
66
+ ? opts.maxBufferBytes
67
+ : DEFAULT_MAX_BUFFER_BYTES;
68
+ }
69
+ /**
70
+ * Feed one streamed token (or chunk) labeled with its stream
71
+ * context. Returns a `TTSRTrigger` when ANY rule fires, otherwise
72
+ * `null`.
73
+ *
74
+ * Multiple rules can match in principle; the first match wins to
75
+ * keep the orchestrator wire simple. Callers wanting all matches
76
+ * can call `observeAll` (below).
77
+ */
78
+ observeToken(token, ctx) {
79
+ const all = this.observeAll(token, ctx);
80
+ return all.length > 0 ? (all[0] ?? null) : null;
81
+ }
82
+ /**
83
+ * Same as `observeToken` but returns every matching rule on the
84
+ * combined buffer. Useful when an orchestrator wants to inject
85
+ * multiple system reminders in one retry.
86
+ */
87
+ observeAll(token, ctx) {
88
+ if (typeof token !== "string" || token.length === 0)
89
+ return [];
90
+ this.#tokenCount++;
91
+ const key = bufferKeyFor(ctx);
92
+ const previous = this.#buffers.get(key) ?? "";
93
+ let buffer = previous + token;
94
+ // Cap buffer size to bound memory + regex work. Keep the most
95
+ // recent half so the suffix the token landed in survives.
96
+ if (this.#maxBufferBytes > 0 && buffer.length > this.#maxBufferBytes) {
97
+ buffer = buffer.slice(-Math.floor(this.#maxBufferBytes / 2));
98
+ }
99
+ this.#buffers.set(key, buffer);
100
+ const triggers = [];
101
+ for (const cr of this.#compiled) {
102
+ // One-shot enforcement: never re-fire.
103
+ if ((cr.rule.oneShot ?? true) && this.#fired.has(cr.rule.id))
104
+ continue;
105
+ if (!cr.scope.reachable)
106
+ continue;
107
+ if (!matchScope(cr.scope, ctx))
108
+ continue;
109
+ const matched = buffer.match(cr.rule.condition);
110
+ if (!matched || matched[0] === undefined)
111
+ continue;
112
+ triggers.push({
113
+ rule: cr.rule,
114
+ matchedAt: this.#tokenCount,
115
+ matchedText: matched[0],
116
+ context: ctx,
117
+ bufferKey: key,
118
+ });
119
+ }
120
+ return triggers;
121
+ }
122
+ /**
123
+ * Notify the runner that the orchestrator processed the trigger
124
+ * for `ruleId`. After this call, one-shot rules stop firing for
125
+ * the rest of the session.
126
+ *
127
+ * Non-one-shot rules are unaffected.
128
+ *
129
+ * Safe to call repeatedly with the same id (idempotent).
130
+ */
131
+ acknowledgeFired(ruleId) {
132
+ if (typeof ruleId !== "string" || ruleId.length === 0)
133
+ return;
134
+ this.#fired.add(ruleId);
135
+ }
136
+ /**
137
+ * Build the injection body the orchestrator should hand back to
138
+ * the model as a system reminder.
139
+ *
140
+ * Currently just `trigger.rule.body`, but kept as a method so we
141
+ * can later add metadata (matched text, file path, etc.) without
142
+ * changing the orchestrator wire.
143
+ */
144
+ getInjectionBody(trigger) {
145
+ return trigger.rule.body;
146
+ }
147
+ /**
148
+ * Clear all per-turn buffers. Call between turns so cross-turn
149
+ * matches do not leak. Does NOT clear the one-shot fired set -
150
+ * one-shot is per-session.
151
+ */
152
+ resetBuffers() {
153
+ this.#buffers.clear();
154
+ this.#tokenCount = 0;
155
+ }
156
+ /**
157
+ * Clear EVERYTHING for a new session: buffers AND fired records.
158
+ * The runner becomes equivalent to a freshly constructed one.
159
+ */
160
+ reset() {
161
+ this.#buffers.clear();
162
+ this.#fired.clear();
163
+ this.#tokenCount = 0;
164
+ }
165
+ /** Inspect runner state. Used by middleware diagnostics + tests. */
166
+ getState() {
167
+ return {
168
+ tokenCount: this.#tokenCount,
169
+ bufferKeys: Array.from(this.#buffers.keys()),
170
+ firedRuleIds: Array.from(this.#fired),
171
+ registeredRuleIds: this.#compiled.map((c) => c.rule.id),
172
+ };
173
+ }
174
+ /** Has this rule already fired (and been acknowledged) this session? */
175
+ hasFired(ruleId) {
176
+ return this.#fired.has(ruleId);
177
+ }
178
+ /**
179
+ * Convenience: peek the buffer for a stream key. Returns empty
180
+ * string when nothing has been buffered yet. Read-only.
181
+ */
182
+ peekBuffer(kindOrKey, toolName) {
183
+ const key = kindOrKey === "text" || kindOrKey === "thinking"
184
+ ? kindOrKey
185
+ : kindOrKey === "tool"
186
+ ? toolName
187
+ ? `tool:${toolName.toLowerCase()}`
188
+ : "tool"
189
+ : kindOrKey;
190
+ return this.#buffers.get(key) ?? "";
191
+ }
192
+ }
193
+ //# sourceMappingURL=ttsr-runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ttsr-runner.js","sourceRoot":"","sources":["../../src/runtime-hooks/ttsr-runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,115 @@
1
+ /**
2
+ * TTSR Scope filter parsing + matching.
3
+ *
4
+ * Port of oh-my-pi's stream-scope filter:
5
+ * - packages/coding-agent/src/capability/rule.ts (quote/brace-aware tokenizer)
6
+ * - packages/coding-agent/src/export/ttsr.ts (TtsrScope + parseToolScopeToken)
7
+ *
8
+ * A ScopeFilter restricts WHEN a TTSR rule may fire during a streamed
9
+ * model turn. The rule only triggers when the current stream context
10
+ * matches its scope, so a rule scoped to `tool:edit(*.ts)` will not
11
+ * fire while the model is producing prose, thinking text, or arguments
12
+ * for a `write` tool call on a `*.md` file.
13
+ *
14
+ * This file is intentionally PURE — it builds matcher predicates and
15
+ * answers boolean questions. It does not touch streams, providers, or
16
+ * the orchestrator. Wiring lives in `ttsr-runner.ts` and (further out)
17
+ * `src/middleware/ttsr.ts`.
18
+ */
19
+ /**
20
+ * Stream context kind associated with the chunk currently being
21
+ * inspected. The orchestrator labels each delta with one of these
22
+ * before handing it to the runner.
23
+ */
24
+ export type StreamKind = "text" | "thinking" | "tool";
25
+ /**
26
+ * Context about the current stream chunk. Tool deltas carry the tool
27
+ * name and (optionally) a `toolInput` partial — file paths are read
28
+ * out of `toolInput.path`, `toolInput.paths`, `toolInput.file_path`,
29
+ * or `toolInput.files[]` so we accept the common provider shapes.
30
+ */
31
+ export interface StreamContext {
32
+ readonly kind: StreamKind;
33
+ readonly toolName?: string;
34
+ readonly toolInput?: Record<string, unknown>;
35
+ /** Optional file paths if the orchestrator pre-extracted them. */
36
+ readonly filePaths?: readonly string[];
37
+ }
38
+ /**
39
+ * Tokens accepted in a scope filter string:
40
+ *
41
+ * "any" - every stream kind
42
+ * "text" - assistant prose
43
+ * "thinking" - chain-of-thought / reasoning channel
44
+ * "tool" - any tool call (no name/path filter)
45
+ * "tool:<name>" - only the named tool
46
+ * "tool:<name>(<glob>)" - only the named tool with matching file path
47
+ *
48
+ * Multi-token scopes are valid too: `"text, tool:write(*.{ts,tsx})"`
49
+ * - the tokenizer in `parseScope` is quote / brace / bracket aware so
50
+ * the comma inside `*.{ts,tsx}` does NOT split the token.
51
+ */
52
+ export type ScopeFilter = string;
53
+ export type ParsedScopeTokenKind = "any" | "text" | "thinking" | "tool";
54
+ /**
55
+ * One parsed token in a (possibly multi-token) scope filter.
56
+ *
57
+ * `kind: "tool"` is the only kind that carries a name or a glob.
58
+ */
59
+ export interface ParsedScopeToken {
60
+ readonly kind: ParsedScopeTokenKind;
61
+ readonly raw: string;
62
+ readonly toolName?: string;
63
+ readonly glob?: string;
64
+ }
65
+ export interface ParsedScope {
66
+ readonly raw: string;
67
+ readonly tokens: readonly ParsedScopeToken[];
68
+ /** True iff the scope is reachable at all (has at least one valid token). */
69
+ readonly reachable: boolean;
70
+ }
71
+ /**
72
+ * Quote-, paren-, bracket-, and brace-aware split on `,`.
73
+ *
74
+ * Mirrors oh-my-pi rule.ts splitScopeTokens so that scope strings such
75
+ * as `"tool:write(*.{ts,tsx}), text"` parse as two tokens, not three.
76
+ *
77
+ * Returns trimmed, non-empty tokens preserving original order.
78
+ */
79
+ export declare function splitScopeTokens(value: string): readonly string[];
80
+ /**
81
+ * Parse a `ScopeFilter` string into a structured `ParsedScope`.
82
+ *
83
+ * - Empty or all-whitespace input -> `reachable: false` with no tokens.
84
+ * - Unknown / malformed tokens are dropped silently (the runner can
85
+ * surface a warning if it wants to).
86
+ * - Multi-token scopes are UNIONed at match time: any one match -> true.
87
+ */
88
+ export declare function parseScope(s: ScopeFilter | undefined | null): ParsedScope;
89
+ /**
90
+ * Pull candidate file paths from a tool input bag. Accepts the
91
+ * common shapes used by tool calls across providers:
92
+ * { path: "src/a.ts" }
93
+ * { file_path: "src/a.ts" }
94
+ * { paths: ["src/a.ts", "src/b.ts"] }
95
+ * { files: [{ path: "src/a.ts" }] }
96
+ *
97
+ * Anything that does not look like a string path is ignored.
98
+ */
99
+ export declare function extractFilePaths(ctx: StreamContext): readonly string[];
100
+ /**
101
+ * Test whether a parsed scope matches the supplied stream context.
102
+ *
103
+ * Multi-token scopes are UNIONed - a single token match returns true.
104
+ * `kind: "any"` always returns true. An unreachable scope (no tokens)
105
+ * returns false: callers must default to a sentinel like `"any"` if
106
+ * they want a permissive default.
107
+ */
108
+ export declare function matchScope(scope: ScopeFilter | ParsedScope | undefined | null, ctx: StreamContext): boolean;
109
+ /**
110
+ * Convenience for tests + downstream wires that have a raw scope string.
111
+ *
112
+ * Returns true if at least one parsed token reaches some stream kind.
113
+ */
114
+ export declare function isReachableScope(s: ScopeFilter | undefined | null): boolean;
115
+ //# sourceMappingURL=ttsr-scope.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ttsr-scope.d.ts","sourceRoot":"","sources":["../../src/runtime-hooks/ttsr-scope.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,CAAC;AAEtD;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC7C,kEAAkE;IAClE,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACxC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC;AAEjC,MAAM,MAAM,oBAAoB,GAAG,KAAK,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,CAAC;AAExE;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IACpC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAC7C,6EAA6E;IAC7E,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC7B;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAiEjE;AAsDD;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,WAAW,GAAG,SAAS,GAAG,IAAI,GAAG,WAAW,CAkBzE;AAqGD;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,aAAa,GAAG,SAAS,MAAM,EAAE,CAkCtE;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CACxB,KAAK,EAAE,WAAW,GAAG,WAAW,GAAG,SAAS,GAAG,IAAI,EACnD,GAAG,EAAE,aAAa,GACjB,OAAO,CAoDT;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,WAAW,GAAG,SAAS,GAAG,IAAI,GAAG,OAAO,CAE3E"}