Packages
fnord
0.8.62
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/conversations.ex
defmodule Cmd.Conversations do
@behaviour Cmd
@impl Cmd
def requires_project?(), do: true
@impl Cmd
def spec do
[
conversations: [
name: "conversations",
about: "List all conversations in the project",
options: [
project: Cmd.project_arg(),
prune: [
value_name: "PRUNE",
long: "--prune",
short: "-P",
help: "Prune conversations older than this many days",
parser: :integer
]
]
]
]
end
@impl Cmd
def run(%{prune: days} = opts, _subcommands, _unknown) when is_integer(days) do
with {:ok, project} <- Store.get_project() do
case prune(opts, project) do
:ok -> :ok
{:error, :cancelled} -> UI.error("Operation cancelled.")
{:error, :invalid_prune_value} -> UI.error("Invalid --prune value: #{days}")
end
else
{:error, :project_not_set} ->
UI.error("No project selected; use --project or run in a project directory.")
end
end
@impl Cmd
def run(opts, _subcommands, _unknown) do
with {:ok, project} <- Store.get_project(),
:ok <- display(opts, project) do
:ok
else
{:error, :project_not_set} ->
UI.error(
"No project selected; please specify --project or run inside a project directory."
)
end
end
defp prune(%{prune: days}, project) when is_integer(days) and days >= 0 do
cutoff = DateTime.utc_now() |> DateTime.add(-days, :day)
UI.info("Pruning conversations older than #{days} days")
to_delete =
project
|> Store.Project.conversations()
|> Enum.reduce([], fn conversation, acc ->
timestamp = Store.Project.Conversation.timestamp(conversation)
if DateTime.compare(timestamp, cutoff) == :lt do
[conversation | acc]
else
acc
end
end)
if to_delete == [] do
UI.info("No conversations to prune.")
:ok
else
UI.info("Preparing to delete the following conversations:")
to_delete
|> Enum.each(fn conversation ->
UI.info(conversation.id)
end)
if UI.confirm("Confirm deletion of the listed conversations. This action cannot be undone.") do
to_delete |> Enum.each(&Store.Project.Conversation.delete/1)
count = length(to_delete)
UI.info("Deleted #{count} conversation(s).")
:ok
else
{:error, :cancelled}
end
end
end
defp prune(%{prune: days}, _project) when is_integer(days) and days < 0 do
{:error, :invalid_prune_value}
end
defp prune(_opts, _project), do: :ok
defp display(_opts, project) do
project
|> Store.Project.conversations()
|> case do
[] ->
UI.puts("No conversations found.")
conversations ->
conversations
|> Enum.map(fn conversation ->
%{
id: conversation.id,
timestamp: Store.Project.Conversation.timestamp(conversation),
file: conversation.store_path,
question: get_question(conversation),
length: Store.Project.Conversation.num_messages(conversation)
}
end)
|> Jason.encode!(pretty: true)
|> UI.puts()
end
:ok
end
defp get_question(conversation) do
with {:ok, question} <- Store.Project.Conversation.question(conversation) do
question
else
{:error, :no_question} -> "(not found)"
end
end
end