|
Download docs/user/develop/framework/index.md from SaylorTwift/deepseek-harness: direct link, hf CLI and curl.
- Browser
- Download file 3.84 kB
-
https://huggingface.co/SaylorTwift/deepseek-harness/resolve/main/docs/user/develop/framework/index.md
- Command line
-
hf download hf://SaylorTwift/deepseek-harness/docs/user/develop/framework/index.md
-
curl -L -o index.md https://huggingface.co/SaylorTwift/deepseek-harness/resolve/main/docs/user/develop/framework/index.md
3.84 kB
| # Plugins and lifecycle | |
| English | [δΈζ](index.zh.md) | |
| This page describes the Cordis plugin model and lifecycle state machine. | |
| ## Fiber state machine | |
| Every loaded plugin owns a **Fiber** scope with the following states: | |
| ``` | |
| PENDING β LOADING β ACTIVE | |
| β FAILED | |
| ACTIVE β UNLOADING β DISPOSED | |
| ``` | |
| | State | Meaning | | |
| |------|------| | |
| | PENDING | Declared, but required dependencies are not ready | | |
| | LOADING | Dependencies are ready and `apply` is running | | |
| | ACTIVE | The plugin is running | | |
| | FAILED | `apply` threw an error | | |
| | UNLOADING | The plugin is unloading and disposing resources | | |
| | DISPOSED | The plugin is fully unloaded | | |
| ## Dependency-driven loading | |
| A plugin with `inject` waits for every required service before loading: | |
| ```ts ignore-check | |
| export const inject = ['tools', 'llm'] | |
| export function apply(ctx: Context) { | |
| // ctx.tools and ctx.llm are ready here. | |
| } | |
| ``` | |
| If a required service disappears, for example during provider replacement, the plugin unloads automatically (ACTIVE β DISPOSED) and loads again when the service returns. | |
| ## Automatic cleanup | |
| Every registration made through `ctx` is undone when the plugin unloads: | |
| ```ts ignore-check | |
| export function apply(ctx: Context) { | |
| // Event listener: removed automatically on unload. | |
| ctx.on('some-event', handler) | |
| // Custom resource: the returned disposer runs on unload. | |
| ctx.effect(() => { | |
| const connection = createConnection() | |
| return () => connection.close() | |
| }) | |
| } | |
| ``` | |
| The framework tracks and disposes all of these operations: | |
| - `ctx.on(event, handler)` β event listener | |
| - `ctx.tools.register(tool)` β tool registration | |
| - `ctx.llm.registerAdapter(names, adapter)` β LLM adapter registration | |
| - `ctx.effect(() => cleanup)` β custom resource | |
| During unload, disposer invocation starts in reverse registration order, but multiple async disposers run concurrently and have no serial completion guarantee. Put order-dependent cleanup in one disposer returned from a single `ctx.effect()` and await its steps serially there. | |
| ## Nested contexts | |
| `ctx.plugin()` creates a child Fiber that inherits the parent context but has an independent lifecycle: | |
| ```ts ignore-check | |
| export function apply(ctx: Context) { | |
| // Register a child plugin. | |
| ctx.plugin(childPlugin) | |
| // The child has its own Fiber and unloads with its parent. | |
| } | |
| ``` | |
| ## Dispose semantics | |
| To stop a plugin instance early: | |
| ```ts | |
| import type { Context } from '@deepseek-ai/cordis' | |
| declare const ctx: Context | |
| declare function myPlugin(ctx: Context): void | |
| const fiber = ctx.plugin(myPlugin) | |
| // Dispose it manually later. | |
| await fiber.dispose() | |
| ``` | |
| `dispose` guarantees: | |
| 1. All registrations owned by the plugin are removed. | |
| 2. Child plugins are recursively unloaded. | |
| 3. The returned promise resolves after all asynchronous cleanup finishes. | |
| ## Hot replacement (HMR) | |
| With `@deepseek-ai/cordis-plugin-hmr` loaded from `cordis.yml`, editing a plugin source file triggers: | |
| 1. Unload the old plugin and clean up its registrations. | |
| 2. Load the new code. | |
| 3. Run the new `apply`. | |
| Because plugin registrations clean themselves up, hot replacement does not retain registrations from the old instance. | |
| ## Example lifecycle | |
| ```ts ignore-check | |
| export function apply(ctx: Context) { | |
| console.log('plugin loading') | |
| ctx.effect(() => { | |
| console.log('effect registered') | |
| return () => console.log('effect cleaned up') | |
| }) | |
| } | |
| ``` | |
| Loading prints: | |
| ``` | |
| plugin loading | |
| effect registered | |
| ``` | |
| Unloading prints: | |
| ``` | |
| effect cleaned up | |
| ``` | |
| ## Next steps | |
| - [Services and dependencies](./service.md) β expose a capability to other plugins | |
| - [Event system](./events.md) β communicate between plugins | |
| - [Cordis tutorial](../../../cordis-tutorial/index.md) β the same lifecycle, services, and events built step by step against the Cordis runtime | |