llama_bot_rails 0.1.3 → 0.1.5

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: 34248e0bbf8e8047cad5836f03e4f37a4b0cc84a5f152a9fcc486f7c32de50ed
4
- data.tar.gz: 0e4a0a1f0d0939d042e21cd1e2745daeae241e33877febe7f45740679b94ff50
3
+ metadata.gz: 2e2df41e770f0dbcc740af59357462c33b0bcb87d3dd0394e343729d4d1a4a45
4
+ data.tar.gz: b7032c39fe95fc8e5dc5ab892c8abd28366c77db7c4826a29f6096511124e9ca
5
5
  SHA512:
6
- metadata.gz: d5cee45f49487fcbf2203d326b62431c4c7fb540004e0004a7929b7ec6fe2487124ed146237333a10b5f75db0f2508d1f1b7e91c7fe41afc7eb67f02a6395231
7
- data.tar.gz: a67f3f5278245e15a0b868a22b27bc56e317cdd3f2aa456ef9c60100bb4547abfabd50e6a37a84cc7a7cdf97e37e45a06ce17a9b1e4dd3cc9c55125834262d40
6
+ metadata.gz: 5b4ad9c9ce5bbb3bbb3d645c3db6e87cff9fc398c0ce412c75d7687c79b7532c751518add6f583566ebb20423e465a1b6f81611448ddf08de4a97d2f5704fc79
7
+ data.tar.gz: 172d5d32f0b0742ca51f6c47468019c628d7043e20b212324fc4f8da987a3aabd0e06dd5375375bf645cb62377f7ca2b12b227f640ff54b494dc52c050a18484
data/README.md CHANGED
@@ -27,7 +27,6 @@ Chat with a powerful agent that has access to your models, your application cont
27
27
 
28
28
  ## 🚀 **Quickstart** →
29
29
 
30
-
31
30
  ```bash
32
31
 
33
32
  # 1. Add the gem
@@ -38,14 +37,29 @@ rails generate llama_bot_rails:install
38
37
 
39
38
  # 3. Clone & run the LangGraph backend
40
39
  git clone https://github.com/kodykendall/llamabot
40
+
41
41
  cd llamabot
42
- OPENAI_API_KEY=your_key
43
- cd backend && uvicorn app:app --reload
44
42
 
45
- # Start your Rails server
43
+ # 4. Set up your environment
44
+ python3 -m venv venv
45
+
46
+ source venv/bin/activate
47
+
48
+ pip install -r requirements.txt
49
+
50
+ echo "OPENAI_API_KEY=your_openai_api_key_here" > .env
51
+
52
+ # 5. Run the agent
53
+ cd backend
54
+ uvicorn app:app --reload
55
+
56
+ # 6. Confirm our agent is running properly. You should see: Hello, World! 🦙💬
57
+ curl http://localhost:8000/hello
58
+
59
+ # 7. Start your Rails server.
46
60
  rails server
47
61
 
48
- # Visit the chat interface and start chatting.
62
+ # 8. Visit the chat interface and start chatting.
49
63
  open http://localhost:3000/llama_bot/agent/chat
50
64
 
51
65
  ```
@@ -405,10 +405,121 @@
405
405
  font-size: 1em;
406
406
  color: var(--text-secondary);
407
407
  }
