draftwatch 0.2.2__tar.gz → 0.2.4__tar.gz
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.
- {draftwatch-0.2.2 → draftwatch-0.2.4}/PKG-INFO +3 -1
- {draftwatch-0.2.2 → draftwatch-0.2.4}/README.md +2 -0
- {draftwatch-0.2.2 → draftwatch-0.2.4}/draftwatch/app.py +61 -20
- draftwatch-0.2.4/draftwatch/assets/favicon.png +0 -0
- draftwatch-0.2.4/draftwatch/assets/icon.png +0 -0
- {draftwatch-0.2.2 → draftwatch-0.2.4}/draftwatch.egg-info/PKG-INFO +3 -1
- {draftwatch-0.2.2 → draftwatch-0.2.4}/draftwatch.egg-info/SOURCES.txt +2 -0
- {draftwatch-0.2.2 → draftwatch-0.2.4}/pyproject.toml +1 -1
- {draftwatch-0.2.2 → draftwatch-0.2.4}/LICENSE +0 -0
- {draftwatch-0.2.2 → draftwatch-0.2.4}/draftwatch/__init__.py +0 -0
- {draftwatch-0.2.2 → draftwatch-0.2.4}/draftwatch/__main__.py +0 -0
- {draftwatch-0.2.2 → draftwatch-0.2.4}/draftwatch/assets/codemirror.js +0 -0
- {draftwatch-0.2.2 → draftwatch-0.2.4}/draftwatch/assets/marked.js +0 -0
- {draftwatch-0.2.2 → draftwatch-0.2.4}/draftwatch/assets/purify.js +0 -0
- {draftwatch-0.2.2 → draftwatch-0.2.4}/draftwatch/assets/turndown.js +0 -0
- {draftwatch-0.2.2 → draftwatch-0.2.4}/draftwatch/assets/xterm.css +0 -0
- {draftwatch-0.2.2 → draftwatch-0.2.4}/draftwatch/assets/xterm.js +0 -0
- {draftwatch-0.2.2 → draftwatch-0.2.4}/draftwatch/term.py +0 -0
- {draftwatch-0.2.2 → draftwatch-0.2.4}/draftwatch.egg-info/dependency_links.txt +0 -0
- {draftwatch-0.2.2 → draftwatch-0.2.4}/draftwatch.egg-info/entry_points.txt +0 -0
- {draftwatch-0.2.2 → draftwatch-0.2.4}/draftwatch.egg-info/requires.txt +0 -0
- {draftwatch-0.2.2 → draftwatch-0.2.4}/draftwatch.egg-info/top_level.txt +0 -0
- {draftwatch-0.2.2 → draftwatch-0.2.4}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: draftwatch
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: Review an AI agent's edits to your writing files as a real git word-diff — keep or revert changes hunk by hunk, then commit.
|
|
5
5
|
Author: Mike Konczal
|
|
6
6
|
License: MIT
|
|
@@ -22,6 +22,8 @@ Dynamic: license-file
|
|
|
22
22
|
|
|
23
23
|
# Draftwatch
|
|
24
24
|
|
|
25
|
+
<img src="https://raw.githubusercontent.com/mtkonczal/Draftwatch/main/draftwatch/assets/icon.png" alt="DraftWatch logo: a white D on blue with equal coral and green revision marks" width="220">
|
|
26
|
+
|
|
25
27
|

|
|
26
28
|
|
|
27
29
|
It’s difficult for writers to have AI act as an editor, because it’s never clear exactly what it changed. You can’t trust eyeballing it, but making the changes manually yourself means you don’t save much time. So you either ignore this potentially powerful writing helper, or you trust it at the risk that it does far more than you asked.
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Draftwatch
|
|
2
2
|
|
|
3
|
+
<img src="https://raw.githubusercontent.com/mtkonczal/Draftwatch/main/draftwatch/assets/icon.png" alt="DraftWatch logo: a white D on blue with equal coral and green revision marks" width="220">
|
|
4
|
+
|
|
3
5
|

