Files
fizzy/app/models/command/ai/parser.rb
T
Jorge Manrubia bd7b9a442e Merge branch 'main' into fizzy-do-prompts
* main: (57 commits)
  Untenanted access in authenticated controllers should request auth
  dep: bundle update
  dep: update Rails
  dep: bump AR::Tenanted
  Clean up the cable meta tag
  Fix activity feed pagination to fetch on demand
  Create a "published" event if a card is created published
  Scatter Honcho seeds over a 30 day period
  Fix the PWA manifest to use slugged URLs
  Collection publication edits render a turbo frame
  Collection workflow edits render a turbo frame
  Collection entropy config edits render a turbo frame
  Use automatic sizing where supported
  Introduce a separate controller for collection entropy config
  Add `card_id` to index
  Move to scope and inline method
  Prefer modern syntax
  Fix that stage should be visible above card background
  Indicate opens menu
  Hide dialog targets from screen readers when closed
  ...

# Conflicts:
#	db/schema.rb
#	db/schema_cache.yml
2025-07-03 16:11:00 +02:00

79 lines
2.7 KiB
Ruby

class Command::Ai::Parser
include Rails.application.routes.url_helpers
attr_reader :context
delegate :user, to: :context
def initialize(context)
@context = context
self.default_url_options[:script_name] = context.script_name
end
def parse(query)
normalized_query = resolve_named_params_to_ids command_translator.translate(query)
build_command_for normalized_query, query
end
private
def command_translator
Command::Ai::Translator.new(context)
end
def build_command_for(normalized_query, query)
query_context = context_from_query(normalized_query)
resolved_context = query_context || context
commands = Array.wrap(commands_from_query(normalized_query, resolved_context))
if query_context
commands.unshift Command::VisitUrl.new(user: user, url: query_context.url, context: resolved_context)
end
if commands.many?
Command::Composite.new(title: query, commands: commands, user: user, line: query, context: resolved_context)
else
build_standalone_command(commands, query)
end
end
def commands_from_query(normalized_query, context)
parser = Command::Parser.new(context)
if command_lines = normalized_query[:commands].presence
command_lines.collect { parser.parse(it) }
end
end
# This saves unnecessary interchanges with browser for redirect responses
def build_standalone_command(commands, query)
commands.first.tap do |command|
command.line = query
end
end
def resolve_named_params_to_ids(normalized_query)
normalized_query.tap do |query_json|
if query_context = query_json[:context].presence
query_context[:assignee_ids] = query_context[:assignee_ids]&.filter_map { |name| context.find_user(name)&.id }
query_context[:creator_ids] = query_context[:creator_ids]&.filter_map { |name| context.find_user(name)&.id }
query_context[:closer_ids] = query_context[:closer_ids]&.filter_map { |name| context.find_user(name)&.id }
query_context[:collection_ids] = query_context[:collection_ids]&.filter_map { |name| context.find_collection(name)&.id }
query_context[:tag_ids] = query_context[:tag_ids]&.filter_map { |name| context.find_tag(name)&.id }
query_context.compact!
end
end
end
def assignee_from(string)
string_without_at = string.delete_prefix("@")
User.all.find { |user| user.mentionable_handles.include?(string_without_at.downcase) }
end
def context_from_query(query_json)
if context_properties = query_json[:context].presence
url = cards_path(**context_properties)
Command::Parser::Context.new(user, url: url, script_name: context.script_name)
end
end
end