command-gate 0.2.4__py3-none-any.whl

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.
Files changed (63) hide show
  1. cgate/__init__.py +26 -0
  2. cgate/__main__.py +8 -0
  3. cgate/_version.py +24 -0
  4. cgate/cli/__init__.py +1 -0
  5. cgate/cli/_console.py +17 -0
  6. cgate/cli/connections.py +212 -0
  7. cgate/cli/history.py +191 -0
  8. cgate/cli/install.py +182 -0
  9. cgate/cli/main.py +115 -0
  10. cgate/cli/mcp.py +197 -0
  11. cgate/cli/uninstall.py +403 -0
  12. cgate/cli/update.py +538 -0
  13. cgate/cli/watch.py +20 -0
  14. cgate/connections/__init__.py +1 -0
  15. cgate/connections/auth.py +93 -0
  16. cgate/connections/detect.py +78 -0
  17. cgate/connections/store.py +88 -0
  18. cgate/core/__init__.py +1 -0
  19. cgate/core/path_env.py +218 -0
  20. cgate/core/paths.py +35 -0
  21. cgate/core/update_log.py +36 -0
  22. cgate/db/__init__.py +1 -0
  23. cgate/db/batches.py +111 -0
  24. cgate/db/commands.py +191 -0
  25. cgate/db/connection.py +104 -0
  26. cgate/db/mode.py +74 -0
  27. cgate/db/rows.py +99 -0
  28. cgate/db/schema.py +54 -0
  29. cgate/db/server_settings.py +105 -0
  30. cgate/db/types.py +77 -0
  31. cgate/executor/__init__.py +7 -0
  32. cgate/executor/base.py +71 -0
  33. cgate/executor/selector.py +61 -0
  34. cgate/executor/ssh.py +157 -0
  35. cgate/executor/winrm.py +129 -0
  36. cgate/helper/__init__.py +10 -0
  37. cgate/helper/__main__.py +112 -0
  38. cgate/helper/waiter.py +123 -0
  39. cgate/mcp_installer.py +161 -0
  40. cgate/mcp_server/__init__.py +6 -0
  41. cgate/mcp_server/__main__.py +6 -0
  42. cgate/mcp_server/auto_resolution.py +80 -0
  43. cgate/mcp_server/server.py +271 -0
  44. cgate/mcp_server/tools.py +351 -0
  45. cgate/risk.py +129 -0
  46. cgate/update.py +713 -0
  47. cgate/watch/__init__.py +7 -0
  48. cgate/watch/app.py +560 -0
  49. cgate/watch/approval.py +237 -0
  50. cgate/watch/command_detail_modal.py +68 -0
  51. cgate/watch/history_modal.py +242 -0
  52. cgate/watch/mode_modal.py +110 -0
  53. cgate/watch/queue.py +106 -0
  54. cgate/watch/render.py +156 -0
  55. cgate/watch/server_settings_modal.py +179 -0
  56. cgate/watch/session.py +40 -0
  57. cgate/watch/theme.py +32 -0
  58. cgate/watch/widgets.py +35 -0
  59. command_gate-0.2.4.dist-info/METADATA +204 -0
  60. command_gate-0.2.4.dist-info/RECORD +63 -0
  61. command_gate-0.2.4.dist-info/WHEEL +4 -0
  62. command_gate-0.2.4.dist-info/entry_points.txt +2 -0
  63. command_gate-0.2.4.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,204 @@
