wp-studio 1.7.10 → 1.7.11
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.
- package/dist/cli/{_events-BcapW3eh.mjs → _events-B8xQ_baD.mjs} +4 -5
- package/dist/cli/appdata-D-luHxJU.mjs +19 -0
- package/dist/cli/{certificate-manager-SVYcCL_i.mjs → certificate-manager-v-yNLDFJ.mjs} +134 -15
- package/dist/cli/{delete-D1924O3o.mjs → delete-BG-E-HsW.mjs} +3 -3
- package/dist/cli/{helpers-oQuItT8n.mjs → helpers-CIAgfdq8.mjs} +2 -2
- package/dist/cli/{index-4lan3TI_.mjs → index-Bej4fL6n.mjs} +31 -4
- package/dist/cli/{index-BjzOJKPi.mjs → index-Dhun0W1n.mjs} +90 -52
- package/dist/cli/{index-DRQnCQvM.mjs → index-ul3DeWvy.mjs} +1308 -1109
- package/dist/cli/{list-DOFyyV1f.mjs → list-ck0oK4vb.mjs} +3 -3
- package/dist/cli/{login-BtPZeZ4G.mjs → login-Dz63Zdfn.mjs} +3 -3
- package/dist/cli/{logout-Cr631QzG.mjs → logout-CLUKQeZh.mjs} +2 -3
- package/dist/cli/main.mjs +2 -2
- package/dist/cli/{paths-CqXGLB7R.mjs → paths-D7DniT1Q.mjs} +7 -6
- package/dist/cli/plugin/skills/rank-me-up/SKILL.md +166 -0
- package/dist/cli/plugin/skills/site-spec/SKILL.md +4 -0
- package/dist/cli/process-manager-daemon.mjs +29 -5
- package/dist/cli/{process-manager-ipc-BisO0qtU.mjs → process-manager-ipc-GCdebuBH.mjs} +4 -1
- package/dist/cli/proxy-daemon.mjs +1 -1
- package/dist/cli/{prune-pm-logs-COryxqeo.mjs → prune-pm-logs-Dm_Bwi7l.mjs} +1 -1
- package/dist/cli/{resume-BwDwdJtq.mjs → resume-BSIOJnyM.mjs} +4 -15
- package/dist/cli/{rewrite-wp-cli-post-content-2zlfFnKT.mjs → rewrite-wp-cli-post-content-Beo5_Ojo.mjs} +32 -531
- package/dist/cli/{set-D5eeqHbp.mjs → set-CtDZnARG.mjs} +2 -3
- package/dist/cli/{set-DYnzUz_G.mjs → set-PJvs-Yw5.mjs} +4 -5
- package/dist/cli/{status-DNvMZBqD.mjs → status-DU07aAtD.mjs} +2 -2
- package/dist/cli/well-known-paths-QcSJNi_l.mjs +95 -0
- package/dist/cli/wordpress-server-child.mjs +5 -3
- package/dist/cli/{wp-DD2-QiiP.mjs → wp-_X-h-yuW.mjs} +2 -2
- package/dist/cli/wp-files/latest/available-site-translations.json +1 -1
- package/dist/cli/wp-files/sqlite-database-integration/admin-page.php +1 -2
- package/dist/cli/wp-files/sqlite-database-integration/constants.php +0 -5
- package/dist/cli/wp-files/sqlite-database-integration/load.php +1 -1
- package/dist/cli/wp-files/sqlite-database-integration/readme.txt +6 -3
- package/dist/cli/wp-files/sqlite-database-integration/wp-includes/database/sqlite/class-wp-pdo-mysql-on-sqlite.php +22 -3
- package/dist/cli/wp-files/sqlite-database-integration/wp-includes/database/version.php +1 -1
- package/dist/cli/wp-files/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-db.php +41 -89
- package/dist/cli/wp-files/sqlite-database-integration/wp-includes/sqlite/db.php +2 -24
- package/dist/cli/wp-files/sqlite-database-integration/wp-includes/sqlite/install-functions.php +7 -16
- package/package.json +2 -1
- package/dist/cli/well-known-paths-BYA1Bw5o.mjs +0 -214
- package/dist/cli/wp-files/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-lexer.php +0 -2575
- package/dist/cli/wp-files/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-pdo-user-defined-functions.php +0 -899
- package/dist/cli/wp-files/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-query-rewriter.php +0 -343
- package/dist/cli/wp-files/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-token.php +0 -327
- package/dist/cli/wp-files/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-translator.php +0 -4543
- package/dist/cli/wp-files/sqlite-database-integration/wp-includes/sqlite/php-polyfills.php +0 -68
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import fs__default from "fs";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { L as LoggerError, c as Logger, x as socketEventSchema, S as SITE_EVENTS, f as SNAPSHOT_EVENTS, A as AUTH_EVENTS, r as readCliConfig, y as siteDetailsSchema } from "./certificate-manager-v-yNLDFJ.mjs";
|
|
3
|
+
import { o as isEmptyDir } from "./rewrite-wp-cli-post-content-Beo5_Ojo.mjs";
|
|
4
4
|
import { s as sequential } from "./sequential-BQFuixXz.mjs";
|
|
5
|
-
import { M as SITE_EVENTS_SOCKET_PATH, w as SiteCommandLoggerAction, B as connectToDaemon, N as getDaemonBus, O as SITE_PROCESS_PREFIX, J as disconnectFromDaemon, Q as removeSiteFromConfig, m as getSiteUrl, l as isSiteRunning } from "./index-
|
|
5
|
+
import { M as SITE_EVENTS_SOCKET_PATH, w as SiteCommandLoggerAction, B as connectToDaemon, N as getDaemonBus, O as SITE_PROCESS_PREFIX, J as disconnectFromDaemon, Q as removeSiteFromConfig, m as getSiteUrl, l as isSiteRunning } from "./index-ul3DeWvy.mjs";
|
|
6
6
|
import { __ } from "@wordpress/i18n";
|
|
7
|
-
import { g as SocketServer } from "./process-manager-ipc-
|
|
8
|
-
import { L as LoggerError, d as Logger } from "./well-known-paths-BYA1Bw5o.mjs";
|
|
7
|
+
import { g as SocketServer } from "./process-manager-ipc-GCdebuBH.mjs";
|
|
9
8
|
const logger = new Logger();
|
|
10
9
|
function toSiteDetails(site) {
|
|
11
10
|
return siteDetailsSchema.parse({
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import os from "os";
|
|
2
|
+
import path__default from "path";
|
|
3
|
+
import { __ } from "@wordpress/i18n";
|
|
4
|
+
import { L as LoggerError } from "./certificate-manager-v-yNLDFJ.mjs";
|
|
5
|
+
function getAppdataDirectory() {
|
|
6
|
+
if (process.env.E2E && process.env.E2E_APP_DATA_PATH) {
|
|
7
|
+
return path__default.join(process.env.E2E_APP_DATA_PATH, "Studio");
|
|
8
|
+
}
|
|
9
|
+
if (process.platform === "win32") {
|
|
10
|
+
if (!process.env.APPDATA) {
|
|
11
|
+
throw new LoggerError(__("Studio config file path not found."));
|
|
12
|
+
}
|
|
13
|
+
return path__default.join(process.env.APPDATA, "Studio");
|
|
14
|
+
}
|
|
15
|
+
return path__default.join(os.homedir(), "Library", "Application Support", "Studio");
|
|
16
|
+
}
|
|
17
|
+
export {
|
|
18
|
+
getAppdataDirectory as g
|
|
19
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fs__default from "fs";
|
|
2
2
|
import path__default from "path";
|
|
3
|
-
import {
|
|
3
|
+
import { f as getConfigDirectory, C as CLI_CONFIG_LOCKFILE_NAME, n as getCliConfigPath, L as LOCKFILE_STALE_TIME, a as LOCKFILE_WAIT_TIME, o as getCertificatesPath, p as CERT_UNTRUSTED_ROOT, q as SERVER_AUTH_OID } from "./well-known-paths-QcSJNi_l.mjs";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
import { execFile } from "child_process";
|
|
6
6
|
import require$$1 from "constants";
|
|
@@ -10,6 +10,7 @@ import require$$0 from "assert";
|
|
|
10
10
|
import require$$2 from "events";
|
|
11
11
|
import { __ } from "@wordpress/i18n";
|
|
12
12
|
import { readFile, writeFile } from "atomically";
|
|
13
|
+
import { Spinner } from "picospinner";
|
|
13
14
|
import { execFile as execFile$1 } from "node:child_process";
|
|
14
15
|
import crypto from "node:crypto";
|
|
15
16
|
import fs from "node:fs";
|
|
@@ -18,6 +19,113 @@ import { domainToASCII } from "node:url";
|
|
|
18
19
|
import { promisify } from "node:util";
|
|
19
20
|
import sudo from "@vscode/sudo-prompt";
|
|
20
21
|
import forge from "node-forge";
|
|
22
|
+
const isIpcMode = Boolean(process.send);
|
|
23
|
+
let progressCallback = null;
|
|
24
|
+
function setProgressCallback(callback) {
|
|
25
|
+
progressCallback = callback;
|
|
26
|
+
}
|
|
27
|
+
function getProgressCallback() {
|
|
28
|
+
return progressCallback;
|
|
29
|
+
}
|
|
30
|
+
function emitProgress(message) {
|
|
31
|
+
progressCallback?.(message);
|
|
32
|
+
}
|
|
33
|
+
function canSend() {
|
|
34
|
+
return isIpcMode && !!process.send && process.connected;
|
|
35
|
+
}
|
|
36
|
+
class LoggerError extends Error {
|
|
37
|
+
constructor(message, previousError) {
|
|
38
|
+
super();
|
|
39
|
+
this.name = "LoggerError";
|
|
40
|
+
this.errorMessage = message;
|
|
41
|
+
if (previousError instanceof Error) {
|
|
42
|
+
this.previousError = previousError;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
get message() {
|
|
46
|
+
if (this.previousError) {
|
|
47
|
+
return `${this.errorMessage}: ${this.previousError.message}`;
|
|
48
|
+
}
|
|
49
|
+
return this.errorMessage;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
class Logger {
|
|
53
|
+
constructor() {
|
|
54
|
+
this.currentAction = null;
|
|
55
|
+
this.spinner = new Spinner();
|
|
56
|
+
}
|
|
57
|
+
reportStart(action, message) {
|
|
58
|
+
this.currentAction = action;
|
|
59
|
+
if (canSend()) {
|
|
60
|
+
process.send({ action, status: "inprogress", message });
|
|
61
|
+
} else if (progressCallback) {
|
|
62
|
+
progressCallback(message);
|
|
63
|
+
} else {
|
|
64
|
+
this.spinner.setText(message);
|
|
65
|
+
if (!this.spinner.running) {
|
|
66
|
+
this.spinner.start();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
reportProgress(message) {
|
|
71
|
+
if (canSend()) {
|
|
72
|
+
process.send({ action: this.currentAction, status: "inprogress", message });
|
|
73
|
+
} else if (progressCallback) {
|
|
74
|
+
progressCallback(message, true);
|
|
75
|
+
} else {
|
|
76
|
+
if (!this.spinner.running) {
|
|
77
|
+
this.spinner.start();
|
|
78
|
+
}
|
|
79
|
+
this.spinner.setText(message);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
reportSuccess(message) {
|
|
83
|
+
if (canSend()) {
|
|
84
|
+
process.send({ action: this.currentAction, status: "success", message });
|
|
85
|
+
} else if (progressCallback) {
|
|
86
|
+
progressCallback(message);
|
|
87
|
+
} else {
|
|
88
|
+
if (!this.spinner.running) {
|
|
89
|
+
this.spinner.start();
|
|
90
|
+
}
|
|
91
|
+
this.spinner.succeed(message);
|
|
92
|
+
}
|
|
93
|
+
this.currentAction = null;
|
|
94
|
+
}
|
|
95
|
+
reportWarning(message) {
|
|
96
|
+
if (canSend()) {
|
|
97
|
+
process.send({ action: this.currentAction, status: "warning", message });
|
|
98
|
+
} else if (progressCallback) {
|
|
99
|
+
progressCallback(message);
|
|
100
|
+
} else {
|
|
101
|
+
if (!this.spinner.running) {
|
|
102
|
+
this.spinner.start();
|
|
103
|
+
}
|
|
104
|
+
this.spinner.warn(message);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
reportError(error, isFatal = true) {
|
|
108
|
+
if (isFatal) {
|
|
109
|
+
process.exitCode = 1;
|
|
110
|
+
}
|
|
111
|
+
if (canSend()) {
|
|
112
|
+
process.send({ action: this.currentAction, status: "fail", message: error.message });
|
|
113
|
+
} else if (progressCallback) {
|
|
114
|
+
progressCallback(error.message);
|
|
115
|
+
} else {
|
|
116
|
+
if (!this.spinner.running) {
|
|
117
|
+
this.spinner.start();
|
|
118
|
+
}
|
|
119
|
+
this.spinner.fail(error.message);
|
|
120
|
+
}
|
|
121
|
+
this.currentAction = null;
|
|
122
|
+
}
|
|
123
|
+
reportKeyValuePair(key, value) {
|
|
124
|
+
if (canSend()) {
|
|
125
|
+
process.send({ action: "keyValuePair", key, value });
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
21
129
|
const authTokenSchema = z.object({
|
|
22
130
|
accessToken: z.string(),
|
|
23
131
|
expiresIn: z.number(),
|
|
@@ -171,6 +279,10 @@ async function isDirectoryHiddenOnWindows(dirPath) {
|
|
|
171
279
|
});
|
|
172
280
|
});
|
|
173
281
|
}
|
|
282
|
+
var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
|
|
283
|
+
function getDefaultExportFromCjs(x) {
|
|
284
|
+
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
|
|
285
|
+
}
|
|
174
286
|
var lockfile$1 = {};
|
|
175
287
|
var signalExit = { exports: {} };
|
|
176
288
|
var signals = { exports: {} };
|
|
@@ -1005,24 +1117,31 @@ function deleteSiteCertificate(domain) {
|
|
|
1005
1117
|
}
|
|
1006
1118
|
export {
|
|
1007
1119
|
AUTH_EVENTS as A,
|
|
1008
|
-
|
|
1120
|
+
LoggerError as L,
|
|
1121
|
+
SITE_EVENTS as S,
|
|
1009
1122
|
lockFileAsync as a,
|
|
1010
1123
|
unlockFileAsync as b,
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1124
|
+
Logger as c,
|
|
1125
|
+
commonjsGlobal as d,
|
|
1126
|
+
authTokenSchema as e,
|
|
1127
|
+
SNAPSHOT_EVENTS as f,
|
|
1128
|
+
getDefaultExportFromCjs as g,
|
|
1016
1129
|
hideDirectoryOnWindows as h,
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1130
|
+
requireSignalExit as i,
|
|
1131
|
+
StatsMetric as j,
|
|
1132
|
+
StatsGroup as k,
|
|
1020
1133
|
lockCliConfig as l,
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1134
|
+
updateCliConfigWithPartial as m,
|
|
1135
|
+
generateSiteCertificate as n,
|
|
1136
|
+
deleteSiteCertificate as o,
|
|
1137
|
+
emitProgress as p,
|
|
1138
|
+
setProgressCallback as q,
|
|
1025
1139
|
readCliConfig as r,
|
|
1026
1140
|
saveCliConfig as s,
|
|
1027
|
-
|
|
1141
|
+
getProgressCallback as t,
|
|
1142
|
+
unlockCliConfig as u,
|
|
1143
|
+
updateCheckSchema as v,
|
|
1144
|
+
isDirectoryHiddenOnWindows as w,
|
|
1145
|
+
socketEventSchema as x,
|
|
1146
|
+
siteDetailsSchema as y
|
|
1028
1147
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { l as listAiSessions, g as getAiSessionsRootDirectory, d as deleteAiSession } from "./paths-
|
|
1
|
+
import { l as listAiSessions, g as getAiSessionsRootDirectory, d as deleteAiSession } from "./paths-D7DniT1Q.mjs";
|
|
2
2
|
import { __ } from "@wordpress/i18n";
|
|
3
|
-
import { c as chooseSessionForAction } from "./helpers-
|
|
4
|
-
import { L as LoggerError,
|
|
3
|
+
import { c as chooseSessionForAction } from "./helpers-CIAgfdq8.mjs";
|
|
4
|
+
import { L as LoggerError, c as Logger } from "./certificate-manager-v-yNLDFJ.mjs";
|
|
5
5
|
const logger = new Logger();
|
|
6
6
|
async function runCommand(sessionIdOrPrefix) {
|
|
7
7
|
let resolvedSessionIdOrPrefix = sessionIdOrPrefix?.trim();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { select } from "@inquirer/prompts";
|
|
2
2
|
import { visibleWidth, truncateToWidth } from "@mariozechner/pi-tui";
|
|
3
|
-
import { l as listAiSessions, g as getAiSessionsRootDirectory } from "./paths-
|
|
4
|
-
import { h as chalk } from "./index-
|
|
3
|
+
import { l as listAiSessions, g as getAiSessionsRootDirectory } from "./paths-D7DniT1Q.mjs";
|
|
4
|
+
import { h as chalk } from "./index-ul3DeWvy.mjs";
|
|
5
5
|
import { __ } from "@wordpress/i18n";
|
|
6
6
|
function formatSessionTimestamp(timestamp) {
|
|
7
7
|
const parsed = Date.parse(timestamp);
|
|
@@ -2,11 +2,11 @@ import { execFile } from "child_process";
|
|
|
2
2
|
import fs__default from "fs";
|
|
3
3
|
import path__default from "path";
|
|
4
4
|
import { confirm } from "@inquirer/prompts";
|
|
5
|
-
import {
|
|
5
|
+
import { r as getAppConfigPath, f as getConfigDirectory, g as getServerFilesPath } from "./well-known-paths-QcSJNi_l.mjs";
|
|
6
6
|
import { __ } from "@wordpress/i18n";
|
|
7
|
-
import {
|
|
7
|
+
import { g as getAppdataDirectory } from "./appdata-D-luHxJU.mjs";
|
|
8
8
|
import fs from "node:fs";
|
|
9
|
-
import { h as hideDirectoryOnWindows,
|
|
9
|
+
import { h as hideDirectoryOnWindows, w as isDirectoryHiddenOnWindows } from "./certificate-manager-v-yNLDFJ.mjs";
|
|
10
10
|
import os from "node:os";
|
|
11
11
|
import path from "node:path";
|
|
12
12
|
function isInstalledOnMacOs() {
|
|
@@ -134,10 +134,37 @@ const renameProcessManagerHome = {
|
|
|
134
134
|
fs.renameSync(getLegacyPmHome(), getNewPmHome());
|
|
135
135
|
}
|
|
136
136
|
};
|
|
137
|
+
function getObsoletePaths() {
|
|
138
|
+
const serverFilesPath = getServerFilesPath();
|
|
139
|
+
return [
|
|
140
|
+
path.join(serverFilesPath, "skills"),
|
|
141
|
+
path.join(serverFilesPath, "sqlite-database-integration"),
|
|
142
|
+
path.join(serverFilesPath, "sqlite-command"),
|
|
143
|
+
path.join(serverFilesPath, "phpmyadmin"),
|
|
144
|
+
path.join(serverFilesPath, "wp-cli.phar"),
|
|
145
|
+
path.join(
|
|
146
|
+
serverFilesPath,
|
|
147
|
+
"wordpress-versions",
|
|
148
|
+
"latest",
|
|
149
|
+
"available-site-translations.json"
|
|
150
|
+
)
|
|
151
|
+
];
|
|
152
|
+
}
|
|
153
|
+
const cleanupObsoleteServerFiles = {
|
|
154
|
+
needsToRun: async () => {
|
|
155
|
+
return getObsoletePaths().some((p) => fs.existsSync(p));
|
|
156
|
+
},
|
|
157
|
+
run: async () => {
|
|
158
|
+
for (const p of getObsoletePaths()) {
|
|
159
|
+
await fs.promises.rm(p, { recursive: true, force: true });
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
};
|
|
137
163
|
const migrations = [
|
|
138
164
|
checkStudioCompatibilityForInitialMigration,
|
|
139
165
|
hideStudioDirWindows,
|
|
140
|
-
renameProcessManagerHome
|
|
166
|
+
renameProcessManagerHome,
|
|
167
|
+
cleanupObsoleteServerFiles
|
|
141
168
|
];
|
|
142
169
|
export {
|
|
143
170
|
migrations
|
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
import { b as getAiSessionsDirectoryForDate, c as buildAiSessionFileName, l as listAiSessions, g as getAiSessionsRootDirectory } from "./paths-
|
|
2
|
-
import { S as STUDIO_SITES_ROOT, c as createRemoteSiteTools, a as createStudioTools, r as readAuthToken, b as getSnapshotsFromConfig, i as isSnapshotExpired, d as captureCommandOutput, e as runCommand$3, f as runCommand$4, h as chalk, j as getSitesRunningStatus, k as getWpComSites, l as isSiteRunning, o as openBrowser, m as getSiteUrl, n as closeSharedBrowser } from "./index-
|
|
1
|
+
import { b as getAiSessionsDirectoryForDate, c as buildAiSessionFileName, l as listAiSessions, g as getAiSessionsRootDirectory } from "./paths-D7DniT1Q.mjs";
|
|
2
|
+
import { S as STUDIO_SITES_ROOT, c as createRemoteSiteTools, a as createStudioTools, r as readAuthToken, b as getSnapshotsFromConfig, i as isSnapshotExpired, d as captureCommandOutput, e as runCommand$3, f as runCommand$4, h as chalk, j as getSitesRunningStatus, k as getWpComSites, l as isSiteRunning, o as openBrowser, m as getSiteUrl, n as closeSharedBrowser } from "./index-ul3DeWvy.mjs";
|
|
3
3
|
import { __, sprintf, _n } from "@wordpress/i18n";
|
|
4
4
|
import fs__default from "fs";
|
|
5
5
|
import path__default from "path";
|
|
6
6
|
import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
7
7
|
import os from "os";
|
|
8
|
-
import { l as lockCliConfig, r as readCliConfig, s as saveCliConfig, u as unlockCliConfig,
|
|
8
|
+
import { l as lockCliConfig, r as readCliConfig, s as saveCliConfig, u as unlockCliConfig, L as LoggerError, m as updateCliConfigWithPartial, c as Logger, q as setProgressCallback } from "./certificate-manager-v-yNLDFJ.mjs";
|
|
9
9
|
import { password } from "@inquirer/prompts";
|
|
10
|
-
import { L as LoggerError, d as Logger, s as setProgressCallback } from "./well-known-paths-BYA1Bw5o.mjs";
|
|
11
10
|
import crypto from "crypto";
|
|
12
11
|
import fs from "fs/promises";
|
|
13
|
-
import { runCommand as runCommand$1 } from "./login-
|
|
14
|
-
import { runCommand as runCommand$2 } from "./logout-
|
|
12
|
+
import { runCommand as runCommand$1 } from "./login-Dz63Zdfn.mjs";
|
|
13
|
+
import { runCommand as runCommand$2 } from "./logout-CLUKQeZh.mjs";
|
|
15
14
|
import { ProcessTerminal, TUI, Container, Loader, CombinedAutocompleteProvider, isKeyRelease, matchesKey, Text, SelectList, Input, Markdown, Editor, visibleWidth, CURSOR_MARKER, truncateToWidth } from "@mariozechner/pi-tui";
|
|
16
15
|
const AI_MODELS = {
|
|
17
16
|
"claude-sonnet-4-6": "Sonnet 4.6",
|
|
@@ -357,6 +356,17 @@ Then continue with:
|
|
|
357
356
|
5. **Check the misuse of HTML blocks**: Verify if HTML blocks were used as sections or not. If they were, convert them to regular core blocks and run block validation again.
|
|
358
357
|
6. **Check the result**: Use take_screenshot to capture the site's landing page on desktop and mobile and verify the design visually on both viewports, check for wrong spacing, alignment, colors, contrast, borders, hover styles and other visual issues. Fix any issues found. Pay particular attention to the navigation menu and the CTA buttons. The design needs to match your original expectations.
|
|
359
358
|
|
|
359
|
+
## Working cadence
|
|
360
|
+
|
|
361
|
+
One \`Write\` or \`Edit\` per turn (read-only \`site_info\`, \`site_list\`, \`wp_cli\` queries may be combined). Short prose between tools — no long design-plan essays. The CLI only renders complete assistant messages, so a turn that batches files or emits >~200 lines spins silently for minutes and can hit gateway timeouts. Cadence is also a quality lever: the screenshot-fix loop only works after small visible increments.
|
|
362
|
+
|
|
363
|
+
**After \`site_create\`** (or "redesign"/"rebuild"/"start over" triggers), the next turn MUST be small: \`site_info\` or a single ≤50-line \`Write\`. Never scaffold a whole theme in one turn.
|
|
364
|
+
|
|
365
|
+
**Long files (>~200 lines): skeleton first, then fill across Edits.**
|
|
366
|
+
|
|
367
|
+
- \`style.css\`: skeleton = \`:root { ... }\` custom properties + 6–10 anchor comments \`/* === <concern> === */\` (e.g. \`reset\`, \`typography\`, \`hero\`, \`features\`, \`cta\`, \`footer\`, \`responsive\`), <2KB total. Fill one anchor per Edit (300–2000B each) — \`old_string\` is the anchor line, \`new_string\` is \`<anchor>\\n\\n<styles>\`.
|
|
368
|
+
- Page content: create the page empty (\`wp_cli post create --post_content=""\`), write \`<theme>/page-content.html\` with \`<!-- section:<concern> -->\` anchors (<1KB), fill one anchor per Edit using only core blocks (never wrap in \`core/html\`), then apply once with \`wp_cli post update <id> --post_content-file=<absolute path>\`.
|
|
369
|
+
|
|
360
370
|
## Available Studio Tools (prefixed with mcp__studio__)
|
|
361
371
|
|
|
362
372
|
- site_create: Create a new WordPress site (name only — handles everything automatically)
|
|
@@ -373,6 +383,7 @@ Then continue with:
|
|
|
373
383
|
- validate_blocks: Validate block content for correctness on a running site (runs each block through its save() function in a real browser). Requires a site name or path. Call after every file write/edit that contains block content.
|
|
374
384
|
- take_screenshot: Take a full-page screenshot of a URL (supports desktop and mobile viewports). Use this to visually check the site after building it.
|
|
375
385
|
- need_for_speed: Measure frontend performance metrics (TTFB, FCP, LCP, CLS, page weight, DOM size, JS/CSS/image/font asset breakdown) for a running site. Use this to identify performance bottlenecks and guide optimization.
|
|
386
|
+
- rank_me_up: Run an on-page SEO audit (title/meta tags, headings, image alt text, OpenGraph/Twitter cards, JSON-LD structured data, robots.txt and sitemap.xml availability) for a running site. Use this to identify on-page SEO issues and guide fixes.
|
|
376
387
|
- site_push: Push a local site to a WordPress.com site. Requires authentication (studio auth login). Specify the remote site URL or ID and sync options (all, sqls, uploads, plugins, themes, contents).
|
|
377
388
|
- site_pull: Pull a WordPress.com site to a local site. Requires authentication. Specify the remote site URL or ID and sync options.
|
|
378
389
|
- site_import: Import a backup file (.zip, .tar.gz, .sql, .wpress) into a local site.
|
|
@@ -464,7 +475,7 @@ function startAiAgent(config) {
|
|
|
464
475
|
prompt,
|
|
465
476
|
env,
|
|
466
477
|
model = DEFAULT_MODEL,
|
|
467
|
-
maxTurns =
|
|
478
|
+
maxTurns = 75,
|
|
468
479
|
resume,
|
|
469
480
|
autoApprove,
|
|
470
481
|
activeSite,
|
|
@@ -579,6 +590,7 @@ function createBaseEnvironment() {
|
|
|
579
590
|
delete env.ANTHROPIC_BASE_URL;
|
|
580
591
|
delete env.ANTHROPIC_CUSTOM_HEADERS;
|
|
581
592
|
delete env.CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS;
|
|
593
|
+
delete env.CLAUDE_CODE_MAX_RETRIES;
|
|
582
594
|
if (!env.CLAUDE_CODE_MAX_RETRIES) {
|
|
583
595
|
env.CLAUDE_CODE_MAX_RETRIES = "1";
|
|
584
596
|
}
|
|
@@ -596,7 +608,7 @@ const AI_PROVIDER_DEFINITIONS = {
|
|
|
596
608
|
}
|
|
597
609
|
throw new LoggerError(__("WordPress.com login required. Use /login to authenticate."));
|
|
598
610
|
},
|
|
599
|
-
resolveEnv: async () => {
|
|
611
|
+
resolveEnv: async (options) => {
|
|
600
612
|
const inlineToken = readInlineWpcomToken();
|
|
601
613
|
const accessToken = inlineToken ?? (await readAuthToken())?.accessToken;
|
|
602
614
|
if (!accessToken) {
|
|
@@ -605,10 +617,15 @@ const AI_PROVIDER_DEFINITIONS = {
|
|
|
605
617
|
const env = createBaseEnvironment();
|
|
606
618
|
env.ANTHROPIC_BASE_URL = getWpcomAiGatewayBaseUrl();
|
|
607
619
|
env.ANTHROPIC_AUTH_TOKEN = accessToken;
|
|
608
|
-
|
|
620
|
+
const customHeaders = {
|
|
609
621
|
"X-WPCOM-AI-Feature": WPCOM_AI_FEATURE_HEADER
|
|
610
|
-
}
|
|
622
|
+
};
|
|
623
|
+
if (options?.sessionId) {
|
|
624
|
+
customHeaders["X-WPCOM-Session-ID"] = options.sessionId;
|
|
625
|
+
}
|
|
626
|
+
env.ANTHROPIC_CUSTOM_HEADERS = buildAnthropicCustomHeaders(customHeaders);
|
|
611
627
|
env.CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS = "1";
|
|
628
|
+
env.CLAUDE_CODE_MAX_RETRIES = "0";
|
|
612
629
|
return env;
|
|
613
630
|
}
|
|
614
631
|
},
|
|
@@ -698,8 +715,8 @@ async function saveSelectedAiProvider(provider) {
|
|
|
698
715
|
async function prepareAiProvider(provider, options) {
|
|
699
716
|
await getAiProviderDefinition(provider).prepare(options);
|
|
700
717
|
}
|
|
701
|
-
async function resolveAiEnvironment(provider) {
|
|
702
|
-
return getAiProviderDefinition(provider).resolveEnv();
|
|
718
|
+
async function resolveAiEnvironment(provider, options) {
|
|
719
|
+
return getAiProviderDefinition(provider).resolveEnv(options);
|
|
703
720
|
}
|
|
704
721
|
function emitEvent(event) {
|
|
705
722
|
if (typeof process.send === "function") {
|
|
@@ -938,15 +955,6 @@ class AiSessionRecorder {
|
|
|
938
955
|
wpcomSiteId: site.wpcomSiteId
|
|
939
956
|
});
|
|
940
957
|
}
|
|
941
|
-
async recordEnvironmentSelected(payload) {
|
|
942
|
-
await this.appendEvent({
|
|
943
|
-
type: "environment.selected",
|
|
944
|
-
timestamp: toIsoTimestamp(),
|
|
945
|
-
environment: payload.environment,
|
|
946
|
-
url: payload.url,
|
|
947
|
-
wpcomSiteId: payload.wpcomSiteId
|
|
948
|
-
});
|
|
949
|
-
}
|
|
950
958
|
async recordUserMessage(options) {
|
|
951
959
|
await this.appendEvent({
|
|
952
960
|
type: "user.message",
|
|
@@ -1033,25 +1041,6 @@ function replaySessionHistory(ui, events) {
|
|
|
1033
1041
|
);
|
|
1034
1042
|
continue;
|
|
1035
1043
|
}
|
|
1036
|
-
if (event.type === "environment.selected") {
|
|
1037
|
-
const current = ui.activeSite;
|
|
1038
|
-
if (!current) {
|
|
1039
|
-
continue;
|
|
1040
|
-
}
|
|
1041
|
-
const isLive = event.environment === "live";
|
|
1042
|
-
ui.setActiveSite(
|
|
1043
|
-
{
|
|
1044
|
-
name: current.name,
|
|
1045
|
-
path: current.path,
|
|
1046
|
-
running: current.running,
|
|
1047
|
-
remote: isLive,
|
|
1048
|
-
url: isLive ? event.url : void 0,
|
|
1049
|
-
wpcomSiteId: isLive ? event.wpcomSiteId : void 0
|
|
1050
|
-
},
|
|
1051
|
-
{ announce: true, emitEvent: false }
|
|
1052
|
-
);
|
|
1053
|
-
continue;
|
|
1054
|
-
}
|
|
1055
1044
|
if (event.type === "user.message") {
|
|
1056
1045
|
if (!isVisibleUserMessage(event)) {
|
|
1057
1046
|
continue;
|
|
@@ -1328,7 +1317,8 @@ const AI_CHAT_SLASH_COMMANDS = [
|
|
|
1328
1317
|
handler: async () => "break"
|
|
1329
1318
|
},
|
|
1330
1319
|
{ name: "taxonomist", description: __("Optimize category taxonomy with AI") },
|
|
1331
|
-
{ name: "need-for-speed", description: __("Run a performance audit on a site") }
|
|
1320
|
+
{ name: "need-for-speed", description: __("Run a performance audit on a site") },
|
|
1321
|
+
{ name: "rank-me-up", description: __("Run an on-page SEO audit on a site") }
|
|
1332
1322
|
];
|
|
1333
1323
|
const THINKING_MESSAGES = [
|
|
1334
1324
|
"Thinking…",
|
|
@@ -1792,6 +1782,7 @@ class AiChatUI {
|
|
|
1792
1782
|
this.editorVisible = false;
|
|
1793
1783
|
this.interruptCallback = null;
|
|
1794
1784
|
this.wasInterrupted = false;
|
|
1785
|
+
this.usageCapReached = false;
|
|
1795
1786
|
this.hasShownResponseMarker = false;
|
|
1796
1787
|
this.turnStartTime = 0;
|
|
1797
1788
|
this.toolStartTime = null;
|
|
@@ -2217,15 +2208,16 @@ ${chalk.dim(message)}
|
|
|
2217
2208
|
this.refreshPromptChrome();
|
|
2218
2209
|
const label = site.remote ? sprintf(
|
|
2219
2210
|
/* translators: %s: site name */
|
|
2220
|
-
__("
|
|
2211
|
+
__(" Selected site: %s (WordPress.com)"),
|
|
2221
2212
|
site.name
|
|
2222
2213
|
) : sprintf(
|
|
2223
2214
|
/* translators: %s: site name */
|
|
2224
|
-
__("
|
|
2215
|
+
__(" Selected site: %s"),
|
|
2225
2216
|
site.name
|
|
2226
2217
|
);
|
|
2227
2218
|
if (announce) {
|
|
2228
|
-
this.messages.addChild(new Text(
|
|
2219
|
+
this.messages.addChild(new Text(`
|
|
2220
|
+
${chalk.hex("#8839ef")(label)}
|
|
2229
2221
|
`, 0, 0));
|
|
2230
2222
|
}
|
|
2231
2223
|
if (emitEvent2) {
|
|
@@ -2448,7 +2440,7 @@ ${chalk.dim(message)}
|
|
|
2448
2440
|
this.tui.start();
|
|
2449
2441
|
}
|
|
2450
2442
|
showWelcome() {
|
|
2451
|
-
const version = "1.7.
|
|
2443
|
+
const version = "1.7.11";
|
|
2452
2444
|
const cwd = process.cwd();
|
|
2453
2445
|
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
2454
2446
|
const displayCwd = home && cwd.startsWith(home) ? "~" + cwd.slice(home.length) : cwd;
|
|
@@ -2622,6 +2614,7 @@ ${chalk.dim(message)}
|
|
|
2622
2614
|
this.currentResponseText = "";
|
|
2623
2615
|
this.hasShownResponseMarker = false;
|
|
2624
2616
|
this.wasInterrupted = false;
|
|
2617
|
+
this.usageCapReached = false;
|
|
2625
2618
|
this.turnStartTime = this.nowMs();
|
|
2626
2619
|
this.todoSnapshot = [];
|
|
2627
2620
|
this.latestTodoSnapshot = [];
|
|
@@ -2648,6 +2641,15 @@ ${chalk.dim(message)}
|
|
|
2648
2641
|
this.pendingTodoRenders.clear();
|
|
2649
2642
|
this.pendingTodoRenderOrder = [];
|
|
2650
2643
|
}
|
|
2644
|
+
/**
|
|
2645
|
+
* Returns true when the current/last turn surfaced the AI usage cap
|
|
2646
|
+
* message to the user. Lets callers suppress redundant downstream
|
|
2647
|
+
* errors (e.g. the SDK's "process exited with code 1" that follows
|
|
2648
|
+
* the upstream 429).
|
|
2649
|
+
*/
|
|
2650
|
+
hasErrorBeenSurfaced() {
|
|
2651
|
+
return this.usageCapReached;
|
|
2652
|
+
}
|
|
2651
2653
|
showOnboarding() {
|
|
2652
2654
|
const text = " " + chalk.blue("⏺") + " " + sprintf(
|
|
2653
2655
|
/* translators: %s: product name (WordPress Studio) */
|
|
@@ -3113,6 +3115,30 @@ ${chalk.dim(message)}
|
|
|
3113
3115
|
handleMessage(message) {
|
|
3114
3116
|
switch (message.type) {
|
|
3115
3117
|
case "assistant": {
|
|
3118
|
+
let isCapMessage = false;
|
|
3119
|
+
if (message.error && this.currentProvider === "wpcom") {
|
|
3120
|
+
for (const block of message.message.content) {
|
|
3121
|
+
if (block.type === "text" && /API Error:\s*429/i.test(block.text ?? "")) {
|
|
3122
|
+
isCapMessage = true;
|
|
3123
|
+
break;
|
|
3124
|
+
}
|
|
3125
|
+
}
|
|
3126
|
+
}
|
|
3127
|
+
if (isCapMessage) {
|
|
3128
|
+
this.hideLoader();
|
|
3129
|
+
this.usageCapReached = true;
|
|
3130
|
+
this.showError(
|
|
3131
|
+
__(
|
|
3132
|
+
"AI usage cap reached. You can continue using Studio Code by switching to your own Anthropic API key."
|
|
3133
|
+
)
|
|
3134
|
+
);
|
|
3135
|
+
this.showInfo(
|
|
3136
|
+
__("Use /provider to switch to Anthropic · API key, or try again later.")
|
|
3137
|
+
);
|
|
3138
|
+
this.currentMarkdown = null;
|
|
3139
|
+
this.currentResponseText = "";
|
|
3140
|
+
return void 0;
|
|
3141
|
+
}
|
|
3116
3142
|
for (const block of message.message.content) {
|
|
3117
3143
|
if (block.type === "text") {
|
|
3118
3144
|
this.hideLoader();
|
|
@@ -3195,6 +3221,9 @@ ${chalk.dim(message)}
|
|
|
3195
3221
|
numTurns: message.num_turns
|
|
3196
3222
|
};
|
|
3197
3223
|
}
|
|
3224
|
+
if (this.usageCapReached) {
|
|
3225
|
+
return { type: "result", sessionId: message.session_id, success: false };
|
|
3226
|
+
}
|
|
3198
3227
|
if (this.wasInterrupted) {
|
|
3199
3228
|
const thinkingSec2 = Math.round((this.nowMs() - this.turnStartTime) / 1e3);
|
|
3200
3229
|
this.messages.addChild(
|
|
@@ -3466,6 +3495,9 @@ async function runCommand(options) {
|
|
|
3466
3495
|
}
|
|
3467
3496
|
function handleAgentTurnError(error) {
|
|
3468
3497
|
sessionId = void 0;
|
|
3498
|
+
if (ui instanceof AiChatUI && ui.hasErrorBeenSurfaced()) {
|
|
3499
|
+
return;
|
|
3500
|
+
}
|
|
3469
3501
|
if (error instanceof LoggerError) {
|
|
3470
3502
|
ui.showError(error.message);
|
|
3471
3503
|
} else if (error instanceof Error) {
|
|
@@ -3588,7 +3620,10 @@ async function runCommand(options) {
|
|
|
3588
3620
|
const MAX_RETRY_ATTEMPTS = 4;
|
|
3589
3621
|
async function runAgentTurn(prompt, retryAttempt = 0) {
|
|
3590
3622
|
await maybeAutoSwitchProvider();
|
|
3591
|
-
const
|
|
3623
|
+
const recorder = await ensureSessionRecorder();
|
|
3624
|
+
const env = await resolveAiEnvironment(currentProvider, {
|
|
3625
|
+
sessionId: recorder?.sessionId
|
|
3626
|
+
});
|
|
3592
3627
|
ui.beginAgentTurn();
|
|
3593
3628
|
let enrichedPrompt = prompt;
|
|
3594
3629
|
const site = ui.activeSite;
|
|
@@ -3608,7 +3643,7 @@ ${prompt}`;
|
|
|
3608
3643
|
}
|
|
3609
3644
|
await persistSessionContext();
|
|
3610
3645
|
await persist(
|
|
3611
|
-
(
|
|
3646
|
+
(recorder2) => recorder2.recordUserMessage({
|
|
3612
3647
|
text: prompt,
|
|
3613
3648
|
source: "prompt",
|
|
3614
3649
|
sitePath: site?.path
|
|
@@ -3633,10 +3668,10 @@ ${prompt}`;
|
|
|
3633
3668
|
for await (const message of agentQuery) {
|
|
3634
3669
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
3635
3670
|
const result = ui.handleMessage(message);
|
|
3636
|
-
await persist((
|
|
3671
|
+
await persist((recorder2) => recorder2.recordSdkMessage(message, timestamp));
|
|
3637
3672
|
if (result) {
|
|
3638
3673
|
sessionId = result.sessionId;
|
|
3639
|
-
await persist((
|
|
3674
|
+
await persist((recorder2) => recorder2.recordAgentSessionId(result.sessionId));
|
|
3640
3675
|
if (result.type === "max_turns") {
|
|
3641
3676
|
maxTurnsResult = {
|
|
3642
3677
|
numTurns: result.numTurns
|
|
@@ -3654,9 +3689,11 @@ ${prompt}`;
|
|
|
3654
3689
|
if (isJsonMode) {
|
|
3655
3690
|
throw error;
|
|
3656
3691
|
}
|
|
3657
|
-
ui.
|
|
3692
|
+
if (!(ui instanceof AiChatUI && ui.hasErrorBeenSurfaced())) {
|
|
3693
|
+
ui.showError(getErrorMessage(error));
|
|
3694
|
+
}
|
|
3658
3695
|
} finally {
|
|
3659
|
-
await persist((
|
|
3696
|
+
await persist((recorder2) => recorder2.recordTurnClosed(turnStatus));
|
|
3660
3697
|
ui.endAgentTurn();
|
|
3661
3698
|
}
|
|
3662
3699
|
if (maxTurnsResult) {
|
|
@@ -3682,7 +3719,8 @@ ${prompt}`;
|
|
|
3682
3719
|
return runAgentTurn("Continue from where you left off.");
|
|
3683
3720
|
}
|
|
3684
3721
|
}
|
|
3685
|
-
|
|
3722
|
+
const hasTerminalError = ui instanceof AiChatUI && ui.hasErrorBeenSurfaced();
|
|
3723
|
+
if (turnStatus === "error" && !isJsonMode && !hasTerminalError) {
|
|
3686
3724
|
if (retryAttempt >= MAX_RETRY_ATTEMPTS) {
|
|
3687
3725
|
ui.showInfo(
|
|
3688
3726
|
__("The server has not recovered after multiple attempts. Please try again later.")
|