@getpaseo/cli 0.1.107 → 0.1.108
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/cli.js +8 -0
- package/dist/commands/agent/delete.js +1 -1
- package/dist/commands/clone.d.ts +17 -0
- package/dist/commands/clone.js +65 -0
- package/dist/utils/client.d.ts +9 -0
- package/dist/utils/client.js +9 -0
- package/package.json +4 -4
package/dist/cli.js
CHANGED
|
@@ -25,6 +25,7 @@ import { addArchiveOptions, runArchiveCommand } from "./commands/agent/archive.j
|
|
|
25
25
|
import { addAttachOptions, runAttachCommand } from "./commands/agent/attach.js";
|
|
26
26
|
import { addImportOptions, runImportCommand } from "./commands/agent/import.js";
|
|
27
27
|
import { withOutput } from "./output/index.js";
|
|
28
|
+
import { runCloneCommand } from "./commands/clone.js";
|
|
28
29
|
import { onboardCommand } from "./commands/onboard.js";
|
|
29
30
|
import { addDaemonHostOption, addJsonAndDaemonHostOptions, addJsonOption, } from "./utils/command-options.js";
|
|
30
31
|
import { resolveCliVersion } from "./version.js";
|
|
@@ -52,6 +53,13 @@ export function createCli() {
|
|
|
52
53
|
addJsonAndDaemonHostOptions(addLsOptions(program.command("ls"))).action(withOutput(runLsCommand));
|
|
53
54
|
addJsonAndDaemonHostOptions(addRunOptions(program.command("run"))).action(withOutput(runRunCommand));
|
|
54
55
|
addJsonAndDaemonHostOptions(addImportOptions(program.command("import"))).action(withOutput(runImportCommand));
|
|
56
|
+
addJsonAndDaemonHostOptions(program
|
|
57
|
+
.command("clone")
|
|
58
|
+
.description("Clone a GitHub repo and register it as a Paseo workspace")
|
|
59
|
+
.argument("<repo>", "GitHub repo in owner/repo format or a full git remote URL")
|
|
60
|
+
.requiredOption("--dir <path>", "Parent directory to clone into (for example: ~/workspace)"))
|
|
61
|
+
.addOption(new Option("--protocol <protocol>", "Protocol for owner/repo shorthand repositories").choices(["https", "ssh"]))
|
|
62
|
+
.action(withOutput(runCloneCommand));
|
|
55
63
|
addDaemonHostOption(addAttachOptions(program.command("attach"))).action(runAttachCommand);
|
|
56
64
|
addDaemonHostOption(addLogsOptions(program.command("logs"))).action(runLogsCommand);
|
|
57
65
|
addJsonAndDaemonHostOptions(addStopOptions(program.command("stop"))).action(withOutput(runStopCommand));
|
|
@@ -63,7 +63,7 @@ export async function runDeleteCommand(id, options, _command) {
|
|
|
63
63
|
const deleteResults = await Promise.all(agents.map(async (agent) => {
|
|
64
64
|
try {
|
|
65
65
|
if (agent.status === "running") {
|
|
66
|
-
await client.cancelAgent(agent.id);
|
|
66
|
+
await client.cancelAgent(agent.id).catch(() => { });
|
|
67
67
|
}
|
|
68
68
|
await client.deleteAgent(agent.id);
|
|
69
69
|
return { ok: true, id: agent.id };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import type { OutputSchema, SingleResult } from "../output/index.js";
|
|
3
|
+
import type { CommandOptions } from "../output/with-output.js";
|
|
4
|
+
type CloneProtocol = "https" | "ssh";
|
|
5
|
+
interface CloneCommandOptions extends CommandOptions {
|
|
6
|
+
protocol?: CloneProtocol;
|
|
7
|
+
}
|
|
8
|
+
export interface CloneResult {
|
|
9
|
+
repo: string;
|
|
10
|
+
checkoutPath: string;
|
|
11
|
+
projectId: string;
|
|
12
|
+
projectName: string;
|
|
13
|
+
}
|
|
14
|
+
export declare const cloneSchema: OutputSchema<CloneResult>;
|
|
15
|
+
export declare function runCloneCommand(repo: string, options: CloneCommandOptions, _command: Command): Promise<SingleResult<CloneResult>>;
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=clone.d.ts.map
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { isCompleteGitRemote } from "@getpaseo/protocol/git-remote";
|
|
2
|
+
import { buildDaemonConnectionCommandError, connectToDaemon } from "../utils/client.js";
|
|
3
|
+
export const cloneSchema = {
|
|
4
|
+
idField: "projectId",
|
|
5
|
+
columns: [
|
|
6
|
+
{ header: "REPO", field: "repo", width: 28 },
|
|
7
|
+
{ header: "PROJECT", field: "projectName", width: 28 },
|
|
8
|
+
{ header: "PATH", field: "checkoutPath", width: 56 },
|
|
9
|
+
],
|
|
10
|
+
};
|
|
11
|
+
function cmdError(code, message, details) {
|
|
12
|
+
return details ? { code, message, details } : { code, message };
|
|
13
|
+
}
|
|
14
|
+
export async function runCloneCommand(repo, options, _command) {
|
|
15
|
+
const targetDirectory = typeof options.dir === "string" ? options.dir.trim() : "";
|
|
16
|
+
if (!targetDirectory) {
|
|
17
|
+
throw cmdError("INVALID_ARGUMENT", "--dir is required");
|
|
18
|
+
}
|
|
19
|
+
const repoIsCompleteRemote = isCompleteGitRemote(repo);
|
|
20
|
+
if (!repoIsCompleteRemote && !options.protocol) {
|
|
21
|
+
throw cmdError("INVALID_ARGUMENT", "--protocol is required for owner/repo repository names");
|
|
22
|
+
}
|
|
23
|
+
let client;
|
|
24
|
+
try {
|
|
25
|
+
client = await connectToDaemon({ host: options.host });
|
|
26
|
+
}
|
|
27
|
+
catch (err) {
|
|
28
|
+
throw buildDaemonConnectionCommandError({ host: options.host, error: err });
|
|
29
|
+
}
|
|
30
|
+
if (client.getLastServerInfoMessage()?.features?.projectGithubClone !== true) {
|
|
31
|
+
await client.close().catch(() => { });
|
|
32
|
+
throw cmdError("UNSUPPORTED_BY_HOST", "This daemon does not support cloning GitHub repos.", "Update the host to a newer Paseo version.");
|
|
33
|
+
}
|
|
34
|
+
try {
|
|
35
|
+
const response = await client.cloneGithubProject({
|
|
36
|
+
repo,
|
|
37
|
+
targetDirectory,
|
|
38
|
+
...(repoIsCompleteRemote ? {} : { cloneProtocol: options.protocol }),
|
|
39
|
+
});
|
|
40
|
+
if (response.error || !response.project || !response.checkoutPath) {
|
|
41
|
+
throw cmdError("CLONE_FAILED", `Failed to clone GitHub repo: ${response.error ?? "no project returned"}`);
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
type: "single",
|
|
45
|
+
data: {
|
|
46
|
+
repo: response.repo,
|
|
47
|
+
checkoutPath: response.checkoutPath,
|
|
48
|
+
projectId: response.project.projectId,
|
|
49
|
+
projectName: response.project.projectDisplayName,
|
|
50
|
+
},
|
|
51
|
+
schema: cloneSchema,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
if (err && typeof err === "object" && "code" in err) {
|
|
56
|
+
throw err;
|
|
57
|
+
}
|
|
58
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
59
|
+
throw cmdError("CLONE_FAILED", `Failed to clone GitHub repo: ${message}`);
|
|
60
|
+
}
|
|
61
|
+
finally {
|
|
62
|
+
await client.close().catch(() => { });
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=clone.js.map
|
package/dist/utils/client.d.ts
CHANGED
|
@@ -3,6 +3,11 @@ export interface ConnectOptions {
|
|
|
3
3
|
host?: string;
|
|
4
4
|
timeout?: number;
|
|
5
5
|
}
|
|
6
|
+
export interface DaemonConnectionCommandError {
|
|
7
|
+
code: "DAEMON_NOT_RUNNING";
|
|
8
|
+
message: string;
|
|
9
|
+
details: string;
|
|
10
|
+
}
|
|
6
11
|
type DaemonTarget = {
|
|
7
12
|
type: "tcp";
|
|
8
13
|
url: string;
|
|
@@ -15,6 +20,10 @@ type DaemonTarget = {
|
|
|
15
20
|
* Get the daemon host from environment or options
|
|
16
21
|
*/
|
|
17
22
|
export declare function getDaemonHost(options?: ConnectOptions): string;
|
|
23
|
+
export declare function buildDaemonConnectionCommandError(options: {
|
|
24
|
+
host?: string;
|
|
25
|
+
error: unknown;
|
|
26
|
+
}): DaemonConnectionCommandError;
|
|
18
27
|
export declare function normalizeDaemonHost(raw: string): string | null;
|
|
19
28
|
export declare function resolveDefaultDaemonHost(env?: NodeJS.ProcessEnv): string;
|
|
20
29
|
export declare function resolveDefaultDaemonHosts(env?: NodeJS.ProcessEnv): string[];
|
package/dist/utils/client.js
CHANGED
|
@@ -16,6 +16,15 @@ const PID_FILENAME = "paseo.pid";
|
|
|
16
16
|
export function getDaemonHost(options) {
|
|
17
17
|
return resolveDaemonHostCandidates(options)[0] ?? DEFAULT_HOST;
|
|
18
18
|
}
|
|
19
|
+
export function buildDaemonConnectionCommandError(options) {
|
|
20
|
+
const host = getDaemonHost({ host: options.host });
|
|
21
|
+
const message = options.error instanceof Error ? options.error.message : String(options.error);
|
|
22
|
+
return {
|
|
23
|
+
code: "DAEMON_NOT_RUNNING",
|
|
24
|
+
message: `Cannot connect to daemon at ${host}: ${message}`,
|
|
25
|
+
details: "Start the daemon with: paseo daemon start",
|
|
26
|
+
};
|
|
27
|
+
}
|
|
19
28
|
export function normalizeDaemonHost(raw) {
|
|
20
29
|
const trimmed = raw.trim();
|
|
21
30
|
if (!trimmed) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getpaseo/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.108",
|
|
4
4
|
"description": "Paseo CLI - control your AI coding agents from the command line",
|
|
5
5
|
"bin": {
|
|
6
6
|
"paseo": "bin/paseo"
|
|
@@ -27,9 +27,9 @@
|
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@clack/prompts": "^1.0.0",
|
|
30
|
-
"@getpaseo/client": "0.1.
|
|
31
|
-
"@getpaseo/protocol": "0.1.
|
|
32
|
-
"@getpaseo/server": "0.1.
|
|
30
|
+
"@getpaseo/client": "0.1.108",
|
|
31
|
+
"@getpaseo/protocol": "0.1.108",
|
|
32
|
+
"@getpaseo/server": "0.1.108",
|
|
33
33
|
"chalk": "^5.3.0",
|
|
34
34
|
"commander": "^12.0.0",
|
|
35
35
|
"mime-types": "^2.1.35",
|