mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-06 10:48:12 +02:00
## Thinking Path > - Paperclip helps people manage AI agents for work. > - Slack connections let a team talk to those agents in Slack. > - Agents now have a saved avatar, but Slack setup did not offer that image. > - A matching avatar helps a team recognize its agent. > - This pull request adds an optional avatar step and a download in connector Settings. > - Users download a PNG and upload it directly in Slack with clear instructions. ## Linked Issues or Issue Description **What existing behavior does this improve?** Slack connector onboarding and its Settings page. **Current behavior** Setup does not offer the assigned agent's avatar or explain how to upload it in Slack. **Proposed behavior** After Slack connection verification, users can download a 512 × 512 PNG of their agent's saved avatar. They can upload it in Slack, confirm, or skip. Settings keeps the download and upload instructions available after onboarding. **Reason and benefit** The same avatar helps people recognize the agent across Paperclip and Slack. Users who skip the optional step can return to it in Settings. **Breaking changes** None. No schema, authentication, Slack scope, or provider API change. Completed connections keep their existing completion state. Searched existing Slack avatar and Cliptoon PRs; no matching implementation was found. ## What Changed - Add an optional avatar step before personal Slack account linking. Keep the numbered sidebar and shared footer. - Resolve the selected agent's saved appearance for the preview and PNG download. - Add the same download and expandable upload instructions to connector Settings. - Remember uploaded or skipped per company and endpoint in browser storage. Treat uploaded as user confirmation, not provider verification. - Reject failed or non-PNG download responses and allow retry. - Reuse the production avatar components in onboarding and Settings stories. - Test wizard progression, resume, Settings, download recovery, storage isolation, and terminated assigned agents. - Exercise real PNG downloads in the Slack browser flow and keep default app names consistent with app creation. - Fetch the assigned agent directly so its saved avatar remains available after termination. ## Verification - Focused chat suites: 48 passed; the two affected suites passed again after the final naming fix (32 tests). - Slack browser E2E passed through setup, avatar download, account linking, and Settings download. PNG signature and 512 × 512 dimensions verified. - UI token gates passed. - Browser: downloaded the real 512 × 512 PNG; checked confirmation, return, mobile layout, and Settings instructions. - Full workspace typecheck, application build, and production Storybook build passed. - All latest-head CI checks passed (54 passed, 2 skipped), including all browser, chat, general, and serialized test groups. The unrelated Sentry test failed once and passed on the single CI rerun; its suite also passed locally. - Local full-suite attempt encountered a rapid Slack callback ordering failure under concurrent build load; that test passed in isolation, and all three chat shards passed in CI. The remaining local run was not used as the merge gate. - Review the Connections / Slack / Add avatar and Avatar in Settings stories. ## Risks - Slack upload is manual. Confirmation does not claim to verify the Slack icon. - Optional step progress is browser-local. Clearing storage or changing browsers can show it again. Setup still works when storage is unavailable. - The existing avatar API remains the image source. Download failures show a retry message. ## Model Used OpenAI GPT-6 through Codex, with reasoning, repository tools, code execution, and browser testing. The exact deployment model ID and context window are not exposed in this session. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
30 lines
1.7 KiB
TypeScript
30 lines
1.7 KiB
TypeScript
import type { Meta, StoryObj } from "@storybook/react-vite";
|
||
import { expect, userEvent, within } from "storybook/test";
|
||
import { SlackAvatarStep } from "../prototypes/slack-avatar/SlackAvatarStep";
|
||
|
||
const meta = {
|
||
title: "Connections/Slack/Add avatar",
|
||
component: SlackAvatarStep,
|
||
parameters: {
|
||
layout: "fullscreen",
|
||
docs: { description: { component: "Proposed optional step after verifying Slack, before linking your account. Downloads a real 512px Cliptoon PNG. Upload is manual in Slack; confirmation is user-reported. Navigation and Save & exit are local preview state, not production persistence." } },
|
||
},
|
||
args: { agentName: "CEO", appName: "ceo-paperclip" },
|
||
render: (args) => <SlackAvatarStep key={JSON.stringify(args)} {...args} />,
|
||
} satisfies Meta<typeof SlackAvatarStep>;
|
||
export default meta;
|
||
type Story = StoryObj<typeof meta>;
|
||
export const DownloadAndUpload: Story = {};
|
||
export const Uploaded: Story = { args: { initialUploaded: true } };
|
||
export const Mobile: Story = { globals: { viewport: { value: "mobile1", isRotated: false } } };
|
||
export const ConfirmAndReturn: Story = {
|
||
play: async ({ canvasElement }) => {
|
||
const canvas = within(canvasElement);
|
||
await expect(canvas.getByRole("link", { name: "Download avatar" })).toHaveAttribute("download", "ceo-paperclip-avatar.png");
|
||
await userEvent.click(canvas.getByRole("button", { name: "I’ve uploaded the avatar" }));
|
||
await expect(canvas.getByRole("heading", { name: "Connect your Slack account" })).toBeVisible();
|
||
await userEvent.click(canvas.getByRole("button", { name: "Back to avatar step" }));
|
||
await expect(canvas.getByRole("status")).toHaveTextContent("You marked the avatar as uploaded");
|
||
},
|
||
};
|