Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
File size: 13,624 Bytes
ee0b555 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 | """Generate and install the pwc CLI skill for AI coding agents."""
from __future__ import annotations
import argparse
import os
import shutil
import tempfile
from pathlib import Path
from pwc_cli import __version__
SKILL_NAME = "pwc-cli"
CENTRAL_LOCAL = Path(".agents/skills")
CENTRAL_GLOBAL = Path("~/.agents/skills")
CLAUDE_LOCAL = Path(".claude/skills")
CLAUDE_GLOBAL = Path("~/.claude/skills")
_DESCRIPTION = (
"Papers With Code CLI (`pwc`) for searching and reading AI/ML papers, "
"discovering recent and trending research, finding related work and paper "
"lineage, browsing tasks, methods, conferences, organizations, frameworks, "
"and benchmark leaderboards, and submitting authenticated paper edits "
"through the public Papers With Code catalog. Use whenever the user asks to "
"find papers, survey literature, compare research, inspect an arXiv paper, "
"explore AI/ML taxonomy or conferences, discover benchmarks or "
"state-of-the-art models, or mentions Papers With Code, `pwc`, or `pwc-cli`."
)
_INTRODUCTION = """
Research commands query the public [Papers With Code](https://paperswithcode.co) catalog anonymously.
Paper editing requires explicit browser authorization through `pwc auth login --paper PAPER`.
Run `pwc --help` or a nested `--help` command when the live parser and this
skill disagree; the parser is authoritative.
Use compact output for reading and discovery. Add `--json` for programmatic
filtering, joining, or schema-dependent processing.
When the user identifies an author, prefer repeatable structured
`pwc paper list --author AUTHOR` filters. Add `--search TEXT` for stated topic
terms and explicit `--order-by date_published --order-dir desc` for newest or
recent work. Author references accept an exact normalized name, numeric ID, or
`@HF_USERNAME`; repeated authors use AND semantics.
Publication date ranges are inclusive: use `--start-date YYYY-MM-DD` and
`--end-date YYYY-MM-DD` with `pwc search` or `pwc paper list`; the start date
must not be later than `--end-date`. The combined flags are
`--start-date YYYY-MM-DD --end-date YYYY-MM-DD`.
Paper discovery commands accept `--implementation-coverage` to add official
implementation status and total linked repository count columns. JSON and
`pwc paper info` always include both fields. Use
`--has-official-implementation` with `pwc search` or `pwc paper list` to require
a catalog-linked official repository; these filters fail closed if unconfirmed.
Use `pwc benchmark --name NAME --max-parameters SIZE` to keep models at or
below an inclusive parameter limit. SIZE accepts values such as `500M`, `1.5B`,
`3B`, and raw integers. Models without one consistent parameter count are
excluded from constrained results.
`PAPER` accepts a modern or legacy arXiv ID, a numeric external-paper ID, or an
exact paper title. Quote titles containing spaces. Title matching is
case-insensitive but exact; ambiguous titles fail with their matching IDs.
When `pwc paper info` or `pwc paper read` names a paper Papers With Code has
not indexed, stderr shows "Not indexed on Papers With Code — available at:"
with public links and metadata before the usual not-found error; cite those
links, not a Papers With Code page.
"""
_WORKFLOW = """
## Research workflow
1. Use `pwc benchmark list --task TASK` to discover active benchmarks, then
`pwc benchmark --name NAME` to inspect a leaderboard. Add
`--max-parameters SIZE` when model size is part of the request.
2. Use `pwc paper info` to inspect promising results. Add
`--include-resources` when repositories, project pages, or Hugging Face
artifacts matter.
3. Use exact `pwc paper list --author`, `--task`, `--method`, `--conference`,
`--framework`, and `--organization` filters for known identities or catalog
associations. Combine them to require every association; do not substitute
a keyword search. Add `--search` for title or abstract topic terms.
4. Use `pwc search` for broader discovery, then `pwc paper read` for primary
evidence.
5. Expand the literature with `pwc paper related` and use
`pwc paper lineage list` when model or method ancestry matters.
6. Preserve paper titles, identifiers, and URLs so claims remain traceable.
## Output and limits
- Interactive output is optimized for people. Benchmark lists remain aligned
when captured; other captured list output uses lossless TSV. Add `--json` for
structured agent or script consumption.
- Stable exit codes are `0` success, `2` invalid usage, `3` network/server
failure, and `4` invalid API response.
- `PWC_API_URL` may select another compatible v1 endpoint. The default is
`https://paperswithcode.co/api/v1`.
- Catalog-filtered paper lists fail closed unless the server confirms every
requested filter; never treat results from an older server as filtered.
- Parameter-filtered benchmark details fail closed unless the server confirms
parameter-filter support and every returned model satisfies the limit.
The research commands contain no authentication, catalog mutation, ingestion,
publication, image, embedding, CRON, or infrastructure-maintenance operations.
"""
class SkillInstallError(Exception):
"""An invalid or unsafe skill installation request."""
def _subcommand_help(action: argparse._SubParsersAction, name: str) -> str:
for choice in action._choices_actions:
if choice.dest == name:
return str(choice.help or "")
return ""
def _command_signature(parser: argparse.ArgumentParser) -> str:
parts: list[str] = []
for action in parser._actions:
if isinstance(action, argparse._SubParsersAction):
continue
if action.dest == "help":
continue
if not action.option_strings:
parts.append(str(action.metavar or action.dest).upper())
continue
option = next(
(item for item in action.option_strings if item.startswith("--")),
action.option_strings[0],
)
if action.nargs == 0:
parts.append(f"[{option}]")
continue
if action.choices:
value = "|".join(str(choice) for choice in action.choices)
else:
value = str(action.metavar or action.dest).upper()
parts.append(f"[{option} {value}]")
return " ".join(parts)
def _command_entries(
parser: argparse.ArgumentParser, prefix: tuple[str, ...] = ()
) -> list[str]:
entries: list[str] = []
for action in parser._actions:
if not isinstance(action, argparse._SubParsersAction):
continue
for name, child in action.choices.items():
path = (*prefix, name)
if "handler" in child._defaults:
signature = _command_signature(child)
invocation = " ".join(("pwc", *path, signature)).rstrip()
help_text = _subcommand_help(action, name)
suffix = f" — {help_text.rstrip('.')}" if help_text else ""
entries.append(f"- `{invocation}`{suffix}.")
entries.extend(_command_entries(child, path))
return entries
def build_skill_md() -> str:
"""Build a Skill matching the commands in the installed pwc version."""
from pwc_cli.cli import build_parser
commands = "\n".join(_command_entries(build_parser()))
return (
"---\n"
f"name: {SKILL_NAME}\n"
f'description: "{_DESCRIPTION}"\n'
"---\n\n"
f"Generated with `pwc v{__version__}`. Run "
"`pwc skills add --force` to regenerate.\n"
f"{_INTRODUCTION}\n"
"## Commands\n\n"
f"{commands}\n"
f"{_WORKFLOW}\n{_EDIT_WORKFLOW}"
)
def _remove_existing(path: Path, force: bool) -> None:
if not (path.exists() or path.is_symlink()):
return
if not force:
raise SkillInstallError(
f"skill already exists at {path}; rerun with --force to overwrite"
)
if path.is_dir() and not path.is_symlink():
shutil.rmtree(path)
else:
path.unlink()
def _install_to(skills_dir: Path, force: bool) -> Path:
skills_dir = skills_dir.expanduser().resolve()
skills_dir.mkdir(parents=True, exist_ok=True)
target = skills_dir / SKILL_NAME
_remove_existing(target, force)
temporary = Path(tempfile.mkdtemp(prefix=f".{SKILL_NAME}-", dir=skills_dir))
try:
(temporary / "SKILL.md").write_text(build_skill_md(), encoding="utf-8")
os.replace(temporary, target)
finally:
if temporary.exists():
shutil.rmtree(temporary)
return target
def _link_to(skills_dir: Path, installed: Path, force: bool) -> Path:
skills_dir = skills_dir.expanduser().resolve()
skills_dir.mkdir(parents=True, exist_ok=True)
link = skills_dir / SKILL_NAME
_remove_existing(link, force)
link.symlink_to(os.path.relpath(installed, skills_dir), target_is_directory=True)
return link
def skills_add(args: argparse.Namespace, _client: object) -> int:
"""Install the generated pwc skill in central and optional harness paths."""
if args.dest is not None and (args.global_ or args.claude):
raise SkillInstallError("--dest cannot be combined with --global or --claude")
if args.dest is not None:
installed = _install_to(args.dest, args.force)
print(f"Installed '{SKILL_NAME}' to {installed}")
return 0
central_root = CENTRAL_GLOBAL if args.global_ else CENTRAL_LOCAL
installed = _install_to(central_root, args.force)
print(f"Installed '{SKILL_NAME}' to {installed}")
if args.claude:
claude_root = CLAUDE_GLOBAL if args.global_ else CLAUDE_LOCAL
link = _link_to(claude_root, installed, args.force)
print(f"Linked '{SKILL_NAME}' for Claude at {link}")
return 0
_EDIT_WORKFLOW = """
## Editing one paper
Use this workflow only when the user requests edits. Research commands remain anonymous.
1. Run `pwc auth login --paper PAPER`. Give the user the browser link and code;
they sign in with Hugging Face and authorize that paper for one hour. Use
`--no-browser` on a remote machine. Never extract, print, or copy credentials.
2. Run `pwc paper edit export PAPER --output edits.json` (the output must not
already exist). It includes paper_id, version, idempotency_key, empty operations,
and current reference data. Change operations, not current. Preserve the
exported version and retry key. Documents may contain at most 50 operations
and 1 MiB of JSON.
3. Add operations of the form `{"section":"tasks","payload":{"task_ids":[1,2]}}`.
A section operation explicitly replaces that section; preserve unrelated links
and tags. Omitted sections stay unchanged. Allowed sections and payload keys:
tasks/task_ids, methods/method_ids, repositories/repositories,
project_pages/project_pages, hf_artifacts/hf_models+hf_datasets+hf_spaces,
x_threads/x_threads, source_url/source_url (external papers only), and
evaluations. Repository/project-page entries contain url and is_official.
x_threads is a list of x.com or twitter.com post URLs in display order (at
most 10). Link only posts in which the paper's authors or their organization
introduce the paper, never outside accounts; the server captures each post's
preview and rejects deleted or protected posts.
4. For evaluations, an operation without evaluation_id creates a row. Include
task_id, dataset_id, metrics (a dictionary of existing metric names to scores),
model_name, and the evaluation setup where available. One row can contain
multiple metrics. Add evaluation_id to correct an existing row on this paper;
omitted update fields stay unchanged. Use source_url and methodology to cite
precise evidence when available; source references remain optional. Existing
benchmark/task/metric definitions are required. Do not invent missing IDs or
create benchmarks. Report unsupported results to the user. No evaluation
deletion, paper identity changes, organization edits, or rank overrides.
5. Run `pwc paper edit preview PAPER --file edits.json`, inspect the before/after
changes, then `pwc paper edit submit PAPER --file edits.json`. Publication is
immediate: no per-batch browser approval. Respect the user's requested scope.
A batch succeeds completely or makes no changes. The response includes status
published and a link to the paper's history.
6. Retry an uncertain network result using the exact same document and retry key.
A 409 means changed data or a reused key with different edits. Fetch a fresh
export, preserve others' edits, and reconcile. Ask the user if the same score
has conflicting corrections. Once you intentionally revise a previously
submitted batch, use a fresh export/key. A 403 may mean expired authorization,
suspension, or insufficient scope: read the error; do not broaden access.
A 429 indicates the shared account limit: 20 distinct papers per UTC day and
30 publications per minute. Do not work around account limits.
7. `pwc auth status --paper PAPER` shows local expiry metadata (revocation is
checked by the server on use). `pwc auth logout --paper PAPER` revokes access.
If authorization expires, keep the prepared file and request browser login
again. Renewing authorization does not require discarding a valid edit document.
Credentials are stored in owner-only files under ~/.config/pwc/edit-credentials,
separately for each API base URL and paper. They never belong in a prompt, edit
file, repository, or command argument. The CLI does not follow edit redirects.
"""
|