yaic 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/.claude/agents/ralph-qa.md +101 -0
- data/.claude/ralph/bin/dump-pid.sh +3 -0
- data/.claude/ralph/bin/kill-claude +6 -0
- data/.claude/ralph/bin/start-ralph +44 -0
- data/.claude/ralph/bin/stop-hook.sh +9 -0
- data/.claude/ralph/bin/stop-ralph +17 -0
- data/.claude/ralph/prompt.md +218 -0
- data/.claude/settings.json +26 -0
- data/.gitmodules +3 -0
- data/CLAUDE.md +65 -0
- data/README.md +106 -17
- data/Rakefile +8 -0
- data/devenv.nix +1 -0
- data/docs/agents/data-model.md +150 -0
- data/docs/agents/ralph/features/01-message-parsing.md.done +160 -0
- data/docs/agents/ralph/features/01-tcpsocket-refactor.md.done +109 -0
- data/docs/agents/ralph/features/02-connection-socket.md.done +138 -0
- data/docs/agents/ralph/features/02-simplified-client-api.md.done +306 -0
- data/docs/agents/ralph/features/03-registration.md.done +147 -0
- data/docs/agents/ralph/features/04-ping-pong.md.done +109 -0
- data/docs/agents/ralph/features/05-event-system.md.done +167 -0
- data/docs/agents/ralph/features/06-privmsg-notice.md.done +163 -0
- data/docs/agents/ralph/features/07-join-part.md.done +190 -0
- data/docs/agents/ralph/features/08-quit.md.done +118 -0
- data/docs/agents/ralph/features/09-nick-change.md.done +109 -0
- data/docs/agents/ralph/features/10-topic.md.done +145 -0
- data/docs/agents/ralph/features/11-kick.md.done +122 -0
- data/docs/agents/ralph/features/12-names.md.done +124 -0
- data/docs/agents/ralph/features/13-mode.md.done +174 -0
- data/docs/agents/ralph/features/14-who-whois.md.done +188 -0
- data/docs/agents/ralph/features/15-client-api.md.done +180 -0
- data/docs/agents/ralph/features/16-ssl-test-infrastructure.md.done +50 -0
- data/docs/agents/ralph/features/17-github-actions-ci.md.done +70 -0
- data/docs/agents/ralph/features/18-brakeman-security-scanning.md.done +67 -0
- data/docs/agents/ralph/features/19-fix-qa.md.done +73 -0
- data/docs/agents/ralph/features/20-test-optimization.md.done +70 -0
- data/docs/agents/ralph/features/21-test-parallelization.md.done +56 -0
- data/docs/agents/ralph/features/22-wait-until-pattern.md.done +90 -0
- data/docs/agents/ralph/features/23-ping-test-optimization.md.done +46 -0
- data/docs/agents/ralph/features/24-blocking-who-whois.md.done +159 -0
- data/docs/agents/ralph/features/25-verbose-mode.md.done +166 -0
- data/docs/agents/ralph/plans/test-optimization-plan.md +172 -0
- data/docs/agents/ralph/progress.md +731 -0
- data/docs/agents/todo.md +5 -0
- data/lib/yaic/channel.rb +22 -0
- data/lib/yaic/client.rb +821 -0
- data/lib/yaic/event.rb +35 -0
- data/lib/yaic/message.rb +119 -0
- data/lib/yaic/registration.rb +17 -0
- data/lib/yaic/socket.rb +120 -0
- data/lib/yaic/source.rb +39 -0
- data/lib/yaic/version.rb +1 -1
- data/lib/yaic/who_result.rb +17 -0
- data/lib/yaic/whois_result.rb +20 -0
- data/lib/yaic.rb +13 -1
- metadata +51 -1
data/lib/yaic/event.rb
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Yaic
|
|
4
|
+
class Event
|
|
5
|
+
attr_reader :type, :message
|
|
6
|
+
|
|
7
|
+
def initialize(type:, message: nil, **attributes)
|
|
8
|
+
@type = type
|
|
9
|
+
@message = message
|
|
10
|
+
@attributes = attributes
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def [](key)
|
|
14
|
+
@attributes[key]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def to_h
|
|
18
|
+
@attributes.dup
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def respond_to_missing?(method_name, include_private = false)
|
|
24
|
+
@attributes.key?(method_name) || super
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def method_missing(method_name, *args)
|
|
28
|
+
if @attributes.key?(method_name) && args.empty?
|
|
29
|
+
@attributes[method_name]
|
|
30
|
+
else
|
|
31
|
+
super
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
data/lib/yaic/message.rb
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "strscan"
|
|
4
|
+
|
|
5
|
+
module Yaic
|
|
6
|
+
class Message
|
|
7
|
+
attr_reader :tags, :source, :command, :params, :raw
|
|
8
|
+
|
|
9
|
+
def initialize(tags: {}, source: nil, command: nil, params: [])
|
|
10
|
+
@tags = tags
|
|
11
|
+
@source = source
|
|
12
|
+
@command = command
|
|
13
|
+
@params = params
|
|
14
|
+
@raw = nil
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.parse(str)
|
|
18
|
+
return nil if str.nil? || str.empty?
|
|
19
|
+
|
|
20
|
+
str = str.b.force_encoding("UTF-8")
|
|
21
|
+
str = str.encode("UTF-8", "ISO-8859-1", invalid: :replace, undef: :replace) unless str.valid_encoding?
|
|
22
|
+
|
|
23
|
+
stripped = str.chomp("\r\n").chomp("\n")
|
|
24
|
+
return nil if stripped.empty?
|
|
25
|
+
|
|
26
|
+
scanner = StringScanner.new(stripped)
|
|
27
|
+
|
|
28
|
+
tags = parse_tags(scanner)
|
|
29
|
+
source = parse_source(scanner)
|
|
30
|
+
command = parse_command(scanner)
|
|
31
|
+
params = parse_params(scanner)
|
|
32
|
+
|
|
33
|
+
msg = new(tags: tags, source: source, command: command, params: params)
|
|
34
|
+
msg.instance_variable_set(:@raw, str)
|
|
35
|
+
msg
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def to_s
|
|
39
|
+
parts = []
|
|
40
|
+
parts << @command
|
|
41
|
+
|
|
42
|
+
@params.each_with_index do |param, idx|
|
|
43
|
+
is_last = idx == @params.length - 1
|
|
44
|
+
parts << if is_last && needs_trailing_prefix?(param, @params.length)
|
|
45
|
+
":#{param}"
|
|
46
|
+
else
|
|
47
|
+
param
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
"#{parts.join(" ")}\r\n"
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
private
|
|
55
|
+
|
|
56
|
+
def needs_trailing_prefix?(param, param_count)
|
|
57
|
+
param.empty? || param.include?(" ") || param.start_with?(":") || param_count > 1
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
class << self
|
|
61
|
+
private
|
|
62
|
+
|
|
63
|
+
def parse_tags(scanner)
|
|
64
|
+
tags = {}
|
|
65
|
+
|
|
66
|
+
if scanner.peek(1) == "@"
|
|
67
|
+
scanner.getch
|
|
68
|
+
tag_str = scanner.scan(/[^ ]+/)
|
|
69
|
+
skip_spaces(scanner)
|
|
70
|
+
|
|
71
|
+
tag_str&.split(";")&.each do |tag|
|
|
72
|
+
key, value = tag.split("=", 2)
|
|
73
|
+
tags[key] = value || ""
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
tags
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def parse_source(scanner)
|
|
81
|
+
return nil unless scanner.peek(1) == ":"
|
|
82
|
+
|
|
83
|
+
scanner.getch
|
|
84
|
+
source_str = scanner.scan(/[^ ]+/)
|
|
85
|
+
skip_spaces(scanner)
|
|
86
|
+
|
|
87
|
+
Source.parse(source_str)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def parse_command(scanner)
|
|
91
|
+
cmd = scanner.scan(/[A-Za-z]+|\d{3}/)
|
|
92
|
+
skip_spaces(scanner)
|
|
93
|
+
cmd
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def parse_params(scanner)
|
|
97
|
+
params = []
|
|
98
|
+
|
|
99
|
+
until scanner.eos?
|
|
100
|
+
if scanner.peek(1) == ":"
|
|
101
|
+
scanner.getch
|
|
102
|
+
params << scanner.rest
|
|
103
|
+
break
|
|
104
|
+
else
|
|
105
|
+
param = scanner.scan(/[^ ]+/)
|
|
106
|
+
params << param if param
|
|
107
|
+
skip_spaces(scanner)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
params
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def skip_spaces(scanner)
|
|
115
|
+
scanner.skip(/ +/)
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Yaic
|
|
4
|
+
module Registration
|
|
5
|
+
def self.pass_message(password)
|
|
6
|
+
Message.new(command: "PASS", params: [password])
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def self.nick_message(nickname)
|
|
10
|
+
Message.new(command: "NICK", params: [nickname])
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.user_message(username, realname)
|
|
14
|
+
Message.new(command: "USER", params: [username, "0", "*", realname])
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
data/lib/yaic/socket.rb
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "socket"
|
|
4
|
+
require "openssl"
|
|
5
|
+
|
|
6
|
+
module Yaic
|
|
7
|
+
class Socket
|
|
8
|
+
def state
|
|
9
|
+
@monitor.synchronize { @state }
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def initialize(host, port, ssl: false, verify_mode: nil, connect_timeout: 30)
|
|
13
|
+
@host = host
|
|
14
|
+
@port = port
|
|
15
|
+
@ssl = ssl
|
|
16
|
+
@verify_mode = verify_mode || OpenSSL::SSL::VERIFY_NONE
|
|
17
|
+
@connect_timeout = connect_timeout
|
|
18
|
+
|
|
19
|
+
@socket = nil
|
|
20
|
+
@read_buffer = String.new(encoding: Encoding::ASCII_8BIT)
|
|
21
|
+
@write_queue = []
|
|
22
|
+
@state = :disconnected
|
|
23
|
+
@monitor = Monitor.new
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def connect
|
|
27
|
+
tcp_socket = TCPSocket.new(@host, @port, connect_timeout: @connect_timeout)
|
|
28
|
+
tcp_socket.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_KEEPALIVE, true)
|
|
29
|
+
|
|
30
|
+
@monitor.synchronize do
|
|
31
|
+
@socket = @ssl ? wrap_ssl(tcp_socket) : tcp_socket
|
|
32
|
+
@state = :connecting
|
|
33
|
+
end
|
|
34
|
+
rescue Errno::ETIMEDOUT, Errno::EHOSTUNREACH, Errno::ECONNREFUSED, IO::TimeoutError, SocketError => e
|
|
35
|
+
raise Yaic::ConnectionError, e.message
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def disconnect
|
|
39
|
+
@monitor.synchronize do
|
|
40
|
+
return if @state == :disconnected
|
|
41
|
+
|
|
42
|
+
begin
|
|
43
|
+
@socket&.close
|
|
44
|
+
rescue
|
|
45
|
+
nil
|
|
46
|
+
end
|
|
47
|
+
@socket = nil
|
|
48
|
+
@read_buffer.clear
|
|
49
|
+
@write_queue.clear
|
|
50
|
+
@state = :disconnected
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def read
|
|
55
|
+
@monitor.synchronize do
|
|
56
|
+
return nil if @socket.nil?
|
|
57
|
+
|
|
58
|
+
begin
|
|
59
|
+
data = @socket.read_nonblock(4096)
|
|
60
|
+
buffer_data(data)
|
|
61
|
+
extract_message
|
|
62
|
+
rescue IO::WaitReadable
|
|
63
|
+
extract_message
|
|
64
|
+
rescue IOError, Errno::ECONNRESET
|
|
65
|
+
nil
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def write(message)
|
|
71
|
+
@monitor.synchronize do
|
|
72
|
+
return if @socket.nil?
|
|
73
|
+
|
|
74
|
+
message = message.dup
|
|
75
|
+
message << "\r\n" unless message.end_with?("\r\n", "\n")
|
|
76
|
+
|
|
77
|
+
begin
|
|
78
|
+
@socket.write_nonblock(message)
|
|
79
|
+
rescue IO::WaitWritable
|
|
80
|
+
@write_queue << message
|
|
81
|
+
flush_write_queue
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
private
|
|
87
|
+
|
|
88
|
+
def wrap_ssl(tcp_socket)
|
|
89
|
+
context = OpenSSL::SSL::SSLContext.new
|
|
90
|
+
context.verify_mode = @verify_mode
|
|
91
|
+
|
|
92
|
+
ssl_socket = OpenSSL::SSL::SSLSocket.new(tcp_socket, context)
|
|
93
|
+
ssl_socket.hostname = @host
|
|
94
|
+
ssl_socket.sync = true
|
|
95
|
+
ssl_socket.connect
|
|
96
|
+
ssl_socket
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def buffer_data(data)
|
|
100
|
+
@read_buffer << data
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def extract_message
|
|
104
|
+
if (idx = @read_buffer.index("\n"))
|
|
105
|
+
@read_buffer.slice!(0..idx)
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def flush_write_queue
|
|
110
|
+
while @write_queue.any?
|
|
111
|
+
begin
|
|
112
|
+
@socket.write_nonblock(@write_queue.first)
|
|
113
|
+
@write_queue.shift
|
|
114
|
+
rescue IO::WaitWritable
|
|
115
|
+
break
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
data/lib/yaic/source.rb
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Yaic
|
|
4
|
+
class Source
|
|
5
|
+
attr_reader :nick, :user, :host, :raw
|
|
6
|
+
|
|
7
|
+
def initialize(nick: nil, user: nil, host: nil, raw: nil)
|
|
8
|
+
@nick = nick
|
|
9
|
+
@user = user
|
|
10
|
+
@host = host
|
|
11
|
+
@raw = raw
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.parse(str)
|
|
15
|
+
return nil if str.nil? || str.empty?
|
|
16
|
+
|
|
17
|
+
nick = nil
|
|
18
|
+
user = nil
|
|
19
|
+
host = nil
|
|
20
|
+
|
|
21
|
+
if str.include?("!")
|
|
22
|
+
nick, rest = str.split("!", 2)
|
|
23
|
+
if rest.include?("@")
|
|
24
|
+
user, host = rest.split("@", 2)
|
|
25
|
+
else
|
|
26
|
+
user = rest
|
|
27
|
+
end
|
|
28
|
+
elsif str.include?("@")
|
|
29
|
+
nick, host = str.split("@", 2)
|
|
30
|
+
elsif str.include?(".")
|
|
31
|
+
host = str
|
|
32
|
+
else
|
|
33
|
+
nick = str
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
new(nick: nick, user: user, host: host, raw: str)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
data/lib/yaic/version.rb
CHANGED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Yaic
|
|
4
|
+
class WhoResult
|
|
5
|
+
attr_reader :channel, :user, :host, :server, :nick, :away, :realname
|
|
6
|
+
|
|
7
|
+
def initialize(channel:, user:, host:, server:, nick:, away:, realname:)
|
|
8
|
+
@channel = channel
|
|
9
|
+
@user = user
|
|
10
|
+
@host = host
|
|
11
|
+
@server = server
|
|
12
|
+
@nick = nick
|
|
13
|
+
@away = away
|
|
14
|
+
@realname = realname
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Yaic
|
|
4
|
+
class WhoisResult
|
|
5
|
+
attr_accessor :nick, :user, :host, :realname, :channels, :server, :idle, :signon, :account, :away
|
|
6
|
+
|
|
7
|
+
def initialize(nick:)
|
|
8
|
+
@nick = nick
|
|
9
|
+
@user = nil
|
|
10
|
+
@host = nil
|
|
11
|
+
@realname = nil
|
|
12
|
+
@channels = []
|
|
13
|
+
@server = nil
|
|
14
|
+
@idle = nil
|
|
15
|
+
@signon = nil
|
|
16
|
+
@account = nil
|
|
17
|
+
@away = nil
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
data/lib/yaic.rb
CHANGED
|
@@ -1,8 +1,20 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "monitor"
|
|
4
|
+
|
|
3
5
|
require_relative "yaic/version"
|
|
6
|
+
require_relative "yaic/source"
|
|
7
|
+
require_relative "yaic/message"
|
|
8
|
+
require_relative "yaic/socket"
|
|
9
|
+
require_relative "yaic/registration"
|
|
10
|
+
require_relative "yaic/event"
|
|
11
|
+
require_relative "yaic/channel"
|
|
12
|
+
require_relative "yaic/who_result"
|
|
13
|
+
require_relative "yaic/whois_result"
|
|
14
|
+
require_relative "yaic/client"
|
|
4
15
|
|
|
5
16
|
module Yaic
|
|
6
17
|
class Error < StandardError; end
|
|
7
|
-
|
|
18
|
+
class TimeoutError < Error; end
|
|
19
|
+
class ConnectionError < Error; end
|
|
8
20
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: yaic
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Joé Dupuis
|
|
@@ -15,17 +15,67 @@ executables: []
|
|
|
15
15
|
extensions: []
|
|
16
16
|
extra_rdoc_files: []
|
|
17
17
|
files:
|
|
18
|
+
- ".claude/agents/ralph-qa.md"
|
|
19
|
+
- ".claude/ralph/bin/dump-pid.sh"
|
|
20
|
+
- ".claude/ralph/bin/kill-claude"
|
|
21
|
+
- ".claude/ralph/bin/start-ralph"
|
|
22
|
+
- ".claude/ralph/bin/stop-hook.sh"
|
|
23
|
+
- ".claude/ralph/bin/stop-ralph"
|
|
24
|
+
- ".claude/ralph/prompt.md"
|
|
25
|
+
- ".claude/settings.json"
|
|
18
26
|
- ".dockerignore"
|
|
27
|
+
- ".gitmodules"
|
|
19
28
|
- ".ruby-version"
|
|
20
29
|
- CHANGELOG.md
|
|
30
|
+
- CLAUDE.md
|
|
21
31
|
- LICENSE.txt
|
|
22
32
|
- README.md
|
|
23
33
|
- Rakefile
|
|
24
34
|
- devenv.lock
|
|
25
35
|
- devenv.nix
|
|
26
36
|
- devenv.yaml
|
|
37
|
+
- docs/agents/data-model.md
|
|
38
|
+
- docs/agents/ralph/features/01-message-parsing.md.done
|
|
39
|
+
- docs/agents/ralph/features/01-tcpsocket-refactor.md.done
|
|
40
|
+
- docs/agents/ralph/features/02-connection-socket.md.done
|
|
41
|
+
- docs/agents/ralph/features/02-simplified-client-api.md.done
|
|
42
|
+
- docs/agents/ralph/features/03-registration.md.done
|
|
43
|
+
- docs/agents/ralph/features/04-ping-pong.md.done
|
|
44
|
+
- docs/agents/ralph/features/05-event-system.md.done
|
|
45
|
+
- docs/agents/ralph/features/06-privmsg-notice.md.done
|
|
46
|
+
- docs/agents/ralph/features/07-join-part.md.done
|
|
47
|
+
- docs/agents/ralph/features/08-quit.md.done
|
|
48
|
+
- docs/agents/ralph/features/09-nick-change.md.done
|
|
49
|
+
- docs/agents/ralph/features/10-topic.md.done
|
|
50
|
+
- docs/agents/ralph/features/11-kick.md.done
|
|
51
|
+
- docs/agents/ralph/features/12-names.md.done
|
|
52
|
+
- docs/agents/ralph/features/13-mode.md.done
|
|
53
|
+
- docs/agents/ralph/features/14-who-whois.md.done
|
|
54
|
+
- docs/agents/ralph/features/15-client-api.md.done
|
|
55
|
+
- docs/agents/ralph/features/16-ssl-test-infrastructure.md.done
|
|
56
|
+
- docs/agents/ralph/features/17-github-actions-ci.md.done
|
|
57
|
+
- docs/agents/ralph/features/18-brakeman-security-scanning.md.done
|
|
58
|
+
- docs/agents/ralph/features/19-fix-qa.md.done
|
|
59
|
+
- docs/agents/ralph/features/20-test-optimization.md.done
|
|
60
|
+
- docs/agents/ralph/features/21-test-parallelization.md.done
|
|
61
|
+
- docs/agents/ralph/features/22-wait-until-pattern.md.done
|
|
62
|
+
- docs/agents/ralph/features/23-ping-test-optimization.md.done
|
|
63
|
+
- docs/agents/ralph/features/24-blocking-who-whois.md.done
|
|
64
|
+
- docs/agents/ralph/features/25-verbose-mode.md.done
|
|
65
|
+
- docs/agents/ralph/plans/test-optimization-plan.md
|
|
66
|
+
- docs/agents/ralph/progress.md
|
|
67
|
+
- docs/agents/todo.md
|
|
27
68
|
- lib/yaic.rb
|
|
69
|
+
- lib/yaic/channel.rb
|
|
70
|
+
- lib/yaic/client.rb
|
|
71
|
+
- lib/yaic/event.rb
|
|
72
|
+
- lib/yaic/message.rb
|
|
73
|
+
- lib/yaic/registration.rb
|
|
74
|
+
- lib/yaic/socket.rb
|
|
75
|
+
- lib/yaic/source.rb
|
|
28
76
|
- lib/yaic/version.rb
|
|
77
|
+
- lib/yaic/who_result.rb
|
|
78
|
+
- lib/yaic/whois_result.rb
|
|
29
79
|
- sig/yaic.rbs
|
|
30
80
|
homepage: https://github.com/JoeDupuis/yaic
|
|
31
81
|
licenses:
|