open-research 0.1.19 → 0.1.20

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 (2) hide show
  1. package/dist/cli.js +83 -15
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -811,7 +811,7 @@ function formatDateTime(value) {
811
811
  }
812
812
 
813
813
  // src/lib/cli/version.ts
814
- var PACKAGE_VERSION = "0.1.19";
814
+ var PACKAGE_VERSION = "0.1.20";
815
815
  function getPackageVersion() {
816
816
  return PACKAGE_VERSION;
817
817
  }
@@ -877,13 +877,13 @@ import {
877
877
  useDeferredValue,
878
878
  useEffect as useEffect2,
879
879
  useMemo as useMemo3,
880
- useRef,
880
+ useRef as useRef2,
881
881
  useState as useState4
882
882
  } from "react";
883
883
  import { Box as Box5, Text as Text5, useApp, useInput as useInput4 } from "ink";
884
884
 
885
885
  // src/tui/text-input.tsx
886
- import { useState, useEffect } from "react";
886
+ import { useState, useEffect, useRef } from "react";
887
887
  import { Box, Text, useInput } from "ink";
888
888
 
889
889
  // node_modules/chalk/source/vendor/ansi-styles/index.js
@@ -1383,6 +1383,22 @@ var source_default = chalk;
1383
1383
 
1384
1384
  // src/tui/text-input.tsx
1385
1385
  import { jsx } from "react/jsx-runtime";
