scitex 2.14.0__py3-none-any.whl → 2.15.1__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.
Files changed (218) hide show
  1. scitex/__init__.py +47 -0
  2. scitex/_env_loader.py +156 -0
  3. scitex/_mcp_resources/__init__.py +37 -0
  4. scitex/_mcp_resources/_cheatsheet.py +135 -0
  5. scitex/_mcp_resources/_figrecipe.py +138 -0
  6. scitex/_mcp_resources/_formats.py +102 -0
  7. scitex/_mcp_resources/_modules.py +337 -0
  8. scitex/_mcp_resources/_session.py +149 -0
  9. scitex/_mcp_tools/__init__.py +4 -0
  10. scitex/_mcp_tools/audio.py +66 -0
  11. scitex/_mcp_tools/diagram.py +11 -95
  12. scitex/_mcp_tools/introspect.py +191 -0
  13. scitex/_mcp_tools/plt.py +260 -305
  14. scitex/_mcp_tools/scholar.py +74 -0
  15. scitex/_mcp_tools/social.py +244 -0
  16. scitex/_mcp_tools/writer.py +21 -204
  17. scitex/ai/_gen_ai/_PARAMS.py +10 -7
  18. scitex/ai/classification/reporters/_SingleClassificationReporter.py +45 -1603
  19. scitex/ai/classification/reporters/_mixins/__init__.py +36 -0
  20. scitex/ai/classification/reporters/_mixins/_constants.py +67 -0
  21. scitex/ai/classification/reporters/_mixins/_cv_summary.py +387 -0
  22. scitex/ai/classification/reporters/_mixins/_feature_importance.py +119 -0
  23. scitex/ai/classification/reporters/_mixins/_metrics.py +275 -0
  24. scitex/ai/classification/reporters/_mixins/_plotting.py +179 -0
  25. scitex/ai/classification/reporters/_mixins/_reports.py +153 -0
  26. scitex/ai/classification/reporters/_mixins/_storage.py +160 -0
  27. scitex/audio/README.md +40 -36
  28. scitex/audio/__init__.py +127 -59
  29. scitex/audio/_branding.py +185 -0
  30. scitex/audio/_mcp/__init__.py +32 -0
  31. scitex/audio/_mcp/handlers.py +59 -6
  32. scitex/audio/_mcp/speak_handlers.py +238 -0
  33. scitex/audio/_relay.py +225 -0
  34. scitex/audio/engines/elevenlabs_engine.py +6 -1
  35. scitex/audio/mcp_server.py +228 -75
  36. scitex/canvas/README.md +1 -1
  37. scitex/canvas/editor/_dearpygui/__init__.py +25 -0
  38. scitex/canvas/editor/_dearpygui/_editor.py +147 -0
  39. scitex/canvas/editor/_dearpygui/_handlers.py +476 -0
  40. scitex/canvas/editor/_dearpygui/_panels/__init__.py +17 -0
  41. scitex/canvas/editor/_dearpygui/_panels/_control.py +119 -0
  42. scitex/canvas/editor/_dearpygui/_panels/_element_controls.py +190 -0
  43. scitex/canvas/editor/_dearpygui/_panels/_preview.py +43 -0
  44. scitex/canvas/editor/_dearpygui/_panels/_sections.py +390 -0
  45. scitex/canvas/editor/_dearpygui/_plotting.py +187 -0
  46. scitex/canvas/editor/_dearpygui/_rendering.py +504 -0
  47. scitex/canvas/editor/_dearpygui/_selection.py +295 -0
  48. scitex/canvas/editor/_dearpygui/_state.py +93 -0
  49. scitex/canvas/editor/_dearpygui/_utils.py +61 -0
  50. scitex/canvas/editor/flask_editor/templates/__init__.py +32 -70
  51. scitex/cli/__init__.py +38 -43
  52. scitex/cli/audio.py +76 -27
  53. scitex/cli/capture.py +13 -20
  54. scitex/cli/introspect.py +443 -0
  55. scitex/cli/main.py +198 -109
  56. scitex/cli/mcp.py +60 -34
  57. scitex/cli/scholar/__init__.py +8 -0
  58. scitex/cli/scholar/_crossref_scitex.py +296 -0
  59. scitex/cli/scholar/_fetch.py +25 -3
  60. scitex/cli/social.py +314 -0
  61. scitex/cli/writer.py +117 -0
  62. scitex/config/README.md +1 -1
  63. scitex/config/__init__.py +16 -2
  64. scitex/config/_env_registry.py +191 -0
  65. scitex/diagram/__init__.py +42 -19
  66. scitex/diagram/mcp_server.py +13 -125
  67. scitex/introspect/__init__.py +75 -0
  68. scitex/introspect/_call_graph.py +303 -0
  69. scitex/introspect/_class_hierarchy.py +163 -0
  70. scitex/introspect/_core.py +42 -0
  71. scitex/introspect/_docstring.py +131 -0
  72. scitex/introspect/_examples.py +113 -0
  73. scitex/introspect/_imports.py +271 -0
  74. scitex/introspect/_mcp/__init__.py +37 -0
  75. scitex/introspect/_mcp/handlers.py +208 -0
  76. scitex/introspect/_members.py +151 -0
  77. scitex/introspect/_resolve.py +89 -0
  78. scitex/introspect/_signature.py +131 -0
  79. scitex/introspect/_source.py +80 -0
  80. scitex/introspect/_type_hints.py +172 -0
  81. scitex/io/bundle/README.md +1 -1
  82. scitex/mcp_server.py +98 -5
  83. scitex/plt/__init__.py +248 -550
  84. scitex/plt/_subplots/_AxisWrapperMixins/_SeabornMixin/_wrappers.py +5 -10
  85. scitex/plt/docs/EXTERNAL_PACKAGE_BRANDING.md +149 -0
  86. scitex/plt/gallery/README.md +1 -1
  87. scitex/plt/utils/_hitmap/__init__.py +82 -0
  88. scitex/plt/utils/_hitmap/_artist_extraction.py +343 -0
  89. scitex/plt/utils/_hitmap/_color_application.py +346 -0
  90. scitex/plt/utils/_hitmap/_color_conversion.py +121 -0
  91. scitex/plt/utils/_hitmap/_constants.py +40 -0
  92. scitex/plt/utils/_hitmap/_hitmap_core.py +334 -0
  93. scitex/plt/utils/_hitmap/_path_extraction.py +357 -0
  94. scitex/plt/utils/_hitmap/_query.py +113 -0
  95. scitex/plt/utils/_hitmap.py +46 -1616
  96. scitex/plt/utils/_metadata/__init__.py +80 -0
  97. scitex/plt/utils/_metadata/_artists/__init__.py +25 -0
  98. scitex/plt/utils/_metadata/_artists/_base.py +195 -0
  99. scitex/plt/utils/_metadata/_artists/_collections.py +356 -0
  100. scitex/plt/utils/_metadata/_artists/_extract.py +57 -0
  101. scitex/plt/utils/_metadata/_artists/_images.py +80 -0
  102. scitex/plt/utils/_metadata/_artists/_lines.py +261 -0
  103. scitex/plt/utils/_metadata/_artists/_patches.py +247 -0
  104. scitex/plt/utils/_metadata/_artists/_text.py +106 -0
  105. scitex/plt/utils/_metadata/_csv.py +416 -0
  106. scitex/plt/utils/_metadata/_detect.py +225 -0
  107. scitex/plt/utils/_metadata/_legend.py +127 -0
  108. scitex/plt/utils/_metadata/_rounding.py +117 -0
  109. scitex/plt/utils/_metadata/_verification.py +202 -0
  110. scitex/schema/README.md +1 -1
  111. scitex/scholar/__init__.py +8 -0
  112. scitex/scholar/_mcp/crossref_handlers.py +265 -0
  113. scitex/scholar/core/Scholar.py +63 -1700
  114. scitex/scholar/core/_mixins/__init__.py +36 -0
  115. scitex/scholar/core/_mixins/_enrichers.py +270 -0
  116. scitex/scholar/core/_mixins/_library_handlers.py +100 -0
  117. scitex/scholar/core/_mixins/_loaders.py +103 -0
  118. scitex/scholar/core/_mixins/_pdf_download.py +375 -0
  119. scitex/scholar/core/_mixins/_pipeline.py +312 -0
  120. scitex/scholar/core/_mixins/_project_handlers.py +125 -0
  121. scitex/scholar/core/_mixins/_savers.py +69 -0
  122. scitex/scholar/core/_mixins/_search.py +103 -0
  123. scitex/scholar/core/_mixins/_services.py +88 -0
  124. scitex/scholar/core/_mixins/_url_finding.py +105 -0
  125. scitex/scholar/crossref_scitex.py +367 -0
  126. scitex/scholar/docs/EXTERNAL_PACKAGE_BRANDING.md +149 -0
  127. scitex/scholar/examples/00_run_all.sh +120 -0
  128. scitex/scholar/jobs/_executors.py +27 -3
  129. scitex/scholar/pdf_download/ScholarPDFDownloader.py +38 -416
  130. scitex/scholar/pdf_download/_cli.py +154 -0
  131. scitex/scholar/pdf_download/strategies/__init__.py +11 -8
  132. scitex/scholar/pdf_download/strategies/manual_download_fallback.py +80 -3
  133. scitex/scholar/pipelines/ScholarPipelineBibTeX.py +73 -121
  134. scitex/scholar/pipelines/ScholarPipelineParallel.py +80 -138
  135. scitex/scholar/pipelines/ScholarPipelineSingle.py +43 -63
  136. scitex/scholar/pipelines/_single_steps.py +71 -36
  137. scitex/scholar/storage/_LibraryManager.py +97 -1695
  138. scitex/scholar/storage/_mixins/__init__.py +30 -0
  139. scitex/scholar/storage/_mixins/_bibtex_handlers.py +128 -0
  140. scitex/scholar/storage/_mixins/_library_operations.py +218 -0
  141. scitex/scholar/storage/_mixins/_metadata_conversion.py +226 -0
  142. scitex/scholar/storage/_mixins/_paper_saving.py +456 -0
  143. scitex/scholar/storage/_mixins/_resolution.py +376 -0
  144. scitex/scholar/storage/_mixins/_storage_helpers.py +121 -0
  145. scitex/scholar/storage/_mixins/_symlink_handlers.py +226 -0
  146. scitex/scholar/url_finder/.tmp/open_url/KNOWN_RESOLVERS.py +462 -0
  147. scitex/scholar/url_finder/.tmp/open_url/README.md +223 -0
  148. scitex/scholar/url_finder/.tmp/open_url/_DOIToURLResolver.py +694 -0
  149. scitex/scholar/url_finder/.tmp/open_url/_OpenURLResolver.py +1160 -0
  150. scitex/scholar/url_finder/.tmp/open_url/_ResolverLinkFinder.py +344 -0
  151. scitex/scholar/url_finder/.tmp/open_url/__init__.py +24 -0
  152. scitex/security/README.md +3 -3
  153. scitex/session/README.md +1 -1
  154. scitex/sh/README.md +1 -1
  155. scitex/social/__init__.py +153 -0
  156. scitex/social/docs/EXTERNAL_PACKAGE_BRANDING.md +149 -0
  157. scitex/template/README.md +1 -1
  158. scitex/template/clone_writer_directory.py +5 -5
  159. scitex/writer/README.md +1 -1
  160. scitex/writer/_mcp/handlers.py +11 -744
  161. scitex/writer/_mcp/tool_schemas.py +5 -335
  162. scitex-2.15.1.dist-info/METADATA +648 -0
  163. {scitex-2.14.0.dist-info → scitex-2.15.1.dist-info}/RECORD +166 -111
  164. scitex/canvas/editor/flask_editor/templates/_scripts.py +0 -4933
  165. scitex/canvas/editor/flask_editor/templates/_styles.py +0 -1658
  166. scitex/dev/plt/data/mpl/PLOTTING_FUNCTIONS.yaml +0 -90
  167. scitex/dev/plt/data/mpl/PLOTTING_SIGNATURES.yaml +0 -1571
  168. scitex/dev/plt/data/mpl/PLOTTING_SIGNATURES_DETAILED.yaml +0 -6262
  169. scitex/dev/plt/data/mpl/SIGNATURES_FLATTENED.yaml +0 -1274
  170. scitex/dev/plt/data/mpl/dir_ax.txt +0 -459
  171. scitex/diagram/_compile.py +0 -312
  172. scitex/diagram/_diagram.py +0 -355
  173. scitex/diagram/_mcp/__init__.py +0 -4
  174. scitex/diagram/_mcp/handlers.py +0 -400
  175. scitex/diagram/_mcp/tool_schemas.py +0 -157
  176. scitex/diagram/_presets.py +0 -173
  177. scitex/diagram/_schema.py +0 -182
  178. scitex/diagram/_split.py +0 -278
  179. scitex/plt/_mcp/__init__.py +0 -4
  180. scitex/plt/_mcp/_handlers_annotation.py +0 -102
  181. scitex/plt/_mcp/_handlers_figure.py +0 -195
  182. scitex/plt/_mcp/_handlers_plot.py +0 -252
  183. scitex/plt/_mcp/_handlers_style.py +0 -219
  184. scitex/plt/_mcp/handlers.py +0 -74
  185. scitex/plt/_mcp/tool_schemas.py +0 -497
  186. scitex/plt/mcp_server.py +0 -231
  187. scitex/scholar/data/.gitkeep +0 -0
  188. scitex/scholar/data/README.md +0 -44
  189. scitex/scholar/data/bib_files/bibliography.bib +0 -1952
  190. scitex/scholar/data/bib_files/neurovista.bib +0 -277
  191. scitex/scholar/data/bib_files/neurovista_enriched.bib +0 -441
  192. scitex/scholar/data/bib_files/neurovista_enriched_enriched.bib +0 -441
  193. scitex/scholar/data/bib_files/neurovista_processed.bib +0 -338
  194. scitex/scholar/data/bib_files/openaccess.bib +0 -89
  195. scitex/scholar/data/bib_files/pac-seizure_prediction_enriched.bib +0 -2178
  196. scitex/scholar/data/bib_files/pac.bib +0 -698
  197. scitex/scholar/data/bib_files/pac_enriched.bib +0 -1061
  198. scitex/scholar/data/bib_files/pac_processed.bib +0 -0
  199. scitex/scholar/data/bib_files/pac_titles.txt +0 -75
  200. scitex/scholar/data/bib_files/paywalled.bib +0 -98
  201. scitex/scholar/data/bib_files/related-papers-by-coauthors.bib +0 -58
  202. scitex/scholar/data/bib_files/related-papers-by-coauthors_enriched.bib +0 -87
  203. scitex/scholar/data/bib_files/seizure_prediction.bib +0 -694
  204. scitex/scholar/data/bib_files/seizure_prediction_processed.bib +0 -0
  205. scitex/scholar/data/bib_files/test_complete_enriched.bib +0 -437
  206. scitex/scholar/data/bib_files/test_final_enriched.bib +0 -437
  207. scitex/scholar/data/bib_files/test_seizure.bib +0 -46
  208. scitex/scholar/data/impact_factor/JCR_IF_2022.xlsx +0 -0
  209. scitex/scholar/data/impact_factor/JCR_IF_2024.db +0 -0
  210. scitex/scholar/data/impact_factor/JCR_IF_2024.xlsx +0 -0
  211. scitex/scholar/data/impact_factor/JCR_IF_2024_v01.db +0 -0
  212. scitex/scholar/data/impact_factor.db +0 -0
  213. scitex/scholar/examples/SUGGESTIONS.md +0 -865
  214. scitex/scholar/examples/dev.py +0 -38
  215. scitex-2.14.0.dist-info/METADATA +0 -1238
  216. {scitex-2.14.0.dist-info → scitex-2.15.1.dist-info}/WHEEL +0 -0
  217. {scitex-2.14.0.dist-info → scitex-2.15.1.dist-info}/entry_points.txt +0 -0
  218. {scitex-2.14.0.dist-info → scitex-2.15.1.dist-info}/licenses/LICENSE +0 -0
