sheafmd 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. sheafmd/__init__.py +48 -0
  2. sheafmd/__main__.py +6 -0
  3. sheafmd/_pandoc.py +20 -0
  4. sheafmd/agent_files/agents-snippet.md +5 -0
  5. sheafmd/agent_files/claude-skill.md +65 -0
  6. sheafmd/agent_setup.py +633 -0
  7. sheafmd/agents/__init__.py +1 -0
  8. sheafmd/agents/base.py +100 -0
  9. sheafmd/agents/claude_code.py +377 -0
  10. sheafmd/agents/detect.py +63 -0
  11. sheafmd/agents/generic.py +57 -0
  12. sheafmd/agents/prompts.py +45 -0
  13. sheafmd/agents/registry.py +42 -0
  14. sheafmd/atomic.py +36 -0
  15. sheafmd/blocks.py +341 -0
  16. sheafmd/charts.py +399 -0
  17. sheafmd/cli.py +1013 -0
  18. sheafmd/comments.py +618 -0
  19. sheafmd/config.py +232 -0
  20. sheafmd/diagnostics.py +135 -0
  21. sheafmd/edit.py +1834 -0
  22. sheafmd/hub/__init__.py +1 -0
  23. sheafmd/hub/asktell.py +547 -0
  24. sheafmd/hub/auth.py +190 -0
  25. sheafmd/hub/client.py +518 -0
  26. sheafmd/hub/core.py +482 -0
  27. sheafmd/hub/events.py +106 -0
  28. sheafmd/hub/handler.py +890 -0
  29. sheafmd/hub/index.py +567 -0
  30. sheafmd/hub/jobs.py +223 -0
  31. sheafmd/hub/live.py +526 -0
  32. sheafmd/hub/peer.py +123 -0
  33. sheafmd/hub/proxy.py +301 -0
  34. sheafmd/hub/recover.py +242 -0
  35. sheafmd/hub/roots.py +569 -0
  36. sheafmd/hub/sender.py +113 -0
  37. sheafmd/hub/server.py +498 -0
  38. sheafmd/hub/service.py +280 -0
  39. sheafmd/hub/sock.py +118 -0
  40. sheafmd/hub/state.py +507 -0
  41. sheafmd/images.py +126 -0
  42. sheafmd/lifecycle.py +284 -0
  43. sheafmd/links.py +124 -0
  44. sheafmd/mcp.py +722 -0
  45. sheafmd/page/index.css +53 -0
  46. sheafmd/page/index.js +78 -0
  47. sheafmd/page/page.css +175 -0
  48. sheafmd/page/page.js +3101 -0
  49. sheafmd/paths.py +233 -0
  50. sheafmd/pdf.py +189 -0
  51. sheafmd/render.py +1189 -0
  52. sheafmd/sanitize.py +182 -0
  53. sheafmd/seat.py +52 -0
  54. sheafmd/source.py +259 -0
  55. sheafmd/theme.py +178 -0
  56. sheafmd/themes/plain/theme.css +32 -0
  57. sheafmd/themes/plain/theme.toml +1 -0
  58. sheafmd-1.0.0.dist-info/METADATA +163 -0
  59. sheafmd-1.0.0.dist-info/RECORD +62 -0
  60. sheafmd-1.0.0.dist-info/WHEEL +4 -0
  61. sheafmd-1.0.0.dist-info/entry_points.txt +2 -0
  62. sheafmd-1.0.0.dist-info/licenses/LICENSE +21 -0
