Commit guided setup and clack dependency updates
This commit is contained in:
53
package-lock.json
generated
53
package-lock.json
generated
@@ -10,6 +10,7 @@
|
|||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@clack/prompts": "^1.2.0",
|
||||||
"@companion-ai/alpha-hub": "^0.1.3",
|
"@companion-ai/alpha-hub": "^0.1.3",
|
||||||
"@mariozechner/pi-ai": "^0.66.1",
|
"@mariozechner/pi-ai": "^0.66.1",
|
||||||
"@mariozechner/pi-coding-agent": "^0.66.1",
|
"@mariozechner/pi-coding-agent": "^0.66.1",
|
||||||
@@ -780,6 +781,28 @@
|
|||||||
"url": "https://github.com/sponsors/Borewit"
|
"url": "https://github.com/sponsors/Borewit"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@clack/core": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@clack/core/-/core-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-qfxof/3T3t9DPU/Rj3OmcFyZInceqj/NVtO9rwIuJqCUgh32gwPjpFQQp/ben07qKlhpwq7GzfWpST4qdJ5Drg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"fast-wrap-ansi": "^0.1.3",
|
||||||
|
"sisteransi": "^1.0.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@clack/prompts": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@clack/prompts/-/prompts-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-4jmztR9fMqPMjz6H/UZXj0zEmE43ha1euENwkckKKel4XpSfokExPo5AiVStdHSAlHekz4d0CA/r45Ok1E4D3w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@clack/core": "1.2.0",
|
||||||
|
"fast-string-width": "^1.1.0",
|
||||||
|
"fast-wrap-ansi": "^0.1.3",
|
||||||
|
"sisteransi": "^1.0.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@companion-ai/alpha-hub": {
|
"node_modules/@companion-ai/alpha-hub": {
|
||||||
"version": "0.1.3",
|
"version": "0.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/@companion-ai/alpha-hub/-/alpha-hub-0.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/@companion-ai/alpha-hub/-/alpha-hub-0.1.3.tgz",
|
||||||
@@ -3206,6 +3229,21 @@
|
|||||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/fast-string-truncated-width": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-string-truncated-width/-/fast-string-truncated-width-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-Q9acT/+Uu3GwGj+5w/zsGuQjh9O1TyywhIwAxHudtWrgF09nHOPrvTLhQevPbttcxjr/SNN7mJmfOw/B1bXgow==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/fast-string-width": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-string-width/-/fast-string-width-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-O3fwIVIH5gKB38QNbdg+3760ZmGz0SZMgvwJbA1b2TGXceKE6A2cOlfogh1iw8lr049zPyd7YADHy+B7U4W9bQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"fast-string-truncated-width": "^1.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/fast-uri": {
|
"node_modules/fast-uri": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz",
|
||||||
@@ -3222,6 +3260,15 @@
|
|||||||
],
|
],
|
||||||
"license": "BSD-3-Clause"
|
"license": "BSD-3-Clause"
|
||||||
},
|
},
|
||||||
|
"node_modules/fast-wrap-ansi": {
|
||||||
|
"version": "0.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-wrap-ansi/-/fast-wrap-ansi-0.1.6.tgz",
|
||||||
|
"integrity": "sha512-HlUwET7a5gqjURj70D5jl7aC3Zmy4weA1SHUfM0JFI0Ptq987NH2TwbBFLoERhfwk+E+eaq4EK3jXoT+R3yp3w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"fast-string-width": "^1.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/fast-xml-builder": {
|
"node_modules/fast-xml-builder": {
|
||||||
"version": "1.1.4",
|
"version": "1.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.1.4.tgz",
|
||||||
@@ -4611,6 +4658,12 @@
|
|||||||
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
|
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
|
"node_modules/sisteransi": {
|
||||||
|
"version": "1.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
|
||||||
|
"integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/smart-buffer": {
|
"node_modules/smart-buffer": {
|
||||||
"version": "4.2.0",
|
"version": "4.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=20.19.0"
|
"node": ">=20.19.0 <25"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"feynman": "bin/feynman.js"
|
"feynman": "bin/feynman.js"
|
||||||
@@ -59,6 +59,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@clack/prompts": "^1.2.0",
|
||||||
"@companion-ai/alpha-hub": "^0.1.3",
|
"@companion-ai/alpha-hub": "^0.1.3",
|
||||||
"@mariozechner/pi-ai": "^0.66.1",
|
"@mariozechner/pi-ai": "^0.66.1",
|
||||||
"@mariozechner/pi-coding-agent": "^0.66.1",
|
"@mariozechner/pi-coding-agent": "^0.66.1",
|
||||||
|
|||||||
@@ -1,15 +1,24 @@
|
|||||||
import { isLoggedIn as isAlphaLoggedIn, login as loginAlpha } from "@companion-ai/alpha-hub/lib";
|
import { isLoggedIn as isAlphaLoggedIn, login as loginAlpha } from "@companion-ai/alpha-hub/lib";
|
||||||
|
import { dirname } from "node:path";
|
||||||
|
|
||||||
import { getDefaultSessionDir, getFeynmanHome } from "../config/paths.js";
|
import { getPiWebAccessStatus } from "../pi/web-access.js";
|
||||||
import { getPiWebAccessStatus, getPiWebSearchConfigPath } from "../pi/web-access.js";
|
|
||||||
import { normalizeFeynmanSettings } from "../pi/settings.js";
|
import { normalizeFeynmanSettings } from "../pi/settings.js";
|
||||||
import type { ThinkingLevel } from "../pi/settings.js";
|
import type { ThinkingLevel } from "../pi/settings.js";
|
||||||
|
import { getMissingConfiguredPackages, installPackageSources } from "../pi/package-ops.js";
|
||||||
|
import { listOptionalPackagePresets } from "../pi/package-presets.js";
|
||||||
import { getCurrentModelSpec, runModelSetup } from "../model/commands.js";
|
import { getCurrentModelSpec, runModelSetup } from "../model/commands.js";
|
||||||
import { buildModelStatusSnapshotFromRecords, getAvailableModelRecords, getSupportedModelRecords } from "../model/catalog.js";
|
import { buildModelStatusSnapshotFromRecords, getAvailableModelRecords, getSupportedModelRecords } from "../model/catalog.js";
|
||||||
import { PANDOC_FALLBACK_PATHS, resolveExecutable } from "../system/executables.js";
|
import { PANDOC_FALLBACK_PATHS, resolveExecutable } from "../system/executables.js";
|
||||||
import { setupPreviewDependencies } from "./preview.js";
|
import { setupPreviewDependencies } from "./preview.js";
|
||||||
import { runDoctor } from "./doctor.js";
|
|
||||||
import { printInfo, printSection, printSuccess } from "../ui/terminal.js";
|
import { printInfo, printSection, printSuccess } from "../ui/terminal.js";
|
||||||
|
import {
|
||||||
|
isInteractiveTerminal,
|
||||||
|
promptConfirm,
|
||||||
|
promptIntro,
|
||||||
|
promptMultiSelect,
|
||||||
|
promptOutro,
|
||||||
|
SetupCancelledError,
|
||||||
|
} from "./prompts.js";
|
||||||
|
|
||||||
type SetupOptions = {
|
type SetupOptions = {
|
||||||
settingsPath: string;
|
settingsPath: string;
|
||||||
@@ -21,10 +30,6 @@ type SetupOptions = {
|
|||||||
defaultThinkingLevel?: ThinkingLevel;
|
defaultThinkingLevel?: ThinkingLevel;
|
||||||
};
|
};
|
||||||
|
|
||||||
function isInteractiveTerminal(): boolean {
|
|
||||||
return Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
||||||
}
|
|
||||||
|
|
||||||
function printNonInteractiveSetupGuidance(): void {
|
function printNonInteractiveSetupGuidance(): void {
|
||||||
printInfo("Non-interactive terminal. Use explicit commands:");
|
printInfo("Non-interactive terminal. Use explicit commands:");
|
||||||
printInfo(" feynman model login <provider>");
|
printInfo(" feynman model login <provider>");
|
||||||
@@ -34,21 +39,152 @@ function printNonInteractiveSetupGuidance(): void {
|
|||||||
printInfo(" feynman doctor");
|
printInfo(" feynman doctor");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function summarizePackageSources(sources: string[]): string {
|
||||||
|
if (sources.length <= 3) {
|
||||||
|
return sources.join(", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${sources.slice(0, 3).join(", ")} +${sources.length - 3} more`;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function maybeInstallBundledPackages(options: SetupOptions): Promise<void> {
|
||||||
|
const agentDir = dirname(options.authPath);
|
||||||
|
const { missing, bundled } = getMissingConfiguredPackages(options.workingDir, agentDir, options.appRoot);
|
||||||
|
const userMissing = missing.filter((entry) => entry.scope === "user").map((entry) => entry.source);
|
||||||
|
const projectMissing = missing.filter((entry) => entry.scope === "project").map((entry) => entry.source);
|
||||||
|
|
||||||
|
printSection("Packages");
|
||||||
|
if (bundled.length > 0) {
|
||||||
|
printInfo(`Bundled research packages ready: ${summarizePackageSources(bundled.map((entry) => entry.source))}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (missing.length === 0) {
|
||||||
|
printInfo("No additional package install required.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printInfo(`Missing packages: ${summarizePackageSources(missing.map((entry) => entry.source))}`);
|
||||||
|
const shouldInstall = await promptConfirm("Install missing Feynman packages now?", true);
|
||||||
|
if (!shouldInstall) {
|
||||||
|
printInfo("Skipping package install. Feynman may install missing packages later if needed.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userMissing.length > 0) {
|
||||||
|
try {
|
||||||
|
await installPackageSources(options.workingDir, agentDir, userMissing);
|
||||||
|
printSuccess(`Installed bundled packages: ${summarizePackageSources(userMissing)}`);
|
||||||
|
} catch (error) {
|
||||||
|
const message = error instanceof Error ? error.message : String(error);
|
||||||
|
printInfo(message.includes("No supported package manager found")
|
||||||
|
? "No package manager available for additional installs. The standalone bundle can still run with its shipped packages."
|
||||||
|
: `Package install skipped: ${message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (projectMissing.length > 0) {
|
||||||
|
try {
|
||||||
|
await installPackageSources(options.workingDir, agentDir, projectMissing, { local: true });
|
||||||
|
printSuccess(`Installed project packages: ${summarizePackageSources(projectMissing)}`);
|
||||||
|
} catch (error) {
|
||||||
|
const message = error instanceof Error ? error.message : String(error);
|
||||||
|
printInfo(`Project package install skipped: ${message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function maybeInstallOptionalPackages(options: SetupOptions): Promise<void> {
|
||||||
|
const agentDir = dirname(options.authPath);
|
||||||
|
const presets = listOptionalPackagePresets();
|
||||||
|
if (presets.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectedPresets = await promptMultiSelect(
|
||||||
|
"Optional packages",
|
||||||
|
presets.map((preset) => ({
|
||||||
|
value: preset.name,
|
||||||
|
label: preset.name,
|
||||||
|
hint: preset.description,
|
||||||
|
})),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
if (selectedPresets.length === 0) {
|
||||||
|
printInfo("No optional packages selected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const presetName of selectedPresets) {
|
||||||
|
const preset = presets.find((entry) => entry.name === presetName);
|
||||||
|
if (!preset) continue;
|
||||||
|
try {
|
||||||
|
await installPackageSources(options.workingDir, agentDir, preset.sources, {
|
||||||
|
persist: true,
|
||||||
|
});
|
||||||
|
printSuccess(`Installed optional preset: ${preset.name}`);
|
||||||
|
} catch (error) {
|
||||||
|
const message = error instanceof Error ? error.message : String(error);
|
||||||
|
printInfo(message.includes("No supported package manager found")
|
||||||
|
? `Skipped optional preset ${preset.name}: no package manager available.`
|
||||||
|
: `Skipped optional preset ${preset.name}: ${message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function maybeLoginAlpha(): Promise<void> {
|
||||||
|
if (isAlphaLoggedIn()) {
|
||||||
|
printInfo("alphaXiv already configured.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const shouldLogin = await promptConfirm("Connect alphaXiv now?", true);
|
||||||
|
if (!shouldLogin) {
|
||||||
|
printInfo("Skipping alphaXiv login for now.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await loginAlpha();
|
||||||
|
printSuccess("alphaXiv login complete");
|
||||||
|
} catch (error) {
|
||||||
|
printInfo(`alphaXiv login skipped: ${error instanceof Error ? error.message : String(error)}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function maybeInstallPreviewDependencies(): Promise<void> {
|
||||||
|
if (resolveExecutable("pandoc", PANDOC_FALLBACK_PATHS)) {
|
||||||
|
printInfo("Preview support already configured.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const shouldInstall = await promptConfirm("Install pandoc for preview/export support?", false);
|
||||||
|
if (!shouldInstall) {
|
||||||
|
printInfo("Skipping preview dependency install.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = setupPreviewDependencies();
|
||||||
|
printSuccess(result.message);
|
||||||
|
} catch (error) {
|
||||||
|
printInfo(`Preview setup skipped: ${error instanceof Error ? error.message : String(error)}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function runSetup(options: SetupOptions): Promise<void> {
|
export async function runSetup(options: SetupOptions): Promise<void> {
|
||||||
if (!isInteractiveTerminal()) {
|
if (!isInteractiveTerminal()) {
|
||||||
printNonInteractiveSetupGuidance();
|
printNonInteractiveSetupGuidance();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await promptIntro("Feynman setup");
|
||||||
await runModelSetup(options.settingsPath, options.authPath);
|
await runModelSetup(options.settingsPath, options.authPath);
|
||||||
|
await maybeInstallBundledPackages(options);
|
||||||
if (!isAlphaLoggedIn()) {
|
await maybeInstallOptionalPackages(options);
|
||||||
await loginAlpha();
|
await maybeLoginAlpha();
|
||||||
printSuccess("alphaXiv login complete");
|
await maybeInstallPreviewDependencies();
|
||||||
}
|
|
||||||
|
|
||||||
const result = setupPreviewDependencies();
|
|
||||||
printSuccess(result.message);
|
|
||||||
|
|
||||||
normalizeFeynmanSettings(
|
normalizeFeynmanSettings(
|
||||||
options.settingsPath,
|
options.settingsPath,
|
||||||
@@ -67,4 +203,17 @@ export async function runSetup(options: SetupOptions): Promise<void> {
|
|||||||
printInfo(`alphaXiv: ${isAlphaLoggedIn() ? "configured" : "not configured"}`);
|
printInfo(`alphaXiv: ${isAlphaLoggedIn() ? "configured" : "not configured"}`);
|
||||||
printInfo(`Preview: ${resolveExecutable("pandoc", PANDOC_FALLBACK_PATHS) ? "configured" : "not configured"}`);
|
printInfo(`Preview: ${resolveExecutable("pandoc", PANDOC_FALLBACK_PATHS) ? "configured" : "not configured"}`);
|
||||||
printInfo(`Web: ${getPiWebAccessStatus().routeLabel}`);
|
printInfo(`Web: ${getPiWebAccessStatus().routeLabel}`);
|
||||||
|
if (modelStatus.recommended && !modelStatus.currentValid) {
|
||||||
|
printInfo(`Recommended model: ${modelStatus.recommended}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
await promptOutro("Feynman is ready");
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof SetupCancelledError) {
|
||||||
|
printInfo("Setup cancelled.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user