mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-25 20:05:46 -06:00
feat(onboarding): recommend plugins and skills from installed apps (#109668)
* feat(onboarding): recommend plugins and skills from installed apps Scan installed macOS apps during classic onboarding (TCC-free), gather candidates from official catalogs + ClawHub search, let the configured model pick genuine matches, and offer an opt-in multiselect install step. Adds a device.apps node-host command (default-off sharing, Android-parity envelope) so remote gateways can request a paired Mac's inventory, and a wizard.appRecommendations kill switch. Custom setup-inference completions no longer inherit the 32-token verification-probe output cap. * feat(onboarding): recommend apps in guided flow * fix(onboarding): harden app recommendations against ClawHub self-promotion Third-party ClawHub skills are never pre-selected regardless of model tier (publisher-controlled listing text reaches the matcher prompt and could promote itself); their labels now say they install third-party code. Installed-app scans follow symlinked .app bundles. Matcher output stays bounded by the resolved model's own maxTokens budget (documented invariant). * fix(onboarding): key official catalog candidates by resolved plugin id Real catalog entries are package manifests without a top-level id; keying the candidate map and channel/provider classification by entry.id collapsed the whole official catalog into one undefined-keyed entry, so no official plugin or channel was ever recommended. Regression test runs against the bundled catalogs. * fix(onboarding): satisfy lint, types, deadcode, and migration gates Split the guided-onboarding test into a self-contained custodian suite to stay under max-lines. Narrow app-recommendation exports (drop dead node-payload normalizer, unexport internal types/helpers, route candidate tests through the public API), replace map-spread with a helper, unexport device.apps result types, add installedAppsSharing to node-host migration expectations, cast the wizard multiselect mock, and regenerate the docs map. * test(onboarding): register new live test in the shard classifier
This commit is contained in:
committed by
GitHub
parent
8020dd3e08
commit
da69daeb72
@@ -6,6 +6,7 @@ import type { SkillBinTrustEntry } from "../infra/exec-approvals.js";
|
||||
import { resolveExecutableFromPathEnv } from "../infra/executable-path.js";
|
||||
import {
|
||||
NODE_AGENT_CLI_CLAUDE_RUN_COMMAND,
|
||||
NODE_DEVICE_APPS_COMMAND,
|
||||
NODE_DUPLEX_INVOKE_IDLE_TIMEOUT_MS,
|
||||
NODE_EXEC_APPROVALS_COMMANDS,
|
||||
NODE_FS_LIST_DIR_COMMAND,
|
||||
@@ -232,6 +233,8 @@ export async function prepareNodeHostRuntime(params?: {
|
||||
enableAgentRuns?: boolean;
|
||||
/** Embedded workers may still host long-lived plugin commands over the app-owned socket. */
|
||||
enableDuplexPluginCommands?: boolean;
|
||||
installedAppsSharingEnabled?: boolean;
|
||||
platform?: NodeJS.Platform;
|
||||
}): Promise<PreparedNodeHostRuntime> {
|
||||
void ensureTerminalUploadCleanup();
|
||||
const config = params?.config ?? getRuntimeConfig();
|
||||
@@ -241,6 +244,9 @@ export async function prepareNodeHostRuntime(params?: {
|
||||
env.PATH = pathEnv;
|
||||
const duplexEnabled =
|
||||
params?.enableAgentRuns === true || params?.enableDuplexPluginCommands === true;
|
||||
const platform = params?.platform ?? process.platform;
|
||||
const installedAppsSharingEnabled =
|
||||
platform === "darwin" && params?.installedAppsSharingEnabled === true;
|
||||
const availabilityContext = { config, env };
|
||||
const resolvePluginNodeHost = () =>
|
||||
listRegisteredNodeHostCapsAndCommands(availabilityContext, {
|
||||
@@ -255,7 +261,14 @@ export async function prepareNodeHostRuntime(params?: {
|
||||
: null;
|
||||
const skills = config.nodeHost?.skills?.enabled === false ? null : scanNodeHostedSkills();
|
||||
const buildManifest = (pluginManifest: typeof pluginNodeHost): NodeHostManifest => ({
|
||||
caps: [...new Set(["system", "mcp", ...pluginManifest.caps])].toSorted(),
|
||||
caps: [
|
||||
...new Set([
|
||||
"system",
|
||||
"mcp",
|
||||
...(installedAppsSharingEnabled ? ["device"] : []),
|
||||
...pluginManifest.caps,
|
||||
]),
|
||||
].toSorted(),
|
||||
commands: [
|
||||
...new Set([
|
||||
...NODE_SYSTEM_RUN_COMMANDS,
|
||||
@@ -263,6 +276,7 @@ export async function prepareNodeHostRuntime(params?: {
|
||||
NODE_FS_LIST_DIR_COMMAND,
|
||||
NODE_TERMINAL_UPLOAD_COMMAND,
|
||||
NODE_MCP_TOOLS_CALL_COMMAND,
|
||||
...(installedAppsSharingEnabled ? [NODE_DEVICE_APPS_COMMAND] : []),
|
||||
...(claudePath ? [NODE_AGENT_CLI_CLAUDE_RUN_COMMAND] : []),
|
||||
...pluginManifest.commands,
|
||||
]),
|
||||
@@ -384,6 +398,8 @@ export async function prepareNodeHostRuntime(params?: {
|
||||
...(claudePath ? { claudePath } : {}),
|
||||
...(controller ? { signal: controller.signal } : {}),
|
||||
...(pluginCommandIo ? { pluginCommandIo } : {}),
|
||||
installedAppsSharingEnabled,
|
||||
installedAppsPlatform: platform,
|
||||
pluginCommandContext,
|
||||
});
|
||||
} finally {
|
||||
|
||||
Reference in New Issue
Block a user