layered-assistant-rails 0.9.1 → 0.10.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c87ef1f390a6a4c102682cb4befebc1950f8566552f5213075a9d9f2ac4c7b49
4
- data.tar.gz: 0d289b5e1f05d1f696ae8e37053ec75b51b3bf3c280091ceb33d836c0f06678b
3
+ metadata.gz: 801e95c2e899ba36085052a8971f405f2a7d5b12f3129193cf738978d0653c2c
4
+ data.tar.gz: b9fefa9325aaf76a334d7f958a37cdf119f73f59bddf08cfbd77b20a62ffddcd
5
5
  SHA512:
6
- metadata.gz: 68cb5c184761c2ef7de4bf43cc6b84a32dfbe2b8cfd434cb3562c72265e7d9640bd3ad41f965a1c4cc04fec13c02b314cacf5780e1d779f2d08fec87aefa260a
7
- data.tar.gz: 8f9cc996f9de499fa6d7c9afaf8f607eed0ea9c06c0f78f3e2ff8aeac67580a8a897002c0b5c350c668d76920311c9c2cbae10c2d11b452b99cd89a3c9c70533
6
+ metadata.gz: cff5a257d775b91f808b1b92cf52a5c9f25be2fe5885edb8557b074c6994f1d664645807c783464552f0b409e7115f65e598fde7618b90f5f34b29c8b8d48dc7
7
+ data.tar.gz: 5e7bf84dafd4756af9bfa208a9711a16411a7543e7bc3b657e56f591643d2d9e748bb32b80cf8bbc3fc469a719ec79382b95847f30dd1ef13926bb8b71c672fd
@@ -27,12 +27,14 @@ The install generator:
27
27
 
28
28
  1. Verifies `layered-ui-rails` is installed - invokes its installer if not.
29
29
  2. Adds `import "layered_assistant"` to `app/javascript/application.js` (after the `layered_ui` import).
30
- 3. Creates `config/initializers/layered_assistant.rb` with example `authorize` and `scope` blocks.
30
+ 3. Creates `config/initializers/layered_assistant.rb` with example `authorize` blocks, notes on record ownership with an optional `owner` block, and tool configuration examples.
31
31
  4. Mounts the engine at `/layered/assistant` in `config/routes.rb`.
32
32
  5. Copies migrations into the host app via the `layered:assistant:migrations` generator.
33
33
 
34
34
  After installation, configure the initializer (see below) - **routes return 403 until an `authorize` block is set**. Then visit `/layered/assistant` to set up providers, models, personas, skills and assistants.
35
35
 
