Skip to content

Operations

An operation is an action with a name, a typed input and a typed output, defined once and run from anywhere in an app, by people and by agents.

An operation definition has a key (a DXN), metadata for people and agents, and schemas for its input and output. A handler is an Effect that takes the input and returns the output. Definitions and handlers are separate values, so a plugin can export a definition for other plugins to call without exposing how it runs.

src/types/StashedLinkOperation.ts
import * as
import Schema
Schema
from 'effect/Schema';
import * as
import Operation
Operation
from '@dxos/compute/Operation';
import {
import Database
Database
,
import DXN
DXN
,
import Ref
Ref
} from '@dxos/echo';
import {
class StashedLink
StashedLink
} from './StashedLink.ts';
export const
const MarkRead: Operation.Definition<{
readonly link: Ref<StashedLink & OfKind<EntityKind.Object> & Unknown>;
}, void, Database.Service>
MarkRead
=
import Operation
Operation
.
const make: <{
readonly meta: {
readonly key: DXN.DXN;
readonly name: "Mark as read";
readonly description: "Mark a link as read.";
readonly icon: "ph--check-circle--regular";
};
readonly services: readonly [typeof Database.Service];
readonly input: Schema.Struct<{
readonly link: Schema.Codec<Ref<StashedLink & OfKind<EntityKind.Object> & Unknown>, EncodedReference, never, never>;
}>;
readonly output: Schema.Void;
}>(props: {
readonly meta: {
readonly key: DXN.DXN;
readonly name: "Mark as read";
readonly description: "Mark a link as read.";
readonly icon: "ph--check-circle--regular";
};
readonly services: readonly [typeof Database.Service];
readonly input: Schema.Struct<{
readonly link: Schema.Codec<Ref<StashedLink & OfKind<EntityKind.Object> & Unknown>, EncodedReference, never, never>;
}>;
readonly output: Schema.Void;
}) => Operation.Definition<...>

Creates a new Operation definition. Applies default executionMode of 'async' if not specified. The returned type preserves the literal types of props (including services).

make
({
meta: {
readonly key: DXN.DXN;
readonly name: "Mark as read";
readonly description: "Mark a link as read.";
readonly icon: "ph--check-circle--regular";
}
meta
: {
key: DXN.DXN
key
:
import DXN
DXN
.
const make: <"com.example.operation.stashedLink.markRead">(nsid: "com.example.operation.stashedLink.markRead", version?: string) => DXN.DXN

Constructs a DXN from an NSID (and optional version). Throws if the result is not a valid DXN. Use tryMake for non-throwing string parsing.

Static NSID strings are validated at compile time via

Name

: the final segment must be camelCase (no hyphens). Template-literal strings with a runtime prefix are accepted here but still validated at runtime.

@example make('org.dxos.type.calendar') → 'dxn:org.dxos.type.calendar'

@example make('org.dxos.type.calendar', '1.0.0') → 'dxn:org.dxos.type.calendar:1.0.0'

make
('com.example.operation.stashedLink.markRead'),
name: "Mark as read"
name
: 'Mark as read',
description: "Mark a link as read."
description
: 'Mark a link as read.',
icon: "ph--check-circle--regular"
icon
: 'ph--check-circle--regular',
},
// The handler resolves the reference in the link's space.
services: readonly [typeof Database.Service]
services
: [
import Database
Database
.
class Service

Effect service tag for Database dependency injection.

Service
],
input: Schema.Struct<{
readonly link: Schema.Codec<Ref<StashedLink & OfKind<EntityKind.Object> & Unknown>, EncodedReference, never, never>;
}>
input
:
import Schema
Schema
.
function Struct<{
readonly link: Schema.Codec<Ref<StashedLink & OfKind<EntityKind.Object> & Unknown>, EncodedReference, never, never>;
}>(fields: {
readonly link: Schema.Codec<Ref<StashedLink & OfKind<EntityKind.Object> & Unknown>, EncodedReference, never, never>;
}): Schema.Struct<{
readonly link: Schema.Codec<Ref<StashedLink & OfKind<EntityKind.Object> & Unknown>, EncodedReference, never, never>;
}>

Defines a struct schema from a map of field schemas.

Details

Each field value is a schema. Use

optionalKey

or

optional

to mark fields as optional, and

mutableKey

to mark them as mutable.

The resulting schema's Type is a readonly object type with the fields' decoded types. The Encoded form mirrors the field schemas' encoded types. Declared fields may be inherited and are copied to own properties in the output. The __proto__ field is accepted only when it is an own property. Parsing does not guarantee that output keys retain their input order.

Example (Defining a basic struct)

import { Schema } from "effect"
const Person = Schema.Struct({
name: Schema.String,
age: Schema.Number,
email: Schema.optionalKey(Schema.String)
})
// { readonly name: string; readonly age: number; readonly email?: string }
type Person = typeof Person.Type
Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 }) // => { name: "Alice", age: 30 }

