Skip to content

Commit c7fc91c

Browse files
committed
fix(react): Add support for Cloud headers and API keys
1 parent c28848b commit c7fc91c

File tree

1 file changed

+44
-15
lines changed

1 file changed

+44
-15
lines changed

packages/react/src/providers/CopilotKitProvider.tsx

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,6 @@
11
"use client";
22

3-
import React, {
4-
createContext,
5-
useContext,
6-
ReactNode,
7-
useMemo,
8-
useEffect,
9-
useReducer,
10-
useRef,
11-
useState,
12-
} from "react";
3+
import React, { createContext, useContext, ReactNode, useMemo, useEffect, useReducer, useRef, useState } from "react";
134
import { ReactActivityMessageRenderer, ReactToolCallRenderer } from "../types";
145
import { ReactCustomMessageRenderer } from "../types/react-custom-message-renderer";
156
import { ReactFrontendTool } from "../types/frontend-tool";
@@ -20,6 +11,9 @@ import { AbstractAgent } from "@ag-ui/client";
2011
import { CopilotKitCoreReact } from "../lib/react-core";
2112
import { CopilotKitInspector } from "../components/CopilotKitInspector";
2213

14+
const HEADER_NAME = "X-CopilotCloud-Public-Api-Key";
15+
const COPILOT_CLOUD_CHAT_URL = "https://api.cloud.copilotkit.ai/copilotkit/v1";
16+
2317
// Define the context value interface - idiomatic React naming
2418
export interface CopilotKitContextValue {
2519
copilotkit: CopilotKitCoreReact;
@@ -35,6 +29,14 @@ export interface CopilotKitProviderProps {
3529
children: ReactNode;
3630
runtimeUrl?: string;
3731
headers?: Record<string, string>;
32+
/**
33+
* The Copilot Cloud public API key.
34+
*/
35+
publicApiKey?: string;
36+
/**
37+
* Alias for `publicApiKey`
38+
**/
39+
publicLicenseKey?: string;
3840
properties?: Record<string, unknown>;
3941
useSingleEndpoint?: boolean;
4042
agents__unsafe_dev_only?: Record<string, AbstractAgent>;
@@ -74,6 +76,8 @@ export const CopilotKitProvider: React.FC<CopilotKitProviderProps> = ({
7476
children,
7577
runtimeUrl,
7678
headers = {},
79+
publicApiKey,
80+
publicLicenseKey,
7781
properties = {},
7882
agents__unsafe_dev_only: agents = {},
7983
renderToolCalls,
@@ -135,6 +139,31 @@ export const CopilotKitProvider: React.FC<CopilotKitProviderProps> = ({
135139
"renderActivityMessages must be a stable array.",
136140
);
137141

142+
const resolvedPublicKey = publicApiKey ?? publicLicenseKey;
143+
const hasLocalAgents = agents && Object.keys(agents).length > 0;
144+
145+
// Merge a provided publicApiKey into headers (without overwriting an explicit header).
146+
const mergedHeaders = useMemo(() => {
147+
if (!resolvedPublicKey) return headers;
148+
if (headers[HEADER_NAME]) return headers;
149+
return {
150+
...headers,
151+
[HEADER_NAME]: resolvedPublicKey,
152+
};
153+
}, [headers, resolvedPublicKey]);
154+
155+
if (!runtimeUrl && !resolvedPublicKey && !hasLocalAgents) {
156+
const message = "Missing required prop: 'runtimeUrl' or 'publicApiKey' or 'publicLicenseKey'";
157+
if (process.env.NODE_ENV === "production") {
158+
throw new Error(message);
159+
} else {
160+
// In dev/test we warn but allow to facilitate local agents and unit tests.
161+
console.warn(message);
162+
}
163+
}
164+
165+
const chatApiEndpoint = runtimeUrl ?? (resolvedPublicKey ? COPILOT_CLOUD_CHAT_URL : undefined);
166+
138167
const frontendToolsList = useStableArrayProp<ReactFrontendTool>(
139168
frontendTools,
140169
"frontendTools must be a stable array. If you want to dynamically add or remove tools, use `useFrontendTool` instead.",
@@ -226,9 +255,9 @@ export const CopilotKitProvider: React.FC<CopilotKitProviderProps> = ({
226255

227256
const copilotkit = useMemo(() => {
228257
const copilotkit = new CopilotKitCoreReact({
229-
runtimeUrl,
258+
runtimeUrl: chatApiEndpoint,
230259
runtimeTransport: useSingleEndpoint ? "single" : "rest",
231-
headers,
260+
headers: mergedHeaders,
232261
properties,
233262
agents__unsafe_dev_only: agents,
234263
tools: allTools,
@@ -257,12 +286,12 @@ export const CopilotKitProvider: React.FC<CopilotKitProviderProps> = ({
257286
}, [copilotkit]);
258287

259288
useEffect(() => {
260-
copilotkit.setRuntimeUrl(runtimeUrl);
289+
copilotkit.setRuntimeUrl(chatApiEndpoint);
261290
copilotkit.setRuntimeTransport(useSingleEndpoint ? "single" : "rest");
262-
copilotkit.setHeaders(headers);
291+
copilotkit.setHeaders(mergedHeaders);
263292
copilotkit.setProperties(properties);
264293
copilotkit.setAgents__unsafe_dev_only(agents);
265-
}, [runtimeUrl, headers, properties, agents, useSingleEndpoint]);
294+
}, [chatApiEndpoint, mergedHeaders, properties, agents, useSingleEndpoint]);
266295

267296
return (
268297
<CopilotKitContext.Provider

0 commit comments

Comments
 (0)