omnara 1.0.5 → 1.0.7
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 +311 -247
- 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,238 @@ ${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, issuerUrl) {
|
|
7113
|
+
const { data } = await sdk_gen_exports.getCurrentUser({ client: client2 });
|
|
7114
|
+
if (data.orgs.length === 0) {
|
|
7115
|
+
throw new CliInputError(
|
|
7116
|
+
`this account has no organizations; create one at ${new URL("/onboarding", issuerUrl).toString()}`
|
|
7117
|
+
);
|
|
7118
|
+
}
|
|
7119
|
+
return selectFrom(
|
|
7120
|
+
"Select an organization",
|
|
7121
|
+
data.orgs.map((org) => ({ id: org.id, label: org.name }))
|
|
7122
|
+
);
|
|
7123
|
+
}
|
|
7124
|
+
async function promptProjectSelection(client2, orgId) {
|
|
7125
|
+
const projects = [];
|
|
7126
|
+
let cursor;
|
|
7127
|
+
do {
|
|
7128
|
+
const { data } = await sdk_gen_exports.listVisibleProjects({
|
|
7129
|
+
client: client2,
|
|
7130
|
+
path: { orgID: orgId },
|
|
7131
|
+
query: cursor === void 0 ? {} : { cursor }
|
|
7132
|
+
});
|
|
7133
|
+
projects.push(...data.data.map((project) => ({ id: project.id, label: project.name })));
|
|
7134
|
+
cursor = data.next_cursor ?? void 0;
|
|
7135
|
+
} while (cursor !== void 0);
|
|
7136
|
+
if (projects.length === 0) {
|
|
7137
|
+
throw new CliInputError(`no projects visible in organization ${orgId}`);
|
|
7138
|
+
}
|
|
7139
|
+
return selectFrom("Select a project", projects);
|
|
7140
|
+
}
|
|
7141
|
+
|
|
7142
|
+
// src/device-login.ts
|
|
7143
|
+
async function isProjectVisible(client2, orgId, projectId) {
|
|
7144
|
+
let cursor;
|
|
7145
|
+
do {
|
|
7146
|
+
const { data } = await sdk_gen_exports.listVisibleProjects({
|
|
7147
|
+
client: client2,
|
|
7148
|
+
path: { orgID: orgId },
|
|
7149
|
+
query: cursor === void 0 ? {} : { cursor }
|
|
7150
|
+
});
|
|
7151
|
+
if (data.data.some((project) => project.id === projectId)) return true;
|
|
7152
|
+
cursor = data.next_cursor ?? void 0;
|
|
7153
|
+
} while (cursor !== void 0);
|
|
7154
|
+
return false;
|
|
7155
|
+
}
|
|
7156
|
+
function interactiveReporter(title) {
|
|
7157
|
+
intro(title);
|
|
7158
|
+
const spin = spinner();
|
|
7159
|
+
return {
|
|
7160
|
+
showCode(userCode, approvalUrl) {
|
|
7161
|
+
note(`Code: ${userCode}
|
|
7162
|
+
${approvalUrl}`, "Confirm this code in your browser");
|
|
7163
|
+
},
|
|
7164
|
+
startWaiting() {
|
|
7165
|
+
spin.start("Waiting for approval in your browser");
|
|
7166
|
+
},
|
|
7167
|
+
stopWaiting(approved) {
|
|
7168
|
+
if (approved) {
|
|
7169
|
+
spin.stop("Approved");
|
|
7170
|
+
} else {
|
|
7171
|
+
spin.error("Approval failed");
|
|
7172
|
+
}
|
|
7173
|
+
},
|
|
7174
|
+
success(message) {
|
|
7175
|
+
log.success(message);
|
|
7176
|
+
},
|
|
7177
|
+
info(message) {
|
|
7178
|
+
log.info(message);
|
|
7179
|
+
},
|
|
7180
|
+
warn(message) {
|
|
7181
|
+
log.warn(message);
|
|
7182
|
+
},
|
|
7183
|
+
finish(message) {
|
|
7184
|
+
outro(message ?? "Done");
|
|
7185
|
+
}
|
|
7186
|
+
};
|
|
7187
|
+
}
|
|
7188
|
+
function plainReporter(title) {
|
|
7189
|
+
console.log(title);
|
|
7190
|
+
return {
|
|
7191
|
+
showCode(userCode, approvalUrl) {
|
|
7192
|
+
console.log(`Confirm this code in your browser: ${userCode}`);
|
|
7193
|
+
console.log(`Approval page: ${approvalUrl}`);
|
|
7194
|
+
},
|
|
7195
|
+
startWaiting() {
|
|
7196
|
+
console.log("Waiting for approval...");
|
|
7197
|
+
},
|
|
7198
|
+
stopWaiting(approved) {
|
|
7199
|
+
if (approved) console.log("Approved.");
|
|
7200
|
+
},
|
|
7201
|
+
success(message) {
|
|
7202
|
+
console.log(message);
|
|
7203
|
+
},
|
|
7204
|
+
info(message) {
|
|
7205
|
+
console.log(message);
|
|
7206
|
+
},
|
|
7207
|
+
warn(message) {
|
|
7208
|
+
console.error(`warning: ${message}`);
|
|
7209
|
+
},
|
|
7210
|
+
finish(message) {
|
|
7211
|
+
if (message !== void 0) console.log(message);
|
|
7212
|
+
}
|
|
7213
|
+
};
|
|
7214
|
+
}
|
|
7215
|
+
function createLoginReporter(title) {
|
|
7216
|
+
return canPromptInteractively() ? interactiveReporter(title) : plainReporter(title);
|
|
7217
|
+
}
|
|
7218
|
+
function loginTokenName(explicit, hostName) {
|
|
7219
|
+
const candidate = explicit ?? cliLoginTokenName(hostName);
|
|
7220
|
+
const result = zResourceName.safeParse(candidate);
|
|
7221
|
+
if (result.success) return result.data;
|
|
7222
|
+
if (explicit === void 0) return cliLoginTokenName();
|
|
7223
|
+
throw new CliInputError(`invalid token name:
|
|
7224
|
+
${z6.prettifyError(result.error)}`);
|
|
7225
|
+
}
|
|
7226
|
+
async function loginWithDevice(options) {
|
|
7227
|
+
const { report } = options;
|
|
7228
|
+
updateConfigFile({});
|
|
7229
|
+
const start = await startDeviceAuth({
|
|
7230
|
+
issuerUrl: options.issuerUrl,
|
|
7231
|
+
clientId: OMNARA_CLI_OAUTH_CLIENT_ID,
|
|
7232
|
+
tokenName: loginTokenName(options.tokenName, hostname())
|
|
7233
|
+
});
|
|
7234
|
+
report.showCode(start.userCode, start.verificationUriComplete);
|
|
7235
|
+
if (options.browser) {
|
|
7236
|
+
openInBrowser(start.verificationUriComplete, (message) => {
|
|
7237
|
+
report.warn(message);
|
|
7238
|
+
});
|
|
7239
|
+
}
|
|
7240
|
+
report.startWaiting();
|
|
7241
|
+
let token;
|
|
7242
|
+
try {
|
|
7243
|
+
token = await pollDeviceAuthToken({
|
|
7244
|
+
tokenEndpoint: start.tokenEndpoint,
|
|
7245
|
+
clientId: start.clientId,
|
|
7246
|
+
deviceCode: start.deviceCode,
|
|
7247
|
+
intervalSeconds: start.intervalSeconds
|
|
7248
|
+
});
|
|
7249
|
+
} catch (error) {
|
|
7250
|
+
report.stopWaiting(false);
|
|
7251
|
+
throw error;
|
|
7252
|
+
}
|
|
7253
|
+
report.stopWaiting(true);
|
|
7254
|
+
const saved = updateConfigFile({
|
|
7255
|
+
token,
|
|
7256
|
+
api_url: options.apiUrl,
|
|
7257
|
+
issuer_url: options.issuerUrl
|
|
7258
|
+
});
|
|
7259
|
+
const client2 = createOmnaraClient({ baseUrl: options.apiUrl, auth: bearerToken(token) });
|
|
7260
|
+
let orgId = saved.org_id;
|
|
7261
|
+
let projectId = saved.project_id;
|
|
7262
|
+
let hasOrganizations;
|
|
7263
|
+
let loginMessage = "Logged in";
|
|
7264
|
+
let validationWarning;
|
|
7265
|
+
try {
|
|
7266
|
+
const { data: me } = await sdk_gen_exports.getCurrentUser({ client: client2 });
|
|
7267
|
+
loginMessage = `Logged in as ${me.user.email || me.user.display_name}`;
|
|
7268
|
+
hasOrganizations = me.orgs.length > 0;
|
|
7269
|
+
if (orgId !== void 0 && !me.orgs.some((org) => org.id === orgId)) {
|
|
7270
|
+
updateConfigFile({ org_id: void 0, project_id: void 0 });
|
|
7271
|
+
orgId = void 0;
|
|
7272
|
+
projectId = void 0;
|
|
7273
|
+
report.warn(
|
|
7274
|
+
"Cleared the saved default organization and project: this account cannot access them."
|
|
7275
|
+
);
|
|
7276
|
+
} else if (orgId !== void 0 && projectId !== void 0 && !await isProjectVisible(client2, orgId, projectId)) {
|
|
7277
|
+
updateConfigFile({ project_id: void 0 });
|
|
7278
|
+
projectId = void 0;
|
|
7279
|
+
report.warn("Cleared the saved default project: this account cannot access it.");
|
|
7280
|
+
}
|
|
7281
|
+
} catch (error) {
|
|
7282
|
+
validationWarning = `could not verify the account or saved organization and project defaults: ${error instanceof Error ? error.message : String(error)}`;
|
|
7283
|
+
}
|
|
7284
|
+
report.success(loginMessage);
|
|
7285
|
+
report.info(`Token saved to ${configFilePath()}`);
|
|
7286
|
+
if (validationWarning !== void 0) report.warn(validationWarning);
|
|
7287
|
+
if (process.env.OMNARA_API_KEY !== void 0) {
|
|
7288
|
+
report.warn("OMNARA_API_KEY is set and takes precedence over the saved token");
|
|
7289
|
+
}
|
|
7290
|
+
return { token, orgId, projectId, hasOrganizations };
|
|
7291
|
+
}
|
|
7292
|
+
|
|
7293
|
+
// src/config.ts
|
|
7294
|
+
var DEFAULT_API_URL = "https://api.omnara.com/v1";
|
|
7295
|
+
var DEFAULT_ISSUER_URL = "https://app.omnara.com";
|
|
7116
7296
|
function resolveUrls(file, env) {
|
|
7117
7297
|
return {
|
|
7118
7298
|
apiUrl: env.OMNARA_API_URL ?? file.api_url ?? DEFAULT_API_URL,
|
|
@@ -7124,23 +7304,58 @@ function migrateLegacyBaseUrl(file) {
|
|
|
7124
7304
|
if (baseUrl === void 0) return void 0;
|
|
7125
7305
|
return rest;
|
|
7126
7306
|
}
|
|
7307
|
+
function createTokenResolver(options) {
|
|
7308
|
+
let token = options.savedToken;
|
|
7309
|
+
let pending;
|
|
7310
|
+
return () => {
|
|
7311
|
+
if (token !== void 0) return Promise.resolve(token);
|
|
7312
|
+
if (!options.canPrompt()) {
|
|
7313
|
+
return Promise.reject(
|
|
7314
|
+
new CliInputError("not logged in: run 'omnara login' or set OMNARA_API_KEY")
|
|
7315
|
+
);
|
|
7316
|
+
}
|
|
7317
|
+
pending ??= options.login().then((result) => {
|
|
7318
|
+
token = result;
|
|
7319
|
+
return result;
|
|
7320
|
+
});
|
|
7321
|
+
return pending;
|
|
7322
|
+
};
|
|
7323
|
+
}
|
|
7127
7324
|
function loadConfig() {
|
|
7128
7325
|
const loaded = readConfigFile();
|
|
7129
7326
|
const migrated = migrateLegacyBaseUrl(loaded);
|
|
7130
7327
|
const file = migrated === void 0 ? loaded : updateConfigFile({ ...migrated, base_url: void 0 });
|
|
7131
7328
|
const { apiUrl, issuerUrl } = resolveUrls(file, process.env);
|
|
7132
|
-
|
|
7329
|
+
let saved = { orgId: file.org_id, projectId: file.project_id };
|
|
7330
|
+
const resolveToken = createTokenResolver({
|
|
7331
|
+
savedToken: process.env.OMNARA_API_KEY ?? file.token,
|
|
7332
|
+
canPrompt: canPromptInteractively,
|
|
7333
|
+
login: async () => {
|
|
7334
|
+
const report = createLoginReporter(`Not logged in yet. Log in to ${issuerUrl}`);
|
|
7335
|
+
const login = await loginWithDevice({ apiUrl, issuerUrl, browser: true, report });
|
|
7336
|
+
saved = { orgId: login.orgId, projectId: login.projectId };
|
|
7337
|
+
report.finish("Continuing");
|
|
7338
|
+
return login.token;
|
|
7339
|
+
}
|
|
7340
|
+
});
|
|
7133
7341
|
const client2 = createOmnaraClient({
|
|
7134
7342
|
baseUrl: apiUrl,
|
|
7135
|
-
auth:
|
|
7343
|
+
auth: bearerToken(resolveToken),
|
|
7136
7344
|
headers: { "User-Agent": "omnara-cli" }
|
|
7137
7345
|
});
|
|
7138
7346
|
return {
|
|
7139
7347
|
client: client2,
|
|
7140
7348
|
apiUrl,
|
|
7141
7349
|
issuerUrl,
|
|
7142
|
-
defaultOrgId
|
|
7143
|
-
|
|
7350
|
+
get defaultOrgId() {
|
|
7351
|
+
return process.env.OMNARA_ORG_ID ?? saved.orgId;
|
|
7352
|
+
},
|
|
7353
|
+
get defaultProjectId() {
|
|
7354
|
+
return process.env.OMNARA_PROJECT_ID ?? saved.projectId;
|
|
7355
|
+
},
|
|
7356
|
+
ensureLoggedIn: async () => {
|
|
7357
|
+
await resolveToken();
|
|
7358
|
+
}
|
|
7144
7359
|
};
|
|
7145
7360
|
}
|
|
7146
7361
|
function describeValue(envName, fileValue, defaultValue) {
|
|
@@ -7185,7 +7400,8 @@ function registerConfigCommand(program2, cli) {
|
|
|
7185
7400
|
if (!canPromptInteractively()) {
|
|
7186
7401
|
throw new CliInputError("interactive selection needs a terminal");
|
|
7187
7402
|
}
|
|
7188
|
-
|
|
7403
|
+
await cli.ensureLoggedIn();
|
|
7404
|
+
const orgId = await promptOrgSelection(cli.client, cli.issuerUrl);
|
|
7189
7405
|
const projectId = await promptProjectSelection(cli.client, orgId);
|
|
7190
7406
|
updateConfigFile({ org_id: orgId, project_id: projectId });
|
|
7191
7407
|
printConfig();
|
|
@@ -7195,10 +7411,10 @@ function registerConfigCommand(program2, cli) {
|
|
|
7195
7411
|
|
|
7196
7412
|
// src/factory.ts
|
|
7197
7413
|
import { InvalidArgumentError } from "commander";
|
|
7198
|
-
import * as
|
|
7414
|
+
import * as z8 from "zod";
|
|
7199
7415
|
|
|
7200
7416
|
// src/flags.ts
|
|
7201
|
-
import * as
|
|
7417
|
+
import * as z7 from "zod";
|
|
7202
7418
|
function kebabCase(name) {
|
|
7203
7419
|
return name.replace(/([a-z0-9])([A-Z])/g, "$1-$2").replaceAll("_", "-").toLowerCase();
|
|
7204
7420
|
}
|
|
@@ -7315,21 +7531,21 @@ function finalizeFlag(draft) {
|
|
|
7315
7531
|
};
|
|
7316
7532
|
}
|
|
7317
7533
|
function deriveFlags(schema) {
|
|
7318
|
-
const jsonSchema =
|
|
7534
|
+
const jsonSchema = z7.toJSONSchema(schema, { io: "input" });
|
|
7319
7535
|
const drafts = /* @__PURE__ */ new Map();
|
|
7320
7536
|
collectDrafts(drafts, jsonSchema, [], false);
|
|
7321
7537
|
return [...drafts.values()].map(finalizeFlag);
|
|
7322
7538
|
}
|
|
7323
7539
|
|
|
7324
7540
|
// src/reporter.ts
|
|
7325
|
-
import { intro, log, note, outro, spinner } from "@clack/prompts";
|
|
7326
|
-
function
|
|
7327
|
-
|
|
7328
|
-
const spin =
|
|
7541
|
+
import { intro as intro2, log as log2, note as note2, outro as outro2, spinner as spinner2 } from "@clack/prompts";
|
|
7542
|
+
function interactiveReporter2(title) {
|
|
7543
|
+
intro2(title);
|
|
7544
|
+
const spin = spinner2();
|
|
7329
7545
|
let spinning = false;
|
|
7330
7546
|
return {
|
|
7331
7547
|
url(label, href) {
|
|
7332
|
-
|
|
7548
|
+
note2(href, label);
|
|
7333
7549
|
},
|
|
7334
7550
|
start(message) {
|
|
7335
7551
|
spin.start(message);
|
|
@@ -7346,17 +7562,17 @@ function interactiveReporter(title) {
|
|
|
7346
7562
|
spinning = false;
|
|
7347
7563
|
},
|
|
7348
7564
|
warn(message) {
|
|
7349
|
-
|
|
7565
|
+
log2.warn(message);
|
|
7350
7566
|
},
|
|
7351
7567
|
info(message) {
|
|
7352
|
-
|
|
7568
|
+
log2.info(message);
|
|
7353
7569
|
},
|
|
7354
7570
|
done() {
|
|
7355
|
-
|
|
7571
|
+
outro2("Done");
|
|
7356
7572
|
}
|
|
7357
7573
|
};
|
|
7358
7574
|
}
|
|
7359
|
-
function
|
|
7575
|
+
function plainReporter2() {
|
|
7360
7576
|
return {
|
|
7361
7577
|
url(label, href) {
|
|
7362
7578
|
console.log(`${label}: ${href}`);
|
|
@@ -7382,7 +7598,7 @@ function plainReporter() {
|
|
|
7382
7598
|
};
|
|
7383
7599
|
}
|
|
7384
7600
|
function createFlowReporter(title) {
|
|
7385
|
-
return canPromptInteractively() ?
|
|
7601
|
+
return canPromptInteractively() ? interactiveReporter2(title) : plainReporter2();
|
|
7386
7602
|
}
|
|
7387
7603
|
|
|
7388
7604
|
// src/factory.ts
|
|
@@ -7411,7 +7627,7 @@ var CONFIG_PARAMS = [
|
|
|
7411
7627
|
configKey: "org_id",
|
|
7412
7628
|
describe: "pass --org or set OMNARA_ORG_ID",
|
|
7413
7629
|
resolve: (config2) => config2.defaultOrgId,
|
|
7414
|
-
prompt: (
|
|
7630
|
+
prompt: (config2) => promptOrgSelection(config2.client, config2.issuerUrl)
|
|
7415
7631
|
},
|
|
7416
7632
|
{
|
|
7417
7633
|
key: "projectID",
|
|
@@ -7420,12 +7636,12 @@ var CONFIG_PARAMS = [
|
|
|
7420
7636
|
configKey: "project_id",
|
|
7421
7637
|
describe: "pass --project or set OMNARA_PROJECT_ID",
|
|
7422
7638
|
resolve: (config2, path) => path.orgID === void 0 || path.orgID === config2.defaultOrgId ? config2.defaultProjectId : void 0,
|
|
7423
|
-
prompt: (
|
|
7639
|
+
prompt: (config2, path) => {
|
|
7424
7640
|
const orgId = path.orgID;
|
|
7425
7641
|
if (typeof orgId !== "string") {
|
|
7426
7642
|
throw new CliInputError("cannot select a project before an organization is set");
|
|
7427
7643
|
}
|
|
7428
|
-
return promptProjectSelection(
|
|
7644
|
+
return promptProjectSelection(config2.client, orgId);
|
|
7429
7645
|
}
|
|
7430
7646
|
}
|
|
7431
7647
|
];
|
|
@@ -7496,7 +7712,7 @@ function parseWithSchema(schema, value, label) {
|
|
|
7496
7712
|
const result = schema.safeParse(value);
|
|
7497
7713
|
if (!result.success) {
|
|
7498
7714
|
throw new CliInputError(`invalid ${label}:
|
|
7499
|
-
${
|
|
7715
|
+
${z8.prettifyError(result.error)}`);
|
|
7500
7716
|
}
|
|
7501
7717
|
return result.data;
|
|
7502
7718
|
}
|
|
@@ -7504,7 +7720,7 @@ async function callOperation(spec, input) {
|
|
|
7504
7720
|
const result = await spec.fn(input);
|
|
7505
7721
|
return result.data;
|
|
7506
7722
|
}
|
|
7507
|
-
var zBodyObject =
|
|
7723
|
+
var zBodyObject = z8.looseObject({});
|
|
7508
7724
|
function deepMerge(base, patch) {
|
|
7509
7725
|
const merged = { ...base };
|
|
7510
7726
|
for (const [key, value] of Object.entries(patch)) {
|
|
@@ -7555,7 +7771,7 @@ async function resolvePathValues(plan, args, options, config2) {
|
|
|
7555
7771
|
usedExplicitOverride = usedExplicitOverride || explicit !== void 0;
|
|
7556
7772
|
let value = explicit ?? param.resolve(config2, path);
|
|
7557
7773
|
if (value === void 0 && canPromptInteractively()) {
|
|
7558
|
-
value = await param.prompt(config2
|
|
7774
|
+
value = await param.prompt(config2, path);
|
|
7559
7775
|
if (!usedExplicitOverride) saveConfigDefault(param.configKey, value);
|
|
7560
7776
|
}
|
|
7561
7777
|
if (value === void 0) {
|
|
@@ -7582,6 +7798,7 @@ function registerOperation(parent, config2, spec) {
|
|
|
7582
7798
|
command.option("--json", "print the raw JSON response");
|
|
7583
7799
|
command.action(async (...args) => {
|
|
7584
7800
|
await runCliAction(async () => {
|
|
7801
|
+
await config2.ensureLoggedIn();
|
|
7585
7802
|
const options = command.opts();
|
|
7586
7803
|
const input = { client: config2.client };
|
|
7587
7804
|
if (spec.path) {
|
|
@@ -7621,6 +7838,7 @@ function registerFlow(parent, config2, spec) {
|
|
|
7621
7838
|
for (const flag of bodyFlags) registerFlag(command, flag);
|
|
7622
7839
|
command.action(async (...args) => {
|
|
7623
7840
|
await runCliAction(async () => {
|
|
7841
|
+
await config2.ensureLoggedIn();
|
|
7624
7842
|
const options = command.opts();
|
|
7625
7843
|
await spec.execute({
|
|
7626
7844
|
client: config2.client,
|
|
@@ -7641,176 +7859,22 @@ function registerGroup(program2, config2, group) {
|
|
|
7641
7859
|
}
|
|
7642
7860
|
|
|
7643
7861
|
// 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
7862
|
function registerLoginCommand(program2, cli) {
|
|
7753
7863
|
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
7864
|
await runCliAction(async () => {
|
|
7755
|
-
|
|
7756
|
-
const
|
|
7757
|
-
|
|
7865
|
+
const report = createLoginReporter(`Log in to ${cli.issuerUrl}`);
|
|
7866
|
+
const { orgId, hasOrganizations } = await loginWithDevice({
|
|
7867
|
+
apiUrl: cli.apiUrl,
|
|
7758
7868
|
issuerUrl: cli.issuerUrl,
|
|
7759
|
-
|
|
7760
|
-
tokenName:
|
|
7869
|
+
browser: options.browser,
|
|
7870
|
+
tokenName: options.tokenName,
|
|
7871
|
+
report
|
|
7761
7872
|
});
|
|
7762
|
-
|
|
7763
|
-
|
|
7764
|
-
|
|
7765
|
-
|
|
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
|
-
if ((process.env.OMNARA_ORG_ID ?? orgId) === void 0) {
|
|
7873
|
+
if (hasOrganizations === false) {
|
|
7874
|
+
report.finish(
|
|
7875
|
+
`This account has no organization yet. Create one at ${new URL("/onboarding", cli.issuerUrl).toString()}, then run 'omnara config select'.`
|
|
7876
|
+
);
|
|
7877
|
+
} else if ((process.env.OMNARA_ORG_ID ?? orgId) === void 0) {
|
|
7814
7878
|
report.finish("Run 'omnara config select' to choose a default organization and project.");
|
|
7815
7879
|
} else {
|
|
7816
7880
|
report.finish();
|
package/package.json
CHANGED