mirror of
https://github.com/Tencent/BrowserSkill.git
synced 2026-09-10 13:01:23 +08:00
feat(dsh-plugin-browserskill): publish the BSK skill through ctx.skills
The plugin exposed only tools; the BrowserSkill agent skill never reached the harness's <available_skills> catalog. Register it as an embedded runtime skill (progressive disclosure: catalog entry resident, body on skill-tool invocation) via the official ctx.skills seam — silent no-op when the composition lacks it. Content is build-time assembled so there is one source of truth: skill/prelude.md (committed, dsh-specific: tool<->CLI map, owned-session semantics, plugin-only overrides) + the canonical repo-root skill/SKILL.md verbatim (the same file crates/bsk-cli/build.rs mirrors; frontmatter stripped, name/description supplied by the registration). Generated into src/skill-content.generated.ts (gitignored) — registration and every pre-step snapshot are pure in-memory reads: no disk, no process, no daemon. Scripts: build:skill chained into build/test/typecheck (same pattern as build:css); biome excludes the generated artifacts. Tests: +3 (catalog content, in-memory weight, silent degradation). 116/116 green.
This commit is contained in:
@@ -17,6 +17,7 @@ import { registerObservationRoutes } from "./observation-http";
|
||||
import { KeyedExecutor } from "./queue";
|
||||
import { type BskRunner, createBskRunner } from "./runner";
|
||||
import { SessionRegistry } from "./sessions";
|
||||
import { registerBskSkill } from "./skill";
|
||||
import { type PluginConfig, registerTools } from "./tools";
|
||||
|
||||
export const name = "dsh-plugin-browserskill";
|
||||
@@ -80,6 +81,10 @@ export function apply(
|
||||
});
|
||||
|
||||
registerTools({ ctx, runner, registry, config: resolved, observation, queue });
|
||||
// Progressive disclosure of the BSK agent skill (catalog entry resident,
|
||||
// body on demand) through the official skill seam; silent no-op when the
|
||||
// composition lacks it.
|
||||
const unregisterSkill = registerBskSkill(ctx);
|
||||
// Route registration rides ctx.inject: the webServer service may be provided
|
||||
// AFTER this plugin loads, and in headless compositions it never appears (the
|
||||
// callback simply never runs, leaving the rest of the plugin unaffected).
|
||||
@@ -110,6 +115,7 @@ export function apply(
|
||||
// are swallowed so one stale handle cannot abort the rest.
|
||||
ctx.effect(() => {
|
||||
return () => {
|
||||
unregisterSkill();
|
||||
removeRoutes();
|
||||
observation.dispose();
|
||||
runner.killAll();
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Progressive disclosure of the BrowserSkill agent skill through the harness's
|
||||
* official skill seam (`ctx.skills`). The catalog entry (name + description)
|
||||
* is resident; the body is loaded only when the model invokes the `skill`
|
||||
* tool. The markdown is build-time assembled into a static module (dsh
|
||||
* prelude + the canonical CLI skill body verbatim), so registration and every
|
||||
* pre-step catalog snapshot are pure in-memory reads — no disk, no process,
|
||||
* no daemon.
|
||||
*/
|
||||
|
||||
import type { Context } from "@deepseek-ai/cordis";
|
||||
import {
|
||||
BSK_SKILL_DESCRIPTION,
|
||||
BSK_SKILL_MARKDOWN,
|
||||
BSK_SKILL_NAME,
|
||||
} from "./skill-content.generated";
|
||||
|
||||
/** Structural view of the skill registry seam (absent in bare compositions). */
|
||||
interface SkillsLike {
|
||||
register(skill: {
|
||||
name: string;
|
||||
description: string;
|
||||
content: string;
|
||||
source?: string;
|
||||
}): () => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish the BSK skill as an embedded runtime skill. Returns the unregistration
|
||||
* disposer. A composition without the `skills` service (or with dsh-tool-skill
|
||||
* retired) leaves the rest of the plugin unaffected — the no-op is silent.
|
||||
*/
|
||||
export function registerBskSkill(ctx: Context): () => void {
|
||||
const skills = ctx.get("skills") as SkillsLike | undefined | null;
|
||||
if (skills == null || typeof skills.register !== "function") {
|
||||
return () => {};
|
||||
}
|
||||
return skills.register({
|
||||
name: BSK_SKILL_NAME,
|
||||
description: BSK_SKILL_DESCRIPTION,
|
||||
content: BSK_SKILL_MARKDOWN,
|
||||
// Prompt-visible origin bucket: packaged with a plugin, not user/project files.
|
||||
source: "bundled",
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user