mirror of
https://github.com/getpaseo/paseo.git
synced 2026-11-04 23:44:41 +00:00
feat(plugins): unify lifecycle hooks and await worktree initialization (#8081)
* refactor(plugins): make lifecycle hook timing explicit Use one registration method and subject.operation.step names so plugin authors can read whether an operation waits. Preserve old registrations through a single SDK adapter and keep timing and payloads unchanged. * fix(plugins): align hook notes and example fixtures with release contracts Keep the changelog inside its versioned beta entry for app parsing. Run current plugin examples against the checkout version so their declared requirements remain valid. * docs(plugins): align translated hook dependency guidance * fix(plugins): align hook exports and release documentation * feat(plugins): use lifecycle positions and await worktree initialization * test(plugins): cover first-agent worktree initialization * test(plugins): verify rollback against workspace catalog entries
This commit is contained in:
@@ -1,15 +1,15 @@
|
||||
# Agent configuration
|
||||
|
||||
Sets saved Codex options through `server.before("agent.create", ...)`:
|
||||
Sets saved Codex options through `server.addHook("agent.create.before", async ...)`:
|
||||
|
||||
- Sets `config.providerOptions.sandbox_mode` to `workspace-write`.
|
||||
- Sets `config.providerOptions.approval_policy` to `on-request`.
|
||||
- Preserves other configuration and provider options.
|
||||
|
||||
Adds the `company` MCP server to Codex launches through
|
||||
`server.before("agent.session_open", ...)`. The server is never saved in the agent's configuration;
|
||||
`server.addHook("agent.open.before", async ...)`. The server is never saved in the agent's configuration;
|
||||
existing saved MCP servers are preserved. Existing agents receive the server through the
|
||||
[session reopen behavior](../../public-docs/plugins/reference.md#attach-tools-to-agents).
|
||||
[session reopen behavior](../../public-docs/plugins/hooks.md#attach-tools-to-agents).
|
||||
|
||||
Replace `https://tools.example.com/mcp` in `index.server.ts` with your MCP server URL before using
|
||||
this example. A `company` name collision with a saved server or another
|
||||
@@ -26,7 +26,7 @@ entries added by this plugin's earlier callbacks. The create callback receives c
|
||||
earlier plugins have transformed it; its explicit Codex options replace the named fields in the
|
||||
saved configuration of new agents and remain after this plugin is disabled.
|
||||
|
||||
See [Inject MCP servers](../../public-docs/plugins/reference.md#inject-mcp-servers) for choosing
|
||||
See [Inject MCP servers](../../public-docs/plugins/hooks.md#inject-mcp-servers) for choosing
|
||||
between saved configuration and plugin-owned servers. [Lifecycle actions](../lifecycle-actions)
|
||||
demonstrates provider switching and environment injection. Its provider-switch callback clears
|
||||
provider options when changing Codex to Claude, so use these examples separately when trying the
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { PluginServerContext } from "@getpaseo/plugin/server";
|
||||
|
||||
export default function contribute(server: PluginServerContext) {
|
||||
server.before("agent.create", ({ request }) => {
|
||||
server.addHook("agent.create.before", async ({ request }) => {
|
||||
if (request.config.provider !== "codex") {
|
||||
return request;
|
||||
}
|
||||
@@ -19,7 +19,7 @@ export default function contribute(server: PluginServerContext) {
|
||||
};
|
||||
});
|
||||
|
||||
server.before("agent.session_open", ({ request }) => {
|
||||
server.addHook("agent.open.before", async ({ request }) => {
|
||||
if (request.provider !== "codex") {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"id": "agent-configuration",
|
||||
"requirements": {
|
||||
"paseo": ">=0.13.2"
|
||||
"paseo": ">=0.14.0-beta.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,5 +29,5 @@ From the repository root, `npm run typecheck` includes this example. Outside thi
|
||||
use `paseo plugin init` to create the package and TypeScript setup, then copy `index.server.ts`
|
||||
and the manifest into that project.
|
||||
|
||||
See [Attach tools to agents](../../public-docs/plugins/reference.md#attach-tools-to-agents)
|
||||
See [Attach tools to agents](../../public-docs/plugins/hooks.md#attach-tools-to-agents)
|
||||
for targeting, execution, provider gates, collisions, and plugin reload behavior.
|
||||
|
||||
@@ -18,7 +18,7 @@ const appendWorkspaceNote = defineAgentTool({
|
||||
});
|
||||
|
||||
export default function contribute(server: PluginServerContext) {
|
||||
server.before("agent.session_open", ({ request }) => {
|
||||
server.addHook("agent.open.before", async ({ request }) => {
|
||||
if (request.labels["notes/enabled"] !== "true") return;
|
||||
return { ...request, tools: [...request.tools, appendWorkspaceNote] };
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"id": "agent-tools",
|
||||
"requirements": { "paseo": ">=0.13.2" }
|
||||
"requirements": { "paseo": ">=0.14.0-beta.1" }
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { PluginServerContext } from "@getpaseo/plugin/server";
|
||||
import { latestOutputText, shellCommand } from "./server/inspect";
|
||||
|
||||
export default function contribute(server: PluginServerContext) {
|
||||
server.before("workspace.create", ({ request }) => {
|
||||
server.addHook("workspace.create.before", async ({ request }) => {
|
||||
if (request.title === "Isolated lifecycle example" && request.source.kind === "directory") {
|
||||
return {
|
||||
...request,
|
||||
@@ -17,7 +17,7 @@ export default function contribute(server: PluginServerContext) {
|
||||
return request;
|
||||
});
|
||||
|
||||
server.on("agent.turn_ended", async (event, context) => {
|
||||
server.addHook("agent.turn.after", async (event, context) => {
|
||||
if (event.outcome.kind === "canceled") {
|
||||
return;
|
||||
}
|
||||
@@ -30,7 +30,7 @@ export default function contribute(server: PluginServerContext) {
|
||||
}
|
||||
});
|
||||
|
||||
server.on("agent.permission_requested", async (event, context) => {
|
||||
server.addHook("agent.permission.before", async (event, context) => {
|
||||
const command = shellCommand(event.request);
|
||||
if (command === null) {
|
||||
return;
|
||||
@@ -56,7 +56,7 @@ export default function contribute(server: PluginServerContext) {
|
||||
}
|
||||
});
|
||||
|
||||
server.before("agent.create", ({ request }) => {
|
||||
server.addHook("agent.create.before", async ({ request }) => {
|
||||
return {
|
||||
...request,
|
||||
env: {
|
||||
@@ -66,7 +66,7 @@ export default function contribute(server: PluginServerContext) {
|
||||
};
|
||||
});
|
||||
|
||||
server.before("agent.create", ({ request }) => {
|
||||
server.addHook("agent.create.before", async ({ request }) => {
|
||||
if (request.config.provider === "codex") {
|
||||
return {
|
||||
...request,
|
||||
@@ -82,7 +82,7 @@ export default function contribute(server: PluginServerContext) {
|
||||
return request;
|
||||
});
|
||||
|
||||
server.before("agent.session_open", ({ request }) => {
|
||||
server.addHook("agent.open.before", async ({ request }) => {
|
||||
return {
|
||||
...request,
|
||||
env: {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"id": "lifecycle-actions",
|
||||
"requirements": {
|
||||
"paseo": ">=0.8.0"
|
||||
"paseo": ">=0.14.0-beta.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,55 +2,59 @@ import type { PluginServerContext } from "@getpaseo/plugin/server";
|
||||
import { logHook } from "./server/log";
|
||||
|
||||
export default function contribute(server: PluginServerContext) {
|
||||
server.before("workspace.create", ({ request }) => {
|
||||
logHook("before workspace.create", { request });
|
||||
server.addHook("workspace.create.before", async ({ request }) => {
|
||||
logHook("workspace.create.before", { request });
|
||||
return request;
|
||||
});
|
||||
|
||||
server.on("workspace.created", (event) => {
|
||||
logHook("workspace.created", event);
|
||||
server.addHook("workspace.create.after", async (event) => {
|
||||
logHook("workspace.create.after", event);
|
||||
});
|
||||
|
||||
server.on("workspace.archived", (event) => {
|
||||
logHook("workspace.archived", event);
|
||||
server.addHook("workspace.archive.after", async (event) => {
|
||||
logHook("workspace.archive.after", event);
|
||||
});
|
||||
|
||||
server.before("agent.create", ({ request }) => {
|
||||
logHook("before agent.create", { request });
|
||||
server.addHook("worktree.create.after", async (event) => {
|
||||
logHook("worktree.create.after", event);
|
||||
});
|
||||
|
||||
server.addHook("agent.create.before", async ({ request }) => {
|
||||
logHook("agent.create.before", { request });
|
||||
return request;
|
||||
});
|
||||
|
||||
server.before("agent.session_open", ({ request }) => {
|
||||
logHook("before agent.session_open", { request });
|
||||
server.addHook("agent.open.before", async ({ request }) => {
|
||||
logHook("agent.open.before", { request });
|
||||
return request;
|
||||
});
|
||||
|
||||
server.on("agent.created", (event) => {
|
||||
logHook("agent.created", event);
|
||||
server.addHook("agent.create.after", async (event) => {
|
||||
logHook("agent.create.after", event);
|
||||
});
|
||||
|
||||
server.on("agent.closed", (event) => {
|
||||
logHook("agent.closed", event);
|
||||
server.addHook("agent.close.after", async (event) => {
|
||||
logHook("agent.close.after", event);
|
||||
});
|
||||
|
||||
server.on("agent.turn_started", (event) => {
|
||||
logHook("agent.turn_started", event);
|
||||
server.addHook("agent.turn.before", async (event) => {
|
||||
logHook("agent.turn.before", event);
|
||||
});
|
||||
|
||||
server.on("agent.turn_ended", (event) => {
|
||||
logHook("agent.turn_ended", event);
|
||||
server.addHook("agent.turn.after", async (event) => {
|
||||
logHook("agent.turn.after", event);
|
||||
});
|
||||
|
||||
server.on("agent.permission_requested", (event) => {
|
||||
logHook("agent.permission_requested", event);
|
||||
server.addHook("agent.permission.before", async (event) => {
|
||||
logHook("agent.permission.before", event);
|
||||
});
|
||||
|
||||
server.on("agent.permission_resolved", (event) => {
|
||||
logHook("agent.permission_resolved", event);
|
||||
server.addHook("agent.permission.after", async (event) => {
|
||||
logHook("agent.permission.after", event);
|
||||
});
|
||||
|
||||
server.on("agent.archived", (event) => {
|
||||
logHook("agent.archived", event);
|
||||
server.addHook("agent.archive.after", async (event) => {
|
||||
logHook("agent.archive.after", event);
|
||||
});
|
||||
|
||||
return () => {};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"id": "lifecycle-logger",
|
||||
"requirements": {
|
||||
"paseo": ">=0.8.0"
|
||||
"paseo": ">=0.14.0-beta.1"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user