darabos commited on
Commit
fc43558
Β·
1 Parent(s): 0715aa0

Find plugins by module name instead of namespace module.

Browse files
Files changed (39) hide show
  1. README.md +2 -3
  2. {lynxkite-app/data β†’ examples}/AIMO +0 -0
  3. {lynxkite-app/data β†’ examples}/Graph RAG +0 -0
  4. {lynxkite-app/data β†’ examples}/Image processing +0 -0
  5. {lynxkite-app/data β†’ examples}/LynxScribe demo +0 -0
  6. {lynxkite-app/data β†’ examples}/NetworkX demo +0 -0
  7. {lynxkite-app/data β†’ examples}/PyTorch demo +0 -0
  8. {lynxkite-app/data β†’ examples}/RAG chatbot app +0 -0
  9. {lynxkite-app/data β†’ examples}/aimo-examples.csv +0 -0
  10. {lynxkite-app/data β†’ examples}/example-pizza.md +0 -0
  11. {lynxkite-app/data β†’ examples}/night demo +0 -0
  12. {lynxkite-app/data β†’ examples}/sql +0 -0
  13. lynxkite-app/README.md +1 -1
  14. lynxkite-app/pyproject.toml +4 -4
  15. lynxkite-app/src/build_frontend.py +1 -1
  16. lynxkite-app/src/lynxkite/app/web_assets/__init__.py +0 -1
  17. lynxkite-app/src/lynxkite/app/web_assets/assets/__init__.py +0 -1
  18. lynxkite-app/src/{lynxkite/app β†’ lynxkite_app}/__init__.py +0 -0
  19. lynxkite-app/src/{lynxkite/app β†’ lynxkite_app}/__main__.py +1 -1
  20. lynxkite-app/src/{lynxkite/app β†’ lynxkite_app}/crdt.py +0 -0
  21. lynxkite-app/src/{lynxkite/app β†’ lynxkite_app}/main.py +14 -20
  22. lynxkite-app/tests/test_crdt.py +1 -1
  23. lynxkite-app/tests/test_main.py +1 -1
  24. lynxkite-app/web/src/Directory.tsx +43 -43
  25. lynxkite-app/web/src/index.css +0 -1
  26. lynxkite-core/src/lynxkite/core/ops.py +2 -0
  27. lynxkite-graph-analytics/pyproject.toml +3 -3
  28. lynxkite-graph-analytics/src/lynxkite_graph_analytics/__init__.py +3 -0
  29. lynxkite-graph-analytics/src/{lynxkite_plugins/graph_analytics β†’ lynxkite_graph_analytics}/lynxkite_ops.py +0 -0
  30. lynxkite-graph-analytics/src/{lynxkite_plugins/graph_analytics β†’ lynxkite_graph_analytics}/networkx_ops.py +0 -0
  31. lynxkite-graph-analytics/src/{lynxkite_plugins/graph_analytics β†’ lynxkite_graph_analytics}/pytorch_model_ops.py +0 -0
  32. lynxkite-graph-analytics/src/lynxkite_plugins/graph_analytics/__init__.py +0 -3
  33. lynxkite-graph-analytics/tests/test_lynxkite_ops.py +1 -1
  34. lynxkite-lynxscribe/README.md +1 -1
  35. lynxkite-lynxscribe/src/{lynxkite_plugins/lynxscribe β†’ lynxkite_lynxscribe}/__init__.py +2 -2
  36. lynxkite-lynxscribe/src/{lynxkite_plugins/lynxscribe β†’ lynxkite_lynxscribe}/llm_ops.py +0 -0
  37. lynxkite-lynxscribe/src/{lynxkite_plugins/lynxscribe β†’ lynxkite_lynxscribe}/lynxscribe_ops.py +0 -0
  38. lynxkite-pillow-example/pyproject.toml +2 -2
  39. lynxkite-pillow-example/src/{lynxkite_plugins/pillow_example β†’ lynxkite_pillow_example}/__init__.py +0 -0
README.md CHANGED
@@ -24,14 +24,13 @@ Install everything like this:
24
  uv venv
25
  source .venv/bin/activate
26
  # The [dev] tag is only needed if you intend on running tests
