promptdock 1.2.0 → 1.2.1

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/dist/verdicts.js CHANGED
@@ -1,7 +1,11 @@
1
1
  import { CliError, EXIT } from "./errors.js";
2
+ import { SERVER_LABEL_MAX, terminalLine } from "./terminal-text.js";
2
3
  import { retryHours } from "./ui.js";
3
- import { CANONICAL_INSTALL_COMMAND, CLI_DOS_MAX_SKILL_FILES, CLI_DOS_MAX_SKILL_TOTAL_BYTES, } from "./generated/constants.js";
4
- export const UPGRADE_URL = "https://promptdock.ai/pricing";
4
+ import { CANONICAL_INSTALL_COMMAND, CANONICAL_ORIGIN, CLI_DOS_MAX_SKILL_FILES, CLI_DOS_MAX_SKILL_TOTAL_BYTES, } from "./generated/constants.js";
5
+ /** ⚠️ DERIVED from `CANONICAL_ORIGIN`. This is the CTA a user follows the moment the CLI
6
+ * tells them their plan is too low — the one link most likely to be clicked under
7
+ * friction, so it must not spend a redirect hop. */
8
+ export const UPGRADE_URL = `${CANONICAL_ORIGIN}/pricing`;
5
9
  /** Numeric semver compare; mirrors compareCliVersions in lib/validation/skills.ts. */
6
10
  function cmpVersion(a, b) {
7
11
  const pa = a.split(".").map((n) => Number(n) || 0);
@@ -23,12 +27,21 @@ function cmpVersion(a, b) {
23
27
  * `assertSafeManifest` stays as the untrusted-server backstop — this check makes it
24
28
  * unreachable in practice, never redundant.
25
29
  */
26
- function assertPackageCompatible(resolve, cliVersion) {
27
- const upgrade = `Update: ${CANONICAL_INSTALL_COMMAND} … (or: npm i -g promptdock@latest)`;
28
- const title = resolve.title ? `"${resolve.title}"` : "This skill";
30
+ function assertPackageCompatible(resolve, refString, cliVersion) {
31
+ // The ref is threaded in for ONE reason: this hint is the whole remedy, and a
32
+ // remedy is only a remedy if it can be pasted. The old copy ended in a literal
33
+ // "…" — three characters that look like a command and are not one, printed at
34
+ // exactly the moment the user is stuck and least able to guess the rest.
35
+ const upgrade = `Update: ${CANONICAL_INSTALL_COMMAND} ${refString} (or: npm i -g promptdock@latest)`;
36
+ // ⚠️ The CliError constructor already strips control characters from these. What it
37
+ // deliberately does NOT do is bound them: `terminalBlock` keeps newlines and applies
38
+ // no cap, so a hostile title could still forge a second line or run to a megabyte.
39
+ // The fragment treatment is what makes the message BOUNDED.
40
+ const safeTitle = terminalLine(resolve.title, SERVER_LABEL_MAX);
41
+ const title = safeTitle ? `"${safeTitle}"` : "This skill";
29
42
  const min = resolve.min_cli_version;
30
43
  if (typeof min === "string" && min.length > 0 && cmpVersion(cliVersion, min) < 0) {
31
- throw new CliError(`${title} needs promptdock CLI ${min} or newer — you are on ${cliVersion}.`, EXIT.DENIED, { footer: "upgrade_required", hint: upgrade });
44
+ throw new CliError(`${title} needs promptdock CLI ${terminalLine(min, SERVER_LABEL_MAX)} or newer — you are on ${cliVersion}.`, EXIT.DENIED, { footer: "upgrade_required", hint: upgrade });
32
45
  }
33
46
  // Belt and braces for a server too old to send min_cli_version: compare the shape
34
47
  // the resolve response already reports against this CLI's own fuses.
@@ -47,14 +60,17 @@ export function assertInstallable(resolve, refString, cliVersion) {
47
60
  switch (resolve.verdict) {
48
61
  case "ok":
49
62
  case "already_entitled":
50
- assertPackageCompatible(resolve, cliVersion);
63
+ assertPackageCompatible(resolve, refString, cliVersion);
51
64
  return;
52
65
  case "not_found":
53
66
  throw new CliError(`skill not found: ${refString} — check the ref (the format is handle/slug; a pasted promptdock.ai skill URL also works)`, EXIT.DENIED, { footer: "not_found" });
54
67
  case "insufficient_tier": {
55
- const title = resolve.title ? `"${resolve.title}"` : "This skill";
68
+ const safe = terminalLine(resolve.title, SERVER_LABEL_MAX);
69
+ const title = safe ? `"${safe}"` : "This skill";
56
70
  throw new CliError(`${title} is a premium skill. Premium skills need the Explorer plan ($10/mo) or higher` +
57
- (resolve.current ? ` — your account is on the ${resolve.current} tier.` : "."), EXIT.DENIED, { footer: "insufficient_tier", hint: `Upgrade: ${UPGRADE_URL}` });
71
+ (resolve.current
72
+ ? ` — your account is on the ${terminalLine(resolve.current, SERVER_LABEL_MAX)} tier.`
73
+ : "."), EXIT.DENIED, { footer: "insufficient_tier", hint: `Upgrade: ${UPGRADE_URL}` });
58
74
  }
59
75
  case "cap_hit": {
60
76
  const wait = retryHours(Number(resolve.retry_after_secs) || 3600);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "promptdock",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "Install AI agent skills from PromptDock — npx promptdock@latest install <handle>/<slug>",
5
5
  "keywords": [
6
6
  "promptdock",
@@ -10,14 +10,15 @@
10
10
  "claude",
11
11
  "cli"
12
12
  ],
13
- "homepage": "https://promptdock.ai",
13
+ "homepage": "https://www.promptdock.ai",
14
14
  "repository": {
15
15
  "type": "git",
16
16
  "url": "git+https://github.com/klicklabs/promptdock.ai.git",
17
17
  "directory": "packages/cli"
18
18
  },
19
19
  "bugs": {
20
- "url": "https://promptdock.ai/docs/cli/errors"
20
+ "url": "https://www.promptdock.ai/docs/cli/errors",
21
+ "email": "support@promptdock.ai"
21
22
  },
22
23
  "license": "MIT",
23
24
  "type": "module",
@@ -42,5 +43,5 @@
42
43
  "typescript": "^5",
43
44
  "vitest": "^4.1.8"
44
45
  },
45
- "gitHead": "53545d74fc0baeec63684c96b49134e93625d63a"
46
+ "gitHead": "46e6b02fe045e9b803f748b32b9443995a40b1ac"
46
47
  }