nexgenr 1.0.0 → 1.0.2
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/README.md +28 -13
- package/dist/main.mjs +7 -174
- package/package.json +9 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# nexgenr
|
|
2
2
|
|
|
3
|
-
NexgenR CLI is a terminal AI coding agent wired to **
|
|
3
|
+
NexgenR CLI is a terminal AI coding agent wired to the **NexgenR red-team** surface.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -18,22 +18,33 @@ pnpm add -g nexgenr
|
|
|
18
18
|
|
|
19
19
|
## Configure
|
|
20
20
|
|
|
21
|
-
NexgenR
|
|
21
|
+
NexgenR signs in with an API key. There is no OAuth and no device flow:
|
|
22
22
|
|
|
23
23
|
```sh
|
|
24
24
|
export NEXGENR_API_KEY="<your key>"
|
|
25
|
-
# optional, defaults to https://
|
|
26
|
-
export NEXGENR_BASE_URL="https://
|
|
25
|
+
# optional, defaults to https://redteam.nexgen.systems/v1
|
|
26
|
+
export NEXGENR_BASE_URL="https://redteam.nexgen.systems/v1"
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
Validate the key and provision the model catalog:
|
|
30
|
-
|
|
31
29
|
```sh
|
|
32
30
|
nexgenr login # reads NEXGENR_API_KEY
|
|
33
31
|
nexgenr login --api-key <your key> # or pass it explicitly
|
|
34
32
|
```
|
|
35
33
|
|
|
36
|
-
|
|
34
|
+
The same key works on both surfaces; the header is what changes:
|
|
35
|
+
|
|
36
|
+
| Surface | Send the key as | Rejected |
|
|
37
|
+
|---|---|---|
|
|
38
|
+
| `/v1/…` inference and catalog | `Authorization: Bearer <key>` or `x-api-key: <key>` | `x-bf-vk` answers 401 here |
|
|
39
|
+
| `/mcp` gateway | `x-bf-vk: <key>` or `Authorization: Bearer <key>` | — |
|
|
40
|
+
|
|
41
|
+
The key must be provisioned for the `vllm` provider and the `nexgen-redteam` model.
|
|
42
|
+
Without that grant `GET /v1/models` answers 200 with an empty catalog and chat fails
|
|
43
|
+
with `400 modelo-desconocido`.
|
|
44
|
+
|
|
45
|
+
`nexgenr login` writes `~/.nexgenr/config.toml` with the `redteam` provider and its single
|
|
46
|
+
model `nexgen-redteam` (262 144 tokens of context), and `~/.nexgenr/mcp.json` with the
|
|
47
|
+
gateway. It does not call the catalog: the model list is static.
|
|
37
48
|
|
|
38
49
|
## Quick start
|
|
39
50
|
|
|
@@ -47,13 +58,17 @@ nexgenr # interactive terminal UI
|
|
|
47
58
|
|
|
48
59
|
| Capability | Endpoint |
|
|
49
60
|
|---|---|
|
|
50
|
-
| Chat
|
|
61
|
+
| Chat, streaming only | `POST /v1/chat/completions` |
|
|
51
62
|
| Model catalog | `GET /v1/models` |
|
|
52
|
-
|
|
|
53
|
-
|
|
|
54
|
-
|
|
63
|
+
| Health and published limits | `GET /health`, no credential |
|
|
64
|
+
| MCP gateway | `POST /mcp` — 24 tools (8 Brave_Search, 16 Crawl4AI) |
|
|
65
|
+
|
|
66
|
+
`POST /v1/completions` and `POST /v1/embeddings` are in the edge allowlist but the engine
|
|
67
|
+
answers 404: `POST /v1/chat/completions` is the only inference route.
|
|
55
68
|
|
|
56
|
-
|
|
69
|
+
Limits, as published by `GET /health`: 4 requests in flight per consumer with `429` and
|
|
70
|
+
`Retry-After: 10` beyond that, a 12 MiB request body, and 262 144 tokens of context. A
|
|
71
|
+
prefill can take minutes, so requests stream and wait up to 3 600 s for the first byte.
|
|
57
72
|
|
|
58
73
|
## Features
|
|
59
74
|
|
|
@@ -68,7 +83,7 @@ Authentication uses `Authorization: Bearer <key>` (and `x-api-key` on the Anthro
|
|
|
68
83
|
- Remote Control (requires a relay service).
|
|
69
84
|
- CDN-based auto-update; upgrade with `npm install -g nexgenr@latest`.
|
|
70
85
|
- The bundled browser UI; `nexgenr web` serves the API plus a minimal landing page.
|
|
71
|
-
-
|
|
86
|
+
- SSO: NexgenR signs in with an API key only.
|
|
72
87
|
|
|
73
88
|
## License
|
|
74
89
|
|
package/dist/main.mjs
CHANGED
|
@@ -62532,19 +62532,7 @@ var init_open_platform = __esmMin((() => {
|
|
|
62532
62532
|
init_identity();
|
|
62533
62533
|
init_managed_nexgenr();
|
|
62534
62534
|
init_model_alias_merge();
|
|
62535
|
-
OPEN_PLATFORMS = [
|
|
62536
|
-
id: "nexgen-cn",
|
|
62537
|
-
name: "Nexgen Platform (API key · platform.nexgenr.com)",
|
|
62538
|
-
baseUrl: "https://ia.nexgen.systems/v1",
|
|
62539
|
-
consoleUrl: "https://ia.nexgen.systems",
|
|
62540
|
-
allowedPrefixes: ["nexgenr-k"]
|
|
62541
|
-
}, {
|
|
62542
|
-
id: "nexgen-ai",
|
|
62543
|
-
name: "Nexgen Platform (API key · platform.nexgenr.ai)",
|
|
62544
|
-
baseUrl: "https://ia.nexgen.systems/v1",
|
|
62545
|
-
consoleUrl: "https://ia.nexgen.systems",
|
|
62546
|
-
allowedPrefixes: ["nexgenr-k"]
|
|
62547
|
-
}];
|
|
62535
|
+
OPEN_PLATFORMS = [];
|
|
62548
62536
|
OpenPlatformApiError = class extends Error {
|
|
62549
62537
|
status;
|
|
62550
62538
|
constructor(message, status) {
|
|
@@ -63043,6 +63031,8 @@ var init_custom_registry = __esmMin((() => {
|
|
|
63043
63031
|
RESERVED_PROVIDER_IDS = /* @__PURE__ */ new Set([
|
|
63044
63032
|
NEXGENR_PLATFORM_ID,
|
|
63045
63033
|
NEXGENR_PROVIDER_NAME,
|
|
63034
|
+
"nexgen-cn",
|
|
63035
|
+
"nexgen-ai",
|
|
63046
63036
|
...OPEN_PLATFORMS.map((platform) => platform.id)
|
|
63047
63037
|
]);
|
|
63048
63038
|
CustomRegistryApiError = class extends Error {
|
|
@@ -323009,9 +322999,6 @@ init_src$8();
|
|
|
323009
322999
|
init_mcp_provision();
|
|
323010
323000
|
init_provision();
|
|
323011
323001
|
const PROBE_TIMEOUT_MS$1 = 15e3;
|
|
323012
|
-
function isVirtualKey(key) {
|
|
323013
|
-
return key !== void 0 && key.startsWith("sk-bf-");
|
|
323014
|
-
}
|
|
323015
323002
|
function mcpHeaders(apiKey) {
|
|
323016
323003
|
if (apiKey === void 0 || apiKey === "") return {};
|
|
323017
323004
|
const headers = redteamAuthHeaders(apiKey);
|
|
@@ -323080,21 +323067,15 @@ async function probeModels(doFetch, baseUrl, apiKey, timeoutMs) {
|
|
|
323080
323067
|
detail: "no API key in config.toml — run `nexgenr login --api-key <token>`"
|
|
323081
323068
|
};
|
|
323082
323069
|
try {
|
|
323083
|
-
const headers = redteamAuthHeaders(apiKey);
|
|
323084
323070
|
const response = await timedFetch(doFetch, `${baseUrl}/models`, {
|
|
323085
323071
|
method: "GET",
|
|
323086
|
-
headers
|
|
323072
|
+
headers: { authorization: `Bearer ${apiKey}` }
|
|
323087
323073
|
}, timeoutMs);
|
|
323088
|
-
if (response.status === 401 || response.status === 403) return
|
|
323089
|
-
name: "models",
|
|
323090
|
-
kind: "probe",
|
|
323091
|
-
state: "BLOQUEADO",
|
|
323092
|
-
detail: `HTTP ${response.status} — a Bifrost virtual key cannot use /v1; the consumer token (64 hex) is a different credential`
|
|
323093
|
-
} : {
|
|
323074
|
+
if (response.status === 401 || response.status === 403) return {
|
|
323094
323075
|
name: "models",
|
|
323095
323076
|
kind: "probe",
|
|
323096
323077
|
state: "DENEGADO",
|
|
323097
|
-
detail: `HTTP ${response.status} — the
|
|
323078
|
+
detail: `HTTP ${response.status} — the credential was rejected on /v1`
|
|
323098
323079
|
};
|
|
323099
323080
|
if (!response.ok) return {
|
|
323100
323081
|
name: "models",
|
|
@@ -463658,51 +463639,7 @@ var init_model_selector = __esmMin((() => {
|
|
|
463658
463639
|
}
|
|
463659
463640
|
};
|
|
463660
463641
|
}));
|
|
463661
|
-
// src/tui/components/dialogs/platform-selector.ts
|
|
463662
|
-
function platformOptions() {
|
|
463663
|
-
return [NEXGENR_REDTEAM_OPTION, ...OPEN_PLATFORMS.map((platform) => ({
|
|
463664
|
-
value: platform.id,
|
|
463665
|
-
label: platform.name
|
|
463666
|
-
}))];
|
|
463667
|
-
}
|
|
463668
|
-
var NEXGENR_REDTEAM_OPTION, PlatformSelectorComponent;
|
|
463669
|
-
var init_platform_selector = __esmMin((() => {
|
|
463670
|
-
init_src$13();
|
|
463671
|
-
init_choice_picker();
|
|
463672
|
-
NEXGENR_REDTEAM_OPTION = {
|
|
463673
|
-
value: "nexgenr",
|
|
463674
|
-
label: "NexgenR (red-team)",
|
|
463675
|
-
description: "Sign in to redteam.nexgen.systems with an API key"
|
|
463676
|
-
};
|
|
463677
|
-
PlatformSelectorComponent = class extends ChoicePickerComponent {
|
|
463678
|
-
constructor(opts) {
|
|
463679
|
-
super({
|
|
463680
|
-
title: "Select a platform",
|
|
463681
|
-
options: [...platformOptions()],
|
|
463682
|
-
onSelect: opts.onSelect,
|
|
463683
|
-
onCancel: opts.onCancel
|
|
463684
|
-
});
|
|
463685
|
-
}
|
|
463686
|
-
};
|
|
463687
|
-
}));
|
|
463688
463642
|
// src/tui/commands/prompts.ts
|
|
463689
|
-
function promptPlatformSelection(host) {
|
|
463690
|
-
return new Promise((resolve) => {
|
|
463691
|
-
const selector = new PlatformSelectorComponent({
|
|
463692
|
-
onSelect: (platformId) => {
|
|
463693
|
-
host.restoreEditor();
|
|
463694
|
-
resolve(platformId);
|
|
463695
|
-
},
|
|
463696
|
-
onCancel: () => {
|
|
463697
|
-
host.restoreEditor();
|
|
463698
|
-
resolve(void 0);
|
|
463699
|
-
}
|
|
463700
|
-
});
|
|
463701
|
-
host.mountEditorReplacement(selector, void 0, () => {
|
|
463702
|
-
resolve(void 0);
|
|
463703
|
-
});
|
|
463704
|
-
});
|
|
463705
|
-
}
|
|
463706
463643
|
function promptLogoutProviderSelection(host, options, currentValue) {
|
|
463707
463644
|
return new Promise((resolve) => {
|
|
463708
463645
|
const picker = new ChoicePickerComponent({
|
|
@@ -463806,57 +463743,13 @@ function promptCatalogProviderSelection(host, catalog) {
|
|
|
463806
463743
|
host.mountEditorReplacement(picker);
|
|
463807
463744
|
});
|
|
463808
463745
|
}
|
|
463809
|
-
async function promptModelSelectionForOpenPlatform(host, models, platform) {
|
|
463810
|
-
const modelDict = {};
|
|
463811
|
-
for (const m of models) modelDict[`${platform.id}/${m.id}`] = {
|
|
463812
|
-
provider: platform.id,
|
|
463813
|
-
model: m.id,
|
|
463814
|
-
maxContextSize: m.contextLength,
|
|
463815
|
-
capabilities: capabilitiesForModel(m),
|
|
463816
|
-
displayName: m.displayName
|
|
463817
|
-
};
|
|
463818
|
-
const selection = await runModelSelector(host, modelDict);
|
|
463819
|
-
if (selection === void 0) return void 0;
|
|
463820
|
-
const model = models.find((m) => `${platform.id}/${m.id}` === selection.alias);
|
|
463821
|
-
return model ? {
|
|
463822
|
-
model,
|
|
463823
|
-
thinking: selection.thinking
|
|
463824
|
-
} : void 0;
|
|
463825
|
-
}
|
|
463826
|
-
function runModelSelector(host, modelDict) {
|
|
463827
|
-
return new Promise((resolve) => {
|
|
463828
|
-
const firstAlias = Object.keys(modelDict)[0] ?? "";
|
|
463829
|
-
const caps = modelDict[firstAlias]?.capabilities ?? [];
|
|
463830
|
-
const initialThinking = caps.includes("always_thinking") || caps.includes("thinking");
|
|
463831
|
-
const selector = new ModelSelectorComponent({
|
|
463832
|
-
models: modelDict,
|
|
463833
|
-
currentValue: firstAlias,
|
|
463834
|
-
currentThinkingEffort: initialThinking ? "on" : "off",
|
|
463835
|
-
searchable: true,
|
|
463836
|
-
onSelect: ({ alias, thinking }) => {
|
|
463837
|
-
host.restoreEditor();
|
|
463838
|
-
resolve({
|
|
463839
|
-
alias,
|
|
463840
|
-
thinking
|
|
463841
|
-
});
|
|
463842
|
-
},
|
|
463843
|
-
onCancel: () => {
|
|
463844
|
-
host.restoreEditor();
|
|
463845
|
-
resolve(void 0);
|
|
463846
|
-
}
|
|
463847
|
-
});
|
|
463848
|
-
host.mountEditorReplacement(selector);
|
|
463849
|
-
});
|
|
463850
|
-
}
|
|
463851
463746
|
var FEEDBACK_ATTACHMENT_OPTIONS;
|
|
463852
463747
|
var init_prompts = __esmMin((() => {
|
|
463853
463748
|
init_src$8();
|
|
463854
|
-
init_src$13();
|
|
463855
463749
|
init_api_key_input_dialog();
|
|
463856
463750
|
init_choice_picker();
|
|
463857
463751
|
init_feedback_input_dialog();
|
|
463858
463752
|
init_model_selector();
|
|
463859
|
-
init_platform_selector();
|
|
463860
463753
|
FEEDBACK_ATTACHMENT_OPTIONS = [
|
|
463861
463754
|
{
|
|
463862
463755
|
value: "none",
|
|
@@ -463880,15 +463773,7 @@ var init_prompts = __esmMin((() => {
|
|
|
463880
463773
|
async function handleLoginCommand(host) {
|
|
463881
463774
|
const releaseAuthBlock = host.beginAuthBlock();
|
|
463882
463775
|
try {
|
|
463883
|
-
|
|
463884
|
-
if (platformId === void 0) return;
|
|
463885
|
-
if (platformId === "nexgenr" || platformId === "nexgenr-global") {
|
|
463886
|
-
await handleRedteamLogin(host);
|
|
463887
|
-
return;
|
|
463888
|
-
}
|
|
463889
|
-
const platform = getOpenPlatformById(platformId);
|
|
463890
|
-
if (platform === void 0) return;
|
|
463891
|
-
await handleOpenPlatformLogin(host, platform);
|
|
463776
|
+
await handleRedteamLogin(host);
|
|
463892
463777
|
} finally {
|
|
463893
463778
|
releaseAuthBlock();
|
|
463894
463779
|
}
|
|
@@ -463947,57 +463832,6 @@ async function writeRedteamMcp(host, apiKey) {
|
|
|
463947
463832
|
return;
|
|
463948
463833
|
}
|
|
463949
463834
|
}
|
|
463950
|
-
async function handleOpenPlatformLogin(host, platform) {
|
|
463951
|
-
const consoleHost = platform.consoleUrl?.replace(/^https?:\/\//, "") ?? "";
|
|
463952
|
-
const apiKey = await promptApiKey(host, consoleHost.length > 0 ? `Nexgen Platform (${consoleHost})` : "Nexgen Platform", [`${"base_url".padEnd(12)}${platform.baseUrl}`, `${"saved to".padEnd(12)}~/.nexgenr/config.toml`]);
|
|
463953
|
-
if (apiKey === void 0) return;
|
|
463954
|
-
const controller = new AbortController();
|
|
463955
|
-
const cancelLogin = () => {
|
|
463956
|
-
controller.abort();
|
|
463957
|
-
};
|
|
463958
|
-
host.cancelInFlight = cancelLogin;
|
|
463959
|
-
let models;
|
|
463960
|
-
try {
|
|
463961
|
-
models = await fetchOpenPlatformModels(platform, apiKey, fetch, controller.signal);
|
|
463962
|
-
models = filterModelsByPrefix(models, platform);
|
|
463963
|
-
} catch (error) {
|
|
463964
|
-
if (controller.signal.aborted) return;
|
|
463965
|
-
const msg = formatErrorMessage$2(error);
|
|
463966
|
-
host.showError(`Failed to verify API key: ${msg}`);
|
|
463967
|
-
if (error instanceof OpenPlatformApiError && error.status === 401) host.showStatus("Hint: If your API key was obtained from NexgenR, please select \"NexgenR\" instead.");
|
|
463968
|
-
return;
|
|
463969
|
-
} finally {
|
|
463970
|
-
if (host.cancelInFlight === cancelLogin) host.cancelInFlight = void 0;
|
|
463971
|
-
}
|
|
463972
|
-
if (models.length === 0) {
|
|
463973
|
-
host.showError("No models available for this platform.");
|
|
463974
|
-
return;
|
|
463975
|
-
}
|
|
463976
|
-
const selection = await promptModelSelectionForOpenPlatform(host, models, platform);
|
|
463977
|
-
if (selection === void 0) return;
|
|
463978
|
-
if ((await host.harness.getConfig()).providers[platform.id] !== void 0) await host.harness.removeProvider(platform.id);
|
|
463979
|
-
const config = await host.harness.getConfig();
|
|
463980
|
-
applyOpenPlatformConfig(config, {
|
|
463981
|
-
platform,
|
|
463982
|
-
models,
|
|
463983
|
-
selectedModel: selection.model,
|
|
463984
|
-
thinking: selection.thinking !== "off",
|
|
463985
|
-
effort: selection.thinking !== "off" && selection.thinking !== "on" ? selection.thinking : void 0,
|
|
463986
|
-
credential: { apiKey }
|
|
463987
|
-
});
|
|
463988
|
-
await host.harness.setConfig({
|
|
463989
|
-
providers: config.providers,
|
|
463990
|
-
models: config.models,
|
|
463991
|
-
defaultModel: config.defaultModel,
|
|
463992
|
-
thinking: config.thinking
|
|
463993
|
-
});
|
|
463994
|
-
await host.authFlow.refreshConfigAfterLogin();
|
|
463995
|
-
host.track("login", {
|
|
463996
|
-
provider: platform.id,
|
|
463997
|
-
method: "api_key"
|
|
463998
|
-
});
|
|
463999
|
-
host.showStatus(`Setup complete: ${platform.name} · ${selection.model.id}`);
|
|
464000
|
-
}
|
|
464001
463835
|
async function handleLogoutCommand(host) {
|
|
464002
463836
|
const hasOAuthToken = (await host.harness.auth.status(DEFAULT_OAUTH_PROVIDER_NAME)).providers.some((p) => p.providerName === "managed:nexgenr" && p.hasToken);
|
|
464003
463837
|
const config = await host.harness.getConfig();
|
|
@@ -464041,7 +463875,6 @@ async function handleLogoutCommand(host) {
|
|
|
464041
463875
|
host.showStatus(`Logged out from ${label}.`);
|
|
464042
463876
|
}
|
|
464043
463877
|
var init_auth = __esmMin((() => {
|
|
464044
|
-
init_src$13();
|
|
464045
463878
|
init_src$8();
|
|
464046
463879
|
init_mcp_provision();
|
|
464047
463880
|
init_provision();
|
package/package.json
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nexgenr",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "NexgenR — terminal AI coding agent",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "NexgenR",
|
|
7
|
-
"homepage": "https://
|
|
7
|
+
"homepage": "https://git.nexgen.systems/IANexgen/NexgenR",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://git.nexgen.systems/IANexgen/NexgenR.git"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://git.nexgen.systems/IANexgen/NexgenR/issues"
|
|
14
|
+
},
|
|
8
15
|
"keywords": [
|
|
9
16
|
"nexgenr",
|
|
10
17
|
"cli",
|