mirror of
https://github.com/Tencent/BrowserSkill.git
synced 2026-09-10 13:01:23 +08:00
feat(packages): add dsh-plugin-browserskill — DeepSeek Harness tools for bsk
Add a new monorepo package that registers BrowserSkill (bsk) browser automation as model-visible tools in DeepSeek Harness (dsh): - 11 tools mapping to bsk CLI --json commands: session start/stop/list, navigate, snapshot, observe, click, fill, press, screenshot, emulate - multi-session support: optional session arg with a current-session pointer, session id echoed in every result, configurable concurrency cap (default 5), and dispose-time cleanup of plugin-started sessions - cancellation: exec.signal aborts kill the underlying bsk child process - terminal-style UI cards (command line as the call card, output as the result card); screenshots inline the PNG through the host attachment store when the model route accepts image input, else return the path - config: bskPath / defaultTimeoutMs / maxSessions via Schemastery schema - install guidance when the bsk binary is missing; bsk JSON error envelopes (code/message/hint) surfaced to the model - unit tests mock the bsk runner (no real browser required); the root lint script now also runs the package's typecheck + tests so the existing CI frontend job covers the new package (a dedicated CI job diff is provided in the PR; the pushing token lacks workflow scope)
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* dsh-plugin-browserskill — a DeepSeek Harness bundle that registers
|
||||
* BrowserSkill (`bsk`) browser automation as model-visible tools.
|
||||
*
|
||||
* Each tool spawns `bsk <cmd> --json`, parses the structured output, and
|
||||
* returns a canonical JSON value. The plugin tracks the sessions it starts so
|
||||
* one agent conversation can drive several browsers at once; unloading the
|
||||
* plugin stops every tracked session and kills any in-flight bsk children.
|
||||
*
|
||||
* @module dsh-plugin-browserskill
|
||||
*/
|
||||
|
||||
import type { Context } from "@deepseek-ai/cordis";
|
||||
import Schema from "@deepseek-ai/schemastery";
|
||||
import { createBskRunner } from "./runner";
|
||||
import { SessionRegistry } from "./sessions";
|
||||
import { type PluginConfig, registerTools } from "./tools";
|
||||
|
||||
export const name = "dsh-plugin-browserskill";
|
||||
export const inject = ["tools"];
|
||||
|
||||
/** Runtime configuration schema (validated and defaulted by Cordis). */
|
||||
export const Config = Schema.object({
|
||||
bskPath: Schema.string()
|
||||
.default("bsk")
|
||||
.description("Path to the bsk CLI binary (defaults to resolving `bsk` from PATH)."),
|
||||
defaultTimeoutMs: Schema.number()
|
||||
.default(120_000)
|
||||
.description("Default per-command timeout in milliseconds."),
|
||||
maxSessions: Schema.number()
|
||||
.default(5)
|
||||
.description("Maximum number of concurrent browser sessions started through this plugin."),
|
||||
});
|
||||
|
||||
export type Config = PluginConfig;
|
||||
|
||||
export function apply(ctx: Context, config: Partial<PluginConfig> = {}): void {
|
||||
const resolved: PluginConfig = {
|
||||
bskPath: config.bskPath ?? "bsk",
|
||||
defaultTimeoutMs: config.defaultTimeoutMs ?? 120_000,
|
||||
maxSessions: config.maxSessions ?? 5,
|
||||
};
|
||||
const runner = createBskRunner(resolved.bskPath);
|
||||
const registry = new SessionRegistry(resolved.maxSessions);
|
||||
|
||||
registerTools({ ctx, runner, registry, config: resolved });
|
||||
|
||||
// Non-blocking install probe: warn early when bsk is missing instead of
|
||||
// failing the first tool call with a bare spawn error.
|
||||
runner.run(["status"], { timeoutMs: 10_000 }).then(
|
||||
() => {},
|
||||
(error: unknown) => {
|
||||
const detail = error instanceof Error ? error.message : String(error);
|
||||
console.warn(
|
||||
`[${name}] bsk probe failed (${detail}); browser tools will report install guidance until the bsk CLI is available`,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
// Unload cleanup: kill in-flight children, then stop every session this
|
||||
// plugin started (best effort; sessions started outside the plugin are
|
||||
// left running).
|
||||
ctx.effect(() => {
|
||||
return () => {
|
||||
runner.killAll();
|
||||
const stops = registry
|
||||
.list()
|
||||
.map((session) =>
|
||||
runner.run(["session", "stop", session.sessionId], { timeoutMs: 15_000 }).catch(() => {}),
|
||||
);
|
||||
return Promise.all(stops).then(() => {});
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export type { BskRunner, BskRunResult, SpawnImpl } from "./runner";
|
||||
export { BskError, createBskRunner } from "./runner";
|
||||
export { SessionRegistry } from "./sessions";
|
||||
export type { PluginConfig, ToolDeps } from "./tools";
|
||||
export { registerTools } from "./tools";
|
||||
Reference in New Issue
Block a user