triage remaining tracker fixes
This commit is contained in:
@@ -140,3 +140,12 @@ Use this file to track chronology, not release notes. Keep entries short, factua
|
||||
- Failed / learned: The first packaged `search status` smoke test still showed the user home path because the native bundle had been built before the `FEYNMAN_HOME` path fix; rebuilding the native bundle resolved that mismatch.
|
||||
- Blockers: PowerShell runtime was unavailable locally, so Windows installer execution remained code-path validated rather than actually executed.
|
||||
- Next: Push the second-pass hardening commit, then keep issue `#46` and issue `#47` open until users on the affected Linux/CJK environments confirm whether the launcher/header fixes fully resolve them.
|
||||
|
||||
### 2026-04-09 10:36 PDT — remaining-tracker-triage-pass
|
||||
|
||||
- Objective: Reduce the remaining open tracker items by landing the lowest-risk missing docs/catalog updates and a targeted Cloud Code Assist compatibility patch instead of only hand-triaging them.
|
||||
- Changed: Added MiniMax M2.7 recommendation preferences in `src/model/catalog.ts`; documented model switching, authenticated-provider visibility, and `/feynman-model` subagent overrides in `website/src/content/docs/getting-started/configuration.md` and `website/src/content/docs/reference/slash-commands.md`; added a runtime patch helper in `scripts/lib/pi-google-legacy-schema-patch.mjs` and wired `scripts/patch-embedded-pi.mjs` to normalize JSON Schema `const` into `enum` for the legacy `parameters` field used by Cloud Code Assist Claude models.
|
||||
- Verified: Ran `npm test`, `npm run typecheck`, `npm run build`, and `cd website && npm run build` after the patch/helper/docs changes.
|
||||
- Failed / learned: The MiniMax provider catalog in Pi already uses canonical IDs like `MiniMax-M2.7`, so the only failure during validation was a test assertion using the wrong casing rather than a runtime bug.
|
||||
- Blockers: The Cloud Code Assist fix is validated by targeted patch tests and code-path review rather than an end-to-end Google account repro in this environment.
|
||||
- Next: Push the tracker-triage commit, close the docs/MiniMax PRs as superseded by main, close the support-style model issues against the new docs, and decide whether the remaining feature requests should be left open or closed as not planned/upstream-dependent.
|
||||
|
||||
1
scripts/lib/pi-google-legacy-schema-patch.d.mts
Normal file
1
scripts/lib/pi-google-legacy-schema-patch.d.mts
Normal file
@@ -0,0 +1 @@
|
||||
export function patchPiGoogleLegacySchemaSource(source: string): string;
|
||||
44
scripts/lib/pi-google-legacy-schema-patch.mjs
Normal file
44
scripts/lib/pi-google-legacy-schema-patch.mjs
Normal file
@@ -0,0 +1,44 @@
|
||||
const HELPER = [
|
||||
"function normalizeLegacyToolSchema(schema) {",
|
||||
" if (Array.isArray(schema)) return schema.map((item) => normalizeLegacyToolSchema(item));",
|
||||
' if (!schema || typeof schema !== "object") return schema;',
|
||||
" const normalized = {};",
|
||||
" for (const [key, value] of Object.entries(schema)) {",
|
||||
' if (key === "const") {',
|
||||
" normalized.enum = [value];",
|
||||
" continue;",
|
||||
" }",
|
||||
" normalized[key] = normalizeLegacyToolSchema(value);",
|
||||
" }",
|
||||
" return normalized;",
|
||||
"}",
|
||||
].join("\n");
|
||||
|
||||
const ORIGINAL =
|
||||
' ...(useParameters ? { parameters: tool.parameters } : { parametersJsonSchema: tool.parameters }),';
|
||||
const PATCHED = [
|
||||
" ...(useParameters",
|
||||
" ? { parameters: normalizeLegacyToolSchema(tool.parameters) }",
|
||||
" : { parametersJsonSchema: tool.parameters }),",
|
||||
].join("\n");
|
||||
|
||||
export function patchPiGoogleLegacySchemaSource(source) {
|
||||
let patched = source;
|
||||
|
||||
if (patched.includes("function normalizeLegacyToolSchema(schema) {")) {
|
||||
return patched;
|
||||
}
|
||||
|
||||
if (!patched.includes(ORIGINAL)) {
|
||||
return source;
|
||||
}
|
||||
|
||||
patched = patched.replace(ORIGINAL, PATCHED);
|
||||
const marker = "export function convertTools(tools, useParameters = false) {";
|
||||
const markerIndex = patched.indexOf(marker);
|
||||
if (markerIndex === -1) {
|
||||
return source;
|
||||
}
|
||||
|
||||
return `${patched.slice(0, markerIndex)}${HELPER}\n\n${patched.slice(markerIndex)}`;
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import { dirname, resolve } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { FEYNMAN_LOGO_HTML } from "../logo.mjs";
|
||||
import { patchPiExtensionLoaderSource } from "./lib/pi-extension-loader-patch.mjs";
|
||||
import { patchPiGoogleLegacySchemaSource } from "./lib/pi-google-legacy-schema-patch.mjs";
|
||||
import { PI_WEB_ACCESS_PATCH_TARGETS, patchPiWebAccessSource } from "./lib/pi-web-access-patch.mjs";
|
||||
import { PI_SUBAGENTS_PATCH_TARGETS, patchPiSubagentsSource } from "./lib/pi-subagents-patch.mjs";
|
||||
|
||||
@@ -616,6 +617,7 @@ if (existsSync(sessionSearchIndexerPath)) {
|
||||
}
|
||||
|
||||
const oauthPagePath = piAiRoot ? resolve(piAiRoot, "dist", "utils", "oauth", "oauth-page.js") : null;
|
||||
const googleSharedPath = piAiRoot ? resolve(piAiRoot, "dist", "providers", "google-shared.js") : null;
|
||||
|
||||
if (oauthPagePath && existsSync(oauthPagePath)) {
|
||||
let source = readFileSync(oauthPagePath, "utf8");
|
||||
@@ -628,6 +630,14 @@ if (oauthPagePath && existsSync(oauthPagePath)) {
|
||||
if (changed) writeFileSync(oauthPagePath, source, "utf8");
|
||||
}
|
||||
|
||||
if (googleSharedPath && existsSync(googleSharedPath)) {
|
||||
const source = readFileSync(googleSharedPath, "utf8");
|
||||
const patched = patchPiGoogleLegacySchemaSource(source);
|
||||
if (patched !== source) {
|
||||
writeFileSync(googleSharedPath, patched, "utf8");
|
||||
}
|
||||
}
|
||||
|
||||
const alphaHubAuthPath = findPackageRoot("@companion-ai/alpha-hub")
|
||||
? resolve(findPackageRoot("@companion-ai/alpha-hub"), "src", "lib", "auth.js")
|
||||
: null;
|
||||
|
||||
@@ -95,6 +95,14 @@ const RESEARCH_MODEL_PREFERENCES = [
|
||||
spec: "zai/glm-5",
|
||||
reason: "good fallback when GLM is the available research model",
|
||||
},
|
||||
{
|
||||
spec: "minimax/minimax-m2.7",
|
||||
reason: "good fallback when MiniMax is the available research model",
|
||||
},
|
||||
{
|
||||
spec: "minimax/minimax-m2.7-highspeed",
|
||||
reason: "good fallback when MiniMax is the available research model",
|
||||
},
|
||||
{
|
||||
spec: "kimi-coding/kimi-k2-thinking",
|
||||
reason: "good fallback when Kimi is the available research model",
|
||||
|
||||
@@ -57,6 +57,16 @@ test("buildModelStatusSnapshotFromRecords flags an invalid current model and sug
|
||||
assert.ok(snapshot.guidance.some((line) => line.includes("Configured default model is unavailable")));
|
||||
});
|
||||
|
||||
test("chooseRecommendedModel prefers MiniMax M2.7 over highspeed when that is the authenticated provider", () => {
|
||||
const authPath = createAuthPath({
|
||||
minimax: { type: "api_key", key: "minimax-test-key" },
|
||||
});
|
||||
|
||||
const recommendation = chooseRecommendedModel(authPath);
|
||||
|
||||
assert.equal(recommendation?.spec, "minimax/MiniMax-M2.7");
|
||||
});
|
||||
|
||||
test("resolveInitialPrompt maps top-level research commands to Pi slash workflows", () => {
|
||||
const workflows = new Set(["lit", "watch", "jobs", "deepresearch"]);
|
||||
assert.equal(resolveInitialPrompt("lit", ["tool-using", "agents"], undefined, workflows), "/lit tool-using agents");
|
||||
@@ -65,4 +75,3 @@ test("resolveInitialPrompt maps top-level research commands to Pi slash workflow
|
||||
assert.equal(resolveInitialPrompt("chat", ["hello"], undefined, workflows), "hello");
|
||||
assert.equal(resolveInitialPrompt("unknown", ["topic"], undefined, workflows), "unknown topic");
|
||||
});
|
||||
|
||||
|
||||
42
tests/pi-google-legacy-schema-patch.test.ts
Normal file
42
tests/pi-google-legacy-schema-patch.test.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
import { patchPiGoogleLegacySchemaSource } from "../scripts/lib/pi-google-legacy-schema-patch.mjs";
|
||||
|
||||
test("patchPiGoogleLegacySchemaSource rewrites legacy parameters conversion to normalize const", () => {
|
||||
const input = [
|
||||
"export function convertTools(tools, useParameters = false) {",
|
||||
" if (tools.length === 0) return undefined;",
|
||||
" return [",
|
||||
" {",
|
||||
" functionDeclarations: tools.map((tool) => ({",
|
||||
" name: tool.name,",
|
||||
" description: tool.description,",
|
||||
' ...(useParameters ? { parameters: tool.parameters } : { parametersJsonSchema: tool.parameters }),',
|
||||
" })),",
|
||||
" },",
|
||||
" ];",
|
||||
"}",
|
||||
"",
|
||||
].join("\n");
|
||||
|
||||
const patched = patchPiGoogleLegacySchemaSource(input);
|
||||
|
||||
assert.match(patched, /function normalizeLegacyToolSchema\(schema\)/);
|
||||
assert.match(patched, /normalized\.enum = \[value\]/);
|
||||
assert.match(patched, /parameters: normalizeLegacyToolSchema\(tool\.parameters\)/);
|
||||
});
|
||||
|
||||
test("patchPiGoogleLegacySchemaSource is idempotent", () => {
|
||||
const input = [
|
||||
"export function convertTools(tools, useParameters = false) {",
|
||||
' ...(useParameters ? { parameters: tool.parameters } : { parametersJsonSchema: tool.parameters }),',
|
||||
"}",
|
||||
"",
|
||||
].join("\n");
|
||||
|
||||
const once = patchPiGoogleLegacySchemaSource(input);
|
||||
const twice = patchPiGoogleLegacySchemaSource(once);
|
||||
|
||||
assert.equal(twice, once);
|
||||
});
|
||||
@@ -41,6 +41,36 @@ To see all models you have configured:
|
||||
feynman model list
|
||||
```
|
||||
|
||||
Only authenticated/configured providers appear in `feynman model list`. If you only see OpenAI models, it usually means only OpenAI auth is configured so far.
|
||||
|
||||
To add another provider, authenticate it first:
|
||||
|
||||
```bash
|
||||
feynman model login anthropic
|
||||
feynman model login google
|
||||
```
|
||||
|
||||
Then switch the default model:
|
||||
|
||||
```bash
|
||||
feynman model set anthropic/claude-opus-4-6
|
||||
```
|
||||
|
||||
## Subagent model overrides
|
||||
|
||||
Feynman's bundled subagents inherit the main default model unless you override them explicitly. Inside the REPL, run:
|
||||
|
||||
```bash
|
||||
/feynman-model
|
||||
```
|
||||
|
||||
This opens an interactive picker where you can either:
|
||||
|
||||
- change the main default model for the session environment
|
||||
- assign a different model to a specific bundled subagent such as `researcher`, `reviewer`, `writer`, or `verifier`
|
||||
|
||||
Per-subagent overrides are persisted in the synced agent files under `~/.feynman/agent/agents/` with a `model:` frontmatter field. Removing that field makes the subagent inherit the main default model again.
|
||||
|
||||
## Thinking levels
|
||||
|
||||
The `thinkingLevel` field controls how much reasoning the model does before responding. Available levels are `off`, `minimal`, `low`, `medium`, `high`, and `xhigh`. Higher levels produce more thorough analysis at the cost of latency and token usage. You can override per-session:
|
||||
|
||||
@@ -30,6 +30,7 @@ These are the primary commands you will use day-to-day. Each workflow dispatches
|
||||
| `/log` | Write a durable session log with completed work, findings, open questions, and next steps |
|
||||
| `/jobs` | Inspect active background work: running processes, scheduled follow-ups, and active watches |
|
||||
| `/help` | Show grouped Feynman commands and prefill the editor with a selected command |
|
||||
| `/feynman-model` | Open the model picker for the main default model and per-subagent overrides |
|
||||
| `/init` | Bootstrap `AGENTS.md` and session-log folders for a new research project |
|
||||
| `/outputs` | Browse all research artifacts (papers, outputs, experiments, notes) |
|
||||
| `/search` | Search prior session transcripts for past research and findings |
|
||||
@@ -37,6 +38,8 @@ These are the primary commands you will use day-to-day. Each workflow dispatches
|
||||
|
||||
Session management commands help you organize ongoing work. The `/log` command is particularly useful at the end of a research session to capture what was accomplished and what remains.
|
||||
|
||||
The `/feynman-model` command opens an interactive picker that lets you either change the main default model or assign a different model to a bundled subagent like `researcher`, `reviewer`, `writer`, or `verifier`.
|
||||
|
||||
## Running workflows from the CLI
|
||||
|
||||
All research workflow slash commands can also be run directly from the command line:
|
||||
|
||||
Reference in New Issue
Block a user