boulder-opal-scale-up-sdk 1.0.2__tar.gz → 1.0.3__tar.gz

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.
Files changed (63) hide show
  1. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/PKG-INFO +1 -1
  2. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/agent/worker.py +10 -5
  3. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/common/dtypes.py +2 -0
  4. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/common/typeclasses.py +22 -0
  5. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/device/__init__.py +1 -2
  6. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/device/common.py +0 -3
  7. boulder_opal_scale_up_sdk-1.0.3/boulderopalscaleupsdk/device/device.py +25 -0
  8. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/device/processor/common.py +36 -14
  9. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/device/processor/superconducting_processor.py +17 -18
  10. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/experiments/__init__.py +4 -0
  11. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/experiments/chi01_scan.py +6 -1
  12. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/experiments/common.py +15 -0
  13. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/experiments/power_rabi.py +4 -3
  14. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/experiments/ramsey.py +5 -8
  15. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/experiments/readout_classifier_calibration.py +5 -1
  16. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/experiments/resonator_spectroscopy.py +5 -8
  17. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/experiments/resonator_spectroscopy_by_bias.py +6 -9
  18. boulder_opal_scale_up_sdk-1.0.3/boulderopalscaleupsdk/experiments/t1.py +54 -0
  19. boulder_opal_scale_up_sdk-1.0.3/boulderopalscaleupsdk/experiments/t2.py +48 -0
  20. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/experiments/transmon_anharmonicity.py +19 -15
  21. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/experiments/transmon_spectroscopy.py +8 -13
  22. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/protobuf/v1/task_pb2.py +16 -16
  23. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/protobuf/v1/task_pb2.pyi +4 -2
  24. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/pyproject.toml +1 -1
  25. boulder_opal_scale_up_sdk-1.0.2/boulderopalscaleupsdk/device/device.py +0 -41
  26. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/LICENSE +0 -0
  27. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/README.md +0 -0
  28. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/__init__.py +0 -0
  29. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/agent/__init__.py +0 -0
  30. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/common/__init__.py +0 -0
  31. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/device/config_loader.py +0 -0
  32. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/device/controller/__init__.py +0 -0
  33. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/device/controller/base.py +0 -0
  34. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/device/controller/qblox.py +0 -0
  35. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/device/controller/quantum_machines.py +0 -0
  36. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/device/controller/resolver.py +0 -0
  37. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/device/defcal.py +0 -0
  38. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/device/processor/__init__.py +0 -0
  39. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/experiments/resonator_spectroscopy_by_power.py +0 -0
  40. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/grpc_interceptors/__init__.py +0 -0
  41. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/grpc_interceptors/auth.py +0 -0
  42. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/plotting/__init__.py +0 -0
  43. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/plotting/dtypes.py +0 -0
  44. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/protobuf/v1/agent_pb2.py +0 -0
  45. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/protobuf/v1/agent_pb2.pyi +0 -0
  46. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/protobuf/v1/agent_pb2_grpc.py +0 -0
  47. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/protobuf/v1/device_pb2.py +0 -0
  48. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/protobuf/v1/device_pb2.pyi +0 -0
  49. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/protobuf/v1/device_pb2_grpc.py +0 -0
  50. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/protobuf/v1/task_pb2_grpc.py +0 -0
  51. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/py.typed +0 -0
  52. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/routines/__init__.py +0 -0
  53. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/routines/common.py +0 -0
  54. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/routines/resonator_mapping.py +0 -0
  55. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/stubs/__init__.py +0 -0
  56. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/stubs/dtypes.py +0 -0
  57. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/stubs/maps.py +0 -0
  58. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/third_party/__init__.py +0 -0
  59. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/third_party/quantum_machines/__init__.py +0 -0
  60. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/third_party/quantum_machines/config.py +0 -0
  61. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/third_party/quantum_machines/constants.py +0 -0
  62. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/utils/__init__.py +0 -0
  63. {boulder_opal_scale_up_sdk-1.0.2 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/utils/serial_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: boulder-opal-scale-up-sdk
3
- Version: 1.0.2
3
+ Version: 1.0.3
4
4
  Summary: Q-CTRL Boulder Opal Scale Up Python SDK
5
5
  License: https://q-ctrl.com/terms
6
6
  Keywords: black opal,boulder opal,fire opal,nisq,open controls,q control,q ctrl,q-control,q-ctrl,qcontrol,qctrl,quantum,quantum algorithms,quantum circuits,quantum coding,quantum coding software,quantum computing,quantum control,quantum control software,quantum control theory,quantum engineering,quantum error correction,quantum firmware,quantum fundamentals,quantum sensing,qubit,qudit
@@ -27,7 +27,7 @@ from grpc import aio as grpc
27
27
  from grpc import ssl_channel_credentials
28
28
  from pydantic_settings import BaseSettings, SettingsConfigDict
29
29
 
30
- from boulderopalscaleupsdk.common.dtypes import GrpcMetadata
30
+ from boulderopalscaleupsdk.common.dtypes import GrpcMetadata, JobId
31
31
  from boulderopalscaleupsdk.protobuf.v1 import agent_pb2, task_pb2, task_pb2_grpc
32
32
 
33
33
  LOG = logging.getLogger(__name__)
@@ -178,7 +178,7 @@ class Agent:
178
178
  device_name: str,
179
179
  routine: str,
180
180
  data: Struct | None,
181
- ) -> str:
181
+ ) -> JobId | None:
182
182
  if not self._channel:
183
183
  raise RuntimeError("Cannot start session: agent is shutdown.")
184
184
  _data = any_pb2.Any()
@@ -196,16 +196,18 @@ class Agent:
196
196
  metadata=metadata,
197
197
  )
198
198
  self._state = response.target_state
199
- await self._resume(response, metadata)
199
+ job_id: JobId | None = await self._resume(response, metadata)
200
200
  await self.shutdown()
201
- return response.session_id
201
+
202
+ return job_id
202
203
 
203
204
  async def _resume(
204
205
  self,
205
206
  response: task_pb2.AgentTasksResponse,
206
207
  metadata: GrpcMetadata,
207
- ) -> None:
208
+ ) -> JobId | None:
208
209
  tasks = response.tasks