408
+
409
+ /* Clean loading indicator - just animated text */
410
+ .loading-indicator {
411
+ display: none;
412
+ align-items: center;
413
+ padding: 16px 20px;
414
+ color: var(--text-secondary);
415
+ font-size: 14px;
416
+ margin-bottom: 10px;
417
+ background: rgba(255, 255, 255, 0.02);
418
+ border-radius: 8px;
419
+ border: 1px solid rgba(255, 255, 255, 0.08);
420
+ }
421
+
422
+ .loading-indicator.visible {
423
+ display: flex;
424
+ }
425
+
426
+ .loading-text {
427
+ font-style: italic;
428
+ }
429
+
430
+ .loading-dots::after {
431
+ content: '';
432
+ animation: dots 1.5s steps(4, end) infinite;
433
+ }
434
+
435
+ @keyframes dots {
436
+ 0%, 20% { content: ''; }
437
+ 40% { content: '.'; }
438
+ 60% { content: '..'; }
439
+ 80%, 100% { content: '...'; }
440
+ }
441
+
442
+ /* Suggested Prompts Styling - Always visible above input */
443
+ .suggested-prompts {
444
+ margin-bottom: 16px;
445
+ padding: 0 4px;
446
+ }
447
+
448
+ .prompts-label {
449
+ font-size: 13px;
450
+ color: var(--text-secondary);
451
+ margin-bottom: 8px;
452
+ font-weight: 500;
453
+ letter-spacing: 0.3px;
454
+ }
455
+
456
+ .prompts-container {
457
+ display: flex;
458
+ flex-direction: column;
459
+ gap: 6px;
460
+ }
461
+
462
+ .prompts-row {
463
+ display: flex;
464
+ gap: 8px;
465
+ overflow-x: auto;
466
+ padding: 2px;
467
+ scrollbar-width: none; /* Firefox */
468
+ -ms-overflow-style: none; /* IE and Edge */
469
+ }
470
+
471
+ .prompts-row::-webkit-scrollbar {
472
+ display: none; /* Chrome, Safari, Opera */
473
+ }
474
+
475
+ .prompt-button {
476
+ background: rgba(255, 255, 255, 0.03);
477
+ border: 1px solid rgba(255, 255, 255, 0.08);
478
+ border-radius: 6px;
479
+ padding: 8px 12px;
480
+ color: var(--text-secondary);
481
+ font-size: 13px;
482
+ cursor: pointer;
483
+ transition: all 0.2s ease;
484
+ font-family: inherit;
485
+ white-space: nowrap;
486
+ flex-shrink: 0;
487
+ min-width: fit-content;
488
+ }
489
+
490
+ .prompt-button:hover {
491
+ background: rgba(33, 150, 243, 0.08);
492
+ border-color: rgba(33, 150, 243, 0.2);
493
+ color: var(--text-primary);
494
+ transform: translateY(-1px);
495
+ }
496
+
497
+ .prompt-button:active {
498
+ transform: translateY(0);
499
+ }
500
+
501
+ @media (max-width: 768px) {
502
+ .prompts-grid {
503
+ grid-template-columns: 1fr;
504
+ }
505
+
506
+ .prompt-button {
507
+ font-size: 13px;
508
+ padding: 10px 14px;
509
+ }
510
+ }
408
511
  </style>
409
- <%= javascript_importmap_tags %>
512
+
513
+ <% if defined?(javascript_importmap_tags) %> <!-- Rails 7+ -->
514
+ <%= javascript_importmap_tags %>
515
+ <% else %> <!-- Rails 6 -->
516
+ <%= javascript_include_tag "application" %>
517
+ <% end %>
518
+
410
519
  <%= javascript_include_tag "llama_bot_rails/application" %>
411
- <%= action_cable_meta_tag %>
520
+ <% if defined?(action_cable_meta_tag) %>
521
+ <%= action_cable_meta_tag %>
522
+ <% end %>
412
523
  <!-- Add Snarkdown CDN -->
413
524
  <script src="https://unpkg.com/snarkdown/dist/snarkdown.umd.js"></script>
414
525
  </head>
@@ -431,7 +542,7 @@
431
542
  </button>
432
543
  <div class="logo-container">
433
544
  <img src="https://service-jobs-images.s3.us-east-2.amazonaws.com/7rl98t1weu387r43il97h6ipk1l7" alt="LlamaBot Logo" class="logo">
434
- <div id="connectionStatusIconForLlamaBot" class="connection-status status-green"></div>
545
+ <div id="connectionStatusIconForLlamaBot" class="connection-status status-yellow"></div>
435
546
  </div>
436
547
  <h1>LlamaBot Chat</h1>
437
548
  </div>
@@ -445,6 +556,30 @@
445
556
  <div class="chat-messages" id="chat-messages">
446
557
  <!-- Messages will be added here dynamically -->
447
558
  </div>
559
+
560
+ <!-- Simple loading indicator with just animated text -->
561
+ <div class="loading-indicator" id="loading-indicator">
562
+ <span class="loading-text">LlamaBot is thinking<span class="loading-dots"></span></span>
563
+ </div>
564
+
565
+ <!-- Suggested Prompts - Always visible above input -->
566
+ <div class="suggested-prompts" id="suggested-prompts">
567
+ <div class="prompts-label">Quick actions:</div>
568
+ <div class="prompts-container">
569
+ <div class="prompts-row">
570
+ <button class="prompt-button" onclick="selectPrompt(this)">What models are defined in this app?</button>
571
+ <button class="prompt-button" onclick="selectPrompt(this)">What routes exist?</button>
572
+ <button class="prompt-button" onclick="selectPrompt(this)">How many users are in the database?</button>
573
+ <button class="prompt-button" onclick="selectPrompt(this)">Show me the schema for the User model</button>
574
+ </div>
575
+ <div class="prompts-row">
576
+ <button class="prompt-button" onclick="selectPrompt(this)">Send a text with Twilio</button>
577
+ <button class="prompt-button" onclick="selectPrompt(this)">Create a BlogPost with title and body fields</button>
578
+ <button class="prompt-button" onclick="selectPrompt(this)">Generate a scaffolded Page model</button>
579
+ </div>
580
+ </div>
581
+ </div>
582
+
448
583
  <div class="input-container">
