omnara 1.0.5 → 1.0.6
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/bin.js +297 -241
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -8,11 +8,6 @@ var __export = (target, all) => {
|
|
|
8
8
|
// src/bin.ts
|
|
9
9
|
import { Command } from "commander";
|
|
10
10
|
|
|
11
|
-
// src/config.ts
|
|
12
|
-
import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
13
|
-
import { homedir } from "node:os";
|
|
14
|
-
import { dirname, join } from "node:path";
|
|
15
|
-
|
|
16
11
|
// ../sdk/src/generated/sdk.gen.ts
|
|
17
12
|
var sdk_gen_exports = {};
|
|
18
13
|
__export(sdk_gen_exports, {
|
|
@@ -1248,7 +1243,7 @@ var zConfiguredModel = z.object({
|
|
|
1248
1243
|
context_window_tokens: z.int(),
|
|
1249
1244
|
max_output_tokens: z.int(),
|
|
1250
1245
|
default_max_output_tokens: z.int().nullish(),
|
|
1251
|
-
default_cache_retention: zModelCacheRetention,
|
|
1246
|
+
default_cache_retention: zModelCacheRetention.optional(),
|
|
1252
1247
|
supports_tools: z.boolean(),
|
|
1253
1248
|
supports_reasoning: z.boolean(),
|
|
1254
1249
|
default_reasoning_effort: z.string(),
|
|
@@ -6810,12 +6805,12 @@ async function pollDeviceAuthToken(options) {
|
|
|
6810
6805
|
}
|
|
6811
6806
|
}
|
|
6812
6807
|
|
|
6813
|
-
// src/config.ts
|
|
6808
|
+
// src/config-file.ts
|
|
6809
|
+
import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
6810
|
+
import { homedir } from "node:os";
|
|
6811
|
+
import { dirname, join } from "node:path";
|
|
6814
6812
|
import * as z5 from "zod";
|
|
6815
6813
|
|
|
6816
|
-
// src/interactive.ts
|
|
6817
|
-
import { isCancel, select } from "@clack/prompts";
|
|
6818
|
-
|
|
6819
6814
|
// src/output.ts
|
|
6820
6815
|
import * as z4 from "zod";
|
|
6821
6816
|
var zRenderValue = z4.json();
|
|
@@ -7003,54 +6998,7 @@ ${z4.prettifyError(error)}`);
|
|
|
7003
6998
|
}
|
|
7004
6999
|
}
|
|
7005
7000
|
|
|
7006
|
-
// src/
|
|
7007
|
-
function canPromptInteractively() {
|
|
7008
|
-
return process.stdin.isTTY && process.stdout.isTTY;
|
|
7009
|
-
}
|
|
7010
|
-
async function selectFrom(message, choices) {
|
|
7011
|
-
const [only] = choices;
|
|
7012
|
-
if (choices.length === 1 && only !== void 0) {
|
|
7013
|
-
console.log(`${message}: ${only.label} (only option)`);
|
|
7014
|
-
return only.id;
|
|
7015
|
-
}
|
|
7016
|
-
const picked = await select({
|
|
7017
|
-
message,
|
|
7018
|
-
options: choices.map((choice) => ({ value: choice.id, label: choice.label, hint: choice.id }))
|
|
7019
|
-
});
|
|
7020
|
-
if (isCancel(picked)) throw new CliInputError("selection cancelled");
|
|
7021
|
-
return picked;
|
|
7022
|
-
}
|
|
7023
|
-
async function promptOrgSelection(client2) {
|
|
7024
|
-
const { data } = await sdk_gen_exports.getCurrentUser({ client: client2 });
|
|
7025
|
-
if (data.orgs.length === 0) {
|
|
7026
|
-
throw new CliInputError("this account has no organizations");
|
|
7027
|
-
}
|
|
7028
|
-
return selectFrom(
|
|
7029
|
-
"Select an organization",
|
|
7030
|
-
data.orgs.map((org) => ({ id: org.id, label: org.name }))
|
|
7031
|
-
);
|
|
7032
|
-
}
|
|
7033
|
-
async function promptProjectSelection(client2, orgId) {
|
|
7034
|
-
const projects = [];
|
|
7035
|
-
let cursor;
|
|
7036
|
-
do {
|
|
7037
|
-
const { data } = await sdk_gen_exports.listVisibleProjects({
|
|
7038
|
-
client: client2,
|
|
7039
|
-
path: { orgID: orgId },
|
|
7040
|
-
query: cursor === void 0 ? {} : { cursor }
|
|
7041
|
-
});
|
|
7042
|
-
projects.push(...data.data.map((project) => ({ id: project.id, label: project.name })));
|
|
7043
|
-
cursor = data.next_cursor ?? void 0;
|
|
7044
|
-
} while (cursor !== void 0);
|
|
7045
|
-
if (projects.length === 0) {
|
|
7046
|
-
throw new CliInputError(`no projects visible in organization ${orgId}`);
|
|
7047
|
-
}
|
|
7048
|
-
return selectFrom("Select a project", projects);
|
|
7049
|
-
}
|
|
7050
|
-
|
|
7051
|
-
// src/config.ts
|
|
7052
|
-
var DEFAULT_API_URL = "https://api.omnara.com/v1";
|
|
7053
|
-
var DEFAULT_ISSUER_URL = "https://app.omnara.com";
|
|
7001
|
+
// src/config-file.ts
|
|
7054
7002
|
var zConfigFile = z5.looseObject({
|
|
7055
7003
|
api_url: z5.url().optional(),
|
|
7056
7004
|
issuer_url: z5.url().optional(),
|
|
@@ -7113,6 +7061,234 @@ ${z5.prettifyError(result.error)}`);
|
|
|
7113
7061
|
chmodSync(configFilePath(), 384);
|
|
7114
7062
|
return result.data;
|
|
7115
7063
|
}
|
|
7064
|
+
|
|
7065
|
+
// src/device-login.ts
|
|
7066
|
+
import { hostname } from "node:os";
|
|
7067
|
+
import { intro, log, note, outro, spinner } from "@clack/prompts";
|
|
7068
|
+
import * as z6 from "zod";
|
|
7069
|
+
|
|
7070
|
+
// src/browser.ts
|
|
7071
|
+
import { spawn } from "node:child_process";
|
|
7072
|
+
function browserCommand(url4) {
|
|
7073
|
+
if (process.platform === "darwin") {
|
|
7074
|
+
return { command: "open", args: [url4], windowsVerbatimArguments: false };
|
|
7075
|
+
}
|
|
7076
|
+
if (process.platform === "win32") {
|
|
7077
|
+
return {
|
|
7078
|
+
command: "cmd",
|
|
7079
|
+
args: ["/c", "start", '""', `"${url4}"`],
|
|
7080
|
+
windowsVerbatimArguments: true
|
|
7081
|
+
};
|
|
7082
|
+
}
|
|
7083
|
+
return { command: "xdg-open", args: [url4], windowsVerbatimArguments: false };
|
|
7084
|
+
}
|
|
7085
|
+
function openInBrowser(url4, onError) {
|
|
7086
|
+
const { command, args, windowsVerbatimArguments } = browserCommand(url4);
|
|
7087
|
+
const child = spawn(command, args, { stdio: "ignore", detached: true, windowsVerbatimArguments });
|
|
7088
|
+
child.once("error", () => {
|
|
7089
|
+
onError("could not open a browser; use the URL above");
|
|
7090
|
+
});
|
|
7091
|
+
child.unref();
|
|
7092
|
+
}
|
|
7093
|
+
|
|
7094
|
+
// src/interactive.ts
|
|
7095
|
+
import { isCancel, select } from "@clack/prompts";
|
|
7096
|
+
function canPromptInteractively() {
|
|
7097
|
+
return process.stdin.isTTY && process.stdout.isTTY;
|
|
7098
|
+
}
|
|
7099
|
+
async function selectFrom(message, choices) {
|
|
7100
|
+
const [only] = choices;
|
|
7101
|
+
if (choices.length === 1 && only !== void 0) {
|
|
7102
|
+
console.log(`${message}: ${only.label} (only option)`);
|
|
7103
|
+
return only.id;
|
|
7104
|
+
}
|
|
7105
|
+
const picked = await select({
|
|
7106
|
+
message,
|
|
7107
|
+
options: choices.map((choice) => ({ value: choice.id, label: choice.label, hint: choice.id }))
|
|
7108
|
+
});
|
|
7109
|
+
if (isCancel(picked)) throw new CliInputError("selection cancelled");
|
|
7110
|
+
return picked;
|
|
7111
|
+
}
|
|
7112
|
+
async function promptOrgSelection(client2) {
|
|
7113
|
+
const { data } = await sdk_gen_exports.getCurrentUser({ client: client2 });
|
|
7114
|
+
if (data.orgs.length === 0) {
|
|
7115
|
+
throw new CliInputError("this account has no organizations");
|
|
7116
|
+
}
|
|
7117
|
+
return selectFrom(
|
|
7118
|
+
"Select an organization",
|
|
7119
|
+
data.orgs.map((org) => ({ id: org.id, label: org.name }))
|
|
7120
|
+
);
|
|
7121
|
+
}
|
|
7122
|
+
async function promptProjectSelection(client2, orgId) {
|
|
7123
|
+
const projects = [];
|
|
7124
|
+
let cursor;
|
|
7125
|
+
do {
|
|
7126
|
+
const { data } = await sdk_gen_exports.listVisibleProjects({
|
|
7127
|
+
client: client2,
|
|
7128
|
+
path: { orgID: orgId },
|
|
7129
|
+
query: cursor === void 0 ? {} : { cursor }
|
|
7130
|
+
});
|
|
7131
|
+
projects.push(...data.data.map((project) => ({ id: project.id, label: project.name })));
|
|
7132
|
+
cursor = data.next_cursor ?? void 0;
|
|
7133
|
+
} while (cursor !== void 0);
|
|
7134
|
+
if (projects.length === 0) {
|
|
7135
|
+
throw new CliInputError(`no projects visible in organization ${orgId}`);
|
|
7136
|
+
}
|
|
7137
|
+
return selectFrom("Select a project", projects);
|
|
7138
|
+
}
|
|
7139
|
+
|
|
7140
|
+
// src/device-login.ts
|
|
7141
|
+
async function isProjectVisible(client2, orgId, projectId) {
|
|
7142
|
+
let cursor;
|
|
7143
|
+
do {
|
|
7144
|
+
const { data } = await sdk_gen_exports.listVisibleProjects({
|
|
7145
|
+
client: client2,
|
|
7146
|
+
path: { orgID: orgId },
|
|
7147
|
+
query: cursor === void 0 ? {} : { cursor }
|
|
7148
|
+
});
|
|
7149
|
+
if (data.data.some((project) => project.id === projectId)) return true;
|
|
7150
|
+
cursor = data.next_cursor ?? void 0;
|
|
7151
|
+
} while (cursor !== void 0);
|
|
7152
|
+
return false;
|
|
7153
|
+
}
|
|
7154
|
+
function interactiveReporter(title) {
|
|
7155
|
+
intro(title);
|
|
7156
|
+
const spin = spinner();
|
|
7157
|
+
return {
|
|
7158
|
+
showCode(userCode, approvalUrl) {
|
|
7159
|
+
note(`Code: ${userCode}
|
|
7160
|
+
${approvalUrl}`, "Confirm this code in your browser");
|
|
7161
|
+
},
|
|
7162
|
+
startWaiting() {
|
|
7163
|
+
spin.start("Waiting for approval in your browser");
|
|
7164
|
+
},
|
|
7165
|
+
stopWaiting(approved) {
|
|
7166
|
+
if (approved) {
|
|
7167
|
+
spin.stop("Approved");
|
|
7168
|
+
} else {
|
|
7169
|
+
spin.error("Approval failed");
|
|
7170
|
+
}
|
|
7171
|
+
},
|
|
7172
|
+
success(message) {
|
|
7173
|
+
log.success(message);
|
|
7174
|
+
},
|
|
7175
|
+
info(message) {
|
|
7176
|
+
log.info(message);
|
|
7177
|
+
},
|
|
7178
|
+
warn(message) {
|
|
7179
|
+
log.warn(message);
|
|
7180
|
+
},
|
|
7181
|
+
finish(message) {
|
|
7182
|
+
outro(message ?? "Done");
|
|
7183
|
+
}
|
|
7184
|
+
};
|
|
7185
|
+
}
|
|
7186
|
+
function plainReporter(title) {
|
|
7187
|
+
console.log(title);
|
|
7188
|
+
return {
|
|
7189
|
+
showCode(userCode, approvalUrl) {
|
|
7190
|
+
console.log(`Confirm this code in your browser: ${userCode}`);
|
|
7191
|
+
console.log(`Approval page: ${approvalUrl}`);
|
|
7192
|
+
},
|
|
7193
|
+
startWaiting() {
|
|
7194
|
+
console.log("Waiting for approval...");
|
|
7195
|
+
},
|
|
7196
|
+
stopWaiting(approved) {
|
|
7197
|
+
if (approved) console.log("Approved.");
|
|
7198
|
+
},
|
|
7199
|
+
success(message) {
|
|
7200
|
+
console.log(message);
|
|
7201
|
+
},
|
|
7202
|
+
info(message) {
|
|
7203
|
+
console.log(message);
|
|
7204
|
+
},
|
|
7205
|
+
warn(message) {
|
|
7206
|
+
console.error(`warning: ${message}`);
|
|
7207
|
+
},
|
|
7208
|
+
finish(message) {
|
|
7209
|
+
if (message !== void 0) console.log(message);
|
|
7210
|
+
}
|
|
7211
|
+
};
|
|
7212
|
+
}
|
|
7213
|
+
function createLoginReporter(title) {
|
|
7214
|
+
return canPromptInteractively() ? interactiveReporter(title) : plainReporter(title);
|
|
7215
|
+
}
|
|
7216
|
+
function loginTokenName(explicit, hostName) {
|
|
7217
|
+
const candidate = explicit ?? cliLoginTokenName(hostName);
|
|
7218
|
+
const result = zResourceName.safeParse(candidate);
|
|
7219
|
+
if (result.success) return result.data;
|
|
7220
|
+
if (explicit === void 0) return cliLoginTokenName();
|
|
7221
|
+
throw new CliInputError(`invalid token name:
|
|
7222
|
+
${z6.prettifyError(result.error)}`);
|
|
7223
|
+
}
|
|
7224
|
+
async function loginWithDevice(options) {
|
|
7225
|
+
const { report } = options;
|
|
7226
|
+
updateConfigFile({});
|
|
7227
|
+
const start = await startDeviceAuth({
|
|
7228
|
+
issuerUrl: options.issuerUrl,
|
|
7229
|
+
clientId: OMNARA_CLI_OAUTH_CLIENT_ID,
|
|
7230
|
+
tokenName: loginTokenName(options.tokenName, hostname())
|
|
7231
|
+
});
|
|
7232
|
+
report.showCode(start.userCode, start.verificationUriComplete);
|
|
7233
|
+
if (options.browser) {
|
|
7234
|
+
openInBrowser(start.verificationUriComplete, (message) => {
|
|
7235
|
+
report.warn(message);
|
|
7236
|
+
});
|
|
7237
|
+
}
|
|
7238
|
+
report.startWaiting();
|
|
7239
|
+
let token;
|
|
7240
|
+
try {
|
|
7241
|
+
token = await pollDeviceAuthToken({
|
|
7242
|
+
tokenEndpoint: start.tokenEndpoint,
|
|
7243
|
+
clientId: start.clientId,
|
|
7244
|
+
deviceCode: start.deviceCode,
|
|
7245
|
+
intervalSeconds: start.intervalSeconds
|
|
7246
|
+
});
|
|
7247
|
+
} catch (error) {
|
|
7248
|
+
report.stopWaiting(false);
|
|
7249
|
+
throw error;
|
|
7250
|
+
}
|
|
7251
|
+
report.stopWaiting(true);
|
|
7252
|
+
const saved = updateConfigFile({
|
|
7253
|
+
token,
|
|
7254
|
+
api_url: options.apiUrl,
|
|
7255
|
+
issuer_url: options.issuerUrl
|
|
7256
|
+
});
|
|
7257
|
+
const client2 = createOmnaraClient({ baseUrl: options.apiUrl, auth: bearerToken(token) });
|
|
7258
|
+
let orgId = saved.org_id;
|
|
7259
|
+
let projectId = saved.project_id;
|
|
7260
|
+
let loginMessage = "Logged in";
|
|
7261
|
+
let validationWarning;
|
|
7262
|
+
try {
|
|
7263
|
+
const { data: me } = await sdk_gen_exports.getCurrentUser({ client: client2 });
|
|
7264
|
+
loginMessage = `Logged in as ${me.user.email || me.user.display_name}`;
|
|
7265
|
+
if (orgId !== void 0 && !me.orgs.some((org) => org.id === orgId)) {
|
|
7266
|
+
updateConfigFile({ org_id: void 0, project_id: void 0 });
|
|
7267
|
+
orgId = void 0;
|
|
7268
|
+
projectId = void 0;
|
|
7269
|
+
report.warn(
|
|
7270
|
+
"Cleared the saved default organization and project: this account cannot access them."
|
|
7271
|
+
);
|
|
7272
|
+
} else if (orgId !== void 0 && projectId !== void 0 && !await isProjectVisible(client2, orgId, projectId)) {
|
|
7273
|
+
updateConfigFile({ project_id: void 0 });
|
|
7274
|
+
projectId = void 0;
|
|
7275
|
+
report.warn("Cleared the saved default project: this account cannot access it.");
|
|
7276
|
+
}
|
|
7277
|
+
} catch (error) {
|
|
7278
|
+
validationWarning = `could not verify the account or saved organization and project defaults: ${error instanceof Error ? error.message : String(error)}`;
|
|
7279
|
+
}
|
|
7280
|
+
report.success(loginMessage);
|
|
7281
|
+
report.info(`Token saved to ${configFilePath()}`);
|
|
7282
|
+
if (validationWarning !== void 0) report.warn(validationWarning);
|
|
7283
|
+
if (process.env.OMNARA_API_KEY !== void 0) {
|
|
7284
|
+
report.warn("OMNARA_API_KEY is set and takes precedence over the saved token");
|
|
7285
|
+
}
|
|
7286
|
+
return { token, orgId, projectId };
|
|
7287
|
+
}
|
|
7288
|
+
|
|
7289
|
+
// src/config.ts
|
|
7290
|
+
var DEFAULT_API_URL = "https://api.omnara.com/v1";
|
|
7291
|
+
var DEFAULT_ISSUER_URL = "https://app.omnara.com";
|
|
7116
7292
|
function resolveUrls(file, env) {
|
|
7117
7293
|
return {
|
|
7118
7294
|
apiUrl: env.OMNARA_API_URL ?? file.api_url ?? DEFAULT_API_URL,
|
|
@@ -7124,23 +7300,58 @@ function migrateLegacyBaseUrl(file) {
|
|
|
7124
7300
|
if (baseUrl === void 0) return void 0;
|
|
7125
7301
|
return rest;
|
|
7126
7302
|
}
|
|
7303
|
+
function createTokenResolver(options) {
|
|
7304
|
+
let token = options.savedToken;
|
|
7305
|
+
let pending;
|
|
7306
|
+
return () => {
|
|
7307
|
+
if (token !== void 0) return Promise.resolve(token);
|
|
7308
|
+
if (!options.canPrompt()) {
|
|
7309
|
+
return Promise.reject(
|
|
7310
|
+
new CliInputError("not logged in: run 'omnara login' or set OMNARA_API_KEY")
|
|
7311
|
+
);
|
|
7312
|
+
}
|
|
7313
|
+
pending ??= options.login().then((result) => {
|
|
7314
|
+
token = result;
|
|
7315
|
+
return result;
|
|
7316
|
+
});
|
|
7317
|
+
return pending;
|
|
7318
|
+
};
|
|
7319
|
+
}
|
|
7127
7320
|
function loadConfig() {
|
|
7128
7321
|
const loaded = readConfigFile();
|
|
7129
7322
|
const migrated = migrateLegacyBaseUrl(loaded);
|
|
7130
7323
|
const file = migrated === void 0 ? loaded : updateConfigFile({ ...migrated, base_url: void 0 });
|
|
7131
7324
|
const { apiUrl, issuerUrl } = resolveUrls(file, process.env);
|
|
7132
|
-
|
|
7325
|
+
let saved = { orgId: file.org_id, projectId: file.project_id };
|
|
7326
|
+
const resolveToken = createTokenResolver({
|
|
7327
|
+
savedToken: process.env.OMNARA_API_KEY ?? file.token,
|
|
7328
|
+
canPrompt: canPromptInteractively,
|
|
7329
|
+
login: async () => {
|
|
7330
|
+
const report = createLoginReporter(`Not logged in yet. Log in to ${issuerUrl}`);
|
|
7331
|
+
const login = await loginWithDevice({ apiUrl, issuerUrl, browser: true, report });
|
|
7332
|
+
saved = { orgId: login.orgId, projectId: login.projectId };
|
|
7333
|
+
report.finish("Continuing");
|
|
7334
|
+
return login.token;
|
|
7335
|
+
}
|
|
7336
|
+
});
|
|
7133
7337
|
const client2 = createOmnaraClient({
|
|
7134
7338
|
baseUrl: apiUrl,
|
|
7135
|
-
auth:
|
|
7339
|
+
auth: bearerToken(resolveToken),
|
|
7136
7340
|
headers: { "User-Agent": "omnara-cli" }
|
|
7137
7341
|
});
|
|
7138
7342
|
return {
|
|
7139
7343
|
client: client2,
|
|
7140
7344
|
apiUrl,
|
|
7141
7345
|
issuerUrl,
|
|
7142
|
-
defaultOrgId
|
|
7143
|
-
|
|
7346
|
+
get defaultOrgId() {
|
|
7347
|
+
return process.env.OMNARA_ORG_ID ?? saved.orgId;
|
|
7348
|
+
},
|
|
7349
|
+
get defaultProjectId() {
|
|
7350
|
+
return process.env.OMNARA_PROJECT_ID ?? saved.projectId;
|
|
7351
|
+
},
|
|
7352
|
+
ensureLoggedIn: async () => {
|
|
7353
|
+
await resolveToken();
|
|
7354
|
+
}
|
|
7144
7355
|
};
|
|
7145
7356
|
}
|
|
7146
7357
|
function describeValue(envName, fileValue, defaultValue) {
|
|
@@ -7185,6 +7396,7 @@ function registerConfigCommand(program2, cli) {
|
|
|
7185
7396
|
if (!canPromptInteractively()) {
|
|
7186
7397
|
throw new CliInputError("interactive selection needs a terminal");
|
|
7187
7398
|
}
|
|
7399
|
+
await cli.ensureLoggedIn();
|
|
7188
7400
|
const orgId = await promptOrgSelection(cli.client);
|
|
7189
7401
|
const projectId = await promptProjectSelection(cli.client, orgId);
|
|
7190
7402
|
updateConfigFile({ org_id: orgId, project_id: projectId });
|
|
@@ -7195,10 +7407,10 @@ function registerConfigCommand(program2, cli) {
|
|
|
7195
7407
|
|
|
7196
7408
|
// src/factory.ts
|
|
7197
7409
|
import { InvalidArgumentError } from "commander";
|
|
7198
|
-
import * as
|
|
7410
|
+
import * as z8 from "zod";
|
|
7199
7411
|
|
|
7200
7412
|
// src/flags.ts
|
|
7201
|
-
import * as
|
|
7413
|
+
import * as z7 from "zod";
|
|
7202
7414
|
function kebabCase(name) {
|
|
7203
7415
|
return name.replace(/([a-z0-9])([A-Z])/g, "$1-$2").replaceAll("_", "-").toLowerCase();
|
|
7204
7416
|
}
|
|
@@ -7315,21 +7527,21 @@ function finalizeFlag(draft) {
|
|
|
7315
7527
|
};
|
|
7316
7528
|
}
|
|
7317
7529
|
function deriveFlags(schema) {
|
|
7318
|
-
const jsonSchema =
|
|
7530
|
+
const jsonSchema = z7.toJSONSchema(schema, { io: "input" });
|
|
7319
7531
|
const drafts = /* @__PURE__ */ new Map();
|
|
7320
7532
|
collectDrafts(drafts, jsonSchema, [], false);
|
|
7321
7533
|
return [...drafts.values()].map(finalizeFlag);
|
|
7322
7534
|
}
|
|
7323
7535
|
|
|
7324
7536
|
// src/reporter.ts
|
|
7325
|
-
import { intro, log, note, outro, spinner } from "@clack/prompts";
|
|
7326
|
-
function
|
|
7327
|
-
|
|
7328
|
-
const spin =
|
|
7537
|
+
import { intro as intro2, log as log2, note as note2, outro as outro2, spinner as spinner2 } from "@clack/prompts";
|
|
7538
|
+
function interactiveReporter2(title) {
|
|
7539
|
+
intro2(title);
|
|
7540
|
+
const spin = spinner2();
|
|
7329
7541
|
let spinning = false;
|
|
7330
7542
|
return {
|
|
7331
7543
|
url(label, href) {
|
|
7332
|
-
|
|
7544
|
+
note2(href, label);
|
|
7333
7545
|
},
|
|
7334
7546
|
start(message) {
|
|
7335
7547
|
spin.start(message);
|
|
@@ -7346,17 +7558,17 @@ function interactiveReporter(title) {
|
|
|
7346
7558
|
spinning = false;
|
|
7347
7559
|
},
|
|
7348
7560
|
warn(message) {
|
|
7349
|
-
|
|
7561
|
+
log2.warn(message);
|
|
7350
7562
|
},
|
|
7351
7563
|
info(message) {
|
|
7352
|
-
|
|
7564
|
+
log2.info(message);
|
|
7353
7565
|
},
|
|
7354
7566
|
done() {
|
|
7355
|
-
|
|
7567
|
+
outro2("Done");
|
|
7356
7568
|
}
|
|
7357
7569
|
};
|
|
7358
7570
|
}
|
|
7359
|
-
function
|
|
7571
|
+
function plainReporter2() {
|
|
7360
7572
|
return {
|
|
7361
7573
|
url(label, href) {
|
|
7362
7574
|
console.log(`${label}: ${href}`);
|
|
@@ -7382,7 +7594,7 @@ function plainReporter() {
|
|
|
7382
7594
|
};
|
|
7383
7595
|
}
|
|
7384
7596
|
function createFlowReporter(title) {
|
|
7385
|
-
return canPromptInteractively() ?
|
|
7597
|
+
return canPromptInteractively() ? interactiveReporter2(title) : plainReporter2();
|
|
7386
7598
|
}
|
|
7387
7599
|
|
|
7388
7600
|
// src/factory.ts
|
|
@@ -7496,7 +7708,7 @@ function parseWithSchema(schema, value, label) {
|
|
|
7496
7708
|
const result = schema.safeParse(value);
|
|
7497
7709
|
if (!result.success) {
|
|
7498
7710
|
throw new CliInputError(`invalid ${label}:
|
|
7499
|
-
${
|
|
7711
|
+
${z8.prettifyError(result.error)}`);
|
|
7500
7712
|
}
|
|
7501
7713
|
return result.data;
|
|
7502
7714
|
}
|
|
@@ -7504,7 +7716,7 @@ async function callOperation(spec, input) {
|
|
|
7504
7716
|
const result = await spec.fn(input);
|
|
7505
7717
|
return result.data;
|
|
7506
7718
|
}
|
|
7507
|
-
var zBodyObject =
|
|
7719
|
+
var zBodyObject = z8.looseObject({});
|
|
7508
7720
|
function deepMerge(base, patch) {
|
|
7509
7721
|
const merged = { ...base };
|
|
7510
7722
|
for (const [key, value] of Object.entries(patch)) {
|
|
@@ -7582,6 +7794,7 @@ function registerOperation(parent, config2, spec) {
|
|
|
7582
7794
|
command.option("--json", "print the raw JSON response");
|
|
7583
7795
|
command.action(async (...args) => {
|
|
7584
7796
|
await runCliAction(async () => {
|
|
7797
|
+
await config2.ensureLoggedIn();
|
|
7585
7798
|
const options = command.opts();
|
|
7586
7799
|
const input = { client: config2.client };
|
|
7587
7800
|
if (spec.path) {
|
|
@@ -7621,6 +7834,7 @@ function registerFlow(parent, config2, spec) {
|
|
|
7621
7834
|
for (const flag of bodyFlags) registerFlag(command, flag);
|
|
7622
7835
|
command.action(async (...args) => {
|
|
7623
7836
|
await runCliAction(async () => {
|
|
7837
|
+
await config2.ensureLoggedIn();
|
|
7624
7838
|
const options = command.opts();
|
|
7625
7839
|
await spec.execute({
|
|
7626
7840
|
client: config2.client,
|
|
@@ -7641,175 +7855,17 @@ function registerGroup(program2, config2, group) {
|
|
|
7641
7855
|
}
|
|
7642
7856
|
|
|
7643
7857
|
// src/login.ts
|
|
7644
|
-
import { hostname } from "node:os";
|
|
7645
|
-
import { intro as intro2, log as log2, note as note2, outro as outro2, spinner as spinner2 } from "@clack/prompts";
|
|
7646
|
-
import * as z8 from "zod";
|
|
7647
|
-
|
|
7648
|
-
// src/browser.ts
|
|
7649
|
-
import { spawn } from "node:child_process";
|
|
7650
|
-
function browserCommand(url4) {
|
|
7651
|
-
if (process.platform === "darwin") {
|
|
7652
|
-
return { command: "open", args: [url4], windowsVerbatimArguments: false };
|
|
7653
|
-
}
|
|
7654
|
-
if (process.platform === "win32") {
|
|
7655
|
-
return {
|
|
7656
|
-
command: "cmd",
|
|
7657
|
-
args: ["/c", "start", '""', `"${url4}"`],
|
|
7658
|
-
windowsVerbatimArguments: true
|
|
7659
|
-
};
|
|
7660
|
-
}
|
|
7661
|
-
return { command: "xdg-open", args: [url4], windowsVerbatimArguments: false };
|
|
7662
|
-
}
|
|
7663
|
-
function openInBrowser(url4, onError) {
|
|
7664
|
-
const { command, args, windowsVerbatimArguments } = browserCommand(url4);
|
|
7665
|
-
const child = spawn(command, args, { stdio: "ignore", detached: true, windowsVerbatimArguments });
|
|
7666
|
-
child.once("error", () => {
|
|
7667
|
-
onError("could not open a browser; use the URL above");
|
|
7668
|
-
});
|
|
7669
|
-
child.unref();
|
|
7670
|
-
}
|
|
7671
|
-
|
|
7672
|
-
// src/login.ts
|
|
7673
|
-
async function isProjectVisible(client2, orgId, projectId) {
|
|
7674
|
-
let cursor;
|
|
7675
|
-
do {
|
|
7676
|
-
const { data } = await sdk_gen_exports.listVisibleProjects({
|
|
7677
|
-
client: client2,
|
|
7678
|
-
path: { orgID: orgId },
|
|
7679
|
-
query: cursor === void 0 ? {} : { cursor }
|
|
7680
|
-
});
|
|
7681
|
-
if (data.data.some((project) => project.id === projectId)) return true;
|
|
7682
|
-
cursor = data.next_cursor ?? void 0;
|
|
7683
|
-
} while (cursor !== void 0);
|
|
7684
|
-
return false;
|
|
7685
|
-
}
|
|
7686
|
-
function interactiveReporter2(issuerUrl) {
|
|
7687
|
-
intro2(`Log in to ${issuerUrl}`);
|
|
7688
|
-
const spin = spinner2();
|
|
7689
|
-
return {
|
|
7690
|
-
showCode(userCode, approvalUrl) {
|
|
7691
|
-
note2(`Code: ${userCode}
|
|
7692
|
-
${approvalUrl}`, "Confirm this code in your browser");
|
|
7693
|
-
},
|
|
7694
|
-
startWaiting() {
|
|
7695
|
-
spin.start("Waiting for approval in your browser");
|
|
7696
|
-
},
|
|
7697
|
-
stopWaiting(approved) {
|
|
7698
|
-
if (approved) {
|
|
7699
|
-
spin.stop("Approved");
|
|
7700
|
-
} else {
|
|
7701
|
-
spin.error("Approval failed");
|
|
7702
|
-
}
|
|
7703
|
-
},
|
|
7704
|
-
success(message) {
|
|
7705
|
-
log2.success(message);
|
|
7706
|
-
},
|
|
7707
|
-
info(message) {
|
|
7708
|
-
log2.info(message);
|
|
7709
|
-
},
|
|
7710
|
-
warn(message) {
|
|
7711
|
-
log2.warn(message);
|
|
7712
|
-
},
|
|
7713
|
-
finish(message) {
|
|
7714
|
-
outro2(message ?? "Done");
|
|
7715
|
-
}
|
|
7716
|
-
};
|
|
7717
|
-
}
|
|
7718
|
-
function plainReporter2() {
|
|
7719
|
-
return {
|
|
7720
|
-
showCode(userCode, approvalUrl) {
|
|
7721
|
-
console.log(`Confirm this code in your browser: ${userCode}`);
|
|
7722
|
-
console.log(`Approval page: ${approvalUrl}`);
|
|
7723
|
-
},
|
|
7724
|
-
startWaiting() {
|
|
7725
|
-
console.log("Waiting for approval...");
|
|
7726
|
-
},
|
|
7727
|
-
stopWaiting(approved) {
|
|
7728
|
-
if (approved) console.log("Approved.");
|
|
7729
|
-
},
|
|
7730
|
-
success(message) {
|
|
7731
|
-
console.log(message);
|
|
7732
|
-
},
|
|
7733
|
-
info(message) {
|
|
7734
|
-
console.log(message);
|
|
7735
|
-
},
|
|
7736
|
-
warn(message) {
|
|
7737
|
-
console.error(`warning: ${message}`);
|
|
7738
|
-
},
|
|
7739
|
-
finish(message) {
|
|
7740
|
-
if (message !== void 0) console.log(message);
|
|
7741
|
-
}
|
|
7742
|
-
};
|
|
7743
|
-
}
|
|
7744
|
-
function loginTokenName(explicit, hostName) {
|
|
7745
|
-
const candidate = explicit ?? cliLoginTokenName(hostName);
|
|
7746
|
-
const result = zResourceName.safeParse(candidate);
|
|
7747
|
-
if (result.success) return result.data;
|
|
7748
|
-
if (explicit === void 0) return cliLoginTokenName();
|
|
7749
|
-
throw new CliInputError(`invalid token name:
|
|
7750
|
-
${z8.prettifyError(result.error)}`);
|
|
7751
|
-
}
|
|
7752
7858
|
function registerLoginCommand(program2, cli) {
|
|
7753
7859
|
program2.command("login").description("Log in via the browser and save an API token").option("--no-browser", "print the approval URL instead of opening a browser").option("--token-name <name>", "name for the created API token").action(async (options) => {
|
|
7754
7860
|
await runCliAction(async () => {
|
|
7755
|
-
|
|
7756
|
-
const
|
|
7757
|
-
|
|
7861
|
+
const report = createLoginReporter(`Log in to ${cli.issuerUrl}`);
|
|
7862
|
+
const { orgId } = await loginWithDevice({
|
|
7863
|
+
apiUrl: cli.apiUrl,
|
|
7758
7864
|
issuerUrl: cli.issuerUrl,
|
|
7759
|
-
|
|
7760
|
-
tokenName:
|
|
7865
|
+
browser: options.browser,
|
|
7866
|
+
tokenName: options.tokenName,
|
|
7867
|
+
report
|
|
7761
7868
|
});
|
|
7762
|
-
report.showCode(start.userCode, start.verificationUriComplete);
|
|
7763
|
-
if (options.browser) {
|
|
7764
|
-
openInBrowser(start.verificationUriComplete, (message) => {
|
|
7765
|
-
report.warn(message);
|
|
7766
|
-
});
|
|
7767
|
-
}
|
|
7768
|
-
report.startWaiting();
|
|
7769
|
-
let token;
|
|
7770
|
-
try {
|
|
7771
|
-
token = await pollDeviceAuthToken({
|
|
7772
|
-
tokenEndpoint: start.tokenEndpoint,
|
|
7773
|
-
clientId: start.clientId,
|
|
7774
|
-
deviceCode: start.deviceCode,
|
|
7775
|
-
intervalSeconds: start.intervalSeconds
|
|
7776
|
-
});
|
|
7777
|
-
} catch (error) {
|
|
7778
|
-
report.stopWaiting(false);
|
|
7779
|
-
throw error;
|
|
7780
|
-
}
|
|
7781
|
-
report.stopWaiting(true);
|
|
7782
|
-
const saved = updateConfigFile({
|
|
7783
|
-
token,
|
|
7784
|
-
api_url: cli.apiUrl,
|
|
7785
|
-
issuer_url: cli.issuerUrl
|
|
7786
|
-
});
|
|
7787
|
-
const client2 = createOmnaraClient({ baseUrl: cli.apiUrl, auth: bearerToken(token) });
|
|
7788
|
-
let orgId = saved.org_id;
|
|
7789
|
-
let loginMessage = "Logged in";
|
|
7790
|
-
let validationWarning;
|
|
7791
|
-
try {
|
|
7792
|
-
const { data: me } = await sdk_gen_exports.getCurrentUser({ client: client2 });
|
|
7793
|
-
loginMessage = `Logged in as ${me.user.email || me.user.display_name}`;
|
|
7794
|
-
if (orgId !== void 0 && !me.orgs.some((org) => org.id === orgId)) {
|
|
7795
|
-
updateConfigFile({ org_id: void 0, project_id: void 0 });
|
|
7796
|
-
orgId = void 0;
|
|
7797
|
-
report.warn(
|
|
7798
|
-
"Cleared the saved default organization and project: this account cannot access them."
|
|
7799
|
-
);
|
|
7800
|
-
} else if (orgId !== void 0 && saved.project_id !== void 0 && !await isProjectVisible(client2, orgId, saved.project_id)) {
|
|
7801
|
-
updateConfigFile({ project_id: void 0 });
|
|
7802
|
-
report.warn("Cleared the saved default project: this account cannot access it.");
|
|
7803
|
-
}
|
|
7804
|
-
} catch (error) {
|
|
7805
|
-
validationWarning = `could not verify the account or saved organization and project defaults: ${error instanceof Error ? error.message : String(error)}`;
|
|
7806
|
-
}
|
|
7807
|
-
report.success(loginMessage);
|
|
7808
|
-
report.info(`Token saved to ${configFilePath()}`);
|
|
7809
|
-
if (validationWarning !== void 0) report.warn(validationWarning);
|
|
7810
|
-
if (process.env.OMNARA_API_KEY !== void 0) {
|
|
7811
|
-
report.warn("OMNARA_API_KEY is set and takes precedence over the saved token");
|
|
7812
|
-
}
|
|
7813
7869
|
if ((process.env.OMNARA_ORG_ID ?? orgId) === void 0) {
|
|
7814
7870
|
report.finish("Run 'omnara config select' to choose a default organization and project.");
|
|
7815
7871
|
} else {
|
package/package.json
CHANGED