diff --git a/.changeset/smart-nails-mix.md b/.changeset/smart-nails-mix.md new file mode 100644 index 0000000..80bda25 --- /dev/null +++ b/.changeset/smart-nails-mix.md @@ -0,0 +1,5 @@ +--- +'@mermaidchart/sdk': patch +--- + +Add a regenerate method to the SDK that complements our Mermaid Diagram Sync GitHub App functionality. This method should accept the existing Mermaid diagram content along with source file changes, and regenerate the diagram based on those updates while preserving the overall diagram structure and intent. diff --git a/packages/sdk/src/index.e2e.test.ts b/packages/sdk/src/index.e2e.test.ts index 99592e1..ff85b99 100644 --- a/packages/sdk/src/index.e2e.test.ts +++ b/packages/sdk/src/index.e2e.test.ts @@ -267,3 +267,46 @@ describe('suggestPrSummary', () => { } }, 60000); // 60 seconds timeout for AI operations }); + +describe('regenerateDiagram', () => { + it('should regenerate a diagram from updated source files', async () => { + const code = `flowchart TD\n A[Start] --> B[Process]\n B --> C[End]`; + const sourceFiles = [ + 'function processOrder(order) {\n validateOrder(order);\n shipOrder(order);\n}', + ]; + + try { + const creditsBefore = await client.getAICredits(); + + const result = await client.regenerateDiagram({ + code, + sourceFiles, + }); + + // Verify response structure + expect(result).toHaveProperty('result'); + expect(result).toHaveProperty('code'); + expect(['ok', 'fail']).toContain(result.result); + + // When the AI successfully regenerates the diagram, creditUsage should be present + // and credits should have been deducted + if (result.result === 'ok' && result.solved === true) { + expect(result.creditUsage).toMatchObject({ + creditsToDeduct: expect.any(Number), + baseCost: expect.any(Number), + reason: expect.any(String), + }); + + const creditsAfter = await client.getAICredits(); + expect(creditsAfter.aiCredits.remaining).toBe( + creditsBefore.aiCredits.remaining - result.creditUsage!.creditsToDeduct, + ); + } + } catch (error) { + if (error instanceof AICreditsLimitExceededError) { + return; // Credits exceeded is acceptable for E2E test + } + throw error; + } + }, 60000); // 60 seconds timeout for AI operations +}); diff --git a/packages/sdk/src/index.ts b/packages/sdk/src/index.ts index 4ffe783..9200077 100644 --- a/packages/sdk/src/index.ts +++ b/packages/sdk/src/index.ts @@ -21,6 +21,8 @@ import type { RepairDiagramResponse, PrSummaryRequest, PrSummaryResponse, + RegenerateDiagramRequest, + RegenerateDiagramResponse, AICreditsUsage, } from './types.js'; import { URLS } from './urls.js'; @@ -351,6 +353,26 @@ export class MermaidChart { } } + /** + * Regenerates a Mermaid diagram based on updated source files using AI. + * + * @param request - `code` (current diagram source) and `sourceFiles` (full contents of related source files) + * @throws {@link AICreditsLimitExceededError} if credits limit exceeded (HTTP 402) + */ + public async regenerateDiagram( + request: RegenerateDiagramRequest, + ): Promise { + try { + const response = await this.axios.post( + URLS.rest.openai.regenerate, + request, + ); + return response.data; + } catch (error: unknown) { + throwIfAICreditsExceeded(error); + } + } + /** * Chat with Mermaid AI about a diagram. * diff --git a/packages/sdk/src/types.ts b/packages/sdk/src/types.ts index 029733b..08e4578 100644 --- a/packages/sdk/src/types.ts +++ b/packages/sdk/src/types.ts @@ -114,6 +114,42 @@ export interface PrSummaryResponse { commitMessage: string; } +/** + * Request parameters for regenerating a Mermaid diagram from updated source files. + */ +export interface RegenerateDiagramRequest { + /** The current Mermaid diagram source to be regenerated. */ + code: string; + /** Ordered full contents of the source files that the diagram is based on. */ + sourceFiles: string[]; +} + +/** + * Response from regenerating a Mermaid diagram. + */ +export interface RegenerateDiagramResponse { + /** + * The status of the regeneration: 'ok' if a valid mermaid code block was generated, 'fail' otherwise. + */ + result: 'ok' | 'fail'; + /** + * Markdown message that may contain a valid mermaid code block. + */ + code: string; + /** + * Whether the diagram regeneration was successful. + */ + solved?: boolean; + /** + * Credit usage for client-side deduction (only present when solved). + */ + creditUsage?: { + creditsToDeduct: number; + baseCost: number; + reason: string; + }; +} + /** * Request parameters for chatting with the Mermaid AI about a diagram. */ diff --git a/packages/sdk/src/urls.ts b/packages/sdk/src/urls.ts index 54d53f3..d525eac 100644 --- a/packages/sdk/src/urls.ts +++ b/packages/sdk/src/urls.ts @@ -42,6 +42,7 @@ export const URLS = { openai: { repair: `/rest-api/openai/repair`, prSummary: `/rest-api/openai/pr-summary`, + regenerate: `/rest-api/openai/regenerate`, chat: `/rest-api/openai/chat`, }, },