@akon-labs/nexus-cli 0.1.5 → 0.1.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/CHANGELOG.md +29 -7
- package/README.md +2 -3
- package/dist/cli/require-login.d.ts.map +1 -1
- package/dist/cli/require-login.js +1 -1
- package/dist/cli/require-login.js.map +1 -1
- package/dist/cli.js +155 -213
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -1
- package/dist/config.js.map +1 -1
- package/dist/core/auth-guidance.d.ts.map +1 -1
- package/dist/core/auth-guidance.js +3 -2
- package/dist/core/auth-guidance.js.map +1 -1
- package/dist/core/auto-model.d.ts +9 -0
- package/dist/core/auto-model.d.ts.map +1 -0
- package/dist/core/auto-model.js +11 -0
- package/dist/core/auto-model.js.map +1 -0
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +4 -8
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +2 -1
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/models-dev-catalog.d.ts.map +1 -1
- package/dist/core/models-dev-catalog.js +11 -7
- package/dist/core/models-dev-catalog.js.map +1 -1
- package/dist/core/sdk.d.ts +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +1 -1
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +1 -1
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/tools/websearch.d.ts.map +1 -1
- package/dist/core/tools/websearch.js +52 -37
- package/dist/core/tools/websearch.js.map +1 -1
- package/dist/extensions/gitnexus/device-auth.d.ts.map +1 -1
- package/dist/extensions/gitnexus/device-auth.js +2 -1
- package/dist/extensions/gitnexus/device-auth.js.map +1 -1
- package/dist/extensions/gitnexus/gateway.d.ts +0 -2
- package/dist/extensions/gitnexus/gateway.d.ts.map +1 -1
- package/dist/extensions/gitnexus/gateway.js +10 -22
- package/dist/extensions/gitnexus/gateway.js.map +1 -1
- package/dist/extensions/gitnexus/index.d.ts.map +1 -1
- package/dist/extensions/gitnexus/index.js +10 -4
- package/dist/extensions/gitnexus/index.js.map +1 -1
- package/dist/extensions/web-access.d.ts +1 -6
- package/dist/extensions/web-access.d.ts.map +1 -1
- package/dist/extensions/web-access.js +8 -21
- package/dist/extensions/web-access.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +159 -213
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +2 -2
- package/dist/migrations.js.map +1 -1
- package/dist/modes/interactive/components/command-palette.d.ts.map +1 -1
- package/dist/modes/interactive/components/command-palette.js +2 -2
- package/dist/modes/interactive/components/command-palette.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +18 -7
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +0 -5
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +22 -128
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/rpc-entry.js +155 -213
- package/dist/vendor/ai.js +12 -12
- package/docs/compaction.md +1 -1
- package/docs/rpc.md +1 -1
- package/docs/settings.md +1 -1
- package/docs/usage.md +0 -2
- package/examples/extensions/border-status-editor.ts +1 -6
- package/examples/extensions/custom-compaction.ts +1 -1
- package/examples/extensions/custom-footer.ts +1 -1
- package/examples/extensions/custom-provider-anthropic/index.ts +3 -3
- package/examples/extensions/custom-provider-gitlab-duo/index.ts +1 -1
- package/examples/extensions/gondolin/index.ts +1 -1
- package/examples/extensions/handoff.ts +2 -2
- package/examples/extensions/hello.ts +1 -1
- package/examples/extensions/plan-mode/index.ts +1 -1
- package/examples/extensions/preset.ts +1 -1
- package/examples/extensions/qna.ts +1 -1
- package/examples/extensions/sandbox/index.ts +1 -1
- package/examples/extensions/subagent/index.ts +3 -3
- package/examples/extensions/summarize.ts +1 -1
- package/examples/extensions/tic-tac-toe.ts +1 -1
- package/examples/extensions/todo.ts +1 -1
- package/examples/extensions/tool-override.ts +1 -1
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,27 +1,49 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [Unreleased]
|
|
4
|
+
|
|
5
|
+
## [0.1.7] - 2026-08-22
|
|
6
|
+
|
|
7
|
+
### Removed
|
|
8
|
+
|
|
9
|
+
- Removed the built-in `/hotkeys` command; keyboard shortcuts remain documented in `docs/keybindings.md`.
|
|
10
|
+
|
|
11
|
+
## [0.1.6] - 2026-08-22
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- Added `/auto` as a direct way to switch back to the hosted Nexus default model.
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
- Pinned `Auto (default)` to the top of model selection and autocomplete, including when scoped experiment models are active.
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- Reconciled the packaging fixes already shipped in `0.1.4` and `0.1.5` back into the repository so future releases cannot regress them.
|
|
24
|
+
|
|
3
25
|
## [0.1.5] - 2026-08-22
|
|
4
26
|
|
|
5
27
|
### Fixed
|
|
6
28
|
|
|
7
|
-
- Fixed startup failing with `OAuth auth derivation failed ... Cannot find module` for users with OAuth credentials
|
|
8
|
-
-
|
|
29
|
+
- Fixed startup failing with `OAuth auth derivation failed ... Cannot find module` for users with OAuth credentials by registering bundled OAuth flow and AWS Bedrock implementations statically.
|
|
30
|
+
- Extended the publish smoke test to seed an OAuth credential and catch missing bundled modules.
|
|
9
31
|
|
|
10
32
|
## [0.1.4] - 2026-08-21
|
|
11
33
|
|
|
12
34
|
### Fixed
|
|
13
35
|
|
|
14
|
-
- Fixed fresh npm installs crashing
|
|
15
|
-
-
|
|
36
|
+
- Fixed fresh npm installs crashing while loading extensions by serving bundled module instances directly instead of resolving internal packages from disk.
|
|
37
|
+
- Bundled the default web access extension instead of installing it dynamically on first launch.
|
|
16
38
|
|
|
17
39
|
### Added
|
|
18
40
|
|
|
19
|
-
-
|
|
20
|
-
-
|
|
41
|
+
- Added public SDK subpath exports for `@akon-labs/nexus-cli/agent-core`, `@akon-labs/nexus-cli/tui`, and `@akon-labs/nexus-cli/ai`.
|
|
42
|
+
- Added a publish-time smoke test that installs and boots the packed tarball.
|
|
21
43
|
|
|
22
44
|
### Changed
|
|
23
45
|
|
|
24
|
-
-
|
|
46
|
+
- Disabled the web access extension's operator slash commands by default; users can explicitly enable them in `web-search.json`.
|
|
25
47
|
|
|
26
48
|
## [0.1.3] - 2026-08-18
|
|
27
49
|
|
package/README.md
CHANGED
|
@@ -117,7 +117,7 @@ See [docs/providers.md](docs/providers.md) for other provider setup instructions
|
|
|
117
117
|
|
|
118
118
|
The interface from top to bottom:
|
|
119
119
|
|
|
120
|
-
- **Startup header** - Shows shortcuts
|
|
120
|
+
- **Startup header** - Shows common shortcuts, loaded AGENTS.md files, prompt templates, skills, and extensions
|
|
121
121
|
- **Messages** - Your messages, assistant responses, tool calls and results, notifications, errors, and extension UI
|
|
122
122
|
- **Editor** - Where you type; border color indicates thinking level
|
|
123
123
|
- **Footer** - Working directory, session name, total token/cache usage (`↑` input, `↓` output, `R` cache read, `W` cache write, `CH` latest cache hit rate), cost, context usage, current model. Totals include assistant responses, usage reported by tools, and summary generation.
|
|
@@ -165,12 +165,11 @@ Type `/` in the editor to trigger commands. [Extensions](#extensions) can regist
|
|
|
165
165
|
| `/import <file>` | Import and resume a session from a JSONL file |
|
|
166
166
|
| `/share` | Upload as private GitHub gist with shareable HTML link |
|
|
167
167
|
| `/reload` | Reload keybindings, extensions, skills, prompts, themes, and context files |
|
|
168
|
-
| `/hotkeys` | Show all keyboard shortcuts |
|
|
169
168
|
| `/quit` | Quit nexus |
|
|
170
169
|
|
|
171
170
|
### Keyboard Shortcuts
|
|
172
171
|
|
|
173
|
-
|
|
172
|
+
Customize shortcuts via `~/.nexus/agent/keybindings.json`. See [docs/keybindings.md](docs/keybindings.md) for the full list.
|
|
174
173
|
|
|
175
174
|
**Commonly used:**
|
|
176
175
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"require-login.d.ts","sourceRoot":"","sources":["../../src/cli/require-login.ts"],"names":[],"mappings":"AA2BA,wBAAgB,mBAAmB,IAAI,OAAO,CAG7C;AAED,MAAM,MAAM,eAAe,GACxB;IAAE,MAAM,EAAE,WAAW,CAAA;CAAE,GACvB;IAAE,MAAM,EAAE,kBAAkB,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/C;IAAE,MAAM,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7C,gFAAgF;AAChF,wBAAsB,kBAAkB,CAAC,MAAM,GAAE,WAAyC,GAAG,OAAO,CAAC,eAAe,CAAC,CAepH;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED,MAAM,WAAW,WAAW;IAC3B,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,oDAAoD;IACpD,KAAK,CAAC,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,mDAAmD;IACnD,IAAI,CAAC,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAMD;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,EAAE,GAAE,WAAuB,GAAG,OAAO,CAAC,OAAO,CAAC,CAmChF;AAED,0EAA0E;AAC1E,wBAAgB,0BAA0B,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAUlE","sourcesContent":["import { APP_NAME, readAppEnv } from \"../config.ts\";\nimport { GitNexusClient, GitNexusClientError } from \"../extensions/gitnexus/client.ts\";\nimport {\n\tDEFAULT_HUB_URL,\n\tgitNexusConfigPath,\n\tresolveGitNexusConfig,\n\tsaveGitNexusConfig,\n} from \"../extensions/gitnexus/config.ts\";\nimport {\n\tdefaultDeviceName,\n\tdeviceFingerprint,\n\tpollDeviceAuth,\n\tstartDeviceAuth,\n} from \"../extensions/gitnexus/device-auth.ts\";\nimport { openBrowser } from \"../utils/open-browser.ts\";\n\n/**\n * Sign-in gate.\n *\n * Nexus is a GitNexus client, so it requires an account. Startup stops here\n * until the hub accepts its credential. Model and session initialization happen\n * only after this check, so a stale token cannot fall through to a local provider.\n */\n\n/** Escape hatch for CI and automated tests, which never have a credential. */\nconst SKIP_ENV_SUFFIX = \"SKIP_LOGIN\";\n\nexport function isLoginGateDisabled(): boolean {\n\tconst value = readAppEnv(SKIP_ENV_SUFFIX);\n\treturn value === \"1\" || value?.toLowerCase() === \"true\";\n}\n\nexport type LoginGateStatus =\n\t| { status: \"signed_in\" }\n\t| { status: \"sign_in_required\"; reason?: string }\n\t| { status: \"unavailable\"; reason: string };\n\n/** Validate configured GitNexus auth against the hub before runtime startup. */\nexport async function getLoginGateStatus(signal: AbortSignal = AbortSignal.timeout(15_000)): Promise<LoginGateStatus> {\n\tif (isLoginGateDisabled()) return { status: \"signed_in\" };\n\tconst config = resolveGitNexusConfig();\n\tif (!config) return { status: \"sign_in_required\" };\n\n\ttry {\n\t\tawait new GitNexusClient(config).callTool(\"list_repos\", {}, signal);\n\t\treturn { status: \"signed_in\" };\n\t} catch (error) {\n\t\tconst reason = error instanceof Error ? error.message : String(error);\n\t\tif (error instanceof GitNexusClientError && error.kind === \"auth\") {\n\t\t\treturn { status: \"sign_in_required\", reason };\n\t\t}\n\t\treturn { status: \"unavailable\", reason };\n\t}\n}\n\nexport function loginUnavailableMessage(reason: string): string {\n\treturn `${APP_NAME}: GitNexus unavailable. Startup stopped.\\n\\n${reason}`;\n}\n\nexport interface LoginGateIo {\n\twrite(text: string): void;\n\t/** Injected in tests so no real waiting happens. */\n\tsleep?(ms: number): Promise<void>;\n\t/** Injected in tests so no browser is launched. */\n\topen?(url: string): void;\n}\n\nconst defaultIo: LoginGateIo = {\n\twrite: (text) => process.stdout.write(text),\n};\n\n/**\n * Run the browser device login and persist the token.\n *\n * Returns true once signed in. Any failure is reported and returns false, so\n * the caller decides whether to exit.\n */\nexport async function runLoginFlow(io: LoginGateIo = defaultIo): Promise<boolean> {\n\tconst hubUrl = process.env.GITNEXUS_HUB_URL ?? DEFAULT_HUB_URL;\n\n\tio.write(`\\nSign in to GitNexus to use ${APP_NAME}.\\n\\n`);\n\n\ttry {\n\t\tconst deviceName = defaultDeviceName();\n\t\tconst fingerprint = deviceFingerprint();\n\t\tconst start = await startDeviceAuth(hubUrl, { deviceName, deviceFingerprint: fingerprint });\n\t\tconst link = start.verificationUrlComplete ?? start.verificationUrl;\n\t\tio.write(` Code: ${start.userCode}\\n`);\n\t\tio.write(` Open: ${link}\\n\\n`);\n\t\t// Best effort: the launcher swallows its own failures, and the link is\n\t\t// printed above regardless, so a headless box still has a way through.\n\t\t(io.open ?? openBrowser)(link);\n\t\tio.write(\"Opening your browser… (ctrl+c to cancel)\\n\");\n\n\t\tconst result = await pollDeviceAuth(hubUrl, start, io.sleep ? { sleep: io.sleep } : {});\n\t\tconst config = {\n\t\t\thubUrl: result.hubUrl,\n\t\t\ttoken: result.token,\n\t\t\tdeviceFingerprint: fingerprint,\n\t\t\tdeviceName,\n\t\t};\n\t\tawait new GitNexusClient(config).callTool(\"list_repos\", {}, AbortSignal.timeout(15_000));\n\t\tconst path = saveGitNexusConfig(config);\n\t\tio.write(`\\nSigned in. Credential saved to ${path}\\n\\n`);\n\t\treturn true;\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tio.write(`\\nSign-in failed: ${message}\\n`);\n\t\tio.write(`Run ${APP_NAME} again to retry, or set GITNEXUS_TOKEN if you already have one.\\n`);\n\t\tio.write(\"Inside a session, /login → GitNexus account does the same thing.\\n\\n\");\n\t\treturn false;\n\t}\n}\n\n/** Message shown when a non-interactive run cannot prompt for sign-in. */\nexport function nonInteractiveLoginMessage(reason?: string): string {\n\treturn [\n\t\t`${APP_NAME}: not signed in.`,\n\t\t...(reason ? [``, reason] : []),\n\t\t\"\",\n\t\t`Run ${APP_NAME} with no arguments once to sign in through your browser,`,\n\t\t\"or set GITNEXUS_TOKEN for non-interactive use.\",\n\t\t\"\",\n\t\t`Credential location: ${gitNexusConfigPath()}`,\n\t].join(\"\\n\");\n}\n"]}
|
|
1
|
+
{"version":3,"file":"require-login.d.ts","sourceRoot":"","sources":["../../src/cli/require-login.ts"],"names":[],"mappings":"AA2BA,wBAAgB,mBAAmB,IAAI,OAAO,CAG7C;AAED,MAAM,MAAM,eAAe,GACxB;IAAE,MAAM,EAAE,WAAW,CAAA;CAAE,GACvB;IAAE,MAAM,EAAE,kBAAkB,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/C;IAAE,MAAM,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7C,gFAAgF;AAChF,wBAAsB,kBAAkB,CAAC,MAAM,GAAE,WAAyC,GAAG,OAAO,CAAC,eAAe,CAAC,CAepH;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED,MAAM,WAAW,WAAW;IAC3B,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,oDAAoD;IACpD,KAAK,CAAC,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,mDAAmD;IACnD,IAAI,CAAC,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAMD;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,EAAE,GAAE,WAAuB,GAAG,OAAO,CAAC,OAAO,CAAC,CAmChF;AAED,0EAA0E;AAC1E,wBAAgB,0BAA0B,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAUlE","sourcesContent":["import { APP_NAME, readAppEnv } from \"../config.ts\";\nimport { GitNexusClient, GitNexusClientError } from \"../extensions/gitnexus/client.ts\";\nimport {\n\tDEFAULT_HUB_URL,\n\tgitNexusConfigPath,\n\tresolveGitNexusConfig,\n\tsaveGitNexusConfig,\n} from \"../extensions/gitnexus/config.ts\";\nimport {\n\tdefaultDeviceName,\n\tdeviceFingerprint,\n\tpollDeviceAuth,\n\tstartDeviceAuth,\n} from \"../extensions/gitnexus/device-auth.ts\";\nimport { openBrowser } from \"../utils/open-browser.ts\";\n\n/**\n * Sign-in gate.\n *\n * Nexus is a GitNexus client, so it requires an account. Startup stops here\n * until the hub accepts its credential. Model and session initialization happen\n * only after this check, so a stale token cannot fall through to a local provider.\n */\n\n/** Escape hatch for CI and automated tests, which never have a credential. */\nconst SKIP_ENV_SUFFIX = \"SKIP_LOGIN\";\n\nexport function isLoginGateDisabled(): boolean {\n\tconst value = readAppEnv(SKIP_ENV_SUFFIX);\n\treturn value === \"1\" || value?.toLowerCase() === \"true\";\n}\n\nexport type LoginGateStatus =\n\t| { status: \"signed_in\" }\n\t| { status: \"sign_in_required\"; reason?: string }\n\t| { status: \"unavailable\"; reason: string };\n\n/** Validate configured GitNexus auth against the hub before runtime startup. */\nexport async function getLoginGateStatus(signal: AbortSignal = AbortSignal.timeout(15_000)): Promise<LoginGateStatus> {\n\tif (isLoginGateDisabled()) return { status: \"signed_in\" };\n\tconst config = resolveGitNexusConfig();\n\tif (!config) return { status: \"sign_in_required\" };\n\n\ttry {\n\t\tawait new GitNexusClient(config).callTool(\"list_repos\", {}, signal);\n\t\treturn { status: \"signed_in\" };\n\t} catch (error) {\n\t\tconst reason = error instanceof Error ? error.message : String(error);\n\t\tif (error instanceof GitNexusClientError && error.kind === \"auth\") {\n\t\t\treturn { status: \"sign_in_required\", reason };\n\t\t}\n\t\treturn { status: \"unavailable\", reason };\n\t}\n}\n\nexport function loginUnavailableMessage(reason: string): string {\n\treturn `${APP_NAME}: GitNexus unavailable. Startup stopped.\\n\\n${reason}`;\n}\n\nexport interface LoginGateIo {\n\twrite(text: string): void;\n\t/** Injected in tests so no real waiting happens. */\n\tsleep?(ms: number): Promise<void>;\n\t/** Injected in tests so no browser is launched. */\n\topen?(url: string): void;\n}\n\nconst defaultIo: LoginGateIo = {\n\twrite: (text) => process.stdout.write(text),\n};\n\n/**\n * Run the browser device login and persist the token.\n *\n * Returns true once signed in. Any failure is reported and returns false, so\n * the caller decides whether to exit.\n */\nexport async function runLoginFlow(io: LoginGateIo = defaultIo): Promise<boolean> {\n\tconst hubUrl = process.env.GITNEXUS_HUB_URL ?? resolveGitNexusConfig()?.hubUrl ?? DEFAULT_HUB_URL;\n\n\tio.write(`\\nSign in to GitNexus to use ${APP_NAME}.\\n\\n`);\n\n\ttry {\n\t\tconst deviceName = defaultDeviceName();\n\t\tconst fingerprint = deviceFingerprint();\n\t\tconst start = await startDeviceAuth(hubUrl, { deviceName, deviceFingerprint: fingerprint });\n\t\tconst link = start.verificationUrlComplete ?? start.verificationUrl;\n\t\tio.write(` Code: ${start.userCode}\\n`);\n\t\tio.write(` Open: ${link}\\n\\n`);\n\t\t// Best effort: the launcher swallows its own failures, and the link is\n\t\t// printed above regardless, so a headless box still has a way through.\n\t\t(io.open ?? openBrowser)(link);\n\t\tio.write(\"Opening your browser… (ctrl+c to cancel)\\n\");\n\n\t\tconst result = await pollDeviceAuth(hubUrl, start, io.sleep ? { sleep: io.sleep } : {});\n\t\tconst config = {\n\t\t\thubUrl: result.hubUrl,\n\t\t\ttoken: result.token,\n\t\t\tdeviceFingerprint: fingerprint,\n\t\t\tdeviceName,\n\t\t};\n\t\tawait new GitNexusClient(config).callTool(\"list_repos\", {}, AbortSignal.timeout(15_000));\n\t\tconst path = saveGitNexusConfig(config);\n\t\tio.write(`\\nSigned in. Credential saved to ${path}\\n\\n`);\n\t\treturn true;\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tio.write(`\\nSign-in failed: ${message}\\n`);\n\t\tio.write(`Run ${APP_NAME} again to retry, or set GITNEXUS_TOKEN if you already have one.\\n`);\n\t\tio.write(\"Inside a session, /login → GitNexus account does the same thing.\\n\\n\");\n\t\treturn false;\n\t}\n}\n\n/** Message shown when a non-interactive run cannot prompt for sign-in. */\nexport function nonInteractiveLoginMessage(reason?: string): string {\n\treturn [\n\t\t`${APP_NAME}: not signed in.`,\n\t\t...(reason ? [``, reason] : []),\n\t\t\"\",\n\t\t`Run ${APP_NAME} with no arguments once to sign in through your browser,`,\n\t\t\"or set GITNEXUS_TOKEN for non-interactive use.\",\n\t\t\"\",\n\t\t`Credential location: ${gitNexusConfigPath()}`,\n\t].join(\"\\n\");\n}\n"]}
|
|
@@ -48,7 +48,7 @@ const defaultIo = {
|
|
|
48
48
|
* the caller decides whether to exit.
|
|
49
49
|
*/
|
|
50
50
|
export async function runLoginFlow(io = defaultIo) {
|
|
51
|
-
const hubUrl = process.env.GITNEXUS_HUB_URL ?? DEFAULT_HUB_URL;
|
|
51
|
+
const hubUrl = process.env.GITNEXUS_HUB_URL ?? resolveGitNexusConfig()?.hubUrl ?? DEFAULT_HUB_URL;
|
|
52
52
|
io.write(`\nSign in to GitNexus to use ${APP_NAME}.\n\n`);
|
|
53
53
|
try {
|
|
54
54
|
const deviceName = defaultDeviceName();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"require-login.js","sourceRoot":"","sources":["../../src/cli/require-login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvF,OAAO,EACN,eAAe,EACf,kBAAkB,EAClB,qBAAqB,EACrB,kBAAkB,GAClB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACN,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,EACd,eAAe,GACf,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEvD;;;;;;GAMG;AAEH,8EAA8E;AAC9E,MAAM,eAAe,GAAG,YAAY,CAAC;AAErC,MAAM,UAAU,mBAAmB,GAAY;IAC9C,MAAM,KAAK,GAAG,UAAU,CAAC,eAAe,CAAC,CAAC;IAC1C,OAAO,KAAK,KAAK,GAAG,IAAI,KAAK,EAAE,WAAW,EAAE,KAAK,MAAM,CAAC;AAAA,CACxD;AAOD,gFAAgF;AAChF,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,MAAM,GAAgB,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,EAA4B;IACrH,IAAI,mBAAmB,EAAE;QAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IAC1D,MAAM,MAAM,GAAG,qBAAqB,EAAE,CAAC;IACvC,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,MAAM,EAAE,kBAAkB,EAAE,CAAC;IAEnD,IAAI,CAAC;QACJ,MAAM,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,YAAY,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC;QACpE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IAChC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,MAAM,MAAM,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACtE,IAAI,KAAK,YAAY,mBAAmB,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACnE,OAAO,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,EAAE,CAAC;QAC/C,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC;IAC1C,CAAC;AAAA,CACD;AAED,MAAM,UAAU,uBAAuB,CAAC,MAAc,EAAU;IAC/D,OAAO,GAAG,QAAQ,+CAA+C,MAAM,EAAE,CAAC;AAAA,CAC1E;AAUD,MAAM,SAAS,GAAgB;IAC9B,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;CAC3C,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,EAAE,GAAgB,SAAS,EAAoB;IACjF,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"require-login.js","sourceRoot":"","sources":["../../src/cli/require-login.ts"],"names":[],"mappings":"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","sourcesContent":["import { APP_NAME, readAppEnv } from \"../config.ts\";\nimport { GitNexusClient, GitNexusClientError } from \"../extensions/gitnexus/client.ts\";\nimport {\n\tDEFAULT_HUB_URL,\n\tgitNexusConfigPath,\n\tresolveGitNexusConfig,\n\tsaveGitNexusConfig,\n} from \"../extensions/gitnexus/config.ts\";\nimport {\n\tdefaultDeviceName,\n\tdeviceFingerprint,\n\tpollDeviceAuth,\n\tstartDeviceAuth,\n} from \"../extensions/gitnexus/device-auth.ts\";\nimport { openBrowser } from \"../utils/open-browser.ts\";\n\n/**\n * Sign-in gate.\n *\n * Nexus is a GitNexus client, so it requires an account. Startup stops here\n * until the hub accepts its credential. Model and session initialization happen\n * only after this check, so a stale token cannot fall through to a local provider.\n */\n\n/** Escape hatch for CI and automated tests, which never have a credential. */\nconst SKIP_ENV_SUFFIX = \"SKIP_LOGIN\";\n\nexport function isLoginGateDisabled(): boolean {\n\tconst value = readAppEnv(SKIP_ENV_SUFFIX);\n\treturn value === \"1\" || value?.toLowerCase() === \"true\";\n}\n\nexport type LoginGateStatus =\n\t| { status: \"signed_in\" }\n\t| { status: \"sign_in_required\"; reason?: string }\n\t| { status: \"unavailable\"; reason: string };\n\n/** Validate configured GitNexus auth against the hub before runtime startup. */\nexport async function getLoginGateStatus(signal: AbortSignal = AbortSignal.timeout(15_000)): Promise<LoginGateStatus> {\n\tif (isLoginGateDisabled()) return { status: \"signed_in\" };\n\tconst config = resolveGitNexusConfig();\n\tif (!config) return { status: \"sign_in_required\" };\n\n\ttry {\n\t\tawait new GitNexusClient(config).callTool(\"list_repos\", {}, signal);\n\t\treturn { status: \"signed_in\" };\n\t} catch (error) {\n\t\tconst reason = error instanceof Error ? error.message : String(error);\n\t\tif (error instanceof GitNexusClientError && error.kind === \"auth\") {\n\t\t\treturn { status: \"sign_in_required\", reason };\n\t\t}\n\t\treturn { status: \"unavailable\", reason };\n\t}\n}\n\nexport function loginUnavailableMessage(reason: string): string {\n\treturn `${APP_NAME}: GitNexus unavailable. Startup stopped.\\n\\n${reason}`;\n}\n\nexport interface LoginGateIo {\n\twrite(text: string): void;\n\t/** Injected in tests so no real waiting happens. */\n\tsleep?(ms: number): Promise<void>;\n\t/** Injected in tests so no browser is launched. */\n\topen?(url: string): void;\n}\n\nconst defaultIo: LoginGateIo = {\n\twrite: (text) => process.stdout.write(text),\n};\n\n/**\n * Run the browser device login and persist the token.\n *\n * Returns true once signed in. Any failure is reported and returns false, so\n * the caller decides whether to exit.\n */\nexport async function runLoginFlow(io: LoginGateIo = defaultIo): Promise<boolean> {\n\tconst hubUrl = process.env.GITNEXUS_HUB_URL ?? resolveGitNexusConfig()?.hubUrl ?? DEFAULT_HUB_URL;\n\n\tio.write(`\\nSign in to GitNexus to use ${APP_NAME}.\\n\\n`);\n\n\ttry {\n\t\tconst deviceName = defaultDeviceName();\n\t\tconst fingerprint = deviceFingerprint();\n\t\tconst start = await startDeviceAuth(hubUrl, { deviceName, deviceFingerprint: fingerprint });\n\t\tconst link = start.verificationUrlComplete ?? start.verificationUrl;\n\t\tio.write(` Code: ${start.userCode}\\n`);\n\t\tio.write(` Open: ${link}\\n\\n`);\n\t\t// Best effort: the launcher swallows its own failures, and the link is\n\t\t// printed above regardless, so a headless box still has a way through.\n\t\t(io.open ?? openBrowser)(link);\n\t\tio.write(\"Opening your browser… (ctrl+c to cancel)\\n\");\n\n\t\tconst result = await pollDeviceAuth(hubUrl, start, io.sleep ? { sleep: io.sleep } : {});\n\t\tconst config = {\n\t\t\thubUrl: result.hubUrl,\n\t\t\ttoken: result.token,\n\t\t\tdeviceFingerprint: fingerprint,\n\t\t\tdeviceName,\n\t\t};\n\t\tawait new GitNexusClient(config).callTool(\"list_repos\", {}, AbortSignal.timeout(15_000));\n\t\tconst path = saveGitNexusConfig(config);\n\t\tio.write(`\\nSigned in. Credential saved to ${path}\\n\\n`);\n\t\treturn true;\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tio.write(`\\nSign-in failed: ${message}\\n`);\n\t\tio.write(`Run ${APP_NAME} again to retry, or set GITNEXUS_TOKEN if you already have one.\\n`);\n\t\tio.write(\"Inside a session, /login → GitNexus account does the same thing.\\n\\n\");\n\t\treturn false;\n\t}\n}\n\n/** Message shown when a non-interactive run cannot prompt for sign-in. */\nexport function nonInteractiveLoginMessage(reason?: string): string {\n\treturn [\n\t\t`${APP_NAME}: not signed in.`,\n\t\t...(reason ? [``, reason] : []),\n\t\t\"\",\n\t\t`Run ${APP_NAME} with no arguments once to sign in through your browser,`,\n\t\t\"or set GITNEXUS_TOKEN for non-interactive use.\",\n\t\t\"\",\n\t\t`Credential location: ${gitNexusConfigPath()}`,\n\t].join(\"\\n\");\n}\n"]}
|