@homespunapps/cli 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.
- package/LICENSE +21 -0
- package/README.md +81 -0
- package/dist/argv.js +140 -0
- package/dist/commands/agent.js +62 -0
- package/dist/commands/apps.js +368 -0
- package/dist/commands/attachment-delete.js +37 -0
- package/dist/commands/attachment-download.js +53 -0
- package/dist/commands/attachment-list.js +50 -0
- package/dist/commands/attachment-show.js +37 -0
- package/dist/commands/attachment-token.js +133 -0
- package/dist/commands/attachment-upload.js +65 -0
- package/dist/commands/attachment.js +133 -0
- package/dist/commands/claim.js +68 -0
- package/dist/commands/config.js +262 -0
- package/dist/commands/data.js +168 -0
- package/dist/commands/deploy.js +136 -0
- package/dist/commands/feedback.js +133 -0
- package/dist/commands/key.js +82 -0
- package/dist/commands/logout.js +59 -0
- package/dist/commands/members.js +143 -0
- package/dist/commands/register.js +131 -0
- package/dist/commands/set-key.js +92 -0
- package/dist/commands/skill.js +145 -0
- package/dist/commands/taste.js +165 -0
- package/dist/config.js +165 -0
- package/dist/format.js +133 -0
- package/dist/index.js +230 -0
- package/dist/input.js +42 -0
- package/dist/output.js +77 -0
- package/dist/resolve-app.js +51 -0
- package/dist/store.js +205 -0
- package/dist/upgrade.js +115 -0
- package/dist/version.js +11 -0
- package/package.json +53 -0
package/dist/upgrade.js
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
// CLI auto-upgrade helpers — install-method detection and message formatting.
|
|
2
|
+
//
|
|
3
|
+
// Called by the top-level error handler when a relay returns 426
|
|
4
|
+
// `cli_upgrade_required`. The goal is to print a single, machine-parseable
|
|
5
|
+
// line the agent can lift verbatim — and tell the human (or the agent's
|
|
6
|
+
// harness) exactly what to run instead of a generic "upgrade @homespunapps/cli".
|
|
7
|
+
//
|
|
8
|
+
// Detection is best-effort: we inspect `process.execPath` and the CLI's own
|
|
9
|
+
// install path. There's no programmatic "ask npm what installed me" API, so
|
|
10
|
+
// the heuristics below are matched against the well-known install layouts
|
|
11
|
+
// of each package manager. Anything unrecognized lands in `unknown`, which
|
|
12
|
+
// means "tell the agent to ask the human" rather than guess.
|
|
13
|
+
/**
|
|
14
|
+
* Detection rules, ordered most-specific to least. Each rule looks at the
|
|
15
|
+
* directory the CLI is running from — caller passes `import.meta.url`-
|
|
16
|
+
* derived absolute path for the CLI entry. The actual file at that path
|
|
17
|
+
* doesn't need to exist; we're only pattern-matching the path itself, so
|
|
18
|
+
* tests can pass synthetic strings.
|
|
19
|
+
*
|
|
20
|
+
* Patterns are deliberately loose (substring tests, not exact prefixes) so
|
|
21
|
+
* the same rule handles per-user installs (`~/.npm-global/lib/node_modules/`),
|
|
22
|
+
* system installs (`/usr/lib/node_modules/`), and the macOS/Linux
|
|
23
|
+
* variations within each manager — without listing every layout.
|
|
24
|
+
*/
|
|
25
|
+
export function detectInstallMethod(entryPath) {
|
|
26
|
+
// Volta wraps every binary in a shim under ~/.volta/tools/image/packages/
|
|
27
|
+
// and re-exports it via ~/.volta/bin/. Either path is a positive match.
|
|
28
|
+
if (entryPath.includes("/.volta/"))
|
|
29
|
+
return "volta";
|
|
30
|
+
// Bun's global registry: ~/.bun/install/global/node_modules/@homespunapps/cli/...
|
|
31
|
+
if (entryPath.includes("/.bun/install/global/"))
|
|
32
|
+
return "bun-global";
|
|
33
|
+
// npm global, in both common shapes:
|
|
34
|
+
// /usr/(local/)?lib/node_modules/@homespunapps/cli/... (system)
|
|
35
|
+
// ~/.npm-global/lib/node_modules/@homespunapps/cli/... (npm prefix)
|
|
36
|
+
// ~/.nvm/versions/node/vXX/lib/node_modules/... (nvm)
|
|
37
|
+
if (/\/lib\/node_modules\/@homespunapps\/cli\//.test(entryPath) ||
|
|
38
|
+
/\/lib\/node_modules\/\.bin\//.test(entryPath)) {
|
|
39
|
+
return "npm-global";
|
|
40
|
+
}
|
|
41
|
+
// npx caches the package under ~/Library/Caches/_npx (macOS) or
|
|
42
|
+
// ~/.npm/_npx (Linux) and runs it from a node_modules inside that dir.
|
|
43
|
+
// Treat this distinctly from a real vendored install: with an npx
|
|
44
|
+
// execution there is no project package.json owning the version and no
|
|
45
|
+
// global to upgrade — the user runs `npx @homespunapps/cli@<version>` each
|
|
46
|
+
// time, so the right answer is "ask the human / re-run with a newer
|
|
47
|
+
// explicit version".
|
|
48
|
+
if (entryPath.includes("/_npx/"))
|
|
49
|
+
return "unknown";
|
|
50
|
+
// Vendored: the CLI lives inside the *project's* node_modules — i.e. the
|
|
51
|
+
// user did `npm i @homespunapps/cli` (no -g) and runs it via a local script.
|
|
52
|
+
// We can't safely upgrade this for them; package.json owns it.
|
|
53
|
+
if (entryPath.includes("/node_modules/@homespunapps/cli/"))
|
|
54
|
+
return "vendored";
|
|
55
|
+
// pnpm temp, asdf, or anything else.
|
|
56
|
+
return "unknown";
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Returns the shell command the human (or the agent, in a sandbox it owns)
|
|
60
|
+
* can run to upgrade @homespunapps/cli to satisfy `minVersion`. `null` means "no
|
|
61
|
+
* portable command exists — escalate to the human."
|
|
62
|
+
*
|
|
63
|
+
* Always pin the upgrade target to `>=${minVersion}` instead of `@latest`
|
|
64
|
+
* so a self-hosted relay that requires 0.0.7 doesn't drag the client to a
|
|
65
|
+
* future 0.1.0 that may have its own incompatibilities. The trailing
|
|
66
|
+
* `@latest`-equivalent is fine for the operator who deliberately
|
|
67
|
+
* fast-forwards.
|
|
68
|
+
*/
|
|
69
|
+
export function upgradeCommandFor(method, minVersion) {
|
|
70
|
+
const spec = `@homespunapps/cli@>=${minVersion}`;
|
|
71
|
+
switch (method) {
|
|
72
|
+
case "npm-global":
|
|
73
|
+
return `npm install -g ${spec}`;
|
|
74
|
+
case "bun-global":
|
|
75
|
+
return `bun install -g ${spec}`;
|
|
76
|
+
case "volta":
|
|
77
|
+
return `volta install ${spec}`;
|
|
78
|
+
case "vendored":
|
|
79
|
+
case "unknown":
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* The deterministic stderr block the CLI prints on a 426 response. The agent
|
|
85
|
+
* is expected to read this verbatim and (per SKILL.md) run the printed
|
|
86
|
+
* command, then re-run its original `homespun` invocation once. Format is held
|
|
87
|
+
* stable across CLI versions so the skill's instructions don't drift — a
|
|
88
|
+
* change here is a contract change.
|
|
89
|
+
*/
|
|
90
|
+
export function formatUpgradeMessage(err, method, command) {
|
|
91
|
+
// The relay's 426 payload puts the two version strings under details. We
|
|
92
|
+
// tolerate a missing/malformed details object so a misbehaving relay
|
|
93
|
+
// can't crash the CLI's own error path — show whatever we have.
|
|
94
|
+
const details = (err.details ?? {});
|
|
95
|
+
const minVersion = typeof details.min_version === "string" ? details.min_version : "?";
|
|
96
|
+
const yourVersion = typeof details.your_version === "string" ? details.your_version : "?";
|
|
97
|
+
const lines = [];
|
|
98
|
+
lines.push(`app: this relay requires @homespunapps/cli >= ${minVersion} (you have ${yourVersion}).`);
|
|
99
|
+
if (command !== null) {
|
|
100
|
+
lines.push(`To upgrade: ${command}`);
|
|
101
|
+
}
|
|
102
|
+
else if (method === "vendored") {
|
|
103
|
+
lines.push("Install method: vendored (inside a project's node_modules). Bump the @homespunapps/cli version in that project's package.json and re-install — the CLI isn't safe to upgrade globally for a vendored install.");
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
lines.push("Install method: unknown. Ask the human to upgrade @homespunapps/cli — the install path didn't match any pattern we recognize (npm-global, bun-global, volta).");
|
|
107
|
+
}
|
|
108
|
+
return lines.join("\n");
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Stable exit code used by the CLI on a `cli_upgrade_required` response.
|
|
112
|
+
* Sysexits.h's `EX_TEMPFAIL` — "temporary failure; retry after fixing".
|
|
113
|
+
* Documented in SKILL.md so an agent's harness can branch on it.
|
|
114
|
+
*/
|
|
115
|
+
export const EXIT_CLI_UPGRADE_REQUIRED = 75;
|
package/dist/version.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// Single source of truth for the CLI version string.
|
|
2
|
+
//
|
|
3
|
+
// - `homespun --version` prints this verbatim.
|
|
4
|
+
// - Every HomespunClient construction passes it as `cliVersion`, which apps
|
|
5
|
+
// as the `x-homespun-cli-version` header on every relay request — drives the
|
|
6
|
+
// relay's version-skew check (HTTP 426 `cli_upgrade_required`).
|
|
7
|
+
//
|
|
8
|
+
// Keep this in lockstep with packages/cli/package.json's `version` field;
|
|
9
|
+
// they're consulted in different places (here for the runtime header,
|
|
10
|
+
// package.json for npm publish + dependency resolution).
|
|
11
|
+
export const VERSION = "0.0.29";
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@homespunapps/cli",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Command-line client for the Homespun relay: create apps, inspect state, send and watch events.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"homespun",
|
|
9
|
+
"cli",
|
|
10
|
+
"agent",
|
|
11
|
+
"relay",
|
|
12
|
+
"human-in-the-loop"
|
|
13
|
+
],
|
|
14
|
+
"homepage": "https://github.com/aerolalit/homespun#readme",
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/aerolalit/homespun.git",
|
|
18
|
+
"directory": "packages/cli"
|
|
19
|
+
},
|
|
20
|
+
"bugs": {
|
|
21
|
+
"url": "https://github.com/aerolalit/homespun/issues"
|
|
22
|
+
},
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=20"
|
|
25
|
+
},
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"access": "public"
|
|
28
|
+
},
|
|
29
|
+
"bin": {
|
|
30
|
+
"homespun": "dist/index.js"
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"dist",
|
|
34
|
+
"LICENSE",
|
|
35
|
+
"README.md"
|
|
36
|
+
],
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "tsc",
|
|
39
|
+
"typecheck": "tsc --noEmit",
|
|
40
|
+
"test": "vitest run",
|
|
41
|
+
"test:unit": "vitest run"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@homespunapps/core": "^1.0.0",
|
|
45
|
+
"qrcode-terminal": "^0.12.0"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@types/node": "^25.9.2",
|
|
49
|
+
"@types/qrcode-terminal": "^0.12.2",
|
|
50
|
+
"typescript": "^6.0.3",
|
|
51
|
+
"vitest": "^4.1.8"
|
|
52
|
+
}
|
|
53
|
+
}
|