From 49f1ac7b9df335b0ee955d729de323212ce578e7 Mon Sep 17 00:00:00 2001 From: Ajay Krishnan Date: Wed, 20 May 2026 05:09:48 -0700 Subject: [PATCH] Scaffold opencode-rails gem structure - opencode-rails.gemspec (Ruby >= 3.2, MIT) - runtime: opencode-ruby ~> 0.0.1.alpha1 - runtime: activerecord/activestorage/activesupport >= 7.1, < 9.0 Per-sublibrary deps (not the rails umbrella) so host apps don't pull in ActionMailer/ActionCable/ActionView just to use this gem. - lib/opencode-rails.rb (umbrella; requires opencode-ruby then leaves then session/turn) - lib/opencode/rails/version.rb (Opencode::Rails::VERSION = 0.0.1.alpha1) - Gemfile (sibling-path pull of opencode-ruby for local dev) - Rakefile, .gitignore Source files will be ported in the next commit. --- .gitignore | 8 ++++++ Gemfile | 11 ++++++++ Rakefile | 12 +++++++++ lib/opencode-rails.rb | 37 +++++++++++++++++++++++++++ lib/opencode/rails/version.rb | 7 +++++ opencode-rails.gemspec | 48 +++++++++++++++++++++++++++++++++++ 6 files changed, 123 insertions(+) create mode 100644 .gitignore create mode 100644 Gemfile create mode 100644 Rakefile create mode 100644 lib/opencode-rails.rb create mode 100644 lib/opencode/rails/version.rb create mode 100644 opencode-rails.gemspec diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..290f8a8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +*.gem +.bundle/ +Gemfile.lock +pkg/ +tmp/ +.ruby-version +.byebug_history +coverage/ diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..0560e3a --- /dev/null +++ b/Gemfile @@ -0,0 +1,11 @@ +source "https://rubygems.org" + +# opencode-ruby is the underlying wire client. During alpha both gems +# evolve in lockstep; the gemspec pins a release version, but for local +# dev we pull from the sibling working copy so changes in opencode-ruby +# are picked up without a release cycle. +if File.exist?(File.expand_path("../opencode-ruby", __dir__)) + gem "opencode-ruby", path: File.expand_path("../opencode-ruby", __dir__) +end + +gemspec diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..8ca97e1 --- /dev/null +++ b/Rakefile @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +require "bundler/gem_tasks" +require "rake/testtask" + +Rake::TestTask.new(:test) do |t| + t.libs << "test" + t.libs << "lib" + t.test_files = FileList["test/**/*_test.rb"] +end + +task default: :test diff --git a/lib/opencode-rails.rb b/lib/opencode-rails.rb new file mode 100644 index 0000000..e36db1b --- /dev/null +++ b/lib/opencode-rails.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +# opencode-rails — Production Rails integration for OpenCode. +# +# Loads the wire-level primitives from opencode-ruby, then layers on the +# AR-coupled session/turn/artifact stack. Caller-facing namespace stays +# flat at `Opencode::*` (no `Opencode::Rails::Session` etc.) so this gem +# can drop into any app that already uses opencode-ruby with zero +# rename work. + +require "opencode-ruby" + +require "active_support/core_ext/object/blank" +require "active_support/core_ext/object/try" +require "active_support/core_ext/hash/keys" +require "active_support/core_ext/string/inflections" + +require_relative "opencode/rails/version" +require_relative "opencode/error_reporter" + +# Tier 4 leaves (no deps on other rails-gem files) +require_relative "opencode/sandbox_file" +require_relative "opencode/sandbox" +require_relative "opencode/transform" +require_relative "opencode/impostor" +require_relative "opencode/artifact" +require_relative "opencode/message_artifacts" +require_relative "opencode/uploaded_files_prompt" +require_relative "opencode/tool_display" +require_relative "opencode/exchange" + +# Tier 3 (depend on the leaves above) +require_relative "opencode/session" +require_relative "opencode/turn" + +module Opencode +end diff --git a/lib/opencode/rails/version.rb b/lib/opencode/rails/version.rb new file mode 100644 index 0000000..3942eb8 --- /dev/null +++ b/lib/opencode/rails/version.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +module Opencode + module Rails + VERSION = "0.0.1.alpha1" + end +end diff --git a/opencode-rails.gemspec b/opencode-rails.gemspec new file mode 100644 index 0000000..e2a97d9 --- /dev/null +++ b/opencode-rails.gemspec @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +require_relative "lib/opencode/rails/version" + +Gem::Specification.new do |spec| + spec.name = "opencode-rails" + spec.version = Opencode::Rails::VERSION + spec.authors = ["Ajay Krishnan"] + spec.email = ["ajay@krishnan.ca"] + + spec.summary = "Production-grade Rails integration for OpenCode." + spec.description = <<~DESC + Rails companion to opencode-ruby. ActiveRecord-aware session lifecycle + (idempotent ensure!/recreate!/abort! with row-level locks), a Turn + orchestrator that drives the Reply state machine + handles + session-not-found recovery, an artifact pipeline backed by + ActiveStorage, sandbox seeding, and tool-display value objects for + Turbo Stream broadcasts. Drop into any Rails 7.1+ app that wants + production-grade OpenCode streaming without rolling your own + boilerplate. + DESC + spec.homepage = "https://gitea.krishnan.ca/ajaynomics/opencode-rails" + spec.license = "MIT" + spec.required_ruby_version = ">= 3.2.0" + + spec.metadata["source_code_uri"] = spec.homepage + spec.metadata["changelog_uri"] = "#{spec.homepage}/src/branch/main/CHANGELOG.md" + spec.metadata["bug_tracker_uri"] = "#{spec.homepage}/issues" + + spec.files = Dir.glob("lib/**/*.rb") + + %w[README.md LICENSE CHANGELOG.md opencode-rails.gemspec] + spec.require_paths = ["lib"] + + # The opencode-ruby gem provides the wire-level Client + Reply primitives + # this gem builds on. Versions are kept in lockstep during the alpha + # phase; will relax to a looser pessimistic pin once both gems stabilize. + spec.add_runtime_dependency "opencode-ruby", "~> 0.0.1.alpha1" + + # Rails sub-libraries used at runtime. Depending on these individually + # (instead of the `rails` umbrella) avoids forcing host apps to load + # ActionMailer, ActionCable, ActionView, etc. just to use this gem. + spec.add_runtime_dependency "activerecord", ">= 7.1", "< 9.0" + spec.add_runtime_dependency "activestorage", ">= 7.1", "< 9.0" + spec.add_runtime_dependency "activesupport", ">= 7.1", "< 9.0" + + spec.add_development_dependency "minitest", "~> 5.20" + spec.add_development_dependency "rake", "~> 13.0" +end