@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.
Files changed (38) hide show
  1. package/dist/cli.js +6 -0
  2. package/dist/commands/daemon/index.js +3 -1
  3. package/dist/commands/daemon/reload.d.ts +10 -0
  4. package/dist/commands/daemon/reload.js +36 -0
  5. package/dist/commands/hub/deploy.d.ts +3 -1
  6. package/dist/commands/hub/deploy.js +7 -4
  7. package/dist/commands/hub/disconnect.js +2 -2
  8. package/dist/commands/hub/hub-client/index.d.ts +3 -2
  9. package/dist/commands/hub/hub-client/index.js +12 -1
  10. package/dist/commands/hub/hub-client/internal/contracts.d.ts +21 -0
  11. package/dist/commands/hub/hub-client/internal/contracts.js +15 -0
  12. package/dist/commands/hub/hub-client/internal/problem.js +16 -3
  13. package/dist/commands/hub/index.js +2 -0
  14. package/dist/commands/hub/init-plan.d.ts +50 -0
  15. package/dist/commands/hub/init-plan.js +136 -0
  16. package/dist/commands/hub/init.d.ts +20 -0
  17. package/dist/commands/hub/init.js +415 -0
  18. package/dist/commands/hub/logout.d.ts +1 -0
  19. package/dist/commands/hub/logout.js +10 -4
  20. package/dist/commands/plugin/index.d.ts +14 -0
  21. package/dist/commands/plugin/index.js +84 -0
  22. package/dist/commands/plugin/scaffold.d.ts +6 -0
  23. package/dist/commands/plugin/scaffold.js +307 -0
  24. package/dist/commands/plugin/shared.d.ts +4 -0
  25. package/dist/commands/plugin/shared.js +26 -0
  26. package/dist/commands/project/create.d.ts +10 -0
  27. package/dist/commands/project/create.js +41 -0
  28. package/dist/commands/project/delete.d.ts +9 -0
  29. package/dist/commands/project/delete.js +33 -0
  30. package/dist/commands/project/index.d.ts +3 -0
  31. package/dist/commands/project/index.js +28 -0
  32. package/dist/commands/project/ls.d.ts +5 -0
  33. package/dist/commands/project/ls.js +19 -0
  34. package/dist/commands/project/rename.d.ts +15 -0
  35. package/dist/commands/project/rename.js +50 -0
  36. package/dist/commands/project/shared.d.ts +11 -0
  37. package/dist/commands/project/shared.js +18 -0
  38. package/package.json +4 -4
package/dist/cli.js CHANGED
@@ -3,6 +3,8 @@ import { createAgentCommand } from "./commands/agent/index.js";
3
3
  import { createDaemonCommand } from "./commands/daemon/index.js";
4
4
  import { createPermitCommand } from "./commands/permit/index.js";
5
5
  import { createProviderCommand } from "./commands/provider/index.js";
6
+ import { createPluginCommand } from "./commands/plugin/index.js";
7
+ import { createProjectCommand } from "./commands/project/index.js";
6
8
  import { createScheduleCommand } from "./commands/schedule/index.js";
7
9
  import { createSpeechCommand } from "./commands/speech/index.js";
8
10
  import { createScriptCommand } from "./commands/script/index.js";
@@ -15,6 +17,7 @@ import { createHooksCommand } from "./commands/hooks.js";
15
17
  import { startCommand as daemonStartCommand } from "./commands/daemon/start.js";
16
18
  import { runStatusCommand as runDaemonStatusCommand } from "./commands/daemon/status.js";
17
19
  import { runRestartCommand as runDaemonRestartCommand } from "./commands/daemon/restart.js";
20
+ import { runDaemonReloadCommand } from "./commands/daemon/reload.js";
18
21
  import { addLsOptions, runLsCommand } from "./commands/agent/ls.js";
19
22
  import { addRunOptions, runRunCommand } from "./commands/agent/run.js";