210
+ job_id = None
209
211
  while self._state not in [
210
212
  task_pb2.AGENT_STATE_SHUTDOWN_MANAGER_INITIATED,
211
213
  task_pb2.AGENT_STATE_SHUTDOWN_FAULT,
@@ -243,6 +245,9 @@ class Agent:
243
245
 
244
246
  tasks = _resp.tasks
245
247
  self._state = _resp.target_state
248
+ job_id = _resp.job_id
249
+
250
+ return job_id or response.job_id
246
251
 
247
252
  async def shutdown(
248
253
  self,
@@ -33,6 +33,8 @@ from pydantic.dataclasses import dataclass
33
33
 
34
34
  GrpcMetadata = list[tuple[str, str | bytes]]
35
35
 
36
+ JobId = str
37
+
36
38
 
37
39
  class BaseType: ...
38
40
 
@@ -83,3 +83,25 @@ class Combine(Protocol[T]):
83
83
  return destination
84
84
 
85
85
  return Combine.create(_combine)
86
+
87
+
88
+ class Eq(Protocol[T]):
89
+ @abstractmethod
90
+ def eq(self, first: T, second: T) -> bool: ...
91
+
92
+ def eq_option(self, first: T | None, second: T | None) -> bool:
93
+ match first, second:
94
+ case None, None:
95
+ return True
96
+ case _ if first is not None and second is not None:
97
+ return self.eq(first, second)
98
+ case _:
99
+ return False
100
+
101
+ @classmethod
102
+ def create(cls, eq_fn: Callable[[T, T], bool]) -> "Eq[T]":
103
+ class _Eq(Eq):
104
+ def eq(self, first: T, second: T) -> bool:
105
+ return eq_fn(first, second)
106
+
107
+ return _Eq()
@@ -11,10 +11,9 @@
11
11
  # distributed under the License is distributed on an "AS IS" BASIS. See the
12
12
  # License for the specific language.
13
13
 
14
- __all__ = ["Device", "InvalidDevice", "InvalidDeviceComponent"]
14
+ __all__ = ["InvalidDevice", "InvalidDeviceComponent"]
15
15
 
16
16
  from boulderopalscaleupsdk.device.device import (
17
- Device,
18
17
  InvalidDevice,
19
18
  InvalidDeviceComponent,
20
19
  )
@@ -23,9 +23,6 @@ ExtraType = JsonDict | Callable[[JsonDict], None] | None
23
23
  ComponentRef = str
24
24
 
25
25
 
26
- class Processor(BaseModel): ...
27
-
28
-
29
26
  class Component(BaseModel, Generic[TraitT]):
30
27
  traits: list[TraitT]
31
28
 
@@ -0,0 +1,25 @@
1
+ # Copyright 2025 Q-CTRL. All rights reserved.
2
+ #
3
+ # Licensed under the Q-CTRL Terms of service (the "License"). Unauthorized
4
+ # copying or use of this file, via any medium, is strictly prohibited.
5
+ # Proprietary and confidential. You may not use this file except in compliance
6
+ # with the License. You may obtain a copy of the License at
7
+ #
8
+ # https://q-ctrl.com/terms
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS. See the
12
+ # License for the specific language.
13
+
14
+
15
+ from pydantic.dataclasses import dataclass
16
+
17
+
18
+ @dataclass
19
+ class InvalidDevice:
20
+ message: str
21
+
22
+
23
+ @dataclass
24
+ class InvalidDeviceComponent:
25
+ message: str
@@ -25,7 +25,7 @@ from boulderopalscaleupsdk.common.dtypes import (
25
25
  Frequency,
26
26
  ISO8601DatetimeUTCLike,
27
27
  )
28
- from boulderopalscaleupsdk.common.typeclasses import Combine
28
+ from boulderopalscaleupsdk.common.typeclasses import Combine, Eq
29
29
 
30
30
  T = TypeVar("T")
31
31
  T2 = TypeVar("T2")
@@ -97,23 +97,40 @@ class ComponentParameter(Generic[T]):
97
97
  @staticmethod
98
98
  def combine(
99
99
  combine_instance: Combine[T],
100
+ eq_instance: Eq[T],
100
101
  ) -> "Combine[ComponentParameter[T]]":
101
102
  def _combine(
102
103
  first: ComponentParameter[T],
103
104
  other: ComponentParameter[Any],
104
105
  ) -> ComponentParameter[T]:
106
+ _value = combine_instance.combine(first.value, other.value)
107
+ _err_minus = combine_instance.combine_option(
108
+ first.err_minus,
109
+ other.err_minus,
110
+ )
111
+ _err_plus = combine_instance.combine_option(
112
+ first.err_plus,
113
+ other.err_plus,
114
+ )
115
+ _calibration_status = other.calibration_status
116
+
117
+ _updated_at: ISO8601DatetimeUTCLike | None
118
+ if (
119
+ not eq_instance.eq(_value, first.value)
120
+ or not eq_instance.eq_option(_err_minus, first.err_minus)
121
+ or not eq_instance.eq_option(_err_plus, first.err_plus)
122
+ or _calibration_status != first.calibration_status
123
+ ):
124
+ _updated_at = datetime.now(tz=UTC)
125
+ else:
126
+ _updated_at = first.updated_at
127
+
105
128
  return ComponentParameter(
106
- value=combine_instance.combine(first.value, other.value),
107
- err_minus=combine_instance.combine_option(
108
- first.err_minus,
109
- other.err_minus,
110
- ),
111
- err_plus=combine_instance.combine_option(
112
- first.err_plus,
113
- other.err_plus,
114
- ),
115
- calibration_status=other.calibration_status,
116
- updated_at=datetime.now(tz=UTC),
129
+ value=_value,
130
+ err_minus=_err_minus,
131
+ err_plus=_err_plus,
132
+ calibration_status=_calibration_status,
133
+ updated_at=_updated_at,
117
134
  )
118
135
 
119
136
  return Combine[ComponentParameter[T]].create(_combine)
@@ -127,8 +144,13 @@ class ComponentParameter(Generic[T]):
127
144
  updated_at=self.updated_at,
128
145
  )
129
146
 
130
- def merge_with(self, other: "ComponentParameter[T]", combine_value: "Combine[T]"):
131
- combined = ComponentParameter[T].combine(combine_value).combine(self, other)
147
+ def merge_with(
148
+ self,
149
+ other: "ComponentParameter[T]",
150
+ combine_value: "Combine[T]",
151
+ eq_value: Eq[T],
152
+ ):
153
+ combined = ComponentParameter[T].combine(combine_value, eq_value).combine(self, other)
132
154
  self.value = combined.value
133
155
  self.err_minus = combined.err_minus
134
156
  self.err_plus = combined.err_plus
@@ -23,7 +23,6 @@ from boulderopalscaleupsdk.common.dtypes import (
23
23
  from boulderopalscaleupsdk.device.common import (
24
24
  Component,
25
25
  ComponentRef,
26
- Processor,
27
26
  )
28
27
  from boulderopalscaleupsdk.device.processor import (
29
28
  ComponentParameter,
@@ -37,12 +36,12 @@ class Transmon(Component[Literal["tunable"]]):
37
36
  dtype: Literal["transmon"] = "transmon"
38
37
  traits: list[Literal["tunable"]] = Field(default=["tunable"])
39
38
 
40
- freq_01: FloatComponentParameter | None = Field(
41
- default=None,
39
+ freq_01: FloatComponentParameter = Field(
40
+ default=ComponentParameter(value=(0.0)),
42
41
  json_schema_extra={"display": {"label": "freq_01", "unit": "MHz", "scale": 1e-6}},
43
42
  )
44
- anharm: FloatComponentParameter | None = Field(
45
- default=None,
43
+ anharm: FloatComponentParameter = Field(
44
+ default=ComponentParameter(value=0.0),
46
45
  json_schema_extra={"display": {"label": "anharm", "unit": "MHz", "scale": 1e-6}},
47
46
  )
48
47
  t1: DurationComponentParameter = Field(
@@ -71,9 +70,9 @@ class Transmon(Component[Literal["tunable"]]):
71
70
  default=ComponentParameter(value=0.0),
72
71
  json_schema_extra={"display": {"label": "dc_bias", "unit": "V", "scale": 1}},
73
72
  )
74
- fmax_bias: FloatComponentParameter = Field(
73
+ bias_offset: FloatComponentParameter = Field(
75
74
  default=ComponentParameter(value=0.0),
76
- json_schema_extra={"display": {"label": "fmax_bias", "unit": "V", "scale": 1}},
75
+ json_schema_extra={"display": {"label": "bias_offset", "unit": "V", "scale": 1}},
77
76
  )
78
77
  bias_period: FloatComponentParameter = Field(
79
78
  default=ComponentParameter(value=0.0),
@@ -85,20 +84,20 @@ class Resonator(Component[Literal["readout"]]):
85
84
  dtype: Literal["resonator"] = "resonator"
86
85
  traits: list[Literal["readout"]] = Field(default=["readout"])
87
86
 
88
- frequency_high: FloatComponentParameter | None = Field(
89
- default=None,
87
+ frequency_high: FloatComponentParameter = Field(
88
+ default=ComponentParameter(value=0.0),
90
89
  json_schema_extra={"display": {"label": "frequency_high", "unit": "MHz", "scale": 1e-6}},
91
90
  )
92
- frequency_low: FloatComponentParameter | None = Field(
93
- default=None,
91
+ frequency_low: FloatComponentParameter = Field(
92
+ default=ComponentParameter(value=0.0),
94
93
  json_schema_extra={"display": {"label": "frequency_low", "unit": "MHz", "scale": 1e-6}},
95
94
  )
96
- kappa_low: FloatComponentParameter | None = Field(
97
- default=None,
95
+ kappa_low: FloatComponentParameter = Field(
96
+ default=ComponentParameter(value=0.0),
98
97
  json_schema_extra={"display": {"label": "kappa_low", "unit": "MHz", "scale": 1e-6}},
99
98
  )
100
- kappa_high: FloatComponentParameter | None = Field(
101
- default=None,
99
+ kappa_high: FloatComponentParameter = Field(
100
+ default=ComponentParameter(value=0.0),
102
101
  json_schema_extra={"display": {"label": "kappa_high", "unit": "MHz", "scale": 1e-6}},
103
102
  )
104
103
  vp_low: FloatComponentParameter = Field(
@@ -128,9 +127,9 @@ class Coupler(Component[Literal["tunable"]]):
128
127
  default=ComponentParameter(value=0.0),
129
128
  json_schema_extra={"display": {"label": "dc_bias", "unit": "V", "scale": 1}},
130
129
  )
131
- fmax_bias: FloatComponentParameter = Field(
130
+ bias_offset: FloatComponentParameter = Field(
132
131
  default=ComponentParameter(value=0.0),
133
- json_schema_extra={"display": {"label": "fmax_bias", "unit": "V", "scale": 1}},
132
+ json_schema_extra={"display": {"label": "bias_offset", "unit": "V", "scale": 1}},
134
133
  )
135
134
  bias_period: FloatComponentParameter = Field(
136
135
  default=ComponentParameter(value=0.0),
@@ -182,7 +181,7 @@ class SuperconductingProcessorTemplate(BaseModel):
182
181
  )
183
182
 
184
183
 
185
- class SuperconductingProcessor(Processor):
184
+ class SuperconductingProcessor(BaseModel):
186
185
  nodes: dict[ComponentRef, SuperconductingComponentType]
187
186
  edges: list[Edge]
188
187
 
@@ -14,6 +14,8 @@
14
14
  """Experiment library."""
15
15
 
16
16
  __all__ = [
17
+ "T1",
18
+ "T2",
17
19
  "CWSIterable",
18
20
  "Chi01Scan",
19
21
  "ConstantWaveform",
@@ -48,5 +50,7 @@ from .readout_classifier_calibration import ReadoutClassifierCalibration
48
50
  from .resonator_spectroscopy import ResonatorSpectroscopy
49
51
  from .resonator_spectroscopy_by_bias import ResonatorSpectroscopyByBias
50
52
  from .resonator_spectroscopy_by_power import ResonatorSpectroscopyByPower
53
+ from .t1 import T1
54
+ from .t2 import T2
51
55
  from .transmon_anharmonicity import TransmonAnharmonicity
52
56
  from .transmon_spectroscopy import TransmonSpectroscopy
@@ -13,7 +13,8 @@
13
13
 
14
14
  from pydantic import PrivateAttr
15
15
 
16
- from boulderopalscaleupsdk.experiments.common import (
16
+ from .common import (
17
+ ConstantWaveform,
17
18
  CWSIterable,
18
19
  Experiment,
19
20
  HypIterable,
@@ -44,6 +45,9 @@ class Chi01Scan(Experiment):
44
45
  shot_count : int, optional
45
46
  The number of shots to be taken in the experiment.
46
47
  Defaults to 100.
48
+ measure_waveform : ConstantWaveform or None, optional
49
+ The waveform to use for the measurement pulse.
50
+ If not provided, the measurement defcal will be used.
47
51
  """
48
52
 
49
53
  _experiment_name: str = PrivateAttr("chi01_scan")
@@ -54,3 +58,4 @@ class Chi01Scan(Experiment):
54
58
  )
55
59
  recycle_delay_ns: int = DEFAULT_RECYCLE_DELAY_NS
56
60
  shot_count: int = DEFAULT_SHOT_COUNT
61
+ measure_waveform: ConstantWaveform | None = None
@@ -56,6 +56,21 @@ class RangeIterable(_RangeIterable):
56
56
  step: float
57
57
 
58
58
 
59
+ class LogspaceIterable(_RangeIterable):
60
+ """A range of values spaced evenly on a log scale."""
61
+
62
+ dtype: Literal["logspace"] = "logspace"
63
+
64
+ # The starting value.
65
+ start: float
66
+ # The final value.
67
+ stop: float
68
+ # The number of values. Defaults to 101.
69
+ count: int = Field(default=101)
70
+ # Base of the logarithm
71
+ base: int = Field(default=10)
72
+
73
+
59
74
  class CWSIterable(_RangeIterable):
60
75
  """A range of linearly spaced values in center ± width/2."""
61
76
 
@@ -39,14 +39,15 @@ class PowerRabi(Experiment):
39
39
  The scaling factors for the drive pulse amplitude. If None, a default scan will be used.
40
40
  drive_waveform : GaussianWaveform
41
41
  The waveform to use for the drive pulse.
42
- measure_waveform : ConstantWaveform
43
- The waveform to use for the measurement pulse.
44
42
  recycle_delay_ns : int
45
43
  The delay time between consecutive shots of the experiment, in nanoseconds.
46
44
  shot_count : int, optional
47
45
  The number of shots to be taken in the experiment. Defaults to 400.
48
46
  pulse_vp : float, optional
49
47
  The voltage per pulse. If None, a default value will be used.
48
+ measure_waveform : ConstantWaveform or None, optional
49
+ The waveform to use for the measurement pulse.
50
+ If not provided, the measurement defcal will be used.
50
51
  """
51
52
 
52
53
  _experiment_name: str = PrivateAttr("power_rabi")
@@ -54,7 +55,7 @@ class PowerRabi(Experiment):
54
55
  transmon: str
55
56
  scales: list[float] | LinspaceIterable | RangeIterable | CWSIterable | HypIterable | None = None
56
57
  drive_waveform: GaussianWaveform
57
- measure_waveform: ConstantWaveform
58
58
  recycle_delay_ns: int
59
59
  shot_count: int = DEFAULT_SHOT_COUNT
60
60
  pulse_vp: float | None = None
61
+ measure_waveform: ConstantWaveform | None = None
@@ -13,7 +13,7 @@
13
13
 
14
14
  from pydantic import PrivateAttr
15
15
 
16
- from .common import Experiment
16
+ from .common import ConstantWaveform, Experiment
17
17
 
18
18
  DEFAULT_RECYCLE_DELAY_NS = 10_000
19
19
  DEFAULT_SHOT_COUNT = 400
@@ -36,17 +36,15 @@ class Ramsey(Experiment):
36
36
  The step for generating the list of delays, in nanoseconds.
37
37
  virtual_detuning : float
38
38
  The difference between the drive signal frequency and the qubit frequency, in Hz.
39
- readout_amplitude : float
40
- The amplitude of the readout pulse.
41
- duration_ns : int, optional
42
- The duration of the pulse, in nanoseconds.
43
- Defaults to 2000 ns.
44
39
  recycle_delay_ns : int, optional
45
40
  The delay time between consecutive shots of the experiment, in nanoseconds.
46
41
  Defaults to 10000 ns.
47
42
  shot_count : int, optional
48
43
  The number of shots to be taken in the experiment.
49
44
  Defaults to 400.
45
+ measure_waveform : ConstantWaveform or None, optional
46
+ The waveform to use for the measurement pulse.
47
+ If not provided, the measurement defcal will be used.
50
48
  """
51
49
 
52
50
  _experiment_name: str = PrivateAttr("ramsey")
@@ -56,7 +54,6 @@ class Ramsey(Experiment):
56
54
  min_delay_ns: int
57
55
  delay_step_ns: int
58
56
  virtual_detuning: float
59
- readout_amplitude: float
60
- duration_ns: int = DEFAULT_DURATION_NS
61
57
  recycle_delay_ns: int = DEFAULT_RECYCLE_DELAY_NS
62
58
  shot_count: int = DEFAULT_SHOT_COUNT
59
+ measure_waveform: ConstantWaveform | None = None
@@ -1,6 +1,6 @@
1
1
  from pydantic import PrivateAttr
2
2
 
3
- from boulderopalscaleupsdk.experiments.common import Experiment
3
+ from .common import ConstantWaveform, Experiment
4
4
 
5
5
 
6
6
  class ReadoutClassifierCalibration(Experiment):
@@ -16,9 +16,13 @@ class ReadoutClassifierCalibration(Experiment):
16
16
  shot_count : int, optional
17
17
  The number of shots to be taken in the experiment.
18
18
  Defaults to 5000.
19
+ measure_waveform : ConstantWaveform or None, optional
20
+ The waveform to use for the measurement pulse.
21
+ If not provided, the measurement defcal will be used.
19
22
  """
20
23
 
21
24
  _experiment_name: str = PrivateAttr("readout_classifier_calibration")
22
25
  transmon: str
23
26
  recycle_delay_ns: int
24
27
  shot_count: int = 5000
28
+ measure_waveform: ConstantWaveform | None = None
@@ -14,6 +14,7 @@
14
14
  from pydantic import PrivateAttr
15
15
 
16
16
  from .common import (
17
+ ConstantWaveform,
17
18
  CWSIterable,
18
19
  Experiment,
19
20
  HypIterable,
@@ -38,18 +39,15 @@ class ResonatorSpectroscopy(Experiment):
38
39
  or HypIterable or None, optional
39
40
  The frequencies at which to scan.
40
41
  If None, frequencies around the readout frequency will be used.
41
- readout_amplitude : float, optional
42
- The amplitude of the readout pulse.
43
- If None, a default amplitude will be used.
44
- duration_ns : int, optional
45
- The duration of the readout pulse, in nanoseconds.
46
- Defaults to 2000 ns.
47
42
  recycle_delay_ns :int, optional
48
43
  The delay time between consecutive shots of the experiment, in nanoseconds.
49
44
  Defaults to 1000 ns.
50
45
  shot_count : int, optional
51
46
  The number of shots to be taken in the experiment.
52
47
  Defaults to 100.
48
+ measure_waveform : ConstantWaveform or None, optional
49
+ The waveform to use for the measurement pulse.
50
+ If not provided, the measurement defcal will be used.
53
51
  """
54
52
 
55
53
  _experiment_name: str = PrivateAttr("resonator_spectroscopy")
@@ -58,7 +56,6 @@ class ResonatorSpectroscopy(Experiment):
58
56
  frequencies: list[int] | LinspaceIterable | RangeIterable | CWSIterable | HypIterable | None = (
59
57
  None
60
58
  )
61
- readout_amplitude: float | None = None
62
- duration_ns: int = DEFAULT_DURATION_NS
63
59
  recycle_delay_ns: int = DEFAULT_RECYCLE_DELAY_NS
64
60
  shot_count: int = DEFAULT_SHOT_COUNT
61
+ measure_waveform: ConstantWaveform | None = None
@@ -14,6 +14,7 @@
14
14
  from pydantic import PrivateAttr
15
15
 
16
16
  from .common import (
17
+ ConstantWaveform,
17
18
  CWSIterable,
18
19
  Experiment,
19
20
  HypIterable,
@@ -36,7 +37,7 @@ class ResonatorSpectroscopyByBias(Experiment):
36
37
  resonator : str
37
38
  The reference for the resonator to target in the experiment.
38
39
  bias_transmons : list[str] or None, optional
39
- The transmons to bias.
40
+ The references for the transmons to bias.
40
41
  If None, it defaults to transmon coupled to the resonator.
41
42
  frequencies : list[int] or LinspaceIterable or RangeIterable or CWSIterable
42
43
  or HypIterable or None, optional
@@ -46,18 +47,15 @@ class ResonatorSpectroscopyByBias(Experiment):
46
47
  or HypIterable, optional
47
48
  The biases at which to scan.
48
49
  If None, defaults to 21 points between -0.49 and 0.49.
49
- readout_amplitude : float, optional
50
- The amplitude of the readout pulse.
51
- Defaults to None.
52
- duration_ns : int, optional
53
- The duration of the pulse, in nanoseconds.
54
- Defaults to 2000 ns.
55
50
  recycle_delay_ns : int, optional
56
51
  The delay time between consecutive shots of the experiment, in nanoseconds.
57
52
  Defaults to 10000 ns.
58
53
  shot_count : int, optional
59
54
  The number of shots to be taken in the experiment.
60
55
  Defaults to 100.
56
+ measure_waveform : ConstantWaveform or None, optional
57
+ The waveform to use for the measurement pulse.
58
+ If not provided, the measurement defcal will be used.
61
59
  """
62
60
 
63
61
  _experiment_name: str = PrivateAttr("resonator_spectroscopy_by_bias")
@@ -70,7 +68,6 @@ class ResonatorSpectroscopyByBias(Experiment):
70
68
  biases: list[float] | LinspaceIterable | RangeIterable | CWSIterable | HypIterable = (
71
69
  DEFAULT_BIASES
72
70
  )
73
- readout_amplitude: float | None = None
74
- duration_ns: int = DEFAULT_DURATION_NS
75
71
  recycle_delay_ns: int = DEFAULT_RECYCLE_DELAY_NS
76
72
  shot_count: int = DEFAULT_SHOT_COUNT
73
+ measure_waveform: ConstantWaveform | None = None
@@ -0,0 +1,54 @@
1
+ # Copyright 2025 Q-CTRL. All rights reserved.
2
+ #
3
+ # Licensed under the Q-CTRL Terms of service (the "License"). Unauthorized
4
+ # copying or use of this file, via any medium, is strictly prohibited.
5
+ # Proprietary and confidential. You may not use this file except in compliance
6
+ # with the License. You may obtain a copy of the License at
7
+ #
8
+ # https://q-ctrl.com/terms
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS. See the
12
+ # License for the specific language.
13
+
14
+ from pydantic import PrivateAttr
15
+
16
+ from .common import Experiment, LogspaceIterable
17
+
18
+ DEFAULT_RECYCLE_DELAY_NS = 200_000
19
+ DEFAULT_SHOT_COUNT = 400
20
+ DEFAULT_DURATION_NS = 2_000
21
+
22
+
23
+ class T1(Experiment):
24
+ """
25
+ Parameters for running a T1 experiment.
26
+
27
+ Parameters
28
+ ----------
29
+ transmon : str
30
+ The transmon to target in the experiment.
31
+ delays_ns : list[int] | RangeIterable
32
+ The delay time, in nanoseconds.
33
+ readout_amplitude : float, optional
34
+ The amplitude of the readout pulse.
35
+ If None, a default amplitude will be used.
36
+ duration_ns : int, optional
37
+ The duration of the readout pulse, in nanoseconds.
38
+ Defaults to 2000 ns.
39
+ recycle_delay_ns : int, optional
40
+ The delay time between consecutive shots of the experiment, in nanoseconds.
41
+ Defaults to 200_000 ns.
42
+ shot_count : int, optional
43
+ The number of shots to be taken in the experiment.
44
+ Defaults to 400.
45
+ """
46
+
47
+ _experiment_name: str = PrivateAttr("t1")
48
+
49
+ transmon: str
50
+ delays_ns: LogspaceIterable
51
+ readout_amplitude: float
52
+ duration_ns: int = DEFAULT_DURATION_NS
53
+ recycle_delay_ns: int = DEFAULT_RECYCLE_DELAY_NS
54
+ shot_count: int = DEFAULT_SHOT_COUNT
@@ -0,0 +1,48 @@
1
+ # Copyright 2025 Q-CTRL. All rights reserved.
2
+ #
3
+ # Licensed under the Q-CTRL Terms of service (the "License"). Unauthorized
4
+ # copying or use of this file, via any medium, is strictly prohibited.
5
+ # Proprietary and confidential. You may not use this file except in compliance
6
+ # with the License. You may obtain a copy of the License at
7
+ #
8
+ # https://q-ctrl.com/terms
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS. See the
12
+ # License for the specific language.
13
+
14
+ from pydantic import PrivateAttr
15
+
16
+ from .common import Experiment, RangeIterable
17
+
18
+ DEFAULT_RECYCLE_DELAY_NS = 100_000
19
+ DEFAULT_SHOT_COUNT = 400
20
+
21
+
22
+ class T2(Experiment):
23
+ """
24
+ Parameters for running a Ramsey experiment.
25
+
26
+ Parameters
27
+ ----------
28
+ transmon : str
29
+ The reference for the transmon to target in the experiment.
30
+ delays_ns : list[int] | RangeIterable
31
+ The delay time, in nanoseconds.
32
+ virtual_detuning : float
33
+ The difference between the drive signal frequency and the qubit frequency, in Hz.
34
+ recycle_delay_ns : int, optional
35
+ The delay time between consecutive shots of the experiment, in nanoseconds.
36
+ Defaults to 100_000 ns.
37
+ shot_count : int, optional
38
+ The number of shots to be taken in the experiment.
39
+ Defaults to 400.
40
+ """
41
+
42
+ _experiment_name: str = PrivateAttr("t2")
43
+
44
+ transmon: str
45
+ delays_ns: list[int] | RangeIterable
46
+ virtual_detuning: float
47
+ recycle_delay_ns: int = DEFAULT_RECYCLE_DELAY_NS
48
+ shot_count: int = DEFAULT_SHOT_COUNT
@@ -13,7 +13,14 @@
13
13
 
14
14
  from pydantic import PrivateAttr
15
15
 
16
- from .common import CWSIterable, Experiment, HypIterable, LinspaceIterable, RangeIterable
16
+ from .common import (
17
+ ConstantWaveform,
18
+ CWSIterable,
19
+ Experiment,
20
+ HypIterable,
21
+ LinspaceIterable,
22
+ RangeIterable,
23
+ )
17
24
 
18
25
  DEFAULT_DURATION_NS = 2_000 # ns
19
26
  DEFAULT_RECYCLE_DELAY_NS = 1_000 # ns
@@ -32,25 +39,24 @@ class TransmonAnharmonicity(Experiment):
32
39
  frequencies : list[int] or LinspaceIterable or RangeIterable or CWSIterable
33
40
  or HypIterable or None, optional
34
41
  The drive frequencies to be scanned in the experiment.
35
- If None, a default scan will be used based on the transmon's frequency and anharmonicity.
36
- spec_amplitude : float
37
- The amplitude of the spectroscopy pulse, in volts.
38
- spec_duration : int
39
- The duration of the spectroscopy pulse, in nanoseconds.
42
+ If None, a default scan will be used based on the transmon's frequency
43
+ and anharmonicity.
40
44
  anharmonicity_guess_hz : float
41
45
  The guessed anharmonicity of the qubit, in Hz. This is used to determine the
42
46
  range of frequencies to scan if `frequencies` is not provided.
43
47
  Defaults to -200 MHz.
44
- readout_amplitude : float
45
- The amplitude of the readout pulse.
46
- duration_ns : int, optional
47
- The duration of the readout pulse, in nanoseconds.
48
- Defaults to 2000 ns.
49
48
  recycle_delay_ns : int, optional
50
49
  The delay time between consecutive shots of the experiment, in nanoseconds.
51
50
  Defaults to 1000 ns.
52
51
  shot_count : int, optional
53
52
  The number of shots to be taken in the experiment. Defaults to 100.
53
+ spectroscopy_waveform : ConstantWaveform or None, optional
54
+ The waveform to use in the spectroscopy pulse.
55
+ If not provided, a waveform with a duration of 2000 ns
56
+ and an amplitude of 1.5 times the transmon's x_vp will be used.
57
+ measure_waveform : ConstantWaveform or None, optional
58
+ The waveform to use for the measurement pulse.
59
+ If not provided, the measurement defcal will be used.
54
60
  """
55
61
 
56
62
  _experiment_name: str = PrivateAttr("transmon_anharmonicity")
@@ -59,10 +65,8 @@ class TransmonAnharmonicity(Experiment):
59
65
  frequencies: list[int] | LinspaceIterable | RangeIterable | CWSIterable | HypIterable | None = (
60
66
  None
61
67
  )
62
- spec_amplitude: float
63
- spec_duration: int
64
68
  anharmonicity_guess_hz: float = DEFAULT_ANHARMONICITY_GUESS
65
- readout_amplitude: float
66
- duration_ns: int = DEFAULT_DURATION_NS
67
69
  recycle_delay_ns: int = DEFAULT_RECYCLE_DELAY_NS
68
70
  shot_count: int = DEFAULT_SHOT_COUNT
71
+ spectroscopy_waveform: ConstantWaveform | None = None
72
+ measure_waveform: ConstantWaveform | None = None
@@ -14,6 +14,7 @@
14
14
  from pydantic import PrivateAttr
15
15
 
16
16
  from .common import (
17
+ ConstantWaveform,
17
18
  CWSIterable,
18
19
  Experiment,
19
20
  HypIterable,
@@ -38,21 +39,17 @@ class TransmonSpectroscopy(Experiment):
38
39
  or HypIterable or None, optional
39
40
  The frequencies at which to scan.
40
41
  If None, frequencies around the readout frequency will be used.
41
- spec_amplitude : float
42
- The amplitude of the spectroscopy pulse.
43
- spec_duration : int
44
- The duration of the spectroscopy pulse, in nanoseconds.
45
- readout_amplitude : float
46
- The amplitude of the readout pulse.
47
- duration_ns : int, optional
48
- The duration of the readout pulse, in nanoseconds.
49
- Defaults to 2000 ns.
50
42
  recycle_delay_ns : int, optional
51
43
  The delay time between consecutive shots of the experiment, in nanoseconds.
52
44
  Defaults to 1000 ns.
53
45
  shot_count : int, optional
54
46
  The number of shots to be taken in the experiment.
55
47
  Defaults to 100.
48
+ spectroscopy_waveform : ConstantWaveform
49
+ The waveform to use in the spectroscopy pulse.
50
+ measure_waveform : ConstantWaveform or None, optional
51
+ The waveform to use for the measurement pulse.
52
+ If not provided, the measurement defcal will be used.
56
53
  """
57
54
 
58
55
  _experiment_name: str = PrivateAttr("transmon_spectroscopy")
@@ -61,9 +58,7 @@ class TransmonSpectroscopy(Experiment):
61
58
  frequencies: list[int] | LinspaceIterable | RangeIterable | CWSIterable | HypIterable | None = (
62
59
  None
63
60
  )
64
- spec_amplitude: float
65
- spec_duration: int
66
- readout_amplitude: float
67
- duration_ns: int = DEFAULT_DURATION_NS
68
61
  recycle_delay_ns: int = DEFAULT_RECYCLE_DELAY_NS
69
62
  shot_count: int = DEFAULT_SHOT_COUNT
63
+ spectroscopy_waveform: ConstantWaveform
64
+ measure_waveform: ConstantWaveform | None = None
@@ -16,7 +16,7 @@ from google.api import annotations_pb2 as google_dot_api_dot_annotations__pb2
16
16
  from google.protobuf import any_pb2 as google_dot_protobuf_dot_any__pb2
17
17
 
18
18
 
19
- DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n,boulderopalscaleupsdk/protobuf/v1/task.proto\x12!boulderopalscaleupsdk.protobuf.v1\x1a\x1cgoogle/api/annotations.proto\x1a\x19google/protobuf/any.proto\"\xc7\x01\n\x13StartSessionRequest\x12\x19\n\x08\x61gent_id\x18\x01 \x01(\tR\x07\x61gentId\x12\x19\n\x08\x61pp_name\x18\x02 \x01(\tR\x07\x61ppName\x12\x1f\n\x0b\x64\x65vice_name\x18\x03 \x01(\tR\ndeviceName\x12!\n\x0croutine_name\x18\x04 \x01(\tR\x0broutineName\x12-\n\x04\x64\x61ta\x18\x05 \x01(\x0b\x32\x14.google.protobuf.AnyH\x00R\x04\x64\x61ta\x88\x01\x01\x42\x07\n\x05_data\"\xfc\x01\n\x14UpdateSessionRequest\x12\x1d\n\nsession_id\x18\x01 \x01(\tR\tsessionId\x12R\n\rcurrent_state\x18\x02 \x01(\x0e\x32-.boulderopalscaleupsdk.protobuf.v1.AgentStateR\x0c\x63urrentState\x12G\n\x07results\x18\x03 \x03(\x0b\x32-.boulderopalscaleupsdk.protobuf.v1.TaskResultR\x07results\x12(\n\x10task_in_progress\x18\x04 \x03(\tR\x0etaskInProgress\"\xac\x03\n\x12\x41gentTasksResponse\x12\x1d\n\nsession_id\x18\x01 \x01(\tR\tsessionId\x12U\n\x0ctarget_state\x18\x02 \x01(\x0e\x32-.boulderopalscaleupsdk.protobuf.v1.AgentStateH\x00R\x0btargetState\x88\x01\x01\x12=\n\x05tasks\x18\x03 \x03(\x0b\x32\'.boulderopalscaleupsdk.protobuf.v1.TaskR\x05tasks\x12)\n\x10invalidate_tasks\x18\x04 \x03(\tR\x0finvalidateTasks\x12\x66\n\x0bretry_tasks\x18\x05 \x03(\x0b\x32\x45.boulderopalscaleupsdk.protobuf.v1.AgentTasksResponse.RetryTasksEntryR\nretryTasks\x1a=\n\x0fRetryTasksEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\x42\x0f\n\r_target_state\"\x94\x02\n\x04Task\x12\x17\n\x07task_id\x18\x01 \x01(\tR\x06taskId\x12\x1d\n\nsession_id\x18\x02 \x01(\tR\tsessionId\x12\x1b\n\ttask_type\x18\x03 \x01(\tR\x08taskType\x12(\n\x04\x64\x61ta\x18\x04 \x01(\x0b\x32\x14.google.protobuf.AnyR\x04\x64\x61ta\x12,\n\x0ftimeout_seconds\x18\x05 \x01(\x05H\x00R\x0etimeoutSeconds\x88\x01\x01\x12\x1f\n\x08\x64\x65\x61\x64line\x18\x06 \x01(\x03H\x01R\x08\x64\x65\x61\x64line\x88\x01\x01\x12\x1d\n\ndepends_on\x18\x07 \x03(\tR\tdependsOnB\x12\n\x10_timeout_secondsB\x0b\n\t_deadline\"\xed\x01\n\nTaskResult\x12\x17\n\x07task_id\x18\x01 \x01(\tR\x06taskId\x12\x1d\n\nsession_id\x18\x03 \x01(\tR\tsessionId\x12\x1f\n\x0bresult_type\x18\x04 \x01(\tR\nresultType\x12.\n\x06result\x18\x05 \x01(\x0b\x32\x14.google.protobuf.AnyH\x00R\x06result\x12J\n\x05\x65rror\x18\x06 \x01(\x0b\x32\x32.boulderopalscaleupsdk.protobuf.v1.TaskErrorDetailH\x00R\x05\x65rrorB\n\n\x08response\"{\n\x0fTaskErrorDetail\x12@\n\x04\x63ode\x18\x01 \x01(\x0e\x32,.boulderopalscaleupsdk.protobuf.v1.TaskErrorR\x04\x63ode\x12\x1b\n\x06\x64\x65tail\x18\x02 \x01(\tH\x00R\x06\x64\x65tail\x88\x01\x01\x42\t\n\x07_detail*\xdd\x01\n\nAgentState\x12\x1b\n\x17\x41GENT_STATE_UNSPECIFIED\x10\x00\x12\x1e\n\x1a\x41GENT_STATE_ACTIVE_SESSION\x10\x01\x12\x1b\n\x17\x41GENT_STATE_ACTIVE_IDLE\x10\x02\x12)\n%AGENT_STATE_SHUTDOWN_CLIENT_INITIATED\x10\x03\x12*\n&AGENT_STATE_SHUTDOWN_MANAGER_INITIATED\x10\x04\x12\x1e\n\x1a\x41GENT_STATE_SHUTDOWN_FAULT\x10\x05*G\n\tTaskError\x12\x1a\n\x16TASK_ERROR_UNSPECIFIED\x10\x00\x12\x1e\n\x1aTASK_ERROR_NOT_IMPLEMENTED\x10\x01\x32\xe0\x02\n\x13\x41gentManagerService\x12\xa1\x01\n\x0cStartSession\x12\x36.boulderopalscaleupsdk.protobuf.v1.StartSessionRequest\x1a\x35.boulderopalscaleupsdk.protobuf.v1.AgentTasksResponse\"\"\x82\xd3\xe4\x93\x02\x1c\"\x17/v1/agent/start_session:\x01*\x12\xa4\x01\n\rUpdateSession\x12\x37.boulderopalscaleupsdk.protobuf.v1.UpdateSessionRequest\x1a\x35.boulderopalscaleupsdk.protobuf.v1.AgentTasksResponse\"#\x82\xd3\xe4\x93\x02\x1d\"\x18/v1/agent/update_session:\x01*B\xa8\x02\n%com.boulderopalscaleupsdk.protobuf.v1B\tTaskProtoP\x01ZNgithub.com/qctrl/boulder-opal-scale-up/proto/boulderopalscaleupsdk/protobuf/v1\xa2\x02\x03\x42PX\xaa\x02!Boulderopalscaleupsdk.Protobuf.V1\xca\x02!Boulderopalscaleupsdk\\Protobuf\\V1\xe2\x02-Boulderopalscaleupsdk\\Protobuf\\V1\\GPBMetadata\xea\x02#Boulderopalscaleupsdk::Protobuf::V1b\x06proto3')
19
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n,boulderopalscaleupsdk/protobuf/v1/task.proto\x12!boulderopalscaleupsdk.protobuf.v1\x1a\x1cgoogle/api/annotations.proto\x1a\x19google/protobuf/any.proto\"\xc7\x01\n\x13StartSessionRequest\x12\x19\n\x08\x61gent_id\x18\x01 \x01(\tR\x07\x61gentId\x12\x19\n\x08\x61pp_name\x18\x02 \x01(\tR\x07\x61ppName\x12\x1f\n\x0b\x64\x65vice_name\x18\x03 \x01(\tR\ndeviceName\x12!\n\x0croutine_name\x18\x04 \x01(\tR\x0broutineName\x12-\n\x04\x64\x61ta\x18\x05 \x01(\x0b\x32\x14.google.protobuf.AnyH\x00R\x04\x64\x61ta\x88\x01\x01\x42\x07\n\x05_data\"\xfc\x01\n\x14UpdateSessionRequest\x12\x1d\n\nsession_id\x18\x01 \x01(\tR\tsessionId\x12R\n\rcurrent_state\x18\x02 \x01(\x0e\x32-.boulderopalscaleupsdk.protobuf.v1.AgentStateR\x0c\x63urrentState\x12G\n\x07results\x18\x03 \x03(\x0b\x32-.boulderopalscaleupsdk.protobuf.v1.TaskResultR\x07results\x12(\n\x10task_in_progress\x18\x04 \x03(\tR\x0etaskInProgress\"\xc3\x03\n\x12\x41gentTasksResponse\x12\x1d\n\nsession_id\x18\x01 \x01(\tR\tsessionId\x12U\n\x0ctarget_state\x18\x02 \x01(\x0e\x32-.boulderopalscaleupsdk.protobuf.v1.AgentStateH\x00R\x0btargetState\x88\x01\x01\x12=\n\x05tasks\x18\x03 \x03(\x0b\x32\'.boulderopalscaleupsdk.protobuf.v1.TaskR\x05tasks\x12)\n\x10invalidate_tasks\x18\x04 \x03(\tR\x0finvalidateTasks\x12\x66\n\x0bretry_tasks\x18\x05 \x03(\x0b\x32\x45.boulderopalscaleupsdk.protobuf.v1.AgentTasksResponse.RetryTasksEntryR\nretryTasks\x12\x15\n\x06job_id\x18\x06 \x01(\tR\x05jobId\x1a=\n\x0fRetryTasksEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\x42\x0f\n\r_target_state\"\x94\x02\n\x04Task\x12\x17\n\x07task_id\x18\x01 \x01(\tR\x06taskId\x12\x1d\n\nsession_id\x18\x02 \x01(\tR\tsessionId\x12\x1b\n\ttask_type\x18\x03 \x01(\tR\x08taskType\x12(\n\x04\x64\x61ta\x18\x04 \x01(\x0b\x32\x14.google.protobuf.AnyR\x04\x64\x61ta\x12,\n\x0ftimeout_seconds\x18\x05 \x01(\x05H\x00R\x0etimeoutSeconds\x88\x01\x01\x12\x1f\n\x08\x64\x65\x61\x64line\x18\x06 \x01(\x03H\x01R\x08\x64\x65\x61\x64line\x88\x01\x01\x12\x1d\n\ndepends_on\x18\x07 \x03(\tR\tdependsOnB\x12\n\x10_timeout_secondsB\x0b\n\t_deadline\"\xed\x01\n\nTaskResult\x12\x17\n\x07task_id\x18\x01 \x01(\tR\x06taskId\x12\x1d\n\nsession_id\x18\x03 \x01(\tR\tsessionId\x12\x1f\n\x0bresult_type\x18\x04 \x01(\tR\nresultType\x12.\n\x06result\x18\x05 \x01(\x0b\x32\x14.google.protobuf.AnyH\x00R\x06result\x12J\n\x05\x65rror\x18\x06 \x01(\x0b\x32\x32.boulderopalscaleupsdk.protobuf.v1.TaskErrorDetailH\x00R\x05\x65rrorB\n\n\x08response\"{\n\x0fTaskErrorDetail\x12@\n\x04\x63ode\x18\x01 \x01(\x0e\x32,.boulderopalscaleupsdk.protobuf.v1.TaskErrorR\x04\x63ode\x12\x1b\n\x06\x64\x65tail\x18\x02 \x01(\tH\x00R\x06\x64\x65tail\x88\x01\x01\x42\t\n\x07_detail*\xdd\x01\n\nAgentState\x12\x1b\n\x17\x41GENT_STATE_UNSPECIFIED\x10\x00\x12\x1e\n\x1a\x41GENT_STATE_ACTIVE_SESSION\x10\x01\x12\x1b\n\x17\x41GENT_STATE_ACTIVE_IDLE\x10\x02\x12)\n%AGENT_STATE_SHUTDOWN_CLIENT_INITIATED\x10\x03\x12*\n&AGENT_STATE_SHUTDOWN_MANAGER_INITIATED\x10\x04\x12\x1e\n\x1a\x41GENT_STATE_SHUTDOWN_FAULT\x10\x05*G\n\tTaskError\x12\x1a\n\x16TASK_ERROR_UNSPECIFIED\x10\x00\x12\x1e\n\x1aTASK_ERROR_NOT_IMPLEMENTED\x10\x01\x32\xe0\x02\n\x13\x41gentManagerService\x12\xa1\x01\n\x0cStartSession\x12\x36.boulderopalscaleupsdk.protobuf.v1.StartSessionRequest\x1a\x35.boulderopalscaleupsdk.protobuf.v1.AgentTasksResponse\"\"\x82\xd3\xe4\x93\x02\x1c\"\x17/v1/agent/start_session:\x01*\x12\xa4\x01\n\rUpdateSession\x12\x37.boulderopalscaleupsdk.protobuf.v1.UpdateSessionRequest\x1a\x35.boulderopalscaleupsdk.protobuf.v1.AgentTasksResponse\"#\x82\xd3\xe4\x93\x02\x1d\"\x18/v1/agent/update_session:\x01*B\xa8\x02\n%com.boulderopalscaleupsdk.protobuf.v1B\tTaskProtoP\x01ZNgithub.com/qctrl/boulder-opal-scale-up/proto/boulderopalscaleupsdk/protobuf/v1\xa2\x02\x03\x42PX\xaa\x02!Boulderopalscaleupsdk.Protobuf.V1\xca\x02!Boulderopalscaleupsdk\\Protobuf\\V1\xe2\x02-Boulderopalscaleupsdk\\Protobuf\\V1\\GPBMetadata\xea\x02#Boulderopalscaleupsdk::Protobuf::V1b\x06proto3')
20
20
 
21
21
  _globals = globals()
22
22
  _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -30,24 +30,24 @@ if not _descriptor._USE_C_DESCRIPTORS:
30
30
  _globals['_AGENTMANAGERSERVICE'].methods_by_name['StartSession']._serialized_options = b'\202\323\344\223\002\034\"\027/v1/agent/start_session:\001*'
31
31
  _globals['_AGENTMANAGERSERVICE'].methods_by_name['UpdateSession']._loaded_options = None
32
32
  _globals['_AGENTMANAGERSERVICE'].methods_by_name['UpdateSession']._serialized_options = b'\202\323\344\223\002\035\"\030/v1/agent/update_session:\001*'
33
- _globals['_AGENTSTATE']._serialized_start=1673
34
- _globals['_AGENTSTATE']._serialized_end=1894
35
- _globals['_TASKERROR']._serialized_start=1896
36
- _globals['_TASKERROR']._serialized_end=1967
33
+ _globals['_AGENTSTATE']._serialized_start=1696
34
+ _globals['_AGENTSTATE']._serialized_end=1917
35
+ _globals['_TASKERROR']._serialized_start=1919
36
+ _globals['_TASKERROR']._serialized_end=1990
37
37
  _globals['_STARTSESSIONREQUEST']._serialized_start=141
38
38
  _globals['_STARTSESSIONREQUEST']._serialized_end=340
39
39
  _globals['_UPDATESESSIONREQUEST']._serialized_start=343
40
40
  _globals['_UPDATESESSIONREQUEST']._serialized_end=595
41
41
  _globals['_AGENTTASKSRESPONSE']._serialized_start=598
42
- _globals['_AGENTTASKSRESPONSE']._serialized_end=1026
43
- _globals['_AGENTTASKSRESPONSE_RETRYTASKSENTRY']._serialized_start=948
44
- _globals['_AGENTTASKSRESPONSE_RETRYTASKSENTRY']._serialized_end=1009
45
- _globals['_TASK']._serialized_start=1029
46
- _globals['_TASK']._serialized_end=1305
47
- _globals['_TASKRESULT']._serialized_start=1308
48
- _globals['_TASKRESULT']._serialized_end=1545
49
- _globals['_TASKERRORDETAIL']._serialized_start=1547
50
- _globals['_TASKERRORDETAIL']._serialized_end=1670
51
- _globals['_AGENTMANAGERSERVICE']._serialized_start=1970
52
- _globals['_AGENTMANAGERSERVICE']._serialized_end=2322
42
+ _globals['_AGENTTASKSRESPONSE']._serialized_end=1049
43
+ _globals['_AGENTTASKSRESPONSE_RETRYTASKSENTRY']._serialized_start=971
44
+ _globals['_AGENTTASKSRESPONSE_RETRYTASKSENTRY']._serialized_end=1032
45
+ _globals['_TASK']._serialized_start=1052
46
+ _globals['_TASK']._serialized_end=1328
47
+ _globals['_TASKRESULT']._serialized_start=1331
48
+ _globals['_TASKRESULT']._serialized_end=1568
49
+ _globals['_TASKERRORDETAIL']._serialized_start=1570
50
+ _globals['_TASKERRORDETAIL']._serialized_end=1693
51
+ _globals['_AGENTMANAGERSERVICE']._serialized_start=1993
52
+ _globals['_AGENTMANAGERSERVICE']._serialized_end=2345
53
53
  # @@protoc_insertion_point(module_scope)
@@ -57,7 +57,7 @@ class UpdateSessionRequest(_message.Message):
57
57
  def __init__(self, session_id: _Optional[str] = ..., current_state: _Optional[_Union[AgentState, str]] = ..., results: _Optional[_Iterable[_Union[TaskResult, _Mapping]]] = ..., task_in_progress: _Optional[_Iterable[str]] = ...) -> None: ...
58
58
 
59
59
  class AgentTasksResponse(_message.Message):
60
- __slots__ = ("session_id", "target_state", "tasks", "invalidate_tasks", "retry_tasks")
60
+ __slots__ = ("session_id", "target_state", "tasks", "invalidate_tasks", "retry_tasks", "job_id")
61
61
  class RetryTasksEntry(_message.Message):
62
62
  __slots__ = ("key", "value")
63
63
  KEY_FIELD_NUMBER: _ClassVar[int]
@@ -70,12 +70,14 @@ class AgentTasksResponse(_message.Message):
70
70
  TASKS_FIELD_NUMBER: _ClassVar[int]
71
71
  INVALIDATE_TASKS_FIELD_NUMBER: _ClassVar[int]
72
72
  RETRY_TASKS_FIELD_NUMBER: _ClassVar[int]
73
+ JOB_ID_FIELD_NUMBER: _ClassVar[int]
73
74
  session_id: str
74
75
  target_state: AgentState
75
76
  tasks: _containers.RepeatedCompositeFieldContainer[Task]
76
77
  invalidate_tasks: _containers.RepeatedScalarFieldContainer[str]
77
78
  retry_tasks: _containers.ScalarMap[str, str]
78
- def __init__(self, session_id: _Optional[str] = ..., target_state: _Optional[_Union[AgentState, str]] = ..., tasks: _Optional[_Iterable[_Union[Task, _Mapping]]] = ..., invalidate_tasks: _Optional[_Iterable[str]] = ..., retry_tasks: _Optional[_Mapping[str, str]] = ...) -> None: ...
79
+ job_id: str
80
+ def __init__(self, session_id: _Optional[str] = ..., target_state: _Optional[_Union[AgentState, str]] = ..., tasks: _Optional[_Iterable[_Union[Task, _Mapping]]] = ..., invalidate_tasks: _Optional[_Iterable[str]] = ..., retry_tasks: _Optional[_Mapping[str, str]] = ..., job_id: _Optional[str] = ...) -> None: ...
79
81
 
80
82
  class Task(_message.Message):
81
83
  __slots__ = ("task_id", "session_id", "task_type", "data", "timeout_seconds", "deadline", "depends_on")
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "boulder-opal-scale-up-sdk"
3
- version = "1.0.2"
3
+ version = "1.0.3"
4
4
  description = "Q-CTRL Boulder Opal Scale Up Python SDK"
5
5
  license = "https://q-ctrl.com/terms"
6
6
  authors = ["Q-CTRL <support@q-ctrl.com>"]
@@ -1,41 +0,0 @@
1
- # Copyright 2025 Q-CTRL. All rights reserved.
2
- #
3
- # Licensed under the Q-CTRL Terms of service (the "License"). Unauthorized
4
- # copying or use of this file, via any medium, is strictly prohibited.
5
- # Proprietary and confidential. You may not use this file except in compliance
6
- # with the License. You may obtain a copy of the License at
7
- #
8
- # https://q-ctrl.com/terms
9
- #
10
- # Unless required by applicable law or agreed to in writing, software
11
- # distributed under the License is distributed on an "AS IS" BASIS. See the
12
- # License for the specific language.
13
-
14
-
15
- from pydantic import BaseModel
16
- from pydantic.dataclasses import dataclass
17
-
18
- from boulderopalscaleupsdk.device.controller import (
19
- QBLOXControllerInfo,
20
- QuantumMachinesControllerInfo,
21
- )
22
- from boulderopalscaleupsdk.device.defcal import DataKeyLike, DefCalData
23
- from boulderopalscaleupsdk.device.processor import SuperconductingProcessor
24
-
25
-
26
- class Device(BaseModel):
27
- """Device specification."""
28
-
29
- processor: SuperconductingProcessor # | OtherProcessorTypes
30
- controller_info: QBLOXControllerInfo | QuantumMachinesControllerInfo
31
- defcals: dict[DataKeyLike, DefCalData]
32
-
33
-
34
- @dataclass
35
- class InvalidDevice:
36
- message: str
37
-
38
-
39
- @dataclass
40
- class InvalidDeviceComponent:
41
- message: str