@mainwp/control 1.0.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 (204) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +583 -0
  3. package/bin/_exit.js +12 -0
  4. package/bin/dev.js +7 -0
  5. package/bin/run.js +7 -0
  6. package/dist/chat/chat-engine.d.ts +213 -0
  7. package/dist/chat/chat-engine.d.ts.map +1 -0
  8. package/dist/chat/chat-engine.js +636 -0
  9. package/dist/chat/chat-engine.js.map +1 -0
  10. package/dist/chat/index.d.ts +10 -0
  11. package/dist/chat/index.d.ts.map +1 -0
  12. package/dist/chat/index.js +14 -0
  13. package/dist/chat/index.js.map +1 -0
  14. package/dist/chat/providers/anthropic.d.ts +52 -0
  15. package/dist/chat/providers/anthropic.d.ts.map +1 -0
  16. package/dist/chat/providers/anthropic.js +292 -0
  17. package/dist/chat/providers/anthropic.js.map +1 -0
  18. package/dist/chat/providers/gemini.d.ts +52 -0
  19. package/dist/chat/providers/gemini.d.ts.map +1 -0
  20. package/dist/chat/providers/gemini.js +284 -0
  21. package/dist/chat/providers/gemini.js.map +1 -0
  22. package/dist/chat/providers/index.d.ts +19 -0
  23. package/dist/chat/providers/index.d.ts.map +1 -0
  24. package/dist/chat/providers/index.js +23 -0
  25. package/dist/chat/providers/index.js.map +1 -0
  26. package/dist/chat/providers/local.d.ts +37 -0
  27. package/dist/chat/providers/local.d.ts.map +1 -0
  28. package/dist/chat/providers/local.js +130 -0
  29. package/dist/chat/providers/local.js.map +1 -0
  30. package/dist/chat/providers/openai-compatible.d.ts +155 -0
  31. package/dist/chat/providers/openai-compatible.d.ts.map +1 -0
  32. package/dist/chat/providers/openai-compatible.js +264 -0
  33. package/dist/chat/providers/openai-compatible.js.map +1 -0
  34. package/dist/chat/providers/openai.d.ts +24 -0
  35. package/dist/chat/providers/openai.d.ts.map +1 -0
  36. package/dist/chat/providers/openai.js +62 -0
  37. package/dist/chat/providers/openai.js.map +1 -0
  38. package/dist/chat/providers/openrouter.d.ts +26 -0
  39. package/dist/chat/providers/openrouter.d.ts.map +1 -0
  40. package/dist/chat/providers/openrouter.js +65 -0
  41. package/dist/chat/providers/openrouter.js.map +1 -0
  42. package/dist/chat/providers/provider-fetch.d.ts +15 -0
  43. package/dist/chat/providers/provider-fetch.d.ts.map +1 -0
  44. package/dist/chat/providers/provider-fetch.js +35 -0
  45. package/dist/chat/providers/provider-fetch.js.map +1 -0
  46. package/dist/chat/providers/provider.d.ts +214 -0
  47. package/dist/chat/providers/provider.d.ts.map +1 -0
  48. package/dist/chat/providers/provider.js +166 -0
  49. package/dist/chat/providers/provider.js.map +1 -0
  50. package/dist/chat/providers/sse-reader.d.ts +21 -0
  51. package/dist/chat/providers/sse-reader.d.ts.map +1 -0
  52. package/dist/chat/providers/sse-reader.js +48 -0
  53. package/dist/chat/providers/sse-reader.js.map +1 -0
  54. package/dist/chat/system-prompt.d.ts +33 -0
  55. package/dist/chat/system-prompt.d.ts.map +1 -0
  56. package/dist/chat/system-prompt.js +166 -0
  57. package/dist/chat/system-prompt.js.map +1 -0
  58. package/dist/chat/tool-envelope.d.ts +72 -0
  59. package/dist/chat/tool-envelope.d.ts.map +1 -0
  60. package/dist/chat/tool-envelope.js +263 -0
  61. package/dist/chat/tool-envelope.js.map +1 -0
  62. package/dist/commands/abilities/info.d.ts +21 -0
  63. package/dist/commands/abilities/info.d.ts.map +1 -0
  64. package/dist/commands/abilities/info.js +80 -0
  65. package/dist/commands/abilities/info.js.map +1 -0
  66. package/dist/commands/abilities/list.d.ts +19 -0
  67. package/dist/commands/abilities/list.d.ts.map +1 -0
  68. package/dist/commands/abilities/list.js +98 -0
  69. package/dist/commands/abilities/list.js.map +1 -0
  70. package/dist/commands/abilities/run.d.ts +75 -0
  71. package/dist/commands/abilities/run.d.ts.map +1 -0
  72. package/dist/commands/abilities/run.js +468 -0
  73. package/dist/commands/abilities/run.js.map +1 -0
  74. package/dist/commands/chat.d.ts +54 -0
  75. package/dist/commands/chat.d.ts.map +1 -0
  76. package/dist/commands/chat.js +384 -0
  77. package/dist/commands/chat.js.map +1 -0
  78. package/dist/commands/config/show.d.ts +54 -0
  79. package/dist/commands/config/show.d.ts.map +1 -0
  80. package/dist/commands/config/show.js +324 -0
  81. package/dist/commands/config/show.js.map +1 -0
  82. package/dist/commands/doctor.d.ts +77 -0
  83. package/dist/commands/doctor.d.ts.map +1 -0
  84. package/dist/commands/doctor.js +412 -0
  85. package/dist/commands/doctor.js.map +1 -0
  86. package/dist/commands/jobs/watch.d.ts +50 -0
  87. package/dist/commands/jobs/watch.d.ts.map +1 -0
  88. package/dist/commands/jobs/watch.js +269 -0
  89. package/dist/commands/jobs/watch.js.map +1 -0
  90. package/dist/commands/login.d.ts +25 -0
  91. package/dist/commands/login.d.ts.map +1 -0
  92. package/dist/commands/login.js +165 -0
  93. package/dist/commands/login.js.map +1 -0
  94. package/dist/commands/profile/delete.d.ts +22 -0
  95. package/dist/commands/profile/delete.d.ts.map +1 -0
  96. package/dist/commands/profile/delete.js +57 -0
  97. package/dist/commands/profile/delete.js.map +1 -0
  98. package/dist/commands/profile/list.d.ts +19 -0
  99. package/dist/commands/profile/list.d.ts.map +1 -0
  100. package/dist/commands/profile/list.js +53 -0
  101. package/dist/commands/profile/list.js.map +1 -0
  102. package/dist/commands/profile/use.d.ts +22 -0
  103. package/dist/commands/profile/use.d.ts.map +1 -0
  104. package/dist/commands/profile/use.js +46 -0
  105. package/dist/commands/profile/use.js.map +1 -0
  106. package/dist/config/fs-utils.d.ts +14 -0
  107. package/dist/config/fs-utils.d.ts.map +1 -0
  108. package/dist/config/fs-utils.js +31 -0
  109. package/dist/config/fs-utils.js.map +1 -0
  110. package/dist/config/keychain.d.ts +53 -0
  111. package/dist/config/keychain.d.ts.map +1 -0
  112. package/dist/config/keychain.js +175 -0
  113. package/dist/config/keychain.js.map +1 -0
  114. package/dist/config/profile-store.d.ts +85 -0
  115. package/dist/config/profile-store.d.ts.map +1 -0
  116. package/dist/config/profile-store.js +228 -0
  117. package/dist/config/profile-store.js.map +1 -0
  118. package/dist/config/settings.d.ts +71 -0
  119. package/dist/config/settings.d.ts.map +1 -0
  120. package/dist/config/settings.js +151 -0
  121. package/dist/config/settings.js.map +1 -0
  122. package/dist/core/abilities-executor.d.ts +126 -0
  123. package/dist/core/abilities-executor.d.ts.map +1 -0
  124. package/dist/core/abilities-executor.js +264 -0
  125. package/dist/core/abilities-executor.js.map +1 -0
  126. package/dist/core/batch-manager.d.ts +113 -0
  127. package/dist/core/batch-manager.d.ts.map +1 -0
  128. package/dist/core/batch-manager.js +244 -0
  129. package/dist/core/batch-manager.js.map +1 -0
  130. package/dist/core/http-client.d.ts +111 -0
  131. package/dist/core/http-client.d.ts.map +1 -0
  132. package/dist/core/http-client.js +329 -0
  133. package/dist/core/http-client.js.map +1 -0
  134. package/dist/core/safety-controller.d.ts +114 -0
  135. package/dist/core/safety-controller.d.ts.map +1 -0
  136. package/dist/core/safety-controller.js +229 -0
  137. package/dist/core/safety-controller.js.map +1 -0
  138. package/dist/hooks/command-not-found.d.ts +12 -0
  139. package/dist/hooks/command-not-found.d.ts.map +1 -0
  140. package/dist/hooks/command-not-found.js +58 -0
  141. package/dist/hooks/command-not-found.js.map +1 -0
  142. package/dist/index.d.ts +7 -0
  143. package/dist/index.d.ts.map +1 -0
  144. package/dist/index.js +7 -0
  145. package/dist/index.js.map +1 -0
  146. package/dist/lib/base-command.d.ts +123 -0
  147. package/dist/lib/base-command.d.ts.map +1 -0
  148. package/dist/lib/base-command.js +285 -0
  149. package/dist/lib/base-command.js.map +1 -0
  150. package/dist/output/formatter.d.ts +48 -0
  151. package/dist/output/formatter.d.ts.map +1 -0
  152. package/dist/output/formatter.js +138 -0
  153. package/dist/output/formatter.js.map +1 -0
  154. package/dist/output/json-envelope.d.ts +43 -0
  155. package/dist/output/json-envelope.d.ts.map +1 -0
  156. package/dist/output/json-envelope.js +73 -0
  157. package/dist/output/json-envelope.js.map +1 -0
  158. package/dist/utils/audit-logger.d.ts +97 -0
  159. package/dist/utils/audit-logger.d.ts.map +1 -0
  160. package/dist/utils/audit-logger.js +169 -0
  161. package/dist/utils/audit-logger.js.map +1 -0
  162. package/dist/utils/colors.d.ts +29 -0
  163. package/dist/utils/colors.d.ts.map +1 -0
  164. package/dist/utils/colors.js +36 -0
  165. package/dist/utils/colors.js.map +1 -0
  166. package/dist/utils/errors.d.ts +107 -0
  167. package/dist/utils/errors.d.ts.map +1 -0
  168. package/dist/utils/errors.js +149 -0
  169. package/dist/utils/errors.js.map +1 -0
  170. package/dist/utils/exit-codes.d.ts +21 -0
  171. package/dist/utils/exit-codes.d.ts.map +1 -0
  172. package/dist/utils/exit-codes.js +20 -0
  173. package/dist/utils/exit-codes.js.map +1 -0
  174. package/dist/utils/format.d.ts +64 -0
  175. package/dist/utils/format.d.ts.map +1 -0
  176. package/dist/utils/format.js +69 -0
  177. package/dist/utils/format.js.map +1 -0
  178. package/dist/utils/prompt.d.ts +34 -0
  179. package/dist/utils/prompt.d.ts.map +1 -0
  180. package/dist/utils/prompt.js +132 -0
  181. package/dist/utils/prompt.js.map +1 -0
  182. package/dist/utils/retry.d.ts +59 -0
  183. package/dist/utils/retry.d.ts.map +1 -0
  184. package/dist/utils/retry.js +96 -0
  185. package/dist/utils/retry.js.map +1 -0
  186. package/dist/utils/terminal-sanitizer.d.ts +60 -0
  187. package/dist/utils/terminal-sanitizer.d.ts.map +1 -0
  188. package/dist/utils/terminal-sanitizer.js +166 -0
  189. package/dist/utils/terminal-sanitizer.js.map +1 -0
  190. package/dist/validation/input-sanitizer.d.ts +76 -0
  191. package/dist/validation/input-sanitizer.d.ts.map +1 -0
  192. package/dist/validation/input-sanitizer.js +199 -0
  193. package/dist/validation/input-sanitizer.js.map +1 -0
  194. package/dist/validation/schema-validator.d.ts +75 -0
  195. package/dist/validation/schema-validator.d.ts.map +1 -0
  196. package/dist/validation/schema-validator.js +147 -0
  197. package/dist/validation/schema-validator.js.map +1 -0
  198. package/oclif.manifest.json +857 -0
  199. package/package.json +101 -0
  200. package/scripts/completions/README.md +221 -0
  201. package/scripts/completions/mainwpcontrol.bash +193 -0
  202. package/scripts/completions/mainwpcontrol.zsh +267 -0
  203. package/scripts/completions/profile-completer.sh +35 -0
  204. package/scripts/completions/regenerate.sh +78 -0
