fix(wizard): prepare default Local Agent and refine Runner setup

This commit is contained in:
RockChinQ
2026-09-18 19:27:56 +08:00
parent bece2aa554
commit da4b0d6ca2
18 changed files with 1424 additions and 359 deletions
@@ -8,6 +8,7 @@ import {
type PluginV4,
type RunnerUsage,
} from '@/app/infra/entities/plugin';
import type { AsyncTask } from '@/app/infra/entities/api';
import type { I18nObject } from '@/app/infra/entities/common';
export const RUNNER_COMPONENT_FILTER = 'Runner';
@@ -54,6 +55,7 @@ export interface PendingRunnerInstall {
interface InstallRunnerOptions {
scope: string;
onTaskCreated?: (taskId: number) => void;
onProgress?: (task: AsyncTask) => void;
}
function wait(ms: number) {
@@ -250,7 +252,7 @@ export async function installMarketplaceRunner(
};
writePendingRunnerInstall(pending);
options.onTaskCreated?.(taskId);
return finishRunnerInstall(pending);
return finishRunnerInstall(pending, options.onProgress);
}
function extractPluginLabel(plugin: PluginV4) {
@@ -267,6 +269,7 @@ function extractPluginLabel(plugin: PluginV4) {
async function finishRunnerInstall(
pending: PendingRunnerInstall,
onProgress?: (task: AsyncTask) => void,
): Promise<InstalledRunner> {
// A refreshed page receives a fresh observation window. The backend task is
// authoritative; `startedAt` is display metadata, not a reason to abandon a
@@ -275,6 +278,7 @@ async function finishRunnerInstall(
let installCompleted = false;
while (true) {
const task = await httpClient.getAsyncTask(pending.taskId);
onProgress?.(task);
if (task.runtime.done) {
if (task.runtime.exception) {
clearPendingRunnerInstall(pending.scope, pending.taskId);
@@ -323,8 +327,9 @@ async function finishRunnerInstall(
export async function resumePendingRunnerInstall(
scope: string,
onProgress?: (task: AsyncTask) => void,
): Promise<InstalledRunner | null> {
const pending = readPendingRunnerInstall(scope);
if (!pending) return null;
return finishRunnerInstall(pending);
return finishRunnerInstall(pending, onProgress);
}
@@ -185,7 +185,9 @@ function isPluginInstallTask(name: string): boolean {
/**
* Convert a backend AsyncTask to our PluginInstallTask.
*/
function asyncTaskToPluginInstallTask(task: AsyncTask): PluginInstallTask {
export function asyncTaskToPluginInstallTask(
task: AsyncTask,
): PluginInstallTask {
const source = extractSourceFromName(task.name);
const md = (task.task_context?.metadata ?? {}) as Record<string, unknown>;
const action = task.task_context?.current_action || '';
File diff suppressed because it is too large Load Diff
+16 -10
View File
@@ -105,13 +105,16 @@ export function isRequiredRunnerConfigComplete(
});
}
export const LOCAL_AGENT_RUNNER_ID = 'plugin:langbot-team/LocalAgent/default';
export function configureLocalAgentPrimaryModel(
config: Record<string, unknown>,
modelUuid: string,
): Record<string, unknown> {
const aiConfig = (config.ai ?? {}) as Record<string, unknown>;
const runnerConfig = (aiConfig.runner ?? {}) as Record<string, unknown>;
const localAgentConfig = (aiConfig['local-agent'] ?? {}) as Record<
const configs = (aiConfig.runner_config ?? {}) as Record<string, unknown>;
const localAgentConfig = (configs[LOCAL_AGENT_RUNNER_ID] ?? {}) as Record<
string,
unknown
>;
@@ -121,15 +124,18 @@ export function configureLocalAgentPrimaryModel(
...config,
ai: {
...aiConfig,
runner: { ...runnerConfig, runner: 'local-agent' },
'local-agent': {
...localAgentConfig,
model: {
...modelConfig,
primary: modelUuid,
fallbacks: Array.isArray(modelConfig.fallbacks)
? modelConfig.fallbacks
: [],
runner: { ...runnerConfig, id: LOCAL_AGENT_RUNNER_ID },
runner_config: {
...configs,
[LOCAL_AGENT_RUNNER_ID]: {
...localAgentConfig,
model: {
...modelConfig,
primary: modelUuid,
fallbacks: Array.isArray(modelConfig.fallbacks)
? modelConfig.fallbacks
: [],
},
},
},
},