modal-devin 0.1.0__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.
- modal_devin-0.1.0/.gitattributes +2 -0
- modal_devin-0.1.0/.github/pull_request_template.md +11 -0
- modal_devin-0.1.0/.github/workflows/ci.yml +73 -0
- modal_devin-0.1.0/.github/workflows/release.yml +30 -0
- modal_devin-0.1.0/.gitignore +11 -0
- modal_devin-0.1.0/.mintignore +9 -0
- modal_devin-0.1.0/CHANGELOG.md +74 -0
- modal_devin-0.1.0/CODE_OF_CONDUCT.md +13 -0
- modal_devin-0.1.0/CONTRIBUTING.md +75 -0
- modal_devin-0.1.0/LICENSE +21 -0
- modal_devin-0.1.0/PKG-INFO +125 -0
- modal_devin-0.1.0/README.md +97 -0
- modal_devin-0.1.0/SECURITY.md +16 -0
- modal_devin-0.1.0/docs.json +94 -0
- modal_devin-0.1.0/explanation/architecture.mdx +63 -0
- modal_devin-0.1.0/explanation/resumability.mdx +55 -0
- modal_devin-0.1.0/explanation/security.mdx +63 -0
- modal_devin-0.1.0/explanation/session-lifecycle.mdx +65 -0
- modal_devin-0.1.0/explanation/timeouts.mdx +43 -0
- modal_devin-0.1.0/guides/customize-image.mdx +86 -0
- modal_devin-0.1.0/guides/multiple-pools.mdx +69 -0
- modal_devin-0.1.0/guides/operate-a-worker.mdx +68 -0
- modal_devin-0.1.0/guides/resources-and-regions.mdx +76 -0
- modal_devin-0.1.0/guides/runtime-configuration.mdx +87 -0
- modal_devin-0.1.0/guides/troubleshooting.mdx +96 -0
- modal_devin-0.1.0/index.mdx +85 -0
- modal_devin-0.1.0/modal_devin/__init__.py +33 -0
- modal_devin-0.1.0/modal_devin/__main__.py +5 -0
- modal_devin-0.1.0/modal_devin/_client.py +224 -0
- modal_devin-0.1.0/modal_devin/_config.py +192 -0
- modal_devin-0.1.0/modal_devin/_exceptions.py +36 -0
- modal_devin-0.1.0/modal_devin/_runtime.py +467 -0
- modal_devin-0.1.0/modal_devin/cli.py +484 -0
- modal_devin-0.1.0/modal_devin/images.py +159 -0
- modal_devin-0.1.0/modal_devin/py.typed +1 -0
- modal_devin-0.1.0/modal_devin/templates/pool.py.tmpl +59 -0
- modal_devin-0.1.0/modal_devin/worker.py +217 -0
- modal_devin-0.1.0/pyproject.toml +78 -0
- modal_devin-0.1.0/reference/cli.mdx +152 -0
- modal_devin-0.1.0/reference/exceptions.mdx +67 -0
- modal_devin-0.1.0/reference/generated-application.mdx +109 -0
- modal_devin-0.1.0/reference/images.mdx +33 -0
- modal_devin-0.1.0/reference/settings.mdx +68 -0
- modal_devin-0.1.0/reference/worker.mdx +146 -0
- modal_devin-0.1.0/tests/integration/test_modal_contract.py +50 -0
- modal_devin-0.1.0/tests/test_cli.py +267 -0
- modal_devin-0.1.0/tests/test_client.py +174 -0
- modal_devin-0.1.0/tests/test_config.py +84 -0
- modal_devin-0.1.0/tests/test_docs_navigation.py +33 -0
- modal_devin-0.1.0/tests/test_docs_security.py +25 -0
- modal_devin-0.1.0/tests/test_images.py +92 -0
- modal_devin-0.1.0/tests/test_runtime.py +695 -0
- modal_devin-0.1.0/tests/test_worker.py +185 -0
- modal_devin-0.1.0/tutorials/create-a-pool.mdx +87 -0
- modal_devin-0.1.0/tutorials/custom-workspace.mdx +90 -0
- modal_devin-0.1.0/tutorials/first-worker.mdx +93 -0
- modal_devin-0.1.0/uv.lock +1272 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
## Summary
|
|
2
|
+
|
|
3
|
+
Describe the user-facing behavior and why it belongs in `modal-devin`.
|
|
4
|
+
|
|
5
|
+
## Verification
|
|
6
|
+
|
|
7
|
+
- [ ] Lifecycle behavior has network-free tests.
|
|
8
|
+
- [ ] `uv run coverage run -m pytest -q` and `uv run coverage report` pass.
|
|
9
|
+
- [ ] Ruff formatting, Ruff lint, `ty`, and package builds pass.
|
|
10
|
+
- [ ] No credential is present in arguments, logs, generated code, or image metadata.
|
|
11
|
+
- [ ] Public API and changelog documentation are updated when applicable.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
permissions:
|
|
4
|
+
contents: read
|
|
5
|
+
|
|
6
|
+
concurrency:
|
|
7
|
+
group: ci-${{ github.ref }}
|
|
8
|
+
cancel-in-progress: true
|
|
9
|
+
|
|
10
|
+
on:
|
|
11
|
+
pull_request:
|
|
12
|
+
push:
|
|
13
|
+
branches: [main]
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
tests:
|
|
17
|
+
name: Test Python ${{ matrix.python-version }}
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
timeout-minutes: 10
|
|
20
|
+
strategy:
|
|
21
|
+
fail-fast: false
|
|
22
|
+
matrix:
|
|
23
|
+
python-version: ["3.11", "3.12", "3.13", "3.14"]
|
|
24
|
+
|
|
25
|
+
steps:
|
|
26
|
+
- uses: actions/checkout@v6
|
|
27
|
+
- uses: actions/setup-python@v6
|
|
28
|
+
with:
|
|
29
|
+
python-version: ${{ matrix.python-version }}
|
|
30
|
+
- uses: astral-sh/setup-uv@v7
|
|
31
|
+
with:
|
|
32
|
+
enable-cache: true
|
|
33
|
+
- run: uv sync --dev
|
|
34
|
+
- run: uv run pytest -q
|
|
35
|
+
|
|
36
|
+
quality:
|
|
37
|
+
name: Quality and package
|
|
38
|
+
runs-on: ubuntu-latest
|
|
39
|
+
timeout-minutes: 15
|
|
40
|
+
|
|
41
|
+
steps:
|
|
42
|
+
- uses: actions/checkout@v6
|
|
43
|
+
- uses: actions/setup-python@v6
|
|
44
|
+
with:
|
|
45
|
+
python-version: "3.12"
|
|
46
|
+
- uses: astral-sh/setup-uv@v7
|
|
47
|
+
with:
|
|
48
|
+
enable-cache: true
|
|
49
|
+
- run: uv sync --dev
|
|
50
|
+
- run: uv run coverage run -m pytest -q
|
|
51
|
+
- run: uv run coverage report
|
|
52
|
+
- run: uv run ruff format --check .
|
|
53
|
+
- run: uv run ruff check .
|
|
54
|
+
- run: uv run ty check --error all .
|
|
55
|
+
- run: uv build
|
|
56
|
+
- name: Smoke-test the built wheel
|
|
57
|
+
run: |
|
|
58
|
+
tmpdir="$(mktemp -d)"
|
|
59
|
+
cd "$tmpdir"
|
|
60
|
+
uv run --isolated --with "$GITHUB_WORKSPACE"/dist/*.whl \
|
|
61
|
+
python -c "from modal_devin import Worker; assert Worker('smoke', pool_id='pool').name == 'smoke'"
|
|
62
|
+
|
|
63
|
+
docs:
|
|
64
|
+
name: Docs
|
|
65
|
+
runs-on: ubuntu-latest
|
|
66
|
+
timeout-minutes: 10
|
|
67
|
+
|
|
68
|
+
steps:
|
|
69
|
+
- uses: actions/checkout@v6
|
|
70
|
+
- uses: actions/setup-node@v5
|
|
71
|
+
with:
|
|
72
|
+
node-version: "22"
|
|
73
|
+
- run: npx -y mint broken-links
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
id-token: write
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
publish:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
timeout-minutes: 10
|
|
15
|
+
environment:
|
|
16
|
+
name: pypi
|
|
17
|
+
url: https://pypi.org/project/modal-devin/
|
|
18
|
+
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v6
|
|
21
|
+
|
|
22
|
+
- uses: astral-sh/setup-uv@v7
|
|
23
|
+
|
|
24
|
+
- name: Verify release tag matches package version
|
|
25
|
+
run: |
|
|
26
|
+
version="$(uv run python -c 'import modal_devin; print(modal_devin.__version__)')"
|
|
27
|
+
test "${GITHUB_REF_NAME#v}" = "$version"
|
|
28
|
+
- run: uv build
|
|
29
|
+
- run: uv run --with twine twine check dist/*
|
|
30
|
+
- run: uv publish --trusted-publishing always dist/*
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes are documented here. The project follows Keep a Changelog
|
|
4
|
+
and uses semantic versioning.
|
|
5
|
+
|
|
6
|
+
## Unreleased
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
|
|
10
|
+
- `Worker` as an immutable configured runtime with durable image, session, and
|
|
11
|
+
dispatch operations.
|
|
12
|
+
- Validated `WorkerSettings` with explicit `MODAL_DEVIN_*` environment loading.
|
|
13
|
+
- Typed public exceptions for configuration, compatibility, API, status, and
|
|
14
|
+
worker-process failures.
|
|
15
|
+
- `modal-devin init`, `deploy`, and `doctor` project-level commands.
|
|
16
|
+
- Modal Dict-backed filesystem snapshot persistence.
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- Generated files now own the `modal.App`, secret, image composition, function
|
|
21
|
+
decorators, schedule, and connection between the scheduler and session function.
|
|
22
|
+
- Session and scheduler bodies are thin adapters into `Worker.run_session()` and
|
|
23
|
+
`Worker.dispatch_pending_sessions()`.
|
|
24
|
+
- Claims are acquired inside the spawned session invocation rather than before the
|
|
25
|
+
asynchronous Modal dispatch, so queue delays and function retries do not reuse a
|
|
26
|
+
stale claim.
|
|
27
|
+
- Outposts session states are parsed into a closed protocol type; malformed or new
|
|
28
|
+
states preserve recovery data instead of being treated as completed.
|
|
29
|
+
- Scheduler functions use a lightweight controller image instead of the full Devin
|
|
30
|
+
worker image.
|
|
31
|
+
- Sidecar image cache entries are versioned by the sidecar recipe digest.
|
|
32
|
+
- `Worker.run_session()` inherits Modal Sandbox keyword typing through `ParamSpec`
|
|
33
|
+
while protecting runtime-owned lifecycle options.
|
|
34
|
+
- Deployed functions are named `scheduler` and `session` by operational role.
|
|
35
|
+
- Worker images remain composable between `Worker.base_image()` and the terminal
|
|
36
|
+
`Worker.prepare_image()` source mount.
|
|
37
|
+
- Final session status failures preserve a recovery snapshot and fail the Modal
|
|
38
|
+
invocation.
|
|
39
|
+
- Nonzero Devin worker exits now raise `WorkerExitedError`.
|
|
40
|
+
- Outer function timeouts now account for status requests and backoff, sidecar
|
|
41
|
+
readiness, snapshot creation, claim release, and cleanup.
|
|
42
|
+
- The Devin worker command receives the configured session timeout directly, while
|
|
43
|
+
the containing Sandbox receives a larger lifecycle budget for startup and recovery.
|
|
44
|
+
- Scheduler transport, protocol, image-build, and dispatch failures now fail the
|
|
45
|
+
scheduled invocation after attempting every independent dispatch.
|
|
46
|
+
- Pending session dispatches use bounded leases to avoid duplicate Modal queue entries.
|
|
47
|
+
- Snapshot index entries are refreshed daily while the scheduler is deployed, keeping
|
|
48
|
+
their retention aligned with 30-day or indefinite filesystem snapshots.
|
|
49
|
+
- Package installation is documented as a project dependency rather than an
|
|
50
|
+
isolated tool installation.
|
|
51
|
+
- Scheduler invocations now surface protocol, sidecar-build, and dispatch failures;
|
|
52
|
+
all pending sessions are still attempted before dispatch errors are reported.
|
|
53
|
+
- Devin CLI installation failures now stop worker image builds at the failing
|
|
54
|
+
installer step.
|
|
55
|
+
|
|
56
|
+
### Removed
|
|
57
|
+
|
|
58
|
+
- The `Worker.app()` application factory and its Modal function-option mappings.
|
|
59
|
+
- The low-level public `poll_and_dispatch()`, `build_sidecar_image_id()`,
|
|
60
|
+
`SessionRunner`, and `OutpostPoolConfig` surface.
|
|
61
|
+
- The redundant `modal-devin outpost` command group.
|
|
62
|
+
- The `clone_private_repo()` image-build helper.
|
|
63
|
+
|
|
64
|
+
### Security
|
|
65
|
+
|
|
66
|
+
- Interactive Modal Secret creation now uses the public Modal SDK directly, keeping
|
|
67
|
+
the Devin service key in memory instead of writing a temporary JSON file or
|
|
68
|
+
invoking a secret-creation subprocess.
|
|
69
|
+
- Secret discovery now uses the public Modal SDK instead of parsing subprocess JSON,
|
|
70
|
+
and credential setup documentation no longer stages tokens in local files.
|
|
71
|
+
- The sidecar health check is served locally and no longer sends a token-bearing
|
|
72
|
+
request to the upstream API.
|
|
73
|
+
- The credential-injecting proxy only forwards Outposts API paths.
|
|
74
|
+
- Worker output combines stdout and stderr so failures remain observable.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Code of Conduct
|
|
2
|
+
|
|
3
|
+
We are committed to a welcoming, harassment-free project for everyone.
|
|
4
|
+
|
|
5
|
+
Be respectful, assume good intent, give actionable technical feedback, and make
|
|
6
|
+
room for people with different backgrounds and levels of experience. Harassment,
|
|
7
|
+
personal attacks, discriminatory language, unwanted sexual attention, and the
|
|
8
|
+
publication of another person's private information are not acceptable.
|
|
9
|
+
|
|
10
|
+
Maintainers may edit or remove contributions and restrict participation when
|
|
11
|
+
behavior threatens the safety or productivity of the community. Report conduct
|
|
12
|
+
concerns privately through the repository owner's GitHub profile. Reports will
|
|
13
|
+
be handled as confidentially as practical.
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Thanks for helping improve `modal-devin`.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
uv sync --dev
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Architecture
|
|
12
|
+
|
|
13
|
+
`Worker` is the supported user-facing abstraction. Keep lifecycle and upstream
|
|
14
|
+
integration details behind the following private boundaries:
|
|
15
|
+
|
|
16
|
+
- `_config.py`: validated settings and resource identities;
|
|
17
|
+
- `_client.py`: Devin Outposts HTTP contract;
|
|
18
|
+
- `_runtime.py`: claim, dispatch, execution, and recovery state machine;
|
|
19
|
+
- `images.py`: composable public image helpers and sidecar compatibility;
|
|
20
|
+
- `worker.py`: the small public runtime and image API;
|
|
21
|
+
- `templates/pool.py.tmpl`: the user-owned Modal application composition root.
|
|
22
|
+
|
|
23
|
+
Generated applications should use Modal's native `App` and `@app.function`
|
|
24
|
+
vocabulary. Do not expose sidecar image IDs, raw tokens, raw HTTP payloads, or
|
|
25
|
+
Modal Dicts through the public API.
|
|
26
|
+
|
|
27
|
+
`Worker.run_session()` deliberately derives its option signature from
|
|
28
|
+
`modal.Sandbox.create` with `ParamSpec`. Keep its runtime validation narrower than
|
|
29
|
+
Modal's full constructor: modal-devin owns command arguments, timeout, workdir, and
|
|
30
|
+
the readiness probe.
|
|
31
|
+
|
|
32
|
+
The scheduler may discover and spawn pending session IDs, but it must not acquire
|
|
33
|
+
their Outposts claims. Claiming belongs inside the spawned session invocation so a
|
|
34
|
+
Modal queue delay or retry cannot outlive the claim deadline. Unknown upstream
|
|
35
|
+
status values must fail closed and preserve a recovery snapshot.
|
|
36
|
+
|
|
37
|
+
Keep the generated scheduler at `max_containers=1`. Dispatch leases are acquired
|
|
38
|
+
before spawning and cleared when the session invocation starts; serialized scheduler
|
|
39
|
+
runs make stale-lease replacement deterministic. Scheduler failures must propagate so
|
|
40
|
+
Modal can alert and apply configured retries.
|
|
41
|
+
|
|
42
|
+
The sidecar image cache key includes the Caddy configuration, install recipe, and
|
|
43
|
+
`_SIDECAR_RECIPE_SCHEMA`. Bump that schema whenever `_sidecar_image()` changes in a
|
|
44
|
+
way not represented by the embedded inputs.
|
|
45
|
+
|
|
46
|
+
## Checks
|
|
47
|
+
|
|
48
|
+
Run the same checks as CI:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
uv run coverage run -m pytest -q
|
|
52
|
+
uv run coverage report
|
|
53
|
+
uv run ruff format --check .
|
|
54
|
+
uv run ruff check .
|
|
55
|
+
uv run ty check --error all .
|
|
56
|
+
uv build
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Tests that require live Modal or Devin credentials must be opt-in and must not
|
|
60
|
+
claim production sessions. Every runtime change should also have a network-free
|
|
61
|
+
lifecycle test covering cleanup and claim release.
|
|
62
|
+
|
|
63
|
+
To verify real Modal serialization and image hydration in a disposable workspace:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
MODAL_DEVIN_RUN_MODAL_INTEGRATION=1 uv run pytest -m integration -q
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
The integration test creates an ephemeral Modal app and does not contact Devin.
|
|
70
|
+
|
|
71
|
+
## Security
|
|
72
|
+
|
|
73
|
+
Never put credentials in command arguments, logs, generated files, image-layer
|
|
74
|
+
metadata, or Git remote URLs. Report vulnerabilities using `SECURITY.md` rather
|
|
75
|
+
than a public issue.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 modal-devin contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: modal-devin
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Run Devin Outposts workers on Modal
|
|
5
|
+
Project-URL: Repository, https://github.com/aaazzam/modal-devin
|
|
6
|
+
Project-URL: Issues, https://github.com/aaazzam/modal-devin/issues
|
|
7
|
+
Project-URL: Changelog, https://github.com/aaazzam/modal-devin/blob/main/CHANGELOG.md
|
|
8
|
+
Project-URL: Documentation, https://github.com/aaazzam/modal-devin#readme
|
|
9
|
+
Author-email: Adam Azzam <33043305+aaazzam@users.noreply.github.com>
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: devin,modal,outposts,workers
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Environment :: Console
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
22
|
+
Classifier: Typing :: Typed
|
|
23
|
+
Requires-Python: >=3.11
|
|
24
|
+
Requires-Dist: cyclopts>=4.20
|
|
25
|
+
Requires-Dist: modal<2,>=1.5.1
|
|
26
|
+
Requires-Dist: rich>=13.6
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
# modal-devin
|
|
30
|
+
|
|
31
|
+
Run Devin Outposts sessions on Modal.
|
|
32
|
+
|
|
33
|
+
Devin's planning remains in Devin Cloud while commands, file edits, and repository
|
|
34
|
+
access run in isolated [Modal Sandboxes](https://modal.com/docs/guide/sandboxes) that
|
|
35
|
+
you control. `modal-devin` provides the orchestrator: it watches your Outposts pool,
|
|
36
|
+
starts a Sandbox for each session, preserves suspended work, and cleans up when the
|
|
37
|
+
session ends.
|
|
38
|
+
|
|
39
|
+
> [!NOTE]
|
|
40
|
+
> `modal-devin` is alpha software. Until the first stable release, only the latest
|
|
41
|
+
> release on the default branch receives security fixes.
|
|
42
|
+
|
|
43
|
+
## When to use it
|
|
44
|
+
|
|
45
|
+
Use `modal-devin` when you want Devin sessions to:
|
|
46
|
+
|
|
47
|
+
- Run with custom tools, repositories, and system packages.
|
|
48
|
+
- Reach services and registries available from your Modal environment.
|
|
49
|
+
- Use Modal compute, memory, and region controls.
|
|
50
|
+
- Resume from a preserved workspace after suspension.
|
|
51
|
+
- Fit into an existing Python and Modal deployment workflow.
|
|
52
|
+
|
|
53
|
+
## How it fits into Outposts
|
|
54
|
+
|
|
55
|
+
Outposts separates the worker from the orchestrator:
|
|
56
|
+
|
|
57
|
+
- The **worker** executes one Devin session. `modal-devin` runs it inside a Modal
|
|
58
|
+
Sandbox.
|
|
59
|
+
- The **orchestrator** finds queued sessions and manages their compute lifecycle.
|
|
60
|
+
`modal-devin` deploys this layer as a Modal application.
|
|
61
|
+
|
|
62
|
+
Workers need outbound HTTPS access to Devin. They do not require inbound ports or a
|
|
63
|
+
public IP.
|
|
64
|
+
|
|
65
|
+
## Quick start
|
|
66
|
+
|
|
67
|
+
You need Python 3.11 or newer, a configured Modal account, an Outposts pool ID, and
|
|
68
|
+
a Devin token authorized for that pool.
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
uv add modal-devin
|
|
72
|
+
uv run modal setup
|
|
73
|
+
uv run modal-devin init my-pool --pool-id outpost_env-...
|
|
74
|
+
uv run modal-devin doctor
|
|
75
|
+
uv run modal-devin deploy pools/my_pool.py
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Run `uv run modal-devin init` without arguments to create a pool interactively.
|
|
79
|
+
|
|
80
|
+
The generated Python file is your Modal application. Edit it to choose the workspace
|
|
81
|
+
image, secrets, compute, region, retry policy, and schedule. The library manages the
|
|
82
|
+
Outposts and Sandbox lifecycle behind that application.
|
|
83
|
+
|
|
84
|
+
## Customize the workspace
|
|
85
|
+
|
|
86
|
+
Add packages and project source to the generated image block, before
|
|
87
|
+
`prepare_image()`:
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
base_image = (
|
|
91
|
+
worker.base_image()
|
|
92
|
+
.apt_install("ripgrep")
|
|
93
|
+
.run_commands(
|
|
94
|
+
"git clone https://github.com/your-org/app /root/workspace/app"
|
|
95
|
+
)
|
|
96
|
+
)
|
|
97
|
+
image = worker.prepare_image(base_image)
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Documentation
|
|
101
|
+
|
|
102
|
+
Full tutorials, how-to guides, and reference docs live in this repository under
|
|
103
|
+
`tutorials/`, `guides/`, `explanation/`, and `reference/`. They're written for the
|
|
104
|
+
project's Mintlify site, which isn't published yet, so some page components won't
|
|
105
|
+
render when viewed directly on GitHub:
|
|
106
|
+
|
|
107
|
+
- [Deploy your first worker](tutorials/first-worker.mdx)
|
|
108
|
+
- [Build a project workspace](tutorials/custom-workspace.mdx)
|
|
109
|
+
- [Configure resources and regions](guides/resources-and-regions.mdx)
|
|
110
|
+
- [Operate a deployed worker](guides/operate-a-worker.mdx)
|
|
111
|
+
- [Security model](explanation/security.mdx)
|
|
112
|
+
|
|
113
|
+
## Security
|
|
114
|
+
|
|
115
|
+
Use a least-privilege Devin service user and separate credentials for environments
|
|
116
|
+
with different trust requirements. The session workload does not receive the raw
|
|
117
|
+
Outposts token in its environment, although it can exercise the Outposts capability
|
|
118
|
+
required to serve its assigned session.
|
|
119
|
+
|
|
120
|
+
Report vulnerabilities through
|
|
121
|
+
[GitHub private vulnerability reporting](https://github.com/aaazzam/modal-devin/security).
|
|
122
|
+
|
|
123
|
+
## Development
|
|
124
|
+
|
|
125
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for the development and test workflow.
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# modal-devin
|
|
2
|
+
|
|
3
|
+
Run Devin Outposts sessions on Modal.
|
|
4
|
+
|
|
5
|
+
Devin's planning remains in Devin Cloud while commands, file edits, and repository
|
|
6
|
+
access run in isolated [Modal Sandboxes](https://modal.com/docs/guide/sandboxes) that
|
|
7
|
+
you control. `modal-devin` provides the orchestrator: it watches your Outposts pool,
|
|
8
|
+
starts a Sandbox for each session, preserves suspended work, and cleans up when the
|
|
9
|
+
session ends.
|
|
10
|
+
|
|
11
|
+
> [!NOTE]
|
|
12
|
+
> `modal-devin` is alpha software. Until the first stable release, only the latest
|
|
13
|
+
> release on the default branch receives security fixes.
|
|
14
|
+
|
|
15
|
+
## When to use it
|
|
16
|
+
|
|
17
|
+
Use `modal-devin` when you want Devin sessions to:
|
|
18
|
+
|
|
19
|
+
- Run with custom tools, repositories, and system packages.
|
|
20
|
+
- Reach services and registries available from your Modal environment.
|
|
21
|
+
- Use Modal compute, memory, and region controls.
|
|
22
|
+
- Resume from a preserved workspace after suspension.
|
|
23
|
+
- Fit into an existing Python and Modal deployment workflow.
|
|
24
|
+
|
|
25
|
+
## How it fits into Outposts
|
|
26
|
+
|
|
27
|
+
Outposts separates the worker from the orchestrator:
|
|
28
|
+
|
|
29
|
+
- The **worker** executes one Devin session. `modal-devin` runs it inside a Modal
|
|
30
|
+
Sandbox.
|
|
31
|
+
- The **orchestrator** finds queued sessions and manages their compute lifecycle.
|
|
32
|
+
`modal-devin` deploys this layer as a Modal application.
|
|
33
|
+
|
|
34
|
+
Workers need outbound HTTPS access to Devin. They do not require inbound ports or a
|
|
35
|
+
public IP.
|
|
36
|
+
|
|
37
|
+
## Quick start
|
|
38
|
+
|
|
39
|
+
You need Python 3.11 or newer, a configured Modal account, an Outposts pool ID, and
|
|
40
|
+
a Devin token authorized for that pool.
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
uv add modal-devin
|
|
44
|
+
uv run modal setup
|
|
45
|
+
uv run modal-devin init my-pool --pool-id outpost_env-...
|
|
46
|
+
uv run modal-devin doctor
|
|
47
|
+
uv run modal-devin deploy pools/my_pool.py
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Run `uv run modal-devin init` without arguments to create a pool interactively.
|
|
51
|
+
|
|
52
|
+
The generated Python file is your Modal application. Edit it to choose the workspace
|
|
53
|
+
image, secrets, compute, region, retry policy, and schedule. The library manages the
|
|
54
|
+
Outposts and Sandbox lifecycle behind that application.
|
|
55
|
+
|
|
56
|
+
## Customize the workspace
|
|
57
|
+
|
|
58
|
+
Add packages and project source to the generated image block, before
|
|
59
|
+
`prepare_image()`:
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
base_image = (
|
|
63
|
+
worker.base_image()
|
|
64
|
+
.apt_install("ripgrep")
|
|
65
|
+
.run_commands(
|
|
66
|
+
"git clone https://github.com/your-org/app /root/workspace/app"
|
|
67
|
+
)
|
|
68
|
+
)
|
|
69
|
+
image = worker.prepare_image(base_image)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Documentation
|
|
73
|
+
|
|
74
|
+
Full tutorials, how-to guides, and reference docs live in this repository under
|
|
75
|
+
`tutorials/`, `guides/`, `explanation/`, and `reference/`. They're written for the
|
|
76
|
+
project's Mintlify site, which isn't published yet, so some page components won't
|
|
77
|
+
render when viewed directly on GitHub:
|
|
78
|
+
|
|
79
|
+
- [Deploy your first worker](tutorials/first-worker.mdx)
|
|
80
|
+
- [Build a project workspace](tutorials/custom-workspace.mdx)
|
|
81
|
+
- [Configure resources and regions](guides/resources-and-regions.mdx)
|
|
82
|
+
- [Operate a deployed worker](guides/operate-a-worker.mdx)
|
|
83
|
+
- [Security model](explanation/security.mdx)
|
|
84
|
+
|
|
85
|
+
## Security
|
|
86
|
+
|
|
87
|
+
Use a least-privilege Devin service user and separate credentials for environments
|
|
88
|
+
with different trust requirements. The session workload does not receive the raw
|
|
89
|
+
Outposts token in its environment, although it can exercise the Outposts capability
|
|
90
|
+
required to serve its assigned session.
|
|
91
|
+
|
|
92
|
+
Report vulnerabilities through
|
|
93
|
+
[GitHub private vulnerability reporting](https://github.com/aaazzam/modal-devin/security).
|
|
94
|
+
|
|
95
|
+
## Development
|
|
96
|
+
|
|
97
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for the development and test workflow.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Supported versions
|
|
4
|
+
|
|
5
|
+
Until the first stable release, only the latest release on the default branch is
|
|
6
|
+
supported with security fixes.
|
|
7
|
+
|
|
8
|
+
## Reporting a vulnerability
|
|
9
|
+
|
|
10
|
+
Please use GitHub's private vulnerability reporting for this repository. Do not
|
|
11
|
+
open a public issue or include live Devin, Modal, or repository credentials in a
|
|
12
|
+
report.
|
|
13
|
+
|
|
14
|
+
Include the affected version, reproduction steps, expected impact, and whether
|
|
15
|
+
you believe a credential or customer workload was exposed. You should receive
|
|
16
|
+
an acknowledgement within five business days.
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://mintlify.com/docs.json",
|
|
3
|
+
"theme": "mint",
|
|
4
|
+
"name": "modal-devin",
|
|
5
|
+
"description": "Run secure, resumable Devin Outposts workers on Modal.",
|
|
6
|
+
"colors": {
|
|
7
|
+
"primary": "#3730A3",
|
|
8
|
+
"light": "#A5B4FC",
|
|
9
|
+
"dark": "#6366F1"
|
|
10
|
+
},
|
|
11
|
+
"navigation": {
|
|
12
|
+
"groups": [
|
|
13
|
+
{
|
|
14
|
+
"group": "Start here",
|
|
15
|
+
"icon": "house",
|
|
16
|
+
"pages": [
|
|
17
|
+
"index"
|
|
18
|
+
]
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"group": "Tutorials",
|
|
22
|
+
"icon": "graduation-cap",
|
|
23
|
+
"pages": [
|
|
24
|
+
"tutorials/first-worker",
|
|
25
|
+
"tutorials/create-a-pool",
|
|
26
|
+
"tutorials/custom-workspace"
|
|
27
|
+
]
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"group": "How-to guides",
|
|
31
|
+
"icon": "screwdriver-wrench",
|
|
32
|
+
"pages": [
|
|
33
|
+
"guides/customize-image",
|
|
34
|
+
"guides/resources-and-regions",
|
|
35
|
+
"guides/runtime-configuration",
|
|
36
|
+
"guides/multiple-pools",
|
|
37
|
+
"guides/operate-a-worker",
|
|
38
|
+
"guides/troubleshooting"
|
|
39
|
+
]
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"group": "Concepts",
|
|
43
|
+
"icon": "lightbulb",
|
|
44
|
+
"pages": [
|
|
45
|
+
"explanation/architecture",
|
|
46
|
+
"explanation/resumability",
|
|
47
|
+
"explanation/security",
|
|
48
|
+
"explanation/session-lifecycle",
|
|
49
|
+
"explanation/timeouts"
|
|
50
|
+
]
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"group": "Reference",
|
|
54
|
+
"icon": "book-open",
|
|
55
|
+
"pages": [
|
|
56
|
+
"reference/cli",
|
|
57
|
+
"reference/worker",
|
|
58
|
+
"reference/settings",
|
|
59
|
+
"reference/images",
|
|
60
|
+
"reference/exceptions",
|
|
61
|
+
"reference/generated-application"
|
|
62
|
+
]
|
|
63
|
+
}
|
|
64
|
+
]
|
|
65
|
+
},
|
|
66
|
+
"navbar": {
|
|
67
|
+
"links": [
|
|
68
|
+
{
|
|
69
|
+
"label": "GitHub",
|
|
70
|
+
"href": "https://github.com/aaazzam/modal-devin"
|
|
71
|
+
}
|
|
72
|
+
],
|
|
73
|
+
"primary": {
|
|
74
|
+
"type": "github",
|
|
75
|
+
"href": "https://github.com/aaazzam/modal-devin"
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
"footer": {
|
|
79
|
+
"socials": {
|
|
80
|
+
"github": "https://github.com/aaazzam/modal-devin"
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
"contextual": {
|
|
84
|
+
"options": [
|
|
85
|
+
"copy",
|
|
86
|
+
"view",
|
|
87
|
+
"chatgpt",
|
|
88
|
+
"claude"
|
|
89
|
+
]
|
|
90
|
+
},
|
|
91
|
+
"styling": {
|
|
92
|
+
"eyebrows": "breadcrumbs"
|
|
93
|
+
}
|
|
94
|
+
}
|