@copilotkit/runtime 1.6.0 → 1.7.0-next.0
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/CHANGELOG.md +21 -0
- package/dist/{chunk-MPI4JZZR.mjs → chunk-2BN7NZNC.mjs} +2 -2
- package/dist/{chunk-DUW72ZZB.mjs → chunk-34Y5DNNJ.mjs} +88 -67
- package/dist/chunk-34Y5DNNJ.mjs.map +1 -0
- package/dist/{chunk-WUMAYJP3.mjs → chunk-PH24IU7T.mjs} +2 -2
- package/dist/{chunk-2RP2NR4F.mjs → chunk-ZYFN76KV.mjs} +2 -2
- package/dist/index.js +87 -66
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +4 -4
- package/dist/lib/index.js +87 -66
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/index.mjs +4 -4
- package/dist/lib/integrations/index.js +4 -1
- package/dist/lib/integrations/index.js.map +1 -1
- package/dist/lib/integrations/index.mjs +4 -4
- package/dist/lib/integrations/nest/index.js +4 -1
- package/dist/lib/integrations/nest/index.js.map +1 -1
- package/dist/lib/integrations/nest/index.mjs +2 -2
- package/dist/lib/integrations/node-express/index.js +4 -1
- package/dist/lib/integrations/node-express/index.js.map +1 -1
- package/dist/lib/integrations/node-express/index.mjs +2 -2
- package/dist/lib/integrations/node-http/index.js +4 -1
- package/dist/lib/integrations/node-http/index.js.map +1 -1
- package/dist/lib/integrations/node-http/index.mjs +1 -1
- package/package.json +2 -2
- package/src/graphql/resolvers/copilot.resolver.ts +4 -0
- package/src/lib/runtime/__tests__/remote-action-constructors.test.ts +45 -35
- package/src/lib/runtime/copilot-runtime.ts +14 -14
- package/src/lib/runtime/remote-action-constructors.ts +28 -68
- package/src/lib/runtime/remote-actions.ts +5 -5
- package/src/lib/streaming.ts +59 -0
- package/src/service-adapters/events.ts +3 -3
- package/dist/chunk-DUW72ZZB.mjs.map +0 -1
- /package/dist/{chunk-MPI4JZZR.mjs.map → chunk-2BN7NZNC.mjs.map} +0 -0
- /package/dist/{chunk-WUMAYJP3.mjs.map → chunk-PH24IU7T.mjs.map} +0 -0
- /package/dist/{chunk-2RP2NR4F.mjs.map → chunk-ZYFN76KV.mjs.map} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @copilotkit/runtime
|
|
2
2
|
|
|
3
|
+
## 1.7.0-next.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 082db7a: - CrewAI support
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- 082db7a: - Added RemoteAgentAdapter and implemented CopilotKit (protocol & events).
|
|
12
|
+
- Integrated CrewAI (with a prototype, HITL, event system, and chat/demo tweaks).
|
|
13
|
+
- Updated docs and cleaned up code (fixing stdout issues, restricting Python version, and streamlining demos).
|
|
14
|
+
- @copilotkit/shared@1.7.0-next.0
|
|
15
|
+
|
|
3
16
|
## 1.6.0
|
|
4
17
|
|
|
5
18
|
### Minor Changes
|
|
@@ -24,6 +37,14 @@
|
|
|
24
37
|
- Updated dependencies [090203d]
|
|
25
38
|
- @copilotkit/shared@1.6.0
|
|
26
39
|
|
|
40
|
+
## 1.6.0-next.12
|
|
41
|
+
|
|
42
|
+
### Patch Changes
|
|
43
|
+
|
|
44
|
+
- 1bb9ca2: - fix(coagents): don't fail when LangSmith API key is missing
|
|
45
|
+
- fix(coagents): don't check for langsmithApiKey in resolveEndpointType
|
|
46
|
+
- @copilotkit/shared@1.6.0-next.12
|
|
47
|
+
|
|
27
48
|
## 1.6.0-next.11
|
|
28
49
|
|
|
29
50
|
### Patch Changes
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
copilotRuntimeNodeHttpEndpoint,
|
|
3
3
|
getRuntimeInstanceTelemetryInfo,
|
|
4
4
|
telemetry_client_default
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-34Y5DNNJ.mjs";
|
|
6
6
|
import {
|
|
7
7
|
__name
|
|
8
8
|
} from "./chunk-FHD4JECV.mjs";
|
|
@@ -22,4 +22,4 @@ __name(copilotRuntimeNestEndpoint, "copilotRuntimeNestEndpoint");
|
|
|
22
22
|
export {
|
|
23
23
|
copilotRuntimeNestEndpoint
|
|
24
24
|
};
|
|
25
|
-
//# sourceMappingURL=chunk-
|
|
25
|
+
//# sourceMappingURL=chunk-2BN7NZNC.mjs.map
|
|
@@ -39,7 +39,7 @@ var require_package = __commonJS({
|
|
|
39
39
|
publishConfig: {
|
|
40
40
|
access: "public"
|
|
41
41
|
},
|
|
42
|
-
version: "1.
|
|
42
|
+
version: "1.7.0-next.0",
|
|
43
43
|
sideEffects: false,
|
|
44
44
|
main: "./dist/index.js",
|
|
45
45
|
module: "./dist/index.mjs",
|
|
@@ -1815,7 +1815,7 @@ async function streamEvents(controller, args) {
|
|
|
1815
1815
|
let emitIntermediateStateUntilEnd = null;
|
|
1816
1816
|
let shouldExit = false;
|
|
1817
1817
|
let externalRunId = null;
|
|
1818
|
-
const
|
|
1818
|
+
const streamResponse = client.runs.stream(threadId, assistantId, payload);
|
|
1819
1819
|
const emit = /* @__PURE__ */ __name((message) => controller.enqueue(new TextEncoder().encode(message)), "emit");
|
|
1820
1820
|
let latestStateValues = {};
|
|
1821
1821
|
let updatedState = state;
|
|
@@ -1825,7 +1825,7 @@ async function streamEvents(controller, args) {
|
|
|
1825
1825
|
telemetry_client_default.capture("oss.runtime.agent_execution_stream_started", {
|
|
1826
1826
|
hashedLgcKey: streamInfo.hashedLgcKey
|
|
1827
1827
|
});
|
|
1828
|
-
for await (const chunk of
|
|
1828
|
+
for await (const chunk of streamResponse) {
|
|
1829
1829
|
if (![
|
|
1830
1830
|
"events",
|
|
1831
1831
|
"values",
|
|
@@ -2240,6 +2240,54 @@ __name(getSchemaKeys, "getSchemaKeys");
|
|
|
2240
2240
|
|
|
2241
2241
|
// src/lib/runtime/remote-action-constructors.ts
|
|
2242
2242
|
import { CopilotKitError, CopilotKitLowLevelError } from "@copilotkit/shared";
|
|
2243
|
+
|
|
2244
|
+
// src/lib/streaming.ts
|
|
2245
|
+
async function writeJsonLineResponseToEventStream(response, eventStream$) {
|
|
2246
|
+
const reader = response.getReader();
|
|
2247
|
+
const decoder = new TextDecoder();
|
|
2248
|
+
let buffer = [];
|
|
2249
|
+
function flushBuffer() {
|
|
2250
|
+
const currentBuffer = buffer.join("");
|
|
2251
|
+
if (currentBuffer.trim().length === 0) {
|
|
2252
|
+
return;
|
|
2253
|
+
}
|
|
2254
|
+
const parts = currentBuffer.split("\n");
|
|
2255
|
+
if (parts.length === 0) {
|
|
2256
|
+
return;
|
|
2257
|
+
}
|
|
2258
|
+
const lastPartIsComplete = currentBuffer.endsWith("\n");
|
|
2259
|
+
buffer = [];
|
|
2260
|
+
if (!lastPartIsComplete) {
|
|
2261
|
+
buffer.push(parts.pop());
|
|
2262
|
+
}
|
|
2263
|
+
parts.map((part) => part.trim()).filter((part) => part != "").forEach((part) => {
|
|
2264
|
+
eventStream$.next(JSON.parse(part));
|
|
2265
|
+
});
|
|
2266
|
+
}
|
|
2267
|
+
__name(flushBuffer, "flushBuffer");
|
|
2268
|
+
try {
|
|
2269
|
+
while (true) {
|
|
2270
|
+
const { done, value } = await reader.read();
|
|
2271
|
+
if (!done) {
|
|
2272
|
+
buffer.push(decoder.decode(value, {
|
|
2273
|
+
stream: true
|
|
2274
|
+
}));
|
|
2275
|
+
}
|
|
2276
|
+
flushBuffer();
|
|
2277
|
+
if (done) {
|
|
2278
|
+
break;
|
|
2279
|
+
}
|
|
2280
|
+
}
|
|
2281
|
+
} catch (error) {
|
|
2282
|
+
console.error("Error in stream", error);
|
|
2283
|
+
eventStream$.error(error);
|
|
2284
|
+
return;
|
|
2285
|
+
}
|
|
2286
|
+
eventStream$.complete();
|
|
2287
|
+
}
|
|
2288
|
+
__name(writeJsonLineResponseToEventStream, "writeJsonLineResponseToEventStream");
|
|
2289
|
+
|
|
2290
|
+
// src/lib/runtime/remote-action-constructors.ts
|
|
2243
2291
|
import { CopilotKitApiDiscoveryError, ResolvedCopilotKitError } from "@copilotkit/shared";
|
|
2244
2292
|
import { parseJson as parseJson2, tryMap } from "@copilotkit/shared";
|
|
2245
2293
|
function constructLGCRemoteAction({ endpoint, graphqlContext, logger: logger2, messages, agentStates }) {
|
|
@@ -2249,7 +2297,7 @@ function constructLGCRemoteAction({ endpoint, graphqlContext, logger: logger2, m
|
|
|
2249
2297
|
parameters: [],
|
|
2250
2298
|
handler: async (_args) => {
|
|
2251
2299
|
},
|
|
2252
|
-
|
|
2300
|
+
remoteAgentHandler: async ({ name, actionInputsWithoutAgents, threadId, nodeName, additionalMessages = [], metaEvents }) => {
|
|
2253
2301
|
logger2.debug({
|
|
2254
2302
|
actionName: agent.name
|
|
2255
2303
|
}, "Executing LangGraph Platform agent");
|
|
@@ -2293,7 +2341,7 @@ function constructLGCRemoteAction({ endpoint, graphqlContext, logger: logger2, m
|
|
|
2293
2341
|
metaEvents
|
|
2294
2342
|
});
|
|
2295
2343
|
const eventSource = new RemoteLangGraphEventSource();
|
|
2296
|
-
|
|
2344
|
+
writeJsonLineResponseToEventStream(response, eventSource.eventStream$);
|
|
2297
2345
|
return eventSource.processLangGraphEvents();
|
|
2298
2346
|
} catch (error) {
|
|
2299
2347
|
logger2.error({
|
|
@@ -2310,6 +2358,11 @@ function constructLGCRemoteAction({ endpoint, graphqlContext, logger: logger2, m
|
|
|
2310
2358
|
];
|
|
2311
2359
|
}
|
|
2312
2360
|
__name(constructLGCRemoteAction, "constructLGCRemoteAction");
|
|
2361
|
+
var RemoteAgentType;
|
|
2362
|
+
(function(RemoteAgentType2) {
|
|
2363
|
+
RemoteAgentType2["LangGraph"] = "langgraph";
|
|
2364
|
+
RemoteAgentType2["CrewAI"] = "crewai";
|
|
2365
|
+
})(RemoteAgentType || (RemoteAgentType = {}));
|
|
2313
2366
|
function constructRemoteActions({ json, url, onBeforeRequest, graphqlContext, logger: logger2, messages, agentStates }) {
|
|
2314
2367
|
const totalAgents = Array.isArray(json["agents"]) ? json["agents"].length : 0;
|
|
2315
2368
|
const actions = json["actions"].map((action) => ({
|
|
@@ -2379,7 +2432,7 @@ function constructRemoteActions({ json, url, onBeforeRequest, graphqlContext, lo
|
|
|
2379
2432
|
parameters: [],
|
|
2380
2433
|
handler: async (_args) => {
|
|
2381
2434
|
},
|
|
2382
|
-
|
|
2435
|
+
remoteAgentHandler: async ({ name, actionInputsWithoutAgents, threadId, nodeName, additionalMessages = [], metaEvents }) => {
|
|
2383
2436
|
logger2.debug({
|
|
2384
2437
|
actionName: agent.name
|
|
2385
2438
|
}, "Executing remote agent");
|
|
@@ -2439,9 +2492,17 @@ function constructRemoteActions({ json, url, onBeforeRequest, graphqlContext, lo
|
|
|
2439
2492
|
isRemoteEndpoint: true
|
|
2440
2493
|
});
|
|
2441
2494
|
}
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2495
|
+
if (agent.type === "langgraph") {
|
|
2496
|
+
const eventSource = new RemoteLangGraphEventSource();
|
|
2497
|
+
writeJsonLineResponseToEventStream(response.body, eventSource.eventStream$);
|
|
2498
|
+
return eventSource.processLangGraphEvents();
|
|
2499
|
+
} else if (agent.type === "crewai") {
|
|
2500
|
+
const eventStream$ = new RuntimeEventSubject();
|
|
2501
|
+
writeJsonLineResponseToEventStream(response.body, eventStream$);
|
|
2502
|
+
return eventStream$;
|
|
2503
|
+
} else {
|
|
2504
|
+
throw new Error("Unsupported agent type");
|
|
2505
|
+
}
|
|
2445
2506
|
} catch (error) {
|
|
2446
2507
|
if (error instanceof CopilotKitError) {
|
|
2447
2508
|
throw error;
|
|
@@ -2459,50 +2520,6 @@ function constructRemoteActions({ json, url, onBeforeRequest, graphqlContext, lo
|
|
|
2459
2520
|
];
|
|
2460
2521
|
}
|
|
2461
2522
|
__name(constructRemoteActions, "constructRemoteActions");
|
|
2462
|
-
async function streamResponse(response, eventStream$) {
|
|
2463
|
-
const reader = response.getReader();
|
|
2464
|
-
const decoder = new TextDecoder();
|
|
2465
|
-
let buffer = [];
|
|
2466
|
-
function flushBuffer() {
|
|
2467
|
-
const currentBuffer = buffer.join("");
|
|
2468
|
-
if (currentBuffer.trim().length === 0) {
|
|
2469
|
-
return;
|
|
2470
|
-
}
|
|
2471
|
-
const parts = currentBuffer.split("\n");
|
|
2472
|
-
if (parts.length === 0) {
|
|
2473
|
-
return;
|
|
2474
|
-
}
|
|
2475
|
-
const lastPartIsComplete = currentBuffer.endsWith("\n");
|
|
2476
|
-
buffer = [];
|
|
2477
|
-
if (!lastPartIsComplete) {
|
|
2478
|
-
buffer.push(parts.pop());
|
|
2479
|
-
}
|
|
2480
|
-
parts.map((part) => part.trim()).filter((part) => part != "").forEach((part) => {
|
|
2481
|
-
eventStream$.next(JSON.parse(part));
|
|
2482
|
-
});
|
|
2483
|
-
}
|
|
2484
|
-
__name(flushBuffer, "flushBuffer");
|
|
2485
|
-
try {
|
|
2486
|
-
while (true) {
|
|
2487
|
-
const { done, value } = await reader.read();
|
|
2488
|
-
if (!done) {
|
|
2489
|
-
buffer.push(decoder.decode(value, {
|
|
2490
|
-
stream: true
|
|
2491
|
-
}));
|
|
2492
|
-
}
|
|
2493
|
-
flushBuffer();
|
|
2494
|
-
if (done) {
|
|
2495
|
-
break;
|
|
2496
|
-
}
|
|
2497
|
-
}
|
|
2498
|
-
} catch (error) {
|
|
2499
|
-
console.error("Error in stream", error);
|
|
2500
|
-
eventStream$.error(error);
|
|
2501
|
-
return;
|
|
2502
|
-
}
|
|
2503
|
-
eventStream$.complete();
|
|
2504
|
-
}
|
|
2505
|
-
__name(streamResponse, "streamResponse");
|
|
2506
2523
|
function createHeaders(onBeforeRequest, graphqlContext) {
|
|
2507
2524
|
const headers = {
|
|
2508
2525
|
"Content-Type": "application/json"
|
|
@@ -2526,13 +2543,13 @@ var EndpointType;
|
|
|
2526
2543
|
EndpointType2["CopilotKit"] = "copilotKit";
|
|
2527
2544
|
EndpointType2["LangGraphPlatform"] = "langgraph-platform";
|
|
2528
2545
|
})(EndpointType || (EndpointType = {}));
|
|
2529
|
-
function
|
|
2546
|
+
function isRemoteAgentAction(action) {
|
|
2530
2547
|
if (!action) {
|
|
2531
2548
|
return false;
|
|
2532
2549
|
}
|
|
2533
|
-
return typeof action.
|
|
2550
|
+
return typeof action.remoteAgentHandler === "function";
|
|
2534
2551
|
}
|
|
2535
|
-
__name(
|
|
2552
|
+
__name(isRemoteAgentAction, "isRemoteAgentAction");
|
|
2536
2553
|
async function fetchRemoteInfo({ url, onBeforeRequest, graphqlContext, logger: logger2, frontendUrl }) {
|
|
2537
2554
|
logger2.debug({
|
|
2538
2555
|
url
|
|
@@ -2794,7 +2811,6 @@ please use an LLM adapter instead.`
|
|
|
2794
2811
|
}
|
|
2795
2812
|
}
|
|
2796
2813
|
async discoverAgentsFromEndpoints(graphqlContext) {
|
|
2797
|
-
const headers = createHeaders(null, graphqlContext);
|
|
2798
2814
|
const agents = this.remoteEndpointDefinitions.reduce(async (acc, endpoint) => {
|
|
2799
2815
|
const agents2 = await acc;
|
|
2800
2816
|
if (endpoint.type === EndpointType.LangGraphPlatform) {
|
|
@@ -2820,11 +2836,12 @@ please use an LLM adapter instead.`
|
|
|
2820
2836
|
...endpointAgents
|
|
2821
2837
|
];
|
|
2822
2838
|
}
|
|
2839
|
+
const cpkEndpoint = endpoint;
|
|
2823
2840
|
const fetchUrl = `${endpoint.url}/info`;
|
|
2824
2841
|
try {
|
|
2825
2842
|
const response = await fetch(fetchUrl, {
|
|
2826
2843
|
method: "POST",
|
|
2827
|
-
headers,
|
|
2844
|
+
headers: createHeaders(cpkEndpoint.onBeforeRequest, graphqlContext),
|
|
2828
2845
|
body: JSON.stringify({
|
|
2829
2846
|
properties: graphqlContext.properties
|
|
2830
2847
|
})
|
|
@@ -2905,11 +2922,12 @@ please use an LLM adapter instead.`
|
|
|
2905
2922
|
};
|
|
2906
2923
|
}
|
|
2907
2924
|
} else if (agentWithEndpoint.endpoint.type === EndpointType.CopilotKit || !("type" in agentWithEndpoint.endpoint)) {
|
|
2908
|
-
const
|
|
2925
|
+
const cpkEndpoint = agentWithEndpoint.endpoint;
|
|
2926
|
+
const fetchUrl = `${cpkEndpoint.url}/agents/state`;
|
|
2909
2927
|
try {
|
|
2910
2928
|
const response = await fetch(fetchUrl, {
|
|
2911
2929
|
method: "POST",
|
|
2912
|
-
headers,
|
|
2930
|
+
headers: createHeaders(cpkEndpoint.onBeforeRequest, graphqlContext),
|
|
2913
2931
|
body: JSON.stringify({
|
|
2914
2932
|
properties: graphqlContext.properties,
|
|
2915
2933
|
threadId,
|
|
@@ -2954,7 +2972,7 @@ please use an LLM adapter instead.`
|
|
|
2954
2972
|
const threadId = threadIdFromRequest ?? agentSession.threadId;
|
|
2955
2973
|
const serverSideActions = await this.getServerSideActions(request);
|
|
2956
2974
|
const messages = convertGqlInputToMessages(rawMessages);
|
|
2957
|
-
const currentAgent = serverSideActions.find((action) => action.name === agentName &&
|
|
2975
|
+
const currentAgent = serverSideActions.find((action) => action.name === agentName && isRemoteAgentAction(action));
|
|
2958
2976
|
if (!currentAgent) {
|
|
2959
2977
|
throw new CopilotKitAgentDiscoveryError({
|
|
2960
2978
|
agentName
|
|
@@ -2962,8 +2980,8 @@ please use an LLM adapter instead.`
|
|
|
2962
2980
|
}
|
|
2963
2981
|
const availableActionsForCurrentAgent = serverSideActions.filter((action) => (
|
|
2964
2982
|
// Case 1: Keep all regular (non-agent) actions
|
|
2965
|
-
!
|
|
2966
|
-
|
|
2983
|
+
!isRemoteAgentAction(action) || // Case 2: For agent actions, keep all except self (prevent infinite loops)
|
|
2984
|
+
isRemoteAgentAction(action) && action.name !== agentName
|
|
2967
2985
|
)).map((action) => ({
|
|
2968
2986
|
name: action.name,
|
|
2969
2987
|
description: action.description,
|
|
@@ -2981,7 +2999,7 @@ please use an LLM adapter instead.`
|
|
|
2981
2999
|
}));
|
|
2982
3000
|
try {
|
|
2983
3001
|
const eventSource = new RuntimeEventSource();
|
|
2984
|
-
const stream = await currentAgent.
|
|
3002
|
+
const stream = await currentAgent.remoteAgentHandler({
|
|
2985
3003
|
name: agentName,
|
|
2986
3004
|
threadId,
|
|
2987
3005
|
nodeName,
|
|
@@ -3352,7 +3370,7 @@ async function executeAction(eventStream$, guardrailsResult$, action, actionArgu
|
|
|
3352
3370
|
return;
|
|
3353
3371
|
}
|
|
3354
3372
|
}
|
|
3355
|
-
if (
|
|
3373
|
+
if (isRemoteAgentAction(action)) {
|
|
3356
3374
|
const result = `${action.name} agent started`;
|
|
3357
3375
|
const agentExecution = plainToInstance2(ActionExecutionMessage, {
|
|
3358
3376
|
id: actionExecutionId,
|
|
@@ -3373,7 +3391,7 @@ async function executeAction(eventStream$, guardrailsResult$, action, actionArgu
|
|
|
3373
3391
|
actionName: action.name,
|
|
3374
3392
|
result
|
|
3375
3393
|
});
|
|
3376
|
-
const stream = await action.
|
|
3394
|
+
const stream = await action.remoteAgentHandler({
|
|
3377
3395
|
name: action.name,
|
|
3378
3396
|
threadId,
|
|
3379
3397
|
actionInputsWithoutAgents,
|
|
@@ -3611,6 +3629,9 @@ var CopilotResolver = class {
|
|
|
3611
3629
|
resolveOutputMessagesPromise = resolve;
|
|
3612
3630
|
rejectOutputMessagesPromise = reject;
|
|
3613
3631
|
});
|
|
3632
|
+
if (copilotCloudPublicApiKey) {
|
|
3633
|
+
ctx.properties["copilotCloudPublicApiKey"] = copilotCloudPublicApiKey;
|
|
3634
|
+
}
|
|
3614
3635
|
logger2.debug("Processing");
|
|
3615
3636
|
const { eventSource, threadId = randomId4(), runId, serverSideActions, actionInputsWithoutAgents, extensions } = await copilotRuntime.processRuntimeRequest({
|
|
3616
3637
|
serviceAdapter,
|
|
@@ -4305,4 +4326,4 @@ export {
|
|
|
4305
4326
|
getCommonConfig,
|
|
4306
4327
|
copilotRuntimeNodeHttpEndpoint
|
|
4307
4328
|
};
|
|
4308
|
-
//# sourceMappingURL=chunk-
|
|
4329
|
+
//# sourceMappingURL=chunk-34Y5DNNJ.mjs.map
|