@evident-ai/cli 3.6.1-dev.f151311 → 3.6.1-dev.fc2beae
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/index.js +434 -19
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -100,6 +100,26 @@ function clearCredentials() {
|
|
|
100
100
|
credentials.set("byEndpoint", byEndpoint);
|
|
101
101
|
hardenCredentialsPermissions();
|
|
102
102
|
}
|
|
103
|
+
function getManagedInferenceCredential(runnerId) {
|
|
104
|
+
hardenCredentialsPermissions();
|
|
105
|
+
return credentials.get("managedInferenceByEndpoint")?.[credentialsKey()]?.[runnerId];
|
|
106
|
+
}
|
|
107
|
+
function setManagedInferenceCredential(runnerId, credential) {
|
|
108
|
+
const byEndpoint = credentials.get("managedInferenceByEndpoint") ?? {};
|
|
109
|
+
byEndpoint[credentialsKey()] ??= {};
|
|
110
|
+
byEndpoint[credentialsKey()][runnerId] = credential;
|
|
111
|
+
credentials.set("managedInferenceByEndpoint", byEndpoint);
|
|
112
|
+
hardenCredentialsPermissions();
|
|
113
|
+
}
|
|
114
|
+
function clearManagedInferenceCredential(runnerId) {
|
|
115
|
+
const byEndpoint = credentials.get("managedInferenceByEndpoint") ?? {};
|
|
116
|
+
const runners = byEndpoint[credentialsKey()];
|
|
117
|
+
if (!runners || !(runnerId in runners)) return;
|
|
118
|
+
delete runners[runnerId];
|
|
119
|
+
if (Object.keys(runners).length === 0) delete byEndpoint[credentialsKey()];
|
|
120
|
+
credentials.set("managedInferenceByEndpoint", byEndpoint);
|
|
121
|
+
hardenCredentialsPermissions();
|
|
122
|
+
}
|
|
103
123
|
function clearAllCredentials() {
|
|
104
124
|
credentials.clear();
|
|
105
125
|
hardenCredentialsPermissions();
|
|
@@ -119,13 +139,13 @@ function getCliName() {
|
|
|
119
139
|
// src/lib/api.ts
|
|
120
140
|
async function request(path, method, body, headers = {}) {
|
|
121
141
|
const url = `${getApiUrlConfig()}${path}`;
|
|
122
|
-
const
|
|
142
|
+
const requestHeaders2 = {
|
|
123
143
|
"Content-Type": "application/json",
|
|
124
144
|
...headers
|
|
125
145
|
};
|
|
126
146
|
const response = await fetch(url, {
|
|
127
147
|
method,
|
|
128
|
-
headers:
|
|
148
|
+
headers: requestHeaders2,
|
|
129
149
|
body: body ? JSON.stringify(body) : void 0
|
|
130
150
|
});
|
|
131
151
|
if (!response.ok) {
|
|
@@ -1287,6 +1307,81 @@ var TUNNEL_USAGE_REARM_PING_PATH = "/__evident/usage-rearm";
|
|
|
1287
1307
|
var MAX_FILE_PUSH_BYTES = 64 * 1024;
|
|
1288
1308
|
var MAX_FILE_SYNC_DIRECTORIES = 16;
|
|
1289
1309
|
|
|
1310
|
+
// ../../packages/types/src/credential-proxy-native-config.ts
|
|
1311
|
+
var EVIDENT_PROXY_TOKEN_REFERENCE = "{env:EVIDENT_PROXY_TOKEN}";
|
|
1312
|
+
var CLAUDE_PROVIDER = {
|
|
1313
|
+
namespace: "evident-claude",
|
|
1314
|
+
name: "Evident Claude credential proxy",
|
|
1315
|
+
npm: "@ai-sdk/anthropic"
|
|
1316
|
+
};
|
|
1317
|
+
var NATIVE_PROVIDERS = {
|
|
1318
|
+
claude: CLAUDE_PROVIDER,
|
|
1319
|
+
anthropic: CLAUDE_PROVIDER,
|
|
1320
|
+
codex: {
|
|
1321
|
+
namespace: "evident-codex",
|
|
1322
|
+
name: "Evident Codex credential proxy",
|
|
1323
|
+
npm: "@ai-sdk/openai"
|
|
1324
|
+
},
|
|
1325
|
+
openai: {
|
|
1326
|
+
namespace: "evident-openai",
|
|
1327
|
+
name: "Evident OpenAI credential proxy",
|
|
1328
|
+
npm: "@ai-sdk/openai"
|
|
1329
|
+
},
|
|
1330
|
+
kimi: {
|
|
1331
|
+
namespace: "evident-kimi",
|
|
1332
|
+
name: "Evident Kimi credential proxy",
|
|
1333
|
+
npm: "@ai-sdk/openai-compatible",
|
|
1334
|
+
sdkName: "evident-kimi"
|
|
1335
|
+
}
|
|
1336
|
+
};
|
|
1337
|
+
function credentialProxyInferenceUrl(baseUrl) {
|
|
1338
|
+
const trimmed = baseUrl.trim().replace(/\/+$/, "");
|
|
1339
|
+
return /\/v1$/i.test(trimmed) ? trimmed : `${trimmed}/v1`;
|
|
1340
|
+
}
|
|
1341
|
+
function buildCredentialProxyNativeConfig({
|
|
1342
|
+
inferenceBaseUrl,
|
|
1343
|
+
modelDescriptors
|
|
1344
|
+
}) {
|
|
1345
|
+
const baseURL = credentialProxyInferenceUrl(inferenceBaseUrl);
|
|
1346
|
+
const providers = {};
|
|
1347
|
+
const unsupportedProviders = /* @__PURE__ */ new Set();
|
|
1348
|
+
for (const descriptor of modelDescriptors) {
|
|
1349
|
+
const definition = NATIVE_PROVIDERS[descriptor.provider.trim().toLowerCase()];
|
|
1350
|
+
if (!definition) {
|
|
1351
|
+
unsupportedProviders.add(descriptor.provider.trim() || descriptor.provider);
|
|
1352
|
+
continue;
|
|
1353
|
+
}
|
|
1354
|
+
providers[definition.namespace] ??= definition.npm === "@ai-sdk/anthropic" ? {
|
|
1355
|
+
name: definition.name,
|
|
1356
|
+
npm: definition.npm,
|
|
1357
|
+
options: { baseURL, authToken: EVIDENT_PROXY_TOKEN_REFERENCE },
|
|
1358
|
+
models: {}
|
|
1359
|
+
} : definition.npm === "@ai-sdk/openai" ? {
|
|
1360
|
+
name: definition.name,
|
|
1361
|
+
npm: definition.npm,
|
|
1362
|
+
options: { baseURL, apiKey: EVIDENT_PROXY_TOKEN_REFERENCE },
|
|
1363
|
+
models: {}
|
|
1364
|
+
} : {
|
|
1365
|
+
name: definition.name,
|
|
1366
|
+
npm: definition.npm,
|
|
1367
|
+
options: {
|
|
1368
|
+
name: definition.sdkName,
|
|
1369
|
+
baseURL,
|
|
1370
|
+
apiKey: EVIDENT_PROXY_TOKEN_REFERENCE
|
|
1371
|
+
},
|
|
1372
|
+
models: {}
|
|
1373
|
+
};
|
|
1374
|
+
providers[definition.namespace].models[descriptor.id] = { name: descriptor.id };
|
|
1375
|
+
}
|
|
1376
|
+
return {
|
|
1377
|
+
unsupportedProviders: [...unsupportedProviders],
|
|
1378
|
+
config: {
|
|
1379
|
+
$schema: "https://opencode.ai/config.json",
|
|
1380
|
+
provider: providers
|
|
1381
|
+
}
|
|
1382
|
+
};
|
|
1383
|
+
}
|
|
1384
|
+
|
|
1290
1385
|
// ../../packages/types/src/logging/index.ts
|
|
1291
1386
|
var CORRELATION_ID_HEADER = "x-evident-correlation-id";
|
|
1292
1387
|
var FORWARD_FAILURE_REASON_HEADER = "X-Evident-Failure-Reason";
|
|
@@ -1326,7 +1421,7 @@ import ora4 from "ora";
|
|
|
1326
1421
|
import { select as select4 } from "@inquirer/prompts";
|
|
1327
1422
|
|
|
1328
1423
|
// src/lib/telemetry.ts
|
|
1329
|
-
var CLI_VERSION = (true ? "3.6.1-dev.
|
|
1424
|
+
var CLI_VERSION = (true ? "3.6.1-dev.fc2beae" : void 0) ?? process.env.npm_package_version ?? "unknown";
|
|
1330
1425
|
function getCliVersion() {
|
|
1331
1426
|
return CLI_VERSION;
|
|
1332
1427
|
}
|
|
@@ -1407,7 +1502,7 @@ async function flushEvents() {
|
|
|
1407
1502
|
const controller = new AbortController();
|
|
1408
1503
|
const timeout = setTimeout(() => controller.abort(), FLUSH_TIMEOUT_MS);
|
|
1409
1504
|
try {
|
|
1410
|
-
const
|
|
1505
|
+
const request3 = {
|
|
1411
1506
|
events,
|
|
1412
1507
|
client_type: "cli",
|
|
1413
1508
|
client_version: CLI_VERSION
|
|
@@ -1418,7 +1513,7 @@ async function flushEvents() {
|
|
|
1418
1513
|
"Content-Type": "application/json",
|
|
1419
1514
|
Authorization: authHeader
|
|
1420
1515
|
},
|
|
1421
|
-
body: JSON.stringify(
|
|
1516
|
+
body: JSON.stringify(request3),
|
|
1422
1517
|
signal: controller.signal
|
|
1423
1518
|
});
|
|
1424
1519
|
if (!response.ok) {
|
|
@@ -4681,11 +4776,11 @@ function failureMessage(status2) {
|
|
|
4681
4776
|
function isRetryableStatus(status2) {
|
|
4682
4777
|
return CONNECT_KEY_RETRY_STATUSES.includes(status2);
|
|
4683
4778
|
}
|
|
4684
|
-
async function importOneCredential(
|
|
4779
|
+
async function importOneCredential(request3, credential, sleepForRetry, log3) {
|
|
4685
4780
|
const path = `/api/integration/${encodeURIComponent(credential.integrationId)}/connect/key`;
|
|
4686
4781
|
for (let attempt = 1; attempt <= CONNECT_KEY_MAX_ATTEMPTS; attempt += 1) {
|
|
4687
4782
|
try {
|
|
4688
|
-
const response = await
|
|
4783
|
+
const response = await request3(
|
|
4689
4784
|
path,
|
|
4690
4785
|
{
|
|
4691
4786
|
method: "POST",
|
|
@@ -4720,7 +4815,7 @@ async function importOneCredential(request2, credential, sleepForRetry, log3) {
|
|
|
4720
4815
|
throw new Error("OpenCode credential import retry loop did not return");
|
|
4721
4816
|
}
|
|
4722
4817
|
async function importOpenCodeCredentials({
|
|
4723
|
-
request:
|
|
4818
|
+
request: request3,
|
|
4724
4819
|
classified,
|
|
4725
4820
|
connectedIntegrationIds,
|
|
4726
4821
|
sleepForRetry = sleep2,
|
|
@@ -4732,7 +4827,7 @@ async function importOpenCodeCredentials({
|
|
|
4732
4827
|
result.alreadyConnected.push(credential.integrationId);
|
|
4733
4828
|
continue;
|
|
4734
4829
|
}
|
|
4735
|
-
const outcome = await importOneCredential(
|
|
4830
|
+
const outcome = await importOneCredential(request3, credential, sleepForRetry, log3);
|
|
4736
4831
|
if (outcome.ok) result.imported.push(credential.integrationId);
|
|
4737
4832
|
else result.failed.push(outcome.failure);
|
|
4738
4833
|
}
|
|
@@ -4750,7 +4845,7 @@ function parseIntegrationList(value) {
|
|
|
4750
4845
|
return { integrationIds, hasData: value.data.length > 0 };
|
|
4751
4846
|
}
|
|
4752
4847
|
async function getConnectedOpenCodeIntegrationIds({
|
|
4753
|
-
request:
|
|
4848
|
+
request: request3,
|
|
4754
4849
|
directory,
|
|
4755
4850
|
sleepForRetry = sleep2,
|
|
4756
4851
|
log: log3
|
|
@@ -4758,7 +4853,7 @@ async function getConnectedOpenCodeIntegrationIds({
|
|
|
4758
4853
|
const path = `/api/integration?location%5Bdirectory%5D=${encodeURIComponent(directory)}`;
|
|
4759
4854
|
for (let attempt = 1; attempt <= INTEGRATION_LIST_MAX_READS; attempt += 1) {
|
|
4760
4855
|
try {
|
|
4761
|
-
const response = await
|
|
4856
|
+
const response = await request3(path);
|
|
4762
4857
|
const parsed = parseIntegrationList(await response.json());
|
|
4763
4858
|
if (parsed === null) {
|
|
4764
4859
|
log3(
|
|
@@ -4787,7 +4882,7 @@ async function getConnectedOpenCodeIntegrationIds({
|
|
|
4787
4882
|
return null;
|
|
4788
4883
|
}
|
|
4789
4884
|
async function importOpenCodeV2Credentials({
|
|
4790
|
-
request:
|
|
4885
|
+
request: request3,
|
|
4791
4886
|
homeDir,
|
|
4792
4887
|
directory,
|
|
4793
4888
|
sleepForRetry = sleep2,
|
|
@@ -4805,7 +4900,7 @@ async function importOpenCodeV2Credentials({
|
|
|
4805
4900
|
const classified = classifyOpenCodeCredentials(credentials2);
|
|
4806
4901
|
if (classified.importable.length === 0) return emptyResult(classified.unsupported);
|
|
4807
4902
|
const connectedIntegrationIds = await getConnectedOpenCodeIntegrationIds({
|
|
4808
|
-
request:
|
|
4903
|
+
request: request3,
|
|
4809
4904
|
directory,
|
|
4810
4905
|
sleepForRetry,
|
|
4811
4906
|
log: log3
|
|
@@ -4814,7 +4909,7 @@ async function importOpenCodeV2Credentials({
|
|
|
4814
4909
|
return emptyResult(classified.unsupported, "connection-list-unavailable");
|
|
4815
4910
|
}
|
|
4816
4911
|
return importOpenCodeCredentials({
|
|
4817
|
-
request:
|
|
4912
|
+
request: request3,
|
|
4818
4913
|
classified,
|
|
4819
4914
|
connectedIntegrationIds,
|
|
4820
4915
|
sleepForRetry,
|
|
@@ -7199,8 +7294,8 @@ import { chmod, mkdir, open as open3, realpath, rename, unlink } from "node:fs/p
|
|
|
7199
7294
|
import { basename as basename2, dirname as dirname6, isAbsolute as isAbsolute2, join as join9, relative as relative2, resolve as resolve3, sep as sep2 } from "node:path";
|
|
7200
7295
|
var FILE_MODE = 384;
|
|
7201
7296
|
var DIRECTORY_MODE = 448;
|
|
7202
|
-
async function writePushedFile(
|
|
7203
|
-
const { requestedPath, content, allowedDirectories, homeDir } =
|
|
7297
|
+
async function writePushedFile(request3) {
|
|
7298
|
+
const { requestedPath, content, allowedDirectories, homeDir } = request3;
|
|
7204
7299
|
const bytes = content.byteLength;
|
|
7205
7300
|
if (allowedDirectories.length === 0) {
|
|
7206
7301
|
return refuse("file_sync_disabled", "File sync is not enabled on this runner.", {
|
|
@@ -13778,6 +13873,44 @@ async function configureGitHubAccess({ env, log: log3 }) {
|
|
|
13778
13873
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
13779
13874
|
import { copyFileSync, existsSync as existsSync2, statSync as statSync6 } from "node:fs";
|
|
13780
13875
|
import { isAbsolute as isAbsolute3, join as join11, resolve as resolve4 } from "node:path";
|
|
13876
|
+
var MANAGED_PROVIDER_NAMESPACES = [
|
|
13877
|
+
"evident-claude",
|
|
13878
|
+
"evident-codex",
|
|
13879
|
+
"evident-openai",
|
|
13880
|
+
"evident-kimi"
|
|
13881
|
+
];
|
|
13882
|
+
function parseConfigContent(content) {
|
|
13883
|
+
if (!content?.trim()) return {};
|
|
13884
|
+
const parsed = JSON.parse(content);
|
|
13885
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
13886
|
+
throw new Error("OPENCODE_CONFIG_CONTENT must contain a JSON object");
|
|
13887
|
+
}
|
|
13888
|
+
return parsed;
|
|
13889
|
+
}
|
|
13890
|
+
function mergeManagedOpenCodeConfigContent(content, managedProviders) {
|
|
13891
|
+
const config = parseConfigContent(content);
|
|
13892
|
+
const provider = typeof config.provider === "object" && config.provider !== null && !Array.isArray(config.provider) ? { ...config.provider } : {};
|
|
13893
|
+
for (const namespace of MANAGED_PROVIDER_NAMESPACES) {
|
|
13894
|
+
delete provider[namespace];
|
|
13895
|
+
}
|
|
13896
|
+
return JSON.stringify({ ...config, provider: { ...provider, ...managedProviders } });
|
|
13897
|
+
}
|
|
13898
|
+
function removeManagedOpenCodeConfigContent(content) {
|
|
13899
|
+
if (!content?.trim()) return content;
|
|
13900
|
+
const config = parseConfigContent(content);
|
|
13901
|
+
if (typeof config.provider !== "object" || config.provider === null || Array.isArray(config.provider)) {
|
|
13902
|
+
return content;
|
|
13903
|
+
}
|
|
13904
|
+
const provider = { ...config.provider };
|
|
13905
|
+
let changed = false;
|
|
13906
|
+
for (const namespace of MANAGED_PROVIDER_NAMESPACES) {
|
|
13907
|
+
if (namespace in provider) {
|
|
13908
|
+
delete provider[namespace];
|
|
13909
|
+
changed = true;
|
|
13910
|
+
}
|
|
13911
|
+
}
|
|
13912
|
+
return changed ? JSON.stringify({ ...config, provider }) : content;
|
|
13913
|
+
}
|
|
13781
13914
|
function isFile(filePath) {
|
|
13782
13915
|
return existsSync2(filePath) && statSync6(filePath).isFile();
|
|
13783
13916
|
}
|
|
@@ -14199,6 +14332,230 @@ function createCredentialSync({
|
|
|
14199
14332
|
};
|
|
14200
14333
|
}
|
|
14201
14334
|
|
|
14335
|
+
// src/lib/managed-inference-setup.ts
|
|
14336
|
+
var defaultStore = {
|
|
14337
|
+
get: getManagedInferenceCredential,
|
|
14338
|
+
set: setManagedInferenceCredential,
|
|
14339
|
+
clear: clearManagedInferenceCredential
|
|
14340
|
+
};
|
|
14341
|
+
function endpoint(options, operation) {
|
|
14342
|
+
return `${options.apiUrl}/runners/${options.agentId}/managed-credentials/${operation}`;
|
|
14343
|
+
}
|
|
14344
|
+
function requestHeaders(options) {
|
|
14345
|
+
return { Authorization: options.getAuthHeader(), "Content-Type": "application/json" };
|
|
14346
|
+
}
|
|
14347
|
+
function request2(options) {
|
|
14348
|
+
return withRequestTimeout(options.fetchImpl ?? fetch, REQUEST_TIMEOUT_MS);
|
|
14349
|
+
}
|
|
14350
|
+
function safeFailure(operation, status2) {
|
|
14351
|
+
return status2 === void 0 ? `${operation} could not reach the managed credential service` : `${operation} returned HTTP ${status2}`;
|
|
14352
|
+
}
|
|
14353
|
+
function logTransportFailure(options, operation, error2, authorization) {
|
|
14354
|
+
let detail = error2 instanceof Error ? error2.message : String(error2);
|
|
14355
|
+
const credential = authorization.split(/\s+/, 2)[1];
|
|
14356
|
+
for (const secret of [authorization, credential]) {
|
|
14357
|
+
if (secret) detail = detail.replaceAll(secret, "[redacted]");
|
|
14358
|
+
}
|
|
14359
|
+
options.log(
|
|
14360
|
+
`MANAGED-INFERENCE-TRANSPORT-FAILED: operation=${operation} detail=${redactDiagnosticText(detail)}`,
|
|
14361
|
+
"debug"
|
|
14362
|
+
);
|
|
14363
|
+
}
|
|
14364
|
+
async function responseJson(response) {
|
|
14365
|
+
try {
|
|
14366
|
+
const value = await response.json();
|
|
14367
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
|
|
14368
|
+
} catch (error2) {
|
|
14369
|
+
return null;
|
|
14370
|
+
}
|
|
14371
|
+
}
|
|
14372
|
+
function readSetup(value) {
|
|
14373
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return null;
|
|
14374
|
+
const setup = value;
|
|
14375
|
+
if (typeof setup.runner_id !== "string" || typeof setup.generation !== "string" || typeof setup.status !== "string" || setup.token_id !== null && typeof setup.token_id !== "string") {
|
|
14376
|
+
return null;
|
|
14377
|
+
}
|
|
14378
|
+
return setup;
|
|
14379
|
+
}
|
|
14380
|
+
function clearLocalSetup(options) {
|
|
14381
|
+
const env = options.env ?? process.env;
|
|
14382
|
+
(options.store ?? defaultStore).clear(options.agentId);
|
|
14383
|
+
delete env.EVIDENT_PROXY_TOKEN;
|
|
14384
|
+
try {
|
|
14385
|
+
const content = removeManagedOpenCodeConfigContent(env.OPENCODE_CONFIG_CONTENT);
|
|
14386
|
+
if (content === void 0) delete env.OPENCODE_CONFIG_CONTENT;
|
|
14387
|
+
else env.OPENCODE_CONFIG_CONTENT = content;
|
|
14388
|
+
} catch (error2) {
|
|
14389
|
+
options.log(
|
|
14390
|
+
"MANAGED-INFERENCE-CLEANUP-PARTIAL: stored credentials were removed, but malformed OPENCODE_CONFIG_CONTENT could not be inspected",
|
|
14391
|
+
"warn"
|
|
14392
|
+
);
|
|
14393
|
+
}
|
|
14394
|
+
}
|
|
14395
|
+
async function discoverManagedInferenceSetup(options) {
|
|
14396
|
+
const headers = requestHeaders(options);
|
|
14397
|
+
let response;
|
|
14398
|
+
try {
|
|
14399
|
+
response = await request2(options)(endpoint(options, "current"), {
|
|
14400
|
+
headers
|
|
14401
|
+
});
|
|
14402
|
+
} catch (error2) {
|
|
14403
|
+
logTransportFailure(options, "discovery", error2, headers.Authorization);
|
|
14404
|
+
return { kind: "failed", reason: safeFailure("Managed setup discovery") };
|
|
14405
|
+
}
|
|
14406
|
+
if (response.status === 404) {
|
|
14407
|
+
clearLocalSetup(options);
|
|
14408
|
+
return { kind: "none" };
|
|
14409
|
+
}
|
|
14410
|
+
if (!response.ok) {
|
|
14411
|
+
return { kind: "failed", reason: safeFailure("Managed setup discovery", response.status) };
|
|
14412
|
+
}
|
|
14413
|
+
const body = await responseJson(response);
|
|
14414
|
+
const setup = readSetup(body?.setup);
|
|
14415
|
+
return setup ? { kind: "setup", setup } : { kind: "failed", reason: "Managed setup discovery returned an invalid response" };
|
|
14416
|
+
}
|
|
14417
|
+
async function post(options, operation, body) {
|
|
14418
|
+
const headers = requestHeaders(options);
|
|
14419
|
+
try {
|
|
14420
|
+
return await request2(options)(endpoint(options, operation), {
|
|
14421
|
+
method: "POST",
|
|
14422
|
+
headers,
|
|
14423
|
+
body: JSON.stringify(body)
|
|
14424
|
+
});
|
|
14425
|
+
} catch (error2) {
|
|
14426
|
+
logTransportFailure(options, operation, error2, headers.Authorization);
|
|
14427
|
+
return null;
|
|
14428
|
+
}
|
|
14429
|
+
}
|
|
14430
|
+
function applyCredential(options, credential) {
|
|
14431
|
+
const { config, unsupportedProviders } = buildCredentialProxyNativeConfig({
|
|
14432
|
+
inferenceBaseUrl: credential.inferenceBaseUrl,
|
|
14433
|
+
modelDescriptors: credential.modelDescriptors
|
|
14434
|
+
});
|
|
14435
|
+
if (unsupportedProviders.length > 0 || Object.keys(config.provider).length === 0) {
|
|
14436
|
+
return "Managed setup contains unsupported provider descriptors";
|
|
14437
|
+
}
|
|
14438
|
+
const env = options.env ?? process.env;
|
|
14439
|
+
let merged;
|
|
14440
|
+
try {
|
|
14441
|
+
merged = mergeManagedOpenCodeConfigContent(env.OPENCODE_CONFIG_CONTENT, config.provider);
|
|
14442
|
+
} catch (error2) {
|
|
14443
|
+
return "OPENCODE_CONFIG_CONTENT is malformed; managed providers were not installed";
|
|
14444
|
+
}
|
|
14445
|
+
try {
|
|
14446
|
+
(options.store ?? defaultStore).set(options.agentId, credential);
|
|
14447
|
+
} catch (error2) {
|
|
14448
|
+
options.log(
|
|
14449
|
+
`MANAGED-INFERENCE-STORE-FAILED: runner=${options.agentId} generation=${credential.generation}`,
|
|
14450
|
+
"warn"
|
|
14451
|
+
);
|
|
14452
|
+
return "Managed credentials could not be written to the protected store";
|
|
14453
|
+
}
|
|
14454
|
+
env.EVIDENT_PROXY_TOKEN = credential.token;
|
|
14455
|
+
env.OPENCODE_CONFIG_CONTENT = merged;
|
|
14456
|
+
return null;
|
|
14457
|
+
}
|
|
14458
|
+
async function reportManagedInferenceApplyFailure(options, failure) {
|
|
14459
|
+
const response = await post(options, "report-failure", {
|
|
14460
|
+
generation: failure.generation,
|
|
14461
|
+
token_id: failure.tokenId
|
|
14462
|
+
});
|
|
14463
|
+
if (!response?.ok) {
|
|
14464
|
+
options.log(
|
|
14465
|
+
`MANAGED-INFERENCE-REPORT-FAILED: runner=${options.agentId} generation=${failure.generation}${response ? ` status=${response.status}` : ""}`,
|
|
14466
|
+
"warn"
|
|
14467
|
+
);
|
|
14468
|
+
}
|
|
14469
|
+
}
|
|
14470
|
+
async function reaffirmStored(options, credential) {
|
|
14471
|
+
const response = await post(options, "reaffirm", {
|
|
14472
|
+
generation: credential.generation,
|
|
14473
|
+
token_id: credential.tokenId
|
|
14474
|
+
});
|
|
14475
|
+
if (!response?.ok) {
|
|
14476
|
+
return {
|
|
14477
|
+
kind: "failed",
|
|
14478
|
+
reason: response?.status === 409 ? "Stored managed credential no longer matches this setup; restart required" : response ? safeFailure("Managed credential reaffirmation", response.status) : safeFailure("Managed credential reaffirmation")
|
|
14479
|
+
};
|
|
14480
|
+
}
|
|
14481
|
+
const body = await responseJson(response);
|
|
14482
|
+
const setup = readSetup(body?.setup);
|
|
14483
|
+
if (!setup || setup.generation !== credential.generation || setup.token_id !== credential.tokenId) {
|
|
14484
|
+
return { kind: "failed", reason: "Managed credential reaffirmation returned a mismatch" };
|
|
14485
|
+
}
|
|
14486
|
+
const failure = applyCredential(options, credential);
|
|
14487
|
+
return failure ? { kind: "failed", reason: failure } : { kind: "ready", generation: credential.generation, tokenId: credential.tokenId };
|
|
14488
|
+
}
|
|
14489
|
+
async function prepareManagedInferenceSetup(options, discovery, health) {
|
|
14490
|
+
if (health.authFailed) {
|
|
14491
|
+
return {
|
|
14492
|
+
kind: "failed",
|
|
14493
|
+
reason: "OpenCode authentication failed; managed credentials were not rotated"
|
|
14494
|
+
};
|
|
14495
|
+
}
|
|
14496
|
+
const stored = (options.store ?? defaultStore).get(options.agentId);
|
|
14497
|
+
if (health.healthy) {
|
|
14498
|
+
if (!stored) {
|
|
14499
|
+
return {
|
|
14500
|
+
kind: "failed",
|
|
14501
|
+
reason: "Managed credentials are missing for the serving OpenCode process; restart required"
|
|
14502
|
+
};
|
|
14503
|
+
}
|
|
14504
|
+
return reaffirmStored(options, stored);
|
|
14505
|
+
}
|
|
14506
|
+
if (discovery.setup.status === "acknowledged" && stored?.generation === discovery.setup.generation && stored.tokenId === discovery.setup.token_id) {
|
|
14507
|
+
return reaffirmStored(options, stored);
|
|
14508
|
+
}
|
|
14509
|
+
const response = await post(options, "bootstrap", { generation: discovery.setup.generation });
|
|
14510
|
+
if (!response?.ok) {
|
|
14511
|
+
return {
|
|
14512
|
+
kind: "failed",
|
|
14513
|
+
reason: response ? safeFailure("Managed credential bootstrap", response.status) : safeFailure("Managed credential bootstrap")
|
|
14514
|
+
};
|
|
14515
|
+
}
|
|
14516
|
+
const body = await responseJson(response);
|
|
14517
|
+
const setup = readSetup(body?.setup);
|
|
14518
|
+
const token = body?.inference_token;
|
|
14519
|
+
const inferenceBaseUrl = body?.inference_base_url;
|
|
14520
|
+
const modelDescriptors = body?.model_descriptors;
|
|
14521
|
+
if (!setup || setup.generation !== discovery.setup.generation || typeof setup.token_id !== "string" || typeof token !== "string" || typeof inferenceBaseUrl !== "string" || !Array.isArray(modelDescriptors) || !modelDescriptors.every(
|
|
14522
|
+
(descriptor) => typeof descriptor === "object" && descriptor !== null && typeof descriptor.id === "string" && typeof descriptor.provider === "string"
|
|
14523
|
+
)) {
|
|
14524
|
+
return { kind: "failed", reason: "Managed credential bootstrap returned an invalid response" };
|
|
14525
|
+
}
|
|
14526
|
+
const credential = {
|
|
14527
|
+
generation: setup.generation,
|
|
14528
|
+
tokenId: setup.token_id,
|
|
14529
|
+
token,
|
|
14530
|
+
inferenceBaseUrl,
|
|
14531
|
+
modelDescriptors
|
|
14532
|
+
};
|
|
14533
|
+
const failure = applyCredential(options, credential);
|
|
14534
|
+
if (failure) {
|
|
14535
|
+
await reportManagedInferenceApplyFailure(options, credential);
|
|
14536
|
+
return { kind: "failed", reason: failure };
|
|
14537
|
+
}
|
|
14538
|
+
return { kind: "ready", generation: credential.generation, tokenId: credential.tokenId };
|
|
14539
|
+
}
|
|
14540
|
+
async function acknowledgeManagedInferenceSetup(options, preparation) {
|
|
14541
|
+
const response = await post(options, "acknowledge", {
|
|
14542
|
+
generation: preparation.generation,
|
|
14543
|
+
token_id: preparation.tokenId,
|
|
14544
|
+
config_validated: true
|
|
14545
|
+
});
|
|
14546
|
+
if (!response?.ok) {
|
|
14547
|
+
throw new Error(
|
|
14548
|
+
response ? safeFailure("Managed credential acknowledgment", response.status) : safeFailure("Managed credential acknowledgment")
|
|
14549
|
+
);
|
|
14550
|
+
}
|
|
14551
|
+
const body = await responseJson(response);
|
|
14552
|
+
const setup = readSetup(body?.setup);
|
|
14553
|
+
if (!setup || setup.generation !== preparation.generation || setup.token_id !== preparation.tokenId) {
|
|
14554
|
+
throw new Error("Managed credential acknowledgment returned a mismatch");
|
|
14555
|
+
}
|
|
14556
|
+
return response.status === 200 && setup.status === "acknowledged" ? "acknowledged" : "pending";
|
|
14557
|
+
}
|
|
14558
|
+
|
|
14202
14559
|
// src/commands/run.ts
|
|
14203
14560
|
var MAX_ACTIVITY_LOG_ENTRIES = 10;
|
|
14204
14561
|
var MAX_DISCONNECT_REASON_LENGTH = 200;
|
|
@@ -15983,6 +16340,40 @@ async function run(options) {
|
|
|
15983
16340
|
for (const warning2 of opencodeVersionWarnings) {
|
|
15984
16341
|
logActivity(state, { type: "info", level: "warn", message: warning2 });
|
|
15985
16342
|
}
|
|
16343
|
+
const managedSetupOptions = {
|
|
16344
|
+
agentId: state.agentId,
|
|
16345
|
+
apiUrl: getApiUrlConfig(),
|
|
16346
|
+
getAuthHeader: () => state.authHeader,
|
|
16347
|
+
log: (message, level = "info") => logActivity(state, {
|
|
16348
|
+
type: level === "error" ? "error" : "info",
|
|
16349
|
+
level,
|
|
16350
|
+
...level === "error" ? { error: message } : { message }
|
|
16351
|
+
})
|
|
16352
|
+
};
|
|
16353
|
+
const managedDiscovery = await discoverManagedInferenceSetup(managedSetupOptions);
|
|
16354
|
+
let managedPreparation = { kind: "none" };
|
|
16355
|
+
if (managedDiscovery.kind === "failed") {
|
|
16356
|
+
managedPreparation = managedDiscovery;
|
|
16357
|
+
managedSetupOptions.log(`MANAGED-INFERENCE-NOT-READY: ${managedDiscovery.reason}`, "warn");
|
|
16358
|
+
} else if (managedDiscovery.kind === "setup") {
|
|
16359
|
+
const managedHealth = opencodeVersion === "v2" ? await checkOpenCode2Health(state.port) : await checkOpenCodeHealth(state.port);
|
|
16360
|
+
managedPreparation = await prepareManagedInferenceSetup(
|
|
16361
|
+
managedSetupOptions,
|
|
16362
|
+
managedDiscovery,
|
|
16363
|
+
managedHealth
|
|
16364
|
+
);
|
|
16365
|
+
if (managedPreparation.kind === "failed") {
|
|
16366
|
+
managedSetupOptions.log(
|
|
16367
|
+
`MANAGED-INFERENCE-NOT-READY: ${managedPreparation.reason}`,
|
|
16368
|
+
"warn"
|
|
16369
|
+
);
|
|
16370
|
+
} else if (managedPreparation.kind === "ready") {
|
|
16371
|
+
managedSetupOptions.log(
|
|
16372
|
+
`MANAGED-INFERENCE-PREPARED: runner=${state.agentId} generation=${managedPreparation.generation}`,
|
|
16373
|
+
"info"
|
|
16374
|
+
);
|
|
16375
|
+
}
|
|
16376
|
+
}
|
|
15986
16377
|
const { value: maxActiveSessions, warnings: maxActiveSessionsWarnings } = resolveMaxActiveSessions(options, process.env);
|
|
15987
16378
|
for (const warning2 of maxActiveSessionsWarnings) {
|
|
15988
16379
|
logActivity(state, { type: "info", level: "warn", message: warning2 });
|
|
@@ -16077,6 +16468,30 @@ async function run(options) {
|
|
|
16077
16468
|
}
|
|
16078
16469
|
}
|
|
16079
16470
|
state.opencodeConnected = oc.notReadyReason === null;
|
|
16471
|
+
if (managedPreparation.kind === "ready" && oc.notReadyReason === null) {
|
|
16472
|
+
try {
|
|
16473
|
+
const acknowledgement = await acknowledgeManagedInferenceSetup(
|
|
16474
|
+
managedSetupOptions,
|
|
16475
|
+
managedPreparation
|
|
16476
|
+
);
|
|
16477
|
+
if (acknowledgement === "acknowledged") {
|
|
16478
|
+
managedSetupOptions.log(
|
|
16479
|
+
`MANAGED-INFERENCE-ACKNOWLEDGED: runner=${state.agentId} generation=${managedPreparation.generation}`,
|
|
16480
|
+
"info"
|
|
16481
|
+
);
|
|
16482
|
+
} else {
|
|
16483
|
+
managedSetupOptions.log(
|
|
16484
|
+
`MANAGED-INFERENCE-NOT-READY: policy refresh is pending for runner=${state.agentId} generation=${managedPreparation.generation}`,
|
|
16485
|
+
"warn"
|
|
16486
|
+
);
|
|
16487
|
+
}
|
|
16488
|
+
} catch (error2) {
|
|
16489
|
+
managedSetupOptions.log(
|
|
16490
|
+
`MANAGED-INFERENCE-NOT-READY: ${error2 instanceof Error ? error2.message : String(error2)}`,
|
|
16491
|
+
"warn"
|
|
16492
|
+
);
|
|
16493
|
+
}
|
|
16494
|
+
}
|
|
16080
16495
|
const version2 = state.opencodeVersion ? ` (v${state.opencodeVersion})` : "";
|
|
16081
16496
|
ocSpinner?.succeed(`OpenCode running on port ${state.port}${version2}`);
|
|
16082
16497
|
if (!state.interactive && oc.notReadyReason !== null) {
|
|
@@ -16478,9 +16893,9 @@ program.name("evident").description("Run OpenCode locally and connect it to Evid
|
|
|
16478
16893
|
"--endpoint <url>",
|
|
16479
16894
|
"Evident API base URL (default: production; e.g. http://localhost:3001)"
|
|
16480
16895
|
).option("--tunnel <url>", "Tunnel WebSocket URL (default: production; e.g. ws://localhost:8787)").hook("preAction", (thisCommand) => {
|
|
16481
|
-
const { endpoint, tunnel } = thisCommand.opts();
|
|
16482
|
-
if (
|
|
16483
|
-
setEndpoint(
|
|
16896
|
+
const { endpoint: endpoint2, tunnel } = thisCommand.opts();
|
|
16897
|
+
if (endpoint2) {
|
|
16898
|
+
setEndpoint(endpoint2);
|
|
16484
16899
|
}
|
|
16485
16900
|
if (tunnel) {
|
|
16486
16901
|
setTunnelUrl(tunnel);
|