scitex/cli/writer.py CHANGED
@@ -280,6 +280,123 @@ def info(dir):
280
280
  sys.exit(1)
281
281
 
282
282
 
283
+ @writer.group()
284
+ def mcp():
285
+ """
286
+ MCP (Model Context Protocol) tools for writer module.
287
+
288
+ \b
289
+ Examples:
290
+ scitex writer mcp list-tools # List available MCP tools
291
+ scitex writer mcp usage # Show tool usage and parameters
292
+ """
293
+ pass
294
+
295
+
296
+ @mcp.command("list-tools")
297
+ @click.option("--json", "as_json", is_flag=True, help="Output as JSON")
298
+ def list_tools(as_json: bool):
299
+ """
300
+ List available MCP tools for writer module.
301
+
302
+ \b
303
+ Examples:
304
+ scitex writer mcp list-tools
305
+ scitex writer mcp list-tools --json
306
+ """
307
+ from scitex.writer._mcp.tool_schemas import get_tool_schemas
308
+
309
+ tools = get_tool_schemas()
310
+
311
+ if as_json:
312
+ import json
313
+
314
+ output = {
315
+ "module": "writer",
316
+ "count": len(tools),
317
+ "tools": [
318
+ {
319
+ "name": t.name,
320
+ "description": t.description,
321
+ "parameters": list(t.inputSchema.get("properties", {}).keys()),
322
+ "required": t.inputSchema.get("required", []),
323
+ }
324
+ for t in tools
325
+ ],
326
+ }
327
+ click.echo(json.dumps(output, indent=2))
328
+ else:
329
+ click.secho(
330
+ f"SciTeX Writer MCP Tools ({len(tools)} total)", fg="cyan", bold=True
331
+ )
332
+ click.echo()
333
+
334
+ for tool in tools:
335
+ click.secho(f" {tool.name}", fg="green", bold=True)
336
+ # First line of description
337
+ desc = tool.description.split("\n")[0] if tool.description else ""
338
+ click.echo(f" {desc}")
339
+
340
+ # Parameters
341
+ props = tool.inputSchema.get("properties", {})
342
+ required = tool.inputSchema.get("required", [])
343
+ if props:
344
+ params = []
345
+ for pname, pinfo in props.items():
346
+ req_marker = "*" if pname in required else ""
347
+ params.append(f"{pname}{req_marker}")
348
+ click.echo(f" Parameters: {', '.join(params)}")
349
+ click.echo()
350
+
351
+
352
+ @mcp.command("usage")
353
+ @click.argument("tool_name", required=False)
354
+ def usage(tool_name: str):
355
+ """
356
+ Show detailed usage for writer MCP tools.
357
+
358
+ \b
359
+ Examples:
360
+ scitex writer mcp usage # Show all tools
361
+ scitex writer mcp usage compile_manuscript # Show specific tool
362
+ """
363
+ from scitex.writer._mcp.tool_schemas import get_tool_schemas
364
+
365
+ tools = get_tool_schemas()
366
+
367
+ if tool_name:
368
+ # Find specific tool
369
+ tool = next((t for t in tools if t.name == tool_name), None)
370
+ if not tool:
371
+ click.secho(f"Tool '{tool_name}' not found", fg="red", err=True)
372
+ click.echo(f"Available tools: {', '.join(t.name for t in tools)}")
373
+ raise SystemExit(1)
374
+ tools = [tool]
375
+
376
+ for tool in tools:
377
+ click.secho(f"━━━ {tool.name} ━━━", fg="cyan", bold=True)
378
+ click.echo()
379
+ click.echo(f"Description: {tool.description}")
380
+ click.echo()
381
+
382
+ props = tool.inputSchema.get("properties", {})
383
+ required = tool.inputSchema.get("required", [])
384
+
385
+ if props:
386
+ click.secho("Parameters:", bold=True)
387
+ for pname, pinfo in props.items():
388
+ req = " (required)" if pname in required else ""
389
+ ptype = pinfo.get("type", "any")
390
+ pdesc = pinfo.get("description", "")
391
+ default = pinfo.get("default")
392
+ default_str = f" [default: {default}]" if default is not None else ""
393
+
394
+ click.echo(f" {pname}: {ptype}{req}{default_str}")
395
+ if pdesc:
396
+ click.echo(f" {pdesc}")
397
+ click.echo()
398
+
399
+
283
400
  @writer.command()