@stability ― stable

@category ― constructors

@since ― 3.10.0

Struct
({
link: Schema.Codec<Ref<StashedLink & OfKind<EntityKind.Object> & Unknown>, EncodedReference, never, never>
link
:
import Ref
Ref
.
const Ref: <typeof StashedLink>(type: typeof StashedLink) => Ref.RefSchema<StashedLink & OfKind<EntityKind.Object> & Unknown> (+3 overloads)
Ref
(
class StashedLink
StashedLink
).
BottomWithoutNew<unknown, unknown, unknown, unknown, AST, Top, unknown, unknown, any, unknown, Mutability, Optionality, ConstructorDefault, Mutability, Optionality>.annotate(annotations: Schema.Annotations.Bottom<Ref<StashedLink & OfKind<EntityKind.Object> & Unknown>, any>): Schema.Codec<Ref<StashedLink & OfKind<EntityKind.Object> & Unknown>, EncodedReference, never, never>
annotate
({
Annotations.Augment.description?: string | undefined
description
: 'The link that was read.',
}),
}),
output: Schema.Void
output
:
import Schema
Schema
.
const Void: Schema.Void

Type-level representation of

Void

.

Schema for a TypeScript void return value.

When to use

Use when you need to model the return value of a function, RPC, or endpoint whose result is intentionally ignored.

Details

Runtime parsing accepts any present value and discards it, producing undefined. The public decoded and encoded TypeScript representation remains void, so typed construction, decoding, and encoding APIs are still modeled as void.

@stability ― stable

@category ― models

@since ― 3.10.0

@see ― Undefined for a schema that matches only the exact undefined value.

@stability ― stable

@category ― schemas

@since ― 3.10.0

Void
,
});

Plugins contribute handlers in an operation handler set through the OperationHandler capability. The operation invoker looks up the handler by the definition’s key and runs it. Any module, handler or graph action can invoke an operation with Operation.invoke; a component uses useOperation.

import * as
import Effect
Effect
from 'effect/Effect';
import * as
import Operation
Operation
from '@dxos/compute/Operation';
import {
import Ref
Ref
} from '@dxos/echo';
import { type
class StashedLink
StashedLink
} from './src/types/StashedLink.ts';
import {
const MarkRead: Operation.Definition<{
readonly link: Ref<StashedLink & OfKind<EntityKind.Object> & Unknown>;
}, void, Service>
MarkRead
} from './src/types/StashedLinkOperation.ts';
// Any module, handler or action can run an operation by its definition.
export const
const markRead: (link: StashedLink) => Effect.Effect<void | undefined, never, Operation.Service>
markRead
= (
link: StashedLink
link
:
class StashedLink
StashedLink
) =>
import Operation
Operation
.
const invoke: <{
readonly link: Ref<StashedLink & OfKind<EntityKind.Object> & Unknown>;
}, void>(op: Operation.Definition<{
readonly link: Ref<StashedLink & OfKind<EntityKind.Object> & Unknown>;
}, void, any>, input: {
readonly link: Ref<StashedLink & OfKind<EntityKind.Object> & Unknown>;
}, options?: Operation.InvokeOptions | undefined) => Effect.Effect<void, Operation.NoHandlerError, Operation.Service>

Invoke an operation as an Effect. Yields the Operation.Service internally.

@example

yield* Operation.invoke(MyOperation, { data: 'test' });

