tidewave 0.4.1 → 0.4.2

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: d3375b13a00fb5b052a2bea5c6b720056379f16a26cc984ffde2973d2d2fca90
4
- data.tar.gz: b5d7c9d2290e2273116712116fcb8336ddbc4009be187ca0413ec3c727b33e6b
3
+ metadata.gz: 2ecc3b3a79123c50c7ec933b8cea5e2e4f61aff33671db1237c69a7536b31071
4
+ data.tar.gz: 14781db2f527923f2c5a52c4830c055659abd2e06d49526dd4630df0cd63d22a
5
5
  SHA512:
6
- metadata.gz: 6ad6d175fef2e61d40ab97de1bbf36bfaf3f37137ee7d54d6cc1f7987096e105e37381376e6f8263b70b31795065824b459225512d62e9ae5615c9dc098a8b2d
7
- data.tar.gz: 2535c2570a69f70114705b2ec13f708b17bae00aefcaae504c97323c2c07edb3686a142d40f6a85f42a7619754f93fb8cbcd7267edcbb349fc621004f15c3ae2
6
+ metadata.gz: 39710ecba05ce8a3bf8686695c4602282fd6ee27356f4cc532cb78ea57a16403d2eb60059163b21ed5b3a3cc9225ae51a32a18df7eeee5b6e70197aae246ab26
7
+ data.tar.gz: e87dccaff2712bb7df136913ab409d9cc818f81444fb3892025541a274ba4ba4f17986bc425ba10c99e414668a7531a5773a8f5043c27b58b1af2d0c53a03538
data/README.md CHANGED
@@ -2,11 +2,17 @@
2
2
 
