Skip to content
This repository was archived by the owner on Jul 22, 2025. It is now read-only.

Commit ccdb0ac

Browse files
committed
allow responding as a whisper
1 parent 2326056 commit ccdb0ac

File tree

3 files changed

+59
-3
lines changed

3 files changed

+59
-3
lines changed

lib/ai_bot/playground.rb

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ def get_context(participants:, conversation_context:, user:, skip_tool_details:
418418
result
419419
end
420420

421-
def reply_to(post, custom_instructions: nil, &blk)
421+
def reply_to(post, custom_instructions: nil, whisper: nil, &blk)
422422
# this is a multithreading issue
423423
# post custom prompt is needed and it may not
424424
# be properly loaded, ensure it is loaded
@@ -428,7 +428,13 @@ def reply_to(post, custom_instructions: nil, &blk)
428428
post_streamer = nil
429429

430430
post_type =
431-
post.post_type == Post.types[:whisper] ? Post.types[:whisper] : Post.types[:regular]
431+
(
432+
if (whisper || post.post_type == Post.types[:whisper])
433+
Post.types[:whisper]
434+
else
435+
Post.types[:regular]
436+
end
437+
)
432438

433439
context =
434440
get_context(

lib/ai_bot/tool_runner.rb

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,12 @@ def attach_discourse(mini_racer_context)
308308
post = Post.find_by(id: @context[:post_id])
309309
return { error: "Post not found" } if post.nil?
310310

311-
reply_post = playground.reply_to(post, custom_instructions: params["instructions"])
311+
reply_post =
312+
playground.reply_to(
313+
post,
314+
custom_instructions: params["instructions"],
315+
whisper: params["whisper"],
316+
)
312317

313318
if reply_post
314319
return(

spec/lib/discourse_automation/llm_tool_triage_spec.rb

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,49 @@
6565
response = post.topic.reload.posts.order(:post_number).last
6666
expect(response.raw).to eq("this is how you reset your password")
6767
end
68+
69+
it "Is able to respond as a whisper if instructed" do
70+
# Create a tool with a script that explicitly requests a whisper response
71+
whisper_tool =
72+
AiTool.create!(
73+
name: "Whisper Triage Tool",
74+
tool_name: "whisper_triage_tool",
75+
description: "Responds with whispers to moderation issues",
76+
parameters: [],
77+
script: <<~JS,
78+
function invoke(params) {
79+
const postId = context.post_id;
80+
const post = discourse.getPost(postId);
81+
82+
const helper = discourse.getPersona("#{ai_persona.name}");
83+
// Pass instructions to make response a whisper
84+
const answer = helper.respondTo({
85+
post_id: post.id,
86+
instructions: "Respond as a whisper for moderators only",
87+
whisper: true
88+
});
89+
90+
return {
91+
answer: answer,
92+
processed: true,
93+
reason: "responded with whisper"
94+
};
95+
}
96+
JS
97+
created_by_id: Discourse.system_user.id,
98+
summary: "Responds with whispers",
99+
enabled: true,
100+
)
101+
102+
result = nil
103+
DiscourseAi::Completions::Llm.with_prepared_responses(
104+
["This moderation note is only visible to staff"],
105+
) { result = described_class.handle(post: post, tool_id: whisper_tool.id) }
106+
107+
expect(result["processed"]).to eq(true)
108+
response = post.topic.reload.posts.order(:post_number).last
109+
expect(response.raw).to eq("This moderation note is only visible to staff")
110+
# Check that the response is indeed a whisper
111+
expect(response.post_type).to eq(Post.types[:whisper])
112+
end
68113
end

0 commit comments

Comments
 (0)