sheafmd/__init__.py ADDED
@@ -0,0 +1,48 @@
1
+ """sheaf: a working page for a markdown document, shared between a person and their agent.
2
+
3
+ The library API (SPEC 16). These names stay stable through 1.x; everything else in
4
+ the package is internal.
5
+
6
+ html = sheafmd.render(path, share=True, theme=None, title=None, toc="auto",
7
+ max_image_width=1400, by=None, for_=None, credit=None, log=None)
8
+ sheafmd.write_pdf(html, out) # raises sheafmd.PdfError
9
+ src = sheafmd.Source(path); text, digest = src.read(); src.update(change)
10
+ sheafmd.strip_comments(text) # the share copy's comment removal
11
+ sheafmd.comments.parse(text) # comments and malformed
12
+ sheafmd.load_root_config(root); sheafmd.load_theme(spec, root)
13
+ """
14
+ from pathlib import Path
15
+
16
+ __version__ = "1.0.0"
17
+
18
+ # `render` below is the public function, and it hides the module sheafmd/render.py as
19
+ # an attribute of the package: inside the package import from it (`from .render import
20
+ # build`), never `from . import render` or `import sheafmd.render as r`.
21
+
22
+ from . import comments
23
+ from .config import ConfigError, RootConfig, load_root_config
24
+ from .pdf import PdfError, write_pdf
25
+ from .render import RenderError, UnclosedComment, render_file, strip_comments
26
+ from .source import Source, StaleError
27
+ from .theme import Theme, load_theme
28
+
29
+ __all__ = ["render", "write_pdf", "Source", "strip_comments", "comments", "load_root_config",
30
+ "load_theme", "RootConfig", "Theme", "PdfError", "StaleError", "ConfigError",
31
+ "RenderError", "UnclosedComment", "__version__"]
32
+
33
+
34
+ def render(path, *, share: bool = True, theme=None, title: str | None = None,
35
+ toc: str = "auto", max_image_width: int = 1400, by: str | None = None,
36
+ for_: str | None = None, credit: bool | None = None,
37
+ log: list[str] | None = None) -> str:
38
+ """The HTML of the markdown file at `path`: a share copy by default, with every
39
+ comment removed and no script; `share=False` gives the page as the hub would serve
40
+ it, without the hub's meta values.
41
+
42
+ Reads the root's `.sheaf.toml` itself (`for`, `links`, `credit`, the theme). `for_`
43
+ replaces its `for` for this render; an empty string leaves the "for" out.
44
+ Every render-log line (`+` added, `!` warning, `-` removed), font failures
45
+ included, is appended to `log`; without one, the warnings go to stderr."""
46
+ return render_file(Path(path), share=share, theme=theme, title=title, toc=toc,
47
+ max_image_width=max_image_width, by=by, for_=for_, credit=credit,
48
+ log=log)
sheafmd/__main__.py ADDED
@@ -0,0 +1,6 @@
1
+ """python -m sheafmd is the same as the sheaf command."""
2
+ import sys
3
+
4
+ from .cli import main
5
+
6
+ sys.exit(main())
sheafmd/_pandoc.py ADDED
@@ -0,0 +1,20 @@
1
+ """The one place the bundled pandoc is started (SPEC 3.2).
2
+
3
+ A document can make pandoc run without end and grow without bound (pandoc 3.9: a footnote
4
+ that cites itself, `[^1]: a [^1]`), so every call has a heap cap and a time limit. A run that
5
+ hits either one comes back as a failed run, like a document pandoc cannot read."""
6
+ import subprocess
7
+
8
+ import pypandoc
9
+
10
+ HEAP = "-M1g" # a 470 KB document needs about 180 MB
11
+ TIMEOUT = 120 # seconds
12
+
13
+
14
+ def run(args: list[str], text: str) -> subprocess.CompletedProcess:
15
+ cmd = [pypandoc.get_pandoc_path(), *args, "+RTS", HEAP, "-RTS"]
16
+ try:
17
+ return subprocess.run(cmd, input=text, capture_output=True, text=True,
18
+ encoding="utf-8", timeout=TIMEOUT)
19
+ except subprocess.TimeoutExpired:
20
+ return subprocess.CompletedProcess(cmd, 124, "", f"pandoc did not finish in {TIMEOUT} seconds")
@@ -0,0 +1,5 @@
1
+ This project keeps documents in markdown and uses sheaf: `sheaf FILE.md` opens a page for the person and prints its URL, which you give them. Do not render text meant for pasting somewhere else (an email, a post, a commit message, a prompt, a config file): put it in the conversation.
2
+ Before you revise a document, read its comments with `sheaf comments FILE.md`.
3
+ After you handle a comment, reply with `sheaf reply FILE.md ID "what you did" --resolve`; never delete a comment. A message that starts "Tell from sheaf" is a comment to act on: do it, then reply with `--role action`.
4
+ Record what goes wrong with `sheaf diag note "what went wrong"`. Never run `sheaf signin-url` yourself: it prints the hub's key; ask the person to run it.
5
+ Every page, article, tool or document you name is a markdown link to its URL, checked with curl that it answers.
@@ -0,0 +1,65 @@
1
+ ---
2
+ name: sheaf
3
+ description: Show a markdown document to the person as a page in their browser and work through the comments they leave on it. Use when the person wants to read, review or edit a .md document on a page, when a document has open comments to answer, or when a message that starts "Tell from sheaf" arrives.
4
+ ---
5
+ <!-- written by sheaf init; sheaf may replace it -->
6
+
7
+ # sheaf
8
+
9
+ sheaf turns a markdown file into a working page for the person: they read it, edit it and leave
10
+ comments on passages. The `.md` stays the source; whatever they do on the page lands back in it.
11
+ You work on the same file, and you see their comments in it.
12
+
13
+ ## Show a document
14
+
15
+ `sheaf <file>` (for example `sheaf plan.md`) starts the hub if none runs, opens the page in the
16
+ person's browser and prints its URL. Give them that URL in your reply. Do it for what they will
17
+ read or review: plans, reports, comparisons, specifications, handoff notes. If they would have to
18
+ read it twice in the terminal, render it once.
19
+
20
+ Do not render text meant for pasting somewhere else (an email, a post, a commit message, a
21
+ prompt, a config file). A page gets in the way of the paste: put it in the conversation.
22
+
23
+ `sheaf <file> --share` writes a copy with no comments and no script, one HTML file to send on.
24
+
25
+ ## Before you revise a document, read its comments
26
+
27
+ sheaf comments plan.md # the open comments: id, author, line, the passage, the thread
28
+ sheaf comments plan.md --all # the resolved ones too
29
+
30
+ If the sheaf tools are connected to you (`documents`, `threads`, `reply`, `resolve`), they do the
31
+ same. A comment sits in the `.md` right after the passage it is about. Edit the text around it
32
+ freely; never write, change or delete a comment by hand, because the commands keep the format the
33
+ page reads.
34
+
35
+ ## After you handle a comment, reply and resolve it
36
+
37
+ sheaf reply plan.md c3 "Moved the date to March and said why." --resolve
38
+
39
+ Reply in the thread, and resolve it when it is done. Never delete a comment: the person reads the
40
+ answers comment by comment. Add a comment of your own on a passage with
41
+ `sheaf comment plan.md "the exact passage" "your note"`.
42
+
43
+ ## A message that starts "Tell from sheaf"
44
+
45
+ The person pressed Tell on a comment: act on it in this conversation, then answer in the thread
46
+ with the role `action`, so the page shows that you did it:
47
+
48
+ sheaf reply plan.md c3 "What you did." --role action
49
+
50
+ With the tools: `reply(doc=..., id=..., text=..., role="action")`. A reply with no role is an
51
+ answer (use it when you only answer a question and change nothing). If you cannot do what the
52
+ comment asks, say so in the thread.
53
+
54
+ ## Links
55
+
56
+ Every page, article, tool or document you name, in text you write into the document or in a reply, is a markdown link [words](https://full-url) to its URL, checked with curl that it answers. Link only what the text names, and never a generic page (a home page, a search page) where a specific one is meant.
57
+
58
+ ## When something goes wrong
59
+
60
+ Record what only you can see, for the person who looks after sheaf: `sheaf diag note "what went
61
+ wrong, and what you were doing"`. It goes to the diagnostics log on their machine, nowhere else.
62
+
63
+ `sheaf signin-url` prints a URL that signs a browser in and holds the hub's key. Never run it
64
+ yourself: the key would be in your transcript. If the person needs one, ask the person to run it
65
+ in their own terminal. Never paste such a URL into a conversation or a file.