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.
- scitex/__init__.py +47 -0
- scitex/_env_loader.py +156 -0
- scitex/_mcp_resources/__init__.py +37 -0
- scitex/_mcp_resources/_cheatsheet.py +135 -0
- scitex/_mcp_resources/_figrecipe.py +138 -0
- scitex/_mcp_resources/_formats.py +102 -0
- scitex/_mcp_resources/_modules.py +337 -0
- scitex/_mcp_resources/_session.py +149 -0
- scitex/_mcp_tools/__init__.py +4 -0
- scitex/_mcp_tools/audio.py +66 -0
- scitex/_mcp_tools/diagram.py +11 -95
- scitex/_mcp_tools/introspect.py +191 -0
- scitex/_mcp_tools/plt.py +260 -305
- scitex/_mcp_tools/scholar.py +74 -0
- scitex/_mcp_tools/social.py +244 -0
- scitex/_mcp_tools/writer.py +21 -204
- scitex/ai/_gen_ai/_PARAMS.py +10 -7
- scitex/ai/classification/reporters/_SingleClassificationReporter.py +45 -1603
- scitex/ai/classification/reporters/_mixins/__init__.py +36 -0
- scitex/ai/classification/reporters/_mixins/_constants.py +67 -0
- scitex/ai/classification/reporters/_mixins/_cv_summary.py +387 -0
- scitex/ai/classification/reporters/_mixins/_feature_importance.py +119 -0
- scitex/ai/classification/reporters/_mixins/_metrics.py +275 -0
- scitex/ai/classification/reporters/_mixins/_plotting.py +179 -0
- scitex/ai/classification/reporters/_mixins/_reports.py +153 -0
- scitex/ai/classification/reporters/_mixins/_storage.py +160 -0
- scitex/audio/README.md +40 -36
- scitex/audio/__init__.py +127 -59
- scitex/audio/_branding.py +185 -0
- scitex/audio/_mcp/__init__.py +32 -0
- scitex/audio/_mcp/handlers.py +59 -6
- scitex/audio/_mcp/speak_handlers.py +238 -0
- scitex/audio/_relay.py +225 -0
- scitex/audio/engines/elevenlabs_engine.py +6 -1
- scitex/audio/mcp_server.py +228 -75
- scitex/canvas/README.md +1 -1
- scitex/canvas/editor/_dearpygui/__init__.py +25 -0
- scitex/canvas/editor/_dearpygui/_editor.py +147 -0
- scitex/canvas/editor/_dearpygui/_handlers.py +476 -0
- scitex/canvas/editor/_dearpygui/_panels/__init__.py +17 -0
- scitex/canvas/editor/_dearpygui/_panels/_control.py +119 -0
- scitex/canvas/editor/_dearpygui/_panels/_element_controls.py +190 -0
- scitex/canvas/editor/_dearpygui/_panels/_preview.py +43 -0
- scitex/canvas/editor/_dearpygui/_panels/_sections.py +390 -0
- scitex/canvas/editor/_dearpygui/_plotting.py +187 -0
- scitex/canvas/editor/_dearpygui/_rendering.py +504 -0
- scitex/canvas/editor/_dearpygui/_selection.py +295 -0
- scitex/canvas/editor/_dearpygui/_state.py +93 -0
- scitex/canvas/editor/_dearpygui/_utils.py +61 -0
- scitex/canvas/editor/flask_editor/templates/__init__.py +32 -70
- scitex/cli/__init__.py +38 -43
- scitex/cli/audio.py +76 -27
- scitex/cli/capture.py +13 -20
- scitex/cli/introspect.py +443 -0
- scitex/cli/main.py +198 -109
- scitex/cli/mcp.py +60 -34
- scitex/cli/scholar/__init__.py +8 -0
- scitex/cli/scholar/_crossref_scitex.py +296 -0
- scitex/cli/scholar/_fetch.py +25 -3
- scitex/cli/social.py +314 -0
- scitex/cli/writer.py +117 -0
- scitex/config/README.md +1 -1
- scitex/config/__init__.py +16 -2
- scitex/config/_env_registry.py +191 -0
- scitex/diagram/__init__.py +42 -19
- scitex/diagram/mcp_server.py +13 -125
- scitex/introspect/__init__.py +75 -0
- scitex/introspect/_call_graph.py +303 -0
- scitex/introspect/_class_hierarchy.py +163 -0
- scitex/introspect/_core.py +42 -0
- scitex/introspect/_docstring.py +131 -0
- scitex/introspect/_examples.py +113 -0
- scitex/introspect/_imports.py +271 -0
- scitex/introspect/_mcp/__init__.py +37 -0
- scitex/introspect/_mcp/handlers.py +208 -0
- scitex/introspect/_members.py +151 -0
- scitex/introspect/_resolve.py +89 -0
- scitex/introspect/_signature.py +131 -0
- scitex/introspect/_source.py +80 -0
- scitex/introspect/_type_hints.py +172 -0
- scitex/io/bundle/README.md +1 -1
- scitex/mcp_server.py +98 -5
- scitex/plt/__init__.py +248 -550
- scitex/plt/_subplots/_AxisWrapperMixins/_SeabornMixin/_wrappers.py +5 -10
- scitex/plt/docs/EXTERNAL_PACKAGE_BRANDING.md +149 -0
- scitex/plt/gallery/README.md +1 -1
- scitex/plt/utils/_hitmap/__init__.py +82 -0
- scitex/plt/utils/_hitmap/_artist_extraction.py +343 -0
- scitex/plt/utils/_hitmap/_color_application.py +346 -0
- scitex/plt/utils/_hitmap/_color_conversion.py +121 -0
- scitex/plt/utils/_hitmap/_constants.py +40 -0
- scitex/plt/utils/_hitmap/_hitmap_core.py +334 -0
- scitex/plt/utils/_hitmap/_path_extraction.py +357 -0
- scitex/plt/utils/_hitmap/_query.py +113 -0
- scitex/plt/utils/_hitmap.py +46 -1616
- scitex/plt/utils/_metadata/__init__.py +80 -0
- scitex/plt/utils/_metadata/_artists/__init__.py +25 -0
- scitex/plt/utils/_metadata/_artists/_base.py +195 -0
- scitex/plt/utils/_metadata/_artists/_collections.py +356 -0
- scitex/plt/utils/_metadata/_artists/_extract.py +57 -0
- scitex/plt/utils/_metadata/_artists/_images.py +80 -0
- scitex/plt/utils/_metadata/_artists/_lines.py +261 -0
- scitex/plt/utils/_metadata/_artists/_patches.py +247 -0
- scitex/plt/utils/_metadata/_artists/_text.py +106 -0
- scitex/plt/utils/_metadata/_csv.py +416 -0
- scitex/plt/utils/_metadata/_detect.py +225 -0
- scitex/plt/utils/_metadata/_legend.py +127 -0
- scitex/plt/utils/_metadata/_rounding.py +117 -0
- scitex/plt/utils/_metadata/_verification.py +202 -0
- scitex/schema/README.md +1 -1
- scitex/scholar/__init__.py +8 -0
- scitex/scholar/_mcp/crossref_handlers.py +265 -0
- scitex/scholar/core/Scholar.py +63 -1700
- scitex/scholar/core/_mixins/__init__.py +36 -0
- scitex/scholar/core/_mixins/_enrichers.py +270 -0
- scitex/scholar/core/_mixins/_library_handlers.py +100 -0
- scitex/scholar/core/_mixins/_loaders.py +103 -0
- scitex/scholar/core/_mixins/_pdf_download.py +375 -0
- scitex/scholar/core/_mixins/_pipeline.py +312 -0
- scitex/scholar/core/_mixins/_project_handlers.py +125 -0
- scitex/scholar/core/_mixins/_savers.py +69 -0
- scitex/scholar/core/_mixins/_search.py +103 -0
- scitex/scholar/core/_mixins/_services.py +88 -0
- scitex/scholar/core/_mixins/_url_finding.py +105 -0
- scitex/scholar/crossref_scitex.py +367 -0
- scitex/scholar/docs/EXTERNAL_PACKAGE_BRANDING.md +149 -0
- scitex/scholar/examples/00_run_all.sh +120 -0
- scitex/scholar/jobs/_executors.py +27 -3
- scitex/scholar/pdf_download/ScholarPDFDownloader.py +38 -416
- scitex/scholar/pdf_download/_cli.py +154 -0
- scitex/scholar/pdf_download/strategies/__init__.py +11 -8
- scitex/scholar/pdf_download/strategies/manual_download_fallback.py +80 -3
- scitex/scholar/pipelines/ScholarPipelineBibTeX.py +73 -121
- scitex/scholar/pipelines/ScholarPipelineParallel.py +80 -138
- scitex/scholar/pipelines/ScholarPipelineSingle.py +43 -63
- scitex/scholar/pipelines/_single_steps.py +71 -36
- scitex/scholar/storage/_LibraryManager.py +97 -1695
- scitex/scholar/storage/_mixins/__init__.py +30 -0
- scitex/scholar/storage/_mixins/_bibtex_handlers.py +128 -0
- scitex/scholar/storage/_mixins/_library_operations.py +218 -0
- scitex/scholar/storage/_mixins/_metadata_conversion.py +226 -0
- scitex/scholar/storage/_mixins/_paper_saving.py +456 -0
- scitex/scholar/storage/_mixins/_resolution.py +376 -0
- scitex/scholar/storage/_mixins/_storage_helpers.py +121 -0
- scitex/scholar/storage/_mixins/_symlink_handlers.py +226 -0
- scitex/scholar/url_finder/.tmp/open_url/KNOWN_RESOLVERS.py +462 -0
- scitex/scholar/url_finder/.tmp/open_url/README.md +223 -0
- scitex/scholar/url_finder/.tmp/open_url/_DOIToURLResolver.py +694 -0
- scitex/scholar/url_finder/.tmp/open_url/_OpenURLResolver.py +1160 -0
- scitex/scholar/url_finder/.tmp/open_url/_ResolverLinkFinder.py +344 -0
- scitex/scholar/url_finder/.tmp/open_url/__init__.py +24 -0
- scitex/security/README.md +3 -3
- scitex/session/README.md +1 -1
- scitex/sh/README.md +1 -1
- scitex/social/__init__.py +153 -0
- scitex/social/docs/EXTERNAL_PACKAGE_BRANDING.md +149 -0
- scitex/template/README.md +1 -1
- scitex/template/clone_writer_directory.py +5 -5
- scitex/writer/README.md +1 -1
- scitex/writer/_mcp/handlers.py +11 -744
- scitex/writer/_mcp/tool_schemas.py +5 -335
- scitex-2.15.1.dist-info/METADATA +648 -0
- {scitex-2.14.0.dist-info → scitex-2.15.1.dist-info}/RECORD +166 -111
- scitex/canvas/editor/flask_editor/templates/_scripts.py +0 -4933
- scitex/canvas/editor/flask_editor/templates/_styles.py +0 -1658
- scitex/dev/plt/data/mpl/PLOTTING_FUNCTIONS.yaml +0 -90
- scitex/dev/plt/data/mpl/PLOTTING_SIGNATURES.yaml +0 -1571
- scitex/dev/plt/data/mpl/PLOTTING_SIGNATURES_DETAILED.yaml +0 -6262
- scitex/dev/plt/data/mpl/SIGNATURES_FLATTENED.yaml +0 -1274
- scitex/dev/plt/data/mpl/dir_ax.txt +0 -459
- scitex/diagram/_compile.py +0 -312
- scitex/diagram/_diagram.py +0 -355
- scitex/diagram/_mcp/__init__.py +0 -4
- scitex/diagram/_mcp/handlers.py +0 -400
- scitex/diagram/_mcp/tool_schemas.py +0 -157
- scitex/diagram/_presets.py +0 -173
- scitex/diagram/_schema.py +0 -182
- scitex/diagram/_split.py +0 -278
- scitex/plt/_mcp/__init__.py +0 -4
- scitex/plt/_mcp/_handlers_annotation.py +0 -102
- scitex/plt/_mcp/_handlers_figure.py +0 -195
- scitex/plt/_mcp/_handlers_plot.py +0 -252
- scitex/plt/_mcp/_handlers_style.py +0 -219
- scitex/plt/_mcp/handlers.py +0 -74
- scitex/plt/_mcp/tool_schemas.py +0 -497
- scitex/plt/mcp_server.py +0 -231
- scitex/scholar/data/.gitkeep +0 -0
- scitex/scholar/data/README.md +0 -44
- scitex/scholar/data/bib_files/bibliography.bib +0 -1952
- scitex/scholar/data/bib_files/neurovista.bib +0 -277
- scitex/scholar/data/bib_files/neurovista_enriched.bib +0 -441
- scitex/scholar/data/bib_files/neurovista_enriched_enriched.bib +0 -441
- scitex/scholar/data/bib_files/neurovista_processed.bib +0 -338
- scitex/scholar/data/bib_files/openaccess.bib +0 -89
- scitex/scholar/data/bib_files/pac-seizure_prediction_enriched.bib +0 -2178
- scitex/scholar/data/bib_files/pac.bib +0 -698
- scitex/scholar/data/bib_files/pac_enriched.bib +0 -1061
- scitex/scholar/data/bib_files/pac_processed.bib +0 -0
- scitex/scholar/data/bib_files/pac_titles.txt +0 -75
- scitex/scholar/data/bib_files/paywalled.bib +0 -98
- scitex/scholar/data/bib_files/related-papers-by-coauthors.bib +0 -58
- scitex/scholar/data/bib_files/related-papers-by-coauthors_enriched.bib +0 -87
- scitex/scholar/data/bib_files/seizure_prediction.bib +0 -694
- scitex/scholar/data/bib_files/seizure_prediction_processed.bib +0 -0
- scitex/scholar/data/bib_files/test_complete_enriched.bib +0 -437
- scitex/scholar/data/bib_files/test_final_enriched.bib +0 -437
- scitex/scholar/data/bib_files/test_seizure.bib +0 -46
- scitex/scholar/data/impact_factor/JCR_IF_2022.xlsx +0 -0
- scitex/scholar/data/impact_factor/JCR_IF_2024.db +0 -0
- scitex/scholar/data/impact_factor/JCR_IF_2024.xlsx +0 -0
- scitex/scholar/data/impact_factor/JCR_IF_2024_v01.db +0 -0
- scitex/scholar/data/impact_factor.db +0 -0
- scitex/scholar/examples/SUGGESTIONS.md +0 -865
- scitex/scholar/examples/dev.py +0 -38
- scitex-2.14.0.dist-info/METADATA +0 -1238
- {scitex-2.14.0.dist-info → scitex-2.15.1.dist-info}/WHEEL +0 -0
- {scitex-2.14.0.dist-info → scitex-2.15.1.dist-info}/entry_points.txt +0 -0
- {scitex-2.14.0.dist-info → scitex-2.15.1.dist-info}/licenses/LICENSE +0 -0
scitex/_mcp_tools/scholar.py
CHANGED
|
@@ -369,5 +369,79 @@ def register_scholar_tools(mcp) -> None:
|
|
|
369
369
|
result = await get_job_result_handler(job_id=job_id)
|
|
370
370
|
return _json(result)
|
|
371
371
|
|
|
372
|
+
# =========================================================================
|
|
373
|
+
# CrossRef Tools (via crossref-local delegation - 167M+ papers)
|
|
374
|
+
# =========================================================================
|
|
375
|
+
|
|
376
|
+
@mcp.tool()
|
|
377
|
+
async def scholar_crossref_search(
|
|
378
|
+
query: str,
|
|
379
|
+
limit: int = 20,
|
|
380
|
+
offset: int = 0,
|
|
381
|
+
year_min: Optional[int] = None,
|
|
382
|
+
year_max: Optional[int] = None,
|
|
383
|
+
enrich: bool = False,
|
|
384
|
+
) -> str:
|
|
385
|
+
"""[scholar] Search CrossRef database (167M+ papers) via crossref-local. Fast full-text search with optional citation enrichment."""
|
|
386
|
+
from scitex.scholar._mcp.crossref_handlers import crossref_search_handler
|
|
387
|
+
|
|
388
|
+
result = await crossref_search_handler(
|
|
389
|
+
query=query,
|
|
390
|
+
limit=limit,
|
|
391
|
+
offset=offset,
|
|
392
|
+
year_min=year_min,
|
|
393
|
+
year_max=year_max,
|
|
394
|
+
enrich=enrich,
|
|
395
|
+
)
|
|
396
|
+
return _json(result)
|
|
397
|
+
|
|
398
|
+
@mcp.tool()
|
|
399
|
+
async def scholar_crossref_get(
|
|
400
|
+
doi: str,
|
|
401
|
+
include_citations: bool = False,
|
|
402
|
+
include_references: bool = False,
|
|
403
|
+
) -> str:
|
|
404
|
+
"""[scholar] Get paper metadata by DOI from CrossRef database."""
|
|
405
|
+
from scitex.scholar._mcp.crossref_handlers import crossref_get_handler
|
|
406
|
+
|
|
407
|
+
result = await crossref_get_handler(
|
|
408
|
+
doi=doi,
|
|
409
|
+
include_citations=include_citations,
|
|
410
|
+
include_references=include_references,
|
|
411
|
+
)
|
|
412
|
+
return _json(result)
|
|
413
|
+
|
|
414
|
+
@mcp.tool()
|
|
415
|
+
async def scholar_crossref_count(query: str) -> str:
|
|
416
|
+
"""[scholar] Count papers matching a query in CrossRef database."""
|
|
417
|
+
from scitex.scholar._mcp.crossref_handlers import crossref_count_handler
|
|
418
|
+
|
|
419
|
+
result = await crossref_count_handler(query=query)
|
|
420
|
+
return _json(result)
|
|
421
|
+
|
|
422
|
+
@mcp.tool()
|
|
423
|
+
async def scholar_crossref_citations(
|
|
424
|
+
doi: str,
|
|
425
|
+
direction: str = "citing",
|
|
426
|
+
limit: int = 100,
|
|
427
|
+
) -> str:
|
|
428
|
+
"""[scholar] Get citation relationships (citing/cited papers) for a DOI."""
|
|
429
|
+
from scitex.scholar._mcp.crossref_handlers import crossref_citations_handler
|
|
430
|
+
|
|
431
|
+
result = await crossref_citations_handler(
|
|
432
|
+
doi=doi,
|
|
433
|
+
direction=direction,
|
|
434
|
+
limit=limit,
|
|
435
|
+
)
|
|
436
|
+
return _json(result)
|
|
437
|
+
|
|
438
|
+
@mcp.tool()
|
|
439
|
+
async def scholar_crossref_info() -> str:
|
|
440
|
+
"""[scholar] Get CrossRef database configuration and status info."""
|
|
441
|
+
from scitex.scholar._mcp.crossref_handlers import crossref_info_handler
|
|
442
|
+
|
|
443
|
+
result = await crossref_info_handler()
|
|
444
|
+
return _json(result)
|
|
445
|
+
|
|
372
446
|
|
|
373
447
|
# EOF
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# Timestamp: 2026-01-22
|
|
3
|
+
# File: /home/ywatanabe/proj/scitex-code/src/scitex/_mcp_tools/social.py
|
|
4
|
+
|
|
5
|
+
"""Social media module tools for FastMCP unified server.
|
|
6
|
+
|
|
7
|
+
All MCP tools delegate to socialia CLI for reproducibility.
|
|
8
|
+
Each tool returns the CLI command used, enabling human reproduction.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import json
|
|
14
|
+
import subprocess
|
|
15
|
+
import sys
|
|
16
|
+
from typing import Optional
|
|
17
|
+
|
|
18
|
+
# Import platform strategies from socialia for MCP tool descriptions
|
|
19
|
+
try:
|
|
20
|
+
from scitex.social import PLATFORM_STRATEGIES
|
|
21
|
+
except ImportError:
|
|
22
|
+
try:
|
|
23
|
+
from socialia import PLATFORM_STRATEGIES
|
|
24
|
+
except ImportError:
|
|
25
|
+
PLATFORM_STRATEGIES = """
|
|
26
|
+
## Platform Strategies (install socialia for full guide)
|
|
27
|
+
- twitter: 280 chars, hook first, 1-2 hashtags at end
|
|
28
|
+
- linkedin: 3000 chars, first 2 lines critical, 3-5 hashtags at end
|
|
29
|
+
- reddit: title is key, no hashtags, value first
|
|
30
|
+
- youtube: keyword-rich title <60 chars, 3-5 hashtags in description
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _json(data: dict) -> str:
|
|
35
|
+
return json.dumps(data, indent=2, default=str)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _run_socialia_cli(*args: str) -> dict:
|
|
39
|
+
"""Run socialia CLI and return structured result."""
|
|
40
|
+
cmd = [sys.executable, "-m", "socialia", "--json", *args]
|
|
41
|
+
cli_command = f"socialia {' '.join(args)}"
|
|
42
|
+
|
|
43
|
+
try:
|
|
44
|
+
result = subprocess.run(cmd, capture_output=True, text=True, timeout=60)
|
|
45
|
+
|
|
46
|
+
if result.returncode == 0:
|
|
47
|
+
try:
|
|
48
|
+
data = json.loads(result.stdout)
|
|
49
|
+
data["cli_command"] = cli_command
|
|
50
|
+
return data
|
|
51
|
+
except json.JSONDecodeError:
|
|
52
|
+
return {
|
|
53
|
+
"success": True,
|
|
54
|
+
"output": result.stdout,
|
|
55
|
+
"cli_command": cli_command,
|
|
56
|
+
}
|
|
57
|
+
else:
|
|
58
|
+
return {
|
|
59
|
+
"success": False,
|
|
60
|
+
"error": result.stderr or result.stdout,
|
|
61
|
+
"cli_command": cli_command,
|
|
62
|
+
}
|
|
63
|
+
except subprocess.TimeoutExpired:
|
|
64
|
+
return {
|
|
65
|
+
"success": False,
|
|
66
|
+
"error": "Command timed out",
|
|
67
|
+
"cli_command": cli_command,
|
|
68
|
+
}
|
|
69
|
+
except Exception as e:
|
|
70
|
+
return {
|
|
71
|
+
"success": False,
|
|
72
|
+
"error": str(e),
|
|
73
|
+
"cli_command": cli_command,
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def register_social_tools(mcp) -> None:
|
|
78
|
+
"""Register social media tools with FastMCP server."""
|
|
79
|
+
|
|
80
|
+
@mcp.tool()
|
|
81
|
+
async def social_post(
|
|
82
|
+
platform: str,
|
|
83
|
+
text: str,
|
|
84
|
+
reply_to: Optional[str] = None,
|
|
85
|
+
quote: Optional[str] = None,
|
|
86
|
+
subreddit: Optional[str] = None,
|
|
87
|
+
title: Optional[str] = None,
|
|
88
|
+
dry_run: bool = False,
|
|
89
|
+
) -> str:
|
|
90
|
+
"""[social] Post content to a social media platform (twitter, linkedin, reddit, youtube).
|
|
91
|
+
|
|
92
|
+
PLATFORM STRATEGIES:
|
|
93
|
+
- twitter: 280 chars. Hook first. 1+ emoji. GitHub URL. 3-5 hashtags at END for SEO
|
|
94
|
+
- linkedin: 3000 chars. First 2 lines critical. Short paragraphs. Include project links. 3-5 hashtags at END
|
|
95
|
+
- reddit: Title is key. NO hashtags. Value first, self-promo last. Link in body
|
|
96
|
+
- youtube: Keyword-rich title <60 chars. Links in description. 3-5 hashtags in description
|
|
97
|
+
|
|
98
|
+
BAD: "SciTeX v2.15.0 released! New feature. #Python #AI"
|
|
99
|
+
GOOD: "Your AI agent can now speak to you remotely.
|
|
100
|
+
|
|
101
|
+
Audio relay bridges the gap.
|
|
102
|
+
|
|
103
|
+
github.com/user/repo
|
|
104
|
+
|
|
105
|
+
#AIAgents #Python"
|
|
106
|
+
"""
|
|
107
|
+
args = ["post", platform, text]
|
|
108
|
+
|
|
109
|
+
if reply_to:
|
|
110
|
+
args.extend(["--reply-to", reply_to])
|
|
111
|
+
if quote:
|
|
112
|
+
args.extend(["--quote", quote])
|
|
113
|
+
if subreddit and platform == "reddit":
|
|
114
|
+
args.extend(["--subreddit", subreddit])
|
|
115
|
+
if title:
|
|
116
|
+
args.extend(["--title", title])
|
|
117
|
+
if dry_run:
|
|
118
|
+
args.append("--dry-run")
|
|
119
|
+
|
|
120
|
+
result = _run_socialia_cli(*args)
|
|
121
|
+
return _json(result)
|
|
122
|
+
|
|
123
|
+
@mcp.tool()
|
|
124
|
+
async def social_delete(
|
|
125
|
+
platform: str,
|
|
126
|
+
post_id: str,
|
|
127
|
+
) -> str:
|
|
128
|
+
"""[social] Delete a post from a platform (twitter, linkedin, reddit)."""
|
|
129
|
+
result = _run_socialia_cli("delete", platform, post_id)
|
|
130
|
+
return _json(result)
|
|
131
|
+
|
|
132
|
+
@mcp.tool()
|
|
133
|
+
async def social_status() -> str:
|
|
134
|
+
"""[social] Check social media configuration and authentication status."""
|
|
135
|
+
result = _run_socialia_cli("status")
|
|
136
|
+
return _json(result)
|
|
137
|
+
|
|
138
|
+
@mcp.tool()
|
|
139
|
+
async def social_analytics(
|
|
140
|
+
platform: str,
|
|
141
|
+
days: int = 7,
|
|
142
|
+
) -> str:
|
|
143
|
+
"""[social] Get analytics for a platform (twitter, youtube, ga)."""
|
|
144
|
+
result = _run_socialia_cli("analytics", platform, "--days", str(days))
|
|
145
|
+
return _json(result)
|
|
146
|
+
|
|
147
|
+
@mcp.tool()
|
|
148
|
+
async def social_thread(
|
|
149
|
+
platform: str,
|
|
150
|
+
posts: list[str],
|
|
151
|
+
delay: int = 2,
|
|
152
|
+
dry_run: bool = False,
|
|
153
|
+
) -> str:
|
|
154
|
+
"""[social] Post a thread of connected posts. Posts are list of strings."""
|
|
155
|
+
import tempfile
|
|
156
|
+
from pathlib import Path
|
|
157
|
+
|
|
158
|
+
# Write posts to temp file (socialia expects file input)
|
|
159
|
+
thread_content = "\n---\n".join(posts)
|
|
160
|
+
with tempfile.NamedTemporaryFile(mode="w", suffix=".txt", delete=False) as f:
|
|
161
|
+
f.write(thread_content)
|
|
162
|
+
temp_path = f.name
|
|
163
|
+
|
|
164
|
+
try:
|
|
165
|
+
args = ["thread", platform, "--file", temp_path, "--delay", str(delay)]
|
|
166
|
+
if dry_run:
|
|
167
|
+
args.append("--dry-run")
|
|
168
|
+
result = _run_socialia_cli(*args)
|
|
169
|
+
result["thread_posts"] = posts
|
|
170
|
+
return _json(result)
|
|
171
|
+
finally:
|
|
172
|
+
Path(temp_path).unlink(missing_ok=True)
|
|
173
|
+
|
|
174
|
+
@mcp.tool()
|
|
175
|
+
async def social_check_availability() -> str:
|
|
176
|
+
"""[social] Check if socialia is installed and list available platforms."""
|
|
177
|
+
try:
|
|
178
|
+
from scitex.social import (
|
|
179
|
+
SOCIALIA_AVAILABLE,
|
|
180
|
+
__socialia_version__,
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
if SOCIALIA_AVAILABLE:
|
|
184
|
+
return _json(
|
|
185
|
+
{
|
|
186
|
+
"available": True,
|
|
187
|
+
"version": __socialia_version__,
|
|
188
|
+
"platforms": ["twitter", "linkedin", "reddit", "youtube"],
|
|
189
|
+
"analytics": ["twitter", "youtube", "ga"],
|
|
190
|
+
}
|
|
191
|
+
)
|
|
192
|
+
else:
|
|
193
|
+
return _json(
|
|
194
|
+
{
|
|
195
|
+
"available": False,
|
|
196
|
+
"error": "socialia not installed",
|
|
197
|
+
"install_command": "pip install socialia",
|
|
198
|
+
}
|
|
199
|
+
)
|
|
200
|
+
except Exception as e:
|
|
201
|
+
return _json(
|
|
202
|
+
{
|
|
203
|
+
"available": False,
|
|
204
|
+
"error": str(e),
|
|
205
|
+
}
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
@mcp.tool()
|
|
209
|
+
async def social_check(
|
|
210
|
+
platform: Optional[str] = None,
|
|
211
|
+
) -> str:
|
|
212
|
+
"""[social] Check platform connection status (v0.1.4+)."""
|
|
213
|
+
args = ["check"]
|
|
214
|
+
if platform:
|
|
215
|
+
args.append(platform)
|
|
216
|
+
result = _run_socialia_cli(*args)
|
|
217
|
+
return _json(result)
|
|
218
|
+
|
|
219
|
+
@mcp.tool()
|
|
220
|
+
async def social_feed(
|
|
221
|
+
platform: Optional[str] = None,
|
|
222
|
+
limit: int = 10,
|
|
223
|
+
mentions: bool = False,
|
|
224
|
+
) -> str:
|
|
225
|
+
"""[social] Get recent posts from platform feeds (v0.1.4+)."""
|
|
226
|
+
args = ["feed"]
|
|
227
|
+
if platform:
|
|
228
|
+
args.append(platform)
|
|
229
|
+
args.extend(["--limit", str(limit)])
|
|
230
|
+
if mentions:
|
|
231
|
+
args.append("--mentions")
|
|
232
|
+
result = _run_socialia_cli(*args)
|
|
233
|
+
return _json(result)
|
|
234
|
+
|
|
235
|
+
@mcp.tool()
|
|
236
|
+
async def social_me(
|
|
237
|
+
platform: str,
|
|
238
|
+
) -> str:
|
|
239
|
+
"""[social] Get user profile information (v0.1.4+)."""
|
|
240
|
+
result = _run_socialia_cli("me", platform)
|
|
241
|
+
return _json(result)
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
# EOF
|
scitex/_mcp_tools/writer.py
CHANGED
|
@@ -1,220 +1,37 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
# Timestamp: 2026-01-
|
|
2
|
+
# Timestamp: 2026-01-20
|
|
3
3
|
# File: /home/ywatanabe/proj/scitex-code/src/scitex/_mcp_tools/writer.py
|
|
4
|
-
"""Writer module tools
|
|
5
|
-
|
|
6
|
-
from __future__ import annotations
|
|
7
|
-
|
|
8
|
-
import json
|
|
9
|
-
from typing import List, Optional, Union
|
|
4
|
+
"""Writer module tools - delegates to scitex-writer package.
|
|
10
5
|
|
|
6
|
+
Provides usage instructions for shell-based compilation workflow.
|
|
7
|
+
"""
|
|
11
8
|
|
|
12
|
-
|
|
13
|
-
return json.dumps(data, indent=2, default=str)
|
|
9
|
+
from __future__ import annotations
|
|
14
10
|
|
|
15
11
|
|
|
16
12
|
def register_writer_tools(mcp) -> None:
|
|
17
|
-
"""Register writer tools
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
async def writer_clone_project(
|
|
21
|
-
project_dir: str,
|
|
22
|
-
git_strategy: str = "child",
|
|
23
|
-
branch: Optional[str] = None,
|
|
24
|
-
tag: Optional[str] = None,
|
|
25
|
-
) -> str:
|
|
26
|
-
"""[writer] Create a new LaTeX manuscript project from template."""
|
|
27
|
-
from scitex.writer._mcp.handlers import clone_project_handler
|
|
28
|
-
|
|
29
|
-
result = await clone_project_handler(
|
|
30
|
-
project_dir=project_dir,
|
|
31
|
-
git_strategy=git_strategy,
|
|
32
|
-
branch=branch,
|
|
33
|
-
tag=tag,
|
|
34
|
-
)
|
|
35
|
-
return _json(result)
|
|
36
|
-
|
|
37
|
-
@mcp.tool()
|
|
38
|
-
async def writer_compile_manuscript(
|
|
39
|
-
project_dir: str,
|
|
40
|
-
timeout: int = 300,
|
|
41
|
-
no_figs: bool = False,
|
|
42
|
-
ppt2tif: bool = False,
|
|
43
|
-
crop_tif: bool = False,
|
|
44
|
-
quiet: bool = False,
|
|
45
|
-
verbose: bool = False,
|
|
46
|
-
force: bool = False,
|
|
47
|
-
) -> str:
|
|
48
|
-
"""[writer] Compile manuscript LaTeX document to PDF."""
|
|
49
|
-
from scitex.writer._mcp.handlers import compile_manuscript_handler
|
|
50
|
-
|
|
51
|
-
result = await compile_manuscript_handler(
|
|
52
|
-
project_dir=project_dir,
|
|
53
|
-
timeout=timeout,
|
|
54
|
-
no_figs=no_figs,
|
|
55
|
-
ppt2tif=ppt2tif,
|
|
56
|
-
crop_tif=crop_tif,
|
|
57
|
-
quiet=quiet,
|
|
58
|
-
verbose=verbose,
|
|
59
|
-
force=force,
|
|
60
|
-
)
|
|
61
|
-
return _json(result)
|
|
62
|
-
|
|
63
|
-
@mcp.tool()
|
|
64
|
-
async def writer_compile_supplementary(
|
|
65
|
-
project_dir: str,
|
|
66
|
-
timeout: int = 300,
|
|
67
|
-
no_figs: bool = False,
|
|
68
|
-
ppt2tif: bool = False,
|
|
69
|
-
crop_tif: bool = False,
|
|
70
|
-
quiet: bool = False,
|
|
71
|
-
) -> str:
|
|
72
|
-
"""[writer] Compile supplementary materials LaTeX document to PDF."""
|
|
73
|
-
from scitex.writer._mcp.handlers import compile_supplementary_handler
|
|
74
|
-
|
|
75
|
-
result = await compile_supplementary_handler(
|
|
76
|
-
project_dir=project_dir,
|
|
77
|
-
timeout=timeout,
|
|
78
|
-
no_figs=no_figs,
|
|
79
|
-
ppt2tif=ppt2tif,
|
|
80
|
-
crop_tif=crop_tif,
|
|
81
|
-
quiet=quiet,
|
|
82
|
-
)
|
|
83
|
-
return _json(result)
|
|
84
|
-
|
|
85
|
-
@mcp.tool()
|
|
86
|
-
async def writer_compile_revision(
|
|
87
|
-
project_dir: str,
|
|
88
|
-
track_changes: bool = False,
|
|
89
|
-
timeout: int = 300,
|
|
90
|
-
) -> str:
|
|
91
|
-
"""[writer] Compile revision document to PDF with optional change tracking."""
|
|
92
|
-
from scitex.writer._mcp.handlers import compile_revision_handler
|
|
93
|
-
|
|
94
|
-
result = await compile_revision_handler(
|
|
95
|
-
project_dir=project_dir,
|
|
96
|
-
track_changes=track_changes,
|
|
97
|
-
timeout=timeout,
|
|
98
|
-
)
|
|
99
|
-
return _json(result)
|
|
100
|
-
|
|
101
|
-
@mcp.tool()
|
|
102
|
-
async def writer_get_project_info(project_dir: str) -> str:
|
|
103
|
-
"""[writer] Get writer project structure and status information."""
|
|
104
|
-
from scitex.writer._mcp.handlers import get_project_info_handler
|
|
13
|
+
"""Register writer tools by delegating to scitex-writer package."""
|
|
14
|
+
try:
|
|
15
|
+
from scitex_writer._server import INSTRUCTIONS
|
|
105
16
|
|
|
106
|
-
|
|
107
|
-
|
|
17
|
+
_SCITEX_WRITER_AVAILABLE = True
|
|
18
|
+
except ImportError:
|
|
19
|
+
_SCITEX_WRITER_AVAILABLE = False
|
|
20
|
+
INSTRUCTIONS = None
|
|
108
21
|
|
|
109
|
-
|
|
110
|
-
async def writer_get_pdf(
|
|
111
|
-
project_dir: str,
|
|
112
|
-
doc_type: str = "manuscript",
|
|
113
|
-
) -> str:
|
|
114
|
-
"""[writer] Get path to compiled PDF for a document type."""
|
|
115
|
-
from scitex.writer._mcp.handlers import get_pdf_handler
|
|
22
|
+
if not _SCITEX_WRITER_AVAILABLE:
|
|
116
23
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
return _json(result)
|
|
24
|
+
@mcp.tool()
|
|
25
|
+
def writer_usage() -> str:
|
|
26
|
+
"""[writer] Get usage guide for SciTeX Writer (not installed)."""
|
|
27
|
+
return "scitex-writer is required. Install with: pip install scitex-writer"
|
|
122
28
|
|
|
123
|
-
|
|
124
|
-
async def writer_list_document_types() -> str:
|
|
125
|
-
"""[writer] List available document types in a writer project."""
|
|
126
|
-
from scitex.writer._mcp.handlers import list_document_types_handler
|
|
127
|
-
|
|
128
|
-
result = await list_document_types_handler()
|
|
129
|
-
return _json(result)
|
|
29
|
+
return
|
|
130
30
|
|
|
131
31
|
@mcp.tool()
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
caption: Optional[str] = None,
|
|
136
|
-
label: Optional[str] = None,
|
|
137
|
-
longtable: bool = False,
|
|
138
|
-
) -> str:
|
|
139
|
-
"""[writer] Convert CSV file to LaTeX table format."""
|
|
140
|
-
from scitex.writer._mcp.handlers import csv2latex_handler
|
|
141
|
-
|
|
142
|
-
result = await csv2latex_handler(
|
|
143
|
-
csv_path=csv_path,
|
|
144
|
-
output_path=output_path,
|
|
145
|
-
caption=caption,
|
|
146
|
-
label=label,
|
|
147
|
-
longtable=longtable,
|
|
148
|
-
)
|
|
149
|
-
return _json(result)
|
|
150
|
-
|
|
151
|
-
@mcp.tool()
|
|
152
|
-
async def writer_latex_to_csv(
|
|
153
|
-
latex_path: str,
|
|
154
|
-
output_path: Optional[str] = None,
|
|
155
|
-
table_index: int = 0,
|
|
156
|
-
) -> str:
|
|
157
|
-
"""[writer] Convert LaTeX table to CSV format."""
|
|
158
|
-
from scitex.writer._mcp.handlers import latex2csv_handler
|
|
159
|
-
|
|
160
|
-
result = await latex2csv_handler(
|
|
161
|
-
latex_path=latex_path,
|
|
162
|
-
output_path=output_path,
|
|
163
|
-
table_index=table_index,
|
|
164
|
-
)
|
|
165
|
-
return _json(result)
|
|
166
|
-
|
|
167
|
-
@mcp.tool()
|
|
168
|
-
async def writer_pdf_to_images(
|
|
169
|
-
pdf_path: str,
|
|
170
|
-
output_dir: Optional[str] = None,
|
|
171
|
-
pages: Optional[Union[int, List[int]]] = None,
|
|
172
|
-
dpi: int = 150,
|
|
173
|
-
format: str = "png",
|
|
174
|
-
) -> str:
|
|
175
|
-
"""[writer] Render PDF pages as images."""
|
|
176
|
-
from scitex.writer._mcp.handlers import pdf_to_images_handler
|
|
177
|
-
|
|
178
|
-
result = await pdf_to_images_handler(
|
|
179
|
-
pdf_path=pdf_path,
|
|
180
|
-
output_dir=output_dir,
|
|
181
|
-
pages=pages,
|
|
182
|
-
dpi=dpi,
|
|
183
|
-
format=format,
|
|
184
|
-
)
|
|
185
|
-
return _json(result)
|
|
186
|
-
|
|
187
|
-
@mcp.tool()
|
|
188
|
-
async def writer_list_figures(
|
|
189
|
-
project_dir: str,
|
|
190
|
-
extensions: Optional[List[str]] = None,
|
|
191
|
-
) -> str:
|
|
192
|
-
"""[writer] List all figures in a writer project directory."""
|
|
193
|
-
from scitex.writer._mcp.handlers import list_figures_handler
|
|
194
|
-
|
|
195
|
-
result = await list_figures_handler(
|
|
196
|
-
project_dir=project_dir,
|
|
197
|
-
extensions=extensions,
|
|
198
|
-
)
|
|
199
|
-
return _json(result)
|
|
200
|
-
|
|
201
|
-
@mcp.tool()
|
|
202
|
-
async def writer_convert_figure(
|
|
203
|
-
input_path: str,
|
|
204
|
-
output_path: str,
|
|
205
|
-
dpi: int = 300,
|
|
206
|
-
quality: int = 95,
|
|
207
|
-
) -> str:
|
|
208
|
-
"""[writer] Convert figure between formats (e.g., PDF to PNG, PNG to JPG)."""
|
|
209
|
-
from scitex.writer._mcp.handlers import convert_figure_handler
|
|
210
|
-
|
|
211
|
-
result = await convert_figure_handler(
|
|
212
|
-
input_path=input_path,
|
|
213
|
-
output_path=output_path,
|
|
214
|
-
dpi=dpi,
|
|
215
|
-
quality=quality,
|
|
216
|
-
)
|
|
217
|
-
return _json(result)
|
|
32
|
+
def writer_usage() -> str:
|
|
33
|
+
"""[writer] Get usage guide for SciTeX Writer LaTeX manuscript compilation system."""
|
|
34
|
+
return INSTRUCTIONS
|
|
218
35
|
|
|
219
36
|
|
|
220
37
|
# EOF
|
scitex/ai/_gen_ai/_PARAMS.py
CHANGED
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
|
-
# Timestamp: "
|
|
4
|
-
# File: /home/ywatanabe/proj/
|
|
5
|
-
|
|
6
|
-
from __future__ import annotations
|
|
7
|
-
import os
|
|
3
|
+
# Timestamp: "2026-01-16 04:02:17 (ywatanabe)"
|
|
4
|
+
# File: /home/ywatanabe/proj/scitex-code/src/scitex/ai/_gen_ai/_PARAMS.py
|
|
5
|
+
|
|
8
6
|
|
|
9
7
|
__FILE__ = __file__
|
|
10
|
-
__DIR__ = os.path.dirname(__FILE__)
|
|
11
|
-
# ----------------------------------------
|
|
12
8
|
|
|
13
9
|
THIS_FILE = "/home/ywatanabe/proj/scitex_repo/src/scitex/ai/_gen_ai/PARAMS.py"
|
|
14
10
|
|
|
@@ -202,6 +198,13 @@ OPENAI_MODELS = [
|
|
|
202
198
|
# https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching#pricing
|
|
203
199
|
# https://docs.anthropic.com/en/docs/about-claude/models#model-comparison-table
|
|
204
200
|
ANTHROPIC_MODELS = [
|
|
201
|
+
{
|
|
202
|
+
"name": "claude-opus-4-5-20251101",
|
|
203
|
+
"input_cost": 5.00,
|
|
204
|
+
"output_cost": 25.00,
|
|
205
|
+
"api_key_env": "ANTHROPIC_API_KEY",
|
|
206
|
+
"provider": "Anthropic",
|
|
207
|
+
},
|
|
205
208
|
{
|
|
206
209
|
"name": "claude-opus-4-1-20250805",
|
|
207
210
|
"input_cost": 15.00,
|