20
23
  import { addLogsOptions, runLogsCommand } from "./commands/agent/logs.js";
@@ -79,6 +82,7 @@ export function createCli() {
79
82
  .description('Show local daemon status (alias for "paseo daemon status")'))
80
83
  .option("--home <path>", "Paseo home directory (default: ~/.paseo)")
81
84
  .action(withOutput(runDaemonStatusCommand));
85
+ addJsonAndDaemonHostOptions(program.command("reload").description('Reload daemon config (alias for "paseo daemon reload")')).action(withOutput(runDaemonReloadCommand));
82
86
  addJsonOption(program
83
87
  .command("restart")
84
88
  .description('Restart local daemon (alias for "paseo daemon restart")'))
@@ -116,9 +120,11 @@ export function createCli() {
116
120
  program.addCommand(createPermitCommand());
117
121
  // Provider commands
118
122
  program.addCommand(createProviderCommand());
123
+ program.addCommand(createPluginCommand());
119
124
  // Speech model commands
120
125
  program.addCommand(createSpeechCommand());
121
126
  // Workspace commands
127
+ program.addCommand(createProjectCommand());
122
128
  program.addCommand(createWorkspaceCommand());
123
129
  // COMPAT(worktreeCli): legacy command alias added before workspace was the product unit.
124
130
  // Added in v0.2.0; remove after 2027-01-17.
@@ -5,8 +5,9 @@ import { runStopCommand } from "./stop.js";
5
5
  import { runRestartCommand } from "./restart.js";
6
6
  import { runSetPasswordCommand } from "./set-password.js";
7
7
  import { pairCommand } from "./pair.js";
8
+ import { runDaemonReloadCommand } from "./reload.js";
8
9
  import { withOutput } from "../../output/index.js";
9
- import { addJsonOption } from "../../utils/command-options.js";
10
+ import { addJsonAndDaemonHostOptions, addJsonOption } from "../../utils/command-options.js";
10
11
  function resolveHostnamesOption(hostnames, allowedHosts) {
11
12
  if (typeof hostnames === "string")
12
13
  return hostnames;
@@ -18,6 +19,7 @@ export function createDaemonCommand() {
18
19
  const daemon = new Command("daemon").description("Manage the Paseo daemon");
19
20
  daemon.addCommand(startCommand());
20
21
  daemon.addCommand(pairCommand());
22
+ addJsonAndDaemonHostOptions(daemon.command("reload").description("Reload config.json without restarting the daemon")).action(withOutput(runDaemonReloadCommand));
21
23
  addJsonOption(daemon.command("status").description("Show local daemon status"))
22
24
  .option("--home <path>", "Paseo home directory (default: ~/.paseo)")
23
25
  .action(withOutput(runStatusCommand));
@@ -0,0 +1,10 @@
1
+ import type { Command } from "commander";
2
+ import type { CommandOptions, OutputSchema, SingleResult } from "../../output/index.js";
3
+ export interface DaemonReloadResult {
4
+ appliedPaths: string[];
5
+ restartRequiredPaths: string[];
6
+ overrideControlledPaths: string[];
7
+ }
8
+ export declare const daemonReloadSchema: OutputSchema<DaemonReloadResult>;
9
+ export declare function runDaemonReloadCommand(options: CommandOptions, _command: Command): Promise<SingleResult<DaemonReloadResult>>;
10
+ //# sourceMappingURL=reload.d.ts.map
@@ -0,0 +1,36 @@
1
+ import { connectToDaemon } from "../../utils/client.js";
2
+ export const daemonReloadSchema = {
3
+ idField: () => "daemon-config",
4
+ columns: [],
5
+ renderHuman(result) {
6
+ if (result.type !== "single")
7
+ return "";
8
+ const lines = ["Configuration reloaded."];
9
+ if (result.data.restartRequiredPaths.length > 0) {
10
+ lines.push("", "Warning: These changes require a daemon restart:", ...result.data.restartRequiredPaths.map((path) => ` ${path}`), "", "Run: paseo daemon restart");
11
+ }
12
+ if (result.data.overrideControlledPaths.length > 0) {
13
+ lines.push("", "Warning: These settings are controlled by daemon launch overrides:", ...result.data.overrideControlledPaths.map((path) => ` ${path}`));
14
+ }
15
+ return lines.join("\n");
16
+ },
17
+ };
18
+ export async function runDaemonReloadCommand(options, _command) {
19
+ const client = await connectToDaemon({ host: options.host });
20
+ try {
21
+ const payload = await client.reloadDaemonConfig();
22
+ return {
23
+ type: "single",
24
+ data: {
25
+ appliedPaths: payload.appliedPaths,
26
+ restartRequiredPaths: payload.restartRequiredPaths,
27
+ overrideControlledPaths: payload.overrideControlledPaths,
28
+ },
29
+ schema: daemonReloadSchema,
30
+ };
31
+ }
32
+ finally {
33
+ await client.close();
34
+ }
35
+ }
36
+ //# sourceMappingURL=reload.js.map
@@ -2,6 +2,7 @@ import type { Command } from "commander";
2
2
  import { type SingleResult } from "../../output/index.js";
3
3
  import { HubHttpClient, type HubInstallResult, type HubValidationResult } from "./hub-client/index.js";
4
4
  import { type HubCredentialStore } from "./credentials.js";
5
+ import { type HubDeployBundle } from "./deploy-bundle.js";
5
6
  import { type HubReporter } from "./reporter.js";
6
7
  export interface HubDeployOptions {
7
8
  project?: string;
@@ -10,7 +11,7 @@ export interface HubDeployOptions {
10
11
  dryRun?: boolean;
11
12
  json?: boolean;
12
13
  }
13
- interface HubDeployEnvironment {
14
+ export interface HubDeployEnvironment {
14
15
  cwd: string;
15
16
  env: Readonly<Record<string, string | undefined>>;
16
17
  credentials?: HubCredentialStore;
@@ -33,6 +34,7 @@ interface HubDryRunResult extends HubValidationResult {
33
34
  workflows: number;
34
35
  }
35
36
  export declare function runHubDeploy(options: HubDeployOptions, environment?: HubDeployEnvironment): Promise<SingleResult<HubDeployResult> | SingleResult<HubDryRunResult>>;
37
+ export declare function runHubDeployBundle(options: HubDeployOptions, deployInput: HubDeployBundle, environment: HubDeployEnvironment): Promise<SingleResult<HubDeployResult> | SingleResult<HubDryRunResult>>;
36
38
  export declare function addHubDeployCommand(hub: Command, dependencies: HubDeployCommandDependencies): void;
37
39
  export {};
38
40
  //# sourceMappingURL=deploy.d.ts.map
@@ -32,6 +32,13 @@ export async function runHubDeploy(options, environment = {
32
32
  credentials: new PrivateHubCredentialStore(),
33
33
  hub: new HubHttpClient(),
34
34
  }) {
35
+ const deployInput = await discoverHubBundle({
36
+ cwd: environment.cwd,
37
+ ...(options.project === undefined ? {} : { project: options.project }),
38
+ });
39
+ return runHubDeployBundle(options, deployInput, environment);
40
+ }
41
+ export async function runHubDeployBundle(options, deployInput, environment) {
35
42
  const credentials = environment.credentials ?? new PrivateHubCredentialStore(environment.env);
36
43
  const resolution = {
37
44
  options: { origin: options.hub, apiKey: options.apiKey },
@@ -39,10 +46,6 @@ export async function runHubDeploy(options, environment = {
39
46
  credentials,
40
47
  };
41
48
  const origin = resolveHubOrigin(resolution);
42
- const deployInput = await discoverHubBundle({
43
- cwd: environment.cwd,
44
- ...(options.project === undefined ? {} : { project: options.project }),
45
- });
46
49
  const action = options.dryRun === true ? "Validating" : "Deploying";
47
50
  reportHubProgress(environment.reporter ?? processHubReporter, options, `${action} ${deployInput.projectSlug} ${options.dryRun === true ? "against" : "to"} ${origin}`);
48
51
  const credential = resolveHubCredential({ ...resolution, origin });
@@ -10,13 +10,13 @@ export function runHubDisconnect(options, dependencies) {
10
10
  reportHubProgress(dependencies.reporter, options, `Disconnecting this daemon from ${current.hubOrigin}`);
11
11
  }
12
12
  const response = await client.disconnectHub(options.force ?? false);
13
- return hubStatusResult(response.status, response.warning, current.hubOrigin);
13
+ return hubStatusResult(response.status, response.warning);
14
14
  });
15
15
  }
16
16
  export function addHubDisconnectCommand(parent, dependencies) {
17
17
  addJsonAndDaemonHostOptions(parent
18
18
  .command("disconnect")
19
- .option("--force", "Remove local authority even if the Hub is offline")).action(withOutput(async (...args) => {
19
+ .option("--force", "Remove local authority without notifying the Hub")).action(withOutput(async (...args) => {
20
20
  const options = args.at(-2);
21
21
  return runHubDisconnect(options, dependencies);
22
22
  }));
@@ -1,6 +1,6 @@
1
1
  import type { HubBundleFile } from "../deploy-bundle.js";
2
- import { type CliAuthorization, type CliAuthorizationPoll, type HubInstallResult, type HubProject, type HubValidationResult } from "./internal/contracts.js";
3
- export type { CliAuthorization, CliAuthorizationPoll, HubInstallResult, HubProject, HubValidationResult, } from "./internal/contracts.js";
2
+ import { type CliAuthorization, type CliAuthorizationPoll, type HubInstallResult, type HubConfigurationResources, type HubProject, type HubValidationResult } from "./internal/contracts.js";
3
+ export type { CliAuthorization, CliAuthorizationPoll, HubInstallResult, HubConfigurationResources, HubProject, HubValidationResult, } from "./internal/contracts.js";
4
4
  interface HubConfigurationInput {
5
5
  origin: string;
6
6
  apiKey: string;
@@ -11,6 +11,7 @@ export declare class HubHttpClient {
11
11
  startCliAuthorization(origin: string): Promise<CliAuthorization>;
12
12
  pollCliAuthorization(origin: string, deviceCode: string, timeoutMilliseconds: number): Promise<CliAuthorizationPoll>;
13
13
  listProjects(origin: string, apiKey: string): Promise<HubProject[]>;
14
+ listConfigurationResources(origin: string, apiKey: string): Promise<HubConfigurationResources>;
14
15
  installConfiguration(input: HubConfigurationInput): Promise<HubInstallResult>;
15
16
  validateConfiguration(input: HubConfigurationInput): Promise<HubValidationResult>;
16
17
  issueEnrollmentToken(origin: string, apiKey: string): Promise<string>;
@@ -1,5 +1,5 @@
1
1
  import { HubCommandError } from "../error.js";
2
- import { authorizationPollSchema, authorizationSchema, enrollmentTokenSchema, installResponseSchema, projectsResponseSchema, validationResponseSchema, } from "./internal/contracts.js";
2
+ import { authorizationPollSchema, authorizationSchema, configurationResourcesSchema, enrollmentTokenSchema, installResponseSchema, projectsResponseSchema, validationResponseSchema, } from "./internal/contracts.js";
3
3
  import { requestHub } from "./internal/transport.js";
4
4
  export class HubHttpClient {
5
5
  startCliAuthorization(origin) {
@@ -45,6 +45,17 @@ export class HubHttpClient {
45
45
  });
46
46
  return response.projects;
47
47
  }
48
+ listConfigurationResources(origin, apiKey) {
49
+ return requestHub({
50
+ origin,
51
+ path: "/api/v1/configuration-resources",
52
+ method: "GET",
53
+ apiKey,
54
+ successStatus: 200,
55
+ schema: configurationResourcesSchema,
56
+ failureMessage: "Hub configuration resource listing failed",
57
+ });
58
+ }
48
59
  installConfiguration(input) {
49
60
  return requestHub({
50
61
  origin: input.origin,
@@ -42,6 +42,26 @@ export declare const projectsResponseSchema: z.ZodObject<{
42
42
  name: z.ZodString;
43
43
  }, z.core.$strict>>;
44
44
  }, z.core.$strict>;
45
+ export declare const configurationResourcesSchema: z.ZodObject<{
46
+ daemons: z.ZodArray<z.ZodObject<{
47
+ id: z.ZodString;
48
+ slug: z.ZodString;
49
+ }, z.core.$strict>>;
50
+ github: z.ZodArray<z.ZodObject<{
51
+ slug: z.ZodString;
52
+ accountLogin: z.ZodString;
53
+ accountType: z.ZodString;
54
+ repositories: z.ZodArray<z.ZodString>;
55
+ }, z.core.$strict>>;
56
+ discord: z.ZodArray<z.ZodObject<{
57
+ slug: z.ZodString;
58
+ guildName: z.ZodString;
59
+ }, z.core.$strict>>;
60
+ slack: z.ZodArray<z.ZodObject<{
61
+ slug: z.ZodString;
62
+ teamName: z.ZodString;
63
+ }, z.core.$strict>>;
64
+ }, z.core.$strict>;
45
65
  export declare const installResponseSchema: z.ZodObject<{
46
66
  projectSlug: z.ZodString;
47
67
  version: z.ZodNumber;
@@ -59,6 +79,7 @@ export declare const enrollmentTokenSchema: z.ZodObject<{
59
79
  export type CliAuthorization = z.infer<typeof authorizationSchema>;
60
80
  export type CliAuthorizationPoll = z.infer<typeof authorizationPollSchema>;
61
81
  export type HubProject = z.infer<typeof projectSchema>;
82
+ export type HubConfigurationResources = z.infer<typeof configurationResourcesSchema>;
62
83
  export type HubInstallResult = z.infer<typeof installResponseSchema>;
63
84
  export type HubValidationResult = z.infer<typeof validationResponseSchema>;
64
85
  export {};
@@ -30,6 +30,21 @@ const projectSchema = z
30
30
  .object({ id: z.string().uuid(), slug: z.string().min(1), name: z.string().min(1) })
31
31
  .strict();
32
32
  export const projectsResponseSchema = z.object({ projects: z.array(projectSchema) }).strict();
33
+ export const configurationResourcesSchema = z
34
+ .object({
35
+ daemons: z.array(z.object({ id: z.string().uuid(), slug: z.string().min(1) }).strict()),
36
+ github: z.array(z
37
+ .object({
38
+ slug: z.string().min(1),
39
+ accountLogin: z.string().min(1),
40
+ accountType: z.string().min(1),
41
+ repositories: z.array(z.string().min(1)),
42
+ })
43
+ .strict()),
44
+ discord: z.array(z.object({ slug: z.string().min(1), guildName: z.string().min(1) }).strict()),
45
+ slack: z.array(z.object({ slug: z.string().min(1), teamName: z.string().min(1) }).strict()),
46
+ })
47
+ .strict();
33
48
  export const installResponseSchema = z
34
49
  .object({
35
50
  projectSlug: z.string().min(1),
@@ -35,9 +35,15 @@ export async function hubRequestFailure(response, failureMessage, apiKey) {
35
35
  return new HubCommandError("HUB_INVALID_RESPONSE", `Hub returned nonconforming problem details for HTTP ${response.status}.`);
36
36
  }
37
37
  const title = parsed.data.title ?? `${failureMessage} with HTTP ${response.status}`;
38
- const message = parsed.data.detail === undefined ? title : `${title}: ${parsed.data.detail}`;
39
38
  const details = formatFieldIssues(parsed.data.errors, parsed.data.issues);
40
- const code = response.status === 422 ? "HUB_VALIDATION_FAILED" : "HUB_REQUEST_FAILED";
39
+ const message = details !== undefined || parsed.data.detail === undefined
40
+ ? title
41
+ : `${title}: ${parsed.data.detail}`;
42
+ let code = "HUB_REQUEST_FAILED";
43
+ if (response.status === 422)
44
+ code = "HUB_VALIDATION_FAILED";
45
+ if (response.status === 404)
46
+ code = "HUB_NOT_FOUND";
41
47
  return new HubCommandError(code, redactSecret(message, apiKey), details === undefined ? undefined : redactSecret(details, apiKey));
42
48
  }
43
49
  function formatFieldIssues(errors, issues) {
@@ -57,6 +63,13 @@ function formatFieldIssues(errors, issues) {
57
63
  function formatIssuePath(path) {
58
64
  if (path === undefined || typeof path === "string")
59
65
  return path;
66
+ const [file, ...fieldPath] = path;
67
+ if (typeof file === "string" && file.startsWith(".paseo/") && fieldPath.length > 0) {
68
+ return `${file}: ${formatPathSegments(fieldPath)}`;
69
+ }
70
+ return formatPathSegments(path) || undefined;
71
+ }
72
+ function formatPathSegments(path) {
60
73
  let formatted = "";
61
74
  for (const segment of path) {
62
75
  if (typeof segment === "number")
@@ -64,7 +77,7 @@ function formatIssuePath(path) {
64
77
  else
65
78
  formatted += formatted.length === 0 ? segment : `.${segment}`;
66
79
  }
67
- return formatted || undefined;
80
+ return formatted;
68
81
  }
69
82
  function redactSecret(value, secret) {
70
83
  return secret === undefined ? value : value.split(secret).join("[redacted]");
@@ -14,6 +14,7 @@ import { addHubProjectsCommand } from "./projects.js";
14
14
  import { processHubReporter } from "./reporter.js";
15
15
  import { hubStatusResult } from "./status-output.js";
16
16
  import { addHubResolutionHelp } from "./help.js";
17
+ import { addHubInitCommand } from "./init.js";
17
18
  function productionEnvironment() {
18
19
  const env = process.env;
19
20
  const hub = new HubHttpClient();
@@ -37,6 +38,7 @@ export function createHubCommand(overrides = {}) {
37
38
  flow: environment.login,
38
39
  reporter: environment.reporter,
39
40
  });
41
+ addHubInitCommand(hub, environment);
40
42
  addHubConnectCommand(hub, {
41
43
  env: environment.env,
42
44
  credentials: environment.credentials,
@@ -0,0 +1,50 @@
1
+ import type { HubDeployBundle } from "./deploy-bundle.js";
2
+ import type { HubProject } from "./hub-client/index.js";
3
+ import type { HubStatus } from "./daemon-client.js";
4
+ export type HubInitProvider = "github" | "slack" | "discord";
5
+ export type HubInitProjectResolution = {
6
+ kind: "none";
7
+ } | {
8
+ kind: "selected";
9
+ project: HubProject;
10
+ } | {
11
+ kind: "choose";
12
+ projects: readonly HubProject[];
13
+ };
14
+ export type HubInitConnectionResolution = {
15
+ kind: "connected";
16
+ daemonId: string;
17
+ } | {
18
+ kind: "pending";
19
+ state: "connecting" | "reconnecting";
20
+ } | {
21
+ kind: "connect";
22
+ } | {
23
+ kind: "conflict";
24
+ origin: string;
25
+ };
26
+ export interface HubInitOpeningPlan {
27
+ replaceExisting: boolean;
28
+ steps: readonly ("login" | "connect" | "project" | "scaffold")[];
29
+ }
30
+ export interface HubInitScaffoldInput {
31
+ cwd: string;
32
+ daemonSlug: string;
33
+ provider: HubInitProvider;
34
+ providerFilters: Readonly<Record<string, string>>;
35
+ }
36
+ export interface HubInitScaffold {
37
+ hub: string;
38
+ workflowPath: string;
39
+ workflow: string;
40
+ testAction: string;
41
+ }
42
+ export declare function planHubInitOpening(input: {
43
+ loggedIn: boolean;
44
+ paseoDirectoryExists: boolean;
45
+ }): HubInitOpeningPlan;
46
+ export declare function createHubInitBundle(projectSlug: string, scaffold: HubInitScaffold): HubDeployBundle;
47
+ export declare function resolveHubInitProjects(projects: readonly HubProject[]): HubInitProjectResolution;
48
+ export declare function resolveHubInitConnection(status: HubStatus, origin: string): HubInitConnectionResolution;
49
+ export declare function createHubInitScaffold(input: HubInitScaffoldInput): HubInitScaffold;
50
+ //# sourceMappingURL=init-plan.d.ts.map
@@ -0,0 +1,136 @@
1
+ import path from "node:path";
2
+ import YAML from "yaml";
3
+ export function planHubInitOpening(input) {
4
+ return {
5
+ replaceExisting: input.paseoDirectoryExists,
6
+ steps: [...(input.loggedIn ? [] : ["login"]), "connect", "project", "scaffold"],
7
+ };
8
+ }
9
+ export function createHubInitBundle(projectSlug, scaffold) {
10
+ return {
11
+ projectSlug,
12
+ workflowCount: 1,
13
+ files: [
14
+ { path: ".paseo/hub.yml", content: scaffold.hub },
15
+ { path: scaffold.workflowPath, content: scaffold.workflow },
16
+ ],
17
+ };
18
+ }
19
+ export function resolveHubInitProjects(projects) {
20
+ if (projects.length === 0)
21
+ return { kind: "none" };
22
+ if (projects.length === 1)
23
+ return { kind: "selected", project: projects[0] };
24
+ return { kind: "choose", projects };
25
+ }
26
+ export function resolveHubInitConnection(status, origin) {
27
+ if (status.state === "connected" && status.hubOrigin === origin && status.daemonId !== null) {
28
+ return { kind: "connected", daemonId: status.daemonId };
29
+ }
30
+ if ((status.state === "connecting" || status.state === "reconnecting") &&
31
+ status.hubOrigin === origin) {
32
+ return { kind: "pending", state: status.state };
33
+ }
34
+ if (status.hubOrigin !== null && status.state !== "not_connected" && status.state !== "revoked") {
35
+ return { kind: "conflict", origin: status.hubOrigin };
36
+ }
37
+ return { kind: "connect" };
38
+ }
39
+ export function createHubInitScaffold(input) {
40
+ const environmentName = input.daemonSlug;
41
+ const hub = YAML.stringify({
42
+ environments: {
43
+ [environmentName]: {
44
+ kind: "daemon",
45
+ daemon: input.daemonSlug,
46
+ cwd: path.resolve(input.cwd),
47
+ },
48
+ },
49
+ agents: {
50
+ codex: {
51
+ provider: "codex",
52
+ mode: "full-access",
53
+ },
54
+ },
55
+ }, { lineWidth: 0 });
56
+ const provider = providerScaffold(input.provider, input.providerFilters, environmentName);
57
+ return {
58
+ hub,
59
+ workflowPath: `.paseo/workflows/${input.provider}-help.yml`,
60
+ workflow: YAML.stringify(provider.workflow, { lineWidth: 0 }),
61
+ testAction: provider.testAction,
62
+ };
63
+ }
64
+ function providerScaffold(provider, filters, environment) {
65
+ if (provider === "github") {
66
+ const repo = requireFilter(filters, "repo");
67
+ const user = requireFilter(filters, "user");
68
+ return {
69
+ workflow: workflow({
70
+ name: "github-help",
71
+ on: "github.issue_comment",
72
+ filters: { repo, contains: "@paseo", from_users: [user] },
73
+ environment,
74
+ }),
75
+ testAction: `Comment \`@paseo have a look\` on ${repo}.`,
76
+ };
77
+ }
78
+ const user = requireFilter(filters, "user");
79
+ if (provider === "slack") {
80
+ const workspace = requireFilter(filters, "workspace");
81
+ return {
82
+ workflow: workflow({
83
+ name: "slack-help",
84
+ on: "slack.mention",
85
+ filters: { workspace, from_users: [user] },
86
+ environment,
87
+ reply: "slack.reply",
88
+ }),
89
+ testAction: "Mention `@Paseo have a look` in Slack.",
90
+ };
91
+ }
92
+ const guild = requireFilter(filters, "guild");
93
+ return {
94
+ workflow: workflow({
95
+ name: "discord-help",
96
+ on: "discord.mention",
97
+ filters: { guild, from_users: [user] },
98
+ environment,
99
+ reply: "discord.reply",
100
+ }),
101
+ testAction: "Mention `@Paseo have a look` in Discord.",
102
+ };
103
+ }
104
+ function workflow(input) {
105
+ const replyInstruction = input.reply === undefined ? "" : "Answer with hub.reply, then ";
106
+ return {
107
+ name: input.name,
108
+ on: input.on,
109
+ max_runtime: "2h",
110
+ filters: input.filters,
111
+ steps: [
112
+ {
113
+ id: "work",
114
+ environment: input.environment,
115
+ max_runtime: "90m",
116
+ idle_timeout: "10m",
117
+ agent: "codex",
118
+ prompt: [
119
+ {
120
+ text: `${replyInstruction}complete this request and call hub.finish_execution when done.\n\n<user-prompt>\n\${{ paseo.prompt }}\n</user-prompt>\n`,
121
+ },
122
+ ],
123
+ ...(input.reply === undefined
124
+ ? {}
125
+ : { allow_outputs: [{ type: input.reply, max: 1, required: true }] }),
126
+ },
127
+ ],
128
+ };
129
+ }
130
+ function requireFilter(filters, name) {
131
+ const value = filters[name]?.trim();
132
+ if (!value)
133
+ throw new Error(`${name} is required for this provider`);
134
+ return value;
135
+ }
136
+ //# sourceMappingURL=init-plan.js.map
@@ -0,0 +1,20 @@
1
+ import type { Command } from "commander";
2
+ import type { HubCredentialStore } from "./credentials.js";
3
+ import type { HubDaemonConnection } from "./daemon-client.js";
4
+ import type { HubHttpClient } from "./hub-client/index.js";
5
+ import type { CliLoginFlow } from "./login-flow.js";
6
+ import type { HubReporter } from "./reporter.js";
7
+ interface HubInitEnvironment {
8
+ env: Readonly<Record<string, string | undefined>>;
9
+ credentials: HubCredentialStore;
10
+ hub: HubHttpClient;
11
+ login: Pick<CliLoginFlow, "authorize">;
12
+ daemon: HubDaemonConnection;
13
+ reporter: HubReporter;
14
+ cwd(): string;
15
+ }
16
+ export declare function addHubInitCommand(parent: Command, environment: HubInitEnvironment): void;
17
+ export declare function runHubInit(environment: HubInitEnvironment): Promise<void>;
18
+ export declare function githubRepositoryFromRemote(remote: string): string | undefined;
19
+ export {};
20
+ //# sourceMappingURL=init.d.ts.map