27
- uv pip install -e lynxkite-core/[dev] lynxkite-app/[dev] lynxkite-graph-analytics/[dev] lynxkite-lynxscribe/ lynxkite-pillow-example/
28
  ```
29
 
30
  This also builds the frontend, hopefully very quickly. To run it:
31
 
32
  ```bash
33
- cd lynxkite-app # just because the "data" directory with the examples is here
34
- LYNXKITE_RELOAD=1 lynxkite
35
  ```
36
 
37
  If you also want to make changes to the frontend with hot reloading:
 
24
  uv venv
25
  source .venv/bin/activate
26
  # The [dev] tag is only needed if you intend on running tests
27
+ uv pip install -e lynxkite-core/[dev] -e lynxkite-app/[dev] -e lynxkite-graph-analytics/[dev] -e lynxkite-lynxscribe/ -e lynxkite-pillow-example/
28
  ```
29
 
30
  This also builds the frontend, hopefully very quickly. To run it:
31
 
32
  ```bash
33
+ LYNXKITE_DATA=examples LYNXKITE_RELOAD=1 lynxkite
 
34
  ```
35
 
36
  If you also want to make changes to the frontend with hot reloading:
{lynxkite-app/data β†’ examples}/AIMO RENAMED
File without changes
{lynxkite-app/data β†’ examples}/Graph RAG RENAMED
File without changes
{lynxkite-app/data β†’ examples}/Image processing RENAMED
File without changes
{lynxkite-app/data β†’ examples}/LynxScribe demo RENAMED
File without changes
{lynxkite-app/data β†’ examples}/NetworkX demo RENAMED
File without changes
{lynxkite-app/data β†’ examples}/PyTorch demo RENAMED
File without changes
{lynxkite-app/data β†’ examples}/RAG chatbot app RENAMED
File without changes
{lynxkite-app/data β†’ examples}/aimo-examples.csv RENAMED
File without changes
{lynxkite-app/data β†’ examples}/example-pizza.md RENAMED
File without changes
{lynxkite-app/data β†’ examples}/night demo RENAMED
File without changes
{lynxkite-app/data β†’ examples}/sql RENAMED
File without changes
lynxkite-app/README.md CHANGED
@@ -13,7 +13,7 @@ To run the backend:
13
 
14
  ```bash
15
  uv pip install -e .
16
- LYNXKITE_RELOAD=1 lynxkite
17
  ```
18
 
19
  To run the frontend:
 
13
 
14
  ```bash
15
  uv pip install -e .
16
+ LYNXKITE_DATA=../examples LYNXKITE_RELOAD=1 lynxkite
17
  ```
18
 
19
  To run the frontend:
