mirror of
https://github.com/Tencent/BrowserSkill.git
synced 2026-09-10 13:01:23 +08:00
fix(dsh-plugin): stabilize skill loading and browser sessions
Register bundled browser instructions at agent scope, prioritize foreground commands over thumbnail capture, and unify cancellation and session cleanup.
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
*/
|
||||
|
||||
import type { Context } from "@deepseek-ai/cordis";
|
||||
import type { Agent } from "@deepseek-ai/dsh-agent";
|
||||
import {
|
||||
BSK_SKILL_DESCRIPTION,
|
||||
BSK_SKILL_MARKDOWN,
|
||||
@@ -25,6 +26,11 @@ interface SkillsLike {
|
||||
}): () => void;
|
||||
}
|
||||
|
||||
/** Structural view of the live-agent registry (absent in bare compositions). */
|
||||
interface AgentsLike {
|
||||
list(): Agent[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish the browser skill as an embedded runtime skill. Returns the unregistration
|
||||
* disposer. A composition without the `skills` service (or with dsh-tool-skill
|
||||
@@ -43,3 +49,54 @@ export function registerBskSkill(ctx: Context): () => void {
|
||||
source: "bundled",
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Install the DSH-specific browser skill into every exact agent scope.
|
||||
*
|
||||
* DSH merges skill layers nearest-first (`agent -> preset -> global`). A legacy
|
||||
* CLI skill installed at `~/.agents/skills/browser-skill` is discovered by the
|
||||
* preset filesystem provider and therefore shadows a plugin-level registration.
|
||||
* Registering the embedded skill through `agent.ctx` makes the DSH protocol
|
||||
* contract authoritative for that agent without touching the shared CLI skill.
|
||||
*
|
||||
* New agents are handled at `agent/session-start`, the first supported startup
|
||||
* injection point and still before the first prompt assembly. Existing agents
|
||||
* are registered immediately so plugin reloads take effect without recreating
|
||||
* the conversation. Returns a disposer for all plugin-owned registrations.
|
||||
*/
|
||||
export function armAgentScopedBskSkill(ctx: Context): () => void {
|
||||
const registrations = new Map<Agent, () => void>();
|
||||
let active = true;
|
||||
|
||||
const registerForAgent = (agent: Agent): void => {
|
||||
if (!active || registrations.has(agent)) return;
|
||||
registrations.set(agent, registerBskSkill(agent.ctx));
|
||||
};
|
||||
|
||||
let stopSessionStart = () => {};
|
||||
let stopDisposed = () => {};
|
||||
if (typeof ctx.on === "function") {
|
||||
stopSessionStart = ctx.on("agent/session-start", ({ agent }) => {
|
||||
registerForAgent(agent);
|
||||
});
|
||||
stopDisposed = ctx.on("agent/disposed", ({ agent }) => {
|
||||
// Agent-scoped effects have already unwound at this lifecycle edge. Drop
|
||||
// the retained disposer without invoking it against a disposed context.
|
||||
registrations.delete(agent);
|
||||
});
|
||||
}
|
||||
|
||||
const agents = ctx.get("agents") as AgentsLike | undefined | null;
|
||||
if (agents != null && typeof agents.list === "function") {
|
||||
for (const agent of agents.list()) registerForAgent(agent);
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (!active) return;
|
||||
active = false;
|
||||
stopDisposed();
|
||||
stopSessionStart();
|
||||
for (const unregister of [...registrations.values()].reverse()) unregister();
|
||||
registrations.clear();
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user