robotrock 0.8.3 → 0.8.5

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/dist/index.d.ts CHANGED
@@ -1,9 +1,10 @@
1
1
  import { R as RobotRock, b as RobotRockConfig } from './client-D-XEBOWd.js';
2
2
  export { c as RobotRockError, d as RobotRockPollingClientConfig, e as RobotRockPollingOptions, f as RobotRockWebhookClientConfig, g as RobotRockWebhookConfig, S as SendToHumanActionInput, a as SendToHumanInput, h as SendToHumanResult, i as SendToHumanValidUntil, j as SendUpdateInput, k as attachWebhookToActions, l as createClient } from './client-D-XEBOWd.js';
3
3
  import { Task, DiscriminatedApprovalResult } from './schemas/index.js';
4
- export { AgentCost, AgentCostTokens, AgentTelemetry, AgentTelemetryInput, AgentToolCalls, ApprovalResult, AssignToInput, CreateTaskBody, CreateTaskBodyInput, DEFAULT_TASK_PRIORITY, DEFAULT_THREAD_UPDATE_STATUS, Handler, InferActionData, LOWEST_TASK_PRIORITY, TASK_PRIORITY_RANK, TaskAction, TaskContext, TaskContextInput, TaskPriority, TaskResponse, TaskResult, TaskStatus, ThreadUpdate, ThreadUpdateBody, ThreadUpdateBodyInput, ThreadUpdateInput, ThreadUpdateResponse, ThreadUpdateSource, ThreadUpdateStatus, TriggerHandler, TupleElementIndices, WebhookHandler, agentCostSchema, agentCostTokensSchema, agentTelemetrySchema, agentToolCallsSchema, assignToSchema, createTaskBodySchema, taskContextSchema, taskPriorities, taskPrioritySchema, threadUpdateBodySchema, threadUpdateInputSchema, threadUpdateStatusSchema, threadUpdateStatuses } from './schemas/index.js';
4
+ export { AGENT_OTEL_SPANS_MAX, AgentCost, AgentCostTokens, AgentOtel, AgentOtelSpanStatus, AgentOtelSpanSummary, AgentTelemetry, AgentTelemetryInput, AgentToolCalls, ApprovalResult, AssignToInput, CreateTaskBody, CreateTaskBodyInput, DEFAULT_TASK_PRIORITY, DEFAULT_THREAD_UPDATE_STATUS, Handler, InferActionData, LOWEST_TASK_PRIORITY, TASK_PRIORITY_RANK, TaskAction, TaskContext, TaskContextInput, TaskPriority, TaskResponse, TaskResult, TaskStatus, ThreadUpdate, ThreadUpdateBody, ThreadUpdateBodyInput, ThreadUpdateInput, ThreadUpdateResponse, ThreadUpdateSource, ThreadUpdateStatus, TriggerHandler, TupleElementIndices, WebhookHandler, agentCostSchema, agentCostTokensSchema, agentOtelSchema, agentOtelSpanStatusSchema, agentOtelSpanSummarySchema, agentTelemetrySchema, agentToolCallsSchema, assignToSchema, createTaskBodySchema, taskContextSchema, taskPriorities, taskPrioritySchema, threadUpdateBodySchema, threadUpdateInputSchema, threadUpdateStatusSchema, threadUpdateStatuses } from './schemas/index.js';
5
5
  import { z } from 'zod';
6
6
  export { R as RobotRockHandlerWebhookPayload } from './handler-webhook-BqEi6Bk-.js';
7
+ export { AgentTelemetryFromOtelOptions, OtelSpanLike, OtelSpanSummaryInput, agentTelemetryFromOtel, toolCallsFromOtelSpans } from './otel/index.js';
7
8
 