lynxkite-app/pyproject.toml CHANGED
@@ -15,7 +15,7 @@ dependencies = [
15
 
16
  [project.optional-dependencies]
17
  dev = [
18
- "pytest",
19
  ]
20
 
21
  [tool.uv.sources]
@@ -30,8 +30,8 @@ namespaces = true
30
  where = ["src"]
31
 
32
  [tool.setuptools.package-data]
33
- "lynxkite.app.web_assets" = ["*"]
34
- "lynxkite.app.web_assets.assets" = ["*"]
35
 
36
  [tool.setuptools]
37
  py-modules = ["build_frontend"]
@@ -41,4 +41,4 @@ include-package-data = true
41
  build_py = "build_frontend.build_py"
42
 
43
  [project.scripts]
44
- lynxkite = "lynxkite.app.__main__:main"
 
15
 
16
  [project.optional-dependencies]
17
  dev = [
18
+ "pytest>=8.3.4",
19
  ]
20
 
21
  [tool.uv.sources]
 
30
  where = ["src"]
31
 
32
  [tool.setuptools.package-data]
33
+ "lynxkite_app.web_assets" = ["*"]
34
+ "lynxkite_app.web_assets.assets" = ["*"]
35
 
36
  [tool.setuptools]
37
  py-modules = ["build_frontend"]
 
41
  build_py = "build_frontend.build_py"
42
 
43
  [project.scripts]
44
+ lynxkite = "lynxkite_app.__main__:main"
lynxkite-app/src/build_frontend.py CHANGED
@@ -11,7 +11,7 @@ class build_py(_build_py):
11
  print("\n\nBuilding frontend...", __file__)
12
  here = Path(__file__).parent.parent
13
  frontend_dir = here / "web"
14
- package_dir = here / "src" / "lynxkite" / "app" / "web_assets"
15
  subprocess.check_call(["npm", "install"], cwd=frontend_dir)
16
  subprocess.check_call(["npm", "run", "build"], cwd=frontend_dir)
17
  print("files in", frontend_dir / "dist")
 
11
  print("\n\nBuilding frontend...", __file__)
12
  here = Path(__file__).parent.parent
13
  frontend_dir = here / "web"
14
+ package_dir = here / "src" / "lynxkite_app" / "web_assets"
15
  subprocess.check_call(["npm", "install"], cwd=frontend_dir)
16
  subprocess.check_call(["npm", "run", "build"], cwd=frontend_dir)
17
  print("files in", frontend_dir / "dist")
lynxkite-app/src/lynxkite/app/web_assets/__init__.py DELETED
@@ -1 +0,0 @@
1
- """The build process (uv build) puts the frontend build artifacts here."""
 
 
lynxkite-app/src/lynxkite/app/web_assets/assets/__init__.py DELETED
@@ -1 +0,0 @@
1
- """More frontend build artifacts."""
 
 
lynxkite-app/src/{lynxkite/app β†’ lynxkite_app}/__init__.py RENAMED
File without changes
lynxkite-app/src/{lynxkite/app β†’ lynxkite_app}/__main__.py RENAMED
@@ -6,7 +6,7 @@ import os
6
  def main():
7
  port = int(os.environ.get("PORT", "8000"))
8
  reload = bool(os.environ.get("LYNXKITE_RELOAD", ""))
9
- uvicorn.run("lynxkite.app.main:app", host="0.0.0.0", port=port, reload=reload)
10
 
11
 
12
  if __name__ == "__main__":
 
6
  def main():
7
  port = int(os.environ.get("PORT", "8000"))
8
  reload = bool(os.environ.get("LYNXKITE_RELOAD", ""))
9
+ uvicorn.run("lynxkite_app.main:app", host="0.0.0.0", port=port, reload=reload)
10
 
11
 
12
  if __name__ == "__main__":
lynxkite-app/src/{lynxkite/app β†’ lynxkite_app}/crdt.py RENAMED
File without changes
lynxkite-app/src/{lynxkite/app β†’ lynxkite_app}/main.py RENAMED
@@ -1,5 +1,8 @@
 
 
1
  import os
2
  import shutil
 
3
  if os.environ.get("NX_CUGRAPH_AUTOCONFIG", "").strip().lower() == "true":
4
  import cudf.pandas
5
 
@@ -17,19 +20,13 @@ from . import crdt
17
 
18
 
19
  def detect_plugins():
20
- try:
21
- import lynxkite_plugins
22
- except ImportError:
23
- print("No modules found in lynxkite_plugins. Be sure to install some plugins.")
24
- return {}
25
-
26
  plugins = {}
27
- for _, name, _ in pkgutil.iter_modules(lynxkite_plugins.__path__):
28
- name = f"lynxkite_plugins.{name}"
29
- print(f"Importing {name}")
30
- plugins[name] = importlib.import_module(name)
31
  if not plugins:
32
- print("No modules found in lynxkite_plugins. Be sure to install some plugins.")
33
  return plugins
34
 
35
 
@@ -69,7 +66,7 @@ async def save_and_execute(req: SaveRequest):
69
  @app.post("/api/delete")
70
  async def delete_workspace(req: dict):
71
  json_path: pathlib.Path = DATA_PATH / req["path"]
72
- crdt_path: pathlib.Path = CRDT_PATH / f"{req["path"]}.crdt"
73
  assert json_path.is_relative_to(DATA_PATH)
74
  assert crdt_path.is_relative_to(CRDT_PATH)
75
  json_path.unlink()
@@ -85,8 +82,9 @@ def load(path: str):
85
  return workspace.load(path)
86
 
87
 
88
- DATA_PATH = pathlib.Path.cwd() / "data"
89
- CRDT_PATH = pathlib.Path.cwd() / "crdt_data"
 
90
 
91
  @dataclasses.dataclass(order=True)
92
  class DirectoryEntry:
@@ -120,11 +118,7 @@ def make_dir(req: dict):
120
  @app.post("/api/dir/delete")
121
  def delete_dir(req: dict):
122
  path: pathlib.Path = DATA_PATH / req["path"]
123
- assert all([
124
- path.is_relative_to(DATA_PATH),
125
- path.exists(),
126
- path.is_dir()
127
- ])
128
  shutil.rmtree(path)
129
  return list_dir(path.parent)
130
 
@@ -159,5 +153,5 @@ class SPAStaticFiles(StaticFiles):
159
  raise ex
160
 
161
 
162
- static_dir = SPAStaticFiles(packages=[("lynxkite.app", "web_assets")], html=True)
163
  app.mount("/", static_dir, name="web_assets")
 
1
+ """The FastAPI server for serving the LynxKite application."""
2
+
3
  import os
4
  import shutil
5
+
6
  if os.environ.get("NX_CUGRAPH_AUTOCONFIG", "").strip().lower() == "true":
7
  import cudf.pandas
8
 
 
20
 
21
 
22
  def detect_plugins():
 
 
 
 
 
 
23
  plugins = {}
24
+ for _, name, _ in pkgutil.iter_modules():
25
+ if name.startswith("lynxkite_"):
26
+ print(f"Importing {name}")
27
+ plugins[name] = importlib.import_module(name)
28
  if not plugins:
29
+ print("No LynxKite plugins found. Be sure to install some!")
30
  return plugins
31
 
32
 
 
66
  @app.post("/api/delete")
67
  async def delete_workspace(req: dict):
68
  json_path: pathlib.Path = DATA_PATH / req["path"]
69
+ crdt_path: pathlib.Path = CRDT_PATH / f"{req['path']}.crdt"
70
  assert json_path.is_relative_to(DATA_PATH)
71
  assert crdt_path.is_relative_to(CRDT_PATH)
72
  json_path.unlink()
 
82
  return workspace.load(path)
83
 
84
 
85
+ DATA_PATH = pathlib.Path(os.environ.get("LYNXKITE_DATA", "lynxkite_data"))
86
+ CRDT_PATH = pathlib.Path(os.environ.get("LYNXKITE_CRDT_DATA", "lynxkite_crdt_data"))
87
+
88
 
89
  @dataclasses.dataclass(order=True)
90
  class DirectoryEntry:
 
118
  @app.post("/api/dir/delete")
119
  def delete_dir(req: dict):
120
  path: pathlib.Path = DATA_PATH / req["path"]
121
+ assert all([path.is_relative_to(DATA_PATH), path.exists(), path.is_dir()])
 
 
 
 
122
  shutil.rmtree(path)
123
  return list_dir(path.parent)
124
 
 
153
  raise ex
154
 
155
 
156
+ static_dir = SPAStaticFiles(packages=[("lynxkite_app", "web_assets")], html=True)
157
  app.mount("/", static_dir, name="web_assets")
lynxkite-app/tests/test_crdt.py CHANGED
@@ -1,7 +1,7 @@
1
  from enum import Enum
2
  import pycrdt
3
  import pytest
4
- from lynxkite.app.crdt import crdt_update
5
 
6
 
7
  @pytest.fixture
 
1
  from enum import Enum
2
  import pycrdt
3
  import pytest
4
+ from lynxkite_app.crdt import crdt_update
5
 
6
 
7
  @pytest.fixture
lynxkite-app/tests/test_main.py CHANGED
@@ -1,6 +1,6 @@
1
  import uuid
2
  from fastapi.testclient import TestClient
3
- from lynxkite.app.main import app, detect_plugins, DATA_PATH
4
  import os
5
 
6
 
 
1
  import uuid
2
  from fastapi.testclient import TestClient
3
+ from lynxkite_app.main import app, detect_plugins, DATA_PATH
4
  import os
5
 
6
 
lynxkite-app/web/src/Directory.tsx CHANGED
@@ -29,8 +29,8 @@ export default function () {
29
  const navigate = useNavigate();
30
  const [isCreatingDir, setIsCreatingDir] = useState(false);
31
  const [isCreatingWorkspace, setIsCreatingWorkspace] = useState(false);
32
-
33
-
34
  function link(item: any) {
35
  if (item.type === 'directory') {
36
  return `/dir/${item.name}`;
@@ -38,7 +38,7 @@ export default function () {
38
  return `/edit/${item.name}`;
39
  }
40
  }
41
-
42
  function shortName(item: any) {
43
  return item.name.split('/').pop();
44
  }
@@ -53,18 +53,18 @@ export default function () {
53
  i++;
54
  }
55
  }
56
-
57
  function newWorkspaceIn(path: string, list: any[], workspaceName?: string) {
58
  const pathSlash = path ? `${path}/` : "";
59
  const name = workspaceName || newName(list);
60
- navigate(`/edit/${pathSlash}${name}`, {replace: true});
61
  }
62
-
63
 
64
  async function newFolderIn(path: string, list: any[], folderName?: string) {
65
  const name = folderName || newName(list, "New Folder");
66
  const pathSlash = path ? `${path}/` : "";
67
-
68
  const res = await fetch(`/api/dir/mkdir`, {
69
  method: 'POST',
70
  headers: { 'Content-Type': 'application/json' },
@@ -76,12 +76,12 @@ export default function () {
76
  alert("Failed to create folder.");
77
  }
78
  }
79
-
80
  async function deleteItem(item: any) {
81
  if (!window.confirm(`Are you sure you want to delete "${item.name}"?`)) return;
82
  const pathSlash = path ? `${path}/` : "";
83
 
84
- const apiPath = item.type === "directory" ? `/api/dir/delete`: `/api/delete`;
85
  await fetch(apiPath, {
86
  method: "POST",
87
  headers: { "Content-Type": "application/json" },
@@ -109,39 +109,39 @@ export default function () {
109
  {list.data && (
110
  <>
111
  <div className="actions">
112
- <div className="new-workspace">
113
- {isCreatingWorkspace &&
114
- // @ts-ignore
115
- <form onSubmit={(e) => {e.preventDefault(); newWorkspaceIn(path || "", list.data, e.target.workspaceName.value.trim())}}>
116
- <input
117
- type="text"
118
- name="workspaceName"
119
- defaultValue={newName(list.data)}
120
- placeholder={newName(list.data)}
121
- />
122
- </form>
123
- }
124
- <button type="button" onClick={() => setIsCreatingWorkspace(true)}>
125
- <FolderPlus /> New workspace
126
- </button>
127
- </div>
128
-
129
- <div className="new-folder">
130
- {isCreatingDir &&
131
- // @ts-ignore
132
- <form onSubmit={(e) =>{e.preventDefault(); newFolderIn(path || "", list.data, e.target.folderName.value.trim())}}>
133
- <input
134
- type="text"
135
- name="folderName"
136
- defaultValue={newName(list.data)}
137
- placeholder={newName(list.data)}
138
- />
139
- </form>
140
- }
141
- <button type="button" onClick={() => setIsCreatingDir(true)}>
142
- <FolderPlus /> New folder
143
- </button>
144
- </div>
145
  </div>
146
 
147
  {path && (
@@ -155,7 +155,7 @@ export default function () {
155
 
156
  {list.data.map((item: any) => (
157
  <div key={item.name} className="entry">
158
- <a key={link(item)} className="entry" href={link(item)}>
159
  {item.type === 'directory' ? <Folder /> : <File />}
160
  {shortName(item)}
161
  </a>
 
29
  const navigate = useNavigate();
30
  const [isCreatingDir, setIsCreatingDir] = useState(false);
31
  const [isCreatingWorkspace, setIsCreatingWorkspace] = useState(false);
32
+
33
+
34
  function link(item: any) {
35
  if (item.type === 'directory') {
36
  return `/dir/${item.name}`;
 
38
  return `/edit/${item.name}`;
39
  }
40
  }
41
+
42
  function shortName(item: any) {
43
  return item.name.split('/').pop();
44
  }
 
53
  i++;
54
  }
55
  }
56
+
57
  function newWorkspaceIn(path: string, list: any[], workspaceName?: string) {
58
  const pathSlash = path ? `${path}/` : "";
59
  const name = workspaceName || newName(list);
60
+ navigate(`/edit/${pathSlash}${name}`, { replace: true });
61
  }
62
+
63
 
64
  async function newFolderIn(path: string, list: any[], folderName?: string) {
65
  const name = folderName || newName(list, "New Folder");
66
  const pathSlash = path ? `${path}/` : "";
67
+
68
  const res = await fetch(`/api/dir/mkdir`, {
69
  method: 'POST',
70
  headers: { 'Content-Type': 'application/json' },
 
76
  alert("Failed to create folder.");
77
  }
78
  }
79
+
80
  async function deleteItem(item: any) {
81
  if (!window.confirm(`Are you sure you want to delete "${item.name}"?`)) return;
82
  const pathSlash = path ? `${path}/` : "";
83
 
84
+ const apiPath = item.type === "directory" ? `/api/dir/delete` : `/api/delete`;
85
  await fetch(apiPath, {
86
  method: "POST",
87
  headers: { "Content-Type": "application/json" },
 
109
  {list.data && (
110
  <>
111
  <div className="actions">
112
+ <div className="new-workspace">
113
+ {isCreatingWorkspace &&
114
+ // @ts-ignore
115
+ <form onSubmit={(e) => { e.preventDefault(); newWorkspaceIn(path || "", list.data, e.target.workspaceName.value.trim()) }}>
116
+ <input
117
+ type="text"
118
+ name="workspaceName"
119
+ defaultValue={newName(list.data)}
120
+ placeholder={newName(list.data)}
121
+ />
122
+ </form>
123
+ }
124
+ <button type="button" onClick={() => setIsCreatingWorkspace(true)}>
125
+ <FolderPlus /> New workspace
126
+ </button>
127
+ </div>
128
+
129
+ <div className="new-folder">
130
+ {isCreatingDir &&
131
+ // @ts-ignore
132
+ <form onSubmit={(e) => { e.preventDefault(); newFolderIn(path || "", list.data, e.target.folderName.value.trim()) }}>
133
+ <input
134
+ type="text"
135
+ name="folderName"
136
+ defaultValue={newName(list.data)}
137
+ placeholder={newName(list.data)}
138
+ />
139
+ </form>
140
+ }
141
+ <button type="button" onClick={() => setIsCreatingDir(true)}>
142
+ <FolderPlus /> New folder
143
+ </button>
144
+ </div>
145
  </div>
146
 
147
  {path && (
 
155
 
156
  {list.data.map((item: any) => (
157
  <div key={item.name} className="entry">
158
+ <a key={link(item)} href={link(item)}>
159
  {item.type === 'directory' ? <Folder /> : <File />}
160
  {shortName(item)}
161
  </a>
lynxkite-app/web/src/index.css CHANGED
@@ -308,7 +308,6 @@ body {
308
  }
309
 
310
  a {
311
- color: black;
312
  text-decoration: none;
313
  }
314
 
 
308
  }
309
 
310
  a {
 
311
  text-decoration: none;
312
  }
313
 
lynxkite-core/src/lynxkite/core/ops.py CHANGED
@@ -206,8 +206,10 @@ def register_executor(env: str):
206
 
207
 
208
  def op_registration(env: str):
 
209
  return functools.partial(op, env)
210
 
211
 
212
  def passive_op_registration(env: str):
 
213
  return functools.partial(register_passive_op, env)
 
206
 
207
 
208
  def op_registration(env: str):
209
+ """Returns a decorator that can be used for registering functions as operations."""
210
  return functools.partial(op, env)
211
 
212
 
213
  def passive_op_registration(env: str):
214
+ """Returns a function that can be used to register operations without associated code."""
215
  return functools.partial(register_passive_op, env)
lynxkite-graph-analytics/pyproject.toml CHANGED
@@ -17,8 +17,8 @@ dependencies = [
17
 
18
  [project.optional-dependencies]
19
  dev = [
20
- "pytest",
21
- "pytest-asyncio",
22
  ]
23
  gpu = [
24
  "nx-cugraph-cu12>=24.12.0",
@@ -28,4 +28,4 @@ gpu = [
28
  lynxkite-core = { path = "../lynxkite-core" }
29
 
30
  [tool.pytest.ini_options]
31
- asyncio_mode = "auto"
 
17
 
18
  [project.optional-dependencies]
19
  dev = [
20
+ "pytest>=8.3.4",
21
+ "pytest-asyncio>=0.25.3",
22
  ]
23
  gpu = [
24
  "nx-cugraph-cu12>=24.12.0",
 
28
  lynxkite-core = { path = "../lynxkite-core" }
29
 
30
  [tool.pytest.ini_options]
31
+ asyncio_mode = "auto"
lynxkite-graph-analytics/src/lynxkite_graph_analytics/__init__.py ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ from . import lynxkite_ops # noqa (imported to trigger registration)
2
+ from . import networkx_ops # noqa (imported to trigger registration)
3
+ from . import pytorch_model_ops # noqa (imported to trigger registration)
lynxkite-graph-analytics/src/{lynxkite_plugins/graph_analytics β†’ lynxkite_graph_analytics}/lynxkite_ops.py RENAMED
File without changes
lynxkite-graph-analytics/src/{lynxkite_plugins/graph_analytics β†’ lynxkite_graph_analytics}/networkx_ops.py RENAMED
File without changes
lynxkite-graph-analytics/src/{lynxkite_plugins/graph_analytics β†’ lynxkite_graph_analytics}/pytorch_model_ops.py RENAMED
File without changes
lynxkite-graph-analytics/src/lynxkite_plugins/graph_analytics/__init__.py DELETED
@@ -1,3 +0,0 @@
1
- from . import lynxkite_ops
2
- from . import networkx_ops
3
- from . import pytorch_model_ops
 
 
 
 
lynxkite-graph-analytics/tests/test_lynxkite_ops.py CHANGED
@@ -3,7 +3,7 @@ import pytest
3
  import networkx as nx
4
 
5
  from lynxkite.core import workspace
6
- from lynxkite_plugins.graph_analytics.lynxkite_ops import Bundle, execute, op
7
 
8
 
9
  async def test_execute_operation_not_in_catalog():
 
3
  import networkx as nx
4
 
5
  from lynxkite.core import workspace
6
+ from lynxkite_graph_analytics.lynxkite_ops import Bundle, execute, op
7
 
8
 
9
  async def test_execute_operation_not_in_catalog():
lynxkite-lynxscribe/README.md CHANGED
@@ -5,7 +5,7 @@ LynxKite UI for building LynxScribe chat applications. Also runs the chat applic
5
  To run a chat UI for LynxScribe workspaces:
6
 
7
  ```bash
8
- WEBUI_AUTH=false OPENAI_API_BASE_URL=http://localhost:8000/api/service/server.lynxscribe_ops uvx open-webui serve
9
  ```
10
 
11
  Or use [Lynx WebUI](https://github.com/biggraph/lynx-webui/) instead of Open WebUI.
 
5
  To run a chat UI for LynxScribe workspaces:
6
 
7
  ```bash
8
+ WEBUI_AUTH=false OPENAI_API_BASE_URL=http://localhost:8000/api/service/lynxscribe/lynxscribe_ops uvx open-webui serve
9
  ```
10
 
11
  Or use [Lynx WebUI](https://github.com/biggraph/lynx-webui/) instead of Open WebUI.
lynxkite-lynxscribe/src/{lynxkite_plugins/lynxscribe β†’ lynxkite_lynxscribe}/__init__.py RENAMED
@@ -1,5 +1,5 @@
1
- from . import lynxscribe_ops
2
- from . import llm_ops
3
  from .lynxscribe_ops import api_service_post, api_service_get
4
 
5
  __all__ = ["api_service_post", "api_service_get"]
 
1
+ from . import lynxscribe_ops # noqa (imported to trigger registration)
2
+ from . import llm_ops # noqa (imported to trigger registration)
3
  from .lynxscribe_ops import api_service_post, api_service_get
4
 
5
  __all__ = ["api_service_post", "api_service_get"]
lynxkite-lynxscribe/src/{lynxkite_plugins/lynxscribe β†’ lynxkite_lynxscribe}/llm_ops.py RENAMED
File without changes
lynxkite-lynxscribe/src/{lynxkite_plugins/lynxscribe β†’ lynxkite_lynxscribe}/lynxscribe_ops.py RENAMED
File without changes
lynxkite-pillow-example/pyproject.toml CHANGED
@@ -8,8 +8,8 @@ dependencies = [
8
  "fsspec>=2025.2.0",
9
  "lynxkite-core",
10
  "pillow>=11.1.0",
11
- "requests",
12
- "aiohttp",
13
  ]
14
 
15
  [tool.uv.sources]
 
8
  "fsspec>=2025.2.0",
9
  "lynxkite-core",
10
  "pillow>=11.1.0",
11
+ "requests>=2.32.3",
12
+ "aiohttp>=3.11.11",
13
  ]
14
 
15
  [tool.uv.sources]
lynxkite-pillow-example/src/{lynxkite_plugins/pillow_example β†’ lynxkite_pillow_example}/__init__.py RENAMED
File without changes