@postplus/cli 0.1.33 → 0.1.35

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.
@@ -0,0 +1,307 @@
1
+ // Generated from the PostPlus Cloud hosted catalog release gate.
2
+ // Keep keys in sync with apps/web hosted capability and collection catalogs.
3
+ export const RESEARCH_COLLECTION_HINTS = {
4
+ 'amazon-asins': {
5
+ asins: ['B0C1234567'],
6
+ country: 'US',
7
+ },
8
+ 'amazon-bestsellers': {
9
+ categoryUrl: 'https://www.amazon.com/Best-Sellers/zgbs',
10
+ maxItems: 5,
11
+ },
12
+ 'amazon-free-products': {
13
+ keyword: 'portable blender',
14
+ maxItems: 5,
15
+ },
16
+ 'amazon-products': {
17
+ country: 'US',
18
+ keyword: 'portable blender',
19
+ maxItems: 5,
20
+ },
21
+ 'amazon-reviews': {
22
+ asin: 'B0C1234567',
23
+ country: 'US',
24
+ maxReviews: 10,
25
+ },
26
+ 'amazon-reviews-v2': {
27
+ asin: 'B0C1234567',
28
+ domainCode: 'com',
29
+ maxReviews: 10,
30
+ },
31
+ 'google-trends-fast': {
32
+ queries: ['portable blender'],
33
+ },
34
+ 'instagram-comments': {
35
+ directUrls: ['https://www.instagram.com/p/example/'],
36
+ resultsLimit: 5,
37
+ },
38
+ 'instagram-email-search': {
39
+ Country: 'www',
40
+ Email_Type: '0',
41
+ Keyword: 'skincare creator',
42
+ Limit: '10',
43
+ social_network: 'instagram.com/',
44
+ },
45
+ 'instagram-hashtags': {
46
+ hashtags: ['desksetup'],
47
+ resultsLimit: 3,
48
+ },
49
+ 'instagram-posts': {
50
+ resultsLimit: 3,
51
+ username: ['openai'],
52
+ },
53
+ 'instagram-profiles': {
54
+ resultsLimit: 3,
55
+ usernames: ['instagram'],
56
+ },
57
+ 'instagram-search': {
58
+ searchLimit: 3,
59
+ searchTerms: ['skincare routine'],
60
+ searchType: 'user',
61
+ },
62
+ 'tiktok-ads-top': {
63
+ include_analytics: true,
64
+ limit: 1,
65
+ },
66
+ 'tiktok-comments': {
67
+ postURLs: ['https://www.tiktok.com/@example/video/1234567890'],
68
+ resultsPerPage: 5,
69
+ },
70
+ 'tiktok-profiles': {
71
+ usernames: ['tiktok'],
72
+ },
73
+ 'tiktok-related-videos': {
74
+ maxItems: 3,
75
+ postURLs: ['https://www.tiktok.com/@example/video/1234567890'],
76
+ },
77
+ 'tiktok-users': {
78
+ maxItems: 5,
79
+ searchQueries: ['skincare creator'],
80
+ },
81
+ 'tiktok-videos': {
82
+ maxItems: 3,
83
+ proxyCountryCode: 'US',
84
+ queries: ['portable blender'],
85
+ searchSection: '/video',
86
+ },
87
+ 'youtube-channel-summary': {
88
+ channels: ['@Google'],
89
+ includeChannelInfo: true,
90
+ includeVideos: false,
91
+ maxVideosPerChannel: 0,
92
+ },
93
+ 'youtube-comments': {
94
+ maxComments: 10,
95
+ startUrls: ['https://www.youtube.com/watch?v=dQw4w9WgXcQ'],
96
+ },
97
+ 'youtube-video-download': {
98
+ urls: ['https://www.youtube.com/watch?v=dQw4w9WgXcQ'],
99
+ },
100
+ 'x-posts': {
101
+ maxItems: 5,
102
+ searchTerms: ['product launch'],
103
+ },
104
+ 'x-profiles': {
105
+ handles: ['OpenAI'],
106
+ },
107
+ };
108
+ export const PUBLIC_CONTENT_SOURCE_HINTS = {
109
+ 'facebook-group-posts': [
110
+ {
111
+ url: 'https://www.facebook.com/groups/example',
112
+ },
113
+ ],
114
+ 'facebook-post-by-url': [
115
+ {
116
+ url: 'https://www.facebook.com/openai/posts/example',
117
+ },
118
+ ],
119
+ 'facebook-profile-posts': [
120
+ {
121
+ url: 'https://www.facebook.com/openai',
122
+ },
123
+ ],
124
+ 'youtube-videos': [
125
+ {
126
+ url: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
127
+ },
128
+ ],
129
+ };
130
+ export const PUBLIC_CONTENT_DISCOVERY_TOOL_HINTS = {
131
+ 'web-search': {
132
+ limit: 5,
133
+ query: 'portable blender reviews',
134
+ },
135
+ };
136
+ export const MEDIA_ENDPOINT_HINTS = {
137
+ 'image-gpt-image-2-edit': {
138
+ inputUrls: ['https://example.com/reference-image.png'],
139
+ prompt: 'Edit the reference into a clean product-style vertical image.',
140
+ quality: 'medium',
141
+ size: '1024x1024',
142
+ },
143
+ 'image-gpt-image-2-text': {
144
+ aspect_ratio: '9:16',
145
+ prompt: 'A realistic vertical product image on a clean white desk.',
146
+ quality: 'medium',
147
+ size: '1024x1024',
148
+ },
149
+ 'image-nano-banana-2-edit': {
150
+ inputUrls: ['https://example.com/reference-image.png'],
151
+ prompt: 'Edit the reference into a clean product-style vertical image.',
152
+ quality: 'medium',
153
+ size: '1024x1024',
154
+ },
155
+ 'image-nano-banana-2-text': {
156
+ aspect_ratio: '9:16',
157
+ prompt: 'A realistic vertical product image on a clean white desk.',
158
+ quality: 'medium',
159
+ size: '1024x1024',
160
+ },
161
+ 'image-nano-banana-pro-edit-1k': {
162
+ inputUrls: ['https://example.com/reference-image.png'],
163
+ prompt: 'Edit the reference into a clean product-style vertical image.',
164
+ resolution: '1k',
165
+ },
166
+ 'image-nano-banana-pro-edit-2k': {
167
+ inputUrls: ['https://example.com/reference-image.png'],
168
+ prompt: 'Edit the reference into a clean product-style vertical image.',
169
+ resolution: '2k',
170
+ },
171
+ 'image-nano-banana-pro-edit-4k': {
172
+ inputUrls: ['https://example.com/reference-image.png'],
173
+ prompt: 'Edit the reference into a clean product-style vertical image.',
174
+ resolution: '4k',
175
+ },
176
+ 'image-nano-banana-pro-text-1k': {
177
+ aspect_ratio: '9:16',
178
+ prompt: 'A realistic vertical product image on a clean white desk.',
179
+ resolution: '1k',
180
+ },
181
+ 'image-nano-banana-pro-text-2k': {
182
+ aspect_ratio: '9:16',
183
+ prompt: 'A realistic vertical product image on a clean white desk.',
184
+ resolution: '2k',
185
+ },
186
+ 'image-nano-banana-pro-text-4k': {
187
+ aspect_ratio: '9:16',
188
+ prompt: 'A realistic vertical product image on a clean white desk.',
189
+ resolution: '4k',
190
+ },
191
+ 'image-seedream-v5-lite-edit': {
192
+ inputUrls: ['https://example.com/reference-image.png'],
193
+ prompt: 'Edit the reference into a clean product-style vertical image.',
194
+ size: '1024x1024',
195
+ },
196
+ 'image-seedream-v5-lite-edit-sequential': {
197
+ inputUrls: ['https://example.com/reference-image.png'],
198
+ prompt: 'Create a coherent sequence of edited product reference images.',
199
+ size: '1024x1024',
200
+ },
201
+ 'image-seedream-v5-lite-sequential': {
202
+ aspect_ratio: '9:16',
203
+ prompt: 'Create a coherent sequence of vertical product images.',
204
+ size: '1024x1024',
205
+ },
206
+ 'image-seedream-v5-lite-text': {
207
+ aspect_ratio: '9:16',
208
+ prompt: 'A realistic vertical product image on a clean white desk.',
209
+ size: '1024x1024',
210
+ },
211
+ 'transcription-whisper': {
212
+ audio: 'https://example.com/input-audio.mp3',
213
+ language: 'en',
214
+ response_format: 'verbose_json',
215
+ timestamp_granularities: ['segment'],
216
+ },
217
+ 'transcription-whisper-turbo': {
218
+ audio: 'https://example.com/input-audio.mp3',
219
+ language: 'en',
220
+ response_format: 'verbose_json',
221
+ timestamp_granularities: ['segment'],
222
+ },
223
+ 'transcription-whisper-with-video': {
224
+ language: 'en',
225
+ response_format: 'verbose_json',
226
+ timestamp_granularities: ['segment'],
227
+ video: 'https://example.com/input-video.mp4',
228
+ },
229
+ 'video-infinitetalk': {
230
+ audio: 'https://example.com/voiceover.wav',
231
+ image: 'https://example.com/persona.png',
232
+ prompt: 'Talking-head delivery in a natural vertical social ad style.',
233
+ },
234
+ 'video-kling-v2-6-pro-motion-control': {
235
+ character_orientation: 'image',
236
+ image: 'https://example.com/subject.png',
237
+ video: 'https://example.com/reference-motion.mp4',
238
+ },
239
+ 'video-kling-v3-0-pro-image': {
240
+ duration: 5,
241
+ image: 'https://example.com/start-frame.png',
242
+ prompt: 'Animate the product in a clean realistic vertical scene.',
243
+ sound: false,
244
+ },
245
+ 'video-kling-v3-0-pro-text': {
246
+ aspect_ratio: '9:16',
247
+ duration: 5,
248
+ prompt: 'A realistic vertical short-form product reveal.',
249
+ sound: false,
250
+ },
251
+ 'video-kling-v3-0-std-image': {
252
+ duration: 5,
253
+ image: 'https://example.com/start-frame.png',
254
+ prompt: 'Animate the product in a clean realistic vertical scene.',
255
+ sound: false,
256
+ },
257
+ 'video-kling-v3-0-std-text': {
258
+ aspect_ratio: '9:16',
259
+ duration: 5,
260
+ prompt: 'A realistic vertical short-form product reveal.',
261
+ sound: false,
262
+ },
263
+ 'video-seedance-2-image': {
264
+ duration: 5,
265
+ image: 'https://example.com/start-frame.png',
266
+ prompt: 'A realistic vertical short-form product reveal.',
267
+ resolution: '720p',
268
+ },
269
+ 'video-seedance-2-image-turbo': {
270
+ duration: 5,
271
+ image: 'https://example.com/start-frame.png',
272
+ prompt: 'A realistic vertical short-form product reveal.',
273
+ resolution: '720p',
274
+ },
275
+ 'video-seedance-2-text': {
276
+ duration: 5,
277
+ prompt: 'A realistic vertical short-form product reveal.',
278
+ resolution: '720p',
279
+ },
280
+ 'video-seedance-2-text-turbo': {
281
+ duration: 5,
282
+ prompt: 'A realistic vertical short-form product reveal.',
283
+ resolution: '720p',
284
+ },
285
+ 'voice-qwen3-clone': {
286
+ reference_audio: 'https://example.com/reference-voice.wav',
287
+ text: 'Short voiceover line to synthesize.',
288
+ },
289
+ 'voice-qwen3-design': {
290
+ language: 'en',
291
+ text: 'Short voiceover line to synthesize.',
292
+ voiceDescription: 'Warm, clear, natural creator voice.',
293
+ },
294
+ };
295
+ export const VIDEO_ANALYSIS_MODEL_HINTS = {
296
+ 'gemini-video-analysis': {
297
+ contents: [
298
+ {
299
+ parts: [
300
+ {
301
+ text: 'Analyze this short video and return concise creative observations.',
302
+ },
303
+ ],
304
+ },
305
+ ],
306
+ },
307
+ };
package/build/index.js CHANGED
@@ -1,18 +1,20 @@
1
1
  #!/usr/bin/env node
