Skip to content

Commit 2f83109

Browse files
committed
chore: add .gitattributes and renormalize line endings to LF
16 tracked C++ sources had drifted to CRLF (mostly on Windows edits), which churned diffs — PR #18 hit exactly this on main.cpp. Add a repo .gitattributes (`* text=auto eol=lf`) so the working tree is LF on every platform, protect .bat/.cmd as CRLF (cmd.exe requires it), mark common binary asset types, then `git add --renormalize .`. Pure line-ending change: the content diff is empty (`git diff --ignore-cr-at-eol` shows only .gitattributes). Submodules (maya, acp-cpp, mcp-cpp, rag-cpp) carry their own attributes and are untouched. Rebuilt the affected TUs (http/acp/main/composer) clean.
1 parent bb2b42a commit 2f83109

17 files changed

Lines changed: 5713 additions & 5686 deletions

File tree

.gitattributes

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Normalize line endings across the repo.
2+
#
3+
# `text=auto` lets git decide which files are text and stores them with LF
4+
# in the repository. `eol=lf` forces LF on checkout too, so the working tree
5+
# stays LF on every platform (including Windows / MSYS2) — this repo builds
6+
# under MinGW and clang64 where stray CRLF churned diffs before. Submodules
7+
# (maya, acp-cpp, mcp-cpp, rag-cpp) carry their own attributes and are
8+
# unaffected.
9+
* text=auto eol=lf
10+
11+
# Windows batch scripts must keep CRLF or cmd.exe mis-parses them.
12+
*.bat text eol=crlf
13+
*.cmd text eol=crlf
14+
15+
# Binary assets: never touch.
16+
*.png binary
17+
*.jpg binary
18+
*.jpeg binary
19+
*.gif binary
20+
*.ico binary
21+
*.woff binary
22+
*.woff2 binary
23+
*.ttf binary
24+
*.otf binary
25+
*.pdf binary
26+
*.zip binary
27+
*.gz binary

include/agentty/acp/server.hpp

Lines changed: 194 additions & 194 deletions
Large diffs are not rendered by default.

include/agentty/io/clipboard.hpp

