@npow/ghostwriter 0.1.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 (113) hide show
  1. package/dist/commands/connect.d.ts +30 -0
  2. package/dist/commands/connect.d.ts.map +1 -0
  3. package/dist/commands/connect.js +442 -0
  4. package/dist/commands/connect.js.map +1 -0
  5. package/dist/commands/create/index.d.ts +6 -0
  6. package/dist/commands/create/index.d.ts.map +1 -0
  7. package/dist/commands/create/index.js +89 -0
  8. package/dist/commands/create/index.js.map +1 -0
  9. package/dist/commands/create/prompts/example-article.d.ts +3 -0
  10. package/dist/commands/create/prompts/example-article.d.ts.map +1 -0
  11. package/dist/commands/create/prompts/example-article.js +32 -0
  12. package/dist/commands/create/prompts/example-article.js.map +1 -0
  13. package/dist/commands/create/prompts/intent-parsing.d.ts +3 -0
  14. package/dist/commands/create/prompts/intent-parsing.d.ts.map +1 -0
  15. package/dist/commands/create/prompts/intent-parsing.js +45 -0
  16. package/dist/commands/create/prompts/intent-parsing.js.map +1 -0
  17. package/dist/commands/create/prompts/page-content.d.ts +3 -0
  18. package/dist/commands/create/prompts/page-content.d.ts.map +1 -0
  19. package/dist/commands/create/prompts/page-content.js +56 -0
  20. package/dist/commands/create/prompts/page-content.js.map +1 -0
  21. package/dist/commands/create/prompts/source-discovery.d.ts +3 -0
  22. package/dist/commands/create/prompts/source-discovery.d.ts.map +1 -0
  23. package/dist/commands/create/prompts/source-discovery.js +46 -0
  24. package/dist/commands/create/prompts/source-discovery.js.map +1 -0
  25. package/dist/commands/create/prompts/voice-generation.d.ts +3 -0
  26. package/dist/commands/create/prompts/voice-generation.d.ts.map +1 -0
  27. package/dist/commands/create/prompts/voice-generation.js +43 -0
  28. package/dist/commands/create/prompts/voice-generation.js.map +1 -0
  29. package/dist/commands/create/steps/assemble-config.d.ts +5 -0
  30. package/dist/commands/create/steps/assemble-config.d.ts.map +1 -0
  31. package/dist/commands/create/steps/assemble-config.js +82 -0
  32. package/dist/commands/create/steps/assemble-config.js.map +1 -0
  33. package/dist/commands/create/steps/discover-sources.d.ts +5 -0
  34. package/dist/commands/create/steps/discover-sources.d.ts.map +1 -0
  35. package/dist/commands/create/steps/discover-sources.js +53 -0
  36. package/dist/commands/create/steps/discover-sources.js.map +1 -0
  37. package/dist/commands/create/steps/fingerprint-style.d.ts +5 -0
  38. package/dist/commands/create/steps/fingerprint-style.d.ts.map +1 -0
  39. package/dist/commands/create/steps/fingerprint-style.js +46 -0
  40. package/dist/commands/create/steps/fingerprint-style.js.map +1 -0
  41. package/dist/commands/create/steps/generate-example.d.ts +4 -0
  42. package/dist/commands/create/steps/generate-example.d.ts.map +1 -0
  43. package/dist/commands/create/steps/generate-example.js +23 -0
  44. package/dist/commands/create/steps/generate-example.js.map +1 -0
  45. package/dist/commands/create/steps/generate-voice.d.ts +4 -0
  46. package/dist/commands/create/steps/generate-voice.d.ts.map +1 -0
  47. package/dist/commands/create/steps/generate-voice.js +32 -0
  48. package/dist/commands/create/steps/generate-voice.js.map +1 -0
  49. package/dist/commands/create/steps/parse-intent.d.ts +4 -0
  50. package/dist/commands/create/steps/parse-intent.d.ts.map +1 -0
  51. package/dist/commands/create/steps/parse-intent.js +16 -0
  52. package/dist/commands/create/steps/parse-intent.js.map +1 -0
  53. package/dist/commands/create/steps/resolve-connection.d.ts +5 -0
  54. package/dist/commands/create/steps/resolve-connection.d.ts.map +1 -0
  55. package/dist/commands/create/steps/resolve-connection.js +100 -0
  56. package/dist/commands/create/steps/resolve-connection.js.map +1 -0
  57. package/dist/commands/create/steps/resolve-schedule.d.ts +13 -0
  58. package/dist/commands/create/steps/resolve-schedule.d.ts.map +1 -0
  59. package/dist/commands/create/steps/resolve-schedule.js +70 -0
  60. package/dist/commands/create/steps/resolve-schedule.js.map +1 -0
  61. package/dist/commands/create/steps/setup-site.d.ts +5 -0
  62. package/dist/commands/create/steps/setup-site.d.ts.map +1 -0
  63. package/dist/commands/create/steps/setup-site.js +44 -0
  64. package/dist/commands/create/steps/setup-site.js.map +1 -0
  65. package/dist/commands/create/steps/validate-and-summary.d.ts +4 -0
  66. package/dist/commands/create/steps/validate-and-summary.d.ts.map +1 -0
  67. package/dist/commands/create/steps/validate-and-summary.js +60 -0
  68. package/dist/commands/create/steps/validate-and-summary.js.map +1 -0
  69. package/dist/commands/create/steps/validate-site-access.d.ts +4 -0
  70. package/dist/commands/create/steps/validate-site-access.d.ts.map +1 -0
  71. package/dist/commands/create/steps/validate-site-access.js +25 -0
  72. package/dist/commands/create/steps/validate-site-access.js.map +1 -0
  73. package/dist/commands/create/types.d.ts +72 -0
  74. package/dist/commands/create/types.d.ts.map +1 -0
  75. package/dist/commands/create/types.js +2 -0
  76. package/dist/commands/create/types.js.map +1 -0
  77. package/dist/commands/fingerprint.d.ts +4 -0
  78. package/dist/commands/fingerprint.d.ts.map +1 -0
  79. package/dist/commands/fingerprint.js +31 -0
  80. package/dist/commands/fingerprint.js.map +1 -0
  81. package/dist/commands/init.d.ts +2 -0
  82. package/dist/commands/init.d.ts.map +1 -0
  83. package/dist/commands/init.js +117 -0
  84. package/dist/commands/init.js.map +1 -0
  85. package/dist/commands/list.d.ts +2 -0
  86. package/dist/commands/list.d.ts.map +1 -0
  87. package/dist/commands/list.js +36 -0
  88. package/dist/commands/list.js.map +1 -0
  89. package/dist/commands/logs.d.ts +6 -0
  90. package/dist/commands/logs.d.ts.map +1 -0
  91. package/dist/commands/logs.js +49 -0
  92. package/dist/commands/logs.js.map +1 -0
  93. package/dist/commands/patterns.d.ts +6 -0
  94. package/dist/commands/patterns.d.ts.map +1 -0
  95. package/dist/commands/patterns.js +51 -0
  96. package/dist/commands/patterns.js.map +1 -0
  97. package/dist/commands/run.d.ts +6 -0
  98. package/dist/commands/run.d.ts.map +1 -0
  99. package/dist/commands/run.js +139 -0
  100. package/dist/commands/run.js.map +1 -0
  101. package/dist/commands/status.d.ts +2 -0
  102. package/dist/commands/status.d.ts.map +1 -0
  103. package/dist/commands/status.js +66 -0
  104. package/dist/commands/status.js.map +1 -0
  105. package/dist/commands/validate.d.ts +2 -0
  106. package/dist/commands/validate.d.ts.map +1 -0
  107. package/dist/commands/validate.js +83 -0
  108. package/dist/commands/validate.js.map +1 -0
  109. package/dist/index.d.ts +3 -0
  110. package/dist/index.d.ts.map +1 -0
  111. package/dist/index.js +76 -0
  112. package/dist/index.js.map +1 -0
  113. package/package.json +38 -0