2
2
  import { readFile } from 'node:fs/promises';
3
+ import { formatAccountBindingLines } from './account-binding-display.js';
3
4
  import { formatAuthRefreshReport, refreshRemoteAuth, revokeRemoteAuthAndReport, } from './auth-lifecycle.js';
4
5
  import { loginWithCloudHandoff } from './auth-login.js';
5
6
  import { formatAuthValidateReport, validateRemoteAuth, } from './auth-validate.js';
6
7
  import { clearAuthState, formatAuthStatusReport, generateAuthStatusReport, } from './auth.js';
7
8
  import { readCurrentCliVersion } from './client-compatibility.js';
8
9
  import { formatDoctorReport, generateDoctorReport } from './doctor.js';
10
+ import { runHostedDomainCommand } from './hosted-domain-commands.js';
9
11
  import { assertConfigFilePermissions } from './local-state.js';
10
12
  import { readLargeCreditQuoteConfirmationChallenge, resolveLargeCreditQuoteConfirmation, } from './quote-confirmation.js';
11
- import { POSTPLUS_SKILLS_CURRENT_DIRECTORY_INSTALL_COMMAND, POSTPLUS_SKILLS_INSTALL_COMMAND, loadPublicSkillCatalog, formatPostPlusSkillsInstallCommand, } from './skill-catalog.js';
13
+ import { POSTPLUS_SKILLS_CURRENT_DIRECTORY_INSTALL_COMMAND, POSTPLUS_SKILLS_INSTALL_COMMAND, formatPostPlusSkillsInstallCommand, loadPublicSkillCatalog, } from './skill-catalog.js';
12
14
  import { formatSkillBaselineVerifyReport, runPostPlusSkillUninstall, runPostPlusSkillUpdate, runPostPlusSkillVerify, } from './skill-management.js';
