@istar-ts/actions 0.0.0-stage → 0.15.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,741 @@
1
+ import { AnyIstarModel, AnyPaletteDescription, CustomProperties, DiagnosticSeverity, ElementKind, GoalDiagnostic, IstarModel, LinkKind, Metamodel, ModelChange, ModelStore, PistarFile, PropertySchema, PropertyShape } from "@istar-ts/core";
2
+ //#region src/actions.d.ts
3
+ /** GLSP's custom arguments: a flat map of primitives. */
4
+ export type Args = Readonly<Record<string, string | number | boolean>>;
5
+ export interface Point {
6
+ readonly x: number;
7
+ readonly y: number;
8
+ }
9
+ export interface Dimension {
10
+ readonly width: number;
11
+ readonly height: number;
12
+ }
13
+ export interface Action {
14
+ readonly kind: string;
15
+ }
16
+ export interface RequestAction extends Action {
17
+ readonly requestId: string;
18
+ /** Milliseconds the sender is willing to wait (GLSP); the in-process dispatcher ignores it. */
19
+ readonly timeout?: number;
20
+ }
21
+ export interface ResponseAction extends Action {
22
+ /** The `requestId` of the request this answers. */
23
+ readonly responseId: string;
24
+ }
25
+ /** An action that edits the model, as one undo step. */
26
+ export interface Operation extends Action {
27
+ /** GLSP's operation marker. Optional here: the dispatcher knows operations by `kind`. */
28
+ readonly isOperation?: true;
29
+ }
30
+ export interface CreateNodeArgs {
31
+ /** Default: the kind's label ("Goal"), as in piStar. */
32
+ readonly name?: string;
33
+ readonly customProperties?: CustomProperties;
34
+ /** The new element's id. Default: a fresh UUID. Lets a compound operation refer to it. */
35
+ readonly id?: string;
36
+ }
37
+ export interface CreateNodeOperation<EK extends string = ElementKind> extends Operation {
38
+ readonly kind: "createNode";
39
+ /** The element kind, e.g. `istar.Goal`. */
40
+ readonly elementTypeId: EK;
41
+ /** Default: the container's position, or the origin. */
42
+ readonly location?: Point;
43
+ /** The actor to create the element in. */
44
+ readonly containerId?: string;
45
+ readonly args?: CreateNodeArgs;
46
+ }
47
+ /** The dependum a dependency creates between its depender and dependee. */
48
+ export interface DependumArgs<EK extends string = ElementKind> {
49
+ /** Default: the metamodel's first node kind that can be a dependum. */
50
+ readonly kind?: EK;
51
+ readonly name?: string;
52
+ readonly id?: string;
53
+ /** Default: midway between depender and dependee, as in piStar. */
54
+ readonly location?: Point;
55
+ readonly customProperties?: CustomProperties;
56
+ }
57
+ export interface CreateEdgeArgs<EK extends string = ElementKind> {
58
+ /** A contribution's value (the link's `label`), e.g. `help`. */
59
+ readonly value?: string;
60
+ readonly name?: string;
61
+ readonly customProperties?: CustomProperties;
62
+ /**
63
+ * The new link's id: for an n-ary kind whose target is not yet a hub, the new hub's; for an
64
+ * n-ary kind whose target already is a hub, the new leg's (same as `legId` there). Default: a
65
+ * fresh UUID.
66
+ */
67
+ readonly id?: string;
68
+ /** For a dependency kind: the dependum to create. */
69
+ readonly dependum?: DependumArgs<EK>;
70
+ /** For a dependency kind: the ids of its two links. */
71
+ readonly linkIds?: readonly [string, string];
72
+ /**
73
+ * The id of the leg it creates: for a target that is not yet a hub, the new leg from source;
74
+ * for a target that already is a hub, the new leg instead of `id`.
75
+ */
76
+ readonly legId?: string;
77
+ /** For an n-ary kind whose target is not yet a hub: the id of the end it creates. */
78
+ readonly endId?: string;
79
+ }
80
+ /**
81
+ * Adds a link. With a dependency kind, adds the dependum and its two links (as `addDependency`
82
+ * does), source being the depender and target the dependee. With an n-ary kind, adds a leg when
83
+ * the target is one of the kind's hubs, else a new hub with a leg and an end.
84
+ */
85
+ export interface CreateEdgeOperation<EK extends string = ElementKind, LK extends string = LinkKind> extends Operation {
86
+ readonly kind: "createEdge";
87
+ /** The link kind, e.g. `istar.ContributionLink`. */
88
+ readonly elementTypeId: LK;
89
+ readonly sourceElementId: string;
90
+ readonly targetElementId: string;
91
+ readonly args?: CreateEdgeArgs<EK>;
92
+ }
93
+ /** Removes elements and links, with everything that depends on them (as the store does). */
94
+ export interface DeleteElementOperation extends Operation {
95
+ readonly kind: "deleteElement";
96
+ /** Element and link ids. */
97
+ readonly elementIds: readonly string[];
98
+ }
99
+ export interface ElementAndBounds {
100
+ readonly elementId: string;
101
+ /** Moving an actor moves its inner elements with it. */
102
+ readonly newPosition?: Point;
103
+ /** Written to the element's `display` (`width`, `height`). */
104
+ readonly newSize?: Dimension;
105
+ }
106
+ export interface ChangeBoundsOperation extends Operation {
107
+ readonly kind: "changeBounds";
108
+ readonly newBounds: readonly ElementAndBounds[];
109
+ }
110
+ /** Moves an inner element into another actor, or out of any actor with `null` (`nestElement`). */
111
+ export interface ChangeContainerOperation extends Operation {
112
+ readonly kind: "changeContainer";
113
+ readonly elementId: string;
114
+ readonly targetContainerId: string | null;
115
+ /** The element's new position, if it moves too. */
116
+ readonly location?: Point;
117
+ }
118
+ /**
119
+ * Gives a link new ends, keeping its id, kind and properties. A dependency's link keeps its
120
+ * dependum end; an n-ary link's leg keeps its hub (or moves to another hub of the kind), its end
121
+ * keeps the hub.
122
+ */
123
+ export interface ReconnectEdgeOperation extends Operation {
124
+ readonly kind: "reconnectEdge";
125
+ readonly edgeElementId: string;
126
+ readonly sourceElementId: string;
127
+ readonly targetElementId: string;
128
+ readonly args?: Args;
129
+ }
130
+ /**
131
+ * Sets an element's or link's name (`labelId` = its id), or one of its custom properties
132
+ * (`labelId` = `"<id>#<key>"`). An element's name is written as-is (`text`, including `""`, as
133
+ * piStar always keeps the key); a link's name is removed from the file when `text` is `""`, as
134
+ * piStar does for a link whose name was cleared (`fileManager.js` only writes `name` when it is
135
+ * truthy).
136
+ */
137
+ export interface ApplyLabelEditOperation extends Operation {
138
+ readonly kind: "applyLabelEdit";
139
+ readonly labelId: string;
140
+ readonly text: string;
141
+ }
142
+ /** Applies its operations in order, as one undo step; if one is rejected, none is applied. */
143
+ export interface CompoundOperation<EK extends string = ElementKind, LK extends string = LinkKind> extends Operation {
144
+ readonly kind: "compound";
145
+ readonly operationList: readonly IstarOperation<EK, LK>[];
146
+ }
147
+ /** Adds a leg from `sourceElementId` to the hub of an n-ary link (`store.addLeg`). */
148
+ export interface AddLegOperation extends Operation {
149
+ readonly kind: "istar.addLeg";
150
+ readonly hubId: string;
151
+ readonly sourceElementId: string;
152
+ readonly args?: {
153
+ readonly id?: string;
154
+ };
155
+ }
156
+ /** Removes a leg of an n-ary link; the last one takes the hub and end with it. */
157
+ export interface RemoveLegOperation extends Operation {
158
+ readonly kind: "istar.removeLeg";
159
+ readonly legId: string;
160
+ }
161
+ export interface SetCollapsedOperation extends Operation {
162
+ readonly kind: "istar.setCollapsed";
163
+ /** An actor. */
164
+ readonly elementId: string;
165
+ readonly collapsed: boolean;
166
+ }
167
+ export interface DiagramPatch {
168
+ readonly name?: string;
169
+ readonly width?: number;
170
+ readonly height?: number;
171
+ /** Replaces the diagram's custom properties. */
172
+ readonly customProperties?: CustomProperties;
173
+ }
174
+ export interface UpdateDiagramOperation extends Operation {
175
+ readonly kind: "istar.updateDiagram";
176
+ readonly diagram: DiagramPatch;
177
+ }
178
+ /**
179
+ * Sets custom properties of an element or link: each key is set to its value, or removed when
180
+ * the value is `null`; other keys are kept. Values are strings, as piStar stores them.
181
+ */
182
+ export interface UpdatePropertiesOperation extends Operation {
183
+ readonly kind: "istar.updateProperties";
184
+ /** An element or link id. */
185
+ readonly elementId: string;
186
+ readonly properties: Readonly<Record<string, string | null>>;
187
+ }
188
+ /**
189
+ * Merges into an element's `display` (colour, the auto-grown height from a label fit): a key set
190
+ * to `undefined` is removed, the rest is written as-is. Same semantics as `ElementPatch.display`
191
+ * (`@istar-ts/core`), which this forwards to.
192
+ */
193
+ export interface UpdateDisplayOperation extends Operation {
194
+ readonly kind: "istar.updateDisplay";
195
+ readonly elementId: string;
196
+ readonly patch: Readonly<Record<string, unknown>>;
197
+ }
198
+ /**
199
+ * Sets an existing link's contribution value (`label` in the save file), e.g. a Contribution
200
+ * link's make/help/hurt/break. `null` clears it. Rejected when the link's kind has no
201
+ * `possibleLabels`, or `value` is not one of them (as `createEdge.args.value` is checked at
202
+ * creation).
203
+ */
204
+ export interface SetLinkValueOperation extends Operation {
205
+ readonly kind: "istar.setLinkValue";
206
+ readonly linkId: string;
207
+ readonly value: string | null;
208
+ }
209
+ /**
210
+ * Merges into a link's `display` (its bend points, `vertices`): a key set to `undefined` is
211
+ * removed, the rest is written as-is. Same semantics as `LinkPatch.display` (`@istar-ts/core`),
212
+ * which this forwards to. GLSP's counterpart is `changeRoutingPoints`.
213
+ */
214
+ export interface UpdateLinkDisplayOperation extends Operation {
215
+ readonly kind: "istar.updateLinkDisplay";
216
+ readonly linkId: string;
217
+ readonly patch: Readonly<Record<string, unknown>>;
218
+ }
219
+ /** Every operation, keyed by `kind`. */
220
+ export type IstarOperation<EK extends string = ElementKind, LK extends string = LinkKind> = CreateNodeOperation<EK> | CreateEdgeOperation<EK, LK> | DeleteElementOperation | ChangeBoundsOperation | ChangeContainerOperation | ReconnectEdgeOperation | ApplyLabelEditOperation | CompoundOperation<EK, LK> | AddLegOperation | RemoveLegOperation | SetCollapsedOperation | UpdateDiagramOperation | UpdatePropertiesOperation | UpdateDisplayOperation | SetLinkValueOperation | UpdateLinkDisplayOperation;
221
+ export interface RequestModelAction extends RequestAction {
222
+ readonly kind: "requestModel";
223
+ readonly options?: Args;
224
+ }
225
+ export interface SetModelAction extends ResponseAction {
226
+ readonly kind: "setModel";
227
+ /** The model as a piStar save file (`toPistarObject`). */
228
+ readonly newRoot: PistarFile;
229
+ }
230
+ /**
231
+ * The model changed: sent to subscribers after every edit, undo, redo or load, whoever caused
232
+ * it. `source` and `changes` are iStar extras (the store's `ModelChangeEvent`).
233
+ */
234
+ export interface ModelSourceChangedAction extends Action {
235
+ readonly kind: "sourceModelChanged";
236
+ /** The dispatcher's `sourceModelName` option. */
237
+ readonly sourceModelName: string;
238
+ readonly source: "edit" | "undo" | "redo" | "load";
239
+ /** What an edit did; empty for undo, redo and load. */
240
+ readonly changes: readonly ModelChange[];
241
+ /**
242
+ * The new model as a piStar save file (`toPistarObject`), when the dispatcher was created with
243
+ * `sendModel`: what a mirror (`createMirrorStore`) follows without asking for it. An iStar
244
+ * extra.
245
+ */
246
+ readonly newRoot?: PistarFile;
247
+ /**
248
+ * Whether undo is possible, from the remote store after this change (when the dispatcher was
249
+ * created with `sendModel`). An iStar extra; a mirror uses this to know the exact state.
250
+ */
251
+ readonly canUndo?: boolean;
252
+ /**
253
+ * Whether redo is possible, from the remote store after this change (when the dispatcher was
254
+ * created with `sendModel`). An iStar extra; a mirror uses this to know the exact state.
255
+ */
256
+ readonly canRedo?: boolean;
257
+ }
258
+ /** Saves the model through the host's `save` callback. */
259
+ export interface SaveModelAction extends Action {
260
+ readonly kind: "saveModel";
261
+ readonly fileUri?: string;
262
+ }
263
+ export type DirtyStateChangeReason = "operation" | "undo" | "redo" | "save" | "external";
264
+ /** Sent to subscribers when the model starts or stops differing from the last saved one. */
265
+ export interface SetDirtyStateAction extends Action {
266
+ readonly kind: "setDirtyState";
267
+ readonly isDirty: boolean;
268
+ readonly reason?: DirtyStateChangeReason;
269
+ }
270
+ export interface UndoAction extends Action {
271
+ readonly kind: "glspUndo";
272
+ }
273
+ export interface RedoAction extends Action {
274
+ readonly kind: "glspRedo";
275
+ }
276
+ export interface TypeHint {
277
+ readonly elementTypeId: string;
278
+ readonly repositionable: boolean;
279
+ readonly deletable: boolean;
280
+ }
281
+ export interface ShapeTypeHint extends TypeHint {
282
+ readonly resizable: boolean;
283
+ /** Can move into or out of an actor. */
284
+ readonly reparentable: boolean;
285
+ /** For an actor: the node kinds it can contain. */
286
+ readonly containableElementTypeIds?: readonly string[];
287
+ }
288
+ export interface EdgeTypeHint extends TypeHint {
289
+ readonly routable: boolean;
290
+ /** Element kinds that may be the source; absent when any may. */
291
+ readonly sourceElementTypeIds?: readonly string[];
292
+ /** Element kinds that may be the target; absent when any may. */
293
+ readonly targetElementTypeIds?: readonly string[];
294
+ /** Always true for iStar: kinds alone don't decide (same actor, uniqueness…); ask `requestCheckEdge`. */
295
+ readonly dynamic?: boolean;
296
+ }
297
+ export interface RequestTypeHintsAction extends RequestAction {
298
+ readonly kind: "requestTypeHints";
299
+ }
300
+ export interface SetTypeHintsAction extends ResponseAction {
301
+ readonly kind: "setTypeHints";
302
+ readonly shapeHints: readonly ShapeTypeHint[];
303
+ readonly edgeHints: readonly EdgeTypeHint[];
304
+ }
305
+ /** Would a link of `edgeType` from source to target be accepted (`canLink`)? */
306
+ export interface RequestCheckEdgeAction extends RequestAction {
307
+ readonly kind: "requestCheckEdge";
308
+ readonly edgeType: string;
309
+ readonly sourceElementId: string;
310
+ /** Absent: is the source an acceptable source at all? */
311
+ readonly targetElementId?: string;
312
+ }
313
+ export interface CheckEdgeResultAction extends ResponseAction {
314
+ readonly kind: "checkEdgeTargetResult";
315
+ readonly isValid: boolean;
316
+ readonly edgeType: string;
317
+ readonly sourceElementId: string;
318
+ readonly targetElementId?: string;
319
+ /** iStar extra: why not, when `isValid` is false. */
320
+ readonly reason?: string;
321
+ /** iStar extra: the constraint that failed (`ConstraintCode`). */
322
+ readonly code?: string;
323
+ }
324
+ export interface EditorContext {
325
+ readonly selectedElementIds: readonly string[];
326
+ /** Where the user is about to create something, in model coordinates. */
327
+ readonly lastMousePosition?: Point;
328
+ readonly args?: Args;
329
+ }
330
+ /** GLSP's context ids. The dispatcher answers every context with the palette. */
331
+ export type ContextId = "tool-palette" | "context-menu" | "command-palette" | (string & {});
332
+ export interface RequestContextActions extends RequestAction {
333
+ readonly kind: "requestContextActions";
334
+ readonly contextId: ContextId;
335
+ readonly editorContext: EditorContext;
336
+ }
337
+ /** One palette entry: the trigger action(s) a click sends, with the palette's data. */
338
+ export interface LabeledAction {
339
+ readonly label: string;
340
+ readonly actions: readonly IstarAction[];
341
+ readonly icon?: string;
342
+ /** iStar extras, from the `PaletteDescription` entry. */
343
+ readonly id?: string;
344
+ readonly group?: string;
345
+ readonly section?: string;
346
+ readonly order?: number;
347
+ }
348
+ export interface SetContextActions extends ResponseAction {
349
+ readonly kind: "setContextActions";
350
+ /** Sorted by `order`. */
351
+ readonly actions: readonly LabeledAction[];
352
+ /** iStar extra: labels of the entries' `group`s (the palette's dropdown buttons). */
353
+ readonly groups?: Readonly<Record<string, {
354
+ readonly label: string;
355
+ }>>;
356
+ readonly args?: Args;
357
+ }
358
+ /** Arms the client's node creation tool; the client then sends a `CreateNodeOperation`. */
359
+ export interface TriggerNodeCreationAction extends Action {
360
+ readonly kind: "triggerNodeCreation";
361
+ readonly elementTypeId: string;
362
+ /** Presets for the operation's `args`. */
363
+ readonly args?: {
364
+ readonly customProperties?: CustomProperties;
365
+ };
366
+ }
367
+ /** Arms the client's edge creation tool; the client then sends a `CreateEdgeOperation`. */
368
+ export interface TriggerEdgeCreationAction extends Action {
369
+ readonly kind: "triggerEdgeCreation";
370
+ readonly elementTypeId: string;
371
+ /** Presets for the operation's `args`: a contribution's value, a dependency's dependum kind. */
372
+ readonly args?: {
373
+ readonly value?: string;
374
+ readonly dependum?: {
375
+ readonly kind: string;
376
+ };
377
+ };
378
+ }
379
+ /** GLSP's validation marker; `kind` is a `DiagnosticSeverity`. */
380
+ export interface Marker {
381
+ /** Short text (the diagnostic's message). */
382
+ readonly label: string;
383
+ /** Full text (the message, with its source when it has one). */
384
+ readonly description: string;
385
+ readonly elementId: string;
386
+ readonly kind: DiagnosticSeverity | (string & {});
387
+ /** iStar extras, kept so a marker converts back to the same `GoalDiagnostic`. */
388
+ readonly key?: string;
389
+ readonly source?: string;
390
+ readonly code?: string;
391
+ }
392
+ /**
393
+ * Markers of the model: link constraint violations (`validateModel`), property issues (the
394
+ * dispatcher's `schemas`) and the host's `diagnostics`.
395
+ */
396
+ export interface RequestMarkersAction extends RequestAction {
397
+ readonly kind: "requestMarkers";
398
+ /**
399
+ * Elements to report on (GLSP's spelling). Empty, or naming no element or link of the model
400
+ * (a GLSP client sends its root's id), means the whole model.
401
+ */
402
+ readonly elementsIDs: readonly string[];
403
+ readonly reason?: string;
404
+ }
405
+ export interface SetMarkersAction extends ResponseAction {
406
+ readonly kind: "setMarkers";
407
+ readonly markers: readonly Marker[];
408
+ readonly reason?: string;
409
+ }
410
+ export interface DeleteMarkersAction extends Action {
411
+ readonly kind: "deleteMarkers";
412
+ readonly markers: readonly Marker[];
413
+ }
414
+ export type IstarRequestAction = RequestModelAction | RequestTypeHintsAction | RequestCheckEdgeAction | RequestContextActions | RequestMarkersAction;
415
+ export type IstarResponseAction = SetModelAction | SetTypeHintsAction | CheckEdgeResultAction | SetContextActions | SetMarkersAction;
416
+ /**
417
+ * Actions the dispatcher does not act on: it passes them to its subscribers (a server telling
418
+ * its clients), and sends the first two itself.
419
+ */
420
+ export type IstarNotificationAction = ModelSourceChangedAction | SetDirtyStateAction | TriggerNodeCreationAction | TriggerEdgeCreationAction | DeleteMarkersAction;
421
+ /** Every action of the protocol, keyed by `kind`. */
422
+ export type IstarAction<EK extends string = ElementKind, LK extends string = LinkKind> = IstarOperation<EK, LK> | UndoAction | RedoAction | SaveModelAction | IstarRequestAction | IstarResponseAction | IstarNotificationAction;
423
+ /**
424
+ * The action kinds `createActionDispatcher` accepts, grouped the way it treats them: `operations`
425
+ * edit the model as one undo step, `requests` get a response action, `notifications` (plus
426
+ * `glspUndo`/`glspRedo`/`saveModel`) are acted on or re-emitted as is. Derived from the same
427
+ * lists `isOperation`/`isRequestAction` use, so it can't drift from the dispatcher.
428
+ */
429
+ export declare const HANDLED_ACTION_KINDS: {
430
+ readonly operations: readonly IstarOperation["kind"][];
431
+ readonly requests: readonly IstarRequestAction["kind"][];
432
+ readonly notifications: readonly (UndoAction | RedoAction | SaveModelAction | IstarNotificationAction)["kind"][];
433
+ };
434
+ /** True for the operations (actions that edit the model). */
435
+ export declare function isOperation<EK extends string, LK extends string>(action: IstarAction<EK, LK>): action is IstarOperation<EK, LK>;
436
+ /** True for the requests (actions answered with a response action). */
437
+ export declare function isRequestAction(action: Action): action is IstarRequestAction;
438
+ //#endregion
439
+ //#region src/dispatcher.d.ts
440
+ /** The response a request is answered with; `never` for other actions. */
441
+ export type ResponseFor<A> = A extends RequestModelAction ? SetModelAction : A extends RequestTypeHintsAction ? SetTypeHintsAction : A extends RequestCheckEdgeAction ? CheckEdgeResultAction : A extends RequestContextActions ? SetContextActions : A extends RequestMarkersAction ? SetMarkersAction : never;
442
+ /**
443
+ * What dispatching an action did. Plain JSON, like the actions.
444
+ *
445
+ * A rejection (`ok: false`) left the model untouched: the same model object, no undo step. Its
446
+ * diagnostics say why (an unknown element, a link `canLink` refuses, a guard, a property schema).
447
+ */
448
+ export type ActionResult<R = never> = {
449
+ readonly ok: true;
450
+ /** Ids of the elements, then links, the action added, in model order. */
451
+ readonly createdIds: readonly string[];
452
+ /** A request's answer. */
453
+ readonly response?: R;
454
+ /** Non-error diagnostics from guards, for an operation that was applied anyway. */
455
+ readonly diagnostics?: readonly GoalDiagnostic[];
456
+ } | {
457
+ readonly ok: false;
458
+ readonly diagnostics: readonly GoalDiagnostic[];
459
+ };
460
+ export type ActionListener<EK extends string = ElementKind, LK extends string = LinkKind> = (action: IstarAction<EK, LK>) => void;
461
+ /**
462
+ * Sends actions and hears what the other side sends back. Implemented in-process by
463
+ * `createActionDispatcher`; a transport implements it over a message port.
464
+ */
465
+ export interface ActionDispatcher<EK extends string = ElementKind, LK extends string = LinkKind> {
466
+ dispatch<A extends IstarAction<EK, LK>>(action: A): Promise<ActionResult<ResponseFor<A>>>;
467
+ /**
468
+ * Hears the actions the dispatcher sends: `ModelSourceChangedAction` after every model change,
469
+ * `SetDirtyStateAction` when the dirty state flips, and the notifications dispatched to it.
470
+ * Returns an unsubscribe function.
471
+ */
472
+ subscribe(listener: ActionListener<EK, LK>): () => void;
473
+ }
474
+ /**
475
+ * A host's rule, run before each operation is applied (and before each operation of a compound
476
+ * one, against the model as the previous ones left it). Diagnostics of severity `error` reject
477
+ * the operation; others are returned with the result.
478
+ */
479
+ export type ActionGuard<EK extends string = ElementKind, LK extends string = LinkKind> = (operation: IstarOperation<EK, LK>, model: IstarModel<EK, LK>) => readonly GoalDiagnostic[] | void;
480
+ export interface ActionDispatcherOptions<EK extends string = ElementKind, LK extends string = LinkKind> {
481
+ readonly guards?: readonly ActionGuard<EK, LK>[];
482
+ /** What `RequestContextActions` offers. Default: `DEFAULT_PALETTE` (iStar 2.0's). */
483
+ readonly palette?: AnyPaletteDescription;
484
+ /**
485
+ * Property schemas an operation must not break: an operation that adds an issue
486
+ * (`validateModelProperties`) is rejected. Their issues are also markers.
487
+ */
488
+ readonly schemas?: readonly PropertySchema<PropertyShape, string>[];
489
+ /** The host's diagnostics (e.g. a `DiagnosticsStore`'s `getAll`), reported as markers. */
490
+ readonly diagnostics?: () => readonly GoalDiagnostic[];
491
+ /** Writes the file for `SaveModelAction`; without it, saving is rejected. */
492
+ readonly save?: (file: PistarFile, action: SaveModelAction) => void | Promise<void>;
493
+ /** `ModelSourceChangedAction.sourceModelName`, e.g. the file name. Default `''`. */
494
+ readonly sourceModelName?: string;
495
+ /**
496
+ * Attach the new model to every `sourceModelChanged` as `newRoot` (piStar JSON), so a mirror
497
+ * on the other end of a transport (`createMirrorStore`) follows without a `requestModel` round
498
+ * trip. Costs a `toPistarObject` per change (0.3 ms on the largest fixture). Default false.
499
+ */
500
+ readonly sendModel?: boolean;
501
+ }
502
+ export interface StoreActionDispatcher<EK extends string = ElementKind, LK extends string = LinkKind> extends ActionDispatcher<EK, LK> {
503
+ /** True while the model differs from the one last saved (or loaded, or given at creation). */
504
+ isDirty(): boolean;
505
+ /** Stops listening to the store. */
506
+ dispose(): void;
507
+ }
508
+ /**
509
+ * A dispatcher over `store`, in-process. Hand it to a transport to serve remote clients.
510
+ */
511
+ export declare function createActionDispatcher<EK extends string = ElementKind, LK extends string = LinkKind>(store: ModelStore<EK, LK>, options?: ActionDispatcherOptions<EK, LK>): StoreActionDispatcher<EK, LK>;
512
+ //#endregion
513
+ //#region src/hints.d.ts
514
+ /**
515
+ * GLSP type hints of a metamodel. Shapes: every element kind (hubs can't be resized or
516
+ * reparented; actors contain the node kinds that can be inner elements). Edges: every link kind,
517
+ * its sources and targets from its rules, or by category for kinds with built-in rules (iStar
518
+ * 2.0's), plus an n-ary kind's hub (`createEdge` onto a hub adds a leg to that link, #108). Edge
519
+ * hints are `repositionable` (their ends can be reconnected) and `dynamic`: `canLink` checks more
520
+ * than kinds.
521
+ */
522
+ export declare function typeHintsFor<EK extends string, LK extends string>(metamodel: Metamodel<EK, LK>): Pick<SetTypeHintsAction, "shapeHints" | "edgeHints">;
523
+ /**
524
+ * A palette as GLSP context actions: one `LabeledAction` per entry, triggering the client's
525
+ * creation tool with the entry's presets, sorted by `order`. Only the metamodel's kinds are
526
+ * offered, in the metamodel's order where orders tie; kinds the palette hides (`false`) or
527
+ * lacks are left out.
528
+ */
529
+ export declare function contextActionsFor<EK extends string, LK extends string>(palette: AnyPaletteDescription, metamodel: Metamodel<EK, LK>): Pick<SetContextActions, "actions" | "groups">;
530
+ //#endregion
531
+ //#region src/host.d.ts
532
+ /** A host's knowledge for the model: a system-prompt section and/or an MCP resource. */
533
+ export interface HostContextProvider {
534
+ /**
535
+ * `^[a-zA-Z0-9_-]{1,64}$`: the MCP resource's name (and its tool's, when the server lists
536
+ * resources as tools), and the section's heading unless `title` is set.
537
+ */
538
+ readonly name: string;
539
+ readonly title?: string;
540
+ /** What the resource holds, for an MCP client's catalog. Default: the title. */
541
+ readonly description?: string;
542
+ /** The text: fixed, or computed from the model each time it is read. */
543
+ readonly text: string | ((model: AnyIstarModel) => string | Promise<string>);
544
+ /** Also a section of `runAgent`'s system prompt. Default true. */
545
+ readonly prompt?: boolean;
546
+ /** Also an MCP resource of every diagram session. Default true. */
547
+ readonly resource?: boolean;
548
+ }
549
+ /** What a host tool's handler is given. */
550
+ export interface HostToolContext {
551
+ /** The model as it is now: the live one, or a Propose-mode run's scratch copy. */
552
+ getModel(): AnyIstarModel;
553
+ /**
554
+ * The session's dispatcher, the only way a tool edits the model. A read-only tool's refuses
555
+ * everything but requests (`requestModel`, `requestMarkers`, ...), with a `read-only-tool`
556
+ * diagnostic.
557
+ */
558
+ readonly dispatcher: ActionDispatcher<string, string>;
559
+ readonly signal?: AbortSignal;
560
+ }
561
+ /**
562
+ * What a host tool answers, in `ActionResult`'s shape: `content` (any JSON value) for the model
563
+ * to read, or a refusal with typed diagnostics it can repair against. A refused dispatch's
564
+ * `ActionResult` is one already: `if (!result.ok) return result;`.
565
+ */
566
+ export type HostToolResult = {
567
+ readonly ok: true;
568
+ readonly content: unknown;
569
+ } | {
570
+ readonly ok: false;
571
+ readonly diagnostics: readonly GoalDiagnostic[];
572
+ };
573
+ /** A tool of the host's own, served next to the istar tools. */
574
+ export interface HostTool {
575
+ /** `^[a-zA-Z0-9_-]{1,64}$`, distinct from every other tool's. */
576
+ readonly name: string;
577
+ readonly title?: string;
578
+ /** What the model reads about the tool. */
579
+ readonly description: string;
580
+ /**
581
+ * JSON Schema of the arguments: an object schema (`{ type: 'object', properties, required }`).
582
+ * Over MCP the server validates calls against it (it needs `zod` 4.2 or later, for
583
+ * `z.fromJSONSchema`), with the session's `sessionId` added.
584
+ */
585
+ readonly inputSchema: {
586
+ readonly [key: string]: unknown;
587
+ };
588
+ /**
589
+ * True for a tool that only reads (MCP's `readOnlyHint`): Propose mode runs it straight away
590
+ * and never makes it a review step, and its `dispatcher` takes requests only.
591
+ */
592
+ readonly readOnly?: boolean;
593
+ handler(args: {
594
+ readonly [key: string]: unknown;
595
+ }, context: HostToolContext): HostToolResult | Promise<HostToolResult>;
596
+ }
597
+ /** `dispatcher`, refusing anything but requests: what a read-only host tool is handed. */
598
+ export declare function readOnlyDispatcher(dispatcher: ActionDispatcher<string, string>, tool: string): ActionDispatcher<string, string>;
599
+ /** The context a call of `tool` gets: `dispatcher` as is, or read-only for a read-only tool. */
600
+ export declare function hostToolContext(tool: HostTool, dispatcher: ActionDispatcher<string, string>, getModel: () => AnyIstarModel, signal?: AbortSignal): HostToolContext;
601
+ /** A provider's text for `model`. */
602
+ export declare function contextText(provider: HostContextProvider, model: AnyIstarModel): Promise<string>;
603
+ //#endregion
604
+ //#region src/markers.d.ts
605
+ /** A `GoalDiagnostic` as a GLSP marker: `kind` is its severity, `label` its message. */
606
+ export declare function diagnosticToMarker(diagnostic: GoalDiagnostic): Marker;
607
+ /**
608
+ * A GLSP marker as a `GoalDiagnostic`. A `kind` that is no `DiagnosticSeverity` reads as
609
+ * `info`; `range` and `data` are not carried by markers.
610
+ */
611
+ export declare function markerToDiagnostic(marker: Marker): GoalDiagnostic;
612
+ //#endregion
613
+ //#region src/mirror.d.ts
614
+ export interface MirrorStoreOptions<EK extends string = ElementKind, LK extends string = LinkKind> {
615
+ /**
616
+ * The metamodel the remote's files are read with (`parsePistar`'s `metamodel`), and of the
617
+ * empty model shown until the first one arrives. Default iStar 2.0.
618
+ */
619
+ readonly metamodel?: Metamodel<EK, LK>;
620
+ /** `parsePistar`'s `fileMetamodel`: apply the file's own `"metamodel"` block. Default false. */
621
+ readonly fileMetamodel?: boolean;
622
+ /**
623
+ * How many undo steps the remote keeps, for `canUndo` estimate (see `MirrorStore`). Only used
624
+ * when the dispatcher doesn't send exact values. Default 100, a `ModelStore`'s default.
625
+ */
626
+ readonly historyLimit?: number;
627
+ /** Hears a failed update (a transport fault, a file that doesn't parse). Default: ignored. */
628
+ readonly onError?: (error: unknown) => void;
629
+ }
630
+ /**
631
+ * A `ModelStore` whose model is the remote's. Reading (`getModel`, `subscribe`, `canLink`) works
632
+ * as on any store; every mutation (`addElement` … `replace`, `load`, `transaction`,
633
+ * `clearHistory`) throws a `ModelOperationError`: dispatch the edit to the remote instead.
634
+ *
635
+ * Undo is the remote's, one stack for all its clients: `undo`/`redo` dispatch `glspUndo` /
636
+ * `glspRedo` to it. `canUndo`/`canRedo` are exact when the dispatcher sends them with each
637
+ * change (a dispatcher created with `sendModel`), or an estimate counted from the notifications
638
+ * heard since the mirror connected (the remote doesn't publish its stack's depth when not sending
639
+ * them): edits made before then are not counted.
640
+ */
641
+ export interface MirrorStore<EK extends string = ElementKind, LK extends string = LinkKind> extends ModelStore<EK, LK> {
642
+ /** Resolves once the remote's model is shown; rejects if the first `requestModel` fails. */
643
+ readonly ready: Promise<void>;
644
+ /**
645
+ * The remote, wrapped so that `dispatch` resolves only once the mirror shows what the action
646
+ * did: give this to `IstarProvider` as `dispatcher`. (With a `sendModel` remote, the remote
647
+ * itself already has that order, since a change's notification arrives before its result.)
648
+ */
649
+ readonly dispatcher: ActionDispatcher<EK, LK>;
650
+ /** Resolves once every change heard so far is shown. */
651
+ synced(): Promise<void>;
652
+ /** Stops following the remote (the remote itself stays open). */
653
+ dispose(): void;
654
+ }
655
+ /**
656
+ * A mirror of `remote`'s model (see `MirrorStore`). Shows an empty model until `ready`.
657
+ *
658
+ * Order: changes are shown in the order the remote sends them, whoever made them, and a
659
+ * `dispatch` through `mirror.dispatcher` resolves after its change is shown, so code that
660
+ * selects a created id or rolls back a rejected one sees the model it expects. A rejected
661
+ * action sends no notification: the mirror stays as it was.
662
+ */
663
+ export declare function createMirrorStore<EK extends string = ElementKind, LK extends string = LinkKind>(remote: ActionDispatcher<EK, LK>, options?: MirrorStoreOptions<EK, LK>): MirrorStore<EK, LK>;
664
+ //#endregion
665
+ //#region src/transport.d.ts
666
+ /** An id a JSON-RPC request carries and its response answers back. */
667
+ export type JsonRpcId = string | number;
668
+ export interface JsonRpcRequest {
669
+ readonly jsonrpc: "2.0";
670
+ readonly id: JsonRpcId;
671
+ readonly method: string;
672
+ readonly params?: unknown;
673
+ }
674
+ /** A subscriber event, sent with no `id`: it expects no response. */
675
+ export interface JsonRpcNotification {
676
+ readonly jsonrpc: "2.0";
677
+ readonly method: string;
678
+ readonly params?: unknown;
679
+ }
680
+ export interface JsonRpcSuccess {
681
+ readonly jsonrpc: "2.0";
682
+ readonly id: JsonRpcId;
683
+ readonly result: unknown;
684
+ }
685
+ export interface JsonRpcErrorObject {
686
+ readonly code: number;
687
+ readonly message: string;
688
+ readonly data?: unknown;
689
+ }
690
+ export interface JsonRpcError {
691
+ readonly jsonrpc: "2.0";
692
+ readonly id: JsonRpcId;
693
+ readonly error: JsonRpcErrorObject;
694
+ }
695
+ /** The envelope `connectDispatcher`/`createRemoteDispatcher` exchange over the port. */
696
+ export type ActionMessage = JsonRpcRequest | JsonRpcNotification | JsonRpcSuccess | JsonRpcError;
697
+ /**
698
+ * Structurally what a DOM `MessagePort`, a worker's `self`, or any two-way `postMessage` channel
699
+ * gives us: enough to send and receive `ActionMessage`s, nothing DOM-specific. Generic over the
700
+ * event type `onmessage` is handed (`MessageEvent` for a real port, inferred at the call site),
701
+ * so a real `MessagePort` or `Worker` fits without a cast: `strictFunctionTypes` checks a
702
+ * property-typed handler's parameter invariantly, so pinning it to a narrower `{ data: unknown }`
703
+ * here would reject `MessagePort`'s own, wider `onmessage` type.
704
+ */
705
+ export interface MessagePortLike<E extends {
706
+ readonly data: unknown;
707
+ } = {
708
+ readonly data: unknown;
709
+ }> {
710
+ postMessage(data: unknown): void;
711
+ onmessage: ((ev: E) => unknown) | null;
712
+ }
713
+ /**
714
+ * Serves `dispatcher` on `port`: every well-formed request is answered with the
715
+ * `ActionResult` as `result`; `dispatcher.subscribe` events are pushed as notifications.
716
+ * A malformed request answers `-32600` (invalid request) or `-32601` (no usable `method`); an
717
+ * exception `dispatch` itself doesn't catch answers `-32603` (internal error). Returns a
718
+ * disposer that stops forwarding subscriber events and detaches the port's `onmessage`.
719
+ */
720
+ export declare function connectDispatcher<EK extends string = ElementKind, LK extends string = LinkKind, E extends {
721
+ readonly data: unknown;
722
+ } = {
723
+ readonly data: unknown;
724
+ }>(port: MessagePortLike<E>, dispatcher: ActionDispatcher<EK, LK>): () => void;
725
+ /**
726
+ * The `ActionDispatcher` for the other end of a `connectDispatcher` port: `dispatch` sends a
727
+ * request and resolves with the `ActionResult` it is answered with (a JSON-RPC `error` rejects
728
+ * the promise instead — a transport fault, not an `ActionResult`); `subscribe` hears the
729
+ * notifications the server pushes.
730
+ */
731
+ export declare function createRemoteDispatcher<EK extends string = ElementKind, LK extends string = LinkKind, E extends {
732
+ readonly data: unknown;
733
+ } = {
734
+ readonly data: unknown;
735
+ }>(port: MessagePortLike<E>): ActionDispatcher<EK, LK>;
736
+ //#endregion
737
+ //#region src/index.d.ts
738
+ /** Version of the action protocol this package speaks. */
739
+ export declare const ACTIONS_PROTOCOL_VERSION: string;
740
+ //#endregion
741
+ //# sourceMappingURL=index.d.cts.map