Packages
fnord
0.8.92
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/cmd/frobs.ex
defmodule Cmd.Frobs do
@behaviour Cmd
@impl Cmd
def requires_project?(), do: false
@impl Cmd
def spec do
[
frobs: [
name: "frobs",
about: "Manages external tool call integrations (frobs)",
subcommands: [
create: [
name: "create",
about: "Creates a new frob",
options: [
name: [
value_name: "NAME",
long: "--name",
short: "-n",
help: "Name of the frob",
required: true
]
]
],
check: [
name: "check",
about: "Validates a frob",
options: [
name: [
value_name: "NAME",
long: "--name",
short: "-n",
help: "Name of the frob",
required: true
]
]
],
list: [
name: "list",
about: "Lists all available frobs"
],
enable: [
name: "enable",
about: "Enables a frob",
options: [
name: [
value_name: "NAME",
long: "--name",
short: "-n",
help: "Name of the frob",
required: true
],
global: [
long: "--global",
help: "Apply to global settings (otherwise current project)",
takes_value: false
],
project: [
long: "--project",
value_name: "PROJECT",
help: "Apply to the named project (overrides selected project)"
]
]
],
disable: [
name: "disable",
about: "Disables a frob",
options: [
name: [
value_name: "NAME",
long: "--name",
short: "-n",
help: "Name of the frob",
required: true
],
global: [
long: "--global",
help: "Apply to global settings (otherwise current project)",
takes_value: false
],
project: [
long: "--project",
value_name: "PROJECT",
help: "Apply to the named project (overrides selected project)"
]
]
]
]
]
]
end
@impl Cmd
def run(opts, subcommands, _unknown) do
Services.Once.set(:frobs_cli_used, true)
try do
with {:ok, msg} <- call_subcommand(subcommands, opts) do
UI.puts(msg)
else
{:error, :invalid_subcommand} ->
UI.fatal("Invalid subcommand. Use `fnord help frobs` for available commands.")
{:error, reason} ->
UI.fatal("Error: #{reason}")
end
rescue
e in RuntimeError ->
UI.fatal("Error: #{e.message}")
end
end
defp call_subcommand(subcommands, opts) do
case subcommands do
[:create] -> create(opts)
[:check] -> check(opts)
[:list] -> list()
[:enable] -> enable(opts)
[:disable] -> disable(opts)
_ -> {:error, :invalid_subcommand}
end
end
defp create(%{name: name}) do
with {:ok, frob} <- Frobs.create(name) do
{:ok,
"""
--------------------------------------------------------------------------------
> Frob created
--------------------------------------------------------------------------------
- Name: `#{frob.name}`
- Home: `#{frob.home}`
- Spec: `#{frob.home}/spec.json`
- Main: `#{frob.home}/main`
--------------------------------------------------------------------------------
> Tips
--------------------------------------------------------------------------------
- Edit `main` to implement your integration.
- Update the spec in `spec.json` to define the frob's interface and parameters.
- Enable your frob via the settings CLI or the Settings.Frobs module.
Fnord communicates run-time information to the frob via environment variables:
- FNORD_PROJECT: The name of the currently selected project
- FNORD_CONFIG: JSON object of project config (see `$HOME/.fnord/settings.json`)
- FNORD_ARGS_JSON: JSON object of LLM-provided arguments (defined in your spec)
!!! You can remove the frob at any time by deleting the directory.
"""}
end
end
defp check(%{name: name}) do
with {:ok, _frob} <- Frobs.load(name) do
{:ok, "Frob #{name} appears to be valid!"}
end
end
defp list() do
frobs =
Frobs.list()
|> Enum.map(fn frob ->
desc = Map.get(frob.spec, "description", "No description provided")
enabled = Settings.Frobs.enabled?(frob.name)
scope_info =
if enabled do
case Settings.get_selected_project() do
{:ok, _} -> "Enabled (global or project)"
_ -> "Enabled (global)"
end
else
"Disabled"
end
"""
- Name: #{frob.name}
- Description: #{desc}
- Location: #{frob.home}
- Status: #{scope_info}
"""
end)
|> Enum.join("\n\n")
if frobs == "" do
case Settings.get_selected_project() do
{:ok, project} ->
{:ok, "No frobs found for project #{project.name}"}
_ ->
{:ok, "No frobs found"}
end
else
{:ok,
"""
--------------------------------------------------------------------------------
> Frobs
--------------------------------------------------------------------------------
#{frobs}
"""}
end
end
defp enable(opts) do
name = opts[:name]
with {:ok, scope} <- resolve_scope(opts),
:ok <- Settings.Frobs.enable(scope, name) do
{:ok, "Frob #{name} enabled in #{scope_label(scope)} scope."}
end
end
defp disable(opts) do
name = opts[:name]
with {:ok, scope} <- resolve_scope(opts),
:ok <- Settings.Frobs.disable(scope, name) do
{:ok, "Frob #{name} disabled in #{scope_label(scope)} scope."}
end
end
defp resolve_scope(opts) do
cond do
opts[:global] ->
{:ok, :global}
is_binary(opts[:project]) and byte_size(opts[:project]) > 0 ->
{:ok, {:project, opts[:project]}}
true ->
case Settings.get_selected_project() do
{:ok, _pn} -> {:ok, :project}
_ -> raise "No project selected. Use --global or --project <name>."
end
end
end
defp scope_label(:global), do: "global"
defp scope_label({:project, name}), do: "project: #{name}"
defp scope_label(:project), do: "project (selected)"
end