diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index a6eaf5c..762afb3 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -79,7 +79,7 @@ "interface": { "displayName": "Freshworks App Development", "shortDescription": "Platform 3.0 apps: manifest, requests, OAuth, serverless, and UI.", - "longDescription": "Enforces Platform 3.0 patterns (modules, request templates, engines), Crayons UI, validation workflows, and slash commands /fdk-fix, /fdk-migrate, /fdk-refactor, /fdk-review. Does not install FDK or Node — pair with fw-setup." + "longDescription": "Enforces Platform 3.0 patterns (modules, request templates, engines), Crayons UI, validation workflows, and slash commands /fdk-fix, /fdk-migrate, /fdk-refactor. For structured pre-submission review, use fw-review skill. Does not install FDK or Node — pair with fw-setup." } }, { diff --git a/.cursor-plugin/marketplace.json b/.cursor-plugin/marketplace.json index 603d9f5..6d8e255 100644 --- a/.cursor-plugin/marketplace.json +++ b/.cursor-plugin/marketplace.json @@ -66,7 +66,7 @@ "interface": { "displayName": "Freshworks App Development", "shortDescription": "Platform 3.0 apps: manifest, requests, OAuth, serverless, and UI.", - "longDescription": "Enforces Platform 3.0 patterns (modules, request templates, engines), Crayons UI, validation workflows, and slash commands /fdk-fix, /fdk-migrate, /fdk-refactor, /fdk-review. Does not install FDK or Node — pair with fw-setup." + "longDescription": "Enforces Platform 3.0 patterns (modules, request templates, engines), Crayons UI, validation workflows, and slash commands /fdk-fix, /fdk-migrate, /fdk-refactor. For structured pre-submission review, use fw-review skill. Does not install FDK or Node — pair with fw-setup." } }, { diff --git a/AGENTS.md b/AGENTS.md index 6712c39..9c8f5ec 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -48,7 +48,7 @@ This repository **bundles MCP config at the root**: **`.mcp.json`** (`fw-dev-mcp If **toolchain + app + publish** apply: **fw-setup** first, then **fw-app-dev** or **fw-ai-actions-app** (by task), **MANDATORY fw-review** before submission, then **fw-publish** when publishing. -**End-to-end reference (cold machine → ship):** **fw-setup** (FDK/Node) → **fw-app-dev** (full UI app) and/or **fw-ai-actions-app** (`actions.json` / SMI) → **MANDATORY fw-review** (structured audit; not the same as **fw-app-dev** `/fdk-review`) → **fw-publish** (MCP upload/submit). Humans: expanded narrative under **`README.md`** *From toolchain to marketplace (lifecycle)*; agents: tables above plus per-skill `SKILL.md`. +**End-to-end reference (cold machine → ship):** **fw-setup** (FDK/Node) → **fw-app-dev** (full UI app) and/or **fw-ai-actions-app** (`actions.json` / SMI) → **MANDATORY fw-review** (structured audit) → **fw-publish** (MCP upload/submit). Humans: expanded narrative under **`README.md`** *From toolchain to marketplace (lifecycle)*; agents: tables above plus per-skill `SKILL.md`. ## Non-negotiables (app work) @@ -69,7 +69,6 @@ When generating or editing **Freshworks apps** (not this repo’s markdown), **` - **`skills/fw-review/scripts/*.js`** — deterministic SC-* checks (not slash commands); mapped from `skills/fw-review/rules/script-check-rules.md` - **`skills/*/references/**`** — load **on demand** (API, errors, events, playbooks); index: `skills/fw-app-dev/references/skill-advanced-topics.md` - **`skills/*/assets/templates/**`** — app skeletons -- **`skills/fw-publish/subagents/**`** — optional deep-dive prompts (no `rules/` or `commands/` trees in that skill) - **`.mcp.json`** (repository root) — canonical **`fw-dev-mcp`** MCP server URL + `Authorization` header shape; see **`skills/fw-publish/SKILL.md`** for Cursor vs Claude setup notes - **`.claude/`** (repository root) — **not versioned**; create local Claude Code project settings if needed (MCP server id should match **`.mcp.json`** when configuring publish) - **`.claude-plugin/marketplace.json`**, **`.cursor-plugin/marketplace.json`** — multi-skill registries (`name`: **`freshworks-dev-tools`**; **`displayName`**: **Freshworks Agentic Developer Toolkit**; optional **`logo`** → **`assets/fw-logo.svg`**); each plugin lists `author`, `license`, `category`, `strict`, `version`, optional `interface` (same pattern as [Salesforce B2C marketplace.json](https://github.com/SalesforceCommerceCloud/b2c-developer-tooling/blob/main/.claude-plugin/marketplace.json)). @@ -104,7 +103,6 @@ Use this list when adding or renaming files so **`.cursor-plugin/marketplace.jso | `/fdk-fix` | `commands/fdk-fix.md` | | `/fdk-migrate` | `commands/fdk-migrate.md` | | `/fdk-refactor` | `commands/fdk-refactor.md` | -| `/fdk-review` | `commands/fdk-review.md` | **Rules (`.mdc`):** `app-building-blocking-gates.mdc`, `app-templates.mdc`, `async-patterns.mdc`, `complexity-reduction.mdc`, `confusion.mdc`, `freshworks-platform3.mdc`, `platform3-modules-locations.mdc`, `prerequisites-check.mdc`, `smart-prerequisites-check.mdc`, `security.mdc`, `validation-workflow.mdc` diff --git a/README.md b/README.md index cae3e89..9fbdcd9 100644 --- a/README.md +++ b/README.md @@ -143,7 +143,6 @@ Scaffold and develop a Platform 3.0 app with Crayons UI, OAuth, and serverless f |---------|-------------| | `/fdk-fix` | Fix `fdk validate` errors automatically | | `/fdk-migrate` | Upgrade a legacy 2.x app to Platform 3.0 | -| `/fdk-review` | Full app audit before submission | > **Validation order:** fw-setup first (when Node/FDK is wrong) → `/fdk-migrate` (legacy apps) → `fdk validate` diff --git a/TROUBLESHOOTING.md b/TROUBLESHOOTING.md index 820ab3b..da519be 100644 --- a/TROUBLESHOOTING.md +++ b/TROUBLESHOOTING.md @@ -338,7 +338,6 @@ ls ~/.cursor/skills/fw-app-dev/commands/*.md fdk-fix.md fdk-migrate.md fdk-refactor.md -fdk-review.md ``` **If you see NO .md files or they're in wrong location:** diff --git a/skills/fw-ai-actions-app/README.md b/skills/fw-ai-actions-app/README.md index 32c9bf2..5bf218c 100644 --- a/skills/fw-ai-actions-app/README.md +++ b/skills/fw-ai-actions-app/README.md @@ -60,8 +60,7 @@ claude plugin install fw-ai-actions-app@freshworks-developers - **agents/** — Integration scoper, scope implementer, AI action integration validator - **rules/** — Scoped `.mdc` rules (platform, schemas, server, requests, validation, test data, README, API docs). Full table in repo [`AGENTS.md`](../../AGENTS.md) (*Rules and slash commands* → **fw-ai-actions-app**). - **references/** — `ai-actions-guide.md`, quick reference, core constraints -- **scripts/ai-actions-skeleton/** — Minimal starter files -- **assets/templates/ai-actions-skeleton/** — Fuller template (manifest, sample actions) +- **assets/templates/ai-actions-skeleton/** — Fuller template (manifest, sample actions, server handlers, test data) ## Requirements diff --git a/skills/fw-ai-actions-app/SKILL.md b/skills/fw-ai-actions-app/SKILL.md index f601ba1..6083b4c 100644 --- a/skills/fw-ai-actions-app/SKILL.md +++ b/skills/fw-ai-actions-app/SKILL.md @@ -108,10 +108,9 @@ app-root/ --- -## Skeleton templates +## Skeleton template -- **`scripts/ai-actions-skeleton/`** — minimal starter (actions, config, server stub). -- **`assets/templates/ai-actions-skeleton/`** — fuller example (e.g. manifest, sample actions). +- **`assets/templates/ai-actions-skeleton/`** — Fuller template with manifest, sample actions (`getResource`, `createResource`), request templates, server handlers with error sanitization, and test data. --- diff --git a/skills/fw-ai-actions-app/assets/templates/ai-actions-skeleton/config/iparams.json b/skills/fw-ai-actions-app/assets/templates/ai-actions-skeleton/config/iparams.json index 5554ab6..33d1552 100644 --- a/skills/fw-ai-actions-app/assets/templates/ai-actions-skeleton/config/iparams.json +++ b/skills/fw-ai-actions-app/assets/templates/ai-actions-skeleton/config/iparams.json @@ -10,6 +10,7 @@ "display_name": "API Base URL", "description": "Base URL for the API (e.g., api.example.com)", "type": "text", - "required": true + "required": true, + "default_value": "api.example.com" } } diff --git a/skills/fw-ai-actions-app/assets/templates/ai-actions-skeleton/server/server.js b/skills/fw-ai-actions-app/assets/templates/ai-actions-skeleton/server/server.js index b84c8bf..d8ef8d8 100644 --- a/skills/fw-ai-actions-app/assets/templates/ai-actions-skeleton/server/server.js +++ b/skills/fw-ai-actions-app/assets/templates/ai-actions-skeleton/server/server.js @@ -1,3 +1,16 @@ +/** + * AI Actions - Server Methods + * + * CRITICAL RULES: + * 1. Function name MUST match actions.json key exactly (case-sensitive) + * 2. Parameters MUST be flat (no nested objects/arrays in actions.json) + * 3. Construct nested structures HERE, not in actions.json + * 4. Use renderData(null, data) for success + * 5. Use renderData({ status, message }) for errors + * 6. Use $request.invokeTemplate() for external API calls + * 7. Keep complexity low (max 7) - extract helpers if needed + */ + // Sanitize before `renderData`: vendor error payloads may contain internal URLs, stack traces, // tokens, or other sensitive data. Strip or map them to short, user-safe strings for the // `message` passed to `renderData`; log the full error server-side only. diff --git a/skills/fw-ai-actions-app/scripts/ai-actions-skeleton/actions.json b/skills/fw-ai-actions-app/scripts/ai-actions-skeleton/actions.json deleted file mode 100644 index a397ba3..0000000 --- a/skills/fw-ai-actions-app/scripts/ai-actions-skeleton/actions.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "actionName": { - "display_name": "Action Display Name", - "description": "Description of what this action does", - "parameters": { - "$schema": "http://json-schema.org/draft-07/schema#", - "type": "object", - "properties": { - "param1": { - "type": "string", - "description": "First parameter description" - }, - "param2": { - "type": "string", - "description": "Second parameter description" - } - }, - "required": ["param1"] - }, - "response": { - "$schema": "http://json-schema.org/draft-07/schema#", - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Resource ID" - }, - "status": { - "type": "string", - "description": "Status" - } - }, - "required": ["id"] - } - } -} diff --git a/skills/fw-ai-actions-app/scripts/ai-actions-skeleton/config/iparams.json b/skills/fw-ai-actions-app/scripts/ai-actions-skeleton/config/iparams.json deleted file mode 100644 index ed0e07c..0000000 --- a/skills/fw-ai-actions-app/scripts/ai-actions-skeleton/config/iparams.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "api_key": { - "display_name": "API Key", - "description": "API key for authentication", - "type": "text", - "required": true, - "secure": true - }, - "api_base_url": { - "display_name": "API Base URL", - "description": "Base URL (e.g., api.example.com)", - "type": "text", - "required": true, - "default_value": "api.example.com" - } -} diff --git a/skills/fw-ai-actions-app/scripts/ai-actions-skeleton/config/requests.json b/skills/fw-ai-actions-app/scripts/ai-actions-skeleton/config/requests.json deleted file mode 100644 index 84859c1..0000000 --- a/skills/fw-ai-actions-app/scripts/ai-actions-skeleton/config/requests.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "requestTemplateName": { - "schema": { - "protocol": "https", - "method": "POST", - "host": "<%= iparam.api_base_url %>", - "path": "/api/v1/endpoint", - "headers": { - "Authorization": "Bearer <%= iparam.api_key %>", - "Content-Type": "application/json" - } - } - } -} diff --git a/skills/fw-ai-actions-app/scripts/ai-actions-skeleton/server/server.js b/skills/fw-ai-actions-app/scripts/ai-actions-skeleton/server/server.js deleted file mode 100644 index 3305131..0000000 --- a/skills/fw-ai-actions-app/scripts/ai-actions-skeleton/server/server.js +++ /dev/null @@ -1,67 +0,0 @@ -/** - * AI Actions - Server Methods - * - * CRITICAL RULES: - * 1. Function name MUST match actions.json key exactly (case-sensitive) - * 2. Parameters MUST be flat (no nested objects/arrays in actions.json) - * 3. Construct nested structures HERE, not in actions.json - * 4. Use renderData(null, data) for success - * 5. Use renderData({ status, message }) for errors - * 6. Use $request.invokeTemplate() for external API calls - * 7. Keep complexity low (max 7) - extract helpers if needed - */ - -exports = { - /** - * Action Handler - * - * Pattern: Validate → Call API → Return - * - * @param {Object} args - Flat parameters from actions.json - */ - actionName: async function(args) { - // Validate required parameters - if (!args.param1) { - return renderData({ - status: 400, - message: 'Missing required parameter: param1' - }); - } - - // Extract flat parameters - const { param1, param2 } = args; - - // Build request body (construct nested if API requires it) - const requestBody = { - data: { - param1: param1, - param2: param2 || '' - } - }; - - try { - // Call external API - const response = await $request.invokeTemplate('requestTemplateName', { - context: {}, - body: JSON.stringify(requestBody) - }); - - // Parse and return response - const parsedResponse = JSON.parse(response.response); - - return renderData(null, { - data: { - response: parsedResponse - } - }); - - } catch (error) { - console.error('Error in actionName:', error); - - return renderData({ - status: error.status || 500, - message: error.message || 'Action failed' - }); - } - } -}; diff --git a/skills/fw-ai-actions-app/scripts/ai-actions-skeleton/server/test_data/actionName.json b/skills/fw-ai-actions-app/scripts/ai-actions-skeleton/server/test_data/actionName.json deleted file mode 100644 index 1e39133..0000000 --- a/skills/fw-ai-actions-app/scripts/ai-actions-skeleton/server/test_data/actionName.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "param1": "value1", - "param2": "value2" -} diff --git a/skills/fw-app-dev/.cursor-plugin/plugin.json b/skills/fw-app-dev/.cursor-plugin/plugin.json index 146e2b7..f5a4d78 100644 --- a/skills/fw-app-dev/.cursor-plugin/plugin.json +++ b/skills/fw-app-dev/.cursor-plugin/plugin.json @@ -2,7 +2,7 @@ "name": "fw-app-dev", "displayName": "Freshworks App Development", "version": "1.0.0", - "description": "Expert-level development skill for building, debugging, reviewing, and migrating Freshworks Platform 3.0 custom apps. Provides /fdk-fix, /fdk-migrate, /fdk-refactor, /fdk-review commands.", + "description": "Expert-level development skill for building, debugging, and migrating Freshworks Platform 3.0 custom apps. Provides /fdk-fix, /fdk-migrate, /fdk-refactor commands.", "author": { "name": "Freshworks Developers", "email": "skills@dev-assist.freshservice.com" @@ -22,7 +22,7 @@ "interface": { "displayName": "Freshworks App Development", "shortDescription": "Platform 3.0 apps: manifest, requests, OAuth, serverless, and Crayons UI.", - "longDescription": "Enforces Platform 3.0 patterns with slash commands /fdk-fix, /fdk-migrate, /fdk-refactor, /fdk-review. Does not install FDK or Node — use the fw-setup skill for the toolchain." + "longDescription": "Enforces Platform 3.0 patterns with slash commands /fdk-fix, /fdk-migrate, /fdk-refactor. For structured pre-submission review, use the fw-review skill. Does not install FDK or Node — use the fw-setup skill for the toolchain." }, "category": "developer-tools", "tags": [ @@ -47,11 +47,6 @@ "name": "fdk-refactor", "description": "Reduce function complexity to meet cyclomatic complexity ≤ 7", "file": "commands/fdk-refactor.md" - }, - { - "name": "fdk-review", - "description": "Review app using multiple rounds of fdk validate", - "file": "commands/fdk-review.md" } ] } diff --git a/skills/fw-app-dev/README.md b/skills/fw-app-dev/README.md index f1297c4..762c38b 100644 --- a/skills/fw-app-dev/README.md +++ b/skills/fw-app-dev/README.md @@ -92,7 +92,6 @@ The plugin should appear in Cursor Settings → Plugins → Installed Plugins. - `/fdk-fix` — `commands/fdk-fix.md` — Fix platform and lint errors - `/fdk-migrate` — `commands/fdk-migrate.md` — Migrate **Platform 2.3** (2.x), **FDK 9.x**, **Node 18** → **Platform 3.0**, **FDK 10.0.1**, **Node 24** - `/fdk-refactor` — `commands/fdk-refactor.md` — Reduce function complexity (≤ 7) -- `/fdk-review` — `commands/fdk-review.md` — Run 3 rounds of `fdk validate` **References:** - Progressive disclosure documentation (140+ files) diff --git a/skills/fw-app-dev/SKILL.md b/skills/fw-app-dev/SKILL.md index 6f65c1d..080fc21 100644 --- a/skills/fw-app-dev/SKILL.md +++ b/skills/fw-app-dev/SKILL.md @@ -3,7 +3,7 @@ name: fw-app-dev version: "1.0.0" description: "Expert-level development skill for building, debugging, reviewing, and migrating Freshworks Platform 3.0 marketplace applications. REQUIRES Node.js 24.x + FDK 10.x installed BEFORE use—checks prerequisites and refuses to proceed without them. Does NOT install or manage FDK/Node—use fw-setup skill. Before fdk validate, follow this SKILL.md Manifest + toolchain gate (fw-setup if CLI wrong, /fdk-migrate on 2.x or legacy engines, then validate—never downgrade to FDK 9/Node 18 as a shortcut except LAST RESORT after six validate iterations). New apps default to FDK 10.0.1 and Node.js 24.x; FDK 9.x/Node 18.x allowed when explicitly requested with deprecation notice. Use for: (1) Creating Platform 3.0 apps (frontend, serverless, hybrid, OAuth), (2) Debugging validation errors, (3) Migrating Platform 2.x apps to 3.0, (4) Reviewing manifest.json, requests.json, oauth_config.json, (5) Implementing Crayons UI, (6) Integrating external APIs or OAuth providers, (7) Any Freshworks Platform 3.0 app development, FDK CLI, or marketplace submission task." compatibility: "Freshworks Platform 3.0. PREREQUISITES: Node.js 24.x + FDK 10.x must be installed. Default engines: FDK 10.0.1 + Node 24.11.0. Last-resort engines downgrade (FDK 9.8.2 + Node 18.20.8) only after six fdk validate fix iterations and toolchain-only failure—see SKILL.md." -argument-hint: "[fdk-fix|fdk-migrate|fdk-refactor|fdk-review]" +argument-hint: "[fdk-fix|fdk-migrate|fdk-refactor]" allowed-tools: "shell read write strreplace glob grep" --- @@ -95,7 +95,7 @@ If **`fdk version`** fails (**command not found**, exit non-zero, or no usable C ## Manifest + toolchain gate **before** any `fdk validate` -Use this gate for **every** fw-app-dev flow that runs **`fdk validate`** (**`/fdk-fix`**, **`/fdk-review`**, **`/fdk-refactor`**, generation, ad-hoc validation) **except** **`/fdk-migrate` Step 4** only (first validate after migration). **`/fdk-migrate` Steps 0–3** already enforce toolchain + legacy detection. +Use this gate for **every** fw-app-dev flow that runs **`fdk validate`** (**`/fdk-fix`**, **`/fdk-refactor`**, generation, ad-hoc validation) **except** **`/fdk-migrate` Step 4** only (first validate after migration). **`/fdk-migrate` Steps 0–3** already enforce toolchain + legacy detection. (For structured pre-submission review, use **fw-review** skill.) 1. Run **`node --version`** and **`fdk version`** (installed toolchain). 2. Read **`manifest.json`**: **`platform-version`**, **`engines.node`**, **`engines.fdk`**. @@ -156,15 +156,7 @@ Use this gate for **every** fw-app-dev flow that runs **`fdk validate`** (**`/fd - You have already directed the user to **fw-setup** (or equivalent) and the environment **still** cannot validate on **10.0.1** + **24.11.0** in this session. - **Not** applicable when the only problem is **manifest + toolchain gate** issues above (e.g. **FDK 10 + Node 24** installed but **`engines`/`platform-version` legacy**) — fix with **`fw-setup`** + **`/fdk-migrate`** / **raise `engines`**, not downgrade. - **Then:** apply the downgrade **once**, **immediately** print the warning block below (fill in ``), re-run `fdk validate`, and continue auto-fix until **0 / 0** if the CLI now runs. **Publishing / marketplace** still requires restoring **`10.0.1` + `24.11.0`** when the user upgrades their toolchain. - -``` -WARNING: DEPRECATED TOOLCHAIN — Manifest engines were set to FDK 9.8.2 + Node 18.20.8 as LAST RESORT after six validate iterations / CLI could not run on FDK 10.0.1 + Node 24.11.0. - -Reason: - -- FDK 9.x + Node 18.x is DEPRECATED. Restore FDK 10.0.1 + Node 24.x for publishing. -``` + **Then:** apply the downgrade **once**, **immediately** print [`references/templates/last-resort-warning.txt`](references/templates/last-resort-warning.txt) (fill in ``), re-run `fdk validate`, and continue auto-fix until **0 / 0** if the CLI now runs. **Publishing / marketplace** still requires restoring **`10.0.1` + `24.11.0`** when the user upgrades their toolchain. You are a Freshworks Platform 3.0 senior solutions architect and enforcement layer. @@ -202,19 +194,8 @@ Before generating ANY code, verify these are NEVER present: 2. **Icon.svg Enforcement** - [FORBIDDEN] NEVER generate frontend app without `app/styles/images/icon.svg` - - [REQUIRED] ALWAYS create `app/styles/images/icon.svg` - NO EXCEPTIONS - - [REQUIRED] File MUST exist before app validation - - [REQUIRED] Use the SVG template below - copy exactly as shown + - [REQUIRED] Copy from skeleton: `assets/templates/*/app/styles/images/icon.svg` (e.g. `frontend-skeleton`, `hybrid-skeleton`, `oauth-skeleton`) - **VALIDATION ERROR IF VIOLATED:** "Icon 'app/styles/images/icon.svg' not found in app folder" - - **THIS IS THE #1 CAUSE OF FDK VALIDATION FAILURES - ALWAYS CREATE IT** - - **MANDATORY icon.svg content (copy this exactly):** - ```svg - - - App - - ``` 3. **Request Template Syntax** - [INVALID] NEVER use `{{variable}}` - causes FQDN validation errors @@ -227,19 +208,7 @@ Before generating ANY code, verify these are NEVER present: - [INVALID] Template in requests.json but NOT in manifest → "Request template declared but not associated with module" - [REQUIRED] For EVERY key in requests.json, add matching entry to `modules.common.requests` - **MANDATORY SYNC PATTERN:** - ``` - config/requests.json: manifest.json: - { "modules": { - "createTask": {...}, → "common": { - "addComment": {...} → "requests": { - } "createTask": {}, - "addComment": {} - } - } - } - ``` - **VALIDATION WARNING IF NOT SYNCED:** "Request template 'X' is declared but not associated with module" + **Sync pattern:** [`references/examples/request-manifest-sync.md`](references/examples/request-manifest-sync.md) 5. **Async/Await Enforcement (CRITICAL - PRE-GENERATION DECISION)** - [INVALID] NEVER use `async` without `await` - causes lint errors @@ -249,29 +218,13 @@ Before generating ANY code, verify these are NEVER present: - [VALID] OR remove `async` keyword if no await is needed - **LINT ERROR:** "Async function has no 'await' expression" - **Handler pattern (minimal examples):** - ```javascript - // [INVALID] async without await → lint error - exports = { onAppInstallHandler: async function(args) { console.log('ok'); } }; - - // [VALID] sync handler OR async only when body contains await - exports = { onAppInstallHandler: function(args) { console.log(args.iparams.domain); } }; - ``` + **Handler patterns:** [`references/examples/handler-patterns.md`](references/examples/handler-patterns.md) 6. **[ALERT] Unused Parameters Enforcement (CRITICAL) - BLOCKING ERROR** - [INVALID] NEVER define parameters that aren't used - **BLOCKS validation** - [INVALID] NEVER use `_args` prefix - **STILL CAUSES BLOCKING LINT ERROR** - [VALID] **ONLY SOLUTION: REMOVE parameter ENTIRELY from function signature** - - **LINT ERROR:** "'args' is defined but never used" or "'_args' is defined but never used" - - **CRITICAL:** Apps with unused parameters CANNOT pass `fdk validate` - - ```javascript - // [INVALID] unused args (and _args) → remove parameter entirely - onAppInstallHandler: function(args) { console.log('Installed'); } - // [VALID] - onAppInstallHandler: function() { console.log('Installed'); } - onAppInstallHandler: function(args) { console.log(args.iparams.domain); } - ``` + - See [`references/examples/handler-patterns.md`](references/examples/handler-patterns.md) 7. **[ALERT] Function Complexity Enforcement (CRITICAL) - BLOCKING ERROR** - [INVALID] NEVER generate functions with complexity > 7 - **BLOCKS validation** @@ -281,24 +234,7 @@ Before generating ANY code, verify these are NEVER present: - **WARNING:** "Function has complexity X. Maximum allowed is 7." - **CRITICAL:** Apps with complexity > 7 CANNOT pass `fdk validate` - **REFACTORING PATTERN 1: Multiple OR comparisons → Sets (MOST COMMON)** - ```javascript - // [INVALID] WRONG - complexity 12 (each || and === adds +1) - function matchesPriority(ticket, filter) { - const p = (ticket.priority || ticket.urgency || 0).toString(); - if (filter.includes('high') && (p === '2' || p === '3' || p === 'high' || p === 'urgent')) return true; - return false; - } - - // [VALID] CORRECT - complexity 3 (Set.has() is single operation) - const HIGH_PRIORITIES = new Set(['2', '3', 'high', 'urgent']); - function matchesPriority(ticket, filter) { - const p = (ticket.priority || ticket.urgency || 0).toString(); - if (filter.includes('high') && HIGH_PRIORITIES.has(p)) return true; - return false; - } - ``` - **Further complexity reduction:** extract helpers after `exports` (see `rules/complexity-reduction.mdc`). + **Refactoring pattern:** [`references/examples/complexity-reduction-pattern.js`](references/examples/complexity-reduction-pattern.js); further helpers after `exports` in `rules/complexity-reduction.mdc`. 8. **[ALERT] Manifest-to-File Consistency (CRITICAL)** - **If manifest has `location` with `url: "index.html"` → `app/index.html` MUST exist** @@ -344,33 +280,7 @@ You are not a tutor. You are an enforcement layer. ### [VALID] Correct Manifest Structure -```json -{ - "platform-version": "3.0", - "app": { - "tracking_id": "<20-char-lowercase-alphanumeric>", - "start_time": "" - }, - "modules": { - "common": { - "requests": { "apiName": {} }, - "functions": { "functionName": {} } - }, - "support_ticket": { - "location": { - "ticket_sidebar": { - "url": "index.html", - "icon": "styles/images/icon.svg" - } - } - } - }, - "engines": { - "node": "24.11.0", - "fdk": "10.0.1" - } -} -``` +See [`references/templates/manifest-3.0.json`](references/templates/manifest-3.0.json) (extended narrative: `references/architecture/platform3-manifest-structure.md`). **[ALERT] CRITICAL: Manifest `name` Field - NEVER INCLUDE:** - [INVALID] `"name": "My App"` inside manifest.json → **PLATFORM ERROR** @@ -399,23 +309,7 @@ Never emit: `platform-version` ≠ `3.0`, `product` key, `whitelisted-domains`, - [REQUIRED] Minimum sections: App name, description, features, setup, usage - **Apps without README.md are INCOMPLETE and INVALID** -**Minimum README.md structure:** -```markdown -# [App Name] - -[1-2 sentence description] - -## Features -- [Key feature 1] -- [Key feature 2] - -## Setup -1. Install app in [Product] -2. [Configuration steps if any] - -## Usage -[How to use the app] -``` +**Minimum README.md structure:** [`references/templates/app-readme-template.md`](references/templates/app-readme-template.md) --- @@ -477,7 +371,7 @@ External API → Hybrid + `requests.json`; OAuth → `oauth-skeleton`. **CRITICAL: README.md is MANDATORY for every app. It must be created BEFORE validation.** -### Step 3: Automatic Validation & Auto-Fix (MANDATORY) +### Step 3: Validate & auto-fix (MANDATORY) **CRITICAL: Fix ALL errors - Platform errors AND Lint errors. ZERO TOLERANCE.** @@ -506,19 +400,7 @@ External API → Hybrid + `requests.json`; OAuth → `oauth-skeleton`. - [VALID] If ALL errors (platform AND lint) are resolved → Present concise success message - [WARNING] If ANY errors persist → Keep iterating, NEVER say "complete" with errors -**Output after successful validation:** -``` -[VALID] App generated successfully in / - -Validation: 0 platform errors, 0 lint errors - -Next steps: -1. cd -2. fdk run -3. Test in product with ?dev=true -4. When ready to publish: use the publish skill -``` - +**Success message template:** [`references/templates/validation-success.txt`](references/templates/validation-success.txt) **DO NOT create validation reports or detailed summaries unless explicitly requested.** **What to FIX (Platform Errors) - BLOCKING:** @@ -550,88 +432,13 @@ Next steps: **OAuth vs API key, full OAuth/iparams JSON patterns, secure iparams, onAppInstall/onAppUninstall:** `references/skill-advanced-topics.md` + `references/architecture/oauth-configuration-latest.md` + `references/api/oauth-docs.md`. -**Frontend apps (frontend-skeleton, hybrid-skeleton, oauth-skeleton):** -``` -README.md # MANDATORY - create FIRST -app/ -├── index.html # MUST include Crayons CDN -├── scripts/app.js # Use IIFE pattern for async -└── styles/ - ├── style.css - └── images/ - └── icon.svg # REQUIRED - FDK validation fails without it -config/ -└── iparams.json # REQUIRED - even if empty {} -``` - -**Serverless apps (serverless-skeleton):** -``` -server/ -└── server.js # Use $request.invokeTemplate() -config/ -└── iparams.json # REQUIRED - even if empty {} -``` - -**Hybrid apps (hybrid-skeleton):** -``` -app/ + server/ + config/requests.json + config/iparams.json -``` - -**OAuth apps (oauth-skeleton):** -``` -app/ + server/ + config/oauth_config.json + config/requests.json + config/iparams.json -``` - -### Step 4: Automatic Validation & Auto-Fix (MANDATORY - DO NOT SKIP) +**App trees:** +frontend → [`references/templates/frontend-app-tree.txt`](references/templates/frontend-app-tree.txt); +serverless → [`references/templates/serverless-app-tree.txt`](references/templates/serverless-app-tree.txt); +OAuth → app/ + server/ + config/oauth_config.json + config/requests.json + config/iparams.json. +**Crayons CDN:** [`references/templates/crayons-cdn.html`](references/templates/crayons-cdn.html). -**CRITICAL: This step is MANDATORY and happens AUTOMATICALLY after creating all files.** - -**AFTER creating ALL app files (including README.md), you MUST AUTOMATICALLY:** - -1. **Run `fdk validate`** in the app directory (DO NOT ask user to run it) - - **If `fdk validate` cannot run** on **`10.0.1` + `24.11.0`:** same as Step 3 — **fw-setup** first; **LAST RESORT** downgrade only per **TOOLCHAIN, SIX `fdk validate` ITERATIONS…**. -2. **Parse validation output** - Identify ALL errors (platform AND lint) -3. **Attempt Auto-Fix Iteration 1 (ALL Errors):** - - Fix JSON structure errors (multiple top-level objects → merge) - - Fix comma placement (missing commas → add, trailing commas → remove) - - Fix template syntax (`{{variable}}` → `<%= context.variable %>`) - - Create missing mandatory files (`icon.svg`, `iparams.json`, `README.md`) - - Fix FQDN issues (host with path → FQDN only) - - Fix path issues (missing `/` → add `/` prefix) - - Re-run `fdk validate` -4. **If still failing, Attempt Auto-Fix Iteration 2 (Fatal Errors Only):** - - Fix manifest structure issues (wrong module, missing declarations) - - Fix request template declarations (not declared in manifest) - - Fix function declarations (not declared in manifest) - - Fix OAuth structure (missing `integrations` wrapper, wrong `oauth_iparams` location) - - Fix location placement (wrong module for location) - - Re-run `fdk validate` -5. **After iterations (up to 6):** - - [VALID] If ALL errors (platform AND lint) are resolved → Present concise success message - - [WARNING] If ANY errors persist → Keep iterating, NEVER say "complete" with errors - -**Output after successful validation:** -``` -[VALID] App generated successfully in / - -Validation: 0 platform errors, 0 lint errors - -Next steps: -1. cd -2. fdk run -3. Test in product with ?dev=true -4. When ready to publish: use the publish skill -``` - -**CRITICAL RULES:** -- [INVALID] NEVER say "app complete" without running `fdk validate` -- [INVALID] NEVER skip README.md creation -- [VALID] ALWAYS create README.md before validation -- [VALID] ALWAYS run validation automatically after file creation -- [VALID] ALWAYS attempt up to 6 fix iterations -- [VALID] ALWAYS re-run `fdk validate` after each fix iteration - -### Step 5: Validate Against Test Patterns +### Step 4: Validate Against Test Patterns Before presenting the app, validate against: - `references/tests/refusal.json` - Should NOT contain forbidden patterns @@ -641,11 +448,7 @@ Before presenting the app, validate against: ## Progressive disclosure (reference index) -**Full map of `references/` paths:** `references/skill-advanced-topics.md`. **Crayons CDN (required in every HTML):** -```html - - -``` +**Full map of `references/` paths:** `references/skill-advanced-topics.md`. **Crayons CDN (required in every HTML):** [`references/templates/crayons-cdn.html`](references/templates/crayons-cdn.html) --- @@ -738,52 +541,9 @@ Before presenting the app, validate against: ## Post-Generation Message -After successfully generating an app, provide a concise summary: - -``` -[VALID] App generated successfully in / - -Validation: [0 platform errors, 0 lint errors] - -Next steps: -1. cd -2. fdk run -3. Test in Freshworks product with ?dev=true -4. When ready to publish: use the publish skill -``` - -**THEN, offer MCP configuration (one time only, if not already configured):** - -After showing the completion message, check if MCP is already configured and optionally offer setup: - -```javascript -// Check if MCP tools are available -try { - CallMcpTool("fw-dev-mcp", "list_custom_apps", {}); - // Success: MCP already configured, skip prompt -} catch { - // MCP not configured: offer setup - // Full implementation: skills/fw-publish/subagents/mcp-config-prompt.md - Read and follow: skills/fw-publish/subagents/mcp-config-prompt.md -} -``` - -**Brief inline version (if subagent not available):** -``` -═══════════════════════════════════════════════════════════ -Optional: Configure Marketplace Publishing - -Would you like to set up publishing tools now? -This connects your IDE to the Freshworks Marketplace API. - -You can skip this and configure later. - -Configure MCP now? (y/N) -═══════════════════════════════════════════════════════════ -``` +After successfully generating an app, use [`references/templates/post-generation-message.txt`](references/templates/post-generation-message.txt). -If YES → Follow `skills/fw-publish/subagents/mcp-config-prompt.md` (Step 3A.1 onwards) -If NO → Skip, user can configure later via `/fw-setup-install` or manually +**Optional MCP (once, if not configured):** check per [`references/examples/mcp-availability-check.md`](references/examples/mcp-availability-check.md); prompt from [`references/templates/mcp-config-prompt.txt`](references/templates/mcp-config-prompt.txt). If YES → `AGENTS.md` + `skills/fw-publish/SKILL.md`. **DO NOT automatically generate:** - [INVALID] Detailed validation reports (.validation-report.md) diff --git a/skills/fw-app-dev/commands/fdk-migrate.md b/skills/fw-app-dev/commands/fdk-migrate.md index aca2b1c..1f983f3 100644 --- a/skills/fw-app-dev/commands/fdk-migrate.md +++ b/skills/fw-app-dev/commands/fdk-migrate.md @@ -9,7 +9,7 @@ always: false **Usage:** `/fdk-migrate` -**Orchestration (matches fw-app-dev SKILL):** (1) If **FDK 10 + Node 24** is **not** installed → **`fw-setup`** first, **then** this migrate flow, **then** **`fdk validate`**. (2) If **FDK 10 + Node 24** **is** installed and the app is legacy → this migrate flow **then** **`fdk validate`**. (3) If the app is already **3.0** with **24.x / 10.x** engines → you do **not** need this command for migration; use **`/fdk-fix`** / **`/fdk-review`** only. **Never** “fix” migration by installing **FDK 9** or switching to **Node 18** — that is the opposite of this command. +**Orchestration (matches fw-app-dev SKILL):** (1) If **FDK 10 + Node 24** is **not** installed → **`fw-setup`** first, **then** this migrate flow, **then** **`fdk validate`**. (2) If **FDK 10 + Node 24** **is** installed and the app is legacy → this migrate flow **then** **`fdk validate`**. (3) If the app is already **3.0** with **24.x / 10.x** engines → you do **not** need this command for migration; use **`/fdk-fix`** only (for structured pre-submission review, use **fw-review** skill). **Never** “fix” migration by installing **FDK 9** or switching to **Node 18** — that is the opposite of this command. You are migrating a **legacy** Freshworks app to **Platform 3.0**. Typical source state: @@ -23,7 +23,7 @@ You are migrating a **legacy** Freshworks app to **Platform 3.0**. Typical sourc **CRITICAL:** Do **not** use **FDK 9.x on Node 18** to validate a finished **Platform 3.0** app. Upgrade the **machine** (shell) to **Node 24.x** + **FDK 10.x** before you rely on `fdk validate` for the migrated tree. Platform 3.0 migration aligns with **fw-app-dev**: **FDK 10.0.1** and **Node.js 24.x** (templates use Node **24.11.0**, FDK **10.0.1**). -**Toolchain** (same split as `/fdk-fix`, `/fdk-review`, `/fdk-refactor`, and always-on **`rules/validation-workflow.mdc`**): +**Toolchain** (same split as `/fdk-fix`, `/fdk-refactor`, and always-on **`rules/validation-workflow.mdc`**): - **fw-app-dev** does not install **`fdk`**, **Node**, **nvm**, or **PATH**. - Use **`fw-setup`** when present: `/fw-setup-install`, `/fw-setup-upgrade`, `/fw-setup-use`, `/fw-setup-status`. diff --git a/skills/fw-app-dev/commands/fdk-review.md b/skills/fw-app-dev/commands/fdk-review.md deleted file mode 100644 index d192b2b..0000000 --- a/skills/fw-app-dev/commands/fdk-review.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -name: fdk-review -description: Review a Freshworks app using multiple rounds of fdk validate. Performs 3 validation rounds, fixes fatal errors, and provides a comprehensive report of platform errors, lint issues, and warnings. -globs: ["**/manifest.json"] -always: false ---- - -# FDK Review Command - -**Usage:** `/fdk-review` - -You are reviewing a Freshworks app using multiple rounds of `fdk validate`. Follow these steps exactly. - -## Step 1: Determine app directory - -1. Search the workspace for `manifest.json` files. -2. If **multiple folders** contain manifest.json: Ask the user which app to review. -3. If **one folder**: Use that directory. -4. If **none**: Inform the user and stop. - -## Step 2: Manifest + toolchain gate - -**Mandatory:** **SKILL.md** → *Manifest + toolchain gate before any `fdk validate`*. Order: **`fw-setup`** if CLI is wrong → **`/fdk-migrate`** if not **Platform 3.0** or legacy **`engines`** → only then validation rounds. **Never** downgrade to **FDK 9 / Node 18** instead of migrate/setup. - -## Step 3: Run validation rounds - -**Toolchain:** **fw-app-dev** does not install **`fdk`** or **Node**. If `fdk` is missing or the stack is not **Node 24.x + FDK 10.x** for Platform 3.0, defer to **fw-setup** or prompt the user to add that skill — see **SKILL.md** (*FDK / Node.js toolchain — not provided by fw-app-dev*). - -Run `fdk validate` from the app directory (the folder containing manifest.json). Perform **3 rounds**: - -### Round 1 -- Run: `cd && fdk validate` -- Capture full output (fatal errors, lint errors, warnings). -- Report: Summary of issues found. - -### Round 2 -- Attempt to fix **fatal errors only** (ignore lint and warnings for now). -- Apply fixes from `references/errors/` and `rules/validation-workflow.mdc`. -- Run: `fdk validate` again. -- Report: Whether fatal errors were resolved. - -### Round 3 -- Run: `fdk validate` again to confirm. -- Capture output. -- Report: Any remaining issues. - -## Step 4: Final report - -After 3 rounds, provide: -- [VALID] **Pass**: App validates successfully. -- [WARNING] **Fatal errors remain**: List them with suggested fixes. -- 📋 **Lint/warnings**: List any remaining (optional to fix). diff --git a/skills/fw-app-dev/references/examples/complexity-reduction-pattern.js b/skills/fw-app-dev/references/examples/complexity-reduction-pattern.js new file mode 100644 index 0000000..15a8aab --- /dev/null +++ b/skills/fw-app-dev/references/examples/complexity-reduction-pattern.js @@ -0,0 +1,18 @@ +// REFACTORING PATTERN: Multiple OR comparisons → Sets (complexity 12 → 3) + +// [INVALID] WRONG - complexity 12 (each || and === adds +1) +function matchesPriorityWrong(ticket, filter) { + const p = (ticket.priority || ticket.urgency || 0).toString(); + if (filter.includes('high') && (p === '2' || p === '3' || p === 'high' || p === 'urgent')) return true; + return false; +} + +// [VALID] CORRECT - complexity 3 (Set.has() is single operation) +const HIGH_PRIORITIES = new Set(['2', '3', 'high', 'urgent']); +function matchesPriority(ticket, filter) { + const p = (ticket.priority || ticket.urgency || 0).toString(); + if (filter.includes('high') && HIGH_PRIORITIES.has(p)) return true; + return false; +} + +// Further complexity reduction: extract helpers after `exports` (see rules/complexity-reduction.mdc). diff --git a/skills/fw-app-dev/references/examples/handler-patterns.md b/skills/fw-app-dev/references/examples/handler-patterns.md new file mode 100644 index 0000000..8d8e48a --- /dev/null +++ b/skills/fw-app-dev/references/examples/handler-patterns.md @@ -0,0 +1,28 @@ +# Handler patterns (async / unused params) + +## Async without await (invalid) + +```javascript +// [INVALID] async without await → lint error +exports = { onAppInstallHandler: async function(args) { console.log('ok'); } }; +``` + +## Valid handlers + +```javascript +// [VALID] sync handler OR async only when body contains await +exports = { onAppInstallHandler: function(args) { console.log(args.iparams.domain); } }; +``` + +## Unused parameters (blocking) + +```javascript +// [INVALID] unused args (and _args) → remove parameter entirely +onAppInstallHandler: function(args) { console.log('Installed'); } + +// [VALID] +onAppInstallHandler: function() { console.log('Installed'); } +onAppInstallHandler: function(args) { console.log(args.iparams.domain); } +``` + +**Lint:** `'args' is defined but never used` — apps with unused parameters cannot pass `fdk validate`. diff --git a/skills/fw-app-dev/references/examples/mcp-availability-check.md b/skills/fw-app-dev/references/examples/mcp-availability-check.md new file mode 100644 index 0000000..499358f --- /dev/null +++ b/skills/fw-app-dev/references/examples/mcp-availability-check.md @@ -0,0 +1,14 @@ +# MCP availability check (post-generation, optional) + +After showing the completion message, check if MCP is already configured: + +```javascript +// Check if MCP tools are available +try { + CallMcpTool("fw-dev-mcp", "list_custom_apps", {}); + // Success: MCP already configured, skip prompt +} catch { + // MCP not configured: offer setup + // See AGENTS.md and skills/fw-publish/SKILL.md for full setup instructions +} +``` diff --git a/skills/fw-app-dev/references/examples/request-manifest-sync.md b/skills/fw-app-dev/references/examples/request-manifest-sync.md new file mode 100644 index 0000000..c465f7f --- /dev/null +++ b/skills/fw-app-dev/references/examples/request-manifest-sync.md @@ -0,0 +1,17 @@ +# Request template ↔ manifest sync + +Every key in `config/requests.json` MUST appear under `modules.common.requests` in `manifest.json`. + +``` +config/requests.json: manifest.json: +{ "modules": { + "createTask": {...}, → "common": { + "addComment": {...} → "requests": { +} "createTask": {}, + "addComment": {} + } + } + } +``` + +**Validation warning if not synced:** `Request template 'X' is declared but not associated with module` diff --git a/skills/fw-app-dev/references/templates/app-readme-template.md b/skills/fw-app-dev/references/templates/app-readme-template.md new file mode 100644 index 0000000..27a50ea --- /dev/null +++ b/skills/fw-app-dev/references/templates/app-readme-template.md @@ -0,0 +1,14 @@ +# [App Name] + +[1-2 sentence description] + +## Features +- [Key feature 1] +- [Key feature 2] + +## Setup +1. Install app in [Product] +2. [Configuration steps if any] + +## Usage +[How to use the app] diff --git a/skills/fw-app-dev/references/templates/crayons-cdn.html b/skills/fw-app-dev/references/templates/crayons-cdn.html new file mode 100644 index 0000000..54f6b7e --- /dev/null +++ b/skills/fw-app-dev/references/templates/crayons-cdn.html @@ -0,0 +1,2 @@ + + diff --git a/skills/fw-app-dev/references/templates/frontend-app-tree.txt b/skills/fw-app-dev/references/templates/frontend-app-tree.txt new file mode 100644 index 0000000..047affc --- /dev/null +++ b/skills/fw-app-dev/references/templates/frontend-app-tree.txt @@ -0,0 +1,10 @@ +README.md # MANDATORY - create FIRST +app/ +├── index.html # MUST include Crayons CDN (see references/templates/crayons-cdn.html) +├── scripts/app.js # Use IIFE pattern for async +└── styles/ + ├── style.css + └── images/ + └── icon.svg # REQUIRED - copy from assets/templates/*/app/styles/images/icon.svg +config/ +└── iparams.json # REQUIRED - even if empty {} diff --git a/skills/fw-app-dev/references/templates/last-resort-warning.txt b/skills/fw-app-dev/references/templates/last-resort-warning.txt new file mode 100644 index 0000000..81b9f03 --- /dev/null +++ b/skills/fw-app-dev/references/templates/last-resort-warning.txt @@ -0,0 +1,5 @@ +WARNING: DEPRECATED TOOLCHAIN — Manifest engines were set to FDK 9.8.2 + Node 18.20.8 as LAST RESORT after six validate iterations / CLI could not run on FDK 10.0.1 + Node 24.11.0. + +Reason: + +- FDK 9.x + Node 18.x is DEPRECATED. Restore FDK 10.0.1 + Node 24.x for publishing. diff --git a/skills/fw-app-dev/references/templates/manifest-3.0.json b/skills/fw-app-dev/references/templates/manifest-3.0.json new file mode 100644 index 0000000..4e5eabc --- /dev/null +++ b/skills/fw-app-dev/references/templates/manifest-3.0.json @@ -0,0 +1,25 @@ +{ + "platform-version": "3.0", + "app": { + "tracking_id": "<20-char-lowercase-alphanumeric>", + "start_time": "" + }, + "modules": { + "common": { + "requests": { "apiName": {} }, + "functions": { "functionName": {} } + }, + "support_ticket": { + "location": { + "ticket_sidebar": { + "url": "index.html", + "icon": "styles/images/icon.svg" + } + } + } + }, + "engines": { + "node": "24.11.0", + "fdk": "10.0.1" + } +} diff --git a/skills/fw-app-dev/references/templates/mcp-config-prompt.txt b/skills/fw-app-dev/references/templates/mcp-config-prompt.txt new file mode 100644 index 0000000..c91a538 --- /dev/null +++ b/skills/fw-app-dev/references/templates/mcp-config-prompt.txt @@ -0,0 +1,10 @@ +═══════════════════════════════════════════════════════════ +Optional: Configure Marketplace Publishing + +Would you like to set up publishing tools now? +This connects your IDE to the Freshworks Marketplace API. + +You can skip this and configure later. + +Configure MCP now? (y/N) +═══════════════════════════════════════════════════════════ diff --git a/skills/fw-app-dev/references/templates/post-generation-message.txt b/skills/fw-app-dev/references/templates/post-generation-message.txt new file mode 100644 index 0000000..e823476 --- /dev/null +++ b/skills/fw-app-dev/references/templates/post-generation-message.txt @@ -0,0 +1,9 @@ +[VALID] App generated successfully in / + +Validation: [0 platform errors, 0 lint errors] + +Next steps: +1. cd +2. fdk run +3. Test in Freshworks product with ?dev=true +4. When ready to publish: use the publish skill diff --git a/skills/fw-app-dev/references/templates/serverless-app-tree.txt b/skills/fw-app-dev/references/templates/serverless-app-tree.txt new file mode 100644 index 0000000..0683880 --- /dev/null +++ b/skills/fw-app-dev/references/templates/serverless-app-tree.txt @@ -0,0 +1,4 @@ +server/ +└── server.js # Use $request.invokeTemplate() +config/ +└── iparams.json # REQUIRED - even if empty {} diff --git a/skills/fw-app-dev/references/templates/validation-success.txt b/skills/fw-app-dev/references/templates/validation-success.txt new file mode 100644 index 0000000..c6ec347 --- /dev/null +++ b/skills/fw-app-dev/references/templates/validation-success.txt @@ -0,0 +1,9 @@ +[VALID] App generated successfully in / + +Validation: 0 platform errors, 0 lint errors + +Next steps: +1. cd +2. fdk run +3. Test in product with ?dev=true +4. When ready to publish: use the publish skill diff --git a/skills/fw-app-dev/rules/validation-workflow.mdc b/skills/fw-app-dev/rules/validation-workflow.mdc index e9e674a..c3fcb6f 100644 --- a/skills/fw-app-dev/rules/validation-workflow.mdc +++ b/skills/fw-app-dev/rules/validation-workflow.mdc @@ -18,7 +18,7 @@ alwaysApply: true ### Step 0: Gate (before any `fdk validate`) -Read **`manifest.json`** and compare to **`node --version`** / **`fdk version`**. Follow **SKILL.md** → *Manifest + toolchain gate before any `fdk validate`*. Do not skip for **`/fdk-fix`**, **`/fdk-review`**, **`/fdk-refactor`**, or generation workflows. +Read **`manifest.json`** and compare to **`node --version`** / **`fdk version`**. Follow **SKILL.md** → *Manifest + toolchain gate before any `fdk validate`*. Do not skip for **`/fdk-fix`**, **`/fdk-refactor`**, or generation workflows. (For structured pre-submission review, use **fw-review** skill.) ### Step 1: Automatic Validation After File Creation diff --git a/skills/fw-publish/SKILL.md b/skills/fw-publish/SKILL.md index 5e92ed5..b2618f0 100644 --- a/skills/fw-publish/SKILL.md +++ b/skills/fw-publish/SKILL.md @@ -38,37 +38,11 @@ The MCP server is set up but the API key needs to be refreshed or was never set. 1. Go to [https://developers.freshworks.com/developer/](https://developers.freshworks.com/developer/) 2. Under **"Connect to Freddy AI Copilot MCP server"** → select your IDE tab (**Cursor** or **VS Code**) -3. **Cursor:** Click **"Install in Cursor"** directly, or manually add to `~/.cursor/mcp.json`: - ```json - { - "mcpServers": { - "fw-dev-mcp": { - "url": "https://mcp.freshworks.dev/mcp", - "headers": { - "Authorization": "Bearer " - } - } - } - } - ``` - Replace `` with the key copied in step 2, then restart Cursor. +3. **Cursor:** Click **"Install in Cursor"** directly, or merge [`references/templates/cursor-mcp-setup.json`](references/templates/cursor-mcp-setup.json) into `~/.cursor/mcp.json` (replace ``, restart Cursor). **Claude Code (via plugin):** The freshworks plugin prompts for the API key at install time. If you skipped it, run `/config` and update the plugin settings. The key is stored securely in the system keychain. - **Claude Code (standalone skill, no plugin):** Add the server to `.mcp.json` at your project root (or add via `claude mcp add` with `--scope user` to store it globally in `~/.claude.json`): - ```json - { - "mcpServers": { - "fw-dev-mcp": { - "url": "https://mcp.freshworks.dev/mcp", - "headers": { - "Authorization": "Bearer " - } - } - } - } - ``` - Replace `` with the key copied in step 2, then restart Claude Code. + **Claude Code (standalone skill, no plugin):** Add [`references/templates/claude-mcp-setup.json`](references/templates/claude-mcp-setup.json) to project `.mcp.json` or `~/.claude.json` via `claude mcp add --scope user` (replace ``, restart Claude Code). 4. Re-run the publish command **DO NOT proceed with any publish step until auth is confirmed.** @@ -92,23 +66,7 @@ The Developer API key is **product-specific**. Ask the user to confirm their con - Read `engines.node` and `engines.fdk` from `manifest.json` in the app directory - Check active versions: `node --version` and `fdk --version` - **If `fdk` is missing** (`fdk --version` fails / command not found): **STOP**. Do **not** auto-install or assume “latest FDK” without asking. Tell the user the Freshworks CLI is required for **`fdk validate`** / **`fdk pack`**. Offer **`fw-setup`**: **`/fw-setup-install`** (default FDK **10.x** on Node **24.11**). **Optional one-shot:** **“Run `/fw-setup-install` now? (y/n)”** — only on **yes**, follow **`skills/fw-setup/SKILL.md`**; on **no**, end until the user installs manually. **Do not** continue to step 4 until **`fdk`** is available (unless the user explicitly overrides with understanding of the risk). -- **If versions mismatch** (but `fdk` is present), **STOP and inform user:** - ``` - Your app requires Node.js X.Y.Z and FDK A.B.C (from manifest.json engines). - - Current environment: Node vW.X.Y, FDK vP.Q.R - - Would you like me to install/switch to the required versions? (yes/no) - - If yes, I'll use the fw-setup skill to: - - Install Node.js X.Y.Z (if not present) and switch to it - - Install/upgrade to FDK A.B.C - - If no, you can manually run: - - /fw-setup-use (in app directory) - switches Node version - - /fw-setup-install --version A.B.C - installs FDK version - - /fw-setup-upgrade --to A.B.C - upgrades FDK version - ``` +- **If versions mismatch** (but `fdk` is present), **STOP** and show [`references/templates/engines-mismatch-prompt.txt`](references/templates/engines-mismatch-prompt.txt) (substitute manifest vs current versions). - **DO NOT proceed with `fdk pack` until versions match or user explicitly overrides** ### 4. fdk validate (pre-publish) @@ -157,12 +115,7 @@ List only paths that exist after unzip (omit **`server`**, **`README.md`**, etc. ### 5.5 Custom app limit warning (MANDATORY — do not skip) -Show this message to the user verbatim before proceeding: -``` -⚠️ The Freshworks Marketplace has a limit of 25 custom apps per developer account. - If you are creating a new listing, ensure you have not reached this limit. - Check your current count at https://developers.freshworks.com/developer/ -``` +Show [`references/templates/custom-app-limit-warning.txt`](references/templates/custom-app-limit-warning.txt) verbatim before proceeding. **Self-check: did you output the above warning in your response? If not, output it now before continuing to step 6.** ### 6. Publish-time routing: new listing vs existing app (MCP handover) @@ -186,16 +139,7 @@ Do this **at publish time** — **after** you have a valid zip **that passes the a. **Call `list_custom_apps`** (paginate if needed). Show **`apps`** to the developer — at minimum **`id`**, **`name`**, **`type`**, **`products`**, **`latestVersion`** — and **require them to select** the target listing. Record that **`appId`**. b. **Check for stuck latest version:** Call **`list_app_versions`** with the selected **`appId`**. Check only the **latest version** (most recent by `updatedAt`). - - **If the latest version has `state: "development"`**, **STOP** and inform the user: - ``` - Cannot publish — the latest version is stuck in "development" state. - Version: [id, version, state] - - This usually means a previous deployment failed. Please: - 1. Go to https://developers.freshworks.com/developer/ - 2. Navigate to your app and delete or resolve the stuck version - 3. Return here and retry - ``` + - **If the latest version has `state: "development"`**, **STOP** and show [`references/templates/stuck-version-warning.txt`](references/templates/stuck-version-warning.txt) (fill version fields). - **If the latest version is in any other state**, proceed to step 7. c. **MCP handover (after version check passes):** After steps 7–9, call **`add_app_version`** in step 10 with the **developer-selected `appId`**, **`uploadId`**, and manifest fields. @@ -272,13 +216,7 @@ Read `manifest.json` in the app directory. Extract: - If the user confirms **yes**, set `worksWith: ["ai_actions"]` for step 10. - If **no** or `actions.json` is absent, omit `worksWith`. -**Downgrade warning (existing app update path only):** If this is an update to an existing app and `actions.json` is **absent** (or user said **no** to `worksWith`), show this warning before proceeding: -``` -⚠️ If the previous version of this app included worksWith: ["ai_actions"], - removing it in this version is not supported and may cause failures. - Only continue if you are sure the previous version was NOT an AI Actions app. - Proceed? (yes/no) -``` +**Downgrade warning (existing app update path only):** If this is an update to an existing app and `actions.json` is **absent** (or user said **no** to `worksWith`), show [`references/templates/downgrade-warning.txt`](references/templates/downgrade-warning.txt) verbatim before proceeding. **Do not proceed to step 10 until the user confirms.** @@ -328,6 +266,45 @@ Optionally, call **`list_app_versions`** with the **`appId`** to verify the new Tell the user: **app id**, **version state**, and where to install custom apps in their product (**Admin -> Apps** or equivalent). +### 14. Clear tracking fields (post-success cleanup) + +**When:** Only after **successful** `submit_custom_app` or `add_app_version` (step 10 succeeded and step 12 verified the new version is **not** stuck in `development`). + +**Why:** Stale `start_time` in the local manifest corrupts per-version "time to build" metrics on the next publish. + +**Actions:** + +1. **Clear manifest `start_time`:** In `/manifest.json`, if an `app` object exists, set `app.start_time` to JSON `null`. **Preserve** `app.tracking_id` and all other manifest fields. Do **not** remove the `app` object. + ```json + "app": { + "tracking_id": "", + "start_time": null + } + ``` + If `app` is missing, skip this edit. + +2. **Clear session state:** Unset agent session `sessionStartTime` (set to `null` or discard). This variable mirrors manifest `app.start_time` during the development cycle (typically set when **fw-app-dev** populates tracking fields). + +3. **Mark publish complete:** Set `publishState = done`. + +**Session state conventions (internal — do not surface to user):** + +| Variable | When set | Cleared in step 14 | +|----------|----------|-------------------| +| `sessionStartTime` | **fw-app-dev** when generating or populating `app.start_time` | unset / `null` | +| `publishState` | `"in_progress"` when the publish flow begins | `"done"` | + +**Verification (Done when):** +- `manifest.json` → `app.start_time` is `null` +- `sessionStartTime` cleared +- `publishState = done` + +**Do NOT clear if:** +- Step 10 failed (`submit_custom_app` / `add_app_version` returned an error) +- Step 12 shows the version is stuck in `development` state (deployment failed) + +**Silent:** Do **not** mention `start_time`, `sessionStartTime`, or `publishState` to the developer (same internal-only rule as **fw-app-dev** tracking fields). The next **fw-app-dev** session regenerates `start_time` when it is missing or empty. + ## MCP tools reference (fw-dev-mcp) **Supported app states:** Only `test` state is supported. Always use `"test"` for `targetState` — never ask the user to choose a state. diff --git a/skills/fw-publish/references/openai-server-mcp-tools.md b/skills/fw-publish/references/openai-server-mcp-tools.md new file mode 100644 index 0000000..0526d1d --- /dev/null +++ b/skills/fw-publish/references/openai-server-mcp-tools.md @@ -0,0 +1,129 @@ +# openai-server MCP tools (fw-dev-mcp) + +**Hosted endpoint:** `https://mcp.freshworks.dev/mcp` + +**Agent routing:** Use **fw-app-dev** for app development. Use **fw-publish** `SKILL.md` for publish orchestration. `**get_developer_docs`** is **FALLBACK ONLY** when fw-app-dev delegates or fails. + +--- + +## `list_custom_apps` + +List custom apps (`type=custom`) for the authenticated developer. Sorted by `updated_at` desc. + + +| Parameter | Type | Required | Default | Description | +| --------- | ------- | -------- | ------- | ------------------- | +| `page` | integer | no | 1 | 1-based page number | +| `perPage` | integer | no | 10 | Page size | + + +**Returns:** `{ "count": number, "apps": [ { "id", "name", "type", "subType", "subscriptionType", "state", "products" }, ... ] }` + +--- + +## `create_app_upload_url` + +Mint presigned S3 URL for zip upload. Call **before** `submit_custom_app` or `add_app_version`. + +**Parameters:** none + +**Returns:** + + +| Field | Description | +| ------------------ | --------------------------------------- | +| `uploadId` | Opaque id for submit/update | +| `uploadUrl` | Presigned URL — **HTTP PUT** zip binary | +| `httpMethod` | Always `"PUT"` | +| `expiresInSeconds` | URL TTL | +| `instructions` | Human-readable curl hint | + + +**Workflow:** `fdk pack` → this tool → PUT zip → pass `uploadId` to submit/update. + +--- + +## `submit_custom_app` + +Create a **new** custom app + first version (Platform **3.x** only). Target state: `**test`** (fixed server-side). + + +| Parameter | Type | Required | Description | +| ----------------- | -------- | -------- | ---------------------------------------------------------------- | +| `appName` | string | yes | Display name, 2–50 characters | +| `appDescription` | string | yes | Plain text, non-empty | +| `appOverview` | string | yes | Tagline, max 150 characters | +| `supportEmail` | string | yes | Publisher support email | +| `alternateEmail` | string | no | Secondary email | +| `platformVersion` | string | yes | From manifest, e.g. `"3.0"` | +| `modules` | string[] | yes | Top-level `manifest.json` `modules` keys; ≥1 non-`common` module | +| `uploadId` | string | yes | From `create_app_upload_url` after PUT | +| `zipFileName` | string | no | e.g. `my-app.zip` | +| `worksWith` | string[] | no | e.g. `["ai_actions"]` for AI Actions apps | + + +**Returns:** `{ "message", "idempotentReplay"?, "idempotencyNote"?, "app": { ... includes latestVersion } }` + +--- + +## `add_app_version` + +Add version to an **existing** app. Blocked if latest version is `**development`** (check via `list_app_versions`). + + +| Parameter | Type | Required | Description | +| ----------------- | -------- | -------- | ---------------------------------------- | +| `appId` | long | yes | From `list_custom_apps` + user selection | +| `platformVersion` | string | yes | From manifest | +| `modules` | string[] | yes | Updated manifest module keys | +| `uploadId` | string | yes | After PUT to presigned URL | +| `zipFileName` | string | no | Optional | +| `worksWith` | string[] | no | e.g. `["ai_actions"]` | + + +**Returns:** Same shape as `submit_custom_app`. + +--- + +## `list_app_versions` + +Per-version rows for one app. + + +| Parameter | Type | Required | +| --------- | ---- | -------- | +| `appId` | long | yes | + + +**Returns:** `{ "appId", "count", "versions": [ { "id", "versionNumber", "platformVersion", "state", "updatedAt" }, ... ] }` + +--- + +## `get_app_status` + +Aggregate app-level snapshot (`state` reflects all versions). + + +| Parameter | Type | Required | +| --------- | ---- | -------- | +| `appId` | long | yes | + + +**Returns:** `{ "id", "name", "type", "subType", "subscriptionType", "state", "products" }` + +--- + +## `get_developer_docs` (fallback) + +RAG retrieval of Freshworks marketplace development docs. + + +| Parameter | Type | Required | Description | +| ----------------- | ------ | -------- | ------------------------------- | +| `query` | string | yes | What you need help with | +| `platformVersion` | string | no | `"v2"` or `"v3"` (default `v3`) | + + +**Returns:** Markdown documentation string (sections separated by `---`). + +**fw-dev-tools policy:** Use only when **fw-app-dev** explicitly delegates or fails — not as primary app-building path. \ No newline at end of file diff --git a/skills/fw-publish/references/templates/claude-mcp-setup.json b/skills/fw-publish/references/templates/claude-mcp-setup.json new file mode 100644 index 0000000..a3f81bd --- /dev/null +++ b/skills/fw-publish/references/templates/claude-mcp-setup.json @@ -0,0 +1,10 @@ +{ + "mcpServers": { + "fw-dev-mcp": { + "url": "https://mcp.freshworks.dev/mcp", + "headers": { + "Authorization": "Bearer " + } + } + } +} diff --git a/skills/fw-publish/references/templates/cursor-mcp-setup.json b/skills/fw-publish/references/templates/cursor-mcp-setup.json new file mode 100644 index 0000000..a3f81bd --- /dev/null +++ b/skills/fw-publish/references/templates/cursor-mcp-setup.json @@ -0,0 +1,10 @@ +{ + "mcpServers": { + "fw-dev-mcp": { + "url": "https://mcp.freshworks.dev/mcp", + "headers": { + "Authorization": "Bearer " + } + } + } +} diff --git a/skills/fw-publish/references/templates/custom-app-limit-warning.txt b/skills/fw-publish/references/templates/custom-app-limit-warning.txt new file mode 100644 index 0000000..bfaeae0 --- /dev/null +++ b/skills/fw-publish/references/templates/custom-app-limit-warning.txt @@ -0,0 +1,3 @@ +⚠️ The Freshworks Marketplace has a limit of 25 custom apps per developer account. + If you are creating a new listing, ensure you have not reached this limit. + Check your current count at https://developers.freshworks.com/developer/ diff --git a/skills/fw-publish/references/templates/downgrade-warning.txt b/skills/fw-publish/references/templates/downgrade-warning.txt new file mode 100644 index 0000000..830d339 --- /dev/null +++ b/skills/fw-publish/references/templates/downgrade-warning.txt @@ -0,0 +1,4 @@ +⚠️ If the previous version of this app included worksWith: ["ai_actions"], + removing it in this version is not supported and may cause failures. + Only continue if you are sure the previous version was NOT an AI Actions app. + Proceed? (yes/no) diff --git a/skills/fw-publish/references/templates/engines-mismatch-prompt.txt b/skills/fw-publish/references/templates/engines-mismatch-prompt.txt new file mode 100644 index 0000000..532fe39 --- /dev/null +++ b/skills/fw-publish/references/templates/engines-mismatch-prompt.txt @@ -0,0 +1,14 @@ +Your app requires Node.js X.Y.Z and FDK A.B.C (from manifest.json engines). + +Current environment: Node vW.X.Y, FDK vP.Q.R + +Would you like me to install/switch to the required versions? (yes/no) + +If yes, I'll use the fw-setup skill to: +- Install Node.js X.Y.Z (if not present) and switch to it +- Install/upgrade to FDK A.B.C + +If no, you can manually run: +- /fw-setup-use (in app directory) - switches Node version +- /fw-setup-install --version A.B.C - installs FDK version +- /fw-setup-upgrade --to A.B.C - upgrades FDK version diff --git a/skills/fw-publish/references/templates/stuck-version-warning.txt b/skills/fw-publish/references/templates/stuck-version-warning.txt new file mode 100644 index 0000000..42eeb41 --- /dev/null +++ b/skills/fw-publish/references/templates/stuck-version-warning.txt @@ -0,0 +1,7 @@ +Cannot publish — the latest version is stuck in "development" state. +Version: [id, version, state] + +This usually means a previous deployment failed. Please: +1. Go to https://developers.freshworks.com/developer/ +2. Navigate to your app and delete or resolve the stuck version +3. Return here and retry diff --git a/skills/fw-publish/scripts/repack-app-zip.sh b/skills/fw-publish/scripts/repack-app-zip.sh new file mode 100755 index 0000000..39a542c --- /dev/null +++ b/skills/fw-publish/scripts/repack-app-zip.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash +# Repack an FDK zip so manifest.json is at archive root (no ./ prefix). +# Usage: repack-app-zip.sh +set -euo pipefail + +SRC_ZIP="${1:?source zip path}" +OUT_DIR="${2:?temp unpack directory}" +OUT_ZIP="${3:?output zip path (full path)}" + +rm -rf "$OUT_DIR" +mkdir -p "$OUT_DIR" +unzip -q -o "$SRC_ZIP" -d "$OUT_DIR" + +cd "$OUT_DIR" +MEMBERS=() +for f in manifest.json app config server README.md; do + [ -e "$f" ] && MEMBERS+=("$f") +done +# Include any other top-level entries not already listed +for entry in *; do + [[ " ${MEMBERS[*]} " == *" $entry "* ]] && continue + MEMBERS+=("$entry") +done + +if [ ${#MEMBERS[@]} -eq 0 ]; then + echo "No files to pack in $OUT_DIR" >&2 + exit 1 +fi + +zip -r "$OUT_ZIP" "${MEMBERS[@]}" +echo "Repacked: $OUT_ZIP" diff --git a/skills/fw-setup/SKILL.md b/skills/fw-setup/SKILL.md index 8e8b662..9fb1f8b 100644 --- a/skills/fw-setup/SKILL.md +++ b/skills/fw-setup/SKILL.md @@ -32,16 +32,7 @@ Parse user request and execute the appropriate operation: | "fdk broken", "fdk not found", `/fw-setup-troubleshoot`; **`--fix`** only if user asks | Diagnose inline; **`--fix`** spawns shell Task (see `commands/fw-setup-troubleshoot.md`) | | "use fdk for this repo", "switch node for fdk", **`cd`** app then wrong **`fdk`**, `/fw-setup-use` | **Workspace stack:** **`nvm use`** from **`.nvmrc`** or explicit **10**/**9** (Node **24.11** vs **18**); optional **`--write-nvmrc`** (inline only — see `commands/fw-setup-use.md`) | -**FDK 9.x Deprecation Warning (Always show when installing/downgrading to FDK 9.x):** -``` -WARNING: FDK 9.x + Node 18.x is DEPRECATED (ends May 31, 2026) - -- Development: Allowed for Platform 3.0 apps -- Publishing: NOT SUPPORTED - requires FDK 10.x + Node 24.x -- Recommendation: Use FDK 10.x for all new development - -Continue with FDK 9.x installation? (y/N) -``` +**FDK 9.x deprecation (install/downgrade to 9.x):** Show verbatim from [`references/templates/fdk9-deprecation-warning.txt`](references/templates/fdk9-deprecation-warning.txt). ## Core Rules - UNIVERSAL ENFORCEMENT @@ -127,37 +118,15 @@ You are not a tutor. You are an enforcement layer. - ❌ `fdk version` on Node 24.14.x with FDK 10.1.0 → engine mismatch error - ❌ Only uninstalling `@freshworks/fdk` → leaves legacy `fdk` package behind -### Correct Workflow: +### Install execution -```bash -# Uninstall both package names -npm uninstall -g @freshworks/fdk 2>/dev/null -npm uninstall -g fdk 2>/dev/null -rm -rf ~/.fdk -npm cache clean --force - -# Install FDK 10.x on Node 24.11.x -nvm install 24.11 -nvm use 24.11 -nvm alias default 24.11 -npm install -g https://cdn.freshdev.io/fdk/latest-v24.tgz - -# Verify -fdk version # Should show 10.x.x -node --version # Should show v24.11.x -``` +Run **`/fw-setup-install`** and follow [`commands/fw-setup-install.md`](commands/fw-setup-install.md) only (CDN tarball + pinned Node per **`docs/engine-matrix.md`**). ## Quick Detection (Pre-Subagent) Run these checks directly before spawning subagents to provide context: -```bash -fdk version 2>&1 || echo "FDK not installed" -node --version 2>&1 || echo "Node not installed" -command -v nvm &>/dev/null && echo "nvm installed" || echo "nvm missing" -nvm current 2>&1 || echo "No nvm version active" -ls ~/.fdk 2>&1 || echo "No ~/.fdk directory" -``` +**Inline:** `bash scripts/fw-setup-quick-detect.sh` (same checks as **`/fw-setup-status`** default block). **Report format:** ``` @@ -175,107 +144,11 @@ DETECTION: **Trigger:** FDK not installed or user requests installation. -**AUTHORITATIVE SOURCE:** Follow **CDN Tarball Reality** (above). Do **not** use `@freshworks/fdk` from the public npm registry, `brew install fdk`, or `choco install fdk` as primary install paths—they do **not** replace **nvm/nvm-windows + CDN tarball + pinned Node**. - -**Steps:** - -1. Detect OS: `uname -s` (macOS: Darwin, Linux: Linux); on Windows PowerShell `$env:OS`. - -2. Check prerequisites (`nvm`/Node). On Windows use **nvm-windows** (see `references/windows.md`). **Do not** use **native** `nvm` on CMD without nvm-windows. If **`where.exe node`** shows **`Program Files\nodejs`** first or **winget/choco/Store** Node competes with nvm, read **`references/windows.md`** (*Installer-based setups*) before **`npm install -g`**. - -3. Spawn subagent with this prompt: - -``` -Install FDK 10.x (default) using nvm + CDN tarball per repository docs (see CDN Tarball Reality + docs/engine-matrix.md). - -DETECTION: -- OS: [detected] -- nvm / nvm-windows: [installed/missing] -- Node: [version/missing] - -AUTHORITATIVE INSTALL (FDK 10.x line): -- Node: nvm install 24.11.0 && nvm use 24.11.0 && nvm alias default 24.11.0 (Unix nvm) OR equivalent nvm-windows commands. -- Remove old globals: npm uninstall -g @freshworks/fdk; npm uninstall -g fdk; rm -rf ~/.fdk (Unix) or remove %USERPROFILE%\.fdk on Windows. -- npm cache clean --force -- npm install -g https://cdn.freshdev.io/fdk/latest-v24.tgz - -FDK 9.x (deprecated): only if user confirms after warning — Node 18.x + npm install -g https://cdn.freshdev.io/fdk/latest.tgz — never publish with 9.x. - -PACKAGE MANAGER NOTE: Homebrew/Chocolatey are NOT authoritative for pinning; if user insists, verify same semver as CDN and still require correct Node via nvm when possible. - -VERIFICATION OS split: -- macOS/Linux new shell: zsh -c 'fdk version' || bash -c 'fdk version' -- Windows: new PowerShell window — where.exe fdk; fdk version (see references/windows.md for PATH refresh if needed). - -REPORT: FDK version, Node version, method = cdn_tarball+nvm. -``` - -4. **MANDATORY VERIFICATION (CRITICAL):** Use **Mandatory verification gates** section below (**Unix/Linux vs Windows** branches). Do **not** claim completion if the OS-appropriate gates fail. - -5. **Report format:** - ``` - [VALID] FDK installed successfully - - Verification: ✓ Gates passed (current + new shell) per OS - - Installation: cdn_tarball+nvm - FDK version: [version] - Node version: [version] - -Next steps: - 1. Restart terminal (Unix: source shell rc if needed) - 2. Run: fdk version - 3. Create app: fdk create - ``` - -6. **Post-install: MCP server configuration (optional, skippable)** - - After a successful install, offer to configure the MCP connection for publish tools: - - ``` - Would you like to configure the Marketplace MCP server for publishing? - This connects your IDE to the Freshworks openai-server so you can - use publish tools (list apps, submit, update, check status). - You can skip this and set it up later. (y/N) - ``` - - **If user says yes:** - - Ask for their **API key**: API key from [developers.freshworks.com/developer/](https://developers.freshworks.com/developer/) - API key for Freddy AI Copilot for VS Code plugin & Agentic Developer Toolkit. or Connect to Developer MCP server (For MCP configuration) - - The MCP server URL is fixed: `https://mcp.freshworks.dev/mcp` - - Detect IDE and write config: - - **Claude Code:** Guide them to run `/config` and set the plugin's `mcp_auth_token` field (stored in system keychain via `userConfig`). The server URL is defined in **`.mcp.json`** at this repository’s root. - - **Cursor:** Write or update `~/.cursor/mcp.json`: - ```json - { - "mcpServers": { - "fw-dev-mcp": { - "url": "https://mcp.freshworks.dev/mcp", - "headers": { - "Authorization": "Bearer " - } - } - } - } - ``` - - Confirm: "MCP server configured. Publish tools are now available." - - **If user says no or skips:** - - "Skipped. Configure MCP later via your IDE settings (see AGENTS.md)." - - **Rules:** - - NEVER ask the user to paste the JWT into chat — write to config file or direct to IDE settings UI - - Only offer this step after **successful install or upgrade**, not during status/troubleshoot/downgrade/uninstall - -**Error handling:** If installation fails, read `references/macos.md` or `references/windows.md` for OS-specific troubleshooting. +1. Run **`/fw-setup-install`** → follow [`commands/fw-setup-install.md`](commands/fw-setup-install.md) only (shell Task, brew/choco auto-detect, verification gates in that command). +2. Enforce **CDN Tarball Reality** (above) — not registry `@freshworks/fdk` as primary. +3. On failure: `references/macos.md` or `references/windows.md`. -**CRITICAL RULES:** -- [INVALID] NEVER say "installation complete" until **Mandatory verification gates** below pass for the user's OS (Unix vs Windows). -- On **macOS/Linux**, new-shell check uses `zsh -c 'fdk version'` or `bash -c 'fdk version'`. -- On **Windows**, new-shell check opens a **new PowerShell window** (or subprocess) and runs `where.exe fdk` + `fdk version`; follow `references/windows.md` if PATH is stale. -- [VALID] Node **24.11.x** active for FDK 10.x line unless user explicitly installs deprecated FDK 9 + Node 18 after confirmation. -- [INVALID] NEVER skip verification steps +**Post-install MCP (optional):** After successful install/upgrade only — offer Marketplace MCP setup; **Cursor** config shape: [`references/templates/cursor-mcp-config.json`](references/templates/cursor-mcp-config.json); **Claude Code:** `.mcp.json` + `mcp_auth_token` per **AGENTS.md**. Never paste JWT in chat. --- @@ -338,21 +211,7 @@ Do **not** use `npm install -g @freshworks/fdk@latest` from the public npm regis **Trigger:** User checks FDK installation. -**Steps:** - -1. Run checks directly (no subagent needed): - -```bash -echo "=== FDK Status ===" -fdk version 2>&1 || echo "Not installed" -node --version 2>&1 || echo "Not installed" -nvm --version 2>&1 || echo "Not installed" - which fdk -[ -d ~/.fdk ] && echo "Cache exists" || echo "No cache" -echo "==================" -``` - -2. Report findings to user. +**Inline only.** Run bash blocks in [`commands/fw-setup-status.md`](commands/fw-setup-status.md) (default; `--verbose` adds PATH/nvm/rc diagnostics). --- diff --git a/skills/fw-setup/commands/fw-setup-install.md b/skills/fw-setup/commands/fw-setup-install.md index 8dbf6ed..e1d0343 100644 --- a/skills/fw-setup/commands/fw-setup-install.md +++ b/skills/fw-setup/commands/fw-setup-install.md @@ -311,8 +311,7 @@ REPORT FORMAT: CRITICAL: If ANY mandatory test fails, do not say "installation complete". POST-INSTALL MCP CONFIG (optional — only after ALL verification passes): - # Offer MCP configuration via dedicated subagent - # Full implementation: skills/fw-publish/subagents/mcp-config-prompt.md + # Offer MCP configuration for marketplace publishing echo "" echo "═══════════════════════════════════════════════════════════" @@ -325,14 +324,12 @@ POST-INSTALL MCP CONFIG (optional — only after ALL verification passes): read -p "Configure MCP now? (y/N): " mcp_response if [[ "$mcp_response" =~ ^[yY]$ ]]; then - # Execute MCP configuration subagent - # Implementation: skills/fw-publish/subagents/mcp-config-prompt.md - # This handles: API key prompt, IDE detection, config file creation, verification + # MCP configuration handles: API key prompt, IDE detection, config file creation, verification + # See AGENTS.md and skills/fw-publish/SKILL.md for full setup instructions echo "" echo "Launching MCP configuration..." - echo "See: skills/fw-publish/subagents/mcp-config-prompt.md for full flow" + echo "See: AGENTS.md and skills/fw-publish/SKILL.md for setup" echo "" - # Agent should read and follow mcp-config-prompt.md from Step 3A.1 onwards else echo "Skipped. Configure MCP later:" echo "- Run: /fw-setup-install (choose MCP option)" diff --git a/skills/fw-setup/references/templates/cursor-mcp-config.json b/skills/fw-setup/references/templates/cursor-mcp-config.json new file mode 100644 index 0000000..1cb5332 --- /dev/null +++ b/skills/fw-setup/references/templates/cursor-mcp-config.json @@ -0,0 +1,10 @@ +{ + "mcpServers": { + "fw-dev-mcp": { + "url": "https://mcp.freshworks.dev/mcp", + "headers": { + "Authorization": "Bearer " + } + } + } +} diff --git a/skills/fw-setup/references/templates/fdk9-deprecation-warning.txt b/skills/fw-setup/references/templates/fdk9-deprecation-warning.txt new file mode 100644 index 0000000..8753139 --- /dev/null +++ b/skills/fw-setup/references/templates/fdk9-deprecation-warning.txt @@ -0,0 +1,7 @@ +WARNING: FDK 9.x + Node 18.x is DEPRECATED (ends May 31, 2026) + +- Development: Allowed for Platform 3.0 apps +- Publishing: NOT SUPPORTED - requires FDK 10.x + Node 24.x +- Recommendation: Use FDK 10.x for all new development + +Continue with FDK 9.x installation? (y/N) diff --git a/skills/fw-setup/scripts/fw-setup-quick-detect.sh b/skills/fw-setup/scripts/fw-setup-quick-detect.sh new file mode 100755 index 0000000..4af090a --- /dev/null +++ b/skills/fw-setup/scripts/fw-setup-quick-detect.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +# Quick FDK/Node/nvm detection (read-only). Used before mutating install Tasks. +set -euo pipefail + +fdk version 2>&1 || echo "FDK not installed" +node --version 2>&1 || echo "Node not installed" +command -v nvm &>/dev/null && echo "nvm installed" || echo "nvm missing" +nvm current 2>&1 || echo "No nvm version active" +ls ~/.fdk 2>&1 || echo "No ~/.fdk directory"