invoke
(
const MarkRead: Operation.Definition<{
readonly link: Ref<StashedLink & OfKind<EntityKind.Object> & Unknown>;
}, void, Service>
MarkRead
, {
link: Ref<StashedLink & OfKind<EntityKind.Object> & Unknown>
link
:
import Ref
Ref
.
const make: <StashedLink>(object: StashedLink) => Ref<StashedLink>

Create a reference to an entity.

@performance ― O(1); allocates a ref that inlines the target, with no lookup.

make
(
link: StashedLink
link
) }).
Pipeable.pipe<Effect.Effect<void, Operation.NoHandlerError, Operation.Service>, Effect.Effect<void | undefined, never, Operation.Service>>(this: Effect.Effect<void, Operation.NoHandlerError, Operation.Service>, ab: (_: Effect.Effect<void, Operation.NoHandlerError, Operation.Service>) => Effect.Effect<void | undefined, never, Operation.Service>): Effect.Effect<void | undefined, never, Operation.Service> (+21 overloads)
pipe
(
import Effect
Effect
.
const catchTag: <"NoHandlerError", Operation.NoHandlerError, undefined, never, never, unassigned, never, never>(k: "NoHandlerError", f: (e: Operation.NoHandlerError) => Effect.Effect<undefined, never, never>, orElse?: ((e: never) => Effect.Effect<unassigned, never, never>) | undefined) => <A, R>(self: Effect.Effect<A, Operation.NoHandlerError, R>) => Effect.Effect<A | undefined, never, R> (+1 overload)

Catches and handles specific errors by their _tag field, which is used as a discriminator.

When to use

Use when you need to recover from one specific tagged error in an effect error channel.

Details

The error type must have a readonly _tag field. catchTag matches that field and only handles errors with the requested tag.

Example (Handling a tagged error)

import { Effect } from "effect"
class NetworkError {
readonly _tag = "NetworkError"
constructor(readonly message: string) {}
}
class ValidationError {
readonly _tag = "ValidationError"
constructor(readonly message: string) {}
}
const task: Effect.Effect<string, NetworkError | ValidationError> =
Effect.fail(new NetworkError("offline"))
const program = Effect.catchTag(
task,
"NetworkError",
(error) => Effect.succeed(`Recovered from network error: ${error.message}`)
)
Effect.runSync(program) // => "Recovered from network error: offline"

@see ― catchTags for handling multiple tagged errors in one call

@see ― catchIf for recovering from errors that match a predicate

@stability ― stable

@category ― error handling

@since ― 2.0.0

catchTag
('NoHandlerError', () =>
import Effect
Effect
.
const succeed: <undefined>(value: undefined) => Effect.Effect<undefined, never, never>

Creates an Effect that always succeeds with a given value.

When to use

Use when an effect should complete successfully with a specific value without any errors or external dependencies.

Example (Creating a successful effect)

import { Effect } from "effect"
// Creating an effect that represents a successful scenario
//
// ┌─── Effect<number, never, never>
// ▼
const success = Effect.succeed(42)
Effect.runSync(success) // => 42

@see ― fail to create an effect that represents a failure.

@stability ― stable

@category ― constructors

@since ― 2.0.0

succeed
(
var undefined
undefined
)),
);

A skill hands operations to the assistant. It is a name, instructions, and a list of operations that become the assistant’s tools; a plugin contributes it through AppCapabilities.SkillDefinition.

src/skills/StashSkill.ts
import * as
import Skill
Skill
from '@dxos/compute/Skill';
import * as
import Template
Template
from '@dxos/compute/Template';
import {
const MarkRead: Definition<{
readonly link: Ref<StashedLink & OfKind<EntityKind.Object> & Unknown>;
}, void, Service>
MarkRead
} from '../types/StashedLinkOperation.ts';
export const
const key: "com.example.skill.stash"
key
= 'com.example.skill.stash';
export const
const make: () => Skill.Skill
make
= ():
import Skill
Skill
.
class Skill

Skill schema defines the structure for AI assistant skills. Skills contain instructions, tools, and artifacts that guide the AI's behavior. Skills may use tools to create and read artifacts, which are managed by the assistant.

