layered-assistant-rails 0.3.2 → 0.4.1

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 (35) hide show
  1. checksums.yaml +4 -4
  2. data/AGENTS.md +3 -4
  3. data/README.md +5 -7
  4. data/app/services/layered/assistant/clients/openai.rb +1 -1
  5. data/app/services/layered/assistant/models/create_service.rb +12 -1
  6. data/app/views/layered/assistant/assistants/edit.html.erb +4 -4
  7. data/app/views/layered/assistant/assistants/index.html.erb +2 -3
  8. data/app/views/layered/assistant/assistants/new.html.erb +4 -4
  9. data/app/views/layered/assistant/conversations/edit.html.erb +4 -4
  10. data/app/views/layered/assistant/conversations/index.html.erb +6 -9
  11. data/app/views/layered/assistant/conversations/new.html.erb +4 -4
  12. data/app/views/layered/assistant/conversations/show.html.erb +0 -1
  13. data/app/views/layered/assistant/messages/index.html.erb +4 -4
  14. data/app/views/layered/assistant/models/edit.html.erb +7 -4
  15. data/app/views/layered/assistant/models/index.html.erb +6 -7
  16. data/app/views/layered/assistant/models/new.html.erb +7 -4
  17. data/app/views/layered/assistant/panel/conversations/show.html.erb +0 -1
  18. data/app/views/layered/assistant/personas/edit.html.erb +5 -1
  19. data/app/views/layered/assistant/personas/index.html.erb +2 -3
  20. data/app/views/layered/assistant/personas/new.html.erb +5 -1
  21. data/app/views/layered/assistant/providers/edit.html.erb +4 -4
  22. data/app/views/layered/assistant/providers/index.html.erb +2 -3
  23. data/app/views/layered/assistant/providers/new.html.erb +4 -4
  24. data/app/views/layered/assistant/public/assistants/index.html.erb +1 -1
  25. data/app/views/layered/assistant/public/conversations/show.html.erb +0 -1
  26. data/app/views/layered/assistant/public/panel/conversations/show.html.erb +0 -1
  27. data/app/views/layered/assistant/setup/index.html.erb +2 -1
  28. data/app/views/layered/assistant/skills/edit.html.erb +5 -1
  29. data/app/views/layered/assistant/skills/index.html.erb +2 -3
  30. data/app/views/layered/assistant/skills/new.html.erb +5 -1
  31. data/data/models.json +21 -18
  32. data/lib/generators/layered/assistant/install_generator.rb +0 -32
  33. data/lib/layered/assistant/version.rb +1 -1
  34. metadata +5 -7
  35. data/app/assets/tailwind/layered/assistant/styles.css +0 -13
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d8d828826c0b73a9efaa2324f15d1e7d684c2b3c00c760421d6d18bbf3f88d39
4
- data.tar.gz: 11f5f52acb971db3b8bee92f6c5739e8cb89c7f5cbbd9411db8570fd53c2be87
3
+ metadata.gz: '07081dd0ae8adfb43bf4bbfcdb5ae6925faa1d31a196762bec9d52efd5a28d11'
4
+ data.tar.gz: 305c23332a9a6e41aa5b8e3814565a4be3c0ea9c25a44aa4103c35b2d8e79d42
5
5
  SHA512:
6
- metadata.gz: d0e8c773d9b788562089ca773c615c1871e7440f453f18f8822074b83ea69db544cd747e8c540a21c10d53fb7babe3c37fe70245ce6bfc31a64fe496dff5a2ae
7
- data.tar.gz: 3d3ee90a358372e72cdadccf200fff09e56adadfefc01c8a010991febc54281466b447d8730b6e00969a29225a56e38e5349187cd23b119274463e610f792fa1
6
+ metadata.gz: b148483c047879c248db3d9275c4f8033ca294cc0d5b575b3ac2960c56b78a854ca444894b4d4e59b03279e4fee10712656fc758ef29fadc66f85cfd58254311
7
+ data.tar.gz: eae3bd16f81cb0542c7e32e7ce332f08027fb24bf5c7241258f5f6c7034e7ef60886dd16871f5de15986c371a9b38d949ad23fc3709de2397df71a1987c6efc8
data/AGENTS.md CHANGED
@@ -4,7 +4,7 @@ This file provides guidance to AI agents when working with code in this reposito
4
4
 
