open-research 0.1.22 → 0.1.23
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 +79 -13
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -8,7 +8,7 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
8
8
|
|
|
9
9
|
// src/cli.ts
|
|
10
10
|
import React5 from "react";
|
|
11
|
-
import
|
|
11
|
+
import path22 from "path";
|
|
12
12
|
import { Command } from "commander";
|
|
13
13
|
import { render } from "ink";
|
|
14
14
|
|
|
@@ -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.23";
|
|
815
815
|
function getPackageVersion() {
|
|
816
816
|
return PACKAGE_VERSION;
|
|
817
817
|
}
|
|
@@ -871,7 +871,7 @@ async function ensureOpenResearchConfig(options) {
|
|
|
871
871
|
}
|
|
872
872
|
|
|
873
873
|
// src/tui/app.tsx
|
|
874
|
-
import
|
|
874
|
+
import path21 from "path";
|
|
875
875
|
import {
|
|
876
876
|
startTransition,
|
|
877
877
|
useDeferredValue,
|
|
@@ -1502,7 +1502,7 @@ function TextInput({
|
|
|
1502
1502
|
}
|
|
1503
1503
|
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;
|
|
1504
1504
|
function sanitizeInput(raw) {
|
|
1505
|
-
return raw.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, "");
|
|
1505
|
+
return raw.replace(/\x1b\[[?>=!]*[0-9;]*[a-zA-Z~]/g, "").replace(/\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)?/g, "").replace(/\[20[01]~/g, "").replace(/\d+;\d+;\d+[~u]/g, "").replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/[\x00-\x08\x0b\x0c\x0e-\x1f]/g, "");
|
|
1506
1506
|
}
|
|
1507
1507
|
function insertCleanText(raw, currentValue, currentCursor) {
|
|
1508
1508
|
const clean = sanitizeInput(raw);
|
|
@@ -1542,7 +1542,7 @@ function TextInput({
|
|
|
1542
1542
|
onTab?.();
|
|
1543
1543
|
return;
|
|
1544
1544
|
}
|
|
1545
|
-
if (key.return && key.shift || key.return && key.meta) {
|
|
1545
|
+
if (key.return && key.shift || key.return && key.meta || input2 === "27;2;13~" || input2.includes("27;2;13")) {
|
|
1546
1546
|
const inserted = currentValue.slice(0, currentCursor) + "\n" + currentValue.slice(currentCursor);
|
|
1547
1547
|
cursorOffsetRef.current = currentCursor + 1;
|
|
1548
1548
|
valueRef.current = inserted;
|
|
@@ -5414,6 +5414,7 @@ ${skill.prompt}`).join("\n\n");
|
|
|
5414
5414
|
"- Be transparent. Show the user what you're doing and why.",
|
|
5415
5415
|
"- When unsure, ask. Use ask_user rather than guessing.",
|
|
5416
5416
|
"- For large outputs, redirect to a file and read selectively.",
|
|
5417
|
+
"- Always wrap file paths in backticks when mentioning them, e.g. `notes/brief.md` or `experiments/analysis.py`. This makes them clickable in the terminal.",
|
|
5417
5418
|
"",
|
|
5418
5419
|
`## Workspace
|
|
5419
5420
|
Root: ${process.cwd()}
|
|
@@ -6616,6 +6617,66 @@ function truncate3(value, max = 96) {
|
|
|
6616
6617
|
import { Box as Box4, Text as Text4 } from "ink";
|
|
6617
6618
|
|
|
6618
6619
|
// src/tui/markdown.ts
|
|
6620
|
+
import path20 from "path";
|
|
6621
|
+
import fs21 from "fs";
|
|
6622
|
+
var FILE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
6623
|
+
".py",
|
|
6624
|
+
".ts",
|
|
6625
|
+
".tsx",
|
|
6626
|
+
".js",
|
|
6627
|
+
".jsx",
|
|
6628
|
+
".r",
|
|
6629
|
+
".R",
|
|
6630
|
+
".tex",
|
|
6631
|
+
".bib",
|
|
6632
|
+
".md",
|
|
6633
|
+
".txt",
|
|
6634
|
+
".json",
|
|
6635
|
+
".yaml",
|
|
6636
|
+
".yml",
|
|
6637
|
+
".toml",
|
|
6638
|
+
".csv",
|
|
6639
|
+
".tsv",
|
|
6640
|
+
".sh",
|
|
6641
|
+
".bash",
|
|
6642
|
+
".zsh",
|
|
6643
|
+
".sql",
|
|
6644
|
+
".html",
|
|
6645
|
+
".css",
|
|
6646
|
+
".xml",
|
|
6647
|
+
".pdf",
|
|
6648
|
+
".png",
|
|
6649
|
+
".jpg",
|
|
6650
|
+
".svg",
|
|
6651
|
+
".gif",
|
|
6652
|
+
".cfg",
|
|
6653
|
+
".ini",
|
|
6654
|
+
".env",
|
|
6655
|
+
".lock",
|
|
6656
|
+
".log"
|
|
6657
|
+
]);
|
|
6658
|
+
function looksLikeFilePath(text) {
|
|
6659
|
+
if (text.length < 3 || text.length > 200) return false;
|
|
6660
|
+
if (text.includes(" ") || text.includes("\n")) return false;
|
|
6661
|
+
const ext = path20.extname(text).toLowerCase();
|
|
6662
|
+
if (FILE_EXTENSIONS.has(ext)) return true;
|
|
6663
|
+
if (text.includes("/") && !text.startsWith("http")) return true;
|
|
6664
|
+
return false;
|
|
6665
|
+
}
|
|
6666
|
+
function resolveFilePath(filePath) {
|
|
6667
|
+
if (path20.isAbsolute(filePath)) return filePath;
|
|
6668
|
+
return path20.resolve(process.cwd(), filePath);
|
|
6669
|
+
}
|
|
6670
|
+
function fileLink(displayText, filePath) {
|
|
6671
|
+
const absPath = resolveFilePath(filePath);
|
|
6672
|
+
try {
|
|
6673
|
+
fs21.statSync(absPath);
|
|
6674
|
+
} catch {
|
|
6675
|
+
return displayText;
|
|
6676
|
+
}
|
|
6677
|
+
const uri = `file://${absPath}`;
|
|
6678
|
+
return `\x1B]8;;${uri}\x1B\\${displayText}\x1B]8;;\x1B\\`;
|
|
6679
|
+
}
|
|
6619
6680
|
function renderMarkdown(text) {
|
|
6620
6681
|
if (!text || !text.trim()) return text;
|
|
6621
6682
|
if (!/[*_`#\[\]>~\-]/.test(text) && !text.includes("```")) return text;
|
|
@@ -6698,7 +6759,12 @@ function renderMarkdown(text) {
|
|
|
6698
6759
|
}
|
|
6699
6760
|
function renderInline(text) {
|
|
6700
6761
|
let result = text;
|
|
6701
|
-
result = result.replace(/`([^`]+)`/g, (_, code) =>
|
|
6762
|
+
result = result.replace(/`([^`]+)`/g, (_, code) => {
|
|
6763
|
+
if (looksLikeFilePath(code)) {
|
|
6764
|
+
return fileLink(source_default.cyan.underline(code), code);
|
|
6765
|
+
}
|
|
6766
|
+
return source_default.cyan(code);
|
|
6767
|
+
});
|
|
6702
6768
|
result = result.replace(/\*\*\*(.+?)\*\*\*/g, (_, t) => source_default.bold.italic(t));
|
|
6703
6769
|
result = result.replace(/___(.+?)___/g, (_, t) => source_default.bold.italic(t));
|
|
6704
6770
|
result = result.replace(/\*\*(.+?)\*\*/g, (_, t) => source_default.bold(t));
|
|
@@ -8305,7 +8371,7 @@ ${error.stack}` : String(error)}` }
|
|
|
8305
8371
|
statusParts,
|
|
8306
8372
|
statusColor,
|
|
8307
8373
|
tokenDisplay,
|
|
8308
|
-
workspaceName: hasWorkspace ?
|
|
8374
|
+
workspaceName: hasWorkspace ? path21.basename(workspacePath) : process.cwd(),
|
|
8309
8375
|
mode: agentMode,
|
|
8310
8376
|
planningStatus: planningState.status
|
|
8311
8377
|
}
|
|
@@ -8317,7 +8383,7 @@ ${error.stack}` : String(error)}` }
|
|
|
8317
8383
|
var program = new Command();
|
|
8318
8384
|
program.name("open-research").version(getPackageVersion()).description("Local-first research CLI powered by ChatGPT/Codex auth.").argument("[workspacePath]", "Optional workspace path to open").action(async (workspacePath) => {
|
|
8319
8385
|
await ensureOpenResearchConfig();
|
|
8320
|
-
const target = workspacePath ?
|
|
8386
|
+
const target = workspacePath ? path22.resolve(workspacePath) : process.cwd();
|
|
8321
8387
|
const project = await loadWorkspaceProject(target);
|
|
8322
8388
|
const auth2 = await loadStoredAuth();
|
|
8323
8389
|
render(
|
|
@@ -8333,7 +8399,7 @@ program.name("open-research").version(getPackageVersion()).description("Local-fi
|
|
|
8333
8399
|
});
|
|
8334
8400
|
program.command("init").argument("[workspacePath]").description("Initialize an Open Research workspace.").action(async (workspacePath) => {
|
|
8335
8401
|
await ensureOpenResearchConfig();
|
|
8336
|
-
const target =
|
|
8402
|
+
const target = path22.resolve(workspacePath ?? process.cwd());
|
|
8337
8403
|
const project = await initWorkspace({ workspaceDir: target });
|
|
8338
8404
|
console.log(`Initialized workspace: ${target}`);
|
|
8339
8405
|
console.log(`Title: ${project.title}`);
|
|
@@ -8402,8 +8468,8 @@ skills.command("create").argument("[name]").description("Scaffold a new user ski
|
|
|
8402
8468
|
});
|
|
8403
8469
|
skills.command("edit").argument("<name>").description("Open a user skill in $EDITOR.").action(async (name) => {
|
|
8404
8470
|
await ensureOpenResearchConfig();
|
|
8405
|
-
const skillDir =
|
|
8406
|
-
openInEditor(
|
|
8471
|
+
const skillDir = path22.join(getOpenResearchSkillsDir(), name);
|
|
8472
|
+
openInEditor(path22.join(skillDir, "SKILL.md"));
|
|
8407
8473
|
const validation = await validateSkillDirectory({ skillDir });
|
|
8408
8474
|
if (!validation.ok) {
|
|
8409
8475
|
console.error(validation.errors.join("\n"));
|
|
@@ -8414,9 +8480,9 @@ skills.command("edit").argument("<name>").description("Open a user skill in $EDI
|
|
|
8414
8480
|
});
|
|
8415
8481
|
skills.command("validate").argument("[nameOrPath]").description("Validate one user skill.").action(async (nameOrPath) => {
|
|
8416
8482
|
await ensureOpenResearchConfig();
|
|
8417
|
-
const skillDir = nameOrPath ?
|
|
8483
|
+
const skillDir = nameOrPath ? path22.isAbsolute(nameOrPath) ? nameOrPath : path22.join(getOpenResearchSkillsDir(), nameOrPath) : getOpenResearchSkillsDir();
|
|
8418
8484
|
const stat = await import("fs/promises").then(
|
|
8419
|
-
(
|
|
8485
|
+
(fs22) => fs22.stat(skillDir).catch(() => null)
|
|
8420
8486
|
);
|
|
8421
8487
|
if (!stat) {
|
|
8422
8488
|
throw new Error(`Skill path not found: ${skillDir}`);
|
package/package.json
CHANGED