diff --git a/packages/junior/src/chat/prompt.ts b/packages/junior/src/chat/prompt.ts index 261b5fec00..b427989ff6 100644 --- a/packages/junior/src/chat/prompt.ts +++ b/packages/junior/src/chat/prompt.ts @@ -332,7 +332,7 @@ const CONVERSATION_RULES = [ ]; const SLACK_ACTION_RULES = [ - "- Assistant text, Slack posts, reactions, new canvases, new lists, and file sends go only to the current conversation or thread. If asked to post elsewhere or create a new top-level channel post, explain the limitation instead of calling a tool, and do not present the text as delivered. Slack read tools can target other public channels with `channel_id`.", + "- Assistant text, Slack posts, reactions, new canvases, new lists, and file sends go only to the current conversation or thread. Your reply is not a channel post, and you cannot create a new top-level channel post. When asked to post to a channel or anywhere else right now, explain that limitation; do not call a Slack send tool, and do not reply with only the requested text or present it as delivered. Scheduled automations can still post to the active channel later. Slack read tools can target other public channels with `channel_id`.", "- Ambient reaction requests target the current inbound message; do not ask for a message reference.", `- When no visible thread reply is requested or useful, keep tool-calling messages text-free and make the final message exactly ${NO_REPLY_MARKER}.`, ]; diff --git a/packages/junior/tests/unit/prompt.test.ts b/packages/junior/tests/unit/prompt.test.ts deleted file mode 100644 index 005742414a..0000000000 --- a/packages/junior/tests/unit/prompt.test.ts +++ /dev/null @@ -1,163 +0,0 @@ -import { describe, expect, it } from "vitest"; -import { createSlackSource } from "@sentry/junior-plugin-api"; -import { buildTurnContextPrompt } from "@/chat/prompt"; - -describe("prompt builders", () => { - it("renders sandbox workspace root as runtime context", () => { - const prompt = buildTurnContextPrompt({ - availableSkills: [], - activeMcpCatalogs: [], - }); - - expect(prompt).toContain("- sandbox.workspace_root: /vercel/sandbox"); - }); - - it("lists disabled tools in follow-up Turn context", () => { - const prompt = buildTurnContextPrompt({ - availableSkills: [], - includeSessionContext: false, - disabledTools: [ - { name: "createEventAutomation", reason: "Needs a Slack message." }, - { name: "listEventAutomations", reason: "Needs a Slack message." }, - { name: "addReaction", reason: "No message to react to." }, - ], - }); - - expect(prompt).toContain(""); - expect(prompt).toContain( - "- `createEventAutomation`, `listEventAutomations`: Needs a Slack message.", - ); - expect(prompt).toContain("- `addReaction`: No message to react to."); - expect(prompt).not.toContain("sandbox.workspace_root"); - }); - - it("renders Slack conversation facts in runtime context", () => { - const prompt = buildTurnContextPrompt({ - availableSkills: [], - activeMcpCatalogs: [], - runtime: { - conversationId: "slack:C123:1712345.000001", - slackConversation: { - type: "private_channel", - name: "#roadmap & launches", - }, - }, - }); - - expect(prompt).toContain( - "- gen_ai.conversation.id: slack:C123:1712345.000001", - ); - expect(prompt).toContain("- slack.conversation.type: private_channel"); - expect(prompt).toContain( - "- slack.conversation.name: #roadmap & launches", - ); - expect(prompt).not.toContain("#roadmap & launches"); - }); - - it("renders generic dispatch facts in runtime context", () => { - const prompt = buildTurnContextPrompt({ - availableSkills: [], - activeMcpCatalogs: [], - dispatch: { - actor: { platform: "system", name: "scheduler" }, - plugin: "scheduler", - source: createSlackSource({ - teamId: "T123", - channelId: "C123", - - visibility: "private", - }), - destination: { - platform: "slack", - teamId: "T123", - channelId: "C123", - }, - metadata: { - scheduledFor: "2026-05-26T12:00:00.000Z", - taskId: "sched_plugin_1", - }, - }, - }); - - expect(prompt).toContain(""); - expect(prompt).toContain( - "- dispatch.execution: execute the dispatched input now", - ); - expect(prompt).toContain( - "- dispatch.delivery: the runtime delivers the final answer to the destination", - ); - expect(prompt).toContain("- dispatch.actor.platform: system"); - expect(prompt).toContain("- dispatch.actor.name: scheduler"); - expect(prompt).toContain("- source.kind: slack"); - expect(prompt).toContain("- destination.channel_id: C123"); - expect(prompt).toContain( - "- dispatch.metadata.scheduledFor: 2026-05-26T12:00:00.000Z", - ); - expect(prompt).toContain("- dispatch.metadata.taskId: sched_plugin_1"); - }); - - it("omits follow-up runtime context once session bootstrap exists", () => { - expect( - buildTurnContextPrompt({ - availableSkills: [ - { - name: "alpha", - description: "Alpha workflow", - skillPath: "/tmp/skills/alpha", - }, - ], - activeMcpCatalogs: [ - { provider: "alpha-provider", available_tool_count: 2 }, - ], - configuration: { - sentry_project: "junior", - }, - includeSessionContext: false, - actor: { - userId: "U0BETA", - userName: "dcramer", - }, - runtime: { - conversationId: "conversation-alpha", - }, - toolGuidance: [ - { - name: "editFile", - promptSnippet: "exact edits", - }, - ], - }), - ).toBeNull(); - }); - - it("renders plugin prompt contributions without replaying follow-up bootstrap context", () => { - const prompt = buildTurnContextPrompt({ - availableSkills: [ - { - name: "alpha", - description: "Alpha workflow", - skillPath: "/tmp/skills/alpha", - }, - ], - activeMcpCatalogs: [ - { provider: "alpha-provider", available_tool_count: 2 }, - ], - includeSessionContext: false, - pluginPromptContributions: [ - { - id: "memory", - pluginName: "memory", - text: "User prefers concise answers.", - }, - ], - runtime: { - conversationId: "conversation-alpha", - }, - }); - - expect(prompt).toContain("User prefers concise answers."); - expect(prompt).toContain('plugin="memory"'); - expect(prompt).not.toContain(""); - expect(prompt).not.toContain("conversation-alpha"); - }); -});