mirror of
https://fastgit.cc/github.com/openclaw/openclaw
synced 2026-05-01 06:36:23 +08:00
refactor(plugin-sdk): add managed task flow runtime
This commit is contained in:
@@ -725,18 +725,18 @@ canonical replacement.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="runtime.tasks.flow → runtime.tasks.flows">
|
||||
<Accordion title="runtime.tasks.flow → runtime.tasks.managedFlows">
|
||||
**Old**: `runtime.tasks.flow` (singular) returned a live task-flow accessor.
|
||||
|
||||
**New**: `runtime.tasks.flows` (plural) returns DTO-based TaskFlow access,
|
||||
which is import-safe and does not require the full task runtime to be
|
||||
loaded.
|
||||
**New**: `runtime.tasks.managedFlows` keeps the managed TaskFlow mutation
|
||||
runtime for plugins that create, update, cancel, or run child tasks from a
|
||||
flow. Use `runtime.tasks.flows` when the plugin only needs DTO-based reads.
|
||||
|
||||
```typescript
|
||||
// Before
|
||||
const flow = api.runtime.tasks.flow(ctx);
|
||||
const flow = api.runtime.tasks.flow.fromToolContext(ctx);
|
||||
// After
|
||||
const flows = api.runtime.tasks.flows(ctx);
|
||||
const flow = api.runtime.tasks.managedFlows.fromToolContext(ctx);
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
|
||||
@@ -179,11 +179,11 @@ Internal OpenClaw runtime code has the same direction: load config once at the C
|
||||
Inside the Gateway this runtime is in-process. In plugin CLI commands it calls the configured Gateway over RPC, so commands such as `openclaw googlemeet recover-tab` can inspect paired nodes from the terminal. Node commands still go through normal Gateway node pairing, command allowlists, and node-local command handling.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="api.runtime.taskFlow">
|
||||
<Accordion title="api.runtime.tasks.managedFlows">
|
||||
Bind a Task Flow runtime to an existing OpenClaw session key or trusted tool context, then create and manage Task Flows without passing an owner on every call.
|
||||
|
||||
```typescript
|
||||
const taskFlow = api.runtime.taskFlow.fromToolContext(ctx);
|
||||
const taskFlow = api.runtime.tasks.managedFlows.fromToolContext(ctx);
|
||||
|
||||
const created = taskFlow.createManaged({
|
||||
controllerId: "my-plugin/review-batch",
|
||||
|
||||
@@ -89,7 +89,7 @@ The plugin applies:
|
||||
- Request body size and timeout guards
|
||||
- Fixed-window rate limiting
|
||||
- In-flight request limiting
|
||||
- Owner-bound TaskFlow access through `api.runtime.taskFlow.bindSession(...)`
|
||||
- Owner-bound TaskFlow access through `api.runtime.tasks.managedFlows.bindSession(...)`
|
||||
|
||||
## Request format
|
||||
|
||||
|
||||
@@ -13,8 +13,8 @@ export default definePluginEntry({
|
||||
return null;
|
||||
}
|
||||
const taskFlow =
|
||||
api.runtime?.taskFlow && ctx.sessionKey
|
||||
? api.runtime.taskFlow.fromToolContext(ctx)
|
||||
api.runtime?.tasks.managedFlows && ctx.sessionKey
|
||||
? api.runtime.tasks.managedFlows.fromToolContext(ctx)
|
||||
: undefined;
|
||||
return createLobsterTool(api, { taskFlow }) as AnyAgentTool;
|
||||
}) as OpenClawPluginToolFactory,
|
||||
|
||||
@@ -12,7 +12,7 @@ type JsonLike =
|
||||
};
|
||||
|
||||
type BoundTaskFlow = ReturnType<
|
||||
NonNullable<OpenClawPluginApi["runtime"]>["taskFlow"]["bindSession"]
|
||||
NonNullable<OpenClawPluginApi["runtime"]>["tasks"]["managedFlows"]["bindSession"]
|
||||
>;
|
||||
|
||||
type FlowRecord = ReturnType<BoundTaskFlow["createManaged"]>;
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
} from "./lobster-taskflow.js";
|
||||
|
||||
type BoundTaskFlow = ReturnType<
|
||||
NonNullable<OpenClawPluginApi["runtime"]>["taskFlow"]["bindSession"]
|
||||
NonNullable<OpenClawPluginApi["runtime"]>["tasks"]["managedFlows"]["bindSession"]
|
||||
>;
|
||||
|
||||
type JsonLike =
|
||||
|
||||
@@ -2,7 +2,7 @@ import { vi } from "vitest";
|
||||
import type { OpenClawPluginApi } from "../runtime-api.js";
|
||||
|
||||
export type BoundTaskFlow = ReturnType<
|
||||
NonNullable<OpenClawPluginApi["runtime"]>["taskFlow"]["bindSession"]
|
||||
NonNullable<OpenClawPluginApi["runtime"]>["tasks"]["managedFlows"]["bindSession"]
|
||||
>;
|
||||
|
||||
export function createFakeTaskFlow(overrides?: Partial<BoundTaskFlow>): BoundTaskFlow {
|
||||
|
||||
@@ -14,8 +14,10 @@ function createApi(params?: {
|
||||
source: "test",
|
||||
pluginConfig: params?.pluginConfig ?? {},
|
||||
runtime: {
|
||||
taskFlow: {
|
||||
bindSession: vi.fn(({ sessionKey }: { sessionKey: string }) => ({ sessionKey })),
|
||||
tasks: {
|
||||
managedFlows: {
|
||||
bindSession: vi.fn(({ sessionKey }: { sessionKey: string }) => ({ sessionKey })),
|
||||
},
|
||||
},
|
||||
} as unknown as OpenClawPluginApi["runtime"],
|
||||
registerHttpRoute: params?.registerHttpRoute ?? vi.fn(),
|
||||
|
||||
@@ -17,7 +17,7 @@ function registerWebhookRoutes(api: OpenClawPluginApi): void {
|
||||
});
|
||||
|
||||
for (const route of routes) {
|
||||
const taskFlow = api.runtime.taskFlow.bindSession({
|
||||
const taskFlow = api.runtime.tasks.managedFlows.bindSession({
|
||||
sessionKey: route.sessionKey,
|
||||
});
|
||||
const target: TaskFlowWebhookTarget = {
|
||||
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
} from "../runtime-api.js";
|
||||
import type { WebhookSecretInput } from "./config.js";
|
||||
|
||||
type BoundTaskFlowRuntime = ReturnType<PluginRuntime["taskFlow"]["bindSession"]>;
|
||||
type BoundTaskFlowRuntime = ReturnType<PluginRuntime["tasks"]["managedFlows"]["bindSession"]>;
|
||||
|
||||
type JsonValue = null | boolean | number | string | JsonValue[] | { [key: string]: JsonValue };
|
||||
|
||||
|
||||
@@ -73,10 +73,10 @@ export function createPluginRuntimeMock(overrides: DeepPartial<PluginRuntime> =
|
||||
const taskFlow = {
|
||||
bindSession: vi.fn(
|
||||
createTaskFlowSessionMock,
|
||||
) as unknown as PluginRuntime["taskFlow"]["bindSession"],
|
||||
) as unknown as PluginRuntime["tasks"]["managedFlows"]["bindSession"],
|
||||
fromToolContext: vi.fn(
|
||||
createTaskFlowSessionMock,
|
||||
) as unknown as PluginRuntime["taskFlow"]["fromToolContext"],
|
||||
) as unknown as PluginRuntime["tasks"]["managedFlows"]["fromToolContext"],
|
||||
};
|
||||
const base: PluginRuntime = {
|
||||
version: "1.0.0-test",
|
||||
@@ -468,6 +468,7 @@ export function createPluginRuntimeMock(overrides: DeepPartial<PluginRuntime> =
|
||||
bindSession: vi.fn(),
|
||||
fromToolContext: vi.fn(),
|
||||
} as PluginRuntime["tasks"]["flows"],
|
||||
managedFlows: taskFlow,
|
||||
flow: taskFlow,
|
||||
},
|
||||
taskFlow,
|
||||
|
||||
@@ -720,7 +720,8 @@ export const PLUGIN_COMPAT_RECORDS = [
|
||||
deprecated: "2026-04-26",
|
||||
warningStarts: "2026-04-26",
|
||||
removeAfter: "2026-07-26",
|
||||
replacement: "`api.runtime.tasks.flows`",
|
||||
replacement:
|
||||
"`api.runtime.tasks.managedFlows` for managed mutations or `api.runtime.tasks.flows` for DTO reads",
|
||||
docsPath: "/plugins/sdk-runtime",
|
||||
surfaces: ["api.runtime.taskFlow", "api.runtime.tasks.flow"],
|
||||
diagnostics: ["plugin runtime compatibility warning"],
|
||||
|
||||
@@ -191,7 +191,7 @@ describe("plugin runtime command execution", () => {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "exposes canonical runtime.tasks.runs and runtime.tasks.flows while keeping legacy TaskFlow aliases",
|
||||
name: "exposes canonical runtime.tasks task runtimes while keeping legacy TaskFlow aliases",
|
||||
assert: (runtime: ReturnType<typeof createPluginRuntime>) => {
|
||||
expectFunctionKeys(runtime.tasks.runs as Record<string, unknown>, [
|
||||
"bindSession",
|
||||
@@ -201,11 +201,16 @@ describe("plugin runtime command execution", () => {
|
||||
"bindSession",
|
||||
"fromToolContext",
|
||||
]);
|
||||
expectFunctionKeys(runtime.tasks.managedFlows as Record<string, unknown>, [
|
||||
"bindSession",
|
||||
"fromToolContext",
|
||||
]);
|
||||
expectFunctionKeys(runtime.tasks.flow as Record<string, unknown>, [
|
||||
"bindSession",
|
||||
"fromToolContext",
|
||||
]);
|
||||
expect(runtime.taskFlow).toBe(runtime.tasks.flow);
|
||||
expect(runtime.tasks.managedFlows).toBe(runtime.tasks.flow);
|
||||
expect(runtime.taskFlow).toBe(runtime.tasks.managedFlows);
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -217,6 +217,7 @@ export function createRuntimeTasks(params: {
|
||||
return {
|
||||
runs: createRuntimeTaskRuns(),
|
||||
flows: createRuntimeTaskFlows(),
|
||||
managedFlows: params.legacyTaskFlow,
|
||||
flow: params.legacyTaskFlow,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -64,6 +64,7 @@ export type PluginRuntimeTaskFlows = {
|
||||
export type PluginRuntimeTasks = {
|
||||
runs: PluginRuntimeTaskRuns;
|
||||
flows: PluginRuntimeTaskFlows;
|
||||
managedFlows: PluginRuntimeTaskFlow;
|
||||
/** @deprecated Use runtime.tasks.flows for DTO-based TaskFlow access. */
|
||||
flow: PluginRuntimeTaskFlow;
|
||||
};
|
||||
|
||||
@@ -231,6 +231,7 @@ export type PluginRuntimeCore = {
|
||||
tasks: {
|
||||
runs: PluginRuntimeTaskRuns;
|
||||
flows: PluginRuntimeTaskFlows;
|
||||
managedFlows: import("./runtime-taskflow.types.js").PluginRuntimeTaskFlow;
|
||||
/** @deprecated Use runtime.tasks.flows for DTO-based TaskFlow access. */
|
||||
flow: import("./runtime-taskflow.types.js").PluginRuntimeTaskFlow;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user