- Rename project config dir from .pi/ to .feynman/ (Pi supports this via piConfig.configDir) - Rename citation agent to verifier across all prompts, agents, skills, and docs - Add website with homepage and 24 doc pages (Astro + Tailwind) - Add skills for all workflows (deep-research, lit, review, audit, replicate, compare, draft, autoresearch, watch, jobs, session-log, agentcomputer) - Add Pi-native prompt frontmatter (args, section, topLevelCli) and read at runtime - Remove sync-docs generation layer — docs are standalone - Remove metadata/prompts.mjs and metadata/packages.mjs — not needed at runtime - Rewrite README and homepage copy - Add environment selection to /replicate before executing - Add prompts/delegate.md and AGENTS.md Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
213 lines
5.8 KiB
TypeScript
213 lines
5.8 KiB
TypeScript
import {
|
|
annotatePaper,
|
|
askPaper,
|
|
clearPaperAnnotation,
|
|
disconnect,
|
|
getPaper,
|
|
getUserName as getAlphaUserName,
|
|
isLoggedIn as isAlphaLoggedIn,
|
|
listPaperAnnotations,
|
|
login as loginAlpha,
|
|
logout as logoutAlpha,
|
|
readPaperCode,
|
|
searchPapers,
|
|
} from "@companion-ai/alpha-hub/lib";
|
|
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
import { Type } from "@sinclair/typebox";
|
|
|
|
import { getExtensionCommandSpec } from "../../metadata/commands.mjs";
|
|
import { formatToolText } from "./shared.js";
|
|
|
|
export function registerAlphaCommands(pi: ExtensionAPI): void {
|
|
pi.registerCommand("alpha-login", {
|
|
description: getExtensionCommandSpec("alpha-login")?.description ?? "Sign in to alphaXiv from inside Feynman.",
|
|
handler: async (_args, ctx) => {
|
|
if (isAlphaLoggedIn()) {
|
|
const name = getAlphaUserName();
|
|
ctx.ui.notify(name ? `alphaXiv already connected as ${name}` : "alphaXiv already connected", "info");
|
|
return;
|
|
}
|
|
|
|
await loginAlpha();
|
|
const name = getAlphaUserName();
|
|
ctx.ui.notify(name ? `alphaXiv connected as ${name}` : "alphaXiv login complete", "info");
|
|
},
|
|
});
|
|
|
|
pi.registerCommand("alpha-logout", {
|
|
description: getExtensionCommandSpec("alpha-logout")?.description ?? "Clear alphaXiv auth from inside Feynman.",
|
|
handler: async (_args, ctx) => {
|
|
logoutAlpha();
|
|
ctx.ui.notify("alphaXiv auth cleared", "info");
|
|
},
|
|
});
|
|
|
|
pi.registerCommand("alpha-status", {
|
|
description: getExtensionCommandSpec("alpha-status")?.description ?? "Show alphaXiv authentication status.",
|
|
handler: async (_args, ctx) => {
|
|
if (!isAlphaLoggedIn()) {
|
|
ctx.ui.notify("alphaXiv not connected", "warning");
|
|
return;
|
|
}
|
|
|
|
const name = getAlphaUserName();
|
|
ctx.ui.notify(name ? `alphaXiv connected as ${name}` : "alphaXiv connected", "info");
|
|
},
|
|
});
|
|
}
|
|
|
|
export function registerAlphaTools(pi: ExtensionAPI): void {
|
|
pi.registerTool({
|
|
name: "alpha_search",
|
|
label: "Alpha Search",
|
|
description: "Search papers through alphaXiv using semantic, keyword, both, agentic, or all retrieval modes.",
|
|
parameters: Type.Object({
|
|
query: Type.String({ description: "Paper search query." }),
|
|
mode: Type.Optional(
|
|
Type.String({
|
|
description: "Search mode: semantic, keyword, both, agentic, or all.",
|
|
}),
|
|
),
|
|
}),
|
|
async execute(_toolCallId, params) {
|
|
try {
|
|
const result = await searchPapers(params.query, params.mode?.trim() || "all");
|
|
return {
|
|
content: [{ type: "text", text: formatToolText(result) }],
|
|
details: result,
|
|
};
|
|
} finally {
|
|
await disconnect();
|
|
}
|
|
},
|
|
});
|
|
|
|
pi.registerTool({
|
|
name: "alpha_get_paper",
|
|
label: "Alpha Get Paper",
|
|
description: "Fetch a paper report or full text, plus any local annotation, using alphaXiv.",
|
|
parameters: Type.Object({
|
|
paper: Type.String({
|
|
description: "arXiv ID, arXiv URL, or alphaXiv URL.",
|
|
}),
|
|
fullText: Type.Optional(
|
|
Type.Boolean({
|
|
description: "Return raw full text instead of the AI report.",
|
|
}),
|
|
),
|
|
}),
|
|
async execute(_toolCallId, params) {
|
|
try {
|
|
const result = await getPaper(params.paper, { fullText: params.fullText });
|
|
return {
|
|
content: [{ type: "text", text: formatToolText(result) }],
|
|
details: result,
|
|
};
|
|
} finally {
|
|
await disconnect();
|
|
}
|
|
},
|
|
});
|
|
|
|
pi.registerTool({
|
|
name: "alpha_ask_paper",
|
|
label: "Alpha Ask Paper",
|
|
description: "Ask a targeted question about a paper using alphaXiv's PDF analysis.",
|
|
parameters: Type.Object({
|
|
paper: Type.String({
|
|
description: "arXiv ID, arXiv URL, or alphaXiv URL.",
|
|
}),
|
|
question: Type.String({
|
|
description: "Question to ask about the paper.",
|
|
}),
|
|
}),
|
|
async execute(_toolCallId, params) {
|
|
try {
|
|
const result = await askPaper(params.paper, params.question);
|
|
return {
|
|
content: [{ type: "text", text: formatToolText(result) }],
|
|
details: result,
|
|
};
|
|
} finally {
|
|
await disconnect();
|
|
}
|
|
},
|
|
});
|
|
|
|
pi.registerTool({
|
|
name: "alpha_annotate_paper",
|
|
label: "Alpha Annotate Paper",
|
|
description: "Write or clear a persistent local annotation for a paper.",
|
|
parameters: Type.Object({
|
|
paper: Type.String({
|
|
description: "Paper ID to annotate.",
|
|
}),
|
|
note: Type.Optional(
|
|
Type.String({
|
|
description: "Annotation text. Omit when clear=true.",
|
|
}),
|
|
),
|
|
clear: Type.Optional(
|
|
Type.Boolean({
|
|
description: "Clear the existing annotation instead of writing one.",
|
|
}),
|
|
),
|
|
}),
|
|
async execute(_toolCallId, params) {
|
|
const result = params.clear
|
|
? await clearPaperAnnotation(params.paper)
|
|
: params.note
|
|
? await annotatePaper(params.paper, params.note)
|
|
: (() => {
|
|
throw new Error("Provide either note or clear=true.");
|
|
})();
|
|
|
|
return {
|
|
content: [{ type: "text", text: formatToolText(result) }],
|
|
details: result,
|
|
};
|
|
},
|
|
});
|
|
|
|
pi.registerTool({
|
|
name: "alpha_list_annotations",
|
|
label: "Alpha List Annotations",
|
|
description: "List all persistent local paper annotations.",
|
|
parameters: Type.Object({}),
|
|
async execute() {
|
|
const result = await listPaperAnnotations();
|
|
return {
|
|
content: [{ type: "text", text: formatToolText(result) }],
|
|
details: result,
|
|
};
|
|
},
|
|
});
|
|
|
|
pi.registerTool({
|
|
name: "alpha_read_code",
|
|
label: "Alpha Read Code",
|
|
description: "Read files from a paper's GitHub repository through alphaXiv.",
|
|
parameters: Type.Object({
|
|
githubUrl: Type.String({
|
|
description: "GitHub repository URL for the paper implementation.",
|
|
}),
|
|
path: Type.Optional(
|
|
Type.String({
|
|
description: "Repository path to inspect. Use / for the repo overview.",
|
|
}),
|
|
),
|
|
}),
|
|
async execute(_toolCallId, params) {
|
|
try {
|
|
const result = await readPaperCode(params.githubUrl, params.path?.trim() || "/");
|
|
return {
|
|
content: [{ type: "text", text: formatToolText(result) }],
|
|
details: result,
|
|
};
|
|
} finally {
|
|
await disconnect();
|
|
}
|
|
},
|
|
});
|
|
}
|