@getpaseo/cli 0.6.1 → 0.7.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.
@@ -78,6 +78,17 @@ function toListItem(agent) {
78
78
  created: relativeTime(agent.createdAt),
79
79
  };
80
80
  }
81
+ function daemonConnectionFailure(host, cause) {
82
+ const reason = cause instanceof Error ? cause.message : String(cause);
83
+ return {
84
+ code: "DAEMON_NOT_RUNNING",
85
+ message: `Cannot reach the daemon at ${host}: ${reason}`,
86
+ details: [
87
+ "Start a local daemon with: paseo daemon start",
88
+ "To use another daemon, pass --host <host:port> or set PASEO_HOST.",
89
+ ].join("\n"),
90
+ };
91
+ }
81
92
  function parseLabelFilters(labels) {
82
93
  const labelFilters = {};
83
94
  for (const labelStr of labels ?? []) {
@@ -126,13 +137,7 @@ export async function runLsCommand(options, _command) {
126
137
  client = await connectToDaemon({ host: options.host });
127
138
  }
128
139
  catch (err) {
129
- const message = err instanceof Error ? err.message : String(err);
130
- const error = {
131
- code: "DAEMON_NOT_RUNNING",
132
- message: `Cannot connect to daemon at ${host}: ${message}`,
133
- details: "Start the daemon with: paseo daemon start\nFor a remote daemon, pass --host <host:port> or set PASEO_HOST.",
134
- };
135
- throw error;
140
+ throw daemonConnectionFailure(host, err);
136
141
  }
137
142
  try {
138
143
  const normalizedThinkingOptionId = options.thinking?.trim();
@@ -5,6 +5,9 @@ import { type PluginScaffold } from "./scaffold.js";
5
5
  interface PluginOptions extends CommandOptions {
6
6
  host?: string;
7
7
  id?: string;
8
+ ref?: string;
9
+ path?: string;
10
+ all?: boolean;
8
11
  }
9
12
  export declare function runPluginInitCommand(directory: string, options: PluginOptions, _command: Command): Promise<SingleResult<PluginScaffold>>;
10
13
  export declare function runPluginListCommand(options: PluginOptions, _command: Command): Promise<ListResult<PluginListItem>>;
@@ -1,8 +1,9 @@
1
1
  import { Command } from "commander";
2
+ import path from "node:path";
2
3
  import { withOutput } from "../../output/index.js";
3
4
  import { addJsonAndDaemonHostOptions, addJsonOption } from "../../utils/command-options.js";
4
5
  import { scaffoldPluginDirectory } from "./scaffold.js";
5
- import { withPluginLogsClient, withPluginManagementClient } from "./shared.js";
6
+ import { withPluginLogsClient, withPluginManagementClient, withPluginSourceClient, } from "./shared.js";
6
7
  const pluginSchema = {
7
8
  idField: "id",
8
9
  columns: [
@@ -28,6 +29,30 @@ const pluginLogsSchema = {
28
29
  { header: "MESSAGE", field: "message", width: 80 },
29
30
  ],
30
31
  };
32
+ function shortCommit(commit) {
33
+ return commit?.slice(0, 12) ?? "-";
34
+ }
35
+ const pluginStatusSchema = {
36
+ idField: "id",
37
+ columns: [
38
+ { header: "PLUGIN", field: "id", width: 20 },
39
+ { header: "SOURCE", field: "source", width: 10 },
40
+ { header: "CURRENT", field: (plugin) => shortCommit(plugin.currentCommit), width: 14 },
41
+ { header: "LATEST", field: (plugin) => shortCommit(plugin.latestCommit), width: 14 },
42
+ { header: "COMMITS", field: (plugin) => String(plugin.commitsBehind ?? 0), width: 8 },
43
+ { header: "REF", field: (plugin) => plugin.ref ?? "-", width: 24 },
44
+ ],
45
+ };
46
+ const pluginUpdateSchema = {
47
+ idField: "id",
48
+ columns: [
49
+ { header: "PLUGIN", field: "id", width: 20 },
50
+ { header: "PREVIOUS", field: (plugin) => shortCommit(plugin.previousCommit), width: 14 },
51
+ { header: "CURRENT", field: (plugin) => shortCommit(plugin.currentCommit), width: 14 },
52
+ { header: "COMMITS", field: (plugin) => String(plugin.commits), width: 8 },
53
+ { header: "UPDATED", field: (plugin) => (plugin.updated ? "yes" : "no"), width: 8 },
54
+ ],
55
+ };
31
56
  export async function runPluginInitCommand(directory, options, _command) {
32
57
  return {
33
58
  type: "single",
@@ -43,10 +68,36 @@ export async function runPluginLogsCommand(pluginId, options, _command) {
43
68
  const data = await withPluginLogsClient(options.host, (client) => client.getPluginLogs(pluginId));
44
69
  return { type: "list", data, schema: pluginLogsSchema };
45
70
  }
46
- async function install(directory, options, _command) {
47
- const data = await withPluginManagementClient(options.host, (client) => client.installDirectoryPlugin(directory, options.id));
71
+ async function install(source, options, _command) {
72
+ const isExplicitPath = path.isAbsolute(source) ||
73
+ source === "." ||
74
+ source === ".." ||
75
+ source.startsWith("./") ||
76
+ source.startsWith("../") ||
77
+ source.startsWith(".\\") ||
78
+ source.startsWith("..\\");
79
+ const canUseLegacyDirectoryInstall = isExplicitPath && !options.ref && !options.path;
80
+ const data = canUseLegacyDirectoryInstall
81
+ ? await withPluginManagementClient(options.host, (client) => client.installDirectoryPlugin(source, options.id))
82
+ : await withPluginSourceClient(options.host, (client) => client.installPluginSource({
83
+ source,
84
+ ...(options.id ? { id: options.id } : {}),
85
+ ...(options.ref ? { ref: options.ref } : {}),
86
+ ...(options.path ? { pluginPath: options.path } : {}),
87
+ }));
48
88
  return { type: "single", data, schema: pluginSchema };
49
89
  }
90
+ async function status(pluginId, options, _command) {
91
+ const data = await withPluginSourceClient(options.host, (client) => client.getPluginSourceStatus(pluginId));
92
+ return { type: "list", data, schema: pluginStatusSchema };
93
+ }
94
+ async function update(pluginId, options, _command) {
95
+ if ((pluginId === undefined) === (options.all !== true)) {
96
+ throw new Error("Choose one plugin ID or pass --all");
97
+ }
98
+ const data = await withPluginSourceClient(options.host, (client) => client.updatePluginSources(pluginId));
99
+ return { type: "list", data, schema: pluginUpdateSchema };
100
+ }
50
101
  async function act(action, pluginId, options) {
51
102
  const data = await withPluginManagementClient(options.host, (client) => client[`${action}Plugin`](pluginId));
52
103
  return { type: "single", data, schema: pluginSchema };
@@ -62,7 +113,7 @@ async function remove(pluginId, options, _command) {
62
113
  return { type: "single", data, schema: pluginSchema };
63
114
  }
64
115
  export function createPluginCommand() {
65
- const plugin = new Command("plugin").description("Manage trusted local plugins");
116
+ const plugin = new Command("plugin").description("Manage trusted plugins");
66
117
  addJsonOption(plugin
67
118
  .command("init")
68
119
  .description("Create a typecheckable local plugin")
@@ -72,11 +123,20 @@ export function createPluginCommand() {
72
123
  addJsonAndDaemonHostOptions(plugin.command("logs").description("Show recent plugin output").argument("<id>")).action(withOutput(runPluginLogsCommand));
73
124
  addJsonAndDaemonHostOptions(plugin
74
125
  .command("install")
75
- .description("Install a local plugin directory")
76
- .argument("<directory>", "Host filesystem directory")
77
- .option("--id <id>", "Runtime plugin ID (defaults to paseo-plugin.json id)")).action(withOutput(install));
126
+ .alias("add")
127
+ .description("Install a plugin from a directory or Git repository")
128
+ .argument("<source>", "Host directory, owner/repo shorthand, or Git URL")
129
+ .option("--id <id>", "Runtime plugin ID (defaults to paseo-plugin.json id)")
130
+ .option("--ref <ref>", "Git branch, tag, or commit")
131
+ .option("--path <path>", "Plugin directory within the repository")).action(withOutput(install));
132
+ addJsonAndDaemonHostOptions(plugin.command("status").description("Check plugin source updates").argument("[id]")).action(withOutput(status));
133
+ addJsonAndDaemonHostOptions(plugin
134
+ .command("update")
135
+ .description("Update a Git-managed plugin")
136
+ .argument("[id]")
137
+ .option("--all", "Update every Git-managed plugin")).action(withOutput(update));
78
138
  for (const action of ["reload", "enable", "disable"]) {
79
- addJsonAndDaemonHostOptions(plugin.command(action).description(`${action} a local plugin`).argument("<id>")).action(withOutput((id, options, _command) => act(action, id, options)));
139
+ addJsonAndDaemonHostOptions(plugin.command(action).description(`${action} a plugin`).argument("<id>")).action(withOutput((id, options, _command) => act(action, id, options)));
80
140
  }
81
141
  addJsonAndDaemonHostOptions(plugin.command("remove").description("Remove plugin configuration").argument("<id>")).action(withOutput(remove));
82
142
  return plugin;
@@ -58,6 +58,7 @@ const SDK_DECLARATIONS = `declare module "@getpaseo/plugin/server" {
58
58
  declare module "@getpaseo/plugin" {
59
59
  import type { ComponentType } from "react";
60
60
  import type { PaseoApi } from "@getpaseo/client";
61
+ import type { AgentTimelineItem } from "@getpaseo/protocol/agent-types";
61
62
  import type { ZodType, input as ZodInput, output as ZodOutput } from "zod";
62
63
  import type {
63
64
  PluginAttachmentSourceContribution,
@@ -80,10 +81,15 @@ declare module "@getpaseo/plugin" {
80
81
  export interface PluginTheme {
81
82
  readonly colors: {
82
83
  readonly surface0: string;
84
+ readonly surface1: string;
85
+ readonly surface2: string;
86
+ readonly border: string;
83
87
  readonly foreground: string;
84
88
  readonly foregroundMuted: string;
85
89
  readonly accent: string;
86
90
  readonly accentForeground: string;
91
+ readonly statusSuccess: string;
92
+ readonly statusWarning: string;
87
93
  readonly statusDanger: string;
88
94
  };
89
95
  }
@@ -96,6 +102,12 @@ declare module "@getpaseo/plugin" {
96
102
 
97
103
  export interface PluginSurfaceProps extends PluginHostProps {}
98
104
 
105
+ export interface PluginIconProps {
106
+ name: string;
107
+ size?: number;
108
+ color?: string;
109
+ }
110
+
99
111
  export interface PluginWorkspaceSnapshot {
100
112
  readonly id: string;
101
113
  readonly projectId: string;
@@ -179,6 +191,29 @@ declare module "@getpaseo/plugin" {
179
191
  Component: ComponentType<PluginSurfaceProps>;
180
192
  }
181
193
 
194
+ export type PluginTimelineData = null | boolean | number | string | PluginTimelineData[] | { [key: string]: PluginTimelineData };
195
+ export interface PluginTimelineItem { type: "plugin"; kind: string; version: number; data: PluginTimelineData; }
196
+ export interface PluginTimelineTransformResult { items: PluginTimelineItem[]; }
197
+ export type PluginTimelineTransformerContribution<ItemType extends AgentTimelineItem["type"] = AgentTimelineItem["type"]> =
198
+ ItemType extends AgentTimelineItem["type"]
199
+ ? {
200
+ id: string;
201
+ query: { itemType: ItemType };
202
+ transform(input: { item: Extract<AgentTimelineItem, { type: ItemType }> }): PluginTimelineTransformResult | undefined;
203
+ }
204
+ : never;
205
+ export interface PluginTimelineItemProps<Data = unknown> extends PluginHostProps {
206
+ agentId: string;
207
+ item: { type: "plugin"; kind: string; version: number; data: Data };
208
+ timestamp: Date;
209
+ }
210
+ export interface PluginTimelineRendererContribution<Schema extends ZodType = ZodType> {
211
+ kind: string;
212
+ version: number;
213
+ schema: Schema;
214
+ Component: ComponentType<PluginTimelineItemProps<ZodOutput<Schema>>>;
215
+ }
216
+
182
217
  export interface PluginCommandCapabilities {
183
218
  paseo: PaseoApi;
184
219
  rpc<InputSchema extends ZodType, OutputSchema extends ZodType>(
@@ -224,11 +259,15 @@ declare module "@getpaseo/plugin" {
224
259
  addCommandCenterItem(contribution: PluginCommandCenterItemContribution): void;
225
260
  addAttachmentSource(contribution: PluginAttachmentSourceContribution): void;
226
261
  addTheme(contribution: PluginThemeContribution): void;
262
+ addTimelineTransformer<ItemType extends AgentTimelineItem["type"]>(contribution: PluginTimelineTransformerContribution<ItemType>): void;
263
+ addTimelineRenderer<Schema extends ZodType>(contribution: PluginTimelineRendererContribution<Schema>): void;
227
264
  }
228
265
 
229
266
  export type PluginCleanup = () => void | Promise<void>;
230
267
  export type PluginContribution = (plugin: PluginContext) => PluginCleanup;
231
268
 
269
+ export const Icon: ComponentType<PluginIconProps>;
270
+
232
271
  export function useRpc<InputSchema extends ZodType, OutputSchema extends ZodType>(
233
272
  contract: PluginRpcContract<InputSchema, OutputSchema>,
234
273
  ): (input: ZodInput<InputSchema>) => Promise<ZodOutput<OutputSchema>>;
@@ -307,6 +346,7 @@ export async function scaffoldPluginDirectory(targetDirectory, requestedId) {
307
346
  scripts: { typecheck: "tsc --noEmit" },
308
347
  devDependencies: {
309
348
  "@getpaseo/client": "^0.4.0",
349
+ "@getpaseo/protocol": "^0.6.1",
310
350
  "@tanstack/react-query": "^5.90.11",
311
351
  "@types/react": "~19.2.0",
312
352
  react: "19.1.0",
@@ -1,4 +1,5 @@
1
1
  import type { DaemonClient } from "@getpaseo/client/internal/daemon-client";
2
2
  export declare function withPluginManagementClient<T>(host: string | undefined, run: (client: DaemonClient) => Promise<T>): Promise<T>;
3
3
  export declare function withPluginLogsClient<T>(host: string | undefined, run: (client: DaemonClient) => Promise<T>): Promise<T>;
4
+ export declare function withPluginSourceClient<T>(host: string | undefined, run: (client: DaemonClient) => Promise<T>): Promise<T>;
4
5
  //# sourceMappingURL=shared.d.ts.map
@@ -23,4 +23,8 @@ export async function withPluginLogsClient(host, run) {
23
23
  // COMPAT(pluginLogs): added in v0.4.0, remove gate after 2027-08-16.
24
24
  return withPluginClient(host, "pluginLogs", "Update the host to view plugin logs.", run);
25
25
  }
26
+ export async function withPluginSourceClient(host, run) {
27
+ // COMPAT(pluginGitManagement): added in v0.7.0, remove gate after 2027-08-26.
28
+ return withPluginClient(host, "pluginGitManagement", "Update the host to install and update Git plugins.", run);
29
+ }
26
30
  //# sourceMappingURL=shared.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getpaseo/cli",
3
- "version": "0.6.1",
3
+ "version": "0.7.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.6.1",
32
- "@getpaseo/protocol": "0.6.1",
33
- "@getpaseo/server": "0.6.1",
31
+ "@getpaseo/client": "0.7.0-beta.1",
32
+ "@getpaseo/protocol": "0.7.0-beta.1",
33
+ "@getpaseo/server": "0.7.0-beta.1",
34
34
  "chalk": "^5.3.0",
35
35
  "commander": "^12.0.0",
36
36
  "mime-types": "^2.1.35",