open-research 0.1.18 → 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.
- package/dist/cli.js +128 -18
- 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.
|
|
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
|
-
|
|
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 (
|
|
1429
|
-
|
|
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
|
-
|
|
1467
|
+
result2 += char;
|
|
1432
1468
|
}
|
|
1433
1469
|
i++;
|
|
1434
1470
|
}
|
|
1435
1471
|
if (cursorOffset === originalValue.length) {
|
|
1436
|
-
|
|
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
|
|
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
|
-
|
|
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
|
}
|
|
@@ -1499,10 +1559,18 @@ function TextInput({
|
|
|
1499
1559
|
} else if (key.rightArrow) {
|
|
1500
1560
|
if (showCursor) nextCursor++;
|
|
1501
1561
|
} else if (!key.ctrl && !key.meta) {
|
|
1502
|
-
const clean = input2.replace(/\x1b\[[?>=!]*[0-9;]*[a-zA-Z]/g, "").replace(/[\x00-\x08\x0e-\x1f]/g, "");
|
|
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
|
-
|
|
1505
|
-
|
|
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));
|
|
@@ -6350,7 +6418,7 @@ var SLASH_COMMANDS = [
|
|
|
6350
6418
|
{ name: "btw", aliases: ["/aside"], description: "Ask a side question without affecting the main conversation", category: "session" },
|
|
6351
6419
|
{ name: "export", aliases: [], description: "Export conversation as markdown to a file", category: "session" },
|
|
6352
6420
|
{ name: "diff", aliases: ["/changes"], description: "Show files the agent has changed in this session", category: "workspace" },
|
|
6353
|
-
{ name: "api-keys", aliases: ["/keys"], description: "Set API keys for Semantic Scholar, OpenAlex
|
|
6421
|
+
{ name: "api-keys", aliases: ["/keys"], description: "Set API keys for Semantic Scholar, OpenAlex", category: "system" },
|
|
6354
6422
|
{ name: "doctor", aliases: [], description: "Diagnose auth, connectivity, and tool availability", category: "system" },
|
|
6355
6423
|
{ name: "preview", aliases: [], description: "Live preview a LaTeX file in browser (e.g. /preview papers/draft.tex)", category: "workspace" },
|
|
6356
6424
|
{ name: "memory", aliases: ["/memories"], description: "View or clear stored memories about you", category: "system" },
|
|
@@ -6369,8 +6437,50 @@ function matchSlashCommand(input2) {
|
|
|
6369
6437
|
}
|
|
6370
6438
|
return null;
|
|
6371
6439
|
}
|
|
6440
|
+
var SUBCOMMAND_HINTS = {
|
|
6441
|
+
"api-keys": [
|
|
6442
|
+
{ name: "api-keys semantic-scholar <key>", description: "Set your Semantic Scholar API key" },
|
|
6443
|
+
{ name: "api-keys openalex <key>", description: "Set your OpenAlex API key" }
|
|
6444
|
+
],
|
|
6445
|
+
"config": [
|
|
6446
|
+
{ name: "config theme dark|light", description: "Set color theme" },
|
|
6447
|
+
{ name: "config auto-approve on|off", description: "Toggle auto-approve mode" }
|
|
6448
|
+
],
|
|
6449
|
+
"memory": [
|
|
6450
|
+
{ name: "memory clear", description: "Clear all global memories" },
|
|
6451
|
+
{ name: "memory clear project", description: "Clear project memories" },
|
|
6452
|
+
{ name: "memory clear all", description: "Clear everything" },
|
|
6453
|
+
{ name: "memory delete <id>", description: "Delete a specific memory" }
|
|
6454
|
+
],
|
|
6455
|
+
"compact": [
|
|
6456
|
+
{ name: "compact", description: "Compress conversation (auto-selects what to keep)" },
|
|
6457
|
+
{ name: "compact keep the statistical findings", description: "Compress but prioritize specific content" }
|
|
6458
|
+
],
|
|
6459
|
+
"export": [
|
|
6460
|
+
{ name: "export", description: "Export to conversation-export.md" },
|
|
6461
|
+
{ name: "export <filename>", description: "Export to a specific file" }
|
|
6462
|
+
],
|
|
6463
|
+
"preview": [
|
|
6464
|
+
{ name: "preview <path-to-tex>", description: "Live preview a LaTeX file in browser" }
|
|
6465
|
+
]
|
|
6466
|
+
};
|
|
6372
6467
|
function getUnifiedSuggestions(partial, allSkills) {
|
|
6373
6468
|
if (!partial.startsWith("/")) return [];
|
|
6469
|
+
if (partial.includes(" ")) {
|
|
6470
|
+
const spaceIdx = partial.indexOf(" ");
|
|
6471
|
+
const cmdPart = partial.slice(1, spaceIdx).toLowerCase();
|
|
6472
|
+
const hints = SUBCOMMAND_HINTS[cmdPart];
|
|
6473
|
+
if (hints) {
|
|
6474
|
+
const argPart = partial.slice(spaceIdx + 1).toLowerCase();
|
|
6475
|
+
const filtered = argPart ? hints.filter((h) => h.name.toLowerCase().includes(argPart)) : hints;
|
|
6476
|
+
return filtered.map((h) => ({
|
|
6477
|
+
kind: "command",
|
|
6478
|
+
name: h.name,
|
|
6479
|
+
description: h.description
|
|
6480
|
+
}));
|
|
6481
|
+
}
|
|
6482
|
+
return [];
|
|
6483
|
+
}
|
|
6374
6484
|
const search = partial.slice(1).toLowerCase();
|
|
6375
6485
|
if (!search) {
|
|
6376
6486
|
const cmds = SLASH_COMMANDS.map((c) => ({
|
|
@@ -6859,7 +6969,7 @@ function App({
|
|
|
6859
6969
|
homeDir
|
|
6860
6970
|
}) {
|
|
6861
6971
|
const app = useApp();
|
|
6862
|
-
const abortRef =
|
|
6972
|
+
const abortRef = useRef2(null);
|
|
6863
6973
|
const [input2, setInput] = useState4("");
|
|
6864
6974
|
const [composerFocused, setComposerFocused] = useState4(true);
|
|
6865
6975
|
const [busy, setBusy] = useState4(false);
|
|
@@ -6891,7 +7001,7 @@ function App({
|
|
|
6891
7001
|
const deferredPendingUpdates = useDeferredValue(pendingUpdates);
|
|
6892
7002
|
const activityFrame = useAnimatedFrame(busy);
|
|
6893
7003
|
const [agentQuestion, setAgentQuestion] = useState4(null);
|
|
6894
|
-
const previewRef =
|
|
7004
|
+
const previewRef = useRef2(null);
|
|
6895
7005
|
const isHome = deferredMessages.length === 0 && !busy;
|
|
6896
7006
|
const hasWorkspace = workspacePath !== null;
|
|
6897
7007
|
const hasAuth = authStatus === "connected";
|
|
@@ -6950,7 +7060,7 @@ function App({
|
|
|
6950
7060
|
if (atMention) {
|
|
6951
7061
|
return getFileSuggestions(atMention.partial, workspaceFiles);
|
|
6952
7062
|
}
|
|
6953
|
-
if (!input2.startsWith("/")
|
|
7063
|
+
if (!input2.startsWith("/")) return [];
|
|
6954
7064
|
return getUnifiedSuggestions(input2, skills2);
|
|
6955
7065
|
}, [input2, skills2, atMention, workspaceFiles]);
|
|
6956
7066
|
useEffect2(() => {
|
package/package.json
CHANGED