@postplus/cli 0.1.37 → 0.1.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/hosted-schema-catalog.js +0 -34
- package/build/index.js +51 -3
- package/build/quote-confirmation.js +78 -1
- package/package.json +1 -1
|
@@ -1,33 +1,6 @@
|
|
|
1
1
|
// Generated from the PostPlus Cloud hosted catalog release gate.
|
|
2
2
|
// Keep keys in sync with apps/web hosted capability and collection catalogs.
|
|
3
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
4
|
'google-trends-fast': {
|
|
32
5
|
queries: ['portable blender'],
|
|
33
6
|
},
|
|
@@ -97,13 +70,6 @@ export const RESEARCH_COLLECTION_HINTS = {
|
|
|
97
70
|
'youtube-video-download': {
|
|
98
71
|
urls: ['https://www.youtube.com/watch?v=dQw4w9WgXcQ'],
|
|
99
72
|
},
|
|
100
|
-
'x-posts': {
|
|
101
|
-
maxItems: 5,
|
|
102
|
-
searchTerms: ['product launch'],
|
|
103
|
-
},
|
|
104
|
-
'x-profiles': {
|
|
105
|
-
handles: ['OpenAI'],
|
|
106
|
-
},
|
|
107
73
|
};
|
|
108
74
|
export const PUBLIC_CONTENT_SOURCE_HINTS = {
|
|
109
75
|
'facebook-group-posts': [
|
package/build/index.js
CHANGED
|
@@ -9,7 +9,7 @@ import { readCurrentCliVersion } from './client-compatibility.js';
|
|
|
9
9
|
import { formatDoctorReport, generateDoctorReport } from './doctor.js';
|
|
10
10
|
import { runHostedDomainCommand } from './hosted-domain-commands.js';
|
|
11
11
|
import { assertConfigFilePermissions } from './local-state.js';
|
|
12
|
-
import { readLargeCreditQuoteConfirmationChallenge, resolveLargeCreditQuoteConfirmation, } from './quote-confirmation.js';
|
|
12
|
+
import { QUOTE_AUTO_CONFIRM_UNDER_ENV, QuoteAutoConfirmCeilingExceededError, QuoteConfirmationNonInteractiveError, confirmLargeCreditQuote, readLargeCreditQuoteConfirmationChallenge, resolveLargeCreditQuoteConfirmation, } from './quote-confirmation.js';
|
|
13
13
|
import { POSTPLUS_SKILLS_CURRENT_DIRECTORY_INSTALL_COMMAND, POSTPLUS_SKILLS_INSTALL_COMMAND, formatPostPlusSkillsInstallCommand, loadPublicSkillCatalog, } from './skill-catalog.js';
|
|
14
14
|
import { formatSkillBaselineVerifyReport, runPostPlusSkillUninstall, runPostPlusSkillUpdate, runPostPlusSkillVerify, } from './skill-management.js';
|
|
15
15
|
import { formatStatusReport, generateStatusReport } from './status.js';
|
|
@@ -51,7 +51,7 @@ Usage:
|
|
|
51
51
|
postplus publish capability --request <hosted-capability-request.json> [--output <result.json>]
|
|
52
52
|
postplus mobile schema [--json]
|
|
53
53
|
postplus mobile capability --request <hosted-capability-request.json> [--output <result.json>]
|
|
54
|
-
postplus quote confirm --json --challenge-file <path>
|
|
54
|
+
postplus quote confirm --json --challenge-file <path> [--auto-confirm-under <millicredits>]
|
|
55
55
|
postplus skills verify [--json]
|
|
56
56
|
postplus studio init|open|status Open bundled Local Studio
|
|
57
57
|
postplus update [--current-directory]
|
|
@@ -208,11 +208,46 @@ async function runQuoteCommand(rest) {
|
|
|
208
208
|
process.stderr.write('Invalid large credit quote confirmation challenge.\n');
|
|
209
209
|
return 1;
|
|
210
210
|
}
|
|
211
|
-
|
|
211
|
+
const ceilingMillicredits = resolveQuoteAutoConfirmCeiling(parsed.autoConfirmUnder);
|
|
212
|
+
try {
|
|
213
|
+
writeJson(await resolveLargeCreditQuoteConfirmation(challenge, {
|
|
214
|
+
confirm: confirmLargeCreditQuote,
|
|
215
|
+
ceilingMillicredits,
|
|
216
|
+
}));
|
|
217
|
+
}
|
|
218
|
+
catch (error) {
|
|
219
|
+
if (error instanceof QuoteAutoConfirmCeilingExceededError ||
|
|
220
|
+
error instanceof QuoteConfirmationNonInteractiveError) {
|
|
221
|
+
process.stderr.write(`${error.message}\n`);
|
|
222
|
+
return 1;
|
|
223
|
+
}
|
|
224
|
+
throw error;
|
|
225
|
+
}
|
|
212
226
|
return 0;
|
|
213
227
|
}
|
|
228
|
+
/**
|
|
229
|
+
* Resolves the bounded auto-confirm ceiling in millicredits. Precedence:
|
|
230
|
+
* explicit --auto-confirm-under flag, then the
|
|
231
|
+
* POSTPLUS_QUOTE_AUTO_CONFIRM_UNDER_MILLICREDITS env var. Returns null when
|
|
232
|
+
* neither is set, leaving today's interactive behavior unchanged.
|
|
233
|
+
*/
|
|
234
|
+
function resolveQuoteAutoConfirmCeiling(flagValue) {
|
|
235
|
+
if (flagValue !== null) {
|
|
236
|
+
return flagValue;
|
|
237
|
+
}
|
|
238
|
+
const envValue = process.env[QUOTE_AUTO_CONFIRM_UNDER_ENV];
|
|
239
|
+
if (envValue === undefined || envValue.trim() === '') {
|
|
240
|
+
return null;
|
|
241
|
+
}
|
|
242
|
+
const parsed = Number(envValue);
|
|
243
|
+
if (!Number.isFinite(parsed) || parsed < 0) {
|
|
244
|
+
throw new Error(`Invalid ${QUOTE_AUTO_CONFIRM_UNDER_ENV}: expected a non-negative number of millicredits.`);
|
|
245
|
+
}
|
|
246
|
+
return parsed;
|
|
247
|
+
}
|
|
214
248
|
function parseQuoteConfirmOptions(args) {
|
|
215
249
|
const options = {
|
|
250
|
+
autoConfirmUnder: null,
|
|
216
251
|
challengeFile: null,
|
|
217
252
|
json: false,
|
|
218
253
|
};
|
|
@@ -231,6 +266,19 @@ function parseQuoteConfirmOptions(args) {
|
|
|
231
266
|
index += 1;
|
|
232
267
|
continue;
|
|
233
268
|
}
|
|
269
|
+
if (arg === '--auto-confirm-under') {
|
|
270
|
+
const rawValue = args[index + 1];
|
|
271
|
+
if (!rawValue || rawValue.startsWith('--')) {
|
|
272
|
+
throw new Error('Missing value for --auto-confirm-under.');
|
|
273
|
+
}
|
|
274
|
+
const value = Number(rawValue);
|
|
275
|
+
if (!Number.isFinite(value) || value < 0) {
|
|
276
|
+
throw new Error('Invalid value for --auto-confirm-under: expected a non-negative number of millicredits.');
|
|
277
|
+
}
|
|
278
|
+
options.autoConfirmUnder = value;
|
|
279
|
+
index += 1;
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
234
282
|
throw new Error(`Unknown option for quote confirm: ${arg}`);
|
|
235
283
|
}
|
|
236
284
|
return options;
|
|
@@ -1,6 +1,50 @@
|
|
|
1
1
|
import readline from 'node:readline/promises';
|
|
2
2
|
import { readLocalConfig, updateLocalConfig } from './local-state.js';
|
|
3
3
|
const PRODUCT_ERROR_CODE = 'postplus_cli_quote_confirmation_required';
|
|
4
|
+
export const QUOTE_AUTO_CONFIRM_CEILING_EXCEEDED_CODE = 'postplus_cli_quote_auto_confirm_ceiling_exceeded';
|
|
5
|
+
export const QUOTE_AUTO_CONFIRM_UNDER_ENV = 'POSTPLUS_QUOTE_AUTO_CONFIRM_UNDER_MILLICREDITS';
|
|
6
|
+
/**
|
|
7
|
+
* Thrown when a bounded auto-confirm ceiling is configured but the challenge
|
|
8
|
+
* cost exceeds it. Carries the original challenge so an orchestrator or human
|
|
9
|
+
* can confirm explicitly instead of the CLI hanging on a readline prompt.
|
|
10
|
+
*/
|
|
11
|
+
export class QuoteAutoConfirmCeilingExceededError extends Error {
|
|
12
|
+
code = QUOTE_AUTO_CONFIRM_CEILING_EXCEEDED_CODE;
|
|
13
|
+
challenge;
|
|
14
|
+
ceilingMillicredits;
|
|
15
|
+
costMillicredits;
|
|
16
|
+
constructor(input) {
|
|
17
|
+
super(`Quote cost ${input.costMillicredits} millicredits exceeds the ` +
|
|
18
|
+
`auto-confirm ceiling of ${input.ceilingMillicredits} millicredits. ` +
|
|
19
|
+
'Confirm explicitly or raise --auto-confirm-under / ' +
|
|
20
|
+
`${QUOTE_AUTO_CONFIRM_UNDER_ENV}.`);
|
|
21
|
+
this.name = 'QuoteAutoConfirmCeilingExceededError';
|
|
22
|
+
this.challenge = input.challenge;
|
|
23
|
+
this.ceilingMillicredits = input.ceilingMillicredits;
|
|
24
|
+
this.costMillicredits = input.costMillicredits;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Thrown when no auto-confirm ceiling is configured and stdin is not a TTY, so
|
|
29
|
+
* the interactive readline prompt would hang. Fails fast with an actionable
|
|
30
|
+
* message instead.
|
|
31
|
+
*/
|
|
32
|
+
export class QuoteConfirmationNonInteractiveError extends Error {
|
|
33
|
+
code = 'postplus_cli_quote_confirmation_non_interactive';
|
|
34
|
+
challenge;
|
|
35
|
+
constructor(challenge) {
|
|
36
|
+
super('Quote confirmation required but stdin is not a TTY and no auto-confirm ' +
|
|
37
|
+
'ceiling is configured. Pass --auto-confirm-under <millicredits>, set ' +
|
|
38
|
+
`${QUOTE_AUTO_CONFIRM_UNDER_ENV}, or run interactively.`);
|
|
39
|
+
this.name = 'QuoteConfirmationNonInteractiveError';
|
|
40
|
+
this.challenge = challenge;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function resolveChallengeCostMillicredits(challenge) {
|
|
44
|
+
return typeof challenge.estimatedMillicredits === 'number'
|
|
45
|
+
? challenge.estimatedMillicredits
|
|
46
|
+
: challenge.requiredTierMillicredits;
|
|
47
|
+
}
|
|
4
48
|
export function readLargeCreditQuoteConfirmationChallenge(value) {
|
|
5
49
|
if (!value || typeof value !== 'object') {
|
|
6
50
|
return null;
|
|
@@ -55,7 +99,7 @@ export async function resolveLargeCreditQuoteConfirmation(challenge, dependencie
|
|
|
55
99
|
}) {
|
|
56
100
|
const acknowledgedTierMillicredits = await readAcknowledgedTierMillicredits(challenge);
|
|
57
101
|
if (acknowledgedTierMillicredits < challenge.requiredTierMillicredits) {
|
|
58
|
-
await
|
|
102
|
+
await runQuoteConfirmation(challenge, dependencies);
|
|
59
103
|
await writeAcknowledgedTierMillicredits(challenge);
|
|
60
104
|
}
|
|
61
105
|
return {
|
|
@@ -63,6 +107,39 @@ export async function resolveLargeCreditQuoteConfirmation(challenge, dependencie
|
|
|
63
107
|
token: challenge.token,
|
|
64
108
|
};
|
|
65
109
|
}
|
|
110
|
+
async function runQuoteConfirmation(challenge, dependencies) {
|
|
111
|
+
const ceiling = dependencies.ceilingMillicredits;
|
|
112
|
+
if (typeof ceiling === 'number' && Number.isFinite(ceiling)) {
|
|
113
|
+
const cost = resolveChallengeCostMillicredits(challenge);
|
|
114
|
+
if (cost > ceiling) {
|
|
115
|
+
throw new QuoteAutoConfirmCeilingExceededError({
|
|
116
|
+
challenge,
|
|
117
|
+
ceilingMillicredits: ceiling,
|
|
118
|
+
costMillicredits: cost,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
const log = dependencies.logNotice ?? defaultLogNotice;
|
|
122
|
+
const now = (dependencies.now ?? (() => new Date()))();
|
|
123
|
+
log(JSON.stringify({
|
|
124
|
+
event: 'quote_auto_confirm',
|
|
125
|
+
timestamp: now.toISOString(),
|
|
126
|
+
accountId: challenge.accountId,
|
|
127
|
+
operationId: challenge.operationId,
|
|
128
|
+
costMillicredits: cost,
|
|
129
|
+
ceilingMillicredits: ceiling,
|
|
130
|
+
requiredTierMillicredits: challenge.requiredTierMillicredits,
|
|
131
|
+
}));
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
const isTty = dependencies.isTty ?? (() => Boolean(process.stdin.isTTY));
|
|
135
|
+
if (!isTty()) {
|
|
136
|
+
throw new QuoteConfirmationNonInteractiveError(challenge);
|
|
137
|
+
}
|
|
138
|
+
await dependencies.confirm(challenge);
|
|
139
|
+
}
|
|
140
|
+
function defaultLogNotice(line) {
|
|
141
|
+
process.stderr.write(`${line}\n`);
|
|
142
|
+
}
|
|
66
143
|
export async function confirmLargeCreditQuote(challenge) {
|
|
67
144
|
const terminal = readline.createInterface({
|
|
68
145
|
input: process.stdin,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@postplus/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.38",
|
|
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.",
|