|
|
4
6
|
|
|
5
7
|
It’s difficult for writers to have AI act as an editor, because it’s never clear exactly what it changed. You can’t trust eyeballing it, but making the changes manually yourself means you don’t save much time. So you either ignore this potentially powerful writing helper, or you trust it at the risk that it does far more than you asked.
|
|
@@ -40,7 +40,7 @@ TERM_SUPPORTED = _term is not None
|
|
|
40
40
|
# Single source of truth for the version and the date of the latest release.
|
|
41
41
|
# __init__.py re-exports __version__; the About panel shows both (injected into
|
|
42
42
|
# the served page from these constants).
|
|
43
|
-
__version__ = "0.2.
|
|
43
|
+
__version__ = "0.2.3"
|
|
44
44
|
RELEASE_DATE = "2026-09-23"
|
|
45
45
|
|
|
46
46
|
# Preferred port. When --port is not given, Draftwatch tries this first and
|
|
@@ -840,6 +840,7 @@ STATIC_ASSETS = {
|
|
|
840
840
|
"marked.js": "application/javascript; charset=utf-8",
|
|
841
841
|
"purify.js": "application/javascript; charset=utf-8",
|
|
842
842
|
"turndown.js": "application/javascript; charset=utf-8",
|
|
843
|
+
"favicon.png": "image/png",
|
|
843
844
|
}
|
|
844
845
|
|
|
845
846
|
|
|
@@ -1462,6 +1463,7 @@ INDEX_HTML = r"""<!DOCTYPE html>
|
|
|
1462
1463
|
<meta name="referrer" content="no-referrer">
|
|
1463
1464
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
1464
1465
|
<title>Draftwatch</title>
|
|
1466
|
+
<link rel="icon" type="image/png" href="/static/favicon.png">
|
|
1465
1467
|
<script src="/static/codemirror.js"></script>
|
|
1466
1468
|
<script src="/static/marked.js"></script>
|
|
1467
1469
|
<script src="/static/purify.js"></script>
|
|
@@ -1617,7 +1619,7 @@ INDEX_HTML = r"""<!DOCTYPE html>
|
|
|
1617
1619
|
|
|
1618
1620
|
/* app chrome (native window via pywebview, ?app=1): the OS title bar
|
|
1619
1621
|
already says "draftwatch · file", so the in-page wordmark is redundant —
|
|
1620
|
-
drop
|
|
1622
|
+
drop the word (the logo, outside .title, stays as the brand), tighten the toolbar, and make the chrome feel native (no text
|
|
1621
1623
|
selection on controls, no web-page tells). */
|
|
1622
1624
|
body.app-mode header .title { display: none; }
|
|
1623
1625
|
body.app-mode header { padding: 5px 10px; }
|
|
@@ -1638,14 +1640,22 @@ INDEX_HTML = r"""<!DOCTYPE html>
|
|
|
1638
1640
|
display: flex;
|
|
1639
1641
|
flex-direction: column;
|
|
1640
1642
|
}
|
|
1643
|
+
/* logo on the left, spanning both toolbar rows; the rows stack beside it */
|
|
1641
1644
|
header {
|
|
1642
1645
|
display: flex;
|
|
1643
|
-
|
|
1644
|
-
gap:
|
|
1646
|
+
align-items: center;
|
|
1647
|
+
gap: 10px;
|
|
1645
1648
|
padding: 8px 12px;
|
|
1646
1649
|
border-bottom: 1px solid var(--border);
|
|
1647
1650
|
background: var(--panel);
|
|
1648
1651
|
}
|
|
1652
|
+
header .rows {
|
|
1653
|
+
flex: 1;
|
|
1654
|
+
min-width: 0;
|
|
1655
|
+
display: flex;
|
|
1656
|
+
flex-direction: column;
|
|
1657
|
+
gap: 6px;
|
|
1658
|
+
}
|
|
1649
1659
|
/* Two fixed rows that never wrap into each other, so the layout stays put
|
|
1650
1660
|
regardless of title length or window width:
|
|
1651
1661
|
row 1 = what you're looking at (title, file picker, baseline selector —
|
|
@@ -1668,19 +1678,11 @@ INDEX_HTML = r"""<!DOCTYPE html>
|
|
|
1668
1678
|
gap: 7px;
|
|
1669
1679
|
letter-spacing: .02em;
|
|
1670
1680
|
}
|
|
1671
|
-
/* the
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
border: 1px solid var(--border);
|
|
1677
|
-
border-radius: 5px;
|
|
1678
|
-
padding: 0 5px;
|
|
1679
|
-
font-weight: 700;
|
|
1680
|
-
line-height: 1.45;
|
|
1681
|
-
}
|
|
1682
|
-
.mark .ma { color: var(--add-fg); }
|
|
1683
|
-
.mark .md { color: var(--del-fg); text-decoration: line-through; }
|
|
1681
|
+
/* the logo: same drawing as the Dock icon and favicon (scripts/make_icon.py),
|
|
1682
|
+
inline so it stays crisp at any size. Fixed brand colors, not the accent. */
|
|
1683
|
+
.logo { width: 28px; height: 28px; flex: none; display: block; }
|
|
1684
|
+
header > .logo { width: 54px; height: 54px; }
|
|
1685
|
+
#about h2 .logo { width: 48px; height: 48px; }
|
|
1684
1686
|
header .status { color: var(--muted); }
|
|
1685
1687
|
header #status {
|
|
1686
1688
|
flex: 1 1 auto;
|
|
@@ -2067,9 +2069,23 @@ INDEX_HTML = r"""<!DOCTYPE html>
|
|
|
2067
2069
|
</style>
|
|
2068
2070
|
</head>
|
|
2069
2071
|
<body>
|
|
2072
|
+
<!-- logo geometry mirrors scripts/make_icon.py (1024 grid, tile at 100..924) -->
|
|
2073
|
+
<svg width="0" height="0" style="position:absolute" aria-hidden="true">
|
|
2074
|
+
<defs>
|
|
2075
|
+
<symbol id="dw-logo" viewBox="100 100 824 824">
|
|
2076
|
+
<rect x="100" y="100" width="824" height="824" rx="182" fill="#2f6fb0"/>
|
|
2077
|
+
<path fill="#f7fbff" fill-rule="evenodd"
|
|
2078
|
+
d="M314 251H461A257 257 0 0 1 461 765H314Z M425 354H461A154 154 0 0 1 461 662H425Z"/>
|
|
2079
|
+
<rect x="472" y="433" width="166" height="48" rx="24" fill="#f18d7f"/>
|
|
2080
|
+
<rect x="472" y="536" width="166" height="48" rx="24" fill="#85d296"/>
|
|
2081
|
+
</symbol>
|
|
2082
|
+
</defs>
|
|
2083
|
+
</svg>
|
|
2070
2084
|
<header>
|
|
2085
|
+
<svg class="logo" aria-hidden="true"><use href="#dw-logo"/></svg>
|
|
2086
|
+
<div class="rows">
|
|
2071
2087
|
<div class="bar">
|
|
2072
|
-
<span class="title"><span class="
|
|
2088
|
+
<span class="title"><span class="word">Draftwatch</span></span>
|
|
2073
2089
|
<span class="filepick">
|
|
2074
2090
|
<label class="status" for="file-select">file</label>
|
|
2075
2091
|
<select id="file-select" title="pick a writing file in this repo"></select>
|
|
@@ -2094,6 +2110,7 @@ INDEX_HTML = r"""<!DOCTYPE html>
|
|
|
2094
2110
|
<button id="accent-toggle" title="accent color — click to cycle"><span class="swatch"></span><span id="accent-name">blue</span></button>
|
|
2095
2111
|
<button id="about-btn" title="what is Draftwatch?">about</button>
|
|
2096
2112
|
</div>
|
|
2113
|
+
</div>
|
|
2097
2114
|
</header>
|
|
2098
2115
|
|
|
2099
2116
|
<div id="banner">
|
|
@@ -2106,7 +2123,7 @@ INDEX_HTML = r"""<!DOCTYPE html>
|
|
|
2106
2123
|
<div id="about" role="dialog" aria-modal="true" aria-label="About Draftwatch">
|
|
2107
2124
|
<div class="card">
|
|
2108
2125
|
<button class="about-close" id="about-close" title="close (Esc)">close ✕</button>
|
|
2109
|
-
<h2><
|
|
2126
|
+
<h2><svg class="logo" aria-hidden="true"><use href="#dw-logo"/></svg>Draftwatch</h2>
|
|
2110
2127
|
<p class="tag">Review an AI agent's edits as a real git diff — locally.</p>
|
|
2111
2128
|
<p>An autonomous agent (Claude Code and the like) edits your files on disk.
|
|
2112
2129
|
Draftwatch shows you exactly what changed, as the word-level diff
|
|
@@ -3799,6 +3816,30 @@ def _webview_available():
|
|
|
3799
3816
|
return False
|
|
3800
3817
|
|
|
3801
3818
|
|
|
3819
|
+
def _app_identity_kwargs(webview):
|
|
3820
|
+
"""Brand the native window as Draftwatch rather than the Python interpreter
|
|
3821
|
+
running it: the Dock icon (draftwatch/assets/icon.png, drawn by
|
|
3822
|
+
scripts/make_icon.py) and, on macOS, the app name in the menu bar and its
|
|
3823
|
+
About/Hide/Quit items. Best effort: any failure leaves pywebview's defaults.
|
|
3824
|
+
Returns the kwargs for webview.start()."""
|
|
3825
|
+
if sys.platform == "darwin":
|
|
3826
|
+
try:
|
|
3827
|
+
from Foundation import NSBundle # PyObjC, a pywebview dependency on macOS
|
|
3828
|
+
info = NSBundle.mainBundle().infoDictionary()
|
|
3829
|
+
if info is not None:
|
|
3830
|
+
info["CFBundleName"] = "Draftwatch"
|
|
3831
|
+
except Exception:
|
|
3832
|
+
pass
|
|
3833
|
+
icon = os.path.join(os.path.dirname(os.path.abspath(__file__)), "assets", "icon.png")
|
|
3834
|
+
try:
|
|
3835
|
+
import inspect
|
|
3836
|
+
takes_icon = "icon" in inspect.signature(webview.start).parameters
|
|
3837
|
+
except (TypeError, ValueError):
|
|
3838
|
+
takes_icon = False
|
|
3839
|
+
# start(icon=) arrived in pywebview 5; on 4.x the window just keeps its default
|
|
3840
|
+
return {"icon": icon} if takes_icon and os.path.isfile(icon) else {}
|
|
3841
|
+
|
|
3842
|
+
|
|
3802
3843
|
def _run_app_window(url, title):
|
|
3803
3844
|
"""Open the UI in a native window (PyWebView). Returns True when the window
|
|
3804
3845
|
ran and was closed by the user; False when unavailable, in which case the
|
|
@@ -3816,7 +3857,7 @@ def _run_app_window(url, title):
|
|
|
3816
3857
|
try:
|
|
3817
3858
|
webview.create_window(title, url, width=1280, height=860,
|
|
3818
3859
|
min_size=(880, 560))
|
|
3819
|
-
webview.start()
|
|
3860
|
+
webview.start(**_app_identity_kwargs(webview))
|
|
3820
3861
|
return True
|
|
3821
3862
|
except Exception as e:
|
|
3822
3863
|
sys.stderr.write(
|
|
Binary file
|
|
Binary file
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: draftwatch
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: Review an AI agent's edits to your writing files as a real git word-diff — keep or revert changes hunk by hunk, then commit.
|
|
5
5
|
Author: Mike Konczal
|
|
6
6
|
License: MIT
|
|
@@ -22,6 +22,8 @@ Dynamic: license-file
|
|
|
22
22
|
|
|
23
23
|
# Draftwatch
|
|
24
24
|
|
|
25
|
+
<img src="https://raw.githubusercontent.com/mtkonczal/Draftwatch/main/draftwatch/assets/icon.png" alt="DraftWatch logo: a white D on blue with equal coral and green revision marks" width="220">
|
|
26
|
+
|
|
25
27
|

|
|
26
28
|
|
|
27
29
|
It’s difficult for writers to have AI act as an editor, because it’s never clear exactly what it changed. You can’t trust eyeballing it, but making the changes manually yourself means you don’t save much time. So you either ignore this potentially powerful writing helper, or you trust it at the risk that it does far more than you asked.
|
|
@@ -12,6 +12,8 @@ draftwatch.egg-info/entry_points.txt
|
|
|
12
12
|
draftwatch.egg-info/requires.txt
|
|
13
13
|
draftwatch.egg-info/top_level.txt
|
|
14
14
|
draftwatch/assets/codemirror.js
|
|
15
|
+
draftwatch/assets/favicon.png
|
|
16
|
+
draftwatch/assets/icon.png
|
|
15
17
|
draftwatch/assets/marked.js
|
|
16
18
|
draftwatch/assets/purify.js
|
|
17
19
|
draftwatch/assets/turndown.js
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "draftwatch"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.4"
|
|
8
8
|
description = "Review an AI agent's edits to your writing files as a real git word-diff — keep or revert changes hunk by hunk, then commit."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|