@agentprojectcontext/apx 1.65.2 → 1.66.0
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/package.json +1 -1
- package/src/core/config/index.js +1 -1
- package/src/core/engines/presets.js +102 -0
- package/src/core/voice/engines/gemini.js +7 -8
- package/src/host/daemon/api/engines.js +6 -0
- package/src/interfaces/cli/commands/setup.js +7 -4
- package/src/interfaces/web/dist/assets/{index-CFcs16SV.js → index-YmMRG--4.js} +134 -134
- package/src/interfaces/web/dist/assets/index-YmMRG--4.js.map +1 -0
- package/src/interfaces/web/dist/index.html +1 -1
- package/src/interfaces/web/src/components/settings/providers/typeStyles.ts +44 -25
- package/src/interfaces/web/src/lib/api/engines.ts +14 -0
- package/src/interfaces/web/src/main.tsx +5 -0
- package/src/interfaces/web/dist/assets/index-CFcs16SV.js.map +0 -1
package/package.json
CHANGED
package/src/core/config/index.js
CHANGED
|
@@ -152,7 +152,7 @@ const DEFAULT_CONFIG = {
|
|
|
152
152
|
piper: { bin: "piper", model: "", speaker: "", extra_args: [] },
|
|
153
153
|
elevenlabs: { api_key: "", model: "eleven_multilingual_v2", voice_id: "", output_format: "mp3_44100_128" },
|
|
154
154
|
openai: { api_key: "", model: "tts-1", voice: "alloy", format: "mp3" },
|
|
155
|
-
gemini: { api_key: "", model: "gemini-2.5-flash-
|
|
155
|
+
gemini: { api_key: "", model: "gemini-2.5-flash-tts", voice: "Kore" },
|
|
156
156
|
},
|
|
157
157
|
},
|
|
158
158
|
};
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// Curated engine catalog — the SINGLE SOURCE OF TRUTH for the known models,
|
|
2
|
+
// per-engine defaults, base URLs and api-key env vars shown across APX.
|
|
3
|
+
//
|
|
4
|
+
// Who consumes this:
|
|
5
|
+
// • CLI — `apx setup` builds its provider/model menus from here
|
|
6
|
+
// (src/interfaces/cli/commands/setup.js).
|
|
7
|
+
// • Web — the admin panel fetches it via `GET /engines/presets` and hydrates
|
|
8
|
+
// its provider forms (src/interfaces/web/.../providers/typeStyles.ts).
|
|
9
|
+
//
|
|
10
|
+
// This is the OFFLINE / no-key fallback list. When the user has an api_key
|
|
11
|
+
// configured, the daemon's `POST /engines/models` returns the provider's LIVE
|
|
12
|
+
// catalog instead (see ./catalog.js). The model field is ALWAYS free-text, so
|
|
13
|
+
// any id can be typed even if it is not listed here.
|
|
14
|
+
//
|
|
15
|
+
// `ollama` and `custom` are intentionally dynamic — no curated model list.
|
|
16
|
+
// Update model ids in THIS file only; every surface reflects the change.
|
|
17
|
+
|
|
18
|
+
/** @typedef {{ base_url: string, default_model: string, api_key_env: string, known_models: string[] }} EnginePreset */
|
|
19
|
+
|
|
20
|
+
/** @type {Record<string, EnginePreset>} */
|
|
21
|
+
export const ENGINE_PRESETS = {
|
|
22
|
+
anthropic: {
|
|
23
|
+
base_url: "", // empty ⇒ adapter uses the built-in Anthropic endpoint
|
|
24
|
+
default_model: "claude-sonnet-5",
|
|
25
|
+
api_key_env: "ANTHROPIC_API_KEY",
|
|
26
|
+
known_models: [
|
|
27
|
+
"claude-opus-4-8",
|
|
28
|
+
"claude-sonnet-5",
|
|
29
|
+
"claude-haiku-4-5",
|
|
30
|
+
"claude-fable-5",
|
|
31
|
+
],
|
|
32
|
+
},
|
|
33
|
+
openai: {
|
|
34
|
+
base_url: "https://api.openai.com/v1",
|
|
35
|
+
default_model: "gpt-5.4-mini",
|
|
36
|
+
api_key_env: "OPENAI_API_KEY",
|
|
37
|
+
known_models: [
|
|
38
|
+
"gpt-5.5",
|
|
39
|
+
"gpt-5.4-mini",
|
|
40
|
+
"gpt-5.4-nano",
|
|
41
|
+
"gpt-5.1",
|
|
42
|
+
"gpt-4.1-mini",
|
|
43
|
+
],
|
|
44
|
+
},
|
|
45
|
+
gemini: {
|
|
46
|
+
base_url: "https://generativelanguage.googleapis.com/v1beta/openai",
|
|
47
|
+
default_model: "gemini-2.5-flash",
|
|
48
|
+
api_key_env: "GEMINI_API_KEY",
|
|
49
|
+
known_models: [
|
|
50
|
+
"gemini-3.5-flash",
|
|
51
|
+
"gemini-3.1-pro-preview",
|
|
52
|
+
"gemini-2.5-pro",
|
|
53
|
+
"gemini-2.5-flash",
|
|
54
|
+
"gemini-2.5-flash-lite",
|
|
55
|
+
],
|
|
56
|
+
},
|
|
57
|
+
groq: {
|
|
58
|
+
base_url: "https://api.groq.com/openai/v1",
|
|
59
|
+
default_model: "openai/gpt-oss-20b",
|
|
60
|
+
api_key_env: "GROQ_API_KEY",
|
|
61
|
+
known_models: [
|
|
62
|
+
"openai/gpt-oss-120b",
|
|
63
|
+
"openai/gpt-oss-20b",
|
|
64
|
+
"qwen/qwen3.6-27b",
|
|
65
|
+
"groq/compound",
|
|
66
|
+
"groq/compound-mini",
|
|
67
|
+
"whisper-large-v3-turbo",
|
|
68
|
+
],
|
|
69
|
+
},
|
|
70
|
+
openrouter: {
|
|
71
|
+
base_url: "https://openrouter.ai/api/v1",
|
|
72
|
+
// openrouter/auto = "Auto Router": OpenRouter picks the best model.
|
|
73
|
+
default_model: "openrouter/auto",
|
|
74
|
+
api_key_env: "OPENROUTER_API_KEY",
|
|
75
|
+
known_models: [
|
|
76
|
+
"openrouter/auto",
|
|
77
|
+
"openrouter/free",
|
|
78
|
+
"anthropic/claude-sonnet-5",
|
|
79
|
+
"openai/gpt-5.4-mini",
|
|
80
|
+
"google/gemini-2.5-flash",
|
|
81
|
+
],
|
|
82
|
+
},
|
|
83
|
+
azure: {
|
|
84
|
+
base_url: "",
|
|
85
|
+
default_model: "", // Azure deployment names are user-defined
|
|
86
|
+
api_key_env: "AZURE_OPENAI_API_KEY",
|
|
87
|
+
known_models: [],
|
|
88
|
+
},
|
|
89
|
+
ollama: {
|
|
90
|
+
base_url: "http://127.0.0.1:11434",
|
|
91
|
+
default_model: "gemma2:9b",
|
|
92
|
+
api_key_env: "",
|
|
93
|
+
known_models: [], // dynamic — fetched live from the local Ollama daemon
|
|
94
|
+
},
|
|
95
|
+
mock: { base_url: "", default_model: "mock", api_key_env: "", known_models: ["mock"] },
|
|
96
|
+
custom: { base_url: "", default_model: "", api_key_env: "", known_models: [] },
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
/** Known models for one engine, or [] if the engine is dynamic/unknown. */
|
|
100
|
+
export function knownModels(engine) {
|
|
101
|
+
return ENGINE_PRESETS[engine]?.known_models ?? [];
|
|
102
|
+
}
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
// Gemini TTS adapter.
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
// include inline audio data.
|
|
2
|
+
// The Gemini TTS surface can vary across SDK versions: some models
|
|
3
|
+
// (gemini-2.5-flash-tts) expose synthesize via the v1beta REST surface, others
|
|
4
|
+
// require Vertex. To keep APX engine-agnostic, this adapter performs a
|
|
5
|
+
// best-effort call against the documented REST shape, but flags itself as
|
|
6
|
+
// not-implemented when the response does not include inline audio data.
|
|
8
7
|
//
|
|
9
8
|
// Config (~/.apx/config.json → voice.tts.gemini):
|
|
10
|
-
// { "api_key": "...", "model": "gemini-2.5-flash-
|
|
9
|
+
// { "api_key": "...", "model": "gemini-2.5-flash-tts", "voice": "Kore",
|
|
11
10
|
// "style": "habla en tono alegre y enérgico" }
|
|
12
11
|
//
|
|
13
12
|
// `style` is an optional natural-language instruction describing HOW the voice
|
|
@@ -22,7 +21,7 @@ import fs from "node:fs";
|
|
|
22
21
|
import path from "node:path";
|
|
23
22
|
import { randomUUID } from "node:crypto";
|
|
24
23
|
|
|
25
|
-
const DEFAULT_MODEL = "gemini-2.5-flash-
|
|
24
|
+
const DEFAULT_MODEL = "gemini-2.5-flash-tts";
|
|
26
25
|
|
|
27
26
|
function getKey(config, parentEnginesCfg) {
|
|
28
27
|
return (
|
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
// GET /engines — list engine adapter ids known to core/engines.
|
|
2
|
+
// GET /engines/presets — curated catalog (known models, defaults) per engine.
|
|
2
3
|
// POST /engines/models — live model catalog from a provider.
|
|
3
4
|
// GET /engines/models — legacy (Ollama only, no auth).
|
|
4
5
|
import { ENGINE_IDS } from "#core/engines/index.js";
|
|
5
6
|
import { listModels } from "#core/engines/catalog.js";
|
|
7
|
+
import { ENGINE_PRESETS } from "#core/engines/presets.js";
|
|
6
8
|
|
|
7
9
|
export function register(app, { config }) {
|
|
8
10
|
app.get("/engines", (_req, res) => res.json({ engines: ENGINE_IDS }));
|
|
9
11
|
|
|
12
|
+
// Curated fallback catalog shared with the CLI wizard. The web hydrates its
|
|
13
|
+
// provider forms from here so model lists never drift between surfaces.
|
|
14
|
+
app.get("/engines/presets", (_req, res) => res.json({ presets: ENGINE_PRESETS }));
|
|
15
|
+
|
|
10
16
|
app.post("/engines/models", async (req, res) => {
|
|
11
17
|
const b = req.body || {};
|
|
12
18
|
const engine = String(b.engine || "").toLowerCase();
|
|
@@ -8,6 +8,7 @@ import http from "node:http";
|
|
|
8
8
|
import readline from "node:readline";
|
|
9
9
|
import { spawnSync } from "node:child_process";
|
|
10
10
|
import { readConfig, writeConfig } from "#core/config/index.js";
|
|
11
|
+
import { ENGINE_PRESETS } from "#core/engines/presets.js";
|
|
11
12
|
import { mascot } from "#core/mascot.js";
|
|
12
13
|
import { setupClaudePermissions } from "../claude-permissions.js";
|
|
13
14
|
import { PERMISSION_MODES, DEFAULT_PERMISSION_MODE } from "#core/constants/permissions.js";
|
|
@@ -59,6 +60,8 @@ async function fetchOllamaModels(baseUrl) {
|
|
|
59
60
|
}
|
|
60
61
|
|
|
61
62
|
// ── Provider definitions ──────────────────────────────────────────────────────
|
|
63
|
+
// Model lists come from the shared catalog (#core/engines/presets.js) so the CLI
|
|
64
|
+
// and the web admin panel never drift. Ollama stays dynamic (fetched at runtime).
|
|
62
65
|
const PROVIDERS = [
|
|
63
66
|
{
|
|
64
67
|
id: "anthropic",
|
|
@@ -66,7 +69,7 @@ const PROVIDERS = [
|
|
|
66
69
|
needsKey: true,
|
|
67
70
|
keyLabel: "Anthropic API key",
|
|
68
71
|
keyHint: "sk-ant-...",
|
|
69
|
-
models:
|
|
72
|
+
models: ENGINE_PRESETS.anthropic.known_models,
|
|
70
73
|
},
|
|
71
74
|
{
|
|
72
75
|
id: "openai",
|
|
@@ -74,7 +77,7 @@ const PROVIDERS = [
|
|
|
74
77
|
needsKey: true,
|
|
75
78
|
keyLabel: "OpenAI API key",
|
|
76
79
|
keyHint: "sk-...",
|
|
77
|
-
models:
|
|
80
|
+
models: ENGINE_PRESETS.openai.known_models,
|
|
78
81
|
},
|
|
79
82
|
{
|
|
80
83
|
id: "ollama",
|
|
@@ -88,7 +91,7 @@ const PROVIDERS = [
|
|
|
88
91
|
needsKey: true,
|
|
89
92
|
keyLabel: "Gemini API key",
|
|
90
93
|
keyHint: "AIza...",
|
|
91
|
-
models:
|
|
94
|
+
models: ENGINE_PRESETS.gemini.known_models,
|
|
92
95
|
},
|
|
93
96
|
];
|
|
94
97
|
|
|
@@ -254,7 +257,7 @@ export async function cmdSetup() {
|
|
|
254
257
|
console.log(` ${cy("2")}. piper ${di("(local, offline; needs piper CLI + voice model)")}`);
|
|
255
258
|
console.log(` ${cy("3")}. elevenlabs ${di("(cloud; eleven_multilingual_v2)")}`);
|
|
256
259
|
console.log(` ${cy("4")}. openai ${di("(cloud; tts-1, reuses your openai key)")}`);
|
|
257
|
-
console.log(` ${cy("5")}. gemini ${di("(
|
|
260
|
+
console.log(` ${cy("5")}. gemini ${di("(cloud; gemini-2.5-flash-tts, 30 voices)")}`);
|
|
258
261
|
console.log(` ${cy("6")}. mock ${di("(silent WAV; useful for tests)")}`);
|
|
259
262
|
console.log();
|
|
260
263
|
const choice = (await ask(` Choose [1-6, default 1]: `)).trim() || "1";
|