3
3
  Tidewave is the coding agent for full-stack web app development. Integrate Claude Code, OpenAI Codex, and other agents with your web app and web framework at every layer, from UI to database. [See our website](https://tidewave.ai) for more information.
4
4
 
5
- This project can also be used as a standalone Model Context Protocol server for your editors.
5
+ This project can also be used as [a standalone Model Context Protocol server](https://hexdocs.pm/tidewave/mcp.html).
6
6
 
7
7
  ## Installation
8
8
 
9
- You can install Tidewave by adding the `tidewave` gem to the development group in your Gemfile:
9
+ You can install Tidewave by running:
10
+
11
+ ```shell
12
+ bundle add tidewave --group development
13
+ ```
14
+
15
+ or by manully adding the `tidewave` gem to the development group in your Gemfile:
10
16
 
11
17
  ```ruby
12
18
  gem "tidewave", group: :development
@@ -16,28 +22,31 @@ Now make sure [Tidewave is installed](https://hexdocs.pm/tidewave/installation.h
16
22
 
17
23
  ## Troubleshooting
18
24
 
19
- ### Content security policy
25
+ ### Using multiple hosts/subdomains
20
26
 
21
- If you have enabled Content-Security-Policy, Tidewave will automatically enable "unsafe-eval" under `script-src` in order for contextual browser testing to work correctly. It also disables the `frame-ancestors` directive.
27
+ If you are using multiple hosts/subdomains during development, you must use `*.localhost`, as such domains are considered secure by browsers. Additionally, add the following to `config/initializers/development.rb`:
22
28
 
23
- ### Production Environment
29
+ ```ruby
30
+ config.session_store :cookie_store,
31
+ key: "__your_app_session",
32
+ same_site: :none,
33
+ secure: true,
34
+ assume_ssl: true
35
+ ```
24
36
 
25
- Tidewave is a powerful tool that can help you develop your web application faster and more efficiently. However, it is important to note that Tidewave is not meant to be used in a production environment.
37
+ And make sure you are using `rack-session` version `2.1.0` or later.
26
38
 
27
- Tidewave will raise an error if it is used in any environment where code reloading is disabled (which typically includes production).
39
+ The above will allow your application to run embedded within Tidewave across multiple subdomains, as long as it is using a secure context (such as `admin.localhost`, `www.foobar.localhost`, etc).
28
40
 
29
- ### Localhost requirement
41
+ ### Content security policy
30
42
 
31
- > This requirement only matters if you are not using the Tidewave app/CLI.
43
+ If you have enabled Content-Security-Policy, Tidewave will automatically enable "unsafe-eval" under `script-src` in order for contextual browser testing to work correctly. It also disables the `frame-ancestors` directive.
32
44
 
33
- Tidewave expects your web application to be running on `localhost`. If you are not running on localhost, you may need to set some additional configuration. In particular, you must configure Tidewave to allow `allow_remote_access` and [optionally configure your Rails hosts](https://guides.rubyonrails.org/configuring.html#actiondispatch-hostauthorization). For example, in your `config/environments/development.rb`:
45
+ ### Production Environment
34
46
 
35
- ```ruby
36
- config.hosts << "company.local"
37
- config.tidewave.allow_remote_access = true
38
- ```
47
+ Tidewave is a powerful tool that can help you develop your web application faster and more efficiently. However, it is important to note that Tidewave is not meant to be used in a production environment.
39
48
 
40
- If you want to use Docker for development, you either need to enable the configuration above or automatically redirect the relevant ports, as done by [devcontainers](https://code.visualstudio.com/docs/devcontainers/containers). See our [containers](https://hexdocs.pm/tidewave/containers.html) guide for more information.
49
+ Tidewave will raise an error if it is used in any environment where code reloading is disabled (which typically includes production).
41
50
 
42
51
  ## Configuration
43
52
 
@@ -57,6 +66,26 @@ The following config is available:
57
66
 
58
67
  * `team` - set your Tidewave Team configuration, such as `config.tidewave.team = { id: "my-company" }`
59
68
 
69
+ ## Available tools
70
+
71
+ - `execute_sql_query` - executes a SQL query within your application
72
+ database, useful for the agent to verify the result of an action
73
+
74
+ - `get_docs` - get the documentation for a given module/class/method.
75
+ It consults the exact versions used by the project, ensuring you always
76
+ get correct information
77
+
78
+ - `get_logs` - reads logs written by the server
79
+
80
+ - `get_models` - lists all modules in the application and their location
81
+ for quick discovery
82
+
83
+ - `get_source_location` - get the source location for a given module/class/method,
84
+ so an agent can directly read the source skipping search
85
+
86
+ - `project_eval` - evaluates code within the Rails application itself, giving the agent
87
+ access to your runtime, dependencies, and in-memory data
88
+
60
89
  ## Acknowledgements
61
90
 
62
91
  A thank you to Yorick Jacquin, for creating [FastMCP](https://github.com/yjacquin/fast_mcp) and implementing the initial version of this project.
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "open3"
4
3
  require "ipaddr"
5
4
  require "fast_mcp"
6
5
  require "rack/request"
@@ -13,7 +12,6 @@ require_relative "streamable_http_transport"
13
12
  class Tidewave::Middleware
14
13
  TIDEWAVE_ROUTE = "tidewave".freeze
15
14
  MCP_ROUTE = "mcp".freeze
16
- SHELL_ROUTE = "shell".freeze
17
15
  CONFIG_ROUTE = "config".freeze
18
16
 
19
17
  INVALID_IP = <<~TEXT.freeze
@@ -64,8 +62,6 @@ class Tidewave::Middleware
64
62
  return home(request)
65
63
  when [ "GET", [ TIDEWAVE_ROUTE, CONFIG_ROUTE ] ]
66
64
  return config_endpoint(request)
67
- when [ "POST", [ TIDEWAVE_ROUTE, SHELL_ROUTE ] ]
68
- return shell(request)
69
65
  end
70
66
  end
71
67
 
@@ -88,7 +84,6 @@ class Tidewave::Middleware
88
84
  <head>
89
85
  <meta charset="UTF-8" />
90
86
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
91
- <meta name="tidewave:config" content="#{ERB::Util.html_escape(JSON.generate(config))}" />
92
87
  <script type="module" src="#{@client_url}/tc/tc.js"></script>
93
88
  </head>
94
89
  <body></body>
@@ -116,66 +111,6 @@ class Tidewave::Middleware
116
111
  [ 403, { "Content-Type" => "text/plain" }, [ message ] ]
117
112
  end
118
113
 
119
- def shell(request)
120
- body = request.body.read
121
- return [ 400, { "Content-Type" => "text/plain" }, [ "Command body is required" ] ] if body.blank?
122
-
123
- begin
124
- parsed_body = JSON.parse(body)
125
- cmd = parsed_body["command"]
126
- return [ 400, { "Content-Type" => "text/plain" }, [ "Command field is required" ] ] if cmd.blank?
127
- rescue JSON::ParserError
128
- return [ 400, { "Content-Type" => "text/plain" }, [ "Invalid JSON in request body" ] ]
129
- end
130
-
131
- response = Rack::Response.new
132
- response.status = 200
133
- response.headers["Content-Type"] = "text/plain"
134
-
135
- response.finish do |res|
136
- begin
137
- Open3.popen3(*cmd) do |stdin, stdout, stderr, wait_thr|
138
- stdin.close
139
-
140
- # Merge stdout and stderr streams
141
- ios = [ stdout, stderr ]
142
-
143
- until ios.empty?
144
- ready = IO.select(ios, nil, nil, 0.1)
145
- next unless ready
146
-
147
- ready[0].each do |io|
148
- begin
149
- data = io.read_nonblock(4096)
150
- if data
151
- # Write binary chunk: type (0 for data) + 4-byte length + data
152
- chunk = [ 0, data.bytesize ].pack("CN") + data
153
- res.write(chunk)
154
- end
155
- rescue IO::WaitReadable
156
- # No data available right now
157
- rescue EOFError
158
- # Stream ended
159
- ios.delete(io)
160
- end
161
- end
162
- end
163
-
164
- # Wait for process to complete and get exit status
165
- exit_status = wait_thr.value.exitstatus
166
- status_json = JSON.generate({ status: exit_status })
167
- # Write binary chunk: type (1 for status) + 4-byte length + JSON data
168
- chunk = [ 1, status_json.bytesize ].pack("CN") + status_json
169
- res.write(chunk)
170
- end
171
- rescue => e
172
- error_json = JSON.generate({ status: 213 })
173
- chunk = [ 1, error_json.bytesize ].pack("CN") + error_json
174
- res.write(chunk)
175
- end
176
- end
177
- end
178
-
179
114
  def valid_client_ip?(request)
180
115
  return true if @allow_remote_access
181
116
 
@@ -76,11 +76,15 @@ module Tidewave
76
76
 
77
77
  @logger.debug("Sending response: #{@captured_response.inspect}")
78
78
 
79
- [
80
- 200,
81
- { "Content-Type" => "application/json" },
82
- [ JSON.generate(@captured_response) ]
83
- ]
79
+ if @captured_response
80
+ [
81
+ 200,
82
+ { "Content-Type" => "application/json" },
83
+ [ JSON.generate(@captured_response) ]
84
+ ]
85
+ else
86
+ [ 202, {}, [] ]
87
+ end
84
88
  rescue JSON::ParserError => e
85
89
  @logger.error("Invalid JSON in request: #{e.message}")
86
90
  json_rpc_error_response(400, -32700, "Parse error", nil)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Tidewave
4
- VERSION = "0.4.1"
4
+ VERSION = "0.4.2"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tidewave
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yorick Jacquin
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2025-11-25 00:00:00.000000000 Z
12
+ date: 2026-02-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails