expect-pty 0.8.0 → 0.8.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ee45b8c572aa37af57de1fae7b298e0a73a1b1157bb77949edb3918b100b8a81
4
- data.tar.gz: 6767f2e994b45d693e5701a9f153cc3991c48255c3bd6f0fec8ce5884aa72fb2
3
+ metadata.gz: f85e305b108edbac5d96859d034af4221948535a6f160296072eb1c8189c8cfc
4
+ data.tar.gz: 83fa7073bac3d7b17ad16f8fb6bf0bbf34d14379378d9813585b64be5ffd2e52
5
5
  SHA512:
6
- metadata.gz: b2e908dc05179ec58c9cfa11d5105f9e1b1b4089996a588ae2f14dd93b5218e0478ad43e749320200b98d880da54d0381963f7dc59891e943f0d1092bf4b4783
7
- data.tar.gz: ae06bd3ffdac6991bf510d10bf52665bfeaaaac6ea46a78b1e7fdc56f37fb6b4523c29e2a3519f6a374dd675df7cc94607c1b56923cf25bff89603bd95549362
6
+ metadata.gz: 3b4cd1a931adbe60f6d12be3fa49adc43ba9605bbd9c7730661ed435f49b68d3cbaac64a2b3a753134a1350a1edaeaa8c363a27eba837af2ac38663dc336d4ac
7
+ data.tar.gz: 74de2bb39b847334e691ea6d6e47f0bce3417ac6755c1aa91ccdc85cf5b00c21924df9a60a2ad09b525038200d6c4877bad2af826fdff5f8998093b5b7ee457f
data/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.8.1 - 2026-10-11
6
+
7
+ - 修复自动应答已在缓冲开头确定获胜模式,却被后续无关正则的编码错误阻断的问题,保留未消费尾部。
8
+ - 修复 EOF 时 transcript 尾部交付失败跳过接收诊断收尾的问题,两个日志通道均尝试冲刷并保留首个常规异常。
9
+ - 降低大量规则继续匹配、转义扫描和单对象日志补记的开销,并让脱敏流结束后的可见日志恢复普通过滤路径。
10
+
5
11
  ## 0.8.0 - 2026-10-11
6
12
 
7
13
  - 新增可复用的自动应答规则,支持重复确认、分页按键、动态回复和次数上限,按输入顺序处理提示且不延长等待期限,并提供批量脚本示例。
@@ -137,25 +137,30 @@ module Expect
137
137
  def self.scan_sequences(buffer, sequences, history, final:)
138
138
  text = nil
139
139
  utf8_regexp = false
140
- matches = sequences.filter_map do |key, handler|
140
+ earliest = nil
141
+ # 只保存最早候选,同位置不替换先注册者;仍扫描全部正则以校验零宽规则并收集编码状态。
142
+ sequences.each do |key, handler|
141
143
  if key.is_a?(Regexp)
142
144
  # 仅在本轮扫描复用组合文本;回调可能更换规则或消费缓冲,下一轮必须重新构造。
143
145
  text ||= history + buffer
144
146
  utf8_regexp ||= key.fixed_encoding? && key.encoding == Encoding::UTF_8
145
147
  position = Pattern.new(value: key).locate(text, final:, captures: false)
146
- if position
147
- offset, length, = position
148
- raise ArgumentError, "escape regexp must consume at least one byte" if length.zero?
148
+ next unless position
149
149
 
150
- # 历史前缀已实时转发,不能撤回;负偏移表示本次只需消费转义尚未转发的部分。
151
- [offset - history.bytesize, length, handler]
152
- end
150
+ offset, length, = position
151
+ raise ArgumentError, "escape regexp must consume at least one byte" if length.zero?
152
+
153
+ # 历史前缀已实时转发,不能撤回;负偏移表示本次只需消费转义尚未转发的部分。
154
+ offset -= history.bytesize
153
155
  else
154
- position = buffer.index(key)
155
- [position, key.bytesize, handler] if position
156
+ offset = buffer.index(key)
157
+ next unless offset
158
+
159
+ length = key.bytesize
156
160
  end