36
+ **Streaming:** replies are generated in an Active Job and broadcast as Turbo Streams over Action Cable. The queue adapter must run jobs in the background (not `:inline`), and if jobs run in a separate worker process (Solid Queue's `bin/jobs`, Sidekiq), `config/cable.yml` must use `solid_cable` or `redis` rather than `async`. The Rails defaults (`:async` jobs, `async` cable) work in a single development process.
37
+
36
38
  ## Authorization
37
39
 
38
40
  All non-public engine routes are gated by an `authorize` block. The block runs in controller context, so you have access to `current_user`, `request`, `redirect_to`, `head`, `main_app`, etc.
@@ -229,6 +231,7 @@ The engine renders inside `layered-ui-rails` layouts and uses only `l-ui-` class
229
231
  - **Provider creation fails with encryption error** - run `bin/rails db:encryption:init` and add the keys to credentials, or set `Layered::Assistant.skip_db_encryption = true` for dev/test.
230
232
  - **Panel body never loads** - `turbo-rails` must be installed and `layered-ui-rails` must be mounted in the layout. Check `import "@hotwired/turbo-rails"` is present.
231
233
  - **`layered_assistant` JS controllers missing** - ensure `import "layered_assistant"` is in `app/javascript/application.js` (added by the install generator, after the `layered_ui` import).
234
+ - **Replies don't stream, or only appear after a refresh** - the job's broadcasts aren't reaching the browser. Avoid the `:inline` queue adapter, and if jobs run in a separate worker, switch `config/cable.yml` from `async` to `solid_cable` or `redis`.
232
235
  - **No records visible, or `MissingOwnerError` on create** - `current_owner` is nil. Check the authorize block only admits signed-in users, and that any `Layered::Assistant.owner` block returns a record.
233
236
 
234
237
  ## Further reference
data/README.md CHANGED
@@ -76,6 +76,22 @@ bin/rails generate layered:assistant:migrations
76
76
  bin/rails db:migrate
77
77
  ```
78
78
 
79
+ ### Background jobs and Action Cable
80
+
81
+ Assistant replies are generated in an Active Job and streamed to the browser
82
+ as Turbo Streams over Action Cable. Streaming needs two things from the host
83
+ app:
84
+
85
+ - **A queue adapter that runs jobs in the background.** With `:inline`, the job
86
+ runs inside the request that sent the message, so the whole reply arrives at
87
+ once instead of streaming. The Rails default (`:async`) and Solid Queue both
88
+ work.
89
+ - **A cable adapter the job process can reach.** The `async` cable adapter only
90
+ works within one process. It is fine when jobs also run in the web process
91
+ (the `:async` queue adapter), but if jobs run in a separate worker (Solid
92
+ Queue's `bin/jobs`, Sidekiq, etc.), their broadcasts never reach the browser.
93
+ Use `solid_cable` or `redis` in `config/cable.yml` instead.
94
+
79
95
  ## Authorization
80
96
 
81
97
  All non-public engine routes are **blocked by default** (403 Forbidden) until you configure an `authorize` block. The install generator creates a starter initialiser at `config/initializers/layered_assistant.rb` - uncomment one of the examples to get started.
@@ -3,8 +3,10 @@ module Layered
3
3
  class Conversation < ApplicationRecord
4
4
  include Ownable
5
5
 
6
- # UID
7
- has_secure_token :uid
6
+ # UID: the public identifier, in the form conversation_<uuid>
7
+ UID_FORMAT = /\Aconversation_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\z/
8
+
9
+ attribute :uid, :string, default: -> { "conversation_#{SecureRandom.uuid}" }
8
10
 
9
11
  # Associations
10
12
  belongs_to :assistant, counter_cache: true
@@ -22,6 +24,7 @@ module Layered
22
24
 
23
25
  # Validations
24
26
  validates :name, presence: true
27
+ validates :uid, format: { with: UID_FORMAT }, uniqueness: true
25
28
 
26
29
  # Scopes
27
30
  scope :by_name, -> { order(name: :asc, created_at: :desc) }
@@ -0,0 +1,14 @@
1
+ class PrefixLayeredAssistantConversationUids < ActiveRecord::Migration[8.0]
2
+ # Conversation uids become conversation_<uuid>. Existing tokens are
3
+ # replaced, so old conversation URLs stop resolving; the integer primary
4
+ # key is untouched.
5
+ def up
6
+ select_values("SELECT id FROM layered_assistant_conversations").each do |id|
7
+ execute "UPDATE layered_assistant_conversations SET uid = #{quote("conversation_#{SecureRandom.uuid}")} WHERE id = #{id.to_i}"
8
+ end
9
+ end
10
+
11
+ def down
12
+ # Irreversible data change; the prefixed uids remain valid.
13
+ end
14
+ end
@@ -1,5 +1,5 @@
1
1
  module Layered
2
2
  module Assistant
3
- VERSION = "0.9.1"
3
+ VERSION = "0.10.0"
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.9.1
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - layered.ai
@@ -427,6 +427,7 @@ files:
427
427
  - db/migrate/20260901000000_create_layered_assistant_assistant_tools.rb
428
428
  - db/migrate/20260901000001_add_user_to_layered_assistant_conversations.rb
429
429
  - db/migrate/20260919000000_add_tool_status_to_layered_assistant_messages.rb
430
+ - db/migrate/20261031000000_prefix_layered_assistant_conversation_uids.rb
430
431
  - lib/generators/layered/assistant/install_agent_skill_generator.rb
431
432
  - lib/generators/layered/assistant/install_generator.rb
432
433
  - lib/generators/layered/assistant/migrations_generator.rb