Class: FloopFloop::Projects
- Inherits:
-
Object
- Object
- FloopFloop::Projects
- Defined in:
- lib/floopfloop/projects.rb
Instance Method Summary collapse
- #cancel(ref) ⇒ Object
- #conversations(ref, limit: nil) ⇒ Object
-
#create(prompt:, **opts) ⇒ Object
POST /api/v1/projects.
-
#get(ref, team_id: nil) ⇒ Object
Fetch a single project by id or subdomain.
-
#initialize(client) ⇒ Projects
constructor
A new instance of Projects.
- #list(team_id: nil) ⇒ Object
- #reactivate(ref) ⇒ Object
-
#refine(ref, message:, **opts) ⇒ Object
Refine returns one of three response shapes.
- #status(ref) ⇒ Object
-
#stream(ref, interval: 2, max_wait: 600) {|status_hash| ... } ⇒ Hash
Poll the status endpoint, yielding each de-duplicated snapshot to the block until a terminal state (live / failed / cancelled), the max_wait elapses, or the block raises / breaks.
-
#wait_for_live(ref, interval: 2, max_wait: 600) ⇒ Object
Block until the project reaches ‘live’ and return the hydrated project hash.
Constructor Details
#initialize(client) ⇒ Projects
Returns a new instance of Projects.
7 8 9 |
# File 'lib/floopfloop/projects.rb', line 7 def initialize(client) @client = client end |
Instance Method Details
#cancel(ref) ⇒ Object
51 52 53 54 |
# File 'lib/floopfloop/projects.rb', line 51 def cancel(ref) @client.request("POST", "/api/v1/projects/#{url_encode(ref)}/cancel") nil end |
#conversations(ref, limit: nil) ⇒ Object
74 75 76 77 |
# File 'lib/floopfloop/projects.rb', line 74 def conversations(ref, limit: nil) query = limit && limit.positive? ? { limit: limit } : nil @client.request("GET", "/api/v1/projects/#{url_encode(ref)}/conversations", query: query) end |
#create(prompt:, **opts) ⇒ Object
POST /api/v1/projects
Input keys: :prompt (required), :name, :subdomain, :bot_type, :is_auth_protected, :team_id. Returns the raw backend shape: { “project” => …, “deployment” => … }.
16 17 18 19 20 21 22 23 24 |
# File 'lib/floopfloop/projects.rb', line 16 def create(prompt:, **opts) body = { prompt: prompt } body[:name] = opts[:name] if opts.key?(:name) body[:subdomain] = opts[:subdomain] if opts.key?(:subdomain) body[:botType] = opts[:bot_type] if opts.key?(:bot_type) body[:isAuthProtected] = opts[:is_auth_protected] if opts.key?(:is_auth_protected) body[:teamId] = opts[:team_id] if opts.key?(:team_id) @client.request("POST", "/api/v1/projects", body: body) end |
#get(ref, team_id: nil) ⇒ Object
Fetch a single project by id or subdomain. No dedicated backend route —filters list() locally, matching the other SDKs.
33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/floopfloop/projects.rb', line 33 def get(ref, team_id: nil) list(team_id: team_id).find do |p| p["id"] == ref || p["subdomain"] == ref end.tap do |match| unless match raise FloopFloop::Error.new( code: "NOT_FOUND", message: "project not found: #{ref}", status: 404, ) end end end |
#list(team_id: nil) ⇒ Object
26 27 28 29 |
# File 'lib/floopfloop/projects.rb', line 26 def list(team_id: nil) query = team_id ? { teamId: team_id } : nil @client.request("GET", "/api/v1/projects", query: query) end |
#reactivate(ref) ⇒ Object
56 57 58 59 |
# File 'lib/floopfloop/projects.rb', line 56 def reactivate(ref) @client.request("POST", "/api/v1/projects/#{url_encode(ref)}/reactivate") nil end |
#refine(ref, message:, **opts) ⇒ Object
Refine returns one of three response shapes. Rather than raising on “unexpected” ones we return the raw hash — callers can inspect .fetch(“queued”) / .fetch(“processing”) to branch. Matches the Python / Go / Node SDKs’ behaviour where the caller decides.
65 66 67 68 69 70 71 72 |
# File 'lib/floopfloop/projects.rb', line 65 def refine(ref, message:, **opts) body = { message: } if opts.key?(:attachments) body[:attachments] = opts[:attachments] end body[:codeEditOnly] = opts[:code_edit_only] if opts.key?(:code_edit_only) @client.request("POST", "/api/v1/projects/#{url_encode(ref)}/refine", body: body) end |
#status(ref) ⇒ Object
47 48 49 |
# File 'lib/floopfloop/projects.rb', line 47 def status(ref) @client.request("GET", "/api/v1/projects/#{url_encode(ref)}/status") end |
#stream(ref, interval: 2, max_wait: 600) {|status_hash| ... } ⇒ Hash
Poll the status endpoint, yielding each de-duplicated snapshot to the block until a terminal state (live / failed / cancelled), the max_wait elapses, or the block raises / breaks.
Events are de-duplicated on (status, step, progress, queuePosition) so callers don’t see dozens of identical “queued” snapshots.
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/floopfloop/projects.rb', line 89 def stream(ref, interval: 2, max_wait: 600) deadline = Time.now + max_wait last_key = nil last_event = nil loop do if Time.now >= deadline raise FloopFloop::Error.new( code: "TIMEOUT", message: "stream: project #{ref} did not reach a terminal state within #{max_wait}s", ) end event = status(ref) key = dedup_key(event) if key != last_key last_key = key yield(event) if block_given? end last_event = event case event["status"] when "live", "archived" # Both are terminal-success states. Archived projects are the # post-active form (still hydrated, just not running) — matches # the Node, Python, Swift, and Kotlin SDKs' handling. return event when "failed" raise FloopFloop::Error.new( code: "BUILD_FAILED", message: event["message"].to_s.empty? ? "build failed" : event["message"], ) when "cancelled" raise FloopFloop::Error.new( code: "BUILD_CANCELLED", message: event["message"].to_s.empty? ? "build cancelled" : event["message"], ) end remaining = deadline - Time.now sleep_for = [interval, remaining].min sleep(sleep_for) if sleep_for.positive? end last_event end |
#wait_for_live(ref, interval: 2, max_wait: 600) ⇒ Object
Block until the project reaches ‘live’ and return the hydrated project hash. Wraps #stream with a no-op block.
138 139 140 141 |
# File 'lib/floopfloop/projects.rb', line 138 def wait_for_live(ref, interval: 2, max_wait: 600) stream(ref, interval: interval, max_wait: max_wait) get(ref) end |