open-research 0.1.16 → 0.1.18
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 +141 -40
- 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.18";
|
|
815
815
|
function getPackageVersion() {
|
|
816
816
|
return PACKAGE_VERSION;
|
|
817
817
|
}
|
|
@@ -827,7 +827,11 @@ var openResearchConfigSchema = z.object({
|
|
|
827
827
|
editPolicy: z.literal("mixed")
|
|
828
828
|
}),
|
|
829
829
|
theme: z.enum(themeValues).default("dark"),
|
|
830
|
-
lastWorkspace: z.string().nullable()
|
|
830
|
+
lastWorkspace: z.string().nullable(),
|
|
831
|
+
apiKeys: z.object({
|
|
832
|
+
semanticScholar: z.string().optional(),
|
|
833
|
+
openAlex: z.string().optional()
|
|
834
|
+
}).optional()
|
|
831
835
|
});
|
|
832
836
|
var DEFAULT_OPEN_RESEARCH_CONFIG = {
|
|
833
837
|
version: 1,
|
|
@@ -837,8 +841,15 @@ var DEFAULT_OPEN_RESEARCH_CONFIG = {
|
|
|
837
841
|
editPolicy: "mixed"
|
|
838
842
|
},
|
|
839
843
|
theme: "dark",
|
|
840
|
-
lastWorkspace: null
|
|
844
|
+
lastWorkspace: null,
|
|
845
|
+
apiKeys: {}
|
|
841
846
|
};
|
|
847
|
+
function getSemanticScholarApiKey(config) {
|
|
848
|
+
return config?.apiKeys?.semanticScholar || process.env.SEMANTIC_SCHOLAR_API_KEY;
|
|
849
|
+
}
|
|
850
|
+
function getOpenAlexApiKey(config) {
|
|
851
|
+
return config?.apiKeys?.openAlex || process.env.OPENALEX_API_KEY;
|
|
852
|
+
}
|
|
842
853
|
async function loadOpenResearchConfig(options) {
|
|
843
854
|
const configFile = getOpenResearchConfigFile(options);
|
|
844
855
|
const config = await readJsonFile(configFile, null);
|
|
@@ -1475,9 +1486,9 @@ function TextInput({
|
|
|
1475
1486
|
nextValue = originalValue.slice(0, cursorOffset - 1) + originalValue.slice(cursorOffset);
|
|
1476
1487
|
nextCursor--;
|
|
1477
1488
|
}
|
|
1478
|
-
} else if (key.meta && key.leftArrow) {
|
|
1489
|
+
} else if (key.meta && key.leftArrow || key.meta && input2 === "b" || key.ctrl && key.leftArrow) {
|
|
1479
1490
|
nextCursor = prevWordBoundary(originalValue, cursorOffset);
|
|
1480
|
-
} else if (key.meta && key.rightArrow) {
|
|
1491
|
+
} else if (key.meta && key.rightArrow || key.meta && input2 === "f" || key.ctrl && key.rightArrow) {
|
|
1481
1492
|
nextCursor = nextWordBoundary(originalValue, cursorOffset);
|
|
1482
1493
|
} else if (key.ctrl && input2 === "a" || key.home) {
|
|
1483
1494
|
nextCursor = 0;
|
|
@@ -2187,12 +2198,27 @@ var TOOL_SCHEMAS = [
|
|
|
2187
2198
|
type: "function",
|
|
2188
2199
|
function: {
|
|
2189
2200
|
name: "search_external_sources",
|
|
2190
|
-
description: "Search OpenAlex, Semantic Scholar, and arXiv for academic papers.",
|
|
2201
|
+
description: "Search OpenAlex, Semantic Scholar, and arXiv for academic papers. Provide one or more search queries. The first query is the primary search; additional queries are variations to broaden coverage.",
|
|
2191
2202
|
parameters: {
|
|
2192
2203
|
type: "object",
|
|
2193
2204
|
properties: {
|
|
2194
|
-
searches: {
|
|
2195
|
-
|
|
2205
|
+
searches: {
|
|
2206
|
+
type: "array",
|
|
2207
|
+
items: {
|
|
2208
|
+
type: "object",
|
|
2209
|
+
properties: {
|
|
2210
|
+
query: { type: "string", description: "The search query string." },
|
|
2211
|
+
intent: { type: "string", description: "Brief description of what you're looking for with this query." }
|
|
2212
|
+
},
|
|
2213
|
+
required: ["query"],
|
|
2214
|
+
additionalProperties: false
|
|
2215
|
+
},
|
|
2216
|
+
description: "Array of search queries. First is primary, rest are variations."
|
|
2217
|
+
},
|
|
2218
|
+
num_results: {
|
|
2219
|
+
type: "number",
|
|
2220
|
+
description: "Maximum number of results to return. Default: 8."
|
|
2221
|
+
}
|
|
2196
2222
|
},
|
|
2197
2223
|
required: ["searches"],
|
|
2198
2224
|
additionalProperties: false
|
|
@@ -4355,11 +4381,14 @@ async function executeSearchExternalSources(args, ctx) {
|
|
|
4355
4381
|
}
|
|
4356
4382
|
const primary = searches[0];
|
|
4357
4383
|
const variations = searches.slice(1).map((item) => item.query);
|
|
4384
|
+
const config = await loadOpenResearchConfig().catch(() => null);
|
|
4358
4385
|
const results = await discoverScholarlySources({
|
|
4359
4386
|
query: primary.query,
|
|
4360
4387
|
queryVariations: variations,
|
|
4361
4388
|
numResults: args.num_results ?? 8,
|
|
4362
|
-
filters: ctx.searchFilters
|
|
4389
|
+
filters: ctx.searchFilters,
|
|
4390
|
+
semanticScholarApiKey: getSemanticScholarApiKey(config),
|
|
4391
|
+
openAlexApiKey: getOpenAlexApiKey(config)
|
|
4363
4392
|
});
|
|
4364
4393
|
const summary = results.map((result, index) => `${index + 1}. ${result.title} [${result.provider}] ${result.url}`).join("\n");
|
|
4365
4394
|
return {
|
|
@@ -5653,6 +5682,9 @@ function timeAgo(dateStr) {
|
|
|
5653
5682
|
if (days < 30) return `${days}d ago`;
|
|
5654
5683
|
return new Date(dateStr).toLocaleDateString();
|
|
5655
5684
|
}
|
|
5685
|
+
function truncate2(text, max) {
|
|
5686
|
+
return text.length > max ? text.slice(0, max) + "\u2026" : text;
|
|
5687
|
+
}
|
|
5656
5688
|
function SessionPicker({ sessions, onSelect, onCancel }) {
|
|
5657
5689
|
const [filter, setFilter] = useState3("");
|
|
5658
5690
|
const [selectedIndex, setSelectedIndex] = useState3(0);
|
|
@@ -5696,43 +5728,67 @@ function SessionPicker({ sessions, onSelect, onCancel }) {
|
|
|
5696
5728
|
setSelectedIndex(0);
|
|
5697
5729
|
}
|
|
5698
5730
|
});
|
|
5699
|
-
|
|
5700
|
-
|
|
5701
|
-
/* @__PURE__ */ jsx3(
|
|
5731
|
+
const width = Math.max(60, (process.stdout.columns ?? 80) - 6);
|
|
5732
|
+
return /* @__PURE__ */ jsxs2(Box3, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
|
|
5733
|
+
/* @__PURE__ */ jsx3(Text3, { bold: true, children: "/resume" }),
|
|
5734
|
+
/* @__PURE__ */ jsxs2(Text3, { color: "gray", dimColor: true, children: [
|
|
5735
|
+
sessions.length,
|
|
5736
|
+
" session",
|
|
5737
|
+
sessions.length !== 1 ? "s" : "",
|
|
5738
|
+
" in this workspace"
|
|
5739
|
+
] }),
|
|
5740
|
+
/* @__PURE__ */ jsxs2(
|
|
5702
5741
|
Box3,
|
|
5703
5742
|
{
|
|
5704
|
-
borderStyle: "
|
|
5743
|
+
borderStyle: "round",
|
|
5705
5744
|
borderColor: filter ? "cyan" : "gray",
|
|
5706
5745
|
paddingX: 1,
|
|
5707
5746
|
marginTop: 1,
|
|
5708
5747
|
marginBottom: 1,
|
|
5709
|
-
children:
|
|
5710
|
-
|
|
5711
|
-
|
|
5712
|
-
filtered.length === 0 ? /* @__PURE__ */ jsx3(Text3, { color: "gray", children: filter ? "No matching sessions." : "No sessions found." }) : /* @__PURE__ */ jsx3(Box3, { flexDirection: "column", children: filtered.slice(0, 15).map((session, idx) => {
|
|
5713
|
-
const isSelected = idx === clampedIndex;
|
|
5714
|
-
const indicator = isSelected ? "\u203A" : " ";
|
|
5715
|
-
const preview = session.preview || "(empty session)";
|
|
5716
|
-
const age = timeAgo(session.lastActivity);
|
|
5717
|
-
const turns = `${session.turnCount} turn${session.turnCount !== 1 ? "s" : ""}`;
|
|
5718
|
-
return /* @__PURE__ */ jsxs2(Box3, { flexDirection: "column", marginBottom: isSelected ? 1 : 0, children: [
|
|
5719
|
-
/* @__PURE__ */ jsxs2(Box3, { children: [
|
|
5720
|
-
/* @__PURE__ */ jsxs2(Text3, { color: isSelected ? "cyan" : "gray", children: [
|
|
5721
|
-
indicator,
|
|
5748
|
+
children: [
|
|
5749
|
+
/* @__PURE__ */ jsxs2(Text3, { color: "gray", children: [
|
|
5750
|
+
"\u2315",
|
|
5722
5751
|
" "
|
|
5723
5752
|
] }),
|
|
5724
|
-
/* @__PURE__ */ jsx3(Text3, {
|
|
5725
|
-
]
|
|
5726
|
-
|
|
5727
|
-
|
|
5728
|
-
|
|
5729
|
-
|
|
5730
|
-
|
|
5731
|
-
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
|
|
5735
|
-
|
|
5753
|
+
/* @__PURE__ */ jsx3(Text3, { children: filter || /* @__PURE__ */ jsx3(Text3, { color: "gray", children: "Search sessions..." }) })
|
|
5754
|
+
]
|
|
5755
|
+
}
|
|
5756
|
+
),
|
|
5757
|
+
filtered.length === 0 ? /* @__PURE__ */ jsx3(Text3, { color: "gray", children: filter ? "No matching sessions." : "No sessions found." }) : /* @__PURE__ */ jsxs2(Box3, { flexDirection: "column", children: [
|
|
5758
|
+
filtered.slice(0, 12).map((session, idx) => {
|
|
5759
|
+
const isSelected = idx === clampedIndex;
|
|
5760
|
+
const preview = session.preview || "(empty session)";
|
|
5761
|
+
const age = timeAgo(session.lastActivity);
|
|
5762
|
+
const turns = `${session.turnCount} turn${session.turnCount !== 1 ? "s" : ""}`;
|
|
5763
|
+
const meta = `${age} \xB7 ${turns}`;
|
|
5764
|
+
if (isSelected) {
|
|
5765
|
+
const line = ` \u203A ${truncate2(preview, width - meta.length - 8)}`;
|
|
5766
|
+
return /* @__PURE__ */ jsxs2(Box3, { flexDirection: "column", marginBottom: 0, children: [
|
|
5767
|
+
/* @__PURE__ */ jsxs2(Box3, { children: [
|
|
5768
|
+
/* @__PURE__ */ jsx3(Text3, { inverse: true, bold: true, children: line }),
|
|
5769
|
+
/* @__PURE__ */ jsx3(Text3, { inverse: true, dimColor: true, children: ` ${meta} ` })
|
|
5770
|
+
] }),
|
|
5771
|
+
/* @__PURE__ */ jsx3(Box3, { marginLeft: 3, children: /* @__PURE__ */ jsxs2(Text3, { color: "gray", dimColor: true, children: [
|
|
5772
|
+
"id: ",
|
|
5773
|
+
session.id.slice(0, 8),
|
|
5774
|
+
" \\u00B7 started ",
|
|
5775
|
+
new Date(session.startedAt).toLocaleString()
|
|
5776
|
+
] }) })
|
|
5777
|
+
] }, session.id);
|
|
5778
|
+
}
|
|
5779
|
+
return /* @__PURE__ */ jsxs2(Box3, { children: [
|
|
5780
|
+
/* @__PURE__ */ jsx3(Text3, { color: "gray", children: " " }),
|
|
5781
|
+
/* @__PURE__ */ jsx3(Text3, { children: truncate2(preview, width - meta.length - 8) }),
|
|
5782
|
+
/* @__PURE__ */ jsx3(Text3, { color: "gray", dimColor: true, children: ` ${meta}` })
|
|
5783
|
+
] }, session.id);
|
|
5784
|
+
}),
|
|
5785
|
+
filtered.length > 12 && /* @__PURE__ */ jsxs2(Text3, { color: "gray", dimColor: true, children: [
|
|
5786
|
+
" \\u2193 ",
|
|
5787
|
+
filtered.length - 12,
|
|
5788
|
+
" more below"
|
|
5789
|
+
] })
|
|
5790
|
+
] }),
|
|
5791
|
+
/* @__PURE__ */ jsx3(Box3, { marginTop: 1, children: /* @__PURE__ */ jsx3(Text3, { color: "gray", dimColor: true, children: "\\u2191/\\u2193 to select \\u00B7 Enter resume \\u00B7 Type to filter \\u00B7 Esc cancel" }) })
|
|
5736
5792
|
] });
|
|
5737
5793
|
}
|
|
5738
5794
|
|
|
@@ -6294,6 +6350,7 @@ var SLASH_COMMANDS = [
|
|
|
6294
6350
|
{ name: "btw", aliases: ["/aside"], description: "Ask a side question without affecting the main conversation", category: "session" },
|
|
6295
6351
|
{ name: "export", aliases: [], description: "Export conversation as markdown to a file", category: "session" },
|
|
6296
6352
|
{ 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 (e.g. /api-keys semantic-scholar YOUR_KEY)", category: "system" },
|
|
6297
6354
|
{ name: "doctor", aliases: [], description: "Diagnose auth, connectivity, and tool availability", category: "system" },
|
|
6298
6355
|
{ name: "preview", aliases: [], description: "Live preview a LaTeX file in browser (e.g. /preview papers/draft.tex)", category: "workspace" },
|
|
6299
6356
|
{ name: "memory", aliases: ["/memories"], description: "View or clear stored memories about you", category: "system" },
|
|
@@ -6359,7 +6416,7 @@ function getFileSuggestions(partial, files) {
|
|
|
6359
6416
|
label: f.label
|
|
6360
6417
|
}));
|
|
6361
6418
|
}
|
|
6362
|
-
function
|
|
6419
|
+
function truncate3(value, max = 96) {
|
|
6363
6420
|
return value.length <= max ? value : `${value.slice(0, max - 1).trimEnd()}\u2026`;
|
|
6364
6421
|
}
|
|
6365
6422
|
|
|
@@ -7261,6 +7318,46 @@ ${msg.text}
|
|
|
7261
7318
|
}
|
|
7262
7319
|
break;
|
|
7263
7320
|
}
|
|
7321
|
+
case "api-keys": {
|
|
7322
|
+
if (!args) {
|
|
7323
|
+
const ssKey = getSemanticScholarApiKey(config);
|
|
7324
|
+
const oaKey = getOpenAlexApiKey(config);
|
|
7325
|
+
addSystemMessage("API Keys:");
|
|
7326
|
+
addSystemMessage(` Semantic Scholar: ${ssKey ? ssKey.slice(0, 8) + "..." : "not set"}`);
|
|
7327
|
+
addSystemMessage(` OpenAlex: ${oaKey ? oaKey.slice(0, 8) + "..." : "not set"}`);
|
|
7328
|
+
addSystemMessage("");
|
|
7329
|
+
addSystemMessage("Set via CLI:");
|
|
7330
|
+
addSystemMessage(" /api-keys semantic-scholar YOUR_KEY");
|
|
7331
|
+
addSystemMessage(" /api-keys openalex YOUR_KEY");
|
|
7332
|
+
addSystemMessage("");
|
|
7333
|
+
addSystemMessage("Or set environment variables:");
|
|
7334
|
+
addSystemMessage(" export SEMANTIC_SCHOLAR_API_KEY=your_key");
|
|
7335
|
+
addSystemMessage(" export OPENALEX_API_KEY=your_key");
|
|
7336
|
+
break;
|
|
7337
|
+
}
|
|
7338
|
+
const [keyName, ...keyParts] = args.split(/\s+/);
|
|
7339
|
+
const keyValue = keyParts.join("").trim();
|
|
7340
|
+
if (!keyValue) {
|
|
7341
|
+
addSystemMessage("Usage: /api-keys <semantic-scholar|openalex> <key>");
|
|
7342
|
+
break;
|
|
7343
|
+
}
|
|
7344
|
+
if (config) {
|
|
7345
|
+
const apiKeys = config.apiKeys ?? {};
|
|
7346
|
+
if (keyName === "semantic-scholar" || keyName === "ss") {
|
|
7347
|
+
apiKeys.semanticScholar = keyValue;
|
|
7348
|
+
} else if (keyName === "openalex" || keyName === "oa") {
|
|
7349
|
+
apiKeys.openAlex = keyValue;
|
|
7350
|
+
} else {
|
|
7351
|
+
addSystemMessage(`Unknown key: ${keyName}. Use semantic-scholar or openalex.`);
|
|
7352
|
+
break;
|
|
7353
|
+
}
|
|
7354
|
+
const updated = { ...config, apiKeys };
|
|
7355
|
+
setConfig(updated);
|
|
7356
|
+
await saveOpenResearchConfig(updated, { homeDir });
|
|
7357
|
+
addSystemMessage(`${keyName} API key saved.`);
|
|
7358
|
+
}
|
|
7359
|
+
break;
|
|
7360
|
+
}
|
|
7264
7361
|
case "doctor": {
|
|
7265
7362
|
addSystemMessage("Running diagnostics...");
|
|
7266
7363
|
const authResult = await getAuthStatus({ homeDir });
|
|
@@ -7268,6 +7365,10 @@ ${msg.text}
|
|
|
7268
7365
|
addSystemMessage(` Workspace: ${workspacePath ? workspacePath : "none"}`);
|
|
7269
7366
|
addSystemMessage(` Files: ${workspaceFiles.length}`);
|
|
7270
7367
|
addSystemMessage(` Skills: ${skills2.length} loaded`);
|
|
7368
|
+
const ssKey = getSemanticScholarApiKey(config);
|
|
7369
|
+
const oaKey = getOpenAlexApiKey(config);
|
|
7370
|
+
addSystemMessage(` Semantic Scholar API: ${ssKey ? "configured" : "not set (rate-limited)"}`);
|
|
7371
|
+
addSystemMessage(` OpenAlex API: ${oaKey ? "configured" : "not set (limited)"}`);
|
|
7271
7372
|
const mems = await loadAllMemories({ homeDir });
|
|
7272
7373
|
addSystemMessage(` Memories: ${mems.length} stored`);
|
|
7273
7374
|
addSystemMessage(` Node: ${process.version}`);
|
|
@@ -7897,7 +7998,7 @@ ${error.stack}` : String(error)}` }
|
|
|
7897
7998
|
PendingUpdateCard,
|
|
7898
7999
|
{
|
|
7899
8000
|
count: deferredPendingUpdates.length,
|
|
7900
|
-
summary:
|
|
8001
|
+
summary: truncate3(deferredPendingUpdates[0].summary, 80)
|
|
7901
8002
|
}
|
|
7902
8003
|
),
|
|
7903
8004
|
planningState.status === "charter-review" && planningState.charter && /* @__PURE__ */ jsxs4(
|
package/package.json
CHANGED