@@ -0,0 +1,228 @@
1
+ /**
2
+ * Profile store for mainwpcontrol
3
+ *
4
+ * Manages multiple Dashboard connection profiles.
5
+ */
6
+ import { promises as fs } from 'node:fs';
7
+ import { join } from 'node:path';
8
+ import { ConfigError } from '../utils/errors.js';
9
+ import { getConfigDir } from './settings.js';
10
+ import { atomicWriteFile } from './fs-utils.js';
11
+ /**
12
+ * Get the profiles file path
13
+ */
14
+ function getProfilesPath() {
15
+ return join(getConfigDir(), 'profiles.json');
16
+ }
17
+ /**
18
+ * Load profiles from file
19
+ */
20
+ async function loadProfilesFile() {
21
+ const path = getProfilesPath();
22
+ try {
23
+ const content = await fs.readFile(path, 'utf-8');
24
+ return JSON.parse(content);
25
+ }
26
+ catch (error) {
27
+ if (error.code === 'ENOENT') {
28
+ return { profiles: [] };
29
+ }
30
+ throw new ConfigError(`Failed to load profiles: ${error.message}`, undefined, 'Check file permissions for ~/.config/mainwpcontrol/profiles.json');
31
+ }
32
+ }
33
+ /**
34
+ * Save profiles to file
35
+ *
36
+ * SECURITY: Uses atomic write (tmp + rename) and restricted permissions.
37
+ */
38
+ async function saveProfilesFile(data) {
39
+ const path = getProfilesPath();
40
+ await atomicWriteFile(path, JSON.stringify(data, null, 2));
41
+ }
42
+ /**
43
+ * Profile store class
44
+ */
45
+ export class ProfileStore {
46
+ data = null;
47
+ /**
48
+ * Validate a URL format and protocol
49
+ */
50
+ validateUrl(url) {
51
+ let parsed;
52
+ try {
53
+ parsed = new URL(url);
54
+ }
55
+ catch {
56
+ throw new ConfigError(`Invalid Dashboard URL format: ${url}`, undefined, 'URL must include protocol (http:// or https://) and hostname');
57
+ }
58
+ if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
59
+ throw new ConfigError(`Invalid URL protocol: ${parsed.protocol}. Must be http or https`, undefined, 'Only HTTP and HTTPS protocols are supported');
60
+ }
61
+ // HTTP warning is emitted at login time via formatWarning, not here
62
+ }
63
+ /**
64
+ * Validate a profile's required fields and URL format
65
+ */
66
+ validateProfile(profile) {
67
+ const validationHint = 'Run `mainwpcontrol login` to create a valid profile';
68
+ if (!profile.name || profile.name.trim().length === 0) {
69
+ throw new ConfigError('Profile validation failed: name is required', undefined, validationHint);
70
+ }
71
+ if (!profile.dashboardUrl || profile.dashboardUrl.trim().length === 0) {
72
+ throw new ConfigError('Profile validation failed: dashboardUrl is required', undefined, validationHint);
73
+ }
74
+ if (!profile.username || profile.username.trim().length === 0) {
75
+ throw new ConfigError('Profile validation failed: username is required', undefined, validationHint);
76
+ }
77
+ if (!profile.createdAt || profile.createdAt.trim().length === 0) {
78
+ throw new ConfigError('Profile validation failed: createdAt is required', undefined, validationHint);
79
+ }
80
+ this.validateUrl(profile.dashboardUrl);
81
+ }
82
+ /**
83
+ * Validate entire profiles file structure
84
+ */
85
+ validateProfilesFile(data) {
86
+ for (const profile of data.profiles) {
87
+ try {
88
+ this.validateProfile(profile);
89
+ }
90
+ catch (error) {
91
+ // Preserve hint from the original ConfigError when rewrapping
92
+ const hint = error instanceof ConfigError ? error.hint : undefined;
93
+ throw new ConfigError(`Invalid profile "${profile.name || 'unnamed'}": ${error.message}`, undefined, hint);
94
+ }
95
+ }
96
+ // Validate activeProfile references an existing profile
97
+ if (data.activeProfile &&
98
+ !data.profiles.some((p) => p.name === data.activeProfile)) {
99
+ data.activeProfile = data.profiles[0]?.name;
100
+ }
101
+ }
102
+ /**
103
+ * Ensure data is loaded
104
+ */
105
+ async ensureLoaded() {
106
+ if (!this.data) {
107
+ const data = await loadProfilesFile();
108
+ this.validateProfilesFile(data);
109
+ this.data = data;
110
+ }
111
+ return this.data;
112
+ }
113
+ /**
114
+ * List all profiles
115
+ */
116
+ async list() {
117
+ const data = await this.ensureLoaded();
118
+ return data.profiles;
119
+ }
120
+ /**
121
+ * Get the active profile
122
+ */
123
+ async getActive() {
124
+ const data = await this.ensureLoaded();
125
+ if (!data.activeProfile) {
126
+ // Return first profile if no active set
127
+ return data.profiles[0];
128
+ }
129
+ return data.profiles.find((p) => p.name === data.activeProfile);
130
+ }
131
+ /**
132
+ * Get the active profile name
133
+ */
134
+ async getActiveName() {
135
+ const data = await this.ensureLoaded();
136
+ return data.activeProfile ?? data.profiles[0]?.name;
137
+ }
138
+ /**
139
+ * Set the active profile
140
+ */
141
+ async setActive(name) {
142
+ const data = await this.ensureLoaded();
143
+ const profile = data.profiles.find((p) => p.name === name);
144
+ if (!profile) {
145
+ throw new ConfigError(`Profile not found: ${name}`, undefined, 'List available profiles with `mainwpcontrol profile list`');
146
+ }
147
+ data.activeProfile = name;
148
+ profile.lastUsedAt = new Date().toISOString();
149
+ await saveProfilesFile(data);
150
+ this.data = data;
151
+ }
152
+ /**
153
+ * Get a profile by name
154
+ */
155
+ async get(name) {
156
+ const data = await this.ensureLoaded();
157
+ return data.profiles.find((p) => p.name === name);
158
+ }
159
+ /**
160
+ * Save a profile (create or update)
161
+ */
162
+ async save(profile) {
163
+ // Validate profile before saving
164
+ this.validateProfile(profile);
165
+ const data = await this.ensureLoaded();
166
+ const existingIndex = data.profiles.findIndex((p) => p.name === profile.name);
167
+ if (existingIndex >= 0) {
168
+ // Update existing
169
+ data.profiles[existingIndex] = profile;
170
+ }
171
+ else {
172
+ // Add new
173
+ data.profiles.push(profile);
174
+ }
175
+ // Set as active if it's the first profile
176
+ if (data.profiles.length === 1) {
177
+ data.activeProfile = profile.name;
178
+ }
179
+ await saveProfilesFile(data);
180
+ this.data = data;
181
+ }
182
+ /**
183
+ * Remove a profile
184
+ */
185
+ async remove(name) {
186
+ const data = await this.ensureLoaded();
187
+ const index = data.profiles.findIndex((p) => p.name === name);
188
+ if (index < 0) {
189
+ throw new ConfigError(`Profile not found: ${name}`, undefined, 'List available profiles with `mainwpcontrol profile list`');
190
+ }
191
+ data.profiles.splice(index, 1);
192
+ // Clear active if we removed the active profile
193
+ if (data.activeProfile === name) {
194
+ data.activeProfile = data.profiles[0]?.name;
195
+ }
196
+ await saveProfilesFile(data);
197
+ this.data = data;
198
+ }
199
+ /**
200
+ * Check if a profile exists
201
+ */
202
+ async exists(name) {
203
+ const data = await this.ensureLoaded();
204
+ return data.profiles.some((p) => p.name === name);
205
+ }
206
+ /**
207
+ * Reload profiles from disk
208
+ */
209
+ async reload() {
210
+ const data = await loadProfilesFile();
211
+ this.validateProfilesFile(data);
212
+ this.data = data;
213
+ }
214
+ }
215
+ /**
216
+ * Singleton instance
217
+ */
218
+ let profileStoreInstance = null;
219
+ /**
220
+ * Get the profile store instance
221
+ */
222
+ export function getProfileStore() {
223
+ if (!profileStoreInstance) {
224
+ profileStoreInstance = new ProfileStore();
225
+ }
226
+ return profileStoreInstance;
227
+ }
228
+ //# sourceMappingURL=profile-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile-store.js","sourceRoot":"","sources":["../../src/config/profile-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Settings file support for mainwpcontrol
3
+ */
4
+ import { type ProviderName } from '../chat/providers/provider.js';
5
+ /**
6
+ * Settings structure
7
+ */
8
+ export interface Settings {
9
+ /** Default output format (true = JSON, false = human-readable) */
10
+ defaultJsonOutput?: boolean;
11
+ /** Default LLM provider */
12
+ llmProvider?: string;
13
+ /** Default timeout for HTTP requests (ms) */
14
+ timeout?: number;
15
+ /** Skip SSL verification (not recommended) */
16
+ skipSSLVerification?: boolean;
17
+ /** Enable debug output */
18
+ debug?: boolean;
19
+ /** Maximum messages to keep in chat context (default: 20, 0 = unlimited) */
20
+ chatContextMessages?: number;
21
+ /** Maximum estimated tokens in chat context (reserved for future use) */
22
+ chatContextTokens?: number;
23
+ /** Allow insecure HTTP connections (not recommended) */
24
+ allowInsecureHttp?: boolean;
25
+ }
26
+ export interface ResolvedSettings {
27
+ defaultJsonOutput: boolean;
28
+ llmProvider?: ProviderName;
29
+ timeout: number;
30
+ skipSSLVerification: boolean;
31
+ debug: boolean;
32
+ chatContextMessages: number;
33
+ chatContextTokens?: number;
34
+ allowInsecureHttp: boolean;
35
+ }
36
+ export interface SettingsResolution {
37
+ settings: ResolvedSettings;
38
+ warnings: string[];
39
+ }
40
+ export declare const SETTINGS_DEFAULTS: ResolvedSettings;
41
+ /**
42
+ * Get the config directory path
43
+ */
44
+ export declare function getConfigDir(): string;
45
+ /**
46
+ * Get the settings file path
47
+ */
48
+ export declare function getSettingsPath(): string;
49
+ /**
50
+ * Load settings from file (cached after first read)
51
+ */
52
+ export declare function loadSettings(): Promise<Settings>;
53
+ /**
54
+ * Validate and normalize settings with safe fallbacks.
55
+ */
56
+ export declare function resolveSettings(raw: Settings): SettingsResolution;
57
+ /**
58
+ * Clear the settings cache (forces re-read on next loadSettings call)
59
+ */
60
+ export declare function clearSettingsCache(): void;
61
+ /**
62
+ * Save settings to file
63
+ *
64
+ * SECURITY: Uses atomic write (tmp + rename) and restricted permissions.
65
+ */
66
+ export declare function saveSettings(settings: Settings): Promise<void>;
67
+ /**
68
+ * Update specific settings
69
+ */
70
+ export declare function updateSettings(updates: Partial<Settings>): Promise<Settings>;
71
+ //# sourceMappingURL=settings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../src/config/settings.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,EAEL,KAAK,YAAY,EAElB,MAAM,+BAA+B,CAAC;AAGvC;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,kEAAkE;IAClE,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAE5B,2BAA2B;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,6CAA6C;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,8CAA8C;IAC9C,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAE9B,0BAA0B;IAC1B,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB,4EAA4E;IAC5E,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAE7B,yEAAyE;IACzE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,wDAAwD;IACxD,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,gBAAgB;IAC/B,iBAAiB,EAAE,OAAO,CAAC;IAC3B,WAAW,CAAC,EAAE,YAAY,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,KAAK,EAAE,OAAO,CAAC;IACf,mBAAmB,EAAE,MAAM,CAAC;IAC5B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,eAAO,MAAM,iBAAiB,EAAE,gBAO/B,CAAC;AAEF;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAMrC;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAUD;;GAEG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,QAAQ,CAAC,CAyBtD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,QAAQ,GAAG,kBAAkB,CA4DjE;AAoBD;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAMpE;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAKlF"}
@@ -0,0 +1,151 @@
1
+ /**
2
+ * Settings file support for mainwpcontrol
3
+ */
4
+ import { promises as fs } from 'node:fs';
5
+ import { join } from 'node:path';
6
+ import { homedir } from 'node:os';
7
+ import { isSupportedProviderName, SUPPORTED_PROVIDER_NAMES, } from '../chat/providers/provider.js';
8
+ import { atomicWriteFile } from './fs-utils.js';
9
+ export const SETTINGS_DEFAULTS = {
10
+ defaultJsonOutput: false,
11
+ timeout: 30000,
12
+ skipSSLVerification: false,
13
+ debug: false,
14
+ chatContextMessages: 20,
15
+ allowInsecureHttp: false,
16
+ };
17
+ /**
18
+ * Get the config directory path
19
+ */
20
+ export function getConfigDir() {
21
+ const xdgConfig = process.env['XDG_CONFIG_HOME'];
22
+ if (xdgConfig) {
23
+ return join(xdgConfig, 'mainwpcontrol');
24
+ }
25
+ return join(homedir(), '.config', 'mainwpcontrol');
26
+ }
27
+ /**
28
+ * Get the settings file path
29
+ */
30
+ export function getSettingsPath() {
31
+ return join(getConfigDir(), 'settings.json');
32
+ }
33
+ /**
34
+ * Cached settings (cleared on explicit reload).
35
+ * No TTL needed: mainwpcontrol is a short-lived CLI process — settings are read
36
+ * once per invocation. clearSettingsCache() handles explicit invalidation
37
+ * (e.g. after saveSettings).
38
+ */
39
+ let cachedSettings = null;
40
+ /**
41
+ * Load settings from file (cached after first read)
42
+ */
43
+ export async function loadSettings() {
44
+ if (cachedSettings) {
45
+ return cachedSettings;
46
+ }
47
+ const path = getSettingsPath();
48
+ try {
49
+ const content = await fs.readFile(path, 'utf-8');
50
+ cachedSettings = JSON.parse(content);
51
+ return cachedSettings;
52
+ }
53
+ catch (error) {
54
+ if (error.code === 'ENOENT') {
55
+ cachedSettings = {};
56
+ return cachedSettings;
57
+ }
58
+ if (error instanceof SyntaxError) {
59
+ // Corrupted/malformed JSON — warn but don't crash
60
+ console.error(`Warning: Failed to parse settings file at ${path}. Using defaults.`);
61
+ cachedSettings = {};
62
+ return cachedSettings;
63
+ }
64
+ // Permission or other I/O error — surface it
65
+ throw error;
66
+ }
67
+ }
68
+ /**
69
+ * Validate and normalize settings with safe fallbacks.
70
+ */
71
+ export function resolveSettings(raw) {
72
+ const warnings = [];
73
+ const settings = { ...SETTINGS_DEFAULTS };
74
+ settings.defaultJsonOutput = readBooleanSetting(raw.defaultJsonOutput, 'defaultJsonOutput', SETTINGS_DEFAULTS.defaultJsonOutput, warnings);
75
+ settings.debug = readBooleanSetting(raw.debug, 'debug', SETTINGS_DEFAULTS.debug, warnings);
76
+ settings.skipSSLVerification = readBooleanSetting(raw.skipSSLVerification, 'skipSSLVerification', SETTINGS_DEFAULTS.skipSSLVerification, warnings);
77
+ settings.allowInsecureHttp = readBooleanSetting(raw.allowInsecureHttp, 'allowInsecureHttp', SETTINGS_DEFAULTS.allowInsecureHttp, warnings);
78
+ if (raw.timeout === undefined) {
79
+ settings.timeout = SETTINGS_DEFAULTS.timeout;
80
+ }
81
+ else if (Number.isInteger(raw.timeout) && raw.timeout > 0) {
82
+ settings.timeout = raw.timeout;
83
+ }
84
+ else {
85
+ warnings.push('Ignoring invalid settings.timeout; expected a positive integer in milliseconds.');
86
+ }
87
+ if (raw.chatContextMessages === undefined) {
88
+ settings.chatContextMessages = SETTINGS_DEFAULTS.chatContextMessages;
89
+ }
90
+ else if (Number.isInteger(raw.chatContextMessages) && raw.chatContextMessages >= 0) {
91
+ settings.chatContextMessages = raw.chatContextMessages;
92
+ }
93
+ else {
94
+ warnings.push('Ignoring invalid settings.chatContextMessages; expected an integer greater than or equal to 0.');
95
+ }
96
+ if (raw.chatContextTokens !== undefined) {
97
+ if (Number.isInteger(raw.chatContextTokens) && raw.chatContextTokens > 0) {
98
+ settings.chatContextTokens = raw.chatContextTokens;
99
+ }
100
+ else {
101
+ warnings.push('Ignoring invalid settings.chatContextTokens; expected a positive integer.');
102
+ }
103
+ }
104
+ if (raw.llmProvider) {
105
+ const normalized = raw.llmProvider.trim().toLowerCase();
106
+ if (isSupportedProviderName(normalized)) {
107
+ settings.llmProvider = normalized;
108
+ }
109
+ else {
110
+ warnings.push(`Ignoring invalid settings.llmProvider "${raw.llmProvider}". Available: ${SUPPORTED_PROVIDER_NAMES.join(', ')}`);
111
+ }
112
+ }
113
+ return { settings, warnings };
114
+ }
115
+ function readBooleanSetting(value, key, fallback, warnings) {
116
+ if (value === undefined) {
117
+ return fallback;
118
+ }
119
+ if (typeof value === 'boolean') {
120
+ return value;
121
+ }
122
+ warnings.push(`Ignoring invalid settings.${key}; expected a boolean.`);
123
+ return fallback;
124
+ }
125
+ /**
126
+ * Clear the settings cache (forces re-read on next loadSettings call)
127
+ */
128
+ export function clearSettingsCache() {
129
+ cachedSettings = null;
130
+ }
131
+ /**
132
+ * Save settings to file
133
+ *
134
+ * SECURITY: Uses atomic write (tmp + rename) and restricted permissions.
135
+ */
136
+ export async function saveSettings(settings) {
137
+ const path = getSettingsPath();
138
+ await atomicWriteFile(path, JSON.stringify(settings, null, 2));
139
+ // Update cache with freshly saved settings
140
+ cachedSettings = settings;
141
+ }
142
+ /**
143
+ * Update specific settings
144
+ */
145
+ export async function updateSettings(updates) {
146
+ const current = await loadSettings();
147
+ const merged = { ...current, ...updates };
148
+ await saveSettings(merged);
149
+ return merged;
150
+ }
151
+ //# sourceMappingURL=settings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings.js","sourceRoot":"","sources":["../../src/config/settings.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Abilities Executor for mainwpcontrol
3
+ *
4
+ * Single execution pathway for all ability calls.
5
+ * INVARIANT: Both commands and chat route through this module.
6
+ */
7
+ import { type HttpClientConfig } from './http-client.js';
8
+ /**
9
+ * Ability annotation metadata
10
+ */
11
+ export interface AbilityAnnotations {
12
+ readonly: boolean;
13
+ destructive: boolean;
14
+ idempotent: boolean;
15
+ instructions?: string;
16
+ }
17
+ /**
18
+ * Ability definition from the API
19
+ */
20
+ export interface Ability {
21
+ name: string;
22
+ label: string;
23
+ description: string;
24
+ category: string;
25
+ input_schema?: Record<string, unknown>;
26
+ output_schema?: Record<string, unknown>;
27
+ meta?: {
28
+ annotations?: AbilityAnnotations;
29
+ };
30
+ }
31
+ /**
32
+ * Execution options
33
+ */
34
+ export interface ExecutionOptions {
35
+ dryRun?: boolean | undefined;
36
+ confirm?: boolean | undefined;
37
+ signal?: AbortSignal | undefined;
38
+ }
39
+ /**
40
+ * Execution result
41
+ */
42
+ export interface ExecutionResult<T = unknown> {
43
+ success: boolean;
44
+ data?: T;
45
+ error?: {
46
+ code: string;
47
+ message: string;
48
+ details?: unknown;
49
+ hint?: string;
50
+ };
51
+ jobId?: string;
52
+ }
53
+ /**
54
+ * Abilities Executor class
55
+ */
56
+ export declare class AbilitiesExecutor {
57
+ private readonly httpClient;
58
+ private readonly baseEndpoint;
59
+ private abilitiesCache;
60
+ private cacheExpiry;
61
+ private readonly cacheTTL;
62
+ constructor(config: HttpClientConfig);
63
+ /**
64
+ * List all available abilities
65
+ */
66
+ listAbilities(): Promise<Ability[]>;
67
+ /**
68
+ * Get a single ability by name
69
+ */
70
+ getAbility(name: string): Promise<Ability | undefined>;
71
+ /**
72
+ * Execute an ability
73
+ *
74
+ * @param abilityName - The ability name (e.g., "list-sites-v1" or "mainwp/list-sites-v1")
75
+ * @param input - The input parameters
76
+ * @param options - Execution options (dryRun, confirm)
77
+ */
78
+ execute<T = unknown>(abilityName: string, input?: Record<string, unknown>, options?: ExecutionOptions): Promise<ExecutionResult<T>>;
79
+ /**
80
+ * Get ability categories
81
+ */
82
+ getCategories(): Promise<string[]>;
83
+ /**
84
+ * List abilities by category
85
+ */
86
+ listByCategory(category: string): Promise<Ability[]>;
87
+ /**
88
+ * Ensure abilities cache is populated
89
+ */
90
+ private ensureCache;
91
+ /**
92
+ * Normalize ability name (handle with/without namespace)
93
+ */
94
+ private normalizeName;
95
+ /**
96
+ * Get short name from full ability name
97
+ */
98
+ private getShortName;
99
+ /**
100
+ * Build request body with execution options.
101
+ * The WP Abilities API expects: { input: { ...userInput, dry_run?, confirm? } }
102
+ */
103
+ private buildRequestBody;
104
+ /**
105
+ * Determine HTTP method based on ability annotations
106
+ */
107
+ private getHttpMethod;
108
+ /**
109
+ * Build query string for GET/DELETE requests with WordPress-style nesting.
110
+ * User input goes under input[key]=value; control flags stay top-level.
111
+ */
112
+ private buildGetQueryString;
113
+ /**
114
+ * Normalize API response to ExecutionResult
115
+ */
116
+ private normalizeResponse;
117
+ /**
118
+ * Clear the abilities cache
119
+ */
120
+ clearCache(): void;
121
+ }
122
+ /**
123
+ * Create an abilities executor from config
124
+ */
125
+ export declare function createAbilitiesExecutor(config: HttpClientConfig): AbilitiesExecutor;
126
+ //# sourceMappingURL=abilities-executor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abilities-executor.d.ts","sourceRoot":"","sources":["../../src/core/abilities-executor.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAc,KAAK,gBAAgB,EAAoB,MAAM,kBAAkB,CAAC;AAIvF;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,IAAI,CAAC,EAAE;QACL,WAAW,CAAC,EAAE,kBAAkB,CAAC;KAClC,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC7B,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,eAAe,CAAC,CAAC,GAAG,OAAO;IAC1C,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,KAAK,CAAC,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACF,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAQD;;GAEG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAa;IACxC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA8B;IAC3D,OAAO,CAAC,cAAc,CAAqC;IAC3D,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiB;gBAE9B,MAAM,EAAE,gBAAgB;IAIpC;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAQzC;;OAEG;IACG,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC;IAK5D;;;;;;OAMG;IACG,OAAO,CAAC,CAAC,GAAG,OAAO,EACvB,WAAW,EAAE,MAAM,EACnB,KAAK,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACnC,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;IAiE9B;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAMxC;;OAEG;IACG,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAK1D;;OAEG;YACW,WAAW;IAyCzB;;OAEG;IACH,OAAO,CAAC,aAAa;IAKrB;;OAEG;IACH,OAAO,CAAC,YAAY;IAKpB;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IAwBxB;;OAEG;IACH,OAAO,CAAC,aAAa;IAoBrB;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IAqC3B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAkBzB;;OAEG;IACH,UAAU,IAAI,IAAI;CAInB;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,gBAAgB,GAAG,iBAAiB,CAEnF"}