Follows the Agent Skills spec (https://agentskills.io/specification) as closely as it can, so a skill means the same here as in any other harness. Add a field the spec lacks only with a strong reason, and say what it is. Credentials and MCP servers do not belong here: a server is a connection, which the space owns and each conversation can turn off. Nor do hooks: a plugin contributes those beside its skills (@dxos/compute/Hook).

The registry key and version are stored in the object meta — access them via Obj.getMeta(skill).key and Obj.getMeta(skill).version.

Skill
=>
import Skill
Skill
.
const make: <"com.example.skill.stash">(props: {
key: "com.example.skill.stash";
version?: string;
name: string;
mcpPrompt?: boolean;
} & Partial<Skill.Skill>) => Skill.Skill

Create a new Skill. The key (and optional version) are stored in the object meta. key must be a valid DXN name (e.g. org.dxos.skill.mySkill).

make
({
key: "com.example.skill.stash"
key
,
name: string
name
: 'Stash',
tools?: readonly (string & Brand<"ToolId">)[] | undefined
tools
:
import Skill
Skill
.
const toolDefinitions: ({ tools, operations, }: {
tools?: readonly string[];
operations?: readonly Definition<I, O, S = any>.Any[];
}) => (string & import("effect/Brand").Brand<"ToolId">)[]

Util to create tool definitions for a skill. Operation tool ids are the model-facing names (see

Operation.toolName

), so the skill's tools array and the session toolkit speak one identifier space.

toolDefinitions
({
operations?: readonly Definition.Any[] | undefined
operations
: [
const MarkRead: Definition<{
readonly link: Ref<StashedLink & OfKind<EntityKind.Object> & Unknown>;
}, void, Service>
MarkRead
] }),
instructions?: {
readonly source: import("@dxos/echo/internal").Ref<Text & import("@dxos/echo/Entity").OfKind<import("@dxos/echo/internal").EntityKind.Object> & Unknown>;
readonly inputs?: readonly {
readonly name: string;
readonly kind: "operation" | "value";
readonly default?: any;
readonly operation?: string | undefined;
}[] | undefined;
} | undefined
instructions
:
import Template
Template
.
const make: ({ id, source, inputs }?: Template.MakeProps) => Template.Template
make
({
source?: string | undefined
source
:
'When the user says they have read a page they stashed, find its ' +
'link and mark it as read.',
}),
});

Stash’s Operations module in the inspector runs Mark as read from a form built from its input schema:

  • One definition serves three callers. A button invokes it through a hook. The command palette lists it. A skill hands it to the assistant as a tool, and the assistant reads the schema descriptions to fill in the input. None of the three needs code of its own.
  • The invoker validates the input against the schema before the handler runs, and the output after.
  • Errors are typed. A handler fails with tagged errors that a caller catches by tag, and invoking an operation that no plugin handles fails with NoHandlerError.
  • An operation can be undone. A plugin contributes an UndoMapping that names the operation’s inverse and derives the inverse’s input from the forward input and output; the app records each undoable invocation and offers to undo it.
import * as
import Effect
Effect
from 'effect/Effect';
import * as
import Schema
Schema
from 'effect/Schema';
import * as
import ActivationEvents
ActivationEvents
from '@dxos/app-framework/ActivationEvents';
import * as
import Capabilities
Capabilities
from '@dxos/app-framework/Capabilities';
import * as
import Capability
Capability
from '@dxos/app-framework/Capability';
import * as
import Operation
Operation
from '@dxos/compute/Operation';
import {
import DXN
DXN
} from '@dxos/echo';
const
const Rename: Operation.Definition<{
readonly id: string;
readonly name: string;
}, {
readonly previous: string;
}, never>
Rename
=
import Operation
Operation
.
const make: <{
readonly meta: {
readonly key: DXN.DXN;
readonly name: "Rename";
};
readonly input: Schema.Struct<{
readonly id: Schema.String;
readonly name: Schema.String;
}>;
readonly output: Schema.Struct<{
readonly previous: Schema.String;
}>;
}>(props: {
readonly meta: {
readonly key: DXN.DXN;
readonly name: "Rename";
};
readonly input: Schema.Struct<{
readonly id: Schema.String;
readonly name: Schema.String;
}>;
readonly output: Schema.Struct<{
readonly previous: Schema.String;
}>;
}) => Operation.Definition<...>

Creates a new Operation definition. Applies default executionMode of 'async' if not specified. The returned type preserves the literal types of props (including services).

make
({
meta: {
readonly key: DXN.DXN;
readonly name: "Rename";
}
meta
: {
key: DXN.DXN
key
:
import DXN
DXN
.
const make: <"com.example.operation.rename">(nsid: "com.example.operation.rename", version?: string) => DXN.DXN

Constructs a DXN from an NSID (and optional version). Throws if the result is not a valid DXN. Use tryMake for non-throwing string parsing.

Static NSID strings are validated at compile time via

Name

: the final segment must be camelCase (no hyphens). Template-literal strings with a runtime prefix are accepted here but still validated at runtime.

@example make('org.dxos.type.calendar') → 'dxn:org.dxos.type.calendar'

@example make('org.dxos.type.calendar', '1.0.0') → 'dxn:org.dxos.type.calendar:1.0.0'

make
('com.example.operation.rename'),
name: "Rename"
name
: 'Rename',
},
input: Schema.Struct<{
readonly id: Schema.String;
readonly name: Schema.String;
}>
input
:
import Schema
Schema
.
function Struct<{
readonly id: Schema.String;
readonly name: Schema.String;
}>(fields: {
readonly id: Schema.String;
readonly name: Schema.String;
}): Schema.Struct<{
readonly id: Schema.String;
readonly name: Schema.String;
}>

Defines a struct schema from a map of field schemas.

Details

Each field value is a schema. Use

optionalKey

or

optional

to mark fields as optional, and

mutableKey

to mark them as mutable.

The resulting schema's Type is a readonly object type with the fields' decoded types. The Encoded form mirrors the field schemas' encoded types. Declared fields may be inherited and are copied to own properties in the output. The __proto__ field is accepted only when it is an own property. Parsing does not guarantee that output keys retain their input order.

Example (Defining a basic struct)

import { Schema } from "effect"
const Person = Schema.Struct({
name: Schema.String,
age: Schema.Number,
email: Schema.optionalKey(Schema.String)
})
// { readonly name: string; readonly age: number; readonly email?: string }
type Person = typeof Person.Type
Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 }) // => { name: "Alice", age: 30 }

@stability ― stable

@category ― constructors

@since ― 3.10.0

Struct
({
id: Schema.String
id
:
import Schema
Schema
.
const String: Schema.String

Type-level representation of

String

.

Schema for string values. Validates that the input is typeof "string".

@stability ― stable

@category ― models

@since ― 4.0.0

@stability ― stable

@category ― schemas

@since ― 4.0.0

String
,
name: Schema.String
name
:
import Schema
Schema
.
const String: Schema.String

Type-level representation of

String

.

Schema for string values. Validates that the input is typeof "string".

@stability ― stable

@category ― models

@since ― 4.0.0

@stability ― stable

@category ― schemas

@since ― 4.0.0

String
}),
output: Schema.Struct<{
readonly previous: Schema.String;
}>
output
:
import Schema
Schema
.
function Struct<{
readonly previous: Schema.String;
}>(fields: {
readonly previous: Schema.String;
}): Schema.Struct<{
readonly previous: Schema.String;
}>

Defines a struct schema from a map of field schemas.

Details

Each field value is a schema. Use

optionalKey

or

optional

to mark fields as optional, and

mutableKey

to mark them as mutable.

The resulting schema's Type is a readonly object type with the fields' decoded types. The Encoded form mirrors the field schemas' encoded types. Declared fields may be inherited and are copied to own properties in the output. The __proto__ field is accepted only when it is an own property. Parsing does not guarantee that output keys retain their input order.

Example (Defining a basic struct)

import { Schema } from "effect"
const Person = Schema.Struct({
name: Schema.String,
age: Schema.Number,
email: Schema.optionalKey(Schema.String)
})
// { readonly name: string; readonly age: number; readonly email?: string }
type Person = typeof Person.Type
Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 }) // => { name: "Alice", age: 30 }