449
584
  <input type="text" id="message-input" placeholder="Type your message...">
450
585
  <button onclick="sendMessage()">Send</button>
@@ -478,7 +613,9 @@
478
613
  }
479
614
 
480
615
  waitForCableConnection((consumer) => {
481
- subscription = consumer.subscriptions.create('LlamaBotRails::ChatChannel', {
616
+ const sessionId = crypto.randomUUID();
617
+
618
+ subscription = consumer.subscriptions.create({channel: 'LlamaBotRails::ChatChannel', session_id: sessionId}, {
482
619
  connected() {
483
620
  console.log('Connected to chat channel');
484
621
  lastPongTime = Date.now();
@@ -692,11 +829,6 @@
692
829
 
693
830
  // Show welcome message
694
831
  showWelcomeMessage();
695
-
696
- // Clear active thread selection
697
- document.querySelectorAll('.thread-item').forEach(item => {
698
- item.classList.remove('active');
699
- });
700
832
  }
701
833
 
702
834
  function showWelcomeMessage() {
@@ -710,6 +842,33 @@
710
842
  messagesDiv.appendChild(welcomeDiv);
711
843
  }
712
844
 
845
+ function showLoadingIndicator() {
846
+ const loadingIndicator = document.getElementById('loading-indicator');
847
+ loadingIndicator.classList.add('visible');
848
+ }
849
+
850
+ function hideLoadingIndicator() {
851
+ const loadingIndicator = document.getElementById('loading-indicator');
852
+ loadingIndicator.classList.remove('visible');
853
+ }
854
+
855
+ function selectPrompt(buttonElement) {
856
+ const promptText = buttonElement.textContent;
857
+ const messageInput = document.getElementById('message-input');
858
+
859
+ // Populate the input field
860
+ messageInput.value = promptText;
861
+
862
+ // Focus the input field for better UX
863
+ messageInput.focus();
864
+
865
+ // Add a subtle animation to show the prompt was selected
866
+ buttonElement.style.transform = 'scale(0.98)';
867
+ setTimeout(() => {
868
+ buttonElement.style.transform = '';
869
+ }, 150);
870
+ }
871
+
713
872
  function sendMessage() {
714
873
  const input = document.getElementById('message-input');
715
874
  const message = input.value.trim();
@@ -731,6 +890,9 @@
731
890
  addMessage(message, 'human');
732
891
  input.value = '';
733
892
 
893
+ // Show loading indicator
894
+ showLoadingIndicator();
895
+
734
896
  // Generate timestamp-based thread ID if we don't have one
735
897
  let threadId = currentThreadId;
736
898
  if (!threadId || threadId === 'global_thread_id') {
@@ -764,6 +926,11 @@
764
926
  function addMessage(text, sender, base_message=null) {
765
927
  console.log('🧠 Message from LlamaBot:', text, sender, base_message);
766
928
 
929
+ // Hide loading indicator when we receive an AI response
930
+ if (sender === 'ai') {
931
+ hideLoadingIndicator();
932
+ }
933
+
767
934
  const messagesDiv = document.getElementById('chat-messages');
768
935
  const messageDiv = document.createElement('div');
769
936
  messageDiv.className = `message ${sender}-message`;
@@ -3,6 +3,11 @@ module LlamaBotRails
3
3
  module Generators
4
4
  class InstallGenerator < Rails::Generators::Base
5
5
  source_root File.expand_path("templates", __dir__)
6
+
7
+ def create_config_file
8
+ empty_directory "config/llama_bot"
9
+ copy_file "agent_prompt.txt", "config/llama_bot/agent_prompt.txt"
10
+ end
6
11
 
7
12
  def mount_engine
8
13
  say <<~MSG, :yellow
@@ -32,6 +37,7 @@ module LlamaBotRails
32
37
  create_file "config/initializers/llama_bot_rails.rb", <<~RUBY
33
38
  Rails.application.configure do
34
39
  config.llama_bot_rails.websocket_url = ENV.fetch("LLAMABOT_WEBSOCKET_URL", "ws://localhost:8000/ws")
40
+ config.llama_bot_rails.llamabot_api_url = ENV.fetch("LLAMABOT_API_URL", "http://localhost:8000")
35
41
  config.llama_bot_rails.enable_console_tool = !Rails.env.production?
36
42
  end
37
43
  RUBY
@@ -0,0 +1 @@
1
+ You are LlamaBot, a helpful assistant inside a Ruby on Rails app.
@@ -10,6 +10,7 @@ module LlamaBotRails
10
10
  user_message: @params[:message], # Rails param from JS/chat UI
11
11
  thread_id: @context[:thread_id],
12
12
  api_token: @context[:api_token],
13
+ agent_prompt: LlamaBotRails.agent_prompt_text,
13
14
  agent_name: "llamabot" #Very important. This routes to the appropriate LangGraph agent as defined in langgraph.json
14
15
  }
15
16
  end
@@ -14,7 +14,7 @@ module LlamaBotRails
14
14
  config.llama_bot_rails.websocket_url = 'ws://localhost:8000/ws' # <-- default
15
15
  config.llama_bot_rails.llamabot_api_url = "http://localhost:8000"
16
16
  config.llama_bot_rails.enable_console_tool = true
17
-
17
+
18
18
  initializer "llama_bot_rails.assets.precompile" do |app|
19
19
  app.config.assets.precompile += %w( llama_bot_rails/application.js )
20
20
  end
@@ -1,3 +1,3 @@
1
1
  module LlamaBotRails
2
- VERSION = "0.1.3"
2
+ VERSION = "0.1.5"
3
3
  end
@@ -6,5 +6,22 @@ module LlamaBotRails
6
6
  def config
7
7
  Rails.application.config.llama_bot_rails
8
8
  end
9
+
10
+ def agent_prompt_path
11
+ Rails.root.join("config", "llama_bot", "agent_prompt.txt")
12
+ end
13
+
14
+ def agent_prompt_text
15
+ if File.exist?(agent_prompt_path)
16
+ File.read(agent_prompt_path)
17
+ else
18
+ "You are LlamaBot, a helpful assistant." #Fallback default.
19
+ end
20
+ end
21
+
22
+ def add_instruction_to_agent_prompt!(new_instruction)
23
+ FileUtils.mkdir_p(agent_prompt_path.dirname)
24
+ File.write(agent_prompt_path, "\n#{new_instruction}", mode: 'a')
25
+ end
9
26
  end
10
27
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: llama_bot_rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kody Kendall
@@ -15,7 +15,7 @@ dependencies:
15
15
  requirements:
16
16
  - - ">="
17
17
  - !ruby/object:Gem::Version
18
- version: '7.0'
18
+ version: '6.0'
19
19
  - - "<"
20
20
  - !ruby/object:Gem::Version
21
21
  version: '9.0'
@@ -25,7 +25,7 @@ dependencies:
25
25
  requirements:
26
26
  - - ">="
27
27
  - !ruby/object:Gem::Version
28
- version: '7.0'
28
+ version: '6.0'
29
29
  - - "<"
30
30
  - !ruby/object:Gem::Version
31
31
  version: '9.0'
@@ -35,7 +35,7 @@ dependencies:
35
35
  requirements:
36
36
  - - ">="
37
37
  - !ruby/object:Gem::Version
38
- version: '7.0'
38
+ version: '6.0'
39
39
  - - "<"
40
40
  - !ruby/object:Gem::Version
41
41
  version: '9.0'
@@ -45,7 +45,7 @@ dependencies:
45
45
  requirements:
46
46
  - - ">="
47
47
  - !ruby/object:Gem::Version
48
- version: '7.0'
48
+ version: '6.0'
49
49
  - - "<"
50
50
  - !ruby/object:Gem::Version
51
51
  version: '9.0'
@@ -122,6 +122,7 @@ files:
122
122
  - config/initializers/llama_bot_rails.rb
123
123
  - config/routes.rb
124
124
  - lib/generators/llama_bot_rails/install/install_generator.rb
125
+ - lib/generators/llama_bot_rails/install/templates/agent_prompt.txt
125
126
  - lib/llama_bot_rails.rb
126
127
  - lib/llama_bot_rails/agent_state_builder.rb
127
128
  - lib/llama_bot_rails/engine.rb