161
+ earliest = [offset, length, handler] if !earliest || offset < earliest.first
157
162
  end
158
- [matches.min_by(&:first), !text.nil?, utf8_regexp]
163
+ [earliest, !text.nil?, utf8_regexp]
159
164
  end
160
165
 
161
166
  # 普通转发和超时排出的字面前缀都属于正则历史,跨次转接时必须接续同一字节流。
@@ -53,7 +53,8 @@ module Expect
53
53
  def write_transcript(*objects)
54
54
  return unless transcript
55
55
 
56
- data = objects.map { |object| object.to_s.b }.join
56
+ # 单对象沿用 Session#write 的转换路径,省去数组与 join;转换后仍重新取得目标。
57
+ data = objects.size == 1 ? objects.first.to_s.b : objects.map { |object| object.to_s.b }.join
57
58
  # to_s 可切换或禁用记录目标;整条记录与其过滤尾部必须属于转换完成后的同一目标。
58
59
  target = transcript
59
60
  return unless target
@@ -94,7 +94,7 @@ module Expect
94
94
  end
95
95
  patterns.each do |pattern|
96
96
  return nil if hard_expired?
97
- next if stalled && stalled[:patterns].include?(pattern)
97
+ next if stalled && stalled[:patterns].key?(pattern)
98
98
 
99
99
  position = if pattern.value.is_a?(String)
100
100
  locate_literal(session, pattern, buffer)
@@ -105,7 +105,8 @@ module Expect
105
105
  return nil if hard_expired?
106
106
  next unless position
107
107
 
108
- return [session, pattern, position] unless @match_by_position
108
+ # 字节 0 已是最早位置,同位置仍由先声明者胜出;不再执行无法胜出的规则。
109
+ return [session, pattern, position] if !@match_by_position || position.first.zero?
109
110
 
110
111
  earliest = [session, pattern, position] if !earliest || position.first < earliest.last.first
111
112
  end
@@ -153,8 +154,11 @@ module Expect
153
154
 
154
155
  # 同值赋回仍须防止空转;嵌套读取到的新字节即使内容相同,也能恢复匹配。
155
156
  if session.received_bytes == received_bytes && session.scan_buffer == previous_buffer
156
- stalled = (@stalled_matches[session] ||= { buffer: previous_buffer, received_bytes:, patterns: [] })
157
- stalled[:patterns] << pattern
157
+ # 声明模式各有独立身份;恒定成本查询,避免重复继续时遍历不断增长的停滞数组。
158
+ stalled = (@stalled_matches[session] ||= {
159
+ buffer: previous_buffer, received_bytes:, patterns: {}.compare_by_identity
160
+ })
161
+ stalled[:patterns][pattern] = true
158
162
  end
159
163
  @deadline = next_deadline if CONTINUE.equal?(action)
160
164
  # 总期限到达时回主循环先派发已知 EOF;仅相对期限延续原有立即超时语义。
@@ -57,6 +57,8 @@ module Expect
57
57
  mark_secrets
58
58
  mark_partial_secrets if partial
59
59
  output = release(@pending.bytesize)
60
+ # 已结束的流没有尚待抑制的字节,后续可见分片恢复普通路径;再次 suppress 时重新建立字节图。
61
+ @suppressed = nil
60
62
  @masking = false
61
63
  output
62
64
  end
@@ -576,8 +576,8 @@ module Expect
576
576
  # 只结束读取方向并冲刷接收记录;EOF 不代表子进程已经退出或写端已经关闭。
577
577
  def mark_eof
578
578
  @eof = true
579
- flush_transcript
580
- flush_diagnostics(:received)
579
+ # EOF 只登记一次;任一日志尾部失败也必须尝试另一通道,保持首个常规异常。
580
+ Cleanup.always(-> { flush_diagnostics(:received) }) { flush_transcript }
581
581
  nil
582
582
  end
583
583
 
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Expect
4
4
  # Gem 与库共用的版本号;独立文件使 gemspec 无需加载完整会话实现。
5
- VERSION = "0.8.0"
5
+ VERSION = "0.8.1"
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: expect-pty
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - expect-pty contributors