5
5
  ## Project Overview
6
6
 
7
- **layered-assistant-rails** is a Rails 8+ engine gem (`Layered::Assistant`) providing AI assistant UI components. It uses `isolate_namespace Layered::Assistant` and distributes assets (Tailwind CSS + importmap JS) to host applications via a generator.
7
+ **layered-assistant-rails** is a Rails 8+ engine gem (`Layered::Assistant`) providing AI assistant UI components. It uses `isolate_namespace Layered::Assistant` and distributes JS (importmap) to host applications via a generator.
8
8
 
9
9
  Requires Rails >= 8.0.0, Ruby >= 3.2.0. Depends on sibling gem `layered-ui-rails` (path dependency at `../layered-ui-rails`).
10
10
 
@@ -18,12 +18,11 @@ Requires Rails >= 8.0.0, Ruby >= 3.2.0. Depends on sibling gem `layered-ui-rails
18
18
 
19
19
  ### Asset Distribution
20
20
 
21
- CSS and JS are authored in the engine and delivered to host apps:
21
+ JS is authored in the engine and delivered to host apps:
22
22
 
23
- - **CSS**: `app/assets/tailwind/layered/assistant/styles.css` — copied to host app by the install generator
24
23
  - **JS**: `app/javascript/layered_assistant/index.js` — pinned via `config/importmap.rb`, made available through engine initializer
25
24
 
26
- The install generator (`lib/generators/layered/assistant/install_generator.rb`) verifies `layered-ui-rails` is installed first, then copies CSS and injects import lines into `application.css` and `application.js`.
25
+ The install generator (`lib/generators/layered/assistant/install_generator.rb`) verifies `layered-ui-rails` is installed first, then injects the JS import line into `application.js`.
27
26
 
28
27
  ### Test Harness
29
28
 
data/README.md CHANGED
@@ -33,7 +33,7 @@ bundle install
33
33
 
34
34
  ### Install generator
35
35
 
36
- Run the install generator to copy CSS and register imports:
36
+ Run the install generator to register imports and mount the engine:
37
37
 
38
38
  ```bash
39
39
  bin/rails generate layered:assistant:install
@@ -43,8 +43,6 @@ This will:
43
43
  - Copy `layered_ui.css` to `app/assets/tailwind/`
44
44
  - Add `@import "./layered_ui";` to your `application.css`
45
45
  - Add `import "layered_ui"` to your `application.js`
46
- - Copy `layered_assistant.css` to `app/assets/tailwind/layered_assistant.css`
47
- - Add `@import "./layered_assistant";` to your `app/assets/tailwind/application.css` (after the layered-ui import)
48
46
  - Add `import "layered_assistant"` to your `app/javascript/application.js` (after the layered-ui import)
49
47
  - Mount the engine at `/layered/assistant` in your `config/routes.rb`
50
48
  - Copy engine migrations into your application
@@ -208,6 +206,10 @@ Run the gem tests from the root directory:
208
206
  bundle exec rake test
