@longtable/cli 0.1.59 → 0.1.61
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 +80 -9
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/search/index.d.ts +1 -6
- package/dist/search/index.js +1 -6
- package/package.json +8 -7
- package/dist/search/publisher-access.d.ts +0 -21
- package/dist/search/publisher-access.js +0 -564
- package/dist/search/query.d.ts +0 -6
- package/dist/search/query.js +0 -179
- package/dist/search/rank.d.ts +0 -2
- package/dist/search/rank.js +0 -173
- package/dist/search/run.d.ts +0 -2
- package/dist/search/run.js +0 -114
- package/dist/search/sources.d.ts +0 -5
- package/dist/search/sources.js +0 -537
- package/dist/search/types.d.ts +0 -181
- package/dist/search/types.js +0 -16
package/dist/cli.js
CHANGED
|
@@ -10,7 +10,7 @@ import { homedir } from "node:os";
|
|
|
10
10
|
import { fileURLToPath } from "node:url";
|
|
11
11
|
import { collectHardStopBlockers } from "@longtable/core";
|
|
12
12
|
import { classifyCheckpointTrigger } from "@longtable/checkpoints";
|
|
13
|
-
import { assessSearchSourceCapabilities, buildResearchSearchIntent, parsePublisherTarget, probePublisherAccess, publisherConfigs, runResearchSearch, SEARCH_SOURCES, summarizeConfiguredPublisherAccess } from "./search/index.js";
|
|
13
|
+
import { assessSearchSourceCapabilities, assessScholarResearchReadiness, buildResearchSearchIntent, buildScholarResearchSmokeFixture, parsePublisherTarget, probePublisherAccess, publisherConfigs, runResearchSearch, SEARCH_SOURCES, writeScholarResearchRunScaffold, summarizeConfiguredPublisherAccess } from "./search/index.js";
|
|
14
14
|
import { buildProviderChoices, buildQuickSetupFlow, createPersistedSetupOutput, installRuntimeConfigFromStoredSetup, loadSetupOutput, renderInstallSummary, renderSetupSummary, resolveDefaultRuntimeConfigPath, resolveDefaultSetupPath, saveSetupOutput, saveSetupAndRuntimeConfig, serializeSetupOutput, writeRuntimeConfig } from "@longtable/setup";
|
|
15
15
|
import { buildCodexSkillSpecs, buildCodexThinWrappedPrompt, installCodexSkills, listInstalledCodexSkills, renderQuestionRecordPrompt, removeCodexSkills, resolveCodexSkillsDir, runCodexThinWrapper } from "@longtable/provider-codex";
|
|
16
16
|
import { buildClaudeSkillSpecs, installClaudeSkills, listInstalledClaudeSkills, renderQuestionRecordInput, removeClaudeSkills, resolveClaudeSkillsDir } from "@longtable/provider-claude";
|
|
@@ -153,7 +153,10 @@ function usage() {
|
|
|
153
153
|
" longtable access status [--json]",
|
|
154
154
|
" longtable access doctor [--doi <doi>] [--publisher auto|elsevier|springer_nature|wiley|taylor_francis|all] [--json]",
|
|
155
155
|
" longtable access probe --doi <doi> [--publisher auto|elsevier|springer_nature|wiley|taylor_francis] [--json]",
|
|
156
|
-
" longtable search --query <text> [--intent literature|theory|measurement|citation|metadata|venue] [--field <text>] [--source all|crossref,arxiv,openalex,semantic_scholar,pubmed,eric,doaj
|
|
156
|
+
" longtable search --query <text> [--intent literature|theory|measurement|citation|metadata|venue] [--field <text>] [--source all|crossref,arxiv,openalex,semantic_scholar,pubmed,eric,doaj] [--must <term[,term]>] [--exclude <term[,term]>] [--limit <n>] [--allow-partial] [--publisher-access] [--record] [--cwd <path>] [--json]",
|
|
157
|
+
" longtable scholar-research doctor [--json]",
|
|
158
|
+
" longtable scholar-research scaffold [--cwd <path>] [--run-id <id>] [--json]",
|
|
159
|
+
" longtable scholar-research smoke-fixture [--json]",
|
|
157
160
|
" longtable sentinel --prompt <text> [--cwd <path>] [--json] [--record]",
|
|
158
161
|
" longtable ask [--prompt <text>] [--print] [--json] [--setup <path>] [--cwd <path>]",
|
|
159
162
|
" longtable clarify --prompt <task-context> [--provider codex|claude] [--required|--advisory] [--print] [--cwd <path>] [--json] [--force]",
|
|
@@ -201,7 +204,7 @@ function parseArgs(argv) {
|
|
|
201
204
|
const values = {};
|
|
202
205
|
let subcommand = maybeSubcommand;
|
|
203
206
|
const modeCommand = command && VALID_MODES.has(command);
|
|
204
|
-
const directCommand = command && ["init", "setup", "start", "resume", "doctor", "status", "audit", "roles", "show", "install", "mcp", "codex", "claude", "ask", "clarify", "question", "clear-question", "prune-questions", "panel", "handoff", "decide", "sentinel", "access", "search", "spec"].includes(command);
|
|
207
|
+
const directCommand = command && ["init", "setup", "start", "resume", "doctor", "status", "audit", "roles", "show", "install", "mcp", "codex", "claude", "ask", "clarify", "question", "clear-question", "prune-questions", "panel", "handoff", "decide", "sentinel", "access", "search", "scholar-research", "spec"].includes(command);
|
|
205
208
|
let startIndex = 1;
|
|
206
209
|
if (modeCommand) {
|
|
207
210
|
subcommand = undefined;
|
|
@@ -210,7 +213,7 @@ function parseArgs(argv) {
|
|
|
210
213
|
else if (command === "codex" || command === "claude" || command === "mcp") {
|
|
211
214
|
startIndex = 2;
|
|
212
215
|
}
|
|
213
|
-
else if ((command === "access" || command === "search" || command === "spec" || command === "panel") && maybeSubcommand && !maybeSubcommand.startsWith("--")) {
|
|
216
|
+
else if ((command === "access" || command === "search" || command === "scholar-research" || command === "spec" || command === "panel") && maybeSubcommand && !maybeSubcommand.startsWith("--")) {
|
|
214
217
|
subcommand = maybeSubcommand;
|
|
215
218
|
startIndex = 2;
|
|
216
219
|
}
|
|
@@ -991,15 +994,25 @@ async function collectProjectInterview(setup, args) {
|
|
|
991
994
|
]));
|
|
992
995
|
console.log("");
|
|
993
996
|
}
|
|
994
|
-
const
|
|
997
|
+
const projectNameInput = (typeof args.name === "string" && args.name.trim()) ||
|
|
995
998
|
(await promptText(renderQuestionHeader(1, 2, "Workspace", "What should this project be called?"), true));
|
|
999
|
+
if (!projectNameInput) {
|
|
1000
|
+
throw new Error("LongTable start needs a project name.");
|
|
1001
|
+
}
|
|
1002
|
+
const projectName = projectNameInput;
|
|
996
1003
|
const suggestedParentDir = typeof args.path === "string" && args.path.trim()
|
|
997
1004
|
? normalizeUserPath(args.path.trim())
|
|
998
1005
|
: homedir();
|
|
999
1006
|
const suggestedPath = resolveInteractiveProjectPath(suggestedParentDir, projectName);
|
|
1000
|
-
const
|
|
1007
|
+
const projectPathInput = typeof args.path === "string" && args.path.trim()
|
|
1001
1008
|
? normalizeUserPath(args.path.trim())
|
|
1002
|
-
:
|
|
1009
|
+
: await promptText(renderQuestionHeader(2, 2, "Workspace", `Which parent directory should contain this project?\nLongTable will create this folder:\n${suggestedPath}`), true);
|
|
1010
|
+
if (!projectPathInput) {
|
|
1011
|
+
throw new Error("LongTable start needs a project path.");
|
|
1012
|
+
}
|
|
1013
|
+
const projectPath = typeof args.path === "string" && args.path.trim()
|
|
1014
|
+
? projectPathInput
|
|
1015
|
+
: resolveInteractiveProjectPath(projectPathInput, projectName);
|
|
1003
1016
|
const adaptive = skipResearchInterview
|
|
1004
1017
|
? {}
|
|
1005
1018
|
: await collectAdaptiveStartInterview({
|
|
@@ -1637,6 +1650,7 @@ async function collectDoctorStatus(args) {
|
|
|
1637
1650
|
return {
|
|
1638
1651
|
setupPath,
|
|
1639
1652
|
setupExists: existsSync(setupPath),
|
|
1653
|
+
scholarResearch: assessScholarResearchReadiness(env),
|
|
1640
1654
|
providers: {
|
|
1641
1655
|
codex: {
|
|
1642
1656
|
command: "codex",
|
|
@@ -1700,6 +1714,8 @@ function renderDoctorStatus(status) {
|
|
|
1700
1714
|
const lines = [
|
|
1701
1715
|
"LongTable doctor",
|
|
1702
1716
|
`- setup: ${status.setupExists ? "present" : "missing"} (${status.setupPath})`,
|
|
1717
|
+
`- scholar-research connectors: ${status.scholarResearch.connectors.filter((connector) => connector.status === "ready").length}/${status.scholarResearch.connectors.length} ready`,
|
|
1718
|
+
`- scholar-research safety: paywall bypass ${status.scholarResearch.safety.paywallBypassAllowed ? "allowed" : "disabled"}, institution login automation ${status.scholarResearch.safety.institutionLoginAutomationAllowed ? "allowed" : "disabled"}`,
|
|
1703
1719
|
"",
|
|
1704
1720
|
...renderProviderDoctorBlock("Codex", status.providers.codex),
|
|
1705
1721
|
`- legacy prompt files: ${status.providers.codex.legacyPromptFilesInstalled.length}`,
|
|
@@ -2083,12 +2099,14 @@ function buildRoleAuditEntry(provider, spec) {
|
|
|
2083
2099
|
}
|
|
2084
2100
|
function runRoleAudit() {
|
|
2085
2101
|
const baseSkillNames = new Set([
|
|
2102
|
+
"critical-interview",
|
|
2086
2103
|
"longtable",
|
|
2087
2104
|
"longtable-start",
|
|
2088
2105
|
"longtable-interview",
|
|
2089
2106
|
"longtable-panel",
|
|
2090
2107
|
"longtable-explore",
|
|
2091
|
-
"longtable-review"
|
|
2108
|
+
"longtable-review",
|
|
2109
|
+
"scholar-research"
|
|
2092
2110
|
]);
|
|
2093
2111
|
const roles = [
|
|
2094
2112
|
...buildCodexSkillSpecs(listRoleDefinitions(), "full")
|
|
@@ -2829,6 +2847,9 @@ async function runPanelCommand(args) {
|
|
|
2829
2847
|
console.log(renderPanelSummary(fallback.plan));
|
|
2830
2848
|
console.log("");
|
|
2831
2849
|
if (finalNativeRun) {
|
|
2850
|
+
if (!nativeRunContext) {
|
|
2851
|
+
throw new Error("Native panel worker run finished without a run context.");
|
|
2852
|
+
}
|
|
2832
2853
|
console.log("LongTable native panel worker run created");
|
|
2833
2854
|
console.log(`- run: ${finalNativeRun.id}`);
|
|
2834
2855
|
console.log(`- status: ${finalNativeRun.status}`);
|
|
@@ -3315,7 +3336,7 @@ async function runInteractiveAccessSetup(args) {
|
|
|
3315
3336
|
return buildAccessReadinessProfile({ readiness, routes: [] });
|
|
3316
3337
|
}
|
|
3317
3338
|
const routeSelections = await promptMultiChoice("Select every scholarly access route that is available or intended. Secrets are never stored.", [
|
|
3318
|
-
{ id: "metadata", label: "Open metadata", description: "Crossref, OpenAlex, Semantic Scholar, PubMed, ERIC, DOAJ
|
|
3339
|
+
{ id: "metadata", label: "Open metadata", description: "Crossref, OpenAlex, Semantic Scholar, PubMed, ERIC, DOAJ." },
|
|
3319
3340
|
{ id: "oa_full_text", label: "OA full text", description: "Use open-access PDF/full-text when legally available." },
|
|
3320
3341
|
{ id: "institutional", label: "Institutional access", description: "VPN, library proxy, or browser SSO handled by the researcher." },
|
|
3321
3342
|
{ id: "publisher_tdm", label: "Publisher API/TDM", description: "Use configured publisher API/TDM environment variables." },
|
|
@@ -3455,6 +3476,52 @@ async function runSearch(subcommand, args) {
|
|
|
3455
3476
|
}
|
|
3456
3477
|
console.log(renderEvidenceRunSummary(run, recordedPath));
|
|
3457
3478
|
}
|
|
3479
|
+
async function runScholarResearch(subcommand, args) {
|
|
3480
|
+
const json = args.json === true;
|
|
3481
|
+
if (subcommand === "doctor" || subcommand === "status" || !subcommand) {
|
|
3482
|
+
const readiness = assessScholarResearchReadiness(env);
|
|
3483
|
+
if (json) {
|
|
3484
|
+
console.log(JSON.stringify(readiness, null, 2));
|
|
3485
|
+
return;
|
|
3486
|
+
}
|
|
3487
|
+
console.log("LongTable scholar-research doctor");
|
|
3488
|
+
for (const connector of readiness.connectors) {
|
|
3489
|
+
const missing = connector.missingEnv.length > 0 ? ` (missing ${connector.missingEnv.join(", ")})` : "";
|
|
3490
|
+
console.log(`- ${connector.name}: ${connector.status}${missing}`);
|
|
3491
|
+
}
|
|
3492
|
+
console.log("- safety: paywall bypass disabled; institution-login automation disabled");
|
|
3493
|
+
return;
|
|
3494
|
+
}
|
|
3495
|
+
if (subcommand === "scaffold") {
|
|
3496
|
+
const workingDirectory = typeof args.cwd === "string" ? args.cwd : cwd();
|
|
3497
|
+
const runId = typeof args["run-id"] === "string" ? args["run-id"] : undefined;
|
|
3498
|
+
const scaffold = await writeScholarResearchRunScaffold({
|
|
3499
|
+
cwd: workingDirectory,
|
|
3500
|
+
...(runId ? { runId } : {})
|
|
3501
|
+
});
|
|
3502
|
+
if (json) {
|
|
3503
|
+
console.log(JSON.stringify(scaffold, null, 2));
|
|
3504
|
+
return;
|
|
3505
|
+
}
|
|
3506
|
+
console.log("LongTable scholar-research scaffold");
|
|
3507
|
+
console.log(`- run: ${scaffold.runId}`);
|
|
3508
|
+
console.log(`- dir: ${scaffold.runDir}`);
|
|
3509
|
+
return;
|
|
3510
|
+
}
|
|
3511
|
+
if (subcommand === "smoke-fixture") {
|
|
3512
|
+
const fixture = buildScholarResearchSmokeFixture();
|
|
3513
|
+
if (json) {
|
|
3514
|
+
console.log(JSON.stringify({ fixture }, null, 2));
|
|
3515
|
+
return;
|
|
3516
|
+
}
|
|
3517
|
+
console.log("LongTable scholar-research smoke fixture");
|
|
3518
|
+
for (const item of fixture) {
|
|
3519
|
+
console.log(`- ${item.id}: ${item.category} - ${item.label}`);
|
|
3520
|
+
}
|
|
3521
|
+
return;
|
|
3522
|
+
}
|
|
3523
|
+
throw new Error(`Unknown scholar-research subcommand: ${subcommand}`);
|
|
3524
|
+
}
|
|
3458
3525
|
async function requireWorkspaceContext(args) {
|
|
3459
3526
|
const workingDirectory = typeof args.cwd === "string" ? args.cwd : cwd();
|
|
3460
3527
|
const context = await loadProjectContextFromDirectory(workingDirectory);
|
|
@@ -4588,6 +4655,10 @@ async function main() {
|
|
|
4588
4655
|
await runSearch(subcommand, values);
|
|
4589
4656
|
return;
|
|
4590
4657
|
}
|
|
4658
|
+
if (command === "scholar-research") {
|
|
4659
|
+
await runScholarResearch(subcommand, values);
|
|
4660
|
+
return;
|
|
4661
|
+
}
|
|
4591
4662
|
if (command === "spec") {
|
|
4592
4663
|
await runSpec(subcommand, values);
|
|
4593
4664
|
return;
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/dist/search/index.d.ts
CHANGED
package/dist/search/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@longtable/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.61",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Researcher-facing LongTable CLI",
|
|
6
6
|
"type": "module",
|
|
@@ -29,12 +29,13 @@
|
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@clack/prompts": "^1.2.0",
|
|
32
|
-
"@longtable/checkpoints": "0.1.
|
|
33
|
-
"@longtable/core": "0.1.
|
|
34
|
-
"@longtable/memory": "0.1.
|
|
35
|
-
"@longtable/provider-claude": "0.1.
|
|
36
|
-
"@longtable/provider-codex": "0.1.
|
|
37
|
-
"@longtable/
|
|
32
|
+
"@longtable/checkpoints": "0.1.61",
|
|
33
|
+
"@longtable/core": "0.1.61",
|
|
34
|
+
"@longtable/memory": "0.1.61",
|
|
35
|
+
"@longtable/provider-claude": "0.1.61",
|
|
36
|
+
"@longtable/provider-codex": "0.1.61",
|
|
37
|
+
"@longtable/scholar-research": "0.1.61",
|
|
38
|
+
"@longtable/setup": "0.1.61"
|
|
38
39
|
},
|
|
39
40
|
"devDependencies": {
|
|
40
41
|
"@types/node": "^22.10.1",
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { type CrossrefTdmDiscovery, type EvidenceCard, type Publisher, type PublisherAccessRecord, type PublisherProbeInput, type PublisherProbeTarget, type SearchFetch } from "./types.js";
|
|
2
|
-
interface PublisherConfig {
|
|
3
|
-
publisher: Publisher;
|
|
4
|
-
label: string;
|
|
5
|
-
requiredEnv: string[];
|
|
6
|
-
optionalEnv: string[];
|
|
7
|
-
setupHint: string;
|
|
8
|
-
}
|
|
9
|
-
export declare function normalizeDoi(value: string): string;
|
|
10
|
-
export declare function parsePublisherTarget(value?: string | boolean): PublisherProbeTarget;
|
|
11
|
-
export declare function discoverCrossrefTdm(doi: string, env?: Record<string, string | undefined>, httpFetch?: SearchFetch): Promise<CrossrefTdmDiscovery>;
|
|
12
|
-
export declare function publisherConfigs(): PublisherConfig[];
|
|
13
|
-
export declare function probePublisherAccess(input: PublisherProbeInput): Promise<PublisherAccessRecord>;
|
|
14
|
-
export declare function summarizeConfiguredPublisherAccess(env?: Record<string, string | undefined>): PublisherAccessRecord[];
|
|
15
|
-
export declare function enrichCardsWithPublisherAccess(input: {
|
|
16
|
-
cards: EvidenceCard[];
|
|
17
|
-
env?: Record<string, string | undefined>;
|
|
18
|
-
fetch?: SearchFetch;
|
|
19
|
-
limit?: number;
|
|
20
|
-
}): Promise<EvidenceCard[]>;
|
|
21
|
-
export {};
|