your_ai_insight 1.0.11 → 1.0.12

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: c400f6bb1a051f84900f4ca7c4d229e6f7193aff9bf27b1c6e13772b36935dc6
4
- data.tar.gz: a05ff0274c36660ed5a0e0dfde6ec242e8c293384dc835fd1b02ba0c471e10bd
3
+ metadata.gz: 7d1204c7328e49de4459471b39022f9d2482ddebc0e72f26774cf889d1feb7fc
4
+ data.tar.gz: c01acdcda667e9bf44ba364d5e9c48138da79ae42375c8a327c65a17c6d1b4c6
5
5
  SHA512:
6
- metadata.gz: e0893b4723fc2827ea30eabc856f9a48820bc377a286b017be3d78e486ffa218e5930c6f4dfb1fca77fc5616e87038912bd11fee75304638c25b6ebdb9a9d879
7
- data.tar.gz: cc045b166a9f36f017d1f2a90f02412eb213c3d54ee0a739a7958e9a9dd47ec87779a25ac2362c9c460d99178a14cba294a84084efbccd1cc7cd6505f9490dd6
6
+ metadata.gz: 53ee1ee3ab937cd1ec3436f44af642a687e223b5c62ba05d7da3d43a0f8f2cc8fbba7c6e577bb9a240f31a19394b3ffa6d78880686d75f0c9d8d5f2c0adca541
7
+ data.tar.gz: 401fba06aff405ab6d07c08aa547b3514ae365fd155add6b61b535d835e22b2254210ff2706e84a8b15abff2a15868274b7035574351f0a04fc801bea8776d1d
@@ -31,24 +31,14 @@ module YourAiInsight
31
31
  PROMPT
32
32
 
33
33
  def initialize
34
- cfg = YourAiInsight.config
35
- @provider = (cfg.ai_provider || :claude).to_sym
36
- @max_tokens = cfg.max_tokens
37
-
38
- case @provider
39
- when :openrouter
40
- @api_key = cfg.openrouter_api_key ||
41
- ENV["OPENROUTER_API_KEY"] ||
42
- raise(ConfigurationError, "Set config.openrouter_api_key or ENV['OPENROUTER_API_KEY']")
43
- @model = cfg.openrouter_model
44
- @site_url = cfg.openrouter_site_url
45
- @site_name = cfg.openrouter_site_name
46
- else
47
- @api_key = cfg.anthropic_api_key ||
48
- ENV["ANTHROPIC_API_KEY"] ||
49
- raise(ConfigurationError, "Set config.anthropic_api_key or ENV['ANTHROPIC_API_KEY']")
50
- @model = cfg.claude_model
51
- end
34
+ cfg = YourAiInsight.config
35
+ @api_key = cfg.openrouter_api_key ||
36
+ ENV["OPENROUTER_API_KEY"] ||
37
+ raise(ConfigurationError, "Set config.openrouter_api_key or ENV['OPENROUTER_API_KEY']")
38
+ @model = cfg.openrouter_model
39
+ @max_tokens = cfg.max_tokens
40
+ @site_url = cfg.openrouter_site_url
41
+ @site_name = cfg.openrouter_site_name
52
42
  end
53
43
 
54
44
  # Free-form chat with optional live data context injected
@@ -69,39 +59,6 @@ module YourAiInsight
69
59
  private
70
60
 
71
61
  def call_api(messages)