209
207
  ```
210
208
 
209
+ ## Contributing
210
+
211
+ This project is still in its early days. We welcome issues, feedback, and ideas - they genuinely help shape the direction of the project. That said, we're holding off on accepting pull requests for now to stay focused on getting the foundations right. Thank you for your patience and interest. See [CLA.md](CLA.md) for the full policy.
212
+
211
213
  ## License
212
214
 
213
215
  Released under the [Apache 2.0 License](LICENSE).
@@ -217,7 +219,3 @@ Copyright 2026 LAYERED AI LIMITED (UK company number: 17056830). See [NOTICE](NO
217
219
  ## Trademarks
218
220
 
219
221
  The source code is fully open, but the layered.ai name, logo, and brand assets are trademarks of LAYERED AI LIMITED. The Apache 2.0 license does not grant rights to use the layered.ai branding. Forks and redistributions must use a distinct name. See [TRADEMARK.md](TRADEMARK.md) for the full policy.
220
-
221
- ## Contributing
222
-
223
- - [CLA.md](CLA.md) - contributor license agreement
@@ -12,7 +12,7 @@ module Layered
12
12
  }
13
13
  if @provider.url.present?
14
14
  client_options[:uri_base] = @provider.url.sub(/\/\z/, "")
15
- client_options[:api_version] = "" # Gemini and other OpenAI-compatible APIs use their own path
15
+ client_options[:api_version] = "" # Gemini and other OpenAI-compatible APIs use their own path
16
16
  end
17
17
 
18
18
  ::OpenAI::Client.new(**client_options) do |f|
@@ -6,13 +6,14 @@ module Layered
6
6
  module Models
7
7
  class CreateService
8
8
  MODELS_URL = "https://raw.githubusercontent.com/layered-ai-public/layered-assistant-rails/main/data/models.json".freeze
9
+ LOCAL_MODELS_PATH = Layered::Assistant::Engine.root.join("data", "models.json").freeze
9
10
 
10
11
  def initialize(provider)
11
12
  @provider = provider
12
13
  end
13
14
 
14
15
  def call
15
- models_data = fetch_models
16
+ models_data = Rails.env.development? ? load_local_models : fetch_models
16
17
  return if models_data.nil?
17
18
 
18
19
  entries = models_data[@provider.name]
@@ -30,6 +31,16 @@ module Layered
30
31
 
31
32
  private
32
33
 
34
+ def load_local_models
35
+ unless File.exist?(LOCAL_MODELS_PATH)
36
+ Rails.logger.info "[layered-ui-assistant] Local model catalogue not found at #{LOCAL_MODELS_PATH} - skipping model sync"
37
+ return nil
38
+ end
39
+
40
+ Rails.logger.info "[layered-ui-assistant] Loading model catalogue from local file (development)"
41
+ JSON.parse(File.read(LOCAL_MODELS_PATH))
42
+ end
43
+
33
44
  def fetch_models
34
45
  uri = URI(MODELS_URL)
35
46
  response = Net::HTTP.get_response(uri)
@@ -1,6 +1,6 @@
1
- <div class="l-ui-container--spread">
2
- <h1>Edit assistant</h1>
3
- <%= link_to "Back", layered_assistant.assistants_path, class: "l-ui-button--outline" %>
4
- </div>
1
+ <%= l_ui_title_bar(
2
+ title: "Edit assistant",
3
+ breadcrumbs: [["Assistants", layered_assistant.assistants_path]]
4
+ ) %>
5
5
 
6
6
  <%= render "form", assistant: @assistant, url: layered_assistant.assistant_path(@assistant) %>
@@ -1,7 +1,6 @@
1
- <div class="l-ui-container--spread">
2
- <h1>Assistants</h1>
1
+ <%= l_ui_title_bar(title: "Assistants") do %>
3
2
  <%= link_to "New", layered_assistant.new_assistant_path, class: "l-ui-button--primary" %>
4
- </div>
3
+ <% end %>
5
4
 
6
5
  <div class="l-ui-container--table l-ui-utility--mt-lg">
7
6
  <table class="l-ui-table">
@@ -1,6 +1,6 @@
1
- <div class="l-ui-container--spread">
2
- <h1>New assistant</h1>
3
- <%= link_to "Back", layered_assistant.assistants_path, class: "l-ui-button--outline" %>
4
- </div>
1
+ <%= l_ui_title_bar(
2
+ title: "New assistant",
3
+ breadcrumbs: [["Assistants", layered_assistant.assistants_path]]
4
+ ) %>
5
5
 
6
6
  <%= render "form", assistant: @assistant, url: layered_assistant.assistants_path %>
@@ -1,6 +1,6 @@
1
- <div class="l-ui-container--spread">
2
- <h1>Edit Conversation</h1>
3
- <%= link_to "Back", layered_assistant.conversations_path, class: "l-ui-button--outline" %>
4
- </div>
1
+ <%= l_ui_title_bar(
2
+ title: "Edit conversation",
3
+ breadcrumbs: [["Conversations", layered_assistant.conversations_path]]
4
+ ) %>
5
5
 
6
6
  <%= render "form", conversation: @conversation, url: layered_assistant.conversation_path(@conversation) %>
@@ -1,12 +1,9 @@
1
- <div class="l-ui-container--spread">
2
- <h1><%= @assistant ? "Conversations - #{@assistant.name}" : "Conversations" %></h1>
3
- <div class="l-ui-container--spread">
4
- <% if @assistant %>
5
- <%= link_to "Back", layered_assistant.assistants_path, class: "l-ui-button--outline" %>
6
- <% end %>
7
- <%= link_to "New", layered_assistant.new_conversation_path(conversation: @assistant ? { assistant_id: @assistant.id } : {}), class: "l-ui-button--primary" %>
8
- </div>
9
- </div>
1
+ <%= l_ui_title_bar(
2
+ title: @assistant ? "Conversations - #{@assistant.name}" : "Conversations",
3
+ breadcrumbs: @assistant ? [["Assistants", layered_assistant.assistants_path]] : []
4
+ ) do %>
5
+ <%= link_to "New", layered_assistant.new_conversation_path(conversation: @assistant ? { assistant_id: @assistant.id } : {}), class: "l-ui-button--primary" %>
6
+ <% end %>
10
7
 
11
8
  <div class="l-ui-container--table l-ui-utility--mt-lg">
12
9
  <table class="l-ui-table">
@@ -1,6 +1,6 @@
1
- <div class="l-ui-container--spread">
2
- <h1>New Conversation</h1>
3
- <%= link_to "Back", layered_assistant.conversations_path, class: "l-ui-button--outline" %>
4
- </div>
1
+ <%= l_ui_title_bar(
2
+ title: "New conversation",
3
+ breadcrumbs: [["Conversations", layered_assistant.conversations_path]]
4
+ ) %>
5
5
 
6
6
  <%= render "form", conversation: @conversation, url: layered_assistant.conversations_path %>
@@ -16,7 +16,6 @@
16
16
  data-action="click->messages#jumpToBottom"
17
17
  aria-label="Scroll to bottom"
18
18
  type="button">
19
- <%= image_tag "layered_ui/icon_chevron_down.svg", class: "l-ui-icon--sm l-ui-icon--dark-invert", alt: "" %>
20
19
  </button>
21
20
  </div>
22
21
 
@@ -1,7 +1,7 @@
1
- <div class="l-ui-container--spread">
2
- <h1>Messages</h1>
3
- <%= link_to "Back", layered_assistant.conversations_path, class: "l-ui-button--outline" %>
4
- </div>
1
+ <%= l_ui_title_bar(
2
+ title: "Messages",
3
+ breadcrumbs: [["Conversations", layered_assistant.conversations_path]]
4
+ ) %>
5
5
 
6
6
  <div class="l-ui-container--table l-ui-utility--mt-lg">
7
7
  <table class="l-ui-table">
@@ -1,6 +1,9 @@
1
- <div class="l-ui-container--spread">
2
- <h1>Edit Model</h1>
3
- <%= link_to "Back", layered_assistant.provider_models_path(@provider), class: "l-ui-button--outline" %>
4
- </div>
1
+ <%= l_ui_title_bar(
2
+ title: "Edit model",
3
+ breadcrumbs: [
4
+ ["Providers", layered_assistant.providers_path],
5
+ ["Models", layered_assistant.provider_models_path(@provider)]
6
+ ]
7
+ ) %>
5
8
 
6
9
  <%= render "form", model: @model, url: layered_assistant.provider_model_path(@provider, @model) %>
@@ -1,10 +1,9 @@
1
- <div class="l-ui-container--spread">
2
- <h1>Models</h1>
3
- <div class="l-ui-container--spread">
4
- <%= link_to "Back", layered_assistant.providers_path, class: "l-ui-button--outline" %>
5
- <%= link_to "New", layered_assistant.new_provider_model_path(@provider), class: "l-ui-button--primary" %>
6
- </div>
7
- </div>
1
+ <%= l_ui_title_bar(
2
+ title: "Models",
3
+ breadcrumbs: [["Providers", layered_assistant.providers_path]]
4
+ ) do %>
5
+ <%= link_to "New", layered_assistant.new_provider_model_path(@provider), class: "l-ui-button--primary" %>
6
+ <% end %>
8
7
 
9
8
  <div class="l-ui-container--table l-ui-utility--mt-lg">
10
9
  <table class="l-ui-table">
@@ -1,6 +1,9 @@
1
- <div class="l-ui-container--spread">
2
- <h1>New Model</h1>
3
- <%= link_to "Back", layered_assistant.provider_models_path(@provider), class: "l-ui-button--outline" %>
4
- </div>
1
+ <%= l_ui_title_bar(
2
+ title: "New model",
3
+ breadcrumbs: [
4
+ ["Providers", layered_assistant.providers_path],
5
+ ["Models", layered_assistant.provider_models_path(@provider)]
6
+ ]
7
+ ) %>
5
8
 
6
9
  <%= render "form", model: @model, url: layered_assistant.provider_models_path(@provider) %>
@@ -14,7 +14,6 @@
14
14
  data-action="click->messages#jumpToBottom"
15
15
  aria-label="Scroll to bottom"
16
16
  type="button">
17
- <%= image_tag "layered_ui/icon_chevron_down.svg", class: "l-ui-icon--sm l-ui-icon--dark-invert", alt: "" %>
18
17
  </button>
19
18
  </div>
20
19
 
@@ -1,2 +1,6 @@
1
- <h1>Edit persona</h1>
1
+ <%= l_ui_title_bar(
2
+ title: "Edit persona",
3
+ breadcrumbs: [["Personas", layered_assistant.personas_path]]
4
+ ) %>
5
+
2
6
  <%= render "form", persona: @persona, url: layered_assistant.persona_path(@persona) %>
@@ -1,7 +1,6 @@
1
- <div class="l-ui-container--spread">
2
- <h1>Personas</h1>
1
+ <%= l_ui_title_bar(title: "Personas") do %>
3
2
  <%= link_to "New", layered_assistant.new_persona_path, class: "l-ui-button--primary" %>
4
- </div>
3
+ <% end %>
5
4
 
6
5
  <div class="l-ui-container--table l-ui-utility--mt-lg">
7
6
  <table class="l-ui-table">
@@ -1,2 +1,6 @@
1
- <h1>New persona</h1>
1
+ <%= l_ui_title_bar(
2
+ title: "New persona",
3
+ breadcrumbs: [["Personas", layered_assistant.personas_path]]
4
+ ) %>
5
+
2
6
  <%= render "form", persona: @persona, url: layered_assistant.personas_path %>
@@ -1,6 +1,6 @@
1
- <div class="l-ui-container--spread">
2
- <h1>Edit Provider</h1>
3
- <%= link_to "Back", layered_assistant.providers_path, class: "l-ui-button--outline" %>
4
- </div>
1
+ <%= l_ui_title_bar(
2
+ title: "Edit provider",
3
+ breadcrumbs: [["Providers", layered_assistant.providers_path]]
4
+ ) %>
5
5
 
6
6
  <%= render "form", provider: @provider, url: layered_assistant.provider_path(@provider) %>
@@ -1,7 +1,6 @@
1
- <div class="l-ui-container--spread">
2
- <h1>Providers</h1>
1
+ <%= l_ui_title_bar(title: "Providers") do %>
3
2
  <%= link_to "New", layered_assistant.new_provider_path, class: "l-ui-button--primary" %>
4
- </div>
3
+ <% end %>
5
4
 
6
5
  <div class="l-ui-container--table l-ui-utility--mt-lg">
7
6
  <table class="l-ui-table">
@@ -1,6 +1,6 @@
1
- <div class="l-ui-container--spread">
2
- <h1>New Provider</h1>
3
- <%= link_to "Back", layered_assistant.providers_path, class: "l-ui-button--outline" %>
4
- </div>
1
+ <%= l_ui_title_bar(
2
+ title: "New provider",
3
+ breadcrumbs: [["Providers", layered_assistant.providers_path]]
4
+ ) %>
5
5
 
6
6
  <%= render "form", provider: @provider, url: layered_assistant.providers_path %>
@@ -1,4 +1,4 @@
1
- <h1>Assistants</h1>
1
+ <%= l_ui_title_bar(title: "Assistants") %>
2
2
 
3
3
  <% if @assistants.any? %>
4
4
  <div class="l-ui-container--table l-ui-utility--mt-lg">
@@ -24,7 +24,6 @@
24
24
  data-action="click->messages#jumpToBottom"
25
25
  aria-label="Scroll to bottom"
26
26
  type="button">
27
- <%= image_tag "layered_ui/icon_chevron_down.svg", class: "l-ui-icon--sm l-ui-icon--dark-invert", alt: "" %>
28
27
  </button>
29
28
  </div>
30
29
 
@@ -14,7 +14,6 @@
14
14
  data-action="click->messages#jumpToBottom"
15
15
  aria-label="Scroll to bottom"
16
16
  type="button">
17
- <%= image_tag "layered_ui/icon_chevron_down.svg", class: "l-ui-icon--sm l-ui-icon--dark-invert", alt: "" %>
18
17
  </button>
19
18
  </div>
20
19
 
@@ -1,2 +1,3 @@
1
- <h1>Setup</h1>
1
+ <%= l_ui_title_bar(title: "Setup") %>
2
+
2
3
  <%= render "layered/assistant/setup/setup" %>
@@ -1,2 +1,6 @@
1
- <h1>Edit skill</h1>
1
+ <%= l_ui_title_bar(
2
+ title: "Edit skill",
3
+ breadcrumbs: [["Skills", layered_assistant.skills_path]]
4
+ ) %>
5
+
2
6
  <%= render "form", skill: @skill, url: layered_assistant.skill_path(@skill) %>
@@ -1,7 +1,6 @@
1
- <div class="l-ui-container--spread">
2
- <h1>Skills</h1>
1
+ <%= l_ui_title_bar(title: "Skills") do %>
3
2
  <%= link_to "New", layered_assistant.new_skill_path, class: "l-ui-button--primary" %>
4
- </div>
3
+ <% end %>
5
4
 
6
5
  <div class="l-ui-container--table l-ui-utility--mt-lg">
7
6
  <table class="l-ui-table">
@@ -1,2 +1,6 @@
1
- <h1>New skill</h1>
1
+ <%= l_ui_title_bar(
2
+ title: "New skill",
3
+ breadcrumbs: [["Skills", layered_assistant.skills_path]]
4
+ ) %>
5
+
2
6
  <%= render "form", skill: @skill, url: layered_assistant.skills_path %>
data/data/models.json CHANGED
@@ -1,42 +1,45 @@
1
1
  {
2
2
  "Anthropic": [
3
- { "name": "Claude Opus 4.6", "identifier": "claude-opus-4-6" },
3
+ { "name": "Claude Opus 4.7", "identifier": "claude-opus-4-7" },
4
4
  { "name": "Claude Sonnet 4.6", "identifier": "claude-sonnet-4-6" },
5
5
  { "name": "Claude Haiku 4.5", "identifier": "claude-haiku-4-5" }
6
6
  ],
7
7
  "OpenAI": [
8
+ { "name": "GPT-5.5", "identifier": "gpt-5.5" },
9
+ { "name": "GPT-5.5 Pro", "identifier": "gpt-5.5-pro" },
8
10
  { "name": "GPT-5.4", "identifier": "gpt-5.4" },
9
- { "name": "GPT-5 Mini", "identifier": "gpt-5-mini" }
11
+ { "name": "GPT-5.4 Mini", "identifier": "gpt-5.4-mini" },
12
+ { "name": "GPT-5.4 Nano", "identifier": "gpt-5.4-nano" }
10
13
  ],
11
14
  "Gemini": [
12
15
  { "name": "Gemini 3.1 Pro Preview", "identifier": "gemini-3.1-pro-preview" },
13
- { "name": "Gemini 2.5 Flash Lite", "identifier": "gemini-2.5-flash-lite" },
16
+ { "name": "Gemini 3 Flash Preview", "identifier": "gemini-3-flash-preview" },
17
+ { "name": "Gemini 3.1 Flash-Lite Preview", "identifier": "gemini-3.1-flash-lite-preview" },
18
+ { "name": "Gemini 2.5 Pro", "identifier": "gemini-2.5-pro" },
14
19
  { "name": "Gemini 2.5 Flash", "identifier": "gemini-2.5-flash" },
15
- { "name": "Gemini 2.5 Pro", "identifier": "gemini-2.5-pro" }
20
+ { "name": "Gemini 2.5 Flash Lite", "identifier": "gemini-2.5-flash-lite" }
16
21
  ],
17
22
  "OpenRouter": [
18
- { "name": "MiniMax M2.5", "identifier": "minimax/minimax-m2.5" },
19
- { "name": "DeepSeek V3.2", "identifier": "deepseek/deepseek-v3.2" },
23
+ { "name": "Grok 4.1 Fast", "identifier": "x-ai/grok-4.1-fast" },
20
24
  { "name": "Grok 4", "identifier": "x-ai/grok-4" },
21
- { "name": "Grok 4 (Fast)", "identifier": "x-ai/grok-4-fast" },
22
- { "name": "Grok 3", "identifier": "x-ai/grok-3" },
23
- { "name": "Llama 4 Maverick", "identifier": "meta-llama/llama-4-maverick-17b-128e-instruct" },
24
- { "name": "Llama 4 Scout", "identifier": "meta-llama/llama-4-scout-17b-16e-instruct" }
25
+ { "name": "DeepSeek V3.2", "identifier": "deepseek/deepseek-v3.2" },
26
+ { "name": "Kimi K2.6", "identifier": "moonshotai/kimi-k2.6" },
27
+ { "name": "MiniMax M2.7", "identifier": "minimax/minimax-m2.7" },
28
+ { "name": "MiniMax M2.5", "identifier": "minimax/minimax-m2.5" },
29
+ { "name": "MiMo V2 Pro", "identifier": "xiaomi/mimo-v2-pro" }
25
30
  ],
26
31
  "Groq": [
27
32
  { "name": "Compound", "identifier": "groq/compound" },
28
33
  { "name": "Compound Mini", "identifier": "groq/compound-mini" },
29
34
  { "name": "GPT-OSS 120B", "identifier": "openai/gpt-oss-120b" },
30
- { "name": "Llama 4 Maverick", "identifier": "meta-llama/llama-4-maverick-17b-128e-instruct" },
31
- { "name": "Llama 4 Scout", "identifier": "meta-llama/llama-4-scout-17b-16e-instruct" },
35
+ { "name": "GPT-OSS 20B", "identifier": "openai/gpt-oss-20b" },
32
36
  { "name": "Llama 3.3 70B Versatile", "identifier": "llama-3.3-70b-versatile" },
33
- { "name": "Llama 3.1 8B Instant", "identifier": "llama-3.1-8b-instant" },
34
- { "name": "Qwen 3 32B", "identifier": "qwen/qwen3-32b" },
35
- { "name": "Kimi K2.5", "identifier": "moonshotai/kimi-k2-instruct-0905" }
37
+ { "name": "Llama 3.1 8B Instant", "identifier": "llama-3.1-8b-instant" }
36
38
  ],
37
39
  "Mistral": [
38
- { "name": "Mistral Large 2512", "identifier": "mistral-large-2512" },
39
- { "name": "Mistral Medium 2508", "identifier": "mistral-medium-2508" },
40
- { "name": "Mistral Small 2506", "identifier": "mistral-small-2506" }
40
+ { "name": "Mistral Large 3", "identifier": "mistral-large-2512" },
41
+ { "name": "Mistral Medium 3.1", "identifier": "mistral-medium-2508" },
42
+ { "name": "Mistral Small 4", "identifier": "mistral-small-2603" },
43
+ { "name": "Magistral Medium 1.2", "identifier": "magistral-medium-2509" }
41
44
  ]
42
45
  }
@@ -21,38 +21,6 @@ module Layered
21
21
  end
22
22
  end
23
23
 
24
- def copy_css
25
- source_path = File.join(self.class.source_root, "app/assets/tailwind/layered/assistant/styles.css")
26
- source_content = File.read(source_path)
27
-
28
- header = <<~CSS
29
- /*
30
- * layered-assistant-rails v#{Layered::Assistant::VERSION}
31
- *
32
- * This file was automatically generated by the layered:assistant:install generator.
33
- * Do not modify directly. To update, re-run: bin/rails generate layered:assistant:install
34
- */
35
-
36
- CSS
37
-
38
- create_file "app/assets/tailwind/layered_assistant.css", header + source_content, force: true
39
- end
40
-
41
- def add_css_import
42
- application_css = "app/assets/tailwind/application.css"
43
-
44
- return unless File.exist?(application_css)
45
-
46
- content = File.read(application_css)
47
- import_line = '@import "./layered_assistant";'
48
-
49
- return if content.match?(%r{@import\s+['"]\.?/?layered_assistant['"]})
50
-
51
- # Insert after the layered_ui import (which must already be present)
52
- inject_into_file application_css, "\n#{import_line}", after: %r{@import\s+['"]\.?/?layered_ui['"];?}
53
- say "Added import to #{application_css}", :green
54
- end
55
-
56
24
  def add_js_import
57
25
  application_js = "app/javascript/application.js"
58
26
 
@@ -1,5 +1,5 @@
1
1
  module Layered
2
2
  module Assistant
3
- VERSION = "0.3.2"
3
+ VERSION = "0.4.1"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: layered-assistant-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - layered.ai
@@ -113,14 +113,14 @@ dependencies:
113
113
  requirements:
114
114
  - - "~>"
115
115
  - !ruby/object:Gem::Version
116
- version: 0.2.1
116
+ version: '0.9'
117
117
  type: :runtime
118
118
  prerelease: false
119
119
  version_requirements: !ruby/object:Gem::Requirement
120
120
  requirements:
121
121
  - - "~>"
122
122
  - !ruby/object:Gem::Version
123
- version: 0.2.1
123
+ version: '0.9'
124
124
  - !ruby/object:Gem::Dependency
125
125
  name: propshaft
126
126
  requirement: !ruby/object:Gem::Requirement
@@ -302,7 +302,6 @@ files:
302
302
  - NOTICE
303
303
  - README.md
304
304
  - Rakefile
305
- - app/assets/tailwind/layered/assistant/styles.css
306
305
  - app/controllers/concerns/layered/assistant/message_creation.rb
307
306
  - app/controllers/concerns/layered/assistant/public/session_conversations.rb
308
307
  - app/controllers/concerns/layered/assistant/stoppable_response.rb
@@ -440,10 +439,9 @@ post_install_message: |
440
439
  bin/rails generate layered:assistant:install
441
440
 
442
441
  This command will:
443
- • Copy the layered assistant CSS to your host app at app/assets/tailwind/layered_assistant.css
444
- • This approach ensures the CSS is processed with your host app's Tailwind configuration
445
- • Add an import statement to your app/assets/tailwind/application.css
446
442
  • Add `import "layered_assistant"` to your app/javascript/application.js (just after `import "layered_ui"`, which must already be present)
443
+ • Mount the engine at /layered/assistant in your config/routes.rb
444
+ • Create a starter initialiser at config/initializers/layered_assistant.rb
447
445
  • Copy engine migrations to your app's db/migrate/
448
446
 
449
447
  If these imports already exist, they will not be duplicated.
@@ -1,13 +0,0 @@
1
- /*
2
- * CSS Formatting Convention
3
- *
4
- * All @apply directives use multi-line formatting with logical grouping:
5
- * 1. Layout (flex, block, fixed, relative, etc.)
6
- * 2. Spacing (padding, margin, gap, width, height)
7
- * 3. Typography (text, font)
8
- * 4. Colors (bg, text, border)
9
- * 5. Effects (hover, transitions, shadows, etc.)
10
- *
11
- * Single-utility classes may remain on one line for brevity.
12
- * This structure improves readability, maintainability, and makes diffs easier to review.
13
- */