@companion-ai/feynman 0.2.7 → 0.2.9
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 +3 -3
- package/dist/model/commands.js +15 -2
- package/dist/ui/terminal.js +11 -0
- package/extensions/research-tools/header.ts +3 -1
- package/logo.d.mts +3 -0
- package/logo.mjs +15 -0
- package/package.json +3 -1
- package/scripts/patch-embedded-pi.mjs +10 -10
package/dist/cli.js
CHANGED
|
@@ -15,7 +15,7 @@ import { printSearchStatus } from "./search/commands.js";
|
|
|
15
15
|
import { runDoctor, runStatus } from "./setup/doctor.js";
|
|
16
16
|
import { setupPreviewDependencies } from "./setup/preview.js";
|
|
17
17
|
import { runSetup } from "./setup/setup.js";
|
|
18
|
-
import { printInfo, printPanel, printSection } from "./ui/terminal.js";
|
|
18
|
+
import { printAsciiHeader, printInfo, printPanel, printSection } from "./ui/terminal.js";
|
|
19
19
|
import { cliCommandSections, formatCliWorkflowUsage, legacyFlags, readPromptSpecs, topLevelCommandNames, } from "../metadata/commands.mjs";
|
|
20
20
|
const TOP_LEVEL_COMMANDS = new Set(topLevelCommandNames);
|
|
21
21
|
function printHelpLine(usage, description) {
|
|
@@ -25,7 +25,7 @@ function printHelpLine(usage, description) {
|
|
|
25
25
|
}
|
|
26
26
|
function printHelp(appRoot) {
|
|
27
27
|
const workflowCommands = readPromptSpecs(appRoot).filter((command) => command.section === "Research Workflows" && command.topLevelCli);
|
|
28
|
-
|
|
28
|
+
printAsciiHeader([
|
|
29
29
|
"Research-first agent shell built on Pi.",
|
|
30
30
|
"Use `feynman setup` first if this is a new machine.",
|
|
31
31
|
]);
|
|
@@ -87,7 +87,7 @@ async function handleModelCommand(subcommand, args, feynmanSettingsPath, feynman
|
|
|
87
87
|
return;
|
|
88
88
|
}
|
|
89
89
|
if (subcommand === "login") {
|
|
90
|
-
await loginModelProvider(feynmanAuthPath, args[0]);
|
|
90
|
+
await loginModelProvider(feynmanAuthPath, args[0], feynmanSettingsPath);
|
|
91
91
|
return;
|
|
92
92
|
}
|
|
93
93
|
if (subcommand === "logout") {
|
package/dist/model/commands.js
CHANGED
|
@@ -3,7 +3,7 @@ import { writeFileSync } from "node:fs";
|
|
|
3
3
|
import { readJson } from "../pi/settings.js";
|
|
4
4
|
import { promptChoice, promptText } from "../setup/prompts.js";
|
|
5
5
|
import { printInfo, printSection, printSuccess, printWarning } from "../ui/terminal.js";
|
|
6
|
-
import { buildModelStatusSnapshotFromRecords, getAvailableModelRecords, getSupportedModelRecords, } from "./catalog.js";
|
|
6
|
+
import { buildModelStatusSnapshotFromRecords, chooseRecommendedModel, getAvailableModelRecords, getSupportedModelRecords, } from "./catalog.js";
|
|
7
7
|
function collectModelStatus(settingsPath, authPath) {
|
|
8
8
|
return buildModelStatusSnapshotFromRecords(getSupportedModelRecords(authPath), getAvailableModelRecords(authPath), getCurrentModelSpec(settingsPath));
|
|
9
9
|
}
|
|
@@ -80,7 +80,7 @@ export function printModelList(settingsPath, authPath) {
|
|
|
80
80
|
printInfo(`${spec}${markers.length > 0 ? ` (${markers.join(", ")})` : ""}`);
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
|
-
export async function loginModelProvider(authPath, providerId) {
|
|
83
|
+
export async function loginModelProvider(authPath, providerId, settingsPath) {
|
|
84
84
|
const provider = providerId ? resolveOAuthProvider(authPath, providerId) : await selectOAuthProvider(authPath, "login");
|
|
85
85
|
if (!provider) {
|
|
86
86
|
if (providerId) {
|
|
@@ -111,6 +111,19 @@ export async function loginModelProvider(authPath, providerId) {
|
|
|
111
111
|
signal: abortController.signal,
|
|
112
112
|
});
|
|
113
113
|
printSuccess(`Model provider login complete: ${provider.id}`);
|
|
114
|
+
if (settingsPath) {
|
|
115
|
+
const currentSpec = getCurrentModelSpec(settingsPath);
|
|
116
|
+
const available = getAvailableModelRecords(authPath);
|
|
117
|
+
const currentValid = currentSpec
|
|
118
|
+
? available.some((m) => `${m.provider}/${m.id}` === currentSpec)
|
|
119
|
+
: false;
|
|
120
|
+
if ((!currentSpec || !currentValid) && available.length > 0) {
|
|
121
|
+
const recommended = chooseRecommendedModel(authPath);
|
|
122
|
+
if (recommended) {
|
|
123
|
+
setDefaultModelSpec(settingsPath, authPath, recommended.spec);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
114
127
|
}
|
|
115
128
|
export async function logoutModelProvider(authPath, providerId) {
|
|
116
129
|
const provider = providerId ? resolveOAuthProvider(authPath, providerId) : await selectOAuthProvider(authPath, "logout");
|
package/dist/ui/terminal.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { FEYNMAN_ASCII_LOGO } from "../../logo.mjs";
|
|
1
2
|
const RESET = "\x1b[0m";
|
|
2
3
|
const BOLD = "\x1b[1m";
|
|
3
4
|
const DIM = "\x1b[2m";
|
|
@@ -31,6 +32,16 @@ export function printSection(title) {
|
|
|
31
32
|
console.log("");
|
|
32
33
|
console.log(paint(`◆ ${title}`, TEAL, BOLD));
|
|
33
34
|
}
|
|
35
|
+
export function printAsciiHeader(subtitleLines = []) {
|
|
36
|
+
console.log("");
|
|
37
|
+
for (const line of FEYNMAN_ASCII_LOGO) {
|
|
38
|
+
console.log(paint(` ${line}`, TEAL, BOLD));
|
|
39
|
+
}
|
|
40
|
+
for (const line of subtitleLines) {
|
|
41
|
+
console.log(paint(` ${line}`, ASH));
|
|
42
|
+
}
|
|
43
|
+
console.log("");
|
|
44
|
+
}
|
|
34
45
|
export function printPanel(title, subtitleLines = []) {
|
|
35
46
|
const inner = 53;
|
|
36
47
|
const border = "─".repeat(inner + 2);
|
|
@@ -230,8 +230,10 @@ export function installFeynmanHeader(
|
|
|
230
230
|
|
|
231
231
|
push("");
|
|
232
232
|
if (cardW >= 70) {
|
|
233
|
+
const maxLogoW = Math.max(...FEYNMAN_AGENT_LOGO.map((l) => l.length));
|
|
234
|
+
const logoOffset = " ".repeat(Math.max(0, Math.floor((cardW - maxLogoW) / 2)));
|
|
233
235
|
for (const logoLine of FEYNMAN_AGENT_LOGO) {
|
|
234
|
-
push(theme.fg("accent", theme.bold(
|
|
236
|
+
push(theme.fg("accent", theme.bold(`${logoOffset}${truncateVisible(logoLine, cardW)}`)));
|
|
235
237
|
}
|
|
236
238
|
push("");
|
|
237
239
|
}
|
package/logo.d.mts
ADDED
package/logo.mjs
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export const FEYNMAN_ASCII_LOGO = [
|
|
2
|
+
" ██████",
|
|
3
|
+
" ███",
|
|
4
|
+
"█████████ ████████ ███ ███ ███ ██████ ██ ███ ████ ███████ ███ ██████",
|
|
5
|
+
" ███ ███ ███ ███ ███ ████ ███ ███ ██ ███ ███ ████ ███",
|
|
6
|
+
" ███ ████████████ ███ ███ ███ ███ ███ ██ ███ █████████ ███ ███",
|
|
7
|
+
" ███ ███ ██ ███ ███ ███ ███ ██ ███ ███ ███ ███ ███",
|
|
8
|
+
"███████ ████████ ████ ███ ███ ███ ██ ███ ██████ ███ ███ ███",
|
|
9
|
+
" ███",
|
|
10
|
+
" █████",
|
|
11
|
+
];
|
|
12
|
+
|
|
13
|
+
export const FEYNMAN_ASCII_LOGO_TEXT = FEYNMAN_ASCII_LOGO.join("\n");
|
|
14
|
+
|
|
15
|
+
export const FEYNMAN_LOGO_HTML = `<link href="https://fonts.googleapis.com/css2?family=VT323&display=swap" rel="stylesheet"><span style="font-family:'VT323',monospace;font-size:64px;letter-spacing:-0.05em;color:#10b981">feynman</span>`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@companion-ai/feynman",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.9",
|
|
4
4
|
"description": "Research-first CLI agent built on Pi and alphaXiv",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -19,6 +19,8 @@
|
|
|
19
19
|
".feynman/themes/",
|
|
20
20
|
"extensions/",
|
|
21
21
|
"prompts/",
|
|
22
|
+
"logo.mjs",
|
|
23
|
+
"logo.d.mts",
|
|
22
24
|
"scripts/",
|
|
23
25
|
"skills/",
|
|
24
26
|
"AGENTS.md",
|
|
@@ -2,7 +2,7 @@ import { spawnSync } from "node:child_process";
|
|
|
2
2
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { dirname, resolve } from "node:path";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
|
-
import {
|
|
5
|
+
import { FEYNMAN_LOGO_HTML } from "../logo.mjs";
|
|
6
6
|
|
|
7
7
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
8
8
|
const appRoot = resolve(here, "..");
|
|
@@ -365,7 +365,7 @@ if (oauthPagePath && existsSync(oauthPagePath)) {
|
|
|
365
365
|
let source = readFileSync(oauthPagePath, "utf8");
|
|
366
366
|
const piLogo = 'const LOGO_SVG = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 800" aria-hidden="true"><path fill="#fff" fill-rule="evenodd" d="M165.29 165.29 H517.36 V400 H400 V517.36 H282.65 V634.72 H165.29 Z M282.65 282.65 V400 H400 V282.65 Z"/><path fill="#fff" d="M517.36 400 H634.72 V634.72 H517.36 Z"/></svg>`;';
|
|
367
367
|
if (source.includes(piLogo)) {
|
|
368
|
-
const feynmanLogo = `const LOGO_SVG = \`${
|
|
368
|
+
const feynmanLogo = `const LOGO_SVG = \`${FEYNMAN_LOGO_HTML}\`;`;
|
|
369
369
|
source = source.replace(piLogo, feynmanLogo);
|
|
370
370
|
writeFileSync(oauthPagePath, source, "utf8");
|
|
371
371
|
}
|
|
@@ -377,17 +377,17 @@ const alphaHubAuthPath = findPackageRoot("@companion-ai/alpha-hub")
|
|
|
377
377
|
|
|
378
378
|
if (alphaHubAuthPath && existsSync(alphaHubAuthPath)) {
|
|
379
379
|
let source = readFileSync(alphaHubAuthPath, "utf8");
|
|
380
|
-
const
|
|
381
|
-
const
|
|
382
|
-
const
|
|
383
|
-
const
|
|
384
|
-
const
|
|
385
|
-
const
|
|
380
|
+
const oldSuccess = "'<html><body><h2>Logged in to Alpha Hub</h2><p>You can close this tab.</p></body></html>'";
|
|
381
|
+
const oldError = "'<html><body><h2>Login failed</h2><p>You can close this tab.</p></body></html>'";
|
|
382
|
+
const bodyAttr = `style="font-family:system-ui,sans-serif;text-align:center;padding-top:20vh;background:#050a08;color:#f0f5f2"`;
|
|
383
|
+
const logo = `<h1 style="font-family:monospace;font-size:48px;color:#34d399;margin:0">feynman</h1>`;
|
|
384
|
+
const newSuccess = `'<html><body ${bodyAttr}>${logo}<h2 style="color:#34d399;margin-top:16px">Logged in</h2><p style="color:#8aaa9a">You can close this tab.</p></body></html>'`;
|
|
385
|
+
const newError = `'<html><body ${bodyAttr}>${logo}<h2 style="color:#ef4444;margin-top:16px">Login failed</h2><p style="color:#8aaa9a">You can close this tab.</p></body></html>'`;
|
|
386
386
|
if (source.includes(oldSuccess)) {
|
|
387
|
-
source = source.replace(oldSuccess,
|
|
387
|
+
source = source.replace(oldSuccess, newSuccess);
|
|
388
388
|
}
|
|
389
389
|
if (source.includes(oldError)) {
|
|
390
|
-
source = source.replace(oldError,
|
|
390
|
+
source = source.replace(oldError, newError);
|
|
391
391
|
}
|
|
392
392
|
writeFileSync(alphaHubAuthPath, source, "utf8");
|
|
393
393
|
}
|