@companion-ai/feynman 0.2.9 → 0.2.10

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 CHANGED
@@ -10,7 +10,7 @@ import { ensureFeynmanHome, getDefaultSessionDir, getFeynmanAgentDir, getFeynman
10
10
  import { launchPiChat } from "./pi/launch.js";
11
11
  import { CORE_PACKAGE_SOURCES, getOptionalPackagePresetSources, listOptionalPackagePresets } from "./pi/package-presets.js";
12
12
  import { normalizeFeynmanSettings, normalizeThinkingLevel, parseModelSpec } from "./pi/settings.js";
13
- import { loginModelProvider, logoutModelProvider, printModelList, setDefaultModelSpec, } from "./model/commands.js";
13
+ import { getCurrentModelSpec, loginModelProvider, logoutModelProvider, printModelList, setDefaultModelSpec, } from "./model/commands.js";
14
14
  import { printSearchStatus } from "./search/commands.js";
15
15
  import { runDoctor, runStatus } from "./setup/doctor.js";
16
16
  import { setupPreviewDependencies } from "./setup/preview.js";
@@ -347,6 +347,21 @@ export async function main() {
347
347
  throw new Error(`Unknown model: ${explicitModelSpec}`);
348
348
  }
349
349
  }
350
+ if (!explicitModelSpec && !getCurrentModelSpec(feynmanSettingsPath) && process.stdin.isTTY && process.stdout.isTTY) {
351
+ await runSetup({
352
+ settingsPath: feynmanSettingsPath,
353
+ bundledSettingsPath,
354
+ authPath: feynmanAuthPath,
355
+ workingDir,
356
+ sessionDir,
357
+ appRoot,
358
+ defaultThinkingLevel: thinkingLevel,
359
+ });
360
+ if (!getCurrentModelSpec(feynmanSettingsPath)) {
361
+ return;
362
+ }
363
+ normalizeFeynmanSettings(feynmanSettingsPath, bundledSettingsPath, thinkingLevel, feynmanAuthPath);
364
+ }
350
365
  await launchPiChat({
351
366
  appRoot,
352
367
  workingDir,
@@ -151,28 +151,20 @@ export function setDefaultModelSpec(settingsPath, authPath, spec) {
151
151
  printSuccess(`Default model set to ${resolvedSpec}`);
152
152
  }
153
153
  export async function runModelSetup(settingsPath, authPath) {
154
- const status = collectModelStatus(settingsPath, authPath);
154
+ let status = collectModelStatus(settingsPath, authPath);
155
155
  if (status.availableModels.length === 0) {
156
- printWarning("No Pi models are currently authenticated for Feynman.");
157
- for (const line of status.guidance) {
158
- printInfo(line);
156
+ await loginModelProvider(authPath, undefined, settingsPath);
157
+ status = collectModelStatus(settingsPath, authPath);
158
+ if (status.availableModels.length === 0) {
159
+ return;
159
160
  }
160
- printInfo("Tip: run `feynman model login <provider>` if your provider supports Pi OAuth login.");
161
- return;
162
161
  }
163
- const choices = status.availableModels.map((spec) => {
164
- const markers = [
165
- spec === status.recommended ? "recommended" : undefined,
166
- spec === status.current ? "current" : undefined,
167
- ].filter(Boolean);
168
- return `${spec}${markers.length > 0 ? ` (${markers.join(", ")})` : ""}`;
169
- });
170
- choices.push(`Keep current (${status.current ?? "unset"})`);
171
- const defaultIndex = status.current ? Math.max(0, status.availableModels.indexOf(status.current)) : 0;
172
- const selection = await promptChoice("Select your default research model:", choices, defaultIndex >= 0 ? defaultIndex : 0);
173
- if (selection >= status.availableModels.length) {
174
- printInfo("Skipped (keeping current model)");
162
+ if (status.currentValid) {
163
+ printInfo(`Model: ${status.current}`);
175
164
  return;
176
165
  }
177
- setDefaultModelSpec(settingsPath, authPath, status.availableModels[selection]);
166
+ const recommended = status.recommended ?? status.availableModels[0];
167
+ if (recommended) {
168
+ setDefaultModelSpec(settingsPath, authPath, recommended);
169
+ }
178
170
  }
@@ -1,119 +1,38 @@
1
1
  import { isLoggedIn as isAlphaLoggedIn, login as loginAlpha } from "@companion-ai/alpha-hub/lib";
2
- import { getDefaultSessionDir, getFeynmanHome } from "../config/paths.js";
3
- import { getPiWebAccessStatus, getPiWebSearchConfigPath } from "../pi/web-access.js";
2
+ import { getPiWebAccessStatus } from "../pi/web-access.js";
4
3
  import { normalizeFeynmanSettings } from "../pi/settings.js";
5
4
  import { getCurrentModelSpec, runModelSetup } from "../model/commands.js";
6
5
  import { buildModelStatusSnapshotFromRecords, getAvailableModelRecords, getSupportedModelRecords } from "../model/catalog.js";
7
6
  import { PANDOC_FALLBACK_PATHS, resolveExecutable } from "../system/executables.js";
8
- import { promptText } from "./prompts.js";
9
7
  import { setupPreviewDependencies } from "./preview.js";
10
- import { runDoctor } from "./doctor.js";
11
- import { printInfo, printPanel, printSection, printSuccess } from "../ui/terminal.js";
12
- async function explainWebAccess() {
13
- const status = getPiWebAccessStatus();
14
- printSection("Web Access");
15
- printInfo("Feynman uses the bundled `pi-web-access` package directly.");
16
- printInfo("Default v1 path: sign into gemini.google.com in a supported Chromium browser.");
17
- printInfo(`Current search route: ${status.routeLabel}`);
18
- printInfo(`Pi config path: ${status.configPath}`);
19
- printInfo("Advanced users can edit the Pi config directly if they want API keys or a different route.");
20
- }
21
- function isPreviewConfigured() {
22
- return Boolean(resolveExecutable("pandoc", PANDOC_FALLBACK_PATHS));
23
- }
8
+ import { printInfo, printSection, printSuccess } from "../ui/terminal.js";
24
9
  function isInteractiveTerminal() {
25
10
  return Boolean(process.stdin.isTTY && process.stdout.isTTY);
26
11
  }
27
12
  function printNonInteractiveSetupGuidance() {
28
- printPanel("Feynman Setup", [
29
- "Non-interactive terminal detected.",
30
- ]);
31
- printInfo("Use the explicit commands instead of the interactive setup wizard:");
32
- printInfo(" feynman status");
13
+ printInfo("Non-interactive terminal. Use explicit commands:");
33
14
  printInfo(" feynman model login <provider>");
34
15
  printInfo(" feynman model set <provider/model>");
35
- printInfo(" feynman search status");
36
- printInfo(` edit ${getPiWebSearchConfigPath()} # optional advanced web config`);
37
16
  printInfo(" feynman alpha login");
38
17
  printInfo(" feynman doctor");
39
- printInfo(" feynman # Pi's /login flow still works inside chat if you prefer it");
40
- }
41
- async function runPreviewSetup() {
42
- const result = setupPreviewDependencies();
43
- printSuccess(result.message);
44
- }
45
- function printConfigurationLocation(appRoot) {
46
- printSection("Configuration Location");
47
- printInfo(`Data folder: ${getFeynmanHome()}`);
48
- printInfo(`Sessions: ${getDefaultSessionDir()}`);
49
- printInfo(`Install dir: ${appRoot}`);
50
18
  }
51
- function printSetupSummary(settingsPath, authPath) {
52
- const modelStatus = buildModelStatusSnapshotFromRecords(getSupportedModelRecords(authPath), getAvailableModelRecords(authPath), getCurrentModelSpec(settingsPath));
53
- printSection("Setup Summary");
54
- printInfo(`Model: ${getCurrentModelSpec(settingsPath) ?? "not set"}`);
55
- printInfo(`Model valid: ${modelStatus.currentValid ? "yes" : "no"}`);
56
- printInfo(`Recommended model: ${modelStatus.recommended ?? "not available"}`);
57
- printInfo(`alphaXiv: ${isAlphaLoggedIn() ? "configured" : "missing"}`);
58
- printInfo(`Web access: pi-web-access (${getPiWebAccessStatus().routeLabel})`);
59
- printInfo(`Preview: ${isPreviewConfigured() ? "configured" : "not configured"}`);
60
- for (const line of modelStatus.guidance) {
61
- printInfo(line);
19
+ export async function runSetup(options) {
20
+ if (!isInteractiveTerminal()) {
21
+ printNonInteractiveSetupGuidance();
22
+ return;
62
23
  }
63
- }
64
- async function runFullSetup(options) {
65
- printConfigurationLocation(options.appRoot);
66
24
  await runModelSetup(options.settingsPath, options.authPath);
67
25
  if (!isAlphaLoggedIn()) {
68
26
  await loginAlpha();
69
27
  printSuccess("alphaXiv login complete");
70
28
  }
71
- else {
72
- printInfo("alphaXiv login already configured");
73
- }
74
- await explainWebAccess();
75
- await runPreviewSetup();
29
+ const result = setupPreviewDependencies();
30
+ printSuccess(result.message);
76
31
  normalizeFeynmanSettings(options.settingsPath, options.bundledSettingsPath, options.defaultThinkingLevel ?? "medium", options.authPath);
77
- runDoctor({
78
- settingsPath: options.settingsPath,
79
- authPath: options.authPath,
80
- sessionDir: options.sessionDir,
81
- workingDir: options.workingDir,
82
- appRoot: options.appRoot,
83
- });
84
- printSetupSummary(options.settingsPath, options.authPath);
85
- }
86
- function hasExistingSetup(settingsPath, authPath) {
87
- const modelStatus = buildModelStatusSnapshotFromRecords(getSupportedModelRecords(authPath), getAvailableModelRecords(authPath), getCurrentModelSpec(settingsPath));
88
- return Boolean(modelStatus.current ||
89
- modelStatus.availableModels.length > 0 ||
90
- isAlphaLoggedIn() ||
91
- isPreviewConfigured());
92
- }
93
- async function runDefaultInteractiveSetup(options) {
94
- const existing = hasExistingSetup(options.settingsPath, options.authPath);
95
- printPanel("Feynman Setup Wizard", [
96
- "Guided setup for the research-first Pi agent.",
97
- "Press Ctrl+C at any time to exit.",
98
- ]);
99
- if (existing) {
100
- printSection("Full Setup");
101
- printInfo("Existing configuration detected. Rerunning the full guided setup.");
102
- }
103
- else {
104
- printInfo("We'll walk you through:");
105
- printInfo(" 1. Model Selection");
106
- printInfo(" 2. alphaXiv Login");
107
- printInfo(" 3. Preview Dependencies");
108
- }
109
- printInfo("Press Enter to begin, or Ctrl+C to exit.");
110
- await promptText("Press Enter to start");
111
- await runFullSetup(options);
112
- }
113
- export async function runSetup(options) {
114
- if (!isInteractiveTerminal()) {
115
- printNonInteractiveSetupGuidance();
116
- return;
117
- }
118
- await runDefaultInteractiveSetup(options);
32
+ const modelStatus = buildModelStatusSnapshotFromRecords(getSupportedModelRecords(options.authPath), getAvailableModelRecords(options.authPath), getCurrentModelSpec(options.settingsPath));
33
+ printSection("Ready");
34
+ printInfo(`Model: ${getCurrentModelSpec(options.settingsPath) ?? "not set"}`);
35
+ printInfo(`alphaXiv: ${isAlphaLoggedIn() ? "configured" : "not configured"}`);
36
+ printInfo(`Preview: ${resolveExecutable("pandoc", PANDOC_FALLBACK_PATHS) ? "configured" : "not configured"}`);
37
+ printInfo(`Web: ${getPiWebAccessStatus().routeLabel}`);
119
38
  }
package/logo.mjs CHANGED
@@ -12,4 +12,4 @@ export const FEYNMAN_ASCII_LOGO = [
12
12
 
13
13
  export const FEYNMAN_ASCII_LOGO_TEXT = FEYNMAN_ASCII_LOGO.join("\n");
14
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>`;
15
+ export const FEYNMAN_LOGO_HTML = `<style>@import url('https://fonts.googleapis.com/css2?family=VT323&display=swap');.logo{width:auto!important;height:auto!important}</style><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.9",
3
+ "version": "0.2.10",
4
4
  "description": "Research-first CLI agent built on Pi and alphaXiv",
5
5
  "type": "module",
6
6
  "engines": {