72
- @provider == :openrouter ? call_openrouter(messages) : call_claude(messages)
73
- end
74
-
75
- def call_claude(messages)
76
- response = self.class.post(
77
- "https://api.anthropic.com/v1/messages",
78
- headers: {
79
- "x-api-key" => @api_key,
80
- "anthropic-version" => "2023-06-01",
81
- "content-type" => "application/json"
82
- },
83
- body: {
84
- model: @model,
85
- max_tokens: @max_tokens,
86
- system: SYSTEM_PROMPT,
87
- messages: messages
88
- }.to_json,
89
- timeout: 90
90
- )
91
-
92
- body = JSON.parse(response.body)
93
- unless response.success?
94
- raise ApiError, "Claude API error (HTTP #{response.code}): #{body.dig('error', 'message')}"
95
- end
96
-
97
- body.dig("content", 0, "text").presence ||
98
- raise(ApiError, "Empty response from Claude API")
99
-
100
- rescue HTTParty::Error, Timeout::Error => e
101
- raise ApiError, "Network error reaching Claude API: #{e.message}"
102
- end
103
-
104
- def call_openrouter(messages)
105
62
  headers = {
106
63
  "Authorization" => "Bearer #{@api_key}",
107
64
  "Content-Type" => "application/json"
@@ -109,7 +66,6 @@ module YourAiInsight
109
66
  headers["HTTP-Referer"] = @site_url if @site_url.present?
110
67
  headers["X-Title"] = @site_name if @site_name.present?
111
68
 
112
- # Prepend system prompt as a system message (OpenAI-compatible format)
113
69
  full_messages = [{ role: "system", content: SYSTEM_PROMPT }] + messages
114
70
 
115
71
  response = self.class.post(
@@ -124,18 +80,18 @@ module YourAiInsight
124
80
  )
125
81
 
126
82
  body = JSON.parse(response.body)
83
+
127
84
  unless response.success?
128
- raise ApiError, "OpenRouter API error (HTTP #{response.code}): #{body.dig('error', 'message')}"
85
+ raise ApiError, "OpenRouter error (HTTP #{response.code}): #{body.dig('error', 'message')}"
129
86
  end
130
87
 
131
88
  body.dig("choices", 0, "message", "content").presence ||
132
- raise(ApiError, "Empty response from OpenRouter API")
89
+ raise(ApiError, "Empty response from OpenRouter")
133
90
 
134
91
  rescue HTTParty::Error, Timeout::Error => e
135
- raise ApiError, "Network error reaching OpenRouter API: #{e.message}"
92
+ raise ApiError, "Network error reaching OpenRouter: #{e.message}"
136
93
  end
137
94
 
138
- # Injects a live snapshot into the chat prompt
139
95
  def context_block(ctx)
140
96
  return nil if ctx.blank?
141
97
  lines = ["## Live Facility Snapshot"]
@@ -1,22 +1,16 @@
1
1
  module YourAiInsight
2
2
  class Configuration
3
- # ── AI Provider ───────────────────────────────────────────────────────────
4
- # :claude (default) or :openrouter
5
- attr_accessor :ai_provider
6
-
7
- # ── Claude / Anthropic settings ───────────────────────────────────────────
8
- attr_accessor :anthropic_api_key
9
- attr_accessor :claude_model # default: claude-opus-4-5
10
- attr_accessor :max_tokens # default: 2048
11
-
12
- # ── OpenRouter settings ───────────────────────────────────────────────────
3
+ # ── OpenRouter (required) ──────────────────────────────────────────────────
13
4
  attr_accessor :openrouter_api_key
14
- # default: meta-llama/llama-3.3-70b-instruct:free (free, no billing needed)
15
- attr_accessor :openrouter_model
5
+ # See https://openrouter.ai/models?q=free for free models
6
+ attr_accessor :openrouter_model # default: meta-llama/llama-3.3-70b-instruct:free
16
7
  attr_accessor :openrouter_site_url # optional — sent as HTTP-Referer
17
8
  attr_accessor :openrouter_site_name # optional — sent as X-Title
18
9
 
19
- # ── Multi-tenancy: scope data to current user's locations/customers ───────
10
+ # ── Response tuning ────────────────────────────────────────────────────────
11
+ attr_accessor :max_tokens # default: 2048
12
+
13
+ # ── Multi-tenancy: scope data to current user's locations/customers ────────
20
14
  # Proc receives current_user and returns an Array of location_ids, or nil for all.
21
15
  # Example: config.location_scope = ->(user) { user.locations.pluck(:id) }
22
16
  attr_accessor :location_scope
@@ -96,16 +90,13 @@ module YourAiInsight
96
90
  attr_accessor :sub_contractors_table # "sub_contractors"
97
91
 
98
92
  def initialize
99
- @ai_provider = :claude
100
- @claude_model = "claude-opus-4-5"
101
- @max_tokens = 2048
102
- @company_name = "AllPro IFM"
103
-
104
93
  @openrouter_model = "meta-llama/llama-3.3-70b-instruct:free"
105
94
  @openrouter_site_url = nil
106
95
  @openrouter_site_name = nil
107
- @logo_url = nil
108
- @default_recipients = []
96
+ @max_tokens = 2048
97
+ @company_name = "AllPro IFM"
98
+ @logo_url = nil
99
+ @default_recipients = []
109
100
 
110
101
  # jobs
111
102
  @jobs_table = "jobs"
@@ -136,11 +127,11 @@ module YourAiInsight
136
127
  @bids_task_id_col = "task_id"
137
128
 
138
129
  # expenses
139
- @expenses_table = "expenses"
140
- @expenses_budget_col = "budget"
141
- @expenses_actual_col = "actual"
142
- @expenses_job_id_col = "job_id"
143
- @expenses_task_id_col= "task_id"
130
+ @expenses_table = "expenses"
131
+ @expenses_budget_col = "budget"
132
+ @expenses_actual_col = "actual"
133
+ @expenses_job_id_col = "job_id"
134
+ @expenses_task_id_col = "task_id"
144
135
 
145
136
  # location_budgets
146
137
  @location_budgets_table = "location_budgets"
@@ -1,3 +1,3 @@
1
1
  module YourAiInsight
2
- VERSION = "1.0.11"
2
+ VERSION = "1.0.12"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: your_ai_insight
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.11
4
+ version: 1.0.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - AllPro IFM