inquirex 0.4.1 → 0.5.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/README.md +84 -52
- data/examples/01_readme_example.rb +55 -0
- data/examples/02_readme_mermaid.png +0 -0
- data/examples/02_readme_mermaid.rb +36 -0
- data/examples/README.md +33 -0
- data/justfile +3 -2
- data/lib/inquirex/version.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1ce3e2bcf0a91cdba8c83abd9af02807b25462ff878762f0a0114372554dfe84
|
|
4
|
+
data.tar.gz: 017b1f51f0641f57aecd2a9c84fb3c4fb5e39b6252ac1a4de4f9735bd79d7837
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a426a31f57e7c3ef4e7bdeb2cd288da6fb66717436c167e0f3a03e808706f9525ea3c687055da32b3413015a80882524f88b05c6d01ea06dc5875dfb96f93521
|
|
7
|
+
data.tar.gz: 9be96813505bf0ce8a0d5eed1a3e775dd0a08b8b54a5484993abe9119663323dd8075aba8fb74d3aebeed63c82370ee04fff6488a2b72d13bfcda0a47d38b525
|
data/README.md
CHANGED
|
@@ -1,50 +1,72 @@
|
|
|
1
|
-
[](https://github.com/inquirex/inquirex/actions/workflows/main.yml)
|
|
1
|
+
[](https://badge.fury.io/rb/inquirex) [](https://github.com/inquirex/inquirex/actions/workflows/main.yml) 
|
|
2
2
|
|
|
3
3
|
# Inquirex
|
|
4
4
|
|
|
5
|
-
`inquirex`
|
|
5
|
+
`inquirex` family of libraries (part Ruby, part JavaScript), is a declarative, rules-driven questionnaire engine for building conditional intake forms, qualification wizards, and branching surveys, which can be AI-enabled, and rendered on your site inside a "copilot" widget window or in a TUI (Terminal UI) all the same.
|
|
6
6
|
|
|
7
7
|
> [!IMPORTANT]
|
|
8
8
|
>
|
|
9
|
-
>
|
|
9
|
+
> Today the ecosystem contains:
|
|
10
10
|
>
|
|
11
|
-
> - [`inquirex`](https://github.com/inquirex/inquirex)
|
|
12
|
-
> - [`inquirex-llm`](https://github.com/inquirex/inquirex-llm)
|
|
13
|
-
> - [`inquirex-tty`](https://github.com/inquirex/inquirex-)
|
|
14
|
-
> - [`inquirex-js`](https://github.com/inquirex/inquirex-js)
|
|
11
|
+
> - [`inquirex`](https://github.com/inquirex/inquirex): the base gem that defines the graph via DSL and provides most of the backend features
|
|
12
|
+
> - [`inquirex-llm`](https://github.com/inquirex/inquirex-llm): a tiny gem that extends the DSL by the word `extract` which, given a previous question answered in the form of free text, can use the model of your choice to return structured breakdown of text into answers to questions that might follow, thus shortening the form considerably.
|
|
13
|
+
> - [`inquirex-tty`](https://github.com/inquirex/inquirex-tty): is the gem that renders the forms on the TUI (Terminal UI). This is also the gem that provides the CLI `inqurex` for performing various tasks such as validating DSL files, converting them from Ruby to JSON and back, and more. It is also the gem where a folder of DSL `examples` can be used to get a feel for how this works.
|
|
14
|
+
> - [`inquirex-js`](https://github.com/inquirex/inquirex-js) (`npmjs` module [`@kigster/inquirex-js`](https://www.npmjs.com/package/@kigster/inquirex-js)) is the NPM package that connects web UI with the form definition in JSON format. If LLM is not needed, the entire flow becomes deterministic and collects answers as the user answers your questions, and then POSTS them to the URL of your choice.
|
|
15
15
|
>
|
|
16
|
-
> For a presentation
|
|
16
|
+
> For a presentation about these gems and what they do please watch the [RubySF presentation](https://www.youtube.com/watch?v=iaoKW7Ap3_M&t=1s) and you can also [view the slides form the presentation](https://reinvent.one/images/talks/pdfs/2026.inquirex.pdf).
|
|
17
|
+
>
|
|
18
|
+
> Finally, the SaaS application [qualified.at](https://qualified.at) allows busy professionals such as consultants, doctors, tax-preparers, who are short on time, or can't be bothered to figure out the technical side of integrating these libraries, to leverage the entire ecosystem by creating their own custom lead intake forms on the SaaS application, dropping the auto-generated widget on their (potentially static website), and showing the copilot to their customers, customizing from nothing at all, to what triggers copilot's appearance, it's look and feel, and so on. The site automatically supports the LLM keyword `extract` as part of the DSL, and also collects the answers from your leads in your account: the data that you own, and can export at any time into a CSV download, a Google Spreadsheet, etc.
|
|
19
|
+
|
|
20
|
+
## Why Inquirex?
|
|
21
|
+
|
|
22
|
+
There are plenty of form builders, state machines, workflow libraries, etc. And yet, none of them combine the convenience of a DSL with logical separation between the form substance, and the rendering UI quite like this.
|
|
23
|
+
|
|
24
|
+
There are plenty of form building gems, hard-coded branching controllers, React components, or database callbacks.
|
|
25
|
+
|
|
26
|
+
***Inquirex is quite different.***
|
|
27
|
+
|
|
28
|
+
It provides a rich DSL for creating dynamic user intake forms, with complexity ranging from a simple straight-line forms to multi-branch, conditional forms with dozens of potential branches, *UI widget hints* for various rendering platforms, with *accumulators* that allow computing sums or products based on user's answers (which allow you to compute — for user or for yourself — that the service you are requesting will cost between $X & $Y).
|
|
29
|
+
|
|
30
|
+
> [!NOTE]
|
|
31
|
+
>
|
|
32
|
+
> For technically inclined, Inquirex turns user forms into a directed graph, where nodes are either questions or statements (or UI transitions), while edges are AST-based logical conditions that can be stacked and joined in arbitrarily complex ways, allowing you to move from one question to any other based on the previous answer. See the details below.
|
|
33
|
+
|
|
34
|
+
***Don't want to deal with figuring it out? Head to [Qualified.At](https://qualified.at/onboarding) and walk through the demo onboarding form, that exists specifically to show you how quickly you can have the same conceptually on your site, tailored to YOUR users.***
|
|
17
35
|
|
|
18
36
|
## Summary
|
|
19
37
|
|
|
20
|
-
|
|
38
|
+
This one is the core gem in the Inquirex ecosystem that focuses on:
|
|
21
39
|
|
|
22
40
|
- A conversational DSL (`ask`, `say`, `header`, `btw`, `warning`, `confirm`)
|
|
41
|
+
|
|
23
42
|
- A serializable AST rule system (`contains`, `equals`, `greater_than`, `less_than`, `not_empty`, `all`, `any`)
|
|
43
|
+
|
|
24
44
|
- Framework-agnostic widget rendering hints (`widget` DSL verb, `WidgetHint`, `WidgetRegistry`)
|
|
25
|
-
|
|
45
|
+
|
|
46
|
+
- Named ***accumulators*** for running totals (pricing, complexity scoring, credit scoring, lead qualification)
|
|
47
|
+
|
|
26
48
|
- An immutable flow definition graph
|
|
49
|
+
|
|
27
50
|
- A runtime engine for stateful step traversal
|
|
51
|
+
|
|
28
52
|
- JSON round-trip serialization for cross-platform clients
|
|
29
|
-
- A structured `Answers` wrapper and Mermaid graph export
|
|
30
53
|
|
|
31
|
-
|
|
54
|
+
- A structured `Answers` wrapper and Mermaid graph export (provided by `inquirex-tty` gem's CLI)
|
|
32
55
|
|
|
33
|
-
-
|
|
34
|
-
- Ruby: `>= 4.0.0` (project currently uses `4.0.5`)
|
|
35
|
-
- Test suite: `220 examples, 0 failures`
|
|
36
|
-
- Coverage: ~`94%` line coverage
|
|
56
|
+
- In short:
|
|
37
57
|
|
|
38
|
-
|
|
58
|
+
- Define once in Ruby
|
|
59
|
+
- Serialize to JSON if you need to show the questions on the web UI
|
|
60
|
+
- Evaluate transitions consistently using rule AST objects
|
|
61
|
+
- Run the same flow identically in concept in different frontends (web widget, TUI, etc.)
|
|
39
62
|
|
|
40
|
-
|
|
63
|
+
So, if you ever wanted to ask users who arrive at your site a few simple questions (PII questions are strongly discouraged due to the fact that the gem is typically used by non-logged in users on your end — except, perhaps, name and email), and depending on their answers you might want to dig a bit deeper, so that once you get on the phone with them you'll already have a general picture, these gems are for you (or head to [qualified.at](https://qualified.at) and set up your free account to see how this works in practice.
|
|
41
64
|
|
|
42
|
-
|
|
43
|
-
- Serialize to JSON
|
|
44
|
-
- Evaluate transitions consistently using rule AST objects
|
|
45
|
-
- Run the same flow in different frontends (web widget, terminal, etc.)
|
|
65
|
+
## Examples
|
|
46
66
|
|
|
47
|
-
|
|
67
|
+
> [!NOTE]
|
|
68
|
+
>
|
|
69
|
+
> There are a couple of examples shown in this `README` file, and also in the [`./examples`](./examples) folder. You can read about running them in a [`README.md`](./examples/README.md) inside that folder.
|
|
48
70
|
|
|
49
71
|
## Installation
|
|
50
72
|
|
|
@@ -52,6 +74,10 @@ Add to your Gemfile:
|
|
|
52
74
|
|
|
53
75
|
```ruby
|
|
54
76
|
gem "inquirex"
|
|
77
|
+
# if you are building a TUI or need the CLI version of this gem
|
|
78
|
+
gem "inquirex-tty"
|
|
79
|
+
# if you want to add the keyword `extract` to the DSL vocabilary
|
|
80
|
+
gem "inquire-llm"
|
|
55
81
|
```
|
|
56
82
|
|
|
57
83
|
Then install:
|
|
@@ -60,6 +86,8 @@ Then install:
|
|
|
60
86
|
bundle install
|
|
61
87
|
```
|
|
62
88
|
|
|
89
|
+
And then, define your form as a Ruby DSL file (see [examples](https://github.com/inquirex/inquirex-tty/tree/main/examples) on Github), and consume it by either the `inquirex-tty` gem on the command line, or on the web via the [@kigster/inqiurex-js](https://www.npmjs.com/package/@kigster/inquirex-js) npmjs package.
|
|
90
|
+
|
|
63
91
|
## Quick Start
|
|
64
92
|
|
|
65
93
|
```ruby
|
|
@@ -170,26 +198,35 @@ end
|
|
|
170
198
|
|
|
171
199
|
When no explicit `widget` is set, `WidgetRegistry` fills in sensible defaults per data type:
|
|
172
200
|
|
|
173
|
-
| Data Type
|
|
174
|
-
|
|
175
|
-
| `:enum`
|
|
201
|
+
| Data Type | Desktop | Mobile | TTY |
|
|
202
|
+
| ------------- | ---------------- | ---------------- | -------------- |
|
|
203
|
+
| `:enum` | `radio_group` | `dropdown` | `select` |
|
|
176
204
|
| `:multi_enum` | `checkbox_group` | `checkbox_group` | `multi_select` |
|
|
177
|
-
| `:boolean`
|
|
178
|
-
| `:string`
|
|
179
|
-
| `:text`
|
|
180
|
-
| `:integer`
|
|
181
|
-
| `:currency`
|
|
182
|
-
| `:date`
|
|
205
|
+
| `:boolean` | `toggle` | `yes_no_buttons` | `yes_no` |
|
|
206
|
+
| `:string` | `text_input` | `text_input` | `text_input` |
|
|
207
|
+
| `:text` | `textarea` | `textarea` | `multiline` |
|
|
208
|
+
| `:integer` | `number_input` | `number_input` | `number_input` |
|
|
209
|
+
| `:currency` | `currency_input` | `currency_input` | `number_input` |
|
|
210
|
+
| `:date` | `date_picker` | `date_picker` | `text_input` |
|
|
183
211
|
|
|
184
212
|
Display verbs (`say`, `header`, `btw`, `warning`) have no widget hints.
|
|
185
213
|
|
|
186
214
|
Widget hints are included in JSON serialization under a `"widget"` key, keyed by target:
|
|
187
215
|
|
|
188
216
|
```json
|
|
189
|
-
|
|
190
|
-
"
|
|
191
|
-
|
|
192
|
-
|
|
217
|
+
{
|
|
218
|
+
"widget": {
|
|
219
|
+
"desktop": {
|
|
220
|
+
"type": "radio_group",
|
|
221
|
+
"columns": 3
|
|
222
|
+
},
|
|
223
|
+
"mobile": {
|
|
224
|
+
"type": "dropdown"
|
|
225
|
+
},
|
|
226
|
+
"tty": {
|
|
227
|
+
"type": "select"
|
|
228
|
+
}
|
|
229
|
+
}
|
|
193
230
|
}
|
|
194
231
|
```
|
|
195
232
|
|
|
@@ -197,7 +234,7 @@ Widget hints are included in JSON serialization under a `"widget"` key, keyed by
|
|
|
197
234
|
|
|
198
235
|
```ruby
|
|
199
236
|
step = definition.step(:priority)
|
|
200
|
-
step.widget_hint_for(target: :desktop)
|
|
237
|
+
step.widget_hint_for(target: :desktop) # explicit hint or nil
|
|
201
238
|
step.effective_widget_hint_for(target: :desktop) # explicit hint or registry default
|
|
202
239
|
```
|
|
203
240
|
|
|
@@ -225,12 +262,12 @@ end
|
|
|
225
262
|
|
|
226
263
|
Use the `accumulate` verb inside any `ask`/`confirm` step. Exactly one **shape** key must be provided:
|
|
227
264
|
|
|
228
|
-
| Shape
|
|
229
|
-
|
|
230
|
-
| `lookup: { ... }`
|
|
231
|
-
| `per_selection: { ... }` | `:multi_enum`
|
|
232
|
-
| `per_unit: N`
|
|
233
|
-
| `flat: N`
|
|
265
|
+
| Shape | Fits | Semantics |
|
|
266
|
+
| ------------------------ | ---------------------- | ----------------------------------------------------- |
|
|
267
|
+
| `lookup: { ... }` | `:enum` | Adds the amount mapped to the chosen option value |
|
|
268
|
+
| `per_selection: { ... }` | `:multi_enum` | Sums the amounts for every selected option |
|
|
269
|
+
| `per_unit: N` | `:integer`, `:decimal` | Multiplies the numeric answer by `N` |
|
|
270
|
+
| `flat: N` | any type | Adds `N` when the step has a truthy, non-empty answer |
|
|
234
271
|
|
|
235
272
|
```ruby
|
|
236
273
|
ask :filing_status do
|
|
@@ -540,15 +577,10 @@ Inquirex.define do # one entry point, all verbs available
|
|
|
540
577
|
end
|
|
541
578
|
```
|
|
542
579
|
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
- **`inquirex-llm`** -- LLM-powered verbs (`clarify`, `describe`, `summarize`, `detour`) for server-side AI processing
|
|
546
|
-
- **`inquirex-tty`** -- terminal adapter using TTY Toolkit
|
|
547
|
-
- **`inquirex-js`** -- embeddable browser widget (chat-style)
|
|
548
|
-
- **`inquirex-rails`** -- Rails Engine for persistence, API, and asset serving
|
|
580
|
+
## License
|
|
549
581
|
|
|
550
|
-
|
|
582
|
+
MIT. See [`LICENSE.txt`](LICENSE.txt).
|
|
551
583
|
|
|
552
|
-
|
|
584
|
+
© 2026 Konstantin Gredeskoul.
|
|
553
585
|
|
|
554
|
-
|
|
586
|
+
0
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "bundler/setup"
|
|
5
|
+
require "inquirex"
|
|
6
|
+
|
|
7
|
+
DEFINITION = Inquirex.define id: "tax-intake-2025", version: "1.0.0" do
|
|
8
|
+
meta title: "Tax Preparation Intake", subtitle: "Let's understand your situation"
|
|
9
|
+
start :filing_status
|
|
10
|
+
|
|
11
|
+
ask :filing_status do
|
|
12
|
+
type :enum
|
|
13
|
+
question "What is your filing status?"
|
|
14
|
+
options single: "Single", married_jointly: "Married Filing Jointly"
|
|
15
|
+
widget target: :desktop, type: :radio_group, columns: 2
|
|
16
|
+
widget target: :mobile, type: :dropdown
|
|
17
|
+
transition to: :dependents
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
ask :dependents do
|
|
21
|
+
type :integer
|
|
22
|
+
question "How many dependents?"
|
|
23
|
+
default 0
|
|
24
|
+
transition to: :business_income
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
confirm :business_income do
|
|
28
|
+
question "Do you have business income?"
|
|
29
|
+
transition to: :business_count, if_rule: equals(:business_income, true)
|
|
30
|
+
transition to: :done
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
ask :business_count do
|
|
34
|
+
type :integer
|
|
35
|
+
question "How many businesses?"
|
|
36
|
+
transition to: :done
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
say :done do
|
|
40
|
+
text "Thanks for completing the intake."
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
engine = Inquirex::Engine.new(DEFINITION)
|
|
45
|
+
|
|
46
|
+
engine.answer("single") # filing_status
|
|
47
|
+
engine.answer(2) # dependents
|
|
48
|
+
engine.answer(false) # business_income
|
|
49
|
+
engine.advance # done (display step)
|
|
50
|
+
engine.finished? # => true
|
|
51
|
+
|
|
52
|
+
if __FILE__ == $0
|
|
53
|
+
require 'json'
|
|
54
|
+
puts JSON.pretty_generate(DEFINITION.to_h)
|
|
55
|
+
end
|
|
Binary file
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require_relative '01_readme_example'
|
|
4
|
+
require 'inquirex'
|
|
5
|
+
require 'stringio'
|
|
6
|
+
|
|
7
|
+
output = StringIO.new
|
|
8
|
+
exporter = Inquirex::Graph::MermaidExporter.new(DEFINITION)
|
|
9
|
+
output << exporter.export
|
|
10
|
+
|
|
11
|
+
source = <<~HTML
|
|
12
|
+
<html>
|
|
13
|
+
<head>
|
|
14
|
+
<meta charset="utf-8">
|
|
15
|
+
</head>
|
|
16
|
+
<body>
|
|
17
|
+
<meta charset="utf-8">
|
|
18
|
+
<div class="mermaid">
|
|
19
|
+
#{output.string}
|
|
20
|
+
</div>
|
|
21
|
+
<script type="module">
|
|
22
|
+
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
|
|
23
|
+
mermaid.initialize({ startOnLoad: true });
|
|
24
|
+
</script>
|
|
25
|
+
</html>
|
|
26
|
+
HTML
|
|
27
|
+
|
|
28
|
+
if __FILE__ == $0
|
|
29
|
+
File.write('mermaid.html', source)
|
|
30
|
+
system("open mermaid.html")
|
|
31
|
+
sleep 10
|
|
32
|
+
|
|
33
|
+
at_exit do
|
|
34
|
+
File.delete('mermaid.html')
|
|
35
|
+
end
|
|
36
|
+
end
|
data/examples/README.md
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Examples
|
|
2
|
+
|
|
3
|
+
This folder contains just a couple examples to demonstrate the API and the functionality.
|
|
4
|
+
|
|
5
|
+
For a fuller list of more comprehensive examples, please see the [examples in the `inquirex-tty` gem](https://github.com/inquirex/inquirex-tty/tree/main/examples).
|
|
6
|
+
|
|
7
|
+
## Running Examples
|
|
8
|
+
|
|
9
|
+
These examples are meant to be run as executables from the root level of the gem folder.
|
|
10
|
+
|
|
11
|
+
### First Example
|
|
12
|
+
|
|
13
|
+
This example should print to stdout the DSL definition in JSON:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# First example — creates a DSL definition and prints it to stdout in JSON format
|
|
17
|
+
./examples/01_readme_example.rb | jq
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### Second Example
|
|
21
|
+
|
|
22
|
+
This is a more interesting example. It builds on the first, takes that definition and uses the mermaid converter to write a tiny HTML file with a mermaid diagram inside, which represents the definition defined in the first file.
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# creates a mermaid.html file at the root of the project
|
|
26
|
+
# opens the browser with the file and waits 10 seconds
|
|
27
|
+
# deletes the HTML file and exits
|
|
28
|
+
./examples/02_readme_mermaid.rb
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The mermaid file generated should look like this:
|
|
32
|
+
|
|
33
|
+
<img src="02_readme_mermaid.png" width="300px" text-align="left"></img>
|
data/justfile
CHANGED
|
@@ -31,7 +31,9 @@ test *args:
|
|
|
31
31
|
test-coverage *args:
|
|
32
32
|
export ENVIRONMENT=test; export COVERAGE=true; {{ rbenv }} rspec {{ args }}
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
ci: lint test-coverage
|
|
35
|
+
|
|
36
|
+
alias check-all := ci
|
|
35
37
|
|
|
36
38
|
clean:
|
|
37
39
|
#!/usr/bin/env bash
|
|
@@ -59,7 +61,6 @@ doc:
|
|
|
59
61
|
publish: build
|
|
60
62
|
{{ rbenv }} rake release[remote]
|
|
61
63
|
|
|
62
|
-
|
|
63
64
|
# Tag v{{ version }}, publish the GH release, & refresh the Homebrew tap.
|
|
64
65
|
release:
|
|
65
66
|
git fetch --tags
|
data/lib/inquirex/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: inquirex
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Konstantin Gredeskoul
|
|
@@ -32,6 +32,10 @@ files:
|
|
|
32
32
|
- README.md
|
|
33
33
|
- Rakefile
|
|
34
34
|
- docs/badges/coverage_badge.svg
|
|
35
|
+
- examples/01_readme_example.rb
|
|
36
|
+
- examples/02_readme_mermaid.png
|
|
37
|
+
- examples/02_readme_mermaid.rb
|
|
38
|
+
- examples/README.md
|
|
35
39
|
- justfile
|
|
36
40
|
- lefthook.yml
|
|
37
41
|
- lib/inquirex.rb
|
|
@@ -68,7 +72,7 @@ licenses:
|
|
|
68
72
|
- MIT
|
|
69
73
|
metadata:
|
|
70
74
|
allowed_push_host: https://rubygems.org
|
|
71
|
-
homepage_uri: https://
|
|
75
|
+
homepage_uri: https://qualified.at
|
|
72
76
|
source_code_uri: https://github.com/inquirex/inquirex
|
|
73
77
|
changelog_uri: https://github.com/inquirex/inquirex/blob/main/CHANGELOG.md
|
|
74
78
|
rubygems_mfa_required: 'true'
|