@camerontaylor/paseo-cli 0.8.0-fork.1 → 0.9.0-beta.2.fork.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 +44 -37
- package/dist/commands/agent/archive.js +2 -15
- package/dist/commands/agent/attach.d.ts +1 -0
- package/dist/commands/agent/attach.js +8 -12
- package/dist/commands/agent/delete.js +4 -15
- package/dist/commands/agent/detach.js +2 -13
- package/dist/commands/agent/import.js +2 -16
- package/dist/commands/agent/inspect.js +2 -15
- package/dist/commands/agent/logs.js +13 -13
- package/dist/commands/agent/ls.js +2 -23
- package/dist/commands/agent/mode.js +2 -2
- package/dist/commands/agent/open.js +2 -8
- package/dist/commands/agent/reload.js +2 -15
- package/dist/commands/agent/run.js +12 -17
- package/dist/commands/agent/send.js +6 -15
- package/dist/commands/agent/stop.js +2 -15
- package/dist/commands/agent/update.js +2 -15
- package/dist/commands/agent/wait.js +4 -15
- package/dist/commands/clone.js +2 -8
- package/dist/commands/daemon/config.d.ts +3 -0
- package/dist/commands/daemon/config.js +103 -0
- package/dist/commands/daemon/index.js +20 -52
- package/dist/commands/daemon/local-daemon.d.ts +10 -75
- package/dist/commands/daemon/local-daemon.js +61 -503
- package/dist/commands/daemon/pair.d.ts +3 -8
- package/dist/commands/daemon/pair.js +33 -61
- package/dist/commands/daemon/reload.d.ts +3 -1
- package/dist/commands/daemon/reload.js +10 -2
- package/dist/commands/daemon/restart.d.ts +19 -11
- package/dist/commands/daemon/restart.js +102 -88
- package/dist/commands/daemon/runtime-toolchain.js +1 -1
- package/dist/commands/daemon/set-password.js +8 -7
- package/dist/commands/daemon/start.d.ts +17 -3
- package/dist/commands/daemon/start.js +47 -52
- package/dist/commands/daemon/status.d.ts +12 -20
- package/dist/commands/daemon/status.js +91 -342
- package/dist/commands/daemon/stop.d.ts +19 -14
- package/dist/commands/daemon/stop.js +53 -55
- package/dist/commands/heartbeat/index.js +3 -3
- package/dist/commands/hub/connect.d.ts +1 -0
- package/dist/commands/hub/connect.js +1 -1
- package/dist/commands/hub/daemon-client.d.ts +3 -2
- package/dist/commands/hub/daemon-client.js +3 -3
- package/dist/commands/hub/disconnect.d.ts +1 -0
- package/dist/commands/hub/disconnect.js +1 -1
- package/dist/commands/hub/index.js +2 -2
- package/dist/commands/hub/init.d.ts +3 -1
- package/dist/commands/hub/init.js +13 -12
- package/dist/commands/hub/login.d.ts +4 -4
- package/dist/commands/hub/login.js +1 -1
- package/dist/commands/hub/logout.d.ts +1 -0
- package/dist/commands/hub/logout.js +2 -2
- package/dist/commands/hub/permissions.d.ts +1 -0
- package/dist/commands/hub/permissions.js +2 -2
- package/dist/commands/onboard.d.ts +7 -2
- package/dist/commands/onboard.js +59 -210
- package/dist/commands/open.js +3 -1
- package/dist/commands/permit/allow.js +2 -15
- package/dist/commands/permit/deny.js +2 -15
- package/dist/commands/permit/ls.js +2 -15
- package/dist/commands/plugin/index.d.ts +6 -0
- package/dist/commands/plugin/index.js +62 -46
- package/dist/commands/plugin/scaffold.js +10 -0
- package/dist/commands/plugin/shared.d.ts +5 -3
- package/dist/commands/plugin/shared.js +13 -9
- package/dist/commands/plugin/update.d.ts +37 -0
- package/dist/commands/plugin/update.js +58 -0
- package/dist/commands/project/create.js +5 -3
- package/dist/commands/project/delete.js +4 -2
- package/dist/commands/project/ls.js +2 -2
- package/dist/commands/project/rename.js +4 -2
- package/dist/commands/provider/add.js +2 -2
- package/dist/commands/provider/diagnostic.js +1 -1
- package/dist/commands/provider/ls.js +2 -30
- package/dist/commands/provider/models.js +1 -1
- package/dist/commands/provider/rm.js +2 -2
- package/dist/commands/schedule/create.js +2 -2
- package/dist/commands/schedule/delete.js +1 -1
- package/dist/commands/schedule/inspect.js +1 -1
- package/dist/commands/schedule/logs.js +1 -1
- package/dist/commands/schedule/ls.js +1 -1
- package/dist/commands/schedule/pause.js +1 -1
- package/dist/commands/schedule/resume.js +1 -1
- package/dist/commands/schedule/run-once.js +1 -1
- package/dist/commands/schedule/shared.d.ts +3 -1
- package/dist/commands/schedule/shared.js +7 -5
- package/dist/commands/schedule/update.js +1 -1
- package/dist/commands/script/ls.js +1 -1
- package/dist/commands/script/shared.d.ts +2 -1
- package/dist/commands/script/shared.js +3 -3
- package/dist/commands/script/start.js +1 -1
- package/dist/commands/script/stop.js +1 -1
- package/dist/commands/terminal/capture.d.ts +1 -1
- package/dist/commands/terminal/capture.js +2 -3
- package/dist/commands/terminal/create.js +1 -1
- package/dist/commands/terminal/kill.js +1 -1
- package/dist/commands/terminal/ls.js +1 -1
- package/dist/commands/terminal/send-keys.d.ts +1 -1
- package/dist/commands/terminal/send-keys.js +2 -3
- package/dist/commands/terminal/shared.d.ts +2 -1
- package/dist/commands/terminal/shared.js +5 -3
- package/dist/commands/workspace/archive.d.ts +1 -0
- package/dist/commands/workspace/archive.js +4 -2
- package/dist/commands/workspace/create.js +4 -2
- package/dist/commands/workspace/ls.d.ts +1 -0
- package/dist/commands/workspace/ls.js +2 -2
- package/dist/commands/workspace/rename.d.ts +1 -0
- package/dist/commands/workspace/rename.js +4 -2
- package/dist/commands/workspace/setup.d.ts +1 -0
- package/dist/commands/workspace/setup.js +2 -2
- package/dist/commands/worktree/archive.js +4 -2
- package/dist/commands/worktree/create.js +2 -10
- package/dist/commands/worktree/ls.d.ts +0 -2
- package/dist/commands/worktree/ls.js +4 -30
- package/dist/output/with-output.d.ts +2 -0
- package/dist/run.js +11 -1
- package/dist/utils/client-id.d.ts +1 -1
- package/dist/utils/client-id.js +8 -14
- package/dist/utils/client.d.ts +16 -21
- package/dist/utils/client.js +57 -109
- package/dist/utils/command-options.d.ts +1 -0
- package/dist/utils/command-options.js +26 -2
- package/dist/utils/daemon-target.d.ts +13 -0
- package/dist/utils/daemon-target.js +51 -0
- package/package.json +8 -4
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { connectToDaemon
|
|
1
|
+
import { connectToDaemon } from "../../utils/client.js";
|
|
2
2
|
/** Schema for permit allow/deny output */
|
|
3
3
|
export const permitResponseSchema = {
|
|
4
4
|
idField: "requestId",
|
|
@@ -21,7 +21,6 @@ export const permitResponseSchema = {
|
|
|
21
21
|
],
|
|
22
22
|
};
|
|
23
23
|
export async function runAllowCommand(agentIdOrPrefix, reqId, options, _command) {
|
|
24
|
-
const host = getDaemonHost({ host: options.host });
|
|
25
24
|
// No validation needed - if no reqId provided, allow all by default
|
|
26
25
|
// Parse input JSON if provided
|
|
27
26
|
let updatedInput;
|
|
@@ -38,19 +37,7 @@ export async function runAllowCommand(agentIdOrPrefix, reqId, options, _command)
|
|
|
38
37
|
throw error;
|
|
39
38
|
}
|
|
40
39
|
}
|
|
41
|
-
|
|
42
|
-
try {
|
|
43
|
-
client = await connectToDaemon({ host: options.host });
|
|
44
|
-
}
|
|
45
|
-
catch (err) {
|
|
46
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
47
|
-
const error = {
|
|
48
|
-
code: "DAEMON_NOT_RUNNING",
|
|
49
|
-
message: `Cannot connect to daemon at ${host}: ${message}`,
|
|
50
|
-
details: "Start the daemon with: paseo daemon start",
|
|
51
|
-
};
|
|
52
|
-
throw error;
|
|
53
|
-
}
|
|
40
|
+
const client = await connectToDaemon({ target: options.daemonTarget });
|
|
54
41
|
try {
|
|
55
42
|
const fetchResult = await client.fetchAgent({ agentId: agentIdOrPrefix });
|
|
56
43
|
if (!fetchResult) {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { connectToDaemon
|
|
1
|
+
import { connectToDaemon } from "../../utils/client.js";
|
|
2
2
|
import { permitResponseSchema } from "./allow.js";
|
|
3
3
|
export async function runDenyCommand(agentIdOrPrefix, reqId, options, _command) {
|
|
4
|
-
const host = getDaemonHost({ host: options.host });
|
|
5
4
|
// Validate arguments
|
|
6
5
|
if (!options.all && !reqId) {
|
|
7
6
|
const error = {
|
|
@@ -11,19 +10,7 @@ export async function runDenyCommand(agentIdOrPrefix, reqId, options, _command)
|
|
|
11
10
|
};
|
|
12
11
|
throw error;
|
|
13
12
|
}
|
|
14
|
-
|
|
15
|
-
try {
|
|
16
|
-
client = await connectToDaemon({ host: options.host });
|
|
17
|
-
}
|
|
18
|
-
catch (err) {
|
|
19
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
20
|
-
const error = {
|
|
21
|
-
code: "DAEMON_NOT_RUNNING",
|
|
22
|
-
message: `Cannot connect to daemon at ${host}: ${message}`,
|
|
23
|
-
details: "Start the daemon with: paseo daemon start",
|
|
24
|
-
};
|
|
25
|
-
throw error;
|
|
26
|
-
}
|
|
13
|
+
const client = await connectToDaemon({ target: options.daemonTarget });
|
|
27
14
|
try {
|
|
28
15
|
const fetchResult = await client.fetchAgent({ agentId: agentIdOrPrefix });
|
|
29
16
|
if (!fetchResult) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { connectToDaemon
|
|
1
|
+
import { connectToDaemon } from "../../utils/client.js";
|
|
2
2
|
/** Schema for permit ls output */
|
|
3
3
|
export const permitLsSchema = {
|
|
4
4
|
idField: "id",
|
|
@@ -20,20 +20,7 @@ function toListItem(agent, permission) {
|
|
|
20
20
|
};
|
|
21
21
|
}
|
|
22
22
|
export async function runLsCommand(options, _command) {
|
|
23
|
-
const
|
|
24
|
-
let client;
|
|
25
|
-
try {
|
|
26
|
-
client = await connectToDaemon({ host: options.host });
|
|
27
|
-
}
|
|
28
|
-
catch (err) {
|
|
29
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
30
|
-
const error = {
|
|
31
|
-
code: "DAEMON_NOT_RUNNING",
|
|
32
|
-
message: `Cannot connect to daemon at ${host}: ${message}`,
|
|
33
|
-
details: "Start the daemon with: paseo daemon start",
|
|
34
|
-
};
|
|
35
|
-
throw error;
|
|
36
|
-
}
|
|
23
|
+
const client = await connectToDaemon({ target: options.daemonTarget });
|
|
37
24
|
try {
|
|
38
25
|
const agentsPayload = await client.fetchAgents({ filter: { includeArchived: true } });
|
|
39
26
|
const agents = agentsPayload.entries.map((entry) => entry.agent);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type UpdateOutcome } from "./update.js";
|
|
1
2
|
import { Command } from "commander";
|
|
2
3
|
import type { PluginListItem, PluginLogEntry } from "@camerontaylor/paseo-protocol/messages";
|
|
3
4
|
import type { CommandOptions, ListResult, SingleResult } from "../../output/index.js";
|
|
@@ -8,10 +9,15 @@ interface PluginOptions extends CommandOptions {
|
|
|
8
9
|
ref?: string;
|
|
9
10
|
path?: string;
|
|
10
11
|
all?: boolean;
|
|
12
|
+
version?: string;
|
|
13
|
+
check?: boolean;
|
|
14
|
+
yes?: boolean;
|
|
11
15
|
}
|
|
12
16
|
export declare function runPluginInitCommand(directory: string, options: PluginOptions, _command: Command): Promise<SingleResult<PluginScaffold>>;
|
|
13
17
|
export declare function runPluginListCommand(pluginId: string | undefined, options: PluginOptions, _command: Command): Promise<ListResult<PluginListItem>>;
|
|
14
18
|
export declare function runPluginLogsCommand(pluginId: string, options: PluginOptions, _command: Command): Promise<ListResult<PluginLogEntry>>;
|
|
19
|
+
export declare function runPluginInstallCommand(source: string, options: PluginOptions, _command: Command): Promise<SingleResult<PluginListItem>>;
|
|
20
|
+
export declare function runPluginUpdateCommand(pluginId: string | undefined, options: PluginOptions, _command: Command): Promise<ListResult<UpdateOutcome>>;
|
|
15
21
|
export declare function createPluginCommand(): Command;
|
|
16
22
|
export {};
|
|
17
23
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1,19 +1,27 @@
|
|
|
1
|
+
import { createInterface } from "node:readline/promises";
|
|
2
|
+
import { reviewPluginUpdates } from "./update.js";
|
|
1
3
|
import { Command } from "commander";
|
|
2
|
-
import
|
|
3
|
-
import { formatPluginSourceReference, parsePluginSourceReference, } from "@camerontaylor/paseo-protocol/plugin-source-reference";
|
|
4
|
+
import { formatPluginSourceReference, formatPluginIdentity, } from "@camerontaylor/paseo-protocol/plugin-source-reference";
|
|
4
5
|
import { withOutput } from "../../output/index.js";
|
|
5
6
|
import { addJsonAndDaemonHostOptions, addJsonOption } from "../../utils/command-options.js";
|
|
6
7
|
import { scaffoldPluginDirectory } from "./scaffold.js";
|
|
7
|
-
import { withPluginLogsClient, withPluginManagementClient, withPluginSourceClient, } from "./shared.js";
|
|
8
|
+
import { withPluginLogsClient, withPluginUpdateClient, withPluginManagementClient, withPluginSourceClient, } from "./shared.js";
|
|
8
9
|
const pluginSchema = {
|
|
9
10
|
idField: "id",
|
|
10
11
|
columns: [
|
|
11
12
|
{ header: "PLUGIN", field: "id", width: 20 },
|
|
12
13
|
{ header: "STATUS", field: "status", width: 10 },
|
|
13
14
|
{ header: "ENABLED", field: (plugin) => (plugin.enabled ? "yes" : "no"), width: 8 },
|
|
14
|
-
{
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
{
|
|
16
|
+
header: "SOURCE",
|
|
17
|
+
field: (plugin) => plugin.installation ? formatPluginIdentity(plugin.installation.identity) : "-",
|
|
18
|
+
width: 40,
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
header: "REVISION",
|
|
22
|
+
field: (plugin) => plugin.installation?.currentRevision ?? "-",
|
|
23
|
+
width: 16,
|
|
24
|
+
},
|
|
17
25
|
{ header: "DIRECTORY", field: "path", width: 40 },
|
|
18
26
|
{ header: "ERROR", field: (plugin) => plugin.error ?? "", width: 40 },
|
|
19
27
|
],
|
|
@@ -33,17 +41,16 @@ const pluginLogsSchema = {
|
|
|
33
41
|
{ header: "MESSAGE", field: "message", width: 80 },
|
|
34
42
|
],
|
|
35
43
|
};
|
|
36
|
-
function shortCommit(commit) {
|
|
37
|
-
return commit?.slice(0, 12) ?? "-";
|
|
38
|
-
}
|
|
39
44
|
const pluginUpdateSchema = {
|
|
40
45
|
idField: "id",
|
|
41
46
|
columns: [
|
|
42
|
-
{ header: "PLUGIN", field: "id", width:
|
|
43
|
-
{ header: "
|
|
44
|
-
{
|
|
45
|
-
|
|
46
|
-
|
|
47
|
+
{ header: "PLUGIN", field: "id", width: 24 },
|
|
48
|
+
{ header: "RESULT", field: "outcome", width: 18 },
|
|
49
|
+
{
|
|
50
|
+
header: "DETAIL",
|
|
51
|
+
field: (item) => item.error ?? item.warning ?? item.plugin?.installation?.currentRevision ?? "",
|
|
52
|
+
width: 50,
|
|
53
|
+
},
|
|
47
54
|
],
|
|
48
55
|
};
|
|
49
56
|
export async function runPluginInitCommand(directory, options, _command) {
|
|
@@ -54,50 +61,55 @@ export async function runPluginInitCommand(directory, options, _command) {
|
|
|
54
61
|
};
|
|
55
62
|
}
|
|
56
63
|
export async function runPluginListCommand(pluginId, options, _command) {
|
|
57
|
-
const plugins = await withPluginManagementClient(options.
|
|
64
|
+
const plugins = await withPluginManagementClient(options.daemonTarget, (client) => client.listPlugins());
|
|
58
65
|
const data = pluginId ? plugins.filter((plugin) => plugin.id === pluginId) : plugins;
|
|
59
66
|
if (pluginId && data.length === 0)
|
|
60
67
|
throw new Error(`Plugin is not configured: ${pluginId}`);
|
|
61
68
|
return { type: "list", data, schema: pluginSchema };
|
|
62
69
|
}
|
|
63
70
|
export async function runPluginLogsCommand(pluginId, options, _command) {
|
|
64
|
-
const data = await withPluginLogsClient(options.
|
|
71
|
+
const data = await withPluginLogsClient(options.daemonTarget, (client) => client.getPluginLogs(pluginId));
|
|
65
72
|
return { type: "list", data, schema: pluginLogsSchema };
|
|
66
73
|
}
|
|
67
|
-
async function
|
|
68
|
-
process.stderr.write("Trusting plugin code: server code and
|
|
69
|
-
const isExplicitPath = path.isAbsolute(source) ||
|
|
70
|
-
source === "." ||
|
|
71
|
-
source === ".." ||
|
|
72
|
-
source.startsWith("./") ||
|
|
73
|
-
source.startsWith("../") ||
|
|
74
|
-
source.startsWith(".\\") ||
|
|
75
|
-
source.startsWith("..\\");
|
|
76
|
-
const hasPluginPathSuffix = parsePluginSourceReference(source).pluginPath !== undefined;
|
|
77
|
-
const canUseLegacyDirectoryInstall = isExplicitPath && !hasPluginPathSuffix && !options.ref && !options.path;
|
|
74
|
+
export async function runPluginInstallCommand(source, options, _command) {
|
|
75
|
+
process.stderr.write("Trusting plugin code: server code and preparation commands run unsandboxed on the daemon host; client code runs inside Paseo. Dependencies and future updates are part of the codebase you trust.\n");
|
|
78
76
|
const sourceReference = formatPluginSourceReference(source, options.path);
|
|
79
|
-
const data =
|
|
80
|
-
|
|
81
|
-
:
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
...(options.ref ? { ref: options.ref } : {}),
|
|
85
|
-
}));
|
|
77
|
+
const data = await withPluginSourceClient(options.daemonTarget, (client) => client.installPluginSource({
|
|
78
|
+
source: sourceReference,
|
|
79
|
+
...(options.id ? { id: options.id } : {}),
|
|
80
|
+
...(options.ref ? { ref: options.ref } : {}),
|
|
81
|
+
}));
|
|
86
82
|
return { type: "single", data, schema: pluginSchema };
|
|
87
83
|
}
|
|
88
|
-
async function
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
84
|
+
export async function runPluginUpdateCommand(pluginId, options, _command) {
|
|
85
|
+
const data = await withPluginUpdateClient(options.daemonTarget, (client) => reviewPluginUpdates(client, { ...options, pluginId }, {
|
|
86
|
+
interactive: process.stdin.isTTY === true,
|
|
87
|
+
structured: options.json === true ||
|
|
88
|
+
["json", "yaml"].includes(options.format?.trim().toLowerCase() ?? ""),
|
|
89
|
+
write: (text) => process.stderr.write(text),
|
|
90
|
+
confirm: async (message) => {
|
|
91
|
+
const prompt = createInterface({ input: process.stdin, output: process.stderr });
|
|
92
|
+
try {
|
|
93
|
+
return /^(y|yes)$/i.test((await prompt.question(message)).trim());
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
finally {
|
|
99
|
+
prompt.close();
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
}));
|
|
103
|
+
if (data.some((item) => item.outcome === "error"))
|
|
104
|
+
process.exitCode = 1;
|
|
93
105
|
return { type: "list", data, schema: pluginUpdateSchema };
|
|
94
106
|
}
|
|
95
107
|
async function act(action, pluginId, options) {
|
|
96
|
-
const data = await withPluginManagementClient(options.
|
|
108
|
+
const data = await withPluginManagementClient(options.daemonTarget, (client) => client[`${action}Plugin`](pluginId));
|
|
97
109
|
return { type: "single", data, schema: pluginSchema };
|
|
98
110
|
}
|
|
99
111
|
async function remove(pluginId, options, _command) {
|
|
100
|
-
const data = await withPluginManagementClient(options.
|
|
112
|
+
const data = await withPluginManagementClient(options.daemonTarget, async (client) => {
|
|
101
113
|
const current = (await client.listPlugins()).find((plugin) => plugin.id === pluginId);
|
|
102
114
|
if (!current)
|
|
103
115
|
throw new Error(`Plugin is not configured: ${pluginId}`);
|
|
@@ -119,16 +131,20 @@ export function createPluginCommand() {
|
|
|
119
131
|
addJsonAndDaemonHostOptions(plugin
|
|
120
132
|
.command("install")
|
|
121
133
|
.alias("add")
|
|
122
|
-
.description("Trust and install a plugin from a directory or
|
|
123
|
-
.argument("<source>", "Host directory, Git source,
|
|
134
|
+
.description("Trust and install a plugin from a directory, Git repository, or npm package")
|
|
135
|
+
.argument("<source>", "Host directory, Git or npm source, optionally followed by :plugin/path")
|
|
124
136
|
.option("--id <id>", "Runtime plugin ID (defaults to paseo-plugin.json id)")
|
|
125
137
|
.option("--ref <ref>", "Git branch, tag, or commit")
|
|
126
|
-
.option("--path <path>", "Legacy form of the :plugin/path source suffix")).action(withOutput(
|
|
138
|
+
.option("--path <path>", "Legacy form of the :plugin/path source suffix")).action(withOutput(runPluginInstallCommand));
|
|
127
139
|
addJsonAndDaemonHostOptions(plugin
|
|
128
140
|
.command("update")
|
|
129
|
-
.description("
|
|
141
|
+
.description("Review and update installed plugins")
|
|
130
142
|
.argument("[id]")
|
|
131
|
-
.option("--all", "
|
|
143
|
+
.option("--all", "Review all configured plugins")
|
|
144
|
+
.option("--check", "Show available updates without installing")
|
|
145
|
+
.option("--yes", "Apply displayed updates without asking")
|
|
146
|
+
.option("--ref <ref>", "Apply a Git branch, tag, or commit without asking")
|
|
147
|
+
.option("--version <version>", "Apply an npm version, tag, or range without asking")).action(withOutput(runPluginUpdateCommand));
|
|
132
148
|
for (const action of ["reload", "enable", "disable"]) {
|
|
133
149
|
addJsonAndDaemonHostOptions(plugin.command(action).description(`${action} a plugin`).argument("<id>")).action(withOutput((id, options, _command) => act(action, id, options)));
|
|
134
150
|
}
|
|
@@ -130,6 +130,16 @@ export async function scaffoldPluginDirectory(targetDirectory, requestedId) {
|
|
|
130
130
|
name: id,
|
|
131
131
|
private: true,
|
|
132
132
|
version: "0.0.0",
|
|
133
|
+
files: [
|
|
134
|
+
"paseo-plugin.json",
|
|
135
|
+
"index.client.ts",
|
|
136
|
+
"index.client.tsx",
|
|
137
|
+
"index.server.ts",
|
|
138
|
+
"index.server.tsx",
|
|
139
|
+
"client/",
|
|
140
|
+
"server/",
|
|
141
|
+
"shared/",
|
|
142
|
+
],
|
|
133
143
|
scripts: { typecheck: "tsc --noEmit" },
|
|
134
144
|
devDependencies: {
|
|
135
145
|
"@camerontaylor/paseo-plugin": version,
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import type { DaemonTarget } from "../../utils/daemon-target.js";
|
|
1
2
|
import type { DaemonClient } from "@camerontaylor/paseo-client/internal/daemon-client";
|
|
2
|
-
export declare function withPluginManagementClient<T>(
|
|
3
|
-
export declare function withPluginLogsClient<T>(
|
|
4
|
-
export declare function withPluginSourceClient<T>(
|
|
3
|
+
export declare function withPluginManagementClient<T>(target: DaemonTarget, run: (client: DaemonClient) => Promise<T>): Promise<T>;
|
|
4
|
+
export declare function withPluginLogsClient<T>(target: DaemonTarget, run: (client: DaemonClient) => Promise<T>): Promise<T>;
|
|
5
|
+
export declare function withPluginSourceClient<T>(target: DaemonTarget, run: (client: DaemonClient) => Promise<T>): Promise<T>;
|
|
6
|
+
export declare function withPluginUpdateClient<T>(target: DaemonTarget, run: (client: DaemonClient) => Promise<T>): Promise<T>;
|
|
5
7
|
//# sourceMappingURL=shared.d.ts.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { connectToDaemon } from "../../utils/client.js";
|
|
2
|
-
async function withPluginClient(
|
|
3
|
-
const client = await connectToDaemon({
|
|
2
|
+
async function withPluginClient(target, feature, updateMessage, run) {
|
|
3
|
+
const client = await connectToDaemon({ target });
|
|
4
4
|
if (client.getLastServerInfoMessage()?.features?.[feature] !== true) {
|
|
5
5
|
await client.close().catch(() => undefined);
|
|
6
6
|
throw {
|
|
@@ -15,16 +15,20 @@ async function withPluginClient(host, feature, updateMessage, run) {
|
|
|
15
15
|
await client.close().catch(() => undefined);
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
|
-
export async function withPluginManagementClient(
|
|
18
|
+
export async function withPluginManagementClient(target, run) {
|
|
19
19
|
// COMPAT(pluginManagement): added in v0.3.1, remove gate after 2027-08-14.
|
|
20
|
-
return withPluginClient(
|
|
20
|
+
return withPluginClient(target, "pluginManagement", "Update the host to use plugin management.", run);
|
|
21
21
|
}
|
|
22
|
-
export async function withPluginLogsClient(
|
|
22
|
+
export async function withPluginLogsClient(target, run) {
|
|
23
23
|
// COMPAT(pluginLogs): added in v0.4.0, remove gate after 2027-08-16.
|
|
24
|
-
return withPluginClient(
|
|
24
|
+
return withPluginClient(target, "pluginLogs", "Update the host to view plugin logs.", run);
|
|
25
25
|
}
|
|
26
|
-
export async function withPluginSourceClient(
|
|
27
|
-
// COMPAT(
|
|
28
|
-
return withPluginClient(
|
|
26
|
+
export async function withPluginSourceClient(target, run) {
|
|
27
|
+
// COMPAT(pluginSourceInstallation): added in v0.8.0; remove gate after 2027-03-16 once daemon floor supports source identifiers.
|
|
28
|
+
return withPluginClient(target, "pluginSourceInstallation", "Update the host to install plugin sources.", run);
|
|
29
|
+
}
|
|
30
|
+
export async function withPluginUpdateClient(target, run) {
|
|
31
|
+
// COMPAT(pluginSourceUpdates): added in v0.8.0; remove after 2027-03-16 once daemon floor supports reviewed updates.
|
|
32
|
+
return withPluginClient(target, "pluginSourceUpdates", "Update the host to review plugin updates.", run);
|
|
29
33
|
}
|
|
30
34
|
//# sourceMappingURL=shared.js.map
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { PluginUpdatePreview, PluginUpdateResult, PluginUpdateSelection, PluginUpdateProposal } from "@camerontaylor/paseo-protocol/messages";
|
|
2
|
+
interface UpdateClient {
|
|
3
|
+
previewPluginUpdates(input: {
|
|
4
|
+
pluginId?: string;
|
|
5
|
+
target?: PluginUpdateSelection;
|
|
6
|
+
}): Promise<PluginUpdatePreview[]>;
|
|
7
|
+
applyPluginUpdates(proposals: PluginUpdateProposal[]): Promise<PluginUpdateResult[]>;
|
|
8
|
+
}
|
|
9
|
+
export interface UpdateOptions {
|
|
10
|
+
pluginId?: string;
|
|
11
|
+
all?: boolean;
|
|
12
|
+
ref?: string;
|
|
13
|
+
version?: string;
|
|
14
|
+
check?: boolean;
|
|
15
|
+
yes?: boolean;
|
|
16
|
+
}
|
|
17
|
+
export interface UpdateInteraction {
|
|
18
|
+
interactive: boolean;
|
|
19
|
+
structured: boolean;
|
|
20
|
+
write(text: string): void;
|
|
21
|
+
confirm(message: string): Promise<boolean>;
|
|
22
|
+
}
|
|
23
|
+
export interface UpdateOutcome {
|
|
24
|
+
id: string;
|
|
25
|
+
outcome: PluginUpdatePreview["outcome"] | PluginUpdateResult["outcome"] | "declined";
|
|
26
|
+
current?: PluginUpdatePreview["current"];
|
|
27
|
+
target?: PluginUpdatePreview["target"];
|
|
28
|
+
links?: string[];
|
|
29
|
+
proposal?: PluginUpdateProposal;
|
|
30
|
+
plugin?: PluginUpdateResult["plugin"];
|
|
31
|
+
error?: string;
|
|
32
|
+
warning?: string;
|
|
33
|
+
}
|
|
34
|
+
export declare function reviewPluginUpdates(client: UpdateClient, options: UpdateOptions, interaction: UpdateInteraction): Promise<UpdateOutcome[]>;
|
|
35
|
+
export declare function formatUpdatePreview(items: PluginUpdatePreview[]): string;
|
|
36
|
+
export {};
|
|
37
|
+
//# sourceMappingURL=update.d.ts.map
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
export async function reviewPluginUpdates(client, options, interaction) {
|
|
2
|
+
if ((options.pluginId === undefined) === (options.all !== true))
|
|
3
|
+
throw new Error("Choose one plugin ID or pass --all");
|
|
4
|
+
if (options.ref && options.version)
|
|
5
|
+
throw new Error("Choose --ref or --version, not both");
|
|
6
|
+
let target;
|
|
7
|
+
if (options.ref)
|
|
8
|
+
target = { kind: "git", ref: options.ref };
|
|
9
|
+
if (options.version)
|
|
10
|
+
target = { kind: "npm", version: options.version };
|
|
11
|
+
if (target && options.all)
|
|
12
|
+
throw new Error("An explicit target requires one plugin ID, without --all");
|
|
13
|
+
const preview = await client.previewPluginUpdates({ pluginId: options.pluginId, target });
|
|
14
|
+
if (!interaction.structured)
|
|
15
|
+
interaction.write(formatUpdatePreview(preview));
|
|
16
|
+
if (options.check)
|
|
17
|
+
return preview;
|
|
18
|
+
const proposals = preview.flatMap((item) => (item.proposal ? [item.proposal] : []));
|
|
19
|
+
if (!proposals.length)
|
|
20
|
+
return preview;
|
|
21
|
+
if (!options.yes && !target) {
|
|
22
|
+
if (interaction.structured || !interaction.interactive)
|
|
23
|
+
throw new Error("Confirmation required; rerun with --yes.");
|
|
24
|
+
if (!(await interaction.confirm(options.all ? "Update these plugins? [y/N] " : `Update ${options.pluginId}? [y/N] `))) {
|
|
25
|
+
return preview.map((item) => (item.proposal ? { id: item.id, outcome: "declined" } : item));
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
const applied = new Map((await client.applyPluginUpdates(proposals)).map((item) => [item.id, item]));
|
|
29
|
+
return preview.map((item) => applied.get(item.id) ?? item);
|
|
30
|
+
}
|
|
31
|
+
export function formatUpdatePreview(items) {
|
|
32
|
+
return items
|
|
33
|
+
.map((item) => {
|
|
34
|
+
const current = item.current?.currentRevision ?? "unknown";
|
|
35
|
+
const target = item.target?.kind === "git" ? item.target.commit : item.target?.version;
|
|
36
|
+
let text;
|
|
37
|
+
switch (item.outcome) {
|
|
38
|
+
case "update":
|
|
39
|
+
text = `${current} → ${target}`;
|
|
40
|
+
break;
|
|
41
|
+
case "current":
|
|
42
|
+
text = `up to date (${current})`;
|
|
43
|
+
break;
|
|
44
|
+
case "installed-newer":
|
|
45
|
+
text = `installed ${current} is newer than latest ${target}; keeping installed version`;
|
|
46
|
+
break;
|
|
47
|
+
case "local":
|
|
48
|
+
text = "local directory; use Reload after editing";
|
|
49
|
+
break;
|
|
50
|
+
case "error":
|
|
51
|
+
text = item.error ?? "Check failed";
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
return `${item.id}: ${text}\n${item.links.map((link) => `Review: ${link}\n`).join("")}`;
|
|
55
|
+
})
|
|
56
|
+
.join("\n");
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=update.js.map
|
|
@@ -18,10 +18,10 @@ export async function runCreateCommand(pathArg, options, _command) {
|
|
|
18
18
|
const projectPath = resolveProjectPath({
|
|
19
19
|
pathArg,
|
|
20
20
|
cwd: process.cwd(),
|
|
21
|
-
daemonTarget: options.
|
|
21
|
+
daemonTarget: options.daemonTarget.kind === "endpoint" ? options.daemonTarget.host : undefined,
|
|
22
22
|
});
|
|
23
|
-
const client = await connectToDaemon({
|
|
24
|
-
throw buildDaemonConnectionCommandError({
|
|
23
|
+
const client = await connectToDaemon({ target: options.daemonTarget }).catch((error) => {
|
|
24
|
+
throw buildDaemonConnectionCommandError({ target: options.daemonTarget, error });
|
|
25
25
|
});
|
|
26
26
|
try {
|
|
27
27
|
const payload = await client.addProject(projectPath);
|
|
@@ -31,6 +31,8 @@ export async function runCreateCommand(pathArg, options, _command) {
|
|
|
31
31
|
return { type: "single", data: toProjectRow(payload.project), schema: projectSchema };
|
|
32
32
|
}
|
|
33
33
|
catch (error) {
|
|
34
|
+
if (error && typeof error === "object" && "code" in error)
|
|
35
|
+
throw error;
|
|
34
36
|
const message = error instanceof Error ? error.message : String(error);
|
|
35
37
|
throw { code: "PROJECT_CREATE_FAILED", message };
|
|
36
38
|
}
|
|
@@ -11,8 +11,8 @@ const projectDeleteSchema = {
|
|
|
11
11
|
],
|
|
12
12
|
};
|
|
13
13
|
export async function runDeleteCommand(projectId, options, _command) {
|
|
14
|
-
const client = await connectToDaemon({
|
|
15
|
-
throw buildDaemonConnectionCommandError({
|
|
14
|
+
const client = await connectToDaemon({ target: options.daemonTarget }).catch((error) => {
|
|
15
|
+
throw buildDaemonConnectionCommandError({ target: options.daemonTarget, error });
|
|
16
16
|
});
|
|
17
17
|
try {
|
|
18
18
|
const result = await client.removeProject(projectId);
|
|
@@ -23,6 +23,8 @@ export async function runDeleteCommand(projectId, options, _command) {
|
|
|
23
23
|
};
|
|
24
24
|
}
|
|
25
25
|
catch (error) {
|
|
26
|
+
if (error && typeof error === "object" && "code" in error)
|
|
27
|
+
throw error;
|
|
26
28
|
const message = error instanceof Error ? error.message : String(error);
|
|
27
29
|
throw { code: "PROJECT_DELETE_FAILED", message };
|
|
28
30
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { buildDaemonConnectionCommandError, connectToDaemon } from "../../utils/client.js";
|
|
2
2
|
import { projectSchema, toProjectRow } from "./shared.js";
|
|
3
3
|
export async function runLsCommand(options, _command) {
|
|
4
|
-
const client = await connectToDaemon({
|
|
5
|
-
throw buildDaemonConnectionCommandError({
|
|
4
|
+
const client = await connectToDaemon({ target: options.daemonTarget }).catch((error) => {
|
|
5
|
+
throw buildDaemonConnectionCommandError({ target: options.daemonTarget, error });
|
|
6
6
|
});
|
|
7
7
|
try {
|
|
8
8
|
const payload = await client.listProjects();
|
|
@@ -28,8 +28,8 @@ export function resolveProjectName(input) {
|
|
|
28
28
|
}
|
|
29
29
|
export async function runRenameCommand(projectId, nameArg, options, _command) {
|
|
30
30
|
const name = resolveProjectName({ name: nameArg, reset: options.reset });
|
|
31
|
-
const client = await connectToDaemon({
|
|
32
|
-
throw buildDaemonConnectionCommandError({
|
|
31
|
+
const client = await connectToDaemon({ target: options.daemonTarget }).catch((error) => {
|
|
32
|
+
throw buildDaemonConnectionCommandError({ target: options.daemonTarget, error });
|
|
33
33
|
});
|
|
34
34
|
try {
|
|
35
35
|
const applied = await client.renameProject(projectId, name);
|
|
@@ -40,6 +40,8 @@ export async function runRenameCommand(projectId, nameArg, options, _command) {
|
|
|
40
40
|
};
|
|
41
41
|
}
|
|
42
42
|
catch (error) {
|
|
43
|
+
if (error && typeof error === "object" && "code" in error)
|
|
44
|
+
throw error;
|
|
43
45
|
const message = error instanceof Error ? error.message : String(error);
|
|
44
46
|
throw { code: "PROJECT_RENAME_FAILED", message };
|
|
45
47
|
}
|
|
@@ -96,8 +96,8 @@ export async function runAddCommand(id, options, _command) {
|
|
|
96
96
|
message: error instanceof Error ? error.message : String(error),
|
|
97
97
|
};
|
|
98
98
|
}
|
|
99
|
-
const host = getDaemonHost({
|
|
100
|
-
const client = await connectToDaemon({
|
|
99
|
+
const host = getDaemonHost({ target: options.daemonTarget });
|
|
100
|
+
const client = await connectToDaemon({ target: options.daemonTarget }).catch((error) => {
|
|
101
101
|
const message = error instanceof Error ? error.message : String(error);
|
|
102
102
|
throw {
|
|
103
103
|
code: "DAEMON_NOT_RUNNING",
|
|
@@ -12,7 +12,7 @@ export const providerDiagnosticSchema = {
|
|
|
12
12
|
},
|
|
13
13
|
};
|
|
14
14
|
export async function runDiagnosticCommand(provider, options, _command) {
|
|
15
|
-
const client = await connectToDaemon({
|
|
15
|
+
const client = await connectToDaemon({ target: options.daemonTarget });
|
|
16
16
|
try {
|
|
17
17
|
const result = await client.getProviderDiagnostic(provider.trim().toLowerCase());
|
|
18
18
|
return {
|
|
@@ -1,18 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { tryConnectToDaemon } from "../../utils/client.js";
|
|
3
|
-
/** Derive provider list from the manifest — single source of truth */
|
|
4
|
-
const PROVIDERS = AGENT_PROVIDER_DEFINITIONS.map((def) => ({
|
|
5
|
-
provider: def.id,
|
|
6
|
-
label: def.label,
|
|
7
|
-
source: "builtin",
|
|
8
|
-
status: "available",
|
|
9
|
-
enabled: def.enabledByDefault === false ? "Disabled" : "Enabled",
|
|
10
|
-
defaultMode: def.defaultModeId ?? "-",
|
|
11
|
-
modes: def.modes.length > 0 ? def.modes.map((m) => m.label).join(", ") : "-",
|
|
12
|
-
}));
|
|
13
|
-
function getStaticProviders() {
|
|
14
|
-
return PROVIDERS;
|
|
15
|
-
}
|
|
1
|
+
import { connectToDaemon } from "../../utils/client.js";
|
|
16
2
|
/** Schema for provider ls output */
|
|
17
3
|
export const providerLsSchema = {
|
|
18
4
|
idField: "provider",
|
|
@@ -38,14 +24,7 @@ export const providerLsSchema = {
|
|
|
38
24
|
],
|
|
39
25
|
};
|
|
40
26
|
export async function runLsCommand(options, _command) {
|
|
41
|
-
const client = await
|
|
42
|
-
if (!client) {
|
|
43
|
-
return {
|
|
44
|
-
type: "list",
|
|
45
|
-
data: getStaticProviders(),
|
|
46
|
-
schema: providerLsSchema,
|
|
47
|
-
};
|
|
48
|
-
}
|
|
27
|
+
const client = await connectToDaemon({ target: options.daemonTarget });
|
|
49
28
|
try {
|
|
50
29
|
const snapshot = await client.getProvidersSnapshot();
|
|
51
30
|
return {
|
|
@@ -62,13 +41,6 @@ export async function runLsCommand(options, _command) {
|
|
|
62
41
|
schema: providerLsSchema,
|
|
63
42
|
};
|
|
64
43
|
}
|
|
65
|
-
catch {
|
|
66
|
-
return {
|
|
67
|
-
type: "list",
|
|
68
|
-
data: getStaticProviders(),
|
|
69
|
-
schema: providerLsSchema,
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
44
|
finally {
|
|
73
45
|
await client.close().catch(() => { });
|
|
74
46
|
}
|
|
@@ -23,7 +23,7 @@ const providerModelsWithThinkingSchema = {
|
|
|
23
23
|
};
|
|
24
24
|
export async function runModelsCommand(provider, options, _command) {
|
|
25
25
|
const normalizedProvider = provider.toLowerCase();
|
|
26
|
-
const client = await connectToDaemon({
|
|
26
|
+
const client = await connectToDaemon({ target: options.daemonTarget });
|
|
27
27
|
try {
|
|
28
28
|
const result = await client.listProviderModels(normalizedProvider);
|
|
29
29
|
if (result.error) {
|
|
@@ -14,8 +14,8 @@ export async function runRmCommand(id, options, _command) {
|
|
|
14
14
|
message: `"${id}" is a built-in provider and cannot be removed.`,
|
|
15
15
|
};
|
|
16
16
|
}
|
|
17
|
-
const host = getDaemonHost({
|
|
18
|
-
const client = await connectToDaemon({
|
|
17
|
+
const host = getDaemonHost({ target: options.daemonTarget });
|
|
18
|
+
const client = await connectToDaemon({ target: options.daemonTarget }).catch((error) => {
|
|
19
19
|
const message = error instanceof Error ? error.message : String(error);
|
|
20
20
|
throw {
|
|
21
21
|
code: "DAEMON_NOT_RUNNING",
|
|
@@ -14,12 +14,12 @@ export async function runCreateCommand(prompt, options, command) {
|
|
|
14
14
|
mode: options.mode,
|
|
15
15
|
thinking: options.thinking,
|
|
16
16
|
cwd: options.cwd,
|
|
17
|
-
|
|
17
|
+
daemonTarget: options.daemonTarget,
|
|
18
18
|
maxRuns: options.maxRuns,
|
|
19
19
|
expiresIn: options.expiresIn,
|
|
20
20
|
runNow,
|
|
21
21
|
});
|
|
22
|
-
const { client } = await connectScheduleClient(options.
|
|
22
|
+
const { client } = await connectScheduleClient(options.daemonTarget);
|
|
23
23
|
try {
|
|
24
24
|
const payload = await client.scheduleCreate(input);
|
|
25
25
|
if (payload.error || !payload.schedule) {
|