@duckcodeailabs/dql-cli 1.7.1 → 1.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -2
- package/dist/assets/dql-notebook/assets/{index-4DbeLWHA.js → index-BgD9b9Om.js} +363 -370
- package/dist/assets/dql-notebook/index.html +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +43 -10
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +7 -4
- package/dist/commands/init.js.map +1 -1
- package/dist/local-runtime.d.ts +2 -0
- package/dist/local-runtime.d.ts.map +1 -1
- package/dist/local-runtime.js +147 -29
- package/dist/local-runtime.js.map +1 -1
- package/dist/npm-runtime.d.ts +24 -0
- package/dist/npm-runtime.d.ts.map +1 -0
- package/dist/npm-runtime.js +72 -0
- package/dist/npm-runtime.js.map +1 -0
- package/dist/package.json +10 -10
- package/dist/settings/provider-settings.d.ts +2 -0
- package/dist/settings/provider-settings.d.ts.map +1 -1
- package/dist/settings/provider-settings.js +16 -7
- package/dist/settings/provider-settings.js.map +1 -1
- package/package.json +10 -10
package/dist/local-runtime.js
CHANGED
|
@@ -4,11 +4,11 @@ import { createServer } from "node:http";
|
|
|
4
4
|
import { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, statSync, watch, writeFileSync, } from "node:fs";
|
|
5
5
|
import { createRequire } from "node:module";
|
|
6
6
|
import { homedir } from "node:os";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
7
8
|
import { dirname, extname, join, normalize, relative, resolve, } from "node:path";
|
|
8
9
|
import { Readable } from "node:stream";
|
|
9
10
|
import { buildMixedSourceWarehouseFallbackSql, findMentionedNotebookDataset, planMixedSourceNotebookSql, planMixedSourceSql, } from "./mixed-source-sql.js";
|
|
10
|
-
import
|
|
11
|
-
import OpenAI from "openai";
|
|
11
|
+
import { resolveNpmInvocation } from './npm-runtime.js';
|
|
12
12
|
import { buildExecutionPlan, createWelcomeNotebook, deserializeNotebook, getConnectorFormSchemas, hasSemanticRefs, hasStandaloneSemanticRef, resolveSemanticRefs, } from '@duckcodeailabs/dql-notebook';
|
|
13
13
|
import { loadSemanticLayerFromDir, normalizeDqlArtifactReference, serializeMetricDefinitionToYaml, resolveSemanticLayerAsync, resolveRepoSource, getDialect, Parser, NodeKind, blockParameterDefinitions, buildLineageGraph, buildManifest, collectInputFiles, findAppDocuments, findDashboardsForApp, isBlockIdRef, loadAppDocument, loadDashboardDocument, analyzeImpact, buildTrustChain, detectDomainFlows, getDomainTrustOverview, queryLineage, queryBusiness360, queryCompleteLineagePaths, LineageGraph, canonicalize, canonicalizeNotebook, diffDQL, diffNotebook, domainFolderSlug, previewModelingChange, applyModelingChange, previewDbtSourcePatch, applyDbtSourcePatch, loadDomainPackageRegistry, loadDbtNodeAuthoringDetail, relationshipValidationProofFingerprint, discoverDbtDomains, renderDomainDeclaration, ProjectSnapshotService, analyzeSqlReferences, } from '@duckcodeailabs/dql-core';
|
|
14
14
|
import { load as loadYaml } from 'js-yaml';
|
|
@@ -16,7 +16,7 @@ import { listBlockTemplates } from './block-templates.js';
|
|
|
16
16
|
import { getRunner as getLLMRunner } from './llm/index.js';
|
|
17
17
|
import { createDqlAgentProviderRunner } from './llm/providers/dql-agent-provider.js';
|
|
18
18
|
import { listRemoteMcpSettings, saveRemoteMcpSettings } from './llm/mcp-config.js';
|
|
19
|
-
import { ClaudeProvider, ConversationStore, advanceThreadState, buildConversationSnapshot, recallRelevantTurns, GeminiProvider, MemoryStore, OllamaProvider, OpenAIProvider, buildBlockBusinessFingerprint, buildBlockSqlFingerprints, buildLocalContextPack, defaultConversationPath, defaultMemoryPath, ensureDefaultMemoryFiles, ensureMetadataCatalogFresh, propose, proposePlan, recordCorrectionTrace, emitCorrectionEvalCase, mineJoinPatterns, reviewHint, AgentRunEngine, FileAgentRunStore, defaultAgentRunGates, createLlmAgentRunPlanner, createHybridRouter, computeResultStats, buildDeterministicDashboardStory, synthesizeAnswer, streamOrGenerate, narrateResult,
|
|
19
|
+
import { ClaudeProvider, ConversationStore, advanceThreadState, buildConversationSnapshot, recallRelevantTurns, GeminiProvider, MemoryStore, OllamaProvider, OpenAIProvider, buildBlockBusinessFingerprint, buildBlockSqlFingerprints, buildLocalContextPack, defaultConversationPath, defaultMemoryPath, ensureDefaultMemoryFiles, ensureMetadataCatalogFresh, propose, proposePlan, recordCorrectionTrace, emitCorrectionEvalCase, mineJoinPatterns, reviewHint, AgentRunEngine, FileAgentRunStore, defaultAgentRunGates, createLlmAgentRunPlanner, createHybridRouter, computeResultStats, buildDeterministicDashboardStory, synthesizeAnswer, streamOrGenerate, narrateResult, buildProposePreview, buildFromPrompt, defaultAgentRunStorePath, resolveLocalOwner, resolveProposeConfig, recordQueryRun, recordRuntimeSchemaSnapshot, latestRuntimeSchemaSnapshotForProject, loadSkills, migrateLegacySkills, configuredSkillsPath, skillsDir, draftDomainSkillBootstrap, buildDomainSkillBootstrapPrompt, mergeDomainSkillBootstrapEnrichment, writeSkill, deleteSkill, deriveGeneratedDraftSlug, reindexProject, invalidateAgentProjectState, resolveDomainContextEnvelope, defaultKgPath, planAppFromPrompt, KGStore, planResearch, loadSemanticMetrics, cascadeTraceToEvidenceRouteSteps, createCascadeAnswerResult, createCascadeTrace, routeReasoningEffort, routeForCascadeAnswerTier, clampReasoningEffort, bumpReasoningEffort, resolveThinkingMode, coerceThinkingMode, probeLocalOllamaEmbeddings, upsertGeneratedDqlArtifactDraft, } from '@duckcodeailabs/dql-agent';
|
|
20
20
|
import { gatherProposeEnrichment } from './propose-enrich.js';
|
|
21
21
|
import { handleAppsApi, proposeAppAiBuild, recommendVisualization } from './apps-api.js';
|
|
22
22
|
import { getActiveProvider, getEffectiveProviderConfig, isProviderSettingsId, listProviderSettings, saveProviderSettings, } from './settings/provider-settings.js';
|
|
@@ -351,6 +351,21 @@ function compactConversationRecord(record) {
|
|
|
351
351
|
function apiRequestId(scope) {
|
|
352
352
|
return `${scope}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
353
353
|
}
|
|
354
|
+
/** UI-007 / E2E-005: report the installed CLI version that owns this runtime. */
|
|
355
|
+
export function readDqlRuntimeVersion(runtimeUrl = import.meta.url) {
|
|
356
|
+
const runtimeDir = dirname(fileURLToPath(runtimeUrl));
|
|
357
|
+
for (const packagePath of [join(runtimeDir, 'package.json'), join(runtimeDir, '../package.json')]) {
|
|
358
|
+
try {
|
|
359
|
+
const parsed = JSON.parse(readFileSync(packagePath, 'utf-8'));
|
|
360
|
+
if (typeof parsed.version === 'string' && parsed.version.trim())
|
|
361
|
+
return parsed.version.trim();
|
|
362
|
+
}
|
|
363
|
+
catch {
|
|
364
|
+
// Source and published layouts place package.json at different levels.
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
return 'unknown';
|
|
368
|
+
}
|
|
354
369
|
function apiErrorEnvelope(input) {
|
|
355
370
|
return {
|
|
356
371
|
requestId: input.requestId,
|
|
@@ -377,6 +392,7 @@ export async function startLocalServer(opts) {
|
|
|
377
392
|
const bindHost = opts.host ?? process.env.DQL_HOST ?? '127.0.0.1';
|
|
378
393
|
const loopback = bindHost === '127.0.0.1' || bindHost === 'localhost' || bindHost === '::1';
|
|
379
394
|
const authToken = opts.authToken ?? process.env.DQL_SERVER_TOKEN;
|
|
395
|
+
const runtimeVersion = readDqlRuntimeVersion();
|
|
380
396
|
const allowedOrigins = new Set((opts.allowedOrigins ?? (process.env.DQL_ALLOWED_ORIGINS ?? '').split(','))
|
|
381
397
|
.map((value) => value.trim().replace(/\/$/, ''))
|
|
382
398
|
.filter(Boolean));
|
|
@@ -3409,13 +3425,42 @@ export async function startLocalServer(opts) {
|
|
|
3409
3425
|
}
|
|
3410
3426
|
if (req.method === 'GET' && path === '/api/health') {
|
|
3411
3427
|
res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });
|
|
3412
|
-
res.end(serializeJSON({ status: 'ok' }));
|
|
3428
|
+
res.end(serializeJSON({ status: 'ok', version: runtimeVersion }));
|
|
3429
|
+
return;
|
|
3430
|
+
}
|
|
3431
|
+
if (req.method === 'GET' && path === '/api/onboarding/launch') {
|
|
3432
|
+
const requestId = apiRequestId('onboarding-launch');
|
|
3433
|
+
const acknowledgedVersion = readUserPrefs(userPrefsPath).setup?.acknowledgedVersion ?? null;
|
|
3434
|
+
const shouldOpen = acknowledgedVersion !== runtimeVersion;
|
|
3435
|
+
res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });
|
|
3436
|
+
res.end(serializeJSON({
|
|
3437
|
+
requestId,
|
|
3438
|
+
version: runtimeVersion,
|
|
3439
|
+
acknowledgedVersion,
|
|
3440
|
+
shouldOpen,
|
|
3441
|
+
reason: shouldOpen ? (acknowledgedVersion ? 'version_upgrade' : 'first_install') : null,
|
|
3442
|
+
}));
|
|
3443
|
+
return;
|
|
3444
|
+
}
|
|
3445
|
+
if (req.method === 'POST' && path === '/api/onboarding/acknowledge') {
|
|
3446
|
+
const requestId = apiRequestId('onboarding-acknowledge');
|
|
3447
|
+
const prefs = readUserPrefs(userPrefsPath);
|
|
3448
|
+
prefs.setup = {
|
|
3449
|
+
acknowledgedVersion: runtimeVersion,
|
|
3450
|
+
acknowledgedAt: new Date().toISOString(),
|
|
3451
|
+
};
|
|
3452
|
+
writeUserPrefs(userPrefsPath, prefs);
|
|
3453
|
+
res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });
|
|
3454
|
+
res.end(serializeJSON({ requestId, version: runtimeVersion, acknowledged: true }));
|
|
3413
3455
|
return;
|
|
3414
3456
|
}
|
|
3415
3457
|
if (req.method === 'GET' && path === '/api/onboarding/status') {
|
|
3416
3458
|
const requestId = apiRequestId('onboarding-status');
|
|
3417
3459
|
const dbtProjectDir = findDbtProjectPath(projectRoot, projectConfig);
|
|
3418
3460
|
const manifestPath = resolve(dbtProjectDir, projectConfig.dbt?.manifestPath ?? 'target/manifest.json');
|
|
3461
|
+
const configuredDbtSource = projectConfig.dbt?.repoUrl ?? projectConfig.dbt?.projectDir;
|
|
3462
|
+
const dbtConfigured = existsSync(join(dbtProjectDir, 'dbt_project.yml'))
|
|
3463
|
+
|| Boolean(configuredDbtSource && !/\{\{[^}]+\}\}/.test(configuredDbtSource));
|
|
3419
3464
|
const configuredProfilesDir = projectConfig.dbt?.profilesDir ? resolve(projectRoot, projectConfig.dbt.profilesDir) : undefined;
|
|
3420
3465
|
const profilePath = findDbtProfilePaths(projectRoot, dbtProjectDir, configuredProfilesDir)[0];
|
|
3421
3466
|
const registry = loadDomainPackageRegistry(projectRoot);
|
|
@@ -3435,7 +3480,7 @@ export async function startLocalServer(opts) {
|
|
|
3435
3480
|
requestId,
|
|
3436
3481
|
snapshotId,
|
|
3437
3482
|
dbt: {
|
|
3438
|
-
configured:
|
|
3483
|
+
configured: dbtConfigured,
|
|
3439
3484
|
projectDir: projectConfig.dbt?.projectDir,
|
|
3440
3485
|
manifestPath: projectConfig.dbt?.manifestPath,
|
|
3441
3486
|
profilesDir: configuredProfilesDir
|
|
@@ -3765,11 +3810,64 @@ export async function startLocalServer(opts) {
|
|
|
3765
3810
|
// provenance references and the sparse DQL overlay, never copied dbt YAML.
|
|
3766
3811
|
if (req.method === 'GET' && path === '/api/modeling/dbt-first') {
|
|
3767
3812
|
const requestId = apiRequestId('modeling-dbt-first');
|
|
3768
|
-
const
|
|
3813
|
+
const modelingEnabled = projectConfig.manifestVersion === 3 && projectConfig.modeling?.mode === 'dbt-first';
|
|
3814
|
+
if (!modelingEnabled) {
|
|
3815
|
+
res.writeHead(404, { 'Content-Type': 'application/json; charset=utf-8' });
|
|
3816
|
+
res.end(serializeJSON(apiErrorEnvelope({
|
|
3817
|
+
requestId,
|
|
3818
|
+
code: 'DBT_FIRST_NOT_ENABLED',
|
|
3819
|
+
message: 'dbt-first modeling is not enabled. Connect and apply a dbt project from Settings → Project & dbt.',
|
|
3820
|
+
details: {
|
|
3821
|
+
manifestVersion: projectConfig.manifestVersion ?? 2,
|
|
3822
|
+
modelingMode: projectConfig.modeling?.mode ?? null,
|
|
3823
|
+
},
|
|
3824
|
+
nextActions: ['Open Settings → Project & dbt and apply a valid dbt project.'],
|
|
3825
|
+
})));
|
|
3826
|
+
return;
|
|
3827
|
+
}
|
|
3828
|
+
const dbtProjectDir = findDbtProjectPath(projectRoot, projectConfig);
|
|
3829
|
+
const configuredManifestPath = projectConfig.dbt?.manifestPath ?? 'target/manifest.json';
|
|
3830
|
+
const expectedManifestPath = resolve(dbtProjectDir, configuredManifestPath);
|
|
3831
|
+
if (!existsSync(expectedManifestPath)) {
|
|
3832
|
+
res.writeHead(409, { 'Content-Type': 'application/json; charset=utf-8' });
|
|
3833
|
+
res.end(serializeJSON(apiErrorEnvelope({
|
|
3834
|
+
requestId,
|
|
3835
|
+
code: 'DBT_MANIFEST_NOT_FOUND',
|
|
3836
|
+
message: `The configured dbt manifest was not found at ${configuredManifestPath}.`,
|
|
3837
|
+
details: {
|
|
3838
|
+
projectDir: projectConfig.dbt?.projectDir ?? portableProjectPath(projectRoot, dbtProjectDir),
|
|
3839
|
+
manifestPath: configuredManifestPath,
|
|
3840
|
+
},
|
|
3841
|
+
nextActions: ['Run dbt parse, dbt compile, or dbt build in the configured dbt project, then refresh Domain Studio.'],
|
|
3842
|
+
})));
|
|
3843
|
+
return;
|
|
3844
|
+
}
|
|
3845
|
+
let snapshot;
|
|
3846
|
+
try {
|
|
3847
|
+
snapshot = projectSnapshot();
|
|
3848
|
+
}
|
|
3849
|
+
catch (error) {
|
|
3850
|
+
res.writeHead(422, { 'Content-Type': 'application/json; charset=utf-8' });
|
|
3851
|
+
res.end(serializeJSON(apiErrorEnvelope({
|
|
3852
|
+
requestId,
|
|
3853
|
+
code: 'DBT_MANIFEST_COMPILE_FAILED',
|
|
3854
|
+
message: apiErrorMessage(error),
|
|
3855
|
+
details: { manifestPath: configuredManifestPath },
|
|
3856
|
+
nextActions: ['Fix or rebuild the dbt manifest, then refresh Domain Studio.'],
|
|
3857
|
+
})));
|
|
3858
|
+
return;
|
|
3859
|
+
}
|
|
3769
3860
|
const manifest = snapshot.manifest;
|
|
3770
3861
|
if (manifest.manifestVersion !== 3 || !manifest.modeling || !manifest.dbtProvenance) {
|
|
3771
|
-
res.writeHead(
|
|
3772
|
-
res.end(serializeJSON(apiErrorEnvelope({
|
|
3862
|
+
res.writeHead(422, { 'Content-Type': 'application/json; charset=utf-8' });
|
|
3863
|
+
res.end(serializeJSON(apiErrorEnvelope({
|
|
3864
|
+
requestId,
|
|
3865
|
+
snapshotId: snapshot.snapshotId,
|
|
3866
|
+
code: 'DBT_MANIFEST_COMPILE_FAILED',
|
|
3867
|
+
message: snapshot.error ?? 'DQL could not compile Domain Studio from the configured dbt manifest.',
|
|
3868
|
+
details: { manifestPath: configuredManifestPath },
|
|
3869
|
+
nextActions: ['Review the dbt artifact and DQL compile diagnostics, rebuild the dbt manifest, then refresh Domain Studio.'],
|
|
3870
|
+
})));
|
|
3773
3871
|
return;
|
|
3774
3872
|
}
|
|
3775
3873
|
res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });
|
|
@@ -10345,7 +10443,7 @@ export function resolveDefaultLLMProvider(projectRoot) {
|
|
|
10345
10443
|
const preferred = ['openai', 'gemini', 'anthropic', 'custom-openai', 'ollama'];
|
|
10346
10444
|
for (const id of preferred) {
|
|
10347
10445
|
const provider = settings.find((item) => item.id === id);
|
|
10348
|
-
if (provider?.enabled && provider.
|
|
10446
|
+
if (provider?.enabled && provider.configured)
|
|
10349
10447
|
return id;
|
|
10350
10448
|
}
|
|
10351
10449
|
return null;
|
|
@@ -11779,7 +11877,8 @@ function installConnectorPackage(projectRoot, driver) {
|
|
|
11779
11877
|
description: 'Project-local DQL connector packages',
|
|
11780
11878
|
}, null, 2) + '\n', 'utf-8');
|
|
11781
11879
|
}
|
|
11782
|
-
|
|
11880
|
+
const npm = resolveNpmInvocation();
|
|
11881
|
+
execFileSync(npm.command, [...npm.argsPrefix, 'install', '--prefix', installRoot, '--no-audit', '--no-fund', definition.packageSpec], {
|
|
11783
11882
|
cwd: projectRoot,
|
|
11784
11883
|
encoding: 'utf-8',
|
|
11785
11884
|
stdio: 'pipe',
|
|
@@ -12986,9 +13085,18 @@ function readUserPrefs(userPrefsPath) {
|
|
|
12986
13085
|
return { favorites: [], recentlyUsed: [] };
|
|
12987
13086
|
}
|
|
12988
13087
|
const raw = JSON.parse(readFileSync(userPrefsPath, 'utf-8'));
|
|
13088
|
+
const acknowledgedVersion = typeof raw.setup?.acknowledgedVersion === 'string'
|
|
13089
|
+
? raw.setup.acknowledgedVersion.trim()
|
|
13090
|
+
: '';
|
|
12989
13091
|
return {
|
|
12990
13092
|
favorites: Array.isArray(raw.favorites) ? raw.favorites.map(String) : [],
|
|
12991
13093
|
recentlyUsed: Array.isArray(raw.recentlyUsed) ? raw.recentlyUsed.map(String) : [],
|
|
13094
|
+
...(acknowledgedVersion ? {
|
|
13095
|
+
setup: {
|
|
13096
|
+
acknowledgedVersion,
|
|
13097
|
+
...(typeof raw.setup?.acknowledgedAt === 'string' ? { acknowledgedAt: raw.setup.acknowledgedAt } : {}),
|
|
13098
|
+
},
|
|
13099
|
+
} : {}),
|
|
12992
13100
|
};
|
|
12993
13101
|
}
|
|
12994
13102
|
catch {
|
|
@@ -15464,7 +15572,7 @@ async function createBlockStudioAssistProvider(projectRoot, requestedProvider) {
|
|
|
15464
15572
|
const activeProvider = getActiveProvider(projectRoot);
|
|
15465
15573
|
// Subscription CLI providers (Claude Code / Codex) carry no API key — they're
|
|
15466
15574
|
// usable when enabled; their real "installed + logged in" check runs in available().
|
|
15467
|
-
const isUsable = (provider) => provider.enabled &&
|
|
15575
|
+
const isUsable = (provider) => provider.enabled && provider.configured;
|
|
15468
15576
|
const selected = requestedProvider
|
|
15469
15577
|
? settings.find((provider) => provider.id === requestedProvider && isUsable(provider))
|
|
15470
15578
|
: settings.find((provider) => provider.id === activeProvider && provider.enabled)
|
|
@@ -17232,7 +17340,12 @@ async function readGitStatus(cwd) {
|
|
|
17232
17340
|
behind = Number(match[0] ?? 0);
|
|
17233
17341
|
ahead = Number(match[1] ?? 0);
|
|
17234
17342
|
}
|
|
17235
|
-
|
|
17343
|
+
// UI-001, E2E-001: the Source Control surface is file-oriented. Git's
|
|
17344
|
+
// "normal" untracked mode collapses a new directory into a single `?? dir/`
|
|
17345
|
+
// record, which prevents the UI from showing or diffing the files inside it.
|
|
17346
|
+
// Enumerate every untracked path so tracked and untracked changes share the
|
|
17347
|
+
// same per-file review contract.
|
|
17348
|
+
const statusRes = await execGit(gitRoot, ['status', '--porcelain=v1', '--untracked-files=all']);
|
|
17236
17349
|
const changes = [];
|
|
17237
17350
|
if (statusRes.code === 0) {
|
|
17238
17351
|
for (const line of statusRes.stdout.split('\n')) {
|
|
@@ -17884,7 +17997,11 @@ async function testProviderConfig(projectRoot, id, overrides) {
|
|
|
17884
17997
|
const base = getEffectiveProviderConfig(projectRoot, id);
|
|
17885
17998
|
// When the user supplies inline values (testing what they typed before saving),
|
|
17886
17999
|
// merge them over the saved config and test reachability regardless of enabled.
|
|
17887
|
-
|
|
18000
|
+
// The test route always passes an override object, even when every draft field
|
|
18001
|
+
// is blank. That still means "test this candidate before save" and must allow
|
|
18002
|
+
// a previously configured-but-disabled provider to be reactivated without
|
|
18003
|
+
// forcing the user to paste its redacted secret again.
|
|
18004
|
+
const inline = overrides !== undefined;
|
|
17888
18005
|
const config = {
|
|
17889
18006
|
...base,
|
|
17890
18007
|
...(overrides?.apiKey ? { apiKey: overrides.apiKey } : {}),
|
|
@@ -17964,15 +18081,19 @@ async function testOpenAIProviderConfig(config, label, details) {
|
|
|
17964
18081
|
return { ok: false, message: `${label} is not configured${details}. Add an API key in Settings or OPENAI_API_KEY.` };
|
|
17965
18082
|
}
|
|
17966
18083
|
try {
|
|
17967
|
-
|
|
17968
|
-
|
|
17969
|
-
|
|
17970
|
-
|
|
17971
|
-
|
|
18084
|
+
// Use the same provider adapter as governed Ask so enterprise gateways are
|
|
18085
|
+
// tested against the runtime path users will actually execute.
|
|
18086
|
+
const provider = new OpenAIProvider({
|
|
18087
|
+
apiKey: config.apiKey,
|
|
18088
|
+
baseUrl: config.baseUrl,
|
|
18089
|
+
model: config.model,
|
|
17972
18090
|
});
|
|
18091
|
+
const response = await provider.generate([
|
|
18092
|
+
{ role: 'user', content: 'Reply with exactly: OK' },
|
|
18093
|
+
], { maxTokens: 16, temperature: 0 });
|
|
17973
18094
|
return {
|
|
17974
18095
|
ok: true,
|
|
17975
|
-
message: `${label}
|
|
18096
|
+
message: `${label} responded through the governed runtime${details}: ${response.trim().slice(0, 80) || 'OK'}`,
|
|
17976
18097
|
};
|
|
17977
18098
|
}
|
|
17978
18099
|
catch (error) {
|
|
@@ -17987,20 +18108,17 @@ async function testAnthropicProviderConfig(config, label, details) {
|
|
|
17987
18108
|
return { ok: false, message: `${label} is not configured${details}. Add an API key in Settings or ANTHROPIC_API_KEY.` };
|
|
17988
18109
|
}
|
|
17989
18110
|
try {
|
|
17990
|
-
const
|
|
18111
|
+
const provider = new ClaudeProvider({
|
|
17991
18112
|
apiKey: config.apiKey,
|
|
17992
|
-
|
|
18113
|
+
baseUrl: config.baseUrl,
|
|
18114
|
+
model: config.model,
|
|
17993
18115
|
});
|
|
17994
|
-
const response = await
|
|
17995
|
-
|
|
17996
|
-
|
|
17997
|
-
temperature: 0,
|
|
17998
|
-
messages: [{ role: 'user', content: 'Reply with exactly: OK' }],
|
|
17999
|
-
});
|
|
18000
|
-
const text = response.content?.filter((block) => block.type === 'text').map((block) => block.text ?? '').join('') ?? '';
|
|
18116
|
+
const response = await provider.generate([
|
|
18117
|
+
{ role: 'user', content: 'Reply with exactly: OK' },
|
|
18118
|
+
], { maxTokens: 16, temperature: 0 });
|
|
18001
18119
|
return {
|
|
18002
18120
|
ok: true,
|
|
18003
|
-
message: `${label}
|
|
18121
|
+
message: `${label} responded through the governed runtime${details}: ${response.trim().slice(0, 80) || 'OK'}`,
|
|
18004
18122
|
};
|
|
18005
18123
|
}
|
|
18006
18124
|
catch (error) {
|