ctx_driver 0.1.0 → 0.2.0
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 +4 -4
- data/CHANGELOG.md +14 -0
- data/README-zh.md +12 -2
- data/README.md +12 -0
- data/docs/architecture-zh.md +5 -1
- data/lib/ctx_driver/capture.rb +16 -0
- data/lib/ctx_driver/failure.rb +7 -3
- data/lib/ctx_driver/reader.rb +42 -24
- data/lib/ctx_driver/{net_connector_session.rb → session.rb} +4 -3
- data/lib/ctx_driver/version.rb +1 -1
- metadata +6 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e6148df70de9c5d2f553071b6ce9179f4cf71aa7c5c51e3293f3d1487f463a34
|
|
4
|
+
data.tar.gz: 5a125fb3880cc2f841d00e5ca98f0884b84a4a6f75be30ec5008e4acba714e1a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3c4430a8db98abfdbaa5919f7f50cc3a0dc3269155e4ca281ba8661535df72ac803cc6484239c5aabc219c748af884d84e155b67109b6ba9387aa0f0a395b024
|
|
7
|
+
data.tar.gz: 84c752509fc15b61ca63ea79081b8a9279220b717cfca788cfb8cf367e41cf05ed6e1634d925e0883288e36a9c098e2b405094a86cef18b0a918dbee7d11884b
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
Changes to the public contract are recorded here. Versions follow Semantic Versioning.
|
|
4
4
|
|
|
5
|
+
## 0.2.0 (2026-10-17)
|
|
6
|
+
|
|
7
|
+
- Require ctx_parser 0.2.x for the renamed public contracts.
|
|
8
|
+
|
|
9
|
+
- Mark an aborted command unusable for the current reader while propagating cancellation, including Thread termination, without closing or replaying the borrowed session.
|
|
10
|
+
- Snapshot start times and response bodies before subsequent caller callbacks can mutate them.
|
|
11
|
+
- Validate session and clock protocols, capture field types, and success/failure/skipped consistency.
|
|
12
|
+
- Ignore non-exception connector `Error` constants when classifying failures.
|
|
13
|
+
- Decode native responses without redundant output concatenation or a full array of body lines.
|
|
14
|
+
|
|
15
|
+
- Name the borrowed-session adapter `CtxDriver::Session` and load it from `ctx_driver/session`.
|
|
16
|
+
|
|
17
|
+
- Separate command receipt, command failure, and retained session failure terminology without changing execution behavior.
|
|
18
|
+
|
|
5
19
|
## 0.1.0 (2026-10-16)
|
|
6
20
|
|
|
7
21
|
### Added
|
data/README-zh.md
CHANGED
|
@@ -76,14 +76,22 @@ puts "SHA-256: #{capture.evidence.first[:sha256]}"
|
|
|
76
76
|
|
|
77
77
|
自定义会话实现 `connected?` 和 `send_commands([command])`。回执提供 `output`、布尔 `success?`、数组 `steps`、成功正文 `value!` 及失败时的 `error`。成功读取必须只有一个完成步骤。只有会话显式声明 `preserve_session_on_rejection:` 关键字时才传入该选项。
|
|
78
78
|
|
|
79
|
-
单个 reader 顺序使用;跨设备并发分别创建 reader。连接、关闭、凭据和批准命令选择由宿主负责,Reader
|
|
79
|
+
单个 reader 顺序使用;跨设备并发分别创建 reader。连接、关闭、凭据和批准命令选择由宿主负责,Reader 不判断任意命令是否只读。普通执行/回执异常转为安全诊断,取消信号继续传播。执行或响应处理被中断后,当前 Reader 记录 `command_aborted`,后续查询跳过;不会凭 `connected?` 仍为 true 就复用同步状态未知的会话,也不会替宿主关闭连接。
|
|
80
|
+
|
|
81
|
+
时钟必须可调用且返回 Time,时间在取得时立即复制。正文在检查后续会话状态之前复制。`Capture` 校验字段与状态:成功必须有字符串正文(允许空串),失败没有正文,跳过必须有失败原因且没有执行证据。墙上时钟可能回拨,时间字段不用于推断单调耗时。
|
|
80
82
|
|
|
81
83
|
详细厂商语义、历史验证记录和 Motor 专用集成说明保留在[架构参考](docs/architecture-zh.md)。其中宿主集成代码需要 Motor,不属于独立 gem API。适配层位于 [Motor 仓库](https://github.com/gatework/motor/tree/main/backend/lib) 的 `backend/lib/baseline`、`backend/lib/vxlan` 和 `backend/lib/wireless`。
|
|
82
84
|
|
|
83
85
|
原生 `Net::Connector::Base` 会话通过 `execute_operation` 自动适配,不连接、不提权。只去除已匹配的提示符和首行命令回显;连接器因拒绝命令而关闭时,后续读取跳过,不自动重连。自定义会话仍可实现 `send_commands` 协议。
|
|
84
86
|
|
|
87
|
+
## 领域术语
|
|
88
|
+
|
|
89
|
+
命令回执属于一次执行,`Capture` 保留处理后的正文和安全证据元数据。命令失败与会话失败具有不同生命周期:独立命令失败后会话仍可能可用,`Reader#failure` 则保留阻止后续查询的首个原因。`Capture#success?` 表示执行结果,不表示解析完整性或设备健康。
|
|
90
|
+
|
|
85
91
|
## 开发与测试
|
|
86
92
|
|
|
93
|
+
共享类按实际职责命名,平台信息放在命名空间中。直接对应设备命令的解析器保留文件名和类名。
|
|
94
|
+
|
|
87
95
|
```sh
|
|
88
96
|
bundle install
|
|
89
97
|
bundle exec rake
|
|
@@ -91,7 +99,9 @@ bundle exec ruby examples/offline.rb
|
|
|
91
99
|
bundle exec rake build
|
|
92
100
|
```
|
|
93
101
|
|
|
94
|
-
`bundle exec rake` 执行 RSpec、RuboCop 及离线示例。测试放在 `spec/`,沿用项目 RSpec
|
|
102
|
+
`bundle exec rake` 执行 RSpec、RuboCop 及离线示例。测试放在 `spec/`,沿用项目 RSpec 约定;样例采用合成或脱敏证据。新增会话适配时补充成功、拒绝、断链、取消、非法回执及证据保留回归。离线测试不代表所有设备版本均通过实机验证。
|
|
103
|
+
|
|
104
|
+
`bundle exec ruby -Ilib benchmark/body.rb` 测量合成回显的正文解码时间及对象分配,并校验正文内容;不代表设备网络吞吐。
|
|
95
105
|
|
|
96
106
|
使用声明的最低 Ruby 版本检查兼容性。方法用途统一使用简明中文注释;复杂实现还需说明业务规则、实现思路及关键分支。保持公开返回值与错误契约。真实回显和凭据不可进入示例、fixture、日志或发布包。
|
|
97
107
|
|
data/README.md
CHANGED
|
@@ -80,8 +80,18 @@ Use each reader sequentially; create separate readers for concurrent devices. Th
|
|
|
80
80
|
|
|
81
81
|
Detailed vendor behavior, historical validation notes, and Motor-only integration are preserved in [the architecture reference](docs/architecture-zh.md). Host integration examples in that reference require Motor; they are not standalone gem APIs. Motor adapters live under `backend/lib/baseline`, `backend/lib/vxlan`, and `backend/lib/wireless` in the [Motor repository](https://github.com/gatework/motor/tree/main/backend/lib).
|
|
82
82
|
|
|
83
|
+
## Domain vocabulary
|
|
84
|
+
|
|
85
|
+
A command receipt belongs to one execution; a `Capture` holds its processed body and safe evidence metadata. Command failure and session failure have different lifetimes: an independent command may fail while the session remains usable, whereas `Reader#failure` retains the first cause that prevents further queries. `Capture#success?` describes execution, not parsing completeness or device health.
|
|
86
|
+
|
|
87
|
+
Cancellation during execution or response processing propagates and marks the reader with `command_aborted`. Later reads are skipped even if the borrowed session still reports connected; the host retains responsibility for closing or replacing it.
|
|
88
|
+
|
|
89
|
+
The clock must be callable and return `Time`. Times and response bodies are copied before later callbacks can mutate them. Successful captures require a string body (including an empty string); failed captures have no body, and skipped captures require a failure without execution evidence. Wall-clock timestamps can move backwards and are not elapsed-time measurements.
|
|
90
|
+
|
|
83
91
|
## Development and tests
|
|
84
92
|
|
|
93
|
+
Name shared classes by their responsibility and use the namespace for platform context. Preserve filenames and class names that directly match device commands.
|
|
94
|
+
|
|
85
95
|
```sh
|
|
86
96
|
bundle install
|
|
87
97
|
bundle exec rake
|
|
@@ -93,6 +103,8 @@ bundle exec rake build
|
|
|
93
103
|
|
|
94
104
|
Use the declared minimum Ruby version for compatibility checks. Document source methods and non-obvious business logic in concise Chinese, preserve public return/error contracts, and never add raw device captures or credentials to examples, fixtures, logs, or release archives.
|
|
95
105
|
|
|
106
|
+
Run `bundle exec ruby -Ilib benchmark/body.rb` to measure body decoding and allocations against synthetic output, with semantic checks. This does not measure device network throughput.
|
|
107
|
+
|
|
96
108
|
## Release
|
|
97
109
|
|
|
98
110
|
This directory can be maintained as the independent [ctx_driver](https://github.com/gatework/ctx_driver) repository. Update `VERSION` and `CHANGELOG.md`, run the validation and build commands above, and inspect the packaged file list before tagging `vVERSION`.
|
data/docs/architecture-zh.md
CHANGED
|
@@ -38,7 +38,11 @@ capture.evidence # command / sha256 / bytes / observed_at
|
|
|
38
38
|
字段 `started_at/completed_at` 为采集阶段时间;证据的 `observed_at` 为实际收到响应的时间。
|
|
39
39
|
命令失败与领域健康状态分开,Reader 不产生 pass/fail 或完整库存判断。
|
|
40
40
|
|
|
41
|
-
`StandardError`
|
|
41
|
+
`StandardError` 在单命令执行、响应验证和状态查询边界转换为安全诊断;取消信号继续抛出。执行或响应处理未能完成回执时,ensure 保留原有失败或记录 `command_aborted`,包括不进入 rescue 的 Thread.kill。此 Reader 后续只返回 skipped,不关闭借用会话、不重放命令。
|
|
42
|
+
|
|
43
|
+
开始时间在执行回调之前保存副本,正文在后续状态回调之前保存副本。注入时钟必须可调用并返回 Time;时间允许因墙上时钟校准而回拨。`Capture` 拒绝类型错误以及成功/失败/跳过状态与正文或证据矛盾的回执。
|
|
44
|
+
|
|
45
|
+
原生适配器只读取渲染后正文的首行来判断回显,不构造全部行数组;成功路径不再调用连接器 `value!` 重复拼接输出,失败仍由连接器原样抛出错误。`benchmark/body.rb` 使用合成回显验证内容、耗时和分配量,不提供真实设备网络性能结论。
|
|
42
46
|
解析异常由领域 Collector 在本条命令或本次 AP 子任务内隔离。
|
|
43
47
|
调用方须顺序使用同一个 Reader;跨设备并发各自建立 Reader。
|
|
44
48
|
|
data/lib/ctx_driver/capture.rb
CHANGED
|
@@ -9,6 +9,22 @@ module CtxDriver
|
|
|
9
9
|
|
|
10
10
|
# 冻结单条命令回执及其正文、时间、证据和失败元数据。
|
|
11
11
|
def initialize(command:, body: nil, started_at:, completed_at:, evidence: [], failure: nil, skipped: false)
|
|
12
|
+
unless command.is_a?(String) && !command.strip.empty? && !/[\x00-\x1f\x7f]/.match?(command)
|
|
13
|
+
raise ArgumentError, "One command without control characters is required"
|
|
14
|
+
end
|
|
15
|
+
raise ArgumentError, "Capture body must be text or nil" unless body.nil? || body.is_a?(String)
|
|
16
|
+
unless started_at.is_a?(Time) && completed_at.is_a?(Time)
|
|
17
|
+
raise ArgumentError, "Capture timestamps must be Time values"
|
|
18
|
+
end
|
|
19
|
+
unless evidence.is_a?(Array) && evidence.all? { |entry| entry.is_a?(Hash) }
|
|
20
|
+
raise ArgumentError, "Capture evidence must be hashes"
|
|
21
|
+
end
|
|
22
|
+
raise ArgumentError, "Capture failure must be a hash or nil" unless failure.nil? || failure.is_a?(Hash)
|
|
23
|
+
raise ArgumentError, "Skipped must be boolean" unless [ true, false ].include?(skipped)
|
|
24
|
+
raise ArgumentError, "Successful captures require a body" if failure.nil? && body.nil?
|
|
25
|
+
raise ArgumentError, "Failed captures cannot contain a body" if failure && !body.nil?
|
|
26
|
+
raise ArgumentError, "Skipped captures require failure without evidence" if skipped && (failure.nil? || evidence.any?)
|
|
27
|
+
|
|
12
28
|
@command = command.dup.freeze
|
|
13
29
|
@body = body&.dup&.freeze
|
|
14
30
|
@started_at, @completed_at = started_at.dup.freeze, completed_at.dup.freeze
|
data/lib/ctx_driver/failure.rb
CHANGED
|
@@ -17,9 +17,13 @@ module CtxDriver
|
|
|
17
17
|
|
|
18
18
|
# 识别传输异常,不要求特定连接器实现。
|
|
19
19
|
def self.connection_error?(error, owner)
|
|
20
|
-
(defined?(Net::Connector::Error) && error.is_a?(Net::Connector::Error))
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
return true if error.is_a?(IOError) || (defined?(Net::Connector::Error) && error.is_a?(Net::Connector::Error))
|
|
21
|
+
return false unless owner.class.const_defined?(:Error)
|
|
22
|
+
|
|
23
|
+
error_type = owner.class.const_get(:Error)
|
|
24
|
+
return false unless error_type.is_a?(Class) && error_type <= StandardError
|
|
25
|
+
|
|
26
|
+
error.is_a?(error_type)
|
|
23
27
|
end
|
|
24
28
|
|
|
25
29
|
# 已加载 net-connector 时复用其稳定诊断词表,否则使用调用方的回退代码。
|
data/lib/ctx_driver/reader.rb
CHANGED
|
@@ -4,7 +4,7 @@ require "digest"
|
|
|
4
4
|
require "time"
|
|
5
5
|
require_relative "capture"
|
|
6
6
|
require_relative "failure"
|
|
7
|
-
require_relative "
|
|
7
|
+
require_relative "session"
|
|
8
8
|
|
|
9
9
|
module CtxDriver
|
|
10
10
|
# 借用已打开会话逐条独立查询;连接归属与领域判断由外部负责。
|
|
@@ -12,14 +12,16 @@ module CtxDriver
|
|
|
12
12
|
# 借用已打开会话,并初始化首个失败的跟踪状态。
|
|
13
13
|
def initialize(session:, clock: -> { Time.now.utc })
|
|
14
14
|
if defined?(Net::Connector::Base) && session.is_a?(Net::Connector::Base)
|
|
15
|
-
session =
|
|
15
|
+
session = Session.new(session)
|
|
16
16
|
end
|
|
17
17
|
unless session.respond_to?(:send_commands)
|
|
18
18
|
raise ArgumentError, "Session must implement #send_commands for the command driver protocol"
|
|
19
19
|
end
|
|
20
|
+
raise ArgumentError, "Session must implement #connected?" unless session.respond_to?(:connected?)
|
|
21
|
+
raise ArgumentError, "Clock must be callable" unless clock.respond_to?(:call)
|
|
20
22
|
|
|
21
23
|
@session, @clock = session, clock
|
|
22
|
-
@
|
|
24
|
+
@session_failure = nil
|
|
23
25
|
end
|
|
24
26
|
|
|
25
27
|
# 执行一条经过校验的查询,保留独立结果或失败。
|
|
@@ -28,67 +30,83 @@ module CtxDriver
|
|
|
28
30
|
raise ArgumentError, "One command without control characters is required"
|
|
29
31
|
end
|
|
30
32
|
command = command.dup.freeze
|
|
31
|
-
|
|
33
|
+
started_at = current_time
|
|
32
34
|
if failure
|
|
33
|
-
return Capture.new(command: command, started_at:
|
|
34
|
-
failure: @
|
|
35
|
+
return Capture.new(command: command, started_at: started_at, completed_at: current_time,
|
|
36
|
+
failure: @session_failure, skipped: true)
|
|
35
37
|
end
|
|
36
38
|
|
|
37
|
-
|
|
39
|
+
capture_command(command, started_at)
|
|
38
40
|
end
|
|
39
41
|
|
|
40
42
|
# 不发送命令即可检查会话可用性,并保留首次失败原因。
|
|
41
43
|
def failure
|
|
42
|
-
@
|
|
44
|
+
@session_failure ||= detect_session_failure
|
|
43
45
|
end
|
|
44
46
|
|
|
45
47
|
private
|
|
46
48
|
|
|
49
|
+
# 立即保存时钟快照,避免后续用户回调改变已记录的时区或时间。
|
|
50
|
+
def current_time
|
|
51
|
+
time = @clock.call
|
|
52
|
+
raise TypeError, "Clock must return a Time" unless time.is_a?(Time)
|
|
53
|
+
|
|
54
|
+
time.dup.freeze
|
|
55
|
+
end
|
|
56
|
+
|
|
47
57
|
# 分离执行与回执校验;后续校验失败时仍保留已取得的证据。
|
|
48
|
-
def
|
|
49
|
-
stage, evidence,
|
|
58
|
+
def capture_command(command, started_at)
|
|
59
|
+
stage, evidence, command_failure, body = :execute, [], nil, nil
|
|
60
|
+
capture_completed = false
|
|
50
61
|
begin
|
|
51
|
-
|
|
62
|
+
receipt = if supports_session_preservation?
|
|
52
63
|
@session.send_commands([ command ], preserve_session_on_rejection: true)
|
|
53
64
|
else
|
|
54
65
|
@session.send_commands([ command ])
|
|
55
66
|
end
|
|
56
67
|
stage = :response
|
|
57
|
-
output =
|
|
68
|
+
output = receipt.output
|
|
58
69
|
raise TypeError, "Command output must be text" unless output.is_a?(String)
|
|
59
70
|
|
|
60
71
|
evidence = [ { command: command, sha256: Digest::SHA256.hexdigest(output), bytes: output.bytesize,
|
|
61
|
-
observed_at:
|
|
62
|
-
success =
|
|
63
|
-
unless [ true, false ].include?(success) &&
|
|
72
|
+
observed_at: current_time.getutc.iso8601(6) } ]
|
|
73
|
+
success = receipt.success?
|
|
74
|
+
unless [ true, false ].include?(success) && receipt.steps.is_a?(Array) && (!success || receipt.steps.one?)
|
|
64
75
|
raise TypeError, "One query must return one completed command"
|
|
65
76
|
end
|
|
66
77
|
if success
|
|
67
|
-
body =
|
|
78
|
+
body = receipt.value!
|
|
68
79
|
raise TypeError, "Command body must be text" unless body.is_a?(String)
|
|
80
|
+
|
|
81
|
+
body = body.dup.freeze
|
|
69
82
|
else
|
|
70
|
-
|
|
83
|
+
command_failure = Failure.details(receipt.error, fallback: :command_failed, stage: :execute)
|
|
71
84
|
end
|
|
72
85
|
rescue StandardError => error
|
|
73
86
|
fallback = stage == :execute ? :command_execution_failed : :invalid_command_result
|
|
74
|
-
|
|
87
|
+
command_failure = Failure.details(error, fallback: fallback, stage: stage)
|
|
75
88
|
end
|
|
76
|
-
state_failure =
|
|
89
|
+
state_failure = detect_session_failure
|
|
77
90
|
# 单命令失败但会话仍可用时继续独立查询;断链或状态不明才阻止后续提交。
|
|
78
|
-
@
|
|
79
|
-
Capture.new(command: command, body:
|
|
80
|
-
evidence: evidence, failure:
|
|
91
|
+
@session_failure = command_failure || state_failure if state_failure
|
|
92
|
+
capture = Capture.new(command: command, body: command_failure ? nil : body, started_at: started_at, completed_at: current_time,
|
|
93
|
+
evidence: evidence, failure: command_failure)
|
|
94
|
+
capture_completed = true
|
|
95
|
+
capture
|
|
96
|
+
ensure
|
|
97
|
+
# Interrupt 与 Thread.kill 不经过 StandardError;未完成回执时禁止继续使用未知同步状态。
|
|
98
|
+
@session_failure ||= command_failure || { code: :command_aborted, stage: stage || :execute }.freeze unless capture_completed
|
|
81
99
|
end
|
|
82
100
|
|
|
83
101
|
# 仅在明确支持时复用命令拒绝后的会话;未知提示符仍由连接器关闭处理。
|
|
84
|
-
def
|
|
102
|
+
def supports_session_preservation?
|
|
85
103
|
@session.method(:send_commands).parameters.any? do |kind, name|
|
|
86
104
|
%i[key keyreq].include?(kind) && name == :preserve_session_on_rejection
|
|
87
105
|
end
|
|
88
106
|
end
|
|
89
107
|
|
|
90
108
|
# 连接状态不确定时视为不可用,后续跳过的查询保留首次失败原因。
|
|
91
|
-
def
|
|
109
|
+
def detect_session_failure
|
|
92
110
|
state = @session.connected?
|
|
93
111
|
raise TypeError, "Connection state must be boolean" unless [ true, false ].include?(state)
|
|
94
112
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
module CtxDriver
|
|
4
4
|
# 适配已加载的 net-connector;不连接、不提权,也不恢复已关闭的借用会话。
|
|
5
|
-
class
|
|
5
|
+
class Session
|
|
6
6
|
# 先交出原始回执,Reader 建立证据后才按需解码正文。
|
|
7
7
|
Response = Data.define(:result) do
|
|
8
8
|
def output = result.output
|
|
@@ -12,10 +12,11 @@ module CtxDriver
|
|
|
12
12
|
|
|
13
13
|
# 只移除匹配的首行命令回显;保留正文缩进及后续相同行。
|
|
14
14
|
def value!
|
|
15
|
-
|
|
15
|
+
# 成功路径无需再次拼接全部输出;失败仍交由连接器保留异常契约。
|
|
16
|
+
result.value! unless result.success?
|
|
16
17
|
step = result.steps.fetch(0)
|
|
17
18
|
body = Net::Connector::TerminalText.render(step.output.delete_suffix(step.prompt.to_s))
|
|
18
|
-
first = body.
|
|
19
|
+
first = body.each_line("\n").first
|
|
19
20
|
first && first.strip == step.command.text ? body.delete_prefix(first) : body
|
|
20
21
|
end
|
|
21
22
|
end
|
data/lib/ctx_driver/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ctx_driver
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Gatework contributors
|
|
@@ -13,16 +13,16 @@ dependencies:
|
|
|
13
13
|
name: ctx_parser
|
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
|
15
15
|
requirements:
|
|
16
|
-
- - "
|
|
16
|
+
- - "~>"
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version:
|
|
18
|
+
version: 0.2.0
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
|
-
- - "
|
|
23
|
+
- - "~>"
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version:
|
|
25
|
+
version: 0.2.0
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: digest
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -67,8 +67,8 @@ files:
|
|
|
67
67
|
- lib/ctx_driver.rb
|
|
68
68
|
- lib/ctx_driver/capture.rb
|
|
69
69
|
- lib/ctx_driver/failure.rb
|
|
70
|
-
- lib/ctx_driver/net_connector_session.rb
|
|
71
70
|
- lib/ctx_driver/reader.rb
|
|
71
|
+
- lib/ctx_driver/session.rb
|
|
72
72
|
- lib/ctx_driver/version.rb
|
|
73
73
|
homepage: https://github.com/gatework/ctx_driver
|
|
74
74
|
licenses:
|