@nice-code/action 0.6.1 → 0.6.2

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.
@@ -2060,6 +2060,11 @@ var SEMANTIC_COLORS = {
2060
2060
  borderColor: DEVTOOL_COLOR_HANDLER_EXTERNAL_BORDER,
2061
2061
  subtle: { color: "#cfa12a9f", borderColor: "transparent" }
2062
2062
  },
2063
+ origin: {
2064
+ color: DEVTOOL_COLOR_SEMANTIC_SYSTEM,
2065
+ borderColor: `${DEVTOOL_COLOR_SEMANTIC_SYSTEM}55`,
2066
+ subtle: { color: `${DEVTOOL_COLOR_SEMANTIC_SYSTEM}9f`, borderColor: "transparent" }
2067
+ },
2063
2068
  age: {
2064
2069
  color: DEVTOOL_COLOR_SEMANTIC_METADATA,
2065
2070
  borderColor: DEVTOOL_SECTION_BACKGROUND,
@@ -2151,6 +2156,16 @@ var STATUS_ICON = {
2151
2156
  failed: CircleX,
2152
2157
  aborted: Circle
2153
2158
  };
2159
+ function getInboundOrigin(entry) {
2160
+ const origin = entry.meta.originClient;
2161
+ if (origin == null || origin.envId === "unknown" || origin.envId === "_unset_")
2162
+ return null;
2163
+ const local = entry.meta.routing[0]?.runtime;
2164
+ if (local == null)
2165
+ return null;
2166
+ const sameRuntime = origin.envId === local.envId && (origin.perId ?? null) === (local.perId ?? null) && (origin.insId ?? null) === (local.insId ?? null);
2167
+ return sameRuntime ? null : origin;
2168
+ }
2154
2169
  function safeStringify(value, indent = 2) {
2155
2170
  if (value === undefined)
2156
2171
  return "undefined";
@@ -3935,8 +3950,49 @@ function MetaSection({ entry }) {
3935
3950
  });
3936
3951
  }
3937
3952
 
3938
- // src/devtools/browser/components/RoutingSection.tsx
3953
+ // src/devtools/browser/components/OriginChip.tsx
3939
3954
  import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