13
15
  import { formatStatusReport, generateStatusReport } from './status.js';
14
- import { refreshUpdateCheckCache, runCliSelfUpdateIfOutdated, } from './update-check.js';
15
16
  import { runStudioCommand } from './studio.js';
17
+ import { refreshUpdateCheckCache, runCliSelfUpdateIfOutdated, } from './update-check.js';
16
18
  function printAuthHelp() {
17
19
  process.stdout.write(`PostPlus CLI — auth commands
18
20
 
@@ -41,6 +43,14 @@ Usage:
41
43
  postplus auth validate [--json]
42
44
  postplus auth logout [--json]
43
45
  postplus doctor [--skill <skill-id>] [--json]
46
+ postplus research schema [--collection-key <key>] [--json]
47
+ postplus research collect --skill <skill-id> --collection-key <key> --input <hosted-envelope.json> [--output <result.json>]
48
+ postplus media schema [--endpoint <endpoint-key>] [--json]
49
+ postplus media capability --request <hosted-capability-request.json> [--output <result.json>]
50
+ postplus publish schema [--json]
51
+ postplus publish capability --request <hosted-capability-request.json> [--output <result.json>]
52
+ postplus mobile schema [--json]
53
+ postplus mobile capability --request <hosted-capability-request.json> [--output <result.json>]
44
54
  postplus quote confirm --json --challenge-file <path>
45
55
  postplus skills verify [--json]
46
56
  postplus studio init|open|status Open bundled Local Studio
@@ -228,6 +238,9 @@ function parseQuoteConfirmOptions(args) {
228
238
  function writeJson(value) {
229
239
  process.stdout.write(`${JSON.stringify(value, null, 2)}\n`);
230
240
  }
241
+ function isHelpArg(value) {
242
+ return value === 'help' || value === '--help' || value === '-h';
243
+ }
231
244
  function parseDiagnosticOptions(args) {
232
245
  const options = {
233
246
  json: false,
@@ -297,7 +310,7 @@ async function runAuthLogin() {
297
310
  process.stdout.write([
298
311
  '',
299
312
  'PostPlus CLI login complete.',
300
- `Account: ${report.accountId}`,
313
+ ...formatAccountBindingLines(report),
301
314
  `PostPlus Cloud: ${report.apiBaseUrl}`,
302
315
  `User: ${report.userEmail ?? 'unknown'}`,
303
316
  '',
@@ -350,6 +363,18 @@ async function main() {
350
363
  case 'doctor':
351
364
  process.exitCode = await runDoctor(parseDiagnosticOptions(rest));
352
365
  return;
366
+ case 'research':
367
+ process.exitCode = await runHostedDomainCommand('research', rest);
368
+ return;
369
+ case 'media':
370
+ process.exitCode = await runHostedDomainCommand('media', rest);
371
+ return;
372
+ case 'publish':
373
+ process.exitCode = await runHostedDomainCommand('publish', rest);
374
+ return;
375
+ case 'mobile':
376
+ process.exitCode = await runHostedDomainCommand('mobile', rest);
377
+ return;
353
378
  case 'quote':
354
379
  process.exitCode = await runQuoteCommand(rest);
355
380
  return;
@@ -379,6 +404,17 @@ async function main() {
379
404
  const [subcommand, ...authRest] = rest;
380
405
  switch (subcommand) {
381
406
  case 'login':
407
+ if (authRest.some(isHelpArg)) {
408
+ printAuthHelp();
409
+ process.exitCode = 0;
410
+ return;
411
+ }
412
+ if (authRest.length > 0) {
413
+ process.stderr.write(`Unknown auth login option: ${authRest[0]}\n\n`);
414
+ printAuthHelp();
415
+ process.exitCode = 1;
416
+ return;
417
+ }
382
418
  process.exitCode = await runAuthLogin();
383
419
  return;
384
420
  case 'refresh':
@@ -94,6 +94,9 @@ export async function clearLocalAuthState() {
94
94
  };
95
95
  delete next.accessToken;
96
96
  delete next.accountId;
97
+ delete next.accountName;
98
+ delete next.accountSlug;
99
+ delete next.accountType;
97
100
  delete next.apiKey;
98
101
  delete next.cliSessionToken;
99
102
  delete next.machineId;
@@ -162,6 +165,9 @@ export async function setLocalSession(input) {
162
165
  return updateLocalConfig((current) => ({
163
166
  ...omitLegacyAuthFields(current),
164
167
  accountId: input.accountId,
168
+ accountName: input.accountName ?? null,
169
+ accountSlug: input.accountSlug ?? null,
170
+ accountType: input.accountType ?? null,
165
171
  apiBaseUrl,
166
172
  cliSessionToken,
167
173
  sessionExpiresAt: input.sessionExpiresAt,
@@ -16,7 +16,6 @@ const POSTPLUS_SKILLS_AGENT_ARGS = POSTPLUS_SKILLS_AGENT_TARGETS.join(' ');
16
16
  export const POSTPLUS_SKILLS_INSTALL_COMMAND = formatPostPlusSkillsInstallCommand();
17
17
  export const POSTPLUS_SKILLS_CURRENT_DIRECTORY_INSTALL_COMMAND = formatPostPlusSkillsInstallCommand(POSTPLUS_SKILLS_REPO, 'current-directory');
18
18
  export const POSTPLUS_SKILLS_LIST_COMMAND = formatPostPlusSkillsListCommand();
19
- const POSTPLUS_SKILLS_INDEX_URL = 'https://raw.githubusercontent.com/PostPlusAI/postplus-skills/main/skills/INDEX.md';
20
19
  const POSTPLUS_SKILLS_CATALOG_URL = 'https://raw.githubusercontent.com/PostPlusAI/postplus-skills/main/skills/catalog.json';
21
20
  export const PUBLIC_SKILL_REQUIREMENT_KEYS = [
22
21
  'accountConnections',
@@ -45,7 +44,6 @@ export async function loadPublicSkillCatalog(fetchFn = fetch, env = process.env)
45
44
  return {
46
45
  ...catalog,
47
46
  catalogUrl,
48
- indexUrl: POSTPLUS_SKILLS_INDEX_URL,
49
47
  installCommand: formatPostPlusSkillsInstallCommand(skillsSource),
50
48
  listCommand: formatPostPlusSkillsListCommand(skillsSource),
51
49
  source: skillsSource,
@@ -59,7 +57,7 @@ export function resolvePostPlusSkillsCatalogUrl(env = process.env) {
59
57
  }
60
58
  export function formatPostPlusSkillsInstallCommand(source = POSTPLUS_SKILLS_REPO, scope = 'global') {
61
59
  const scopeArgs = scope === 'global' ? ' --global' : '';
62
- return `npx -y skills add ${source}${scopeArgs} --full-depth --skill '*' --agent ${POSTPLUS_SKILLS_AGENT_ARGS} --yes`;
60
+ return `for agent in ${POSTPLUS_SKILLS_AGENT_ARGS}; do npx -y skills add ${source}${scopeArgs} --full-depth --skill '*' --agent "$agent" --yes; done`;
63
61
  }
64
62
  export function formatPostPlusSkillsListCommand(source = POSTPLUS_SKILLS_REPO) {
65
63
  return `npx -y skills add ${source} --list --full-depth`;
@@ -17,14 +17,18 @@ export async function runPostPlusSkillUpdate(dependencies = {
17
17
  if (skillNames.length === 0) {
18
18
  throw new Error('PostPlus public skill catalog has no released skills.');
19
19
  }
20
- const updateExitCode = await dependencies.runInteractiveCommand('npx', buildPostPlusSkillUpdateArgs(skillNames, options.scope));
21
- if (updateExitCode !== 0) {
22
- return updateExitCode;
20
+ for (const agentTarget of POSTPLUS_SKILLS_AGENT_TARGETS) {
21
+ const updateExitCode = await dependencies.runInteractiveCommand('npx', buildPostPlusSkillUpdateArgs(skillNames, options.scope, agentTarget));
22
+ if (updateExitCode !== 0) {
23
+ return updateExitCode;
24
+ }
23
25
  }
24
26
  if (retiredSkillNames.length > 0) {
25
- const removeExitCode = await dependencies.runInteractiveCommand('npx', buildPostPlusSkillUninstallArgs(retiredSkillNames, options.scope));
26
- if (removeExitCode !== 0) {
27
- return removeExitCode;
27
+ for (const agentTarget of POSTPLUS_SKILLS_AGENT_TARGETS) {
28
+ const removeExitCode = await dependencies.runInteractiveCommand('npx', buildPostPlusSkillUninstallArgs(retiredSkillNames, options.scope, agentTarget));
29
+ if (removeExitCode !== 0) {
30
+ return removeExitCode;
31
+ }
28
32
  }
29
33
  }
30
34
  await writeManagedSkillBaseline({
@@ -45,17 +49,20 @@ export async function runPostPlusSkillUninstall(dependencies = {
45
49
  if (allKnownSkillNames.length === 0) {
46
50
  throw new Error('PostPlus public skill catalog has no released skills.');
47
51
  }
48
- const exitCode = await dependencies.runInteractiveCommand('npx', buildPostPlusSkillUninstallArgs(allKnownSkillNames, options.scope));
49
- if (exitCode === 0) {
50
- await clearManagedSkillBaseline();
51
- await clearUpdateCheckCache();
52
+ for (const agentTarget of POSTPLUS_SKILLS_AGENT_TARGETS) {
53
+ const exitCode = await dependencies.runInteractiveCommand('npx', buildPostPlusSkillUninstallArgs(allKnownSkillNames, options.scope, agentTarget));
54
+ if (exitCode !== 0) {
55
+ return exitCode;
56
+ }
52
57
  }
53
- return exitCode;
58
+ await clearManagedSkillBaseline();
59
+ await clearUpdateCheckCache();
60
+ return 0;
54
61
  }
55
62
  export async function generateSkillInstallStatusReport(dependencies = {
56
63
  runCommand,
57
- }) {
58
- return (await inspectPostPlusSkillInstall(dependencies)).report;
64
+ }, options = {}) {
65
+ return (await inspectPostPlusSkillInstall(dependencies, options)).report;
59
66
  }
60
67
  export async function runPostPlusSkillVerify(dependencies = {
61
68
  runCommand,
@@ -84,7 +91,7 @@ export async function runPostPlusSkillVerify(dependencies = {
84
91
  verifiedSkillsReleaseId: inspection.catalog.releaseId,
85
92
  };
86
93
  }
87
- async function inspectPostPlusSkillInstall(dependencies) {
94
+ async function inspectPostPlusSkillInstall(dependencies, options = {}) {
88
95
  const catalog = await loadPublicSkillCatalog();
89
96
  const requiredSkillNames = catalog.skills.map((skill) => skill.skillId);
90
97
  const requiredSkills = new Set(requiredSkillNames);
@@ -95,6 +102,24 @@ async function inspectPostPlusSkillInstall(dependencies) {
95
102
  const postPlusInstalled = installed.filter((skill) => requiredSkills.has(skill.name));
96
103
  const installedNames = new Set(postPlusInstalled.map((skill) => skill.name));
97
104
  const missingSkills = [...requiredSkills].filter((skill) => !installedNames.has(skill));
105
+ let managedSkillsReleaseId = baseline.releaseId;
106
+ let currentRetiredManagedSkills = retiredManagedSkills;
107
+ if (options.repairManagedBaseline === true &&
108
+ missingSkills.length === 0 &&
109
+ shouldRepairManagedBaseline({
110
+ baseline,
111
+ releaseId: catalog.releaseId,
112
+ skillNames: requiredSkillNames,
113
+ })) {
114
+ await writeManagedSkillBaseline({
115
+ releaseId: catalog.releaseId,
116
+ skillNames: requiredSkillNames,
117
+ });
118
+ await writeCurrentCliVersionToLocalConfig();
119
+ await clearUpdateCheckCache();
120
+ managedSkillsReleaseId = catalog.releaseId;
121
+ currentRetiredManagedSkills = [];
122
+ }
98
123
  const scopes = [
99
124
  ...new Set(postPlusInstalled
100
125
  .map((skill) => skill.scope)
@@ -107,10 +132,10 @@ async function inspectPostPlusSkillInstall(dependencies) {
107
132
  error: null,
108
133
  installCommand: formatPostPlusSkillsInstallCommand(catalog.source),
109
134
  installedCount: installedNames.size,
110
- managedSkillsReleaseId: baseline.releaseId,
135
+ managedSkillsReleaseId,
111
136
  missingSkills,
112
137
  requiredCount: requiredSkills.size,
113
- retiredManagedSkills,
138
+ retiredManagedSkills: currentRetiredManagedSkills,
114
139
  scopes,
115
140
  source: catalog.source,
116
141
  updateCommand: formatPostPlusSkillUpdateCommand(),
@@ -192,7 +217,7 @@ export function formatSkillBaselineVerifyReport(report) {
192
217
  }
193
218
  return lines.join('\n');
194
219
  }
195
- export function buildPostPlusSkillUpdateArgs(skillNames, scope = 'global') {
220
+ export function buildPostPlusSkillUpdateArgs(skillNames, scope = 'global', agentTarget) {
196
221
  if (skillNames.length === 0) {
197
222
  throw new Error('PostPlus public skill catalog has no released skills.');
198
223
  }
@@ -206,18 +231,18 @@ export function buildPostPlusSkillUpdateArgs(skillNames, scope = 'global') {
206
231
  '--skill',
207
232
  '*',
208
233
  '--agent',
209
- ...POSTPLUS_SKILLS_AGENT_TARGETS,
234
+ ...(agentTarget ? [agentTarget] : POSTPLUS_SKILLS_AGENT_TARGETS),
210
235
  '--yes',
211
236
  ];
212
237
  }
213
- export function buildPostPlusSkillUninstallArgs(skillNames, scope = 'global') {
238
+ export function buildPostPlusSkillUninstallArgs(skillNames, scope = 'global', agentTarget) {
214
239
  return [
215
240
  ...NPX_SKILLS,
216
241
  'remove',
217
242
  ...skillNames,
218
243
  ...buildSkillScopeArgs(scope),
219
244
  '--agent',
220
- ...POSTPLUS_SKILLS_AGENT_TARGETS,
245
+ ...(agentTarget ? [agentTarget] : POSTPLUS_SKILLS_AGENT_TARGETS),
221
246
  '--yes',
222
247
  ];
223
248
  }
@@ -237,6 +262,18 @@ function buildSkillScopeArgs(scope) {
237
262
  function mergeSkillNames(left, right) {
238
263
  return [...new Set([...left, ...right])].sort((a, b) => a.localeCompare(b));
239
264
  }
265
+ function shouldRepairManagedBaseline(input) {
266
+ if (input.baseline.releaseId !== input.releaseId) {
267
+ return true;
268
+ }
269
+ return !haveSameSkillNames(input.baseline.skillNames, input.skillNames);
270
+ }
271
+ function haveSameSkillNames(left, right) {
272
+ const normalizedLeft = mergeSkillNames(left, []);
273
+ const normalizedRight = mergeSkillNames(right, []);
274
+ return (normalizedLeft.length === normalizedRight.length &&
275
+ normalizedLeft.every((value, index) => value === normalizedRight[index]));
276
+ }
240
277
  async function listInstalledSkills(dependencies) {
241
278
  const project = await listInstalledSkillsForScope(dependencies, []);
242
279
  const global = await listInstalledSkillsForScope(dependencies, ['--global']);
package/build/status.js CHANGED
@@ -10,12 +10,15 @@ export async function generateStatusReportWithDependencies(dependencies = {}, op
10
10
  await writeCurrentCliVersionToLocalConfig();
11
11
  const generateAuthStatus = dependencies.generateAuthStatus ?? generateAuthStatusReport;
12
12
  const generateDoctor = dependencies.generateDoctor ?? generateDoctorReport;
13
- const generateSkillStatus = dependencies.generateSkillStatus ?? generateSkillInstallStatusReport;
13
+ const generateSkillStatus = dependencies.generateSkillStatus ??
14
+ (() => generateSkillInstallStatusReport(undefined, {
15
+ repairManagedBaseline: true,
16
+ }));
14
17
  const generateUpdateStatus = dependencies.generateUpdateStatus ?? generateUpdateStatusReport;
15
- const [doctor, auth, skills, updates] = await Promise.all([
18
+ const skills = await generateSkillStatus();
19
+ const [doctor, auth, updates] = await Promise.all([
16
20
  generateDoctor({ skillId: options.skillId }),
17
21
  generateAuthStatus(),
18
- generateSkillStatus(),
19
22
  generateUpdateStatus(),
20
23
  ]);
21
24
  return {
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "@postplus/cli",
3
- "version": "0.1.33",
3
+ "version": "0.1.35",
4
4
  "packageManager": "pnpm@10.30.3+sha512.c961d1e0a2d8e354ecaa5166b822516668b7f44cb5bd95122d590dd81922f606f5473b6d23ec4a5be05e7fcd18e8488d47d978bbe981872f1145d06e9a740017",
5
5
  "type": "module",
6
6
  "description": "PostPlus CLI for PostPlus Cloud auth, status, and diagnostics.",
7
7
  "license": "SEE LICENSE IN LICENSE",
8
8
  "files": [
9
+ "build/account-binding-display.js",
9
10
  "build/auth-lifecycle.js",
10
11
  "build/auth-login.js",
11
12
  "build/auth-session.js",
@@ -14,7 +15,10 @@
14
15
  "build/client-compatibility.js",
15
16
  "build/command-runner.js",
16
17
  "build/doctor.js",
18
+ "build/hosted-domain-commands.js",
17
19
  "build/hosted-release.js",
20
+ "build/hosted-schema-catalog.js",
21
+ "build/hosted-request-schemas.js",
18
22
  "build/index.js",
19
23
  "build/local-dependencies.js",
20
24
  "build/local-state.js",
@@ -41,7 +45,7 @@
41
45
  "postplus": "build/index.js"
42
46
  },
43
47
  "scripts": {
44
- "build": "node ./scripts/clean-build.mjs && tsc",
48
+ "build": "node ./scripts/clean-build.mjs && tsc && node ./scripts/finalize-build.mjs",
45
49
  "clean": "rm -rf .turbo node_modules build",
46
50
  "release:package": "node ./scripts/package-release.mjs",
47
51
  "start": "tsx src/index.ts",