feat(hub): guide starter setup (#3651)
* feat(hub): guide setup with provider IDs * fix(hub): preserve login setup state * feat(hub): select starter agent runtime Use the connected daemon's provider snapshot so generated Hub bundles only contain complete provider, model, and mode combinations. * fix(hub): stage starter runtime choices Keep providers with valid modes selectable when the daemon has no default mode, so users explicitly choose the complete runtime. * fix(hub): scope runtime choices to workspace Provider capabilities can vary by repository, so request the snapshot for the bundle directory that guided setup will deploy.
This commit is contained in:
@@ -91,6 +91,56 @@ describe("Hub commands", () => {
|
||||
assert.equal(result.data.origin, "https://hub.paseo.sh");
|
||||
});
|
||||
|
||||
it("interactive login continues through the injected guided setup coordinator without invoking a CLI command", async () => {
|
||||
const credentials = new MemoryCredentials();
|
||||
const events: string[] = [];
|
||||
|
||||
await runHubLogin(
|
||||
"https://hub.test",
|
||||
{},
|
||||
{
|
||||
env: {},
|
||||
credentials,
|
||||
flow: {
|
||||
authorize: async () => {
|
||||
events.push("login");
|
||||
return "paseo_cli_prefix_durable-secret";
|
||||
},
|
||||
},
|
||||
isInteractive: () => true,
|
||||
continueGuidedSetup: async (origin) => {
|
||||
events.push(`connect:${origin}`);
|
||||
events.push("init");
|
||||
events.push("deploy");
|
||||
},
|
||||
reporter: quietReporter,
|
||||
},
|
||||
);
|
||||
|
||||
assert.deepEqual(events, ["login", "connect:https://hub.test", "init", "deploy"]);
|
||||
});
|
||||
|
||||
it("JSON and noninteractive login remain login-only", async () => {
|
||||
for (const [options, interactive] of [
|
||||
[{ json: true }, true],
|
||||
[{}, false],
|
||||
] as const) {
|
||||
const credentials = new MemoryCredentials();
|
||||
let continuationCount = 0;
|
||||
await runHubLogin(undefined, options, {
|
||||
env: {},
|
||||
credentials,
|
||||
flow: { authorize: async () => "paseo_cli_prefix_durable-secret" },
|
||||
isInteractive: () => interactive,
|
||||
continueGuidedSetup: async () => {
|
||||
continuationCount += 1;
|
||||
},
|
||||
reporter: quietReporter,
|
||||
});
|
||||
assert.equal(continuationCount, 0);
|
||||
}
|
||||
});
|
||||
|
||||
it("connect exchanges authority once and gives only the enrollment token to the daemon", async () => {
|
||||
const credentials = new MemoryCredentials();
|
||||
credentials.save({ origin: "https://hub.test", credential: "stored-human-secret" });
|
||||
@@ -484,6 +534,10 @@ class FakeDaemon implements HubDaemonClient {
|
||||
return { status: hubStatus("connected", this.origin) };
|
||||
}
|
||||
|
||||
async getProvidersSnapshot() {
|
||||
return { entries: [] };
|
||||
}
|
||||
|
||||
async disconnectHub(force: boolean) {
|
||||
this.disconnects += 1;
|
||||
this.disconnectForces.push(force);
|
||||
|
||||
Reference in New Issue
Block a user