rolemodel-rails 1.1.0 → 2.1.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 +117 -7
- data/lib/generators/rolemodel/all_generator.rb +0 -1
- data/lib/generators/rolemodel/optics/icons/README.md +6 -1
- data/lib/generators/rolemodel/optics/icons/icons_generator.rb +14 -9
- data/lib/generators/rolemodel/optics/icons/templates/app/helpers/icon_helper.rb.tt +4 -2
- data/lib/generators/rolemodel/testing/README.md +4 -1
- data/lib/generators/rolemodel/testing/all_generator.rb +3 -3
- data/lib/generators/rolemodel/testing/jasmine_playwright/jasmine_playwright_generator.rb +1 -1
- data/lib/generators/rolemodel/testing/rspec/README.md +1 -1
- data/lib/generators/rolemodel/testing/rspec/USAGE +1 -1
- data/lib/generators/rolemodel/testing/rspec/rspec_generator.rb +15 -14
- data/lib/generators/rolemodel/testing/rspec/templates/spec/support/capybara_config.rb.tt +9 -0
- data/lib/{generators/rolemodel/optics/icons/templates/app/icon_builders → rolemodel/optics}/custom_icon_builder.rb +1 -1
- data/lib/{generators/rolemodel/optics/icons/templates/app/icon_builders → rolemodel/optics}/feather_icon_builder.rb +1 -1
- data/lib/{generators/rolemodel/optics/icons/templates/app/icon_builders → rolemodel/optics}/icon_builder.rb +10 -19
- data/lib/{generators/rolemodel/optics/icons/templates/app/icon_builders → rolemodel/optics}/lucide_icon_builder.rb +1 -1
- data/lib/{generators/rolemodel/optics/icons/templates/app/icon_builders → rolemodel/optics}/material_icon_builder.rb +1 -1
- data/lib/{generators/rolemodel/optics/icons/templates/app/icon_builders → rolemodel/optics}/phosphor_icon_builder.rb +1 -1
- data/lib/{generators/rolemodel/optics/icons/templates/app/icon_builders → rolemodel/optics}/tabler_icon_builder.rb +1 -1
- data/lib/rolemodel/optics.rb +9 -0
- data/lib/rolemodel/utility/task_tools.rb +69 -0
- data/lib/rolemodel/utility.rb +3 -0
- data/lib/rolemodel/version.rb +1 -1
- data/lib/rolemodel-rails.rb +2 -0
- metadata +35 -42
- data/lib/generators/rolemodel/mcp/README.md +0 -13
- data/lib/generators/rolemodel/mcp/USAGE +0 -8
- data/lib/generators/rolemodel/mcp/mcp_generator.rb +0 -110
- data/lib/generators/rolemodel/mcp/templates/app/assets/stylesheets/components/doorkeeper.css +0 -140
- data/lib/generators/rolemodel/mcp/templates/app/controllers/doorkeeper/base_controller.rb +0 -7
- data/lib/generators/rolemodel/mcp/templates/app/controllers/mcp_controller.rb.tt +0 -91
- data/lib/generators/rolemodel/mcp/templates/app/controllers/oauth_registrations_controller.rb +0 -46
- data/lib/generators/rolemodel/mcp/templates/app/controllers/well_known_controller.rb +0 -39
- data/lib/generators/rolemodel/mcp/templates/app/mcp/prompts/sample.rb +0 -36
- data/lib/generators/rolemodel/mcp/templates/app/mcp/resources/controller.rb +0 -57
- data/lib/generators/rolemodel/mcp/templates/app/mcp/resources/docs/SAMPLE_DOC.md +0 -4
- data/lib/generators/rolemodel/mcp/templates/app/mcp/resources/docs_controller.rb +0 -46
- data/lib/generators/rolemodel/mcp/templates/app/mcp/tools/sample.rb +0 -42
- data/lib/generators/rolemodel/mcp/templates/app/views/doorkeeper/authorizations/error.html.slim.tt +0 -13
- data/lib/generators/rolemodel/mcp/templates/app/views/doorkeeper/authorizations/new.html.slim.tt +0 -41
- data/lib/generators/rolemodel/mcp/templates/app/views/layouts/doorkeeper.html.slim +0 -7
- data/lib/generators/rolemodel/mcp/templates/config/initializers/doorkeeper.rb +0 -537
- data/lib/generators/rolemodel/mcp/templates/spec/mcp/prompts/sample_spec.rb +0 -15
- data/lib/generators/rolemodel/mcp/templates/spec/mcp/resources/controller_spec.rb +0 -16
- data/lib/generators/rolemodel/mcp/templates/spec/mcp/resources/docs_controller_spec.rb +0 -55
- data/lib/generators/rolemodel/mcp/templates/spec/mcp/tools/sample_spec.rb +0 -15
- data/lib/generators/rolemodel/mcp/templates/spec/requests/mcp_controller_spec.rb +0 -84
- data/lib/generators/rolemodel/mcp/templates/spec/requests/oauth_registrations_controller_spec.rb +0 -62
- data/lib/generators/rolemodel/mcp/templates/spec/requests/well_known_controller_spec.rb +0 -30
- data/lib/generators/rolemodel/testing/rspec/templates/support/capybara_testid.rb +0 -5
- /data/lib/generators/rolemodel/testing/rspec/templates/{rails_helper.rb → spec/rails_helper.rb.tt} +0 -0
- /data/lib/generators/rolemodel/testing/rspec/templates/{spec_helper.rb → spec/spec_helper.rb.tt} +0 -0
- /data/lib/generators/rolemodel/testing/rspec/templates/{support/capybara_drivers.rb → spec/support/capybara_drivers.rb.tt} +0 -0
- /data/lib/generators/rolemodel/testing/rspec/templates/{support → spec/support}/helpers/action_cable_helper.rb +0 -0
- /data/lib/generators/rolemodel/testing/rspec/templates/{support → spec/support}/helpers/capybara_helper.rb +0 -0
- /data/lib/generators/rolemodel/testing/rspec/templates/{support → spec/support}/helpers/playwright_helper.rb +0 -0
- /data/lib/generators/rolemodel/testing/rspec/templates/{support → spec/support}/helpers/select_helper.rb +0 -0
- /data/lib/generators/rolemodel/testing/rspec/templates/{support → spec/support}/helpers/test_element_helper.rb +0 -0
- /data/lib/generators/rolemodel/testing/rspec/templates/{support/helpers.rb → spec/support/helpers.rb.tt} +0 -0
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'rails_helper'
|
|
4
|
-
|
|
5
|
-
RSpec.describe Prompts::Sample do
|
|
6
|
-
describe '.template' do
|
|
7
|
-
subject(:result) { described_class.template({}) }
|
|
8
|
-
|
|
9
|
-
it 'has the correct description' do
|
|
10
|
-
expect(result.messages.length).to eq(1)
|
|
11
|
-
expect(result.messages.first.role).to eq('assistant')
|
|
12
|
-
expect(result.description).to include('This is a sample prompt.')
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
end
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'rails_helper'
|
|
4
|
-
|
|
5
|
-
RSpec.describe Resources::Controller do
|
|
6
|
-
it 'returns error messages when invalid' do
|
|
7
|
-
allow_any_instance_of(described_class).to receive(:valid?).and_return(false)
|
|
8
|
-
allow_any_instance_of(described_class).to receive_message_chain(:errors, :full_messages).and_return(['Invalid params'])
|
|
9
|
-
expect do
|
|
10
|
-
described_class.call({ uri: 'docs://missing-doc' }, { current_user: nil })
|
|
11
|
-
end.to raise_error(
|
|
12
|
-
MCP::Server::RequestHandlerError,
|
|
13
|
-
/Invalid params/
|
|
14
|
-
)
|
|
15
|
-
end
|
|
16
|
-
end
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'rails_helper'
|
|
4
|
-
|
|
5
|
-
RSpec.describe Resources::DocsController do
|
|
6
|
-
describe 'class methods' do
|
|
7
|
-
it 'returns the correct values' do
|
|
8
|
-
expect(described_class.schema).to eq('docs://')
|
|
9
|
-
expect(described_class.mime_type).to eq('text/markdown')
|
|
10
|
-
end
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
describe '.resource_list' do
|
|
14
|
-
it 'registers the sample resource' do
|
|
15
|
-
expect(described_class.resource_list.map(&:uri)).to contain_exactly('docs://SAMPLE_DOC.md')
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
describe 'validations' do
|
|
20
|
-
it 'is valid for a known docs resource' do
|
|
21
|
-
controller = described_class.new('SAMPLE_DOC.md')
|
|
22
|
-
|
|
23
|
-
expect(controller).to be_valid
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
it 'is invalid for an unknown docs resource' do
|
|
27
|
-
controller = described_class.new('missing-doc')
|
|
28
|
-
|
|
29
|
-
expect(controller).not_to be_valid
|
|
30
|
-
expect(controller.errors[:file_path]).to eq(['Unknown docs resource: missing-doc'])
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
it 'is invalid when the mapped file is missing' do
|
|
34
|
-
stub_const(
|
|
35
|
-
'Resources::DocsController::FILES',
|
|
36
|
-
{ 'SAMPLE_DOC.md' => Rails.root.join('app/mcp/resources/docs/missing.md') }.freeze
|
|
37
|
-
)
|
|
38
|
-
|
|
39
|
-
controller = described_class.new('SAMPLE_DOC.md')
|
|
40
|
-
|
|
41
|
-
expect(controller).not_to be_valid
|
|
42
|
-
expect(controller.errors[:file_path]).to eq(['Missing docs file for SAMPLE_DOC.md'])
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
describe '#serve' do
|
|
47
|
-
it 'returns the markdown for the requested docs resource' do
|
|
48
|
-
controller = described_class.new('SAMPLE_DOC.md')
|
|
49
|
-
|
|
50
|
-
content = controller.serve
|
|
51
|
-
|
|
52
|
-
expect(content).to include('# Hello World')
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
end
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'rails_helper'
|
|
4
|
-
|
|
5
|
-
RSpec.describe Tools::Sample do
|
|
6
|
-
describe '.call' do
|
|
7
|
-
it 'returns a hash with expected fields' do
|
|
8
|
-
result = described_class.call(name: 'Alice', server_context: {})
|
|
9
|
-
|
|
10
|
-
expect(result).not_to be_error
|
|
11
|
-
|
|
12
|
-
expect(result.structured_content).to have_key(:sample)
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
end
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'rails_helper'
|
|
4
|
-
|
|
5
|
-
RSpec.describe 'MCPController', type: :request do
|
|
6
|
-
let(:user) { create(:user, name: 'Jane Smith', active: true, employee: true) }
|
|
7
|
-
let(:application) do
|
|
8
|
-
Doorkeeper::Application.create!(
|
|
9
|
-
name: 'MCP Test Client',
|
|
10
|
-
redirect_uri: 'https://example.com/callback',
|
|
11
|
-
scopes: 'mcp',
|
|
12
|
-
)
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
describe 'POST /mcp' do
|
|
16
|
-
let(:token) do
|
|
17
|
-
Doorkeeper::AccessToken.create!(
|
|
18
|
-
application: application,
|
|
19
|
-
resource_owner_id: user.id,
|
|
20
|
-
scopes: 'mcp',
|
|
21
|
-
expires_in: 2.hours.to_i,
|
|
22
|
-
)
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
let(:initialize_request) do
|
|
26
|
-
{
|
|
27
|
-
jsonrpc: '2.0',
|
|
28
|
-
id: 1,
|
|
29
|
-
method: 'initialize',
|
|
30
|
-
params: {
|
|
31
|
-
protocolVersion: '2025-11-25',
|
|
32
|
-
capabilities: {},
|
|
33
|
-
clientInfo: {
|
|
34
|
-
name: 'rspec',
|
|
35
|
-
version: '1.0',
|
|
36
|
-
},
|
|
37
|
-
},
|
|
38
|
-
}
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
let(:headers) do
|
|
42
|
-
{
|
|
43
|
-
'CONTENT_TYPE' => 'application/json',
|
|
44
|
-
'ACCEPT' => 'application/json, text/event-stream',
|
|
45
|
-
}
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
let(:authorized_headers) do
|
|
49
|
-
headers.merge('Authorization' => "Bearer #{token.token}")
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
it 'returns unauthorized when no bearer token is provided' do
|
|
53
|
-
post '/mcp', params: initialize_request.to_json, headers: headers
|
|
54
|
-
|
|
55
|
-
expect(response).to have_http_status(:unauthorized)
|
|
56
|
-
expect(response.headers['WWW-Authenticate']).to include('resource_metadata=')
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
it 'returns forbidden when token does not include mcp scope' do
|
|
60
|
-
token = Doorkeeper::AccessToken.create!(
|
|
61
|
-
application: application,
|
|
62
|
-
resource_owner_id: user.id,
|
|
63
|
-
scopes: 'other',
|
|
64
|
-
expires_in: 2.hours.to_i,
|
|
65
|
-
)
|
|
66
|
-
|
|
67
|
-
post '/mcp',
|
|
68
|
-
params: initialize_request.to_json,
|
|
69
|
-
headers: headers.merge('Authorization' => "Bearer #{token.token}")
|
|
70
|
-
|
|
71
|
-
expect(response).to have_http_status(:forbidden)
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
it 'returns initialize response for a valid bearer token' do
|
|
75
|
-
post '/mcp',
|
|
76
|
-
params: initialize_request.to_json,
|
|
77
|
-
headers: authorized_headers
|
|
78
|
-
|
|
79
|
-
expect(response).to have_http_status(:ok)
|
|
80
|
-
expect(response.parsed_body['result']).to be_present
|
|
81
|
-
expect(response.parsed_body['result']['capabilities']).to include('tools')
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
end
|
data/lib/generators/rolemodel/mcp/templates/spec/requests/oauth_registrations_controller_spec.rb
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'rails_helper'
|
|
4
|
-
|
|
5
|
-
RSpec.describe 'OauthRegistrationsController', type: :request do
|
|
6
|
-
describe 'POST /oauth/register' do
|
|
7
|
-
let(:params) do
|
|
8
|
-
{
|
|
9
|
-
client_name: 'GitHub Copilot',
|
|
10
|
-
redirect_uris: ['http://localhost:12345/callback'],
|
|
11
|
-
grant_types: ['authorization_code'],
|
|
12
|
-
response_types: ['code'],
|
|
13
|
-
token_endpoint_auth_method: 'none',
|
|
14
|
-
scope: 'mcp',
|
|
15
|
-
}
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
it 'creates an OAuth application and returns client_id' do
|
|
19
|
-
expect { post '/oauth/register', params: params, as: :json }
|
|
20
|
-
.to change(Doorkeeper::Application, :count).by(1)
|
|
21
|
-
|
|
22
|
-
expect(response).to have_http_status(:created)
|
|
23
|
-
body = response.parsed_body
|
|
24
|
-
expect(body['client_id']).to be_present
|
|
25
|
-
expect(body['client_name']).to eq('GitHub Copilot')
|
|
26
|
-
expect(body['redirect_uris']).to eq(['http://localhost:12345/callback'])
|
|
27
|
-
expect(body['token_endpoint_auth_method']).to eq('none')
|
|
28
|
-
expect(body).not_to have_key('client_secret')
|
|
29
|
-
|
|
30
|
-
app = Doorkeeper::Application.last
|
|
31
|
-
expect(app.name).to eq('GitHub Copilot')
|
|
32
|
-
expect(app.redirect_uri).to eq('http://localhost:12345/callback')
|
|
33
|
-
expect(app.scopes).to contain_exactly('mcp')
|
|
34
|
-
expect(app).not_to be_confidential
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
it 'returns bad_request when redirect_uris is missing' do
|
|
38
|
-
post '/oauth/register', params: { client_name: 'Test' }, as: :json
|
|
39
|
-
|
|
40
|
-
expect(response).to have_http_status(:bad_request)
|
|
41
|
-
expect(response.parsed_body['error']).to eq('invalid_client_metadata')
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
it 'creates a confidential client when token_endpoint_auth_method is not none' do
|
|
45
|
-
params[:token_endpoint_auth_method] = 'client_secret_basic'
|
|
46
|
-
post '/oauth/register', params: params, as: :json
|
|
47
|
-
|
|
48
|
-
expect(response).to have_http_status(:created)
|
|
49
|
-
body = response.parsed_body
|
|
50
|
-
expect(body['client_secret']).to be_present
|
|
51
|
-
expect(body['token_endpoint_auth_method']).to eq('client_secret_basic')
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
it 'allows loopback redirect URIs for native clients' do
|
|
55
|
-
params[:redirect_uris] = ['http://127.0.0.1:33418/']
|
|
56
|
-
post '/oauth/register', params: params, as: :json
|
|
57
|
-
|
|
58
|
-
expect(response).to have_http_status(:created)
|
|
59
|
-
expect(response.parsed_body['redirect_uris']).to eq(['http://127.0.0.1:33418/'])
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
end
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'rails_helper'
|
|
4
|
-
|
|
5
|
-
RSpec.describe 'WellKnownController', type: :request do
|
|
6
|
-
describe 'GET /.well-known/oauth-protected-resource' do
|
|
7
|
-
it 'returns the MCP resource and authorization server' do
|
|
8
|
-
get '/.well-known/oauth-protected-resource'
|
|
9
|
-
|
|
10
|
-
expect(response).to have_http_status(:ok)
|
|
11
|
-
body = response.parsed_body
|
|
12
|
-
expect(body['resource']).to end_with('/mcp')
|
|
13
|
-
expect(body['authorization_servers']).to be_an(Array)
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
describe 'GET /.well-known/oauth-authorization-server' do
|
|
18
|
-
it 'returns authorization server metadata with registration_endpoint' do
|
|
19
|
-
get '/.well-known/oauth-authorization-server'
|
|
20
|
-
|
|
21
|
-
expect(response).to have_http_status(:ok)
|
|
22
|
-
body = response.parsed_body
|
|
23
|
-
expect(body['registration_endpoint']).to end_with('/oauth/register')
|
|
24
|
-
expect(body['authorization_endpoint']).to end_with('/oauth/authorize')
|
|
25
|
-
expect(body['token_endpoint']).to end_with('/oauth/token')
|
|
26
|
-
expect(body['code_challenge_methods_supported']).to include('S256')
|
|
27
|
-
expect(body['scopes_supported']).to include('mcp')
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
end
|
/data/lib/generators/rolemodel/testing/rspec/templates/{rails_helper.rb → spec/rails_helper.rb.tt}
RENAMED
|
File without changes
|
/data/lib/generators/rolemodel/testing/rspec/templates/{spec_helper.rb → spec/spec_helper.rb.tt}
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|