@higherdev/cli 0.14.5 → 0.15.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/README.md +7 -1
- package/dist/api.js +9 -0
- package/dist/index.js +35 -1
- package/dist/out.js +1 -0
- package/dist/workspace-preflight.js +2 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -47,6 +47,9 @@ workspace-map config shapes are migrated automatically when they are read.
|
|
|
47
47
|
| `hd env ls` | List workspace environment variable names |
|
|
48
48
|
| `hd env set NAME=VALUE [NAME=VALUE...]` | Set workspace environment variables |
|
|
49
49
|
| `hd env rm NAME` | Remove a workspace environment variable |
|
|
50
|
+
| `hd host env ls` | List environment variable names on the workspace's default host |
|
|
51
|
+
| `hd host env set NAME=VALUE [NAME=VALUE...]` | Set host-only environment variables |
|
|
52
|
+
| `hd host env rm NAME` | Remove a host-only environment variable |
|
|
50
53
|
| `hd logs KEY [-f]` | Show or follow run events |
|
|
51
54
|
| `hd msg KEY "message" [--interrupt]` | Message a builder |
|
|
52
55
|
| `hd decide` | List open decisions |
|
|
@@ -62,7 +65,7 @@ elsewhere. If the runner environment or service unit already exists, inspect the
|
|
|
62
65
|
pass `--force` only when replacing that host configuration is intentional.
|
|
63
66
|
|
|
64
67
|
`hd workspace new` uses the operator's authenticated `gh`, defaults to the repository's real default
|
|
65
|
-
branch, bootstraps an empty repository unless `--no-bootstrap` is set, and invites `mel-ilotus` unless
|
|
68
|
+
branch, bootstraps an empty repository unless `--no-bootstrap` is set, and invites `mel-ilotus` as an admin unless
|
|
66
69
|
`--runner-user USER` overrides it. On a terminal, missing name or repo flags start a guided wizard. If
|
|
67
70
|
the repository is missing, approve private creation interactively, use `--create` to force it, or
|
|
68
71
|
`--no-create` to fail. Fully flagged calls remain non-interactive for scripts and Mel.
|
|
@@ -71,6 +74,9 @@ the repository is missing, approve private creation interactively, use `--create
|
|
|
71
74
|
They require the operator's authenticated `gh` account to have repository admin permission. Secret values are sent
|
|
72
75
|
to `gh` through stdin and are never printed.
|
|
73
76
|
|
|
77
|
+
Use `hd host env set SUPABASE_ACCESS_TOKEN=... SUPABASE_ORG_ID=...` once to let the runner provision
|
|
78
|
+
Supabase for workspaces assigned to that host. Host values are never passed to builder processes.
|
|
79
|
+
|
|
74
80
|
Inside the TUI, use `/board`, `/inbox`, `/ticket`, `/queue`, `/cancel`, `/epic new`,
|
|
75
81
|
`/epic approve`, `/epics`, `/architect` (or `/plan`), `/decide`, `/agents add`, `/agents rm`, `/env`, `/settings`, `/workspace`,
|
|
76
82
|
`/workspace new`, `/workspace set`, `/workspace rotate-key`, `/feed`,
|
package/dist/api.js
CHANGED
|
@@ -114,6 +114,15 @@ export async function setWorkspaceEnv(name, value, config = loadConfig()) {
|
|
|
114
114
|
export async function removeWorkspaceEnv(name, config = loadConfig()) {
|
|
115
115
|
return request(config, "DELETE", `/api/w/${config.slug}/env`, { name });
|
|
116
116
|
}
|
|
117
|
+
export async function listHostEnv(host, config = loadConfig()) {
|
|
118
|
+
return request(config, "GET", `/api/hosts/${encodeURIComponent(host)}/env`);
|
|
119
|
+
}
|
|
120
|
+
export async function setHostEnv(host, name, value, config = loadConfig()) {
|
|
121
|
+
return request(config, "PUT", `/api/hosts/${encodeURIComponent(host)}/env`, { name, value });
|
|
122
|
+
}
|
|
123
|
+
export async function removeHostEnv(host, name, config = loadConfig()) {
|
|
124
|
+
return request(config, "DELETE", `/api/hosts/${encodeURIComponent(host)}/env`, { name });
|
|
125
|
+
}
|
|
117
126
|
export async function listEpics(config = loadConfig()) {
|
|
118
127
|
return request(config, "GET", `/api/w/${config.slug}/epics`);
|
|
119
128
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { realpathSync } from "node:fs";
|
|
3
3
|
import { pathToFileURL } from "node:url";
|
|
4
|
-
import { approveEpic, answerDecision, cancelTicket, createAgent, createEpic, createTicket, deleteAgent, deleteEpic, getStatus, listAgents, listEpics, listWorkspaceEnv, listTicketEvents, listTickets, listWorkspaces, postMessage, queueTicket, removeWorkspaceEnv, setPaused, setWorkspaceEnv, showTicket, updateAgent, updateCaps, } from "./api.js";
|
|
4
|
+
import { approveEpic, answerDecision, cancelTicket, createAgent, createEpic, createTicket, deleteAgent, deleteEpic, getStatus, listAgents, listEpics, listHostEnv, listWorkspaceEnv, listTicketEvents, listTickets, listWorkspaces, postMessage, queueTicket, removeWorkspaceEnv, removeHostEnv, setPaused, setWorkspaceEnv, setHostEnv, showTicket, updateAgent, updateCaps, } from "./api.js";
|
|
5
5
|
import { initHost, parseHostFlags } from "./host.js";
|
|
6
6
|
import { login, parseLoginFlags } from "./login.js";
|
|
7
7
|
import { loadConfig } from "./config.js";
|
|
@@ -412,6 +412,36 @@ export async function cmdEnv(argv, deps = {}) {
|
|
|
412
412
|
}
|
|
413
413
|
fail("usage: hd env ls | set NAME=VALUE [NAME=VALUE...] | rm NAME");
|
|
414
414
|
}
|
|
415
|
+
async function cmdHost(argv) {
|
|
416
|
+
const [scope, action, ...args] = argv;
|
|
417
|
+
const usage = "usage: hd host env ls | set NAME=VALUE [NAME=VALUE...] | rm NAME";
|
|
418
|
+
if (scope !== "env")
|
|
419
|
+
fail(usage);
|
|
420
|
+
const host = (await getStatus()).workspace.default_host;
|
|
421
|
+
if (action === "ls") {
|
|
422
|
+
const { env } = await listHostEnv(host);
|
|
423
|
+
if (!env.length)
|
|
424
|
+
return console.log(c.dim(`No environment variables for host ${host}.`));
|
|
425
|
+
console.log(table(["NAME", "UPDATED"], env.map((row) => [row.name, row.updated_at])));
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
if (action === "set" && args.length) {
|
|
429
|
+
for (const assignment of args) {
|
|
430
|
+
const at = assignment.indexOf("=");
|
|
431
|
+
if (at < 1)
|
|
432
|
+
fail(usage);
|
|
433
|
+
await setHostEnv(host, assignment.slice(0, at), assignment.slice(at + 1));
|
|
434
|
+
}
|
|
435
|
+
console.log(`set ${args.length} host variable${args.length === 1 ? "" : "s"} on ${host}`);
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
if (action === "rm" && args.length === 1) {
|
|
439
|
+
await removeHostEnv(host, args[0]);
|
|
440
|
+
console.log(`removed ${args[0]} from ${host}`);
|
|
441
|
+
return;
|
|
442
|
+
}
|
|
443
|
+
fail(usage);
|
|
444
|
+
}
|
|
415
445
|
export async function main(argv = process.argv.slice(2), deps = {}) {
|
|
416
446
|
const [cmd, ...rest] = argv;
|
|
417
447
|
try {
|
|
@@ -477,6 +507,10 @@ export async function main(argv = process.argv.slice(2), deps = {}) {
|
|
|
477
507
|
await cmdEnv(rest, deps);
|
|
478
508
|
return;
|
|
479
509
|
}
|
|
510
|
+
if (cmd === "host") {
|
|
511
|
+
await cmdHost(rest);
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
480
514
|
if (cmd === "pause" || cmd === "off") {
|
|
481
515
|
await setPaused(true);
|
|
482
516
|
console.log(cmd === "off" ? "off" : "paused");
|
package/dist/out.js
CHANGED
|
@@ -71,6 +71,7 @@ export function usage() {
|
|
|
71
71
|
` ${c.blue("hd agents [add | rm | set]")} manage agents`,
|
|
72
72
|
` ${c.blue("hd caps [set PROVIDER N]")} provider concurrency`,
|
|
73
73
|
` ${c.blue("hd env ls | set | rm")} workspace environment`,
|
|
74
|
+
` ${c.blue("hd host env ls | set | rm")} host environment`,
|
|
74
75
|
` ${c.blue("hd logs KEY [-f]")} run events`,
|
|
75
76
|
` ${c.blue("hd msg KEY TEXT")} message a builder`,
|
|
76
77
|
` ${c.blue("hd decide [ID --answer TEXT]")} decisions`,
|
|
@@ -55,9 +55,6 @@ export async function requireAdminRepo(repo, gh = defaultGh) {
|
|
|
55
55
|
async function repoView(repo, gh) {
|
|
56
56
|
return JSON.parse(await gh(["repo", "view", repo, "--json", "defaultBranchRef,isEmpty,viewerPermission"]));
|
|
57
57
|
}
|
|
58
|
-
function canPush(permission) {
|
|
59
|
-
return ["admin", "maintain", "write", "push"].includes(permission.toLowerCase());
|
|
60
|
-
}
|
|
61
58
|
export async function preflightWorkspace(input, gh = defaultGh) {
|
|
62
59
|
try {
|
|
63
60
|
await gh(["--version"]);
|
|
@@ -94,9 +91,9 @@ export async function preflightWorkspace(input, gh = defaultGh) {
|
|
|
94
91
|
if (!/404|not found/i.test(errorMessage(error)))
|
|
95
92
|
throw error;
|
|
96
93
|
}
|
|
97
|
-
const invitationPending =
|
|
94
|
+
const invitationPending = permission.toLowerCase() !== "admin";
|
|
98
95
|
if (invitationPending) {
|
|
99
|
-
await gh(["api", "-X", "PUT", `repos/${input.repo}/collaborators/${runnerUser}`, "-f", "permission=
|
|
96
|
+
await gh(["api", "-X", "PUT", `repos/${input.repo}/collaborators/${runnerUser}`, "-f", "permission=admin"]);
|
|
100
97
|
}
|
|
101
98
|
return { branch, invitationPending };
|
|
102
99
|
}
|