mirror of
https://github.com/cline/cline.git
synced 2026-09-19 02:05:44 +08:00
Add Client Type to Recommended Models requests (#14224)
Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
This commit is contained in:
co-authored by
Saoud Rizwan
parent
721d185485
commit
7f75100da2
@@ -1,4 +1,5 @@
|
||||
import { Readable, Writable } from "node:stream";
|
||||
import { registerClineClientIdentity } from "../utils/cline-client-identity";
|
||||
import { writeDiagnostic } from "../utils/output";
|
||||
|
||||
export interface AcpModeOptions {
|
||||
@@ -11,6 +12,8 @@ export async function runAcpMode(options?: AcpModeOptions): Promise<void> {
|
||||
);
|
||||
const { AcpAgent } = await import("./acpAgent");
|
||||
|
||||
registerClineClientIdentity("cline-acp");
|
||||
|
||||
writeDiagnostic("[acp] starting ACP mode over stdio…");
|
||||
|
||||
const stream = ndJsonStream(
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
cleanupActiveRuntime,
|
||||
isAbortInProgress,
|
||||
} from "./runtime/active-runtime";
|
||||
import { registerClineClientIdentity } from "./utils/cline-client-identity";
|
||||
import { resolveCliLaunchSpec } from "./utils/internal-launch";
|
||||
import { writeErr } from "./utils/output";
|
||||
|
||||
@@ -32,6 +33,7 @@ if (!isMainThread) {
|
||||
// daemon-hosted session spawns do not inherit it and try to become daemons.
|
||||
// The hub daemon owns its process-level abort handling. Installing the CLI's
|
||||
// fatal rejection handler first would make expected abort rejections exit it.
|
||||
registerClineClientIdentity("cline-cli");
|
||||
void import("@cline/core/hub/daemon-entry");
|
||||
} else {
|
||||
// Same reasoning as the daemon sentinel above: consume the supervised-connector
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
import { CLI_DEFAULT_CHECKPOINT_CONFIG } from "./runtime/defaults";
|
||||
import type { TuiStartupTarget } from "./tui/types";
|
||||
import { filterChatModels } from "./utils/chat-models";
|
||||
import { registerClineClientIdentity } from "./utils/cline-client-identity";
|
||||
import { getCliBuildInfo } from "./utils/common";
|
||||
import {
|
||||
buildCliCompactionConfig,
|
||||
@@ -146,6 +147,7 @@ function startupTargetTakesPrecedenceOverMigrationNotice(
|
||||
}
|
||||
|
||||
export async function runCli(): Promise<void> {
|
||||
registerClineClientIdentity("cline-cli");
|
||||
installStreamErrorGuards();
|
||||
autoUpdateOnStartup();
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import { setClineClientIdentity } from "@cline/shared";
|
||||
import { getCliBuildInfo } from "./common";
|
||||
|
||||
export function registerClineClientIdentity(name: string): void {
|
||||
const { version } = getCliBuildInfo();
|
||||
setClineClientIdentity({
|
||||
name,
|
||||
version,
|
||||
platform: "cli",
|
||||
platformVersion: version,
|
||||
});
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
import type { AgentEvent } from "@cline/core";
|
||||
import { setClineClientIdentity } from "@cline/shared";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { registerClineClientIdentity } from "./cline-client-identity";
|
||||
import {
|
||||
clearClineFreeModelCostCache,
|
||||
shouldZeroClineFreeModelCost,
|
||||
@@ -9,6 +11,7 @@ import {
|
||||
|
||||
afterEach(() => {
|
||||
clearClineFreeModelCostCache();
|
||||
setClineClientIdentity(undefined);
|
||||
vi.unstubAllGlobals();
|
||||
});
|
||||
|
||||
@@ -39,6 +42,29 @@ describe("shouldZeroClineFreeModelCost", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("identifies the CLI client on the free model request", async () => {
|
||||
const fetchMock = vi.fn(
|
||||
async (_input: Parameters<typeof fetch>[0], _init?: RequestInit) => {
|
||||
return new Response(JSON.stringify({ free: [] }), {
|
||||
status: 200,
|
||||
headers: { "content-type": "application/json" },
|
||||
});
|
||||
},
|
||||
);
|
||||
vi.stubGlobal("fetch", fetchMock);
|
||||
registerClineClientIdentity("cline-cli");
|
||||
|
||||
await shouldZeroClineFreeModelCost({
|
||||
providerId: "cline",
|
||||
modelId: "deepseek/deepseek-v4-flash",
|
||||
baseUrl: "https://cline.test/api/v1",
|
||||
});
|
||||
|
||||
expect(fetchMock.mock.calls[0]?.[1]?.headers).toMatchObject({
|
||||
"X-CLIENT-TYPE": "cline-cli",
|
||||
});
|
||||
});
|
||||
|
||||
it("matches cline-free model ids from the free endpoint bucket exactly", async () => {
|
||||
vi.stubGlobal(
|
||||
"fetch",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { AgentEvent } from "@cline/core";
|
||||
import { type AgentEvent, buildClineClientHeaders } from "@cline/core";
|
||||
import { getClineEnvironmentConfig } from "@cline/shared";
|
||||
import type { Config } from "./types";
|
||||
|
||||
@@ -37,6 +37,7 @@ async function fetchClineFreeModelIds(
|
||||
);
|
||||
try {
|
||||
const response = await fetch(resolveClineRecommendedModelsUrl(baseUrl), {
|
||||
headers: buildClineClientHeaders(),
|
||||
signal: controller.signal,
|
||||
});
|
||||
if (!response.ok) return undefined;
|
||||
|
||||
@@ -12,8 +12,10 @@ import { runRemoteHelperEntrypoint } from "@cline/core/remote/helper";
|
||||
import {
|
||||
captureSdkError,
|
||||
disableCurrentDirectoryExecutableSearch,
|
||||
setClineClientIdentity,
|
||||
} from "@cline/shared";
|
||||
import { prewarmWorkspaceMetadata } from "./chat-session";
|
||||
import { DESKTOP_CLIENT_CONTEXT } from "./client-context";
|
||||
import { configureConnectorCliLaunch } from "./connectors";
|
||||
import {
|
||||
broadcastEvent,
|
||||
@@ -236,6 +238,8 @@ async function runEntrypoint(): Promise<void> {
|
||||
runTelemetrySelfcheck();
|
||||
return;
|
||||
}
|
||||
setClineClientIdentity(DESKTOP_CLIENT_CONTEXT);
|
||||
|
||||
disableCurrentDirectoryExecutableSearch();
|
||||
if (await runRemoteHelperEntrypoint()) {
|
||||
return;
|
||||
|
||||
@@ -12,6 +12,7 @@ import { StateManager } from "./core/storage/StateManager"
|
||||
import { AgentConfigLoader } from "./core/task/tools/subagent/AgentConfigLoader"
|
||||
import { ExtensionRegistryInfo } from "./registry"
|
||||
import { registerVsCodeLmHandler } from "./sdk/vscode-lm/register-vscode-lm"
|
||||
import { registerClineClientIdentity } from "./services/ClineClientIdentity"
|
||||
import { ErrorService } from "./services/error"
|
||||
import { featureFlagsService } from "./services/feature-flags"
|
||||
import { getDistinctId } from "./services/logging/distinctId"
|
||||
@@ -63,6 +64,8 @@ export async function initialize(storageContext: StorageContext): Promise<Webvie
|
||||
})
|
||||
}
|
||||
|
||||
void registerClineClientIdentity()
|
||||
|
||||
// Register host-only SDK provider handlers (e.g. VS Code Language Model API),
|
||||
// which depend on the `vscode` module and cannot live in the SDK package.
|
||||
// Must run before any handler is built (standalone utilities or task loop).
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest"
|
||||
|
||||
const identityMocks = vi.hoisted(() => ({
|
||||
setClineClientIdentity: vi.fn(),
|
||||
}))
|
||||
|
||||
const hostState = vi.hoisted(() => ({
|
||||
hostVersion: {} as {
|
||||
platform?: string
|
||||
version?: string
|
||||
clineType?: string
|
||||
clineVersion?: string
|
||||
},
|
||||
hostVersionError: undefined as Error | undefined,
|
||||
}))
|
||||
|
||||
vi.mock("@cline/shared", () => ({
|
||||
setClineClientIdentity: identityMocks.setClineClientIdentity,
|
||||
}))
|
||||
|
||||
vi.mock("@/hosts/host-provider", () => ({
|
||||
HostProvider: {
|
||||
env: {
|
||||
getHostVersion: vi.fn(async () => {
|
||||
if (hostState.hostVersionError) {
|
||||
throw hostState.hostVersionError
|
||||
}
|
||||
return hostState.hostVersion
|
||||
}),
|
||||
},
|
||||
},
|
||||
}))
|
||||
|
||||
vi.mock("@/shared/services/Logger", () => ({
|
||||
Logger: { log: vi.fn(), error: vi.fn(), debug: vi.fn() },
|
||||
}))
|
||||
|
||||
vi.mock("@/registry", () => ({
|
||||
ExtensionRegistryInfo: { version: "9.9.9" },
|
||||
}))
|
||||
|
||||
import { registerClineClientIdentity } from "./ClineClientIdentity"
|
||||
|
||||
describe("registerClineClientIdentity", () => {
|
||||
beforeEach(() => {
|
||||
identityMocks.setClineClientIdentity.mockClear()
|
||||
hostState.hostVersionError = undefined
|
||||
hostState.hostVersion = {
|
||||
platform: "Visual Studio Code",
|
||||
version: "1.103.0",
|
||||
clineType: "VSCode Extension",
|
||||
clineVersion: "3.40.0",
|
||||
}
|
||||
})
|
||||
|
||||
it("publishes the host-reported client identity", async () => {
|
||||
await registerClineClientIdentity()
|
||||
|
||||
expect(identityMocks.setClineClientIdentity).toHaveBeenCalledWith({
|
||||
name: "VSCode Extension",
|
||||
version: "3.40.0",
|
||||
platform: "Visual Studio Code",
|
||||
platformVersion: "1.103.0",
|
||||
})
|
||||
})
|
||||
|
||||
it("falls back to the extension's own identity when the host bridge fails", async () => {
|
||||
hostState.hostVersionError = new Error("host bridge unavailable")
|
||||
|
||||
await registerClineClientIdentity()
|
||||
|
||||
expect(identityMocks.setClineClientIdentity).toHaveBeenCalledWith({
|
||||
name: "VSCode Extension",
|
||||
version: "9.9.9",
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,24 @@
|
||||
import { setClineClientIdentity } from "@cline/shared"
|
||||
import { HostProvider } from "@/hosts/host-provider"
|
||||
import { ExtensionRegistryInfo } from "@/registry"
|
||||
import { ClineClient } from "@/shared/cline"
|
||||
import { EmptyRequest } from "@/shared/proto/cline/common"
|
||||
import { Logger } from "@/shared/services/Logger"
|
||||
|
||||
export async function registerClineClientIdentity(): Promise<void> {
|
||||
try {
|
||||
const host = await HostProvider.env.getHostVersion(EmptyRequest.create({}))
|
||||
setClineClientIdentity({
|
||||
name: host.clineType || ClineClient.VSCode,
|
||||
version: host.clineVersion || ExtensionRegistryInfo.version,
|
||||
platform: host.platform || undefined,
|
||||
platformVersion: host.version || undefined,
|
||||
})
|
||||
} catch (error) {
|
||||
Logger.log("Failed to get IDE/platform info via HostBridge EnvService.getHostVersion", error)
|
||||
setClineClientIdentity({
|
||||
name: ClineClient.VSCode,
|
||||
version: ExtensionRegistryInfo.version,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ export default defineConfig({
|
||||
"src/core/controller/remoteConfig/**/*.test.ts",
|
||||
"src/core/controller/state/**/*.test.ts",
|
||||
"src/core/controller/slash/**/*.test.ts",
|
||||
"src/services/ClineClientIdentity.test.ts",
|
||||
"src/services/mcp/__tests__/settingsLock.test.ts",
|
||||
"src/shared/model-catalog/provider-helpers.test.ts",
|
||||
"src/core/controller/models/__tests__/providerCatalogHandlers.test.ts",
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
export * as Llms from "@cline/llms";
|
||||
export {
|
||||
buildClineClientHeaders,
|
||||
ClineFreeModelLimitError,
|
||||
ClineNotSubscribedError,
|
||||
ClineOrgIndividualInferenceSubscriptionError,
|
||||
|
||||
@@ -2,7 +2,8 @@ import {
|
||||
GENERATED_CLINE_RECOMMENDED_MODELS,
|
||||
getGeneratedProviderModels,
|
||||
} from "@cline/llms";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { setClineClientIdentity } from "@cline/shared";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
applyClineFeaturedModels,
|
||||
type ClineRecommendedModelsData,
|
||||
@@ -94,6 +95,10 @@ function namesOf(data: ClineRecommendedModelsData) {
|
||||
}
|
||||
|
||||
describe("fetchClineRecommendedModels", () => {
|
||||
afterEach(() => {
|
||||
setClineClientIdentity(undefined);
|
||||
});
|
||||
|
||||
it("resolves display names from the models catalog", async () => {
|
||||
const data = await fetchClineRecommendedModels({
|
||||
baseUrl: BASE_URL,
|
||||
@@ -118,6 +123,22 @@ describe("fetchClineRecommendedModels", () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it("identifies the client on the feed request", async () => {
|
||||
setClineClientIdentity({ name: "VSCode Extension", version: "3.40.0" });
|
||||
const fetchImpl = vi.fn(jsonResponse(ENDPOINT_PAYLOAD));
|
||||
|
||||
await fetchClineRecommendedModels({
|
||||
baseUrl: BASE_URL,
|
||||
fetchImpl: fetchImpl as unknown as typeof fetch,
|
||||
catalogLoader: async () => CATALOG,
|
||||
});
|
||||
|
||||
expect(fetchImpl.mock.calls[0]?.[1]?.headers).toMatchObject({
|
||||
"X-CLIENT-TYPE": "VSCode Extension",
|
||||
"X-CLIENT-VERSION": "3.40.0",
|
||||
});
|
||||
});
|
||||
|
||||
it("degrades to endpoint names and id slugs when the catalog is unavailable", async () => {
|
||||
const data = await fetchClineRecommendedModels({
|
||||
baseUrl: BASE_URL,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import {
|
||||
buildClineClientHeaders,
|
||||
GENERATED_CLINE_RECOMMENDED_MODELS,
|
||||
getGeneratedProviderModels,
|
||||
VERCEL_OPENROUTER_MODEL_ID_ALIAS_RULES,
|
||||
@@ -133,11 +134,12 @@ async function fetchWithTimeout(
|
||||
fetchImpl: typeof fetch,
|
||||
input: string,
|
||||
timeoutMs: number,
|
||||
headers: Record<string, string>,
|
||||
): Promise<Response> {
|
||||
const controller = new AbortController();
|
||||
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
||||
try {
|
||||
return await fetchImpl(input, { signal: controller.signal });
|
||||
return await fetchImpl(input, { headers, signal: controller.signal });
|
||||
} finally {
|
||||
clearTimeout(timer);
|
||||
}
|
||||
@@ -265,6 +267,7 @@ export async function fetchClineRecommendedModels(
|
||||
fetchImpl,
|
||||
`${base}/api/v1/ai/cline/recommended-models`,
|
||||
timeoutMs,
|
||||
buildClineClientHeaders(),
|
||||
);
|
||||
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
|
||||
const json: unknown = await resp.json();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { getClineEnvironmentConfig } from "@cline/shared";
|
||||
import { buildClineClientHeaders } from "../providers/cline-client-headers";
|
||||
import type { ModelInfo } from "./types";
|
||||
|
||||
export interface ClineRecommendedModelEntry {
|
||||
@@ -159,7 +160,7 @@ export async function fetchClineRecommendedModelsPayload(
|
||||
fetcher: typeof fetch = fetch,
|
||||
): Promise<ClineRecommendedModelsPayload> {
|
||||
const url = `${getClineEnvironmentConfig().apiBaseUrl}/api/v1/ai/cline/recommended-models`;
|
||||
const response = await fetcher(url);
|
||||
const response = await fetcher(url, { headers: buildClineClientHeaders() });
|
||||
if (!response.ok) {
|
||||
throw new Error(
|
||||
`Failed to load Cline recommended models from ${url}: HTTP ${response.status}`,
|
||||
|
||||
@@ -1143,6 +1143,9 @@ describe("models-dev-catalog", () => {
|
||||
expect(fetcher).toHaveBeenCalledWith("https://models.dev/api.json");
|
||||
expect(fetcher).toHaveBeenCalledWith(
|
||||
"https://api.cline.bot/api/v1/ai/cline/recommended-models",
|
||||
expect.objectContaining({
|
||||
headers: expect.objectContaining({ "X-CLIENT-TYPE": "cline-sdk" }),
|
||||
}),
|
||||
);
|
||||
expect(result.openrouter).toHaveProperty("vendor/live-base-model");
|
||||
expect(result["cline-pass"]?.["cline-pass/live-base-model"]).toMatchObject({
|
||||
|
||||
@@ -37,6 +37,7 @@ export {
|
||||
resolveProviderUsageCostDisplay,
|
||||
shouldShowProviderUsageCost,
|
||||
} from "./providers/billing";
|
||||
export { buildClineClientHeaders } from "./providers/cline-client-headers";
|
||||
export {
|
||||
type ProviderLocalCli,
|
||||
resolveProviderLocalCli,
|
||||
|
||||
@@ -106,6 +106,7 @@ export {
|
||||
resolveProviderUsageCostDisplay,
|
||||
shouldShowProviderUsageCost,
|
||||
} from "./providers/billing";
|
||||
export { buildClineClientHeaders } from "./providers/cline-client-headers";
|
||||
export type * from "./providers/gateway";
|
||||
export { createGateway, DefaultGateway } from "./providers/gateway";
|
||||
export {
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
import { getClineClientIdentity, setClineClientIdentity } from "@cline/shared";
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { buildClineClientHeaders } from "./cline-client-headers";
|
||||
|
||||
afterEach(() => {
|
||||
setClineClientIdentity(undefined);
|
||||
});
|
||||
|
||||
describe("buildClineClientHeaders", () => {
|
||||
it("falls back to the SDK client type when no identity is registered", () => {
|
||||
expect(getClineClientIdentity()).toBeUndefined();
|
||||
expect(buildClineClientHeaders()).toEqual({
|
||||
"HTTP-Referer": "https://cline.bot",
|
||||
"X-Title": "Cline",
|
||||
"X-IS-MULTIROOT": "false",
|
||||
"User-Agent": "Cline/unknown",
|
||||
"X-CLIENT-TYPE": "cline-sdk",
|
||||
"X-CLIENT-VERSION": "unknown",
|
||||
"X-PLATFORM": "cline-sdk",
|
||||
"X-PLATFORM-VERSION": "unknown",
|
||||
});
|
||||
});
|
||||
|
||||
it("stamps the registered client identity", () => {
|
||||
setClineClientIdentity({
|
||||
name: "VSCode Extension",
|
||||
version: "3.40.0",
|
||||
platform: "Visual Studio Code",
|
||||
platformVersion: "1.100.0",
|
||||
});
|
||||
|
||||
expect(buildClineClientHeaders()).toMatchObject({
|
||||
"User-Agent": "Cline/3.40.0",
|
||||
"X-CLIENT-TYPE": "VSCode Extension",
|
||||
"X-CLIENT-VERSION": "3.40.0",
|
||||
"X-PLATFORM": "Visual Studio Code",
|
||||
"X-PLATFORM-VERSION": "1.100.0",
|
||||
});
|
||||
});
|
||||
|
||||
it("ignores blank identity fields and honors an explicit override", () => {
|
||||
setClineClientIdentity({ name: " ", version: "9.9.9" });
|
||||
|
||||
expect(buildClineClientHeaders()).toMatchObject({
|
||||
"X-CLIENT-TYPE": "cline-sdk",
|
||||
"X-CLIENT-VERSION": "9.9.9",
|
||||
"X-PLATFORM": "cline-sdk",
|
||||
"X-PLATFORM-VERSION": "9.9.9",
|
||||
});
|
||||
expect(
|
||||
buildClineClientHeaders({ name: "cline-cli", version: "1.2.3" }),
|
||||
).toMatchObject({
|
||||
"X-CLIENT-TYPE": "cline-cli",
|
||||
"X-CLIENT-VERSION": "1.2.3",
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,28 @@
|
||||
import {
|
||||
type ClineClientIdentity,
|
||||
getClineClientIdentity,
|
||||
} from "@cline/shared";
|
||||
import { DEFAULT_CLINE_REQUEST_HEADERS } from "./request-headers";
|
||||
|
||||
function trimNonEmpty(value: string | undefined): string | undefined {
|
||||
const trimmed = value?.trim();
|
||||
return trimmed && trimmed.length > 0 ? trimmed : undefined;
|
||||
}
|
||||
|
||||
export function buildClineClientHeaders(
|
||||
identity: ClineClientIdentity | undefined = getClineClientIdentity(),
|
||||
): Record<string, string> {
|
||||
const clientType =
|
||||
trimNonEmpty(identity?.name) ??
|
||||
DEFAULT_CLINE_REQUEST_HEADERS["X-CLIENT-TYPE"];
|
||||
const clientVersion = trimNonEmpty(identity?.version) ?? "unknown";
|
||||
return {
|
||||
...DEFAULT_CLINE_REQUEST_HEADERS,
|
||||
"User-Agent": `Cline/${clientVersion}`,
|
||||
"X-CLIENT-TYPE": clientType,
|
||||
"X-CLIENT-VERSION": clientVersion,
|
||||
"X-PLATFORM": trimNonEmpty(identity?.platform) ?? clientType,
|
||||
"X-PLATFORM-VERSION":
|
||||
trimNonEmpty(identity?.platformVersion) ?? clientVersion,
|
||||
};
|
||||
}
|
||||
@@ -32,7 +32,7 @@ export interface ResolveProviderRequestHeadersInput {
|
||||
headers?: ProviderRequestHeaderLayers;
|
||||
}
|
||||
|
||||
const DEFAULT_CLINE_REQUEST_HEADERS: Record<string, string> = {
|
||||
export const DEFAULT_CLINE_REQUEST_HEADERS: Record<string, string> = {
|
||||
"HTTP-Referer": "https://cline.bot",
|
||||
"X-Title": "Cline",
|
||||
"X-IS-MULTIROOT": "false",
|
||||
|
||||
@@ -422,6 +422,11 @@ export {
|
||||
TEAM_LIFECYCLE_EVENT_TYPE,
|
||||
TEAM_PROGRESS_EVENT_TYPE,
|
||||
} from "./rpc/team-progress";
|
||||
export type { ClineClientIdentity } from "./runtime/cline-client-identity";
|
||||
export {
|
||||
getClineClientIdentity,
|
||||
setClineClientIdentity,
|
||||
} from "./runtime/cline-client-identity";
|
||||
export type {
|
||||
ClineEnvironment,
|
||||
ClineEnvironmentConfig,
|
||||
|
||||
@@ -484,6 +484,11 @@ export {
|
||||
resolveClineBuildEnv,
|
||||
withResolvedClineBuildEnv,
|
||||
} from "./runtime/build-env";
|
||||
export type { ClineClientIdentity } from "./runtime/cline-client-identity";
|
||||
export {
|
||||
getClineClientIdentity,
|
||||
setClineClientIdentity,
|
||||
} from "./runtime/cline-client-identity";
|
||||
export type {
|
||||
ClineEnvironment,
|
||||
ClineEnvironmentConfig,
|
||||
@@ -523,6 +528,7 @@ export type {
|
||||
CaptureAgentUnexpectedReasoningTokensInput,
|
||||
CaptureSdkErrorInput,
|
||||
CaptureTaskLifecycleEventInput,
|
||||
CoreSpawnReason,
|
||||
ITelemetryService,
|
||||
OpenTelemetryClientConfig,
|
||||
SdkTelemetryErrorComponent,
|
||||
@@ -533,11 +539,11 @@ export type {
|
||||
TelemetryPrimitive,
|
||||
TelemetryProperties,
|
||||
TelemetryValue,
|
||||
CoreSpawnReason,
|
||||
} from "./services/telemetry";
|
||||
export {
|
||||
AGENT_UNEXPECTED_REASONING_TOKENS_EVENT,
|
||||
buildSdkErrorProperties,
|
||||
CORE_SPAWN_REASONS,
|
||||
captureAgentUnexpectedReasoningTokens,
|
||||
captureSdkError,
|
||||
captureTaskLifecycleEvent,
|
||||
@@ -552,7 +558,6 @@ export {
|
||||
TASK_PROVIDER_REQUEST_STARTED_EVENT,
|
||||
TASK_PROVIDER_STREAM_FAILED_EVENT,
|
||||
TASK_PROVIDER_STREAM_STARTED_EVENT,
|
||||
CORE_SPAWN_REASONS,
|
||||
} from "./services/telemetry";
|
||||
export type { ClineTelemetryServiceConfig } from "./services/telemetry-config";
|
||||
export {
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
export interface ClineClientIdentity {
|
||||
name?: string;
|
||||
version?: string;
|
||||
platform?: string;
|
||||
platformVersion?: string;
|
||||
}
|
||||
|
||||
interface ClineClientIdentityGlobal {
|
||||
__clineClientIdentity?: ClineClientIdentity;
|
||||
}
|
||||
|
||||
function identityHolder(): ClineClientIdentityGlobal {
|
||||
return globalThis as ClineClientIdentityGlobal;
|
||||
}
|
||||
|
||||
export function setClineClientIdentity(
|
||||
identity: ClineClientIdentity | undefined,
|
||||
): void {
|
||||
identityHolder().__clineClientIdentity = identity;
|
||||
}
|
||||
|
||||
export function getClineClientIdentity(): ClineClientIdentity | undefined {
|
||||
return identityHolder().__clineClientIdentity;
|
||||
}
|
||||
Reference in New Issue
Block a user