@postplus/cli 0.1.7 → 0.1.8
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/README.md +2 -2
- package/build/doctor.js +118 -0
- package/build/skill-catalog.js +11 -2
- package/package.json +12 -3
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ Requires Node.js `>=20.10.0` and npm.
|
|
|
11
11
|
```bash
|
|
12
12
|
npm install -g @postplus/cli
|
|
13
13
|
postplus auth login
|
|
14
|
-
npx -y skills add PostPlusAI/postplus-skills --
|
|
14
|
+
npx -y skills add PostPlusAI/postplus-skills --skill '*' --agent claude-code codex cursor --yes
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
## Commands
|
|
@@ -30,5 +30,5 @@ npx -y skills add PostPlusAI/postplus-skills --all
|
|
|
30
30
|
installation commands. Use:
|
|
31
31
|
|
|
32
32
|
```bash
|
|
33
|
-
npx -y skills add PostPlusAI/postplus-skills --
|
|
33
|
+
npx -y skills add PostPlusAI/postplus-skills --skill '*' --agent claude-code codex cursor --yes
|
|
34
34
|
```
|
package/build/doctor.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { resolveHostedBaseUrl } from './hosted-release.js';
|
|
2
|
+
import { resolveAccessTokenState } from './local-state.js';
|
|
2
3
|
function createPass(id, label, detail) {
|
|
3
4
|
return {
|
|
4
5
|
id,
|
|
@@ -7,16 +8,133 @@ function createPass(id, label, detail) {
|
|
|
7
8
|
detail,
|
|
8
9
|
};
|
|
9
10
|
}
|
|
11
|
+
function createFail(id, label, detail, fix) {
|
|
12
|
+
return {
|
|
13
|
+
id,
|
|
14
|
+
label,
|
|
15
|
+
status: 'fail',
|
|
16
|
+
detail,
|
|
17
|
+
fix,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
10
20
|
export async function generateDoctorReport() {
|
|
11
21
|
const hostedBaseUrl = await resolveHostedBaseUrl();
|
|
12
22
|
const checks = [
|
|
13
23
|
createPass('hosted_base_url', 'PostPlus Cloud', `Using ${hostedBaseUrl ?? 'https://postplus.io'}`),
|
|
14
24
|
];
|
|
25
|
+
const accessToken = await resolveAccessTokenState();
|
|
26
|
+
if (!hostedBaseUrl) {
|
|
27
|
+
checks.push(createFail('remote_auth', 'Remote auth', 'PostPlus Cloud base URL could not be resolved.', 'Configure POSTPLUS_API_BASE_URL or run `postplus auth login`.'));
|
|
28
|
+
return buildDoctorReport(checks);
|
|
29
|
+
}
|
|
30
|
+
if (!accessToken.present || !accessToken.value) {
|
|
31
|
+
checks.push(createFail('remote_auth', 'Remote auth', 'No PostPlus CLI session is configured.', 'Run `postplus auth login`.'));
|
|
32
|
+
return buildDoctorReport(checks);
|
|
33
|
+
}
|
|
34
|
+
const authCheck = await checkRemoteAuth({
|
|
35
|
+
accessToken: accessToken.value,
|
|
36
|
+
hostedBaseUrl,
|
|
37
|
+
});
|
|
38
|
+
checks.push(authCheck);
|
|
39
|
+
if (authCheck.status === 'pass') {
|
|
40
|
+
checks.push(await checkHostedCapabilities({
|
|
41
|
+
accessToken: accessToken.value,
|
|
42
|
+
hostedBaseUrl,
|
|
43
|
+
}));
|
|
44
|
+
}
|
|
45
|
+
return buildDoctorReport(checks);
|
|
46
|
+
}
|
|
47
|
+
function buildDoctorReport(checks) {
|
|
15
48
|
return {
|
|
16
49
|
ok: checks.every((check) => check.status === 'pass'),
|
|
17
50
|
checks,
|
|
18
51
|
};
|
|
19
52
|
}
|
|
53
|
+
async function checkRemoteAuth(input) {
|
|
54
|
+
try {
|
|
55
|
+
const response = await fetch(`${input.hostedBaseUrl}/api/postplus-cli/auth/whoami`, {
|
|
56
|
+
headers: {
|
|
57
|
+
accept: 'application/json',
|
|
58
|
+
authorization: `Bearer ${input.accessToken}`,
|
|
59
|
+
},
|
|
60
|
+
signal: AbortSignal.timeout(15000),
|
|
61
|
+
});
|
|
62
|
+
const payload = (await response.json());
|
|
63
|
+
if (!response.ok) {
|
|
64
|
+
return createFail('remote_auth', 'Remote auth', readErrorMessage(payload, 'PostPlus Cloud rejected the CLI session.'), 'Run `postplus auth login`.');
|
|
65
|
+
}
|
|
66
|
+
const accountId = typeof payload.accountId === 'string' ? payload.accountId : 'unknown';
|
|
67
|
+
const user = typeof payload.userEmail === 'string'
|
|
68
|
+
? payload.userEmail
|
|
69
|
+
: typeof payload.userId === 'string'
|
|
70
|
+
? payload.userId
|
|
71
|
+
: 'unknown';
|
|
72
|
+
const subscription = typeof payload.subscriptionStatus === 'string'
|
|
73
|
+
? payload.subscriptionStatus
|
|
74
|
+
: 'unknown';
|
|
75
|
+
return createPass('remote_auth', 'Remote auth', `Account ${accountId}; user ${user}; subscription ${subscription}`);
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
return createFail('remote_auth', 'Remote auth', error instanceof Error
|
|
79
|
+
? error.message
|
|
80
|
+
: 'Failed to validate PostPlus Cloud auth.', 'Run `postplus auth validate` after confirming network access.');
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
async function checkHostedCapabilities(input) {
|
|
84
|
+
try {
|
|
85
|
+
const response = await fetch(`${input.hostedBaseUrl}/api/postplus-cli/hosted/readiness`, {
|
|
86
|
+
headers: {
|
|
87
|
+
accept: 'application/json',
|
|
88
|
+
authorization: `Bearer ${input.accessToken}`,
|
|
89
|
+
},
|
|
90
|
+
signal: AbortSignal.timeout(15000),
|
|
91
|
+
});
|
|
92
|
+
const payload = (await response.json());
|
|
93
|
+
if (!response.ok) {
|
|
94
|
+
return createFail('hosted_capabilities', 'Hosted capabilities', readErrorMessage(payload, 'PostPlus Cloud hosted readiness check failed.'));
|
|
95
|
+
}
|
|
96
|
+
const capabilities = Array.isArray(payload.capabilities)
|
|
97
|
+
? payload.capabilities
|
|
98
|
+
: [];
|
|
99
|
+
const failedLabels = capabilities
|
|
100
|
+
.map(readCapabilityFailureLabel)
|
|
101
|
+
.filter((value) => value !== null);
|
|
102
|
+
if (payload.subscriptionActive !== true) {
|
|
103
|
+
const status = typeof payload.subscriptionStatus === 'string'
|
|
104
|
+
? payload.subscriptionStatus
|
|
105
|
+
: 'unknown';
|
|
106
|
+
failedLabels.unshift(`subscription ${status}`);
|
|
107
|
+
}
|
|
108
|
+
if (payload.ok !== true || failedLabels.length > 0) {
|
|
109
|
+
return createFail('hosted_capabilities', 'Hosted capabilities', `Not ready: ${failedLabels.join(', ') || 'unknown capability failure'}`, 'Check PostPlus Cloud provider configuration and subscription state.');
|
|
110
|
+
}
|
|
111
|
+
return createPass('hosted_capabilities', 'Hosted capabilities', `Ready (${capabilities.length} capability checks passed)`);
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
return createFail('hosted_capabilities', 'Hosted capabilities', error instanceof Error
|
|
115
|
+
? error.message
|
|
116
|
+
: 'Failed to check hosted capability readiness.');
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function readCapabilityFailureLabel(value) {
|
|
120
|
+
if (!value || typeof value !== 'object') {
|
|
121
|
+
return 'invalid capability response';
|
|
122
|
+
}
|
|
123
|
+
const record = value;
|
|
124
|
+
if (record.ok === true) {
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
return typeof record.label === 'string'
|
|
128
|
+
? record.label
|
|
129
|
+
: typeof record.id === 'string'
|
|
130
|
+
? record.id
|
|
131
|
+
: 'unknown capability';
|
|
132
|
+
}
|
|
133
|
+
function readErrorMessage(payload, fallback) {
|
|
134
|
+
return typeof payload.error === 'string' && payload.error.trim().length > 0
|
|
135
|
+
? payload.error
|
|
136
|
+
: fallback;
|
|
137
|
+
}
|
|
20
138
|
export function formatDoctorReport(report) {
|
|
21
139
|
const lines = ['PostPlus CLI doctor', ''];
|
|
22
140
|
for (const check of report.checks) {
|
package/build/skill-catalog.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export const POSTPLUS_SKILLS_REPO = 'PostPlusAI/postplus-skills';
|
|
2
|
-
export const POSTPLUS_SKILLS_INSTALL_COMMAND =
|
|
2
|
+
export const POSTPLUS_SKILLS_INSTALL_COMMAND = "npx -y skills add PostPlusAI/postplus-skills --skill '*' --agent claude-code codex cursor --yes";
|
|
3
3
|
export const POSTPLUS_SKILLS_LIST_COMMAND = 'npx -y skills add PostPlusAI/postplus-skills --list';
|
|
4
4
|
const POSTPLUS_SKILLS_INDEX_URL = 'https://raw.githubusercontent.com/PostPlusAI/postplus-skills/main/skills/INDEX.md';
|
|
5
5
|
export async function loadPublicSkillCatalog() {
|
|
@@ -13,21 +13,27 @@ export async function loadPublicSkillCatalog() {
|
|
|
13
13
|
throw new Error(`Failed to load PostPlus skill catalog (${response.status}): ${response.statusText}`);
|
|
14
14
|
}
|
|
15
15
|
const indexText = await response.text();
|
|
16
|
+
const skills = parseSkillIndex(indexText);
|
|
17
|
+
if (skills.length === 0) {
|
|
18
|
+
throw new Error('PostPlus public skill catalog is invalid: no released skills were found.');
|
|
19
|
+
}
|
|
16
20
|
return {
|
|
17
21
|
source: POSTPLUS_SKILLS_REPO,
|
|
18
22
|
indexUrl: POSTPLUS_SKILLS_INDEX_URL,
|
|
19
23
|
installCommand: POSTPLUS_SKILLS_INSTALL_COMMAND,
|
|
20
24
|
listCommand: POSTPLUS_SKILLS_LIST_COMMAND,
|
|
21
|
-
skills
|
|
25
|
+
skills,
|
|
22
26
|
};
|
|
23
27
|
}
|
|
24
28
|
function parseSkillIndex(indexText) {
|
|
25
29
|
const skills = [];
|
|
26
30
|
let inReleasedSkills = false;
|
|
31
|
+
let sawReleasedSkillsSection = false;
|
|
27
32
|
let currentSkill = null;
|
|
28
33
|
for (const line of indexText.split('\n')) {
|
|
29
34
|
if (line.trim() === '## Released Skills') {
|
|
30
35
|
inReleasedSkills = true;
|
|
36
|
+
sawReleasedSkillsSection = true;
|
|
31
37
|
continue;
|
|
32
38
|
}
|
|
33
39
|
if (!inReleasedSkills) {
|
|
@@ -52,5 +58,8 @@ function parseSkillIndex(indexText) {
|
|
|
52
58
|
}
|
|
53
59
|
}
|
|
54
60
|
}
|
|
61
|
+
if (!sawReleasedSkillsSection) {
|
|
62
|
+
throw new Error('PostPlus public skill catalog is invalid: missing ## Released Skills section.');
|
|
63
|
+
}
|
|
55
64
|
return skills;
|
|
56
65
|
}
|
package/package.json
CHANGED
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@postplus/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
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": "Apache-2.0",
|
|
8
8
|
"files": [
|
|
9
|
-
"build
|
|
9
|
+
"build/auth-lifecycle.js",
|
|
10
|
+
"build/auth-login.js",
|
|
11
|
+
"build/auth-validate.js",
|
|
12
|
+
"build/auth.js",
|
|
13
|
+
"build/doctor.js",
|
|
14
|
+
"build/hosted-release.js",
|
|
15
|
+
"build/index.js",
|
|
16
|
+
"build/local-state.js",
|
|
17
|
+
"build/skill-catalog.js",
|
|
18
|
+
"build/status.js",
|
|
10
19
|
"LICENSE",
|
|
11
20
|
"NOTICE",
|
|
12
21
|
"README.md"
|
|
@@ -22,7 +31,7 @@
|
|
|
22
31
|
"postplus": "./build/index.js"
|
|
23
32
|
},
|
|
24
33
|
"scripts": {
|
|
25
|
-
"build": "tsc",
|
|
34
|
+
"build": "node ./scripts/clean-build.mjs && tsc",
|
|
26
35
|
"clean": "rm -rf .turbo node_modules build",
|
|
27
36
|
"release:package": "node ./scripts/package-release.mjs",
|
|
28
37
|
"start": "tsx src/index.ts",
|