Skip to content

Commit c9c7c37

Browse files
feat(api): expose lifecycle_hooks on LaunchParameters lifecycle (#9115)
1 parent de2e170 commit c9c7c37

7 files changed

Lines changed: 132 additions & 10 deletions

File tree

.stats.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
configured_endpoints: 119
2-
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai/runloop-6ec03cfc156036a0758aebc523b469f3007de431312c536c434efe795e1892e7.yml
3-
openapi_spec_hash: 092761a0209e0950cfd8f262a981adb1
2+
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai/runloop-d4505c10f86f4ad122bfbc2a82a519278d626ac399c9ef3780496d5d7d1b99b9.yml
3+
openapi_spec_hash: b29dfd448505a0a3a6686202f606b8f7
44
config_hash: 06faf3176c48bf2b258730ce50809f0f

src/runloop_api_client/types/shared/launch_parameters.py

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,28 @@
66
from ..._models import BaseModel
77
from .after_idle import AfterIdle
88

9-
__all__ = ["LaunchParameters", "Lifecycle", "LifecycleResumeTriggers", "UserParameters"]
9+
__all__ = ["LaunchParameters", "Lifecycle", "LifecycleLifecycleHooks", "LifecycleResumeTriggers", "UserParameters"]
10+
11+
12+
class LifecycleLifecycleHooks(BaseModel):
13+
"""Optional lifecycle hooks.
14+
15+
suspend_commands run through the suspend path before the Devbox suspends; see launch_commands for work on every startup.
16+
"""
17+
18+
suspend_commands: Optional[List[str]] = None
19+
"""Commands to run through the suspend path before the Devbox suspends (e.g.
20+
21+
cleanup, quiesce daemons).
22+
"""
23+
24+
suspend_deadline_ms: Optional[int] = None
25+
"""Deadline in milliseconds for broker drain and suspend_commands during suspend.
26+
27+
Defaults to 30000 ms and may not exceed 60000 ms. If exceeded, suspend work is
28+
abandoned, the timeout is logged, and the Devbox still proceeds to suspend by
29+
shutting down vmagent and killing the VM.
30+
"""
1031

1132

1233
class LifecycleResumeTriggers(BaseModel):
@@ -22,7 +43,7 @@ class LifecycleResumeTriggers(BaseModel):
2243
class Lifecycle(BaseModel):
2344
"""Lifecycle configuration for idle and resume behavior.
2445
25-
Configure idle policy via lifecycle.after_idle (if both this and the top-level after_idle are set, they must match) and resume triggers via lifecycle.resume_triggers.
46+
Configure idle policy via lifecycle.after_idle (if both this and the top-level after_idle are set, they must match), resume triggers via lifecycle.resume_triggers, and optional lifecycle hooks via lifecycle.lifecycle_hooks.
2647
"""
2748

2849
after_idle: Optional[AfterIdle] = None
@@ -32,6 +53,13 @@ class Lifecycle(BaseModel):
3253
value. Prefer this field for new integrations.
3354
"""
3455

56+
lifecycle_hooks: Optional[LifecycleLifecycleHooks] = None
57+
"""Optional lifecycle hooks.
58+
59+
suspend_commands run through the suspend path before the Devbox suspends; see
60+
launch_commands for work on every startup.
61+
"""
62+
3563
resume_triggers: Optional[LifecycleResumeTriggers] = None
3664
"""Triggers that can resume a suspended Devbox."""
3765

@@ -93,8 +121,9 @@ class LaunchParameters(BaseModel):
93121
"""Lifecycle configuration for idle and resume behavior.
94122
95123
Configure idle policy via lifecycle.after_idle (if both this and the top-level
96-
after_idle are set, they must match) and resume triggers via
97-
lifecycle.resume_triggers.
124+
after_idle are set, they must match), resume triggers via
125+
lifecycle.resume_triggers, and optional lifecycle hooks via
126+
lifecycle.lifecycle_hooks.
98127
"""
99128

100129
network_policy_id: Optional[str] = None

src/runloop_api_client/types/shared_params/launch_parameters.py

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,28 @@
88
from ..._types import SequenceNotStr
99
from .after_idle import AfterIdle
1010

11-
__all__ = ["LaunchParameters", "Lifecycle", "LifecycleResumeTriggers", "UserParameters"]
11+
__all__ = ["LaunchParameters", "Lifecycle", "LifecycleLifecycleHooks", "LifecycleResumeTriggers", "UserParameters"]
12+
13+
14+
class LifecycleLifecycleHooks(TypedDict, total=False):
15+
"""Optional lifecycle hooks.
16+
17+
suspend_commands run through the suspend path before the Devbox suspends; see launch_commands for work on every startup.
18+
"""
19+
20+
suspend_commands: Optional[SequenceNotStr[str]]
21+
"""Commands to run through the suspend path before the Devbox suspends (e.g.
22+
23+
cleanup, quiesce daemons).
24+
"""
25+
26+
suspend_deadline_ms: Optional[int]
27+
"""Deadline in milliseconds for broker drain and suspend_commands during suspend.
28+
29+
Defaults to 30000 ms and may not exceed 60000 ms. If exceeded, suspend work is
30+
abandoned, the timeout is logged, and the Devbox still proceeds to suspend by
31+
shutting down vmagent and killing the VM.
32+
"""
1233

1334

1435
class LifecycleResumeTriggers(TypedDict, total=False):
@@ -24,7 +45,7 @@ class LifecycleResumeTriggers(TypedDict, total=False):
2445
class Lifecycle(TypedDict, total=False):
2546
"""Lifecycle configuration for idle and resume behavior.
2647
27-
Configure idle policy via lifecycle.after_idle (if both this and the top-level after_idle are set, they must match) and resume triggers via lifecycle.resume_triggers.
48+
Configure idle policy via lifecycle.after_idle (if both this and the top-level after_idle are set, they must match), resume triggers via lifecycle.resume_triggers, and optional lifecycle hooks via lifecycle.lifecycle_hooks.
2849
"""
2950

3051
after_idle: Optional[AfterIdle]
@@ -34,6 +55,13 @@ class Lifecycle(TypedDict, total=False):
3455
value. Prefer this field for new integrations.
3556
"""
3657

