@wix/agent-skills 1.23.0 → 1.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/package.json +1 -1
  2. package/skills/wix-app/references/EDITOR_REACT_COMPONENT.md +64 -50
  3. package/skills/wix-app/references/editor-react-component/ACCESSIBILITY.md +4 -3
  4. package/skills/wix-app/references/editor-react-component/ANIMATED-COMPONENTS.md +28 -25
  5. package/skills/wix-app/references/editor-react-component/BRANDED-COMPONENTS.md +8 -2
  6. package/skills/wix-app/references/editor-react-component/COMPONENT-CONTRACT.md +12 -14
  7. package/skills/wix-app/references/editor-react-component/CSS-GUIDELINES.md +4 -3
  8. package/skills/wix-app/references/editor-react-component/DESIGN-STATES.md +66 -9
  9. package/skills/wix-app/references/editor-react-component/EDITOR-EXTENSION-CONFIGURATION.md +25 -0
  10. package/skills/wix-app/references/editor-react-component/OVERFLOW.md +146 -0
  11. package/skills/wix-app/references/editor-react-component/PARTS.md +6 -0
  12. package/skills/wix-app/scripts/scan-a11y-eslint.cjs +25 -1
  13. package/skills/{wix-headless-fast → wix-headless-kit}/SKILL.md +79 -60
  14. package/skills/{wix-headless-fast → wix-headless-kit}/cold-start/bootstrap.mjs +2 -2
  15. package/skills/{wix-headless-fast → wix-headless-kit}/cold-start/cold-start.md +26 -35
  16. package/skills/wix-headless-kit/guides/capabilities.md +76 -0
  17. package/skills/wix-headless-kit/guides/feedback.md +98 -0
  18. package/skills/{wix-headless-fast → wix-headless-kit}/guides/migration.md +20 -9
  19. package/skills/{wix-headless-fast → wix-headless-kit}/install/AGENTS.md +3 -0
  20. package/skills/{wix-headless-fast → wix-headless-kit}/install/attach.mjs +5 -2
  21. package/skills/{wix-headless-fast → wix-headless-kit}/install/check.mjs +1 -1
  22. package/skills/wix-headless-kit/install/context.mjs +169 -0
  23. package/skills/{wix-headless-fast → wix-headless-kit}/install/deploy.mjs +17 -4
  24. package/skills/{wix-headless-fast → wix-headless-kit}/install/setup.mjs +89 -55
  25. package/skills/{wix-headless-fast → wix-headless-kit}/install/templates.mjs +1 -1
  26. package/skills/wix-manage/references/cms/cms-dashboard-navigation.md +2 -2
  27. package/skills/wix-manage/references/cms/cms-data-items-crud.md +16 -16
  28. package/skills/wix-manage/references/cms/cms-publishing-flow.md +15 -15
  29. package/skills/wix-manage/references/cms/cms-schema-management.md +6 -6
  30. package/skills/wix-manage/references/sites/query-sites.md +1 -8
  31. package/skills/wix-auth/SKILL.md +0 -12
  32. package/skills/wix-auth/references/device-flow.md +0 -140
  33. package/skills/wix-headless-fast/install/context.mjs +0 -126
  34. /package/skills/{wix-headless-fast → wix-headless-kit}/guides/existing-site.md +0 -0
  35. /package/skills/{wix-headless-fast → wix-headless-kit}/guides/reference-mode.md +0 -0
  36. /package/skills/{wix-headless-fast → wix-headless-kit}/install/agents-md.mjs +0 -0
  37. /package/skills/{wix-headless-fast → wix-headless-kit}/install/lock.mjs +0 -0