3955
+ function OriginChip({
3956
+ origin,
3957
+ size = "md" /* md */,
3958
+ subtle
3959
+ }) {
3960
+ return /* @__PURE__ */ jsx15(Chip, {
3961
+ color: "origin" /* origin */,
3962
+ size,
3963
+ subtle,
3964
+ tooltip: {
3965
+ title: "Received from",
3966
+ content: /* @__PURE__ */ jsxs13("div", {
3967
+ style: { display: "flex", flexDirection: "column", gap: "2px", fontSize: "11px" },
3968
+ children: [
3969
+ /* @__PURE__ */ jsxs13("span", {
3970
+ children: [
3971
+ "env ",
3972
+ origin.envId
3973
+ ]
3974
+ }),
3975
+ origin.perId != null && /* @__PURE__ */ jsxs13("span", {
3976
+ children: [
3977
+ "perId ",
3978
+ origin.perId
3979
+ ]
3980
+ }),
3981
+ origin.insId != null && /* @__PURE__ */ jsxs13("span", {
3982
+ children: [
3983
+ "insId ",
3984
+ origin.insId
3985
+ ]
3986
+ })
3987
+ ]
3988
+ })
3989
+ },
3990
+ children: `⇠ ${origin.envId}`
3991
+ });
3992
+ }
3993
+
3994
+ // src/devtools/browser/components/RoutingSection.tsx
3995
+ import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
3940
3996
  function RoutingSection({
3941
3997
  entry,
3942
3998
  minHopCount = 0
@@ -3946,12 +4002,12 @@ function RoutingSection({
3946
4002
  const phantomCount = Math.max(0, minHopCount - hopCount);
3947
4003
  if (hopCount === 0 && phantomCount === 0)
3948
4004
  return null;
3949
- return /* @__PURE__ */ jsxs13("div", {
4005
+ return /* @__PURE__ */ jsxs14("div", {
3950
4006
  children: [
3951
- /* @__PURE__ */ jsx15(SectionLabel, {
4007
+ /* @__PURE__ */ jsx16(SectionLabel, {
3952
4008
  label: hopCount > 0 ? `Routing · ${hopCount} hop${hopCount !== 1 ? "s" : ""}` : "Routing"
3953
4009
  }),
3954
- /* @__PURE__ */ jsxs13("div", {
4010
+ /* @__PURE__ */ jsxs14("div", {
3955
4011
  style: { display: "flex", flexDirection: "column", gap: "2px" },
3956
4012
  children: [
3957
4013
  meta.routing.map((hop, i) => {
@@ -3961,7 +4017,7 @@ function RoutingSection({
3961
4017
  const badgeText = isLocal ? "● exec" : `→ ${hop.transportSummary ?? hop.transport ?? "ext"}`;
3962
4018
  const transportTooltip = isLocal ? undefined : getTransportTooltip(hop);
3963
4019
  const runtimeTitle = [hop.runtime.perId, hop.runtime.insId].filter(Boolean).join(" · ") || undefined;
3964
- return /* @__PURE__ */ jsxs13("div", {
4020
+ return /* @__PURE__ */ jsxs14("div", {
3965
4021
  style: {
3966
4022
  background: DEVTOOL_SECTION_BACKGROUND,
3967
4023
  borderRadius: "4px",
@@ -3974,10 +4030,10 @@ function RoutingSection({
3974
4030
  padding: "4px 8px"
3975
4031
  },
3976
4032
  children: [
3977
- /* @__PURE__ */ jsxs13("span", {
4033
+ /* @__PURE__ */ jsxs14("span", {
3978
4034
  style: { display: "flex", flexDirection: "row", alignItems: "center", gap: "10px" },
3979
4035
  children: [
3980
- /* @__PURE__ */ jsx15("span", {
4036
+ /* @__PURE__ */ jsx16("span", {
3981
4037
  style: {
3982
4038
  color: DEVTOOL_COLOR_TEXT_FAINT,
3983
4039
  fontSize: "10px",
@@ -3986,7 +4042,7 @@ function RoutingSection({
3986
4042
  },
3987
4043
  children: i + 1
3988
4044
  }),
3989
- /* @__PURE__ */ jsx15("span", {
4045
+ /* @__PURE__ */ jsx16("span", {
3990
4046
  title: runtimeTitle,
3991
4047
  style: {
3992
4048
  color: DEVTOOL_COLOR_TEXT_SECONDARY,
@@ -4000,10 +4056,10 @@ function RoutingSection({
4000
4056
  })
4001
4057
  ]
4002
4058
  }),
4003
- /* @__PURE__ */ jsx15(HoverTooltip, {
4059
+ /* @__PURE__ */ jsx16(HoverTooltip, {
4004
4060
  config: transportTooltip,
4005
4061
  style: { display: "block", minWidth: 0, overflow: "hidden" },
4006
- children: /* @__PURE__ */ jsx15("span", {
4062
+ children: /* @__PURE__ */ jsx16("span", {
4007
4063
  style: {
4008
4064
  color: badgeColor,
4009
4065
  fontSize: "10px",
@@ -4015,7 +4071,7 @@ function RoutingSection({
4015
4071
  children: badgeText
4016
4072
  })
4017
4073
  }),
4018
- /* @__PURE__ */ jsxs13("span", {
4074
+ /* @__PURE__ */ jsxs14("span", {
4019
4075
  style: {
4020
4076
  display: "flex",
4021
4077
  alignItems: "center",
@@ -4024,7 +4080,7 @@ function RoutingSection({
4024
4080
  overflow: "hidden"
4025
4081
  },
4026
4082
  children: [
4027
- /* @__PURE__ */ jsx15("span", {
4083
+ /* @__PURE__ */ jsx16("span", {
4028
4084
  style: {
4029
4085
  color: DEVTOOL_COLOR_TEXT_MUTED,
4030
4086
  fontSize: "10px",
@@ -4034,7 +4090,7 @@ function RoutingSection({
4034
4090
  },
4035
4091
  children: hop.handlerClient != null ? `↳ ${hop.handlerClient.envId}` : ""
4036
4092
  }),
4037
- /* @__PURE__ */ jsxs13("span", {
4093
+ /* @__PURE__ */ jsxs14("span", {
4038
4094
  style: {
4039
4095
  color: DEVTOOL_COLOR_TEXT_FAINT,
4040
4096
  fontSize: "10px",
@@ -4052,7 +4108,7 @@ function RoutingSection({
4052
4108
  ]
4053
4109
  }, `${hop.time}-${hop.runtime.envId}`);
4054
4110
  }),
4055
- Array.from({ length: phantomCount }, (_, i) => `routing-phantom-${hopCount + i}`).map((key) => /* @__PURE__ */ jsxs13("div", {
4111
+ Array.from({ length: phantomCount }, (_, i) => `routing-phantom-${hopCount + i}`).map((key) => /* @__PURE__ */ jsxs14("div", {
4056
4112
  "aria-hidden": "true",
4057
4113
  style: {
4058
4114
  visibility: "hidden",
@@ -4065,24 +4121,24 @@ function RoutingSection({
4065
4121
  padding: "4px 8px"
4066
4122
  },
4067
4123
  children: [
4068
- /* @__PURE__ */ jsxs13("span", {
4124
+ /* @__PURE__ */ jsxs14("span", {
4069
4125
  style: { display: "flex", flexDirection: "row", alignItems: "center", gap: "10px" },
4070
4126
  children: [
4071
- /* @__PURE__ */ jsx15("span", {
4127
+ /* @__PURE__ */ jsx16("span", {
4072
4128
  style: { fontSize: "10px", width: "16px" },
4073
4129
  children: "0"
4074
4130
  }),
4075
- /* @__PURE__ */ jsx15("span", {
4131
+ /* @__PURE__ */ jsx16("span", {
4076
4132
  style: { fontSize: "11px" },
4077
4133
  children: "placeholder"
4078
4134
  })
4079
4135
  ]
4080
4136
  }),
4081
- /* @__PURE__ */ jsx15("span", {
4137
+ /* @__PURE__ */ jsx16("span", {
4082
4138
  style: { fontSize: "10px" },
4083
4139
  children: "placeholder"
4084
4140
  }),
4085
- /* @__PURE__ */ jsx15("span", {})
4141
+ /* @__PURE__ */ jsx16("span", {})
4086
4142
  ]
4087
4143
  }, key))
4088
4144
  ]
@@ -4092,7 +4148,7 @@ function RoutingSection({
4092
4148
  }
4093
4149
 
4094
4150
  // src/devtools/browser/components/action_detail/ActionDetailPanel.tsx
4095
- import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
4151
+ import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
4096
4152
  var STATUS_BADGE_LABEL = {
4097
4153
  running: "RUNNING",
4098
4154
  success: "SUCCESS",
@@ -4123,7 +4179,8 @@ function DetailHeader({
4123
4179
  const color = STATUS_COLOR[entry.status];
4124
4180
  const StatusIconComponent = STATUS_ICON[entry.status];
4125
4181
  const timestamp = formatTimestamp(entry.startTime);
4126
- return /* @__PURE__ */ jsx16("div", {
4182
+ const inboundOrigin = getInboundOrigin(entry);
4183
+ return /* @__PURE__ */ jsx17("div", {
4127
4184
  onClick: !isActive ? onClick : undefined,
4128
4185
  style: {
4129
4186
  padding: "0.5em 1em",
@@ -4137,13 +4194,13 @@ function DetailHeader({
4137
4194
  gap: "1em",
4138
4195
  cursor: isActive ? "default" : "pointer"
4139
4196
  },
4140
- children: /* @__PURE__ */ jsxs14("div", {
4197
+ children: /* @__PURE__ */ jsxs15("div", {
4141
4198
  style: { flex: 1, minWidth: 0, display: "flex", flexDirection: "column", gap: "0.5em" },
4142
4199
  children: [
4143
- /* @__PURE__ */ jsxs14("div", {
4200
+ /* @__PURE__ */ jsxs15("div", {
4144
4201
  style: { display: "flex", alignItems: "center", minWidth: 0, gap: "0.5em" },
4145
4202
  children: [
4146
- /* @__PURE__ */ jsx16("span", {
4203
+ /* @__PURE__ */ jsx17("span", {
4147
4204
  style: {
4148
4205
  color,
4149
4206
  flexShrink: 0,
@@ -4151,12 +4208,12 @@ function DetailHeader({
4151
4208
  alignItems: "center",
4152
4209
  animation: entry.status === "running" ? "__nice-action-pulse 1.2s ease-in-out infinite" : undefined
4153
4210
  },
4154
- children: /* @__PURE__ */ jsx16(StatusIconComponent, {
4211
+ children: /* @__PURE__ */ jsx17(StatusIconComponent, {
4155
4212
  size: 20,
4156
4213
  strokeWidth: 1.75
4157
4214
  })
4158
4215
  }),
4159
- /* @__PURE__ */ jsx16("span", {
4216
+ /* @__PURE__ */ jsx17("span", {
4160
4217
  style: {
4161
4218
  color: DEVTOOL_COLOR_TEXT_EMPHASIS,
4162
4219
  fontSize: "1.2em",
@@ -4170,7 +4227,7 @@ function DetailHeader({
4170
4227
  },
4171
4228
  children: entry.actionId
4172
4229
  }),
4173
- /* @__PURE__ */ jsx16("span", {
4230
+ /* @__PURE__ */ jsx17("span", {
4174
4231
  style: {
4175
4232
  flexShrink: 0,
4176
4233
  padding: "2px 9px",
@@ -4185,14 +4242,14 @@ function DetailHeader({
4185
4242
  },
4186
4243
  children: STATUS_BADGE_LABEL[entry.status]
4187
4244
  }),
4188
- /* @__PURE__ */ jsx16(DomainChip, {
4245
+ /* @__PURE__ */ jsx17(DomainChip, {
4189
4246
  domain: entry.domain,
4190
4247
  allDomains: entry.allDomains,
4191
4248
  size: "md" /* md */
4192
4249
  })
4193
4250
  ]
4194
4251
  }),
4195
- /* @__PURE__ */ jsxs14("div", {
4252
+ /* @__PURE__ */ jsxs15("div", {
4196
4253
  style: {
4197
4254
  display: "flex",
4198
4255
  alignItems: "center",
@@ -4200,7 +4257,7 @@ function DetailHeader({
4200
4257
  gap: "8px"
4201
4258
  },
4202
4259
  children: [
4203
- /* @__PURE__ */ jsxs14("div", {
4260
+ /* @__PURE__ */ jsxs15("div", {
4204
4261
  style: {
4205
4262
  display: "flex",
4206
4263
  alignItems: "center",
@@ -4209,20 +4266,24 @@ function DetailHeader({
4209
4266
  overflow: "hidden"
4210
4267
  },
4211
4268
  children: [
4212
- /* @__PURE__ */ jsx16(HandlerChips, {
4269
+ inboundOrigin != null && /* @__PURE__ */ jsx17(OriginChip, {
4270
+ origin: inboundOrigin,
4271
+ size: "md" /* md */
4272
+ }),
4273
+ /* @__PURE__ */ jsx17(HandlerChips, {
4213
4274
  entry,
4214
4275
  size: "md" /* md */
4215
4276
  }),
4216
- /* @__PURE__ */ jsx16(ChildDispatchChips, {
4277
+ /* @__PURE__ */ jsx17(ChildDispatchChips, {
4217
4278
  childRouteItems: childExternalRouteItems,
4218
4279
  size: "md" /* md */
4219
4280
  })
4220
4281
  ]
4221
4282
  }),
4222
- /* @__PURE__ */ jsxs14("div", {
4283
+ /* @__PURE__ */ jsxs15("div", {
4223
4284
  style: { display: "flex", alignItems: "center", gap: "8px", flexShrink: 0 },
4224
4285
  children: [
4225
- /* @__PURE__ */ jsx16("span", {
4286
+ /* @__PURE__ */ jsx17("span", {
4226
4287
  style: {
4227
4288
  color: DEVTOOL_COLOR_SEMANTIC_METADATA,
4228
4289
  fontSize: "10px",
@@ -4231,9 +4292,9 @@ function DetailHeader({
4231
4292
  },
4232
4293
  children: timestamp
4233
4294
  }),
4234
- /* @__PURE__ */ jsx16("span", {
4295
+ /* @__PURE__ */ jsx17("span", {
4235
4296
  style: { color, fontSize: "12px", fontWeight: "500" },
4236
- children: /* @__PURE__ */ jsx16(DurationDisplay, {
4297
+ children: /* @__PURE__ */ jsx17(DurationDisplay, {
4237
4298
  entry
4238
4299
  })
4239
4300
  })
@@ -4273,7 +4334,7 @@ function ActionDetailPanel({
4273
4334
  const handleFocusChild = (cuid) => {
4274
4335
  setFocusedChildCuid((prev) => prev === cuid ? null : cuid);
4275
4336
  };
4276
- return /* @__PURE__ */ jsxs14("div", {
4337
+ return /* @__PURE__ */ jsxs15("div", {
4277
4338
  style: {
4278
4339
  flex: 1,
4279
4340
  display: "flex",
@@ -4283,20 +4344,20 @@ function ActionDetailPanel({
4283
4344
  background: DEVTOOL_DETAIL_BASE_BACKGROUND
4284
4345
  },
4285
4346
  children: [
4286
- /* @__PURE__ */ jsx16(DetailHeader, {
4347
+ /* @__PURE__ */ jsx17(DetailHeader, {
4287
4348
  entry,
4288
4349
  isActive: focusedChildCuid === null,
4289
4350
  onClick: () => setFocusedChildCuid(null),
4290
4351
  childExternalRouteItems
4291
4352
  }),
4292
- /* @__PURE__ */ jsx16(CallStackSection, {
4353
+ /* @__PURE__ */ jsx17(CallStackSection, {
4293
4354
  parent,
4294
4355
  childEntries,
4295
4356
  focusedChildCuid,
4296
4357
  onFocusChild: handleFocusChild,
4297
4358
  onSelectParent: onSelectEntry
4298
4359
  }),
4299
- /* @__PURE__ */ jsxs14("div", {
4360
+ /* @__PURE__ */ jsxs15("div", {
4300
4361
  style: {
4301
4362
  flex: 1,
4302
4363
  overflowY: "auto",
@@ -4307,37 +4368,37 @@ function ActionDetailPanel({
4307
4368
  gap: "8px"
4308
4369
  },
4309
4370
  children: [
4310
- focusedEntry.input !== undefined ? /* @__PURE__ */ jsx16(DetailSection, {
4371
+ focusedEntry.input !== undefined ? /* @__PURE__ */ jsx17(DetailSection, {
4311
4372
  label: "Input",
4312
4373
  value: focusedEntry.input
4313
- }) : /* @__PURE__ */ jsx16(DetailSection, {
4374
+ }) : /* @__PURE__ */ jsx17(DetailSection, {
4314
4375
  label: "Input",
4315
4376
  value: "No input required or given"
4316
4377
  }),
4317
- focusedEntry.status === "success" && /* @__PURE__ */ jsx16(DetailSection, {
4378
+ focusedEntry.status === "success" && /* @__PURE__ */ jsx17(DetailSection, {
4318
4379
  label: "Output",
4319
4380
  value: focusedEntry.output,
4320
4381
  color: DEVTOOL_COLOR_SEMANTIC_SUCCESS
4321
4382
  }),
4322
- (focusedEntry.status === "action-error" || focusedEntry.status === "failed" || focusedEntry.status === "aborted") && /* @__PURE__ */ jsx16(ActionErrorDisplay, {
4383
+ (focusedEntry.status === "action-error" || focusedEntry.status === "failed" || focusedEntry.status === "aborted") && /* @__PURE__ */ jsx17(ActionErrorDisplay, {
4323
4384
  entry: focusedEntry
4324
4385
  }),
4325
- focusedEntry.progressUpdates.length > 0 && /* @__PURE__ */ jsx16(DetailSection, {
4386
+ focusedEntry.progressUpdates.length > 0 && /* @__PURE__ */ jsx17(DetailSection, {
4326
4387
  label: `Progress (${focusedEntry.progressUpdates.length})`,
4327
4388
  value: focusedEntry.progressUpdates
4328
4389
  }),
4329
- /* @__PURE__ */ jsx16(StackTraceSection, {
4390
+ /* @__PURE__ */ jsx17(StackTraceSection, {
4330
4391
  runtime: entry.meta.originClient,
4331
4392
  label: "Dispatch Site",
4332
4393
  stack: focusedEntry.callSite,
4333
4394
  color: DEVTOOL_COLOR_TEXT_SECONDARY,
4334
4395
  minFrameCount: maxCallSiteFrames
4335
4396
  }),
4336
- /* @__PURE__ */ jsx16(RoutingSection, {
4397
+ /* @__PURE__ */ jsx17(RoutingSection, {
4337
4398
  entry: focusedEntry,
4338
4399
  minHopCount: maxRoutingHops
4339
4400
  }),
4340
- /* @__PURE__ */ jsx16(MetaSection, {
4401
+ /* @__PURE__ */ jsx17(MetaSection, {
4341
4402
  entry: focusedEntry
4342
4403
  })
4343
4404
  ]
@@ -4358,7 +4419,7 @@ import { CircleX as CircleX2, PackageCheck, Sparkle, Variable } from "lucide-rea
4358
4419
  import { useState as useState9 } from "react";
4359
4420
 
4360
4421
  // src/devtools/browser/components/action_list/IoTooltipContent.tsx
4361
- import { jsx as jsx17, Fragment as Fragment8 } from "react/jsx-runtime";
4422
+ import { jsx as jsx18, Fragment as Fragment8 } from "react/jsx-runtime";
4362
4423
  var JSON_TOKEN_RE2 = /("(?:\\.|[^"\\])*")(\s*:)?|(-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)|(\btrue\b|\bfalse\b|\bnull\b|\bundefined\b)|([{}[\],])/g;
4363
4424
  function renderColoredJson2(text) {
4364
4425
  const nodes = [];
@@ -4371,32 +4432,32 @@ function renderColoredJson2(text) {
4371
4432
  const [, str, colon, num, kw, punct] = m;
4372
4433
  if (str != null) {
4373
4434
  if (colon != null) {
4374
- nodes.push(/* @__PURE__ */ jsx17("span", {
4435
+ nodes.push(/* @__PURE__ */ jsx18("span", {
4375
4436
  style: { color: DEVTOOL_JSON_KEY },
4376
4437
  children: str
4377
4438
  }, i++));
4378
- nodes.push(/* @__PURE__ */ jsx17("span", {
4439
+ nodes.push(/* @__PURE__ */ jsx18("span", {
4379
4440
  style: { color: DEVTOOL_JSON_PUNCTUATION },
4380
4441
  children: colon
4381
4442
  }, i++));
4382
4443
  } else {
4383
- nodes.push(/* @__PURE__ */ jsx17("span", {
4444
+ nodes.push(/* @__PURE__ */ jsx18("span", {
4384
4445
  style: { color: DEVTOOL_JSON_STRING },
4385
4446
  children: str
4386
4447
  }, i++));
4387
4448
  }
4388
4449
  } else if (num != null) {
4389
- nodes.push(/* @__PURE__ */ jsx17("span", {
4450
+ nodes.push(/* @__PURE__ */ jsx18("span", {
4390
4451
  style: { color: DEVTOOL_JSON_NUMBER },
4391
4452
  children: num
4392
4453
  }, i++));
4393
4454
  } else if (kw != null) {
4394
- nodes.push(/* @__PURE__ */ jsx17("span", {
4455
+ nodes.push(/* @__PURE__ */ jsx18("span", {
4395
4456
  style: { color: DEVTOOL_JSON_KEYWORD },
4396
4457
  children: kw
4397
4458
  }, i++));
4398
4459
  } else if (punct != null) {
4399
- nodes.push(/* @__PURE__ */ jsx17("span", {
4460
+ nodes.push(/* @__PURE__ */ jsx18("span", {
4400
4461
  style: { color: DEVTOOL_JSON_PUNCTUATION },
4401
4462
  children: punct
4402
4463
  }, i++));
@@ -4418,7 +4479,7 @@ function stripOuterBraces(json) {
4418
4479
  }
4419
4480
  function IoTooltipContent({ value }) {
4420
4481
  const text = stripOuterBraces(safeStringify(value, 2));
4421
- return /* @__PURE__ */ jsx17("div", {
4482
+ return /* @__PURE__ */ jsx18("div", {
4422
4483
  style: {
4423
4484
  fontFamily: "ui-monospace, 'Cascadia Code', 'Source Code Pro', monospace",
4424
4485
  fontSize: "10px",
@@ -4432,7 +4493,7 @@ function IoTooltipContent({ value }) {
4432
4493
  }
4433
4494
 
4434
4495
  // src/devtools/browser/components/action_list/ActionInputAndOutputChip.tsx
4435
- import { jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
4496
+ import { jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
4436
4497
  var ActionInputAndOutputChip = ({
4437
4498
  entry,
4438
4499
  breakReasons,
@@ -4453,35 +4514,35 @@ var ActionInputAndOutputChip = ({
4453
4514
  const sizeNum = getSizeValue(size);
4454
4515
  const newIconSizeEm = `${sizeNum * 0.9}em`;
4455
4516
  const label = `${(isLocal ? localEnvId : externalLabel) ?? "unknown"}`;
4456
- const newSparkleComp = /* @__PURE__ */ jsx18("div", {
4517
+ const newSparkleComp = /* @__PURE__ */ jsx19("div", {
4457
4518
  style: {
4458
4519
  opacity: 0.9,
4459
4520
  alignSelf: "start",
4460
4521
  marginLeft: "-0.6em"
4461
4522
  },
4462
- children: /* @__PURE__ */ jsx18(Sparkle, {
4523
+ children: /* @__PURE__ */ jsx19(Sparkle, {
4463
4524
  strokeWidth: "0.2em",
4464
4525
  color: "rgba(243, 250, 140, 1)",
4465
4526
  width: newIconSizeEm,
4466
4527
  height: newIconSizeEm
4467
4528
  })
4468
4529
  });
4469
- return /* @__PURE__ */ jsx18(Chip, {
4530
+ return /* @__PURE__ */ jsx19(Chip, {
4470
4531
  color,
4471
4532
  size,
4472
4533
  subtle,
4473
- children: /* @__PURE__ */ jsxs15("div", {
4534
+ children: /* @__PURE__ */ jsxs16("div", {
4474
4535
  style: { display: "flex", alignItems: "center", gap: "0.4em" },
4475
4536
  children: [
4476
- /* @__PURE__ */ jsx18(Icon, {
4537
+ /* @__PURE__ */ jsx19(Icon, {
4477
4538
  noBackground: true,
4478
4539
  icon: Variable,
4479
4540
  color,
4480
4541
  subtle: subtle || entry.input === undefined,
4481
4542
  tooltip: {
4482
- content: entry.input !== undefined ? /* @__PURE__ */ jsx18(IoTooltipContent, {
4543
+ content: entry.input !== undefined ? /* @__PURE__ */ jsx19(IoTooltipContent, {
4483
4544
  value: entry.input
4484
- }) : /* @__PURE__ */ jsx18("span", {
4545
+ }) : /* @__PURE__ */ jsx19("span", {
4485
4546
  style: { color: DEVTOOL_COLOR_TEXT_MUTED, fontSize: "10px" },
4486
4547
  children: "No input required or given"
4487
4548
  }),
@@ -4489,43 +4550,43 @@ var ActionInputAndOutputChip = ({
4489
4550
  }
4490
4551
  }),
4491
4552
  isNewInput && newSparkleComp,
4492
- /* @__PURE__ */ jsx18("span", {
4553
+ /* @__PURE__ */ jsx19("span", {
4493
4554
  style: { opacity: 0.6 },
4494
4555
  color,
4495
4556
  children: "→"
4496
4557
  }),
4497
- /* @__PURE__ */ jsx18("span", {
4558
+ /* @__PURE__ */ jsx19("span", {
4498
4559
  style: { opacity: 0.8, cursor: transportTooltip != null ? "default" : undefined },
4499
4560
  onMouseEnter: transportTooltip != null ? (e) => setLabelAnchor(e.currentTarget.getBoundingClientRect()) : undefined,
4500
4561
  onMouseLeave: transportTooltip != null ? () => setLabelAnchor(null) : undefined,
4501
4562
  children: label
4502
4563
  }),
4503
- labelAnchor != null && transportTooltip != null && /* @__PURE__ */ jsx18(Tooltip, {
4564
+ labelAnchor != null && transportTooltip != null && /* @__PURE__ */ jsx19(Tooltip, {
4504
4565
  anchor: labelAnchor,
4505
4566
  config: transportTooltip
4506
4567
  }),
4507
- /* @__PURE__ */ jsx18("span", {
4568
+ /* @__PURE__ */ jsx19("span", {
4508
4569
  style: { opacity: 0.6 },
4509
4570
  color,
4510
4571
  children: "→"
4511
4572
  }),
4512
- entry.status === "success" && entry.output !== undefined && /* @__PURE__ */ jsx18(Icon, {
4573
+ entry.status === "success" && entry.output !== undefined && /* @__PURE__ */ jsx19(Icon, {
4513
4574
  noBackground: true,
4514
4575
  icon: PackageCheck,
4515
4576
  color: !hasError ? color : "default" /* default */,
4516
4577
  tooltip: {
4517
- content: /* @__PURE__ */ jsx18(IoTooltipContent, {
4578
+ content: /* @__PURE__ */ jsx19(IoTooltipContent, {
4518
4579
  value: entry.output
4519
4580
  }),
4520
4581
  title: isNewOutput ? "New Output" : "Output"
4521
4582
  }
4522
4583
  }),
4523
- (entry.error != null || entry.abortReason != null) && /* @__PURE__ */ jsx18(Icon, {
4584
+ (entry.error != null || entry.abortReason != null) && /* @__PURE__ */ jsx19(Icon, {
4524
4585
  noBackground: true,
4525
4586
  icon: CircleX2,
4526
4587
  color: entry.status === "aborted" ? "aborted" /* aborted */ : "error" /* error */,
4527
4588
  tooltip: {
4528
- content: /* @__PURE__ */ jsx18(ActionErrorDisplay, {
4589
+ content: /* @__PURE__ */ jsx19(ActionErrorDisplay, {
4529
4590
  entry,
4530
4591
  compact: true
4531
4592
  }),
@@ -4540,7 +4601,7 @@ var ActionInputAndOutputChip = ({
4540
4601
  };
4541
4602
 
4542
4603
  // src/devtools/browser/components/action_list/ActionEntryRow.tsx
4543
- import { jsx as jsx19, jsxs as jsxs16, Fragment as Fragment10 } from "react/jsx-runtime";
4604
+ import { jsx as jsx20, jsxs as jsxs17, Fragment as Fragment10 } from "react/jsx-runtime";
4544
4605
  var MAX_GROUP_DOTS = 5;
4545
4606
  function getLatestChipColor(status) {
4546
4607
  if (status === "failed")
@@ -4563,14 +4624,14 @@ function GroupDotTooltip({
4563
4624
  const deltaMs = refTime - entry.startTime;
4564
4625
  const relStr = index === 0 ? "latest run" : `−${formatRelativeAge(deltaMs)} from latest`;
4565
4626
  const durationStr = entry.endTime != null ? `${entry.endTime - entry.startTime}ms` : "running…";
4566
- return /* @__PURE__ */ jsx19(Tooltip, {
4627
+ return /* @__PURE__ */ jsx20(Tooltip, {
4567
4628
  anchor,
4568
4629
  config: {
4569
4630
  align: "center",
4570
4631
  maxWidth: 240,
4571
- content: /* @__PURE__ */ jsxs16(Fragment10, {
4632
+ content: /* @__PURE__ */ jsxs17(Fragment10, {
4572
4633
  children: [
4573
- /* @__PURE__ */ jsxs16("div", {
4634
+ /* @__PURE__ */ jsxs17("div", {
4574
4635
  style: { color: dotColor, marginBottom: "1px" },
4575
4636
  children: [
4576
4637
  symbol,
@@ -4580,15 +4641,15 @@ function GroupDotTooltip({
4580
4641
  total
4581
4642
  ]
4582
4643
  }),
4583
- /* @__PURE__ */ jsx19("div", {
4644
+ /* @__PURE__ */ jsx20("div", {
4584
4645
  style: { color: DEVTOOL_COLOR_TEXT_SECONDARY },
4585
4646
  children: formatTimestamp(entry.startTime)
4586
4647
  }),
4587
- /* @__PURE__ */ jsx19("div", {
4648
+ /* @__PURE__ */ jsx20("div", {
4588
4649
  style: { color: DEVTOOL_COLOR_TEXT_MUTED },
4589
4650
  children: durationStr
4590
4651
  }),
4591
- index > 0 && /* @__PURE__ */ jsx19("div", {
4652
+ index > 0 && /* @__PURE__ */ jsx20("div", {
4592
4653
  style: {
4593
4654
  color: DEVTOOL_COLOR_TEXT_MUTED,
4594
4655
  marginTop: "3px",
@@ -4613,9 +4674,9 @@ function GroupDot({
4613
4674
  const [anchor, setAnchor] = useState10(null);
4614
4675
  const dotColor = STATUS_COLOR[entry.status];
4615
4676
  const hovered = anchor != null;
4616
- return /* @__PURE__ */ jsxs16(Fragment10, {
4677
+ return /* @__PURE__ */ jsxs17(Fragment10, {
4617
4678
  children: [
4618
- /* @__PURE__ */ jsx19("button", {
4679
+ /* @__PURE__ */ jsx20("button", {
4619
4680
  "data-cuid": entry.cuid,
4620
4681
  onClick: (e) => {
4621
4682
  e.stopPropagation();
@@ -4637,7 +4698,7 @@ function GroupDot({
4637
4698
  transition: "transform 0.1s ease, opacity 0.1s ease, border-color 0.1s ease"
4638
4699
  }
4639
4700
  }),
4640
- hovered && anchor != null && /* @__PURE__ */ jsx19(GroupDotTooltip, {
4701
+ hovered && anchor != null && /* @__PURE__ */ jsx20(GroupDotTooltip, {
4641
4702
  entry,
4642
4703
  index,
4643
4704
  total,
@@ -4662,11 +4723,12 @@ function ActionEntryRow({
4662
4723
  }) {
4663
4724
  const timestamp = formatTimestamp(entry.startTime);
4664
4725
  const hasGroup = groupEntries != null && groupEntries.length > 1;
4726
+ const inboundOrigin = getInboundOrigin(entry);
4665
4727
  const externalChildEntries = childEntries?.filter((child) => child.meta.routing[0]?.handlerType === "external") ?? [];
4666
4728
  const nonIoBreakReasons = breakReasons?.filter((r) => r !== "new_input" /* new_input */ && r !== "new_output" /* new_output */) ?? [];
4667
4729
  const hasBottomError = entry.error != null || entry.abortReason != null;
4668
4730
  const hasBottomContent = externalChildEntries.length > 0 || nonIoBreakReasons.length > 0;
4669
- return /* @__PURE__ */ jsxs16("div", {
4731
+ return /* @__PURE__ */ jsxs17("div", {
4670
4732
  "data-cuid": entry.cuid,
4671
4733
  onClick,
4672
4734
  style: {
@@ -4683,7 +4745,7 @@ function ActionEntryRow({
4683
4745
  margin: "2px 4px"
4684
4746
  },
4685
4747
  children: [
4686
- /* @__PURE__ */ jsx19("div", {
4748
+ /* @__PURE__ */ jsx20("div", {
4687
4749
  style: {
4688
4750
  position: "absolute",
4689
4751
  left: "2em",
@@ -4695,10 +4757,10 @@ function ActionEntryRow({
4695
4757
  zIndex: 0
4696
4758
  }
4697
4759
  }),
4698
- /* @__PURE__ */ jsxs16("div", {
4760
+ /* @__PURE__ */ jsxs17("div", {
4699
4761
  style: { display: "flex", alignItems: "center", gap: "8px" },
4700
4762
  children: [
4701
- /* @__PURE__ */ jsx19("div", {
4763
+ /* @__PURE__ */ jsx20("div", {
4702
4764
  style: {
4703
4765
  position: "relative",
4704
4766
  zIndex: 1,
@@ -4708,11 +4770,11 @@ function ActionEntryRow({
4708
4770
  alignItems: "center",
4709
4771
  justifyContent: "flex-start"
4710
4772
  },
4711
- children: isLatest ? /* @__PURE__ */ jsx19(Chip, {
4773
+ children: isLatest ? /* @__PURE__ */ jsx20(Chip, {
4712
4774
  size: "sm" /* sm */,
4713
4775
  color: getLatestChipColor(entry.status),
4714
4776
  children: "latest"
4715
- }) : /* @__PURE__ */ jsxs16(Chip, {
4777
+ }) : /* @__PURE__ */ jsxs17(Chip, {
4716
4778
  size: "sm" /* sm */,
4717
4779
  color: getLatestChipColor(entry.status),
4718
4780
  children: [
@@ -4721,10 +4783,10 @@ function ActionEntryRow({
4721
4783
  ]
4722
4784
  })
4723
4785
  }),
4724
- /* @__PURE__ */ jsxs16("div", {
4786
+ /* @__PURE__ */ jsxs17("div", {
4725
4787
  style: { flex: 1, minWidth: 0, display: "flex", alignItems: "center", gap: "0.5em" },
4726
4788
  children: [
4727
- /* @__PURE__ */ jsx19("span", {
4789
+ /* @__PURE__ */ jsx20("span", {
4728
4790
  style: {
4729
4791
  color: DEVTOOL_COLOR_TEXT_SECONDARY,
4730
4792
  fontSize: "1em",
@@ -4738,14 +4800,19 @@ function ActionEntryRow({
4738
4800
  },
4739
4801
  children: entry.actionId
4740
4802
  }),
4741
- /* @__PURE__ */ jsx19(ActionInputAndOutputChip, {
4803
+ inboundOrigin != null && /* @__PURE__ */ jsx20(OriginChip, {
4804
+ origin: inboundOrigin,
4805
+ size: "sm" /* sm */,
4806
+ subtle: true
4807
+ }),
4808
+ /* @__PURE__ */ jsx20(ActionInputAndOutputChip, {
4742
4809
  breakReasons,
4743
4810
  entry
4744
4811
  }),
4745
- /* @__PURE__ */ jsx19("div", {
4812
+ /* @__PURE__ */ jsx20("div", {
4746
4813
  style: { flex: 1 }
4747
4814
  }),
4748
- /* @__PURE__ */ jsxs16("div", {
4815
+ /* @__PURE__ */ jsxs17("div", {
4749
4816
  style: {
4750
4817
  display: "flex",
4751
4818
  flexDirection: "column",
@@ -4755,7 +4822,7 @@ function ActionEntryRow({
4755
4822
  marginRight: "-0.2em"
4756
4823
  },
4757
4824
  children: [
4758
- /* @__PURE__ */ jsx19("span", {
4825
+ /* @__PURE__ */ jsx20("span", {
4759
4826
  style: {
4760
4827
  display: "flex",
4761
4828
  color: DEVTOOL_COLOR_SEMANTIC_METADATA,
@@ -4768,7 +4835,7 @@ function ActionEntryRow({
4768
4835
  },
4769
4836
  children: timestamp
4770
4837
  }),
4771
- /* @__PURE__ */ jsx19("span", {
4838
+ /* @__PURE__ */ jsx20("span", {
4772
4839
  style: {
4773
4840
  display: "flex",
4774
4841
  color: DEVTOOL_COLOR_SEMANTIC_WARNING,
@@ -4777,7 +4844,7 @@ function ActionEntryRow({
4777
4844
  opacity: 0.9,
4778
4845
  flexShrink: 0
4779
4846
  },
4780
- children: /* @__PURE__ */ jsx19(DurationDisplay, {
4847
+ children: /* @__PURE__ */ jsx20(DurationDisplay, {
4781
4848
  entry
4782
4849
  })
4783
4850
  })
@@ -4787,7 +4854,7 @@ function ActionEntryRow({
4787
4854
  })
4788
4855
  ]
4789
4856
  }),
4790
- hasBottomContent && /* @__PURE__ */ jsxs16("div", {
4857
+ hasBottomContent && /* @__PURE__ */ jsxs17("div", {
4791
4858
  style: {
4792
4859
  display: "flex",
4793
4860
  flexWrap: "wrap",
@@ -4796,35 +4863,35 @@ function ActionEntryRow({
4796
4863
  paddingLeft: "4.5em"
4797
4864
  },
4798
4865
  children: [
4799
- externalChildEntries.map((child) => /* @__PURE__ */ jsxs16(Fragment9, {
4866
+ externalChildEntries.map((child) => /* @__PURE__ */ jsxs17(Fragment9, {
4800
4867
  children: [
4801
- /* @__PURE__ */ jsx19(Icon, {
4868
+ /* @__PURE__ */ jsx20(Icon, {
4802
4869
  size: "sm" /* sm */,
4803
4870
  icon: Variable2,
4804
4871
  color: "io_input" /* io_input */,
4805
4872
  subtle: true,
4806
4873
  tooltip: {
4807
- content: child.input !== undefined ? /* @__PURE__ */ jsx19(IoTooltipContent, {
4874
+ content: child.input !== undefined ? /* @__PURE__ */ jsx20(IoTooltipContent, {
4808
4875
  value: child.input
4809
- }) : /* @__PURE__ */ jsx19("span", {
4876
+ }) : /* @__PURE__ */ jsx20("span", {
4810
4877
  style: { color: DEVTOOL_COLOR_TEXT_MUTED, fontSize: "10px" },
4811
4878
  children: "No input required or given"
4812
4879
  }),
4813
4880
  title: `Input · ${child.actionId}`
4814
4881
  }
4815
4882
  }),
4816
- /* @__PURE__ */ jsx19(HandlerChips, {
4883
+ /* @__PURE__ */ jsx20(HandlerChips, {
4817
4884
  entry: child,
4818
4885
  size: "sm" /* sm */,
4819
4886
  subtle: true
4820
4887
  }),
4821
- child.status === "success" && child.output !== undefined && /* @__PURE__ */ jsx19(Icon, {
4888
+ child.status === "success" && child.output !== undefined && /* @__PURE__ */ jsx20(Icon, {
4822
4889
  size: "sm" /* sm */,
4823
4890
  icon: PackageCheck2,
4824
4891
  color: "io_output" /* io_output */,
4825
4892
  subtle: true,
4826
4893
  tooltip: {
4827
- content: /* @__PURE__ */ jsx19(IoTooltipContent, {
4894
+ content: /* @__PURE__ */ jsx20(IoTooltipContent, {
4828
4895
  value: child.output
4829
4896
  }),
4830
4897
  title: `Output · ${child.actionId}`
@@ -4832,18 +4899,18 @@ function ActionEntryRow({
4832
4899
  })
4833
4900
  ]
4834
4901
  }, child.actionId)),
4835
- nonIoBreakReasons.map((reason) => /* @__PURE__ */ jsx19(Chip, {
4902
+ nonIoBreakReasons.map((reason) => /* @__PURE__ */ jsx20(Chip, {
4836
4903
  color: "default" /* default */,
4837
4904
  subtle: true,
4838
4905
  children: reason
4839
4906
  }, reason)),
4840
- externalChildEntries.length > 0 && hasBottomError && /* @__PURE__ */ jsx19(Icon, {
4907
+ externalChildEntries.length > 0 && hasBottomError && /* @__PURE__ */ jsx20(Icon, {
4841
4908
  size: "sm" /* sm */,
4842
4909
  icon: CircleX3,
4843
4910
  color: entry.status === "aborted" ? "aborted" /* aborted */ : "error" /* error */,
4844
4911
  subtle: true,
4845
4912
  tooltip: {
4846
- content: /* @__PURE__ */ jsx19(ActionErrorDisplay, {
4913
+ content: /* @__PURE__ */ jsx20(ActionErrorDisplay, {
4847
4914
  entry,
4848
4915
  compact: true
4849
4916
  }),
@@ -4853,7 +4920,7 @@ function ActionEntryRow({
4853
4920
  })
4854
4921
  ]
4855
4922
  }),
4856
- hasGroup && /* @__PURE__ */ jsxs16("div", {
4923
+ hasGroup && /* @__PURE__ */ jsxs17("div", {
4857
4924
  style: {
4858
4925
  display: "flex",
4859
4926
  flexWrap: "wrap",
@@ -4863,7 +4930,7 @@ function ActionEntryRow({
4863
4930
  paddingBottom: "2px"
4864
4931
  },
4865
4932
  children: [
4866
- groupEntries.slice(0, MAX_GROUP_DOTS).map((e, i) => /* @__PURE__ */ jsx19(GroupDot, {
4933
+ groupEntries.slice(0, MAX_GROUP_DOTS).map((e, i) => /* @__PURE__ */ jsx20(GroupDot, {
4867
4934
  entry: e,
4868
4935
  index: i,
4869
4936
  total: groupEntries.length,
@@ -4871,7 +4938,7 @@ function ActionEntryRow({
4871
4938
  isActive: selectedGroupCuid === e.cuid,
4872
4939
  onSelect: () => onSelectGroupEntry?.(e.cuid)
4873
4940
  }, e.cuid)),
4874
- groupEntries.length > MAX_GROUP_DOTS && /* @__PURE__ */ jsxs16("span", {
4941
+ groupEntries.length > MAX_GROUP_DOTS && /* @__PURE__ */ jsxs17("span", {
4875
4942
  style: {
4876
4943
  fontSize: "0.7em",
4877
4944
  opacity: 0.5,
@@ -4890,7 +4957,7 @@ function ActionEntryRow({
4890
4957
  }
4891
4958
 
4892
4959
  // src/devtools/browser/components/action_list/ActionList.tsx
4893
- import { jsx as jsx20, jsxs as jsxs17 } from "react/jsx-runtime";
4960
+ import { jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
4894
4961
  function getBreakReasons(current, previous) {
4895
4962
  const reasons = [];
4896
4963
  const inputChanged = current.inputHash != null && previous.inputHash != null ? current.inputHash !== previous.inputHash : safeStringify(current.input, 0) !== safeStringify(previous.input, 0);
@@ -4957,29 +5024,29 @@ function ActionList({
4957
5024
  containerRef.current?.querySelector(`[data-cuid="${repCuid}"]`)?.scrollIntoView({ block: "nearest" });
4958
5025
  }, [selectedCuid, flatItems]);
4959
5026
  if (groups.length === 0) {
4960
- return /* @__PURE__ */ jsx20("div", {
5027
+ return /* @__PURE__ */ jsx21("div", {
4961
5028
  style,
4962
- children: /* @__PURE__ */ jsx20("div", {
5029
+ children: /* @__PURE__ */ jsx21("div", {
4963
5030
  style: { padding: "24px", textAlign: "center", color: DEVTOOL_COLOR_TEXT_MUTED },
4964
5031
  children: "No actions recorded yet"
4965
5032
  })
4966
5033
  });
4967
5034
  }
4968
- return /* @__PURE__ */ jsxs17("div", {
5035
+ return /* @__PURE__ */ jsxs18("div", {
4969
5036
  ref: containerRef,
4970
5037
  style,
4971
5038
  children: [
4972
5039
  flatItems.map((item) => {
4973
5040
  const key = getFlatItemKey(item);
4974
5041
  const { group } = item;
4975
- return /* @__PURE__ */ jsxs17("div", {
5042
+ return /* @__PURE__ */ jsxs18("div", {
4976
5043
  style: {
4977
5044
  borderBottom: `1px solid ${DEVTOOL_LIST_GROUP_DIVIDER}`,
4978
5045
  position: "relative",
4979
5046
  overflow: "hidden"
4980
5047
  },
4981
5048
  children: [
4982
- /* @__PURE__ */ jsx20("div", {
5049
+ /* @__PURE__ */ jsx21("div", {
4983
5050
  style: {
4984
5051
  position: "absolute",
4985
5052
  inset: 0,
@@ -4988,7 +5055,7 @@ function ActionList({
4988
5055
  animation: "__nice-action-shine 0.65s ease-out forwards"
4989
5056
  }
4990
5057
  }, group.representative.cuid),
4991
- /* @__PURE__ */ jsx20(ActionEntryRow, {
5058
+ /* @__PURE__ */ jsx21(ActionEntryRow, {
4992
5059
  entry: group.representative,
4993
5060
  isSelected: selectedCuid === group.representative.cuid || group.rest.some((e) => e.cuid === selectedCuid),
4994
5061
  isLatest: item.groupIndex === 0,
@@ -5003,7 +5070,7 @@ function ActionList({
5003
5070
  ]
5004
5071
  }, key);
5005
5072
  }),
5006
- /* @__PURE__ */ jsx20("div", {
5073
+ /* @__PURE__ */ jsx21("div", {
5007
5074
  style: { padding: "24px", textAlign: "center", color: DEVTOOL_COLOR_TEXT_MUTED },
5008
5075
  children: "Start of action history"
5009
5076
  })
@@ -5013,7 +5080,7 @@ function ActionList({
5013
5080
 
5014
5081
  // src/devtools/browser/components/PanelChrome.tsx
5015
5082
  import { useState as useState11 } from "react";
5016
- import { jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
5083
+ import { jsx as jsx22, jsxs as jsxs19 } from "react/jsx-runtime";
5017
5084
  var MONO_FONT = "ui-monospace, 'Cascadia Code', 'Source Code Pro', monospace";
5018
5085
  var SANS_FONT = "ui-sans-serif, system-ui, sans-serif";
5019
5086
  var DOCKED_SIZE_MIN = 140;
@@ -5047,7 +5114,7 @@ function PanelHeader({
5047
5114
  onClear,
5048
5115
  openOthers
5049
5116
  }) {
5050
- return /* @__PURE__ */ jsxs18("div", {
5117
+ return /* @__PURE__ */ jsxs19("div", {
5051
5118
  style: {
5052
5119
  display: "flex",
5053
5120
  alignItems: "center",
@@ -5059,10 +5126,10 @@ function PanelHeader({
5059
5126
  flexShrink: 0
5060
5127
  },
5061
5128
  children: [
5062
- /* @__PURE__ */ jsxs18("div", {
5129
+ /* @__PURE__ */ jsxs19("div", {
5063
5130
  style: { display: "flex", alignItems: "center", gap: "8px", minWidth: 0 },
5064
5131
  children: [
5065
- /* @__PURE__ */ jsx21("span", {
5132
+ /* @__PURE__ */ jsx22("span", {
5066
5133
  style: {
5067
5134
  color: DEVTOOL_COLOR_SEMANTIC_SYSTEM,
5068
5135
  fontWeight: "bold",
@@ -5071,7 +5138,7 @@ function PanelHeader({
5071
5138
  },
5072
5139
  children: "⚡ action"
5073
5140
  }),
5074
- openOthers?.map((item) => /* @__PURE__ */ jsxs18("button", {
5141
+ openOthers?.map((item) => /* @__PURE__ */ jsxs19("button", {
5075
5142
  onClick: item.onOpen,
5076
5143
  title: `Open ${item.label} devtools`,
5077
5144
  style: {
@@ -5089,13 +5156,13 @@ function PanelHeader({
5089
5156
  whiteSpace: "nowrap"
5090
5157
  },
5091
5158
  children: [
5092
- /* @__PURE__ */ jsx21("span", {
5159
+ /* @__PURE__ */ jsx22("span", {
5093
5160
  children: item.icon
5094
5161
  }),
5095
- /* @__PURE__ */ jsx21("span", {
5162
+ /* @__PURE__ */ jsx22("span", {
5096
5163
  children: item.label
5097
5164
  }),
5098
- item.badge != null && /* @__PURE__ */ jsx21("span", {
5165
+ item.badge != null && /* @__PURE__ */ jsx22("span", {
5099
5166
  style: { color: DEVTOOL_COLOR_SEMANTIC_SYSTEM },
5100
5167
  children: item.badge
5101
5168
  })
@@ -5103,14 +5170,14 @@ function PanelHeader({
5103
5170
  }, item.id))
5104
5171
  ]
5105
5172
  }),
5106
- /* @__PURE__ */ jsxs18("div", {
5173
+ /* @__PURE__ */ jsxs19("div", {
5107
5174
  style: { display: "flex", gap: "10px", alignItems: "center" },
5108
5175
  children: [
5109
- /* @__PURE__ */ jsx21(PositionPicker, {
5176
+ /* @__PURE__ */ jsx22(PositionPicker, {
5110
5177
  position,
5111
5178
  onChange: onPositionChange
5112
5179
  }),
5113
- onClear != null && /* @__PURE__ */ jsx21("button", {
5180
+ onClear != null && /* @__PURE__ */ jsx22("button", {
5114
5181
  onClick: onClear,
5115
5182
  style: {
5116
5183
  background: "none",
@@ -5122,7 +5189,7 @@ function PanelHeader({
5122
5189
  },
5123
5190
  children: "clear"
5124
5191
  }),
5125
- /* @__PURE__ */ jsx21("button", {
5192
+ /* @__PURE__ */ jsx22("button", {
5126
5193
  onClick: onClose,
5127
5194
  style: {
5128
5195
  background: "none",
@@ -5144,17 +5211,17 @@ function PositionPicker({
5144
5211
  position,
5145
5212
  onChange
5146
5213
  }) {
5147
- return /* @__PURE__ */ jsx21("div", {
5214
+ return /* @__PURE__ */ jsx22("div", {
5148
5215
  title: "Move / dock panel",
5149
5216
  style: { display: "grid", gridTemplateColumns: "repeat(3, 9px)", gap: "2px", padding: "2px" },
5150
5217
  children: POSITION_GRID.map(({ key, pos }) => {
5151
5218
  if (pos == null)
5152
- return /* @__PURE__ */ jsx21("div", {
5219
+ return /* @__PURE__ */ jsx22("div", {
5153
5220
  style: { width: "9px", height: "9px" }
5154
5221
  }, key);
5155
5222
  const isTopBottom = pos === "dock-top" || pos === "dock-bottom";
5156
5223
  const isActive = pos === position;
5157
- return /* @__PURE__ */ jsx21("div", {
5224
+ return /* @__PURE__ */ jsx22("div", {
5158
5225
  title: pos,
5159
5226
  onClick: () => onChange(pos),
5160
5227
  style: {
@@ -5165,7 +5232,7 @@ function PositionPicker({
5165
5232
  justifyContent: "center",
5166
5233
  cursor: "pointer"
5167
5234
  },
5168
- children: /* @__PURE__ */ jsx21("div", {
5235
+ children: /* @__PURE__ */ jsx22("div", {
5169
5236
  style: {
5170
5237
  width: isTopBottom ? "9px" : "3px",
5171
5238
  height: isTopBottom ? "3px" : "9px",
@@ -5201,7 +5268,7 @@ function ResizeHandle({
5201
5268
  window.addEventListener("mouseup", onUp);
5202
5269
  };
5203
5270
  const edgeStyle = dockSide === "bottom" ? { top: 0, left: 0, right: 0, height: "5px", cursor: "ns-resize" } : dockSide === "top" ? { bottom: 0, left: 0, right: 0, height: "5px", cursor: "ns-resize" } : dockSide === "right" ? { top: 0, bottom: 0, left: 0, width: "5px", cursor: "ew-resize" } : { top: 0, bottom: 0, right: 0, width: "5px", cursor: "ew-resize" };
5204
- return /* @__PURE__ */ jsx21("div", {
5271
+ return /* @__PURE__ */ jsx22("div", {
5205
5272
  onMouseDown,
5206
5273
  style: {
5207
5274
  position: "absolute",
@@ -5235,7 +5302,7 @@ function SplitHandle({
5235
5302
  window.addEventListener("mousemove", onMove);
5236
5303
  window.addEventListener("mouseup", onUp);
5237
5304
  };
5238
- return /* @__PURE__ */ jsx21("div", {
5305
+ return /* @__PURE__ */ jsx22("div", {
5239
5306
  onMouseDown,
5240
5307
  onMouseEnter: () => setHovered(true),
5241
5308
  onMouseLeave: () => setHovered(false),
@@ -5250,7 +5317,7 @@ function SplitHandle({
5250
5317
  });
5251
5318
  }
5252
5319
  function DevtoolsLauncher({ items }) {
5253
- return /* @__PURE__ */ jsx21("div", {
5320
+ return /* @__PURE__ */ jsx22("div", {
5254
5321
  style: {
5255
5322
  position: "fixed",
5256
5323
  bottom: "16px",
@@ -5260,7 +5327,7 @@ function DevtoolsLauncher({ items }) {
5260
5327
  fontFamily: MONO_FONT,
5261
5328
  fontSize: "12px"
5262
5329
  },
5263
- children: /* @__PURE__ */ jsx21("div", {
5330
+ children: /* @__PURE__ */ jsx22("div", {
5264
5331
  style: {
5265
5332
  display: "flex",
5266
5333
  background: DEVTOOL_SECTION_BACKGROUND,
@@ -5269,7 +5336,7 @@ function DevtoolsLauncher({ items }) {
5269
5336
  overflow: "hidden",
5270
5337
  boxShadow: "0 8px 24px rgba(0,0,0,0.35)"
5271
5338
  },
5272
- children: items.map((item, i) => /* @__PURE__ */ jsxs18("button", {
5339
+ children: items.map((item, i) => /* @__PURE__ */ jsxs19("button", {
5273
5340
  onClick: item.onOpen,
5274
5341
  style: {
5275
5342
  display: "flex",
@@ -5286,13 +5353,13 @@ function DevtoolsLauncher({ items }) {
5286
5353
  lineHeight: "1.5"
5287
5354
  },
5288
5355
  children: [
5289
- /* @__PURE__ */ jsx21("span", {
5356
+ /* @__PURE__ */ jsx22("span", {
5290
5357
  children: item.icon
5291
5358
  }),
5292
- /* @__PURE__ */ jsx21("span", {
5359
+ /* @__PURE__ */ jsx22("span", {
5293
5360
  children: item.label
5294
5361
  }),
5295
- item.badge != null && /* @__PURE__ */ jsx21("span", {
5362
+ item.badge != null && /* @__PURE__ */ jsx22("span", {
5296
5363
  style: { color: DEVTOOL_COLOR_SEMANTIC_SYSTEM },
5297
5364
  children: item.badge
5298
5365
  })
@@ -5410,7 +5477,7 @@ function getDevtoolsDockCoordinator() {
5410
5477
  }
5411
5478
 
5412
5479
  // src/devtools/browser/NiceActionDevtools.tsx
5413
- import { jsx as jsx22, jsxs as jsxs19, Fragment as Fragment11 } from "react/jsx-runtime";
5480
+ import { jsx as jsx23, jsxs as jsxs20, Fragment as Fragment11 } from "react/jsx-runtime";
5414
5481
  if (typeof document !== "undefined" && !document.getElementById("__nice-action-devtools-styles")) {
5415
5482
  const style = document.createElement("style");
5416
5483
  style.id = "__nice-action-devtools-styles";
@@ -5514,7 +5581,7 @@ function NiceActionDevtools({ forceEnable, ...props }) {
5514
5581
  if (!forceEnable && process["env"]["NODE_ENV"] !== "development") {
5515
5582
  return null;
5516
5583
  }
5517
- return /* @__PURE__ */ jsx22(NiceActionDevtools_Panel, {
5584
+ return /* @__PURE__ */ jsx23(NiceActionDevtools_Panel, {
5518
5585
  ...props
5519
5586
  });
5520
5587
  }
@@ -5601,7 +5668,7 @@ function NiceActionDevtools_Panel({
5601
5668
  };
5602
5669
  if (!isOpen) {
5603
5670
  if (view.isPrimary && !view.anyOpen) {
5604
- return /* @__PURE__ */ jsx22(DevtoolsLauncher, {
5671
+ return /* @__PURE__ */ jsx23(DevtoolsLauncher, {
5605
5672
  items: view.devtools
5606
5673
  });
5607
5674
  }
@@ -5653,16 +5720,16 @@ function NiceActionDevtools_Panel({
5653
5720
  },
5654
5721
  childEntriesMap
5655
5722
  };
5656
- return /* @__PURE__ */ jsxs19("div", {
5723
+ return /* @__PURE__ */ jsxs20("div", {
5657
5724
  id: "__nice-action-devtools-panel",
5658
5725
  style: panelStyle,
5659
5726
  children: [
5660
- /* @__PURE__ */ jsx22(ResizeHandle, {
5727
+ /* @__PURE__ */ jsx23(ResizeHandle, {
5661
5728
  dockSide,
5662
5729
  dockedSize,
5663
5730
  onChange: (size) => setPrefs(isHorizDock ? { dockedHeight: size } : { dockedWidth: size })
5664
5731
  }),
5665
- /* @__PURE__ */ jsx22(PanelHeader, {
5732
+ /* @__PURE__ */ jsx23(PanelHeader, {
5666
5733
  position,
5667
5734
  onPositionChange: (p) => setPrefs({ position: p }),
5668
5735
  onClose: () => setPrefs({ isOpen: false }),
@@ -5672,7 +5739,7 @@ function NiceActionDevtools_Panel({
5672
5739
  } : undefined,
5673
5740
  openOthers: view.otherClosed
5674
5741
  }),
5675
- /* @__PURE__ */ jsxs19("div", {
5742
+ /* @__PURE__ */ jsxs20("div", {
5676
5743
  style: {
5677
5744
  flex: 1,
5678
5745
  display: "flex",
@@ -5681,7 +5748,7 @@ function NiceActionDevtools_Panel({
5681
5748
  minHeight: 0
5682
5749
  },
5683
5750
  children: [
5684
- /* @__PURE__ */ jsx22("div", {
5751
+ /* @__PURE__ */ jsx23("div", {
5685
5752
  style: {
5686
5753
  flexGrow: selectedEntry != null ? 1 - detailRatio : 1,
5687
5754
  flexShrink: 1,
@@ -5689,18 +5756,18 @@ function NiceActionDevtools_Panel({
5689
5756
  minWidth: 0,
5690
5757
  minHeight: 0
5691
5758
  },
5692
- children: /* @__PURE__ */ jsx22(ActionList, {
5759
+ children: /* @__PURE__ */ jsx23(ActionList, {
5693
5760
  ...virtualListProps,
5694
5761
  style: { width: "100%", height: "100%", overflowY: "auto" }
5695
5762
  })
5696
5763
  }),
5697
- selectedEntry != null && /* @__PURE__ */ jsxs19(Fragment11, {
5764
+ selectedEntry != null && /* @__PURE__ */ jsxs20(Fragment11, {
5698
5765
  children: [
5699
- /* @__PURE__ */ jsx22(SplitHandle, {
5766
+ /* @__PURE__ */ jsx23(SplitHandle, {
5700
5767
  horizontal: isHorizDock,
5701
5768
  onRatioChange: (ratio) => setPrefs({ detailRatio: ratio })
5702
5769
  }),
5703
- /* @__PURE__ */ jsx22("div", {
5770
+ /* @__PURE__ */ jsx23("div", {
5704
5771
  style: {
5705
5772
  flexGrow: detailRatio,
5706
5773
  flexShrink: 1,
@@ -5718,7 +5785,7 @@ function NiceActionDevtools_Panel({
5718
5785
  boxShadow: "inset 0 18px 36px -14px rgba(0,0,0,0.8)"
5719
5786
  }
5720
5787
  },
5721
- children: /* @__PURE__ */ jsx22(ActionDetailPanel, {
5788
+ children: /* @__PURE__ */ jsx23(ActionDetailPanel, {
5722
5789
  entry: selectedEntry,
5723
5790
  parent: selectedEntryParent,
5724
5791
  childEntries: selectedEntryChildren,
package/build/index.js CHANGED
@@ -965,6 +965,7 @@ class ActionRuntime {
965
965
  }
966
966
  async handleActionPayload(action, options) {
967
967
  if (action.type === "request" /* request */) {
968
+ const observers = action.context._domain._collectActionObservers();
968
969
  let handlerForAction;
969
970
  try {
970
971
  handlerForAction = this.getHandlerForActionOrThrow(action, options);
@@ -973,6 +974,7 @@ class ActionRuntime {
973
974
  context: action.context,
974
975
  request: action
975
976
  });
977
+ runningAction2.addUpdateListeners(observers);
976
978
  runningAction2._completeWithResult(action.errorResult(castNiceError(err2)));
977
979
  return runningAction2;
978
980
  }
@@ -980,6 +982,7 @@ class ActionRuntime {
980
982
  ...options,
981
983
  targetLocalRuntime: this
982
984
  });
985
+ runningAction.addUpdateListeners(observers);
983
986
  this._trySetupReturnDispatch(runningAction);
984
987
  return runningAction;
985
988
  }
@@ -1293,6 +1296,9 @@ class ActionDomainBase {
1293
1296
  this._listeners = this._listeners.filter((l) => l !== listener);
1294
1297
  };
1295
1298
  }
1299
+ _getActionObservers() {
1300
+ return this._listeners;
1301
+ }
1296
1302
  }
1297
1303
 
1298
1304
  // src/ActionDefinition/Domain/ActionDomain.ts
@@ -1309,6 +1315,9 @@ class ActionDomain extends ActionDomainBase {
1309
1315
  get rootDomain() {
1310
1316
  return this._rootDomain;
1311
1317
  }
1318
+ _collectActionObservers() {
1319
+ return [...this._rootDomain._getActionObservers(), ...this._getActionObservers()];
1320
+ }
1312
1321
  _registerRuntime(runtime2) {
1313
1322
  this._rootDomain._registerRuntime(runtime2);
1314
1323
  }
@@ -0,0 +1,15 @@
1
+ import { ESize } from "../ui_util/size";
2
+ /**
3
+ * Marks an action that was received from another runtime (a backend push, or an action relayed from
4
+ * another client) rather than dispatched locally. The chip shows the origin's `envId`; the tooltip
5
+ * carries the full coordinate. Render it only when {@link getInboundOrigin} returns a value.
6
+ */
7
+ export declare function OriginChip({ origin, size, subtle, }: {
8
+ origin: {
9
+ envId: string;
10
+ perId?: string;
11
+ insId?: string;
12
+ };
13
+ size?: ESize;
14
+ subtle?: boolean;
15
+ }): import("react/jsx-runtime").JSX.Element;
@@ -5,6 +5,17 @@ export declare const STATUS_COLOR: Record<TDevtoolsActionStatus, string>;
5
5
  export declare const STATUS_THING: Record<TDevtoolsActionStatus, ESemanticThing>;
6
6
  export declare const STATUS_SYMBOL: Record<TDevtoolsActionStatus, string>;
7
7
  export declare const STATUS_ICON: Record<TDevtoolsActionStatus, LucideIcon>;
8
+ /**
9
+ * The runtime an action *originated* on, when that differs from the runtime that handled it — i.e. an
10
+ * inbound action received over a transport (a backend push, or an action relayed from another client),
11
+ * rather than one dispatched locally. Returns `null` for locally-originated actions (where the origin
12
+ * matches the handling runtime) and for actions with no known origin.
13
+ */
14
+ export declare function getInboundOrigin(entry: IDevtoolsActionEntry): {
15
+ envId: string;
16
+ perId?: string;
17
+ insId?: string;
18
+ } | null;
8
19
  export declare function safeStringify(value: unknown, indent?: number): string;
9
20
  export declare function formatRelativeAge(ms: number): string;
10
21
  export declare function formatDuration(entry: IDevtoolsActionEntry): string | null;
@@ -54,6 +54,7 @@ export declare enum ESemanticThing {
54
54
  domain = "domain",
55
55
  handler_local = "handler_local",
56
56
  handler_external = "handler_external",
57
+ origin = "origin",// runtime an action was received from (inbound / pushed actions)
57
58
  age = "age",// non-latest relative-age chip
58
59
  io_input = "io_input",
59
60
  io_output = "io_output",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nice-code/action",
3
- "version": "0.6.1",
3
+ "version": "0.6.2",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "exports": {
@@ -44,9 +44,9 @@
44
44
  "build-types": "tsc --project tsconfig.build.json"
45
45
  },
46
46
  "dependencies": {
47
- "@nice-code/common-errors": "0.6.1",
48
- "@nice-code/error": "0.6.1",
49
- "@nice-code/util": "0.6.1",
47
+ "@nice-code/common-errors": "0.6.2",
48
+ "@nice-code/error": "0.6.2",
49
+ "@nice-code/util": "0.6.2",
50
50
  "@standard-schema/spec": "^1.1.0",
51
51
  "@tanstack/react-virtual": "^3.13.26",
52
52
  "http-status-codes": "^2.3.0",