1386
+ var PASTE_MARKER = "\uFFFC";
1387
+ function expandPasteMarkers(value, pasteMap) {
1388
+ let result = "";
1389
+ let pasteIdx = 0;
1390
+ const ids = [...pasteMap.keys()].sort((a, b) => a - b);
1391
+ for (const char of value) {
1392
+ if (char === PASTE_MARKER && pasteIdx < ids.length) {
1393
+ const entry = pasteMap.get(ids[pasteIdx]);
1394
+ result += entry?.text ?? "";
1395
+ pasteIdx++;
1396
+ } else {
1397
+ result += char;
1398
+ }
1399
+ }
1400
+ return result;
1401
+ }
1386
1402
  function prevWordBoundary(value, cursor) {
1387
1403
  let i = cursor;
1388
1404
  while (i > 0 && /\s/.test(value[i - 1])) i--;
@@ -1408,6 +1424,8 @@ function TextInput({
1408
1424
  cursorToEnd = 0
1409
1425
  }) {
1410
1426
  const [cursorOffset, setCursorOffset] = useState(originalValue.length);
1427
+ const pasteMapRef = useRef(/* @__PURE__ */ new Map());
1428
+ const pasteCounterRef = useRef(0);
1411
1429
  useEffect(() => {
1412
1430
  if (!focus || !showCursor) return;
1413
1431
  if (cursorOffset > originalValue.length) {
@@ -1419,25 +1437,55 @@ function TextInput({
1419
1437
  setCursorOffset(originalValue.length);
1420
1438
  }
1421
1439
  }, [cursorToEnd]);
1440
+ useEffect(() => {
1441
+ if (originalValue === "") {
1442
+ pasteMapRef.current.clear();
1443
+ }
1444
+ }, [originalValue]);
1445
+ function pasteBadge(entry) {
1446
+ return source_default.dim.cyan(`[Pasted text #${entry.id} +${entry.lineCount} lines]`);
1447
+ }
1422
1448
  function buildRendered() {
1423
1449
  if (showCursor && focus) {
1424
1450
  if (originalValue.length === 0) return source_default.inverse(" ");
1425
- let result = "";
1451
+ const pasteIds2 = [...pasteMapRef.current.keys()].sort((a, b) => a - b);
1452
+ let pasteIdx2 = 0;
1453
+ let result2 = "";
1426
1454
  let i = 0;
1427
1455
  for (const char of originalValue) {
1428
- if (i === cursorOffset) {
1429
- result += char === "\n" ? source_default.inverse(" ") + "\n" : source_default.inverse(char);
1456
+ if (char === PASTE_MARKER) {
1457
+ const entry = pasteIdx2 < pasteIds2.length ? pasteMapRef.current.get(pasteIds2[pasteIdx2]) : void 0;
1458
+ pasteIdx2++;
1459
+ if (i === cursorOffset) {
1460
+ result2 += entry ? pasteBadge(entry) + source_default.inverse(" ") : source_default.inverse(" ");
1461
+ } else {
1462
+ result2 += entry ? pasteBadge(entry) : "";
1463
+ }
1464
+ } else if (i === cursorOffset) {
1465
+ result2 += char === "\n" ? source_default.inverse(" ") + "\n" : source_default.inverse(char);
1430
1466
  } else {
1431
- result += char;
1467
+ result2 += char;
1432
1468
  }
1433
1469
  i++;
1434
1470
  }
1435
1471
  if (cursorOffset === originalValue.length) {
1436
- result += source_default.inverse(" ");
1472
+ result2 += source_default.inverse(" ");
1473
+ }
1474
+ return result2;
1475
+ }
1476
+ let result = "";
1477
+ const pasteIds = [...pasteMapRef.current.keys()].sort((a, b) => a - b);
1478
+ let pasteIdx = 0;
1479
+ for (const char of originalValue) {
1480
+ if (char === PASTE_MARKER) {
1481
+ const entry = pasteIdx < pasteIds.length ? pasteMapRef.current.get(pasteIds[pasteIdx]) : void 0;
1482
+ pasteIdx++;
1483
+ result += entry ? pasteBadge(entry) : "";
1484
+ } else {
1485
+ result += char;
1437
1486
  }
1438
- return result;
1439
1487
  }
1440
- return originalValue;
1488
+ return result;
1441
1489
  }
1442
1490
  const renderedPlaceholder = showCursor && focus && placeholder.length > 0 ? source_default.inverse(placeholder[0]) + source_default.grey(placeholder.slice(1)) : placeholder ? source_default.grey(placeholder) : void 0;
1443
1491
  useInput(
@@ -1464,7 +1512,8 @@ function TextInput({
1464
1512
  return;
1465
1513
  }
1466
1514
  if (key.return) {
1467
- onSubmit?.(originalValue);
1515
+ const expanded = expandPasteMarkers(originalValue, pasteMapRef.current);
1516
+ onSubmit?.(expanded);
1468
1517
  return;
1469
1518
  }
1470
1519
  let nextValue = originalValue;
@@ -1483,6 +1532,17 @@ function TextInput({
1483
1532
  nextValue = originalValue.slice(0, cursorOffset) + originalValue.slice(boundary);
1484
1533
  } else if (key.backspace || key.delete) {
1485
1534
  if (cursorOffset > 0) {
1535
+ const deletedChar = originalValue[cursorOffset - 1];
1536
+ if (deletedChar === PASTE_MARKER) {
1537
+ let markerIndex = 0;
1538
+ for (let ci = 0; ci < cursorOffset - 1; ci++) {
1539
+ if (originalValue[ci] === PASTE_MARKER) markerIndex++;
1540
+ }
1541
+ const ids = [...pasteMapRef.current.keys()].sort((a, b) => a - b);
1542
+ if (markerIndex < ids.length) {
1543
+ pasteMapRef.current.delete(ids[markerIndex]);
1544
+ }
1545
+ }
1486
1546
  nextValue = originalValue.slice(0, cursorOffset - 1) + originalValue.slice(cursorOffset);
1487
1547
  nextCursor--;
1488
1548
  }
@@ -1501,8 +1561,16 @@ function TextInput({
1501
1561
  } else if (!key.ctrl && !key.meta) {
1502
1562
  const clean = input2.replace(/\x1b\[[?>=!]*[0-9;]*[a-zA-Z~]/g, "").replace(/\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)?/g, "").replace(/\[20[01]~/g, "").replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/[\x00-\x08\x0b\x0c\x0e-\x1f]/g, "");
1503
1563
  if (clean) {
1504
- nextValue = originalValue.slice(0, cursorOffset) + clean + originalValue.slice(cursorOffset);
1505
- nextCursor += clean.length;
1564
+ const lineCount = (clean.match(/\n/g) || []).length;
1565
+ if (lineCount >= 2) {
1566
+ const id = ++pasteCounterRef.current;
1567
+ pasteMapRef.current.set(id, { text: clean, lineCount, id });
1568
+ nextValue = originalValue.slice(0, cursorOffset) + PASTE_MARKER + originalValue.slice(cursorOffset);
1569
+ nextCursor += 1;
1570
+ } else {
1571
+ nextValue = originalValue.slice(0, cursorOffset) + clean + originalValue.slice(cursorOffset);
1572
+ nextCursor += clean.length;
1573
+ }
1506
1574
  }
1507
1575
  }
1508
1576
  nextCursor = Math.max(0, Math.min(nextCursor, nextValue.length));
@@ -6901,7 +6969,7 @@ function App({
6901
6969
  homeDir
6902
6970
  }) {
6903
6971
  const app = useApp();
6904
- const abortRef = useRef(null);
6972
+ const abortRef = useRef2(null);
6905
6973
  const [input2, setInput] = useState4("");
6906
6974
  const [composerFocused, setComposerFocused] = useState4(true);
6907
6975
  const [busy, setBusy] = useState4(false);
@@ -6933,7 +7001,7 @@ function App({
6933
7001
  const deferredPendingUpdates = useDeferredValue(pendingUpdates);
6934
7002
  const activityFrame = useAnimatedFrame(busy);
6935
7003
  const [agentQuestion, setAgentQuestion] = useState4(null);
6936
- const previewRef = useRef(null);
7004
+ const previewRef = useRef2(null);
6937
7005
  const isHome = deferredMessages.length === 0 && !busy;
6938
7006
  const hasWorkspace = workspacePath !== null;
6939
7007
  const hasAuth = authStatus === "connected";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-research",
3
- "version": "0.1.19",
3
+ "version": "0.1.20",
4
4
  "description": "Local-first research CLI agent — discover papers, synthesize notes, run analysis, and draft artifacts from your terminal.",
5
5
  "type": "module",
6
6
  "license": "MIT",