devin-devkit 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- devin_devkit/__init__.py +1 -0
- devin_devkit/cli.py +128 -0
- devin_devkit/installer.py +213 -0
- devin_devkit/manifest.json +1201 -0
- devin_devkit/updater.py +262 -0
- devin_devkit-0.1.0.dist-info/METADATA +129 -0
- devin_devkit-0.1.0.dist-info/RECORD +10 -0
- devin_devkit-0.1.0.dist-info/WHEEL +5 -0
- devin_devkit-0.1.0.dist-info/entry_points.txt +2 -0
- devin_devkit-0.1.0.dist-info/top_level.txt +1 -0
devin_devkit/updater.py
ADDED
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
"""Update installed tools against the remote devkit manifest.
|
|
2
|
+
|
|
3
|
+
The bundled ``manifest.json`` is a snapshot: every install spec is pinned to a
|
|
4
|
+
PyPI version or a GitHub tarball SHA at export time, so installs never move by
|
|
5
|
+
themselves. This module fetches the manifest published in the devin-devkit
|
|
6
|
+
repository (always the newest registry export) and computes a plan to bring
|
|
7
|
+
installed tools up to date.
|
|
8
|
+
"""
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import json
|
|
12
|
+
import os
|
|
13
|
+
import re
|
|
14
|
+
import shutil
|
|
15
|
+
import subprocess
|
|
16
|
+
import urllib.error
|
|
17
|
+
import urllib.request
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
from typing import Any, Callable
|
|
20
|
+
|
|
21
|
+
from devin_devkit.installer import DevKitError
|
|
22
|
+
|
|
23
|
+
REMOTE_MANIFEST_URL = (
|
|
24
|
+
"https://raw.githubusercontent.com/Icaro0310/devin-devkit/main/"
|
|
25
|
+
"packages/devkit/src/devin_devkit/manifest.json"
|
|
26
|
+
)
|
|
27
|
+
FETCH_TIMEOUT = 15
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def fetch_remote_manifest(
|
|
31
|
+
url: str = REMOTE_MANIFEST_URL,
|
|
32
|
+
*,
|
|
33
|
+
opener: Callable[..., Any] | None = None,
|
|
34
|
+
) -> dict[str, Any]:
|
|
35
|
+
"""Download and parse the published manifest; raise DevKitError on failure."""
|
|
36
|
+
open_fn = opener or urllib.request.urlopen
|
|
37
|
+
try:
|
|
38
|
+
with open_fn(url, timeout=FETCH_TIMEOUT) as response:
|
|
39
|
+
data = json.loads(response.read().decode("utf-8"))
|
|
40
|
+
except (OSError, urllib.error.URLError, json.JSONDecodeError) as exc:
|
|
41
|
+
raise DevKitError(f"cannot fetch remote manifest: {exc}") from exc
|
|
42
|
+
if data.get("schema") != "devin-devkit-manifest/0.1":
|
|
43
|
+
raise DevKitError("remote manifest has an unexpected schema")
|
|
44
|
+
return data
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def installed_uv_tools(
|
|
48
|
+
runner: Callable[..., Any] = subprocess.run,
|
|
49
|
+
) -> dict[str, str]:
|
|
50
|
+
"""Return {package: version} from ``uv tool list``."""
|
|
51
|
+
try:
|
|
52
|
+
result = runner(
|
|
53
|
+
["uv", "tool", "list"], capture_output=True, text=True, check=False
|
|
54
|
+
)
|
|
55
|
+
except OSError:
|
|
56
|
+
return {}
|
|
57
|
+
if result.returncode != 0:
|
|
58
|
+
return {}
|
|
59
|
+
installed: dict[str, str] = {}
|
|
60
|
+
for line in (result.stdout or "").splitlines():
|
|
61
|
+
if not line.strip() or line.startswith("-"):
|
|
62
|
+
continue
|
|
63
|
+
name, _, version = line.strip().partition(" ")
|
|
64
|
+
if name:
|
|
65
|
+
installed[name] = version.lstrip("v")
|
|
66
|
+
return installed
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
try:
|
|
70
|
+
import tomllib
|
|
71
|
+
except ImportError: # Python 3.10 — declared as a conditional dependency
|
|
72
|
+
import tomli as tomllib
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _uv_tools_dir() -> Path:
|
|
76
|
+
override = os.environ.get("UV_TOOL_DIR")
|
|
77
|
+
return (
|
|
78
|
+
Path(override)
|
|
79
|
+
if override
|
|
80
|
+
else Path.home() / ".local" / "share" / "uv" / "tools"
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def installed_uv_specs(
|
|
85
|
+
tools_dir: str | Path | None = None,
|
|
86
|
+
) -> dict[str, str]:
|
|
87
|
+
"""Return {package: installed requirement} parsed from uv receipts.
|
|
88
|
+
|
|
89
|
+
``uv tool list`` reports only name and version; the per-tool
|
|
90
|
+
``uv-receipt.toml`` also records the requirement, including the
|
|
91
|
+
source URL for non-PyPI installs. That lets the updater detect a
|
|
92
|
+
channel migration (git archive -> PyPI) even when the version number
|
|
93
|
+
did not change.
|
|
94
|
+
"""
|
|
95
|
+
root = Path(tools_dir) if tools_dir else _uv_tools_dir()
|
|
96
|
+
specs: dict[str, str] = {}
|
|
97
|
+
if not root.is_dir():
|
|
98
|
+
return specs
|
|
99
|
+
for receipt in root.glob("*/uv-receipt.toml"):
|
|
100
|
+
try:
|
|
101
|
+
data = tomllib.loads(receipt.read_text(encoding="utf-8"))
|
|
102
|
+
except (OSError, tomllib.TOMLDecodeError):
|
|
103
|
+
continue
|
|
104
|
+
for req in data.get("tool", {}).get("requirements", []):
|
|
105
|
+
if not isinstance(req, dict):
|
|
106
|
+
continue
|
|
107
|
+
name = req.get("name")
|
|
108
|
+
if not name:
|
|
109
|
+
continue
|
|
110
|
+
specs[name] = req.get("url") or f"{name}{req.get('specifier', '')}"
|
|
111
|
+
return specs
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def _spec_channel(spec: str) -> str:
|
|
115
|
+
"""Compare-key for install specs: PyPI installs collapse to 'pypi',
|
|
116
|
+
URL installs compare by exact URL."""
|
|
117
|
+
if re.match(r"(https?://|git\+)", spec):
|
|
118
|
+
return f"url:{spec}"
|
|
119
|
+
return "pypi"
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def installed_npm_tools(
|
|
123
|
+
runner: Callable[..., Any] = subprocess.run,
|
|
124
|
+
) -> dict[str, str]:
|
|
125
|
+
"""Return {package: version} from ``npm ls -g --depth=0 --json``."""
|
|
126
|
+
try:
|
|
127
|
+
result = runner(
|
|
128
|
+
["npm", "ls", "--global", "--depth=0", "--json"],
|
|
129
|
+
capture_output=True, text=True, check=False,
|
|
130
|
+
)
|
|
131
|
+
except OSError:
|
|
132
|
+
return {}
|
|
133
|
+
try:
|
|
134
|
+
data = json.loads(result.stdout or "{}")
|
|
135
|
+
except json.JSONDecodeError:
|
|
136
|
+
return {}
|
|
137
|
+
return {
|
|
138
|
+
name: meta.get("version", "")
|
|
139
|
+
for name, meta in data.get("dependencies", {}).items()
|
|
140
|
+
if isinstance(meta, dict)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def build_update_plan(
|
|
145
|
+
remote: dict[str, Any],
|
|
146
|
+
*,
|
|
147
|
+
installed: dict[str, str] | None = None,
|
|
148
|
+
installed_specs: dict[str, str] | None = None,
|
|
149
|
+
which: Callable[[str], str | None] = shutil.which,
|
|
150
|
+
runner: Callable[..., Any] = subprocess.run,
|
|
151
|
+
force: bool = False,
|
|
152
|
+
) -> dict[str, Any]:
|
|
153
|
+
"""Diff installed tools against the remote manifest.
|
|
154
|
+
|
|
155
|
+
``installed`` maps package name to installed version; when None it is
|
|
156
|
+
discovered via ``uv tool list`` and ``npm ls -g``.
|
|
157
|
+
``installed_specs`` maps package name to the requirement it was
|
|
158
|
+
installed from (uv receipts); when None it is discovered via
|
|
159
|
+
``installed_uv_specs``. A same-version channel change (git archive
|
|
160
|
+
-> PyPI pin) plans a reinstall rather than reporting ``current``.
|
|
161
|
+
"""
|
|
162
|
+
if installed is None:
|
|
163
|
+
installed = installed_uv_tools(runner)
|
|
164
|
+
installed.update(installed_npm_tools(runner))
|
|
165
|
+
if installed_specs is None:
|
|
166
|
+
installed_specs = installed_uv_specs()
|
|
167
|
+
|
|
168
|
+
actions: list[dict[str, Any]] = []
|
|
169
|
+
for tool in remote.get("tools", []):
|
|
170
|
+
tool_id = tool["id"]
|
|
171
|
+
manager = tool.get("manager")
|
|
172
|
+
if manager == "manual" or tool.get("status") == "manual":
|
|
173
|
+
continue
|
|
174
|
+
commands = tool.get("commands", [])
|
|
175
|
+
on_path = any(which(command) is not None for command in commands)
|
|
176
|
+
if tool["package"] not in installed and not on_path:
|
|
177
|
+
actions.append({"tool": tool_id, "action": "not-installed"})
|
|
178
|
+
continue
|
|
179
|
+
spec = tool.get("install_spec")
|
|
180
|
+
if not spec:
|
|
181
|
+
actions.append({"tool": tool_id, "action": "blocked", "detail": "missing install specification"})
|
|
182
|
+
continue
|
|
183
|
+
local_version = installed.get(tool["package"], "?")
|
|
184
|
+
remote_version = tool.get("version", "?")
|
|
185
|
+
if not force and local_version == remote_version:
|
|
186
|
+
installed_spec = installed_specs.get(tool["package"])
|
|
187
|
+
if (
|
|
188
|
+
manager == "uv"
|
|
189
|
+
and installed_spec is not None
|
|
190
|
+
and _spec_channel(installed_spec) != _spec_channel(spec)
|
|
191
|
+
):
|
|
192
|
+
actions.append({
|
|
193
|
+
"tool": tool_id,
|
|
194
|
+
"action": "update",
|
|
195
|
+
"from": local_version,
|
|
196
|
+
"to": remote_version,
|
|
197
|
+
"reason": "install source changed",
|
|
198
|
+
"command": ["uv", "tool", "install", "--force", spec],
|
|
199
|
+
})
|
|
200
|
+
else:
|
|
201
|
+
actions.append({"tool": tool_id, "action": "current", "version": local_version})
|
|
202
|
+
continue
|
|
203
|
+
command = (
|
|
204
|
+
["uv", "tool", "install", "--force", spec]
|
|
205
|
+
if manager == "uv"
|
|
206
|
+
else ["npm", "install", "--global", spec]
|
|
207
|
+
)
|
|
208
|
+
actions.append({
|
|
209
|
+
"tool": tool_id,
|
|
210
|
+
"action": "update",
|
|
211
|
+
"from": local_version,
|
|
212
|
+
"to": remote_version,
|
|
213
|
+
"command": command,
|
|
214
|
+
})
|
|
215
|
+
return {
|
|
216
|
+
"registry_version": remote.get("registry_version"),
|
|
217
|
+
"generated": remote.get("generated"),
|
|
218
|
+
"actions": actions,
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def apply_update_plan(
|
|
223
|
+
plan: dict[str, Any],
|
|
224
|
+
runner: Callable[..., Any] = subprocess.run,
|
|
225
|
+
) -> dict[str, Any]:
|
|
226
|
+
updated: list[str] = []
|
|
227
|
+
failed: list[str] = []
|
|
228
|
+
for action in plan["actions"]:
|
|
229
|
+
if action["action"] != "update":
|
|
230
|
+
continue
|
|
231
|
+
try:
|
|
232
|
+
result = runner(action["command"], check=False)
|
|
233
|
+
except OSError:
|
|
234
|
+
result = None
|
|
235
|
+
if result is None or result.returncode:
|
|
236
|
+
failed.append(action["tool"])
|
|
237
|
+
else:
|
|
238
|
+
updated.append(action["tool"])
|
|
239
|
+
return {"updated": updated, "failed": failed}
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
def freshness_hint(
|
|
243
|
+
manifest: dict[str, Any],
|
|
244
|
+
*,
|
|
245
|
+
opener: Callable[..., Any] | None = None,
|
|
246
|
+
) -> str | None:
|
|
247
|
+
"""One-line hint when the remote registry is newer than the bundled manifest.
|
|
248
|
+
|
|
249
|
+
Never raises: network or parse problems simply return None.
|
|
250
|
+
"""
|
|
251
|
+
try:
|
|
252
|
+
remote = fetch_remote_manifest(opener=opener)
|
|
253
|
+
except DevKitError:
|
|
254
|
+
return None
|
|
255
|
+
local_version = manifest.get("registry_version", 0)
|
|
256
|
+
remote_version = remote.get("registry_version", 0)
|
|
257
|
+
if remote_version > local_version:
|
|
258
|
+
return (
|
|
259
|
+
f"registry v{remote_version} is available "
|
|
260
|
+
f"(bundled: v{local_version}); run 'devin-devkit update'"
|
|
261
|
+
)
|
|
262
|
+
return None
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: devin-devkit
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Install public Devin CLI profiles through uv
|
|
5
|
+
Author: Icaro0310
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
Requires-Dist: tomli>=2.0; python_version < "3.11"
|
|
10
|
+
Provides-Extra: dev
|
|
11
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
12
|
+
|
|
13
|
+
<div align="center">
|
|
14
|
+
|
|
15
|
+
<a href="https://github.com/Icaro0310/devin-devkit/actions/workflows/test-devkit.yml"><img src="https://github.com/Icaro0310/devin-devkit/actions/workflows/test-devkit.yml/badge.svg" alt="ci"/></a>
|
|
16
|
+
|
|
17
|
+
<a href="https://scorecard.dev/viewer/?uri=github.com/Icaro0310/devin-devkit"><img src="https://api.scorecard.dev/projects/github.com/Icaro0310/devin-devkit/badge" alt="OpenSSF Scorecard"/></a>
|
|
18
|
+
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-green" alt="License: MIT"/></a>
|
|
19
|
+
<a href="https://www.python.org/"><img src="https://img.shields.io/badge/python-3.10%2B-blue" alt="Python 3.10+"/></a>
|
|
20
|
+
<a href="https://github.com/Icaro0310/devin-devkit"><img src="https://img.shields.io/github/stars/Icaro0310/devin-devkit" alt="GitHub stars"/></a>
|
|
21
|
+
<a href="https://github.com/Icaro0310/devin-devkit/commits/main"><img src="https://img.shields.io/github/last-commit/Icaro0310/devin-devkit" alt="Last commit"/></a>
|
|
22
|
+
<a href="https://github.com/Icaro0310/awesome-devin"><img src="https://img.shields.io/badge/part%20of-devin--*-ecosystem-7c3aed" alt="devin-* ecosystem"/></a>
|
|
23
|
+
<a href="https://github.com/Icaro0310/devin-devkit/issues"><img src="https://img.shields.io/badge/PRs-welcome-brightgreen" alt="PRs welcome"/></a>
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
# devin-devkit
|
|
27
|
+
|
|
28
|
+
> Unofficial community project. Not affiliated with, endorsed by, or sponsored by Cognition AI. Devin is a Cognition AI trademark.
|
|
29
|
+
|
|
30
|
+
**[Linux](README.linux.md)** · **[Personal Windows](README.windows.md)** · **[Corporate Windows](README.corporate-windows.md)** · **[Compatibility](COMPATIBILITY.md)** · **[macOS status](README.macos.md)**
|
|
31
|
+
|
|
32
|
+
Part of the [awesome-devin](https://github.com/Icaro0310/awesome-devin) ecosystem: the curated hub for the devin-* tools.
|
|
33
|
+
|
|
34
|
+
`devin-devkit` turns the public `devin-powerups` registry into selectable installation profiles. It is an **installer/distribution tool**, not a meta-package: each Python app gets its own isolated `uv` environment, and the Node bridge uses npm separately.
|
|
35
|
+
|
|
36
|
+

|
|
37
|
+
|
|
38
|
+
## Source → tools → profiles
|
|
39
|
+
|
|
40
|
+
- `devin-powerups/registry.json` is the catalog and profile source of truth for the first-party `devin-*` tools, this separate DevKit distribution, the maintainer hub, and related artifacts.
|
|
41
|
+
- `tools/export_devkit_manifest.py` builds this repo's bundled manifest from the registry, including artifact, interface, audience, platform and environment metadata. The exporter rejects private or unregistered tools and verifies immutable Git commit references.
|
|
42
|
+
- `src/devin_devkit/cli.py` previews and installs the selected profile under an explicit execution environment. It does not edit Devin settings, inspect session databases, or install Slack/Obsidian/VM services.
|
|
43
|
+
|
|
44
|
+
## Execution environments
|
|
45
|
+
|
|
46
|
+
One `devin-devkit` distribution supports three environments. Linux and Personal Windows use the extended runtime: local execution plus optional delegated workloads through Devin VM or QwenPaw when the selected tool supports them. Corporate Windows is intentionally self-contained: local execution only, with no VM, QwenPaw, Slack dependency, external compute, or workload delegation.
|
|
47
|
+
|
|
48
|
+
The installer defaults to `linux` on Linux and `personal-windows` on Windows. Corporate Windows is never inferred from the operating system; select it explicitly so restricted machines fail closed:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
devin-devkit install qa --environment linux
|
|
52
|
+
devin-devkit install qa --environment personal-windows
|
|
53
|
+
devin-devkit install qa --environment corporate-windows
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Environment entry points: [Linux](environments/linux/README.md) · [Personal Windows](environments/personal-windows/README.md) · [Corporate Windows](environments/corporate-windows/README.md).
|
|
57
|
+
|
|
58
|
+
The generated [compatibility matrix](COMPATIBILITY.md) is rendered from `registry.json`; unsupported entries carry an explicit registry reason rather than guessed compatibility.
|
|
59
|
+
|
|
60
|
+
## Profiles
|
|
61
|
+
|
|
62
|
+
| Profile | Contents |
|
|
63
|
+
|---|---|
|
|
64
|
+
| `qa` | internals spec, QA pack, evals, metrics, doctor |
|
|
65
|
+
| `evaluation` | internals spec, evals, metrics, synthetic task fixtures |
|
|
66
|
+
| `security` | redact, bridge, janitor |
|
|
67
|
+
| `memory` / `agent` | memory, graph, search, poordjaevin |
|
|
68
|
+
| `operations` | backup, history, doctor, metrics, janitor, PM, orchestrator, switch and skill catalog |
|
|
69
|
+
| `full` / `all` | every automatically installable profile tool; `devin-office` remains a manual source-only service |
|
|
70
|
+
|
|
71
|
+
QwenPaw is an optional add-on and is not installed by these profiles. macOS is planned, not tested.
|
|
72
|
+
|
|
73
|
+
## Use
|
|
74
|
+
|
|
75
|
+
Install the current GitHub source archive or use a local checkout; the package has no runtime dependencies:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
uv tool install "git+https://github.com/Icaro0310/devin-devkit.git#subdirectory=packages/devkit"
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
From a local checkout, use `uv tool install .`. Then inspect the available profiles and preview before applying:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
devin-devkit profiles
|
|
85
|
+
devin-devkit list
|
|
86
|
+
devin-devkit install qa
|
|
87
|
+
devin-devkit install qa --apply
|
|
88
|
+
devin-devkit install full --apply
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Install specs are pinned (PyPI versions or GitHub archive SHAs), so an install never drifts on its own. To move forward:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
devin-devkit outdated # which installed tools have newer pins
|
|
95
|
+
devin-devkit update # preview the update plan
|
|
96
|
+
devin-devkit update --apply # reinstall outdated tools
|
|
97
|
+
devin-devkit update --force --apply # reinstall everything
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
`outdated`/`update` read the manifest published in this repository, which a weekly workflow re-exports from the maintainer registry, so the pins are never more than about a week behind upstream.
|
|
101
|
+
|
|
102
|
+
To run from a checkout without installing the DevKit itself:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
uv run --project . python -m devin_devkit.cli install qa
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
After a PyPI package release, the installer can also be run with `uvx devin-devkit ...`.
|
|
109
|
+
|
|
110
|
+
The manifest pins PyPI versions where available and GitHub source archives to immutable commit SHAs otherwise. Before it starts, the installer checks platform support, registry-declared environment compatibility, required managers, Node.js for `devin-bridge`, and existing command collisions. It never overwrites an existing command; commands already on `PATH` are reported as pre-existing but are not version-verified, and a partial collision blocks the profile before any installs run.
|
|
111
|
+
|
|
112
|
+
## Runtime requirements
|
|
113
|
+
|
|
114
|
+
- Python tools: Python 3.10 or newer, installed in isolated environments managed by `uv`.
|
|
115
|
+
- `devin-bridge`: Node.js 20 or newer and npm. Its pinned GitHub archive is downloaded over HTTPS.
|
|
116
|
+
- Current installable profiles do not need Git. Git is needed only for manual source checkouts such as `devin-office`; package archives use HTTPS.
|
|
117
|
+
- Supported environments: Linux, Personal Windows and Corporate Windows. Linux and Personal Windows may use optional delegated runtime; Corporate Windows rejects registry entries that require external runtime, delegation or external integrations. macOS is planned but not claimed as tested.
|
|
118
|
+
|
|
119
|
+
## Development and synchronization
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
uv run --extra dev pytest
|
|
123
|
+
python ../devin-powerups/tools/validate_registry.py
|
|
124
|
+
python ../devin-powerups/tools/export_devkit_manifest.py
|
|
125
|
+
python ../devin-powerups/tools/export_devkit_manifest.py --check
|
|
126
|
+
python ../devin-powerups/tools/render_catalog.py --check ../Icaro0310/README.md
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
The DevKit package has no runtime dependencies. New catalog entries and profiles belong in the registry; regenerate the manifest instead of hand-editing its generated copy. For local sibling development, install dependencies editably in a virtual environment (examples in the OS guides); keep relative file paths out of publishable package metadata.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
devin_devkit/__init__.py,sha256=kUR5RAFc7HCeiqdlX36dZOHkUI5wI6V_43RpEcD8b-0,22
|
|
2
|
+
devin_devkit/cli.py,sha256=d47vn96QAuW-inihysQ6PZnC_YoWjP1WVKGnMaBMuJE,6348
|
|
3
|
+
devin_devkit/installer.py,sha256=4sD6jF4mhiXCRiHKHfR8MnS9igPMSow5ltRcpMGtvuc,9369
|
|
4
|
+
devin_devkit/manifest.json,sha256=dkoeo9v3lS7st2h1e6KBWY5GPDhJZ5uvU5ptCVFmnoQ,32670
|
|
5
|
+
devin_devkit/updater.py,sha256=Ula6hTPJul1LPd0pqcOzmd4iAKem3LMXHrrK_tC23TU,8916
|
|
6
|
+
devin_devkit-0.1.0.dist-info/METADATA,sha256=LYBZ5Hfw3tYHR7pFbUYzrJu6XmAgzPAARgywlL69ZYI,7963
|
|
7
|
+
devin_devkit-0.1.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
8
|
+
devin_devkit-0.1.0.dist-info/entry_points.txt,sha256=BGUJCma8kpI1LPWYzFy_I7IjFItBXV4BegYR_dWxOYg,55
|
|
9
|
+
devin_devkit-0.1.0.dist-info/top_level.txt,sha256=a-JvTFjEDz6sJz_SmzJLF5pxXiqBNNyd-RtD0QxQGdI,13
|
|
10
|
+
devin_devkit-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
devin_devkit
|