clankersupport 1.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: a8af4f02b44610de78162c7b0b518d39ba5dce08d4e8a7f18baac209cc57c55a
4
+ data.tar.gz: e426d8afb55f8c158cd44f929945b5239632e283b775fb2003743351c59efa9f
5
+ SHA512:
6
+ metadata.gz: 7e6f04f2ccd0a58c7a54c563f2944e1e5efefd5af47f2604316b4bbee7b71f7e35e4a60612ba23e553353bed73deea10a6d1db3c00b436785504404ef3b28342
7
+ data.tar.gz: 9b2a64564e8910a89cda36c6ea6c5954665cb4272966c61a967dd190f8538aebc3d4a22eb0dc97750e9fd4bb4a6ae4a1cbf2685df55fb18af9ddcabb9dd38910
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026-present LLMGateway, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,91 @@
1
+ # clankersupport
2
+
3
+ Embed the [Clanker Support](https://clankersupport.com) AI-powered support agent in any Ruby web app. One helper renders the widget `<script>` tag — escaped, validated, and framework-friendly — so visitors get streaming answers from your knowledge base, human escalation, and operator replies, with zero backend work in your app.
4
+
5
+ ```sh
6
+ bundle add clankersupport
7
+ ```
8
+
9
+ ## Quick start
10
+
11
+ Grab your project's public key from the dashboard (Project → Embed), then render the tag into your layout:
12
+
13
+ ```ruby
14
+ require "clankersupport"
15
+
16
+ tag = ClankerSupport.script_tag("pk_your_project_key")
17
+ # <script src="https://api.clankersupport.com/widget.js" data-project="pk_your_project_key" data-api="https://api.clankersupport.com" async></script>
18
+ ```
19
+
20
+ The return value is a plain `String`. Plain ERB (outside Rails) doesn't autoescape, so `<%= tag %>` just works — no `raw` or `.html_safe` needed. Rails ERB *does* autoescape; use the built-in helper below, which handles that for you.
21
+
22
+ > The public key is safe to expose — it's the same key the plain `<script>` embed uses.
23
+
24
+ ### Rails
25
+
26
+ The gem ships a Railtie that registers a view helper in ActionView. Set `CLANKER_PROJECT_KEY` in your environment and drop the helper into your layout:
27
+
28
+ ```erb
29
+ <%# app/views/layouts/application.html.erb %>
30
+ <body>
31
+ <%= yield %>
32
+ <%= clanker_support_tag %>
33
+ </body>
34
+ ```
35
+
36
+ Or pass the key and options explicitly:
37
+
38
+ ```erb
39
+ <%= clanker_support_tag "pk_your_project_key", theme: "auto", brand_color: "#4f46e5" %>
40
+ ```
41
+
42
+ `clanker_support_tag` returns an `html_safe` string, so Rails renders it as markup.
43
+
44
+ ### Sinatra
45
+
46
+ ```ruby
47
+ require "sinatra"
48
+ require "clankersupport"
49
+
50
+ get "/" do
51
+ erb :index, locals: { clanker_support: ClankerSupport.script_tag("pk_your_project_key") }
52
+ end
53
+ ```
54
+
55
+ ```erb
56
+ <%# views/index.erb %>
57
+ <body>
58
+ <h1>Hello</h1>
59
+ <%= clanker_support %>
60
+ </body>
61
+ ```
62
+
63
+ (If you enable Sinatra's `:escape_html`, output it with `<%== clanker_support %>` instead.)
64
+
65
+ ## Options
66
+
67
+ | Option | Default | Description |
68
+ | ---------------------- | ------------------------------ | ------------------------------------------------------------------ |
69
+ | `project_key` | required | The project's public widget key (dashboard → Project → Embed). |
70
+ | `api_url:` | `https://api.clankersupport.com` | API origin — point at your own deployment when self-hosting. |
71
+ | `brand_color:` | widget default | Launcher/header accent color, e.g. `"#4f46e5"`. |
72
+ | `mode:` | `"bubble"` | `"bubble"` (floating launcher) or `"inline"` (mounts in place). |
73
+ | `theme:` | `"light"` | `"light"`, `"dark"`, or `"auto"` (follow the OS). |
74
+ | `escalation_threshold:`| project default | Visitor messages before "Talk to a human" appears (positive Integer). |
75
+
76
+ Invalid values (empty key, unknown mode/theme, non-positive or non-Integer threshold) raise `ArgumentError` at render time, so misconfiguration fails in development instead of silently shipping a broken widget.
77
+
78
+ ## Self-hosting
79
+
80
+ Clanker Support is open source ([theopenco/llmchat](https://github.com/theopenco/llmchat)). Point `api_url:` at your own deployment; the tag's `src` and `data-api` both follow it.
81
+
82
+ ## Publishing (maintainers)
83
+
84
+ ```sh
85
+ gem build clankersupport.gemspec
86
+ gem push clankersupport-1.0.0.gem
87
+ ```
88
+
89
+ ## License
90
+
91
+ MIT
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Rails integration. This file is only required from lib/clankersupport.rb
4
+ # when Rails::Railtie is defined, and every constant reference below is
5
+ # guarded, so the gem loads fine without Rails.
6
+
7
+ module ClankerSupport
8
+ # View helper mixed into ActionView by the Railtie.
9
+ #
10
+ # <%= clanker_support_tag %> <%# uses ENV["CLANKER_PROJECT_KEY"] %>
11
+ # <%= clanker_support_tag "pk_abc123", theme: "auto" %>
12
+ module Helper
13
+ # Render the widget script tag, marked +html_safe+ so Rails' ERB
14
+ # autoescaping emits it as markup. The project key defaults to
15
+ # +ENV["CLANKER_PROJECT_KEY"]+.
16
+ def clanker_support_tag(project_key = nil, **options)
17
+ key = project_key || ENV["CLANKER_PROJECT_KEY"]
18
+ ClankerSupport.script_tag(key, **options).html_safe
19
+ end
20
+ end
21
+
22
+ if defined?(Rails::Railtie)
23
+ class Railtie < Rails::Railtie
24
+ initializer "clankersupport.view_helper" do
25
+ ActiveSupport.on_load(:action_view) do
26
+ include ClankerSupport::Helper
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ClankerSupport
4
+ VERSION = "1.0.0"
5
+ end
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Render the Clanker Support widget embed for Ruby web apps.
4
+ #
5
+ # The widget itself is client-side JavaScript served by the Clanker Support
6
+ # API (+/widget.js+); a backend's job is only to emit the script tag with the
7
+ # right +data-*+ attributes. {ClankerSupport.script_tag} does that with
8
+ # HTML-attribute escaping, mirroring the snippet the dashboard's Embed page
9
+ # generates.
10
+ #
11
+ # require "clankersupport"
12
+ #
13
+ # tag = ClankerSupport.script_tag("pk_your_project_key")
14
+ #
15
+ # The return value is a plain +String+. In Rails, use the +clanker_support_tag+
16
+ # view helper (see ClankerSupport::Helper), which marks the tag +html_safe+.
17
+
18
+ require "cgi"
19
+
20
+ require_relative "clankersupport/version"
21
+
22
+ module ClankerSupport
23
+ DEFAULT_API_URL = "https://api.clankersupport.com"
24
+
25
+ # +data-mode+ values the widget understands. +bubble+ (the default) is the
26
+ # floating launcher; +inline+ mounts the panel in place.
27
+ MODES = ["bubble", "inline"].freeze
28
+
29
+ # +data-theme+ values the widget understands. Absent means +light+.
30
+ THEMES = ["light", "dark", "auto"].freeze
31
+
32
+ # Build the Clanker Support widget +<script>+ tag.
33
+ #
34
+ # @param project_key [String] the project's public widget key (dashboard →
35
+ # Project → Embed). Safe to expose — it's the same key the script embed uses.
36
+ # @param api_url [String] API origin. Point at your own deployment when
37
+ # self-hosting; trailing slashes are stripped.
38
+ # @param brand_color [String, nil] accent color for the launcher/header,
39
+ # e.g. "#4f46e5". Omitted → the widget default.
40
+ # @param mode [String, nil] "bubble" (floating launcher, default) or "inline".
41
+ # @param theme [String, nil] "light" (default), "dark", or "auto" (follow OS).
42
+ # @param escalation_threshold [Integer, nil] visitor messages before
43
+ # "Talk to a human" appears. Omitted → the project's configured default.
44
+ # @return [String]
45
+ # @raise [ArgumentError] on an empty project key, an unknown mode/theme, or
46
+ # a non-positive escalation threshold — misconfiguration should fail at
47
+ # render time in development, not silently ship a broken widget.
48
+ def self.script_tag(
49
+ project_key,
50
+ api_url: DEFAULT_API_URL,
51
+ brand_color: nil,
52
+ mode: nil,
53
+ theme: nil,
54
+ escalation_threshold: nil
55
+ )
56
+ key = project_key.to_s
57
+ raise ArgumentError, "project_key is required" if key.strip.empty?
58
+ if !mode.nil? && !MODES.include?(mode)
59
+ raise ArgumentError, "mode must be one of #{MODES.inspect}, got #{mode.inspect}"
60
+ end
61
+ if !theme.nil? && !THEMES.include?(theme)
62
+ raise ArgumentError, "theme must be one of #{THEMES.inspect}, got #{theme.inspect}"
63
+ end
64
+ if !escalation_threshold.nil?
65
+ unless escalation_threshold.is_a?(Integer) && escalation_threshold >= 1
66
+ raise ArgumentError,
67
+ "escalation_threshold must be a positive Integer, got #{escalation_threshold.inspect}"
68
+ end
69
+ end
70
+
71
+ base = api_url.to_s.sub(%r{/+\z}, "")
72
+ parts = [
73
+ %(<script src="#{escape_attr(base)}/widget.js"),
74
+ %(data-project="#{escape_attr(key)}"),
75
+ %(data-api="#{escape_attr(base)}"),
76
+ ]
77
+ parts << %(data-brand="#{escape_attr(brand_color)}") unless brand_color.nil?
78
+ parts << %(data-mode="#{escape_attr(mode)}") unless mode.nil?
79
+ parts << %(data-theme="#{escape_attr(theme)}") unless theme.nil?
80
+ unless escalation_threshold.nil?
81
+ parts << %(data-escalation-threshold="#{escalation_threshold}")
82
+ end
83
+ parts << "async></script>"
84
+ parts.join(" ")
85
+ end
86
+
87
+ # HTML-attribute escaping, mirroring the dashboard snippet generator.
88
+ def self.escape_attr(value)
89
+ CGI.escapeHTML(value.to_s)
90
+ end
91
+ private_class_method :escape_attr
92
+ end
93
+
94
+ require_relative "clankersupport/railtie" if defined?(Rails::Railtie)
metadata ADDED
@@ -0,0 +1,53 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: clankersupport
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - The Open Company
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2026-07-18 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Renders the Clanker Support widget <script> tag — escaped, validated,
14
+ and framework-friendly — so visitors get streaming answers from your knowledge base,
15
+ human escalation, and operator replies, with zero backend work in your app. Includes
16
+ a Rails view helper (clanker_support_tag). Clanker Support is open source and self-hostable.
17
+ email:
18
+ - hello@clankersupport.com
19
+ executables: []
20
+ extensions: []
21
+ extra_rdoc_files: []
22
+ files:
23
+ - LICENSE
24
+ - README.md
25
+ - lib/clankersupport.rb
26
+ - lib/clankersupport/railtie.rb
27
+ - lib/clankersupport/version.rb
28
+ homepage: https://clankersupport.com
29
+ licenses:
30
+ - MIT
31
+ metadata:
32
+ source_code_uri: https://github.com/theopenco/llmchat
33
+ documentation_uri: https://docs.clankersupport.com
34
+ post_install_message:
35
+ rdoc_options: []
36
+ require_paths:
37
+ - lib
38
+ required_ruby_version: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: '3.0'
43
+ required_rubygems_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ requirements: []
49
+ rubygems_version: 3.5.22
50
+ signing_key:
51
+ specification_version: 4
52
+ summary: Embed the Clanker Support AI-powered support agent in any Ruby web app.
53
+ test_files: []