@stability ― stable

@category ― constructors

@since ― 3.10.0

Struct
({
previous: Schema.String
previous
:
import Schema
Schema
.
const String: Schema.String

Type-level representation of

String

.

Schema for string values. Validates that the input is typeof "string".

@stability ― stable

@category ― models

@since ― 4.0.0

@stability ― stable

@category ― schemas

@since ― 4.0.0

String
}),
});
// The inverse is the same operation with the previous name.
export const
const RenameUndoModule: Capability.Module<void>
RenameUndoModule
=
import Capability
Capability
.
const inlineModule: <readonly [Capability.MultiTag<Capabilities.UndoMapping[], "org.dxos.app-framework.capability.undoMapping">], readonly [], void, void>(name: string, spec: ModuleSpec<readonly [Capability.MultiTag<Capabilities.UndoMapping[], "org.dxos.app-framework.capability.undoMapping">], readonly [], void, void>, activate: (props: void) => Effect.Effect<Capability.Contribution<Capability.CapabilityIdentifier<"org.dxos.app-framework.capability.undoMapping", "multi">> | readonly Capability.Contribution<Capability.CapabilityIdentifier<"org.dxos.app-framework.capability.undoMapping", "multi">>[], Error, Capability.Requirements<...>>) => Capability.Module<...>

Helper to define an eager module body with the same spec-carrying shape as

lazyModule

— for bodies that are plain values (translations, schema) or too small to justify a chunk, so plugin definitions stay a uniform chain of spec-carrying modules.

@param ― name The module name — used to auto-compute module IDs.

@param ― spec The requires/provides declaration.

@param ― activate The module body.

