Packages
fnord
0.8.60
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/notify.ex
defmodule AI.Tools.Notify do
@behaviour AI.Tools
@impl AI.Tools
def async?, do: false
@impl AI.Tools
def is_available?, do: true
@impl AI.Tools
def read_args(args), do: {:ok, args}
@impl AI.Tools
def ui_note_on_request(_), do: nil
@impl AI.Tools
def ui_note_on_result(_args, _res), do: nil
@impl AI.Tools
def spec do
%{
type: "function",
function: %{
name: "notify_tool",
description: """
While you are researching or working on a task, regular feedback to the user improves the user experience.
Use this tool **EXTENSIVELY** to send short messages, explanations, or warnings to the user.
Examples:
- "I am looking up the latest information on the topic." (info)
- "Interesting! I learned that $SomeComponent is actually performing the validation itself!" (info)
- "This is taking longer than expected due to unexpected findings." (warn)
- "The shell command is taking longer than expected, working on it." (error)
You are encouraged to speak in character. Software engineers love their geekdoms!
Memory memos:
- If your message includes a line starting with "note to self:" or "remember:", the notes agent will capture it as a high-priority, non-transient fact in the project notes.
- Keep memos concise and specific (one line per memo).
Additionally, any lines in the message beginning with `note to self:` or `remember:` (case-insensitive) will be captured as memos in your project notes.
""",
parameters: %{
type: "object",
required: ["level", "message"],
additionalProperties: false,
properties: %{
level: %{
type: "string",
enum: ["info", "warn", "error", "debug"],
description: """
The type of notification to send.
Can be "info", "warn", or "error".
Use `info` to report general information to the user about what you are doing.
Use `warn` to warn the user of potential delays (problems getting tool calls to work, unexpected findings during research, red herrings, kvetching about how difficult something is, etc.).
Use `error` to report an error that prevents you from completing the task.
Use `debug` to report debug information when the user asks for additional information about what you are doing.
"""
},
message: %{
type: "string",
description: "The message content to send as feedback."
}
}
}
}
}
end
@impl AI.Tools
def call(args) do
with {:ok, level} <- AI.Tools.get_arg(args, "level"),
{:ok, message} <- AI.Tools.get_arg(args, "message") do
# Capture memo lines and ingest asynchronously
message
|> extract_memo_lines()
|> ingest_memos()
name = get_name()
case level do
"info" -> UI.feedback(:info, name, message)
"warn" -> UI.feedback(:warn, name, message)
"error" -> UI.feedback(:error, name, message)
"debug" -> UI.feedback(:debug, name, message)
end
end
end
defp get_name do
with {:ok, name} <- Services.NamePool.get_name_by_pid(self()) do
name
else
_ -> Services.NamePool.default_name()
end
end
@spec extract_memo_lines(String.t()) :: [String.t()]
defp extract_memo_lines(message) do
message
|> String.split("\n")
|> Enum.reduce([], fn line, acc ->
case Regex.run(~r/^\s*(?:note to self:|remember:)\s*(.+)$/i, line) do
[_, memo_raw] ->
memo = String.trim(memo_raw)
if memo != "" do
[memo | acc]
else
acc
end
_ ->
acc
end
end)
|> Enum.reverse()
end
@spec ingest_memos([String.t()]) :: :ok
defp ingest_memos(memos) do
Enum.each(memos, &Services.Notes.ingest_user_msg(&1))
:ok
end
end