diff --git a/.gitignore b/.gitignore index d24e487..17ee8a4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,8 @@ .claude/ +.github/ apimatic-portal-workspace/ skills/apimatic-portal/evals/workspace/ skills/apimatic-portal/evals/results.json +apimatic-sdk-workspace/ +skills/apimatic-sdk/evals/workspace/ +skills/apimatic-sdk/evals/results.json \ No newline at end of file diff --git a/skills/apimatic-portal/scripts/auth-login.mjs b/skills/apimatic-portal/scripts/auth-login.mjs index b21ad24..e4cdf6e 100644 --- a/skills/apimatic-portal/scripts/auth-login.mjs +++ b/skills/apimatic-portal/scripts/auth-login.mjs @@ -21,6 +21,7 @@ import { spawn } from "node:child_process"; const child = spawn("apimatic", ["auth", "login"], { detached: true, stdio: "ignore", + shell: process.platform === "win32", }); child.unref(); diff --git a/skills/apimatic-sdk/SKILL.md b/skills/apimatic-sdk/SKILL.md new file mode 100644 index 0000000..fc73d20 --- /dev/null +++ b/skills/apimatic-sdk/SKILL.md @@ -0,0 +1,430 @@ +--- +name: apimatic-sdk +description: Use for any task involving APIMatic's SDK generation toolchain. Use when a user wants to generate, create, customize, download, or publish an SDK using the APIMatic CLI. Also use when the user has already customized a generated SDK and wants to save those changes, when the user wants to make a specific change to an SDK (e.g. "change the analyzer", "switch the linter"), when the user asks about CodeGen settings, SDK configuration, or APIMATIC-META.json (e.g. "enable retry on timeout", "disable linting", "set the project name"), or when the user wants to publish an SDK to a package registry or source repository, or wants to list publishing profiles. +--- + +# APIMatic SDK + +Generate SDKs for your APIs in multiple languages using the APIMatic CLI. + +## When to Use + +- User wants to create, generate, or download an SDK using the APIMatic CLI +- User wants to customize an SDK, asks about custom code injection, or wants to preserve customizations across regenerations +- User mentions `sdk save-changes` or asks how to save SDK changes +- User says they have already customized a generated SDK and want to save or commit those changes +- User asks to customize an SDK in a specific way (e.g. "change the analyzer", "switch the linter", "update the formatter in the PHP SDK") +- User asks to change a CodeGen setting (e.g. "enable retry on timeout", "set the project name", "disable linting", "change the timeout", "enable HTTP cache") — these can be applied via `APIMATIC-META.json` and a regeneration +- User wants to publish an SDK to a package registry (npm, PyPI, NuGet) or source code repository (GitHub) +- User wants to list publishing profiles or find a profile ID for publishing +- User mentions `sdk publish` or `publishing profile list` + +## Red Flags — STOP and re-read the relevant section + +- About to pass the spec file path to `--input` → `--input` must point to the parent directory that contains `src/`, not the spec file itself (e.g., `--input=./my-project`, not `--input=./openapi.yaml`) → commands run from project root, never from inside `src/` +- About to add `--zip` when the user didn't ask for it → only include `--zip` if the user explicitly requested a zip download +- About to rerun `sdk generate` with `--force` without asking → when the CLI reports an SDK already exists, ask the user before adding `--force` +- About to `cd src/` before running generate → run from the project root (the directory that _contains_ `src/`), never from inside `src/` +- About to proceed to SDK generation before the user confirms browser auth → wait for user confirmation after launching browser login, then verify with `apimatic auth status` +- About to run `sdk save-changes` without `--track-changes` having been enabled → change tracking must be initialized during generation; regenerate with `--track-changes` first +- About to add `--api-version` when user hasn't mentioned a specific API version → only include `--api-version` when the user explicitly names a version +- About to ask for information the user already stated in their prompt → use what was given; only ask for genuinely unknown values +- About to edit a generated SDK file for a change that could be a CodeGen setting → read each file in `references/` that covers settings (e.g. `endpoint-settings.md`, `http-configuration-settings.md`, `timeout-and-retries-settings.md`, `sdk-interface-customization-settings.md`, etc.) and check whether the change maps to a listed setting; if it does, update `APIMATIC-META.json` and regenerate instead of modifying generated files +- About to pick the first matching CodeGen setting without reading all reference files → read all reference files first, then pick the most suitable match +- About to manually delete or remove a generated folder or file (e.g., `docs/`, `README.md`) as a customization → check codegen settings first; (e.g., removing docs maps to `DisableDocs: true` in `APIMATIC-META.json`) — set this before generating, not after via file deletion or custom code injection +- About to open, read, or edit the `.` files inside `sdk-source-tree/` (e.g., `.typescript`, `.python`) → these files are managed exclusively by the CLI; never touch them directly under any circumstance +- About to manually compare or inspect customizations by reading `sdk-source-tree/` → if the user wants to see what changed between a plain generation and their customized one, regenerate using `--skip-changes` to produce a clean copy, then compare that against the customized SDK; do not manipulate or read the source tree files +- About to run `sdk publish` because the user said "for publishing", "to publish", "for npm", or similar contextual phrases → these describe the user's **goal**, not a publish instruction; only run `sdk publish` if the user explicitly asks to publish (e.g., "publish the SDK", "run sdk publish", "push to npm using apimatic", "push to GitHub using apimatic"); for any other phrasing, stop at SDK generation +- About to run `sdk publish` without a `--profile-id` and the user hasn't provided one → run `apimatic publishing profile list` first and present the available profiles so the user can choose +- About to pass a `--publish-type` value other than `package` or `sourcecode` → see the [Publish Types](#publish-types) section for valid values + +## Communication Guidelines + +This skill is used by developers of all experience levels. All messages shown to the user must be clear, non-technical, and action-oriented. Follow these rules in every response: + +- **Never forward raw CLI output:** Do not paste or quote terminal output, spinner characters, ANSI escape codes, or build logs. Summarize what happened in plain language. +- **Use the verbatim blocks provided:** When this skill provides a specific message to show, output it exactly as written. Do not paraphrase or add technical context around it. +- **Keep error guidance actionable:** When something fails, tell the user what went wrong in simple terms and what they can do about it. Do not describe the internal recovery steps you are attempting — just attempt them silently and report the outcome. +- **When in doubt, less is more:** If you are unsure whether a detail is useful to the user, leave it out. + +## Customize an SDK + +## Fast Path — Already-Customized SDK + +If the user's message indicates they have **already made customizations** to a generated SDK and want to save those changes (e.g. "I customized my SDK", "I made changes to the generated SDK", "save my SDK changes", "save changes in it"): + +1. Confirm the Prerequisites section below is satisfied (Node.js, CLI installed). +2. Complete Step 1: Authenticate with APIMatic below. +3. **Check for `sdk-source-tree`** — see the [SDK Source Tree Check](#sdk-source-tree-check) section below. + +## Fast Path — Apply a Specific Customization to an SDK + +If the user asks Claude to make a specific change to an SDK (e.g. "change the phan analyzer to something else", "switch the linter in my PHP SDK", "update the test framework in my TypeScript SDK"): + +1. Confirm the Prerequisites section below is satisfied (Node.js, CLI installed). +2. Complete Step 1: Authenticate with APIMatic below. +3. **Check if the change is a CodeGen setting first** — see the [CodeGen Settings Check](#codegen-settings-check) section below. If the change maps to a CodeGen setting, follow that path instead. +4. If the change is not a CodeGen setting, **check for `sdk-source-tree`** — see the [SDK Source Tree Check](#sdk-source-tree-check) section below. + +Do not ask whether the user wants to customize or save — they have already told you what change to make. Proceed without prompting unless something is genuinely unknown. + +## CodeGen Settings Check + +Before editing any generated SDK files for a customization, check whether the change can be applied as a CodeGen setting in `APIMATIC-META.json`. + +Read each of the following reference files one by one and check whether the requested change maps to a setting described in that file. Read all of them before deciding — pick the most suitable match: + +- `references/user-agent-settings.md` +- `references/code-branding-settings.md` +- `references/endpoint-settings.md` +- `references/enum-settings.md` +- `references/exception-settings.md` +- `references/http-configuration-settings.md` +- `references/miscellaneous-settings.md` +- `references/model-settings.md` +- `references/sdk-docs-configuration-settings.md` +- `references/sdk-interface-customization-settings.md` +- `references/serialization-settings.md` +- `references/timeout-and-retries-settings.md` + +**If a matching setting is found in any of those files:** + +Follow the numbered steps in that reference file to apply the setting and verify the output. Then continue below: + +1. If the input directory is not already known, ask: "What is the path to the directory that contains the `src/` folder?" +2. Open `/src/spec/APIMATIC-META.json`. If this is a fresh project being scaffolded (the main Step 2 — Determine the input directory — is in progress), note the setting and apply it to `APIMATIC-META.json` as part of scaffolding — then continue to generation. If the file does not exist and the project should already have it, follow `references/first-time-setup.md` to scaffold the project first. +3. Locate the `CodeGenSettings` object. Add or update the relevant key with the appropriate value. +4. Save the file. +5. Regenerate the SDK — proceed from [Step 3 to Step 7](#step-3-choose-the-language), skip the steps for which you have the values already known (language, destination, and API version). + +This is always the preferred approach when a CodeGen setting covers the request. Settings applied this way are baked into the generation config and survive every future regeneration — no manual file edits required. + +**If the setting is not listed there:** + +Continue to the [SDK Source Tree Check](#sdk-source-tree-check) for file-level customization. + +--- + +## SDK Source Tree Check + +Look for `/sdk-source-tree/` and within it a file named after the target language (e.g. `.php`, `.typescript`, `.python`). + +**If `sdk-source-tree` is present and has an entry for the target language:** + +Proceed directly to `references/save-changes.md`. + +**If `sdk-source-tree` is absent or has no entry for the target language:** + +Change tracking has never been initialized. Follow Steps 2 through 7 below to generate the SDK with `--track-changes`. Use any values already known from context (language, input dir, API version) — do not ask for them again. Only ask for values that are genuinely unknown. + +There is one additional concern depending on context: + +- **User has already made customizations (Fast Path — Already-Customized SDK):** + The SDK must **not** be generated into the same folder as the user's existing customized SDK — doing so will overwrite their changes. Before running Step 7, ask only for the destination: "Change tracking isn't enabled for this SDK yet. I need to run a fresh generation to initialize it, but generating into your current SDK folder would overwrite your changes. Would you like me to use a temporary folder, or do you have a preferred destination?" + - If user provides a path → use it as `--destination` in Step 4. + - If user says temporary/default → use `/sdk/temp/` as `--destination` in Step 4. After generation, delete the `/sdk/temp` directory — it is not needed. + After Step 7 completes, follow `references/save-changes.md` with `--sdk` pointing at the user's **original** customized SDK path, so their customizations are captured — not the temp output. + +- **Claude is applying the customization (Fast Path — Apply a Specific Customization):** + No destination conflict — proceed through Steps 2–7 normally with `--track-changes`. After generation, apply the requested customizations to the generated SDK following the [Customization Guidelines](#customization-guidelines) section, then follow `references/save-changes.md`. + +## Customization Guidelines + +Apply these principles whenever you are making SDK customizations on the user's behalf, and share them as tips when the user is customizing themselves. + +1. **Add custom logic in a new file** where possible. +2. **Avoid editing generated files directly.** +3. **If you must edit a generated file**, add your changes at the top or bottom to reduce merge conflicts. + +--- + +## Generate an SDK + +> These steps (Prerequisites through Step 7) are also used when initializing change tracking as part of a customization workflow. + +## Prerequisites + +Confirm these are in place before starting: + +- **Node.js >= 20 and npm installed** + If not installed, download from https://nodejs.org (LTS version recommended). Verify with: + + ``` + node --version + ``` + +- **APIMatic account** + Free trial available at app.apimatic.io. Required for authentication. + +- **APIMatic CLI installed globally:** + + ``` + npm install -g @apimatic/cli + ``` + + Verify the CLI is available: + + ``` + apimatic --version + ``` + + If the version command fails, the CLI is not installed. Re-run the install command above. + +--- + +## Step 1: Authenticate with APIMatic + +First check whether the user is already authenticated: + +``` +apimatic auth status +``` + +If the output shows an account email, authentication is already in place — skip to Step 2. + +**Primary flow (browser-based):** + +Run the auth launcher script from the project directory. It spawns `apimatic auth login` as a detached process so the terminal does not block: + +``` +node {skill_dir}/scripts/auth-login.mjs +``` + +Where `{skill_dir}` is the absolute path to the directory containing the `apimatic-sdk` skill file (the `auth-login.mjs` script lives there). + +The script launches the browser OAuth flow and immediately returns. Relay the following message to the user: "A browser window has opened. Complete sign-in in the browser, then confirm here when done." + +Wait for the user to confirm sign-in is complete before proceeding. + +After confirmation, verify auth succeeded: + +``` +apimatic auth status +``` + +The output should show the account email. If it does not, authentication did not complete — try the fallback below. + +**Fallback flow (API key):** + +Use this when browser auth is not available (CI environment, headless system) or when the user prefers a key-based approach. + +Option 1 — CLI flag: + +``` +apimatic auth login --auth-key=YOUR_API_KEY +``` + +Option 2 — environment variable (no login command needed): + +```bash +# macOS / Linux / bash / zsh: +export APIMATIC_API_KEY=YOUR_API_KEY + +# Windows PowerShell: +$env:APIMATIC_API_KEY = "YOUR_API_KEY" + +# Windows Command Prompt: +set APIMATIC_API_KEY=YOUR_API_KEY +``` + +API keys are generated at: APIMatic Dashboard > Account > API Keys. + +**If both methods fail:** + +Stop the workflow. Tell the user: + +"Authentication failed. Check that your APIMatic account is active, your API key is correct, and you have internet access to apimatic.io. If using browser login, try the --auth-key fallback instead." + +Do not proceed past this point until authentication is confirmed. + +## Step 2: Determine the input directory + +If you do not know whether the user has an existing project with a `src/` folder, ask: + +"Is this your first time generating an SDK for this API, or have you generated one before?" + +- **Has a `src/` folder →** Ask: "What is the path to the directory that contains the `src/` folder?" + The `--input` flag will point to this directory. + +- **Starting from scratch →** Read `references/first-time-setup.md` and follow every step in order to scaffold the project directory with `src/spec/`, the user's API spec, and `APIMATIC-META.json`. Then continue to Step 3. + +## Step 3: Choose the language + +If the language is not already known from context, ask the user which language they want to generate the SDK in. Present the supported options: + +| Flag value | Language | +| ------------ | ---------- | +| `csharp` | C# | +| `java` | Java | +| `php` | PHP | +| `python` | Python | +| `ruby` | Ruby | +| `typescript` | TypeScript | +| `go` | Go | + +## Step 4: Choose the destination + +If the destination is not already known from context, ask: "Do you have a specific path where you want the SDK to be generated, or should I use the default location?" + +- **User provides a path →** Use the `--destination` flag with the given path. +- **User says default / no preference →** Omit the `--destination` flag. The SDK will be generated at `/sdk/` (or `/sdk//` if multiple API versions exist). + +## Step 5: Choose the API version + +Check whether the user wants to generate the SDK for a specific API version. Look for phrases like "versioned build", "specific version", "for version X", "v2", "api version", or any mention of targeting a particular version of their API. + +- **User specifies a version →** Add `--api-version=` to the generate command (e.g., `--api-version=v2`). +- **User doesn't mention versioning →** Omit the `--api-version` flag. Do not ask. + +## Step 6: Customization intent + +If the user has already described a specific change they want (e.g., "remove the docs folder", "disable documentation", "set the project name", "disable linting"), **check codegen settings first** — see the [CodeGen Settings Check](#codegen-settings-check) section, which will have you scan the individual reference files — before planning any manual file edits or deletions or additions. + +If the change maps to a CodeGen setting: + +- **New project (being scaffolded now):** Apply the setting to `APIMATIC-META.json` before generating. The setting is baked in from the start — no post-generation editing needed. +- **Existing project (already has `APIMATIC-META.json`):** Apply the setting now and regenerate. The setting takes effect automatically. + +**Never plan to apply a CodeGen-covered customization by manually editing or deleting or adding generated files.** For example, "remove the docs folder" maps to `DisableDocs: true` — the correct fix is to set it before generation, not to delete the output folder afterward as a custom code injection. + +If the change does not map to any CodeGen setting, continue below. + +If not already known from context, ask: "Would you like to customize the SDK after generating it? (e.g., add custom code, modify generated files)" + +- **User says yes →** + + Ask: "Do you already have a generated SDK you've customized, or are you starting fresh?" + - **Already has a customized SDK →** Skip generation entirely. Ask: "Would you like me to apply the customizations, or will you handle them yourself?" then follow the appropriate path below. + - **Starting fresh →** Add the `--track-changes` flag to the generate command. After generation completes in Step 7, ask: "Would you like me to apply the customizations, or will you handle them yourself?" then follow the appropriate path below. + + **If the skill applies customizations:** + + Ask the user what changes they want made. Apply them following the [Customization Guidelines](#customization-guidelines) section. Once the changes are in place, follow `references/save-changes.md`. See `examples/generate-customize-save.md` for the expected flow of commands — flags and paths will differ based on the user's setup. + + **If the user applies customizations:** + + See `examples/generate-customize-save.md` for the expected flow of commands — flags and paths will differ based on the user's setup. + + Share these tips before handing off: + + > - Add custom logic in a **new file** where possible — new files are never overwritten on regeneration. + > - Avoid editing generated files directly. + > - If you must edit a generated file, add your changes at the **top or bottom** to reduce merge conflicts. + + Then prompt: "Make your customizations now, then let me know when you're ready to save them." Once they confirm, follow `references/save-changes.md`. + +- **User says no / no preference →** Omit the `--track-changes` flag. + +## Step 7: Generate the SDK + +Navigate to the project root (the directory that contains `src/`): + +``` +cd your-project-directory +``` + +Run the generate command with the chosen language: + +``` +apimatic sdk generate --language= +``` + +To specify the input directory explicitly (the parent directory containing `src/`): + +``` +apimatic sdk generate --input=path/to/parent-of-src --language= +``` + +**With an API key directly (recommended for CI — no interactive auth needed):** + +``` +apimatic sdk generate --input=path/to/parent-of-src --language= --auth-key=YOUR_API_KEY +``` + +**If SDK generation fails:** + +1. **Authentication error:** Re-run `apimatic auth status` to verify. If expired, re-authenticate (Step 1). +2. **Missing `src/` folder or spec file:** Check that the input directory contains a `src/` folder with the API spec in `src/spec/`. +3. **SDK already exists at destination:** The CLI will refuse to overwrite. Immediately ask the user: "An SDK already exists at the destination. Would you like to overwrite it?" If yes, re-run the same command with `--force` appended (see Additional flags). If no, ask for a different destination path and re-run with `--destination=`. +4. **`apimatic` command not found:** Run `npm install -g @apimatic/cli` and verify with `apimatic --version`. +5. **Any other error:** Read the exact error message from the CLI output. Do not retry automatically — diagnose the specific error first. + +## Additional flags + +- `--force, -f` : Overwrite if an SDK already exists in the destination. Use for repeated CI builds. +- `--zip` : Download the generated SDK as a .zip archive instead of a directory. +- `--track-changes` : Enable change tracking to preserve manual customizations across regenerations. Must be used during the initial generation to set up the source tree. See `references/save-changes.md` for how to save changes after generation. +- `--skip-changes` : Generate the SDK without reapplying saved customizations, even if change tracking is enabled. Use when the user wants to preview the plain generated output. Saved customizations are not modified and will still be applied in future runs unless explicitly removed. + +## Publish an SDK + +> **Only follow this section when the user explicitly requests publishing** (e.g., "publish the SDK", "push to npm", "push to GitHub", "run sdk publish"). Phrases like "generate an SDK for publishing" or "generate for npm" express intent but are not publish instructions — stop at SDK generation in those cases. + +Publish an SDK to a package registry (npm, PyPI, NuGet) or source code repository (GitHub) using a publishing profile configured in the APIMatic App. + +### Step 1: Authenticate with APIMatic + +Follow [Step 1: Authenticate with APIMatic](#step-1-authenticate-with-apimatic) above. + +### Step 2: Find the Publishing Profile ID + +If the user does not already know their profile ID, run: + +``` +apimatic publishing profile list +``` + +This lists all publishing profiles with their names, IDs, and enabled languages. Do not forward the raw table output to the user — summarize the available profiles and their IDs in plain language so the user can identify the one they want. + +### Step 3: Run SDK Publish + +See `examples/publish-sdk.md` for the expected command and output — flags and paths will differ based on the user's setup. + +**Non-interactive flow** requires all four of these flags — missing any one will drop the CLI into the interactive prompt: + +``` +apimatic sdk publish --profile-id= --language= --version= --publish-type= +``` + +#### Flags + +| Flag | Required (non-interactive) | Description | +| -------------------- | -------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| `--profile-id`, `-p` | Yes | ID of the publishing profile to use. Run `apimatic publishing profile list` to find your profile ID. | +| `--language`, `-l` | Yes | SDK language to generate and publish. | +| `--version`, `-v` | Yes | Semantic version of the SDK (e.g. `1.0.0`). | +| `--publish-type` | Yes (at least one) | Publishing target(s): `package` or `sourcecode` only. Can be specified multiple times. See [Publish Types](#publish-types). | +| `--input` | No | Path to the parent directory containing the `src/` directory. Defaults to `./`. | +| `--destination` | No | Directory where the generated SDK will be saved locally. Defaults to `/sdk`. | +| `--dry-run` | No | Generate the SDK locally for review without publishing. | +| `--force`, `-f` | No | Overwrite existing output without prompting. | + +#### Publish Types + +Pass `--publish-type` once or twice to target one or both destinations. The language and publish type(s) must be configured in the publishing profile. + +``` +# Publish to package registry only +apimatic sdk publish --profile-id= --language=java --version=2.0.0 --publish-type=package + +# Publish to both package registry and source repository +apimatic sdk publish --profile-id= --language=typescript --version=1.0.0 --publish-type=package --publish-type=sourcecode +``` + +#### Dry Run + +Use `--dry-run` to generate the SDK locally and inspect it before publishing: + +``` +apimatic sdk publish --dry-run --profile-id= --language=python --version=1.0.0 --publish-type=package +``` + +### If SDK Publish Fails + +1. **Profile not found or invalid ID:** Run `apimatic publishing profile list` to confirm the correct profile ID. +2. **Language or publish type not supported by profile:** The language and publish type(s) must be enabled in the publishing profile. Check the profile configuration in the APIMatic App. +3. **Authentication error:** Re-run `apimatic auth status` and re-authenticate if needed. +4. **SDK already exists at destination:** Re-run with `--force` to overwrite. +5. **Any other error:** Read the exact error message from the CLI output. Do not retry automatically — diagnose the specific error first. + +--- diff --git a/skills/apimatic-sdk/evals/evals.json b/skills/apimatic-sdk/evals/evals.json new file mode 100644 index 0000000..3522ed1 --- /dev/null +++ b/skills/apimatic-sdk/evals/evals.json @@ -0,0 +1,1666 @@ +{ + "skill_name": "apimatic-sdk", + "evals": [ + { + "id": 0, + "prompt": "I need to generate a Python SDK for my API. I haven't used the APIMatic CLI before. My project is at ~/my-api-project/ and it has a src/ folder with my spec in src/spec/. Can you help?", + "expected_output": "The agent checks auth status, walks through the login flow (browser-based primary, API key fallback), waits for user confirmation, asks about destination preference, then runs `apimatic sdk generate --language=python` from the project root. Does NOT add --zip unless the user asked for it.", + "files": [], + "assertions": [ + { + "id": "checks-auth-status", + "description": "Response includes checking auth status before login", + "type": "contains", + "value": "apimatic auth status" + }, + { + "id": "runs-auth-login", + "description": "Response includes the auth login command", + "type": "contains", + "value": "apimatic auth login" + }, + { + "id": "waits-for-user-confirmation", + "description": "Response pauses and asks the user to confirm sign-in before proceeding", + "type": "contains_any", + "value": [ + "confirm", + "let me know", + "once you", + "when you're done", + "when done", + "after you" + ] + }, + { + "id": "generates-python-sdk", + "description": "Response includes the SDK generate command with python language", + "type": "contains", + "value": "--language=python" + }, + { + "id": "does-not-add-zip-unprompted", + "description": "Response does NOT add --zip flag since the user did not request it", + "type": "not_contains", + "value": "--zip" + }, + { + "id": "asks-about-destination", + "description": "Response asks the user about the SDK output destination", + "type": "contains_any", + "value": [ + "destination", + "where you want the SDK", + "output path", + "default location", + "specific path" + ] + } + ] + }, + { + "id": 1, + "prompt": "I already have APIMatic CLI set up and authenticated. Generate a TypeScript SDK for the project at D:\\work\\payments-api\\ — it has the src/ directory with the spec. Give me a zip. Put it in D:\\output\\ts-sdk.", + "expected_output": "The agent skips auth, navigates to or uses --input with the parent directory containing src/, and runs apimatic sdk generate --language=typescript --zip --destination=D:\\output\\ts-sdk.", + "files": [], + "assertions": [ + { + "id": "skips-auth", + "description": "Response does NOT run auth login since user said they are already authenticated", + "type": "not_contains", + "value": "apimatic auth login" + }, + { + "id": "uses-correct-directory", + "description": "Response references the user's project directory path", + "type": "contains_any", + "value": [ + "payments-api", + "D:\\work\\payments-api", + "D:/work/payments-api" + ] + }, + { + "id": "generates-typescript-sdk", + "description": "Response includes the SDK generate command with typescript language", + "type": "contains", + "value": "--language=typescript" + }, + { + "id": "includes-zip-flag", + "description": "Response includes --zip flag as requested by the user", + "type": "contains", + "value": "--zip" + }, + { + "id": "uses-custom-destination", + "description": "Response uses the --destination flag with the user's specified path", + "type": "contains_any", + "value": [ + "--destination", + "D:\\output\\ts-sdk", + "D:/output/ts-sdk" + ] + }, + { + "id": "runs-from-project-root", + "description": "Response runs from the project root (parent of src/), not from inside src/", + "type": "not_contains", + "value": "cd src" + } + ] + }, + { + "id": 2, + "prompt": "I want to create a Go SDK for my REST API. I have my OpenAPI spec at ./openapi.yaml but no project directory set up yet. What do I do?", + "expected_output": "The agent tells the user they need to create a project directory with a src/ folder and place the spec inside src/spec/ before generating. Does NOT run apimatic sdk generate against a raw spec file.", + "files": [], + "assertions": [ + { + "id": "mentions-src-directory", + "description": "Response tells user to create src/ directory structure", + "type": "contains_any", + "value": [ + "src/", + "src\\", + "src folder", + "src directory" + ] + }, + { + "id": "mentions-spec-in-src-spec", + "description": "Response tells user to place the spec in src/spec/", + "type": "contains_any", + "value": [ + "src/spec", + "src\\spec", + "spec/" + ] + }, + { + "id": "does-not-generate-directly", + "description": "Response does NOT directly run sdk generate against the raw spec file without setup", + "type": "not_contains", + "value": "apimatic sdk generate --input=./openapi.yaml" + }, + { + "id": "mentions-go-language", + "description": "Response acknowledges the Go language choice", + "type": "contains_any", + "value": [ + "go", + "Go", + "--language=go" + ] + }, + { + "id": "does-not-mention-portal-skill", + "description": "Response does NOT direct user to the portal skill — tells them to set up manually", + "type": "not_contains_any", + "value": [ + "portal skill", + "apimatic-portal", + "apimatic portal" + ] + } + ] + }, + { + "id": 3, + "prompt": "I already generated a C# SDK yesterday but I need to regenerate it with some spec changes. The project is at ./my-api/ and I'm already logged in. Just overwrite the old one.", + "expected_output": "The agent skips auth, runs apimatic sdk generate --language=csharp --force from the project directory to overwrite the existing SDK.", + "files": [], + "assertions": [ + { + "id": "skips-auth", + "description": "Response does NOT run auth login since user said they are logged in", + "type": "not_contains", + "value": "apimatic auth login" + }, + { + "id": "generates-csharp-sdk", + "description": "Response includes the SDK generate command with csharp language", + "type": "contains", + "value": "--language=csharp" + }, + { + "id": "uses-force-flag", + "description": "Response includes --force flag to overwrite the existing SDK", + "type": "contains", + "value": "--force" + }, + { + "id": "references-project-dir", + "description": "Response references the user's project directory", + "type": "contains_any", + "value": [ + "my-api", + "./my-api" + ] + }, + { + "id": "does-not-add-zip-unprompted", + "description": "Response does NOT add --zip since user did not request it", + "type": "not_contains", + "value": "--zip" + } + ] + }, + { + "id": 4, + "prompt": "Generate a Ruby SDK for my API project at ~/ruby-project/. I'm authenticated. Use the default output location, no zip needed.", + "expected_output": "The agent skips auth, runs apimatic sdk generate --language=ruby without --destination or --zip flags.", + "files": [], + "assertions": [ + { + "id": "skips-auth", + "description": "Response does NOT run auth login", + "type": "not_contains", + "value": "apimatic auth login" + }, + { + "id": "generates-ruby-sdk", + "description": "Response includes the SDK generate command with ruby language", + "type": "contains", + "value": "--language=ruby" + }, + { + "id": "no-destination-flag", + "description": "Response does NOT include --destination since user wants default", + "type": "not_contains", + "value": "--destination" + }, + { + "id": "no-zip-flag", + "description": "Response does NOT include --zip since user explicitly said no zip", + "type": "not_contains", + "value": "--zip" + }, + { + "id": "references-project-dir", + "description": "Response references the user's project directory", + "type": "contains_any", + "value": [ + "ruby-project", + "~/ruby-project" + ] + } + ] + }, + { + "id": 5, + "prompt": "I completed browser sign-in for APIMatic but apimatic auth status doesn't show my email. How do I fix this?", + "expected_output": "The agent offers the API key fallback (apimatic auth login --auth-key=YOUR_API_KEY), tells the user where to find API keys, and does NOT proceed to SDK generation until auth is confirmed.", + "files": [], + "assertions": [ + { + "id": "offers-api-key-fallback", + "description": "Response offers the --auth-key fallback", + "type": "contains", + "value": "--auth-key" + }, + { + "id": "mentions-api-keys-location", + "description": "Response tells user where to find their API key", + "type": "contains_any", + "value": [ + "API Keys", + "Account > API Keys", + "APIMatic Dashboard", + "app.apimatic.io" + ] + }, + { + "id": "does-not-proceed-to-generate", + "description": "Response does NOT proceed to SDK generation while auth is unconfirmed", + "type": "not_contains", + "value": "apimatic sdk generate" + } + ] + }, + { + "id": 6, + "prompt": "I want to generate a Java SDK and I plan to customize the generated code afterwards. My project is at ./my-java-api/ and I'm authenticated.", + "expected_output": "The agent adds the --track-changes flag to enable change tracking so customizations are preserved across regenerations.", + "files": [], + "assertions": [ + { + "id": "skips-auth", + "description": "Response does NOT run auth login", + "type": "not_contains", + "value": "apimatic auth login" + }, + { + "id": "generates-java-sdk", + "description": "Response includes the SDK generate command with java language", + "type": "contains", + "value": "--language=java" + }, + { + "id": "uses-track-changes", + "description": "Response includes --track-changes flag since user wants to customize", + "type": "contains", + "value": "--track-changes" + }, + { + "id": "references-project-dir", + "description": "Response references the user's project directory", + "type": "contains_any", + "value": [ + "my-java-api", + "./my-java-api" + ] + } + ] + }, + { + "id": 7, + "prompt": "I'm setting up a CI/CD pipeline with GitHub Actions to generate a PHP SDK on every push. I have an API key stored as a secret. How do I run the SDK generation non-interactively?", + "expected_output": "The agent recommends apimatic sdk generate --language=php --auth-key=YOUR_API_KEY as the CI-appropriate pattern. Does NOT suggest browser-based login.", + "files": [], + "assertions": [ + { + "id": "runs-sdk-generate", + "description": "Response includes apimatic sdk generate", + "type": "contains", + "value": "apimatic sdk generate" + }, + { + "id": "uses-auth-key-flag", + "description": "Response includes the --auth-key flag", + "type": "contains", + "value": "--auth-key" + }, + { + "id": "generates-php-sdk", + "description": "Response includes --language=php", + "type": "contains", + "value": "--language=php" + }, + { + "id": "recommends-for-ci", + "description": "Response frames --auth-key as appropriate for CI environments", + "type": "contains_any", + "value": [ + "CI", + "non-interactive", + "without browser", + "pipeline", + "GitHub Actions" + ] + }, + { + "id": "no-browser-login-for-ci", + "description": "Response does NOT recommend browser-based login for CI", + "type": "not_contains", + "value": "apimatic auth login\n" + } + ] + }, + { + "id": 8, + "prompt": "I ran npm install -g @apimatic/cli but apimatic --version says command not found. I need to generate a Python SDK.", + "expected_output": "The agent troubleshoots the CLI installation issue and does NOT proceed to SDK generation until the CLI is verified.", + "files": [], + "assertions": [ + { + "id": "suggests-reinstall", + "description": "Response suggests reinstalling the CLI", + "type": "contains", + "value": "npm install -g @apimatic/cli" + }, + { + "id": "does-not-proceed-to-generate", + "description": "Response does NOT proceed to SDK generation while CLI is missing", + "type": "not_contains", + "value": "apimatic sdk generate" + }, + { + "id": "does-not-proceed-to-auth", + "description": "Response does NOT proceed to authentication while CLI is missing", + "type": "not_contains", + "value": "apimatic auth login" + }, + { + "id": "mentions-version-check", + "description": "Response mentions verifying with apimatic --version", + "type": "contains", + "value": "apimatic --version" + } + ] + }, + { + "id": 9, + "prompt": "I already have a TypeScript SDK that I've customized with some extra helper methods. I want to save those changes so they're preserved when I regenerate later. I'm authenticated. My project is at ./ts-api/.", + "expected_output": "The agent recognizes the user already has a customized SDK, skips SDK generation entirely, and runs apimatic sdk save-changes --language=typescript.", + "files": [], + "assertions": [ + { + "id": "does-not-regenerate", + "description": "Response does NOT run sdk generate since user already has their SDK customized", + "type": "not_contains", + "value": "apimatic sdk generate" + }, + { + "id": "runs-save-changes", + "description": "Response runs the sdk save-changes command", + "type": "contains", + "value": "apimatic sdk save-changes" + }, + { + "id": "uses-typescript-language", + "description": "Response uses --language=typescript", + "type": "contains", + "value": "--language=typescript" + }, + { + "id": "references-project-dir", + "description": "Response references the user's project directory", + "type": "contains_any", + "value": [ + "ts-api", + "./ts-api" + ] + } + ] + }, + { + "id": 10, + "prompt": "I want to generate a Python SDK for my API project at ./python-api/ and then add some custom utility functions to it. I'm authenticated and have the src/ folder set up already.", + "expected_output": "The agent generates the SDK with --track-changes enabled, then prompts the user to make their customizations, and runs apimatic sdk save-changes --language=python once the user confirms they are done.", + "files": [], + "assertions": [ + { + "id": "generates-with-track-changes", + "description": "Response generates the SDK with --track-changes flag", + "type": "contains", + "value": "--track-changes" + }, + { + "id": "generates-python-sdk", + "description": "Response uses --language=python", + "type": "contains", + "value": "--language=python" + }, + { + "id": "prompts-user-to-customize", + "description": "Response asks the user to make their customizations before saving", + "type": "contains_any", + "value": [ + "make your customizations", + "add your customizations", + "make your changes", + "add your changes", + "let me know when", + "once you've made", + "when you're ready", + "when you're done" + ] + }, + { + "id": "runs-save-changes", + "description": "Response includes the sdk save-changes command for the next step", + "type": "contains", + "value": "apimatic sdk save-changes" + } + ] + }, + { + "id": 11, + "prompt": "I have no SDK yet and I want to generate one from scratch and customize it. I don't have a project directory set up. My API spec is at ~/specs/payments.yaml. I'm authenticated.", + "expected_output": "The agent scaffolds the project directory (src/spec/ structure), generates the SDK with --track-changes, prompts the user to make customizations, then runs apimatic sdk save-changes.", + "files": [], + "assertions": [ + { + "id": "scaffolds-src-structure", + "description": "Response creates the src/spec/ directory structure before generating", + "type": "contains_any", + "value": [ + "src/spec", + "src\\spec", + "mkdir", + "New-Item" + ] + }, + { + "id": "generates-with-track-changes", + "description": "Response generates the SDK with --track-changes flag", + "type": "contains", + "value": "--track-changes" + }, + { + "id": "prompts-user-to-customize", + "description": "Response asks the user to add their customizations before saving", + "type": "contains_any", + "value": [ + "make your customizations", + "add your customizations", + "make your changes", + "add your changes", + "let me know when", + "once you've made", + "when you're ready", + "when you're done" + ] + }, + { + "id": "runs-save-changes", + "description": "Response includes the sdk save-changes command for the next step", + "type": "contains", + "value": "apimatic sdk save-changes" + } + ] + }, + { + "id": 12, + "prompt": "I have change tracking enabled for my Java SDK but I want to see what the SDK looks like without my customizations applied. I'm authenticated, project is at ./java-api/.", + "expected_output": "The agent runs apimatic sdk generate --language=java --skip-changes and explains this is non-destructive — saved customizations are not removed.", + "files": [], + "assertions": [ + { + "id": "generates-java-sdk", + "description": "Response uses --language=java", + "type": "contains", + "value": "--language=java" + }, + { + "id": "uses-skip-changes-flag", + "description": "Response includes the --skip-changes flag", + "type": "contains", + "value": "--skip-changes" + }, + { + "id": "non-destructive-explanation", + "description": "Response clarifies that saved customizations are not removed", + "type": "contains_any", + "value": [ + "not modified", + "not removed", + "still applied", + "still be applied", + "won't be removed", + "are not modified", + "are preserved", + "untouched", + "non-destructive" + ] + }, + { + "id": "does-not-delete-sdk-source-tree", + "description": "Response does NOT tell user to delete the sdk-source-tree to preview", + "type": "not_contains", + "value": "delete" + } + ] + }, + { + "id": 13, + "prompt": "I need to generate a Go SDK for version v2 of my API. My project is at ./multi-version-api/ and it has a src/ folder set up. I'm already authenticated.", + "expected_output": "The agent includes --api-version=v2 in the generate command to target the specific API version, along with --language=go.", + "files": [], + "assertions": [ + { + "id": "skips-auth", + "description": "Response does NOT run auth login since user said they are authenticated", + "type": "not_contains", + "value": "apimatic auth login" + }, + { + "id": "generates-go-sdk", + "description": "Response includes the SDK generate command with go language", + "type": "contains", + "value": "--language=go" + }, + { + "id": "uses-api-version-flag", + "description": "Response includes --api-version=v2 to target the specific API version", + "type": "contains", + "value": "--api-version=v2" + }, + { + "id": "references-project-dir", + "description": "Response references the user's project directory", + "type": "contains_any", + "value": [ + "multi-version-api", + "./multi-version-api" + ] + }, + { + "id": "does-not-add-zip-unprompted", + "description": "Response does NOT add --zip since user did not request it", + "type": "not_contains", + "value": "--zip" + } + ] + }, + { + "id": 15, + "prompt": "I want to generate a Python SDK for my API project at ./payments-api/ and make sure every generated file has a copyright notice in it. I'm already authenticated and the src/ folder is set up.", + "expected_output": "The agent recognizes that adding a copyright notice to every file is covered by the ShortCopyrightNotice CodeGen setting. It updates APIMATIC-META.json with ShortCopyrightNotice set to the copyright text, then generates the SDK. It does NOT manually edit generated files or inject copyright via custom code.", + "files": [], + "assertions": [ + { + "id": "uses-short-copyright-notice-setting", + "description": "Response uses the ShortCopyrightNotice CodeGen setting in APIMATIC-META.json", + "type": "contains", + "value": "ShortCopyrightNotice" + }, + { + "id": "updates-apimatic-meta", + "description": "Response updates APIMATIC-META.json with the copyright setting", + "type": "contains", + "value": "APIMATIC-META.json" + }, + { + "id": "generates-python-sdk", + "description": "Response generates the SDK with --language=python", + "type": "contains", + "value": "--language=python" + }, + { + "id": "skips-auth", + "description": "Response does NOT run auth login since user is already authenticated", + "type": "not_contains", + "value": "apimatic auth login" + }, + { + "id": "does-not-manually-inject-copyright", + "description": "Response does NOT manually edit generated files or add copyright as custom code injection", + "type": "not_contains_any", + "value": [ + "sdk-source-tree", + "custom code injection", + "inject the copyright", + "manually add", + "manually edit" + ] + }, + { + "id": "references-project-dir", + "description": "Response references the user's project directory", + "type": "contains_any", + "value": [ + "payments-api", + "./payments-api" + ] + } + ] + }, + { + "id": 14, + "prompt": "I'm running SDK generation in Docker and can't run apimatic auth login interactively. I don't want the API key to appear in my shell history. What's the cleanest way to authenticate?", + "expected_output": "The agent recommends setting the APIMATIC_API_KEY environment variable (no login command needed) as the cleanest approach that avoids the key appearing in command history. It also mentions the --auth-key flag as an alternative.", + "files": [], + "assertions": [ + { + "id": "recommends-env-var", + "description": "Response recommends the APIMATIC_API_KEY environment variable", + "type": "contains", + "value": "APIMATIC_API_KEY" + }, + { + "id": "shows-env-var-syntax", + "description": "Response shows how to set the environment variable", + "type": "contains_any", + "value": [ + "export APIMATIC_API_KEY", + "$env:APIMATIC_API_KEY", + "set APIMATIC_API_KEY" + ] + }, + { + "id": "does-not-recommend-browser-login", + "description": "Response does NOT recommend browser-based auth for Docker/CI", + "type": "not_contains", + "value": "auth-login.mjs" + }, + { + "id": "mentions-no-login-command-needed", + "description": "Response notes that the env var approach requires no login command", + "type": "contains_any", + "value": [ + "no login", + "without login", + "no auth login", + "without running", + "no login command", + "without the login", + "no interactive" + ] + } + ] + }, + { + "id": 16, + "prompt": "I want to generate a TypeScript SDK without any documentation files. My project is at ./my-api/ and I'm already authenticated with the src/ folder set up.", + "expected_output": "The agent recognizes that disabling docs is covered by the DisableDocs CodeGen setting. It updates APIMATIC-META.json with DisableDocs set to true, then generates the SDK. It does NOT manually delete the docs folder or README.", + "files": [], + "assertions": [ + { + "id": "uses-disable-docs-setting", + "description": "Response uses the DisableDocs CodeGen setting", + "type": "contains", + "value": "DisableDocs" + }, + { + "id": "updates-apimatic-meta", + "description": "Response updates APIMATIC-META.json", + "type": "contains", + "value": "APIMATIC-META.json" + }, + { + "id": "generates-typescript-sdk", + "description": "Response generates the SDK with --language=typescript", + "type": "contains", + "value": "--language=typescript" + }, + { + "id": "skips-auth", + "description": "Response does NOT run auth login since user is already authenticated", + "type": "not_contains", + "value": "apimatic auth login" + }, + { + "id": "does-not-manually-delete-docs", + "description": "Response does NOT manually delete docs folder or use file deletion commands", + "type": "not_contains_any", + "value": [ + "rm ", + "del ", + "Remove-Item", + "rmdir", + "manually delete", + "delete the docs" + ] + } + ] + }, + { + "id": 17, + "prompt": "Disable linting in my PHP SDK. My project is at ./php-project/ and I'm already authenticated.", + "expected_output": "The agent recognizes that disabling linting is covered by the DisableLinting CodeGen setting. It updates APIMATIC-META.json with DisableLinting set to true, then regenerates the SDK.", + "files": [], + "assertions": [ + { + "id": "uses-disable-linting-setting", + "description": "Response uses the DisableLinting CodeGen setting", + "type": "contains", + "value": "DisableLinting" + }, + { + "id": "updates-apimatic-meta", + "description": "Response updates APIMATIC-META.json", + "type": "contains", + "value": "APIMATIC-META.json" + }, + { + "id": "generates-php-sdk", + "description": "Response generates the SDK with --language=php", + "type": "contains", + "value": "--language=php" + }, + { + "id": "skips-auth", + "description": "Response does NOT run auth login since user is already authenticated", + "type": "not_contains", + "value": "apimatic auth login" + } + ] + }, + { + "id": 18, + "prompt": "Set the timeout to 60 seconds and enable retry with 3 attempts for my C# SDK. My project is at ./csharp-api/ and I'm already authenticated.", + "expected_output": "The agent recognizes that timeout and retry settings are covered by the Timeout, RetryOnTimeout, and Retries CodeGen settings. It updates APIMATIC-META.json with all relevant settings, then regenerates the SDK.", + "files": [], + "assertions": [ + { + "id": "uses-timeout-setting", + "description": "Response uses the Timeout CodeGen setting", + "type": "contains", + "value": "Timeout" + }, + { + "id": "uses-retries-setting", + "description": "Response uses the Retries CodeGen setting", + "type": "contains", + "value": "Retries" + }, + { + "id": "updates-apimatic-meta", + "description": "Response updates APIMATIC-META.json", + "type": "contains", + "value": "APIMATIC-META.json" + }, + { + "id": "generates-csharp-sdk", + "description": "Response generates the SDK with --language=csharp", + "type": "contains", + "value": "--language=csharp" + }, + { + "id": "skips-auth", + "description": "Response does NOT run auth login since user is already authenticated", + "type": "not_contains", + "value": "apimatic auth login" + } + ] + }, + { + "id": 19, + "prompt": "Set the SDK project name to 'PaymentsSDK' for my Java SDK. My project is at ./payments/ and I'm already authenticated.", + "expected_output": "The agent recognizes that setting the project name is covered by the ProjectName CodeGen setting. It updates APIMATIC-META.json with ProjectName set to PaymentsSDK, then regenerates the SDK.", + "files": [], + "assertions": [ + { + "id": "uses-project-name-setting", + "description": "Response uses the ProjectName CodeGen setting", + "type": "contains", + "value": "ProjectName" + }, + { + "id": "uses-correct-name", + "description": "Response includes the user's requested project name", + "type": "contains", + "value": "PaymentsSDK" + }, + { + "id": "updates-apimatic-meta", + "description": "Response updates APIMATIC-META.json", + "type": "contains", + "value": "APIMATIC-META.json" + }, + { + "id": "generates-java-sdk", + "description": "Response generates the SDK with --language=java", + "type": "contains", + "value": "--language=java" + }, + { + "id": "skips-auth", + "description": "Response does NOT run auth login since user is already authenticated", + "type": "not_contains", + "value": "apimatic auth login" + } + ] + }, + { + "id": 20, + "prompt": "Enable logging in my Python SDK. My project is at ./py-api/ and I'm already authenticated.", + "expected_output": "The agent recognizes that enabling logging is covered by the EnableLogging CodeGen setting. It updates APIMATIC-META.json with EnableLogging set to true, then regenerates the SDK.", + "files": [], + "assertions": [ + { + "id": "uses-enable-logging-setting", + "description": "Response uses the EnableLogging CodeGen setting", + "type": "contains", + "value": "EnableLogging" + }, + { + "id": "updates-apimatic-meta", + "description": "Response updates APIMATIC-META.json", + "type": "contains", + "value": "APIMATIC-META.json" + }, + { + "id": "generates-python-sdk", + "description": "Response generates the SDK with --language=python", + "type": "contains", + "value": "--language=python" + }, + { + "id": "skips-auth", + "description": "Response does NOT run auth login since user is already authenticated", + "type": "not_contains", + "value": "apimatic auth login" + } + ] + }, + { + "id": 21, + "prompt": "Set a custom user agent string for my Ruby SDK that includes the language and version. My project is at ./ruby-api/ and I'm already authenticated.", + "expected_output": "The agent recognizes that setting a custom user agent is covered by the UserAgent CodeGen setting with placeholders. It updates APIMATIC-META.json with UserAgent set to a string containing {language} and {version} placeholders, then regenerates the SDK.", + "files": [], + "assertions": [ + { + "id": "uses-user-agent-setting", + "description": "Response uses the UserAgent CodeGen setting", + "type": "contains", + "value": "UserAgent" + }, + { + "id": "includes-placeholders", + "description": "Response includes the {language} and/or {version} placeholders", + "type": "contains_any", + "value": [ + "{language}", + "{version}" + ] + }, + { + "id": "updates-apimatic-meta", + "description": "Response updates APIMATIC-META.json", + "type": "contains", + "value": "APIMATIC-META.json" + }, + { + "id": "generates-ruby-sdk", + "description": "Response generates the SDK with --language=ruby", + "type": "contains", + "value": "--language=ruby" + }, + { + "id": "skips-auth", + "description": "Response does NOT run auth login since user is already authenticated", + "type": "not_contains", + "value": "apimatic auth login" + } + ] + }, + { + "id": 22, + "prompt": "Change array serialization to CSV format for my TypeScript SDK. My project is at ./ts-project/ and I'm already authenticated.", + "expected_output": "The agent recognizes that array serialization format is covered by the ArraySerialization CodeGen setting. It updates APIMATIC-META.json with ArraySerialization set to CSV, then regenerates the SDK.", + "files": [], + "assertions": [ + { + "id": "uses-array-serialization-setting", + "description": "Response uses the ArraySerialization CodeGen setting", + "type": "contains", + "value": "ArraySerialization" + }, + { + "id": "sets-csv-format", + "description": "Response sets the value to CSV", + "type": "contains", + "value": "CSV" + }, + { + "id": "updates-apimatic-meta", + "description": "Response updates APIMATIC-META.json", + "type": "contains", + "value": "APIMATIC-META.json" + }, + { + "id": "generates-typescript-sdk", + "description": "Response generates the SDK with --language=typescript", + "type": "contains", + "value": "--language=typescript" + }, + { + "id": "skips-auth", + "description": "Response does NOT run auth login since user is already authenticated", + "type": "not_contains", + "value": "apimatic auth login" + } + ] + }, + { + "id": 23, + "prompt": "Make my C# SDK return null instead of throwing an exception on 404 responses. My project is at ./csharp-api/ and I'm already authenticated.", + "expected_output": "The agent recognizes that returning null on 404 is covered by the Nullify404 CodeGen setting. It updates APIMATIC-META.json with Nullify404 set to true, then regenerates the SDK. It does NOT add custom exception handling code.", + "files": [], + "assertions": [ + { + "id": "uses-nullify404-setting", + "description": "Response uses the Nullify404 CodeGen setting", + "type": "contains", + "value": "Nullify404" + }, + { + "id": "updates-apimatic-meta", + "description": "Response updates APIMATIC-META.json", + "type": "contains", + "value": "APIMATIC-META.json" + }, + { + "id": "generates-csharp-sdk", + "description": "Response generates the SDK with --language=csharp", + "type": "contains", + "value": "--language=csharp" + }, + { + "id": "skips-auth", + "description": "Response does NOT run auth login since user is already authenticated", + "type": "not_contains", + "value": "apimatic auth login" + }, + { + "id": "does-not-add-custom-exception-handling", + "description": "Response does NOT add manual exception handling or try-catch code", + "type": "not_contains_any", + "value": [ + "try {", + "catch (", + "try:", + "except ", + "custom exception handling" + ] + } + ] + }, + { + "id": 24, + "prompt": "Add our company name 'Acme Corp' to all generated file headers in my Go SDK. My project is at ./acme-api/ and I'm already authenticated.", + "expected_output": "The agent recognizes that adding a company name to file headers is covered by the BrandLabel CodeGen setting. It updates APIMATIC-META.json with BrandLabel set to Acme Corp, then regenerates the SDK.", + "files": [], + "assertions": [ + { + "id": "uses-brand-label-setting", + "description": "Response uses the BrandLabel CodeGen setting", + "type": "contains", + "value": "BrandLabel" + }, + { + "id": "includes-company-name", + "description": "Response includes the user's company name", + "type": "contains", + "value": "Acme Corp" + }, + { + "id": "updates-apimatic-meta", + "description": "Response updates APIMATIC-META.json", + "type": "contains", + "value": "APIMATIC-META.json" + }, + { + "id": "generates-go-sdk", + "description": "Response generates the SDK with --language=go", + "type": "contains", + "value": "--language=go" + }, + { + "id": "skips-auth", + "description": "Response does NOT run auth login since user is already authenticated", + "type": "not_contains", + "value": "apimatic auth login" + } + ] + }, + { + "id": 25, + "prompt": "Add 'Model' postfix to all model class names in my Java SDK to avoid naming conflicts. My project is at ./java-api/ and I'm already authenticated.", + "expected_output": "The agent recognizes that adding a Model postfix is covered by the UseModelPrefix CodeGen setting. It updates APIMATIC-META.json with UseModelPrefix set to true, then regenerates the SDK.", + "files": [], + "assertions": [ + { + "id": "uses-model-prefix-setting", + "description": "Response uses the UseModelPrefix CodeGen setting", + "type": "contains", + "value": "UseModelPrefix" + }, + { + "id": "updates-apimatic-meta", + "description": "Response updates APIMATIC-META.json", + "type": "contains", + "value": "APIMATIC-META.json" + }, + { + "id": "generates-java-sdk", + "description": "Response generates the SDK with --language=java", + "type": "contains", + "value": "--language=java" + }, + { + "id": "skips-auth", + "description": "Response does NOT run auth login since user is already authenticated", + "type": "not_contains", + "value": "apimatic auth login" + } + ] + }, + { + "id": 26, + "prompt": "Disable native enum types in my Python SDK and use plain strings instead. My project is at ./py-project/ and I'm already authenticated.", + "expected_output": "The agent recognizes that disabling native enums is covered by the GenerateEnums CodeGen setting. It updates APIMATIC-META.json with GenerateEnums set to false, then regenerates the SDK.", + "files": [], + "assertions": [ + { + "id": "uses-generate-enums-setting", + "description": "Response uses the GenerateEnums CodeGen setting", + "type": "contains", + "value": "GenerateEnums" + }, + { + "id": "sets-to-false", + "description": "Response sets GenerateEnums to false", + "type": "contains", + "value": "false" + }, + { + "id": "updates-apimatic-meta", + "description": "Response updates APIMATIC-META.json", + "type": "contains", + "value": "APIMATIC-META.json" + }, + { + "id": "generates-python-sdk", + "description": "Response generates the SDK with --language=python", + "type": "contains", + "value": "--language=python" + }, + { + "id": "skips-auth", + "description": "Response does NOT run auth login since user is already authenticated", + "type": "not_contains", + "value": "apimatic auth login" + } + ] + }, + { + "id": 27, + "prompt": "Set custom error messages for 401 and 5XX responses in my TypeScript SDK. For 401 use 'Authorization failed, code: {$statusCode}' and for 5XX use 'Server error, code: {$statusCode}'. My project is at ./ts-api/ and I'm already authenticated.", + "expected_output": "The agent recognizes that custom error messages are covered by the ErrorTemplates CodeGen setting. It updates APIMATIC-META.json with ErrorTemplates containing entries for 401 and 5XX with the user's specified messages, then regenerates the SDK.", + "files": [], + "assertions": [ + { + "id": "uses-error-templates-setting", + "description": "Response uses the ErrorTemplates CodeGen setting", + "type": "contains", + "value": "ErrorTemplates" + }, + { + "id": "includes-401-code", + "description": "Response includes the 401 error code", + "type": "contains", + "value": "401" + }, + { + "id": "includes-5xx-code", + "description": "Response includes the 5XX error code", + "type": "contains", + "value": "5XX" + }, + { + "id": "updates-apimatic-meta", + "description": "Response updates APIMATIC-META.json", + "type": "contains", + "value": "APIMATIC-META.json" + }, + { + "id": "generates-typescript-sdk", + "description": "Response generates the SDK with --language=typescript", + "type": "contains", + "value": "--language=typescript" + }, + { + "id": "skips-auth", + "description": "Response does NOT run auth login since user is already authenticated", + "type": "not_contains", + "value": "apimatic auth login" + } + ] + }, + { + "id": 28, + "prompt": "Generate my C# SDK with synchronous methods instead of async. My project is at ./sync-api/ and I'm already authenticated.", + "expected_output": "The agent recognizes that switching to synchronous methods is covered by the SynchronyMode CodeGen setting. It updates APIMATIC-META.json with SynchronyMode set to Synchronous, then regenerates the SDK.", + "files": [], + "assertions": [ + { + "id": "uses-synchrony-mode-setting", + "description": "Response uses the SynchronyMode CodeGen setting", + "type": "contains", + "value": "SynchronyMode" + }, + { + "id": "sets-synchronous-value", + "description": "Response sets the value to Synchronous", + "type": "contains", + "value": "Synchronous" + }, + { + "id": "updates-apimatic-meta", + "description": "Response updates APIMATIC-META.json", + "type": "contains", + "value": "APIMATIC-META.json" + }, + { + "id": "generates-csharp-sdk", + "description": "Response generates the SDK with --language=csharp", + "type": "contains", + "value": "--language=csharp" + }, + { + "id": "skips-auth", + "description": "Response does NOT run auth login since user is already authenticated", + "type": "not_contains", + "value": "apimatic auth login" + } + ] + }, + { + "id": 29, + "prompt": "Remove the docs folder from my generated Python SDK. My project is at ./my-sdk/ and I'm already authenticated.", + "expected_output": "The agent recognizes that removing docs is covered by the DisableDocs CodeGen setting. It updates APIMATIC-META.json with DisableDocs set to true, then regenerates the SDK. It does NOT manually delete files, use rm commands, or treat this as a custom code injection.", + "files": [], + "assertions": [ + { + "id": "uses-disable-docs-setting", + "description": "Response uses the DisableDocs CodeGen setting instead of manual deletion", + "type": "contains", + "value": "DisableDocs" + }, + { + "id": "updates-apimatic-meta", + "description": "Response updates APIMATIC-META.json", + "type": "contains", + "value": "APIMATIC-META.json" + }, + { + "id": "does-not-manually-delete", + "description": "Response does NOT use file deletion commands", + "type": "not_contains_any", + "value": [ + "rm ", + "del ", + "Remove-Item", + "rmdir", + "sdk-source-tree", + "custom code injection", + "manually delete" + ] + }, + { + "id": "generates-python-sdk", + "description": "Response generates the SDK with --language=python", + "type": "contains", + "value": "--language=python" + }, + { + "id": "skips-auth", + "description": "Response does NOT run auth login since user is already authenticated", + "type": "not_contains", + "value": "apimatic auth login" + } + ] + }, + { + "id": 30, + "prompt": "Enable keyword arguments in my TypeScript SDK. My project is at ./ts-project/ and I'm already authenticated.", + "expected_output": "The agent recognizes that ForceKeywordArgsInRuby is a Ruby-only setting and informs the user that keyword arguments are not available for TypeScript. It does NOT blindly apply the setting.", + "files": [], + "assertions": [ + { + "id": "mentions-ruby-only", + "description": "Response mentions that keyword arguments are only available for Ruby", + "type": "contains_any", + "value": [ + "Ruby", + "ruby", + "not supported", + "not available", + "only available", + "Ruby only", + "ForceKeywordArgsInRuby", + "doesn't support", + "does not support", + "isn't available", + "is not available" + ] + }, + { + "id": "does-not-blindly-apply", + "description": "Response does NOT apply ForceKeywordArgsInRuby for TypeScript", + "type": "not_contains", + "value": "\"ForceKeywordArgsInRuby\": true" + } + ] + }, + { + "id": 31, + "prompt": "For my Java SDK at ./java-api/: set the project name to 'OrdersSDK', disable docs generation, and enable logging. I'm already authenticated.", + "expected_output": "The agent recognizes all three changes map to CodeGen settings: ProjectName, DisableDocs, and EnableLogging. It updates APIMATIC-META.json with all three settings in a single CodeGenSettings block, then regenerates the SDK once.", + "files": [], + "assertions": [ + { + "id": "uses-project-name-setting", + "description": "Response uses the ProjectName CodeGen setting", + "type": "contains", + "value": "ProjectName" + }, + { + "id": "uses-disable-docs-setting", + "description": "Response uses the DisableDocs CodeGen setting", + "type": "contains", + "value": "DisableDocs" + }, + { + "id": "uses-enable-logging-setting", + "description": "Response uses the EnableLogging CodeGen setting", + "type": "contains", + "value": "EnableLogging" + }, + { + "id": "includes-orders-sdk-name", + "description": "Response includes the requested project name", + "type": "contains", + "value": "OrdersSDK" + }, + { + "id": "updates-apimatic-meta", + "description": "Response updates APIMATIC-META.json", + "type": "contains", + "value": "APIMATIC-META.json" + }, + { + "id": "generates-java-sdk", + "description": "Response generates the SDK with --language=java", + "type": "contains", + "value": "--language=java" + }, + { + "id": "skips-auth", + "description": "Response does NOT run auth login since user is already authenticated", + "type": "not_contains", + "value": "apimatic auth login" + } + ] + }, + { + "id": 32, + "prompt": "Add an option to skip SSL certificate verification in my Python SDK for development environments. My project is at ./dev-api/ and I'm already authenticated.", + "expected_output": "The agent recognizes that adding SSL skip is covered by the AllowSkippingSSLCertVerification CodeGen setting. It updates APIMATIC-META.json with AllowSkippingSSLCertVerification set to true, then regenerates the SDK.", + "files": [], + "assertions": [ + { + "id": "uses-ssl-skip-setting", + "description": "Response uses the AllowSkippingSSLCertVerification CodeGen setting", + "type": "contains", + "value": "AllowSkippingSSLCertVerification" + }, + { + "id": "updates-apimatic-meta", + "description": "Response updates APIMATIC-META.json", + "type": "contains", + "value": "APIMATIC-META.json" + }, + { + "id": "generates-python-sdk", + "description": "Response generates the SDK with --language=python", + "type": "contains", + "value": "--language=python" + }, + { + "id": "skips-auth", + "description": "Response does NOT run auth login since user is already authenticated", + "type": "not_contains", + "value": "apimatic auth login" + } + ] + }, + { + "id": 33, + "prompt": "Change the controller suffix from 'Controller' to 'Api' in my C# SDK. My project is at ./api-project/ and I'm already authenticated.", + "expected_output": "The agent recognizes that changing the controller suffix is covered by the ControllerPostfix CodeGen setting. It updates APIMATIC-META.json with ControllerPostfix set to Api, then regenerates the SDK.", + "files": [], + "assertions": [ + { + "id": "uses-controller-postfix-setting", + "description": "Response uses the ControllerPostfix CodeGen setting", + "type": "contains", + "value": "ControllerPostfix" + }, + { + "id": "sets-api-value", + "description": "Response sets the postfix to Api", + "type": "contains", + "value": "Api" + }, + { + "id": "updates-apimatic-meta", + "description": "Response updates APIMATIC-META.json", + "type": "contains", + "value": "APIMATIC-META.json" + }, + { + "id": "generates-csharp-sdk", + "description": "Response generates the SDK with --language=csharp", + "type": "contains", + "value": "--language=csharp" + }, + { + "id": "skips-auth", + "description": "Response does NOT run auth login since user is already authenticated", + "type": "not_contains", + "value": "apimatic auth login" + } + ] + }, + { + "id": 34, + "prompt": "I want my PHP SDK to return full HTTP responses including headers and status codes, not just the response body. My project is at ./php-api/ and I'm already authenticated.", + "expected_output": "The agent recognizes that returning full HTTP responses is covered by the ReturnCompleteHttpResponse CodeGen setting. It updates APIMATIC-META.json with ReturnCompleteHttpResponse set to true, then regenerates the SDK.", + "files": [], + "assertions": [ + { + "id": "uses-return-complete-response-setting", + "description": "Response uses the ReturnCompleteHttpResponse CodeGen setting", + "type": "contains", + "value": "ReturnCompleteHttpResponse" + }, + { + "id": "updates-apimatic-meta", + "description": "Response updates APIMATIC-META.json", + "type": "contains", + "value": "APIMATIC-META.json" + }, + { + "id": "generates-php-sdk", + "description": "Response generates the SDK with --language=php", + "type": "contains", + "value": "--language=php" + }, + { + "id": "skips-auth", + "description": "Response does NOT run auth login since user is already authenticated", + "type": "not_contains", + "value": "apimatic auth login" + } + ] + }, + { + "id": 35, + "prompt": "Publish my Java SDK version 2.0.0 to the package registry. My profile ID is b2c3d4e5f6a1b2c3d4e5f6a1. My project is at ./java-api/ and I'm already authenticated.", + "expected_output": "The agent runs apimatic sdk publish in non-interactive mode with all four required flags: --profile-id, --language, --version, and --publish-type=package. It does NOT add --publish-type=sourcecode since the user only asked for the package registry.", + "files": [], + "assertions": [ + { + "id": "runs-sdk-publish", + "description": "Response includes the sdk publish command", + "type": "contains", + "value": "apimatic sdk publish" + }, + { + "id": "uses-profile-id", + "description": "Response includes the user's profile ID", + "type": "contains", + "value": "--profile-id=b2c3d4e5f6a1b2c3d4e5f6a1" + }, + { + "id": "uses-java-language", + "description": "Response includes --language=java", + "type": "contains", + "value": "--language=java" + }, + { + "id": "uses-version", + "description": "Response includes --version=2.0.0", + "type": "contains", + "value": "--version=2.0.0" + }, + { + "id": "uses-package-publish-type", + "description": "Response includes --publish-type=package", + "type": "contains", + "value": "--publish-type=package" + }, + { + "id": "does-not-add-sourcecode-unprompted", + "description": "Response does NOT add --publish-type=sourcecode since user only asked for package registry", + "type": "not_contains", + "value": "--publish-type=sourcecode" + }, + { + "id": "skips-auth", + "description": "Response does NOT run auth login since user is already authenticated", + "type": "not_contains", + "value": "apimatic auth login" + } + ] + }, + { + "id": 36, + "prompt": "Publish my TypeScript SDK version 1.0.0 to both npm and GitHub. My profile ID is a1b2c3d4e5f6a1b2c3d4e5f6. My project is at ./ts-api/ and I'm already authenticated.", + "expected_output": "The agent runs apimatic sdk publish with --publish-type=package and --publish-type=sourcecode both present, targeting both the package registry and the source repository.", + "files": [], + "assertions": [ + { + "id": "runs-sdk-publish", + "description": "Response includes the sdk publish command", + "type": "contains", + "value": "apimatic sdk publish" + }, + { + "id": "uses-profile-id", + "description": "Response includes the user's profile ID", + "type": "contains", + "value": "--profile-id=a1b2c3d4e5f6a1b2c3d4e5f6" + }, + { + "id": "uses-typescript-language", + "description": "Response includes --language=typescript", + "type": "contains", + "value": "--language=typescript" + }, + { + "id": "uses-version", + "description": "Response includes --version=1.0.0", + "type": "contains", + "value": "--version=1.0.0" + }, + { + "id": "uses-package-publish-type", + "description": "Response includes --publish-type=package", + "type": "contains", + "value": "--publish-type=package" + }, + { + "id": "uses-sourcecode-publish-type", + "description": "Response includes --publish-type=sourcecode", + "type": "contains", + "value": "--publish-type=sourcecode" + }, + { + "id": "skips-auth", + "description": "Response does NOT run auth login since user is already authenticated", + "type": "not_contains", + "value": "apimatic auth login" + } + ] + }, + { + "id": 37, + "prompt": "I want to test publishing my Python SDK before actually pushing it live. My profile ID is c3d4e5f6a1b2c3d4e5f6a1b2, version is 1.0.0, publish to package registry. I'm authenticated, project at ./py-api/.", + "expected_output": "The agent uses --dry-run so the SDK is generated locally for review without publishing. All other required flags are still included.", + "files": [], + "assertions": [ + { + "id": "runs-sdk-publish", + "description": "Response includes the sdk publish command", + "type": "contains", + "value": "apimatic sdk publish" + }, + { + "id": "uses-dry-run", + "description": "Response includes the --dry-run flag", + "type": "contains", + "value": "--dry-run" + }, + { + "id": "uses-profile-id", + "description": "Response includes the user's profile ID", + "type": "contains", + "value": "--profile-id=c3d4e5f6a1b2c3d4e5f6a1b2" + }, + { + "id": "uses-python-language", + "description": "Response includes --language=python", + "type": "contains", + "value": "--language=python" + }, + { + "id": "uses-version", + "description": "Response includes --version=1.0.0", + "type": "contains", + "value": "--version=1.0.0" + }, + { + "id": "skips-auth", + "description": "Response does NOT run auth login since user is already authenticated", + "type": "not_contains", + "value": "apimatic auth login" + } + ] + }, + { + "id": 38, + "prompt": "Show me all my publishing profiles and their IDs. I'm already authenticated.", + "expected_output": "The agent runs apimatic publishing profile list and presents the available profiles in plain language. It does NOT forward the raw CLI table output verbatim.", + "files": [], + "assertions": [ + { + "id": "runs-profile-list", + "description": "Response includes the publishing profile list command", + "type": "contains", + "value": "apimatic publishing profile list" + }, + { + "id": "skips-auth", + "description": "Response does NOT run auth login since user is already authenticated", + "type": "not_contains", + "value": "apimatic auth login" + }, + { + "id": "does-not-run-sdk-generate", + "description": "Response does NOT run sdk generate or sdk publish — the user only asked to list profiles", + "type": "not_contains_any", + "value": [ + "apimatic sdk generate", + "apimatic sdk publish" + ] + } + ] + }, + { + "id": 39, + "prompt": "I want to publish my C# SDK version 3.0.0 to the package registry but I don't know my profile ID. I'm authenticated, project at ./csharp-api/.", + "expected_output": "The agent runs apimatic publishing profile list first to help the user find their profile ID. It does NOT run apimatic sdk publish with a made-up or placeholder profile ID before the user provides their real one.", + "files": [], + "assertions": [ + { + "id": "lists-profiles-first", + "description": "Response runs publishing profile list to find the profile ID", + "type": "contains", + "value": "apimatic publishing profile list" + }, + { + "id": "does-not-fabricate-profile-id", + "description": "Response does NOT run sdk publish with a made-up profile ID before the user provides one", + "type": "not_contains", + "value": "--profile-id=a1b2c3d4" + }, + { + "id": "skips-auth", + "description": "Response does NOT run auth login since user is already authenticated", + "type": "not_contains", + "value": "apimatic auth login" + } + ] + }, + { + "id": 40, + "prompt": "I want to publish my Ruby SDK using a CI pipeline. My profile ID is d4e5f6a1b2c3d4e5f6a1b2c3, version is 0.9.0, publish to package registry. Store the API key as an env variable, no browser login.", + "expected_output": "The agent uses the APIMATIC_API_KEY environment variable for auth (no browser login, no apimatic auth login command) and runs apimatic sdk publish with all required flags non-interactively.", + "files": [], + "assertions": [ + { + "id": "runs-sdk-publish", + "description": "Response includes the sdk publish command", + "type": "contains", + "value": "apimatic sdk publish" + }, + { + "id": "uses-profile-id", + "description": "Response includes the user's profile ID", + "type": "contains", + "value": "--profile-id=d4e5f6a1b2c3d4e5f6a1b2c3" + }, + { + "id": "uses-ruby-language", + "description": "Response includes --language=ruby", + "type": "contains", + "value": "--language=ruby" + }, + { + "id": "uses-version", + "description": "Response includes --version=0.9.0", + "type": "contains", + "value": "--version=0.9.0" + }, + { + "id": "uses-env-var-for-auth", + "description": "Response recommends setting the APIMATIC_API_KEY environment variable", + "type": "contains", + "value": "APIMATIC_API_KEY" + }, + { + "id": "does-not-use-browser-login", + "description": "Response does NOT recommend browser-based login for CI", + "type": "not_contains", + "value": "auth-login.mjs" + } + ] + } + ] +} diff --git a/skills/apimatic-sdk/evals/grade.py b/skills/apimatic-sdk/evals/grade.py new file mode 100644 index 0000000..59bb43b --- /dev/null +++ b/skills/apimatic-sdk/evals/grade.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python3 +"""Grade all apimatic-sdk evals against their assertions from evals.json.""" + +import json +import os + +WORKSPACE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "workspace") +EVALS_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "evals.json") + +with open(EVALS_FILE) as f: + evals_data = json.load(f) + +def check_assertion(text, assertion): + t = assertion["type"] + v = assertion["value"] + text_lower = text.lower() + + if t == "contains": + passed = v.lower() in text_lower + evidence = f"Found '{v}'" if passed else f"NOT FOUND: '{v}'" + elif t == "contains_any": + matched = [item for item in v if item.lower() in text_lower] + passed = len(matched) > 0 + evidence = f"Found: {matched}" if passed else f"NONE FOUND: {v}" + elif t == "not_contains": + passed = v.lower() not in text_lower + evidence = f"Correctly absent: '{v}'" if passed else f"SHOULD NOT CONTAIN: '{v}'" + elif t == "not_contains_any": + found = [item for item in v if item.lower() in text_lower] + passed = len(found) == 0 + evidence = f"Correctly absent" if passed else f"SHOULD NOT CONTAIN: {found}" + else: + passed = False + evidence = f"Unknown assertion type: {t}" + + return passed, evidence + +total_assertions = 0 +total_passed = 0 +results_by_eval = [] +failed_evals = [] + +for eval_item in evals_data["evals"]: + eval_id = eval_item["id"] + response_path = os.path.join(WORKSPACE, f"eval-{eval_id}-response.md") + + if not os.path.exists(response_path): + print(f"\n=== EVAL {eval_id} === MISSING response file: {response_path}") + failed_evals.append(eval_id) + continue + + with open(response_path) as f: + response_text = f.read() + + assertions = eval_item.get("assertions", []) + results = [] + eval_passed = 0 + for assertion in assertions: + passed, evidence = check_assertion(response_text, assertion) + results.append({ + "id": assertion["id"], + "passed": passed, + "evidence": evidence + }) + total_assertions += 1 + if passed: + total_passed += 1 + eval_passed += 1 + + pass_rate = eval_passed / len(assertions) if assertions else 1.0 + results_by_eval.append({ + "id": eval_id, + "prompt": eval_item["prompt"][:80], + "pass_rate": pass_rate, + "results": results + }) + + status = "✓" if pass_rate == 1.0 else ("~" if pass_rate >= 0.5 else "✗") + print(f"\n{status} EVAL {eval_id}: {eval_item['prompt'][:60]}...") + for r in results: + sym = "✓" if r["passed"] else "✗" + print(f" {sym} {r['id']}: {r['evidence']}") + print(f" Pass rate: {pass_rate:.0%} ({eval_passed}/{len(assertions)})") + +print(f"\n{'='*60}") +print(f"OVERALL: {total_passed}/{total_assertions} assertions passed ({total_passed/total_assertions:.0%})") + +# Summary of failing evals +failing = [e for e in results_by_eval if e["pass_rate"] < 1.0] +if failing: + print(f"\nFAILING EVALS ({len(failing)}):") + for e in failing: + failing_assertions = [r for r in e["results"] if not r["passed"]] + print(f" Eval {e['id']}: {e['pass_rate']:.0%} — failing: {[r['id'] for r in failing_assertions]}") +else: + print("\nAll evals passed!") + +# Write results JSON +results_out = { + "total_passed": total_passed, + "total_assertions": total_assertions, + "pass_rate": total_passed / total_assertions if total_assertions else 0, + "evals": results_by_eval +} +out_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "results.json") +with open(out_path, "w") as f: + json.dump(results_out, f, indent=2) +print(f"\nDetailed results written to: {out_path}") diff --git a/skills/apimatic-sdk/examples/generate-customize-save.md b/skills/apimatic-sdk/examples/generate-customize-save.md new file mode 100644 index 0000000..570db5d --- /dev/null +++ b/skills/apimatic-sdk/examples/generate-customize-save.md @@ -0,0 +1,101 @@ +# Generate, Customize, and Save SDK Changes + +This example shows how to generate an SDK with change tracking, customize a generated file, save those customizations, and regenerate with them automatically reapplied. + +**Flow:** generate with change tracking → customize → save-changes → regenerate + +--- + +## Step 1: Generate the SDK + +Run from the directory that contains `src/`: + +``` +apimatic sdk generate --language=typescript --track-changes +``` + +Output: + +``` +SDK generated successfully. +| +• The generated SDK can be found at '\sdk\typescript'. +| +• Change tracking is enabled for 'typescript'. The 'sdk-source-tree' has been saved to '\src\sdk-source-tree\.typescript'. +| +o Next Steps -------------------------------------------------------------+ +| | +| Customize your SDK, then run: | +| 'apimatic sdk save-changes --language=typescript' | +| This persists your changes so they reapply on every future generation. | +| | ++--------------------------------------------------------------------------+ +| +— Succeeded +``` + +--- + +## Step 2: Customize the generated SDK + +Edit any generated file. In this example, `sdk/typescript/README.md` is updated: + +```diff +- This is a sample Pet Store Server based on the OpenAPI 3.0 specification. You can find out more about Swagger at https://swagger.io. In the third iteration of the pet store, we've switched to the design first approach! + ++ This is a sample Pet Store Server built on the OpenAPI 3.0 specification. It demonstrates a fully functional REST API for managing pets, orders, and users. For more information about the OpenAPI standard and tooling, visit https://swagger.io. +``` + +--- + +## Step 3: Save the changes + +``` +apimatic sdk save-changes --language=typescript +``` + +Output: + +``` +T Save Changes +| +• Detected changes in the following file(s): +| └─ typescript +| └─ README.md # Modified +| +| +o Do you want to review these changes? +| No +| +* Changes saved successfully at '\src\sdk-source-tree\.typescript'. +| +• Your saved changes will reapply automatically the next time you generate this SDK. +| +— Succeeded +``` + +--- + +## Step 4: Regenerate + +``` +apimatic sdk generate --language=typescript +``` + +Output: + +``` +T Generate SDK +| +o The destination '\sdk' is not empty, do you want to overwrite? +| Yes +| +o SDK generated successfully. +| +• Successfully applied saved changes for 'typescript' SDK. +| +• The generated SDK can be found at '\sdk\typescript' +| and the 'sdk-source-tree' can be found at '\src\sdk-source-tree\.typescript'. +| +— Succeeded +``` diff --git a/skills/apimatic-sdk/examples/publish-sdk.md b/skills/apimatic-sdk/examples/publish-sdk.md new file mode 100644 index 0000000..91db170 --- /dev/null +++ b/skills/apimatic-sdk/examples/publish-sdk.md @@ -0,0 +1,48 @@ +# Publish an SDK + +This example shows how to publish a generated SDK using the APIMatic CLI. + +--- + +## Publish the SDK + +``` +apimatic sdk publish --profile-id=b2c3d4e5f6a1b2c3d4e5f6a1 --language=typescript --version=1.0.0 --publish-type=sourcecode +``` + +Output: + +``` +T Publish SDK +| +o Profile search complete. +| +• Version tags will not be created in your Git repository because you have opted to publish Source Code only. +| +o The destination '\sdk' is not empty, do you want to overwrite? +| Yes +| +o SDK generated successfully. +| +• The generated SDK can be found at '\sdk\typescript'. +| +o Publishing initiated. +| +• Publishing is running for the following: +| +| Profile: +| Language: typescript +| Version: 1.0.0 +| Targets: Source Code +| +o Source Code: [Published] +| +o Next Steps ------------------------------------------------------------------------------------------+ +| | +| To view publishing logs, please visit: | +| https://dash.apimatic.io/publish//logs/ | +| | ++-------------------------------------------------------------------------------------------------------+ +| +— Succeeded +``` diff --git a/skills/apimatic-sdk/references/code-branding-settings.md b/skills/apimatic-sdk/references/code-branding-settings.md new file mode 100644 index 0000000..cf1f7a7 --- /dev/null +++ b/skills/apimatic-sdk/references/code-branding-settings.md @@ -0,0 +1,97 @@ +# Code Branding Settings + +These settings allow white-labeling and personalization of SDKs. Use this reference when the user wants to add a brand label, set a copyright notice, or customize the attribution text in generated SDK files. + +--- + +## Step 1: Identify the Required Setting + +Find the setting that matches what the user wants to change: + +| Setting | What it does | +| ---------------------- | ------------------------------------------------------------------------------------ | +| `BrandLabel` | Adds the company name to the auto-generated header comment in every SDK file | +| `ShortCopyrightNotice` | Replaces the default MIT license notice with custom copyright text in all code files | + +--- + +## Step 2: Check Language Support + +Both settings are supported across all SDK languages: + +| C# | Java | PHP | Python | Ruby | TS | Go | +| --- | ---- | --- | ------ | ---- | --- | --- | +| Yes | Yes | Yes | Yes | Yes | Yes | Yes | + +> **Note for BrandLabel:** If creating a fully white-labeled SDK where all APIMatic attribution is already removed, this setting has no effect. + +> **Note for ShortCopyrightNotice:** This setting is only applicable to white-labeled SDKs. + +--- + +## Step 3: Apply the Setting in APIMATIC-META.json + +Open `/src/spec/APIMATIC-META.json` and add the relevant key under `CodeGenSettings`. + +**Brand Label** — specify the company name as a string: + +```json +{ + "CodeGenSettings": { + "BrandLabel": "Tech Corp" + } +} +``` + +**Short Copyright Notice** — specify the full copyright text as a string. If omitted, the default MIT notice is used: + +```json +{ + "CodeGenSettings": { + "ShortCopyrightNotice": "Copyright (c) 2025 Tech Corp. All rights reserved." + } +} +``` + +Both settings can be combined: + +```json +{ + "CodeGenSettings": { + "BrandLabel": "Tech Corp", + "ShortCopyrightNotice": "Copyright (c) 2025 Tech Corp. All rights reserved." + } +} +``` + +--- + +## Step 4: Regenerate the SDK + +Navigate to the project root (the directory that contains `src/`) and run: + +``` +apimatic sdk generate --language= +``` + +Use the same `--input`, `--destination`, and `--api-version` flags that were used when the SDK was originally generated. The updated `APIMATIC-META.json` is picked up automatically — no extra flags are needed. + +--- + +## Step 5: Verify the Output + +After generation, open any source file in the generated SDK and confirm the header reflects the configured values. + +**BrandLabel effect** — every generated file header changes from: + +``` +This file was automatically generated by APIMATIC v3.0 ( https://www.apimatic.io ). +``` + +to: + +``` +This file was automatically generated for Tech Corp by APIMATIC v3.0 ( https://www.apimatic.io ). +``` + +**ShortCopyrightNotice effect** — the license file and file headers use the custom copyright text instead of the default MIT notice. diff --git a/skills/apimatic-sdk/references/endpoint-settings.md b/skills/apimatic-sdk/references/endpoint-settings.md new file mode 100644 index 0000000..f3e3728 --- /dev/null +++ b/skills/apimatic-sdk/references/endpoint-settings.md @@ -0,0 +1,298 @@ +# Endpoint Settings + +These settings manage endpoint-specific behavior in the generated SDKs. Use this reference when the user wants to change how endpoint methods are named, what they return, how parameters are handled, or how the SDK responds to specific HTTP status codes. + +## Contents + +- [Step 1: Identify the Required Setting](#step-1-identify-the-required-setting) +- [Step 2: Check Language Support](#step-2-check-language-support) +- [Step 3: Apply the Setting in APIMATIC-META.json](#step-3-apply-the-setting-in-apimatic-metajson) +- [Step 4: Regenerate the SDK](#step-4-regenerate-the-sdk) +- [Step 5: Verify the Output](#step-5-verify-the-output) + +--- + +## Step 1: Identify the Required Setting + +Find the setting that matches what the user wants to change: + +| Setting | What it does | +| ------- | ------------ | +| `ReturnCompleteHttpResponse` | Returns the full HTTP response (headers + status code) instead of just the response body | +| `UseHttpMethodPrefix` | Prefixes endpoint method names with the HTTP verb (`Get`, `Update`, or `Delete`) | +| `EncodeTemplateParameters` | Encodes endpoint-level template parameters | +| `ValidateRequiredParameters` | Throws an exception when a required parameter is passed as null | +| `CollapseParamsToArray` | Collapses multiple endpoint parameters into a single options array | +| `UseEndpointMethodName` | Uses the `MethodName` property on the endpoint entity instead of `Name` for method naming | +| `Nullify404` | Returns null instead of throwing an exception on HTTP 404 | +| `NullifyEmptyResponses` | Accepts empty response payloads as null when multiple response types are defined | +| `LiftParameterDescriptionFromCustomType` | Uses a referenced custom type's description as the parameter description when the parameter has none | +| `ForceKeywordArgsInRuby` | Uses keyword arguments instead of positional arguments for required parameters (Ruby only) | +| `MapErrorTypesInCompleteResponseForPHP` | Maps typed error responses when returning complete HTTP responses (PHP only, requires `ReturnCompleteHttpResponse`) | + +--- + +## Step 2: Check Language Support + +| Setting | C# | Java | PHP | Python | Ruby | TS | Go | +| ------- | --- | --- | --- | --- | --- | --- | --- | +| `ReturnCompleteHttpResponse` | Yes | Yes | Yes | Yes | Yes | Built-in | Built-in | +| `UseHttpMethodPrefix` | Yes | Yes | Yes | Yes | Yes | Yes | Yes | +| `EncodeTemplateParameters` | No | Yes | No | Yes | Yes | Yes | No | +| `ValidateRequiredParameters` | Yes | Yes | Yes | Yes | Yes | Yes | Built-in | +| `CollapseParamsToArray` | Yes | Yes | Yes | Yes | Yes | Yes | Yes | +| `UseEndpointMethodName` | Yes | Yes | Yes | No | No | Yes | Yes | +| `Nullify404` | Yes | Yes | Yes | Yes | Yes | No | No | +| `NullifyEmptyResponses` | Yes | Yes | Yes | Yes | Yes | Yes | Yes | +| `LiftParameterDescriptionFromCustomType` | Yes | Yes | Yes | Yes | Yes | Yes | Yes | +| `ForceKeywordArgsInRuby` | No | No | No | No | Yes | No | No | +| `MapErrorTypesInCompleteResponseForPHP` | No | No | Yes | No | No | No | No | + +**Built-in** means the behavior is inherently supported by default in that language and cannot be disabled. + +--- + +## Step 3: Apply the Setting in APIMATIC-META.json + +Open `/src/spec/APIMATIC-META.json` and add the relevant key under `CodeGenSettings`. + +**Return Complete HTTP Response** — default: `false` +```json +{ + "CodeGenSettings": { + "ReturnCompleteHttpResponse": true + } +} +``` + +**Use HTTP Method Prefix** — default: `false` + +> **Note:** Has no effect on method names that are already prefixed. + +```json +{ + "CodeGenSettings": { + "UseHttpMethodPrefix": true + } +} +``` + +**Encode Template Parameters** — default: `true` (experimental) +```json +{ + "CodeGenSettings": { + "EncodeTemplateParameters": true + } +} +``` + +**Validate Required Parameters** — default: `false` + +> **Note:** Default values for required parameters are ignored. + +```json +{ + "CodeGenSettings": { + "ValidateRequiredParameters": true + } +} +``` + +**Collapse Params to Array** — default: `false` + +> **Caution:** Use only in specific scenarios — this setting can hide type information from SDKs and documentation. + +```json +{ + "CodeGenSettings": { + "CollapseParamsToArray": true + } +} +``` + +**Use Endpoint Method Name** — default: `false` (experimental) +```json +{ + "CodeGenSettings": { + "UseEndpointMethodName": true + } +} +``` + +**Nullify 404** — default: `false` +```json +{ + "CodeGenSettings": { + "Nullify404": true + } +} +``` + +**Nullify Empty Responses** — default: `false` +```json +{ + "CodeGenSettings": { + "NullifyEmptyResponses": true + } +} +``` + +**Lift Parameter Description From Custom Type** — default: `false` +```json +{ + "CodeGenSettings": { + "LiftParameterDescriptionFromCustomType": true + } +} +``` + +**Force Keyword Arguments in Ruby** — default: `false` +```json +{ + "CodeGenSettings": { + "ForceKeywordArgsInRuby": true + } +} +``` + +**Map Error Types in Complete Response for PHP** — default: `false` + +> **Note:** Only applies when `ReturnCompleteHttpResponse` is also enabled. + +```json +{ + "CodeGenSettings": { + "ReturnCompleteHttpResponse": true, + "MapErrorTypesInCompleteResponseForPHP": true + } +} +``` + +--- + +## Step 4: Regenerate the SDK + +Navigate to the project root (the directory that contains `src/`) and run: + +``` +apimatic sdk generate --language= +``` + +Use the same `--input`, `--destination`, and `--api-version` flags that were used when the SDK was originally generated. The updated `APIMATIC-META.json` is picked up automatically — no extra flags are needed. + +--- + +## Step 5: Verify the Output + +After generation, check the affected endpoint methods in the generated SDK to confirm the change. + +**ReturnCompleteHttpResponse — `true`:** +```csharp +// C# +public ApiResponse GetData() +``` +```java +// Java +public ApiResponse getData() +``` +```php +// PHP +public function getData(): ApiResponse +``` +```python +# Python +def get_data(): + """Returns: ApiResponse""" +``` +```ruby +# Ruby +# @return [ApiResponse] +def get_data() +``` + +**ReturnCompleteHttpResponse — `false` (default):** +```csharp +// C# +public Models.ServerResponse GetData() +``` + +--- + +**UseHttpMethodPrefix — `true`:** +```csharp +// C# +dynamic result = await echoController.CreateJsonEchoAsync(input); +``` +```java +// Java +echoController.createJsonEchoAsync(input) +``` +```python +# Python +result = echo_controller.create_json_echo(input) +``` + +**UseHttpMethodPrefix — `false` (default):** +```csharp +dynamic result = await echoController.JsonEchoAsync(input); +``` + +--- + +**CollapseParamsToArray — `true`:** +```csharp +// C# +public Models.ServerResponse PostData(Models.PostDataInput input) +``` +```python +# Python +def post_data(self, options=dict()) +``` + +**CollapseParamsToArray — `false` (default):** +```csharp +public Models.ServerResponse PostData(bool unSet, bool setToNull, string field, Models.MyData data) +``` +```python +def post_data(self, un_set, set_to_null, field, data) +``` + +--- + +**Nullify404 — `true`:** Returns `null` on HTTP 404 instead of throwing an exception. + +**NullifyEmptyResponses — `true`:** Empty response payloads are returned as `null`; typed responses are returned normally. + +--- + +**ForceKeywordArgsInRuby — `true`:** +```ruby +result = echo_controller.json_echo(input: input) +``` + +**ForceKeywordArgsInRuby — `false` (default):** +```ruby +result = echo_controller.json_echo(input) +``` + +--- + +**MapErrorTypesInCompleteResponseForPHP — `true`:** +```php +if ($apiResponse->isError()) { + $error = $apiResponse->getResult(); + if ($error instanceof CustomAlphaException) { + echo "CustomAlphaException: $error"; + } elseif ($error instanceof CustomBetaException) { + echo "CustomBetaException: $error"; + } +} +``` + +**MapErrorTypesInCompleteResponseForPHP — `false` (default):** +```php +if ($apiResponse->isError()) { + $error = $apiResponse->getResult(); + echo "Untyped raw response body: $error"; +} +``` diff --git a/skills/apimatic-sdk/references/enum-settings.md b/skills/apimatic-sdk/references/enum-settings.md new file mode 100644 index 0000000..b4abb59 --- /dev/null +++ b/skills/apimatic-sdk/references/enum-settings.md @@ -0,0 +1,117 @@ +# Enum Settings + +These settings control how enums are generated within the SDKs. Use this reference when the user wants to enable or disable native enum types, or add a postfix to enum class names. + +--- + +## Step 1: Identify the Required Setting + +Find the setting that matches what the user wants to change: + +| Setting | What it does | +| --------------- | -------------------------------------------------------------------------------------------------------------------- | +| `GenerateEnums` | Generates enums as native enum types; when disabled, enum fields use primitive types (e.g., `string`, `int`) instead | +| `UseEnumPrefix` | Postfixes each enum class name with the word `Enum` (e.g., `Days` → `DaysEnum`) | + +--- + +## Step 2: Check Language Support + +| Setting | C# | Java | PHP | Python | Ruby | TS | Go | +| --------------- | --- | ---- | -------- | ------ | ---- | --- | -------- | +| `GenerateEnums` | Yes | Yes | Built-in | Yes | Yes | Yes | Built-in | +| `UseEnumPrefix` | Yes | Yes | Yes | Yes | Yes | Yes | Yes | + +**Built-in** means the behavior is inherently supported by default in that language and cannot be disabled. + +--- + +## Step 3: Apply the Setting in APIMATIC-META.json + +Open `/src/spec/APIMATIC-META.json` and add the relevant key under `CodeGenSettings`. + +**Generate Enums** — default: `true` + +```json +{ + "CodeGenSettings": { + "GenerateEnums": false + } +} +``` + +**Use Enum Prefix** — default: `true` + +```json +{ + "CodeGenSettings": { + "UseEnumPrefix": true + } +} +``` + +Both settings can be combined: + +```json +{ + "CodeGenSettings": { + "GenerateEnums": true, + "UseEnumPrefix": false + } +} +``` + +--- + +## Step 4: Regenerate the SDK + +Navigate to the project root (the directory that contains `src/`) and run: + +``` +apimatic sdk generate --language= +``` + +Use the same `--input`, `--destination`, and `--api-version` flags that were used when the SDK was originally generated. The updated `APIMATIC-META.json` is picked up automatically — no extra flags are needed. + +--- + +## Step 5: Verify the Output + +After generation, check the affected endpoint signatures in the generated SDK to confirm the change. + +**GenerateEnums — `true` (default):** + +```csharp +// C# +public Models.ServerResponse PostStringEnumArray(List days) +``` + +```java +// Java +public ServerResponse postStringEnumArray(final List days) +``` + +```python +# Python +days = [Days.SUNDAY, Days.MONDAY, Days.TUESDAY] +``` + +**GenerateEnums — `false`:** + +```csharp +public Models.ServerResponse PostStringEnumArray(List days) +``` + +```java +public ServerResponse postStringEnumArray(final List days) +``` + +```python +days = ['Sunday', 'Monday', 'Tuesday'] +``` + +--- + +**UseEnumPrefix — `true` (default):** `SuiteCodeEnum.HEARTS` / `DaysEnum` + +**UseEnumPrefix — `false`:** `SuiteCode.HEARTS` / `Days` diff --git a/skills/apimatic-sdk/references/exception-settings.md b/skills/apimatic-sdk/references/exception-settings.md new file mode 100644 index 0000000..711a4ec --- /dev/null +++ b/skills/apimatic-sdk/references/exception-settings.md @@ -0,0 +1,101 @@ +# Exception Settings + +These settings control how exceptions are handled and reported in the generated SDKs. Use this reference when the user wants to customize error messages for specific HTTP status codes or resolve naming conflicts in C# exception models. + +--- + +## Step 1: Identify the Required Setting + +| Setting | What it does | +| ------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------- | +| `ErrorTemplates` | Configures custom error message templates for specific HTTP error codes or ranges; use `{$statusCode}` as a placeholder for the actual status code | +| `CSharpResolveExceptionPropertyCollisions` | Resolves naming conflicts in C# exception models where generated properties overlap with `System.Exception` members (e.g., `Message`, `StackTrace`) | + +--- + +## Step 2: Check Language Support + +| Setting | C# | Java | PHP | Python | Ruby | TS | Go | +| ------------------------------------------ | --- | ---- | --- | ------ | ---- | --- | --- | +| `ErrorTemplates` | Yes | Yes | Yes | Yes | Yes | Yes | Yes | +| `CSharpResolveExceptionPropertyCollisions` | Yes | No | No | No | No | No | No | + +--- + +## Step 3: Apply the Setting in APIMATIC-META.json + +Open `/src/spec/APIMATIC-META.json` and add the relevant key under `CodeGenSettings`. + +**Error Templates** — default: `null` + +Keys are HTTP error codes (`"401"`) or ranges (`"5XX"`, `"0"`). Values are message strings with optional `{$statusCode}` placeholder. + +```json +{ + "CodeGenSettings": { + "ErrorTemplates": { + "401": "Failed to authorize, Code: {$statusCode}.", + "5XX": "Internal server error, Code: {$statusCode}.", + "0": "An error occurred. Code: {$statusCode}" + } + } +} +``` + +**CSharp Resolve Exception Property Collisions** — default: `false` + +Conflicting properties include: `Message`, `ResponseCode`, `StackTrace`, `Source`, `Data`, `HelpLink`, `HttpContext`, `InnerException`, `HResult`, `TargetSite`. + +> **Caution:** Enabling this setting may rename existing exception properties (e.g., `Message` → `MessageProperty`). Any code accessing the original property names will need to be updated. + +```json +{ + "CodeGenSettings": { + "CSharpResolveExceptionPropertyCollisions": true + } +} +``` + +--- + +## Step 4: Regenerate the SDK + +Navigate to the project root (the directory that contains `src/`) and run: + +``` +apimatic sdk generate --language= +``` + +Use the same `--input`, `--destination`, and `--api-version` flags that were used when the SDK was originally generated. The updated `APIMATIC-META.json` is picked up automatically — no extra flags are needed. + +--- + +## Step 5: Verify the Output + +**ErrorTemplates** — check the exception classes in the generated SDK. The custom message template should appear in the error handling logic for the configured status codes. + +**CSharpResolveExceptionPropertyCollisions — `true`:** + +```csharp +public class Error : ApiException +{ + [JsonProperty("name")] + public string Name { get; set; } + + [JsonProperty("message")] + public string MessageProperty { get; set; } +} +``` + +**CSharpResolveExceptionPropertyCollisions — `false` (default):** + +```csharp +public class Error : ApiException +{ + [JsonProperty("name")] + public string Name { get; set; } + + [JsonProperty("message")] + public new string Message { get; set; } +} +``` diff --git a/skills/apimatic-sdk/references/first-time-setup.md b/skills/apimatic-sdk/references/first-time-setup.md new file mode 100644 index 0000000..9ac4960 --- /dev/null +++ b/skills/apimatic-sdk/references/first-time-setup.md @@ -0,0 +1,90 @@ +# First-Time Setup: Scaffolding the Project + +Use this when the user does not have a `src/` folder yet and needs to set up a project from scratch for SDK generation. + +--- + +## Step 1: Get the project directory + +Ask the user: "Where would you like me to set up the project directory? (Give a path, or I'll use the current directory)" + +- If the user provides a path, use that as the project root. +- If no path given, use the current working directory. + +--- + +## Step 2: Get the API spec file + +Ask the user: "What is the path to your API specification file? (OpenAPI JSON/YAML, Postman collection, or other supported format)" + +Store the spec file path. + +--- + +## Step 3: Create the directory structure + +Create the `src/spec/` directory inside the project root: + +```bash +mkdir -p /src/spec +``` + +On Windows PowerShell: + +```powershell +New-Item -ItemType Directory -Force -Path "\src\spec" +``` + +--- + +## Step 4: Copy the user's spec file + +Copy the user's API spec into `src/spec/`: + +```bash +cp /src/spec/ +``` + +On Windows PowerShell: + +```powershell +Copy-Item "" -Destination "\src\spec\" +``` + +--- + +## Step 5: Download APIMATIC-META.json + +Download the `APIMATIC-META.json` file from the sample portal repository into `src/spec/`: + +```bash +curl -L -o /src/spec/APIMATIC-META.json https://raw.githubusercontent.com/apimatic/sample-docs-as-code-portal/refs/heads/master/src/spec/APIMATIC-META.json +``` + +On Windows PowerShell: + +```powershell +Invoke-WebRequest -Uri "https://raw.githubusercontent.com/apimatic/sample-docs-as-code-portal/refs/heads/master/src/spec/APIMATIC-META.json" -OutFile "\src\spec\APIMATIC-META.json" +``` + +On macOS/Linux if `curl` is unavailable: + +```bash +wget -O /src/spec/APIMATIC-META.json https://raw.githubusercontent.com/apimatic/sample-docs-as-code-portal/refs/heads/master/src/spec/APIMATIC-META.json +``` + +--- + +## Step 6: Verify the structure + +After setup, the project directory should look like this: + +``` +/ +└── src/ + └── spec/ + ├── (e.g., openapi.json, petstore.yaml) + └── APIMATIC-META.json (downloaded from sample portal) +``` + +Navigate to the project root and continue with the SDK generation workflow. diff --git a/skills/apimatic-sdk/references/http-configuration-settings.md b/skills/apimatic-sdk/references/http-configuration-settings.md new file mode 100644 index 0000000..4c3abf7 --- /dev/null +++ b/skills/apimatic-sdk/references/http-configuration-settings.md @@ -0,0 +1,98 @@ +# HTTP Configuration Settings + +These settings manage HTTP behavior in the generated SDKs. Use this reference when the user wants to enable HTTP caching, control content-type headers, or add an option to skip SSL certificate verification. + +--- + +## Step 1: Identify the Required Setting + +| Setting | What it does | +| ---------------------------------- | ------------------------------------------------------------------------------------------------------------ | +| `EnableHttpCache` | Enables HTTP caching for idempotent endpoint methods | +| `AppendContentHeaders` | Automatically appends `accept` and `content-type` headers based on the serialization mode | +| `AllowSkippingSSLCertVerification` | Adds a configuration option in the SDK to optionally skip SSL certificate verification for HTTPS connections | + +--- + +## Step 2: Check Language Support + +| Setting | C# | Java | PHP | Python | Ruby | TS | Go | +| ---------------------------------- | --- | ---- | --- | ------ | ---- | --- | --- | +| `EnableHttpCache` | No | No | No | Yes | Yes | No | No | +| `AppendContentHeaders` | Yes | Yes | Yes | Yes | Yes | Yes | Yes | +| `AllowSkippingSSLCertVerification` | Yes | Yes | Yes | Yes | Yes | No | No | + +--- + +## Step 3: Apply the Setting in APIMATIC-META.json + +Open `/src/spec/APIMATIC-META.json` and add the relevant key under `CodeGenSettings`. + +**Enable HTTP Cache** — default: `false` + +> **Note:** This setting is experimental and may not function properly at all times. + +```json +{ + "CodeGenSettings": { + "EnableHttpCache": true + } +} +``` + +**Append Content Headers** — default: `true` + +```json +{ + "CodeGenSettings": { + "AppendContentHeaders": true + } +} +``` + +**Allow Skipping SSL Certificate Verification** — default: `false` + +> **Caution:** Skipping SSL certificate verification is not recommended as it opens a security vulnerability. + +```json +{ + "CodeGenSettings": { + "AllowSkippingSSLCertVerification": true + } +} +``` + +--- + +## Step 4: Regenerate the SDK + +Navigate to the project root (the directory that contains `src/`) and run: + +``` +apimatic sdk generate --language= +``` + +Use the same `--input`, `--destination`, and `--api-version` flags that were used when the SDK was originally generated. The updated `APIMATIC-META.json` is picked up automatically — no extra flags are needed. + +--- + +## Step 5: Verify the Output + +**AppendContentHeaders — `true` (default):** + +```curl +curl -X GET -G \ + --url 'http://localhost:3000/response/date' \ + -H 'Accept: application/json' \ + -d 'array=true' +``` + +**AppendContentHeaders — `false`:** + +```curl +curl -X GET -G \ + --url 'http://localhost:3000/response/date' \ + -d 'array=true' +``` + +**AllowSkippingSSLCertVerification** — when enabled, the generated SDK client exposes a configuration option (e.g., `skipSslCertVerification`, `verifyPeer`) that can be set to `true` to bypass certificate checks during development or testing. diff --git a/skills/apimatic-sdk/references/miscellaneous-settings.md b/skills/apimatic-sdk/references/miscellaneous-settings.md new file mode 100644 index 0000000..20282b4 --- /dev/null +++ b/skills/apimatic-sdk/references/miscellaneous-settings.md @@ -0,0 +1,191 @@ +# Miscellaneous Settings + +These settings cover code generation options that don't fit into a specific category but allow fine-tuning of SDK behavior, authentication handling, licensing, and casing conventions. + +## Contents + +- [Step 1: Identify the Required Setting](#step-1-identify-the-required-setting) +- [Step 2: Check Language Support](#step-2-check-language-support) +- [Step 3: Apply the Setting in APIMATIC-META.json](#step-3-apply-the-setting-in-apimatic-metajson) +- [Step 4: Regenerate the SDK](#step-4-regenerate-the-sdk) +- [Step 5: Verify the Output](#step-5-verify-the-output) + +--- + +## Step 1: Identify the Required Setting + +| Setting | What it does | +| ----------------------------- | ---------------------------------------------------------------------------------------------------- | +| `DisableLinting` | Disables generation of lint test files and commands | +| `DisableMultipleAuth` | Disables multiple authentication support; only the first security scheme from the spec is applied | +| `AddSingleAuthDeprecatedCode` | Controls whether deprecated single-auth client setup code is included alongside the new auth flow | +| `JavaUsePropertiesConfig` | Allows the Java SDK to load its configuration from a properties file | +| `LicenseText` | Replaces the default MIT license text with a custom string in the SDK's license file | +| `StoreTimezoneInformation` | Stores timezone info with date-time values; when disabled, all date-time values are converted to UTC | +| `ApplyCustomizations` | Applies a list of APIMatic-provided customer-specific customization keys during SDK generation | +| `EnforceStandardizedCasing` | Enforces standardized casing conventions during SDK and docs generation | + +--- + +## Step 2: Check Language Support + +| Setting | C# | Java | PHP | Python | Ruby | TS | Go | +| ----------------------------- | --- | ---- | --- | ------ | ---- | --- | --- | +| `DisableLinting` | No | No | Yes | No | Yes | Yes | No | +| `DisableMultipleAuth` | Yes | Yes | Yes | Yes | Yes | Yes | Yes | +| `AddSingleAuthDeprecatedCode` | Yes | Yes | Yes | Yes | Yes | Yes | N/A | +| `JavaUsePropertiesConfig` | No | Yes | No | No | No | No | No | +| `LicenseText` | Yes | Yes | Yes | Yes | Yes | Yes | No | +| `StoreTimezoneInformation` | Yes | Yes | No | No | No | No | No | +| `ApplyCustomizations` | Yes | Yes | Yes | Yes | Yes | Yes | No | +| `EnforceStandardizedCasing` | Yes | Yes | Yes | Yes | Yes | Yes | Yes | + +--- + +## Step 3: Apply the Setting in APIMATIC-META.json + +Open `/src/spec/APIMATIC-META.json` and add the relevant key under `CodeGenSettings`. + +**Disable Linting** — default: `false` + +```json +{ + "CodeGenSettings": { + "DisableLinting": true + } +} +``` + +**Disable Multiple Auth** — default: `false` + +> **Caution:** Disabling multiple authentication only applies the first security scheme from the OpenAPI specification. This flag will be deprecated eventually; using the full multiple-auth flow is recommended. + +```json +{ + "CodeGenSettings": { + "DisableMultipleAuth": true + } +} +``` + +**Add Single Auth Deprecated Code** — default: `true` + +```json +{ + "CodeGenSettings": { + "AddSingleAuthDeprecatedCode": false + } +} +``` + +**Java Use Properties Config** — default: `false` + +> **Note:** This is an experimental setting and may not work in all cases. + +```json +{ + "CodeGenSettings": { + "JavaUsePropertiesConfig": true + } +} +``` + +**License Text** — default: MIT license + +```json +{ + "CodeGenSettings": { + "LicenseText": "License text here..." + } +} +``` + +**Store Timezone Information** — default: `false` + +```json +{ + "CodeGenSettings": { + "StoreTimezoneInformation": true + } +} +``` + +**Apply Customizations** — list of APIMatic-provided keys + +```json +{ + "CodeGenSettings": { + "ApplyCustomizations": ["custom-abc", "custom-xyz"] + } +} +``` + +**Enforce Standardized Casing** — default: `false` + +```json +{ + "CodeGenSettings": { + "EnforceStandardizedCasing": true + } +} +``` + +--- + +## Step 4: Regenerate the SDK + +Navigate to the project root (the directory that contains `src/`) and run: + +``` +apimatic sdk generate --language= +``` + +Use the same `--input`, `--destination`, and `--api-version` flags that were used when the SDK was originally generated. The updated `APIMATIC-META.json` is picked up automatically — no extra flags are needed. + +--- + +## Step 5: Verify the Output + +**AddSingleAuthDeprecatedCode — `true` (default):** deprecated fields appear alongside the new auth flow + +```ts +const client = new Client({ + basicAuthUsername: "Username", // Deprecated + basicAuthPassword: "Password", // Deprecated + basicAuthCredentials: { + username: "Username", + password: "Password", + }, +}); +``` + +**AddSingleAuthDeprecatedCode — `false`:** only the new auth flow is present + +```ts +const client = new Client({ + basicAuthCredentials: { + username: "Username", + password: "Password", + }, +}); +``` + +**StoreTimezoneInformation — `true`:** + +```csharp +DateTimeOffset datetime = DateTime.ParseExact("2023-03-13T12:52:32.123Z", ...); +``` + +```java +ZonedDateTime datetime = DateTimeHelper.fromRfc8601DateTime("2023-03-13T12:52:32.123Z"); +``` + +**StoreTimezoneInformation — `false` (default):** + +```csharp +DateTime datetime = DateTime.ParseExact("2023-03-13T12:52:32.123Z", ...); +``` + +```java +LocalDateTime datetime = DateTimeHelper.fromRfc8601DateTime("2023-03-13T12:52:32.123Z"); +``` diff --git a/skills/apimatic-sdk/references/model-settings.md b/skills/apimatic-sdk/references/model-settings.md new file mode 100644 index 0000000..49a9bbf --- /dev/null +++ b/skills/apimatic-sdk/references/model-settings.md @@ -0,0 +1,137 @@ +# Model Settings + +These settings control model-specific behavior in the generated SDKs. Use this reference when the user wants to enable typed additional properties, add a model name postfix, use keyword arguments in Ruby models, or skip equality method generation in C#. + +## Contents + +- [Step 1: Identify the Required Setting](#step-1-identify-the-required-setting) +- [Step 2: Check Language Support](#step-2-check-language-support) +- [Step 3: Apply the Setting in APIMATIC-META.json](#step-3-apply-the-setting-in-apimatic-metajson) +- [Step 4: Regenerate the SDK](#step-4-regenerate-the-sdk) +- [Step 5: Verify the Output](#step-5-verify-the-output) + +--- + +## Step 1: Identify the Required Setting + +| Setting | What it does | +| ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | +| `ExtendedAdditionalPropertiesSupport` | Enables typed additional properties on models, allowing specific data types instead of a generic type for extra fields | +| `UseModelPrefix` | Postfixes each model class name with `Model` (e.g., `Person` → `PersonModel`) to avoid naming conflicts | +| `EnableModelKeywordArgsInRuby` | Uses keyword arguments in Ruby model constructors instead of positional arguments | +| `CSharpSkipEqualityMethods` | Skips generation of `Equals` and `GetHashCode` implementations for models and container types in C# | + +--- + +## Step 2: Check Language Support + +| Setting | C# | Java | PHP | Python | Ruby | TS | Go | +| ------------------------------------- | --- | ---- | --- | ------ | ---- | --- | --- | +| `ExtendedAdditionalPropertiesSupport` | Yes | Yes | Yes | Yes | Yes | Yes | Yes | +| `UseModelPrefix` | Yes | Yes | Yes | Yes | Yes | Yes | No | +| `EnableModelKeywordArgsInRuby` | No | No | No | No | Yes | No | No | +| `CSharpSkipEqualityMethods` | Yes | No | No | No | No | No | No | + +--- + +## Step 3: Apply the Setting in APIMATIC-META.json + +Open `/src/spec/APIMATIC-META.json` and add the relevant key under `CodeGenSettings`. + +**Extended Additional Properties Support** — default: `false` + +```json +{ + "CodeGenSettings": { + "ExtendedAdditionalPropertiesSupport": true + } +} +``` + +**Use Model Prefix** — default: `false` + +> **Note:** Use this only if there is a risk of naming conflicts between models and other identifiers (APIs, endpoints, controllers) in the OpenAPI specification. + +```json +{ + "CodeGenSettings": { + "UseModelPrefix": true + } +} +``` + +**Enable Model Keyword Args in Ruby** — default: `false` + +```json +{ + "CodeGenSettings": { + "EnableModelKeywordArgsInRuby": true + } +} +``` + +**CSharp Skip Equality Methods** — default: `false` + +> **Note:** Enabling this prevents incorrect equality and hashing on mutable models. Any code relying on value-based equality (`Equals`, `==`, `Dictionary`, `HashSet`) may observe different behavior after enabling. + +```json +{ + "CodeGenSettings": { + "CSharpSkipEqualityMethods": true + } +} +``` + +--- + +## Step 4: Regenerate the SDK + +Navigate to the project root (the directory that contains `src/`) and run: + +``` +apimatic sdk generate --language= +``` + +Use the same `--input`, `--destination`, and `--api-version` flags that were used when the SDK was originally generated. The updated `APIMATIC-META.json` is picked up automatically — no extra flags are needed. + +--- + +## Step 5: Verify the Output + +**ExtendedAdditionalPropertiesSupport — `true`:** + +```csharp +StudentResult body = new StudentResult { + Email = "student616@oxford.ac.uk", + ["Theory Of Automata"] = 82.1, + ["Computational complexity"] = 72.5, +}; +``` + +**ExtendedAdditionalPropertiesSupport — `false` (default):** + +```csharp +StudentResult body = new StudentResult { + Email = "student616@oxford.ac.uk", +}; +``` + +**UseModelPrefix — `true`:** `PersonModel`, `DeleteBodyModel`, `ServerResponseModel` + +**UseModelPrefix — `false` (default):** `Person`, `DeleteBody`, `ServerResponse` + +**EnableModelKeywordArgsInRuby — `true`:** + +```ruby +user = User.new(email: "bob@example.com", name: "Bob") +``` + +**EnableModelKeywordArgsInRuby — `false` (default):** + +```ruby +user = User.new("Alice", "alice@example.com") +``` + +**CSharpSkipEqualityMethods — `true`:** `Equals` and `GetHashCode` are not generated; equality falls back to reference comparison. + +**CSharpSkipEqualityMethods — `false` (default):** `Equals` and `GetHashCode` are generated for all models. diff --git a/skills/apimatic-sdk/references/save-changes.md b/skills/apimatic-sdk/references/save-changes.md new file mode 100644 index 0000000..7422242 --- /dev/null +++ b/skills/apimatic-sdk/references/save-changes.md @@ -0,0 +1,80 @@ +# Saving SDK Customizations + +Use this after the user has made their custom changes to a generated SDK and wants to preserve them across future regenerations. + +## Step 1: Determine flags + +**If `sdk generate` was already run in this session**, carry the values forward — do not ask again: + +- `--input` from generate → use the same value for `--input`. Omit if it was the default. +- `--destination` from generate → use the same value for `--sdk`. Omit if destination was the default. +- `--api-version` from generate → use the same value for `--api-version`. Omit if it was not used. + +**If starting save-changes without a prior generate step**, collect only what is unknown: + +- **Input directory (`--input`)** — if you do not know where the project root is, ask: "Is your project in the current directory, or is it somewhere else?" + - Current directory → omit `--input`. + - Different path → add `--input=` pointing to the parent directory that contains `src/`. + +- **SDK path (`--sdk`)** — if you do not know where the SDK lives, ask: "Is the SDK at the default location, or was it generated to a custom path?" + - Default location → omit `--sdk`. + - Custom path → add `--sdk=` pointing to the folder containing the updated SDK. + +- **API version (`--api-version`)** — do not ask. Only add `--api-version=` if the user mentions a specific version themselves. + +## Step 2: Run save-changes + +Run the command with the applicable flags: + +``` +apimatic sdk save-changes --language= +``` + +Examples with optional flags: + +``` +# Non-default input directory +apimatic sdk save-changes --language=typescript --input=./my-project + +# SDK at a custom path +apimatic sdk save-changes --language=typescript --sdk=./output/my-sdk + +# Specific API version (only when user mentioned it) +apimatic sdk save-changes --language=typescript --api-version=v2 +``` + +--- + +## Step 3: Verify and next steps + +After saving, ask the user: + +"Do you want to regenerate the SDK now to confirm your customizations are applied correctly?" + +- **Yes** → run: + + ``` + apimatic sdk generate --language= + ``` + +- **No** → inform the user: "Your customizations are saved. The next time you run `sdk generate` for this language, they'll be reapplied automatically." + +--- + +## Reverting customizations + +**Preview the SDK without customizations** (non-destructive — saved state is untouched): + +``` +apimatic sdk generate --language= --skip-changes +``` + +**Revert a specific customization** — undo the change in the generated SDK files, then save the updated state: + +``` +apimatic sdk save-changes --language= +``` + +This overwrites the previously saved state so the reverted change is no longer reapplied. + +**Remove all customizations** — delete the language file (e.g., `.typescript`) from the `sdk-source-tree` folder in the input directory. The next `sdk generate` for that language will run without any customizations, and change tracking will need to be re-initialized with `--track-changes`. diff --git a/skills/apimatic-sdk/references/sdk-docs-configuration-settings.md b/skills/apimatic-sdk/references/sdk-docs-configuration-settings.md new file mode 100644 index 0000000..2bc0403 --- /dev/null +++ b/skills/apimatic-sdk/references/sdk-docs-configuration-settings.md @@ -0,0 +1,157 @@ +# SDK Docs Configuration + +These settings control documentation generation for SDKs. Use this reference when the user wants to disable docs, include optional field examples, hide version numbers, pin a usage example endpoint, or configure resource sorting in generated documentation. + +## Contents + +- [Step 1: Identify the Required Setting](#step-1-identify-the-required-setting) +- [Step 2: Check Language Support](#step-2-check-language-support) +- [Step 3: Apply the Setting in APIMATIC-META.json](#step-3-apply-the-setting-in-apimatic-metajson) +- [Step 4: Regenerate the SDK](#step-4-regenerate-the-sdk) +- [Step 5: Verify the Output](#step-5-verify-the-output) + +--- + +## Step 1: Identify the Required Setting + +| Setting | What it does | +| ----------------------------------- | ---------------------------------------------------------------------------------------------------- | +| `DisableDocs` | Disables README and all other SDK documentation file generation | +| `GenerateExamplesForOptionalFields` | Includes optional fields when generating sample values in docs | +| `IsLatestVersion` | Replaces specific version numbers in install commands and package repo links with generic references | +| `UsageExampleEndpoint` | Specifies an endpoint to display as a full usage example in the README | +| `SortResources` | Sorts endpoint groups, endpoints, and models alphabetically in generated docs | +| `ConfigureComponentSorting` | Provides per-component sorting control, overriding `SortResources` for the component types it covers | + +--- + +## Step 2: Check Language Support + +| Setting | C# | Java | PHP | Python | Ruby | TS | Go | +| ----------------------------------- | --- | ---- | --- | ------ | ---- | --- | --- | +| `DisableDocs` | Yes | Yes | Yes | Yes | Yes | Yes | Yes | +| `GenerateExamplesForOptionalFields` | Yes | Yes | Yes | Yes | Yes | Yes | Yes | +| `IsLatestVersion` | Yes | No | Yes | Yes | Yes | Yes | Yes | +| `UsageExampleEndpoint` | Yes | Yes | Yes | Yes | Yes | Yes | Yes | +| `SortResources` | Yes | Yes | Yes | Yes | Yes | Yes | Yes | +| `ConfigureComponentSorting` | Yes | Yes | Yes | Yes | Yes | Yes | Yes | + +--- + +## Step 3: Apply the Setting in APIMATIC-META.json + +Open `/src/spec/APIMATIC-META.json` and add the relevant key under `CodeGenSettings`. + +**Disable Docs** — default: `false` + +```json +{ + "CodeGenSettings": { + "DisableDocs": true + } +} +``` + +**Generate Examples for Optional Fields** — default: `false` + +```json +{ + "CodeGenSettings": { + "GenerateExamplesForOptionalFields": true + } +} +``` + +**Is Latest Version** — default: `false` + +```json +{ + "CodeGenSettings": { + "IsLatestVersion": true + } +} +``` + +**Usage Example Endpoint** — specify `Description`, `EndpointGroupName`, and `EndpointName` + +```json +{ + "CodeGenSettings": { + "UsageExampleEndpoint": { + "Description": "Endpoint description here", + "EndpointGroupName": "Calculator", + "EndpointName": "OperationGet" + } + } +} +``` + +**Sort Resources** — default: `false` + +```json +{ + "CodeGenSettings": { + "SortResources": true + } +} +``` + +**Configure Component Sorting** — overrides `SortResources` for the component types it covers + +| Field | Type | Description | Default | +| ----------------------- | ------- | --------------------------------------------- | -------- | +| `SortEndpointGroups` | Boolean | Sort endpoint groups alphabetically | `false` | +| `EndpointSorting` | String | `"None"`, `"Alphabetical"`, or `"HttpMethod"` | `"None"` | +| `SortWebhookGroups` | Boolean | Sort webhook groups alphabetically | `false` | +| `WebhookEventsSorting` | String | `"None"`, `"Alphabetical"`, or `"HttpMethod"` | `"None"` | +| `SortCallbackGroups` | Boolean | Sort callback groups alphabetically | `false` | +| `CallbackEventsSorting` | String | `"None"`, `"Alphabetical"`, or `"HttpMethod"` | `"None"` | +| `SortModels` | Boolean | Sort models alphabetically | `false` | + +```json +{ + "CodeGenSettings": { + "ConfigureComponentSorting": { + "SortEndpointGroups": true, + "EndpointSorting": "HttpMethod", + "SortWebhookGroups": true, + "SortCallbackGroups": true, + "WebhookEventsSorting": "HttpMethod", + "CallbackEventsSorting": "HttpMethod", + "SortModels": true + } + } +} +``` + +--- + +## Step 4: Regenerate the SDK + +Navigate to the project root (the directory that contains `src/`) and run: + +``` +apimatic sdk generate --language= +``` + +Use the same `--input`, `--destination`, and `--api-version` flags that were used when the SDK was originally generated. The updated `APIMATIC-META.json` is picked up automatically — no extra flags are needed. + +--- + +## Step 5: Verify the Output + +**IsLatestVersion — `true`:** install command in README omits the version number + +``` +npm install container +``` + +**IsLatestVersion — `false` (default):** install command includes the specific version + +``` +npm install container@2.0.1 +``` + +**UsageExampleEndpoint:** a **Make Calls with the API Client** section appears in `Readme.md` for all SDKs, containing a full code sample for the configured endpoint. + +**SortResources / ConfigureComponentSorting:** endpoint groups, endpoints, and models in the generated docs appear in sorted order rather than the order defined in the OpenAPI specification. diff --git a/skills/apimatic-sdk/references/sdk-interface-customization-settings.md b/skills/apimatic-sdk/references/sdk-interface-customization-settings.md new file mode 100644 index 0000000..fac8632 --- /dev/null +++ b/skills/apimatic-sdk/references/sdk-interface-customization-settings.md @@ -0,0 +1,281 @@ +# SDK Interface Customization + +These settings control the overall look and feel of the generated SDK code — naming conventions, namespaces, controller structure, interfaces, authentication naming, logging, and synchrony mode. + +## Contents + +- [Step 1: Identify the Required Setting](#step-1-identify-the-required-setting) +- [Step 2: Check Language Support](#step-2-check-language-support) +- [Step 3: Apply the Setting in APIMATIC-META.json](#step-3-apply-the-setting-in-apimatic-metajson) +- [Step 4: Regenerate the SDK](#step-4-regenerate-the-sdk) +- [Step 5: Verify the Output](#step-5-verify-the-output) + +--- + +## Step 1: Identify the Required Setting + +| Setting | What it does | +| ------------------------------------ | ------------------------------------------------------------------------------------------ | +| `ProjectName` | Sets the name of the generated SDK package and client class | +| `CSharpNamespace` | Sets the root namespace for C# SDKs | +| `JavaPackageName` | Sets the root package name for Java SDKs | +| `PHPNamespace` | Sets the root namespace for PHP SDKs | +| `UseControllerPrefix` | Appends a postfix (default: `Controller`) to each controller class name | +| `ControllerPostfix` | Sets a custom postfix string for controller classes (requires `UseControllerPrefix: true`) | +| `ControllerNamespace` | Sets the namespace/folder name where controller classes are placed | +| `GenerateInterfaces` | Generates interfaces for controller classes to support mock testing | +| `ClientInterfaceName` | Sets the class name for the client interface (Python only) | +| `UseSecuritySchemeNameForSingleAuth` | Uses the auth scheme name from the spec as the auth method name in the client | +| `DoNotSplitWords` | List of words that should not be split when converting identifiers (e.g., brand names) | +| `SynchronyMode` | Switches between `Asynchronous` (default) and `Synchronous` code generation | +| `EnableLogging` | Includes logging configuration support in the generated SDK client | +| `SymbolizeHashKeysInRuby` | Uses symbols instead of strings for hash keys in Ruby SDKs | + +--- + +## Step 2: Check Language Support + +| Setting | C# | Java | PHP | Python | Ruby | TS | Go | +| ------------------------------------ | --- | ---- | --- | ------ | ---- | -------- | -------- | +| `ProjectName` | Yes | Yes | Yes | Yes | Yes | Yes | Yes | +| `CSharpNamespace` | Yes | No | No | No | No | No | No | +| `JavaPackageName` | No | Yes | No | No | No | No | No | +| `PHPNamespace` | No | No | Yes | No | No | No | No | +| `UseControllerPrefix` | Yes | Yes | Yes | Yes | Yes | Yes | Yes | +| `ControllerPostfix` | Yes | Yes | Yes | Yes | Yes | Yes | Yes | +| `ControllerNamespace` | Yes | Yes | Yes | Yes | Yes | Yes | Yes | +| `GenerateInterfaces` | Yes | Yes | No | No | No | No | Built-in | +| `ClientInterfaceName` | No | No | No | Yes | No | No | No | +| `UseSecuritySchemeNameForSingleAuth` | Yes | Yes | Yes | Yes | Yes | Yes | Yes | +| `DoNotSplitWords` | Yes | Yes | Yes | Yes | Yes | Yes | Yes | +| `SynchronyMode` | Yes | Yes | No | No | No | Built-in | Built-in | +| `EnableLogging` | Yes | Yes | Yes | Yes | Yes | Yes | Yes | +| `SymbolizeHashKeysInRuby` | No | No | No | No | Yes | No | No | + +**Built-in** means the behavior is inherent to the language and cannot be changed. + +--- + +## Step 3: Apply the Setting in APIMATIC-META.json + +Open `/src/spec/APIMATIC-META.json` and add the relevant key under `CodeGenSettings`. + +**Project Name** — default: API name + +```json +{ + "CodeGenSettings": { + "ProjectName": "MyProject" + } +} +``` + +**CSharp Namespace** — default: API name + +```json +{ + "CodeGenSettings": { + "CSharpNamespace": "OrgNamespace" + } +} +``` + +**Java Package Name** — default: derived from Base URI (e.g., `apimatic.io` → `io.apimatic`) + +```json +{ + "CodeGenSettings": { + "JavaPackageName": "com.example.sdk" + } +} +``` + +**PHP Namespace** — default: API name + +```json +{ + "CodeGenSettings": { + "PHPNamespace": "Apimatic" + } +} +``` + +**Use Controller Prefix** — default: `true` + +```json +{ + "CodeGenSettings": { + "UseControllerPrefix": true + } +} +``` + +**Controller Postfix** — default: `"Controller"` (requires `UseControllerPrefix: true`) + +```json +{ + "CodeGenSettings": { + "ControllerPostfix": "Api" + } +} +``` + +**Controller Namespace** — default: `"Controllers"` + +```json +{ + "CodeGenSettings": { + "ControllerNamespace": "Apis" + } +} +``` + +**Generate Interfaces** — default: `false` + +> **Note:** This is an experimental setting and may not work in all cases. + +```json +{ + "CodeGenSettings": { + "GenerateInterfaces": true + } +} +``` + +**Client Interface Name** — default: derived from `ProjectName` (e.g., `TesterClient`) + +```json +{ + "CodeGenSettings": { + "ClientInterfaceName": "Interface" + } +} +``` + +**Use Security Scheme Name For Single Auth** — default: `false` + +```json +{ + "CodeGenSettings": { + "UseSecuritySchemeNameForSingleAuth": true + } +} +``` + +**Do Not Split Words** — list of words (alphanumeric only); order determines priority + +```json +{ + "CodeGenSettings": { + "DoNotSplitWords": ["apimatic", "vmware", "petId"] + } +} +``` + +**Synchrony Mode** — default: `"Asynchronous"` + +```json +{ + "CodeGenSettings": { + "SynchronyMode": "Synchronous" + } +} +``` + +**Enable Logging** — default: `false` + +```json +{ + "CodeGenSettings": { + "EnableLogging": true + } +} +``` + +**Symbolize Hash Keys in Ruby** — default: `false` + +```json +{ + "CodeGenSettings": { + "SymbolizeHashKeysInRuby": true + } +} +``` + +--- + +## Step 4: Regenerate the SDK + +Navigate to the project root (the directory that contains `src/`) and run: + +``` +apimatic sdk generate --language= +``` + +Use the same `--input`, `--destination`, and `--api-version` flags that were used when the SDK was originally generated. The updated `APIMATIC-META.json` is picked up automatically — no extra flags are needed. + +--- + +## Step 5: Verify the Output + +**ProjectName — `"MyProject"`:** + +```csharp +// C# +MyProject.Standard.MyProjectClient client = new MyProject.Standard.MyProjectClient.Builder() + .Environment(MyProject.Standard.Environment.Testing) + .Build(); +``` + +```java +// Java +MyProjectClient client = new MyProjectClient.Builder() + .environment(Environment.TESTING) + .build(); +``` + +**UseControllerPrefix — `true` (default):** `responseTypesController.getContentTypeHeaders()` + +**UseControllerPrefix — `false`:** `responseTypes.getContentTypeHeaders()` + +**ControllerPostfix — `"Api"`:** `echoApi.jsonEcho(input)` instead of `echoController.jsonEcho(input)` + +**GenerateInterfaces — `true`:** + +```csharp +IBodyParamsController bodyParamsController = client.BodyParamsController; +``` + +**UseSecuritySchemeNameForSingleAuth — `true`:** auth method uses the scheme name from the spec (e.g., `ccgAuth`) instead of the generic type name (`clientCredentialsAuth`): + +```csharp +// true +new SdkClient.Builder().CcgAuth(new CcgAuthModel.Builder("id", "secret").Build()).Build(); +// false (default) +new SdkClient.Builder().ClientCredentialsAuth(new ClientCredentialsAuthModel.Builder("id", "secret").Build()).Build(); +``` + +**DoNotSplitWords — `["petId"]`:** the word `petId` is treated as one token and lowercased instead of split: + +```csharp +public Models.Pet GetPetById(long petid) // configured +public Models.Pet GetPetById(long petId) // default +``` + +**SynchronyMode — `"Synchronous"`:** + +```csharp +EmployeeComp result = responseTypesController.ReturnEmployeeModel(); // Synchronous +EmployeeComp result = await responseTypesController.ReturnEmployeeModelAsync(); // Asynchronous (default) +``` + +**EnableLogging — `true`:** the SDK client exposes logging configuration options: + +```csharp +SdkClient client = new SdkClient.Builder() + .LoggingConfig(config => config + .LogLevel(LogLevel.Information) + .RequestConfig(reqConfig => reqConfig.Body(true)) + ) + .Build(); +``` diff --git a/skills/apimatic-sdk/references/serialization-settings.md b/skills/apimatic-sdk/references/serialization-settings.md new file mode 100644 index 0000000..0753f7b --- /dev/null +++ b/skills/apimatic-sdk/references/serialization-settings.md @@ -0,0 +1,125 @@ +# Serialization Settings + +These settings configure how values are serialized and deserialized in the generated SDKs. Use this reference when the user wants to change how arrays are formatted in query/form parameters or how `any`-typed fields are handled. + +## Contents + +- [Step 1: Identify the Required Setting](#step-1-identify-the-required-setting) +- [Step 2: Check Language Support](#step-2-check-language-support) +- [Step 3: Apply the Setting in APIMATIC-META.json](#step-3-apply-the-setting-in-apimatic-metajson) +- [Step 4: Regenerate the SDK](#step-4-regenerate-the-sdk) +- [Step 5: Verify the Output](#step-5-verify-the-output) + +--- + +## Step 1: Identify the Required Setting + +| Setting | What it does | +| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | +| `ArraySerialization` | Sets the serialization format for arrays in query and form parameters; allowed values: `Indexed`, `UnIndexed`, `Plain`, `CSV`, `TSV`, `PSV` | +| `EnableJsonPassThroughForAny` | When enabled, `any`-typed fields are passed as raw JSON objects (`JsonObject`) instead of generic `object` types | + +--- + +## Step 2: Check Language Support + +| Setting | C# | Java | PHP | Python | Ruby | TS | Go | +| ----------------------------- | --- | ---- | --- | ------ | ---- | --- | --- | +| `ArraySerialization` | Yes | Yes | Yes | Yes | Yes | Yes | Yes | +| `EnableJsonPassThroughForAny` | Yes | Yes | Yes | Yes | Yes | Yes | No | + +--- + +## Step 3: Apply the Setting in APIMATIC-META.json + +Open `/src/spec/APIMATIC-META.json` and add the relevant key under `CodeGenSettings`. + +**Array Serialization** — default: `"Indexed"` + +| Value | Format example | +| ----------- | ----------------------------------------------- | +| `Indexed` | `variableName[0]=value1&variableName[1]=value2` | +| `UnIndexed` | `variableName[]=value1&variableName[]=value2` | +| `Plain` | `variableName=value1&variableName=value2` | +| `CSV` | `variableName=value1,value2` | +| `TSV` | `variableName=value1\tvalue2` | +| `PSV` | `variableName=value1\|value2` | + +```json +{ + "CodeGenSettings": { + "ArraySerialization": "CSV" + } +} +``` + +**Enable JSON Pass Through for Any** — default: `false` + +```json +{ + "CodeGenSettings": { + "EnableJsonPassThroughForAny": true + } +} +``` + +--- + +## Step 4: Regenerate the SDK + +Navigate to the project root (the directory that contains `src/`) and run: + +``` +apimatic sdk generate --language= +``` + +Use the same `--input`, `--destination`, and `--api-version` flags that were used when the SDK was originally generated. The updated `APIMATIC-META.json` is picked up automatically — no extra flags are needed. + +--- + +## Step 5: Verify the Output + +**EnableJsonPassThroughForAny — `true`:** + +```csharp +// C# +JsonObject body = JsonObject.FromJsonString("{\"key1\":\"val1\",\"key2\":\"val2\"}"); +ServerResponse result = await controller.SendSchemaasBodyAsync(body); +``` + +```java +// Java +JsonObject body = JsonObject.fromJsonString("{\"key1\":\"val1\",\"key2\":\"val2\"}"); +``` + +```php +// PHP +$body = '{"key1":"val1","key2":"val2"}'; +``` + +```python +# Python — body is typed as dict +body = {"key1": "val1", "key2": "val2"} +``` + +**EnableJsonPassThroughForAny — `false` (default):** + +```csharp +// C# +object body = ApiHelper.JsonDeserialize("{\"key1\":\"val1\",\"key2\":\"val2\"}"); +``` + +```java +// Java +Object body = ApiHelper.deserialize("{\"key1\":\"val1\",\"key2\":\"val2\"}"); +``` + +```php +// PHP +$body = ["key1" => "val1", "key2" => "val2"]; +``` + +```python +# Python — body is typed as object (any value) +body = 'Any Value' +``` diff --git a/skills/apimatic-sdk/references/timeout-and-retries-settings.md b/skills/apimatic-sdk/references/timeout-and-retries-settings.md new file mode 100644 index 0000000..d8304bc --- /dev/null +++ b/skills/apimatic-sdk/references/timeout-and-retries-settings.md @@ -0,0 +1,198 @@ +# Timeout and Retries Settings + +These settings control request timeouts, retry behavior, and exponential backoff in the generated SDKs. Use this reference when the user wants to configure how long requests wait before timing out, when to retry, and how retries are spaced. + +## Contents + +- [Step 1: Identify the Required Setting](#step-1-identify-the-required-setting) +- [Step 2: Check Language Support](#step-2-check-language-support) +- [Step 3: Apply the Setting in APIMATIC-META.json](#step-3-apply-the-setting-in-apimatic-metajson) +- [Step 4: Regenerate the SDK](#step-4-regenerate-the-sdk) +- [Step 5: Verify the Output](#step-5-verify-the-output) + +--- + +## Step 1: Identify the Required Setting + +| Setting | What it does | +| ------------------------- | -------------------------------------------------------------------------------------------------------------- | +| `Timeout` | Sets the request timeout in seconds; `0` means no timeout | +| `RetryOnTimeout` | Enables retrying requests that time out; must be enabled to use the other retry settings | +| `RequestMethodsToRetry` | Specifies which HTTP methods to retry; allowed values: `GET`, `PUT` | +| `StatusCodesToRetry` | Specifies which HTTP status codes trigger a retry; allowed: `408, 413, 429, 500, 502, 503, 504, 521, 522, 524` | +| `BackoffMax` | Sets the maximum total wait time (in seconds) across all retry attempts | +| `Retries` | Sets the number of retry attempts before the request fails | +| `RetryInterval` | Sets the base time interval (in seconds) between retries | +| `BackOffFactor` | Multiplier applied to `RetryInterval` on each successive retry for exponential backoff | +| `UserConfigurableRetries` | Exposes retry configuration options to SDK users in the client constructor | + +--- + +## Step 2: Check Language Support + +| Setting | C# | Java | PHP | Python | Ruby | TS | Go | +| ------------------------- | --- | ---- | --- | -------- | -------- | --- | --- | +| `Timeout` | Yes | Yes | Yes | Yes | Yes | Yes | Yes | +| `RetryOnTimeout` | Yes | Yes | Yes | Built-in | Built-in | Yes | Yes | +| `RequestMethodsToRetry` | Yes | Yes | Yes | Yes | Yes | Yes | Yes | +| `StatusCodesToRetry` | Yes | Yes | Yes | Yes | Yes | Yes | Yes | +| `BackoffMax` | Yes | Yes | Yes | No | No | Yes | Yes | +| `Retries` | Yes | Yes | Yes | Yes | Yes | Yes | Yes | +| `RetryInterval` | Yes | Yes | Yes | Yes | Yes | Yes | Yes | +| `BackOffFactor` | Yes | Yes | Yes | Yes | Yes | Yes | Yes | +| `UserConfigurableRetries` | Yes | No | No | No | No | Yes | Yes | + +**Built-in** means Python and Ruby always retry on timeout and the behavior cannot be disabled. + +--- + +## Step 3: Apply the Setting in APIMATIC-META.json + +Open `/src/spec/APIMATIC-META.json` and add the relevant keys under `CodeGenSettings`. + +> **Note:** `RetryOnTimeout` must be set to `true` to activate `RequestMethodsToRetry`, `StatusCodesToRetry`, `BackoffMax`, `Retries`, `RetryInterval`, and `BackOffFactor`. + +**Timeout** — default: `0` (no timeout) + +```json +{ + "CodeGenSettings": { + "Timeout": 30 + } +} +``` + +**RetryOnTimeout** — default: `true` + +```json +{ + "CodeGenSettings": { + "RetryOnTimeout": true + } +} +``` + +**RequestMethodsToRetry** — default: `["GET", "PUT"]` + +```json +{ + "CodeGenSettings": { + "RequestMethodsToRetry": ["GET", "PUT"] + } +} +``` + +**StatusCodesToRetry** — default: `[408, 413, 429, 500, 502, 503, 504, 521, 522, 524]` + +```json +{ + "CodeGenSettings": { + "StatusCodesToRetry": [408, 429, 503] + } +} +``` + +**BackoffMax** — maximum total retry wait time in seconds + +```json +{ + "CodeGenSettings": { + "BackoffMax": 120 + } +} +``` + +**Retries** — default: `0` + +```json +{ + "CodeGenSettings": { + "Retries": 3 + } +} +``` + +**RetryInterval** — base interval in seconds, default: `1.0` + +```json +{ + "CodeGenSettings": { + "RetryInterval": 1.5 + } +} +``` + +**BackOffFactor** — exponential backoff multiplier, default: `2` + +```json +{ + "CodeGenSettings": { + "BackOffFactor": 1.5 + } +} +``` + +**UserConfigurableRetries** — default: `true` + +```json +{ + "CodeGenSettings": { + "UserConfigurableRetries": true + } +} +``` + +All retry settings combined example: + +```json +{ + "CodeGenSettings": { + "Timeout": 30, + "RetryOnTimeout": true, + "RequestMethodsToRetry": ["GET", "PUT"], + "StatusCodesToRetry": [408, 429, 503], + "BackoffMax": 120, + "Retries": 3, + "RetryInterval": 1.5, + "BackOffFactor": 2, + "UserConfigurableRetries": true + } +} +``` + +--- + +## Step 4: Regenerate the SDK + +Navigate to the project root (the directory that contains `src/`) and run: + +``` +apimatic sdk generate --language= +``` + +Use the same `--input`, `--destination`, and `--api-version` flags that were used when the SDK was originally generated. The updated `APIMATIC-META.json` is picked up automatically — no extra flags are needed. + +--- + +## Step 5: Verify the Output + +When `UserConfigurableRetries` is `true`, SDK users can configure timeout and retry behavior in their client constructor: + +```typescript +const client = new Client({ + timeout: 60, + httpClientOptions: { + retryConfig: { + maxNumberOfRetries: 3, + retryOnTimeout: true, + retryInterval: 1, + httpStatusCodesToRetry: [ + 408, 413, 429, 500, 502, 503, 504, 521, 522, 524, + ], + httpMethodsToRetry: ["GET", "PUT"], + }, + }, +}); +``` + +When `UserConfigurableRetries` is `false`, these options are not exposed in the client constructor and the retry configuration is fixed to the values set in `APIMATIC-META.json`. diff --git a/skills/apimatic-sdk/references/user-agent-settings.md b/skills/apimatic-sdk/references/user-agent-settings.md new file mode 100644 index 0000000..80ee45f --- /dev/null +++ b/skills/apimatic-sdk/references/user-agent-settings.md @@ -0,0 +1,102 @@ +# User Agent Settings + +These settings configure the user agent string sent in API call headers. Use this reference when the user wants to disable the global user agent or customize the user agent string with dynamic placeholders. + +--- + +## Step 1: Identify the Required Setting + +| Setting | What it does | +| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | +| `EnableGlobalUserAgent` | Enables or disables sending the `UserAgent` field in the user-agent header globally across all API calls | +| `UserAgent` | Sets a custom user agent string; supports placeholders like `{language}`, `{version}`, `{engine}`, `{engine-version}`, and `{os-info}` | + +--- + +## Step 2: Check Language Support + +| Setting | C# | Java | PHP | Python | Ruby | TS | Go | +| ----------------------- | --- | ---- | --- | ------ | ---- | --- | --- | +| `EnableGlobalUserAgent` | Yes | Yes | Yes | Yes | Yes | Yes | Yes | +| `UserAgent` | Yes | Yes | Yes | Yes | Yes | Yes | Yes | + +--- + +## Step 3: Apply the Setting in APIMATIC-META.json + +Open `/src/spec/APIMATIC-META.json` and add the relevant key under `CodeGenSettings`. + +**Enable Global User Agent** — default: `true` + +> **Note:** Disabling this setting will not prevent the user agent from being sent if it has been explicitly set as an additional header or included in the endpoint parameters as a header parameter. + +```json +{ + "CodeGenSettings": { + "EnableGlobalUserAgent": false + } +} +``` + +**User Agent** — default: `"APIMATIC 3.0"` + +Supported placeholders: + +| Placeholder | Resolves to | +| ------------------ | ------------------------------------------ | +| `{language}` | SDK language name (e.g., `Java`, `PHP`) | +| `{version}` | API version from the OpenAPI specification | +| `{engine}` | Runtime engine name | +| `{engine-version}` | Runtime engine version | +| `{os-info}` | OS where the SDK is being operated | + +```json +{ + "CodeGenSettings": { + "UserAgent": "{language} SDK, Version: {version}, on OS {os-info}" + } +} +``` + +Both settings can be combined: + +```json +{ + "CodeGenSettings": { + "EnableGlobalUserAgent": true, + "UserAgent": "{language} SDK, Version: {version}, on OS {os-info}" + } +} +``` + +--- + +## Step 4: Regenerate the SDK + +Navigate to the project root (the directory that contains `src/`) and run: + +``` +apimatic sdk generate --language= +``` + +Use the same `--input`, `--destination`, and `--api-version` flags that were used when the SDK was originally generated. The updated `APIMATIC-META.json` is picked up automatically — no extra flags are needed. + +--- + +## Step 5: Verify the Output + +After generation, inspect the SDK's HTTP client initialization or request builder to confirm the user agent header. + +**Default user agent (`APIMATIC 3.0`):** + +``` +User-Agent: APIMATIC 3.0 +``` + +**Custom user agent with placeholders resolved at runtime:** + +``` +User-Agent: Java SDK, Version: 1.0, on OS Linux +``` + +**EnableGlobalUserAgent — `false`:** the SDK omits the `User-Agent` header from requests unless it is explicitly passed as an additional header or endpoint parameter. diff --git a/skills/apimatic-sdk/scripts/auth-login.mjs b/skills/apimatic-sdk/scripts/auth-login.mjs new file mode 100644 index 0000000..e4cdf6e --- /dev/null +++ b/skills/apimatic-sdk/scripts/auth-login.mjs @@ -0,0 +1,31 @@ +#!/usr/bin/env node +/** + * APIMatic browser-based auth launcher. + * + * Usage: + * node auth-login.mjs + * + * Spawns `apimatic auth login` as a detached process so the terminal is not + * blocked while the user completes the browser OAuth flow. Prints a message + * for Claude to relay to the user, then exits immediately. + * + * After the user confirms sign-in in the browser, Claude should run: + * apimatic auth status + * to verify the session is active. + * + * No external dependencies — Node.js built-ins only. + */ + +import { spawn } from "node:child_process"; + +const child = spawn("apimatic", ["auth", "login"], { + detached: true, + stdio: "ignore", + shell: process.platform === "win32", +}); +child.unref(); + +console.log(`AUTH_LOGIN_LAUNCHED pid=${child.pid}`); +console.log( + "A browser window has opened. Complete sign-in in the browser, then confirm here when done." +);