by-framework 0.2.2.dev13__py3-none-any.whl → 0.2.2.dev15__py3-none-any.whl

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.
@@ -971,6 +971,12 @@ class GatewayClient:
971
971
  "parent_message_id": params["parent_message_id"] or "",
972
972
  "source_agent_type": CLIENT_SOURCE_AGENT_TYPE,
973
973
  "target_agent_type": params["target_agent_type"],
974
+ # What this execution was dispatched with, so a worker
975
+ # can restore it after the execution suspends and
976
+ # resumes (see worker/_resume_metadata.py). Only the
977
+ # non-RESUME branch reaches here, so this never
978
+ # overwrites a suspended execution's original.
979
+ "metadata": dict(metadata or {}),
974
980
  "stream_name": route.stream_name,
975
981
  "status": "QUEUED",
976
982
  "route_policy": route_policy,
@@ -367,6 +367,60 @@ _CATALOG: dict[str, MetricDefinition] = {
367
367
  "Instrumentation reliability signal pinpointing exporter failures."
368
368
  ),
369
369
  ),
370
+ # Self-monitoring for the background collector in metrics/collector.py.
371
+ # Exactly one process holds its Redis lock and writes history points, so
372
+ # these answer "is anyone still collecting?" — a gap here means the
373
+ # dashboards go stale silently rather than erroring.
374
+ "by_framework_metrics_collector_cycles_total": MetricDefinition(
375
+ name="by_framework_metrics_collector_cycles_total",
376
+ kind=MetricKind.COUNTER,
377
+ unit=MetricUnit.NONE,
378
+ labels=("result",),
379
+ description=(
380
+ "Metrics collector cycles by result "
381
+ "(success, snapshot_failed, lock_skipped, disabled)."
382
+ ),
383
+ interpretation=(
384
+ "Collector health signal: only the lock holder reports success, so "
385
+ "lock_skipped dominating across a fleet is expected."
386
+ ),
387
+ ),
388
+ "by_framework_metrics_collector_snapshot_duration_ms": MetricDefinition(
389
+ name="by_framework_metrics_collector_snapshot_duration_ms",
390
+ kind=MetricKind.HISTOGRAM,
391
+ unit=MetricUnit.MILLISECONDS,
392
+ description=(
393
+ "Duration of one collector snapshot build plus history write."
394
+ ),
395
+ interpretation=(
396
+ "Latency signal for collection itself; approaching the collection "
397
+ "interval means cycles are about to overlap."
398
+ ),
399
+ ),
400
+ "by_framework_metrics_collector_lock_held": MetricDefinition(
401
+ name="by_framework_metrics_collector_lock_held",
402
+ kind=MetricKind.GAUGE,
403
+ unit=MetricUnit.NONE,
404
+ description=(
405
+ "Whether this process currently holds the metrics collector lock."
406
+ ),
407
+ interpretation=(
408
+ "Saturation signal: should sum to 1 across the fleet — 0 means "
409
+ "nobody is collecting, above 1 means the lock split."
410
+ ),
411
+ ),
412
+ "by_framework_metrics_collector_last_success_timestamp_ms": MetricDefinition(
413
+ name="by_framework_metrics_collector_last_success_timestamp_ms",
414
+ kind=MetricKind.GAUGE,
415
+ unit=MetricUnit.MILLISECONDS,
416
+ description=(
417
+ "Unix timestamp in milliseconds of the last successful collection."
418
+ ),
419
+ interpretation=(
420
+ "Freshness signal: alert on now minus this value exceeding a few "
421
+ "collection intervals."
422
+ ),
423
+ ),
370
424
  }
371
425
 
372
426
 