inlineModule
(
'RenameUndo',
{
provides: readonly [Capability.MultiTag<Capabilities.UndoMapping[], "org.dxos.app-framework.capability.undoMapping">]
provides
: [
import Capabilities
Capabilities
.
const UndoMapping: Capability.MultiTag<Capabilities.UndoMapping[], "org.dxos.app-framework.capability.undoMapping">

Undo mapping registration - contributed by plugins.

@category ― Capability

UndoMapping
],
activatesOn?: Events | undefined

Activates when this runtime event fires instead of during the dependency pass.

activatesOn
:
import ActivationEvents
ActivationEvents
.
const Startup: ActivationEvent

Fired when the app is started. Defined in core; see

ActivationEvent$.Startup

.

Startup
,
},
() =>
import Effect
Effect
.
const succeed: <Capability.Contribution<Capability.CapabilityIdentifier<"org.dxos.app-framework.capability.undoMapping", "multi">>>(value: Capability.Contribution<Capability.CapabilityIdentifier<"org.dxos.app-framework.capability.undoMapping", "multi">>) => Effect.Effect<Capability.Contribution<Capability.CapabilityIdentifier<"org.dxos.app-framework.capability.undoMapping", "multi">>, never, never>

Creates an Effect that always succeeds with a given value.

When to use

Use when an effect should complete successfully with a specific value without any errors or external dependencies.

Example (Creating a successful effect)

import { Effect } from "effect"
// Creating an effect that represents a successful scenario
//
// ┌─── Effect<number, never, never>
// ▼
const success = Effect.succeed(42)
Effect.runSync(success) // => 42

@see ― fail to create an effect that represents a failure.

@stability ― stable

@category ― constructors

@since ― 2.0.0

succeed
(
import Capability
Capability
.
const contribute: <Capability.MultiTag<Capabilities.UndoMapping[], "org.dxos.app-framework.capability.undoMapping">>(capability: Capability.MultiTag<Capabilities.UndoMapping[], "org.dxos.app-framework.capability.undoMapping">, implementation: Capabilities.UndoMapping[]) => Capability.Contribution<Capability.CapabilityIdentifier<"org.dxos.app-framework.capability.undoMapping", "multi">> (+1 overload)
contribute
(
import Capabilities
Capabilities
.
const UndoMapping: Capability.MultiTag<Capabilities.UndoMapping[], "org.dxos.app-framework.capability.undoMapping">

Undo mapping registration - contributed by plugins.

@category ― Capability

UndoMapping
, [
{
UndoMapping<Definition<any, any, any>, Definition<any, any, any>>.operation: Operation.Definition<any, any, any>

The forward operation.

operation
:
const Rename: Operation.Definition<{
readonly id: string;
readonly name: string;
}, {
readonly previous: string;
}, never>
Rename
,
UndoMapping<Definition<any, any, any>, Definition<any, any, any>>.inverse: Operation.Definition<any, any, any>

The inverse operation to invoke for undo.

inverse
:
const Rename: Operation.Definition<{
readonly id: string;
readonly name: string;
}, {
readonly previous: string;
}, never>
Rename
,
UndoMapping<Definition<any, any, any>, Definition<any, any, any>>.deriveContext: (input: any, output: any) => any

Derives the input for the inverse operation from the forward operation's input and output.

@param ― input - The input that was passed to the forward operation.

@param ― output - The output that was returned by the forward operation.

@returns ― The input to pass to the inverse operation, or undefined to indicate the operation is not undoable.

deriveContext
: (
input: any
input
,
output: any
output
) => ({
id: any
id
:
input: any
input
.
any
id
,
name: any
name
:
output: any
output
.
any
previous
,
}),
UndoMapping<Definition<any, any, any>, Definition<any, any, any>>.message?: MessageProvider<Operation.Definition<any, any, any>> | undefined

Optional message to show in the undo toast. Can be a static Label or a function that derives the message from input/output.

message
: 'Renamed',
},
]),
),
);
  • Handlers load lazily. A lazy handler set names each handler’s module, and the framework imports it the first time the operation is invoked.
  • The App Toolkit defines operations every plugin can call. LayoutOperation.Open opens items by path, LayoutOperation.Close closes them, and SpaceOperation.AddObject adds an object to a space.
  • A handler runs with the services its definition declares, plus the operation service for invoking other operations. It does not get the React tree.
  • An operation’s input must be serializable for the assistant to call it. Pass objects by reference where the caller is an agent.
  • Undo replays the inverse operation; it does not restore a snapshot. An operation whose effect cannot be inverted from its input and output is not undoable.