8
9
  /**
9
10
  * Read RobotRock client config from environment variables.
@@ -31,6 +32,72 @@ declare function toDiscriminatedApprovalResult<A extends readonly {
31
32
  schema?: unknown;
32
33
  }[]>(actions: A, task: Task): DiscriminatedApprovalResult<A>;
33
34
 
35
+ /**
36
+ * Reserved inbox actions that reviewers can take outside your task's defined actions.
37
+ * Agents and integrations must treat these as terminal — stop the run and do not retry sendToHuman.
38
+ */
39
+ declare const PLATFORM_MARK_DONE_ACTION_ID: "robotrock:mark-done";
40
+ declare const PLATFORM_REJECT_REQUEST_ACTION_ID: "robotrock:reject-request";
41
+ declare const PLATFORM_MARK_DONE_ACTION_TITLE = "Mark as done";
42
+ declare const PLATFORM_REJECT_REQUEST_ACTION_TITLE = "Reject request";
43
+ declare const PLATFORM_TERMINAL_ACTION_IDS: readonly ["robotrock:mark-done", "robotrock:reject-request"];
44
+ type PlatformTerminalActionId = (typeof PLATFORM_TERMINAL_ACTION_IDS)[number];
45
+ type PlatformRejectRequestData = {
46
+ feedback: string;
47
+ };
48
+ type HandledActionInput = {
49
+ actionId: string;
50
+ data?: unknown;
51
+ handledBy?: string;
52
+ handledAt?: number | Date;
53
+ };
54
+ type PlatformMarkDoneOutcome = {
55
+ source: "platform";
56
+ kind: "mark-done";
57
+ actionId: typeof PLATFORM_MARK_DONE_ACTION_ID;
58
+ data: Record<string, never>;
59
+ handledBy?: string;
60
+ handledAt?: Date;
61
+ };
62
+ type PlatformRejectRequestOutcome = {
63
+ source: "platform";
64
+ kind: "reject-request";
65
+ actionId: typeof PLATFORM_REJECT_REQUEST_ACTION_ID;
66
+ data: PlatformRejectRequestData;
67
+ handledBy?: string;
68
+ handledAt?: Date;
69
+ };
70
+ type TaskActionOutcome = {
71
+ source: "task";
72
+ actionId: string;
73
+ data: unknown;
74
+ handledBy?: string;
75
+ handledAt?: Date;
76
+ };
77
+ type HandledOutcome = PlatformMarkDoneOutcome | PlatformRejectRequestOutcome | TaskActionOutcome;
78
+ declare class PlatformRejectRequestError extends Error {
79
+ readonly actionId: "robotrock:reject-request";
80
+ readonly feedback: string;
81
+ constructor(feedback: string, message?: string);
82
+ }
83
+ declare function isPlatformMarkDoneAction(actionId: string | undefined): actionId is typeof PLATFORM_MARK_DONE_ACTION_ID;
84
+ declare function isPlatformRejectRequestAction(actionId: string | undefined): actionId is typeof PLATFORM_REJECT_REQUEST_ACTION_ID;
85
+ declare function isPlatformTerminalAction(actionId: string | undefined): actionId is PlatformTerminalActionId;
86
+ declare function parsePlatformRejectRequestData(data: unknown): PlatformRejectRequestData | null;
87
+ /**
88
+ * Classify a handled task action as a platform terminal outcome or a normal task action.
89
+ */
90
+ declare function parseHandledOutcome(input: HandledActionInput): HandledOutcome;
91
+ /**
92
+ * Throw when a human rejected the request from the inbox (not your task's reject action).
93
+ * Use after polling, webhooks, or getTask when you want agents to stop immediately.
94
+ */
95
+ declare function assertNotPlatformRejectRequest(actionId: string, data?: unknown): void;
96
+ /**
97
+ * Returns true when the agent should stop — platform mark-done or reject-request.
98
+ */
99
+ declare function shouldStopAgentForHandledAction(actionId: string | undefined): boolean;
100
+
34
101
  declare const robotRockWebhookPayloadSchema: z.ZodObject<{
35
102
  taskId: z.ZodString;
36
103
  action: z.ZodObject<{
@@ -70,4 +137,4 @@ interface VerifyRobotRockWebhookOptions {
70
137
  */
71
138
  declare function verifyRobotRockWebhook(request: Request, options?: VerifyRobotRockWebhookOptions): Promise<RobotRockWebhookPayload>;
72
139
 
73
- export { DiscriminatedApprovalResult, RobotRock, RobotRockConfig, RobotRockWebhookError, type RobotRockWebhookErrorCode, type RobotRockWebhookPayload, Task, TaskExpiredError, TaskTimeoutError, type VerifyRobotRockWebhookOptions, resolveRobotRockClient, resolveRobotRockConfig, toDiscriminatedApprovalResult, verifyRobotRockWebhook };
140
+ export { DiscriminatedApprovalResult, type HandledActionInput, type HandledOutcome, PLATFORM_MARK_DONE_ACTION_ID, PLATFORM_MARK_DONE_ACTION_TITLE, PLATFORM_REJECT_REQUEST_ACTION_ID, PLATFORM_REJECT_REQUEST_ACTION_TITLE, PLATFORM_TERMINAL_ACTION_IDS, type PlatformMarkDoneOutcome, type PlatformRejectRequestData, PlatformRejectRequestError, type PlatformRejectRequestOutcome, type PlatformTerminalActionId, RobotRock, RobotRockConfig, RobotRockWebhookError, type RobotRockWebhookErrorCode, type RobotRockWebhookPayload, Task, type TaskActionOutcome, TaskExpiredError, TaskTimeoutError, type VerifyRobotRockWebhookOptions, assertNotPlatformRejectRequest, isPlatformMarkDoneAction, isPlatformRejectRequestAction, isPlatformTerminalAction, parseHandledOutcome, parsePlatformRejectRequestData, resolveRobotRockClient, resolveRobotRockConfig, shouldStopAgentForHandledAction, toDiscriminatedApprovalResult, verifyRobotRockWebhook };
package/dist/index.js CHANGED
@@ -291,7 +291,20 @@ var agentCostSchema = z.object({
291
291
  });
292
292
  var AGENT_INFO_MAX_KEYS = 32;
293
293
  var AGENT_TOOL_CALLS_MAX_KEYS = 64;
294
+ var AGENT_OTEL_SPANS_MAX = 32;
294
295
  var agentToolCallsSchema = z.record(z.string().min(1), nonNegativeInt);
296
+ var agentOtelSpanStatusSchema = z.enum(["ok", "error"]);
297
+ var agentOtelSpanSummarySchema = z.object({
298
+ name: z.string().min(1),
299
+ durationMs: z.number().nonnegative(),
300
+ status: agentOtelSpanStatusSchema
301
+ });
302
+ var agentOtelSchema = z.object({
303
+ traceId: z.string().min(1),
304
+ spanId: z.string().min(1).optional(),
305
+ rootDurationMs: z.number().nonnegative().optional(),
306
+ spans: z.array(agentOtelSpanSummarySchema).max(AGENT_OTEL_SPANS_MAX).optional()
307
+ });
295
308
  var agentTelemetrySchema = z.object({
296
309
  /** Agent or app version (semver, git SHA, deploy tag — caller-defined). */
297
310
  version: z.string().min(1).optional(),
@@ -301,7 +314,9 @@ var agentTelemetrySchema = z.object({
301
314
  toolCalls: agentToolCallsSchema.optional(),
302
315
  cost: agentCostSchema.optional(),
303
316
  /** Free-form metadata for experiments (model, prompt variant, etc.). */
304
- info: z.record(z.string(), z.unknown()).optional()
317
+ info: z.record(z.string(), z.unknown()).optional(),
318
+ /** Structured OpenTelemetry span snapshot for feedback analysis. */
319
+ otel: agentOtelSchema.optional()
305
320
  }).refine(
306
321
  (data) => {
307
322
  const keys = data.info ? Object.keys(data.info) : [];
@@ -455,13 +470,27 @@ var agentCostSchema2 = z2.object({
455
470
  });
456
471
  var AGENT_INFO_MAX_KEYS2 = 32;
457
472
  var AGENT_TOOL_CALLS_MAX_KEYS2 = 64;
473
+ var AGENT_OTEL_SPANS_MAX2 = 32;
458
474
  var agentToolCallsSchema2 = z2.record(z2.string().min(1), nonNegativeInt2);
475
+ var agentOtelSpanStatusSchema2 = z2.enum(["ok", "error"]);
476
+ var agentOtelSpanSummarySchema2 = z2.object({
477
+ name: z2.string().min(1),
478
+ durationMs: z2.number().nonnegative(),
479
+ status: agentOtelSpanStatusSchema2
480
+ });
481
+ var agentOtelSchema2 = z2.object({
482
+ traceId: z2.string().min(1),
483
+ spanId: z2.string().min(1).optional(),
484
+ rootDurationMs: z2.number().nonnegative().optional(),
485
+ spans: z2.array(agentOtelSpanSummarySchema2).max(AGENT_OTEL_SPANS_MAX2).optional()
486
+ });
459
487
  var agentTelemetrySchema2 = z2.object({
460
488
  version: z2.string().min(1).optional(),
461
489
  toolCallCount: nonNegativeInt2.optional(),
462
490
  toolCalls: agentToolCallsSchema2.optional(),
463
491
  cost: agentCostSchema2.optional(),
464
- info: z2.record(z2.string(), z2.unknown()).optional()
492
+ info: z2.record(z2.string(), z2.unknown()).optional(),
493
+ otel: agentOtelSchema2.optional()
465
494
  }).refine(
466
495
  (data) => {
467
496
  const keys = data.info ? Object.keys(data.info) : [];
@@ -856,6 +885,97 @@ function resolveRobotRockClient(client, configOverrides) {
856
885
  return createClient(resolveRobotRockConfig(configOverrides));
857
886
  }
858
887
 
888
+ // src/platform-actions.ts
889
+ var PLATFORM_MARK_DONE_ACTION_ID = "robotrock:mark-done";
890
+ var PLATFORM_REJECT_REQUEST_ACTION_ID = "robotrock:reject-request";
891
+ var PLATFORM_MARK_DONE_ACTION_TITLE = "Mark as done";
892
+ var PLATFORM_REJECT_REQUEST_ACTION_TITLE = "Reject request";
893
+ var PLATFORM_TERMINAL_ACTION_IDS = [
894
+ PLATFORM_MARK_DONE_ACTION_ID,
895
+ PLATFORM_REJECT_REQUEST_ACTION_ID
896
+ ];
897
+ var PlatformRejectRequestError = class extends Error {
898
+ actionId = PLATFORM_REJECT_REQUEST_ACTION_ID;
899
+ feedback;
900
+ constructor(feedback, message) {
901
+ super(message ?? `Human rejected the request: ${feedback}`);
902
+ this.name = "PlatformRejectRequestError";
903
+ this.feedback = feedback;
904
+ }
905
+ };
906
+ function isPlatformMarkDoneAction(actionId) {
907
+ return actionId === PLATFORM_MARK_DONE_ACTION_ID;
908
+ }
909
+ function isPlatformRejectRequestAction(actionId) {
910
+ return actionId === PLATFORM_REJECT_REQUEST_ACTION_ID;
911
+ }
912
+ function isPlatformTerminalAction(actionId) {
913
+ return isPlatformMarkDoneAction(actionId) || isPlatformRejectRequestAction(actionId);
914
+ }
915
+ function parsePlatformRejectRequestData(data) {
916
+ if (data == null || typeof data !== "object") {
917
+ return null;
918
+ }
919
+ const feedback = data.feedback;
920
+ if (typeof feedback !== "string") {
921
+ return null;
922
+ }
923
+ const trimmed = feedback.trim();
924
+ if (!trimmed) {
925
+ return null;
926
+ }
927
+ return { feedback: trimmed };
928
+ }
929
+ function toHandledAt(value) {
930
+ if (value === void 0) {
931
+ return void 0;
932
+ }
933
+ return value instanceof Date ? value : new Date(value);
934
+ }
935
+ function parseHandledOutcome(input) {
936
+ const handledAt = toHandledAt(input.handledAt);
937
+ const handledBy = input.handledBy;
938
+ if (isPlatformMarkDoneAction(input.actionId)) {
939
+ return {
940
+ source: "platform",
941
+ kind: "mark-done",
942
+ actionId: PLATFORM_MARK_DONE_ACTION_ID,
943
+ data: {},
944
+ handledBy,
945
+ handledAt
946
+ };
947
+ }
948
+ if (isPlatformRejectRequestAction(input.actionId)) {
949
+ return {
950
+ source: "platform",
951
+ kind: "reject-request",
952
+ actionId: PLATFORM_REJECT_REQUEST_ACTION_ID,
953
+ data: parsePlatformRejectRequestData(input.data) ?? { feedback: "" },
954
+ handledBy,
955
+ handledAt
956
+ };
957
+ }
958
+ return {
959
+ source: "task",
960
+ actionId: input.actionId,
961
+ data: input.data ?? {},
962
+ handledBy,
963
+ handledAt
964
+ };
965
+ }
966
+ function assertNotPlatformRejectRequest(actionId, data) {
967
+ if (!isPlatformRejectRequestAction(actionId)) {
968
+ return;
969
+ }
970
+ const parsed = parsePlatformRejectRequestData(data);
971
+ throw new PlatformRejectRequestError(
972
+ parsed?.feedback ?? "No feedback provided"
973
+ );
974
+ }
975
+ function shouldStopAgentForHandledAction(actionId) {
976
+ return isPlatformTerminalAction(actionId);
977
+ }
978
+
859
979
  // src/webhook.ts
860
980
  import { createHmac, timingSafeEqual } from "crypto";
861
981
  import { z as z3 } from "zod";
@@ -961,10 +1081,125 @@ function normalizeHeaders(headers) {
961
1081
  });
962
1082
  return result;
963
1083
  }
1084
+
1085
+ // src/agent-telemetry-from-otel.ts
1086
+ import { trace } from "@opentelemetry/api";
1087
+ var AGENT_INFO_MAX_KEYS3 = 32;
1088
+ function sumToolCalls(toolCalls) {
1089
+ return Object.values(toolCalls).reduce((sum, count) => sum + count, 0);
1090
+ }
1091
+ function isValidTraceId(traceId) {
1092
+ return typeof traceId === "string" && traceId.length > 0 && traceId !== "00000000000000000000000000000000";
1093
+ }
1094
+ function resolveSpanContext(span) {
1095
+ const active = span ?? trace.getActiveSpan();
1096
+ const ctx = active?.spanContext();
1097
+ if (!ctx || !isValidTraceId(ctx.traceId)) {
1098
+ return void 0;
1099
+ }
1100
+ return { traceId: ctx.traceId, spanId: ctx.spanId };
1101
+ }
1102
+ function countErrorSpans(spans) {
1103
+ if (!spans) return 0;
1104
+ return spans.filter((entry) => entry.status === "error").length;
1105
+ }
1106
+ function buildInfo(options, spanCtx) {
1107
+ const info = { ...options.extraInfo };
1108
+ if (spanCtx) {
1109
+ info.traceId = spanCtx.traceId;
1110
+ info.spanId = spanCtx.spanId;
1111
+ }
1112
+ if (options.runStartedAt != null) {
1113
+ const durationMs = Date.now() - options.runStartedAt;
1114
+ if (durationMs >= 0) {
1115
+ info.durationMs = durationMs;
1116
+ }
1117
+ }
1118
+ const errorCount = countErrorSpans(options.otel?.spans);
1119
+ if (errorCount > 0) {
1120
+ info.errorCount = errorCount;
1121
+ }
1122
+ const keys = Object.keys(info);
1123
+ if (keys.length === 0) {
1124
+ return void 0;
1125
+ }
1126
+ if (keys.length > AGENT_INFO_MAX_KEYS3) {
1127
+ const trimmed = {};
1128
+ for (const key of keys.slice(0, AGENT_INFO_MAX_KEYS3)) {
1129
+ trimmed[key] = info[key];
1130
+ }
1131
+ return trimmed;
1132
+ }
1133
+ return info;
1134
+ }
1135
+ function buildOtelBlock(options, spanCtx) {
1136
+ const traceId = options.otel?.traceId ?? spanCtx?.traceId;
1137
+ if (!isValidTraceId(traceId)) {
1138
+ return void 0;
1139
+ }
1140
+ const spans = options.otel?.spans;
1141
+ const rootDurationMs = options.otel?.rootDurationMs ?? (options.runStartedAt != null ? Math.max(0, Date.now() - options.runStartedAt) : void 0);
1142
+ const block = { traceId };
1143
+ const spanId = options.otel?.spanId ?? spanCtx?.spanId;
1144
+ if (spanId) {
1145
+ block.spanId = spanId;
1146
+ }
1147
+ if (rootDurationMs != null) {
1148
+ block.rootDurationMs = rootDurationMs;
1149
+ }
1150
+ if (spans && spans.length > 0) {
1151
+ block.spans = spans;
1152
+ }
1153
+ return block;
1154
+ }
1155
+ function agentTelemetryFromOtel(options = {}) {
1156
+ const spanCtx = resolveSpanContext(options.span);
1157
+ const telemetry = {};
1158
+ if (options.version) {
1159
+ telemetry.version = options.version;
1160
+ }
1161
+ if (options.toolCalls && Object.keys(options.toolCalls).length > 0) {
1162
+ telemetry.toolCalls = options.toolCalls;
1163
+ }
1164
+ if (options.toolCallCount !== void 0) {
1165
+ telemetry.toolCallCount = options.toolCallCount;
1166
+ } else if (telemetry.toolCalls) {
1167
+ const sum = sumToolCalls(telemetry.toolCalls);
1168
+ if (sum > 0) {
1169
+ telemetry.toolCallCount = sum;
1170
+ }
1171
+ }
1172
+ if (options.cost) {
1173
+ telemetry.cost = options.cost;
1174
+ }
1175
+ const info = buildInfo(options, spanCtx);
1176
+ if (info) {
1177
+ telemetry.info = info;
1178
+ }
1179
+ const otel = buildOtelBlock(options, spanCtx);
1180
+ if (otel) {
1181
+ telemetry.otel = otel;
1182
+ }
1183
+ return agentTelemetrySchema2.parse(telemetry);
1184
+ }
1185
+ function toolCallsFromOtelSpans(spans) {
1186
+ const counts = {};
1187
+ for (const span of spans) {
1188
+ counts[span.name] = (counts[span.name] ?? 0) + 1;
1189
+ }
1190
+ return counts;
1191
+ }
964
1192
  export {
1193
+ AGENT_OTEL_SPANS_MAX2 as AGENT_OTEL_SPANS_MAX,
965
1194
  DEFAULT_TASK_PRIORITY,
966
1195
  DEFAULT_THREAD_UPDATE_STATUS,
967
1196
  LOWEST_TASK_PRIORITY,
1197
+ PLATFORM_MARK_DONE_ACTION_ID,
1198
+ PLATFORM_MARK_DONE_ACTION_TITLE,
1199
+ PLATFORM_REJECT_REQUEST_ACTION_ID,
1200
+ PLATFORM_REJECT_REQUEST_ACTION_TITLE,
1201
+ PLATFORM_TERMINAL_ACTION_IDS,
1202
+ PlatformRejectRequestError,
968
1203
  RobotRock,
969
1204
  RobotRockError,
970
1205
  RobotRockWebhookError,
@@ -973,14 +1208,25 @@ export {
973
1208
  TaskTimeoutError,
974
1209
  agentCostSchema2 as agentCostSchema,
975
1210
  agentCostTokensSchema2 as agentCostTokensSchema,
1211
+ agentOtelSchema2 as agentOtelSchema,
1212
+ agentOtelSpanStatusSchema2 as agentOtelSpanStatusSchema,
1213
+ agentOtelSpanSummarySchema2 as agentOtelSpanSummarySchema,
1214
+ agentTelemetryFromOtel,
976
1215
  agentTelemetrySchema2 as agentTelemetrySchema,
977
1216
  agentToolCallsSchema2 as agentToolCallsSchema,
1217
+ assertNotPlatformRejectRequest,
978
1218
  assignToSchema2 as assignToSchema,
979
1219
  attachWebhookToActions,
980
1220
  createClient,
981
1221
  createTaskBodySchema2 as createTaskBodySchema,
1222
+ isPlatformMarkDoneAction,
1223
+ isPlatformRejectRequestAction,
1224
+ isPlatformTerminalAction,
1225
+ parseHandledOutcome,
1226
+ parsePlatformRejectRequestData,
982
1227
  resolveRobotRockClient,
983
1228
  resolveRobotRockConfig,
1229
+ shouldStopAgentForHandledAction,
984
1230
  taskContextSchema2 as taskContextSchema,
985
1231
  taskPriorities2 as taskPriorities,
986
1232
  taskPrioritySchema2 as taskPrioritySchema,
@@ -989,6 +1235,7 @@ export {
989
1235
  threadUpdateStatusSchema2 as threadUpdateStatusSchema,
990
1236
  threadUpdateStatuses2 as threadUpdateStatuses,
991
1237
  toDiscriminatedApprovalResult,
1238
+ toolCallsFromOtelSpans,
992
1239
  verifyRobotRockWebhook
993
1240
  };
994
1241
  //# sourceMappingURL=index.js.map