File size: 10,249 Bytes
99a44ac
 
 
 
 
b60973d
8012b6f
 
 
 
 
 
 
 
 
2460317
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8012b6f
ec6b346
 
99a44ac
45ebf29
99a44ac
93ef16f
99a44ac
 
07c5477
b60973d
99a44ac
 
 
 
 
 
 
 
 
93ef16f
f35d3f6
 
 
 
b60973d
 
99a44ac
 
784680a
93ef16f
 
 
2460317
8012b6f
3b2fb14
53148eb
b60973d
99a44ac
 
 
93ef16f
 
 
53148eb
 
 
 
 
 
 
 
3a73292
 
 
 
 
 
 
 
 
 
 
 
 
53148eb
 
3b2fb14
 
 
 
 
 
 
 
f35d3f6
 
 
 
 
 
 
 
 
 
 
b60973d
 
314a59f
 
 
b60973d
 
 
 
 
 
 
 
 
 
 
 
99a44ac
e5e233a
8a9d88a
 
d3283b8
8c82c03
 
d3283b8
8a9d88a
 
 
 
 
 
e5e233a
46a2576
e5e233a
 
4fcf51c
b60973d
ec6b346
 
 
 
 
 
 
 
 
 
 
 
 
 
99a44ac
9d479ea
6912fd3
b60973d
 
6912fd3
f9ca812
 
 
 
 
99a44ac
 
b60973d
93ef16f
 
 
 
 
b60973d
04b2acc
b60973d
ec3a520
 
 
f9ca812
 
 
735a30f
ec3a520
 
 
 
 
6912fd3
ec3a520
 
 
 
 
 
 
 
99a44ac
b60973d
99a44ac
 
 
 
 
 
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
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>Document</title>
  <script>
    // theme before first paint: a stored choice, else the OS setting
    try {
      var t = localStorage.getItem('cw-theme')
      document.documentElement.dataset.theme =
        t === 'dark' || t === 'light' ? t : matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
    } catch (e) {
      document.documentElement.dataset.theme = 'light'
    }
    // …and the document style, so the sheet is never set in the wrong face for
    // a frame. Reading also needs its serif early: the stylesheet only asks for
    // it once text is laid out, which is a whole round trip too late.
    try {
      var s = localStorage.getItem('cw-doc-style')
      document.documentElement.dataset.docStyle = s === 'reading' ? 'reading' : 'docs'
      if (s === 'reading') {
        var l = document.createElement('link')
        l.rel = 'preload'; l.as = 'font'; l.type = 'font/woff2'; l.crossOrigin = 'anonymous'
        l.id = 'serif-preload'; l.href = '/fonts/libre-baskerville-latin.woff2'
        document.head.appendChild(l)
      }
    } catch (e) {
      document.documentElement.dataset.docStyle = 'docs'
    }
  </script>
  <link rel="preload" href="/fonts/inter-latin.woff2" as="font" type="font/woff2" crossorigin />
  <!--boot-->
  <link rel="stylesheet" href="/app.css" />
  <link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' rx='8' fill='%231d5c45'/%3E%3Crect x='9' y='10' width='14' height='2.2' rx='1.1' fill='white'/%3E%3Crect x='9' y='15' width='14' height='2.2' rx='1.1' fill='white'/%3E%3Crect x='9' y='20' width='9' height='2.2' rx='1.1' fill='white'/%3E%3C/svg%3E" />
