@evident-ai/cli 3.6.1-dev.43c1fd7 → 3.6.1-dev.5f836c8
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 +4 -0
- package/dist/index.js +152 -44
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -125,6 +125,10 @@ Options:
|
|
|
125
125
|
- `--opencode-config-overlay <path>` — Apply a runner-provided OpenCode config
|
|
126
126
|
before starting OpenCode. Relative paths are resolved from the working directory;
|
|
127
127
|
an existing `opencode.jsonc` is replaced before `opencode.json`.
|
|
128
|
+
- `--auto-configure-credentials-proxy` — Install Evident's generated `evident-*`
|
|
129
|
+
OpenCode provider entries for the runner's credential pool. This is off by default;
|
|
130
|
+
without it, the CLI only delivers `EVIDENT_PROXY_TOKEN` and leaves provider
|
|
131
|
+
configuration to you.
|
|
128
132
|
- `--credential-sync-marker <path>` — Own the interval credential sync and write
|
|
129
133
|
this marker once the shutdown flush has finished, so the runner image's lifecycle
|
|
130
134
|
hooks can wait on it.
|
package/dist/index.js
CHANGED
|
@@ -1442,7 +1442,7 @@ import ora4 from "ora";
|
|
|
1442
1442
|
import { select as select4 } from "@inquirer/prompts";
|
|
1443
1443
|
|
|
1444
1444
|
// src/lib/telemetry.ts
|
|
1445
|
-
var CLI_VERSION = (true ? "3.6.1-dev.
|
|
1445
|
+
var CLI_VERSION = (true ? "3.6.1-dev.5f836c8" : void 0) ?? process.env.npm_package_version ?? "unknown";
|
|
1446
1446
|
function getCliVersion() {
|
|
1447
1447
|
return CLI_VERSION;
|
|
1448
1448
|
}
|
|
@@ -3209,6 +3209,52 @@ async function getModelAttachmentCapability(port, model, client) {
|
|
|
3209
3209
|
return null;
|
|
3210
3210
|
}
|
|
3211
3211
|
}
|
|
3212
|
+
async function isPinnedProviderLoaded(port, model, client) {
|
|
3213
|
+
if (client?.version === "v2") return null;
|
|
3214
|
+
const { model: baseModel } = splitModelVariant(model);
|
|
3215
|
+
if (!baseModel) return null;
|
|
3216
|
+
const slash = baseModel.indexOf("/");
|
|
3217
|
+
if (slash <= 0) return null;
|
|
3218
|
+
const providerId = baseModel.slice(0, slash);
|
|
3219
|
+
try {
|
|
3220
|
+
const res = await requestWithClient(port, client, "/config/providers");
|
|
3221
|
+
if (!res.ok) {
|
|
3222
|
+
console.error(
|
|
3223
|
+
`[isPinnedProviderLoaded] GET /config/providers returned HTTP ${res.status} (port ${port})`
|
|
3224
|
+
);
|
|
3225
|
+
return null;
|
|
3226
|
+
}
|
|
3227
|
+
const body = await res.json();
|
|
3228
|
+
if (body === null || typeof body !== "object" || Array.isArray(body)) {
|
|
3229
|
+
console.error(
|
|
3230
|
+
`[isPinnedProviderLoaded] GET /config/providers body was not a plain object (port ${port})`
|
|
3231
|
+
);
|
|
3232
|
+
return null;
|
|
3233
|
+
}
|
|
3234
|
+
const providers = body.providers;
|
|
3235
|
+
if (!Array.isArray(providers)) {
|
|
3236
|
+
console.error(
|
|
3237
|
+
`[isPinnedProviderLoaded] GET /config/providers body had no providers array (port ${port})`
|
|
3238
|
+
);
|
|
3239
|
+
return null;
|
|
3240
|
+
}
|
|
3241
|
+
const providerIds = providers.filter(
|
|
3242
|
+
(provider) => provider !== null && typeof provider === "object" && typeof provider.id === "string"
|
|
3243
|
+
).map((provider) => provider.id);
|
|
3244
|
+
if (providerIds.length === 0) {
|
|
3245
|
+
console.error(
|
|
3246
|
+
`[isPinnedProviderLoaded] GET /config/providers had no provider entries with string ids (port ${port})`
|
|
3247
|
+
);
|
|
3248
|
+
return null;
|
|
3249
|
+
}
|
|
3250
|
+
return providerIds.includes(providerId);
|
|
3251
|
+
} catch (err) {
|
|
3252
|
+
console.error(
|
|
3253
|
+
`[isPinnedProviderLoaded] GET /config/providers failed (port ${port}): ${err instanceof Error ? err.message : String(err)}`
|
|
3254
|
+
);
|
|
3255
|
+
return null;
|
|
3256
|
+
}
|
|
3257
|
+
}
|
|
3212
3258
|
async function buildFileParts(attachments, capable) {
|
|
3213
3259
|
const outcomes = [];
|
|
3214
3260
|
const parts = [];
|
|
@@ -5621,7 +5667,11 @@ function isSessionDbProvenanceRecord(value) {
|
|
|
5621
5667
|
var OPENCODE2_PACKAGE_SPEC = "@opencode-ai/cli@0.0.0-beta-17823";
|
|
5622
5668
|
|
|
5623
5669
|
// src/lib/opencode/opencode-version-gate.ts
|
|
5624
|
-
var QUEUE_VALIDATED_OPENCODE_VERSIONS = [
|
|
5670
|
+
var QUEUE_VALIDATED_OPENCODE_VERSIONS = [
|
|
5671
|
+
"1.17.11",
|
|
5672
|
+
"1.18.3",
|
|
5673
|
+
"1.18.35"
|
|
5674
|
+
];
|
|
5625
5675
|
function isQueueValidatedVersion(version2) {
|
|
5626
5676
|
if (!version2) return false;
|
|
5627
5677
|
return QUEUE_VALIDATED_OPENCODE_VERSIONS.includes(version2);
|
|
@@ -8718,6 +8768,47 @@ var ChannelDriver = class _ChannelDriver {
|
|
|
8718
8768
|
agent: message.opencode_agent ?? void 0,
|
|
8719
8769
|
model: message.opencode_model ?? void 0
|
|
8720
8770
|
};
|
|
8771
|
+
const pinnedProviderLoaded = await isPinnedProviderLoaded(
|
|
8772
|
+
this.port,
|
|
8773
|
+
options.model,
|
|
8774
|
+
this.openCodeClient
|
|
8775
|
+
);
|
|
8776
|
+
if (pinnedProviderLoaded === false) {
|
|
8777
|
+
const dispatchedModel = message.opencode_model;
|
|
8778
|
+
const separator = dispatchedModel?.indexOf("/") ?? -1;
|
|
8779
|
+
const hasProviderAndModel = dispatchedModel !== null && separator > 0 && separator < dispatchedModel.length - 1;
|
|
8780
|
+
const providerId = hasProviderAndModel ? dispatchedModel.slice(0, separator) : null;
|
|
8781
|
+
const modelId = hasProviderAndModel ? dispatchedModel.slice(separator + 1) : null;
|
|
8782
|
+
const errorMessage3 = `Provider namespace not loaded on this runner: ${message.opencode_model}. Refused before dispatch; no turn was started.`;
|
|
8783
|
+
this.log({
|
|
8784
|
+
level: "error",
|
|
8785
|
+
message: `Refusing message ${message.id.slice(0, 8)} in conversation ${conv.id.slice(0, 8)}: provider namespace ${providerId ?? "(unknown)"} is not loaded; no turn was started`,
|
|
8786
|
+
conversation_id: conv.id,
|
|
8787
|
+
message_id: message.id
|
|
8788
|
+
});
|
|
8789
|
+
try {
|
|
8790
|
+
await this.markFailed(conv.id, message.id, sessionId, errorMessage3, void 0, {
|
|
8791
|
+
classification: {
|
|
8792
|
+
kind: "model_auth",
|
|
8793
|
+
providerId,
|
|
8794
|
+
modelId,
|
|
8795
|
+
reason: "missing"
|
|
8796
|
+
},
|
|
8797
|
+
errorShape: { name: null, statusCode: null }
|
|
8798
|
+
});
|
|
8799
|
+
this.signalDispatchNotStarted(conv, message, "model_provider_absent");
|
|
8800
|
+
} catch (markErr) {
|
|
8801
|
+
this.log({
|
|
8802
|
+
level: "warn",
|
|
8803
|
+
message: `markFailed PATCH for refused message ${message.id.slice(0, 8)} (conversation ${conv.id.slice(0, 8)}) failed: ${markErr instanceof Error ? markErr.message : String(markErr)}`,
|
|
8804
|
+
conversation_id: conv.id,
|
|
8805
|
+
message_id: message.id
|
|
8806
|
+
});
|
|
8807
|
+
this.signalDispatchNotStarted(conv, message, "failure_unreported");
|
|
8808
|
+
}
|
|
8809
|
+
await this.repairProviderRegistry(conv.id, message.id);
|
|
8810
|
+
break;
|
|
8811
|
+
}
|
|
8721
8812
|
let opencodeMessageId;
|
|
8722
8813
|
let preDispatchUserIds = null;
|
|
8723
8814
|
try {
|
|
@@ -13916,22 +14007,6 @@ function mergeManagedOpenCodeConfigContent(content, managedProviders) {
|
|
|
13916
14007
|
}
|
|
13917
14008
|
return JSON.stringify({ ...config, provider: { ...provider, ...managedProviders } });
|
|
13918
14009
|
}
|
|
13919
|
-
function removeManagedOpenCodeConfigContent(content) {
|
|
13920
|
-
if (!content?.trim()) return content;
|
|
13921
|
-
const config = parseConfigContent(content);
|
|
13922
|
-
if (typeof config.provider !== "object" || config.provider === null || Array.isArray(config.provider)) {
|
|
13923
|
-
return content;
|
|
13924
|
-
}
|
|
13925
|
-
const provider = { ...config.provider };
|
|
13926
|
-
let changed = false;
|
|
13927
|
-
for (const namespace of CREDENTIAL_PROXY_NATIVE_NAMESPACES) {
|
|
13928
|
-
if (namespace in provider) {
|
|
13929
|
-
delete provider[namespace];
|
|
13930
|
-
changed = true;
|
|
13931
|
-
}
|
|
13932
|
-
}
|
|
13933
|
-
return changed ? JSON.stringify({ ...config, provider }) : content;
|
|
13934
|
-
}
|
|
13935
14010
|
function isFile(filePath) {
|
|
13936
14011
|
return existsSync2(filePath) && statSync6(filePath).isFile();
|
|
13937
14012
|
}
|
|
@@ -14393,23 +14468,23 @@ async function responseJson(response) {
|
|
|
14393
14468
|
function readSetup(value) {
|
|
14394
14469
|
if (typeof value !== "object" || value === null || Array.isArray(value)) return null;
|
|
14395
14470
|
const setup = value;
|
|
14396
|
-
if (typeof setup.runner_id !== "string" || typeof setup.generation !== "string" || typeof setup.status !== "string" || setup.token_id !== null && typeof setup.token_id !== "string") {
|
|
14471
|
+
if (typeof setup.runner_id !== "string" || typeof setup.generation !== "string" || typeof setup.status !== "string" || setup.token_id !== null && typeof setup.token_id !== "string" || typeof setup.acknowledged_at !== "string" && setup.acknowledged_at !== null) {
|
|
14397
14472
|
return null;
|
|
14398
14473
|
}
|
|
14399
14474
|
return setup;
|
|
14400
14475
|
}
|
|
14401
14476
|
function clearLocalSetup(options) {
|
|
14402
14477
|
const env = options.env ?? process.env;
|
|
14403
|
-
|
|
14404
|
-
|
|
14405
|
-
|
|
14406
|
-
|
|
14407
|
-
|
|
14408
|
-
|
|
14409
|
-
}
|
|
14478
|
+
const store = options.store ?? defaultStore;
|
|
14479
|
+
const stored = store.get(options.agentId);
|
|
14480
|
+
store.clear(options.agentId);
|
|
14481
|
+
const token = env.EVIDENT_PROXY_TOKEN;
|
|
14482
|
+
if (token !== void 0 && token === stored?.token) {
|
|
14483
|
+
delete env.EVIDENT_PROXY_TOKEN;
|
|
14484
|
+
} else if (token !== void 0) {
|
|
14410
14485
|
options.log(
|
|
14411
|
-
|
|
14412
|
-
"
|
|
14486
|
+
`MANAGED-INFERENCE-CLEANUP-PRESERVED-EXTERNAL-TOKEN: runner=${options.agentId}`,
|
|
14487
|
+
"debug"
|
|
14413
14488
|
);
|
|
14414
14489
|
}
|
|
14415
14490
|
}
|
|
@@ -14435,6 +14510,25 @@ async function discoverManagedInferenceSetup(options) {
|
|
|
14435
14510
|
const setup = readSetup(body?.setup);
|
|
14436
14511
|
return setup ? { kind: "setup", setup } : { kind: "failed", reason: "Managed setup discovery returned an invalid response" };
|
|
14437
14512
|
}
|
|
14513
|
+
async function enrollManagedInferenceSetup(options) {
|
|
14514
|
+
const response = await post(options, "enroll", {});
|
|
14515
|
+
if (!response) {
|
|
14516
|
+
return { kind: "failed", reason: safeFailure("Managed credential enrollment") };
|
|
14517
|
+
}
|
|
14518
|
+
if (response.status === 404) {
|
|
14519
|
+
return { kind: "none" };
|
|
14520
|
+
}
|
|
14521
|
+
const body = await responseJson(response);
|
|
14522
|
+
if (!response.ok) {
|
|
14523
|
+
const serverError = body?.error;
|
|
14524
|
+
return {
|
|
14525
|
+
kind: "failed",
|
|
14526
|
+
reason: typeof serverError === "string" && serverError.trim() ? redactDiagnosticText(serverError).slice(0, 500) : safeFailure("Managed credential enrollment", response.status)
|
|
14527
|
+
};
|
|
14528
|
+
}
|
|
14529
|
+
const setup = readSetup(body?.setup);
|
|
14530
|
+
return setup ? { kind: "setup", setup } : { kind: "failed", reason: "Managed credential enrollment returned an invalid response" };
|
|
14531
|
+
}
|
|
14438
14532
|
async function post(options, operation, body) {
|
|
14439
14533
|
const headers = requestHeaders(options);
|
|
14440
14534
|
try {
|
|
@@ -14449,31 +14543,37 @@ async function post(options, operation, body) {
|
|
|
14449
14543
|
}
|
|
14450
14544
|
}
|
|
14451
14545
|
function applyCredential(options, credential) {
|
|
14452
|
-
const { config, unsupportedProviders } = buildCredentialProxyNativeConfig({
|
|
14453
|
-
inferenceBaseUrl: credential.inferenceBaseUrl,
|
|
14454
|
-
modelDescriptors: credential.modelDescriptors
|
|
14455
|
-
});
|
|
14456
|
-
if (unsupportedProviders.length > 0 || Object.keys(config.provider).length === 0) {
|
|
14457
|
-
return "Managed setup contains unsupported provider descriptors";
|
|
14458
|
-
}
|
|
14459
14546
|
const env = options.env ?? process.env;
|
|
14460
14547
|
let merged;
|
|
14461
|
-
|
|
14462
|
-
|
|
14463
|
-
|
|
14464
|
-
|
|
14548
|
+
if (options.autoConfigureCredentialsProxy) {
|
|
14549
|
+
const { config, unsupportedProviders } = buildCredentialProxyNativeConfig({
|
|
14550
|
+
inferenceBaseUrl: credential.inferenceBaseUrl,
|
|
14551
|
+
modelDescriptors: credential.modelDescriptors
|
|
14552
|
+
});
|
|
14553
|
+
if (unsupportedProviders.length > 0 || Object.keys(config.provider).length === 0) {
|
|
14554
|
+
return "Managed setup contains unsupported provider descriptors";
|
|
14555
|
+
}
|
|
14556
|
+
try {
|
|
14557
|
+
merged = mergeManagedOpenCodeConfigContent(env.OPENCODE_CONFIG_CONTENT, config.provider);
|
|
14558
|
+
} catch (error2) {
|
|
14559
|
+
return "OPENCODE_CONFIG_CONTENT is malformed; managed providers were not installed";
|
|
14560
|
+
}
|
|
14465
14561
|
}
|
|
14466
14562
|
try {
|
|
14467
14563
|
(options.store ?? defaultStore).set(options.agentId, credential);
|
|
14468
14564
|
} catch (error2) {
|
|
14565
|
+
const detail = (error2 instanceof Error ? error2.message : String(error2)).replaceAll(
|
|
14566
|
+
credential.token,
|
|
14567
|
+
"[redacted]"
|
|
14568
|
+
);
|
|
14469
14569
|
options.log(
|
|
14470
|
-
`MANAGED-INFERENCE-STORE-FAILED: runner=${options.agentId} generation=${credential.generation}`,
|
|
14570
|
+
`MANAGED-INFERENCE-STORE-FAILED: runner=${options.agentId} generation=${credential.generation} detail=${redactDiagnosticText(detail)}`,
|
|
14471
14571
|
"warn"
|
|
14472
14572
|
);
|
|
14473
14573
|
return "Managed credentials could not be written to the protected store";
|
|
14474
14574
|
}
|
|
14475
14575
|
env.EVIDENT_PROXY_TOKEN = credential.token;
|
|
14476
|
-
env.OPENCODE_CONFIG_CONTENT = merged;
|
|
14576
|
+
if (merged !== void 0) env.OPENCODE_CONFIG_CONTENT = merged;
|
|
14477
14577
|
return null;
|
|
14478
14578
|
}
|
|
14479
14579
|
async function reportManagedInferenceApplyFailure(options, failure) {
|
|
@@ -14524,7 +14624,7 @@ async function prepareManagedInferenceSetup(options, discovery, health) {
|
|
|
14524
14624
|
}
|
|
14525
14625
|
return reaffirmStored(options, stored);
|
|
14526
14626
|
}
|
|
14527
|
-
if (discovery.setup.
|
|
14627
|
+
if (discovery.setup.acknowledged_at !== null && stored?.generation === discovery.setup.generation && stored.tokenId === discovery.setup.token_id) {
|
|
14528
14628
|
return reaffirmStored(options, stored);
|
|
14529
14629
|
}
|
|
14530
14630
|
const response = await post(options, "bootstrap", { generation: discovery.setup.generation });
|
|
@@ -14562,7 +14662,7 @@ async function acknowledgeManagedInferenceSetup(options, preparation) {
|
|
|
14562
14662
|
const response = await post(options, "acknowledge", {
|
|
14563
14663
|
generation: preparation.generation,
|
|
14564
14664
|
token_id: preparation.tokenId,
|
|
14565
|
-
config_validated: true
|
|
14665
|
+
config_validated: options.autoConfigureCredentialsProxy === true
|
|
14566
14666
|
});
|
|
14567
14667
|
if (!response?.ok) {
|
|
14568
14668
|
throw new Error(
|
|
@@ -16365,13 +16465,17 @@ async function run(options) {
|
|
|
16365
16465
|
agentId: state.agentId,
|
|
16366
16466
|
apiUrl: getApiUrlConfig(),
|
|
16367
16467
|
getAuthHeader: () => state.authHeader,
|
|
16468
|
+
autoConfigureCredentialsProxy: options.autoConfigureCredentialsProxy,
|
|
16368
16469
|
log: (message, level = "info") => logActivity(state, {
|
|
16369
16470
|
type: level === "error" ? "error" : "info",
|
|
16370
16471
|
level,
|
|
16371
16472
|
...level === "error" ? { error: message } : { message }
|
|
16372
16473
|
})
|
|
16373
16474
|
};
|
|
16374
|
-
|
|
16475
|
+
let managedDiscovery = await discoverManagedInferenceSetup(managedSetupOptions);
|
|
16476
|
+
if (managedDiscovery.kind === "none") {
|
|
16477
|
+
managedDiscovery = await enrollManagedInferenceSetup(managedSetupOptions);
|
|
16478
|
+
}
|
|
16375
16479
|
let managedPreparation = { kind: "none" };
|
|
16376
16480
|
if (managedDiscovery.kind === "failed") {
|
|
16377
16481
|
managedPreparation = managedDiscovery;
|
|
@@ -16992,6 +17096,9 @@ program.command("run").description("Connect to Evident and process messages").op
|
|
|
16992
17096
|
).option(
|
|
16993
17097
|
"--opencode-config-overlay <path>",
|
|
16994
17098
|
"Apply this runner-provided OpenCode config before starting OpenCode."
|
|
17099
|
+
).option(
|
|
17100
|
+
"--auto-configure-credentials-proxy",
|
|
17101
|
+
"Install Evident's generated OpenCode providers for the runner's credential pool (off by default)."
|
|
16995
17102
|
).option(
|
|
16996
17103
|
"--credential-sync-marker <path>",
|
|
16997
17104
|
"Own the interval credential sync and write this marker once the shutdown flush has finished, so the runner image's lifecycle hooks can wait on it."
|
|
@@ -17035,6 +17142,7 @@ program.command("run").description("Connect to Evident and process messages").op
|
|
|
17035
17142
|
restoreSessionDb: options.restoreSessionDb,
|
|
17036
17143
|
restoreRunnerCredentials: options.restoreRunnerCredentials,
|
|
17037
17144
|
opencodeConfigOverlay: options.opencodeConfigOverlay,
|
|
17145
|
+
autoConfigureCredentialsProxy: options.autoConfigureCredentialsProxy,
|
|
17038
17146
|
credentialSyncMarker: options.credentialSyncMarker
|
|
17039
17147
|
});
|
|
17040
17148
|
}
|