@juspay/neurolink 11.11.5 → 11.11.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 +5 -1
- package/dist/browser/neurolink.min.js +304 -304
- package/dist/cli/commands/proxy.d.ts +0 -18
- package/dist/cli/commands/proxy.js +30 -473
- package/dist/cli/proxy-clients/claudeCode.d.ts +24 -0
- package/dist/cli/proxy-clients/claudeCode.js +130 -0
- package/dist/cli/proxy-clients/codex.d.ts +23 -0
- package/dist/cli/proxy-clients/codex.js +217 -0
- package/dist/cli/proxy-clients/copilot.d.ts +40 -0
- package/dist/cli/proxy-clients/copilot.js +124 -0
- package/dist/cli/proxy-clients/openCode.d.ts +26 -0
- package/dist/cli/proxy-clients/openCode.js +162 -0
- package/dist/cli/proxy-clients/qwenCode.d.ts +36 -0
- package/dist/cli/proxy-clients/qwenCode.js +139 -0
- package/dist/cli/proxy-clients/registry.d.ts +19 -0
- package/dist/cli/proxy-clients/registry.js +69 -0
- package/dist/lib/types/index.d.ts +1 -0
- package/dist/lib/types/index.js +1 -0
- package/dist/lib/types/loopEngine.d.ts +0 -3
- package/dist/lib/types/proxyClient.d.ts +54 -0
- package/dist/lib/types/proxyClient.js +2 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +1 -0
- package/dist/types/loopEngine.d.ts +0 -3
- package/dist/types/proxyClient.d.ts +54 -0
- package/dist/types/proxyClient.js +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenCode client configurator.
|
|
3
|
+
*
|
|
4
|
+
* Moved verbatim out of `proxy.ts` so that adding a CLI means adding a file
|
|
5
|
+
* here rather than editing a 5,000-line command module in seven places.
|
|
6
|
+
*/
|
|
7
|
+
import { homedir } from "os";
|
|
8
|
+
import { join } from "path";
|
|
9
|
+
import { logger } from "../../lib/utils/logger.js";
|
|
10
|
+
function getOpenCodeConfigDir() {
|
|
11
|
+
// OpenCode resolves this with the unmodified `xdg-basedir` package —
|
|
12
|
+
// `XDG_CONFIG_HOME || ~/.config` — on every platform, macOS included. There
|
|
13
|
+
// is deliberately no darwin branch here: `~/Library/Application Support/
|
|
14
|
+
// opencode` is not a path OpenCode reads. (The similar-looking literal in
|
|
15
|
+
// OpenCode's binary is `systemManagedConfigDir()`, an MDM policy directory
|
|
16
|
+
// at the filesystem root with no $HOME prefix.)
|
|
17
|
+
return join(process.env.XDG_CONFIG_HOME || join(homedir(), ".config"), "opencode");
|
|
18
|
+
}
|
|
19
|
+
function getOpenCodeConfigPath() {
|
|
20
|
+
return join(getOpenCodeConfigDir(), "opencode.json");
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Key under which we persist the snapshot of the user's pre-existing
|
|
24
|
+
* `provider.neurolink` config inside `opencode.json` itself. Persisting (rather
|
|
25
|
+
* than relying on in-process state) means restoration still works even if the
|
|
26
|
+
* proxy crashes or shutdown handlers run in a different process.
|
|
27
|
+
*
|
|
28
|
+
* Mirrors the Claude pattern (`__proxy_original_env` inside Claude's settings).
|
|
29
|
+
*/
|
|
30
|
+
const OPENCODE_ORIGINAL_KEY = "__proxy_original_neurolink";
|
|
31
|
+
export async function setOpenCodeProxySettings(baseUrl, proxyKey) {
|
|
32
|
+
const fs = await import("fs");
|
|
33
|
+
const configDir = getOpenCodeConfigDir();
|
|
34
|
+
try {
|
|
35
|
+
fs.accessSync(configDir);
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
// OpenCode not installed — config directory does not exist. Report the
|
|
39
|
+
// skip so the caller does not print a success message for work that did
|
|
40
|
+
// not happen.
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
let config;
|
|
44
|
+
try {
|
|
45
|
+
config = JSON.parse(fs.readFileSync(getOpenCodeConfigPath(), "utf8"));
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
// file missing/invalid — create fresh config object
|
|
49
|
+
config = { provider: {} };
|
|
50
|
+
}
|
|
51
|
+
const provider = (config.provider ?? {});
|
|
52
|
+
// Persist a snapshot of the user's pre-existing provider.neurolink — but
|
|
53
|
+
// only the first time we touch the file. Subsequent set() calls must NOT
|
|
54
|
+
// overwrite the snapshot (otherwise after the proxy writes its own block,
|
|
55
|
+
// the next set() would store the proxy's block as the "original" and
|
|
56
|
+
// permanently lose the user's real config on the next clear()).
|
|
57
|
+
if (!(OPENCODE_ORIGINAL_KEY in config)) {
|
|
58
|
+
config[OPENCODE_ORIGINAL_KEY] =
|
|
59
|
+
"neurolink" in provider
|
|
60
|
+
? JSON.parse(JSON.stringify(provider.neurolink))
|
|
61
|
+
: null;
|
|
62
|
+
}
|
|
63
|
+
provider.neurolink = {
|
|
64
|
+
id: "neurolink",
|
|
65
|
+
name: "NeuroLink Proxy",
|
|
66
|
+
npm: "@ai-sdk/openai-compatible",
|
|
67
|
+
env: [],
|
|
68
|
+
models: {},
|
|
69
|
+
options: {
|
|
70
|
+
baseURL: baseUrl,
|
|
71
|
+
apiKey: proxyKey || "neurolink-proxy",
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
config.provider = provider;
|
|
75
|
+
fs.writeFileSync(getOpenCodeConfigPath(), JSON.stringify(config, null, 2));
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
export async function clearOpenCodeProxySettings(expectedBaseUrl) {
|
|
79
|
+
const fs = await import("fs");
|
|
80
|
+
let config;
|
|
81
|
+
try {
|
|
82
|
+
config = JSON.parse(fs.readFileSync(getOpenCodeConfigPath(), "utf8"));
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
const provider = config.provider;
|
|
88
|
+
if (!provider || !("neurolink" in provider)) {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
// Check if our proxy URL matches before removing
|
|
92
|
+
const existing = provider.neurolink;
|
|
93
|
+
if (expectedBaseUrl && existing) {
|
|
94
|
+
const options = existing.options;
|
|
95
|
+
if (options && typeof options.baseURL === "string") {
|
|
96
|
+
if (options.baseURL !== expectedBaseUrl) {
|
|
97
|
+
// User configured a different URL; do not clobber
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
const hadNeurolink = "neurolink" in provider;
|
|
103
|
+
// Restore from the snapshot persisted at first set(), regardless of process
|
|
104
|
+
// identity. Only delete provider.neurolink when the snapshot says the user
|
|
105
|
+
// explicitly had no entry before — never on an "undefined" snapshot, since
|
|
106
|
+
// that would mean the snapshot was lost and we cannot prove the entry is ours.
|
|
107
|
+
if (OPENCODE_ORIGINAL_KEY in config) {
|
|
108
|
+
const snapshot = config[OPENCODE_ORIGINAL_KEY];
|
|
109
|
+
if (snapshot === null) {
|
|
110
|
+
// User had no provider.neurolink before the proxy started — safe to remove.
|
|
111
|
+
delete provider.neurolink;
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
provider.neurolink = snapshot;
|
|
115
|
+
}
|
|
116
|
+
delete config[OPENCODE_ORIGINAL_KEY];
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
// No snapshot present — refuse to delete to avoid destroying a config
|
|
120
|
+
// the proxy may not own (e.g. a user wrote their own `neurolink` block
|
|
121
|
+
// before the snapshot key was introduced, or this is being cleared from
|
|
122
|
+
// a process that never ran set()).
|
|
123
|
+
logger.debug("[proxy] OpenCode clear: no original-provider snapshot found, leaving provider.neurolink intact");
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
config.provider = provider;
|
|
127
|
+
fs.writeFileSync(getOpenCodeConfigPath(), JSON.stringify(config, null, 2));
|
|
128
|
+
return hadNeurolink;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Test-only export (CLAUDE.md rule 15 determinism exception). The OpenCode
|
|
132
|
+
* client writers resolve paths from the environment and are only reachable
|
|
133
|
+
* from `proxy start` / `proxy setup`, neither of which can be driven against a
|
|
134
|
+
* throwaway HOME without starting a real server. Consumed by
|
|
135
|
+
* test/continuous-test-suite-proxy.ts.
|
|
136
|
+
*/
|
|
137
|
+
export const __openCodeTestHooks = {
|
|
138
|
+
getOpenCodeConfigDir,
|
|
139
|
+
getOpenCodeConfigPath,
|
|
140
|
+
setOpenCodeProxySettings,
|
|
141
|
+
clearOpenCodeProxySettings,
|
|
142
|
+
};
|
|
143
|
+
export const openCodeConfigurator = {
|
|
144
|
+
id: "opencode",
|
|
145
|
+
displayName: "OpenCode",
|
|
146
|
+
detect: async () => {
|
|
147
|
+
const fs = await import("fs");
|
|
148
|
+
try {
|
|
149
|
+
fs.accessSync(getOpenCodeConfigDir());
|
|
150
|
+
return true;
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
// OpenCode speaks OpenAI Chat Completions, so it points at the /v1 door
|
|
157
|
+
// rather than the proxy root. The suffix belongs to the client, not the
|
|
158
|
+
// caller — every call site used to have to remember it.
|
|
159
|
+
apply: (proxyBaseUrl) => setOpenCodeProxySettings(`${proxyBaseUrl}/v1`),
|
|
160
|
+
restore: (proxyBaseUrl) => clearOpenCodeProxySettings(`${proxyBaseUrl}/v1`),
|
|
161
|
+
};
|
|
162
|
+
//# sourceMappingURL=openCode.js.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Qwen Code client configurator.
|
|
3
|
+
*
|
|
4
|
+
* Qwen Code is OpenAI-compatible: its `cli.js` reads `OPENAI_BASE_URL` and
|
|
5
|
+
* `OPENAI_API_KEY`, and its settings file carries the same pair under
|
|
6
|
+
* `security.auth`. It therefore needs no new proxy route — it points at the
|
|
7
|
+
* existing `/v1/chat/completions` door.
|
|
8
|
+
*
|
|
9
|
+
* Settings shape verified against a real `~/.qwen/settings.json` (`$version` 2)
|
|
10
|
+
* from `@qwen-code/qwen-code@0.17.0`:
|
|
11
|
+
*
|
|
12
|
+
* {
|
|
13
|
+
* "security": { "auth": {
|
|
14
|
+
* "selectedType": "openai", "apiKey": "...", "baseUrl": "https://..."
|
|
15
|
+
* } },
|
|
16
|
+
* "model": { "name": "..." },
|
|
17
|
+
* "$version": 2
|
|
18
|
+
* }
|
|
19
|
+
*/
|
|
20
|
+
import type { CliProxyClientConfigurator } from "../../lib/types/index.js";
|
|
21
|
+
/**
|
|
22
|
+
* Resolved per call rather than at module load so `detect()` and `apply()`
|
|
23
|
+
* agree when HOME changes — under test, and on the `--dev` isolation path.
|
|
24
|
+
*/
|
|
25
|
+
declare function getQwenConfigDir(): string;
|
|
26
|
+
declare function getQwenSettingsPath(): string;
|
|
27
|
+
export declare function setQwenProxySettings(baseUrl: string, proxyKey?: string): Promise<boolean>;
|
|
28
|
+
export declare function clearQwenProxySettings(expectedBaseUrl?: string): Promise<boolean>;
|
|
29
|
+
export declare const qwenCodeConfigurator: CliProxyClientConfigurator;
|
|
30
|
+
export declare const __qwenCodeTestHooks: {
|
|
31
|
+
getQwenConfigDir: typeof getQwenConfigDir;
|
|
32
|
+
getQwenSettingsPath: typeof getQwenSettingsPath;
|
|
33
|
+
setQwenProxySettings: typeof setQwenProxySettings;
|
|
34
|
+
clearQwenProxySettings: typeof clearQwenProxySettings;
|
|
35
|
+
};
|
|
36
|
+
export {};
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Qwen Code client configurator.
|
|
3
|
+
*
|
|
4
|
+
* Qwen Code is OpenAI-compatible: its `cli.js` reads `OPENAI_BASE_URL` and
|
|
5
|
+
* `OPENAI_API_KEY`, and its settings file carries the same pair under
|
|
6
|
+
* `security.auth`. It therefore needs no new proxy route — it points at the
|
|
7
|
+
* existing `/v1/chat/completions` door.
|
|
8
|
+
*
|
|
9
|
+
* Settings shape verified against a real `~/.qwen/settings.json` (`$version` 2)
|
|
10
|
+
* from `@qwen-code/qwen-code@0.17.0`:
|
|
11
|
+
*
|
|
12
|
+
* {
|
|
13
|
+
* "security": { "auth": {
|
|
14
|
+
* "selectedType": "openai", "apiKey": "...", "baseUrl": "https://..."
|
|
15
|
+
* } },
|
|
16
|
+
* "model": { "name": "..." },
|
|
17
|
+
* "$version": 2
|
|
18
|
+
* }
|
|
19
|
+
*/
|
|
20
|
+
import { homedir } from "os";
|
|
21
|
+
import { join } from "path";
|
|
22
|
+
import { logger } from "../../lib/utils/logger.js";
|
|
23
|
+
/**
|
|
24
|
+
* Resolved per call rather than at module load so `detect()` and `apply()`
|
|
25
|
+
* agree when HOME changes — under test, and on the `--dev` isolation path.
|
|
26
|
+
*/
|
|
27
|
+
function getQwenConfigDir() {
|
|
28
|
+
return join(homedir(), ".qwen");
|
|
29
|
+
}
|
|
30
|
+
function getQwenSettingsPath() {
|
|
31
|
+
return join(getQwenConfigDir(), "settings.json");
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Key under which the user's pre-existing `security.auth` block is stashed,
|
|
35
|
+
* inside the settings file itself. Persisting it there (rather than in memory)
|
|
36
|
+
* means a restore still works after a crash, or from a different process —
|
|
37
|
+
* the same approach the Claude and OpenCode writers take.
|
|
38
|
+
*/
|
|
39
|
+
const QWEN_ORIGINAL_KEY = "__proxy_original_qwen_auth";
|
|
40
|
+
function readQwenSettings(fs) {
|
|
41
|
+
try {
|
|
42
|
+
const parsed = JSON.parse(fs.readFileSync(getQwenSettingsPath(), "utf8"));
|
|
43
|
+
return parsed !== null && typeof parsed === "object"
|
|
44
|
+
? parsed
|
|
45
|
+
: null;
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
export async function setQwenProxySettings(baseUrl, proxyKey) {
|
|
52
|
+
const fs = await import("fs");
|
|
53
|
+
try {
|
|
54
|
+
fs.accessSync(getQwenConfigDir());
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// Qwen Code not installed — report the skip so no caller prints a success
|
|
58
|
+
// message for work that did not happen.
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
const settings = readQwenSettings(fs) ?? {};
|
|
62
|
+
const security = (settings.security ?? {});
|
|
63
|
+
const auth = (security.auth ?? {});
|
|
64
|
+
// Snapshot only on first touch. A second apply() must not overwrite the
|
|
65
|
+
// snapshot with our own block, which would lose the user's real config on
|
|
66
|
+
// the next restore.
|
|
67
|
+
if (!(QWEN_ORIGINAL_KEY in settings)) {
|
|
68
|
+
settings[QWEN_ORIGINAL_KEY] =
|
|
69
|
+
"auth" in security ? JSON.parse(JSON.stringify(auth)) : null;
|
|
70
|
+
}
|
|
71
|
+
auth.selectedType = "openai";
|
|
72
|
+
auth.baseUrl = baseUrl;
|
|
73
|
+
auth.apiKey = proxyKey || "neurolink-proxy";
|
|
74
|
+
security.auth = auth;
|
|
75
|
+
settings.security = security;
|
|
76
|
+
fs.writeFileSync(getQwenSettingsPath(), JSON.stringify(settings, null, 2));
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
export async function clearQwenProxySettings(expectedBaseUrl) {
|
|
80
|
+
const fs = await import("fs");
|
|
81
|
+
const settings = readQwenSettings(fs);
|
|
82
|
+
if (!settings) {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
const security = settings.security;
|
|
86
|
+
const auth = security?.auth;
|
|
87
|
+
if (!security || !auth) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
// The user may have pointed Qwen somewhere else since the proxy started.
|
|
91
|
+
// Never clobber a base URL we did not write.
|
|
92
|
+
if (expectedBaseUrl &&
|
|
93
|
+
typeof auth.baseUrl === "string" &&
|
|
94
|
+
auth.baseUrl !== expectedBaseUrl) {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
if (!(QWEN_ORIGINAL_KEY in settings)) {
|
|
98
|
+
// No snapshot means we cannot prove this block is ours. Leaving a stale
|
|
99
|
+
// proxy URL behind is recoverable; destroying a real credential is not.
|
|
100
|
+
logger.debug("[proxy] Qwen clear: no original-auth snapshot found, leaving security.auth intact");
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
const snapshot = settings[QWEN_ORIGINAL_KEY];
|
|
104
|
+
if (snapshot === null) {
|
|
105
|
+
delete security.auth;
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
security.auth = snapshot;
|
|
109
|
+
}
|
|
110
|
+
delete settings[QWEN_ORIGINAL_KEY];
|
|
111
|
+
settings.security = security;
|
|
112
|
+
fs.writeFileSync(getQwenSettingsPath(), JSON.stringify(settings, null, 2));
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
export const qwenCodeConfigurator = {
|
|
116
|
+
id: "qwen-code",
|
|
117
|
+
displayName: "Qwen Code",
|
|
118
|
+
detect: async () => {
|
|
119
|
+
const fs = await import("fs");
|
|
120
|
+
try {
|
|
121
|
+
fs.accessSync(getQwenConfigDir());
|
|
122
|
+
return true;
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
// Qwen speaks OpenAI Chat Completions, so it points at the /v1 door rather
|
|
129
|
+
// than the proxy root.
|
|
130
|
+
apply: (proxyBaseUrl) => setQwenProxySettings(`${proxyBaseUrl}/v1`),
|
|
131
|
+
restore: (proxyBaseUrl) => clearQwenProxySettings(`${proxyBaseUrl}/v1`),
|
|
132
|
+
};
|
|
133
|
+
export const __qwenCodeTestHooks = {
|
|
134
|
+
getQwenConfigDir,
|
|
135
|
+
getQwenSettingsPath,
|
|
136
|
+
setQwenProxySettings,
|
|
137
|
+
clearQwenProxySettings,
|
|
138
|
+
};
|
|
139
|
+
//# sourceMappingURL=qwenCode.js.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { CliProxyClientApplyResult, CliProxyClientConfigurator, CliProxyClientRestoreResult } from "../../lib/types/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Every CLI the proxy auto-configures, in apply order.
|
|
4
|
+
*
|
|
5
|
+
* Order is behaviour: it is the order messages appear during `proxy start`.
|
|
6
|
+
* Restore runs in the same order.
|
|
7
|
+
*/
|
|
8
|
+
export declare const PROXY_CLIENT_CONFIGURATORS: readonly CliProxyClientConfigurator[];
|
|
9
|
+
/**
|
|
10
|
+
* Point every detected client at the proxy.
|
|
11
|
+
*
|
|
12
|
+
* One client failing must never stop the others, so each is wrapped
|
|
13
|
+
* independently and its error is returned rather than thrown. Callers decide
|
|
14
|
+
* how loudly to report — the daemon-start path logs failures at debug level
|
|
15
|
+
* while the setup wizard prints a visible warning.
|
|
16
|
+
*/
|
|
17
|
+
export declare function applyAllClients(proxyBaseUrl: string): Promise<CliProxyClientApplyResult[]>;
|
|
18
|
+
/** Restore every client's previous configuration. See applyAllClients. */
|
|
19
|
+
export declare function restoreAllClients(proxyBaseUrl: string): Promise<CliProxyClientRestoreResult[]>;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { claudeCodeConfigurator } from "./claudeCode.js";
|
|
2
|
+
import { openCodeConfigurator } from "./openCode.js";
|
|
3
|
+
import { codexConfigurator } from "./codex.js";
|
|
4
|
+
import { qwenCodeConfigurator } from "./qwenCode.js";
|
|
5
|
+
import { copilotConfigurator } from "./copilot.js";
|
|
6
|
+
/**
|
|
7
|
+
* Every CLI the proxy auto-configures, in apply order.
|
|
8
|
+
*
|
|
9
|
+
* Order is behaviour: it is the order messages appear during `proxy start`.
|
|
10
|
+
* Restore runs in the same order.
|
|
11
|
+
*/
|
|
12
|
+
export const PROXY_CLIENT_CONFIGURATORS = [
|
|
13
|
+
claudeCodeConfigurator,
|
|
14
|
+
openCodeConfigurator,
|
|
15
|
+
codexConfigurator,
|
|
16
|
+
qwenCodeConfigurator,
|
|
17
|
+
copilotConfigurator,
|
|
18
|
+
];
|
|
19
|
+
/**
|
|
20
|
+
* Point every detected client at the proxy.
|
|
21
|
+
*
|
|
22
|
+
* One client failing must never stop the others, so each is wrapped
|
|
23
|
+
* independently and its error is returned rather than thrown. Callers decide
|
|
24
|
+
* how loudly to report — the daemon-start path logs failures at debug level
|
|
25
|
+
* while the setup wizard prints a visible warning.
|
|
26
|
+
*/
|
|
27
|
+
export async function applyAllClients(proxyBaseUrl) {
|
|
28
|
+
const results = [];
|
|
29
|
+
for (const client of PROXY_CLIENT_CONFIGURATORS) {
|
|
30
|
+
try {
|
|
31
|
+
const applied = (await client.detect())
|
|
32
|
+
? await client.apply(proxyBaseUrl)
|
|
33
|
+
: false;
|
|
34
|
+
results.push({ id: client.id, displayName: client.displayName, applied });
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
results.push({
|
|
38
|
+
id: client.id,
|
|
39
|
+
displayName: client.displayName,
|
|
40
|
+
applied: false,
|
|
41
|
+
error: error instanceof Error ? error : new Error(String(error)),
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return results;
|
|
46
|
+
}
|
|
47
|
+
/** Restore every client's previous configuration. See applyAllClients. */
|
|
48
|
+
export async function restoreAllClients(proxyBaseUrl) {
|
|
49
|
+
const results = [];
|
|
50
|
+
for (const client of PROXY_CLIENT_CONFIGURATORS) {
|
|
51
|
+
try {
|
|
52
|
+
results.push({
|
|
53
|
+
id: client.id,
|
|
54
|
+
displayName: client.displayName,
|
|
55
|
+
restored: await client.restore(proxyBaseUrl),
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
results.push({
|
|
60
|
+
id: client.id,
|
|
61
|
+
displayName: client.displayName,
|
|
62
|
+
restored: false,
|
|
63
|
+
error: error instanceof Error ? error : new Error(String(error)),
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return results;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=registry.js.map
|
package/dist/lib/types/index.js
CHANGED
|
@@ -95,9 +95,6 @@ export type AgenticLoopToolFailureBreaker = {
|
|
|
95
95
|
export type AgenticLoopAdapter<TConversation = unknown, TRaw = unknown> = {
|
|
96
96
|
readonly providerLabel: string;
|
|
97
97
|
readonly maxSteps: number;
|
|
98
|
-
/** Pre-existing per-family flat timeout, used as createTurnClock's deadline default. */
|
|
99
|
-
readonly defaultTurnTimeoutMs?: number;
|
|
100
|
-
readonly stallTimeoutMs?: number;
|
|
101
98
|
/** Set only for adapter instances whose client has the TOOL_NOT_FOUND strike breaker today: both Gemini adapters (AI Studio, Vertex+Gemini) AND the Vertex+Claude call to createAnthropicLoopAdapter — NOT the native-Anthropic call to that same factory, and not Bedrock. See Verified Fact 4. */
|
|
102
99
|
readonly toolFailureBreaker?: AgenticLoopToolFailureBreaker;
|
|
103
100
|
/**
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One AI coding CLI the proxy can point at itself.
|
|
3
|
+
*
|
|
4
|
+
* Adding a CLI means adding one implementation of this type and one line in
|
|
5
|
+
* `src/cli/proxy-clients/registry.ts`. Nothing else in the proxy should need
|
|
6
|
+
* to know the client exists.
|
|
7
|
+
*/
|
|
8
|
+
export type CliProxyClientConfigurator = {
|
|
9
|
+
/** Stable kebab-case identifier, e.g. "claude-code". */
|
|
10
|
+
id: string;
|
|
11
|
+
/** Human-readable name used in CLI output, e.g. "Claude Code". */
|
|
12
|
+
displayName: string;
|
|
13
|
+
/**
|
|
14
|
+
* Whether this CLI appears to be installed. Configurators must not create
|
|
15
|
+
* config files for a CLI the user never installed.
|
|
16
|
+
*/
|
|
17
|
+
detect: () => Promise<boolean>;
|
|
18
|
+
/**
|
|
19
|
+
* Point the CLI at the proxy. `proxyBaseUrl` is the bare proxy origin
|
|
20
|
+
* (e.g. "http://127.0.0.1:55669"); the configurator appends whatever path
|
|
21
|
+
* suffix its CLI needs. Returns false when nothing was written, so callers
|
|
22
|
+
* never print a success message for work that did not happen.
|
|
23
|
+
*/
|
|
24
|
+
apply: (proxyBaseUrl: string) => Promise<boolean>;
|
|
25
|
+
/**
|
|
26
|
+
* Restore the user's previous configuration. `proxyBaseUrl` is the same bare
|
|
27
|
+
* origin; a configurator that finds a different URL configured must leave it
|
|
28
|
+
* alone and return false.
|
|
29
|
+
*/
|
|
30
|
+
restore: (proxyBaseUrl: string) => Promise<boolean>;
|
|
31
|
+
};
|
|
32
|
+
/** Outcome of applying one configurator, for per-client CLI reporting. */
|
|
33
|
+
export type CliProxyClientApplyResult = {
|
|
34
|
+
id: string;
|
|
35
|
+
displayName: string;
|
|
36
|
+
/** True only when the configurator actually wrote configuration. */
|
|
37
|
+
applied: boolean;
|
|
38
|
+
/** Present when the configurator threw; the caller decides how loud to be. */
|
|
39
|
+
error?: Error;
|
|
40
|
+
};
|
|
41
|
+
/** Outcome of restoring one configurator. */
|
|
42
|
+
export type CliProxyClientRestoreResult = {
|
|
43
|
+
id: string;
|
|
44
|
+
displayName: string;
|
|
45
|
+
/** True only when a previous configuration was actually restored. */
|
|
46
|
+
restored: boolean;
|
|
47
|
+
error?: Error;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Raw contents of a Qwen Code `settings.json`. Deliberately open-ended: the
|
|
51
|
+
* configurator rewrites only `security.auth` and must round-trip every other
|
|
52
|
+
* key the user has set, including ones this repo does not know about.
|
|
53
|
+
*/
|
|
54
|
+
export type CliQwenSettings = Record<string, unknown>;
|
package/dist/types/index.d.ts
CHANGED
package/dist/types/index.js
CHANGED
|
@@ -95,9 +95,6 @@ export type AgenticLoopToolFailureBreaker = {
|
|
|
95
95
|
export type AgenticLoopAdapter<TConversation = unknown, TRaw = unknown> = {
|
|
96
96
|
readonly providerLabel: string;
|
|
97
97
|
readonly maxSteps: number;
|
|
98
|
-
/** Pre-existing per-family flat timeout, used as createTurnClock's deadline default. */
|
|
99
|
-
readonly defaultTurnTimeoutMs?: number;
|
|
100
|
-
readonly stallTimeoutMs?: number;
|
|
101
98
|
/** Set only for adapter instances whose client has the TOOL_NOT_FOUND strike breaker today: both Gemini adapters (AI Studio, Vertex+Gemini) AND the Vertex+Claude call to createAnthropicLoopAdapter — NOT the native-Anthropic call to that same factory, and not Bedrock. See Verified Fact 4. */
|
|
102
99
|
readonly toolFailureBreaker?: AgenticLoopToolFailureBreaker;
|
|
103
100
|
/**
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One AI coding CLI the proxy can point at itself.
|
|
3
|
+
*
|
|
4
|
+
* Adding a CLI means adding one implementation of this type and one line in
|
|
5
|
+
* `src/cli/proxy-clients/registry.ts`. Nothing else in the proxy should need
|
|
6
|
+
* to know the client exists.
|
|
7
|
+
*/
|
|
8
|
+
export type CliProxyClientConfigurator = {
|
|
9
|
+
/** Stable kebab-case identifier, e.g. "claude-code". */
|
|
10
|
+
id: string;
|
|
11
|
+
/** Human-readable name used in CLI output, e.g. "Claude Code". */
|
|
12
|
+
displayName: string;
|
|
13
|
+
/**
|
|
14
|
+
* Whether this CLI appears to be installed. Configurators must not create
|
|
15
|
+
* config files for a CLI the user never installed.
|
|
16
|
+
*/
|
|
17
|
+
detect: () => Promise<boolean>;
|
|
18
|
+
/**
|
|
19
|
+
* Point the CLI at the proxy. `proxyBaseUrl` is the bare proxy origin
|
|
20
|
+
* (e.g. "http://127.0.0.1:55669"); the configurator appends whatever path
|
|
21
|
+
* suffix its CLI needs. Returns false when nothing was written, so callers
|
|
22
|
+
* never print a success message for work that did not happen.
|
|
23
|
+
*/
|
|
24
|
+
apply: (proxyBaseUrl: string) => Promise<boolean>;
|
|
25
|
+
/**
|
|
26
|
+
* Restore the user's previous configuration. `proxyBaseUrl` is the same bare
|
|
27
|
+
* origin; a configurator that finds a different URL configured must leave it
|
|
28
|
+
* alone and return false.
|
|
29
|
+
*/
|
|
30
|
+
restore: (proxyBaseUrl: string) => Promise<boolean>;
|
|
31
|
+
};
|
|
32
|
+
/** Outcome of applying one configurator, for per-client CLI reporting. */
|
|
33
|
+
export type CliProxyClientApplyResult = {
|
|
34
|
+
id: string;
|
|
35
|
+
displayName: string;
|
|
36
|
+
/** True only when the configurator actually wrote configuration. */
|
|
37
|
+
applied: boolean;
|
|
38
|
+
/** Present when the configurator threw; the caller decides how loud to be. */
|
|
39
|
+
error?: Error;
|
|
40
|
+
};
|
|
41
|
+
/** Outcome of restoring one configurator. */
|
|
42
|
+
export type CliProxyClientRestoreResult = {
|
|
43
|
+
id: string;
|
|
44
|
+
displayName: string;
|
|
45
|
+
/** True only when a previous configuration was actually restored. */
|
|
46
|
+
restored: boolean;
|
|
47
|
+
error?: Error;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Raw contents of a Qwen Code `settings.json`. Deliberately open-ended: the
|
|
51
|
+
* configurator rewrites only `security.auth` and must round-trip every other
|
|
52
|
+
* key the user has set, including ones this repo does not know about.
|
|
53
|
+
*/
|
|
54
|
+
export type CliQwenSettings = Record<string, unknown>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juspay/neurolink",
|
|
3
|
-
"version": "11.11.
|
|
3
|
+
"version": "11.11.7",
|
|
4
4
|
"packageManager": "pnpm@10.15.1",
|
|
5
5
|
"description": "TypeScript AI SDK with 24+ LLM providers behind one consistent API. MCP-native (connect any MCP server), voice TTS/STT/realtime, RAG, agents, memory, context compaction. OpenAI · Anthropic · Gemini · Bedrock · Azure · Ollama · DeepSeek · NVIDIA NIM and more.",
|
|
6
6
|
"author": {
|