@camerontaylor/paseo-cli 0.8.0-fork.3 → 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 +19 -0
- package/dist/commands/agent/logs.js +1 -1
- package/dist/commands/agent/run.js +1 -1
- package/dist/commands/daemon/config.js +2 -1
- package/dist/commands/daemon/local-daemon.d.ts +1 -1
- package/dist/commands/daemon/local-daemon.js +1 -1
- package/dist/commands/daemon/pair.js +3 -1
- package/dist/commands/daemon/restart.js +1 -1
- package/dist/commands/daemon/runtime-toolchain.js +1 -1
- package/dist/commands/daemon/set-password.js +3 -1
- package/dist/commands/daemon/start.js +1 -1
- package/dist/commands/daemon/status.js +2 -1
- package/dist/commands/daemon/stop.js +1 -1
- package/dist/commands/onboard.js +2 -1
- package/dist/commands/open.js +1 -1
- package/dist/commands/plugin/index.d.ts +6 -0
- package/dist/commands/plugin/index.js +58 -42
- package/dist/commands/plugin/scaffold.js +10 -0
- package/dist/commands/plugin/shared.d.ts +1 -0
- package/dist/commands/plugin/shared.js +6 -2
- package/dist/commands/plugin/update.d.ts +37 -0
- package/dist/commands/plugin/update.js +58 -0
- package/dist/utils/client-id.js +1 -1
- package/dist/utils/client.d.ts +1 -1
- package/dist/utils/client.js +1 -1
- package/dist/utils/command-options.js +4 -2
- package/dist/utils/daemon-target.js +1 -1
- package/package.json +4 -4
package/dist/cli.js
CHANGED
|
@@ -102,6 +102,25 @@ export function createCli() {
|
|
|
102
102
|
// COMPAT(worktreeCli): legacy command alias added before workspace was the product unit.
|
|
103
103
|
// Added in v0.2.0; remove after 2027-01-17.
|
|
104
104
|
program.addCommand(createWorktreeCommand(), { hidden: true });
|
|
105
|
+
// Stop root parsing at the command so `plugin update --version` belongs to update.
|
|
106
|
+
// Keep global options available after a command, as they were before positional parsing.
|
|
107
|
+
program.enablePositionalOptions();
|
|
108
|
+
for (const command of program.commands) {
|
|
109
|
+
for (const option of program.options) {
|
|
110
|
+
if (option.long === "--version")
|
|
111
|
+
continue;
|
|
112
|
+
if (!command.options.some((local) => local.long === option.long))
|
|
113
|
+
command.addOption(option);
|
|
114
|
+
if (option.long === "--home" || option.long === "--host")
|
|
115
|
+
continue;
|
|
116
|
+
command.on(`option:${option.name()}`, () => {
|
|
117
|
+
const key = option.attributeName();
|
|
118
|
+
program.setOptionValueWithSource(key, command.opts()[key], "cli");
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
if (command.name() !== "plugin")
|
|
122
|
+
command.version(VERSION, "-v, --version", "output the version number");
|
|
123
|
+
}
|
|
105
124
|
const enforceSelectorDuplicates = (command) => {
|
|
106
125
|
for (const option of command.options) {
|
|
107
126
|
if (option.long !== "--home" && option.long !== "--host")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { connectToDaemon } from "../../utils/client.js";
|
|
2
2
|
import { fetchProjectedTimelineItems, LIVE_HISTORY_FETCH_TIMEOUT_MS, } from "../../utils/timeline.js";
|
|
3
|
-
import { curateAgentActivity } from "@camerontaylor/paseo-server";
|
|
3
|
+
import { curateAgentActivity } from "@camerontaylor/paseo-server/agent-activity";
|
|
4
4
|
export function addLogsOptions(cmd) {
|
|
5
5
|
return cmd
|
|
6
6
|
.description("View agent activity/timeline")
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Option } from "commander";
|
|
2
|
-
import { getStructuredAgentResponse, StructuredAgentResponseError } from "@camerontaylor/paseo-server";
|
|
2
|
+
import { getStructuredAgentResponse, StructuredAgentResponseError, } from "@camerontaylor/paseo-server/agent-response";
|
|
3
3
|
import { connectToDaemon } from "../../utils/client.js";
|
|
4
4
|
import { readFileSync } from "node:fs";
|
|
5
5
|
import { resolve } from "node:path";
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { addLocalDaemonOptions } from "../../utils/command-options.js";
|
|
2
2
|
import { Command } from "commander";
|
|
3
|
-
import { readDaemonInstance
|
|
3
|
+
import { readDaemonInstance } from "@camerontaylor/paseo-server/daemon-control";
|
|
4
|
+
import { readPersistedConfig, getPersistedConfigValue, editPersistedConfig, } from "@camerontaylor/paseo-server/configuration";
|
|
4
5
|
import { connectToDaemon } from "../../utils/client.js";
|
|
5
6
|
import { withOutput } from "../../output/index.js";
|
|
6
7
|
function redact(value) {
|
|
@@ -4,7 +4,7 @@ export declare function launchLocalDaemon(options: {
|
|
|
4
4
|
timeoutMs?: number;
|
|
5
5
|
foreground?: boolean;
|
|
6
6
|
}): Promise<{
|
|
7
|
-
instance: import("@camerontaylor/paseo-server").DaemonInstance;
|
|
7
|
+
instance: import("@camerontaylor/paseo-server/daemon-control").DaemonInstance;
|
|
8
8
|
spawned: boolean;
|
|
9
9
|
exitCode?: number;
|
|
10
10
|
}>;
|
|
@@ -2,7 +2,7 @@ import { Option } from "commander";
|
|
|
2
2
|
import { existsSync, readFileSync } from "node:fs";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import path from "node:path";
|
|
5
|
-
import { startDaemonInstance, resolvePaseoHome } from "@camerontaylor/paseo-server";
|
|
5
|
+
import { startDaemonInstance, resolvePaseoHome } from "@camerontaylor/paseo-server/daemon-control";
|
|
6
6
|
const require = createRequire(import.meta.url);
|
|
7
7
|
function resolveServerRunnerFromDir(currentDir) {
|
|
8
8
|
const packageJsonPath = path.join(currentDir, "package.json");
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { confirm, isCancel, log } from "@clack/prompts";
|
|
2
2
|
import { Command } from "commander";
|
|
3
3
|
import chalk from "chalk";
|
|
4
|
-
import { generateLocalPairingOffer
|
|
4
|
+
import { generateLocalPairingOffer } from "@camerontaylor/paseo-server/pairing";
|
|
5
|
+
import { readDaemonInstance } from "@camerontaylor/paseo-server/daemon-control";
|
|
6
|
+
import { readPersistedConfig, editPersistedConfig, resolveConfigFromPersisted, } from "@camerontaylor/paseo-server/configuration";
|
|
5
7
|
import { connectToDaemon } from "../../utils/client.js";
|
|
6
8
|
import { addJsonAndDaemonHostOptions, withGlobalOptions } from "../../utils/command-options.js";
|
|
7
9
|
import { formatPairingInstructions } from "../../output/pairing.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
|
-
import { readDaemonInstance, isSameDaemonInstance, DaemonInstanceError } from "@camerontaylor/paseo-server";
|
|
2
|
+
import { readDaemonInstance, isSameDaemonInstance, DaemonInstanceError, } from "@camerontaylor/paseo-server/daemon-control";
|
|
3
3
|
import { setTimeout as delay } from "node:timers/promises";
|
|
4
4
|
import { connectToDaemon } from "../../utils/client.js";
|
|
5
5
|
import { withOutput } from "../../output/index.js";
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { isCancel, password as passwordPrompt } from "@clack/prompts";
|
|
3
|
-
import { hashDaemonPassword
|
|
3
|
+
import { hashDaemonPassword } from "@camerontaylor/paseo-server/auth";
|
|
4
|
+
import { readPersistedConfig, savePersistedConfig, } from "@camerontaylor/paseo-server/configuration";
|
|
5
|
+
import { resolvePaseoHome } from "@camerontaylor/paseo-server/daemon-control";
|
|
4
6
|
const CONFIG_FILENAME = "config.json";
|
|
5
7
|
const setPasswordResultSchema = {
|
|
6
8
|
idField: "action",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { addLocalDaemonOptions } from "../../utils/command-options.js";
|
|
2
2
|
import { Command } from "commander";
|
|
3
|
-
import { daemonLogPath } from "@camerontaylor/paseo-server";
|
|
3
|
+
import { daemonLogPath } from "@camerontaylor/paseo-server/daemon-control";
|
|
4
4
|
import { launchLocalDaemon, parseTimeoutMs, rejectRemovedLaunchFlags } from "./local-daemon.js";
|
|
5
5
|
import { withOutput } from "../../output/index.js";
|
|
6
6
|
export function startCommand() {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
2
|
import { DaemonConnectionError } from "@camerontaylor/paseo-client/internal/daemon-client";
|
|
3
|
-
import { readDaemonInstance,
|
|
3
|
+
import { readDaemonInstance, daemonLogPath, isSameDaemonInstance, DaemonInstanceError, } from "@camerontaylor/paseo-server/daemon-control";
|
|
4
|
+
import { readPersistedConfig, resolveConfigFromPersisted } from "@camerontaylor/paseo-server/configuration";
|
|
4
5
|
import { connectToDaemon, buildDaemonConnectionCommandError } from "../../utils/client.js";
|
|
5
6
|
import { withOutput, toCommandError } from "../../output/index.js";
|
|
6
7
|
import { addJsonAndDaemonHostOptions } from "../../utils/command-options.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
|
-
import { stopDaemonInstance } from "@camerontaylor/paseo-server";
|
|
2
|
+
import { stopDaemonInstance } from "@camerontaylor/paseo-server/daemon-control";
|
|
3
3
|
import { connectToDaemon } from "../../utils/client.js";
|
|
4
4
|
import { withOutput } from "../../output/index.js";
|
|
5
5
|
import { addJsonAndDaemonHostOptions } from "../../utils/command-options.js";
|
package/dist/commands/onboard.js
CHANGED
|
@@ -2,7 +2,8 @@ import { addLocalDaemonOptions } from "../utils/command-options.js";
|
|
|
2
2
|
import { cancel, confirm, intro, isCancel, log, note, outro } from "@clack/prompts";
|
|
3
3
|
import { Command, Option } from "commander";
|
|
4
4
|
import path from "node:path";
|
|
5
|
-
import { readPersistedConfig as loadPersistedConfig, savePersistedConfig,
|
|
5
|
+
import { readPersistedConfig as loadPersistedConfig, savePersistedConfig, } from "@camerontaylor/paseo-server/configuration";
|
|
6
|
+
import { readDaemonInstance, waitForDaemonReady } from "@camerontaylor/paseo-server/daemon-control";
|
|
6
7
|
import { withGlobalOptions } from "../utils/command-options.js";
|
|
7
8
|
import { launchLocalDaemon, parseTimeoutMs } from "./daemon/local-daemon.js";
|
|
8
9
|
import { connectToDaemon } from "../utils/client.js";
|
package/dist/commands/open.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import path from "node:path";
|
|
4
|
-
import { spawnProcess } from "@camerontaylor/paseo-server";
|
|
4
|
+
import { spawnProcess } from "@camerontaylor/paseo-server/process";
|
|
5
5
|
import { buildAgentDeepLink } from "@camerontaylor/paseo-protocol/agent-deep-link";
|
|
6
6
|
function findDesktopApp() {
|
|
7
7
|
if (process.platform === "darwin") {
|
|
@@ -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) {
|
|
@@ -64,32 +71,37 @@ export async function runPluginLogsCommand(pluginId, options, _command) {
|
|
|
64
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) {
|
|
@@ -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,
|
|
@@ -3,4 +3,5 @@ import type { DaemonClient } from "@camerontaylor/paseo-client/internal/daemon-c
|
|
|
3
3
|
export declare function withPluginManagementClient<T>(target: DaemonTarget, run: (client: DaemonClient) => Promise<T>): Promise<T>;
|
|
4
4
|
export declare function withPluginLogsClient<T>(target: DaemonTarget, run: (client: DaemonClient) => Promise<T>): Promise<T>;
|
|
5
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>;
|
|
6
7
|
//# sourceMappingURL=shared.d.ts.map
|
|
@@ -24,7 +24,11 @@ export async function withPluginLogsClient(target, run) {
|
|
|
24
24
|
return withPluginClient(target, "pluginLogs", "Update the host to view plugin logs.", run);
|
|
25
25
|
}
|
|
26
26
|
export async function withPluginSourceClient(target, run) {
|
|
27
|
-
// COMPAT(
|
|
28
|
-
return withPluginClient(target, "
|
|
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
|
package/dist/utils/client-id.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ensurePrivateDirectory } from "@camerontaylor/paseo-server";
|
|
1
|
+
import { ensurePrivateDirectory } from "@camerontaylor/paseo-server/daemon-control";
|
|
2
2
|
import { readFile, writeFile } from "node:fs/promises";
|
|
3
3
|
import { randomUUID } from "node:crypto";
|
|
4
4
|
import { join } from "node:path";
|
package/dist/utils/client.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type DaemonInstance } from "@camerontaylor/paseo-server";
|
|
1
|
+
import { type DaemonInstance } from "@camerontaylor/paseo-server/daemon-control";
|
|
2
2
|
import { type DaemonTarget } from "./daemon-target.js";
|
|
3
3
|
export type { DaemonTarget } from "./daemon-target.js";
|
|
4
4
|
import { DaemonClient } from "@camerontaylor/paseo-client/internal/daemon-client";
|
package/dist/utils/client.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { waitForDaemonReady, resolvePaseoHome } from "@camerontaylor/paseo-server";
|
|
1
|
+
import { waitForDaemonReady, resolvePaseoHome, } from "@camerontaylor/paseo-server/daemon-control";
|
|
2
2
|
import { describeDaemonTarget } from "./daemon-target.js";
|
|
3
3
|
import { buildDaemonWebSocketUrl, buildRelayWebSocketUrl, normalizeHostPort, parseConnectionUri, shouldUseTlsForDefaultHostedRelay, } from "@camerontaylor/paseo-protocol/daemon-endpoints";
|
|
4
4
|
import { parseConnectionOfferFromUrl, } from "@camerontaylor/paseo-protocol/connection-offer";
|
|
@@ -36,8 +36,10 @@ export function withGlobalOptions(handler) {
|
|
|
36
36
|
selectors[key].add(value);
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
for (const key of ["home", "host"]) {
|
|
40
|
+
if (selectors[key].size > 1)
|
|
41
|
+
throw { code: "TARGET_AMBIGUOUS", message: `Conflicting duplicate --${key} selectors.` };
|
|
42
|
+
}
|
|
41
43
|
const localOnly = localCommands.has(command);
|
|
42
44
|
options.daemonTarget = selectDaemonTarget(options, process.env, localOnly);
|
|
43
45
|
mergedArgs[mergedArgs.length - 2] = options;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { resolvePaseoHome } from "@camerontaylor/paseo-server";
|
|
1
|
+
import { resolvePaseoHome } from "@camerontaylor/paseo-server/daemon-control";
|
|
2
2
|
export function selectDaemonTarget(options, env = process.env, localOnly = false) {
|
|
3
3
|
for (const key of ["home", "host"]) {
|
|
4
4
|
if (options[key] !== undefined && !options[key].trim())
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camerontaylor/paseo-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0-beta.2.fork.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
|
-
"@camerontaylor/paseo-client": "0.
|
|
32
|
-
"@camerontaylor/paseo-protocol": "0.
|
|
33
|
-
"@camerontaylor/paseo-server": "0.
|
|
31
|
+
"@camerontaylor/paseo-client": "0.9.0-beta.2.fork.1",
|
|
32
|
+
"@camerontaylor/paseo-protocol": "0.9.0-beta.2.fork.1",
|
|
33
|
+
"@camerontaylor/paseo-server": "0.9.0-beta.2.fork.1",
|
|
34
34
|
"chalk": "^5.3.0",
|
|
35
35
|
"commander": "^12.0.0",
|
|
36
36
|
"mime-types": "^2.1.35",
|