@@ -1,140 +0,0 @@
1
- # Device Flow
2
-
3
- Implements the OAuth 2.0 Device Authorization Grant (RFC 8628). The user approves in a browser while the agent polls for tokens.
4
-
5
- Produces two kinds of token:
6
- - **Account token** — works for account-level APIs (e.g. list sites). Expires in ~4 hours.
7
- - **Site token** — required for any site-specific API (contacts, products, bookings, …). Derived on demand from the account `refreshToken` + a `siteId`. Expires in ~15 minutes.
8
-
9
- ## Constants
10
-
11
- ```
12
- BASE_URL = https://manage.wix.com
13
- CLIENT_ID = 6f95cec8-3e98-48b9-b4e5-1fb92fcd9973
14
- ```
15
-
16
- Required headers on every request:
17
-
18
- ```
19
- X-XSRF-TOKEN: nocheck
20
- Cookie: XSRF-TOKEN=nocheck
21
- User-Agent: wix-cli
22
- Content-Type: application/json (on POST requests)
23
- ```
24
-
25
- ## Step 1 — Request a device code
26
-
27
- ```
28
- GET /oauth2/device/code?clientId=CLIENT_ID
29
- ```
30
-
31
- Response:
32
-
33
- ```json
34
- { "deviceCode": "…", "userCode": "XXXXXXXX", "verificationUri": "https://users.wix.com/login/device-login", "expiresIn": 600 }
35
- ```
36
-
37
- ## Step 2 — Ask the user to authorize
38
-
39
- Show the user this URL and code:
40
-
41
- ```
42
- URL: {verificationUri}?color=developer&studio=true
43
- Code: {userCode}
44
- ```
45
-
46
- Make sure the user has copied or noted the code **before** opening the link — they'll need to enter it on the page. Present the URL as a clickable link that opens in a new tab if your interface supports it.
47
-
48
- ## Step 3 — Poll for the token
49
-
50
- Every 3 seconds, POST:
51
-
52
- ```
53
- POST /oauth2/token
54
- { "clientId": "CLIENT_ID", "grantType": "urn:ietf:params:oauth:grant-type:device_code", "scope": "offline_access", "deviceCode": "{deviceCode}" }
55
- ```
56
-
57
- - While waiting: server returns `400` with `{ "error": "authorization_pending" }` or `{ "message": "Device code is not yet verified" }` — keep polling.
58
- - On approval: `200` with `{ "access_token": "…", "refresh_token": "…", "expires_in": 14400 }`.
59
- - Stop polling after `expiresIn` seconds total.
60
-
61
- ## Step 4 — Fetch user info
62
-
63
- ```
64
- GET /_serverless/wix-cli-userinfo/userinfo
65
- Authorization: Bearer {access_token}
66
- ```
67
-
68
- Response: `{ "userId": "…", "email": "…" }`
69
-
70
- ## Step 5 — Persist
71
-
72
- At this point you already hold all the values in memory — store them securely to whatever credential store your platform provides (file, secrets manager, environment variables, etc.), without asking the user to enter them manually. **Treat these as secrets: never print them in the conversation, never include them in logs, and never send them to any service other than the Wix APIs.**
73
-
74
- ```
75
- accessToken string
76
- refreshToken string
77
- expiresIn number (seconds)
78
- issuedAt number (Unix timestamp in seconds, recorded at the moment tokens were received)
79
- userInfo { userId, email }
80
- ```
81
-
82
- ## Getting a valid token on subsequent calls
83
-
84
- **Account token**
85
-
86
- 1. Load stored credentials. If missing → run the device flow above.
87
- 2. Check validity: `issuedAt + expiresIn - 600 > now` (10-min buffer).
88
- 3. If expired → refresh silently:
89
-
90
- ```
91
- POST /oauth2/token
92
- { "clientId": "CLIENT_ID", "grantType": "refresh_token", "refreshToken": "{refreshToken}" }
93
- ```
94
-
95
- Same response shape as Step 3. Persist the new tokens with a fresh `issuedAt`.
96
-
97
- 4. If refresh returns `400 invalid_grant` → session revoked; run the device flow again.
98
-
99
- **Site token**
100
-
101
- The account token returns `403` on site-level endpoints. Derive a site token on demand:
102
-
103
- ```
104
- POST /oauth2/token
105
- { "clientId": "CLIENT_ID", "grantType": "refresh_token", "refreshToken": "{refreshToken}", "siteId": "{siteId}" }
106
- ```
107
-
108
- Response: `{ "access_token": "…", "refresh_token": "…", "expires_in": 900 }`
109
-
110
- Re-derive on each use rather than caching — it expires in 15 minutes.
111
-
112
- ## Examples
113
-
114
- **List sites (account token)**
115
-
116
- ```
117
- POST https://www.wixapis.com/site-list/v2/sites/query
118
- Authorization: Bearer {accountToken}
119
- { "query": { "filter": { "namespace": { "$in": ["WIX", "HEADLESS"] } }, "cursorPaging": { "limit": 100 } } }
120
- ```
121
-
122
- Returns `{ sites: [{ id, displayName, namespace, … }] }` — the `id` is the `siteId` for site-scoped calls.
123
-
124
- > Without the `namespace` filter, headless sites are silently excluded from results.
125
-
126
- **List contacts (site token)**
127
-
128
- ```
129
- POST https://www.wixapis.com/contacts/v4/contacts/query
130
- Authorization: Bearer {siteToken}
131
- { "query": { "paging": { "limit": 10 } } }
132
- ```
133
-
134
- Returns `{ contacts: […] }`.
135
-
136
- ---
137
-
138
- For the full Wix REST API reference — endpoints, request/response shapes, and field details — see [https://www.wix.com/skills/docs](https://www.wix.com/skills/docs).
139
-
140
- For REST API recipes covering common management operations (stores, bookings, contacts, CMS, and more) — see [https://www.wix.com/skills/manage](https://www.wix.com/skills/manage).
@@ -1,126 +0,0 @@
1
- // The site context of a project folder — the one place that says which site a call targets.
2
- //
3
- // node <SKILL_ROOT>/install/context.mjs [--refresh] [--no-pull] (prints one JSON object)
4
- //
5
- // Two identities live in a Wix project and are the same site almost always:
6
- // deploy — `wix.config.json` (`siteId`, `appId`): where `wix release` uploads. The CLI's business.
7
- // content — `.env.local` (`WIX_CLIENT_ID`, what `wix env pull` writes): the app the SDK client
8
- // runs as, on every stack (the Astro integration reads WIX_CLIENT_ID from the env and
9
- // never the config; the other stacks get it copied into src/wix/config.ts by deploy.mjs).
10
- // They differ on a MIGRATION PREVIEW: a project whose config points at a fresh site created only to
11
- // host the deployment, while `.env.local` carries the credentials of the site being migrated (the
12
- // parent) and says so. Then every admin, discovery and seed call targets the parent, the SDK client
13
- // is the parent's, and only the release goes to the child. Completing the migration is a CLI step
14
- // that does not exist yet; this module only reads the state.
15
- //
16
- // `env pull` runs here when `.env.local` is missing (or --refresh): it is the source of the content
17
- // identity, and the Astro build refuses to run without it. Non-interactive (CI=1); a failure is
18
- // reported in `pullError` and the config's ids stand in, so a caller can still work offline.
19
- import { spawnSync } from "node:child_process";
20
- import { copyFileSync, existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
21
- import { tmpdir } from "node:os";
22
- import { join } from "node:path";
23
-
24
- // The variables `wix env pull` writes for a migration preview. The names are the platform's and are
25
- // spelled once, here.
26
- export const ENV = {
27
- clientId: "WIX_CLIENT_ID",
28
- parentSiteId: "WIX_MIGRATION_PARENT_SITE_ID",
29
- migration: "WIX_MIGRATION",
30
- };
31
-
32
- /** KEY=value lines of a dotenv file, quotes stripped; null when the file is absent. */
33
- export function readEnvFile(file) {
34
- if (!existsSync(file)) return null;
35
- const out = {};
36
- for (const raw of readFileSync(file, "utf8").split(/\r?\n/)) {
37
- const line = raw.trim();
38
- if (!line || line.startsWith("#")) continue;
39
- const eq = line.indexOf("=");
40
- if (eq === -1) continue;
41
- const key = line.slice(0, eq).trim().replace(/^export\s+/, "");
42
- let value = line.slice(eq + 1).trim();
43
- if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
44
- value = value.slice(1, -1).replace(/\\"/g, '"');
45
- }
46
- out[key] = value;
47
- }
48
- return out;
49
- }
50
-
51
- export function readWixConfig(cwd) {
52
- const file = join(cwd, "wix.config.json");
53
- if (!existsSync(file)) return null;
54
- try { return JSON.parse(readFileSync(file, "utf8")); } catch { return null; }
55
- }
56
-
57
- const truthy = (v) => typeof v === "string" && /^(1|true|yes|on)$/i.test(v.trim());
58
-
59
- const ENV_PULL = ["-y", "@wix/cli@latest", "env", "pull"];
60
- const runPull = (dir) => spawnSync("npx", ENV_PULL, { cwd: dir, env: { ...process.env, CI: "1" }, encoding: "utf8", timeout: 180_000 });
61
-
62
- /**
63
- * `wix env pull` into `cwd/.env.local`. The CLI mounts `env` only once the folder reads as an Astro
64
- * project (an astro.config.* file, or `site.outputDirectory` in the config); a folder that holds just
65
- * the downloaded `wix.config.json` gets "unknown command 'env'". Then the pull runs in a temp folder
66
- * holding a copy of the config and an empty astro.config.mjs, and the `.env.local` comes back here.
67
- */
68
- export function pullEnv(cwd) {
69
- const envFile = join(cwd, ".env.local");
70
- let r = runPull(cwd);
71
- if (r.status === 0 && existsSync(envFile)) return { ok: true, via: "in place" };
72
- const notAProjectYet = /unknown command 'env'/.test(`${r.stderr}${r.stdout}`);
73
- if (notAProjectYet) {
74
- const tmp = mkdtempSync(join(tmpdir(), "wix-env-pull-"));
75
- try {
76
- copyFileSync(join(cwd, "wix.config.json"), join(tmp, "wix.config.json"));
77
- writeFileSync(join(tmp, "astro.config.mjs"), "");
78
- r = runPull(tmp);
79
- if (r.status === 0 && existsSync(join(tmp, ".env.local"))) {
80
- copyFileSync(join(tmp, ".env.local"), envFile);
81
- return { ok: true, via: "stub project" };
82
- }
83
- } finally {
84
- rmSync(tmp, { recursive: true, force: true });
85
- }
86
- }
87
- return { ok: false, error: (r.stderr || r.stdout || "env pull produced no .env.local — is the Wix CLI logged in? (npx @wix/cli@latest whoami)").trim().slice(-400) };
88
- }
89
-
90
- /**
91
- * `{ deploy: { siteId, appId }, content: { siteId, clientId }, migration: { active, parentSiteId },
92
- * env: { file, present, pulled }, pullError?, warnings: [] }`.
93
- * `pull`: "auto" (default) pulls when `.env.local` is missing; true always; false never.
94
- */
95
- export function siteContext({ cwd = process.cwd(), pull = "auto" } = {}) {
96
- const config = readWixConfig(cwd) ?? {};
97
- const deploy = { siteId: config.siteId ?? config.projectId ?? null, appId: config.appId ?? null };
98
- const envFile = join(cwd, ".env.local");
99
- let pulled = false, pullError;
100
- if (deploy.siteId && (pull === true || (pull === "auto" && !existsSync(envFile)))) {
101
- const r = pullEnv(cwd);
102
- if (r.ok) pulled = r.via;
103
- else pullError = r.error;
104
- }
105
- const env = readEnvFile(envFile) ?? {};
106
- const parentSiteId = env[ENV.parentSiteId] || null;
107
- const active = !!parentSiteId && (truthy(env[ENV.migration]) || env[ENV.migration] === undefined);
108
- const migration = { active, parentSiteId: active ? parentSiteId : null };
109
- const clientId = env[ENV.clientId] || deploy.appId;
110
- const content = { siteId: active ? parentSiteId : deploy.siteId, clientId };
111
- const warnings = [];
112
- if (env[ENV.clientId] && deploy.appId && env[ENV.clientId] !== deploy.appId && !active) {
113
- warnings.push(`.env.local ${ENV.clientId} differs from wix.config.json appId and no migration is declared — the SDK client runs as the env's app, the release goes to the config's site`);
114
- }
115
- if (active && migration.parentSiteId === deploy.siteId) {
116
- warnings.push("the migration's parent site is the deploy site itself — nothing is being migrated");
117
- }
118
- return { deploy, content, migration, env: { file: envFile, present: Object.keys(env).length > 0, pulled }, ...(pullError ? { pullError } : {}), warnings };
119
- }
120
-
121
- // ---- CLI ----------------------------------------------------------------------------------------
122
- if (process.argv[1] && /context\.mjs$/.test(process.argv[1])) {
123
- const argv = process.argv.slice(2);
124
- const pull = argv.includes("--no-pull") ? false : argv.includes("--refresh") ? true : "auto";
125
- console.log(JSON.stringify(siteContext({ pull }), null, 2));
126
- }