document360-writer 0.3.1 → 0.4.0

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.
package/dist/repl.js CHANGED
@@ -1,7 +1,30 @@
1
1
  import { createInterface } from 'node:readline/promises';
2
2
  import { createSession, resolveAuth, getSession, setTitle, slugify, touchSession, upsertSession, generateTitle, resolveActiveProfile, decodeJwtClaims, isExpired, loadTokens, } from 'document360-engine';
3
3
  import { slashCommands, parseSlash } from './commands/index.js';
4
- import { accent, banner, dim, error, muted, ok, warn } from './lib/colors.js';
4
+ import { accent, banner, bold, dim, error, muted, ok, warn } from './lib/colors.js';
5
+ import { formatToolResult, formatToolUse } from './lib/toolFormat.js';
6
+ import { articleEditorUrl, extractArticleId, extractPublicUrl } from './d360/portalLink.js';
7
+ /** D360 write tools whose results deserve a portal/live link. (unpublish excluded.) */
8
+ const ARTICLE_WRITE_TOOLS = /^mcp__document360__d360_(create_article|update_article|fork_article|publish_article)$/;
9
+ /** After a successful article write, print where to see the outcome. */
10
+ function printArticleLinks(toolName, input, output, cwd) {
11
+ if (!ARTICLE_WRITE_TOOLS.test(toolName))
12
+ return;
13
+ try {
14
+ const active = resolveActiveProfile(cwd);
15
+ const projectId = (typeof input['project_id'] === 'string' && input['project_id']) || active.project.projectId;
16
+ const articleId = extractArticleId(input, output);
17
+ const publicUrl = extractPublicUrl(output);
18
+ if (toolName.endsWith('publish_article') && publicUrl)
19
+ console.log(accent(` ⮕ Live: ${publicUrl}`));
20
+ if (articleId && projectId) {
21
+ console.log(accent(` ⮕ Preview in Document360: ${articleEditorUrl(active.connection.portalUrl, projectId, articleId, active.project.languageCode ?? 'en')}`));
22
+ }
23
+ }
24
+ catch {
25
+ /* no/invalid profile — skip the links */
26
+ }
27
+ }
5
28
  export async function runRepl(cwd = process.cwd(), authMode = 'auto', profileName) {
6
29
  const auth = resolveAuth(authMode);
7
30
  if (auth.kind === 'none') {
@@ -206,11 +229,12 @@ function fireTitleGeneration(tracker, cwd) {
206
229
  }
207
230
  /** Drive one user turn through the engine, rendering EngineEvents to the terminal. */
208
231
  async function runTurn(session, text, auth, tracker, cwd) {
232
+ const shownTools = new Map(); // tool_use ids whose header we rendered
209
233
  for await (const ev of session.send(text)) {
210
- renderEvent(ev, tracker, cwd, auth);
234
+ renderEvent(ev, tracker, cwd, auth, shownTools);
211
235
  }
212
236
  }
213
- function renderEvent(ev, tracker, cwd, auth) {
237
+ function renderEvent(ev, tracker, cwd, auth, shownTools) {
214
238
  switch (ev.type) {
215
239
  case 'session':
216
240
  if (!tracker.uuid)
@@ -219,10 +243,29 @@ function renderEvent(ev, tracker, cwd, auth) {
219
243
  case 'text':
220
244
  process.stdout.write(ev.delta);
221
245
  break;
222
- case 'tool':
223
- process.stdout.write('\n');
224
- console.log(muted(` ⚙ ${ev.name}`));
246
+ case 'tool': {
247
+ const header = formatToolUse(ev.name, ev.input);
248
+ if (header) {
249
+ process.stdout.write('\n\n');
250
+ console.log(`${ok('●')} ${bold(header.title)}${header.arg !== null ? muted(`${header.sep}(${header.arg})`) : ''}`);
251
+ shownTools.set(ev.id, { name: ev.name, input: ev.input });
252
+ }
225
253
  break;
254
+ }
255
+ case 'tool_result': {
256
+ const pending = shownTools.get(ev.id);
257
+ if (!pending)
258
+ break; // hidden tools stay hidden
259
+ shownTools.delete(ev.id);
260
+ const view = formatToolResult(ev.output);
261
+ const paint = ev.isError ? error : muted;
262
+ view.lines.forEach((line, i) => console.log(paint((i === 0 ? ' ⎿ ' : ' ') + line)));
263
+ if (view.hidden > 0)
264
+ console.log(dim(` … +${view.hidden} lines`));
265
+ if (!ev.isError)
266
+ printArticleLinks(pending.name, pending.input, ev.output, cwd);
267
+ break;
268
+ }
226
269
  case 'result':
227
270
  process.stdout.write('\n');
228
271
  console.log(dim(` (${ev.inputTokens}→${ev.outputTokens} tokens)`));
package/dist/repl.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"repl.js","sourceRoot":"","sources":["../src/repl.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"repl.js","sourceRoot":"","sources":["../src/repl.ts"],"names":[],"mappings":"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"}
package/dist/tui/App.js CHANGED
@@ -1,12 +1,17 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
3
- import { Box, Static, Text, useApp, useInput, useStdout } from 'ink';
4
- import { createSession, resolveActiveProfile, decodeJwtClaims, isExpired, loadTokens, setTitle, slugify, touchSession, upsertSession, generateTitle, findByName, listSessions, renameSession, readProjectConfig, writeProjectConfig, } from 'document360-engine';
3
+ import { Box, Text, useApp, useInput, useStdout } from 'ink';
4
+ import { existsSync, readFileSync } from 'node:fs';
5
+ import { basename, isAbsolute, join } from 'node:path';
6
+ import { createSession, resolveActiveProfile, resolveProjectId, getArticle, decodeJwtClaims, isExpired, loadTokens, setTitle, slugify, touchSession, upsertSession, generateTitle, findByName, listSessions, renameSession, suggestNextAction, readProjectConfig, writeProjectConfig, } from 'document360-engine';
5
7
  import { publishCommand } from '../commands/publish.js';
6
8
  import { auditCommand } from '../commands/audit.js';
7
9
  import { screenshotCommand } from '../commands/screenshot.js';
8
10
  import { COMMANDS, filterCommands } from './catalog.js';
9
- import { Markdown } from './markdown.js';
11
+ import { renderItem, renderTranscript } from './itemRender.js';
12
+ import { formatToolResult, formatToolUse } from '../lib/toolFormat.js';
13
+ import { liveTail, streamCut } from '../lib/streaming.js';
14
+ import { articleEditorUrl, extractArticleId, extractPublicUrl } from '../d360/portalLink.js';
10
15
  import { fetchWorkspaces, matchWorkspace, setWorkspace } from '../d360/workspaceCli.js';
11
16
  function computeBanner(cwd, version, auth, profileName) {
12
17
  const claude = auth.kind === 'api' ? 'API key' : auth.kind === 'subscription' ? 'subscription' : 'not configured';
@@ -51,21 +56,26 @@ const GERUNDS = [
51
56
  'Polishing', 'Synthesizing', 'Curating', 'Distilling', 'Weaving', 'Wrangling', 'Pondering',
52
57
  ];
53
58
  const SPINNER = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
54
- /** Prettify a tool name for display; returns null for internal tools that should be hidden. */
55
- function prettyTool(name) {
56
- if (name === 'ToolSearch')
57
- return null; // deferred-tool search internal noise
58
- if (name.startsWith('mcp__')) {
59
- const tool = name.split('__').slice(2).join('__'); // mcp__<server>__<tool>
60
- return 'Document360: ' + tool.replace(/^d360_/, '').replace(/_/g, ' ');
61
- }
62
- return name; // built-in tools (Read, Write, Bash, ) shown as-is
59
+ const PLACEHOLDER = 'Ask me to write or update an article…';
60
+ /**
61
+ * Claude Code-style blinking block cursor: inverse-video over `ch` (the first
62
+ * placeholder character when the input is empty, a space at the end while typing).
63
+ */
64
+ function Cursor({ ch, dim }) {
65
+ const [on, setOn] = useState(true);
66
+ useEffect(() => {
67
+ const id = setInterval(() => setOn(o => !o), 530);
68
+ return () => clearInterval(id);
69
+ }, []);
70
+ return (_jsx(Text, { inverse: on, color: dim && !on ? 'gray' : undefined, children: ch }));
63
71
  }
64
- function formatDuration(seconds) {
65
- if (seconds < 60)
66
- return `${seconds}s`;
67
- return `${Math.floor(seconds / 60)}m ${seconds % 60}s`;
72
+ /** D360 write tools whose results deserve a portal/live link. (unpublish excluded.) */
73
+ const ARTICLE_WRITE_TOOLS = /^mcp__document360__d360_(create_article|update_article|fork_article|publish_article)$/;
74
+ function stripFrontmatter(md) {
75
+ const m = md.match(/^---\r?\n[\s\S]*?\r?\n---\r?\n/);
76
+ return m ? md.slice(m[0].length) : md;
68
77
  }
78
+ const ARTICLE_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
69
79
  /** Animated "working" line: spinner + rotating verb + live timer + ~token estimate. */
70
80
  function Working({ startTime, chars }) {
71
81
  const [tick, setTick] = useState(0);
@@ -81,15 +91,26 @@ function Working({ startTime, chars }) {
81
91
  }
82
92
  export function App({ cwd, auth, profileName, version }) {
83
93
  const { exit } = useApp();
84
- const [items, setItems] = useState(() => [{ id: 0, kind: 'banner', info: computeBanner(cwd, version, auth, profileName) }]);
85
94
  const [live, setLive] = useState(null);
86
95
  const [input, setInput] = useState('');
87
96
  const [busy, setBusy] = useState(false);
97
+ /** Ghost-text suggestion for the next prompt (Claude Code-style: tab to accept). */
98
+ const [ghost, setGhost] = useState(null);
99
+ /** Bumped on every turn/accept — late suggestion responses for old turns are dropped. */
100
+ const ghostSeqRef = useRef(0);
101
+ // The placeholder is a first-run affordance — once a prompt has been sent the input
102
+ // is just a cursor (matches Claude Code). After /clear it returns.
103
+ const [started, setStarted] = useState(false);
88
104
  const [turnChars, setTurnChars] = useState(0);
89
105
  const turnStartRef = useRef(0);
90
106
  const [paletteIndex, setPaletteIndex] = useState(0);
91
107
  const [historyIndex, setHistoryIndex] = useState(null);
92
- const idRef = useRef(0);
108
+ /** The transcript model. Items are printed (markdown-rendered to ANSI) through Ink's
109
+ console patch the moment they're pushed — console.log inside an Ink app atomically
110
+ erases the dynamic frame, writes, and repaints it. Kept here so the WHOLE
111
+ transcript can be re-rendered at the new width on resize (which <Static> cannot
112
+ do safely — see .claude/docs/gotchas-writer-tui.md). */
113
+ const itemsRef = useRef([]);
93
114
  // LAZY init — `useRef(createSession(...))` would call createSession on EVERY render
94
115
  // (useRef keeps only the first value but still evaluates the argument each time), and
95
116
  // createSession spawns an Agent SDK subprocess → a new subprocess per keystroke →
@@ -99,20 +120,72 @@ export function App({ cwd, auth, profileName, version }) {
99
120
  sessionRef.current = createSession({ cwd, profileName, allowProdWrites: false });
100
121
  }
101
122
  const trackerRef = useRef({ uuid: null, firstPrompt: null, titleFired: false });
123
+ /** tool_use ids whose header we rendered (with their call details, for result
124
+ pairing + article-link extraction) — the rest stay hidden. */
125
+ const shownToolsRef = useRef(new Map());
102
126
  const allowProdRef = useRef(false);
103
127
  const historyRef = useRef([]);
104
128
  const { stdout } = useStdout();
105
129
  const [, setResizeTick] = useState(0);
106
- // Re-render on resize so the width below recomputes. NOTE: do NOT write any clear
107
- // escape here that caused a clear→resize→clear feedback loop on Windows Terminal.
108
- // A plain state bump is loop-safe (no stdout write); Ink repaints with the new width.
130
+ // Cols AND rows: height-only resizes also reflow under conpty and can strand
131
+ // dynamic-frame fragments, so they get a replay too (pty-harness verified).
132
+ const lastSizeRef = useRef(`${stdout.columns ?? 80}x${stdout.rows ?? 24}`);
133
+ const transcriptWidth = useCallback(() => Math.max(20, (stdout.columns ?? 80) - 1), [stdout]);
134
+ /** Append + print one transcript item (markdown-rendered, via Ink's console patch). */
135
+ const push = useCallback((item) => {
136
+ itemsRef.current.push(item);
137
+ console.log(renderItem(item, transcriptWidth()));
138
+ }, [transcriptWidth]);
139
+ // Print the banner once on mount (it's a transcript item like everything else).
140
+ useEffect(() => {
141
+ push({ kind: 'banner', info: computeBanner(cwd, version, auth, profileName) });
142
+ // eslint-disable-next-line react-hooks/exhaustive-deps
143
+ }, []);
144
+ // Resize redraw (debounced; only when COLUMNS changed — height changes don't rewrap).
145
+ // The terminal rewraps old lines on narrow-resize, so nothing already printed can be
146
+ // trusted; we erase the viewport and replay the whole transcript at the new width.
147
+ // Hardening (SNAG-0026: mid-drag settles tore lines while conpty reflowed):
148
+ // - 400ms debounce: a direction-change pause in a back-and-forth drag is not
149
+ // "settled" — one replay at the end, not several along the way.
150
+ // - home BEFORE erase (\x1b[H\x1b[2J — canonical cls order conpty handles).
151
+ // - synchronized output (\x1b[?2026h/l): WT applies clear+replay as ONE frame.
152
+ // The whole write goes THROUGH the console patch (serialized with Ink's frame
153
+ // erase/repaint) — never write raw escapes behind Ink's back, and never remount
154
+ // <Static> (see .claude/docs/gotchas-writer-tui.md for the s-0024 incident).
109
155
  useEffect(() => {
110
- const onResize = () => setResizeTick(t => t + 1);
156
+ let timer = null;
157
+ let replayTimer = null;
158
+ const onResize = () => {
159
+ if (timer)
160
+ clearTimeout(timer);
161
+ timer = setTimeout(() => {
162
+ timer = null;
163
+ const size = `${stdout.columns ?? 80}x${stdout.rows ?? 24}`;
164
+ if (size === lastSizeRef.current)
165
+ return;
166
+ lastSizeRef.current = size;
167
+ // ORDER MATTERS (pty-harness verified): first re-render the dynamic region at
168
+ // the new width; only after Ink painted that frame do the replay. Replaying
169
+ // first leaves Ink writing an OLD-width frame after our clear — its rewrapped
170
+ // lines defeat the next erase and strand the frame's top border on screen.
171
+ setResizeTick(t => t + 1);
172
+ if (replayTimer)
173
+ clearTimeout(replayTimer);
174
+ replayTimer = setTimeout(() => {
175
+ replayTimer = null;
176
+ console.log('\x1b[?2026h\x1b[H\x1b[2J' + renderTranscript(itemsRef.current, transcriptWidth()) + '\x1b[?2026l');
177
+ }, 80);
178
+ }, 400);
179
+ };
111
180
  stdout.on('resize', onResize);
112
181
  return () => {
182
+ if (timer)
183
+ clearTimeout(timer);
184
+ if (replayTimer)
185
+ clearTimeout(replayTimer);
113
186
  stdout.off('resize', onResize);
114
187
  };
115
- }, [stdout]);
188
+ }, [stdout, transcriptWidth]);
116
189
  // CRITICAL: cap the rendered width to columns-1. A full-terminal-width element (the
117
190
  // input border) sits exactly at the wrap boundary and wraps by one column; Ink then
118
191
  // erases by a line count that's short, leaving the overflow behind — so every render
@@ -122,15 +195,41 @@ export function App({ cwd, auth, profileName, version }) {
122
195
  const status = useMemo(() => statusLine(cwd, profileName), [cwd, profileName]);
123
196
  const palette = filterCommands(input);
124
197
  const paletteOpen = palette.length > 0 && !busy;
125
- const nextId = () => ++idRef.current;
126
- const push = useCallback((item) => setItems(prev => [...prev, { ...item, id: nextId() }]), []);
198
+ // Cap the live area well under typical terminal heights; the held-back text appears
199
+ // markdown-rendered when its paragraph (or code fence) completes.
200
+ const liveView = live !== null ? liveTail(live, 8, width) : null;
127
201
  const restartSession = useCallback((resume) => {
128
202
  sessionRef.current?.close();
129
203
  sessionRef.current = createSession({ cwd, resume, profileName, allowProdWrites: allowProdRef.current });
130
204
  if (!resume)
131
205
  trackerRef.current = { uuid: null, firstPrompt: null, titleFired: false };
132
206
  }, [cwd, profileName]);
207
+ /** After a successful article write, surface where to see the outcome (option C). */
208
+ const pushArticleLinks = useCallback((toolName, input, output) => {
209
+ if (!ARTICLE_WRITE_TOOLS.test(toolName))
210
+ return;
211
+ try {
212
+ const active = resolveActiveProfile(cwd, profileName);
213
+ const projectId = (typeof input['project_id'] === 'string' && input['project_id']) || active.project.projectId;
214
+ const articleId = extractArticleId(input, output);
215
+ const lines = [];
216
+ const publicUrl = extractPublicUrl(output);
217
+ if (toolName.endsWith('publish_article') && publicUrl)
218
+ lines.push(`Live: ${publicUrl}`);
219
+ if (articleId && projectId) {
220
+ lines.push(`Preview in Document360: ${articleEditorUrl(active.connection.portalUrl, projectId, articleId, active.project.languageCode ?? 'en')}`);
221
+ }
222
+ if (lines.length > 0)
223
+ push({ kind: 'link', lines });
224
+ }
225
+ catch {
226
+ /* no/invalid profile — skip the links */
227
+ }
228
+ }, [cwd, profileName, push]);
133
229
  const runPrompt = useCallback(async (text) => {
230
+ setStarted(true);
231
+ setGhost(null);
232
+ const ghostSeq = ++ghostSeqRef.current;
134
233
  push({ kind: 'user', text });
135
234
  const tracker = trackerRef.current;
136
235
  if (!tracker.firstPrompt)
@@ -138,14 +237,33 @@ export function App({ cwd, auth, profileName, version }) {
138
237
  turnStartRef.current = Date.now();
139
238
  setTurnChars(0);
140
239
  setBusy(true);
240
+ shownToolsRef.current.clear();
241
+ let turnText = ''; // all assistant text this turn (for the next-action suggestion)
141
242
  let buffer = '';
243
+ // Throttle live repaints to ~16fps: a repaint per token delta flickers and
244
+ // multiplies the chances of erase/rewrap races; batching costs nothing visible.
245
+ let liveTimer = null;
246
+ const scheduleLive = () => {
247
+ if (liveTimer)
248
+ return;
249
+ liveTimer = setTimeout(() => {
250
+ liveTimer = null;
251
+ setLive(buffer.length > 0 ? buffer : null);
252
+ }, 60);
253
+ };
254
+ const clearLive = () => {
255
+ if (liveTimer)
256
+ clearTimeout(liveTimer);
257
+ liveTimer = null;
258
+ setLive(null);
259
+ };
142
260
  const flush = () => {
143
- if (buffer) {
144
- const t = buffer;
261
+ if (buffer.trim()) {
262
+ const t = buffer.trimEnd();
145
263
  push({ kind: 'assistant', text: t });
146
- buffer = '';
147
- setLive(null);
148
264
  }
265
+ buffer = '';
266
+ clearLive();
149
267
  };
150
268
  try {
151
269
  for await (const ev of sessionRef.current.send(text)) {
@@ -158,19 +276,51 @@ export function App({ cwd, auth, profileName, version }) {
158
276
  }
159
277
  else if (ev.type === 'text') {
160
278
  buffer += ev.delta;
161
- setLive(buffer);
279
+ turnText += ev.delta;
280
+ // Flush completed paragraphs into the (markdown-rendered) transcript as they
281
+ // stream — text that scrolls out of the viewport can't be repainted later.
282
+ const cut = streamCut(buffer);
283
+ if (cut > 0) {
284
+ const chunk = buffer.slice(0, cut).trimEnd();
285
+ if (chunk)
286
+ push({ kind: 'assistant', text: chunk });
287
+ buffer = buffer.slice(cut);
288
+ }
289
+ scheduleLive();
162
290
  setTurnChars(c => c + ev.delta.length);
163
291
  }
164
292
  else if (ev.type === 'tool') {
165
- const pretty = prettyTool(ev.name);
166
- if (pretty) {
293
+ const header = formatToolUse(ev.name, ev.input);
294
+ if (header) {
167
295
  flush();
168
- push({ kind: 'tool', name: pretty });
296
+ push({ kind: 'tool', title: header.title, sep: header.sep, arg: header.arg });
297
+ shownToolsRef.current.set(ev.id, { name: ev.name, input: ev.input });
298
+ }
299
+ }
300
+ else if (ev.type === 'tool_result') {
301
+ // Only render results whose call we showed (hidden tools stay hidden).
302
+ const pending = shownToolsRef.current.get(ev.id);
303
+ if (pending) {
304
+ shownToolsRef.current.delete(ev.id);
305
+ flush();
306
+ const view = formatToolResult(ev.output);
307
+ push({ kind: 'tool-result', lines: view.lines, hidden: view.hidden, isError: ev.isError });
308
+ if (!ev.isError)
309
+ pushArticleLinks(pending.name, pending.input, ev.output);
169
310
  }
170
311
  }
171
312
  else if (ev.type === 'result') {
172
313
  flush();
173
314
  push({ kind: 'done', seconds: Math.round((Date.now() - turnStartRef.current) / 1000), tokens: ev.outputTokens, ok: ev.ok });
315
+ // Fire-and-forget ghost-text suggestion; drop it if a newer turn started.
316
+ if (ev.ok && turnText.trim()) {
317
+ void suggestNextAction(text, turnText, cwd)
318
+ .then(s => {
319
+ if (s && ghostSeqRef.current === ghostSeq)
320
+ setGhost(s);
321
+ })
322
+ .catch(() => { });
323
+ }
174
324
  if (tracker.uuid) {
175
325
  touchSession(tracker.uuid);
176
326
  if (!tracker.titleFired) {
@@ -190,9 +340,9 @@ export function App({ cwd, auth, profileName, version }) {
190
340
  }
191
341
  finally {
192
342
  setBusy(false);
193
- setLive(null);
343
+ clearLive();
194
344
  }
195
- }, [cwd, push]);
345
+ }, [cwd, push, pushArticleLinks]);
196
346
  const handleCommand = useCallback(async (line) => {
197
347
  const parts = line.slice(1).trim().split(/\s+/);
198
348
  const name = (parts[0] ?? '').toLowerCase();
@@ -208,7 +358,10 @@ export function App({ cwd, auth, profileName, version }) {
208
358
  return;
209
359
  case 'clear':
210
360
  restartSession();
211
- setItems([]);
361
+ itemsRef.current = []; // fresh transcript model (what's on screen stays in scrollback)
362
+ setStarted(false);
363
+ setGhost(null);
364
+ ghostSeqRef.current++;
212
365
  push({ kind: 'note', tone: 'info', text: 'Conversation reset (the previous session is still resumable via /resume).' });
213
366
  return;
214
367
  case 'allow-prod': {
@@ -308,6 +461,38 @@ export function App({ cwd, auth, profileName, version }) {
308
461
  restartSession();
309
462
  return;
310
463
  }
464
+ case 'preview': {
465
+ const target = args.join(' ').trim();
466
+ if (!target) {
467
+ push({ kind: 'note', tone: 'error', text: 'Usage: /preview <path-to.md | article-id>' });
468
+ return;
469
+ }
470
+ const asPath = isAbsolute(target) ? target : join(cwd, target);
471
+ if (existsSync(asPath)) {
472
+ try {
473
+ push({ kind: 'preview', name: basename(asPath), text: stripFrontmatter(readFileSync(asPath, 'utf8')) });
474
+ }
475
+ catch (e) {
476
+ push({ kind: 'note', tone: 'error', text: `Could not read ${asPath}: ${e.message}` });
477
+ }
478
+ return;
479
+ }
480
+ if (ARTICLE_ID_RE.test(target)) {
481
+ try {
482
+ const active = resolveActiveProfile(cwd, profileName);
483
+ const ctx = { profile: active.name, connection: active.connection };
484
+ const projectId = active.project.projectId ?? resolveProjectId(ctx);
485
+ const article = await getArticle(ctx, projectId, target);
486
+ push({ kind: 'preview', name: article.title ?? target, text: article.content ?? '*(article has no content)*' });
487
+ }
488
+ catch (e) {
489
+ push({ kind: 'note', tone: 'error', text: `Could not fetch article: ${e.message}` });
490
+ }
491
+ return;
492
+ }
493
+ push({ kind: 'note', tone: 'error', text: `"${target}" is neither a file (relative to ${cwd}) nor an article id.` });
494
+ return;
495
+ }
311
496
  case 'publish':
312
497
  case 'audit':
313
498
  case 'screenshot': {
@@ -352,6 +537,13 @@ export function App({ cwd, auth, profileName, version }) {
352
537
  }
353
538
  if (busy)
354
539
  return; // ignore input while the agent is working
540
+ // Tab accepts the ghost suggestion (palette is closed when input is empty).
541
+ if (key.tab && !input && ghost) {
542
+ setInput(ghost);
543
+ setGhost(null);
544
+ ghostSeqRef.current++;
545
+ return;
546
+ }
355
547
  if (paletteOpen) {
356
548
  if (key.upArrow) {
357
549
  setPaletteIndex(i => Math.max(0, i - 1));
@@ -404,36 +596,12 @@ export function App({ cwd, auth, profileName, version }) {
404
596
  if (key.escape) {
405
597
  setInput('');
406
598
  setPaletteIndex(0);
599
+ setGhost(null);
407
600
  return;
408
601
  }
409
602
  if (char && !key.ctrl && !key.meta)
410
603
  setInput(s => s + char);
411
604
  });
412
- return (_jsxs(Box, { flexDirection: "column", width: width, children: [_jsx(Static, { items: items, children: item => _jsx(ItemView, { item: item }, item.id) }), live !== null && (_jsx(Box, { children: _jsx(Text, { children: live }) })), busy && _jsx(Working, { startTime: turnStartRef.current, chars: turnChars }), paletteOpen && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: palette.map((c, i) => (_jsxs(Text, { color: i === paletteIndex ? 'cyan' : 'gray', children: [i === paletteIndex ? '❯ ' : ' ', c.usage.padEnd(22), " ", c.desc] }, c.name))) })), _jsxs(Box, { borderStyle: "round", borderColor: status.prod ? 'yellow' : 'cyan', borderTop: true, borderBottom: true, borderLeft: false, borderRight: false, marginTop: paletteOpen ? 0 : 1, children: [_jsx(Text, { color: "cyan", children: '> ' }), input ? _jsx(Text, { children: input }) : _jsx(Text, { color: "gray", children: "Ask me to write or update an article\u2026" }), _jsx(Text, { color: "gray", children: "\u258F" })] }), _jsx(Box, { paddingX: 1, children: _jsxs(Text, { color: "gray", children: [status.prod ? '⚠ PRODUCTION · ' : '', '/help · ↑ history · ctrl+c exit'] }) })] }));
413
- }
414
- function Row({ label, children }) {
415
- // Fixed-width label column → values align uniformly regardless of label length.
416
- return (_jsxs(Box, { children: [_jsx(Box, { width: 15, flexShrink: 0, children: _jsx(Text, { color: "gray", children: ` ${label}` }) }), children] }));
417
- }
418
- function BannerView({ info }) {
419
- return (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsxs(Box, { children: [_jsx(Text, { color: "cyan", bold: true, children: '✎ document360-writer' }), _jsx(Text, { color: "gray", children: ` v${info.version}` })] }), _jsx(Text, { color: "gray", children: ' Reads your code, writes your docs.' }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Row, { label: "Claude:", children: _jsx(Text, { children: info.claude }) }), _jsx(Row, { label: "Document360:", children: info.loggedOut ? _jsx(Text, { color: "yellow", children: "not logged in \u2014 run: d360-writer login" }) : _jsx(Text, { children: info.who }) }), _jsxs(Row, { label: "Profile:", children: [_jsx(Text, { children: info.profile }), _jsx(Text, { color: "gray", children: ` (${info.apiUrl})` }), info.prod && _jsx(Text, { color: "yellow", bold: true, children: ' ⚠ PRODUCTION' })] }), _jsx(Row, { label: "Project:", children: _jsx(Text, { children: info.project }) }), _jsx(Row, { label: "cwd:", children: _jsx(Text, { color: "gray", children: info.cwd }) })] })] }));
420
- }
421
- function ItemView({ item }) {
422
- switch (item.kind) {
423
- case 'banner':
424
- return _jsx(BannerView, { info: item.info });
425
- case 'user':
426
- return (_jsxs(Box, { children: [_jsx(Text, { color: "cyan", children: '❯ ' }), _jsx(Text, { children: item.text })] }));
427
- case 'assistant':
428
- return (_jsx(Box, { marginBottom: 1, children: _jsx(Markdown, { text: item.text }) }));
429
- case 'tool':
430
- return _jsx(Text, { color: "gray", children: ` ⚙ ${item.name}` });
431
- case 'note': {
432
- const color = item.tone === 'error' ? 'red' : item.tone === 'warn' ? 'yellow' : item.tone === 'ok' ? 'green' : 'gray';
433
- return _jsx(Text, { color: color, children: item.text });
434
- }
435
- case 'done':
436
- return (_jsxs(Box, { marginTop: 1, marginBottom: 1, children: [_jsx(Text, { color: item.ok ? 'magenta' : 'red', children: '✶ ' }), _jsx(Text, { color: "gray", children: `Cooked for ${formatDuration(item.seconds)} · ${item.tokens} tokens` })] }));
437
- }
605
+ return (_jsxs(Box, { flexDirection: "column", width: width, children: [liveView !== null && (_jsxs(Box, { marginTop: 1, flexDirection: "column", children: [liveView.truncated && _jsx(Text, { dimColor: true, children: '…' }), _jsx(Text, { children: liveView.text })] })), busy && _jsx(Working, { startTime: turnStartRef.current, chars: turnChars }), paletteOpen && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: palette.map((c, i) => (_jsxs(Text, { color: i === paletteIndex ? 'cyan' : 'gray', children: [i === paletteIndex ? '❯ ' : ' ', c.usage.padEnd(22), " ", c.desc] }, c.name))) })), _jsxs(Box, { borderStyle: "round", borderColor: status.prod ? 'yellow' : 'cyan', borderTop: true, borderBottom: true, borderLeft: false, borderRight: false, marginTop: paletteOpen ? 0 : 1, children: [_jsx(Text, { color: "cyan", children: '> ' }), input ? (_jsxs(_Fragment, { children: [_jsx(Text, { children: input }), _jsx(Cursor, { ch: " " })] })) : ghost && !busy ? (_jsxs(_Fragment, { children: [_jsx(Cursor, { ch: ghost[0], dim: true }), _jsx(Text, { color: "gray", children: ghost.slice(1) }), _jsx(Text, { dimColor: true, children: ' (tab)' })] })) : started ? (_jsx(Cursor, { ch: " " })) : (_jsxs(_Fragment, { children: [_jsx(Cursor, { ch: PLACEHOLDER[0], dim: true }), _jsx(Text, { color: "gray", children: PLACEHOLDER.slice(1) })] }))] }), _jsx(Box, { paddingX: 1, children: _jsxs(Text, { color: "gray", children: [status.prod ? '⚠ PRODUCTION · ' : '', '/help · ↑ history · ctrl+c exit'] }) })] }));
438
606
  }
439
607
  //# sourceMappingURL=App.js.map