284
401
  @click.option(
285
402
  "--dir",
scitex/config/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  <!-- ---
2
2
  !-- Timestamp: 2025-12-09
3
3
  !-- Author: ywatanabe
4
- !-- File: /home/ywatanabe/proj/scitex-code/src/scitex/config/README.md
4
+ !-- File: /home/ywatanabe/proj/scitex-python/src/scitex/config/README.md
5
5
  !-- --- -->
6
6
 
7
7
  # SciTeX Configuration Module
scitex/config/__init__.py CHANGED
@@ -1,5 +1,4 @@
1
1
  #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
2
  # Timestamp: "2025-12-09 (ywatanabe)"
4
3
  # File: ./src/scitex/config/__init__.py
5
4
 
@@ -34,8 +33,16 @@ Usage:
34
33
  cache_dir = paths.resolve("cache", user_provided_path)
35
34
  """
36
35
 
37
- from ._PriorityConfig import PriorityConfig, get_scitex_dir, load_dotenv
36
+ from ._env_registry import (
37
+ ENV_REGISTRY,
38
+ EnvVar,
39
+ generate_template,
40
+ get_all_modules,
41
+ get_env_by_module,
42
+ get_env_docs,
43
+ )
38
44
  from ._paths import ScitexPaths, get_paths
45
+ from ._PriorityConfig import PriorityConfig, get_scitex_dir, load_dotenv
39
46
  from ._ScitexConfig import ScitexConfig, get_config, load_yaml
40
47
 
41
48
  __all__ = [
@@ -50,6 +57,13 @@ __all__ = [
50
57
  "PriorityConfig",
51
58
  "get_scitex_dir",
52
59
  "load_dotenv",
60
+ # Environment variable registry
61
+ "ENV_REGISTRY",
62
+ "EnvVar",
63
+ "generate_template",
64
+ "get_all_modules",
65
+ "get_env_by_module",
66
+ "get_env_docs",
53
67
  ]
54
68
 
55
69
 
@@ -0,0 +1,191 @@
1
+ #!/usr/bin/env python3
2
+ # Timestamp: 2026-01-24
3
+ # File: src/scitex/config/_env_registry.py
4
+
5
+ """
6
+ Registry of all SCITEX environment variables.
7
+
8
+ Provides documentation and template generation for environment configuration.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ from dataclasses import dataclass
14
+ from typing import Dict, List, Optional
15
+
16
+
17
+ @dataclass
18
+ class EnvVar:
19
+ """Environment variable definition."""
20
+
21
+ name: str
22
+ description: str
23
+ module: str
24
+ default: Optional[str] = None
25
+ required: bool = False
26
+ sensitive: bool = False
27
+
28
+
29
+ # Registry of all SCITEX environment variables
30
+ ENV_REGISTRY: List[EnvVar] = [
31
+ # Core
32
+ EnvVar("SCITEX_DIR", "Base directory for scitex data", "core", "~/.scitex"),
33
+ EnvVar("SCITEX_ENV_SRC", "Path to env source file/directory", "core"),
34
+ EnvVar("SCITEX_LOGGING_LEVEL", "Logging level", "logging", "INFO"),
35
+ EnvVar("SCITEX_LOG_FORMAT", "Log format style", "logging", "default"),
36
+ EnvVar("SCITEX_FORCE_COLOR", "Force colored output", "logging", "false"),
37
+ # Audio
38
+ EnvVar("SCITEX_AUDIO_MODE", "Audio mode: local/remote/auto", "audio", "auto"),
39
+ EnvVar("SCITEX_AUDIO_RELAY_URL", "Relay server URL for remote audio", "audio"),
40
+ EnvVar("SCITEX_AUDIO_RELAY_HOST", "Relay server host", "audio"),
41
+ EnvVar("SCITEX_AUDIO_RELAY_PORT", "Relay server port", "audio", "31293"),
42
+ EnvVar("SCITEX_AUDIO_PORT", "Audio server port", "audio", "31293"),
43
+ EnvVar("ELEVENLABS_API_KEY", "ElevenLabs API key", "audio", sensitive=True),
44
+ # Scholar
45
+ EnvVar("SCITEX_SCHOLAR_DIR", "Scholar library directory", "scholar"),
46
+ EnvVar("SCITEX_CROSSREF_EMAIL", "Email for Crossref API", "scholar"),
47
+ EnvVar("SCITEX_PUBMED_EMAIL", "Email for PubMed API", "scholar"),
48
+ EnvVar("SCITEX_SCHOLAR_CROSSREF_DB", "Local Crossref database path", "scholar"),
49
+ EnvVar("SCITEX_SCHOLAR_CROSSREF_API_URL", "Crossref API URL", "scholar"),
50
+ EnvVar(
51
+ "SCITEX_SCHOLAR_CROSSREF_MODE", "Crossref mode: local/api/hybrid", "scholar"
52
+ ),
53
+ EnvVar("SCITEX_SCHOLAR_OPENATHENS_EMAIL", "OpenAthens login email", "scholar"),
54
+ EnvVar(
55
+ "SCITEX_SCHOLAR_OPENATHENS_ENABLED",
56
+ "Enable OpenAthens auth",
57
+ "scholar",
58
+ "false",
59
+ ),
60
+ EnvVar(
61
+ "SCITEX_SCHOLAR_EZPROXY_URL", "EZProxy URL for institutional access", "scholar"
62
+ ),
63
+ EnvVar("SCITEX_SCHOLAR_OPENURL_RESOLVER_URL", "OpenURL resolver URL", "scholar"),
64
+ EnvVar(
65
+ "SCITEX_SCHOLAR_ZENROWS_API_KEY",
66
+ "ZenRows API key for scraping",
67
+ "scholar",
68
+ sensitive=True,
69
+ ),
70
+ # Social
71
+ EnvVar("SCITEX_X_CONSUMER_KEY", "Twitter/X consumer key", "social", sensitive=True),
72
+ EnvVar(
73
+ "SCITEX_X_CONSUMER_SECRET",
74
+ "Twitter/X consumer secret",
75
+ "social",
76
+ sensitive=True,
77
+ ),
78
+ EnvVar("SCITEX_X_ACCESS_TOKEN", "Twitter/X access token", "social", sensitive=True),
79
+ EnvVar(
80
+ "SCITEX_X_ACCESS_TOKEN_SECRET",
81
+ "Twitter/X access token secret",
82
+ "social",
83
+ sensitive=True,
84
+ ),
85
+ EnvVar(
86
+ "SCITEX_LINKEDIN_ACCESS_TOKEN",
87
+ "LinkedIn access token",
88
+ "social",
89
+ sensitive=True,
90
+ ),
91
+ EnvVar("SCITEX_REDDIT_CLIENT_ID", "Reddit client ID", "social", sensitive=True),
92
+ EnvVar(
93
+ "SCITEX_REDDIT_CLIENT_SECRET",
94
+ "Reddit client secret",
95
+ "social",
96
+ sensitive=True,
97
+ ),
98
+ EnvVar("SCITEX_YOUTUBE_API_KEY", "YouTube API key", "social", sensitive=True),
99
+ EnvVar("SCITEX_GA_PROPERTY_ID", "Google Analytics property ID", "social"),
100
+ # Cloud
101
+ EnvVar("SCITEX_CLOUD_USERNAME", "Cloud username", "cloud", sensitive=True),
102
+ EnvVar("SCITEX_CLOUD_PASSWORD", "Cloud password", "cloud", sensitive=True),
103
+ EnvVar(
104
+ "SCITEX_CLOUD_CODE_WORKSPACE", "Running in cloud workspace", "cloud", "false"
105
+ ),
106
+ EnvVar("SCITEX_CLOUD_CODE_PROJECT_ROOT", "Cloud project root", "cloud"),
107
+ EnvVar("SCITEX_CLOUD_CODE_BACKEND", "Cloud backend type", "cloud"),
108
+ # UI/Notification
109
+ EnvVar("SCITEX_UI_DEFAULT_BACKEND", "Default notification backend", "ui"),
110
+ EnvVar(
111
+ "SCITEX_UI_BACKEND_PRIORITY",
112
+ "Notification backend priority (comma-sep)",
113
+ "ui",
114
+ ),
115
+ EnvVar("SCITEX_UI_INFO_BACKENDS", "Backends for info notifications", "ui"),
116
+ EnvVar("SCITEX_UI_WARNING_BACKENDS", "Backends for warning notifications", "ui"),
117
+ EnvVar("SCITEX_UI_ERROR_BACKENDS", "Backends for error notifications", "ui"),
118
+ EnvVar("SCITEX_UI_CRITICAL_BACKENDS", "Backends for critical notifications", "ui"),
119
+ EnvVar("SCITEX_NOTIFY_EMAIL_FROM", "Email notification sender", "ui"),
120
+ EnvVar("SCITEX_NOTIFY_EMAIL_TO", "Email notification recipient", "ui"),
121
+ EnvVar("SCITEX_NOTIFY_WEBHOOK_URL", "Webhook URL for notifications", "ui"),
122
+ # Capture
123
+ EnvVar("SCITEX_CAPTURE_DIR", "Screenshot capture directory", "capture"),
124
+ # Web
125
+ EnvVar("SCITEX_WEB_DOWNLOADS_DIR", "Web downloads directory", "web"),
126
+ # PLT
127
+ EnvVar("SCITEX_PLT_AXES_WIDTH_MM", "Default axes width in mm", "plt"),
128
+ EnvVar("SCITEX_PLT_LINES_TRACE_MM", "Default line trace width in mm", "plt"),
129
+ EnvVar("SCITEX_STYLE", "Default plot style", "plt"),
130
+ EnvVar("SCITEX_COLORS", "Color palette to use", "plt"),
131
+ ]
132
+
133
+
134
+ def get_env_by_module(module: str) -> List[EnvVar]:
135
+ """Get all environment variables for a module."""
136
+ return [e for e in ENV_REGISTRY if e.module == module]
137
+
138
+
139
+ def get_all_modules() -> List[str]:
140
+ """Get list of all modules with env vars."""
141
+ return sorted(set(e.module for e in ENV_REGISTRY))
142
+
143
+
144
+ def generate_template(
145
+ include_sensitive: bool = True, include_defaults: bool = True
146
+ ) -> str:
147
+ """Generate a template .src file with all environment variables."""
148
+ lines = [
149
+ "#!/bin/bash",
150
+ "# SciTeX Environment Variables Template",
151
+ "# Generated by scitex.config.generate_template()",
152
+ "#",
153
+ "# Usage: source this file or set SCITEX_ENV_SRC to this path",
154
+ "",
155
+ ]
156
+
157
+ for module in get_all_modules():
158
+ lines.append(f"# === {module.upper()} ===")
159
+ for env in get_env_by_module(module):
160
+ if env.sensitive and not include_sensitive:
161
+ continue
162
+
163
+ if env.description:
164
+ lines.append(f"# {env.description}")
165
+
166
+ if env.default and include_defaults:
167
+ lines.append(f'export {env.name}="{env.default}"')
168
+ elif env.sensitive:
169
+ lines.append(f'# export {env.name}="YOUR_{env.name}_HERE"')
170
+ else:
171
+ lines.append(f"# export {env.name}=")
172
+ lines.append("")
173
+
174
+ return "\n".join(lines)
175
+
176
+
177
+ def get_env_docs() -> Dict[str, Dict]:
178
+ """Get documentation for all environment variables."""
179
+ return {
180
+ e.name: {
181
+ "description": e.description,
182
+ "module": e.module,
183
+ "default": e.default,
184
+ "required": e.required,
185
+ "sensitive": e.sensitive,
186
+ }
187
+ for e in ENV_REGISTRY
188
+ }
189
+
190
+
191
+ # EOF
@@ -1,38 +1,59 @@
1
1
  #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
- # Timestamp: 2025-12-15
2
+ # Timestamp: 2026-01-24
4
3
  # Author: ywatanabe / Claude
5
4
  # File: scitex/diagram/__init__.py
6
5
 
7
6
  """
8
7
  SciTeX Diagram - Paper-optimized diagram generation.
9
8
 
10
- This module provides a semantic layer above Mermaid/Graphviz/D2 that
11
- understands paper constraints (column width, reading direction, emphasis)
12
- and compiles to backend formats with appropriate layout hints.
13
-
14
- Key insight: LLMs are good at generating CONSTRAINTS, not pixel layouts.
15
- SciTeX Diagram defines "what this diagram means for a paper" and compiles
16
- that to backend-specific layout directives.
9
+ This module delegates entirely to figrecipe._diagram.
10
+ figrecipe is the single source of truth for diagram functionality.
17
11
 
18
12
  Example
19
13
  -------
20
- >>> from scitex.diagram import Diagram
14
+ >>> import scitex as stx
15
+ >>>
16
+ >>> # Recommended: Use stx.Diagram directly
17
+ >>> d = stx.Diagram(type="pipeline")
18
+ >>> d.add_node("input", "Raw Data")
19
+ >>> d.add_node("process", "Transform", emphasis="primary")
20
+ >>> d.add_edge("input", "process")
21
+ >>> d.to_mermaid("pipeline.mmd")
21
22
  >>>
22
- >>> diagram = Diagram.from_yaml("workflow.diagram.yaml")
23
- >>> diagram.to_mermaid("workflow.mmd")
24
- >>> diagram.to_graphviz("workflow.dot")
23
+ >>> # From YAML spec
24
+ >>> d = stx.Diagram.from_yaml("workflow.diagram.yaml")
25
+ >>> d.to_mermaid("workflow.mmd")
26
+ >>> d.to_graphviz("workflow.dot")
25
27
  """
26
28
 
27
- from scitex.diagram._schema import DiagramSpec, PaperConstraints, LayoutHints, PaperMode
28
- from scitex.diagram._diagram import Diagram
29
- from scitex.diagram._compile import compile_to_mermaid, compile_to_graphviz
30
- from scitex.diagram._presets import WORKFLOW_PRESET, DECISION_PRESET, PIPELINE_PRESET
31
- from scitex.diagram._split import split_diagram, SplitConfig, SplitStrategy, SplitResult
29
+ # Import everything from figrecipe._diagram (single source of truth)
30
+ from figrecipe._diagram import (
31
+ DECISION_PRESET,
32
+ PIPELINE_PRESET,
33
+ SCIENTIFIC_PRESET,
34
+ WORKFLOW_PRESET,
35
+ Diagram,
36
+ DiagramSpec,
37
+ DiagramType,
38
+ EdgeSpec,
39
+ LayoutHints,
40
+ NodeSpec,
41
+ PaperConstraints,
42
+ PaperMode,
43
+ SplitConfig,
44
+ SplitResult,
45
+ SplitStrategy,
46
+ get_preset,
47
+ list_presets,
48
+ )
49
+ from figrecipe._diagram._compile import compile_to_graphviz, compile_to_mermaid
32
50
 
33
51
  __all__ = [
34
52
  "Diagram",
35
53
  "DiagramSpec",
54
+ "DiagramType",
55
+ "NodeSpec",
56
+ "EdgeSpec",
36
57
  "PaperConstraints",
37
58
  "LayoutHints",
38
59
  "PaperMode",
@@ -41,7 +62,9 @@ __all__ = [
41
62
  "WORKFLOW_PRESET",
42
63
  "DECISION_PRESET",
43
64
  "PIPELINE_PRESET",
44
- "split_diagram",
65
+ "SCIENTIFIC_PRESET",
66
+ "get_preset",
67
+ "list_presets",
45
68
  "SplitConfig",
46
69
  "SplitStrategy",
47
70
  "SplitResult",
@@ -1,148 +1,36 @@
1
1
  #!/usr/bin/env python3
2
- # Timestamp: 2026-01-08
2
+ # Timestamp: 2026-01-24
3
3
  # File: src/scitex/diagram/mcp_server.py
4
- # ----------------------------------------
5
4
 
6
5
  """
7
- MCP Server for SciTeX diagram - Paper-optimized diagram generation.
6
+ MCP Server for SciTeX diagram - delegates to figrecipe.
8
7
 
9
- Provides tools for:
10
- - Creating diagrams from YAML specs
11
- - Compiling to Mermaid/Graphviz formats
12
- - Using workflow/decision/pipeline presets
13
- - Splitting large diagrams for publication layouts
8
+ This is a thin wrapper that redirects to figrecipe's MCP server.
9
+ figrecipe is the single source of truth for diagram functionality.
14
10
  """
15
11
 
16
12
  from __future__ import annotations
17
13
 
18
- import asyncio
19
-
20
- # Graceful MCP dependency handling
21
- try:
22
- import mcp.types as types
23
- from mcp.server import NotificationOptions, Server
24
- from mcp.server.models import InitializationOptions
25
- from mcp.server.stdio import stdio_server
26
-
27
- MCP_AVAILABLE = True
28
- except ImportError:
29
- MCP_AVAILABLE = False
30
- types = None # type: ignore
31
- Server = None # type: ignore
32
- NotificationOptions = None # type: ignore
33
- InitializationOptions = None # type: ignore
34
- stdio_server = None # type: ignore
35
-
36
- __all__ = ["DiagramServer", "main", "MCP_AVAILABLE"]
37
-
38
-
39
- class DiagramServer:
40
- """MCP Server for Paper-Optimized Diagram Generation."""
41
-
42
- def __init__(self):
43
- self.server = Server("scitex-diagram")
44
- self.setup_handlers()
45
-
46
- def setup_handlers(self):
47
- """Set up MCP server handlers."""
48
- from ._mcp.handlers import (
49
- compile_graphviz_handler,
50
- compile_mermaid_handler,
51
- create_diagram_handler,
52
- get_paper_modes_handler,
53
- get_preset_handler,
54
- list_presets_handler,
55
- split_diagram_handler,
56
- )
57
- from ._mcp.tool_schemas import get_tool_schemas
58
-
59
- @self.server.list_tools()
60
- async def handle_list_tools():
61
- return get_tool_schemas()
62
-
63
- @self.server.call_tool()
64
- async def handle_call_tool(name: str, arguments: dict):
65
- if name == "create_diagram":
66
- return await self._wrap_result(create_diagram_handler(**arguments))
67
-
68
- elif name == "compile_mermaid":
69
- return await self._wrap_result(compile_mermaid_handler(**arguments))
70
-
71
- elif name == "compile_graphviz":
72
- return await self._wrap_result(compile_graphviz_handler(**arguments))
73
-
74
- elif name == "list_presets":
75
- return await self._wrap_result(list_presets_handler())
76
-
77
- elif name == "get_preset":
78
- return await self._wrap_result(get_preset_handler(**arguments))
79
-
80
- elif name == "split_diagram":
81
- return await self._wrap_result(split_diagram_handler(**arguments))
82
-
83
- elif name == "get_paper_modes":
84
- return await self._wrap_result(get_paper_modes_handler())
85
-
86
- else:
87
- raise ValueError(f"Unknown tool: {name}")
88
-
89
- async def _wrap_result(self, coro):
90
- """Wrap handler result as MCP TextContent."""
91
- import json
92
-
93
- try:
94
- result = await coro
95
- return [
96
- types.TextContent(
97
- type="text",
98
- text=json.dumps(result, indent=2, default=str),
99
- )
100
- ]
101
- except Exception as e:
102
- return [
103
- types.TextContent(
104
- type="text",
105
- text=json.dumps({"success": False, "error": str(e)}, indent=2),
106
- )
107
- ]
108
-
109
-
110
- async def _run_server():
111
- """Run the MCP server (internal)."""
112
- server = DiagramServer()
113
- async with stdio_server() as (read_stream, write_stream):
114
- await server.server.run(
115
- read_stream,
116
- write_stream,
117
- InitializationOptions(
118
- server_name="scitex-diagram",
119
- server_version="0.1.0",
120
- capabilities=server.server.get_capabilities(
121
- notification_options=NotificationOptions(),
122
- experimental_capabilities={},
123
- ),
124
- ),
125
- )
126
-
127
14
 
128
15
  def main():
129
- """Main entry point for the MCP server."""
130
- if not MCP_AVAILABLE:
16
+ """Main entry point - delegates to figrecipe's MCP server."""
17
+ try:
18
+ from figrecipe._mcp.server import mcp
19
+
20
+ mcp.run()
21
+ except ImportError as e:
131
22
  import sys
132
23
 
133
24
  print("=" * 60)
134
- print("MCP Server 'scitex-diagram' requires the 'mcp' package.")
25
+ print("scitex-diagram requires figrecipe with MCP support.")
135
26
  print()
136
27
  print("Install with:")
137
- print(" pip install mcp")
28
+ print(" pip install figrecipe[mcp]")
138
29
  print()
139
- print("Or install scitex with MCP support:")
140
- print(" pip install scitex[mcp]")
30
+ print(f"Error: {e}")
141
31
  print("=" * 60)
142
32
  sys.exit(1)
143
33
 
144
- asyncio.run(_run_server())
145
-
146
34
 
147
35
  if __name__ == "__main__":
148
36
  main()
@@ -0,0 +1,75 @@
1
+ #!/usr/bin/env python3
2
+ # Timestamp: 2025-01-20
3
+ # File: /home/ywatanabe/proj/scitex-code/src/scitex/introspect/__init__.py
4
+
5
+ """
6
+ Introspection utilities for Python packages.
7
+
8
+ Provides IPython-like introspection capabilities for any Python package.
9
+
10
+ Basic Introspection:
11
+ - get_signature: Function/class signature with type hints (like `func?`)
12
+ - get_docstring: Docstring extraction with parsing
13
+ - get_source: Full source code (like `func??`)
14
+ - list_members: List attributes/methods (like `dir()`)
15
+ - get_exports: Module's __all__ contents
16
+ - find_examples: Find usage examples in tests/examples
17
+
18
+ Advanced Introspection:
19
+ - get_class_hierarchy: Inheritance tree (MRO + subclasses)
20
+ - get_mro: Method Resolution Order only
21
+ - get_type_hints_detailed: Detailed type annotation analysis
22
+ - get_class_annotations: Class variable and method annotations
23
+ - get_imports: Static import analysis using AST
24
+ - get_dependencies: Module dependency analysis
25
+ - get_call_graph: Function call graph (with timeout protection)
26
+ - get_function_calls: Simple outgoing calls list
27
+ """
28
+
29
+ from ._core import (
30
+ # Basic
31
+ find_examples,
32
+ # Advanced - Call graph
33
+ get_call_graph,
34
+ # Advanced - Type hints
35
+ get_class_annotations,
36
+ # Advanced - Class hierarchy
37
+ get_class_hierarchy,
38
+ # Advanced - Imports
39
+ get_dependencies,
40
+ get_docstring,
41
+ get_exports,
42
+ get_function_calls,
43
+ get_imports,
44
+ get_mro,
45
+ get_signature,
46
+ get_source,
47
+ get_type_hints_detailed,
48
+ get_type_info,
49
+ list_members,
50
+ resolve_object,
51
+ )
52
+
53
+ __all__ = [
54
+ # Basic
55
+ "get_signature",
56
+ "get_docstring",
57
+ "get_source",
58
+ "list_members",
59
+ "get_exports",
60
+ "find_examples",
61
+ "resolve_object",
62
+ "get_type_info",
63
+ # Advanced - Class hierarchy
64
+ "get_class_hierarchy",
65
+ "get_mro",
66
+ # Advanced - Type hints
67
+ "get_type_hints_detailed",
68
+ "get_class_annotations",
69
+ # Advanced - Imports
70
+ "get_imports",
71
+ "get_dependencies",
72
+ # Advanced - Call graph
73
+ "get_call_graph",
74
+ "get_function_calls",
75
+ ]