58+
lifecycle_hooks: Optional[LifecycleLifecycleHooks]
59+
"""Optional lifecycle hooks.
60+
61+
suspend_commands run through the suspend path before the Devbox suspends; see
62+
launch_commands for work on every startup.
63+
"""
64+
3765
resume_triggers: Optional[LifecycleResumeTriggers]
3866
"""Triggers that can resume a suspended Devbox."""
3967

@@ -95,8 +123,9 @@ class LaunchParameters(TypedDict, total=False):
95123
"""Lifecycle configuration for idle and resume behavior.
96124
97125
Configure idle policy via lifecycle.after_idle (if both this and the top-level
98-
after_idle are set, they must match) and resume triggers via
99-
lifecycle.resume_triggers.
126+
after_idle are set, they must match), resume triggers via
127+
lifecycle.resume_triggers, and optional lifecycle hooks via
128+
lifecycle.lifecycle_hooks.
100129
"""
101130

102131
network_policy_id: Optional[str]

tests/api_resources/test_benchmarks.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,10 @@ def test_method_start_run_with_all_params(self, client: Runloop) -> None:
304304
"idle_time_seconds": 0,
305305
"on_idle": "shutdown",
306306
},
307+
"lifecycle_hooks": {
308+
"suspend_commands": ["string"],
309+
"suspend_deadline_ms": 0,
310+
},
307311
"resume_triggers": {
308312
"axon_event": True,
309313
"http": True,
@@ -689,6 +693,10 @@ async def test_method_start_run_with_all_params(self, async_client: AsyncRunloop
689693
"idle_time_seconds": 0,
690694
"on_idle": "shutdown",
691695
},
696+
"lifecycle_hooks": {
697+
"suspend_commands": ["string"],
698+
"suspend_deadline_ms": 0,
699+
},
692700
"resume_triggers": {
693701
"axon_event": True,
694702
"http": True,

tests/api_resources/test_blueprints.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ def test_method_create_with_all_params(self, client: Runloop) -> None:
7070
"idle_time_seconds": 0,
7171
"on_idle": "shutdown",
7272
},
73+
"lifecycle_hooks": {
74+
"suspend_commands": ["string"],
75+
"suspend_deadline_ms": 0,
76+
},
7377
"resume_triggers": {
7478
"axon_event": True,
7579
"http": True,
@@ -295,6 +299,10 @@ def test_method_create_from_inspection_with_all_params(self, client: Runloop) ->
295299
"idle_time_seconds": 0,
296300
"on_idle": "shutdown",
297301
},
302+
"lifecycle_hooks": {
303+
"suspend_commands": ["string"],
304+
"suspend_deadline_ms": 0,
305+
},
298306
"resume_triggers": {
299307
"axon_event": True,
300308
"http": True,
@@ -464,6 +472,10 @@ def test_method_preview_with_all_params(self, client: Runloop) -> None:
464472
"idle_time_seconds": 0,
465473
"on_idle": "shutdown",
466474
},
475+
"lifecycle_hooks": {
476+
"suspend_commands": ["string"],
477+
"suspend_deadline_ms": 0,
478+
},
467479
"resume_triggers": {
468480
"axon_event": True,
469481
"http": True,
@@ -576,6 +588,10 @@ async def test_method_create_with_all_params(self, async_client: AsyncRunloop) -
576588
"idle_time_seconds": 0,
577589
"on_idle": "shutdown",
578590
},
591+
"lifecycle_hooks": {
592+
"suspend_commands": ["string"],
593+
"suspend_deadline_ms": 0,
594+
},
579595
"resume_triggers": {
580596
"axon_event": True,
581597
"http": True,
@@ -801,6 +817,10 @@ async def test_method_create_from_inspection_with_all_params(self, async_client:
801817
"idle_time_seconds": 0,
802818
"on_idle": "shutdown",
803819
},
820+
"lifecycle_hooks": {
821+
"suspend_commands": ["string"],
822+
"suspend_deadline_ms": 0,
823+
},
804824
"resume_triggers": {
805825
"axon_event": True,
806826
"http": True,
@@ -970,6 +990,10 @@ async def test_method_preview_with_all_params(self, async_client: AsyncRunloop)
970990
"idle_time_seconds": 0,
971991
"on_idle": "shutdown",
972992
},
993+
"lifecycle_hooks": {
994+
"suspend_commands": ["string"],
995+
"suspend_deadline_ms": 0,
996+
},
973997
"resume_triggers": {
974998
"axon_event": True,
975999
"http": True,

tests/api_resources/test_devboxes.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ def test_method_create_with_all_params(self, client: Runloop) -> None:
9191
"idle_time_seconds": 0,
9292
"on_idle": "shutdown",
9393
},
94+
"lifecycle_hooks": {
95+
"suspend_commands": ["string"],
96+
"suspend_deadline_ms": 0,
97+
},
9498
"resume_triggers": {
9599
"axon_event": True,
96100
"http": True,
@@ -1756,6 +1760,10 @@ async def test_method_create_with_all_params(self, async_client: AsyncRunloop) -
17561760
"idle_time_seconds": 0,
17571761
"on_idle": "shutdown",
17581762
},
1763+
"lifecycle_hooks": {
1764+
"suspend_commands": ["string"],
1765+
"suspend_deadline_ms": 0,
1766+
},
17591767
"resume_triggers": {
17601768
"axon_event": True,
17611769
"http": True,

tests/api_resources/test_scenarios.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@ def test_method_create_with_all_params(self, client: Runloop) -> None:
8383
"idle_time_seconds": 0,
8484
"on_idle": "shutdown",
8585
},
86+
"lifecycle_hooks": {
87+
"suspend_commands": ["string"],
88+
"suspend_deadline_ms": 0,
89+
},
8690
"resume_triggers": {
8791
"axon_event": True,
8892
"http": True,
@@ -228,6 +232,10 @@ def test_method_update_with_all_params(self, client: Runloop) -> None:
228232
"idle_time_seconds": 0,
229233
"on_idle": "shutdown",
230234
},
235+
"lifecycle_hooks": {
236+
"suspend_commands": ["string"],
237+
"suspend_deadline_ms": 0,
238+
},
231239
"resume_triggers": {
232240
"axon_event": True,
233241
"http": True,
@@ -446,6 +454,10 @@ def test_method_start_run_with_all_params(self, client: Runloop) -> None:
446454
"idle_time_seconds": 0,
447455
"on_idle": "shutdown",
448456
},
457+
"lifecycle_hooks": {
458+
"suspend_commands": ["string"],
459+
"suspend_deadline_ms": 0,
460+
},
449461
"resume_triggers": {
450462
"axon_event": True,
451463
"http": True,
@@ -564,6 +576,10 @@ async def test_method_create_with_all_params(self, async_client: AsyncRunloop) -
564576
"idle_time_seconds": 0,
565577
"on_idle": "shutdown",
566578
},
579+
"lifecycle_hooks": {
580+
"suspend_commands": ["string"],
581+
"suspend_deadline_ms": 0,
582+
},
567583
"resume_triggers": {
568584
"axon_event": True,
569585
"http": True,
@@ -709,6 +725,10 @@ async def test_method_update_with_all_params(self, async_client: AsyncRunloop) -
709725
"idle_time_seconds": 0,
710726
"on_idle": "shutdown",
711727
},
728+
"lifecycle_hooks": {
729+
"suspend_commands": ["string"],
730+
"suspend_deadline_ms": 0,
731+
},
712732
"resume_triggers": {
713733
"axon_event": True,
714734
"http": True,
@@ -927,6 +947,10 @@ async def test_method_start_run_with_all_params(self, async_client: AsyncRunloop
927947
"idle_time_seconds": 0,
928948
"on_idle": "shutdown",
929949
},
950+
"lifecycle_hooks": {
951+
"suspend_commands": ["string"],
952+
"suspend_deadline_ms": 0,
953+
},
930954
"resume_triggers": {
931955
"axon_event": True,
932956
"http": True,

0 commit comments

Comments
 (0)