1
+ Metadata-Version: 2.5
2
+ Name: command-gate
3
+ Version: 0.2.4
4
+ Summary: Middleware and CLI between AI assistants and managed servers so AI proposes commands, humans approve them, and every action is audited.
5
+ Project-URL: Homepage, https://github.com/wanderlp/command-gate-for-ai-agents
6
+ Project-URL: Repository, https://github.com/wanderlp/command-gate-for-ai-agents
7
+ Project-URL: Issues, https://github.com/wanderlp/command-gate-for-ai-agents/issues
8
+ Project-URL: Changelog, https://github.com/wanderlp/command-gate-for-ai-agents/releases
9
+ Author: wanderlp
10
+ License: MIT
11
+ License-File: LICENSE
12
+ Keywords: ai-agents,audit,cli,human-in-the-loop,mcp,ssh,winrm
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Environment :: Console
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: Intended Audience :: System Administrators
17
+ Classifier: License :: OSI Approved :: MIT License
18
+ Classifier: Operating System :: MacOS
19
+ Classifier: Operating System :: Microsoft :: Windows
20
+ Classifier: Operating System :: POSIX :: Linux
21
+ Classifier: Programming Language :: Python :: 3
22
+ Classifier: Programming Language :: Python :: 3.11
23
+ Classifier: Programming Language :: Python :: 3.12
24
+ Classifier: Topic :: Security
25
+ Classifier: Topic :: System :: Systems Administration
26
+ Classifier: Typing :: Typed
27
+ Requires-Python: >=3.11
28
+ Requires-Dist: keyring>=25.0
29
+ Requires-Dist: mcp>=1.0
30
+ Requires-Dist: packaging>=23.0
31
+ Requires-Dist: paramiko>=3.0
32
+ Requires-Dist: pydantic>=2.7
33
+ Requires-Dist: pywinrm>=0.4
34
+ Requires-Dist: requests>=2.31
35
+ Requires-Dist: rich>=13.0
36
+ Requires-Dist: sigstore>=4.5.0
37
+ Requires-Dist: textual>=8.2.8
38
+ Requires-Dist: typer>=0.12
39
+ Requires-Dist: typing-extensions>=4.12
40
+ Provides-Extra: dev
41
+ Requires-Dist: basedpyright>=1.13; extra == 'dev'
42
+ Requires-Dist: hatch-vcs>=0.5; extra == 'dev'
43
+ Requires-Dist: pyinstaller>=6.0; extra == 'dev'
44
+ Requires-Dist: pytest-cov>=5; extra == 'dev'
45
+ Requires-Dist: pytest>=8; extra == 'dev'
46
+ Requires-Dist: ruff>=0.6; extra == 'dev'
47
+ Description-Content-Type: text/markdown
48
+
49
+ # command-gate-for-ai-agents (`cgate`)
50
+
51
+ Give your AI agents hands — safely.
52
+
53
+ AI agents can now write and run real shell commands against real servers. That's
54
+ powerful, and also the kind of thing that goes badly the first time an agent
55
+ misunderstands what you asked for. `cgate` sits between the agent and your
56
+ infrastructure: the agent proposes a command, a human decides whether it runs, and
57
+ every proposal, decision, and result is recorded.
58
+
59
+ You stop choosing between "the agent can't actually do anything" and "the agent can do
60
+ anything, unsupervised."
61
+
62
+ > **⚠️ Beta.** `cgate` is under active development. Expect rough edges, breaking
63
+ > changes between releases, and incoming revisions as it matures — feedback and bug
64
+ > reports are welcome.
65
+
66
+ ## Why teams use it
67
+
68
+ - **Agents propose, humans decide.** Every command an AI agent wants to run on a
69
+ connected server lands in an approval queue first. Nothing executes without a human
70
+ saying yes.
71
+ - **A full audit trail.** Every proposal, approval, rejection, and execution result is
72
+ recorded — who approved it, when, and what happened.
73
+ - **Drops into the AI tools you already use.** Registers itself as an MCP server for
74
+ Claude Code, opencode, Cursor, and other MCP-compatible clients.
75
+ - **One binary, nothing to configure.** Ships as a single executable per platform —
76
+ download it and run it, done.
77
+
78
+ ## Modes: PROPOSE and AUTO
79
+
80
+ `cgate` ships in two modes, and you pick per server which ones can ever run
81
+ unattended. The default is the safe one.
82
+
83
+ **PROPOSE** (default): every command an AI agent calls lands in the watch queue. You
84
+ press `y` or `n` per command. Nothing runs without you.
85
+
86
+ **AUTO**: when the agent calls `propose_command`, it runs immediately **only if the
87
+ target server is on your allow-list**. Servers are off by default — you opt them in
88
+ explicitly. Two switches need to land in the "go" position before anything runs
89
+ unattended: the global mode is AUTO *and* that specific server is opted in.
90
+
91
+ ```text
92
+ ┌─────────────────────────────────────────────────────────────┐
93
+ │ cgate watch MODE: AUTO ⚡ | 1 servers auto-allowed │
94
+ ├─────────────────────────────────────────────────────────────┤
95
+ │ [Queue] [Servers] │
96
+ │ ▶ "deploy v2" dev-1 LNX [✓] │
97
+ │ stage-2 LNX [ ] │
98
+ │ prod-db WIN [ ] │
99
+ ├─────────────────────────────────────────────────────────────┤
100
+ │ [y]approve [n]reject [a]approve batch [m]ode [h]istory ... │
101
+ └─────────────────────────────────────────────────────────────┘
102
+ ```
103
+
104
+ ↑/↓ + Enter on the queue sidebar jumps straight to any pending batch — you're not
105
+ forced to clear the queue in strict arrival order to get to the one you actually
106
+ want to approve next.
107
+
108
+ ### Switching modes
109
+
110
+ Press **`m`** in `cgate watch` to flip the global mode (one keystroke + `y` to
111
+ confirm). Press **`s`** to open the server allow-list and toggle any connection on or
112
+ off. Both modals need an explicit `y` or `Enter`; everything else cancels without
113
+ writing. AI agents have no MCP tool that can change either setting — only your
114
+ keystrokes can.
115
+
116
+ ### Why two switches?
117
+
118
+ If you leave `MODE: AUTO` on by accident, the worst case is that nothing runs on
119
+ servers that haven't been explicitly opted in. To actually run something
120
+ unattended you must enable the mode **and** flip the per-server switch. Belt and
121
+ suspenders, default-safe at every level.
122
+
123
+ ### A third switch: high-blast-radius commands never auto-run
124
+
125
+ Even with both switches flipped, a command matching a known high-blast-radius
126
+ pattern — a recursive force-delete, a raw disk write, deleting shadow copies or
127
+ backups, disabling System Restore, and similar — always queues for a human. It
128
+ shows a bold red `⚠ RISKY` warning in `cgate watch` (in **either** mode, so you
129
+ notice it in PROPOSE too, not only when it changed what AUTO would have done),
130
+ and the MCP response carries `effective_reason: "risky_command"` so the agent
131
+ knows why. This is a regex-based heuristic, not a guarantee — it catches the
132
+ common, obvious forms (see `src/cgate/risk.py`), not every possible obfuscation.
133
+ Absence of the flag is not the same as "safe."
134
+
135
+ ### The audit trail still works
136
+
137
+ Every command a batch ever queued shows an `⚙ auto` or `👤 <username>` badge next
138
+ to it, so you always know whether a human or AUTO mode approved it — and once a
139
+ batch resolves, it doesn't vanish: press **`h`** in `cgate watch` to browse every
140
+ resolved batch, see the agent's stated `reason` for wanting the command, and view
141
+ the full, untruncated result. Press **`/`** there to filter live against a batch's
142
+ title, its commands, and their server aliases all at once -- `Esc` clears the
143
+ filter first, then closes the screen on a second press.
144
+
145
+ Need it outside the TUI — for a compliance report, or just to grep offline?
146
+
147
+ ```bash
148
+ cgate history export # full audit trail as CSV, to stdout
149
+ cgate history export --format json -o audit.json
150
+ cgate history export --limit 100 # only the 100 most recently resolved batches
151
+ ```
152
+
153
+ Human-only: this isn't exposed to AI agents over MCP. An agent that proposed a
154
+ batch can already poll `check_status(batch_id)` for it at any time, resolved or
155
+ not, so there's no reason to hand it a browse of everyone else's history too.
156
+
157
+ Prefer raw SQL? The same data is still just a query away:
158
+
159
+ ```sql
160
+ SELECT * FROM commands WHERE approved_by LIKE 'auto:%';
161
+ ```
162
+
163
+ ### What the AI sees (and what it can ask first)
164
+
165
+ The MCP server exposes three read-only tools the AI can use to plan with full
166
+ information, plus `propose_command` to act:
167
+
168
+ - **`list_connections`** — every saved connection and its `auto_allowed` flag
169
+ (the AI knows up front which servers could auto-execute).
170
+ - **`get_mode`** — the current global mode (`propose` or `auto`) and the list of
171
+ aliases opted into auto-execution. Read-only, safe to call any time.
172
+ - **`check_status`** — what's pending in a given batch.
173
+
174
+ With these, the AI never has to guess whether a command will auto-run or wait
175
+ for you — it can call `get_mode` and `list_connections` first, plan accordingly,
176
+ and only invoke `propose_command` when it knows what will happen.
177
+
178
+ ## Get started
179
+
180
+ 1. Download the binary for your platform from the
181
+ [latest release](https://github.com/wanderlp/command-gate-for-ai-agents/releases/latest).
182
+ 2. Run it (double-click it, or just `.\cgate-windows-amd64.exe` from the folder you
183
+ downloaded it to). On first run it installs itself into a per-user bin directory,
184
+ adds that directory to your `PATH`, and registers with any AI clients it finds —
185
+ no admin/sudo, no flags to remember.
186
+ 3. Open a new terminal and restart your AI client. Done.
187
+
188
+ From there, `cgate watch` opens a live approval queue: agent proposals show up as they
189
+ come in, you approve or reject with a keypress, and the result streams back to the
190
+ agent.
191
+
192
+ > First run on Windows or macOS may show a one-time "unrecognized publisher" warning —
193
+ > these binaries aren't code-signed yet. See
194
+ > [TECHNICAL.md](./TECHNICAL.md#first-run-warnings-binaries-are-not-code-signed) for
195
+ > what to do about it.
196
+
197
+ ## Learn more
198
+
199
+ Package-manager installs, architecture, development setup, and building from source
200
+ live in [TECHNICAL.md](./TECHNICAL.md).
201
+
202
+ ## License
203
+
204
+ [MIT](./LICENSE)
@@ -0,0 +1,63 @@
1
+ cgate/__init__.py,sha256=j2uYGJonOw5SJL8TzNmvBLX8X96YLlyicTIWeAJiIpA,1028
2
+ cgate/__main__.py,sha256=_JRJpLo2Nk9U35g-q_UWIsjXOTpx7t3iENDAgIaOhBo,151
3
+ cgate/_version.py,sha256=oIZQE-4i_2bThWVLsbnRskxqsRwrfcev8lVgZK6VSzM,520
4
+ cgate/mcp_installer.py,sha256=j-N-kynR2TDQOQKjJeA0apEUj3D2DAKitF4VbO5DR4E,5855
5
+ cgate/risk.py,sha256=n0rJCJrfH7OSOIiSazX22ae1gLzQeMtwCVbwS_Du3-s,5227
6
+ cgate/update.py,sha256=jPmKnbfTY5o3-J2p9K3-JA3UuudGIrHZ4ZlLZt5x5HE,26807
7
+ cgate/cli/__init__.py,sha256=U4S_2y3zgLZVfMenHRaJFBW8yqh2mUBuI291LGQVOJ8,35
8
+ cgate/cli/_console.py,sha256=9z01vJcoeOfcQysiOX41hYZlk2WleOxwuFycK7OVh5E,527
9
+ cgate/cli/connections.py,sha256=qeJtjiB9UjSi7O8mBLCslidBGPemTVLYPyDMte6w4UQ,8248
10
+ cgate/cli/history.py,sha256=80S-U3pZzXdZX0C4byuvCQbvzdQ8tVxyoI7kT9bq1Nk,6176
11
+ cgate/cli/install.py,sha256=bC4v6AMR1MD7VUVygaIwLpG3LfHdADW7joXTHP-dpM8,6903
12
+ cgate/cli/main.py,sha256=Fri_KfkSFRa_3ePyyEC_PJ9Op4pVGJvym7hvTAvjdGs,3874
13
+ cgate/cli/mcp.py,sha256=Gb8bJ4HDTlP17DtRm88KTW1lqs0R3t1f2urwz5074nw,6077
14
+ cgate/cli/uninstall.py,sha256=JrlSTkvJdUuMo86tRDErd8qJK3P4k6g-N6wiftfovCc,15257
15
+ cgate/cli/update.py,sha256=TNCT7gYvcYUYDCu7eJTLK4cy8E5f1B1nLuBuThRq95g,22034
16
+ cgate/cli/watch.py,sha256=kT6KpdydhJdx_xyaQn7oJUDW8eXUr7qJIEO75xBzh1o,633
17
+ cgate/connections/__init__.py,sha256=U4S_2y3zgLZVfMenHRaJFBW8yqh2mUBuI291LGQVOJ8,35
18
+ cgate/connections/auth.py,sha256=KDdsDc91WMi-G23Yfkj9FyIZqdEYpzWANinJbajRF3k,2713
19
+ cgate/connections/detect.py,sha256=f5A5hZQgmmFDDzz_2Mco3dQlr8RpeBHSZa6BDY9TOMk,2257
20
+ cgate/connections/store.py,sha256=s96p8MxHm4UpjwvddKGQYTLzkrAfChlcmTdK9_5EFMs,3003
21
+ cgate/core/__init__.py,sha256=U4S_2y3zgLZVfMenHRaJFBW8yqh2mUBuI291LGQVOJ8,35
22
+ cgate/core/path_env.py,sha256=nfiKoEDKgAFU_1YChjuDZdWudBnSuNe4_ivlUsTVjYY,8434
23
+ cgate/core/paths.py,sha256=U6cBTEEJU9aIu38juZ1Mh4uICxIAZfr9GPxxVNS-lqU,1063
24
+ cgate/core/update_log.py,sha256=hpDDmiQ8FprxmXh_3uq_t1EyrwciXaXUmCmKiIFmziY,1340
25
+ cgate/db/__init__.py,sha256=U4S_2y3zgLZVfMenHRaJFBW8yqh2mUBuI291LGQVOJ8,35
26
+ cgate/db/batches.py,sha256=Xq1UFTZmiNhbSzGWI80y5ZhFENbJ_Y-Xbe9unTwicRY,4117
27
+ cgate/db/commands.py,sha256=TsEK8-nPurqufhNooUKA3-5kyHEx_yIdQiP-h7IdqJw,7652
28
+ cgate/db/connection.py,sha256=qjObNpj3HwlEDhXsXxxwcOQUcGNtDtBLtn2m5re-FgU,4065
29
+ cgate/db/mode.py,sha256=AaSF5UhpoVIIlqiGlf0gNBQcCSmz_rINusulucgIp1A,2492
30
+ cgate/db/rows.py,sha256=SRmO4KXP8CgJoCQjs4FHM0XOOhc-ckKffQbqyg8I1XM,3144
31
+ cgate/db/schema.py,sha256=6e0XavNzmDays5_2FVyceJ7pyz3hhFUdyvIFoNWa9NI,1599
32
+ cgate/db/server_settings.py,sha256=I-Cmry17oT1IBhQ7HhplE40Q3_Jv6_Ez-uXPqrQdFbQ,3799
33
+ cgate/db/types.py,sha256=9BrIRI0pSSlzL03osxB8rJslCVLXZcsISg0rBP8qN18,1866
34
+ cgate/executor/__init__.py,sha256=WhfPSo-O46l5DEuwr0b9VWVck_FugZTg-qxioZymNjo,328
35
+ cgate/executor/base.py,sha256=PWPUbCJgWz-KB4x6agRhongtQ4xtxq231bFgD4-7lhU,2041
36
+ cgate/executor/selector.py,sha256=uo_1Z2tIiaY2ioB4GLiiXlmpDV0YGECQhhyr-oH1uS4,2119
37
+ cgate/executor/ssh.py,sha256=TQqk8PpQ7n-Zb4uzPdHCqqH9cwGLPMMrIpiKhh_QU60,5608
38
+ cgate/executor/winrm.py,sha256=3qRAM1m6Jpf6-BrbGzRI4mw1qRRxPCHhRYfYv_PCdzg,5066
39
+ cgate/helper/__init__.py,sha256=2QKg7XZo1jy3pLEDceecHC7ydOq1X6jZdMYzjIQcga4,451
40
+ cgate/helper/__main__.py,sha256=LtCQn_2Jj5mnNYRo1G0F6yq5CqTCM-svMLosXS8gJkc,4299
41
+ cgate/helper/waiter.py,sha256=dt30KFVi-9nHeNX4tsq6zrj9regq_xOPM91A4a3KkJ8,4633
42
+ cgate/mcp_server/__init__.py,sha256=hgpeupqz73g6-PFfequOp7HZmyGtix_xLqBG-HwsgqQ,189
43
+ cgate/mcp_server/__main__.py,sha256=4SGNpnD2Zai-RQOZGHUhKC4KUE821vAQ_ZsultAZDMk,149
44
+ cgate/mcp_server/auto_resolution.py,sha256=i7iRX615JnWtlK0aPd8LGnJittz8rqZ5JWfTdwPg4WY,2980
45
+ cgate/mcp_server/server.py,sha256=1UpfsYd6ohnyso70mKnGOGc_vFVoZe_kbTM5rvzgnkQ,10178
46
+ cgate/mcp_server/tools.py,sha256=Axa4hNFj6zN2m4e7U_y1NN4ogR3dDyQ142ZDVFxaDZI,11824
47
+ cgate/watch/__init__.py,sha256=dh1jr9CPf50HHtRAyyIKedUoIfmPn85ilau1kOCHBik,194
48
+ cgate/watch/app.py,sha256=1W6cBE0hIJy5hoSq6yseSWSuBeLEoy9g6GJQh53s4R8,23105
49
+ cgate/watch/approval.py,sha256=UKdTisgCrORdDw8FzX7ky0u2ktZAgVZqnCd9mhxeh3U,8154
50
+ cgate/watch/command_detail_modal.py,sha256=g0gD3gjlqkR2r6vh6PcSDWW4mxUCnoYnWgEDRTKOnG8,2190
51
+ cgate/watch/history_modal.py,sha256=3Tz77WecBuKeO6ZNvwnF56Hfc3j1aQjAITpqJ_LRzkQ,9933
52
+ cgate/watch/mode_modal.py,sha256=LuksUIPOHJQfdhwGdpcR1rUqaKjiVUuavyaYALuyeR8,3965
53
+ cgate/watch/queue.py,sha256=-Bol4-kPceV3MxEcnFp0qVq1mnGdtH_dkbbK3YZlgAk,4156
54
+ cgate/watch/render.py,sha256=Lw_-pKVfTmnhhm4t_wfw8s2p8uS2jg94Gm2WAorsDJo,6309
55
+ cgate/watch/server_settings_modal.py,sha256=gp1I3NuLmasc3Um-CELs_pz0NXO-Z7M2Lv6m4yyCylQ,7055
56
+ cgate/watch/session.py,sha256=DYfQsYSPPr7DeWkyfdX_sel4vawrrl9zuk_O0l_zuYc,1309
57
+ cgate/watch/theme.py,sha256=vf4m8-hhY3QjNfodl9zwUGGcuHUTpaeYWmUNgoiEDr0,1062
58
+ cgate/watch/widgets.py,sha256=AGf06cjwHIwns1Ey1AEVSgfdmrnnTdZp3sf3yccqLRM,1051
59
+ command_gate-0.2.4.dist-info/METADATA,sha256=baQxhQ7-eLnZhAS15Xeht4tQsviCaRANJ6JCQr2SK8Q,9883
60
+ command_gate-0.2.4.dist-info/WHEEL,sha256=THafob7ofN-NsuMN7Mg4qZyHaQI7KkD-QlcQatYhXPo,87
61
+ command_gate-0.2.4.dist-info/entry_points.txt,sha256=Z1vx-ws6uoKZdAGifcDYVNiRxnlGK8lDlHwFwq2qDwE,46
62
+ command_gate-0.2.4.dist-info/licenses/LICENSE,sha256=lJZtUokrYiJzTLMawbBuLr14YKukTMEEF4YCKNz4n20,1065
63
+ command_gate-0.2.4.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.32.3
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ cgate = cgate.cli.main:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 wanderlp
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.