Skip to content

Commit c8d7a0a

Browse files
authored
fix(sdk): code hygiene (#1357)
1 parent a138a8f commit c8d7a0a

File tree

20 files changed

+207
-62
lines changed

20 files changed

+207
-62
lines changed

.changeset/few-spies-bet.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@langchain/langgraph-sdk": patch
3+
---
4+
5+
Add missing optional peer dependency on react-dom

libs/sdk/.eslintrc.cjs

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
module.exports = {
2+
extends: [
3+
"airbnb-base",
4+
"eslint:recommended",
5+
"prettier",
6+
"plugin:@typescript-eslint/recommended",
7+
"plugin:react-hooks/recommended-legacy",
8+
],
9+
parserOptions: {
10+
ecmaVersion: 12,
11+
parser: "@typescript-eslint/parser",
12+
project: "./tsconfig.json",
13+
sourceType: "module",
14+
},
15+
plugins: ["@typescript-eslint", "no-instanceof"],
16+
ignorePatterns: [
17+
".eslintrc.cjs",
18+
"scripts",
19+
"node_modules",
20+
"dist",
21+
"dist-cjs",
22+
"*.js",
23+
"*.cjs",
24+
"*.d.ts",
25+
],
26+
rules: {
27+
"no-process-env": 2,
28+
"no-instanceof/no-instanceof": 2,
29+
"@typescript-eslint/explicit-module-boundary-types": 0,
30+
"@typescript-eslint/no-empty-function": 0,
31+
"@typescript-eslint/no-shadow": 0,
32+
"@typescript-eslint/no-empty-interface": 0,
33+
"@typescript-eslint/no-use-before-define": ["error", "nofunc"],
34+
"@typescript-eslint/no-unused-vars": ["warn", { args: "none" }],
35+
"@typescript-eslint/no-floating-promises": "error",
36+
"@typescript-eslint/no-misused-promises": "error",
37+
"arrow-body-style": 0,
38+
camelcase: 0,
39+
"class-methods-use-this": 0,
40+
"import/extensions": [2, "ignorePackages"],
41+
"import/no-extraneous-dependencies": [
42+
"error",
43+
{ devDependencies: ["**/*.test.ts", "**/*.test-d.ts"] },
44+
],
45+
"import/no-unresolved": 0,
46+
"import/prefer-default-export": 0,
47+
"keyword-spacing": "error",
48+
"max-classes-per-file": 0,
49+
"max-len": 0,
50+
"no-await-in-loop": 0,
51+
"no-bitwise": 0,
52+
"no-console": 0,
53+
"no-empty-function": 0,
54+
"no-restricted-syntax": 0,
55+
"no-shadow": 0,
56+
"no-continue": 0,
57+
"no-void": 0,
58+
"no-underscore-dangle": 0,
59+
"no-use-before-define": 0,
60+
"no-useless-constructor": 0,
61+
"no-return-await": 0,
62+
"consistent-return": 0,
63+
"no-else-return": 0,
64+
"func-names": 0,
65+
"no-lonely-if": 0,
66+
"prefer-rest-params": 0,
67+
"new-cap": ["error", { properties: false, capIsNew: false }],
68+
},
69+
overrides: [
70+
{
71+
files: ["src/tests/**/*.ts"],
72+
rules: {
73+
"no-instanceof/no-instanceof": 0,
74+
"@typescript-eslint/no-explicit-any": 0,
75+
},
76+
},
77+
],
78+
};

libs/sdk/package.json

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,11 @@
88
"build": "yarn turbo:command build:internal --filter=@langchain/langgraph-sdk",
99
"build:internal": "yarn clean && yarn lc_build --create-entrypoints --pre --tree-shaking",
1010
"prepack": "yarn run build",
11+
"format:check": "prettier --check src",
1112
"format": "prettier --write src",
12-
"lint": "prettier --check src",
13+
"lint:eslint": "NODE_OPTIONS=--max-old-space-size=4096 eslint --cache --ext .ts,.js,.jsx,.tsx src/",
14+
"lint": "yarn lint:eslint",
15+
"lint:fix": "yarn lint:eslint --fix",
1316
"test": "vitest run",
1417
"typedoc": "typedoc && typedoc src/react/index.ts --out docs/react --options typedoc.react.json && typedoc src/auth/index.ts --out docs/auth --options typedoc.auth.json"
1518
},
@@ -29,6 +32,15 @@
2932
"@types/react": "^19.0.8",
3033
"@types/react-dom": "^19.0.3",
3134
"@types/uuid": "^9.0.1",
35+
"@typescript-eslint/eslint-plugin": "^6.12.0",
36+
"@typescript-eslint/parser": "^6.12.0",
37+
"eslint": "^8.33.0",
38+
"eslint-config-airbnb-base": "^15.0.0",
39+
"eslint-config-prettier": "^8.6.0",
40+
"eslint-plugin-import": "^2.29.1",
41+
"eslint-plugin-no-instanceof": "^1.0.1",
42+
"eslint-plugin-prettier": "^4.2.1",
43+
"eslint-plugin-react-hooks": "^5.2.0",
3244
"prettier": "^2.8.3",
3345
"react": "^19.0.0",
3446
"react-dom": "^19.0.0",
@@ -37,14 +49,18 @@
3749
},
3850
"peerDependencies": {
3951
"@langchain/core": ">=0.2.31 <0.4.0",
40-
"react": "^18 || ^19"
52+
"react": "^18 || ^19",
53+
"react-dom": "^18 || ^19"
4154
},
4255
"peerDependenciesMeta": {
4356
"@langchain/core": {
4457
"optional": true
4558
},
4659
"react": {
4760
"optional": true
61+
},
62+
"react-dom": {
63+
"optional": true
4864
}
4965
},
5066
"exports": {

libs/sdk/src/auth/error.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ const HTTP_STATUS_MAPPING: { [key: number]: string } = {
6565

6666
export class HTTPException extends Error {
6767
status: number;
68+
6869
headers: HeadersInit;
6970

7071
constructor(

libs/sdk/src/auth/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import type {
99
} from "./types.js";
1010

1111
export class Auth<
12-
TExtra = {},
12+
TExtra = {}, // eslint-disable-line @typescript-eslint/ban-types
1313
TAuthReturn extends BaseAuthReturn = BaseAuthReturn,
1414
TUser extends BaseUser = ToUserLike<TAuthReturn>
1515
> {

libs/sdk/src/auth/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ interface ThreadDelete {
9898
*/
9999
interface ThreadSearch {
100100
thread_id?: Maybe<string>;
101-
status?: Maybe<"idle" | "busy" | "interrupted" | "error" | (string & {})>;
101+
status?: Maybe<"idle" | "busy" | "interrupted" | "error" | (string & {})>; // eslint-disable-line @typescript-eslint/ban-types
102102
metadata?: Maybe<Record<string, unknown>>;
103103
values?: Maybe<Record<string, unknown>>;
104104
limit?: Maybe<number>;
@@ -330,7 +330,7 @@ type CallbackParameter<
330330
Event extends string = string,
331331
Resource extends string = string,
332332
Action extends string = string,
333-
Value extends unknown = unknown,
333+
Value = unknown,
334334
TUser extends BaseUser = BaseUser
335335
> = {
336336
event: Event;

libs/sdk/src/client.ts

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ function* iterateHeaders(
4949
let iter: Iterable<(HeaderValue | HeaderValue | null[])[]>;
5050
let shouldClear = false;
5151

52+
// eslint-disable-next-line no-instanceof/no-instanceof
5253
if (headers instanceof Headers) {
5354
const entries: [string, string][] = [];
5455
headers.forEach((value, name) => {
@@ -62,7 +63,7 @@ function* iterateHeaders(
6263
iter = Object.entries(headers ?? {});
6364
}
6465

65-
for (let item of iter) {
66+
for (const item of iter) {
6667
const name = item[0];
6768
if (typeof name !== "string")
6869
throw new TypeError(
@@ -263,7 +264,7 @@ class BaseClient {
263264
for (const [key, value] of Object.entries(mutatedOptions.params)) {
264265
if (value == null) continue;
265266

266-
let strValue =
267+
const strValue =
267268
typeof value === "string" || typeof value === "number"
268269
? value.toString()
269270
: JSON.stringify(value);
@@ -345,7 +346,7 @@ export class CronsClient extends BaseClient {
345346
assistantId: string,
346347
payload?: CronsCreatePayload
347348
): Promise<CronCreateForThreadResponse> {
348-
const json: Record<string, any> = {
349+
const json: Record<string, unknown> = {
349350
schedule: payload?.schedule,
350351
input: payload?.input,
351352
config: payload?.config,
@@ -377,7 +378,7 @@ export class CronsClient extends BaseClient {
377378
assistantId: string,
378379
payload?: CronsCreatePayload
379380
): Promise<CronCreateResponse> {
380-
const json: Record<string, any> = {
381+
const json: Record<string, unknown> = {
381382
schedule: payload?.schedule,
382383
input: payload?.input,
383384
config: payload?.config,
@@ -879,7 +880,7 @@ export class ThreadsClient<
879880

880881
return this.fetch<void>(`/threads/${threadId}/state`, {
881882
method: "PATCH",
882-
json: { metadata: metadata },
883+
json: { metadata },
883884
});
884885
}
885886

@@ -973,7 +974,7 @@ export class RunsClient<
973974
TUpdateType,
974975
TCustomEventType
975976
> {
976-
const json: Record<string, any> = {
977+
const json: Record<string, unknown> = {
977978
input: payload?.input,
978979
command: payload?.command,
979980
config: payload?.config,
@@ -1011,6 +1012,7 @@ export class RunsClient<
10111012
const runMetadata = getRunMetadataFromResponse(response);
10121013
if (runMetadata) payload?.onRunCreated?.(runMetadata);
10131014

1015+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
10141016
const stream: ReadableStream<{ event: any; data: any }> = (
10151017
response.body || new ReadableStream({ start: (ctrl) => ctrl.close() })
10161018
)
@@ -1033,7 +1035,7 @@ export class RunsClient<
10331035
assistantId: string,
10341036
payload?: RunsCreatePayload
10351037
): Promise<Run> {
1036-
const json: Record<string, any> = {
1038+
const json: Record<string, unknown> = {
10371039
input: payload?.input,
10381040
command: payload?.command,
10391041
config: payload?.config,
@@ -1120,7 +1122,7 @@ export class RunsClient<
11201122
assistantId: string,
11211123
payload?: RunsWaitPayload
11221124
): Promise<ThreadState["values"]> {
1123-
const json: Record<string, any> = {
1125+
const json: Record<string, unknown> = {
11241126
input: payload?.input,
11251127
command: payload?.command,
11261128
config: payload?.config,
@@ -1239,7 +1241,7 @@ export class RunsClient<
12391241
method: "POST",
12401242
params: {
12411243
wait: wait ? "1" : "0",
1242-
action: action,
1244+
action,
12431245
},
12441246
});
12451247
}
@@ -1287,10 +1289,12 @@ export class RunsClient<
12871289
streamMode?: StreamMode | StreamMode[];
12881290
}
12891291
| AbortSignal
1292+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
12901293
): AsyncGenerator<{ id?: string; event: StreamEvent; data: any }> {
12911294
const opts =
12921295
typeof options === "object" &&
12931296
options != null &&
1297+
// eslint-disable-next-line no-instanceof/no-instanceof
12941298
options instanceof AbortSignal
12951299
? { signal: options }
12961300
: options;
@@ -1315,6 +1319,7 @@ export class RunsClient<
13151319
)
13161320
);
13171321

1322+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
13181323
const stream: ReadableStream<{ event: string; data: any }> = (
13191324
response.body || new ReadableStream({ start: (ctrl) => ctrl.close() })
13201325
)
@@ -1341,6 +1346,7 @@ export class RunsClient<
13411346
interface APIItem {
13421347
namespace: string[];
13431348
key: string;
1349+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
13441350
value: Record<string, any>;
13451351
created_at: string;
13461352
updated_at: string;
@@ -1373,7 +1379,7 @@ export class StoreClient extends BaseClient {
13731379
async putItem(
13741380
namespace: string[],
13751381
key: string,
1376-
value: Record<string, any>,
1382+
value: Record<string, unknown>,
13771383
options?: {
13781384
index?: false | string[] | null;
13791385
ttl?: number | null;
@@ -1441,7 +1447,7 @@ export class StoreClient extends BaseClient {
14411447
}
14421448
});
14431449

1444-
const params: Record<string, any> = {
1450+
const params: Record<string, unknown> = {
14451451
namespace: namespace.join("."),
14461452
key,
14471453
};
@@ -1524,7 +1530,7 @@ export class StoreClient extends BaseClient {
15241530
async searchItems(
15251531
namespacePrefix: string[],
15261532
options?: {
1527-
filter?: Record<string, any>;
1533+
filter?: Record<string, unknown>;
15281534
limit?: number;
15291535
offset?: number;
15301536
query?: string;
@@ -1603,7 +1609,7 @@ class UiClient extends BaseClient {
16031609
}
16041610

16051611
async getComponent(assistantId: string, agentName: string): Promise<string> {
1606-
return UiClient["getOrCached"](
1612+
return UiClient.getOrCached(
16071613
`${this.apiUrl}-${assistantId}-${agentName}`,
16081614
async () => {
16091615
const response = await this.asyncCaller.fetch(

libs/sdk/src/react-ui/client.tsx

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

3-
import { useStream } from "../react/index.js";
4-
import type { UIMessage } from "./types.js";
5-
63
import * as React from "react";
74
import * as ReactDOM from "react-dom";
85
import * as JsxRuntime from "react/jsx-runtime";
6+
import type { UIMessage } from "./types.js";
7+
import { useStream } from "../react/index.js";
98
import type { UseStream } from "../react/stream.js";
109

1110
const UseStreamContext = React.createContext<{
@@ -64,13 +63,15 @@ interface ComponentTarget {
6463

6564
class ComponentStore {
6665
private cache: Record<string, ComponentTarget> = {};
66+
6767
private boundCache: Record<
6868
string,
6969
{
7070
subscribe: (onStoreChange: () => void) => () => void;
7171
getSnapshot: () => ComponentTarget | undefined;
7272
}
7373
> = {};
74+
7475
private callbacks: Record<
7576
string,
7677
((
@@ -184,17 +185,18 @@ export function LoadExternalComponent({
184185
const clientComponent = components?.[message.name];
185186
const hasClientComponent = clientComponent != null;
186187

187-
const fallbackComponent = isReactNode(fallback)
188-
? fallback
189-
: typeof fallback === "object" && fallback != null
190-
? fallback?.[message.name]
191-
: null;
188+
let fallbackComponent = null;
189+
if (isReactNode(fallback)) {
190+
fallbackComponent = fallback;
191+
} else if (typeof fallback === "object" && fallback != null) {
192+
fallbackComponent = fallback?.[message.name];
193+
}
192194

193195
const uiNamespace = namespace ?? stream.assistantId;
194196
const uiClient = stream.client["~ui"];
195197
React.useEffect(() => {
196198
if (hasClientComponent) return;
197-
uiClient.getComponent(uiNamespace, message.name).then((html) => {
199+
void uiClient.getComponent(uiNamespace, message.name).then((html) => {
198200
const dom = ref.current;
199201
if (!dom) return;
200202
const root = dom.shadowRoot ?? dom.attachShadow({ mode: "open" });

libs/sdk/src/react-ui/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { bootstrapUiContext } from "./client.js";
2+
23
bootstrapUiContext();
34

45
export {

0 commit comments

Comments
 (0)