@getpaseo/cli 0.4.0-beta.2 → 0.5.0-beta.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/cli.js +6 -0
- package/dist/commands/daemon/index.js +3 -1
- package/dist/commands/daemon/reload.d.ts +10 -0
- package/dist/commands/daemon/reload.js +36 -0
- package/dist/commands/hub/deploy.d.ts +3 -1
- package/dist/commands/hub/deploy.js +7 -4
- package/dist/commands/hub/disconnect.js +2 -2
- package/dist/commands/hub/hub-client/index.d.ts +3 -2
- package/dist/commands/hub/hub-client/index.js +12 -1
- package/dist/commands/hub/hub-client/internal/contracts.d.ts +21 -0
- package/dist/commands/hub/hub-client/internal/contracts.js +15 -0
- package/dist/commands/hub/hub-client/internal/problem.js +16 -3
- package/dist/commands/hub/index.js +2 -0
- package/dist/commands/hub/init-plan.d.ts +50 -0
- package/dist/commands/hub/init-plan.js +136 -0
- package/dist/commands/hub/init.d.ts +20 -0
- package/dist/commands/hub/init.js +415 -0
- package/dist/commands/hub/logout.d.ts +1 -0
- package/dist/commands/hub/logout.js +10 -4
- package/dist/commands/plugin/index.d.ts +14 -0
- package/dist/commands/plugin/index.js +84 -0
- package/dist/commands/plugin/scaffold.d.ts +6 -0
- package/dist/commands/plugin/scaffold.js +307 -0
- package/dist/commands/plugin/shared.d.ts +4 -0
- package/dist/commands/plugin/shared.js +26 -0
- package/dist/commands/project/create.d.ts +10 -0
- package/dist/commands/project/create.js +41 -0
- package/dist/commands/project/delete.d.ts +9 -0
- package/dist/commands/project/delete.js +33 -0
- package/dist/commands/project/index.d.ts +3 -0
- package/dist/commands/project/index.js +28 -0
- package/dist/commands/project/ls.d.ts +5 -0
- package/dist/commands/project/ls.js +19 -0
- package/dist/commands/project/rename.d.ts +15 -0
- package/dist/commands/project/rename.js +50 -0
- package/dist/commands/project/shared.d.ts +11 -0
- package/dist/commands/project/shared.js +18 -0
- package/package.json +4 -4
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
import { mkdir, readdir, writeFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { PluginIdSchema } from "@getpaseo/protocol/messages";
|
|
4
|
+
const SDK_DECLARATIONS = `declare module "@paseo/plugin/server" {
|
|
5
|
+
import type { PaseoApi } from "@getpaseo/client";
|
|
6
|
+
import type { ZodType, input as ZodInput, output as ZodOutput } from "zod";
|
|
7
|
+
|
|
8
|
+
export interface PluginRpcContract<
|
|
9
|
+
InputSchema extends ZodType = ZodType,
|
|
10
|
+
OutputSchema extends ZodType = ZodType,
|
|
11
|
+
> {
|
|
12
|
+
name: string;
|
|
13
|
+
input: InputSchema;
|
|
14
|
+
output: OutputSchema;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface PluginAttachmentItem {
|
|
18
|
+
id: string;
|
|
19
|
+
identifier: string;
|
|
20
|
+
title: string;
|
|
21
|
+
subtitle?: string;
|
|
22
|
+
url: string;
|
|
23
|
+
text: string;
|
|
24
|
+
resourceType: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface PluginAttachmentSearchPayload {
|
|
28
|
+
items: PluginAttachmentItem[];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface PluginAttachmentSourceContribution {
|
|
32
|
+
id: string;
|
|
33
|
+
title: string;
|
|
34
|
+
icon: string;
|
|
35
|
+
pickerTitle: string;
|
|
36
|
+
searchPlaceholder: string;
|
|
37
|
+
search: PluginRpcContract;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface PluginHandlerContext {
|
|
41
|
+
paseo: PaseoApi;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function defineRpc<InputSchema extends ZodType, OutputSchema extends ZodType>(definition: {
|
|
45
|
+
name: string;
|
|
46
|
+
input: InputSchema;
|
|
47
|
+
output: OutputSchema;
|
|
48
|
+
}): PluginRpcContract<InputSchema, OutputSchema>;
|
|
49
|
+
|
|
50
|
+
export function defineAttachmentSource<Definition extends PluginAttachmentSourceContribution>(
|
|
51
|
+
definition: Definition,
|
|
52
|
+
): Definition;
|
|
53
|
+
|
|
54
|
+
export const PluginAttachmentItemSchema: import("zod").ZodType<PluginAttachmentItem>;
|
|
55
|
+
export const PluginAttachmentSearchPayloadSchema: import("zod").ZodType<PluginAttachmentSearchPayload>;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
declare module "@paseo/plugin" {
|
|
59
|
+
import type { ComponentType } from "react";
|
|
60
|
+
import type { PaseoApi } from "@getpaseo/client";
|
|
61
|
+
import type { ZodType, input as ZodInput, output as ZodOutput } from "zod";
|
|
62
|
+
import type {
|
|
63
|
+
PluginAttachmentSourceContribution,
|
|
64
|
+
PluginHandlerContext,
|
|
65
|
+
PluginRpcContract,
|
|
66
|
+
} from "@paseo/plugin/server";
|
|
67
|
+
|
|
68
|
+
export {
|
|
69
|
+
PluginAttachmentItemSchema,
|
|
70
|
+
PluginAttachmentSearchPayloadSchema,
|
|
71
|
+
defineAttachmentSource,
|
|
72
|
+
defineRpc,
|
|
73
|
+
type PluginAttachmentItem,
|
|
74
|
+
type PluginAttachmentSearchPayload,
|
|
75
|
+
type PluginAttachmentSourceContribution,
|
|
76
|
+
type PluginHandlerContext,
|
|
77
|
+
type PluginRpcContract,
|
|
78
|
+
} from "@paseo/plugin/server";
|
|
79
|
+
|
|
80
|
+
export interface PluginTheme {
|
|
81
|
+
readonly colors: {
|
|
82
|
+
readonly surface0: string;
|
|
83
|
+
readonly foreground: string;
|
|
84
|
+
readonly foregroundMuted: string;
|
|
85
|
+
readonly accent: string;
|
|
86
|
+
readonly accentForeground: string;
|
|
87
|
+
readonly statusDanger: string;
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export interface PluginHostProps {
|
|
92
|
+
theme: PluginTheme;
|
|
93
|
+
host: { id: string; label: string };
|
|
94
|
+
layout: { compact: boolean; platform: "ios" | "android" | "web" };
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export interface PluginSurfaceProps extends PluginHostProps {}
|
|
98
|
+
|
|
99
|
+
export interface PluginWorkspaceSnapshot {
|
|
100
|
+
readonly id: string;
|
|
101
|
+
readonly projectId: string;
|
|
102
|
+
readonly projectDisplayName: string;
|
|
103
|
+
readonly projectRootPath: string;
|
|
104
|
+
readonly directory: string;
|
|
105
|
+
readonly projectKind: "git" | "non_git" | "directory";
|
|
106
|
+
readonly kind: "directory" | "local_checkout" | "checkout" | "worktree";
|
|
107
|
+
readonly name: string;
|
|
108
|
+
readonly title: string | null;
|
|
109
|
+
readonly status: "needs_input" | "failed" | "running" | "attention" | "done";
|
|
110
|
+
readonly statusEnteredAt: string | null;
|
|
111
|
+
readonly archivingAt: string | null;
|
|
112
|
+
readonly diffStat: { readonly additions: number; readonly deletions: number } | null;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export interface PluginAgentSnapshot {
|
|
116
|
+
readonly id: string;
|
|
117
|
+
readonly workspaceId: string;
|
|
118
|
+
readonly provider: string;
|
|
119
|
+
readonly status: "initializing" | "idle" | "running" | "error" | "closed";
|
|
120
|
+
readonly createdAt: string;
|
|
121
|
+
readonly updatedAt: string;
|
|
122
|
+
readonly lastActivityAt: string;
|
|
123
|
+
readonly title: string | null;
|
|
124
|
+
readonly cwd: string;
|
|
125
|
+
readonly model: string | null;
|
|
126
|
+
readonly currentModeId: string | null;
|
|
127
|
+
readonly thinkingOptionId: string | null;
|
|
128
|
+
readonly requiresAttention: boolean;
|
|
129
|
+
readonly attentionReason: "finished" | "error" | "permission" | null;
|
|
130
|
+
readonly parentAgentId: string | null;
|
|
131
|
+
readonly labels: Readonly<Record<string, string>>;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export interface PluginWorkspacePanelProps extends PluginHostProps {
|
|
135
|
+
context: "workspace";
|
|
136
|
+
workspaceId: string;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export interface PluginAgentPanelProps extends PluginHostProps {
|
|
140
|
+
context: "agent";
|
|
141
|
+
workspaceId: string;
|
|
142
|
+
agentId: string;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export type PluginWorkspacePanelContribution =
|
|
146
|
+
| { id: string; title: string; icon: string; context: "workspace"; Component: ComponentType<PluginWorkspacePanelProps> }
|
|
147
|
+
| { id: string; title: string; icon: string; context: "agent"; Component: ComponentType<PluginAgentPanelProps> };
|
|
148
|
+
|
|
149
|
+
export interface PluginSidebarContribution {
|
|
150
|
+
id: string;
|
|
151
|
+
title: string;
|
|
152
|
+
icon: string;
|
|
153
|
+
surface: string;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export interface PluginSurfaceContribution {
|
|
157
|
+
id: string;
|
|
158
|
+
Component: ComponentType<PluginSurfaceProps>;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export interface PluginCommandCapabilities {
|
|
162
|
+
paseo: PaseoApi;
|
|
163
|
+
rpc<InputSchema extends ZodType, OutputSchema extends ZodType>(
|
|
164
|
+
contract: PluginRpcContract<InputSchema, OutputSchema>,
|
|
165
|
+
input: ZodInput<InputSchema>,
|
|
166
|
+
): Promise<ZodOutput<OutputSchema>>;
|
|
167
|
+
openSurface(id: string): void;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export interface PluginGlobalCommandContext extends PluginCommandCapabilities {
|
|
171
|
+
context: "global";
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export interface PluginWorkspaceCommandContext extends PluginCommandCapabilities {
|
|
175
|
+
context: "workspace";
|
|
176
|
+
workspace: PluginWorkspaceSnapshot;
|
|
177
|
+
openPanel(id: string): void;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export interface PluginAgentCommandContext extends PluginCommandCapabilities {
|
|
181
|
+
context: "agent";
|
|
182
|
+
workspace: PluginWorkspaceSnapshot;
|
|
183
|
+
agent: PluginAgentSnapshot;
|
|
184
|
+
openPanel(id: string): void;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export type PluginCommandCenterItemContribution =
|
|
188
|
+
| { id: string; title: string; icon: string; keywords?: readonly string[]; context: "global"; onSelect(context: PluginGlobalCommandContext): void | Promise<void> }
|
|
189
|
+
| { id: string; title: string; icon: string; keywords?: readonly string[]; context: "workspace"; onSelect(context: PluginWorkspaceCommandContext): void | Promise<void> }
|
|
190
|
+
| { id: string; title: string; icon: string; keywords?: readonly string[]; context: "agent"; onSelect(context: PluginAgentCommandContext): void | Promise<void> };
|
|
191
|
+
|
|
192
|
+
export interface PluginContext {
|
|
193
|
+
handle<InputSchema extends ZodType, OutputSchema extends ZodType>(
|
|
194
|
+
contract: PluginRpcContract<InputSchema, OutputSchema>,
|
|
195
|
+
handler: (
|
|
196
|
+
input: ZodOutput<InputSchema>,
|
|
197
|
+
context: PluginHandlerContext,
|
|
198
|
+
) => ZodInput<OutputSchema> | Promise<ZodInput<OutputSchema>>,
|
|
199
|
+
): void;
|
|
200
|
+
addSurface(id: string, Component: ComponentType<PluginSurfaceProps>): void;
|
|
201
|
+
addSidebarItem(contribution: PluginSidebarContribution): void;
|
|
202
|
+
addWorkspacePanel(contribution: PluginWorkspacePanelContribution): void;
|
|
203
|
+
addCommandCenterItem(contribution: PluginCommandCenterItemContribution): void;
|
|
204
|
+
addAttachmentSource(contribution: PluginAttachmentSourceContribution): void;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export type PluginCleanup = () => void | Promise<void>;
|
|
208
|
+
export type PluginContribution = (plugin: PluginContext) => PluginCleanup;
|
|
209
|
+
|
|
210
|
+
export function useRpc<InputSchema extends ZodType, OutputSchema extends ZodType>(
|
|
211
|
+
contract: PluginRpcContract<InputSchema, OutputSchema>,
|
|
212
|
+
): (input: ZodInput<InputSchema>) => Promise<ZodOutput<OutputSchema>>;
|
|
213
|
+
|
|
214
|
+
export function usePaseo(): PaseoApi;
|
|
215
|
+
|
|
216
|
+
export function useWorkspace<Selection>(
|
|
217
|
+
workspaceId: string,
|
|
218
|
+
selector: (workspace: PluginWorkspaceSnapshot) => Selection,
|
|
219
|
+
): Selection | null;
|
|
220
|
+
|
|
221
|
+
export function useAgent<Selection>(
|
|
222
|
+
agentId: string,
|
|
223
|
+
selector: (agent: PluginAgentSnapshot) => Selection,
|
|
224
|
+
): Selection | null;
|
|
225
|
+
}
|
|
226
|
+
`;
|
|
227
|
+
const TSCONFIG = {
|
|
228
|
+
compilerOptions: {
|
|
229
|
+
target: "ES2020",
|
|
230
|
+
module: "ESNext",
|
|
231
|
+
moduleResolution: "Bundler",
|
|
232
|
+
lib: ["ES2023", "DOM"],
|
|
233
|
+
jsx: "react-jsx",
|
|
234
|
+
strict: true,
|
|
235
|
+
skipLibCheck: true,
|
|
236
|
+
noEmit: true,
|
|
237
|
+
esModuleInterop: true,
|
|
238
|
+
allowSyntheticDefaultImports: true,
|
|
239
|
+
},
|
|
240
|
+
include: ["**/*.ts", "**/*.tsx"],
|
|
241
|
+
};
|
|
242
|
+
const ENTRY = `import type { PluginContext } from "@paseo/plugin";
|
|
243
|
+
import { MainSurface } from "./main.client";
|
|
244
|
+
|
|
245
|
+
export default function contribute(plugin: PluginContext) {
|
|
246
|
+
plugin.addSurface("main", MainSurface);
|
|
247
|
+
return () => {};
|
|
248
|
+
}
|
|
249
|
+
`;
|
|
250
|
+
const CLIENT_SURFACE = `import type { PluginSurfaceProps } from "@paseo/plugin";
|
|
251
|
+
import React, { useMemo } from "react";
|
|
252
|
+
import { Text, View } from "react-native";
|
|
253
|
+
|
|
254
|
+
export function MainSurface({ theme, layout }: PluginSurfaceProps) {
|
|
255
|
+
const styles = useMemo(
|
|
256
|
+
() => ({
|
|
257
|
+
screen: {
|
|
258
|
+
flex: 1,
|
|
259
|
+
padding: layout.compact ? 16 : 24,
|
|
260
|
+
backgroundColor: theme.colors.surface0,
|
|
261
|
+
},
|
|
262
|
+
text: { color: theme.colors.foreground },
|
|
263
|
+
}),
|
|
264
|
+
[theme, layout.compact],
|
|
265
|
+
);
|
|
266
|
+
return (
|
|
267
|
+
<View style={styles.screen}>
|
|
268
|
+
<Text style={styles.text}>Hello from my plugin</Text>
|
|
269
|
+
</View>
|
|
270
|
+
);
|
|
271
|
+
}
|
|
272
|
+
`;
|
|
273
|
+
export async function scaffoldPluginDirectory(targetDirectory, requestedId) {
|
|
274
|
+
const directory = path.resolve(targetDirectory);
|
|
275
|
+
const id = PluginIdSchema.parse(requestedId ?? path.basename(directory));
|
|
276
|
+
await mkdir(directory, { recursive: true });
|
|
277
|
+
const existing = await readdir(directory);
|
|
278
|
+
if (existing.length > 0) {
|
|
279
|
+
throw new Error(`Plugin directory must be empty: ${directory}`);
|
|
280
|
+
}
|
|
281
|
+
const packageJson = {
|
|
282
|
+
name: id,
|
|
283
|
+
private: true,
|
|
284
|
+
version: "0.0.0",
|
|
285
|
+
scripts: { typecheck: "tsc --noEmit" },
|
|
286
|
+
devDependencies: {
|
|
287
|
+
"@getpaseo/client": "^0.4.0",
|
|
288
|
+
"@tanstack/react-query": "^5.90.11",
|
|
289
|
+
"@types/react": "~19.2.0",
|
|
290
|
+
react: "19.1.0",
|
|
291
|
+
"react-native": "0.81.5",
|
|
292
|
+
typescript: "^5.9.3",
|
|
293
|
+
zod: "^4.4.3",
|
|
294
|
+
},
|
|
295
|
+
};
|
|
296
|
+
const files = new Map([
|
|
297
|
+
["paseo-plugin.json", `${JSON.stringify({ id }, null, 2)}\n`],
|
|
298
|
+
["package.json", `${JSON.stringify(packageJson, null, 2)}\n`],
|
|
299
|
+
["tsconfig.json", `${JSON.stringify(TSCONFIG, null, 2)}\n`],
|
|
300
|
+
["paseo-plugin.d.ts", SDK_DECLARATIONS],
|
|
301
|
+
["index.ts", ENTRY],
|
|
302
|
+
["main.client.tsx", CLIENT_SURFACE],
|
|
303
|
+
]);
|
|
304
|
+
await Promise.all([...files].map(([filename, contents]) => writeFile(path.join(directory, filename), contents, { flag: "wx" })));
|
|
305
|
+
return { id, directory };
|
|
306
|
+
}
|
|
307
|
+
//# sourceMappingURL=scaffold.js.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { DaemonClient } from "@getpaseo/client/internal/daemon-client";
|
|
2
|
+
export declare function withPluginManagementClient<T>(host: string | undefined, run: (client: DaemonClient) => Promise<T>): Promise<T>;
|
|
3
|
+
export declare function withPluginLogsClient<T>(host: string | undefined, run: (client: DaemonClient) => Promise<T>): Promise<T>;
|
|
4
|
+
//# sourceMappingURL=shared.d.ts.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { connectToDaemon } from "../../utils/client.js";
|
|
2
|
+
async function withPluginClient(host, feature, updateMessage, run) {
|
|
3
|
+
const client = await connectToDaemon({ host });
|
|
4
|
+
if (client.getLastServerInfoMessage()?.features?.[feature] !== true) {
|
|
5
|
+
await client.close().catch(() => undefined);
|
|
6
|
+
throw {
|
|
7
|
+
code: "DAEMON_UPDATE_REQUIRED",
|
|
8
|
+
message: updateMessage,
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
try {
|
|
12
|
+
return await run(client);
|
|
13
|
+
}
|
|
14
|
+
finally {
|
|
15
|
+
await client.close().catch(() => undefined);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export async function withPluginManagementClient(host, run) {
|
|
19
|
+
// COMPAT(pluginManagement): added in v0.3.1, remove gate after 2027-08-14.
|
|
20
|
+
return withPluginClient(host, "pluginManagement", "Update the host to use plugin management.", run);
|
|
21
|
+
}
|
|
22
|
+
export async function withPluginLogsClient(host, run) {
|
|
23
|
+
// COMPAT(pluginLogs): added in v0.4.0, remove gate after 2027-08-16.
|
|
24
|
+
return withPluginClient(host, "pluginLogs", "Update the host to view plugin logs.", run);
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=shared.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import type { CommandOptions, SingleResult } from "../../output/index.js";
|
|
3
|
+
import { type ProjectRow } from "./shared.js";
|
|
4
|
+
export declare function resolveProjectPath(input: {
|
|
5
|
+
pathArg?: string;
|
|
6
|
+
cwd: string;
|
|
7
|
+
daemonTarget?: string;
|
|
8
|
+
}): string;
|
|
9
|
+
export declare function runCreateCommand(pathArg: string | undefined, options: CommandOptions, _command: Command): Promise<SingleResult<ProjectRow>>;
|
|
10
|
+
//# sourceMappingURL=create.d.ts.map
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { buildDaemonConnectionCommandError, connectToDaemon } from "../../utils/client.js";
|
|
3
|
+
import { projectSchema, toProjectRow } from "./shared.js";
|
|
4
|
+
export function resolveProjectPath(input) {
|
|
5
|
+
if (input.daemonTarget) {
|
|
6
|
+
if (input.pathArg === undefined) {
|
|
7
|
+
throw {
|
|
8
|
+
code: "MISSING_PATH",
|
|
9
|
+
message: "Project path is required when targeting a daemon explicitly",
|
|
10
|
+
details: "Usage: paseo project create <path> --host <host>",
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
return input.pathArg;
|
|
14
|
+
}
|
|
15
|
+
return path.resolve(input.cwd, input.pathArg ?? ".");
|
|
16
|
+
}
|
|
17
|
+
export async function runCreateCommand(pathArg, options, _command) {
|
|
18
|
+
const projectPath = resolveProjectPath({
|
|
19
|
+
pathArg,
|
|
20
|
+
cwd: process.cwd(),
|
|
21
|
+
daemonTarget: options.host ?? process.env.PASEO_HOST,
|
|
22
|
+
});
|
|
23
|
+
const client = await connectToDaemon({ host: options.host }).catch((error) => {
|
|
24
|
+
throw buildDaemonConnectionCommandError({ host: options.host, error });
|
|
25
|
+
});
|
|
26
|
+
try {
|
|
27
|
+
const payload = await client.addProject(projectPath);
|
|
28
|
+
if (!payload.project) {
|
|
29
|
+
throw new Error(payload.error ?? "Project creation failed");
|
|
30
|
+
}
|
|
31
|
+
return { type: "single", data: toProjectRow(payload.project), schema: projectSchema };
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
35
|
+
throw { code: "PROJECT_CREATE_FAILED", message };
|
|
36
|
+
}
|
|
37
|
+
finally {
|
|
38
|
+
await client.close().catch(() => undefined);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=create.js.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import type { CommandOptions, SingleResult } from "../../output/index.js";
|
|
3
|
+
interface ProjectDeleteResult {
|
|
4
|
+
projectId: string;
|
|
5
|
+
removedWorkspaceIds: string[];
|
|
6
|
+
}
|
|
7
|
+
export declare function runDeleteCommand(projectId: string, options: CommandOptions, _command: Command): Promise<SingleResult<ProjectDeleteResult>>;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=delete.d.ts.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { buildDaemonConnectionCommandError, connectToDaemon } from "../../utils/client.js";
|
|
2
|
+
const projectDeleteSchema = {
|
|
3
|
+
idField: "projectId",
|
|
4
|
+
columns: [
|
|
5
|
+
{ header: "PROJECT ID", field: "projectId", width: 20 },
|
|
6
|
+
{
|
|
7
|
+
header: "REMOVED WORKSPACES",
|
|
8
|
+
field: (result) => result.removedWorkspaceIds.length,
|
|
9
|
+
width: 18,
|
|
10
|
+
},
|
|
11
|
+
],
|
|
12
|
+
};
|
|
13
|
+
export async function runDeleteCommand(projectId, options, _command) {
|
|
14
|
+
const client = await connectToDaemon({ host: options.host }).catch((error) => {
|
|
15
|
+
throw buildDaemonConnectionCommandError({ host: options.host, error });
|
|
16
|
+
});
|
|
17
|
+
try {
|
|
18
|
+
const result = await client.removeProject(projectId);
|
|
19
|
+
return {
|
|
20
|
+
type: "single",
|
|
21
|
+
data: { projectId, removedWorkspaceIds: result.removedWorkspaceIds },
|
|
22
|
+
schema: projectDeleteSchema,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
27
|
+
throw { code: "PROJECT_DELETE_FAILED", message };
|
|
28
|
+
}
|
|
29
|
+
finally {
|
|
30
|
+
await client.close().catch(() => undefined);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=delete.js.map
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { withOutput } from "../../output/index.js";
|
|
3
|
+
import { addJsonAndDaemonHostOptions } from "../../utils/command-options.js";
|
|
4
|
+
import { runCreateCommand } from "./create.js";
|
|
5
|
+
import { runDeleteCommand } from "./delete.js";
|
|
6
|
+
import { runLsCommand } from "./ls.js";
|
|
7
|
+
import { runRenameCommand } from "./rename.js";
|
|
8
|
+
export function createProjectCommand() {
|
|
9
|
+
const project = new Command("project").description("Manage projects");
|
|
10
|
+
addJsonAndDaemonHostOptions(project
|
|
11
|
+
.command("create")
|
|
12
|
+
.description("Register a project directory")
|
|
13
|
+
.argument("[path]", "Project directory (default: current directory)")).action(withOutput(runCreateCommand));
|
|
14
|
+
addJsonAndDaemonHostOptions(project.command("ls").description("List projects")).action(withOutput(runLsCommand));
|
|
15
|
+
addJsonAndDaemonHostOptions(project
|
|
16
|
+
.command("rename")
|
|
17
|
+
.description("Set a project's user-visible name")
|
|
18
|
+
.argument("<project-id>", "Project id")
|
|
19
|
+
.argument("[name]", "New project name")
|
|
20
|
+
.option("--reset", "Clear the custom name and use the directory name")
|
|
21
|
+
.allowExcessArguments(false)).action(withOutput(runRenameCommand));
|
|
22
|
+
addJsonAndDaemonHostOptions(project
|
|
23
|
+
.command("delete")
|
|
24
|
+
.description("Delete a project and its workspaces")
|
|
25
|
+
.argument("<project-id>", "Project id")).action(withOutput(runDeleteCommand));
|
|
26
|
+
return project;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import type { CommandOptions, ListResult } from "../../output/index.js";
|
|
3
|
+
import { type ProjectRow } from "./shared.js";
|
|
4
|
+
export declare function runLsCommand(options: CommandOptions, _command: Command): Promise<ListResult<ProjectRow>>;
|
|
5
|
+
//# sourceMappingURL=ls.d.ts.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { buildDaemonConnectionCommandError, connectToDaemon } from "../../utils/client.js";
|
|
2
|
+
import { projectSchema, toProjectRow } from "./shared.js";
|
|
3
|
+
export async function runLsCommand(options, _command) {
|
|
4
|
+
const client = await connectToDaemon({ host: options.host }).catch((error) => {
|
|
5
|
+
throw buildDaemonConnectionCommandError({ host: options.host, error });
|
|
6
|
+
});
|
|
7
|
+
try {
|
|
8
|
+
const payload = await client.listProjects();
|
|
9
|
+
return {
|
|
10
|
+
type: "list",
|
|
11
|
+
data: payload.projects.map(toProjectRow),
|
|
12
|
+
schema: projectSchema,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
finally {
|
|
16
|
+
await client.close().catch(() => undefined);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=ls.js.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import type { CommandOptions, SingleResult } from "../../output/index.js";
|
|
3
|
+
interface ProjectRenameResult {
|
|
4
|
+
projectId: string;
|
|
5
|
+
name: string | null;
|
|
6
|
+
}
|
|
7
|
+
export declare function resolveProjectName(input: {
|
|
8
|
+
name?: string;
|
|
9
|
+
reset?: boolean;
|
|
10
|
+
}): string | null;
|
|
11
|
+
export declare function runRenameCommand(projectId: string, nameArg: string | undefined, options: CommandOptions & {
|
|
12
|
+
reset?: boolean;
|
|
13
|
+
}, _command: Command): Promise<SingleResult<ProjectRenameResult>>;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=rename.d.ts.map
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { buildDaemonConnectionCommandError, connectToDaemon } from "../../utils/client.js";
|
|
2
|
+
const projectRenameSchema = {
|
|
3
|
+
idField: "projectId",
|
|
4
|
+
columns: [
|
|
5
|
+
{ header: "PROJECT ID", field: "projectId", width: 20 },
|
|
6
|
+
{ header: "NAME", field: "name", width: 30 },
|
|
7
|
+
],
|
|
8
|
+
};
|
|
9
|
+
export function resolveProjectName(input) {
|
|
10
|
+
if (input.reset) {
|
|
11
|
+
if (input.name !== undefined) {
|
|
12
|
+
throw {
|
|
13
|
+
code: "INVALID_OPTIONS",
|
|
14
|
+
message: "--reset cannot be combined with a name",
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
const name = input.name?.trim() ?? "";
|
|
20
|
+
if (name.length === 0) {
|
|
21
|
+
throw {
|
|
22
|
+
code: "MISSING_NAME",
|
|
23
|
+
message: "Project name cannot be empty",
|
|
24
|
+
details: "Usage: paseo project rename <project-id> <name> | --reset",
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
return name;
|
|
28
|
+
}
|
|
29
|
+
export async function runRenameCommand(projectId, nameArg, options, _command) {
|
|
30
|
+
const name = resolveProjectName({ name: nameArg, reset: options.reset });
|
|
31
|
+
const client = await connectToDaemon({ host: options.host }).catch((error) => {
|
|
32
|
+
throw buildDaemonConnectionCommandError({ host: options.host, error });
|
|
33
|
+
});
|
|
34
|
+
try {
|
|
35
|
+
const applied = await client.renameProject(projectId, name);
|
|
36
|
+
return {
|
|
37
|
+
type: "single",
|
|
38
|
+
data: { projectId, name: applied.customName },
|
|
39
|
+
schema: projectRenameSchema,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
44
|
+
throw { code: "PROJECT_RENAME_FAILED", message };
|
|
45
|
+
}
|
|
46
|
+
finally {
|
|
47
|
+
await client.close().catch(() => undefined);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=rename.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { WorkspaceProjectDescriptorPayload } from "@getpaseo/protocol/messages";
|
|
2
|
+
import type { OutputSchema } from "../../output/index.js";
|
|
3
|
+
export interface ProjectRow {
|
|
4
|
+
projectId: string;
|
|
5
|
+
name: string;
|
|
6
|
+
kind: "git" | "non_git" | "directory";
|
|
7
|
+
path: string;
|
|
8
|
+
}
|
|
9
|
+
export declare const projectSchema: OutputSchema<ProjectRow>;
|
|
10
|
+
export declare function toProjectRow(project: WorkspaceProjectDescriptorPayload): ProjectRow;
|
|
11
|
+
//# sourceMappingURL=shared.d.ts.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export const projectSchema = {
|
|
2
|
+
idField: "projectId",
|
|
3
|
+
columns: [
|
|
4
|
+
{ header: "PROJECT ID", field: "projectId", width: 20 },
|
|
5
|
+
{ header: "NAME", field: "name", width: 24 },
|
|
6
|
+
{ header: "KIND", field: "kind", width: 10 },
|
|
7
|
+
{ header: "PATH", field: "path", width: 42 },
|
|
8
|
+
],
|
|
9
|
+
};
|
|
10
|
+
export function toProjectRow(project) {
|
|
11
|
+
return {
|
|
12
|
+
projectId: project.projectId,
|
|
13
|
+
name: project.projectDisplayName,
|
|
14
|
+
kind: project.projectKind,
|
|
15
|
+
path: project.projectRootPath,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=shared.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getpaseo/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0-beta.1",
|
|
4
4
|
"description": "Paseo CLI - control your AI coding agents from the command line",
|
|
5
5
|
"bin": {
|
|
6
6
|
"paseo": "bin/paseo"
|
|
@@ -28,9 +28,9 @@
|
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@clack/prompts": "^1.0.0",
|
|
31
|
-
"@getpaseo/client": "0.
|
|
32
|
-
"@getpaseo/protocol": "0.
|
|
33
|
-
"@getpaseo/server": "0.
|
|
31
|
+
"@getpaseo/client": "0.5.0-beta.1",
|
|
32
|
+
"@getpaseo/protocol": "0.5.0-beta.1",
|
|
33
|
+
"@getpaseo/server": "0.5.0-beta.1",
|
|
34
34
|
"chalk": "^5.3.0",
|
|
35
35
|
"commander": "^12.0.0",
|
|
36
36
|
"mime-types": "^2.1.35",
|