</head>
<body class="page-doc">
  <div id="signin" class="overlay hidden">
    <div class="card">
      <h2>cowrite</h2>
      <p>Collaborative documents where agents comment and suggest — but never write.</p>
      <a class="btn primary" id="signin-btn" href="/auth/login">Sign in with Hugging Face</a>
      <div id="dev-login" class="hidden">
        <input id="dev-user" placeholder="dev username" />
        <button class="btn" id="dev-go">Dev sign-in</button>
      </div>
    </div>
  </div>

  <header id="topbar">
    <button class="iconbtn phone-only" id="m-pages" title="Pages"></button>
    <button id="docs-btn" title="Documents — switch or create">
      <span id="doc-title">…</span>
      <span id="docs-caret" aria-hidden="true"></span>
    </button>
    <span id="conn" title="connection"></span>
    <div id="header-tools"></div>
    <div class="spacer"></div>
    <div id="presence"></div>
    <div id="mode-switch" title="Editing writes straight into the document; Suggesting proposes changes instead"></div>
    <button class="iconbtn phone-only" id="m-fmt" title="Formatting">Aa</button>
    <button class="iconbtn phone-only" id="m-comments" title="Comments"></button>
    <button class="iconbtn phone-only" id="m-more" title="More">⋯</button>
    <button class="iconbtn" id="docstyle-btn" title="Switch document style"></button>
    <button class="iconbtn" id="theme-btn" title="Switch theme"></button>
    <button class="iconbtn" id="download-btn" title="Download"></button>
    <button class="btn ghost small" id="share-btn">Share</button>
    <button class="btn ghost small" id="agents-btn">Agents</button>
    <span id="whoami"></span>
  </header>

  <div id="more-pop" class="hidden"></div>
  <div id="scrim" class="hidden"></div>

  <div id="share-pop" class="hidden">
    <h3>Share</h3>
    <p class="hint">People you share with can read, edit, comment — and point their own agents at this doc.</p>
    <div id="share-list" class="muted">loading…</div>
    <form id="share-form">
      <input id="share-user" placeholder="Hugging Face username" />
      <button class="btn small" type="submit">Share</button>
    </form>
    <div id="link-share" class="hidden">
      <div class="link-head">
        <div>
          <strong>Anyone with the link</strong>
          <p class="hint" id="link-hint">Off — only the people above can open this.</p>
        </div>
        <button class="btn small ghost" id="link-toggle">Create link</button>
      </div>
      <div id="link-row" class="hidden">
        <input id="link-url" readonly />
        <button class="btn small" id="link-copy">Copy</button>
      </div>
    </div>
  </div>

  <div id="download-pop" class="hidden">
    <h3>Download</h3>
    <div class="dl-choice" id="dl-scope" role="radiogroup" aria-label="What to download"></div>
    <div class="dl-choice" id="dl-format" role="radiogroup" aria-label="Format"></div>
    <p class="hint" id="dl-hint"></p>
    <button class="btn small primary" id="dl-go">Download</button>
  </div>

  <div id="docs-pop" class="hidden">
    <h3>Documents</h3>
    <div id="docs-list" class="loading">
      <div class="sk-card"></div><div class="sk-card"></div><div class="sk-card"></div>
    </div>
    <div class="docs-actions">
      <button class="btn small primary" id="new-doc">New document</button>
      <button class="btn small" id="playground-btn">Playground</button>
    </div>
  </div>

  <div id="agents-pop" class="hidden">
    <h3>Agents</h3>
    <p class="hint">Your private built-in agent uses Kimi K3 and can search the web. Mention it in
    any comment: <b>@handle do something</b>. You can also register an external agent, copy its
    prompt, and point any coding agent at Cowrite.</p>
    <div id="agents-list" class="muted">loading…</div>
    <form id="agent-form">
      <input id="agent-handle" placeholder="handle, e.g. leandro-claude" />
      <button class="btn small" type="submit">Add</button>
    </form>
  </div>

  <div id="link-pop" class="hidden">
    <input id="link-url" placeholder="https://…" />
    <button class="btn small primary" id="link-apply">Link</button>
  </div>

  <main id="layout">
    <nav id="sidebar" class="hidden">
      <div id="sidebar-sticky-head">
        <div id="sidebar-head">
          <div id="sidebar-search-wrap">
            <input id="sidebar-search" type="text" placeholder="Search pages…" autocomplete="off" aria-label="Search page titles and text" />
            <button id="sidebar-search-key" type="button" aria-label="Focus search">⌘K</button>
          </div>
          <div class="sidebar-actions">
            <button class="iconbtn" id="page-add" title="New page" aria-label="New page"></button>
            <button class="iconbtn" id="group-add" title="New group" aria-label="New group"></button>
          </div>
          <button class="iconbtn phone-only" id="sidebar-close" title="Close"></button>
        </div>
      </div>
      <div id="page-tree"></div>
    </nav>
    <button id="sidebar-toggle" title="Toggle pages sidebar"></button>
    <button id="margin-toggle" title="Toggle comments panel"></button>
    <div id="editor-col">
      <!-- Painted with the first frame, before the editor bundle has even
           parsed, and removed once the document has synced. Without it the
           first thing you see is an empty sheet, which reads as "loaded but
           blank" rather than "still coming". -->
      <div id="doc-skeleton" aria-hidden="true">
        <div class="sk-line sk-title"></div>
        <div class="sk-line w90"></div>
        <div class="sk-line w75"></div>
        <div class="sk-line w82"></div>
        <div class="sk-line sk-gap w40"></div>
        <div class="sk-line w88"></div>
        <div class="sk-line w70"></div>
        <div class="sk-line w80"></div>
      </div>
      <div id="editor"></div>
      <div id="proposal-view" class="hidden"></div>
      <div id="selection-menu" class="hidden">
        <button id="comment-btn"></button>
        <button id="suggest-btn"></button>
      </div>
      <!-- The hover affordance: appears in the page's right margin, level with
           the paragraph the pointer is beside, and leaves a comment anchored to
           that place rather than to a selected span. Positioned by JS, so it
           needs no box of its own in the flow — nothing here shifts the page. -->
      <button id="hover-comment" class="hidden" type="button" data-tip="Comment here" aria-label="Comment beside this paragraph"></button>
    </div>

    <aside id="margin-col">
      <div id="margin-head">
        <span id="margin-grab"></span>
        <span id="margin-head-title">Comments</span>
        <button class="iconbtn" id="margin-close" title="Close comments"></button>
      </div>
      <div id="margin-tools">
        <label class="row" style="gap:6px; cursor:pointer;"><input type="checkbox" id="show-resolved" /> show closed</label>
      </div>
      <div id="margin-items">
        <div id="composer" class="composer-box hidden">
          <blockquote id="composer-quote"></blockquote>
          <!-- A position-anchored comment has nothing to quote, so it gets a
               locator line instead of the blockquote (see openComposer). -->
          <div id="composer-loc" class="anchor-loc hidden"></div>
          <textarea id="composer-text" rows="3" placeholder="Comment — @handle to hand it to an agent. Enter sends, Shift+Enter for a new line."></textarea>
          <div id="composer-mentions" class="mention-menu hidden"></div>
          <div class="row">
            <button class="btn small ghost" id="composer-cancel">Cancel</button>
            <button class="btn small primary" id="composer-send">Comment</button>
          </div>
        </div>
        <div id="suggest-composer" class="composer-box hidden">
          <blockquote id="suggest-quote"></blockquote>
          <textarea id="suggest-text" rows="6" placeholder="Rewrite the selected block(s) in markdown…"></textarea>
          <input id="suggest-rationale" placeholder="Why? (optional)" />
          <div class="row">
            <button class="btn small ghost" id="suggest-cancel">Cancel</button>
            <button class="btn small primary" id="suggest-send">Suggest</button>
          </div>
        </div>
      </div>
    </aside>
  </main>

  <script src="/doc.js"></script>
</body>
</html>