@@ -0,0 +1,30 @@
1
+ import { type ConnectionEntry } from "@ghostwriter/core";
2
+ export declare function connectCommand(platform?: string): Promise<void>;
3
+ /**
4
+ * Interactive WordPress connection setup.
5
+ * Exported so the `create` command can call it programmatically.
6
+ */
7
+ export declare function connectWordPress(): Promise<void>;
8
+ /**
9
+ * Interactive WordPress.com OAuth connection setup.
10
+ * Exported so the `create` command can call it programmatically.
11
+ */
12
+ export declare function connectWordPressCom(): Promise<ConnectionEntry | undefined>;
13
+ export declare function checkWordPressApi(baseUrl: string): Promise<{
14
+ ok: true;
15
+ name: string;
16
+ version: string;
17
+ } | {
18
+ ok: false;
19
+ error: string;
20
+ }>;
21
+ export declare function testWordPressAuth(baseUrl: string, username: string, appPassword: string): Promise<{
22
+ ok: true;
23
+ displayName: string;
24
+ role: string;
25
+ capabilities?: Record<string, boolean>;
26
+ } | {
27
+ ok: false;
28
+ error: string;
29
+ }>;
30
+ //# sourceMappingURL=connect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connect.d.ts","sourceRoot":"","sources":["../../src/commands/connect.ts"],"names":[],"mappings":"AAIA,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,mBAAmB,CAAC;AAe3B,wBAAsB,cAAc,CAAC,QAAQ,CAAC,EAAE,MAAM,iBA+BrD;AAoBD;;;GAGG;AACH,wBAAsB,gBAAgB,kBAiNrC;AAID;;;GAGG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAClD,eAAe,GAAG,SAAS,CAC5B,CA4KA;AAgFD,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,MAAM,GACd,OAAO,CACN;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC3C;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAC/B,CAgCA;AAED,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,GAClB,OAAO,CACN;IACE,EAAE,EAAE,IAAI,CAAC;IACT,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACxC,GACD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAC/B,CA2CA"}
@@ -0,0 +1,442 @@
1
+ import chalk from "chalk";
2
+ import { input, password, select, confirm } from "@inquirer/prompts";
3
+ import { saveConnection, loadConnections, } from "@ghostwriter/core";
4
+ import { buildAuthorizeUrl, exchangeCodeForToken, fetchCurrentUser, fetchUserSites, startCallbackServer, generateState, } from "@ghostwriter/site-setup";
5
+ export async function connectCommand(platform) {
6
+ if (!platform) {
7
+ platform = await select({
8
+ message: "Which platform do you want to connect?",
9
+ choices: [
10
+ { value: "wordpress-com", name: "WordPress.com (OAuth)" },
11
+ { value: "wordpress", name: "WordPress (self-hosted)" },
12
+ { value: "twitter", name: "Twitter / X" },
13
+ { value: "list", name: "List existing connections" },
14
+ ],
15
+ });
16
+ }
17
+ switch (platform) {
18
+ case "wordpress":
19
+ await connectWordPress();
20
+ break;
21
+ case "wordpress-com":
22
+ await connectWordPressCom();
23
+ break;
24
+ case "twitter":
25
+ await connectTwitter();
26
+ break;
27
+ case "list":
28
+ await listConnections();
29
+ break;
30
+ default:
31
+ console.log(chalk.red(`\n Unknown platform: ${platform}`));
32
+ console.log(` Supported: wordpress, wordpress-com, twitter\n`);
33
+ process.exitCode = 1;
34
+ }
35
+ }
36
+ async function listConnections() {
37
+ const connections = await loadConnections();
38
+ if (connections.length === 0) {
39
+ console.log(chalk.dim("\n No connections yet. Run: ghostwriter connect\n"));
40
+ return;
41
+ }
42
+ console.log(chalk.blue("\n Saved connections:\n"));
43
+ for (const conn of connections) {
44
+ console.log(` ${chalk.green(conn.id)} — ${conn.platform}${conn.url ? ` (${conn.url})` : ""}`);
45
+ }
46
+ console.log();
47
+ }
48
+ // ─── WordPress ─────────────────────────────────────────────────────────────
49
+ /**
50
+ * Interactive WordPress connection setup.
51
+ * Exported so the `create` command can call it programmatically.
52
+ */
53
+ export async function connectWordPress() {
54
+ console.log(chalk.blue("\n Connect WordPress\n"));
55
+ console.log(chalk.dim(" This uses WordPress Application Passwords (available in WP 5.6+).\n" +
56
+ " No plugins needed — it's built into WordPress core.\n"));
57
+ // Step 1: Name this connection
58
+ const existingWp = (await loadConnections()).filter((c) => c.platform === "wordpress");
59
+ const defaultName = existingWp.length === 0
60
+ ? "wordpress"
61
+ : `wordpress-${existingWp.length + 1}`;
62
+ const connectionId = await input({
63
+ message: "Connection name (used as target ID in channel config):",
64
+ default: defaultName,
65
+ validate: (val) => /^[a-z0-9-]+$/.test(val) ||
66
+ "Use lowercase letters, numbers, and hyphens only",
67
+ });
68
+ // Step 2: Get site URL
69
+ const siteUrl = await input({
70
+ message: "WordPress site URL:",
71
+ validate: (val) => {
72
+ try {
73
+ new URL(val);
74
+ return true;
75
+ }
76
+ catch {
77
+ return "Enter a valid URL (e.g. https://your-site.com)";
78
+ }
79
+ },
80
+ });
81
+ const baseUrl = siteUrl.replace(/\/$/, "");
82
+ // Step 3: Verify it's a WordPress site
83
+ console.log(chalk.dim("\n Checking WordPress REST API..."));
84
+ const wpCheck = await checkWordPressApi(baseUrl);
85
+ if (!wpCheck.ok) {
86
+ console.log(chalk.red(`\n Could not reach WordPress REST API at ${baseUrl}`));
87
+ console.log(chalk.dim(` Error: ${wpCheck.error}`));
88
+ console.log(chalk.dim(" Make sure:"));
89
+ console.log(chalk.dim(" - The URL is correct"));
90
+ console.log(chalk.dim(" - The site is accessible from this machine"));
91
+ console.log(chalk.dim(" - The REST API is enabled (not blocked by a security plugin)\n"));
92
+ const proceed = await confirm({
93
+ message: "Continue anyway?",
94
+ default: false,
95
+ });
96
+ if (!proceed)
97
+ return;
98
+ }
99
+ else {
100
+ console.log(chalk.green(` Found: ${wpCheck.name} (WordPress ${wpCheck.version})`));
101
+ }
102
+ // Step 4: Get credentials
103
+ console.log(chalk.dim("\n To create an Application Password:\n" +
104
+ ` 1. Go to ${baseUrl}/wp-admin/profile.php\n` +
105
+ ' 2. Scroll to "Application Passwords"\n' +
106
+ ' 3. Enter a name (e.g. "ghostwriter") and click "Add New Application Password"\n' +
107
+ " 4. Copy the generated password\n"));
108
+ const openBrowser = await confirm({
109
+ message: "Open your browser to the Application Passwords page?",
110
+ default: true,
111
+ });
112
+ if (openBrowser) {
113
+ const { exec } = await import("node:child_process");
114
+ const cmd = process.platform === "darwin"
115
+ ? "open"
116
+ : process.platform === "win32"
117
+ ? "start"
118
+ : "xdg-open";
119
+ exec(`${cmd} "${baseUrl}/wp-admin/profile.php#application-passwords-section"`);
120
+ console.log(chalk.dim(" Browser opened. Create the password, then come back here.\n"));
121
+ }
122
+ const username = await input({
123
+ message: "WordPress username:",
124
+ });
125
+ const appPassword = await password({
126
+ message: "Application password (paste it here):",
127
+ mask: "*",
128
+ });
129
+ const normalizedPassword = appPassword.trim();
130
+ // Step 5: Test the connection
131
+ console.log(chalk.dim("\n Testing connection..."));
132
+ const testResult = await testWordPressAuth(baseUrl, username, normalizedPassword);
133
+ if (!testResult.ok) {
134
+ console.log(chalk.red(`\n Authentication failed: ${testResult.error}`));
135
+ console.log(chalk.dim(" Check that:"));
136
+ console.log(chalk.dim(" - Username is correct"));
137
+ console.log(chalk.dim(" - Application Password was copied correctly (spaces are OK)"));
138
+ console.log(chalk.dim(" - The user has permission to create posts\n"));
139
+ const saveAnyway = await confirm({
140
+ message: "Save credentials anyway?",
141
+ default: false,
142
+ });
143
+ if (!saveAnyway)
144
+ return;
145
+ }
146
+ else {
147
+ console.log(chalk.green(` Connected as: ${testResult.displayName} (${testResult.role})`));
148
+ if (testResult.capabilities?.publish_posts) {
149
+ console.log(chalk.green(" Can publish posts: yes"));
150
+ }
151
+ else {
152
+ console.log(chalk.yellow(" Warning: this user may not have permission to publish posts"));
153
+ }
154
+ }
155
+ // Step 6: Save to connections store
156
+ await saveConnection({
157
+ id: connectionId,
158
+ platform: "wordpress",
159
+ url: baseUrl,
160
+ credentials: {
161
+ url: baseUrl,
162
+ username,
163
+ password: normalizedPassword,
164
+ },
165
+ createdAt: new Date().toISOString(),
166
+ });
167
+ console.log(chalk.green("\n WordPress connected successfully!"));
168
+ console.log(chalk.dim(` Saved as "${connectionId}" in ~/.ghostwriter/connections.json\n`));
169
+ // Show config example
170
+ const allWp = (await loadConnections()).filter((c) => c.platform === "wordpress");
171
+ if (allWp.length > 1) {
172
+ console.log(" You have multiple WordPress sites. Use the ID to target each one:\n");
173
+ console.log(chalk.cyan(" publishTargets:"));
174
+ for (const wp of allWp) {
175
+ console.log(chalk.cyan(` - platform: wordpress`));
176
+ console.log(chalk.cyan(` id: ${wp.id}`));
177
+ console.log(chalk.cyan(` url: ${wp.url}`));
178
+ }
179
+ }
180
+ else {
181
+ console.log(" Add this to your channel config:\n");
182
+ console.log(chalk.cyan(" publishTargets:\n" +
183
+ ` - platform: wordpress\n` +
184
+ ` id: ${connectionId}\n` +
185
+ ` url: ${baseUrl}\n`));
186
+ }
187
+ console.log();
188
+ }
189
+ // ─── WordPress.com OAuth ────────────────────────────────────────────────────
190
+ /**
191
+ * Interactive WordPress.com OAuth connection setup.
192
+ * Exported so the `create` command can call it programmatically.
193
+ */
194
+ export async function connectWordPressCom() {
195
+ console.log(chalk.blue("\n Connect WordPress.com (OAuth)\n"));
196
+ // Step 1: Check env vars
197
+ const clientId = process.env.WPCOM_CLIENT_ID;
198
+ const clientSecret = process.env.WPCOM_CLIENT_SECRET;
199
+ if (!clientId || !clientSecret) {
200
+ console.log(chalk.red(" Missing environment variables: WPCOM_CLIENT_ID and/or WPCOM_CLIENT_SECRET\n"));
201
+ console.log(chalk.dim(" To set up a WordPress.com OAuth app:"));
202
+ console.log(chalk.dim(" 1. Go to https://developer.wordpress.com/apps/"));
203
+ console.log(chalk.dim(" 2. Create a new application"));
204
+ console.log(chalk.dim(' 3. Set the redirect URL to "http://localhost:{port}/callback"'));
205
+ console.log(chalk.dim(" 4. Export WPCOM_CLIENT_ID and WPCOM_CLIENT_SECRET\n"));
206
+ process.exitCode = 1;
207
+ return undefined;
208
+ }
209
+ // Step 2: Connection name
210
+ const existingWpCom = (await loadConnections()).filter((c) => c.platform === "wordpress-com");
211
+ const defaultName = existingWpCom.length === 0
212
+ ? "wordpress-com"
213
+ : `wordpress-com-${existingWpCom.length + 1}`;
214
+ const connectionId = await input({
215
+ message: "Connection name (used as target ID in channel config):",
216
+ default: defaultName,
217
+ validate: (val) => /^[a-z0-9-]+$/.test(val) ||
218
+ "Use lowercase letters, numbers, and hyphens only",
219
+ });
220
+ // Step 3: Start local callback server (fixed port so it matches the registered redirect URI)
221
+ const port = 3456;
222
+ const redirectUri = `http://localhost:${port}/callback`;
223
+ const config = {
224
+ clientId,
225
+ clientSecret,
226
+ redirectUri,
227
+ };
228
+ const state = generateState();
229
+ const authorizeUrl = buildAuthorizeUrl(config, state);
230
+ const callbackPromise = startCallbackServer(port, state);
231
+ // Step 4: Open browser
232
+ const { exec } = await import("node:child_process");
233
+ const cmd = process.platform === "darwin"
234
+ ? "open"
235
+ : process.platform === "win32"
236
+ ? "start"
237
+ : "xdg-open";
238
+ exec(`${cmd} "${authorizeUrl}"`);
239
+ console.log(chalk.dim("\n Browser opened for authorization."));
240
+ console.log(chalk.dim(" If it didn't open, visit this URL:\n"));
241
+ console.log(` ${chalk.cyan(authorizeUrl)}\n`);
242
+ console.log(chalk.dim(" Waiting for authorization..."));
243
+ // Step 5: Wait for callback
244
+ let callbackResult;
245
+ try {
246
+ callbackResult = await callbackPromise;
247
+ }
248
+ catch (err) {
249
+ console.log(chalk.red(`\n Authorization failed: ${err instanceof Error ? err.message : String(err)}\n`));
250
+ return undefined;
251
+ }
252
+ // Step 6: Exchange code for token
253
+ console.log(chalk.dim(" Exchanging authorization code for token..."));
254
+ let tokenResponse;
255
+ try {
256
+ tokenResponse = await exchangeCodeForToken(config, callbackResult.code);
257
+ }
258
+ catch (err) {
259
+ console.log(chalk.red(`\n Token exchange failed: ${err instanceof Error ? err.message : String(err)}\n`));
260
+ return undefined;
261
+ }
262
+ // Step 7: Fetch user info
263
+ const user = await fetchCurrentUser(tokenResponse.access_token);
264
+ console.log(chalk.green(` Authenticated as: ${user.display_name} (@${user.username})`));
265
+ // Step 8: Resolve site — token response includes blog_id and blog_url
266
+ let siteUrl = tokenResponse.blog_url;
267
+ const blogId = tokenResponse.blog_id;
268
+ if (siteUrl) {
269
+ console.log(chalk.green(` Site: ${siteUrl} (blog ID: ${blogId})`));
270
+ }
271
+ else {
272
+ // Fallback: try to list sites
273
+ try {
274
+ const sites = await fetchUserSites(tokenResponse.access_token);
275
+ const readySites = sites.filter((s) => s.visible && !s.is_coming_soon);
276
+ if (readySites.length === 1) {
277
+ siteUrl = readySites[0].URL;
278
+ console.log(chalk.green(` Auto-selected site: ${readySites[0].name} (${siteUrl})`));
279
+ }
280
+ else if (readySites.length > 1) {
281
+ siteUrl = await select({
282
+ message: "Which site do you want to connect?",
283
+ choices: readySites.map((s) => ({
284
+ value: s.URL,
285
+ name: `${s.name} — ${s.URL}`,
286
+ })),
287
+ });
288
+ }
289
+ }
290
+ catch {
291
+ // Site listing failed — ask manually
292
+ }
293
+ if (!siteUrl) {
294
+ siteUrl = await input({
295
+ message: "WordPress.com site URL (e.g. https://yoursite.wordpress.com):",
296
+ validate: (val) => {
297
+ try {
298
+ new URL(val);
299
+ return true;
300
+ }
301
+ catch {
302
+ return "Enter a valid URL";
303
+ }
304
+ },
305
+ });
306
+ }
307
+ }
308
+ // Step 9: Save connection
309
+ const conn = {
310
+ id: connectionId,
311
+ platform: "wordpress-com",
312
+ url: siteUrl,
313
+ credentials: {
314
+ token: tokenResponse.access_token,
315
+ },
316
+ createdAt: new Date().toISOString(),
317
+ };
318
+ await saveConnection(conn);
319
+ console.log(chalk.green("\n WordPress.com connected successfully!"));
320
+ console.log(chalk.dim(` Saved as "${connectionId}" in ~/.ghostwriter/connections.json\n`));
321
+ // Show config example
322
+ console.log(" Add this to your channel config:\n");
323
+ console.log(chalk.cyan(" publishTargets:\n" +
324
+ ` - platform: wordpress\n` +
325
+ ` id: ${connectionId}\n`));
326
+ console.log();
327
+ return conn;
328
+ }
329
+ // ─── Twitter ───────────────────────────────────────────────────────────────
330
+ async function connectTwitter() {
331
+ console.log(chalk.blue("\n Connect Twitter / X\n"));
332
+ console.log(chalk.dim(" You need a Twitter Developer account with v2 API access.\n" +
333
+ " Create an app at https://developer.twitter.com/en/portal/dashboard\n"));
334
+ const existingTw = (await loadConnections()).filter((c) => c.platform === "twitter");
335
+ const defaultName = existingTw.length === 0
336
+ ? "twitter"
337
+ : `twitter-${existingTw.length + 1}`;
338
+ const connectionId = await input({
339
+ message: "Connection name:",
340
+ default: defaultName,
341
+ validate: (val) => /^[a-z0-9-]+$/.test(val) ||
342
+ "Use lowercase letters, numbers, and hyphens only",
343
+ });
344
+ const openBrowser = await confirm({
345
+ message: "Open Twitter Developer Portal?",
346
+ default: true,
347
+ });
348
+ if (openBrowser) {
349
+ const { exec } = await import("node:child_process");
350
+ const cmd = process.platform === "darwin"
351
+ ? "open"
352
+ : process.platform === "win32"
353
+ ? "start"
354
+ : "xdg-open";
355
+ exec(`${cmd} "https://developer.twitter.com/en/portal/dashboard"`);
356
+ }
357
+ const apiKey = await password({ message: "API Key:", mask: "*" });
358
+ const apiSecret = await password({ message: "API Secret:", mask: "*" });
359
+ const accessToken = await password({
360
+ message: "Access Token:",
361
+ mask: "*",
362
+ });
363
+ const accessSecret = await password({
364
+ message: "Access Token Secret:",
365
+ mask: "*",
366
+ });
367
+ await saveConnection({
368
+ id: connectionId,
369
+ platform: "twitter",
370
+ credentials: {
371
+ apiKey: apiKey.trim(),
372
+ apiSecret: apiSecret.trim(),
373
+ accessToken: accessToken.trim(),
374
+ accessSecret: accessSecret.trim(),
375
+ },
376
+ createdAt: new Date().toISOString(),
377
+ });
378
+ console.log(chalk.green("\n Twitter connected successfully!"));
379
+ console.log(chalk.dim(` Saved as "${connectionId}" in ~/.ghostwriter/connections.json\n`));
380
+ }
381
+ // ─── Helpers ───────────────────────────────────────────────────────────────
382
+ export async function checkWordPressApi(baseUrl) {
383
+ try {
384
+ const resp = await fetch(`${baseUrl}/wp-json/`, {
385
+ signal: AbortSignal.timeout(10_000),
386
+ });
387
+ if (!resp.ok) {
388
+ return { ok: false, error: `HTTP ${resp.status}` };
389
+ }
390
+ const data = (await resp.json());
391
+ const hasWpV2 = data.namespaces?.includes("wp/v2");
392
+ if (!hasWpV2) {
393
+ return {
394
+ ok: false,
395
+ error: "wp/v2 namespace not found — REST API may be disabled",
396
+ };
397
+ }
398
+ return {
399
+ ok: true,
400
+ name: data.name ?? "Unknown",
401
+ version: "5.6+",
402
+ };
403
+ }
404
+ catch (err) {
405
+ return {
406
+ ok: false,
407
+ error: err instanceof Error ? err.message : String(err),
408
+ };
409
+ }
410
+ }
411
+ export async function testWordPressAuth(baseUrl, username, appPassword) {
412
+ try {
413
+ const credentials = Buffer.from(`${username}:${appPassword}`).toString("base64");
414
+ const resp = await fetch(`${baseUrl}/wp-json/wp/v2/users/me?context=edit`, {
415
+ headers: { Authorization: `Basic ${credentials}` },
416
+ signal: AbortSignal.timeout(10_000),
417
+ });
418
+ if (resp.status === 401) {
419
+ return {
420
+ ok: false,
421
+ error: "Invalid username or application password",
422
+ };
423
+ }
424
+ if (!resp.ok) {
425
+ return { ok: false, error: `HTTP ${resp.status}` };
426
+ }
427
+ const user = (await resp.json());
428
+ return {
429
+ ok: true,
430
+ displayName: user.name,
431
+ role: user.roles?.[0] ?? "unknown",
432
+ capabilities: user.capabilities,
433
+ };
434
+ }
435
+ catch (err) {
436
+ return {
437
+ ok: false,
438
+ error: err instanceof Error ? err.message : String(err),
439
+ };
440
+ }
441
+ }
442
+ //# sourceMappingURL=connect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connect.js","sourceRoot":"","sources":["../../src/commands/connect.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export declare function createCommand(descriptionParts: string[], options: {
2
+ interactive?: boolean;
3
+ siteSetup?: boolean;
4
+ dryRun?: boolean;
5
+ }): Promise<void>;
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/create/index.ts"],"names":[],"mappings":"AAgBA,wBAAsB,aAAa,CACjC,gBAAgB,EAAE,MAAM,EAAE,EAC1B,OAAO,EAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GACxE,OAAO,CAAC,IAAI,CAAC,CAuFf"}
@@ -0,0 +1,89 @@
1
+ import ora from "ora";
2
+ import chalk from "chalk";
3
+ import { confirm } from "@inquirer/prompts";
4
+ import { parseIntent } from "./steps/parse-intent.js";
5
+ import { resolveConnection } from "./steps/resolve-connection.js";
6
+ import { fingerprintStyle } from "./steps/fingerprint-style.js";
7
+ import { generateVoice } from "./steps/generate-voice.js";
8
+ import { discoverSources } from "./steps/discover-sources.js";
9
+ import { resolveSchedule } from "./steps/resolve-schedule.js";
10
+ import { assembleConfig } from "./steps/assemble-config.js";
11
+ import { validateSiteAccess } from "./steps/validate-site-access.js";
12
+ import { setupSite } from "./steps/setup-site.js";
13
+ import { generateExample } from "./steps/generate-example.js";
14
+ import { validateAndSummary } from "./steps/validate-and-summary.js";
15
+ export async function createCommand(descriptionParts, options) {
16
+ const rawDescription = descriptionParts.join(" ").trim();
17
+ if (!rawDescription) {
18
+ console.log(chalk.red("\n Please provide a description of the channel to create.\n"));
19
+ console.log(chalk.dim(' Example: ghostwriter create "weekly stock market recap blog, casual and funny"\n'));
20
+ process.exitCode = 1;
21
+ return;
22
+ }
23
+ const opts = {
24
+ interactive: options.interactive ?? false,
25
+ siteSetup: options.siteSetup !== false, // default true (--no-site-setup sets to false)
26
+ dryRun: options.dryRun ?? false,
27
+ };
28
+ const ctx = {
29
+ rawDescription,
30
+ options: opts,
31
+ totalCost: 0,
32
+ };
33
+ console.log("");
34
+ if (opts.dryRun) {
35
+ console.log(chalk.yellow(" Dry run mode — no files will be written\n"));
36
+ }
37
+ const spinner = ora({ indent: 2 });
38
+ try {
39
+ // Stage 1: Parse intent
40
+ ctx.intent = await parseIntent(ctx, spinner);
41
+ if (opts.interactive && !(await confirmStep("Continue with this intent?")))
42
+ return;
43
+ // Stage 2: Resolve connection
44
+ ctx.connection = await resolveConnection(ctx, spinner);
45
+ if (opts.interactive && !(await confirmStep("Continue with this connection?")))
46
+ return;
47
+ // Stage 2.5: Validate site access
48
+ if (ctx.connection) {
49
+ await validateSiteAccess(ctx, spinner);
50
+ }
51
+ // Stage 3: Fingerprint style
52
+ ctx.styleProfile = await fingerprintStyle(ctx, spinner);
53
+ if (opts.interactive && ctx.styleProfile && !(await confirmStep("Continue with this style profile?")))
54
+ return;
55
+ // Stage 4: Generate voice
56
+ ctx.voice = await generateVoice(ctx, spinner);
57
+ if (opts.interactive && !(await confirmStep("Continue with this voice?")))
58
+ return;
59
+ // Stage 5: Discover sources
60
+ ctx.dataSources = await discoverSources(ctx, spinner);
61
+ if (opts.interactive && !(await confirmStep("Continue with these sources?")))
62
+ return;
63
+ // Stage 6: Resolve schedule
64
+ ctx.schedule = resolveSchedule(ctx, spinner);
65
+ // Stage 7: Assemble config
66
+ ctx.config = await assembleConfig(ctx, spinner);
67
+ // Stage 8: Setup site (if enabled)
68
+ if (opts.siteSetup && ctx.intent.publishPlatform === "wordpress-com") {
69
+ if (opts.interactive && !(await confirmStep("Configure WordPress site?"))) {
70
+ // Skip site setup
71
+ }
72
+ else {
73
+ ctx.siteResult = await setupSite(ctx, spinner);
74
+ }
75
+ }
76
+ // Stage 9: Generate example
77
+ await generateExample(ctx, spinner);
78
+ // Stage 10: Validate & summary
79
+ await validateAndSummary(ctx, spinner);
80
+ }
81
+ catch (err) {
82
+ spinner.fail(`Error: ${err instanceof Error ? err.message : String(err)}`);
83
+ process.exitCode = 1;
84
+ }
85
+ }
86
+ async function confirmStep(message) {
87
+ return confirm({ message, default: true });
88
+ }
89
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/create/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare const EXAMPLE_ARTICLE_SYSTEM = "You are a blog writer. Write a sample article that demonstrates the voice, style, and topic focus described.\nThis article will be used as a reference example for future content generation.\n\nRules:\n- Write approximately 500 words\n- Use the voice persona's verbal tics and preferred vocabulary\n- Match the described tone exactly\n- Include the kind of structure (headings, lists, etc.) typical for this content type\n- Make it feel authentic and natural \u2014 not like AI-generated content\n- Vary sentence length significantly (some short punchy sentences, some longer flowing ones)\n- Use contractions naturally\n- Include specific details, even if fictional/example data\n- Do NOT use any phrases from the forbidden vocabulary list\n- Output ONLY the article in markdown format (no meta-commentary)";
2
+ export declare function buildExampleArticlePrompt(channelName: string, contentType: string, topicFocus: string, voiceName: string, voicePersona: string, verbalTics: string[], preferredVocab: string[], forbiddenVocab: string[], tone: string): string;
3
+ //# sourceMappingURL=example-article.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"example-article.d.ts","sourceRoot":"","sources":["../../../../src/commands/create/prompts/example-article.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,sBAAsB,2yBAa+B,CAAC;AAEnE,wBAAgB,yBAAyB,CACvC,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAAE,EACpB,cAAc,EAAE,MAAM,EAAE,EACxB,cAAc,EAAE,MAAM,EAAE,EACxB,IAAI,EAAE,MAAM,GACX,MAAM,CAgBR"}
@@ -0,0 +1,32 @@
1
+ export const EXAMPLE_ARTICLE_SYSTEM = `You are a blog writer. Write a sample article that demonstrates the voice, style, and topic focus described.
2
+ This article will be used as a reference example for future content generation.
3
+
4
+ Rules:
5
+ - Write approximately 500 words
6
+ - Use the voice persona's verbal tics and preferred vocabulary
7
+ - Match the described tone exactly
8
+ - Include the kind of structure (headings, lists, etc.) typical for this content type
9
+ - Make it feel authentic and natural — not like AI-generated content
10
+ - Vary sentence length significantly (some short punchy sentences, some longer flowing ones)
11
+ - Use contractions naturally
12
+ - Include specific details, even if fictional/example data
13
+ - Do NOT use any phrases from the forbidden vocabulary list
14
+ - Output ONLY the article in markdown format (no meta-commentary)`;
15
+ export function buildExampleArticlePrompt(channelName, contentType, topicFocus, voiceName, voicePersona, verbalTics, preferredVocab, forbiddenVocab, tone) {
16
+ return `Write a sample ${contentType} for "${channelName}".
17
+
18
+ Topic focus: ${topicFocus}
19
+
20
+ Voice: ${voiceName}
21
+ ${voicePersona}
22
+
23
+ Verbal tics to use naturally: ${verbalTics.join(", ") || "none"}
24
+ Preferred vocabulary: ${preferredVocab.join(", ") || "none"}
25
+ Tone: ${tone}
26
+
27
+ FORBIDDEN phrases (never use these):
28
+ ${forbiddenVocab.map((p) => `- "${p}"`).join("\n")}
29
+
30
+ Write the article now (~500 words, markdown format).`;
31
+ }
32
+ //# sourceMappingURL=example-article.js.map