Run on the deployment's local models without any model choice, preselect Claude Opus 5.5 otherwise, explain why dictation is unavailable (#151)
* Recommend Claude Opus 5.5 by bumping the Pi model catalog The pinned pi-ai 0.85.1 had no Claude Opus 5.5, so the connect flow fell back to Opus 5. pi-ai and pi-agent-core 0.87.1 add it, and the keyless recommendation now preselects it. The new catalog names router aliases "Qwen Max Latest (Qwen3.8 Max)"; those now read "(auto-updates)" like the other alias labels, so no picker entry claims to be "latest". Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KWEAjTw26eRf3ZXTXfRjmD * Name HTTPS as the cause when dictation is unavailable, and translate it Over plain HTTP on a LAN address, Safari hides the microphone and speech recognition, so voice mode said the browser had no dictation, in English inside a German UI. Dictation now checks for a secure context first and says to open the address with https://. Its other errors go through Lingui too, and Safari's blocked recognizer gets a clear message instead of "Dictation failed: not-allowed". Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KWEAjTw26eRf3ZXTXfRjmD * Serve a fake Kokoro voice server in the E2E harness Onboarding's voice step connects to the local Kokoro server on its default port, so the shell E2E failed on any machine where nothing (or a misbehaving server) listened there: the failed request shows up as a browser console error. The harness now starts an offline stand-in and points KOKORO_BASE_URL at it, so the suite no longer depends on the runner host's own voice server. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KWEAjTw26eRf3ZXTXfRjmD * Show only the recommended sign-in until a model is connected With no model connected, "Connect model" opened the full model settings: provider list, tiers and a model picker, even though the recommendation was already preselected. Until something is connected, the Models panel now shows just the preselected model with its sign-in and API key field; "Other providers" reveals the full settings. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KWEAjTw26eRf3ZXTXfRjmD * Give the second chart-links test the same cold-load allowance as the first Each Playwright test runs in a fresh browser context, so the second test's first navigation re-fetches the lazily imported Plot chunk just like the first test's warm-up does. On a loaded CI runner that exceeded the default 20 s expect timeout. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KWEAjTw26eRf3ZXTXfRjmD * Use the recommended model as the Anthropic deployment default A deployment that sets only ANTHROPIC_API_KEY and PI_DEFAULT_PROVIDER=anthropic now runs Claude Opus 5.5, the same model the connect flow preselects, instead of an older default. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KWEAjTw26eRf3ZXTXfRjmD * Run every space on the deployment's local models without a connect step A deployment with PI_DEFAULT_PROVIDER=local and RAKAZO_LOCAL_MODELS set still asked every user to connect a model, because only OpenRouter and Anthropic counted as a deployment model. Configured local models now do, keylessly. RAKAZO_LOCAL_TIERS assigns local models to the tiers the agent delegates to, for spaces that have not mapped their own, and a RAKAZO_LOCAL_MODELS entry can name its own server (id=url) when the models run behind different endpoints. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KWEAjTw26eRf3ZXTXfRjmD * Hide model choices when the deployment routes models itself When the server provides its own models, the system picks and routes them per task, so Settings no longer offers Models and bot settings no longer offer Model and Thinking, on web and mobile. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KWEAjTw26eRf3ZXTXfRjmD * Wait for the workspace pane's width transition before measuring it The pane animates its width over 300 ms, so a single boundingBox read right after it opens can land mid-transition on a slow runner. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KWEAjTw26eRf3ZXTXfRjmD * Allow chart re-renders inside the chart-links loops to take longer Each navigation in the loops renders Observable Plot again. On a loaded CI runner that exceeded the default expect timeout even after the warm-up, so the per-iteration visibility checks get 30 s. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KWEAjTw26eRf3ZXTXfRjmD --------- Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
parent
9062717eee
commit
b78eff1f7b
@ -99,8 +99,12 @@ PI_DEFAULT_PROVIDER=openrouter
|
||||
# Computer-use tests can override this with COMPUTER_E2E_MODEL.
|
||||
PI_DEFAULT_MODEL=openai/gpt-5.6-luna
|
||||
# Optional local OpenAI-compatible models. Leave blank to disable the provider.
|
||||
# With PI_DEFAULT_PROVIDER=local they are the deployment's model and nobody has to connect one.
|
||||
# An entry may name its own server: id=http://host:port/v1.
|
||||
RAKAZO_LOCAL_MODELS=
|
||||
RAKAZO_LOCAL_MODELS_URL=http://127.0.0.1:11434/v1
|
||||
# Optional tiers the agent can delegate to, for every space: fast=id,standard=id,code=id.
|
||||
RAKAZO_LOCAL_TIERS=
|
||||
RAKAZO_LOCAL_CONTEXT_WINDOW=32768
|
||||
RAKAZO_LOCAL_MAX_TOKENS=4096
|
||||
# Allow user-connected OpenAI-compatible endpoints on public hostnames (default: private/loopback only).
|
||||
|
||||
@ -226,6 +226,7 @@ describe("model setup gate", () => {
|
||||
await expect(response.json()).resolves.toEqual({
|
||||
json: expect.objectContaining({
|
||||
needsModel: false,
|
||||
modelsManaged: true,
|
||||
defaultProvider: "openrouter",
|
||||
defaultModel: "test-model",
|
||||
}),
|
||||
@ -245,8 +246,9 @@ describe("model setup gate", () => {
|
||||
// The connect flow opens on the recommendation, not the keyless deployment default.
|
||||
json: expect.objectContaining({
|
||||
needsModel: true,
|
||||
modelsManaged: false,
|
||||
defaultProvider: "anthropic",
|
||||
defaultModel: "claude-opus-5",
|
||||
defaultModel: "claude-opus-5-5",
|
||||
}),
|
||||
});
|
||||
});
|
||||
|
||||
@ -5543,6 +5543,7 @@ async function meDto(deps: RouterDeps, actor: Actor): Promise<Me> {
|
||||
spaceId: actor.spaceId,
|
||||
isDeploymentOwner: actor.isDeploymentOwner,
|
||||
needsModel: setup.needsModel,
|
||||
modelsManaged: Boolean(deps.env.deploymentModelKey),
|
||||
defaultProvider:
|
||||
setup.credential?.provider ?? setup.settings?.defaultModelProvider ?? fallback.provider,
|
||||
defaultModel:
|
||||
|
||||
@ -353,15 +353,17 @@ export default function Account() {
|
||||
</View>
|
||||
) : null}
|
||||
|
||||
<Pressable
|
||||
accessibilityRole="button"
|
||||
disabled={pending}
|
||||
onPress={() => router.push("/models")}
|
||||
style={({ pressed }) => [styles.settingsButton, pressed && styles.pressed]}
|
||||
>
|
||||
<Text style={styles.settingsTitle}>{t("Models")}</Text>
|
||||
<Text style={styles.chevron}>›</Text>
|
||||
</Pressable>
|
||||
{me?.modelsManaged ? null : (
|
||||
<Pressable
|
||||
accessibilityRole="button"
|
||||
disabled={pending}
|
||||
onPress={() => router.push("/models")}
|
||||
style={({ pressed }) => [styles.settingsButton, pressed && styles.pressed]}
|
||||
>
|
||||
<Text style={styles.settingsTitle}>{t("Models")}</Text>
|
||||
<Text style={styles.chevron}>›</Text>
|
||||
</Pressable>
|
||||
)}
|
||||
|
||||
<Pressable
|
||||
accessibilityRole="button"
|
||||
|
||||
@ -353,25 +353,27 @@ export default function BotSettingsScreen() {
|
||||
<OoAtelier value={color} identity={bot?.id ?? ""} onChange={setColor} />
|
||||
</View>
|
||||
<ComputerModePicker value={computerMode} onChange={setComputerMode} />
|
||||
<Pressable
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel={t("Advanced")}
|
||||
accessibilityState={{ expanded: advancedOpen }}
|
||||
onPress={() => setAdvancedOpen((open) => !open)}
|
||||
style={{
|
||||
marginTop: 20,
|
||||
minHeight: 44,
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
}}
|
||||
>
|
||||
<Text style={{ color: tokens.mutedForeground, fontSize: 14 }}>{t("Advanced")}</Text>
|
||||
<Text style={{ color: tokens.mutedForeground, fontSize: 18 }}>
|
||||
{advancedOpen ? "⌃" : "⌄"}
|
||||
</Text>
|
||||
</Pressable>
|
||||
{advancedOpen ? (
|
||||
{me?.modelsManaged ? null : (
|
||||
<Pressable
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel={t("Advanced")}
|
||||
accessibilityState={{ expanded: advancedOpen }}
|
||||
onPress={() => setAdvancedOpen((open) => !open)}
|
||||
style={{
|
||||
marginTop: 20,
|
||||
minHeight: 44,
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
}}
|
||||
>
|
||||
<Text style={{ color: tokens.mutedForeground, fontSize: 14 }}>{t("Advanced")}</Text>
|
||||
<Text style={{ color: tokens.mutedForeground, fontSize: 18 }}>
|
||||
{advancedOpen ? "⌃" : "⌄"}
|
||||
</Text>
|
||||
</Pressable>
|
||||
)}
|
||||
{advancedOpen && !me?.modelsManaged ? (
|
||||
<View>
|
||||
<Text
|
||||
style={{
|
||||
|
||||
@ -740,6 +740,7 @@ export type MobileMe = Pick<
|
||||
| "defaultProvider"
|
||||
| "defaultModel"
|
||||
| "needsModel"
|
||||
| "modelsManaged"
|
||||
| "avatarStyle"
|
||||
| "isDeploymentOwner"
|
||||
>;
|
||||
|
||||
@ -18,7 +18,8 @@ test("chart links cannot execute script when clicked or expanded", async ({ page
|
||||
]) {
|
||||
await page.goto(`${fixture}?${new URLSearchParams({ href, inspect })}`);
|
||||
const circle = page.locator("svg circle").first();
|
||||
await expect(circle).toBeVisible();
|
||||
// Every navigation renders Plot again, which takes seconds on a loaded CI runner.
|
||||
await expect(circle).toBeVisible({ timeout: 30_000 });
|
||||
const assertInert = async () => {
|
||||
const links = page.locator("svg a");
|
||||
expect(await links.count()).toBeGreaterThan(0);
|
||||
@ -40,7 +41,7 @@ test("chart links cannot execute script when clicked or expanded", async ({ page
|
||||
await assertInert();
|
||||
await page.getByRole("button", { name: "Expand", exact: true }).click();
|
||||
const dialog = page.getByRole("dialog");
|
||||
await expect(dialog.locator("svg circle")).toBeVisible();
|
||||
await expect(dialog.locator("svg circle")).toBeVisible({ timeout: 30_000 });
|
||||
await dialog.locator("svg circle").click();
|
||||
await assertInert();
|
||||
await expect(page).toHaveURL(`${fixture}?${new URLSearchParams({ href, inspect })}`);
|
||||
@ -51,12 +52,16 @@ test("chart links cannot execute script when clicked or expanded", async ({ page
|
||||
});
|
||||
|
||||
test("chart links retain supported URLs and browser encoding semantics", async ({ page }) => {
|
||||
test.setTimeout(120_000);
|
||||
await page.route("https://example.test/**", (route) =>
|
||||
route.fulfill({ body: "Chart destination" }),
|
||||
);
|
||||
await page.route("**/e2e/fixtures/java*", (route) =>
|
||||
route.fulfill({ body: "Chart destination" }),
|
||||
);
|
||||
// Each test gets a fresh browser context, so this one pays the cold Plot import too.
|
||||
await page.goto(`${fixture}?${new URLSearchParams({ href: "#details" })}`);
|
||||
await expect(page.locator("svg circle").first()).toBeVisible({ timeout: 90_000 });
|
||||
for (const href of [
|
||||
"https://example.test/chart?a=1&b=2",
|
||||
"mailto:chart@example.test",
|
||||
@ -67,8 +72,7 @@ test("chart links retain supported URLs and browser encoding semantics", async (
|
||||
"java%73cript:void(0)",
|
||||
]) {
|
||||
await page.goto(`${fixture}?${new URLSearchParams({ href })}`);
|
||||
// ChartCanvas lazy-loads Plot; mirror the inert-link test and wait for marks first.
|
||||
await expect(page.locator("svg circle").first()).toBeVisible();
|
||||
await expect(page.locator("svg circle").first()).toBeVisible({ timeout: 30_000 });
|
||||
const link = page.locator("svg a").first();
|
||||
await expect(link).toBeAttached();
|
||||
expect(
|
||||
|
||||
@ -27,7 +27,11 @@ test("without a model the composer offers to connect one", async ({ page }) => {
|
||||
await completeOnboarding(page, undefined, { mainConversation: true });
|
||||
|
||||
// Scripted CI has a model; this is what the API returns without one.
|
||||
const keyless = { needsModel: true, defaultProvider: "anthropic", defaultModel: "claude-opus-5" };
|
||||
const keyless = {
|
||||
needsModel: true,
|
||||
defaultProvider: "anthropic",
|
||||
defaultModel: "claude-opus-5-5",
|
||||
};
|
||||
await routePatchRpc(page, "bootstrap", (json) => ({
|
||||
...json,
|
||||
me: { ...(json.me as Record<string, unknown>), ...keyless },
|
||||
@ -43,9 +47,15 @@ test("without a model the composer offers to connect one", async ({ page }) => {
|
||||
const settings = page.getByTestId("model-settings");
|
||||
await expect(settings).toBeVisible();
|
||||
// The recommendation is preselected, so only the key or sign-in is left.
|
||||
await expect(settings.getByRole("combobox", { name: "Model" })).toHaveText("Claude Opus 5");
|
||||
await expect(settings).toContainText("Claude Opus 5.5");
|
||||
await expect(settings.getByRole("combobox", { name: "Model" })).toHaveCount(0);
|
||||
await expect(settings.getByRole("button", { name: /Sign in with Claude/ })).toBeVisible();
|
||||
await expect(settings.getByLabel("Or connect an API key")).toBeVisible();
|
||||
await captureScreenshot(page, testInfo, "model-settings-recommended");
|
||||
await page.emulateMedia({ colorScheme: "dark" });
|
||||
await expect(page.locator("html")).toHaveAttribute("data-theme", "dark");
|
||||
await captureScreenshot(page, testInfo, "model-settings-recommended-dark");
|
||||
|
||||
await settings.getByRole("button", { name: "Other providers" }).click();
|
||||
await expect(settings.getByRole("combobox", { name: "Model" })).toHaveText("Claude Opus 5.5");
|
||||
});
|
||||
|
||||
28
apps/web/e2e/models-managed.spec.ts
Normal file
28
apps/web/e2e/models-managed.spec.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
import {
|
||||
captureScreenshot,
|
||||
completeOnboarding,
|
||||
openUserSettings,
|
||||
routePatchRpc,
|
||||
signup,
|
||||
} from "./helpers";
|
||||
|
||||
test("settings hide Models when the deployment routes models itself", async ({
|
||||
page,
|
||||
}, testInfo) => {
|
||||
await routePatchRpc(page, "me", (json) => ({ ...json, modelsManaged: true }));
|
||||
await routePatchRpc(page, "bootstrap", (json) => ({
|
||||
...json,
|
||||
me: { ...(json.me as Record<string, unknown>), modelsManaged: true },
|
||||
}));
|
||||
|
||||
const stamp = Date.now();
|
||||
await signup(page, `models-managed-${stamp}@rakazo.test`, "password12", `Managed ${stamp}`);
|
||||
await completeOnboarding(page);
|
||||
|
||||
const settings = await openUserSettings(page);
|
||||
await expect(settings.getByTestId("settings-nav-general")).toBeVisible();
|
||||
await expect(settings.getByTestId("settings-nav-memory")).toBeVisible();
|
||||
await expect(settings.getByTestId("settings-nav-models")).toHaveCount(0);
|
||||
await captureScreenshot(page, testInfo, "settings-models-managed");
|
||||
});
|
||||
@ -1,4 +1,13 @@
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
vi.mock("@lingui/core/macro", () => ({
|
||||
t: (parts: TemplateStringsArray, ...values: unknown[]) =>
|
||||
parts.reduce(
|
||||
(text, part, index) => text + part + (index < values.length ? values[index] : ""),
|
||||
"",
|
||||
),
|
||||
}));
|
||||
|
||||
import {
|
||||
Dictation,
|
||||
MAX_TRANSCRIPTION_RESPONSE_BYTES,
|
||||
@ -662,3 +671,18 @@ describe("Dictation web speech", () => {
|
||||
expect(dictation.state.error).toMatch(/Microphone access denied/i);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Dictation outside a secure context", () => {
|
||||
it("names HTTPS as the cause instead of blaming the browser", async () => {
|
||||
vi.stubGlobal("window", { isSecureContext: false });
|
||||
const getUserMedia = vi.fn();
|
||||
vi.stubGlobal("navigator", { mediaDevices: { getUserMedia }, language: "de-DE" });
|
||||
const dictation = new Dictation();
|
||||
|
||||
await dictation.listen({ mode: "endpoint", transcribe: true, onFinal: vi.fn() });
|
||||
|
||||
expect(dictation.state.status).toBe("idle");
|
||||
expect(dictation.state.error).toMatch(/https:\/\//);
|
||||
expect(getUserMedia).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { t } from "@lingui/core/macro";
|
||||
import { readBoundedResponseBytes } from "@rakazo/core";
|
||||
import { selectedSpaceId, withSpaceHeaders } from "./rpc.js";
|
||||
|
||||
@ -30,10 +31,15 @@ const ENDPOINT_TICK_MS = 80;
|
||||
const SILENCE_RMS = 0.035;
|
||||
export const TRANSCRIPTION_RESPONSE_TIMEOUT_MS = 70_000;
|
||||
export const MAX_TRANSCRIPTION_RESPONSE_BYTES = 64 * 1024;
|
||||
const ENDPOINT_UNSUPPORTED =
|
||||
"This browser can't detect when you stop talking. Use Chrome, the desktop app, or hold-to-talk in the composer.";
|
||||
const MIC_UNAVAILABLE =
|
||||
"Microphone access is not available in this browser. Use Chrome, the desktop app, or check system settings.";
|
||||
const endpointUnsupported = () =>
|
||||
t`This browser can't detect when you stop talking. Use Chrome, the desktop app, or hold-to-talk in the composer.`;
|
||||
const micUnavailable = () =>
|
||||
t`Microphone access is not available in this browser. Use Chrome, the desktop app, or check system settings.`;
|
||||
|
||||
/** Browsers hide the microphone and speech recognition outside HTTPS and localhost. */
|
||||
function insecureContext(): boolean {
|
||||
return typeof window !== "undefined" && window.isSecureContext === false;
|
||||
}
|
||||
|
||||
export function webSpeechAvailable(): boolean {
|
||||
return Boolean(speechRecognitionCtor());
|
||||
@ -131,6 +137,13 @@ export class Dictation {
|
||||
const mine = this.token;
|
||||
const spaceId = selectedSpaceId();
|
||||
this.onFinal = opts.onFinal;
|
||||
if (insecureContext()) {
|
||||
this.set({
|
||||
...IDLE,
|
||||
error: t`Voice input needs a secure connection. Open this address with https://.`,
|
||||
});
|
||||
return;
|
||||
}
|
||||
this.set({ status: "listening", transcript: "", energy: 0 });
|
||||
if (webSpeechAvailable()) {
|
||||
const stream = await this.openMic(mine);
|
||||
@ -146,8 +159,7 @@ export class Dictation {
|
||||
}
|
||||
this.set({
|
||||
...IDLE,
|
||||
error:
|
||||
"This browser has no on-device dictation. Connect a voice provider with transcription, or use Chrome / the desktop app.",
|
||||
error: t`This browser can't recognize speech itself. Connect a voice provider with transcription, or use Safari, Chrome or the desktop app.`,
|
||||
});
|
||||
}
|
||||
|
||||
@ -182,7 +194,7 @@ export class Dictation {
|
||||
if (event.error === "aborted" || event.error === "no-speech") return;
|
||||
this.set({
|
||||
...IDLE,
|
||||
error: event.error ? `Dictation failed: ${event.error}` : "Dictation failed.",
|
||||
error: dictationFailed(event.error),
|
||||
});
|
||||
};
|
||||
rec.onend = () => {
|
||||
@ -200,7 +212,7 @@ export class Dictation {
|
||||
try {
|
||||
rec.start();
|
||||
} catch {
|
||||
this.set({ ...IDLE, error: "Dictation ended unexpectedly." });
|
||||
this.set({ ...IDLE, error: t`Dictation ended unexpectedly.` });
|
||||
}
|
||||
};
|
||||
this.recognition = rec;
|
||||
@ -210,7 +222,7 @@ export class Dictation {
|
||||
private async openMic(mine: number): Promise<MediaStream | null> {
|
||||
if (!navigator.mediaDevices?.getUserMedia) {
|
||||
if (this.token !== mine) return null;
|
||||
this.set({ ...IDLE, error: MIC_UNAVAILABLE });
|
||||
this.set({ ...IDLE, error: micUnavailable() });
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
@ -236,7 +248,7 @@ export class Dictation {
|
||||
}
|
||||
if (mode === "endpoint" && !this.armSilence(stream, mine, endpointMs)) {
|
||||
for (const track of stream.getTracks()) track.stop();
|
||||
this.set({ ...IDLE, error: ENDPOINT_UNSUPPORTED });
|
||||
this.set({ ...IDLE, error: endpointUnsupported() });
|
||||
return;
|
||||
}
|
||||
const media = new MediaRecorder(stream);
|
||||
@ -375,7 +387,7 @@ export class Dictation {
|
||||
const body = await readTranscriptionBody(res, abort.signal);
|
||||
if (this.token !== mine) return;
|
||||
if (!res.ok) {
|
||||
this.set({ ...IDLE, error: body.error ?? "Could not transcribe that recording." });
|
||||
this.set({ ...IDLE, error: body.error ?? t`Could not transcribe that recording.` });
|
||||
return;
|
||||
}
|
||||
this.finish(body.text ?? "", mine);
|
||||
@ -389,12 +401,12 @@ export class Dictation {
|
||||
abort.signal.reason.message === "Transcription request timed out.") ||
|
||||
(error instanceof Error && error.message === "Transcription request timed out.");
|
||||
if (timedOut || (error instanceof Error && error.name === "AbortError")) {
|
||||
this.set({ ...IDLE, error: "Transcription request timed out." });
|
||||
this.set({ ...IDLE, error: t`Transcription request timed out.` });
|
||||
return;
|
||||
}
|
||||
this.set({
|
||||
...IDLE,
|
||||
error: error instanceof Error ? error.message : "Could not transcribe that recording.",
|
||||
error: error instanceof Error ? error.message : t`Could not transcribe that recording.`,
|
||||
});
|
||||
} finally {
|
||||
clearTimeout(timer);
|
||||
@ -495,13 +507,21 @@ function rmsEnergyFromAnalyser(analyser: AnalyserNode, data: Uint8Array): number
|
||||
function micErrorMessage(error: unknown): string {
|
||||
if (error instanceof DOMException) {
|
||||
if (error.name === "NotAllowedError") {
|
||||
return "Microphone access denied. Allow the microphone in your browser or system settings, then try again.";
|
||||
return t`Microphone access denied. Allow the microphone in your browser or system settings, then try again.`;
|
||||
}
|
||||
if (error.name === "NotFoundError") {
|
||||
return "No microphone found. Connect a microphone and try again.";
|
||||
return t`No microphone found. Connect a microphone and try again.`;
|
||||
}
|
||||
}
|
||||
return error instanceof Error ? error.message : "Microphone failed";
|
||||
return error instanceof Error ? error.message : t`Microphone failed`;
|
||||
}
|
||||
|
||||
function dictationFailed(code: string | undefined): string {
|
||||
// Safari reports a blocked recognizer (Siri & Dictation off) as not-allowed.
|
||||
if (code === "not-allowed" || code === "service-not-allowed") {
|
||||
return t`Speech recognition is blocked. Allow the microphone and turn on dictation in your system settings.`;
|
||||
}
|
||||
return code ? t`Dictation failed: ${code}` : t`Dictation failed.`;
|
||||
}
|
||||
|
||||
export const dictation = new Dictation();
|
||||
|
||||
@ -1352,6 +1352,7 @@ msgstr "Passwort bestätigen"
|
||||
msgid "Connect"
|
||||
msgstr "Verbinden"
|
||||
|
||||
#: src/pages/ModelSettingsOverlay.tsx
|
||||
#: src/pages/shell/composer.tsx
|
||||
msgid "Connect a model so your Oo can reply."
|
||||
msgstr "Verbinde ein Modell, damit dein Oo antworten kann."
|
||||
@ -1778,6 +1779,10 @@ msgstr "Antwort konnte nicht gesendet werden"
|
||||
msgid "Could not take control"
|
||||
msgstr "Kontrolle konnte nicht übernommen werden"
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Could not transcribe that recording."
|
||||
msgstr "Die Aufnahme konnte nicht transkribiert werden."
|
||||
|
||||
#: src/pages/ScratchpadSection.tsx
|
||||
msgid "Could not update"
|
||||
msgstr "Aktualisierung fehlgeschlagen"
|
||||
@ -2089,6 +2094,18 @@ msgstr "Desktop-Update"
|
||||
msgid "Developer tools"
|
||||
msgstr "Entwicklertools"
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Dictation ended unexpectedly."
|
||||
msgstr "Das Diktat wurde unerwartet beendet."
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Dictation failed: {code}"
|
||||
msgstr "Diktat fehlgeschlagen: {code}"
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Dictation failed."
|
||||
msgstr "Diktat fehlgeschlagen."
|
||||
|
||||
#: src/components/integrations/IntegrationSetup.tsx
|
||||
msgid "Direct MCP"
|
||||
msgstr "Direktes MCP"
|
||||
@ -3206,6 +3223,15 @@ msgstr "Nachricht an {peer} gesendet"
|
||||
msgid "Messaging"
|
||||
msgstr "Messaging"
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Microphone access denied. Allow the microphone in your browser or system settings, then try again."
|
||||
msgstr "Kein Zugriff aufs Mikrofon. Erlaube das Mikrofon in den Browser- oder Systemeinstellungen und versuch es noch einmal."
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Microphone access is not available in this browser. Use Chrome, the desktop app, or check system settings."
|
||||
msgstr "Dieser Browser bietet keinen Mikrofonzugriff. Nutze Chrome, die Desktop-App oder prüfe die Systemeinstellungen."
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
#: src/pages/CallView.tsx
|
||||
msgid "Microphone failed"
|
||||
msgstr "Mikrofonfehler"
|
||||
@ -3518,6 +3544,10 @@ msgstr "Noch keine MCP-Server."
|
||||
msgid "No messages with {peerBotName} yet."
|
||||
msgstr "Noch keine Nachrichten mit {peerBotName}."
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "No microphone found. Connect a microphone and try again."
|
||||
msgstr "Kein Mikrofon gefunden. Schließ ein Mikrofon an und versuch es noch einmal."
|
||||
|
||||
#: src/pages/ModelSettingsOverlay.tsx
|
||||
msgid "No model catalog is available."
|
||||
msgstr "Kein Modellkatalog verfügbar."
|
||||
@ -3751,6 +3781,10 @@ msgstr "Organisations-API-Schlüssel"
|
||||
msgid "Other model…"
|
||||
msgstr "Anderes Modell…"
|
||||
|
||||
#: src/pages/ModelSettingsOverlay.tsx
|
||||
msgid "Other providers"
|
||||
msgstr "Andere Anbieter"
|
||||
|
||||
#: src/components/browser/InAppBrowser.tsx
|
||||
msgid "Page"
|
||||
msgstr "Seite"
|
||||
@ -4737,6 +4771,10 @@ msgstr "Spezialisten-Team"
|
||||
msgid "Species"
|
||||
msgstr "Wesen"
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Speech recognition is blocked. Allow the microphone and turn on dictation in your system settings."
|
||||
msgstr "Die Spracherkennung ist blockiert. Erlaube das Mikrofon und schalte das Diktieren in den Systemeinstellungen ein."
|
||||
|
||||
#: src/lib/model-tier-label.ts
|
||||
msgid "Standard"
|
||||
msgstr "Standard"
|
||||
@ -4965,6 +5003,14 @@ msgstr "Denkmodus"
|
||||
msgid "This bot runs on this computer, not a Linux desktop. Shell and files use your home folder."
|
||||
msgstr "Dieser Bot wird auf diesem Computer und nicht auf einem Linux-Desktop ausgeführt. Shell und Dateien verwenden deinen persönlichen Ordner."
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "This browser can't detect when you stop talking. Use Chrome, the desktop app, or hold-to-talk in the composer."
|
||||
msgstr "Dieser Browser erkennt nicht, wann du aufhörst zu sprechen. Nutze Chrome, die Desktop-App oder halte im Eingabefeld zum Sprechen gedrückt."
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "This browser can't recognize speech itself. Connect a voice provider with transcription, or use Safari, Chrome or the desktop app."
|
||||
msgstr "Dieser Browser kann Sprache nicht selbst erkennen. Verbinde einen Sprachanbieter mit Transkription oder nutze Safari, Chrome oder die Desktop-App."
|
||||
|
||||
#: src/pages/shell/dialogs.tsx
|
||||
msgid "This cannot be undone."
|
||||
msgstr "Dies kann nicht rückgängig gemacht werden."
|
||||
@ -5099,6 +5145,10 @@ msgstr "Transkript"
|
||||
msgid "Transcription"
|
||||
msgstr "Transkription"
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Transcription request timed out."
|
||||
msgstr "Die Transkription hat zu lange gedauert."
|
||||
|
||||
#: src/pages/ExternalConversationSettings.tsx
|
||||
msgid "Treat like a person"
|
||||
msgstr "Wie eine Person behandeln"
|
||||
@ -5298,6 +5348,10 @@ msgstr "Stimme"
|
||||
msgid "Voice \"{0}\" not found."
|
||||
msgstr "Stimme „{0}“ nicht gefunden."
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Voice input needs a secure connection. Open this address with https://."
|
||||
msgstr "Spracheingabe braucht eine sichere Verbindung. Öffne diese Adresse mit https://."
|
||||
|
||||
#: src/components/onboarding/OnboardingVoiceStep.tsx
|
||||
msgid "Voice is not available yet. You can turn it on later in settings."
|
||||
msgstr "Die Stimme ist noch nicht verfügbar. Du kannst sie später in den Einstellungen aktivieren."
|
||||
|
||||
@ -1352,6 +1352,7 @@ msgstr "Confirm password"
|
||||
msgid "Connect"
|
||||
msgstr "Connect"
|
||||
|
||||
#: src/pages/ModelSettingsOverlay.tsx
|
||||
#: src/pages/shell/composer.tsx
|
||||
msgid "Connect a model so your Oo can reply."
|
||||
msgstr "Connect a model so your Oo can reply."
|
||||
@ -1778,6 +1779,10 @@ msgstr "Could not submit this answer"
|
||||
msgid "Could not take control"
|
||||
msgstr "Could not take control"
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Could not transcribe that recording."
|
||||
msgstr "Could not transcribe that recording."
|
||||
|
||||
#: src/pages/ScratchpadSection.tsx
|
||||
msgid "Could not update"
|
||||
msgstr "Could not update"
|
||||
@ -2089,6 +2094,18 @@ msgstr "Desktop update"
|
||||
msgid "Developer tools"
|
||||
msgstr "Developer tools"
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Dictation ended unexpectedly."
|
||||
msgstr "Dictation ended unexpectedly."
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Dictation failed: {code}"
|
||||
msgstr "Dictation failed: {code}"
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Dictation failed."
|
||||
msgstr "Dictation failed."
|
||||
|
||||
#: src/components/integrations/IntegrationSetup.tsx
|
||||
msgid "Direct MCP"
|
||||
msgstr "Direct MCP"
|
||||
@ -3206,6 +3223,15 @@ msgstr "Messaged {peer}"
|
||||
msgid "Messaging"
|
||||
msgstr "Messaging"
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Microphone access denied. Allow the microphone in your browser or system settings, then try again."
|
||||
msgstr "Microphone access denied. Allow the microphone in your browser or system settings, then try again."
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Microphone access is not available in this browser. Use Chrome, the desktop app, or check system settings."
|
||||
msgstr "Microphone access is not available in this browser. Use Chrome, the desktop app, or check system settings."
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
#: src/pages/CallView.tsx
|
||||
msgid "Microphone failed"
|
||||
msgstr "Microphone failed"
|
||||
@ -3518,6 +3544,10 @@ msgstr "No MCP servers yet."
|
||||
msgid "No messages with {peerBotName} yet."
|
||||
msgstr "No messages with {peerBotName} yet."
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "No microphone found. Connect a microphone and try again."
|
||||
msgstr "No microphone found. Connect a microphone and try again."
|
||||
|
||||
#: src/pages/ModelSettingsOverlay.tsx
|
||||
msgid "No model catalog is available."
|
||||
msgstr "No model catalog is available."
|
||||
@ -3751,6 +3781,10 @@ msgstr "Organization API key"
|
||||
msgid "Other model…"
|
||||
msgstr "Other model…"
|
||||
|
||||
#: src/pages/ModelSettingsOverlay.tsx
|
||||
msgid "Other providers"
|
||||
msgstr "Other providers"
|
||||
|
||||
#: src/components/browser/InAppBrowser.tsx
|
||||
msgid "Page"
|
||||
msgstr "Page"
|
||||
@ -4737,6 +4771,10 @@ msgstr "Specialist crew"
|
||||
msgid "Species"
|
||||
msgstr "Species"
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Speech recognition is blocked. Allow the microphone and turn on dictation in your system settings."
|
||||
msgstr "Speech recognition is blocked. Allow the microphone and turn on dictation in your system settings."
|
||||
|
||||
#: src/lib/model-tier-label.ts
|
||||
msgid "Standard"
|
||||
msgstr "Standard"
|
||||
@ -4965,6 +5003,14 @@ msgstr "Thinking"
|
||||
msgid "This bot runs on this computer, not a Linux desktop. Shell and files use your home folder."
|
||||
msgstr "This bot runs on this computer, not a Linux desktop. Shell and files use your home folder."
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "This browser can't detect when you stop talking. Use Chrome, the desktop app, or hold-to-talk in the composer."
|
||||
msgstr "This browser can't detect when you stop talking. Use Chrome, the desktop app, or hold-to-talk in the composer."
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "This browser can't recognize speech itself. Connect a voice provider with transcription, or use Safari, Chrome or the desktop app."
|
||||
msgstr "This browser can't recognize speech itself. Connect a voice provider with transcription, or use Safari, Chrome or the desktop app."
|
||||
|
||||
#: src/pages/shell/dialogs.tsx
|
||||
msgid "This cannot be undone."
|
||||
msgstr "This cannot be undone."
|
||||
@ -5099,6 +5145,10 @@ msgstr "Transcript"
|
||||
msgid "Transcription"
|
||||
msgstr "Transcription"
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Transcription request timed out."
|
||||
msgstr "Transcription request timed out."
|
||||
|
||||
#: src/pages/ExternalConversationSettings.tsx
|
||||
msgid "Treat like a person"
|
||||
msgstr "Treat like a person"
|
||||
@ -5298,6 +5348,10 @@ msgstr "Voice"
|
||||
msgid "Voice \"{0}\" not found."
|
||||
msgstr "Voice \"{0}\" not found."
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Voice input needs a secure connection. Open this address with https://."
|
||||
msgstr "Voice input needs a secure connection. Open this address with https://."
|
||||
|
||||
#: src/components/onboarding/OnboardingVoiceStep.tsx
|
||||
msgid "Voice is not available yet. You can turn it on later in settings."
|
||||
msgstr "Voice is not available yet. You can turn it on later in settings."
|
||||
|
||||
@ -1352,6 +1352,7 @@ msgstr "Confirmar contraseña"
|
||||
msgid "Connect"
|
||||
msgstr "Conectar"
|
||||
|
||||
#: src/pages/ModelSettingsOverlay.tsx
|
||||
#: src/pages/shell/composer.tsx
|
||||
msgid "Connect a model so your Oo can reply."
|
||||
msgstr ""
|
||||
@ -1778,6 +1779,10 @@ msgstr "No se pudo enviar esta respuesta"
|
||||
msgid "Could not take control"
|
||||
msgstr "No se pudo tomar el control"
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Could not transcribe that recording."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/ScratchpadSection.tsx
|
||||
msgid "Could not update"
|
||||
msgstr "No se pudo actualizar"
|
||||
@ -2089,6 +2094,18 @@ msgstr ""
|
||||
msgid "Developer tools"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Dictation ended unexpectedly."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Dictation failed: {code}"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Dictation failed."
|
||||
msgstr ""
|
||||
|
||||
#: src/components/integrations/IntegrationSetup.tsx
|
||||
msgid "Direct MCP"
|
||||
msgstr ""
|
||||
@ -3206,6 +3223,15 @@ msgstr "Mensaje enviado a {peer}"
|
||||
msgid "Messaging"
|
||||
msgstr "Mensajería"
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Microphone access denied. Allow the microphone in your browser or system settings, then try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Microphone access is not available in this browser. Use Chrome, the desktop app, or check system settings."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
#: src/pages/CallView.tsx
|
||||
msgid "Microphone failed"
|
||||
msgstr "Falló el micrófono"
|
||||
@ -3518,6 +3544,10 @@ msgstr "Aún no hay servidores MCP."
|
||||
msgid "No messages with {peerBotName} yet."
|
||||
msgstr "Aún no hay mensajes con {peerBotName}."
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "No microphone found. Connect a microphone and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/ModelSettingsOverlay.tsx
|
||||
msgid "No model catalog is available."
|
||||
msgstr "No hay un catálogo de modelos disponible."
|
||||
@ -3751,6 +3781,10 @@ msgstr "Clave de API de organización"
|
||||
msgid "Other model…"
|
||||
msgstr "Otro modelo…"
|
||||
|
||||
#: src/pages/ModelSettingsOverlay.tsx
|
||||
msgid "Other providers"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/browser/InAppBrowser.tsx
|
||||
msgid "Page"
|
||||
msgstr ""
|
||||
@ -4737,6 +4771,10 @@ msgstr ""
|
||||
msgid "Species"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Speech recognition is blocked. Allow the microphone and turn on dictation in your system settings."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/model-tier-label.ts
|
||||
msgid "Standard"
|
||||
msgstr ""
|
||||
@ -4965,6 +5003,14 @@ msgstr "Pensando"
|
||||
msgid "This bot runs on this computer, not a Linux desktop. Shell and files use your home folder."
|
||||
msgstr "Este bot se ejecuta en esta computadora, no en un escritorio Linux. El shell y los archivos usan tu carpeta de inicio."
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "This browser can't detect when you stop talking. Use Chrome, the desktop app, or hold-to-talk in the composer."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "This browser can't recognize speech itself. Connect a voice provider with transcription, or use Safari, Chrome or the desktop app."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/shell/dialogs.tsx
|
||||
msgid "This cannot be undone."
|
||||
msgstr "Esto no se puede deshacer."
|
||||
@ -5099,6 +5145,10 @@ msgstr ""
|
||||
msgid "Transcription"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Transcription request timed out."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/ExternalConversationSettings.tsx
|
||||
msgid "Treat like a person"
|
||||
msgstr ""
|
||||
@ -5298,6 +5348,10 @@ msgstr "Voz"
|
||||
msgid "Voice \"{0}\" not found."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Voice input needs a secure connection. Open this address with https://."
|
||||
msgstr ""
|
||||
|
||||
#: src/components/onboarding/OnboardingVoiceStep.tsx
|
||||
msgid "Voice is not available yet. You can turn it on later in settings."
|
||||
msgstr ""
|
||||
|
||||
@ -1352,6 +1352,7 @@ msgstr "पासवर्ड की पुष्टि करें"
|
||||
msgid "Connect"
|
||||
msgstr "कनेक्ट करें"
|
||||
|
||||
#: src/pages/ModelSettingsOverlay.tsx
|
||||
#: src/pages/shell/composer.tsx
|
||||
msgid "Connect a model so your Oo can reply."
|
||||
msgstr ""
|
||||
@ -1778,6 +1779,10 @@ msgstr "यह उत्तर सबमिट नहीं किया जा
|
||||
msgid "Could not take control"
|
||||
msgstr "नियंत्रण नहीं लिया जा सका"
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Could not transcribe that recording."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/ScratchpadSection.tsx
|
||||
msgid "Could not update"
|
||||
msgstr "अपडेट नहीं हो सका"
|
||||
@ -2089,6 +2094,18 @@ msgstr ""
|
||||
msgid "Developer tools"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Dictation ended unexpectedly."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Dictation failed: {code}"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Dictation failed."
|
||||
msgstr ""
|
||||
|
||||
#: src/components/integrations/IntegrationSetup.tsx
|
||||
msgid "Direct MCP"
|
||||
msgstr ""
|
||||
@ -3206,6 +3223,15 @@ msgstr "{peer} को संदेश भेजा"
|
||||
msgid "Messaging"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Microphone access denied. Allow the microphone in your browser or system settings, then try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Microphone access is not available in this browser. Use Chrome, the desktop app, or check system settings."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
#: src/pages/CallView.tsx
|
||||
msgid "Microphone failed"
|
||||
msgstr "माइक्रोफ़ोन विफल"
|
||||
@ -3518,6 +3544,10 @@ msgstr "अभी तक कोई MCP सर्वर नहीं।"
|
||||
msgid "No messages with {peerBotName} yet."
|
||||
msgstr "{peerBotName} के साथ अभी कोई संदेश नहीं."
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "No microphone found. Connect a microphone and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/ModelSettingsOverlay.tsx
|
||||
msgid "No model catalog is available."
|
||||
msgstr "कोई मॉडल कैटलॉग उपलब्ध नहीं है।"
|
||||
@ -3751,6 +3781,10 @@ msgstr "संगठन API कुंजी"
|
||||
msgid "Other model…"
|
||||
msgstr "अन्य मॉडल…"
|
||||
|
||||
#: src/pages/ModelSettingsOverlay.tsx
|
||||
msgid "Other providers"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/browser/InAppBrowser.tsx
|
||||
msgid "Page"
|
||||
msgstr ""
|
||||
@ -4737,6 +4771,10 @@ msgstr ""
|
||||
msgid "Species"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Speech recognition is blocked. Allow the microphone and turn on dictation in your system settings."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/model-tier-label.ts
|
||||
msgid "Standard"
|
||||
msgstr ""
|
||||
@ -4965,6 +5003,14 @@ msgstr "सोच रहा है"
|
||||
msgid "This bot runs on this computer, not a Linux desktop. Shell and files use your home folder."
|
||||
msgstr "यह बॉट इसी कंप्यूटर पर चलता है, किसी Linux डेस्कटॉप पर नहीं। शेल और फ़ाइलें आपके होम फ़ोल्डर का उपयोग करती हैं।"
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "This browser can't detect when you stop talking. Use Chrome, the desktop app, or hold-to-talk in the composer."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "This browser can't recognize speech itself. Connect a voice provider with transcription, or use Safari, Chrome or the desktop app."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/shell/dialogs.tsx
|
||||
msgid "This cannot be undone."
|
||||
msgstr "इसे पूर्ववत नहीं किया जा सकता।"
|
||||
@ -5099,6 +5145,10 @@ msgstr ""
|
||||
msgid "Transcription"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Transcription request timed out."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/ExternalConversationSettings.tsx
|
||||
msgid "Treat like a person"
|
||||
msgstr ""
|
||||
@ -5298,6 +5348,10 @@ msgstr "आवाज़"
|
||||
msgid "Voice \"{0}\" not found."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Voice input needs a secure connection. Open this address with https://."
|
||||
msgstr ""
|
||||
|
||||
#: src/components/onboarding/OnboardingVoiceStep.tsx
|
||||
msgid "Voice is not available yet. You can turn it on later in settings."
|
||||
msgstr ""
|
||||
|
||||
@ -1352,6 +1352,7 @@ msgstr "비밀번호 확인"
|
||||
msgid "Connect"
|
||||
msgstr "연결"
|
||||
|
||||
#: src/pages/ModelSettingsOverlay.tsx
|
||||
#: src/pages/shell/composer.tsx
|
||||
msgid "Connect a model so your Oo can reply."
|
||||
msgstr ""
|
||||
@ -1778,6 +1779,10 @@ msgstr "답변을 보내지 못했습니다."
|
||||
msgid "Could not take control"
|
||||
msgstr "직접 조작으로 전환하지 못했습니다."
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Could not transcribe that recording."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/ScratchpadSection.tsx
|
||||
msgid "Could not update"
|
||||
msgstr "업데이트하지 못했습니다."
|
||||
@ -2089,6 +2094,18 @@ msgstr ""
|
||||
msgid "Developer tools"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Dictation ended unexpectedly."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Dictation failed: {code}"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Dictation failed."
|
||||
msgstr ""
|
||||
|
||||
#: src/components/integrations/IntegrationSetup.tsx
|
||||
msgid "Direct MCP"
|
||||
msgstr ""
|
||||
@ -3206,6 +3223,15 @@ msgstr "{peer}에게 메시지 보냄"
|
||||
msgid "Messaging"
|
||||
msgstr "메시징"
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Microphone access denied. Allow the microphone in your browser or system settings, then try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Microphone access is not available in this browser. Use Chrome, the desktop app, or check system settings."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
#: src/pages/CallView.tsx
|
||||
msgid "Microphone failed"
|
||||
msgstr "마이크를 사용할 수 없습니다."
|
||||
@ -3518,6 +3544,10 @@ msgstr "아직 연결된 MCP 서버가 없습니다."
|
||||
msgid "No messages with {peerBotName} yet."
|
||||
msgstr "{peerBotName}와의 메시지가 아직 없습니다."
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "No microphone found. Connect a microphone and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/ModelSettingsOverlay.tsx
|
||||
msgid "No model catalog is available."
|
||||
msgstr "사용 가능한 모델 목록이 없습니다."
|
||||
@ -3751,6 +3781,10 @@ msgstr "조직 API 키"
|
||||
msgid "Other model…"
|
||||
msgstr "다른 모델 직접 입력…"
|
||||
|
||||
#: src/pages/ModelSettingsOverlay.tsx
|
||||
msgid "Other providers"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/browser/InAppBrowser.tsx
|
||||
msgid "Page"
|
||||
msgstr ""
|
||||
@ -4737,6 +4771,10 @@ msgstr ""
|
||||
msgid "Species"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Speech recognition is blocked. Allow the microphone and turn on dictation in your system settings."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/model-tier-label.ts
|
||||
msgid "Standard"
|
||||
msgstr ""
|
||||
@ -4965,6 +5003,14 @@ msgstr "생각 깊이"
|
||||
msgid "This bot runs on this computer, not a Linux desktop. Shell and files use your home folder."
|
||||
msgstr "이 Bot은 별도 Linux 화면이 아니라 현재 컴퓨터에서 실행됩니다. 터미널과 파일 작업은 홈 폴더를 사용합니다."
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "This browser can't detect when you stop talking. Use Chrome, the desktop app, or hold-to-talk in the composer."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "This browser can't recognize speech itself. Connect a voice provider with transcription, or use Safari, Chrome or the desktop app."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/shell/dialogs.tsx
|
||||
msgid "This cannot be undone."
|
||||
msgstr "이 작업은 되돌릴 수 없습니다."
|
||||
@ -5099,6 +5145,10 @@ msgstr ""
|
||||
msgid "Transcription"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Transcription request timed out."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/ExternalConversationSettings.tsx
|
||||
msgid "Treat like a person"
|
||||
msgstr ""
|
||||
@ -5298,6 +5348,10 @@ msgstr "음성"
|
||||
msgid "Voice \"{0}\" not found."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Voice input needs a secure connection. Open this address with https://."
|
||||
msgstr ""
|
||||
|
||||
#: src/components/onboarding/OnboardingVoiceStep.tsx
|
||||
msgid "Voice is not available yet. You can turn it on later in settings."
|
||||
msgstr ""
|
||||
|
||||
@ -1352,6 +1352,7 @@ msgstr "Confirmar senha"
|
||||
msgid "Connect"
|
||||
msgstr "Conectar"
|
||||
|
||||
#: src/pages/ModelSettingsOverlay.tsx
|
||||
#: src/pages/shell/composer.tsx
|
||||
msgid "Connect a model so your Oo can reply."
|
||||
msgstr ""
|
||||
@ -1778,6 +1779,10 @@ msgstr "Não foi possível enviar esta resposta"
|
||||
msgid "Could not take control"
|
||||
msgstr "Não foi possível assumir o controle"
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Could not transcribe that recording."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/ScratchpadSection.tsx
|
||||
msgid "Could not update"
|
||||
msgstr "Não foi possível atualizar"
|
||||
@ -2089,6 +2094,18 @@ msgstr ""
|
||||
msgid "Developer tools"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Dictation ended unexpectedly."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Dictation failed: {code}"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Dictation failed."
|
||||
msgstr ""
|
||||
|
||||
#: src/components/integrations/IntegrationSetup.tsx
|
||||
msgid "Direct MCP"
|
||||
msgstr ""
|
||||
@ -3206,6 +3223,15 @@ msgstr "Enviou mensagem para {peer}"
|
||||
msgid "Messaging"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Microphone access denied. Allow the microphone in your browser or system settings, then try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Microphone access is not available in this browser. Use Chrome, the desktop app, or check system settings."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
#: src/pages/CallView.tsx
|
||||
msgid "Microphone failed"
|
||||
msgstr "Falha no microfone"
|
||||
@ -3518,6 +3544,10 @@ msgstr "Ainda não há servidores MCP."
|
||||
msgid "No messages with {peerBotName} yet."
|
||||
msgstr "Ainda sem mensagens com {peerBotName}."
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "No microphone found. Connect a microphone and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/ModelSettingsOverlay.tsx
|
||||
msgid "No model catalog is available."
|
||||
msgstr "Nenhum catálogo de modelos está disponível."
|
||||
@ -3751,6 +3781,10 @@ msgstr "Chave da API da organização"
|
||||
msgid "Other model…"
|
||||
msgstr "Outro modelo..."
|
||||
|
||||
#: src/pages/ModelSettingsOverlay.tsx
|
||||
msgid "Other providers"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/browser/InAppBrowser.tsx
|
||||
msgid "Page"
|
||||
msgstr ""
|
||||
@ -4737,6 +4771,10 @@ msgstr ""
|
||||
msgid "Species"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Speech recognition is blocked. Allow the microphone and turn on dictation in your system settings."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/model-tier-label.ts
|
||||
msgid "Standard"
|
||||
msgstr ""
|
||||
@ -4965,6 +5003,14 @@ msgstr "Pensando"
|
||||
msgid "This bot runs on this computer, not a Linux desktop. Shell and files use your home folder."
|
||||
msgstr "Este bot é executado neste computador, não em um desktop Linux. Shell e arquivos usam sua pasta inicial."
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "This browser can't detect when you stop talking. Use Chrome, the desktop app, or hold-to-talk in the composer."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "This browser can't recognize speech itself. Connect a voice provider with transcription, or use Safari, Chrome or the desktop app."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/shell/dialogs.tsx
|
||||
msgid "This cannot be undone."
|
||||
msgstr "Essa ação não pode ser desfeita."
|
||||
@ -5099,6 +5145,10 @@ msgstr ""
|
||||
msgid "Transcription"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Transcription request timed out."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/ExternalConversationSettings.tsx
|
||||
msgid "Treat like a person"
|
||||
msgstr ""
|
||||
@ -5298,6 +5348,10 @@ msgstr "Voz"
|
||||
msgid "Voice \"{0}\" not found."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Voice input needs a secure connection. Open this address with https://."
|
||||
msgstr ""
|
||||
|
||||
#: src/components/onboarding/OnboardingVoiceStep.tsx
|
||||
msgid "Voice is not available yet. You can turn it on later in settings."
|
||||
msgstr ""
|
||||
|
||||
@ -1352,6 +1352,7 @@ msgstr "Подтвердите пароль"
|
||||
msgid "Connect"
|
||||
msgstr "Подключить"
|
||||
|
||||
#: src/pages/ModelSettingsOverlay.tsx
|
||||
#: src/pages/shell/composer.tsx
|
||||
msgid "Connect a model so your Oo can reply."
|
||||
msgstr ""
|
||||
@ -1778,6 +1779,10 @@ msgstr "Не удалось отправить этот ответ"
|
||||
msgid "Could not take control"
|
||||
msgstr "Не смог взять под контроль"
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Could not transcribe that recording."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/ScratchpadSection.tsx
|
||||
msgid "Could not update"
|
||||
msgstr "Не удалось обновить"
|
||||
@ -2089,6 +2094,18 @@ msgstr "Обновление настольного приложения"
|
||||
msgid "Developer tools"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Dictation ended unexpectedly."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Dictation failed: {code}"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Dictation failed."
|
||||
msgstr ""
|
||||
|
||||
#: src/components/integrations/IntegrationSetup.tsx
|
||||
msgid "Direct MCP"
|
||||
msgstr "Прямой MCP"
|
||||
@ -3206,6 +3223,15 @@ msgstr "Отправлено сообщение {peer}"
|
||||
msgid "Messaging"
|
||||
msgstr "Обмен сообщениями"
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Microphone access denied. Allow the microphone in your browser or system settings, then try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Microphone access is not available in this browser. Use Chrome, the desktop app, or check system settings."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
#: src/pages/CallView.tsx
|
||||
msgid "Microphone failed"
|
||||
msgstr "Ошибка микрофона"
|
||||
@ -3518,6 +3544,10 @@ msgstr "Серверов MCP пока нет."
|
||||
msgid "No messages with {peerBotName} yet."
|
||||
msgstr "Сообщений с {peerBotName} пока нет."
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "No microphone found. Connect a microphone and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/ModelSettingsOverlay.tsx
|
||||
msgid "No model catalog is available."
|
||||
msgstr "Каталога моделей нет."
|
||||
@ -3751,6 +3781,10 @@ msgstr "Ключ API организации"
|
||||
msgid "Other model…"
|
||||
msgstr "Другая модель…"
|
||||
|
||||
#: src/pages/ModelSettingsOverlay.tsx
|
||||
msgid "Other providers"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/browser/InAppBrowser.tsx
|
||||
msgid "Page"
|
||||
msgstr ""
|
||||
@ -4737,6 +4771,10 @@ msgstr ""
|
||||
msgid "Species"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Speech recognition is blocked. Allow the microphone and turn on dictation in your system settings."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/model-tier-label.ts
|
||||
msgid "Standard"
|
||||
msgstr ""
|
||||
@ -4965,6 +5003,14 @@ msgstr "рассуждение"
|
||||
msgid "This bot runs on this computer, not a Linux desktop. Shell and files use your home folder."
|
||||
msgstr "Этот бот работает на этом компьютере, а не на рабочем столе Linux. Оболочка и файлы используют вашу домашнюю папку."
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "This browser can't detect when you stop talking. Use Chrome, the desktop app, or hold-to-talk in the composer."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "This browser can't recognize speech itself. Connect a voice provider with transcription, or use Safari, Chrome or the desktop app."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/shell/dialogs.tsx
|
||||
msgid "This cannot be undone."
|
||||
msgstr "Это невозможно отменить."
|
||||
@ -5099,6 +5145,10 @@ msgstr ""
|
||||
msgid "Transcription"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Transcription request timed out."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/ExternalConversationSettings.tsx
|
||||
msgid "Treat like a person"
|
||||
msgstr "Считать человеком"
|
||||
@ -5298,6 +5348,10 @@ msgstr "Голос"
|
||||
msgid "Voice \"{0}\" not found."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Voice input needs a secure connection. Open this address with https://."
|
||||
msgstr ""
|
||||
|
||||
#: src/components/onboarding/OnboardingVoiceStep.tsx
|
||||
msgid "Voice is not available yet. You can turn it on later in settings."
|
||||
msgstr ""
|
||||
|
||||
@ -1352,6 +1352,7 @@ msgstr "Parolayı doğrulayın"
|
||||
msgid "Connect"
|
||||
msgstr "Bağlan"
|
||||
|
||||
#: src/pages/ModelSettingsOverlay.tsx
|
||||
#: src/pages/shell/composer.tsx
|
||||
msgid "Connect a model so your Oo can reply."
|
||||
msgstr ""
|
||||
@ -1778,6 +1779,10 @@ msgstr "Bu yanıt gönderilemedi"
|
||||
msgid "Could not take control"
|
||||
msgstr "Kontrol alınamadı"
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Could not transcribe that recording."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/ScratchpadSection.tsx
|
||||
msgid "Could not update"
|
||||
msgstr "Güncellenemedi"
|
||||
@ -2089,6 +2094,18 @@ msgstr ""
|
||||
msgid "Developer tools"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Dictation ended unexpectedly."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Dictation failed: {code}"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Dictation failed."
|
||||
msgstr ""
|
||||
|
||||
#: src/components/integrations/IntegrationSetup.tsx
|
||||
msgid "Direct MCP"
|
||||
msgstr ""
|
||||
@ -3206,6 +3223,15 @@ msgstr "{peer} botuna mesaj gönderildi"
|
||||
msgid "Messaging"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Microphone access denied. Allow the microphone in your browser or system settings, then try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Microphone access is not available in this browser. Use Chrome, the desktop app, or check system settings."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
#: src/pages/CallView.tsx
|
||||
msgid "Microphone failed"
|
||||
msgstr "Mikrofon hatası"
|
||||
@ -3518,6 +3544,10 @@ msgstr "Henüz MCP sunucusu yok."
|
||||
msgid "No messages with {peerBotName} yet."
|
||||
msgstr "{peerBotName} ile henüz mesaj yok."
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "No microphone found. Connect a microphone and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/ModelSettingsOverlay.tsx
|
||||
msgid "No model catalog is available."
|
||||
msgstr "Kullanılabilir model kataloğu yok."
|
||||
@ -3751,6 +3781,10 @@ msgstr "Kuruluş API anahtarı"
|
||||
msgid "Other model…"
|
||||
msgstr "Başka model…"
|
||||
|
||||
#: src/pages/ModelSettingsOverlay.tsx
|
||||
msgid "Other providers"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/browser/InAppBrowser.tsx
|
||||
msgid "Page"
|
||||
msgstr ""
|
||||
@ -4737,6 +4771,10 @@ msgstr ""
|
||||
msgid "Species"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Speech recognition is blocked. Allow the microphone and turn on dictation in your system settings."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/model-tier-label.ts
|
||||
msgid "Standard"
|
||||
msgstr ""
|
||||
@ -4965,6 +5003,14 @@ msgstr "Düşünüyor"
|
||||
msgid "This bot runs on this computer, not a Linux desktop. Shell and files use your home folder."
|
||||
msgstr "Bu bot bir Linux masaüstünde değil, bu bilgisayarda çalışır. Kabuk ve dosyalar senin kullanıcı klasörünü kullanır."
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "This browser can't detect when you stop talking. Use Chrome, the desktop app, or hold-to-talk in the composer."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "This browser can't recognize speech itself. Connect a voice provider with transcription, or use Safari, Chrome or the desktop app."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/shell/dialogs.tsx
|
||||
msgid "This cannot be undone."
|
||||
msgstr "Bu işlem geri alınamaz."
|
||||
@ -5099,6 +5145,10 @@ msgstr ""
|
||||
msgid "Transcription"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Transcription request timed out."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/ExternalConversationSettings.tsx
|
||||
msgid "Treat like a person"
|
||||
msgstr ""
|
||||
@ -5298,6 +5348,10 @@ msgstr "Ses"
|
||||
msgid "Voice \"{0}\" not found."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Voice input needs a secure connection. Open this address with https://."
|
||||
msgstr ""
|
||||
|
||||
#: src/components/onboarding/OnboardingVoiceStep.tsx
|
||||
msgid "Voice is not available yet. You can turn it on later in settings."
|
||||
msgstr ""
|
||||
|
||||
@ -1352,6 +1352,7 @@ msgstr "确认密码"
|
||||
msgid "Connect"
|
||||
msgstr "连接"
|
||||
|
||||
#: src/pages/ModelSettingsOverlay.tsx
|
||||
#: src/pages/shell/composer.tsx
|
||||
msgid "Connect a model so your Oo can reply."
|
||||
msgstr ""
|
||||
@ -1778,6 +1779,10 @@ msgstr "无法提交此回答"
|
||||
msgid "Could not take control"
|
||||
msgstr "无法接管"
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Could not transcribe that recording."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/ScratchpadSection.tsx
|
||||
msgid "Could not update"
|
||||
msgstr "无法更新"
|
||||
@ -2089,6 +2094,18 @@ msgstr ""
|
||||
msgid "Developer tools"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Dictation ended unexpectedly."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Dictation failed: {code}"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Dictation failed."
|
||||
msgstr ""
|
||||
|
||||
#: src/components/integrations/IntegrationSetup.tsx
|
||||
msgid "Direct MCP"
|
||||
msgstr ""
|
||||
@ -3206,6 +3223,15 @@ msgstr "已发给 {peer}"
|
||||
msgid "Messaging"
|
||||
msgstr "消息"
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Microphone access denied. Allow the microphone in your browser or system settings, then try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Microphone access is not available in this browser. Use Chrome, the desktop app, or check system settings."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
#: src/pages/CallView.tsx
|
||||
msgid "Microphone failed"
|
||||
msgstr "麦克风失败"
|
||||
@ -3518,6 +3544,10 @@ msgstr "还没有 MCP 服务器。"
|
||||
msgid "No messages with {peerBotName} yet."
|
||||
msgstr "还没有与 {peerBotName} 的消息。"
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "No microphone found. Connect a microphone and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/ModelSettingsOverlay.tsx
|
||||
msgid "No model catalog is available."
|
||||
msgstr "没有可用的模型目录。"
|
||||
@ -3751,6 +3781,10 @@ msgstr "组织 API 密钥"
|
||||
msgid "Other model…"
|
||||
msgstr "其他模型…"
|
||||
|
||||
#: src/pages/ModelSettingsOverlay.tsx
|
||||
msgid "Other providers"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/browser/InAppBrowser.tsx
|
||||
msgid "Page"
|
||||
msgstr ""
|
||||
@ -4737,6 +4771,10 @@ msgstr ""
|
||||
msgid "Species"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Speech recognition is blocked. Allow the microphone and turn on dictation in your system settings."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/model-tier-label.ts
|
||||
msgid "Standard"
|
||||
msgstr ""
|
||||
@ -4965,6 +5003,14 @@ msgstr "思考"
|
||||
msgid "This bot runs on this computer, not a Linux desktop. Shell and files use your home folder."
|
||||
msgstr "此 Bot 运行在这台电脑上,而不是 Linux 桌面。Shell 和文件使用你的主目录。"
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "This browser can't detect when you stop talking. Use Chrome, the desktop app, or hold-to-talk in the composer."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "This browser can't recognize speech itself. Connect a voice provider with transcription, or use Safari, Chrome or the desktop app."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/shell/dialogs.tsx
|
||||
msgid "This cannot be undone."
|
||||
msgstr "此操作无法撤销。"
|
||||
@ -5099,6 +5145,10 @@ msgstr ""
|
||||
msgid "Transcription"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Transcription request timed out."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/ExternalConversationSettings.tsx
|
||||
msgid "Treat like a person"
|
||||
msgstr ""
|
||||
@ -5298,6 +5348,10 @@ msgstr "语音"
|
||||
msgid "Voice \"{0}\" not found."
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/dictation.ts
|
||||
msgid "Voice input needs a secure connection. Open this address with https://."
|
||||
msgstr ""
|
||||
|
||||
#: src/components/onboarding/OnboardingVoiceStep.tsx
|
||||
msgid "Voice is not available yet. You can turn it on later in settings."
|
||||
msgstr ""
|
||||
|
||||
@ -74,6 +74,7 @@ export function ModelSettingsOverlay({
|
||||
const [pending, setPending] = useState<"connect" | "default" | null>(null);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [notice, setNotice] = useState<string | null>(null);
|
||||
const [showProviders, setShowProviders] = useState(false);
|
||||
const detailScrollRef = useRef<HTMLDivElement>(null);
|
||||
const refreshRevisionRef = useRef(0);
|
||||
const selectionRevisionRef = useRef(0);
|
||||
@ -192,6 +193,9 @@ export function ModelSettingsOverlay({
|
||||
const subscriptionSignIn = selected?.signIn !== undefined;
|
||||
const busy = pending !== null || oauthPending;
|
||||
const effectiveBaseUrl = baseUrl.trim();
|
||||
// Until something is connected, only the preselected recommendation's sign-in is shown.
|
||||
const setupOnly =
|
||||
!showProviders && Boolean(me?.needsModel) && credentials.length === 0 && !isOpenAiCompatible;
|
||||
const openAiCompatibleReady = openAiCompatibleConnectReady({
|
||||
baseUrl: effectiveBaseUrl,
|
||||
modelId,
|
||||
@ -356,6 +360,8 @@ export function ModelSettingsOverlay({
|
||||
|
||||
const description = loading ? (
|
||||
<Trans>Loading model catalog…</Trans>
|
||||
) : setupOnly ? (
|
||||
<Trans>Connect a model so your Oo can reply.</Trans>
|
||||
) : localOwner ? (
|
||||
<Trans>Models for the server owner’s default space.</Trans>
|
||||
) : (
|
||||
@ -399,10 +405,10 @@ export function ModelSettingsOverlay({
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<ModelTierSettings credentials={credentials} catalog={catalog} />
|
||||
{setupOnly ? null : <ModelTierSettings credentials={credentials} catalog={catalog} />}
|
||||
|
||||
<div className="flex min-h-0 flex-1 flex-col gap-6 overflow-hidden px-6 py-6 sm:px-8 md:flex-row">
|
||||
<div className="flex min-h-0 shrink-0 flex-col md:w-[310px]">
|
||||
<div className={setupOnly ? "hidden" : "flex min-h-0 shrink-0 flex-col md:w-[310px]"}>
|
||||
<div className="mb-3 text-ui-body text-muted-foreground">
|
||||
<Trans>Providers</Trans>
|
||||
</div>
|
||||
@ -603,7 +609,7 @@ export function ModelSettingsOverlay({
|
||||
maxImagesLabel={t`Maximum images per request`}
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
) : setupOnly ? null : (
|
||||
<>
|
||||
<span>
|
||||
<Trans>Model</Trans>
|
||||
@ -622,13 +628,13 @@ export function ModelSettingsOverlay({
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
{!isOpenAiCompatible && selected.billing ? (
|
||||
{!isOpenAiCompatible && !setupOnly && selected.billing ? (
|
||||
<p className="mt-2 text-ui-body-sm leading-[1.5] text-muted-foreground">
|
||||
{selected.billing}
|
||||
</p>
|
||||
) : null}
|
||||
|
||||
{!isOpenAiCompatible ? (
|
||||
{!isOpenAiCompatible && !setupOnly ? (
|
||||
<div className="mt-5 rounded-xl border border-border px-4 py-3">
|
||||
<div className="text-ui-body-sm uppercase tracking-[0.08em] text-muted-foreground/80">
|
||||
<Trans>Personal credential</Trans>
|
||||
@ -651,7 +657,7 @@ export function ModelSettingsOverlay({
|
||||
) : null}
|
||||
|
||||
{subscriptionSignIn ? (
|
||||
<div className="mt-5">
|
||||
<div className={setupOnly ? undefined : "mt-5"}>
|
||||
{oauth ? (
|
||||
<div className="rounded-xl border border-border px-4 py-3">
|
||||
{oauth.mode === "auth-url" ? (
|
||||
@ -800,6 +806,17 @@ export function ModelSettingsOverlay({
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{setupOnly ? (
|
||||
<Button
|
||||
type="button"
|
||||
variant="link"
|
||||
className="mt-5 h-auto px-0 text-ui-body-sm text-muted-foreground underline"
|
||||
onClick={() => setShowProviders(true)}
|
||||
>
|
||||
<Trans>Other providers</Trans>
|
||||
</Button>
|
||||
) : null}
|
||||
|
||||
{selected.auth === "oauth" && !subscriptionSignIn ? (
|
||||
<p className="mt-5 text-sm leading-[1.5] text-muted-foreground">
|
||||
<Trans>
|
||||
|
||||
@ -56,6 +56,7 @@ export function SettingsOverlay({
|
||||
usage,
|
||||
initialSection = "general",
|
||||
isDeploymentOwner = false,
|
||||
modelsManaged = false,
|
||||
sandboxProvider,
|
||||
messagingEnabled = false,
|
||||
onOpenMessaging,
|
||||
@ -71,6 +72,7 @@ export function SettingsOverlay({
|
||||
usage?: { runs: number; inputTokens: number; outputTokens: number } | null;
|
||||
initialSection?: SettingsSection;
|
||||
isDeploymentOwner?: boolean;
|
||||
modelsManaged?: boolean;
|
||||
sandboxProvider?: string | null;
|
||||
messagingEnabled?: boolean;
|
||||
onOpenMessaging?: () => void;
|
||||
@ -103,7 +105,7 @@ export function SettingsOverlay({
|
||||
const navItems: NavItem[] = [
|
||||
{ id: "general", label: t`General`, icon: Settings },
|
||||
{ id: "integrations", label: t`Integrations`, icon: LayoutGrid },
|
||||
{ id: "models", label: t`Models`, icon: Cpu },
|
||||
...(modelsManaged ? [] : [{ id: "models" as const, label: t`Models`, icon: Cpu }]),
|
||||
{ id: "memory", label: t`Memory`, icon: Brain },
|
||||
{ id: "voice", label: t`Voice`, icon: Volume2 },
|
||||
...(isDeploymentOwner ? [{ id: "media" as const, label: t`Media`, icon: Clapperboard }] : []),
|
||||
@ -252,7 +254,7 @@ export function SettingsOverlay({
|
||||
{section === "updates" ? (
|
||||
<UpdatesSettingsPanel isDeploymentOwner={isDeploymentOwner} />
|
||||
) : null}
|
||||
{section === "models" ? (
|
||||
{section === "models" && !modelsManaged ? (
|
||||
<ModelSettingsOverlay embedded onClose={requestClose} />
|
||||
) : null}
|
||||
{section === "memory" ? (
|
||||
|
||||
@ -4134,6 +4134,7 @@ export function ShellPage() {
|
||||
usage={usage}
|
||||
initialSection={settingsSection}
|
||||
isDeploymentOwner={bootstrapMe?.isDeploymentOwner === true}
|
||||
modelsManaged={bootstrapMe?.modelsManaged === true}
|
||||
sandboxProvider={bootstrapMe?.sandboxProvider}
|
||||
messagingEnabled={messagingSurfaceEnabled}
|
||||
onOpenMessaging={() => {
|
||||
|
||||
@ -561,66 +561,70 @@ export function BotSettings({
|
||||
<KnowledgeSection botId={bot.id} onSkillsChange={onSkillsChange} />
|
||||
) : null}
|
||||
</Suspense>
|
||||
<label htmlFor={`${ids}-model`} className={fieldLabelClass}>
|
||||
<Trans>Model</Trans>
|
||||
<NativeSelect
|
||||
id={`${ids}-model`}
|
||||
className="mt-2 w-full"
|
||||
value={modelKey}
|
||||
onChange={(event) => {
|
||||
setModelKey(event.target.value);
|
||||
setThinkingLevel("");
|
||||
}}
|
||||
>
|
||||
<NativeSelectOption value="">
|
||||
{t`Space default`}
|
||||
{me?.defaultModel
|
||||
? ` (${catalogLabel(catalog, me.defaultProvider, me.defaultModel) ?? me.defaultModel})`
|
||||
: ""}
|
||||
</NativeSelectOption>
|
||||
{tierOptions.length ? (
|
||||
<NativeSelectOptGroup label={t`Tiers`}>
|
||||
{tierOptions.map((option) => (
|
||||
{me?.modelsManaged ? null : (
|
||||
<>
|
||||
<label htmlFor={`${ids}-model`} className={fieldLabelClass}>
|
||||
<Trans>Model</Trans>
|
||||
<NativeSelect
|
||||
id={`${ids}-model`}
|
||||
className="mt-2 w-full"
|
||||
value={modelKey}
|
||||
onChange={(event) => {
|
||||
setModelKey(event.target.value);
|
||||
setThinkingLevel("");
|
||||
}}
|
||||
>
|
||||
<NativeSelectOption value="">
|
||||
{t`Space default`}
|
||||
{me?.defaultModel
|
||||
? ` (${catalogLabel(catalog, me.defaultProvider, me.defaultModel) ?? me.defaultModel})`
|
||||
: ""}
|
||||
</NativeSelectOption>
|
||||
{tierOptions.length ? (
|
||||
<NativeSelectOptGroup label={t`Tiers`}>
|
||||
{tierOptions.map((option) => (
|
||||
<NativeSelectOption key={option.key} value={option.key}>
|
||||
{option.label}
|
||||
</NativeSelectOption>
|
||||
))}
|
||||
</NativeSelectOptGroup>
|
||||
) : null}
|
||||
{modelKey &&
|
||||
!selectedTier &&
|
||||
!connectedOptions.some((option) => option.key === modelKey) ? (
|
||||
<NativeSelectOption value={modelKey}>
|
||||
{parseModelOptionKey(modelKey)?.modelId ?? modelKey}
|
||||
</NativeSelectOption>
|
||||
) : null}
|
||||
{connectedOptions.map((option) => (
|
||||
<NativeSelectOption key={option.key} value={option.key}>
|
||||
{option.label}
|
||||
</NativeSelectOption>
|
||||
))}
|
||||
</NativeSelectOptGroup>
|
||||
</NativeSelect>
|
||||
</label>
|
||||
{thinkingOptions.length ? (
|
||||
<label htmlFor={`${ids}-thinking`} className={fieldLabelClass}>
|
||||
<Trans>Thinking</Trans>
|
||||
<NativeSelect
|
||||
id={`${ids}-thinking`}
|
||||
className="mt-2 w-full"
|
||||
value={thinkingLevel}
|
||||
onChange={(event) => setThinkingLevel(event.target.value)}
|
||||
>
|
||||
<NativeSelectOption value="">
|
||||
{t`Default (${thinkingLevelLabel(defaultThinkingLevel)})`}
|
||||
</NativeSelectOption>
|
||||
{thinkingOptions.map((level) => (
|
||||
<NativeSelectOption key={level} value={level}>
|
||||
{thinkingLevelLabel(level)}
|
||||
</NativeSelectOption>
|
||||
))}
|
||||
</NativeSelect>
|
||||
</label>
|
||||
) : null}
|
||||
{modelKey &&
|
||||
!selectedTier &&
|
||||
!connectedOptions.some((option) => option.key === modelKey) ? (
|
||||
<NativeSelectOption value={modelKey}>
|
||||
{parseModelOptionKey(modelKey)?.modelId ?? modelKey}
|
||||
</NativeSelectOption>
|
||||
) : null}
|
||||
{connectedOptions.map((option) => (
|
||||
<NativeSelectOption key={option.key} value={option.key}>
|
||||
{option.label}
|
||||
</NativeSelectOption>
|
||||
))}
|
||||
</NativeSelect>
|
||||
</label>
|
||||
{thinkingOptions.length ? (
|
||||
<label htmlFor={`${ids}-thinking`} className={fieldLabelClass}>
|
||||
<Trans>Thinking</Trans>
|
||||
<NativeSelect
|
||||
id={`${ids}-thinking`}
|
||||
className="mt-2 w-full"
|
||||
value={thinkingLevel}
|
||||
onChange={(event) => setThinkingLevel(event.target.value)}
|
||||
>
|
||||
<NativeSelectOption value="">
|
||||
{t`Default (${thinkingLevelLabel(defaultThinkingLevel)})`}
|
||||
</NativeSelectOption>
|
||||
{thinkingOptions.map((level) => (
|
||||
<NativeSelectOption key={level} value={level}>
|
||||
{thinkingLevelLabel(level)}
|
||||
</NativeSelectOption>
|
||||
))}
|
||||
</NativeSelect>
|
||||
</label>
|
||||
) : null}
|
||||
</>
|
||||
)}
|
||||
{memoryProviderConfigured ? (
|
||||
<div className="mt-4 text-ui-body text-muted-foreground">
|
||||
<Trans>Memory scope</Trans>
|
||||
|
||||
@ -233,6 +233,19 @@ way by default.
|
||||
Only configure an endpoint you control: prompts, attachments, and tool results sent to that model
|
||||
leave evOo through this URL. Leave `RAKAZO_LOCAL_MODELS` blank to disable the provider.
|
||||
|
||||
To run every space on these models without anyone connecting one, make them the deployment's
|
||||
model, and optionally assign them to the tiers the agent delegates to. An entry can name its own
|
||||
endpoint when the models run behind different servers:
|
||||
|
||||
```env
|
||||
PI_DEFAULT_PROVIDER=local
|
||||
PI_DEFAULT_MODEL=qwen3-vl # the main agent's model; defaults to the first id
|
||||
RAKAZO_LOCAL_MODELS=qwen3-vl,llama3.1:8b,qwen3:4b=http://127.0.0.1:11435/v1
|
||||
RAKAZO_LOCAL_TIERS=fast=qwen3:4b,standard=llama3.1:8b,code=qwen3-vl
|
||||
```
|
||||
|
||||
A tier a space maps in **Settings → Models** still wins, and a tier left out keeps the run's model.
|
||||
|
||||
Each user can also connect their own OpenAI-compatible endpoint from **Connect a model** /
|
||||
**Settings → Models** on web and mobile. Choose **OpenAI-compatible**, enter the server base URL
|
||||
(for example `http://127.0.0.1:8000/v1`), the exact model id, and an optional API key.
|
||||
|
||||
@ -19,8 +19,8 @@
|
||||
"@composio/core": "0.18.1",
|
||||
"@daytona/sdk": "0.211.2",
|
||||
"@e2b/desktop": "2.4.0",
|
||||
"@earendil-works/pi-agent-core": "0.85.1",
|
||||
"@earendil-works/pi-ai": "0.85.1",
|
||||
"@earendil-works/pi-agent-core": "0.87.1",
|
||||
"@earendil-works/pi-ai": "0.87.1",
|
||||
"@modelcontextprotocol/sdk": "1.30.0",
|
||||
"@mozilla/readability": "0.6.0",
|
||||
"@observablehq/plot": "0.6.17",
|
||||
|
||||
@ -3,7 +3,7 @@ import type { ActionApprovalRule } from "@rakazo/core";
|
||||
import { type AutoReviewJudgeDecision, redactSecrets } from "@rakazo/core";
|
||||
import { formatCurrentTimeInstruction } from "./current-time.js";
|
||||
import { resolveDeploymentModel } from "./deployment-model.js";
|
||||
import { LOCAL_PROVIDER_ID } from "./pi-local-provider.js";
|
||||
import { LOCAL_PROVIDER_ID, localModelIds } from "./pi-local-provider.js";
|
||||
|
||||
const DEFAULT_TIMEOUT_MS = 1_500;
|
||||
const MAX_TASK_CHARS = 400;
|
||||
@ -29,13 +29,6 @@ function envFlag(env: NodeJS.ProcessEnv, name: string): boolean {
|
||||
return value === "1" || value === "true" || value === "yes" || value === "on";
|
||||
}
|
||||
|
||||
function localModelIds(env: NodeJS.ProcessEnv): string[] {
|
||||
return (env.RAKAZO_LOCAL_MODELS ?? "")
|
||||
.split(",")
|
||||
.map((id) => id.trim())
|
||||
.filter((id) => id.length > 0);
|
||||
}
|
||||
|
||||
/** Deployment default for the user toggle when no preference row exists. */
|
||||
export function deploymentAutoReviewDefault(env: NodeJS.ProcessEnv = process.env): boolean {
|
||||
return envFlag(env, "RAKAZO_AUTO_REVIEW");
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { resolveDeploymentModel } from "./deployment-model.js";
|
||||
import { LOCAL_API_KEY } from "./pi-local-provider.js";
|
||||
|
||||
describe("resolveDeploymentModel", () => {
|
||||
it("pairs the deployment model key with the provider it belongs to", () => {
|
||||
@ -12,12 +13,24 @@ describe("resolveDeploymentModel", () => {
|
||||
// The whole point: switching the provider switches the key with it.
|
||||
expect(resolveDeploymentModel({ ...both, PI_DEFAULT_PROVIDER: "anthropic" })).toEqual({
|
||||
provider: "anthropic",
|
||||
model: "claude-sonnet-5",
|
||||
model: "claude-opus-5-5",
|
||||
key: "sk-ant-key",
|
||||
});
|
||||
// A provider with no key configured yields no key — never another vendor's.
|
||||
expect(
|
||||
resolveDeploymentModel({ OPENROUTER_API_KEY: "or-key", PI_DEFAULT_PROVIDER: "anthropic" }),
|
||||
).toEqual({ provider: "anthropic", model: "claude-sonnet-5", key: undefined });
|
||||
).toEqual({ provider: "anthropic", model: "claude-opus-5-5", key: undefined });
|
||||
});
|
||||
|
||||
it("treats configured local models as the deployment's keyless model", () => {
|
||||
const local = { PI_DEFAULT_PROVIDER: "local", RAKAZO_LOCAL_MODELS: "strong,weak" };
|
||||
expect(resolveDeploymentModel(local)).toEqual({
|
||||
provider: "local",
|
||||
model: "strong",
|
||||
key: LOCAL_API_KEY,
|
||||
});
|
||||
expect(resolveDeploymentModel({ ...local, PI_DEFAULT_MODEL: "weak" }).model).toBe("weak");
|
||||
// Without local models there is nothing to run, so no key either.
|
||||
expect(resolveDeploymentModel({ PI_DEFAULT_PROVIDER: "local" }).key).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import { LOCAL_API_KEY, localModelIds } from "./pi-local-provider.js";
|
||||
|
||||
export const DEFAULT_OPENROUTER_MODEL_ID = "openai/gpt-5.6-luna";
|
||||
|
||||
/** What the connect flow preselects while no model is connected: the user only adds a key or signs in. */
|
||||
export const RECOMMENDED_MODEL = { provider: "anthropic", model: "claude-opus-5" } as const;
|
||||
export const RECOMMENDED_MODEL = { provider: "anthropic", model: "claude-opus-5-5" } as const;
|
||||
|
||||
/**
|
||||
* The deployment-wide model default: which provider a run falls back to when no user
|
||||
@ -14,13 +16,17 @@ export function resolveDeploymentModel(env: NodeJS.ProcessEnv = process.env) {
|
||||
// A row per provider that ships a deployment key. A third one adds a row here, not a
|
||||
// branch at each call site — and an unknown provider gets no key rather than another
|
||||
// vendor's, which a ternary on one provider would not give.
|
||||
const localIds = localModelIds(env);
|
||||
const keys: Record<string, string | undefined> = {
|
||||
openrouter: env.OPENROUTER_API_KEY,
|
||||
anthropic: env.ANTHROPIC_API_KEY,
|
||||
// Keyless: configured local models are the deployment's model on their own.
|
||||
local: localIds.length ? LOCAL_API_KEY : undefined,
|
||||
};
|
||||
const models: Record<string, string> = {
|
||||
openrouter: DEFAULT_OPENROUTER_MODEL_ID,
|
||||
anthropic: "claude-sonnet-5",
|
||||
anthropic: RECOMMENDED_MODEL.model,
|
||||
...(localIds[0] ? { local: localIds[0] } : {}),
|
||||
};
|
||||
return {
|
||||
provider,
|
||||
|
||||
@ -18,6 +18,7 @@ import {
|
||||
settleSteeringAttachmentLoads,
|
||||
} from "./executor-attachments.js";
|
||||
import { threadContextForRun } from "./executor-completion.js";
|
||||
import { LOCAL_API_KEY } from "./pi-local-provider.js";
|
||||
import { serializeModelSecret } from "./pi-oauth.js";
|
||||
|
||||
describe("tool completion audit", () => {
|
||||
@ -1706,7 +1707,11 @@ description: Prepare standup notes
|
||||
});
|
||||
|
||||
// One router connection serves several local models; tiers pick among them.
|
||||
function tierPrisma(bot: Record<string, unknown> | null, tierRow: unknown) {
|
||||
function tierPrisma(
|
||||
bot: Record<string, unknown> | null,
|
||||
tierRow: unknown,
|
||||
deploymentModelKey?: string,
|
||||
) {
|
||||
const plaintext = serializeModelSecret({
|
||||
kind: "openai_compatible",
|
||||
baseUrl: "http://127.0.0.1:8080/v1",
|
||||
@ -1740,6 +1745,7 @@ description: Prepare standup notes
|
||||
const executor = createRunExecutor({
|
||||
prisma,
|
||||
secretStore: { load: vi.fn(() => plaintext), put: vi.fn() },
|
||||
deploymentModelKey,
|
||||
} as unknown as Parameters<typeof createRunExecutor>[0]);
|
||||
return { executor, findUnique };
|
||||
}
|
||||
@ -1847,4 +1853,27 @@ description: Prepare standup notes
|
||||
unmapped.executor.resolveTierModel({ userId: "user-1", spaceId: "ws-1" }, "fast"),
|
||||
).resolves.toBeNull();
|
||||
});
|
||||
|
||||
it("falls back to the tiers a local-model deployment assigns", async () => {
|
||||
vi.stubEnv("PI_DEFAULT_PROVIDER", "local");
|
||||
vi.stubEnv("RAKAZO_LOCAL_MODELS", "strong,weak=http://127.0.0.1:1239/v1");
|
||||
vi.stubEnv("RAKAZO_LOCAL_TIERS", "fast=weak,code=strong");
|
||||
try {
|
||||
const { executor } = tierPrisma(null, null, LOCAL_API_KEY);
|
||||
await expect(
|
||||
executor.resolveTierModel({ userId: "user-1", spaceId: "ws-1" }, "fast"),
|
||||
).resolves.toMatchObject({ provider: "local", id: "weak", apiKey: LOCAL_API_KEY });
|
||||
// A tier the deployment leaves out keeps the run's own model.
|
||||
await expect(
|
||||
executor.resolveTierModel({ userId: "user-1", spaceId: "ws-1" }, "standard"),
|
||||
).resolves.toBeNull();
|
||||
// A space's own mapping still wins over the deployment's.
|
||||
const mapped = tierPrisma(null, routerTier, LOCAL_API_KEY);
|
||||
await expect(
|
||||
mapped.executor.resolveTierModel({ userId: "user-1", spaceId: "ws-1" }, "code"),
|
||||
).resolves.toMatchObject({ provider: "openai-compatible", id: "router-code" });
|
||||
} finally {
|
||||
vi.unstubAllEnvs();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@ -332,6 +332,7 @@ import {
|
||||
} from "./model-vision.js";
|
||||
import { notifyUserFromTool } from "./notify-user-tool.js";
|
||||
import { toOAuthCredential } from "./pi-credentials.js";
|
||||
import { LOCAL_PROVIDER_ID, localTierModels } from "./pi-local-provider.js";
|
||||
import {
|
||||
parseModelSecret,
|
||||
resolveModelAuth,
|
||||
@ -782,7 +783,12 @@ export function createRunExecutor(deps: ExecutorDeps) {
|
||||
registerSecrets?: (values: string[]) => void,
|
||||
): Promise<AgentRunRequest["model"] | null> => {
|
||||
const mapped = await findSpaceModelTier(deps.prisma, scope, tier);
|
||||
if (!mapped) return null;
|
||||
if (!mapped) {
|
||||
// A deployment serving local models may assign them to tiers for every space.
|
||||
const deploymentTier = deps.deploymentModelKey ? localTierModels()[tier] : undefined;
|
||||
if (!deploymentTier || resolveDeploymentModel().provider !== LOCAL_PROVIDER_ID) return null;
|
||||
return connectedModel(scope, null, LOCAL_PROVIDER_ID, deploymentTier, registerSecrets);
|
||||
}
|
||||
return connectedModel(
|
||||
scope,
|
||||
mapped.credential,
|
||||
|
||||
@ -4,6 +4,7 @@ import {
|
||||
LOCAL_PROVIDER_ID,
|
||||
localBaseUrl,
|
||||
localProvider,
|
||||
localTierModels,
|
||||
registerLocalProvider,
|
||||
} from "./pi-local-provider.js";
|
||||
|
||||
@ -12,6 +13,7 @@ const ENV_KEYS = [
|
||||
"RAKAZO_LOCAL_MODELS_URL",
|
||||
"RAKAZO_LOCAL_CONTEXT_WINDOW",
|
||||
"RAKAZO_LOCAL_MAX_TOKENS",
|
||||
"RAKAZO_LOCAL_TIERS",
|
||||
] as const;
|
||||
|
||||
const saved = new Map<string, string | undefined>();
|
||||
@ -114,4 +116,21 @@ describe("local model provider", () => {
|
||||
const withLocal = registerLocalProvider(builtinModels());
|
||||
expect(withLocal.getModel(LOCAL_PROVIDER_ID, "qwen3:4b")).toBeDefined();
|
||||
});
|
||||
|
||||
it("serves each model from its own server when the entry names one", () => {
|
||||
process.env.RAKAZO_LOCAL_MODELS_URL = "http://127.0.0.1:1234/v1";
|
||||
setModels("strong, weak=http://127.0.0.1:1239/v1");
|
||||
const models = registerLocalProvider(builtinModels());
|
||||
expect(models.getModel(LOCAL_PROVIDER_ID, "strong")?.baseUrl).toBe("http://127.0.0.1:1234/v1");
|
||||
expect(models.getModel(LOCAL_PROVIDER_ID, "weak")?.baseUrl).toBe("http://127.0.0.1:1239/v1");
|
||||
|
||||
setModels("weak=not a url");
|
||||
expect(() => localProvider()).toThrow(/URL for weak must be an absolute HTTP\(S\) URL/);
|
||||
});
|
||||
|
||||
it("maps tiers only to configured local models", () => {
|
||||
setModels("strong,weak=http://127.0.0.1:1239/v1");
|
||||
process.env.RAKAZO_LOCAL_TIERS = "fast=weak, code=strong, standard=missing, huge=strong";
|
||||
expect(localTierModels()).toEqual({ fast: "weak", code: "strong" });
|
||||
});
|
||||
});
|
||||
|
||||
@ -6,6 +6,7 @@ import {
|
||||
} from "@earendil-works/pi-ai";
|
||||
import { openAICompletionsApi } from "@earendil-works/pi-ai/api/openai-completions.lazy";
|
||||
|
||||
import { type ModelTier, ModelTierSchema } from "@rakazo/contracts";
|
||||
import { declaredVisionModelIds, inputModalities } from "./model-modalities.js";
|
||||
/**
|
||||
* Local OpenAI-compatible model server (Ollama, LM Studio, llama.cpp, MLX).
|
||||
@ -19,6 +20,9 @@ import { declaredVisionModelIds, inputModalities } from "./model-modalities.js";
|
||||
*/
|
||||
export const LOCAL_PROVIDER_ID = "local";
|
||||
|
||||
/** Placeholder sent as the key: local servers ignore it, and it is distinct enough to redact safely. */
|
||||
export const LOCAL_API_KEY = "rakazo-local-model-server";
|
||||
|
||||
/** Model ids the local server serves with vision, declared by the operator. */
|
||||
export const LOCAL_VISION_MODELS_ENV = "RAKAZO_LOCAL_VISION_MODELS";
|
||||
|
||||
@ -31,15 +35,18 @@ const DEFAULT_CONTEXT_WINDOW = 32_768;
|
||||
const DEFAULT_MAX_TOKENS = 4_096;
|
||||
|
||||
export function localBaseUrl(): string {
|
||||
const value = process.env.RAKAZO_LOCAL_MODELS_URL?.trim() || DEFAULT_BASE_URL;
|
||||
return checkedUrl(process.env.RAKAZO_LOCAL_MODELS_URL?.trim() || DEFAULT_BASE_URL);
|
||||
}
|
||||
|
||||
function checkedUrl(value: string, name = "RAKAZO_LOCAL_MODELS_URL"): string {
|
||||
let url: URL;
|
||||
try {
|
||||
url = new URL(value);
|
||||
} catch {
|
||||
throw new Error("RAKAZO_LOCAL_MODELS_URL must be an absolute HTTP(S) URL");
|
||||
throw new Error(`${name} must be an absolute HTTP(S) URL`);
|
||||
}
|
||||
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
||||
throw new Error("RAKAZO_LOCAL_MODELS_URL must be an absolute HTTP(S) URL");
|
||||
throw new Error(`${name} must be an absolute HTTP(S) URL`);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@ -61,21 +68,53 @@ function tokenLimit(name: string, fallback: number): number {
|
||||
return value;
|
||||
}
|
||||
|
||||
/** Comma-separated model ids exactly as the local server names them. */
|
||||
function localModelIds(): string[] {
|
||||
return (process.env.RAKAZO_LOCAL_MODELS ?? "")
|
||||
/**
|
||||
* Comma-separated model ids exactly as the local server names them. An entry may name its own
|
||||
* server as `id=url` when the models run behind different endpoints.
|
||||
*/
|
||||
function localModelEntries(env: NodeJS.ProcessEnv): { id: string; baseUrl?: string }[] {
|
||||
return (env.RAKAZO_LOCAL_MODELS ?? "")
|
||||
.split(",")
|
||||
.map((id) => id.trim())
|
||||
.filter((id) => id.length > 0);
|
||||
.map((entry) => entry.trim())
|
||||
.filter((entry) => entry.length > 0)
|
||||
.map((entry) => {
|
||||
const separator = entry.indexOf("=");
|
||||
if (separator < 0) return { id: entry };
|
||||
return { id: entry.slice(0, separator).trim(), baseUrl: entry.slice(separator + 1).trim() };
|
||||
});
|
||||
}
|
||||
|
||||
function localModel(id: string): Model<"openai-completions"> {
|
||||
export function localModelIds(env: NodeJS.ProcessEnv = process.env): string[] {
|
||||
return localModelEntries(env).map((entry) => entry.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* The deployment's tiers served by local models, from `RAKAZO_LOCAL_TIERS` (`tier=id,…`).
|
||||
* Entries naming an unknown tier or a model outside `RAKAZO_LOCAL_MODELS` are ignored.
|
||||
*/
|
||||
export function localTierModels(
|
||||
env: NodeJS.ProcessEnv = process.env,
|
||||
): Partial<Record<ModelTier, string>> {
|
||||
const ids = new Set(localModelIds(env));
|
||||
const tiers: Partial<Record<ModelTier, string>> = {};
|
||||
for (const entry of (env.RAKAZO_LOCAL_TIERS ?? "").split(",")) {
|
||||
const [tier, id] = entry.split("=").map((part) => part.trim());
|
||||
const parsed = ModelTierSchema.safeParse(tier);
|
||||
if (parsed.success && id && ids.has(id)) tiers[parsed.data] = id;
|
||||
}
|
||||
return tiers;
|
||||
}
|
||||
|
||||
function localModel(entry: { id: string; baseUrl?: string }): Model<"openai-completions"> {
|
||||
const { id } = entry;
|
||||
return {
|
||||
id,
|
||||
name: id,
|
||||
api: "openai-completions",
|
||||
provider: LOCAL_PROVIDER_ID,
|
||||
baseUrl: localBaseUrl(),
|
||||
baseUrl: entry.baseUrl
|
||||
? checkedUrl(entry.baseUrl, `The RAKAZO_LOCAL_MODELS URL for ${id}`)
|
||||
: localBaseUrl(),
|
||||
reasoning: false,
|
||||
compat: { supportsDeveloperRole: false, supportsReasoningEffort: false },
|
||||
input: inputModalities(localVisionModelIds().has(id)),
|
||||
@ -88,8 +127,8 @@ function localModel(id: string): Model<"openai-completions"> {
|
||||
|
||||
/** The provider, or undefined when no local models are configured. */
|
||||
export function localProvider(): Provider | undefined {
|
||||
const ids = localModelIds();
|
||||
if (!ids.length) return undefined;
|
||||
const entries = localModelEntries(process.env);
|
||||
if (!entries.length) return undefined;
|
||||
return createProvider({
|
||||
id: LOCAL_PROVIDER_ID,
|
||||
name: "Local (Ollama / LM Studio)",
|
||||
@ -98,12 +137,12 @@ export function localProvider(): Provider | undefined {
|
||||
apiKey: {
|
||||
name: "Local model server",
|
||||
resolve: async () => ({
|
||||
auth: { apiKey: "local", baseUrl: localBaseUrl() },
|
||||
auth: { apiKey: LOCAL_API_KEY, baseUrl: localBaseUrl() },
|
||||
source: "local model server",
|
||||
}),
|
||||
},
|
||||
},
|
||||
models: ids.map(localModel),
|
||||
models: entries.map(localModel),
|
||||
api: openAICompletionsApi(),
|
||||
});
|
||||
}
|
||||
|
||||
@ -127,6 +127,11 @@ describe("catalogModelLabel", () => {
|
||||
["gemini-flash-latest", "Gemini Flash Latest", "Gemini Flash (auto-updates)"],
|
||||
["foo-latest", "foo-latest", "foo (auto-updates)"],
|
||||
["foo/latest", "foo/latest", "foo (auto-updates)"],
|
||||
[
|
||||
"accounts/fireworks/routers/qwen-max-latest",
|
||||
"Qwen Max Latest (Qwen3.8 Max)",
|
||||
"Qwen Max (auto-updates)",
|
||||
],
|
||||
// Pinned: `-preview` is its own model and a dated id is already a snapshot, so promise nothing.
|
||||
["foo", "Foo Latest", "Foo"],
|
||||
["claude-opus-4-5-20251101", "Claude Opus 4.5 (latest)", "Claude Opus 4.5"],
|
||||
|
||||
@ -98,6 +98,8 @@ function buildPiCatalog(): PiCatalogEntry[] {
|
||||
|
||||
/** Trailing upstream "latest" marker: "Claude Opus 4.5 (latest)", "Gemini Flash Latest", "foo-latest". */
|
||||
const LATEST_MARKER = /[\s(/-]*\blatest\b\s*\)?\s*$/i;
|
||||
/** Router aliases name their current target after the marker: "Qwen Max Latest (Qwen3.8 Max)". */
|
||||
const LATEST_ROUTER_MARKER = /\s+\blatest\b\s*\([^)]*\)\s*$/i;
|
||||
|
||||
/**
|
||||
* Upstream marks auto-updating alias ids with a trailing "latest". That is an alias marker, not a
|
||||
@ -111,8 +113,9 @@ export function catalogModelLabel(
|
||||
providerModelIds: readonly string[] = [],
|
||||
): string {
|
||||
const label = name || id;
|
||||
if (!LATEST_MARKER.test(label)) return label;
|
||||
const base = label.replace(LATEST_MARKER, "").trim();
|
||||
const marker = [LATEST_MARKER, LATEST_ROUTER_MARKER].find((pattern) => pattern.test(label));
|
||||
if (!marker) return label;
|
||||
const base = label.replace(marker, "").trim();
|
||||
if (!base) return label;
|
||||
return isAliasModelId(id, providerModelIds) ? `${base} (auto-updates)` : base;
|
||||
}
|
||||
|
||||
@ -1277,6 +1277,8 @@ export const MeSchema = z.object({
|
||||
spaceId: Id,
|
||||
isDeploymentOwner: z.boolean(),
|
||||
needsModel: z.boolean(),
|
||||
/** The deployment picks and routes models itself, so nobody chooses one. */
|
||||
modelsManaged: z.boolean(),
|
||||
defaultProvider: z.string().nullable(),
|
||||
defaultModel: z.string().nullable(),
|
||||
computerHost: z.enum(["docker", "this-mac"]).nullable(),
|
||||
|
||||
502
pnpm-lock.yaml
generated
502
pnpm-lock.yaml
generated
@ -559,11 +559,11 @@ importers:
|
||||
specifier: 2.4.0
|
||||
version: 2.4.0
|
||||
'@earendil-works/pi-agent-core':
|
||||
specifier: 0.85.1
|
||||
version: 0.85.1(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(zod@4.6.2))(ws@8.21.3)(zod@4.6.2)
|
||||
specifier: 0.87.1
|
||||
version: 0.87.1(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(zod@4.6.2))(ws@8.21.3)(zod@4.6.2)
|
||||
'@earendil-works/pi-ai':
|
||||
specifier: 0.85.1
|
||||
version: 0.85.1(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(zod@4.6.2))(ws@8.21.3)(zod@4.6.2)
|
||||
specifier: 0.87.1
|
||||
version: 0.87.1(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(zod@4.6.2))(ws@8.21.3)(zod@4.6.2)
|
||||
'@modelcontextprotocol/sdk':
|
||||
specifier: 1.30.0
|
||||
version: 1.30.0(@cfworker/json-schema@4.1.1)(zod@4.6.2)
|
||||
@ -931,8 +931,8 @@ importers:
|
||||
|
||||
packages:
|
||||
|
||||
'@anthropic-ai/sdk@0.123.0':
|
||||
resolution: {integrity: sha512-Y9oX9mPNGZClHQOFqrWRk43Srcu/UHuPq3rfxxOq7JgW0gi+lJA2MAOK4Ul3k/+AUrwRWFJvd0tK3oC0Pw25dw==}
|
||||
'@anthropic-ai/sdk@0.124.0':
|
||||
resolution: {integrity: sha512-cN5O8i9UVxHeOQAzj/XjshWXG8KiibJDw9OGpH2Z/eR3n/RBxdoLxDJOcfqAJWvjaMDFfHTBADU04hWRJVkDyA==}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
zod: ^3.25.0 || ^4.0.0
|
||||
@ -1062,25 +1062,12 @@ packages:
|
||||
'@astrojs/yaml2ts@0.2.4':
|
||||
resolution: {integrity: sha512-8oddpOae35pJsXPQXhTkM0ypfKPskVsh2bCxRtbf7e+/Epw2nReakFYpLKjZMEr75CsoF203PMnCocpfz0s69A==}
|
||||
|
||||
'@aws-crypto/sha256-browser@5.2.0':
|
||||
resolution: {integrity: sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==}
|
||||
|
||||
'@aws-crypto/sha256-js@5.2.0':
|
||||
resolution: {integrity: sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==}
|
||||
engines: {node: '>=16.0.0'}
|
||||
|
||||
'@aws-crypto/supports-web-crypto@5.2.0':
|
||||
resolution: {integrity: sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==}
|
||||
|
||||
'@aws-crypto/util@5.2.0':
|
||||
resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==}
|
||||
|
||||
'@aws-sdk/checksums@3.1000.29':
|
||||
resolution: {integrity: sha512-Dtu0gr4dnATZAPwEYbpCsG+MpLM7OAliy2gTepEFQwl1vZ6DL3QMH2FveMa3HLvPsOdhJsPRB3KtxVhph9T75A==}
|
||||
engines: {node: '>=20.0.0'}
|
||||
|
||||
'@aws-sdk/client-bedrock-runtime@3.1048.0':
|
||||
resolution: {integrity: sha512-u+NT61JZEkRFtpL0CAw1N1dwxnaLgwVXQl/zjJxTGgLyS/jTIdg2SdoEoCTHxgDyCnqa1HEi9QOoE9/pYRNpOQ==}
|
||||
'@aws-sdk/client-bedrock-runtime@3.1127.0':
|
||||
resolution: {integrity: sha512-IDl/lrPb90aH+pZFHGNDmgH9nAUQj5PlZH1sJ3w7RikctyjHSnY3oNjZhrLoaBoQn/rNK0zsP6OHEqEhj2tdLA==}
|
||||
engines: {node: '>=20.0.0'}
|
||||
|
||||
'@aws-sdk/client-s3@3.1127.0':
|
||||
@ -1153,20 +1140,16 @@ packages:
|
||||
resolution: {integrity: sha512-L+2xZTye/2T96f3lwCws0Zw6GG2JHZW9e8FpVgGBeeExSKyeoZ6CWRpBml/7DNiK/O26jrgPM9F+Ay8VkgzUWQ==}
|
||||
engines: {node: '>=20.0.0'}
|
||||
|
||||
'@aws-sdk/token-providers@3.1048.0':
|
||||
resolution: {integrity: sha512-k0y/GcuesuSfWyUM0WamrGyeZmltRYaPbHO82UDA6mZ/doB+FOHKutikPAtSXMn/hDz970cF+iRuuiYO9VEbAA==}
|
||||
engines: {node: '>=20.0.0'}
|
||||
|
||||
'@aws-sdk/token-providers@3.1116.0':
|
||||
resolution: {integrity: sha512-ygIivKqh8aHzNkucOCXHyIBgBpLPfrSI0mCqXF+vLBsPTUKqj0VSqAY0GFPe7lQl4HntjOcQ+KSyS7oUV2C54Q==}
|
||||
engines: {node: '>=20.0.0'}
|
||||
|
||||
'@aws-sdk/types@3.974.5':
|
||||
resolution: {integrity: sha512-LkwLL2BLbC6wNNm4JaH9mbEqBMdOZCct6VAYqhdN4U1xrWM+fUJQEfbHwQgDypapOWTRtlk25akb5afM0P8CIQ==}
|
||||
'@aws-sdk/token-providers@3.1127.0':
|
||||
resolution: {integrity: sha512-Dv2TMWBshJ+tF6ahs2Sy5bh4Iabsd4GAQqVvE9XZmYmnoaVbpS2QKIKE/HRacc7bTtbjEEvP+laGzHvHlf1CiQ==}
|
||||
engines: {node: '>=20.0.0'}
|
||||
|
||||
'@aws-sdk/util-locate-window@3.965.10':
|
||||
resolution: {integrity: sha512-ycwH6Zd2GhuSqdXX9ihbCjeGTB6xOJs+O3+Jb8/zDG9978XU80qs75dfkPJRMNKe5MvBZPuNeFpd4JZKPoUF4g==}
|
||||
'@aws-sdk/types@3.974.5':
|
||||
resolution: {integrity: sha512-LkwLL2BLbC6wNNm4JaH9mbEqBMdOZCct6VAYqhdN4U1xrWM+fUJQEfbHwQgDypapOWTRtlk25akb5afM0P8CIQ==}
|
||||
engines: {node: '>=20.0.0'}
|
||||
|
||||
'@aws-sdk/xml-builder@3.972.40':
|
||||
@ -1932,21 +1915,21 @@ packages:
|
||||
resolution: {integrity: sha512-eeY4p/lz7kkDJMidREe7sp2nln16P1M1p64Fb+csn4SssxC2EjKBGqP0NEIlVDVd6iCuPbM7cVlkE/qbwJX4jg==}
|
||||
engines: {node: '>=20.18.1 <21 || >=22'}
|
||||
|
||||
'@earendil-works/chord@0.85.1':
|
||||
resolution: {integrity: sha512-VDlkEC3dhCzQ5fcyH1OhG19dq+6jCn+rqc/iXFivwDYGR5anwo2RCiXij9PpHhqNR5GuhhE+Er69Zi1Sn4eY6w==}
|
||||
'@earendil-works/chord@0.87.1':
|
||||
resolution: {integrity: sha512-bg7IkJGFcEaMqqYgOGUiq5Ky9RghpRfrlZ8I/v/1b4bBZ02A7t3E+6uhPRbadwWb/kWsnVFbZsqOKRN4a3LLCg==}
|
||||
engines: {node: '>=22.19.0'}
|
||||
|
||||
'@earendil-works/pi-agent-core@0.85.1':
|
||||
resolution: {integrity: sha512-hIXIP3eAWueAYiAl8aMvWCvvZ8Q5gT3Dip5bE5uJyIGh4+YlWRjtMLI4BaeoXoSs93zndjue61u1B/vhefLnuA==}
|
||||
'@earendil-works/pi-agent-core@0.87.1':
|
||||
resolution: {integrity: sha512-Zev3B0HK7YS5A4EZQ2XnEqiJuirx6QBiltJ+LpmjV5a/+2IU0cfKtIfnkNkORK707XOvKBY2WRtk7cAwHpbh2Q==}
|
||||
engines: {node: '>=22.19.0'}
|
||||
|
||||
'@earendil-works/pi-ai@0.85.1':
|
||||
resolution: {integrity: sha512-+VgVIJDkDO2efYJKEEqvPTH4zmnIaXdAppGbO+vKFA9qy5PdhFiAenuFAkU+oiCSfOC4dMHDyrjdQeL4ZoC5CQ==}
|
||||
'@earendil-works/pi-ai@0.87.1':
|
||||
resolution: {integrity: sha512-X/3PfQBnnoeVdO9Cv8zHghUMglzlgNZYGNzoPnbRoGnHl3Rw3TlA2UKSUB7BRHUOxMryHXYa8dnjWZlbRheDZA==}
|
||||
engines: {node: '>=22.19.0'}
|
||||
hasBin: true
|
||||
|
||||
'@earendil-works/pi-telemetry@0.85.1':
|
||||
resolution: {integrity: sha512-Bg/YN6kA7Swja/NQxka8xFdecb4E/auIEGF2G5A25EaQXhRnPj300/7/KpgsDDMYUzHTDAv4RyUxaQPJKW81Rw==}
|
||||
'@earendil-works/pi-telemetry@0.87.1':
|
||||
resolution: {integrity: sha512-MC6TRQH5lgMXpcN+Vku2WMI2T8BsiUPzMQHGo81uqFZD3/9O79WWJAysEDGuzduP6R4tvtgwMLwmqIxynM10JQ==}
|
||||
engines: {node: '>=22.19.0'}
|
||||
|
||||
'@egjs/hammerjs@2.0.17':
|
||||
@ -2047,312 +2030,156 @@ packages:
|
||||
'@epic-web/invariant@1.0.0':
|
||||
resolution: {integrity: sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA==}
|
||||
|
||||
'@esbuild/aix-ppc64@0.28.1':
|
||||
resolution: {integrity: sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ppc64]
|
||||
os: [aix]
|
||||
|
||||
'@esbuild/aix-ppc64@0.28.2':
|
||||
resolution: {integrity: sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ppc64]
|
||||
os: [aix]
|
||||
|
||||
'@esbuild/android-arm64@0.28.1':
|
||||
resolution: {integrity: sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/android-arm64@0.28.2':
|
||||
resolution: {integrity: sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/android-arm@0.28.1':
|
||||
resolution: {integrity: sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/android-arm@0.28.2':
|
||||
resolution: {integrity: sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/android-x64@0.28.1':
|
||||
resolution: {integrity: sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/android-x64@0.28.2':
|
||||
resolution: {integrity: sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/darwin-arm64@0.28.1':
|
||||
resolution: {integrity: sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@esbuild/darwin-arm64@0.28.2':
|
||||
resolution: {integrity: sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@esbuild/darwin-x64@0.28.1':
|
||||
resolution: {integrity: sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@esbuild/darwin-x64@0.28.2':
|
||||
resolution: {integrity: sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@esbuild/freebsd-arm64@0.28.1':
|
||||
resolution: {integrity: sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [freebsd]
|
||||
|
||||
'@esbuild/freebsd-arm64@0.28.2':
|
||||
resolution: {integrity: sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [freebsd]
|
||||
|
||||
'@esbuild/freebsd-x64@0.28.1':
|
||||
resolution: {integrity: sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
|
||||
'@esbuild/freebsd-x64@0.28.2':
|
||||
resolution: {integrity: sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
|
||||
'@esbuild/linux-arm64@0.28.1':
|
||||
resolution: {integrity: sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-arm64@0.28.2':
|
||||
resolution: {integrity: sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-arm@0.28.1':
|
||||
resolution: {integrity: sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-arm@0.28.2':
|
||||
resolution: {integrity: sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-ia32@0.28.1':
|
||||
resolution: {integrity: sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ia32]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-ia32@0.28.2':
|
||||
resolution: {integrity: sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ia32]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-loong64@0.28.1':
|
||||
resolution: {integrity: sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [loong64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-loong64@0.28.2':
|
||||
resolution: {integrity: sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [loong64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-mips64el@0.28.1':
|
||||
resolution: {integrity: sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [mips64el]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-mips64el@0.28.2':
|
||||
resolution: {integrity: sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [mips64el]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-ppc64@0.28.1':
|
||||
resolution: {integrity: sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-ppc64@0.28.2':
|
||||
resolution: {integrity: sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-riscv64@0.28.1':
|
||||
resolution: {integrity: sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-riscv64@0.28.2':
|
||||
resolution: {integrity: sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-s390x@0.28.1':
|
||||
resolution: {integrity: sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-s390x@0.28.2':
|
||||
resolution: {integrity: sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-x64@0.28.1':
|
||||
resolution: {integrity: sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-x64@0.28.2':
|
||||
resolution: {integrity: sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/netbsd-arm64@0.28.1':
|
||||
resolution: {integrity: sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [netbsd]
|
||||
|
||||
'@esbuild/netbsd-arm64@0.28.2':
|
||||
resolution: {integrity: sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [netbsd]
|
||||
|
||||
'@esbuild/netbsd-x64@0.28.1':
|
||||
resolution: {integrity: sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [netbsd]
|
||||
|
||||
'@esbuild/netbsd-x64@0.28.2':
|
||||
resolution: {integrity: sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [netbsd]
|
||||
|
||||
'@esbuild/openbsd-arm64@0.28.1':
|
||||
resolution: {integrity: sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [openbsd]
|
||||
|
||||
'@esbuild/openbsd-arm64@0.28.2':
|
||||
resolution: {integrity: sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [openbsd]
|
||||
|
||||
'@esbuild/openbsd-x64@0.28.1':
|
||||
resolution: {integrity: sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [openbsd]
|
||||
|
||||
'@esbuild/openbsd-x64@0.28.2':
|
||||
resolution: {integrity: sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [openbsd]
|
||||
|
||||
'@esbuild/openharmony-arm64@0.28.1':
|
||||
resolution: {integrity: sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [openharmony]
|
||||
|
||||
'@esbuild/openharmony-arm64@0.28.2':
|
||||
resolution: {integrity: sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [openharmony]
|
||||
|
||||
'@esbuild/sunos-x64@0.28.1':
|
||||
resolution: {integrity: sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [sunos]
|
||||
|
||||
'@esbuild/sunos-x64@0.28.2':
|
||||
resolution: {integrity: sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [sunos]
|
||||
|
||||
'@esbuild/win32-arm64@0.28.1':
|
||||
resolution: {integrity: sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@esbuild/win32-arm64@0.28.2':
|
||||
resolution: {integrity: sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@esbuild/win32-ia32@0.28.1':
|
||||
resolution: {integrity: sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
||||
'@esbuild/win32-ia32@0.28.2':
|
||||
resolution: {integrity: sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
||||
'@esbuild/win32-x64@0.28.1':
|
||||
resolution: {integrity: sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@esbuild/win32-x64@0.28.2':
|
||||
resolution: {integrity: sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==}
|
||||
engines: {node: '>=18'}
|
||||
@ -2577,8 +2404,8 @@ packages:
|
||||
'@fontsource-variable/inter@5.3.0':
|
||||
resolution: {integrity: sha512-OupL48va4JNofb97w6NYeF9S7W/kHNKM0Er8Dem5nqi4jeOLrVJDoE8tZEpnMJmtkvNbB1EIPPwHcdkF6b1oUA==}
|
||||
|
||||
'@google/genai@1.52.0':
|
||||
resolution: {integrity: sha512-gwSvbpiN/17O9TbsqSsE/OzZcpv5Fo4RQjdngGgogtuB9RsyJ8ZHhX5KjHj1bp5N9snN2eK8LDGXSaWW2hof8Q==}
|
||||
'@google/genai@2.21.0':
|
||||
resolution: {integrity: sha512-+PDtco2/Z0ONdzCGekCoCT+O1VJS9xJQNN4XzQpXG/t3El/SWWMkCWlFRO1KmivOHPa4Q0VjUYu1HBKCZ/v33Q==}
|
||||
engines: {node: '>=20.0.0'}
|
||||
peerDependencies:
|
||||
'@modelcontextprotocol/sdk': ^1.25.2
|
||||
@ -4000,18 +3827,10 @@ packages:
|
||||
resolution: {integrity: sha512-ycSJu3tFAQ4v04CBB0agqFMVsSQ1iG3yw+SpgxRqKfaURpQD4CZ8Wn0zPMmSnOuTpTh65Vz+EA0rMrw089wvkA==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
|
||||
'@smithy/is-array-buffer@2.2.0':
|
||||
resolution: {integrity: sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
|
||||
'@smithy/node-http-handler@4.12.1':
|
||||
resolution: {integrity: sha512-ThMkboGeONWXAelq9FvGsuJC4rOi+qyC4/zhUF58xYpxUg5sQKx2VXZYJmtNjr4dSuBJ1HeJXETQILCz3wOHvw==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
|
||||
'@smithy/node-http-handler@4.7.3':
|
||||
resolution: {integrity: sha512-/jPhevcTFPMVl6KNjbaI47iOg1zxC7IsnX4PQDGVZKMFceOXtB8IEYaB7a9VvkP/3oC60WzTeKocvSI7vLT0vA==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
|
||||
'@smithy/signature-v4@5.7.3':
|
||||
resolution: {integrity: sha512-7ImGm+FkHRLcBaRttIAMZ6bzJZWb2cJGoYjq46F2UjycujWzrL9GEN9h4w7eQyXJYnltrUhxbbieBAIRrdqpow==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
@ -4020,14 +3839,6 @@ packages:
|
||||
resolution: {integrity: sha512-CgB6HHWer/vrKps24ulRIbpcpb7K4xAU7SkZ7YHzBPlwHsvsrCJFEXK421s+cJzX+ZrqtA/TuU5w1HzI7k9N8A==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
|
||||
'@smithy/util-buffer-from@2.2.0':
|
||||
resolution: {integrity: sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
|
||||
'@smithy/util-utf8@2.3.0':
|
||||
resolution: {integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
|
||||
'@socket.io/component-emitter@3.1.2':
|
||||
resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==}
|
||||
|
||||
@ -4670,6 +4481,10 @@ packages:
|
||||
resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==}
|
||||
engines: {node: '>= 14'}
|
||||
|
||||
agent-base@9.0.0:
|
||||
resolution: {integrity: sha512-TQf59BsZnytt8GdJKLPfUZ54g/iaUL2OWDSFCCvMOhsHduDQxO8xC4PNeyIkVcA5KwL2phPSv0douC0fgWzmnA==}
|
||||
engines: {node: '>= 20'}
|
||||
|
||||
agent-cli-detector@0.1.7:
|
||||
resolution: {integrity: sha512-d8OWDVdZMgjhLUT9ZPgSv/BdFFF9pVuscC0JdUSz3bjwE15gcp6u/o0/JooM2yyAWC49KThFhXlgTXRa9B7yng==}
|
||||
engines: {node: '>=18.18'}
|
||||
@ -6016,11 +5831,6 @@ packages:
|
||||
es6-error@4.1.1:
|
||||
resolution: {integrity: sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==}
|
||||
|
||||
esbuild@0.28.1:
|
||||
resolution: {integrity: sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==}
|
||||
engines: {node: '>=18'}
|
||||
hasBin: true
|
||||
|
||||
esbuild@0.28.2:
|
||||
resolution: {integrity: sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==}
|
||||
engines: {node: '>=18'}
|
||||
@ -6772,6 +6582,10 @@ packages:
|
||||
resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==}
|
||||
engines: {node: '>= 14'}
|
||||
|
||||
http-proxy-agent@9.1.0:
|
||||
resolution: {integrity: sha512-2NxoveTT58mjYT4n3RPTEfCZGLMbidoO8XEieXfpSYxu+PQJ1qpx4ypwH6N+uF9twBPIvRRgvkvW5HUTYWENig==}
|
||||
engines: {node: '>= 20'}
|
||||
|
||||
http2-wrapper@1.0.3:
|
||||
resolution: {integrity: sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==}
|
||||
engines: {node: '>=10.19.0'}
|
||||
@ -6788,6 +6602,10 @@ packages:
|
||||
resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==}
|
||||
engines: {node: '>= 14'}
|
||||
|
||||
https-proxy-agent@9.1.0:
|
||||
resolution: {integrity: sha512-ag87y7cJJ9/3+GxFr8Oy4O5faDsGRGnBGsJj/YjOSsSx/5eadKLYTMPlzuR6obgoCDDm0abAAZitXXQkMOPSpA==}
|
||||
engines: {node: '>= 20'}
|
||||
|
||||
human-signals@2.1.0:
|
||||
resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
|
||||
engines: {node: '>=10.17.0'}
|
||||
@ -6810,8 +6628,8 @@ packages:
|
||||
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
|
||||
engines: {node: '>= 4'}
|
||||
|
||||
ignore@7.0.5:
|
||||
resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==}
|
||||
ignore@7.0.8:
|
||||
resolution: {integrity: sha512-YYNsSlXBjMk92SKnkwvB5LOVSa6OznlFUGcsvrFgNJbJCd0M1XKeFVRc8ZByeCqz32FivYNHJVooLmdqrmvp/Q==}
|
||||
engines: {node: '>= 4'}
|
||||
|
||||
import-fresh@3.3.1:
|
||||
@ -8307,6 +8125,15 @@ packages:
|
||||
resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
|
||||
engines: {node: '>= 0.10'}
|
||||
|
||||
proxy-agent-negotiate@1.1.0:
|
||||
resolution: {integrity: sha512-N8IBcM3UgCVzz2L2Lqv8DVntDnnC8/hiV4nEDUPkqq72TPUgYWjQc+bdZlBPZK9LzPAvOY//gAt0S0DApoOXWQ==}
|
||||
engines: {node: '>= 20'}
|
||||
peerDependencies:
|
||||
kerberos: ^2.0.0
|
||||
peerDependenciesMeta:
|
||||
kerberos:
|
||||
optional: true
|
||||
|
||||
proxy-from-env@2.1.0:
|
||||
resolution: {integrity: sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==}
|
||||
engines: {node: '>=10'}
|
||||
@ -9317,8 +9144,8 @@ packages:
|
||||
resolution: {integrity: sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==}
|
||||
engines: {node: '>= 18'}
|
||||
|
||||
typebox@1.3.7:
|
||||
resolution: {integrity: sha512-meKuifc33Pccx0O6PdIzYMq3Og8zvP4TIi/a+Bw3AEMZMxOD0+RHGQvpglEe6Zdy3wZ8nqn/j95h8LUZLk/6Hg==}
|
||||
typebox@1.3.27:
|
||||
resolution: {integrity: sha512-zu+jc1pcy4UiNThxikUr36f0Rybk9PEeCg/NE6adeWr/SKsdNO4EzZHYRDlv2YCVAfj3Odq3dESSo/jNyoBXzA==}
|
||||
|
||||
typesafe-path@0.2.2:
|
||||
resolution: {integrity: sha512-OJabfkAg1WLZSqJAJ0Z6Sdt3utnbzr/jh+NAHoyWHJe8CMSy79Gm085094M9nvTPy22KzTVn5Zq5mbapCI/hPA==}
|
||||
@ -10016,7 +9843,7 @@ packages:
|
||||
|
||||
snapshots:
|
||||
|
||||
'@anthropic-ai/sdk@0.123.0(zod@4.6.2)':
|
||||
'@anthropic-ai/sdk@0.124.0(zod@4.6.2)':
|
||||
dependencies:
|
||||
json-schema-to-ts: 3.1.1
|
||||
standardwebhooks: 1.1.1
|
||||
@ -10196,32 +10023,6 @@ snapshots:
|
||||
dependencies:
|
||||
yaml: 2.9.0
|
||||
|
||||
'@aws-crypto/sha256-browser@5.2.0':
|
||||
dependencies:
|
||||
'@aws-crypto/sha256-js': 5.2.0
|
||||
'@aws-crypto/supports-web-crypto': 5.2.0
|
||||
'@aws-crypto/util': 5.2.0
|
||||
'@aws-sdk/types': 3.974.5
|
||||
'@aws-sdk/util-locate-window': 3.965.10
|
||||
'@smithy/util-utf8': 2.3.0
|
||||
tslib: 2.8.1
|
||||
|
||||
'@aws-crypto/sha256-js@5.2.0':
|
||||
dependencies:
|
||||
'@aws-crypto/util': 5.2.0
|
||||
'@aws-sdk/types': 3.974.5
|
||||
tslib: 2.8.1
|
||||
|
||||
'@aws-crypto/supports-web-crypto@5.2.0':
|
||||
dependencies:
|
||||
tslib: 2.8.1
|
||||
|
||||
'@aws-crypto/util@5.2.0':
|
||||
dependencies:
|
||||
'@aws-sdk/types': 3.974.5
|
||||
'@smithy/util-utf8': 2.3.0
|
||||
tslib: 2.8.1
|
||||
|
||||
'@aws-sdk/checksums@3.1000.29':
|
||||
dependencies:
|
||||
'@aws-sdk/core': 3.977.9
|
||||
@ -10230,16 +10031,14 @@ snapshots:
|
||||
'@smithy/types': 4.18.0
|
||||
tslib: 2.8.1
|
||||
|
||||
'@aws-sdk/client-bedrock-runtime@3.1048.0':
|
||||
'@aws-sdk/client-bedrock-runtime@3.1127.0':
|
||||
dependencies:
|
||||
'@aws-crypto/sha256-browser': 5.2.0
|
||||
'@aws-crypto/sha256-js': 5.2.0
|
||||
'@aws-sdk/core': 3.977.9
|
||||
'@aws-sdk/credential-provider-node': 3.972.82
|
||||
'@aws-sdk/eventstream-handler-node': 3.972.34
|
||||
'@aws-sdk/middleware-eventstream': 3.972.29
|
||||
'@aws-sdk/middleware-websocket': 3.972.52
|
||||
'@aws-sdk/token-providers': 3.1048.0
|
||||
'@aws-sdk/token-providers': 3.1127.0
|
||||
'@aws-sdk/types': 3.974.5
|
||||
'@smithy/core': 3.33.3
|
||||
'@smithy/fetch-http-handler': 5.8.0
|
||||
@ -10417,7 +10216,7 @@ snapshots:
|
||||
'@smithy/types': 4.18.0
|
||||
tslib: 2.8.1
|
||||
|
||||
'@aws-sdk/token-providers@3.1048.0':
|
||||
'@aws-sdk/token-providers@3.1116.0':
|
||||
dependencies:
|
||||
'@aws-sdk/core': 3.977.9
|
||||
'@aws-sdk/nested-clients': 3.997.44
|
||||
@ -10426,7 +10225,7 @@ snapshots:
|
||||
'@smithy/types': 4.18.0
|
||||
tslib: 2.8.1
|
||||
|
||||
'@aws-sdk/token-providers@3.1116.0':
|
||||
'@aws-sdk/token-providers@3.1127.0':
|
||||
dependencies:
|
||||
'@aws-sdk/core': 3.977.9
|
||||
'@aws-sdk/nested-clients': 3.997.44
|
||||
@ -10440,10 +10239,6 @@ snapshots:
|
||||
'@smithy/types': 4.18.0
|
||||
tslib: 2.8.1
|
||||
|
||||
'@aws-sdk/util-locate-window@3.965.10':
|
||||
dependencies:
|
||||
tslib: 2.8.1
|
||||
|
||||
'@aws-sdk/xml-builder@3.972.40':
|
||||
dependencies:
|
||||
'@smithy/types': 4.18.0
|
||||
@ -11329,48 +11124,50 @@ snapshots:
|
||||
dependencies:
|
||||
e2b: 2.49.1
|
||||
|
||||
'@earendil-works/chord@0.85.1':
|
||||
'@earendil-works/chord@0.87.1':
|
||||
dependencies:
|
||||
esbuild: 0.28.1
|
||||
esbuild: 0.28.2
|
||||
|
||||
'@earendil-works/pi-agent-core@0.85.1(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(zod@4.6.2))(ws@8.21.3)(zod@4.6.2)':
|
||||
'@earendil-works/pi-agent-core@0.87.1(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(zod@4.6.2))(ws@8.21.3)(zod@4.6.2)':
|
||||
dependencies:
|
||||
'@earendil-works/chord': 0.85.1
|
||||
'@earendil-works/pi-ai': 0.85.1(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(zod@4.6.2))(ws@8.21.3)(zod@4.6.2)
|
||||
'@earendil-works/pi-telemetry': 0.85.1
|
||||
'@earendil-works/chord': 0.87.1
|
||||
'@earendil-works/pi-ai': 0.87.1(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(zod@4.6.2))(ws@8.21.3)(zod@4.6.2)
|
||||
'@earendil-works/pi-telemetry': 0.87.1
|
||||
diff: 8.0.4
|
||||
ignore: 7.0.5
|
||||
typebox: 1.3.7
|
||||
ignore: 7.0.8
|
||||
typebox: 1.3.27
|
||||
yaml: 2.9.0
|
||||
transitivePeerDependencies:
|
||||
- '@modelcontextprotocol/sdk'
|
||||
- bufferutil
|
||||
- kerberos
|
||||
- supports-color
|
||||
- utf-8-validate
|
||||
- ws
|
||||
- zod
|
||||
|
||||
'@earendil-works/pi-ai@0.85.1(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(zod@4.6.2))(ws@8.21.3)(zod@4.6.2)':
|
||||
'@earendil-works/pi-ai@0.87.1(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(zod@4.6.2))(ws@8.21.3)(zod@4.6.2)':
|
||||
dependencies:
|
||||
'@anthropic-ai/sdk': 0.123.0(zod@4.6.2)
|
||||
'@aws-sdk/client-bedrock-runtime': 3.1048.0
|
||||
'@earendil-works/pi-telemetry': 0.85.1
|
||||
'@google/genai': 1.52.0(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(zod@4.6.2))
|
||||
'@smithy/node-http-handler': 4.7.3
|
||||
http-proxy-agent: 7.0.2
|
||||
https-proxy-agent: 7.0.6
|
||||
'@anthropic-ai/sdk': 0.124.0(zod@4.6.2)
|
||||
'@aws-sdk/client-bedrock-runtime': 3.1127.0
|
||||
'@earendil-works/pi-telemetry': 0.87.1
|
||||
'@google/genai': 2.21.0(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(zod@4.6.2))
|
||||
'@smithy/node-http-handler': 4.12.1
|
||||
http-proxy-agent: 9.1.0
|
||||
https-proxy-agent: 9.1.0
|
||||
openai: 6.40.0(ws@8.21.3)(zod@4.6.2)
|
||||
partial-json: 0.1.7
|
||||
typebox: 1.3.7
|
||||
typebox: 1.3.27
|
||||
transitivePeerDependencies:
|
||||
- '@modelcontextprotocol/sdk'
|
||||
- bufferutil
|
||||
- kerberos
|
||||
- supports-color
|
||||
- utf-8-validate
|
||||
- ws
|
||||
- zod
|
||||
|
||||
'@earendil-works/pi-telemetry@0.85.1': {}
|
||||
'@earendil-works/pi-telemetry@0.87.1': {}
|
||||
|
||||
'@egjs/hammerjs@2.0.17':
|
||||
dependencies:
|
||||
@ -11526,159 +11323,81 @@ snapshots:
|
||||
|
||||
'@epic-web/invariant@1.0.0': {}
|
||||
|
||||
'@esbuild/aix-ppc64@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/aix-ppc64@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-arm64@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-arm64@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-arm@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-arm@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-x64@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-x64@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/darwin-arm64@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/darwin-arm64@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/darwin-x64@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/darwin-x64@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/freebsd-arm64@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/freebsd-arm64@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/freebsd-x64@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/freebsd-x64@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-arm64@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-arm64@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-arm@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-arm@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-ia32@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-ia32@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-loong64@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-loong64@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-mips64el@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-mips64el@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-ppc64@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-ppc64@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-riscv64@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-riscv64@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-s390x@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-s390x@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-x64@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-x64@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/netbsd-arm64@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/netbsd-arm64@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/netbsd-x64@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/netbsd-x64@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openbsd-arm64@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openbsd-arm64@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openbsd-x64@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openbsd-x64@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openharmony-arm64@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openharmony-arm64@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/sunos-x64@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/sunos-x64@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-arm64@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-arm64@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-ia32@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-ia32@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-x64@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-x64@0.28.2':
|
||||
optional: true
|
||||
|
||||
@ -12120,7 +11839,7 @@ snapshots:
|
||||
|
||||
'@fontsource-variable/inter@5.3.0': {}
|
||||
|
||||
'@google/genai@1.52.0(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(zod@4.6.2))':
|
||||
'@google/genai@2.21.0(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(zod@4.6.2))':
|
||||
dependencies:
|
||||
google-auth-library: 10.9.1
|
||||
p-retry: 4.6.2
|
||||
@ -13769,22 +13488,12 @@ snapshots:
|
||||
'@smithy/types': 4.18.0
|
||||
tslib: 2.8.1
|
||||
|
||||
'@smithy/is-array-buffer@2.2.0':
|
||||
dependencies:
|
||||
tslib: 2.8.1
|
||||
|
||||
'@smithy/node-http-handler@4.12.1':
|
||||
dependencies:
|
||||
'@smithy/core': 3.33.3
|
||||
'@smithy/types': 4.18.0
|
||||
tslib: 2.8.1
|
||||
|
||||
'@smithy/node-http-handler@4.7.3':
|
||||
dependencies:
|
||||
'@smithy/core': 3.33.3
|
||||
'@smithy/types': 4.18.0
|
||||
tslib: 2.8.1
|
||||
|
||||
'@smithy/signature-v4@5.7.3':
|
||||
dependencies:
|
||||
'@smithy/core': 3.33.3
|
||||
@ -13795,16 +13504,6 @@ snapshots:
|
||||
dependencies:
|
||||
tslib: 2.8.1
|
||||
|
||||
'@smithy/util-buffer-from@2.2.0':
|
||||
dependencies:
|
||||
'@smithy/is-array-buffer': 2.2.0
|
||||
tslib: 2.8.1
|
||||
|
||||
'@smithy/util-utf8@2.3.0':
|
||||
dependencies:
|
||||
'@smithy/util-buffer-from': 2.2.0
|
||||
tslib: 2.8.1
|
||||
|
||||
'@socket.io/component-emitter@3.1.2': {}
|
||||
|
||||
'@stablelib/base64@1.0.1': {}
|
||||
@ -14505,6 +14204,8 @@ snapshots:
|
||||
|
||||
agent-base@7.1.4: {}
|
||||
|
||||
agent-base@9.0.0: {}
|
||||
|
||||
agent-cli-detector@0.1.7: {}
|
||||
|
||||
ajv-draft-04@1.0.0(ajv@8.20.0):
|
||||
@ -16071,35 +15772,6 @@ snapshots:
|
||||
es6-error@4.1.1:
|
||||
optional: true
|
||||
|
||||
esbuild@0.28.1:
|
||||
optionalDependencies:
|
||||
'@esbuild/aix-ppc64': 0.28.1
|
||||
'@esbuild/android-arm': 0.28.1
|
||||
'@esbuild/android-arm64': 0.28.1
|
||||
'@esbuild/android-x64': 0.28.1
|
||||
'@esbuild/darwin-arm64': 0.28.1
|
||||
'@esbuild/darwin-x64': 0.28.1
|
||||
'@esbuild/freebsd-arm64': 0.28.1
|
||||
'@esbuild/freebsd-x64': 0.28.1
|
||||
'@esbuild/linux-arm': 0.28.1
|
||||
'@esbuild/linux-arm64': 0.28.1
|
||||
'@esbuild/linux-ia32': 0.28.1
|
||||
'@esbuild/linux-loong64': 0.28.1
|
||||
'@esbuild/linux-mips64el': 0.28.1
|
||||
'@esbuild/linux-ppc64': 0.28.1
|
||||
'@esbuild/linux-riscv64': 0.28.1
|
||||
'@esbuild/linux-s390x': 0.28.1
|
||||
'@esbuild/linux-x64': 0.28.1
|
||||
'@esbuild/netbsd-arm64': 0.28.1
|
||||
'@esbuild/netbsd-x64': 0.28.1
|
||||
'@esbuild/openbsd-arm64': 0.28.1
|
||||
'@esbuild/openbsd-x64': 0.28.1
|
||||
'@esbuild/openharmony-arm64': 0.28.1
|
||||
'@esbuild/sunos-x64': 0.28.1
|
||||
'@esbuild/win32-arm64': 0.28.1
|
||||
'@esbuild/win32-ia32': 0.28.1
|
||||
'@esbuild/win32-x64': 0.28.1
|
||||
|
||||
esbuild@0.28.2:
|
||||
optionalDependencies:
|
||||
'@esbuild/aix-ppc64': 0.28.2
|
||||
@ -17060,6 +16732,15 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
http-proxy-agent@9.1.0:
|
||||
dependencies:
|
||||
agent-base: 9.0.0
|
||||
debug: 4.4.3
|
||||
proxy-agent-negotiate: 1.1.0
|
||||
transitivePeerDependencies:
|
||||
- kerberos
|
||||
- supports-color
|
||||
|
||||
http2-wrapper@1.0.3:
|
||||
dependencies:
|
||||
quick-lru: 5.1.1
|
||||
@ -17081,6 +16762,15 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
https-proxy-agent@9.1.0:
|
||||
dependencies:
|
||||
agent-base: 9.0.0
|
||||
debug: 4.4.3
|
||||
proxy-agent-negotiate: 1.1.0
|
||||
transitivePeerDependencies:
|
||||
- kerberos
|
||||
- supports-color
|
||||
|
||||
human-signals@2.1.0: {}
|
||||
|
||||
hyphenate-style-name@1.1.0: {}
|
||||
@ -17097,7 +16787,7 @@ snapshots:
|
||||
|
||||
ignore@5.3.2: {}
|
||||
|
||||
ignore@7.0.5: {}
|
||||
ignore@7.0.8: {}
|
||||
|
||||
import-fresh@3.3.1:
|
||||
dependencies:
|
||||
@ -18800,6 +18490,8 @@ snapshots:
|
||||
forwarded: 0.2.0
|
||||
ipaddr.js: 1.9.1
|
||||
|
||||
proxy-agent-negotiate@1.1.0: {}
|
||||
|
||||
proxy-from-env@2.1.0: {}
|
||||
|
||||
pseudolocale@2.3.0:
|
||||
@ -20008,7 +19700,7 @@ snapshots:
|
||||
media-typer: 1.1.1
|
||||
mime-types: 3.0.2
|
||||
|
||||
typebox@1.3.7: {}
|
||||
typebox@1.3.27: {}
|
||||
|
||||
typesafe-path@0.2.2: {}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user