@@ -0,0 +1,65 @@
1
+ """The inbound half of a resumed execution's metadata.
2
+
3
+ Two different directions restore metadata on a resume, and they are NOT the
4
+ same rule. Keep them apart:
5
+
6
+ - **Outbound** (``GatewayWorker._resolve_reply_command`` /
7
+ ``GatewayProcessor._resolve_reply_header``): the header a resumed execution
8
+ *sends* to its caller. The stored dispatch metadata **replaces**
9
+ ``header.metadata`` wholesale — the waking hop's data is plumbing the
10
+ original caller never asked for, and ``_enqueue_agent_return``'s
11
+ ``{**header.metadata, **task_result.metadata}`` is the one sanctioned
12
+ channel for a handler to forward part of it.
13
+ - **Inbound** (this module): the header a resumed execution's own handler
14
+ *reads*. Here the waking message's metadata is legitimate payload — an
15
+ ``ask_user`` answer's metadata was sent BY a client TO this agent — so it is
16
+ merged on top of the original dispatch metadata rather than discarded.
17
+
18
+ Without this, everything a handler was originally dispatched with disappears
19
+ the first time it suspends: it comes back seeing only whatever woke it up.
20
+ """
21
+
22
+ from typing import Any, Mapping, Optional
23
+
24
+ # Injected per dispatch by AgentContext._dispatch_single_task, not supplied by
25
+ # business code. A stored copy of them is stale by definition — it describes
26
+ # the hop that dispatched the execution, not the hop resuming it now — so they
27
+ # are dropped from the restored base and always come from the current message.
28
+ # Letting them through would surface a dispatch-time span id where the waking
29
+ # message has none, and AgentContext._resolve_call_langfuse_parent_id() reads
30
+ # exactly that as its last-resort fallback: a call made after a resume would
31
+ # parent to the original dispatch's observation.
32
+ FRAMEWORK_HOP_METADATA_KEYS = frozenset(
33
+ {
34
+ "trace_parent_span_id",
35
+ "framework_parent_span_id",
36
+ "langfuse_parent_observation_id",
37
+ }
38
+ )
39
+
40
+
41
+ def merge_resume_metadata(
42
+ stored: Optional[Mapping[str, Any]],
43
+ incoming: Optional[Mapping[str, Any]],
44
+ ) -> dict[str, Any]:
45
+ """Merge an execution's original dispatch metadata under this hop's.
46
+
47
+ ``stored`` is the ``metadata`` field of the execution record (what the
48
+ execution was originally dispatched with); ``incoming`` is the waking
49
+ message's own metadata. The waking message wins on key collisions: it is
50
+ the newer, more specific hop, and this keeps the property that every key a
51
+ handler can read today stays readable — the restore only ever adds keys.
52
+
53
+ A ``stored`` that is missing (an execution recorded before this field
54
+ existed, or one dispatched by an SDK that doesn't write it) degrades to
55
+ ``incoming`` unchanged, i.e. exactly the pre-restore behaviour.
56
+
57
+ Neither argument is mutated.
58
+ """
59
+ merged = {
60
+ key: value
61
+ for key, value in (stored or {}).items()
62
+ if key not in FRAMEWORK_HOP_METADATA_KEYS
63
+ }
64
+ merged.update(incoming or {})
65
+ return merged
@@ -24,6 +24,7 @@ from by_framework.core.protocol.results import (
24
24
  from by_framework.core.runtime.file_permissions import FilePermissionPolicy
25
25
  from by_framework.core.wait_gate import consume_wait_entry, emit_orphaned_reply
26
26
  from by_framework.core.wait_reply import flush_pending_group_replies
27
+ from by_framework.worker._resume_metadata import merge_resume_metadata
27
28
  from by_framework.worker.context import AgentContext
28
29
 
29
30
  ContextHandler = Callable[
@@ -99,8 +100,18 @@ class GatewayProcessor:
99
100
  )
100
101
  return None
101
102
 
102
- reply_header = await self._resolve_reply_header(command)
103
+ # One lookup feeds both directions: the header this execution replies
104
+ # with, and the header its own handler reads. They are different
105
+ # rules over the same record — see _resolve_reply_header and
106
+ # _restore_inbound_metadata.
107
+ snapshot = (
108
+ await self._load_execution_snapshot(command) if is_agent_return else None
109
+ )
110
+ raw_command = command
111
+ reply_header = self._resolve_reply_header(command, snapshot)
103
112
  has_source_agent = reply_header is not None
113
+ command = self._restore_inbound_metadata(command, is_agent_return, snapshot)
114
+ header = command.header
104
115
 
105
116
  context = AgentContext(
106
117
  session_id=header.session_id,
@@ -163,8 +174,10 @@ class GatewayProcessor:
163
174
  getattr(context, "_is_suspended", False)
164
175
  ) and not is_terminal_state(task_result.status)
165
176
  if has_source_agent and not is_suspended:
177
+ # raw_command, not the inbound-restored one: the reply is the
178
+ # outbound direction and must not inherit the inbound merge.
166
179
  await self._enqueue_callback(
167
- command,
180
+ raw_command,
168
181
  task_result.status,
169
182
  task_result.reply_data,
170
183
  content=task_result.content,
@@ -210,7 +223,7 @@ class GatewayProcessor:
210
223
 
211
224
  if has_source_agent:
212
225
  await self._enqueue_callback(
213
- command,
226
+ raw_command,
214
227
  AgentState.FAILED.value,
215
228
  {"error": str(e)},
216
229
  reply_header=reply_header,
@@ -221,47 +234,101 @@ class GatewayProcessor:
221
234
  )
222
235
  raise
223
236
 
224
- async def _resolve_reply_header(
237
+ async def _load_execution_snapshot(
225
238
  self, command: GatewayCommand
226
- ) -> Optional[MessageHeader]:
227
- """Return the header describing the caller this execution owes a reply
228
- to, or None when nobody is waiting.
239
+ ) -> Optional[dict[str, Any]]:
240
+ """Read the execution record the original dispatch wrote.
229
241
 
230
- Mirrors ``GatewayWorker._resolve_reply_command``: a resume's header
231
- describes the sub-agent that just finished, so the caller has to be
232
- read back from the execution record the original dispatch wrote — and,
233
- for the same reason as there, ``CLIENT_SOURCE_AGENT_TYPE`` is not a
234
- caller. It is what a client writes on a root execution's record, and
235
- nothing consumes its control stream.
242
+ Fetched once per resume and shared by both restore directions.
243
+ Fail-soft: a registry error degrades to "no record", which each caller
244
+ then handles as its own no-op.
236
245
  """
237
246
  header = command.header
238
- if not isinstance(command, ResumeCommand):
239
- return header if header.source_agent_type else None
240
-
241
- execution: Optional[dict[str, Any]] = None
242
247
  try:
243
248
  from by_framework.core.registry import WorkerRegistry
244
249
 
245
- execution = await WorkerRegistry(self.redis).get_execution_by_message_id(
250
+ return await WorkerRegistry(self.redis).get_execution_by_message_id(
246
251
  header.message_id, session_id=header.session_id
247
252
  )
248
253
  except Exception as error: # pylint: disable=broad-exception-caught
249
254
  self.logger.warning(
250
- "[%s] Could not resolve the caller of resumed execution %s: %s",
255
+ "[%s] Could not load the execution record of resumed execution "
256
+ "%s: %s",
251
257
  self.worker_id,
252
258
  header.message_id,
253
259
  error,
254
260
  )
255
261
  return None
256
262
 
257
- caller_agent_type = str((execution or {}).get("source_agent_type", "") or "")
263
+ def _resolve_reply_header(
264
+ self,
265
+ command: GatewayCommand,
266
+ snapshot: Optional[dict[str, Any]],
267
+ ) -> Optional[MessageHeader]:
268
+ """Return the header describing the caller this execution owes a reply
269
+ to, or None when nobody is waiting.
270
+
271
+ Mirrors ``GatewayWorker._resolve_reply_command``: a resume's header
272
+ describes the sub-agent that just finished, so the caller has to be
273
+ read back from the execution record the original dispatch wrote — and,
274
+ for the same reason as there, ``CLIENT_SOURCE_AGENT_TYPE`` is not a
275
+ caller. It is what a client writes on a root execution's record, and
276
+ nothing consumes its control stream.
277
+
278
+ Four fields come from that snapshot, not from the waking message:
279
+ ``source_agent_type``, ``parent_message_id``, ``task_group_id`` and
280
+ ``metadata``. The last one is restored as a full replacement rather
281
+ than a merge, exactly as ``GatewayWorker._resolve_reply_command``
282
+ does it: the waking message (an ``ask_user`` answer, or a sub-call's
283
+ reply) is transient plumbing for that one hop, not something the
284
+ caller ever sent. A snapshot missing the field (an execution recorded
285
+ before it existed) degrades to an empty dict rather than leaking the
286
+ waking message's metadata to the caller.
287
+
288
+ This is the OUTBOUND direction only. What the handler itself reads is
289
+ ``_restore_inbound_metadata``, which merges rather than replaces —
290
+ and which must run even when this returns None, since a
291
+ client-dispatched root has no caller but still has its own metadata
292
+ to get back.
293
+ """
294
+ header = command.header
295
+ if not isinstance(command, ResumeCommand):
296
+ return header if header.source_agent_type else None
297
+
298
+ caller_agent_type = str((snapshot or {}).get("source_agent_type", "") or "")
258
299
  if not caller_agent_type or caller_agent_type == CLIENT_SOURCE_AGENT_TYPE:
259
300
  return None
260
301
  return replace(
261
302
  header,
262
303
  source_agent_type=caller_agent_type,
263
- parent_message_id=str((execution or {}).get("parent_message_id", "") or ""),
264
- task_group_id=str((execution or {}).get("task_group_id", "") or ""),
304
+ parent_message_id=str((snapshot or {}).get("parent_message_id", "") or ""),
305
+ task_group_id=str((snapshot or {}).get("task_group_id", "") or ""),
306
+ metadata=dict((snapshot or {}).get("metadata") or {}),
307
+ )
308
+
309
+ @staticmethod
310
+ def _restore_inbound_metadata(
311
+ command: GatewayCommand,
312
+ is_agent_return: bool,
313
+ snapshot: Optional[dict[str, Any]],
314
+ ) -> GatewayCommand:
315
+ """Give a resumed handler its own dispatch metadata back.
316
+
317
+ Mirrors ``GatewayWorker._restore_inbound_metadata``, including its
318
+ merge-don't-replace rule and its no-mutation rule; see that docstring
319
+ for why the inbound direction differs from the outbound one.
320
+ """
321
+ if not is_agent_return:
322
+ return command
323
+ return replace(
324
+ command,
325
+ header=replace(
326
+ command.header,
327
+ metadata=merge_resume_metadata(
328
+ (snapshot or {}).get("metadata"),
329
+ command.header.metadata,
330
+ ),
331
+ ),
265
332
  )
266
333
 
267
334
  async def _enqueue_callback(
@@ -625,11 +625,33 @@ class WorkerRunner:
625
625
  if registry:
626
626
  if existing_execution:
627
627
  if hasattr(registry, "update_execution_status"):
628
+ status_fields: dict[str, Any] = {
629
+ "worker_id": self.worker.worker_id
630
+ }
631
+ if not isinstance(command, ResumeCommand):
632
+ # The dispatch metadata, recorded by whoever is
633
+ # executing the message rather than by whoever
634
+ # sent it: header.metadata IS the dispatch
635
+ # metadata by definition, so this is correct for
636
+ # every dispatcher — including a client root
637
+ # dispatch and a TS/Java caller, neither of which
638
+ # writes the field (see context.py's
639
+ # initialize_execution, which does, and is kept
640
+ # because it is the only record that exists
641
+ # before a callee is ever picked up).
642
+ # _handle_message reads it back to restore what
643
+ # this execution was originally asked for once it
644
+ # resumes.
645
+ #
646
+ # A ResumeCommand must NOT write it: the waking
647
+ # message's metadata would overwrite the very
648
+ # original this exists to preserve.
649
+ status_fields["metadata"] = dict(header.metadata)
628
650
  await registry.update_execution_status(
629
651
  execution_id,
630
652
  header.session_id,
631
653
  "RUNNING",
632
- worker_id=self.worker.worker_id,
654
+ **status_fields,
633
655
  )
634
656
  elif hasattr(registry, "save_execution"):
635
657
  await registry.save_execution(
@@ -641,6 +663,12 @@ class WorkerRunner:
641
663
  "parent_message_id": header.parent_message_id or "",
642
664
  "worker_id": self.worker.worker_id,
643
665
  "target_agent_type": header.target_agent_type,
666
+ # Same reason as the update branch above. This one
667
+ # is the no-existing-record fallback, so there is
668
+ # no stored original to protect and no ResumeCommand
669
+ # guard to make: whatever woke this is all this
670
+ # execution has ever been told.
671
+ "metadata": dict(header.metadata),
644
672
  "stream_name": stream_name,
645
673
  "redis_message_id": msg_id,
646
674
  "status": "RUNNING",
@@ -59,6 +59,7 @@ from by_framework.trace.span_recorder import TraceSpan, str_to_uint64
59
59
  from by_framework.worker.context import AgentContext, current_agent_context_var
60
60
  from by_framework.worker.heartbeat import WorkerHeartbeat
61
61
 
62
+ from ._resume_metadata import merge_resume_metadata
62
63
  from .sandbox.hook_sandbox import active_workspace
63
64
 
64
65
 
@@ -377,6 +378,47 @@ class GatewayWorker(ABC):
377
378
  ),
378
379
  )
379
380
 
381
+ @staticmethod
382
+ def _restore_inbound_metadata(
383
+ command: GatewayCommand,
384
+ is_agent_return: bool,
385
+ execution: Optional["RunningExecution"],
386
+ ) -> GatewayCommand:
387
+ """Give a resumed handler its own dispatch metadata back.
388
+
389
+ The mirror image of ``_resolve_reply_command``, and deliberately not
390
+ the same rule. That one rebuilds the header this execution *sends*;
391
+ this one rebuilds the header it *reads*. A resumed handler otherwise
392
+ sees only the metadata of whatever woke it up — an ``ask_user``
393
+ answer's, or a sub-call's reply — and everything the execution was
394
+ originally dispatched with is gone from the moment it first suspends.
395
+
396
+ Merged, not replaced (the opposite of the outbound direction): this
397
+ agent IS the addressee of the waking message, so its metadata is real
398
+ payload here rather than someone else's plumbing. Original dispatch
399
+ metadata is the base, the waking message wins on collisions. See
400
+ ``_resume_metadata.py`` for why the framework's per-hop trace keys are
401
+ excluded from the base.
402
+
403
+ Returns a NEW command — never mutates. ``prepare_command_for_processing``
404
+ returns the *same* object for the base worker (only ``ByaiWorker``
405
+ rebuilds it), so mutating the header here would also rewrite
406
+ ``raw_command``'s and leak this merge into the reply that goes out.
407
+ """
408
+ if not is_agent_return:
409
+ return command
410
+ snapshot = getattr(execution, "existing_data", None) or {}
411
+ return replace(
412
+ command,
413
+ header=replace(
414
+ command.header,
415
+ metadata=merge_resume_metadata(
416
+ snapshot.get("metadata"),
417
+ command.header.metadata,
418
+ ),
419
+ ),
420
+ )
421
+
380
422
  @staticmethod
381
423
  def _apply_suspended_status(
382
424
  task_result: AgentTaskResult,
@@ -682,6 +724,7 @@ class GatewayWorker(ABC):
682
724
  is_agent_return = isinstance(raw_command, ResumeCommand)
683
725
  reply_command = self._resolve_reply_command(raw_command, execution)
684
726
  has_source_agent = reply_command is not None
727
+ command = self._restore_inbound_metadata(command, is_agent_return, execution)
685
728
 
686
729
  # Get workspace dir from workspace_manager if available
687
730
  # Note: We don't use hasattr check because it doesn't work well with mocks
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: by-framework
3
- Version: 0.2.2.dev13
3
+ Version: 0.2.2.dev15
4
4
  Summary: 分布式 Agent 调度框架
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.12
@@ -5,7 +5,7 @@ by_framework/admin/cli.py,sha256=YW4tQxb0kBheRNQR53zOkoAlYHWP4bgycuZkaJIU3WA,119
5
5
  by_framework/admin/worker_manager.py,sha256=ihXRMlFJAR74T2JSh3xTNCDjzAElWd0-_yVDAZwSTJU,5924
6
6
  by_framework/client/__init__.py,sha256=kGP7uoXIlTJuiJ2Cgl1Q5wqYjnMA4SZqoa7Q7BhQ5JQ,272
7
7
  by_framework/client/byai_client.py,sha256=bB1NyKLvVW82bXefD_3zymqZ1vk2O925CIbxOho9Qww,2426
8
- by_framework/client/client.py,sha256=_zVSzEFOz6c4LYnsmPbRazGVo_ZdNfuOLk93Py7ufAI,45235
8
+ by_framework/client/client.py,sha256=XcI29Jm9ktb74cq-VcUoMl0lyIfAvGrSRcS4CttATug,45666
9
9
  by_framework/common/__init__.py,sha256=EkfIiVdmb8SCpi7OOUm6Hu84B7Wzekb-TG2hbvD_R1w,1685
10
10
  by_framework/common/config.py,sha256=mTbCn3YspY8k00b4URSbi07MNC3Cfdj7RPtDLrXrJV8,5107
11
11
  by_framework/common/constants.py,sha256=sZOUw5rlwszzsYO57yUHXI4zyrEuwka2cOyji_jblRE,34857
@@ -69,7 +69,7 @@ by_framework/errors/http.py,sha256=xtm4EKwbE1Z0n4yqWTjPOVbDd9fIPfmT8W4ou5aOLCQ,7
69
69
  by_framework/errors/protocol.py,sha256=MWr15TFIHs8Ql67mgvU9mebGdE04yPxmg4AOEGbF9E4,1269
70
70
  by_framework/errors/registry.py,sha256=LmcqSXiW8FSOghpLPHTllkbrQCnVcMYTLzO2cNU3wIw,842
71
71
  by_framework/metrics/__init__.py,sha256=8AQpVnOwAmHoQsDhCfkNXSKUOX_ZCBF_QajBXmsNhgc,11353
72
- by_framework/metrics/catalog.py,sha256=CR9-1M_L0rR-5jgGUw3M1TplTzntpTjN2MXG34s9lnw,17355
72
+ by_framework/metrics/catalog.py,sha256=1yWxVCvvrbkT0Rdmi0x-rtRwtXFzQg6Dmuj75izN2X0,19684
73
73
  by_framework/metrics/collector.py,sha256=uIO2TJfX4zQTBi5gWbMfgwtdMjrhmhzjzW36BcqxBKE,8533
74
74
  by_framework/metrics/read_client.py,sha256=kcgHJlJh47eFPhlbH8QOyD-K6SpKbZHEX624XD6Mvxo,18511
75
75
  by_framework/metrics/snapshot.py,sha256=eI4JVV3uma7fT6nvp2bliO2ZUBJhJT6bzTvQDIeC-wk,101784
@@ -86,19 +86,20 @@ by_framework/worker/__init__.py,sha256=GBkUWYnHc2j3_Wx2AC2P49DzFl0CSrl0SKhdRP5CT
86
86
  by_framework/worker/_control_handling.py,sha256=0bL1Alx8_qaeXQV32Xv4ARSd9q77ySh9LMd7KtZZXu8,8111
87
87
  by_framework/worker/_execution_tracking.py,sha256=AWahfDKTXGrx_JWSCNisjGKkGAQruu9vSlXisof0BYQ,2493
88
88
  by_framework/worker/_message_processing.py,sha256=rgKzJTgPVDFp_HUfMcqJBwNdTCEfspuRAo5IM9VKsxs,2622
89
+ by_framework/worker/_resume_metadata.py,sha256=bo3OiO_E5e6PaGcKRzwDdEKjFjMTe2d26aRPCpFSSBg,2938
89
90
  by_framework/worker/app.py,sha256=UHaQZzalqfPmHvfq-XL7vlPOJ8mTm5ULIU4JpeXA85g,16319
90
91
  by_framework/worker/byai_context.py,sha256=DvKw-X8ePZr5c5osdapvzTvH4G23u0J80U-fgMLtge4,2388
91
92
  by_framework/worker/byai_worker.py,sha256=0NoRqzuTG_MPMxVbZ1ueeOrqI0H8-Adxh7dM3vckjJo,1757
92
93
  by_framework/worker/context.py,sha256=5As3GcnVrwIE1nCJDDYLt_Ke8-8nzh44CzQBvyncQsU,59833
93
94
  by_framework/worker/health_server.py,sha256=4Jw3ltAD7Ow4dPHhwTUU_4JjKz-iDCNG7RJzD2VzPlM,6090
94
95
  by_framework/worker/heartbeat.py,sha256=trHDS8FUALsA6jyzDPa087hpr8_2vY8ZUFn0ld1kI2o,15465
95
- by_framework/worker/processor.py,sha256=3UjK6bqAWhmLXwQTroO5vxZlV6_j4iGQNzg_nAkDd2w,13173
96
- by_framework/worker/runner.py,sha256=y7qr6n-DdJyqX6RMzEknuiKsTA6wa2zjhXnLn8VuCk4,50016
97
- by_framework/worker/worker.py,sha256=tJfnPkRH_c-C1NGyP3tS_kpl3tfDubu0KWGH-cbQk0s,47525
96
+ by_framework/worker/processor.py,sha256=UgC4_p-bg2KOHVTEILeMXF44rT9VLrRP5vompX0EeiQ,16243
97
+ by_framework/worker/runner.py,sha256=6_L_UUV1Kljys_4Eh_qnwMd7a-gGsikd4M_O5K879NA,51897
98
+ by_framework/worker/worker.py,sha256=IaPFLWCFo5U5Xo7PIQHtTt4JmtxZA1O_3nAuGl_g4N0,49527
98
99
  by_framework/worker/sandbox/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
99
100
  by_framework/worker/sandbox/hook_sandbox.py,sha256=XXSdH5YGX814LvV03vkq-zn5DVIBPYYt2NhRv1lT1Bk,2329
100
- by_framework-0.2.2.dev13.dist-info/METADATA,sha256=C1KKoZ2p5Kq4scXP0AoQ2UpLvnWFLcw6_s4Xr8PFCjY,28018
101
- by_framework-0.2.2.dev13.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
102
- by_framework-0.2.2.dev13.dist-info/entry_points.txt,sha256=5t6kgMjkR0UgJTpOsbuQDo0fOf7zeXjQW9DhkxfAGFc,56
103
- by_framework-0.2.2.dev13.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
104
- by_framework-0.2.2.dev13.dist-info/RECORD,,
101
+ by_framework-0.2.2.dev15.dist-info/METADATA,sha256=l050msraVm4RdyM0rIA_GXOpYu5pWyuUTdw7e2IBdd4,28018
102
+ by_framework-0.2.2.dev15.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
103
+ by_framework-0.2.2.dev15.dist-info/entry_points.txt,sha256=5t6kgMjkR0UgJTpOsbuQDo0fOf7zeXjQW9DhkxfAGFc,56
104
+ by_framework-0.2.2.dev15.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
105
+ by_framework-0.2.2.dev15.dist-info/RECORD,,