hypha-cli 0.1.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/bin/hypha.mjs +40 -0
- package/dist/apps-rK1_N8nw.mjs +512 -0
- package/dist/artifactPath-DCtvp6Go.mjs +51 -0
- package/dist/artifacts-8p2A4NMr.mjs +764 -0
- package/dist/cli.mjs +99 -0
- package/dist/helpers-BvfSCkvr.mjs +188 -0
- package/dist/index.mjs +5 -0
- package/dist/workspace-wlyR33kp.mjs +127 -0
- package/package.json +36 -0
package/dist/cli.mjs
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
const nodeMajor = parseInt(process.versions.node.split(".")[0], 10);
|
|
2
|
+
if (nodeMajor < 22) {
|
|
3
|
+
console.error(`Error: hypha requires Node.js >= 22 (you have ${process.version}).`);
|
|
4
|
+
process.exit(1);
|
|
5
|
+
}
|
|
6
|
+
const args = process.argv.slice(2);
|
|
7
|
+
function extractGlobalFlag(argList, flag) {
|
|
8
|
+
const idx = argList.indexOf(flag);
|
|
9
|
+
if (idx === -1 || idx >= argList.length - 1) return void 0;
|
|
10
|
+
const value = argList[idx + 1];
|
|
11
|
+
argList.splice(idx, 2);
|
|
12
|
+
return value;
|
|
13
|
+
}
|
|
14
|
+
const globalServer = extractGlobalFlag(args, "--server");
|
|
15
|
+
const globalWorkspace = extractGlobalFlag(args, "--workspace");
|
|
16
|
+
if (globalServer) process.env.HYPHA_SERVER_URL = globalServer;
|
|
17
|
+
if (globalWorkspace) process.env.HYPHA_WORKSPACE = globalWorkspace;
|
|
18
|
+
const subcommand = args[0];
|
|
19
|
+
function printHelp() {
|
|
20
|
+
console.log(`hypha \u2014 Hypha Cloud CLI
|
|
21
|
+
|
|
22
|
+
Usage: hypha [--server URL] [--workspace WS] <command> [options]
|
|
23
|
+
|
|
24
|
+
Workspace:
|
|
25
|
+
login [server-url] Login to Hypha server (opens browser)
|
|
26
|
+
token [options] Generate a workspace token
|
|
27
|
+
services [options] List services in workspace
|
|
28
|
+
info Show workspace info
|
|
29
|
+
|
|
30
|
+
Apps (manage server app definitions and instances):
|
|
31
|
+
apps list [--json] List installed app definitions
|
|
32
|
+
apps info <app-id> Show app details
|
|
33
|
+
apps install <source> Install an app
|
|
34
|
+
apps uninstall <app-id> Remove an app (alias: rm)
|
|
35
|
+
apps start <app-id> Start an app instance
|
|
36
|
+
apps stop <id> [--all] Stop instance(s)
|
|
37
|
+
apps ps [--json] List running instances
|
|
38
|
+
apps logs <instance-id> View instance logs
|
|
39
|
+
|
|
40
|
+
Artifacts (manage data, models, and files):
|
|
41
|
+
artifacts ls [artifact[:path]] List artifacts or files (alias: list)
|
|
42
|
+
artifacts cat <artifact:path> Read file to stdout
|
|
43
|
+
artifacts cp <src> <dest> Upload/download files (scp-style)
|
|
44
|
+
artifacts rm <artifact[:path]> Delete artifact or file
|
|
45
|
+
artifacts create <alias> Create a new artifact (alias: mkdir)
|
|
46
|
+
artifacts info <artifact> Show artifact metadata
|
|
47
|
+
artifacts search <query> Search artifacts (alias: find)
|
|
48
|
+
artifacts commit <artifact> Commit staged changes
|
|
49
|
+
artifacts edit <artifact> Edit artifact metadata
|
|
50
|
+
artifacts discard <artifact> Discard staged changes
|
|
51
|
+
|
|
52
|
+
Global options:
|
|
53
|
+
--server <url> Hypha server URL (overrides env/config)
|
|
54
|
+
--workspace <ws> Workspace ID (overrides env/config)
|
|
55
|
+
--help, -h Show help
|
|
56
|
+
--version, -v Show version
|
|
57
|
+
|
|
58
|
+
Shorthand: "art" is an alias for "artifacts".
|
|
59
|
+
Config: ~/.hypha/.env (HYPHA_SERVER_URL, HYPHA_TOKEN, HYPHA_WORKSPACE)`);
|
|
60
|
+
}
|
|
61
|
+
async function main() {
|
|
62
|
+
if (!subcommand || subcommand === "--help" || subcommand === "-h") {
|
|
63
|
+
printHelp();
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (subcommand === "--version" || subcommand === "-v") {
|
|
67
|
+
const version = process.env.HYPHA_CLI_VERSION || "0.1.0";
|
|
68
|
+
console.log(`hypha-cli ${version}`);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const commandArgs = args.slice(1);
|
|
72
|
+
if (subcommand === "login") {
|
|
73
|
+
const { loginCommand } = await import('./workspace-wlyR33kp.mjs');
|
|
74
|
+
await loginCommand(commandArgs);
|
|
75
|
+
} else if (subcommand === "token") {
|
|
76
|
+
const { tokenCommand } = await import('./workspace-wlyR33kp.mjs');
|
|
77
|
+
await tokenCommand(commandArgs);
|
|
78
|
+
} else if (subcommand === "services") {
|
|
79
|
+
const { servicesCommand } = await import('./workspace-wlyR33kp.mjs');
|
|
80
|
+
await servicesCommand(commandArgs);
|
|
81
|
+
} else if (subcommand === "info") {
|
|
82
|
+
const { infoCommand } = await import('./workspace-wlyR33kp.mjs');
|
|
83
|
+
await infoCommand(commandArgs);
|
|
84
|
+
} else if (subcommand === "apps") {
|
|
85
|
+
const { handleAppsCommand } = await import('./apps-rK1_N8nw.mjs');
|
|
86
|
+
await handleAppsCommand(commandArgs);
|
|
87
|
+
} else if (subcommand === "artifacts" || subcommand === "art") {
|
|
88
|
+
const { handleArtifactsCommand } = await import('./artifacts-8p2A4NMr.mjs');
|
|
89
|
+
await handleArtifactsCommand(commandArgs);
|
|
90
|
+
} else {
|
|
91
|
+
console.error(`Unknown command: ${subcommand}`);
|
|
92
|
+
console.error("Run `hypha --help` for usage.");
|
|
93
|
+
process.exit(1);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
main().catch((err) => {
|
|
97
|
+
console.error(err.message || err);
|
|
98
|
+
process.exit(1);
|
|
99
|
+
});
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { homedir } from 'os';
|
|
4
|
+
|
|
5
|
+
function getHyphaHome() {
|
|
6
|
+
return process.env.HYPHA_HOME || join(homedir(), ".hypha");
|
|
7
|
+
}
|
|
8
|
+
function getEnvFilePath() {
|
|
9
|
+
return join(getHyphaHome(), ".env");
|
|
10
|
+
}
|
|
11
|
+
function readEnvValue(key) {
|
|
12
|
+
const envFile = getEnvFilePath();
|
|
13
|
+
if (!existsSync(envFile)) return void 0;
|
|
14
|
+
const lines = readFileSync(envFile, "utf-8").split("\n");
|
|
15
|
+
for (const line of lines) {
|
|
16
|
+
const trimmed = line.trim();
|
|
17
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
18
|
+
const eqIdx = trimmed.indexOf("=");
|
|
19
|
+
if (eqIdx === -1) continue;
|
|
20
|
+
const k = trimmed.slice(0, eqIdx).trim();
|
|
21
|
+
const v = trimmed.slice(eqIdx + 1).trim().replace(/^["']|["']$/g, "");
|
|
22
|
+
if (k === key) return v;
|
|
23
|
+
}
|
|
24
|
+
return void 0;
|
|
25
|
+
}
|
|
26
|
+
function writeEnvValue(key, value) {
|
|
27
|
+
const envFile = getEnvFilePath();
|
|
28
|
+
const dir = getHyphaHome();
|
|
29
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
30
|
+
let lines = [];
|
|
31
|
+
if (existsSync(envFile)) {
|
|
32
|
+
lines = readFileSync(envFile, "utf-8").split("\n");
|
|
33
|
+
}
|
|
34
|
+
let found = false;
|
|
35
|
+
for (let i = 0; i < lines.length; i++) {
|
|
36
|
+
const trimmed = lines[i].trim();
|
|
37
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
38
|
+
const eqIdx = trimmed.indexOf("=");
|
|
39
|
+
if (eqIdx === -1) continue;
|
|
40
|
+
if (trimmed.slice(0, eqIdx).trim() === key) {
|
|
41
|
+
lines[i] = `${key}=${value}`;
|
|
42
|
+
found = true;
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (!found) {
|
|
47
|
+
lines.push(`${key}=${value}`);
|
|
48
|
+
}
|
|
49
|
+
writeFileSync(envFile, lines.join("\n") + "\n", { mode: 384 });
|
|
50
|
+
}
|
|
51
|
+
function resolveServerUrl(opts) {
|
|
52
|
+
return opts?.serverUrl || process.env.HYPHA_SERVER_URL || readEnvValue("HYPHA_SERVER_URL") || "https://hypha.aicell.io";
|
|
53
|
+
}
|
|
54
|
+
function resolveToken(opts) {
|
|
55
|
+
return opts?.token || process.env.HYPHA_TOKEN || readEnvValue("HYPHA_TOKEN");
|
|
56
|
+
}
|
|
57
|
+
function resolveWorkspace(opts) {
|
|
58
|
+
return opts?.workspace || process.env.HYPHA_WORKSPACE || readEnvValue("HYPHA_WORKSPACE");
|
|
59
|
+
}
|
|
60
|
+
async function connectToHypha(opts) {
|
|
61
|
+
const serverUrl = resolveServerUrl(opts);
|
|
62
|
+
const token = resolveToken(opts);
|
|
63
|
+
const workspace = resolveWorkspace(opts);
|
|
64
|
+
if (!token) {
|
|
65
|
+
console.error("No token found. Run `hypha login` first, or set HYPHA_TOKEN.");
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
const { hyphaWebsocketClient } = await import('hypha-rpc');
|
|
69
|
+
const server = await hyphaWebsocketClient.connectToServer({
|
|
70
|
+
server_url: serverUrl,
|
|
71
|
+
token,
|
|
72
|
+
workspace: workspace || void 0
|
|
73
|
+
});
|
|
74
|
+
return server;
|
|
75
|
+
}
|
|
76
|
+
async function loginToHypha(serverUrl) {
|
|
77
|
+
const url = serverUrl || resolveServerUrl();
|
|
78
|
+
const { hyphaWebsocketClient } = await import('hypha-rpc');
|
|
79
|
+
console.log(`Logging in to ${url}...`);
|
|
80
|
+
const token = await hyphaWebsocketClient.login({
|
|
81
|
+
server_url: url
|
|
82
|
+
});
|
|
83
|
+
if (!token) {
|
|
84
|
+
console.error("Login failed \u2014 no token received.");
|
|
85
|
+
process.exit(1);
|
|
86
|
+
}
|
|
87
|
+
const server = await hyphaWebsocketClient.connectToServer({
|
|
88
|
+
server_url: url,
|
|
89
|
+
token
|
|
90
|
+
});
|
|
91
|
+
const ws = server.config.workspace;
|
|
92
|
+
writeEnvValue("HYPHA_SERVER_URL", url);
|
|
93
|
+
writeEnvValue("HYPHA_TOKEN", token);
|
|
94
|
+
writeEnvValue("HYPHA_WORKSPACE", ws);
|
|
95
|
+
console.log(`Logged in to workspace: ${ws}`);
|
|
96
|
+
console.log(`Credentials saved to ${getEnvFilePath()}`);
|
|
97
|
+
await server.disconnect();
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function getFlag(args, flag, shortFlag) {
|
|
101
|
+
for (let i = 0; i < args.length; i++) {
|
|
102
|
+
if ((args[i] === flag || shortFlag && args[i] === shortFlag) && i + 1 < args.length) {
|
|
103
|
+
return args[i + 1];
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return void 0;
|
|
107
|
+
}
|
|
108
|
+
function getFlagInt(args, flag, shortFlag) {
|
|
109
|
+
const val = getFlag(args, flag, shortFlag);
|
|
110
|
+
if (val === void 0) return void 0;
|
|
111
|
+
const n = parseInt(val, 10);
|
|
112
|
+
return isNaN(n) ? void 0 : n;
|
|
113
|
+
}
|
|
114
|
+
function getAllFlags(args, flag) {
|
|
115
|
+
const results = [];
|
|
116
|
+
for (let i = 0; i < args.length; i++) {
|
|
117
|
+
if (args[i] === flag && i + 1 < args.length) {
|
|
118
|
+
results.push(args[i + 1]);
|
|
119
|
+
i++;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return results;
|
|
123
|
+
}
|
|
124
|
+
function hasFlag(args, ...flags) {
|
|
125
|
+
return args.some((a) => flags.includes(a));
|
|
126
|
+
}
|
|
127
|
+
function positionalArgs(args, knownFlags = []) {
|
|
128
|
+
const result = [];
|
|
129
|
+
for (let i = 0; i < args.length; i++) {
|
|
130
|
+
if (args[i].startsWith("-")) {
|
|
131
|
+
if (knownFlags.includes(args[i]) && i + 1 < args.length) {
|
|
132
|
+
i++;
|
|
133
|
+
}
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
result.push(args[i]);
|
|
137
|
+
}
|
|
138
|
+
return result;
|
|
139
|
+
}
|
|
140
|
+
function formatJson(data) {
|
|
141
|
+
return JSON.stringify(data, null, 2);
|
|
142
|
+
}
|
|
143
|
+
function formatTable(rows) {
|
|
144
|
+
if (rows.length === 0) return "";
|
|
145
|
+
const colCount = rows[0].length;
|
|
146
|
+
const widths = new Array(colCount).fill(0);
|
|
147
|
+
for (const row of rows) {
|
|
148
|
+
for (let i = 0; i < row.length; i++) {
|
|
149
|
+
widths[i] = Math.max(widths[i], (row[i] || "").length);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return rows.map(
|
|
153
|
+
(row) => row.map((cell, i) => (cell || "").padEnd(widths[i])).join(" ")
|
|
154
|
+
).join("\n");
|
|
155
|
+
}
|
|
156
|
+
function humanSize(bytes) {
|
|
157
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
158
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
159
|
+
if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
160
|
+
return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;
|
|
161
|
+
}
|
|
162
|
+
function relativeTime(timestamp) {
|
|
163
|
+
const diff = Date.now() - timestamp;
|
|
164
|
+
const seconds = Math.floor(diff / 1e3);
|
|
165
|
+
if (seconds < 60) return `${seconds}s ago`;
|
|
166
|
+
const minutes = Math.floor(seconds / 60);
|
|
167
|
+
if (minutes < 60) return `${minutes}m ago`;
|
|
168
|
+
const hours = Math.floor(minutes / 60);
|
|
169
|
+
if (hours < 24) return `${hours}h ago`;
|
|
170
|
+
const days = Math.floor(hours / 24);
|
|
171
|
+
return `${days}d ago`;
|
|
172
|
+
}
|
|
173
|
+
function printProgress(label, current, total) {
|
|
174
|
+
if (total <= 0) return;
|
|
175
|
+
const pct = Math.min(100, Math.round(current / total * 100));
|
|
176
|
+
const barWidth = 30;
|
|
177
|
+
const filled = Math.round(barWidth * (current / total));
|
|
178
|
+
const bar = "=".repeat(filled) + (filled < barWidth ? ">" : "") + " ".repeat(Math.max(0, barWidth - filled - 1));
|
|
179
|
+
const sizeStr = `${humanSize(current)}/${humanSize(total)}`;
|
|
180
|
+
const maxLabel = 25;
|
|
181
|
+
const displayLabel = label.length > maxLabel ? "..." + label.slice(-22) : label;
|
|
182
|
+
process.stderr.write(`\r ${displayLabel.padEnd(maxLabel)} [${bar}] ${pct}% ${sizeStr} `);
|
|
183
|
+
if (current >= total) {
|
|
184
|
+
process.stderr.write("\n");
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export { formatTable as a, resolveToken as b, connectToHypha as c, resolveWorkspace as d, hasFlag as e, formatJson as f, getFlagInt as g, humanSize as h, getFlag as i, relativeTime as j, getAllFlags as k, loginToHypha as l, printProgress as m, positionalArgs as p, resolveServerUrl as r };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { c as connectToHypha, f as formatJson, a as formatTable, h as humanSize, l as loginToHypha, r as resolveServerUrl, b as resolveToken, d as resolveWorkspace } from './helpers-BvfSCkvr.mjs';
|
|
2
|
+
export { d as determineCpDirection, i as isArtifactPath, p as parseArtifactPath } from './artifactPath-DCtvp6Go.mjs';
|
|
3
|
+
import 'fs';
|
|
4
|
+
import 'path';
|
|
5
|
+
import 'os';
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { e as hasFlag, l as loginToHypha, c as connectToHypha, g as getFlagInt, i as getFlag, f as formatJson, a as formatTable } from './helpers-BvfSCkvr.mjs';
|
|
2
|
+
import 'fs';
|
|
3
|
+
import 'path';
|
|
4
|
+
import 'os';
|
|
5
|
+
|
|
6
|
+
async function loginCommand(args) {
|
|
7
|
+
if (hasFlag(args, "--help", "-h")) {
|
|
8
|
+
console.log(`Usage: hypha login [server-url]
|
|
9
|
+
|
|
10
|
+
Login to a Hypha server via browser-based OAuth.
|
|
11
|
+
Credentials are saved to ~/.hypha/.env.
|
|
12
|
+
|
|
13
|
+
Default server: https://hypha.aicell.io`);
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const serverUrl = args[0] && !args[0].startsWith("-") ? args[0] : void 0;
|
|
17
|
+
await loginToHypha(serverUrl);
|
|
18
|
+
}
|
|
19
|
+
async function tokenCommand(args) {
|
|
20
|
+
if (hasFlag(args, "--help", "-h")) {
|
|
21
|
+
console.log(`Usage: hypha token [options]
|
|
22
|
+
|
|
23
|
+
Generate a workspace token.
|
|
24
|
+
|
|
25
|
+
Options:
|
|
26
|
+
--expires-in <seconds> Token expiration (default: 3600)
|
|
27
|
+
--permission <perm> Permission level: read, read_write, admin (default: read_write)
|
|
28
|
+
--workspace <ws> Target workspace (default: current)
|
|
29
|
+
--json Output as JSON`);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const server = await connectToHypha();
|
|
33
|
+
try {
|
|
34
|
+
const expiresIn = getFlagInt(args, "--expires-in") || 3600;
|
|
35
|
+
const permission = getFlag(args, "--permission") || "read_write";
|
|
36
|
+
const workspace = getFlag(args, "--workspace") || server.config.workspace;
|
|
37
|
+
const json = hasFlag(args, "--json");
|
|
38
|
+
const token = await server.generateToken({
|
|
39
|
+
expires_in: expiresIn,
|
|
40
|
+
permission,
|
|
41
|
+
workspace
|
|
42
|
+
});
|
|
43
|
+
if (json) {
|
|
44
|
+
console.log(formatJson({
|
|
45
|
+
token,
|
|
46
|
+
workspace,
|
|
47
|
+
permission,
|
|
48
|
+
expires_in: expiresIn
|
|
49
|
+
}));
|
|
50
|
+
} else {
|
|
51
|
+
console.log(token);
|
|
52
|
+
}
|
|
53
|
+
} finally {
|
|
54
|
+
await server.disconnect();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
async function servicesCommand(args) {
|
|
58
|
+
if (hasFlag(args, "--help", "-h")) {
|
|
59
|
+
console.log(`Usage: hypha services [options]
|
|
60
|
+
|
|
61
|
+
List services in the current workspace.
|
|
62
|
+
|
|
63
|
+
Options:
|
|
64
|
+
--type <type> Filter by service type
|
|
65
|
+
--include-unlisted Include unlisted services
|
|
66
|
+
--json Output as JSON`);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const server = await connectToHypha();
|
|
70
|
+
try {
|
|
71
|
+
const type = getFlag(args, "--type");
|
|
72
|
+
const includeUnlisted = hasFlag(args, "--include-unlisted");
|
|
73
|
+
const json = hasFlag(args, "--json");
|
|
74
|
+
const query = { _rkwargs: true };
|
|
75
|
+
if (type) query.type = type;
|
|
76
|
+
if (includeUnlisted) query.include_unlisted = true;
|
|
77
|
+
const services = await server.listServices(query);
|
|
78
|
+
if (json) {
|
|
79
|
+
console.log(formatJson(services));
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
if (!services || services.length === 0) {
|
|
83
|
+
console.log("No services found.");
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
const rows = [["ID", "NAME", "TYPE", "DESCRIPTION"]];
|
|
87
|
+
for (const svc of services) {
|
|
88
|
+
rows.push([
|
|
89
|
+
svc.id || "",
|
|
90
|
+
svc.name || "",
|
|
91
|
+
svc.type || "",
|
|
92
|
+
(svc.description || "").slice(0, 60)
|
|
93
|
+
]);
|
|
94
|
+
}
|
|
95
|
+
console.log(formatTable(rows));
|
|
96
|
+
} finally {
|
|
97
|
+
await server.disconnect();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
async function infoCommand(args) {
|
|
101
|
+
if (hasFlag(args, "--help", "-h")) {
|
|
102
|
+
console.log(`Usage: hypha info [--json]
|
|
103
|
+
|
|
104
|
+
Show workspace information.`);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const server = await connectToHypha();
|
|
108
|
+
try {
|
|
109
|
+
const json = hasFlag(args, "--json");
|
|
110
|
+
const info = {
|
|
111
|
+
server_url: server.config.server_url,
|
|
112
|
+
workspace: server.config.workspace,
|
|
113
|
+
client_id: server.config.client_id
|
|
114
|
+
};
|
|
115
|
+
if (json) {
|
|
116
|
+
console.log(formatJson(info));
|
|
117
|
+
} else {
|
|
118
|
+
console.log(`Server: ${info.server_url}`);
|
|
119
|
+
console.log(`Workspace: ${info.workspace}`);
|
|
120
|
+
console.log(`Client ID: ${info.client_id}`);
|
|
121
|
+
}
|
|
122
|
+
} finally {
|
|
123
|
+
await server.disconnect();
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export { infoCommand, loginCommand, servicesCommand, tokenCommand };
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "hypha-cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Hypha Cloud CLI — manage workspaces, apps, and artifacts",
|
|
5
|
+
"author": "Amun AI AB",
|
|
6
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"bin": {
|
|
9
|
+
"hypha": "./bin/hypha.mjs"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist",
|
|
13
|
+
"bin"
|
|
14
|
+
],
|
|
15
|
+
"main": "./dist/index.mjs",
|
|
16
|
+
"exports": {
|
|
17
|
+
".": "./dist/index.mjs",
|
|
18
|
+
"./cli": "./dist/cli.mjs"
|
|
19
|
+
},
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "tsc --noEmit && pkgroll",
|
|
22
|
+
"typecheck": "tsc --noEmit",
|
|
23
|
+
"test": "npx tsx test/test-cli-routing.mjs && npx tsx test/test-artifact-path.mjs && npx tsx test/test-apps-commands.mjs && npx tsx test/test-artifacts-commands.mjs && npx tsx test/test-helpers.mjs",
|
|
24
|
+
"test:integration": "npx tsx test/test-integration.mjs",
|
|
25
|
+
"dev": "tsx src/cli.ts"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"hypha-rpc": "0.21.29"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@types/node": ">=20",
|
|
32
|
+
"pkgroll": "^2.14.2",
|
|
33
|
+
"tsx": "^4.20.6",
|
|
34
|
+
"typescript": "5.9.3"
|
|
35
|
+
}
|
|
36
|
+
}
|