Lines changed: 64 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,67 @@
1-
#pragma once
2-
// Read an image from the system clipboard via platform-native tooling.
3-
//
4-
// Bracketed paste delivers UTF-8 text only; binary clipboard content
5-
// (a PNG that a screenshot tool put on the clipboard) is dropped or
6-
// mangled by every mainstream terminal. The reliable path is to ASK
7-
// the platform clipboard for its image content out-of-band, via a
8-
// small subprocess:
9-
//
10-
// Linux/Wayland → wl-paste --type image/png
11-
// Linux/X11 → xclip -selection clipboard -t image/png -o
12-
// macOS → pngpaste - (brew install pngpaste)
13-
// Windows → powershell System.Windows.Forms.Clipboard.GetImage
14-
//
15-
// All capture stdout as raw bytes — `tools::util::Subprocess` runs its
16-
// captured output through to_valid_utf8(), which would replace every
17-
// non-UTF-8 byte with U+FFFD and corrupt the image. So this module
18-
// has its own popen-based capture that doesn't touch the bytes.
19-
//
20-
// The reducer arm in update/composer.cpp calls read_clipboard_image()
21-
// synchronously on Ctrl+V. The subprocesses all exit immediately when
22-
// no image is available (non-zero status, empty stdout) so the worst
23-
// case is the shell-spawn cost (~10-50 ms on Linux, ~100-200 ms on
24-
// macOS via osascript). Acceptable on the UI thread for an explicit
25-
// user action.
26-
27-
#include <optional>
28-
#include <string>
29-
30-
namespace agentty {
31-
32-
struct ClipboardImage {
33-
/// Raw image bytes — PNG / JPEG / GIF / WEBP. Sniffed from the
34-
/// magic prefix of the captured stdout, so format mismatch
35-
/// between tool flags and actual content (rare, but possible
36-
/// under odd compositor configurations) is surfaced cleanly.
37-
std::string bytes;
38-
/// MIME type (e.g. "image/png") matching the magic prefix.
39-
std::string media_type;
40-
};
41-
42-
/// Read an image from the system clipboard. On success returns the
43-
/// raw bytes + sniffed MIME type. On failure (tool missing, clipboard
44-
/// empty, no image type on clipboard, image too large), returns
45-
/// nullopt and writes a one-line human-readable diagnostic to
46-
/// `*error_out` so the caller can surface it as a status toast that
47-
/// names the actual failure (the previous "no image on clipboard"
48-
/// blanket message was unhelpful when the real fix was "install
49-
/// wl-clipboard" or "the clipboard has only text").
50-
[[nodiscard]] std::optional<ClipboardImage>
51-
read_clipboard_image(std::string* error_out = nullptr);
52-
53-
/// Read plain UTF-8 text from the system clipboard. Used by the
54-
/// composer's "smart paste" path: when Ctrl+V / Ctrl+Shift+V arrive
55-
/// via a trigger that didn't already carry bracketed-paste content
56-
/// (Windows Terminal swallows Ctrl+V and emits nothing on an
57-
/// image-only clipboard; the user's Alt+V fallback also goes through
58-
/// the same path), the composer asks the OS clipboard for whatever
59-
/// it has — image first, text second — so the same shortcut "just
60-
/// works" regardless of clipboard contents.
61-
///
62-
/// Returns nullopt if the clipboard has no text or the platform tool
63-
/// is missing; writes a diagnostic to `*error_out` for the toast
64-
/// path.
1+
#pragma once
2+
// Read an image from the system clipboard via platform-native tooling.
3+
//
4+
// Bracketed paste delivers UTF-8 text only; binary clipboard content
5+
// (a PNG that a screenshot tool put on the clipboard) is dropped or
6+
// mangled by every mainstream terminal. The reliable path is to ASK
7+
// the platform clipboard for its image content out-of-band, via a
8+
// small subprocess:
9+
//
10+
// Linux/Wayland → wl-paste --type image/png
11+
// Linux/X11 → xclip -selection clipboard -t image/png -o
12+
// macOS → pngpaste - (brew install pngpaste)
13+
// Windows → powershell System.Windows.Forms.Clipboard.GetImage
14+
//
15+
// All capture stdout as raw bytes — `tools::util::Subprocess` runs its
16+
// captured output through to_valid_utf8(), which would replace every
17+
// non-UTF-8 byte with U+FFFD and corrupt the image. So this module
18+
// has its own popen-based capture that doesn't touch the bytes.
19+
//
20+
// The reducer arm in update/composer.cpp calls read_clipboard_image()
21+
// synchronously on Ctrl+V. The subprocesses all exit immediately when
22+
// no image is available (non-zero status, empty stdout) so the worst
23+
// case is the shell-spawn cost (~10-50 ms on Linux, ~100-200 ms on
24+
// macOS via osascript). Acceptable on the UI thread for an explicit
25+
// user action.
26+
27+
#include <optional>
28+
#include <string>
29+
30+
namespace agentty {
31+
32+
struct ClipboardImage {
33+
/// Raw image bytes — PNG / JPEG / GIF / WEBP. Sniffed from the
34+
/// magic prefix of the captured stdout, so format mismatch
35+
/// between tool flags and actual content (rare, but possible
36+
/// under odd compositor configurations) is surfaced cleanly.
37+
std::string bytes;
38+
/// MIME type (e.g. "image/png") matching the magic prefix.
39+
std::string media_type;
40+
};
41+
42+
/// Read an image from the system clipboard. On success returns the
43+
/// raw bytes + sniffed MIME type. On failure (tool missing, clipboard
44+
/// empty, no image type on clipboard, image too large), returns
45+
/// nullopt and writes a one-line human-readable diagnostic to
46+
/// `*error_out` so the caller can surface it as a status toast that
47+
/// names the actual failure (the previous "no image on clipboard"
48+
/// blanket message was unhelpful when the real fix was "install
49+
/// wl-clipboard" or "the clipboard has only text").
50+
[[nodiscard]] std::optional<ClipboardImage>
51+
read_clipboard_image(std::string* error_out = nullptr);
52+
53+
/// Read plain UTF-8 text from the system clipboard. Used by the
54+
/// composer's "smart paste" path: when Ctrl+V / Ctrl+Shift+V arrive
55+
/// via a trigger that didn't already carry bracketed-paste content
56+
/// (Windows Terminal swallows Ctrl+V and emits nothing on an
57+
/// image-only clipboard; the user's Alt+V fallback also goes through
58+
/// the same path), the composer asks the OS clipboard for whatever
59+
/// it has — image first, text second — so the same shortcut "just
60+
/// works" regardless of clipboard contents.
61+
///
62+
/// Returns nullopt if the clipboard has no text or the platform tool
63+
/// is missing; writes a diagnostic to `*error_out` for the toast
64+
/// path.
6565
[[nodiscard]] std::optional<std::string>
6666
read_clipboard_text(std::string* error_out = nullptr);
6767

0 commit comments

Comments
 (0)