Packages
fnord
0.9.19
0.9.40
0.9.39
0.9.38
0.9.37
0.9.36
0.9.35
0.9.34
0.9.33
0.9.32
0.9.31
0.9.30
0.9.29
0.9.28
0.9.27
0.9.26
0.9.25
0.9.24
0.9.23
0.9.22
0.9.21
0.9.20
0.9.19
0.9.18
0.9.17
0.9.16
0.9.15
0.9.14
0.9.13
0.9.12
0.9.11
0.9.10
0.9.9
0.9.8
0.9.7
0.9.6
0.9.5
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.8.99
0.8.98
0.8.97
0.8.96
0.8.95
0.8.94
0.8.93
0.8.92
0.8.91
0.8.90
0.8.89
0.8.88
0.8.87
0.8.86
0.8.85
0.8.84
0.8.83
0.8.82
0.8.81
0.8.80
0.8.79
0.8.78
0.8.77
0.8.76
0.8.75
0.8.74
0.8.73
0.8.72
0.8.71
0.8.70
0.8.69
0.8.68
0.8.67
0.8.66
0.8.65
0.8.64
0.8.63
0.8.62
0.8.61
0.8.60
0.8.59
0.8.58
0.8.57
0.8.56
0.8.55
0.8.54
0.8.53
0.8.52
0.8.51
0.8.50
0.8.49
0.8.48
0.8.47
0.8.46
0.8.45
0.8.44
0.8.43
0.8.42
0.8.41
0.8.40
0.8.39
0.8.38
0.8.37
0.8.36
0.8.35
0.8.34
0.8.33
0.8.32
0.8.31
0.8.30
0.8.29
0.8.27
0.8.26
0.8.25
0.8.24
0.8.23
0.8.22
0.8.21
0.8.20
0.8.19
0.8.18
0.8.17
0.8.16
0.8.15
0.8.14
0.8.13
0.8.12
0.8.11
0.8.1
0.8.0
0.7.24
0.7.23
0.7.22
0.7.21
0.7.20
0.7.19
0.7.18
0.7.17
0.7.16
0.7.15
0.7.14
0.7.13
0.7.12
0.7.11
0.7.10
0.7.9
0.7.8
0.7.7
0.7.6
0.7.5
0.7.3
0.7.2
0.7.1
0.7.0
0.6.9
0.6.8
0.6.7
0.6.6
0.6.5
0.6.4
0.6.3
0.6.1
0.6.0
0.5.9
0.5.8
0.5.7
0.5.6
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.44
0.4.43
0.4.42
0.4.41
0.4.40
0.4.39
0.4.38
0.4.37
0.4.36
0.4.35
0.4.34
0.4.33
0.4.32
0.4.30
0.4.29
0.4.28
0.4.27
0.4.26
0.4.25
0.4.24
0.4.23
0.4.22
0.4.21
0.4.20
0.4.19
0.4.18
0.4.17
0.4.16
0.4.15
0.4.14
0.4.13
0.4.12
0.4.11
0.4.10
0.4.9
0.4.8
0.4.7
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.0
0.2.0
0.1.0
AI code archaeology
Current section
Files
Jump to
Current section
Files
lib/ai/tools/research.ex
defmodule AI.Tools.Research do
@behaviour AI.Tools
@impl AI.Tools
def async?, do: true
@impl AI.Tools
def is_available?, do: true
@impl AI.Tools
def ui_note_on_request(%{"prompt" => prompt} = args) do
project = get_project(args)
{"Requesting research in #{project}", prompt}
end
@impl AI.Tools
def ui_note_on_result(%{"prompt" => prompt} = args, result) do
project = get_project(args)
{"Research completed in #{project}",
"""
# Request
#{prompt}
# Findings
#{result}
"""}
end
@impl AI.Tools
def tool_call_failure_message(_args, _reason), do: :default
@impl AI.Tools
def read_args(args), do: {:ok, args}
@impl AI.Tools
def spec() do
current =
case Settings.get_selected_project() do
{:ok, project} -> project
_ -> nil
end
projects =
Settings.new()
|> Settings.list_projects()
|> Enum.map(fn project ->
if project == current do
"- #{project} (current)"
else
"- #{project}"
end
end)
|> Enum.join("\n")
%{
type: "function",
function: %{
name: "research_tool",
description: """
**This is your research assistant.**
Spin off a focused sub-research process to perform multiple lines of
research in parallel, allowing you to gather information from multiple
sources and synthesize findings into a hollistic view of the code base.
Research is performed by another AI agent which has access to most of
the same tools that you do to perform their task.
The following projects are available for research:
#{projects}
!!! This is your most powerful tool !!!
""",
parameters: %{
type: "object",
required: ["prompt"],
additionalProperties: false,
properties: %{
prompt: %{
type: "string",
description: """
The research task to perform. This should be a specific question
or task that you want the AI agent to research. Provide context
as needed to clarify the task, as they will be starting from
scratch with no context. The more explicit and clear you are, the
more likely they are to produce useful results.
"""
},
fnord_project: %{
type: "string",
description: """
By default, research is performed within the current project. If
the user asks for you to cross-reference a different project,
this option may be specified to indicate that the research should
be performed in that project instead.
Possible values:
#{projects}
"""
}
}
}
}
}
end
@impl AI.Tools
def call(%{"prompt" => prompt} = args) do
with {:ok, selected_project} <- Settings.get_selected_project() do
args
|> get_project()
|> case do
^selected_project -> do_research(prompt)
project -> do_research(project, prompt)
end
end
end
defp do_research(prompt) do
AI.Agent.Researcher
|> AI.Agent.new()
|> AI.Agent.get_response(%{prompt: prompt})
end
defp do_research(project, prompt) do
fnord =
:escript.script_name()
|> Path.expand()
|> Path.absname()
System.cmd(
fnord,
["ask", "--quiet", "--project", project, "--question", prompt],
env: [
{"LOGGER_LEVEL", "error"},
{"FNORD_FORMATTER", ""}
],
parallelism: true,
stderr_to_stdout: true,
into: ""
)
|> case do
{output, 0} -> {:ok, output}
{output, _} -> {:error, output}
end
end
defp get_project(args) do
args
|> Map.get("fnord_project", nil)
|> case do
nil ->
case Settings.get_selected_project() do
{:ok, project} -> project
_ -> raise "No project specified and no current project selected."
end
project ->
project
end
end
end