dsh-repeat-guard 0.1.3 → 0.1.4

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.
@@ -29,6 +29,7 @@ type StreamListener = (
29
29
  * @param sessionId - 当前会话 id;有值才登记待续跑标记。
30
30
  * @param state - 跨监听保留的拦截状态。
31
31
  * @param readConfig - 取当前配置;每个 chunk 现取,改设置立即生效。
32
+ * @param countHit - 记一次拦截;只在真的掐断时调用。
32
33
  * @returns 包好的流。
33
34
  */
34
35
  async function* guardStream(
@@ -36,6 +37,7 @@ async function* guardStream(
36
37
  sessionId: GenerateOptions['sessionId'],
37
38
  state: GuardState,
38
39
  readConfig: ConfigSource,
40
+ countHit: () => void,
39
41
  ): AsyncGenerator<StreamChunk> {
40
42
  const iterator = downstream[Symbol.asyncIterator]();
41
43
  let accumulated = '';
@@ -49,10 +51,16 @@ async function* guardStream(
49
51
  if (chunk.type === 'reasoning-delta') {
50
52
  accumulated += chunk.text;
51
53
  const config = readConfig();
52
- const hit = findDegenerateLine(accumulated, config.fragments, config.threshold);
54
+ const hit = findDegenerateLine(
55
+ accumulated,
56
+ config.fragments,
57
+ config.threshold,
58
+ config.inlineRepeat,
59
+ );
53
60
  if (hit !== null) {
54
61
  const probe = await iterator.next();
55
62
  if (!probe.done && probe.value.type === 'reasoning-delta') {
63
+ countHit();
56
64
  if (sessionId !== undefined) {
57
65
  state.pending.add(sessionId);
58
66
  }
@@ -92,14 +100,19 @@ async function* guardStream(
92
100
  * 造一个 `llm/stream` 监听器。
93
101
  * @param state - 跨监听保留的拦截状态。
94
102
  * @param readConfig - 取当前配置。
103
+ * @param countHit - 记一次拦截。
95
104
  * @returns 监听器;辅助调用直接透传,其余包一层复读检测。
96
105
  */
97
- export function createStreamGuard(state: GuardState, readConfig: ConfigSource): StreamListener {
106
+ export function createStreamGuard(
107
+ state: GuardState,
108
+ readConfig: ConfigSource,
109
+ countHit: () => void,
110
+ ): StreamListener {
98
111
  return (options, next) => {
99
112
  // 辅助调用(上下文压缩、会话标题)不参与检测。
100
113
  if (options.purpose !== undefined) {
101
114
  return next();
102
115
  }
103
- return guardStream(next(), options.sessionId, state, readConfig);
116
+ return guardStream(next(), options.sessionId, state, readConfig, countHit);
104
117
  };
105
118
  }
@@ -6,16 +6,18 @@
6
6
  */
7
7
 
8
8
  import type { Agent } from '@deepseek-ai/dsh-agent';
9
+ import type { ConfigSource } from './config.js';
9
10
  import { reviveTurn } from './resume.js';
10
11
  import type { GuardState } from './types.js';
11
12
 
12
13
  /**
13
14
  * 造一个 `agent/turn-stopping` 监听器。
14
15
  * @param state - 跨监听保留的拦截状态。
16
+ * @param readConfig - 取当前配置。
15
17
  * @returns 监听器;只在有待续跑标记时推一条输入。
16
18
  */
17
- export function createTurnStoppingGuard(state: GuardState) {
19
+ export function createTurnStoppingGuard(state: GuardState, readConfig: ConfigSource) {
18
20
  return (payload: { agent: Agent }): void => {
19
- reviveTurn(state, payload.agent);
21
+ reviveTurn(state, payload.agent, readConfig());
20
22
  };
21
23
  }