@ixo/editor 6.22.0 → 6.24.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.
@@ -1,2144 +0,0 @@
1
- import { a7 as FlowNode, ac as FlowNodeAuthzExtension, a4 as FlowNodeRuntimeState, a5 as IxoEditorType, f as UcanService, I as InvocationStore, aa as EvaluationStatus, i as UcanCapability, U as UcanDelegationStore, S as StoredDelegation } from './index-BC4ycOwH.js';
2
- import * as Y from 'yjs';
3
- import { Doc, Map } from 'yjs';
4
- import { MatrixClient } from 'matrix-js-sdk';
5
-
6
- /** Condition that gates when a capability activates. */
7
- interface ConditionRef {
8
- /** ID of the upstream capability whose output is checked. */
9
- sourceId: string;
10
- /** Output field path to inspect, e.g., "decision". */
11
- field: string;
12
- /** Comparison operator. */
13
- operator: 'eq' | 'neq' | 'gt' | 'lt' | 'in' | 'exists';
14
- /** Value to compare against (omit for 'exists'). */
15
- value?: unknown;
16
- /** What happens when the condition is (not) met. */
17
- effect?: {
18
- action: 'enable' | 'disable' | 'hide' | 'show';
19
- message?: string;
20
- };
21
- }
22
- /** Authorization constraint for a capability. */
23
- interface ActorConstraint {
24
- /** Whitelisted actor DIDs. */
25
- authorisedActors?: string[];
26
- /** Parent capability URI for delegation chain. */
27
- parentCapability?: string;
28
- }
29
- /** Time-to-live constraint for a capability. */
30
- interface TTLConstraint {
31
- /** Hard deadline (ISO 8601 date string). */
32
- absoluteDueDate?: string;
33
- /** Duration from when the block becomes enabled (ISO 8601 duration, e.g., "P7D"). */
34
- fromEnablement?: string;
35
- /** Duration from when an actor commits (ISO 8601 duration, e.g., "PT2H"). */
36
- fromCommitment?: string;
37
- }
38
- /**
39
- * A single capability in a Base UCAN flow plan.
40
- *
41
- * UCAN semantics:
42
- * can = the action
43
- * with = the resource or scope
44
- * nb = typed caveats, inputs, parameters
45
- *
46
- * Workflow semantics (kept separate from nb):
47
- * condition, trigger, parallelGroup, phase
48
- */
49
- interface FlowCapability {
50
- /** Stable node identifier for this step. */
51
- id: string;
52
- /** UCAN-style ability string, e.g., "bid/submit", "email/send". */
53
- can: string;
54
- /** Resource URI, e.g., "ixo:flow:{flowId}" or "ixo:flow:{flowId}:{nodeId}". */
55
- with: string;
56
- /** Typed caveats / input parameters. Shape is dictated by the action registry. */
57
- nb?: Record<string, unknown>;
58
- /** Condition that must be met for this capability to activate. */
59
- condition?: ConditionRef;
60
- /** Capabilities sharing a parallelGroup run concurrently. */
61
- parallelGroup?: string;
62
- /** Semantic grouping for layout lanes. */
63
- phase?: string;
64
- /** Who can execute this step. */
65
- actor?: ActorConstraint;
66
- /** Time-to-live constraints. */
67
- ttl?: TTLConstraint;
68
- /**
69
- * When and how this block fires. Defaults to `{ type: 'manual' }` if absent
70
- * (i.e. block runs only when a user explicitly invokes it).
71
- *
72
- * `block.event` triggers turn this block into a listener: when the source
73
- * block emits an event matching `eventName`, a pending invocation is
74
- * queued on this block and the assigned actor is DM'd to invoke it. See
75
- * `docs/flow-engine/events-and-triggers-plan.md` §3.7 and §18 for the full model.
76
- *
77
- * Triggers are a NEW sibling field on FlowCapability (decided in eng review
78
- * pass 2 phase 0 #1). They are NOT an extension of `condition`. The decompile
79
- * branch's author needs to add `props.trigger` parsing when their work merges.
80
- */
81
- trigger?: TriggerSpec;
82
- /** Display title (falls back to can statement). */
83
- title?: string;
84
- /** Description of what this step does. */
85
- description?: string;
86
- /** Icon identifier. */
87
- icon?: string;
88
- }
89
- /**
90
- * Trigger declaration for a block. When and how it fires.
91
- */
92
- /** A single event source in a barrier trigger. */
93
- interface TriggerSource {
94
- /** ID of the block that emits the event. */
95
- sourceBlockId: string;
96
- /** Name of the event (must match an event declared on the source action's `events` vocabulary). */
97
- eventName: string;
98
- /** Namespace alias for payload access: `trigger.payload.<alias>.*` */
99
- alias: string;
100
- /**
101
- * When `true`, this source does NOT block queuing — the barrier fires once all
102
- * *required* (non-optional) sources have fired. If an optional source fired before
103
- * the barrier completes, its payload is merged in; if it never fires, it's skipped.
104
- * Defaults to `false` (required) for backward compatibility.
105
- */
106
- optional?: boolean;
107
- }
108
- interface TriggerSpec {
109
- /**
110
- * - `manual`: block runs only when a user explicitly invokes it (default).
111
- * - `flow.start`: block runs when the flow execution begins.
112
- * - `block.event`: block runs each time another block emits a matching event.
113
- * - `block.event.all`: block runs once ALL listed sources have emitted (barrier/join).
114
- */
115
- type: 'manual' | 'flow.start' | 'block.event' | 'block.event.all';
116
- /** Required when `type === 'block.event'`. ID of the block that emits the event. */
117
- sourceBlockId?: string;
118
- /** Required when `type === 'block.event'`. Name of the event (must match an event declared on the source action's `events` vocabulary). */
119
- eventName?: string;
120
- /** Required when `type === 'block.event.all'`. Array of event sources — ALL must fire before the listener is queued. */
121
- sources?: TriggerSource[];
122
- }
123
- /**
124
- * The Base UCAN flow plan — the intermediate representation between
125
- * user intent and the compiled flow graph.
126
- *
127
- * capabilities is an ordered list. Each capability carries its own stable `id`.
128
- */
129
- interface BaseUcanFlow {
130
- kind: 'qi.flow.base-ucan';
131
- version: '1.0';
132
- flowId: string;
133
- title: string;
134
- goal?: string;
135
- meta?: {
136
- entityDid?: string;
137
- flowUri?: string;
138
- rootIssuer?: string;
139
- };
140
- /** Ordered capabilities, each with its own stable node ID. */
141
- capabilities: FlowCapability[];
142
- }
143
- /** A reference to an upstream node's output field. Format: "nodeId.output.fieldPath" */
144
- interface RuntimeRef {
145
- $ref: string;
146
- }
147
- declare function isRuntimeRef(value: unknown): value is RuntimeRef;
148
- /** A single block ready for insertion into BlockNote. */
149
- interface CompiledBlock {
150
- /** Pre-generated stable block ID. */
151
- id: string;
152
- /** BlockNote block type (e.g., "action"). */
153
- type: string;
154
- /** Block props — all values are strings per BlockNote convention. */
155
- props: Record<string, string>;
156
- }
157
- /**
158
- * An edge in the flow graph. Currently only `kind: 'trigger'` edges are
159
- * synthesized — they come from `block.event` triggers and represent the
160
- * source → listener relationship visually on the canvas.
161
- */
162
- interface CompiledEdge {
163
- id: string;
164
- source: string;
165
- target: string;
166
- kind: 'trigger';
167
- condition?: ConditionRef;
168
- }
169
- /** A compiled flow node stored in qi.flow.nodes. */
170
- interface CompiledFlowNode {
171
- id: string;
172
- blockId: string;
173
- can: string;
174
- with: string;
175
- registryType: string;
176
- title: string;
177
- description: string;
178
- props: Record<string, string>;
179
- phase?: string;
180
- parallelGroup?: string;
181
- actor?: ActorConstraint;
182
- }
183
- /** The complete compiled output from the Base UCAN compiler. */
184
- interface CompiledFlow {
185
- /** Flow metadata for qi.flow.meta and Y.Map('root'). */
186
- meta: {
187
- flowId: string;
188
- title: string;
189
- goal?: string;
190
- version: string;
191
- flowOwnerDid: string;
192
- flowUri?: string;
193
- compiledAt: string;
194
- compiledFrom: 'BaseUcanFlow';
195
- };
196
- /** Blocks to insert into BlockNote, in topological order. */
197
- blocks: CompiledBlock[];
198
- /** Flow graph nodes, keyed by node ID. */
199
- nodes: Record<string, CompiledFlowNode>;
200
- /** Dependency edges. */
201
- edges: CompiledEdge[];
202
- /** Topological order of node IDs. */
203
- order: string[];
204
- /** nodeId → blockId mapping. */
205
- blockIndex: Record<string, string>;
206
- }
207
- /** Strategy for how a compiled flow is applied to an existing document. */
208
- type FlowStrategy = 'full' | 'merge' | 'patch';
209
-
210
- declare const buildAuthzFromProps: (props: Record<string, any>) => FlowNodeAuthzExtension;
211
- declare const buildFlowNodeFromBlock: (block: any) => FlowNode;
212
-
213
- interface FlowRuntimeStateManager {
214
- get: (nodeId: string) => FlowNodeRuntimeState;
215
- update: (nodeId: string, updates: Partial<FlowNodeRuntimeState>) => void;
216
- }
217
- declare const createRuntimeStateManager: (editor?: IxoEditorType | null) => FlowRuntimeStateManager;
218
- /**
219
- * Clears runtime, invocations, and pending invocations from a Y.Doc.
220
- * Used when cloning a flow as a template — the new document should
221
- * carry only configuration (intent), not execution history.
222
- *
223
- * The audit trail (which now also holds run records as `type: 'block.run'`
224
- * entries) and pending invocations are observation, not configuration —
225
- * both are cleared on template clone.
226
- */
227
- declare function clearRuntimeForTemplateClone(yDoc: Doc): void;
228
-
229
- /**
230
- * Run record stored in the audit trail as `type: 'block.run'`.
231
- *
232
- * Per Phase 0 #2 (eng review pass 2), run records are NOT a parallel
233
- * `_yRunHistory` structure — they ride on the existing `auditTrail` Y.Map
234
- * via `useAuditTrail.addEvent`. The shape below is what goes into the
235
- * audit trail event's `details` field.
236
- *
237
- * See `docs/flow-engine/events-and-triggers-plan.md` §3.4, §18, §19.
238
- */
239
- interface RunRecordDetails {
240
- /** Stable identifier for this run, deterministic from invocation context. */
241
- runId: string;
242
- /** Action's output. */
243
- output: Record<string, unknown>;
244
- /**
245
- * Events the action emitted on this run. Persisted as part of the run
246
- * record so the reconciliation loop can process them idempotently — even
247
- * across page refreshes and across multiple clients.
248
- */
249
- events: Array<{
250
- name: string;
251
- payload: Record<string, unknown>;
252
- }>;
253
- /** ISO timestamp when the action started. */
254
- startedAt: string;
255
- /** ISO timestamp when the action completed (success or failure). */
256
- completedAt: string;
257
- /** DID of the actor who signed the invocation that produced this run. */
258
- actorDid: string;
259
- /** UCAN invocation CID when execution produced one. */
260
- invocationCid?: string;
261
- /** Capability/proof CID used when no invocation CID was produced. */
262
- capabilityId?: string;
263
- /** Optional error if the run failed. */
264
- error?: {
265
- message: string;
266
- code?: string;
267
- };
268
- /** External read-back metadata associated with this run or reconciliation. */
269
- readBack?: Record<string, unknown>;
270
- /** True when this audit entry was written by external read-back reconciliation. */
271
- reconciled?: boolean;
272
- /**
273
- * If this run was triggered by a pending invocation (i.e. it's a listener
274
- * run), the id of that pending invocation. Used to dedup replays and trace
275
- * causality back through `triggeredBy`.
276
- */
277
- fromPendingInvocationId?: string;
278
- /**
279
- * If this run is a listener run, the (sourceBlockId, eventName) that
280
- * caused it. Used by the failure visibility surface to attribute failures
281
- * back to the source block (CP-1).
282
- */
283
- triggeredBy?: {
284
- sourceBlockId: string;
285
- eventName: string;
286
- };
287
- /** Source run id for listener runs, stored explicitly for failure lookups. */
288
- sourceRunId?: string;
289
- }
290
- declare const RUN_RECORD_AUDIT_TYPE = "block.run";
291
- /**
292
- * Pending invocation queued on a listener block.
293
- *
294
- * Stored in `_yPendingInvocations: Y.Map<blockId, Y.Map<id, PendingInvocation>>`.
295
- *
296
- * The id is deterministic — derived from
297
- * `(sourceBlockId, sourceRunId, listenerBlockId, eventName, eventIndex)` —
298
- * so the reconciliation loop can run idempotently from multiple clients
299
- * without producing duplicates.
300
- *
301
- * See `docs/flow-engine/events-and-triggers-plan.md` §3.4, §3.5.1, §18.
302
- */
303
- interface PendingInvocation {
304
- /** Deterministic id, see `computePendingInvocationId`. */
305
- id: string;
306
- /** Block that emitted the event. */
307
- triggeringBlockId: string;
308
- /** Run id of the triggering source run, used for the deterministic id. */
309
- sourceRunId: string;
310
- /** Event name from the source action's vocabulary. */
311
- eventName: string;
312
- /** Event index within the source run's `events` array (a single run can emit multiple). */
313
- eventIndex: number;
314
- /**
315
- * The frozen event payload, captured by value at emission time. The
316
- * assignee invokes the listener against this payload, not against the
317
- * source block's current state. This is the property that makes the
318
- * Sally → Mike scenario produce 10 distinct emails even when Mike acts
319
- * on them all hours later.
320
- */
321
- payload: Record<string, unknown>;
322
- /**
323
- * Snapshots of `nodeId.output.*` ref values that the listener's inputs
324
- * reference, captured at queue time. Keyed by the full ref string.
325
- *
326
- * §3.5.1: ref snapshots are the load-bearing fix for the lag-time
327
- * overwrite scenario. If a listener references a non-trigger block's
328
- * output (e.g. `evaluateBlock.output.claimId`), that value is captured
329
- * here at queue time. Resolution at invocation time prefers the snapshot
330
- * over current state, so multiple queued invocations don't drift when
331
- * the source re-runs.
332
- */
333
- refSnapshots: Record<string, unknown>;
334
- /** DID of the assigned actor who must invoke this listener. Resolved from `props.assignment.assignedActor.did`. */
335
- assigneeDid: string;
336
- /** ISO timestamp when the source emission happened. */
337
- emittedAt: string;
338
- /** ISO timestamp after which this pending invocation is considered expired. Resolved from `FlowCapability.ttl` at queue time. */
339
- expiresAt: string;
340
- }
341
- /**
342
- * Compute a deterministic id for a pending invocation from its content.
343
- *
344
- * The same (sourceBlockId, sourceRunId, listenerBlockId, eventName,
345
- * eventIndex) tuple always produces the same id. This is the property that
346
- * makes the reconciliation loop idempotent — re-running it from a different
347
- * client, or after a page refresh, produces the same `Y.Map.set` operation
348
- * with the same key, which Yjs converges to a single entry.
349
- *
350
- * Implementation: simple deterministic string concatenation, hashed via a
351
- * 32-bit FNV-1a. The id is short and stable; collision risk within a single
352
- * flow is negligible because the inputs are scoped (block ids are unique
353
- * within a flow, run ids are unique within a block).
354
- */
355
- declare function computePendingInvocationId(args: {
356
- sourceBlockId: string;
357
- sourceRunId: string;
358
- listenerBlockId: string;
359
- eventName: string;
360
- eventIndex: number;
361
- }): string;
362
- /**
363
- * Walk an inputs object and collect every RuntimeRef of the form
364
- * `nodeId.output.fieldPath`. Returns a map of `{refString: resolvedValue}`
365
- * suitable for storing as `PendingInvocation.refSnapshots`.
366
- *
367
- * The walker mirrors `resolveRuntimeRefs` in `flowCompiler/resolveRefs.ts`
368
- * but reads instead of resolving — it captures the current value of each
369
- * ref so the listener can later resolve against the snapshot rather than
370
- * against current state.
371
- *
372
- * See `docs/flow-engine/events-and-triggers-plan.md` §3.5.1.
373
- */
374
- declare function snapshotInputRefs(inputs: unknown, getNodeOutput: (nodeId: string) => Record<string, unknown> | undefined): Record<string, unknown>;
375
- /**
376
- * Get the top-level pending invocations Y.Map from the editor's yDoc.
377
- * Lazily creates it if missing.
378
- *
379
- * Shape: `Y.Map<blockId, Y.Map<pendingInvocationId, PendingInvocation>>`.
380
- * The outer map is keyed by listener block id; the inner map is keyed by
381
- * deterministic pending invocation id (see `computePendingInvocationId`).
382
- */
383
- declare function getPendingInvocationsMap(yDoc: Y.Doc): Y.Map<Y.Map<unknown>>;
384
- /**
385
- * Get the inner pending-invocations map for a specific listener block.
386
- * Lazily creates it if missing. Caller is responsible for being inside a
387
- * Yjs transaction if atomic creation matters.
388
- */
389
- declare function getOrCreateBlockPendingMap(yDoc: Y.Doc, blockId: string): Y.Map<unknown>;
390
- /**
391
- * Read all pending invocations for a block as plain JS objects.
392
- * Returns an array sorted by `emittedAt` ascending (oldest first).
393
- */
394
- declare function readPendingInvocations(yDoc: Y.Doc, blockId: string): PendingInvocation[];
395
- /**
396
- * Idempotently write a pending invocation under its deterministic id.
397
- *
398
- * Returns true if a new entry was created, false if the id already
399
- * existed (meaning another client or a previous reconciliation pass
400
- * already queued this invocation). This is the property that makes
401
- * `reconcilePendingInvocations` safe to run from multiple clients
402
- * simultaneously and across page refreshes — see plan §18.
403
- *
404
- * Wraps the write in a Yjs transaction so the existence check and the
405
- * subsequent set are atomic from the local client's perspective. Concurrent
406
- * clients each computing the same id will all converge to a single entry
407
- * because Y.Map.set with the same key is last-writer-wins on identical
408
- * content.
409
- */
410
- declare function queuePendingInvocation(yDoc: Y.Doc, listenerBlockId: string, invocation: PendingInvocation): boolean;
411
- /**
412
- * Remove a pending invocation by id. Used when the assignee completes the
413
- * invocation (transitioning to a `block.run` audit trail entry) or when
414
- * the expiration sweep marks it as expired.
415
- */
416
- declare function removePendingInvocation(yDoc: Y.Doc, listenerBlockId: string, pendingInvocationId: string): boolean;
417
- /**
418
- * Append a run record to the audit trail for a block. Run records are
419
- * stored as audit trail events with `type: 'block.run'` and the structured
420
- * data in `details`. Per Phase 0 #2 of eng review pass 2, this avoids
421
- * inventing a parallel `_yRunHistory` storage system.
422
- *
423
- * Y.Array.push from concurrent clients merges correctly — verified by the
424
- * existing `useAuditTrail` shipping in production.
425
- */
426
- declare function appendRunRecord(yDoc: Y.Doc, blockId: string, details: RunRecordDetails, userId: string): void;
427
- /**
428
- * Read all run records for a block from the audit trail. Filters audit
429
- * trail entries to only those with `type: 'block.run'`.
430
- */
431
- declare function readRunRecords(yDoc: Y.Doc, blockId: string): RunRecordDetails[];
432
- /**
433
- * A failed listener run, attributed to the source block emission that
434
- * triggered it. Used by the failure visibility surface (CP-1) on source
435
- * blocks: the source block can show "N listeners failed for your last run".
436
- */
437
- interface FailedListenerRun {
438
- /** Block id of the listener whose run failed. */
439
- listenerBlockId: string;
440
- /** The full RunRecordDetails of the failed listener invocation. */
441
- record: RunRecordDetails;
442
- }
443
- /**
444
- * Find all failed listener runs that were triggered by a specific source
445
- * block run. Walks every block's audit trail, filters to listener runs
446
- * triggered by (sourceBlockId, sourceRunId), and returns the ones with an
447
- * error set.
448
- *
449
- * Used by the source block UI to show a failure badge linked to a specific
450
- * run — if Sally evaluates 10 claims and 2 of Mike's emails fail, Sally
451
- * sees "2 failed listeners on claim-G" rather than discovering it days
452
- * later in the email service logs.
453
- */
454
- declare function findFailedListenersForSourceRun(yDoc: Y.Doc, sourceBlockId: string, sourceRunId: string, listenerBlockIds: string[]): FailedListenerRun[];
455
- /**
456
- * Replay a previously failed listener run by re-queueing a pending
457
- * invocation with the same content. Reuses the original frozen payload
458
- * and ref snapshots from the failed run record's audit trail entry, so the
459
- * replay sees exactly the same data the original invocation saw.
460
- *
461
- * CP-2 from the plan. Used by the replay button in the failure visibility
462
- * surface. Returns true if a new pending invocation was queued.
463
- *
464
- * Note: replay does NOT re-derive the deterministic id from the original
465
- * source emission, because the original pending invocation's id is already
466
- * present (or removed) in the pendingInvocations Y.Map. Instead, replay
467
- * generates a fresh id by appending a `:replay-N` suffix to the original.
468
- * This means the replay creates a NEW pending invocation that the assignee
469
- * can act on, separate from any history of the original.
470
- */
471
- declare function replayFailedListenerRun(yDoc: Y.Doc, failedRecord: RunRecordDetails, listenerBlockId: string, originalPayload: Record<string, unknown>, originalRefSnapshots: Record<string, unknown>, assigneeDid: string): boolean;
472
-
473
- /**
474
- * The raw consumer handler bag (mantine `BlocknoteHandlers`), as visible to
475
- * action `run()` implementations via `ctx.handlers`. The real interface lives
476
- * in the mantine layer and cannot be imported here without a core→mantine
477
- * cycle, so this declares only the members actions actually call — loosely
478
- * typed, since the parameter shapes are owned by the consumer contract.
479
- *
480
- * There is deliberately NO index signature: calling an undeclared handler is a
481
- * compile error, so a renamed consumer handler surfaces here instead of
482
- * failing at runtime. Add the member when an action starts using a new
483
- * handler. Prefer `ctx.services.*` (the typed, adapted contract) over
484
- * `ctx.handlers` for new actions — this escape hatch exists for actions that
485
- * predate `buildServicesFromHandlers`.
486
- */
487
- interface ActionHandlers {
488
- askCompanion?: (prompt: string) => Promise<any>;
489
- vote?: (...args: any[]) => any;
490
- getPreProposalContractAddress?: (...args: any[]) => any;
491
- getGroupContractAddress?: (...args: any[]) => any;
492
- getProposalContractAddress?: (...args: any[]) => any;
493
- createProposal?: (...args: any[]) => any;
494
- getUserRoles?: (...args: any[]) => any;
495
- getClaimData?: (...args: any[]) => any;
496
- requestPin?: (...args: any[]) => any;
497
- signCredential?: (...args: any[]) => any;
498
- publicFileUpload?: (...args: any[]) => any;
499
- createDomain?: (...args: any[]) => any;
500
- createAddLinkedResourceMessage?: (...args: any[]) => any;
501
- executeTransaction?: (...args: any[]) => any;
502
- createGovernanceGroup?: (...args: any[]) => any;
503
- getEntityDid?: (...args: any[]) => any;
504
- getCurrentUser?: (...args: any[]) => any;
505
- createAddLinkedEntityMessage?: (...args: any[]) => any;
506
- sourceDomainSpaces?: (...args: any[]) => any;
507
- importProtocolTemplatesToSpace?: (...args: any[]) => any;
508
- integrations?: {
509
- executeTool?: (...args: any[]) => any;
510
- fetchCurrentState?: (...args: any[]) => any;
511
- getEntityDid?: (...args: any[]) => any;
512
- };
513
- }
514
- interface ActionContext {
515
- actorDid: string;
516
- flowId: string;
517
- nodeId: string;
518
- services: ActionServices;
519
- flowNode?: FlowNode;
520
- runtime?: FlowRuntimeStateManager;
521
- flowUri?: string;
522
- handlers?: ActionHandlers;
523
- editor?: IxoEditorType;
524
- pendingInvocation?: PendingInvocation;
525
- }
526
- /**
527
- * Lifecycle state of an IXO claims-module collection.
528
- *
529
- * Mirrors `ixo.claims.v1beta1.CollectionState` (the on-chain enum). Carried as
530
- * a numeric enum at this boundary so the consumer-side handler can map it
531
- * directly onto the SDK enum without a string lookup.
532
- *
533
- * - `OPEN` (0) — accepting claims/bids.
534
- * - `PAUSED` (1) — temporarily not accepting submissions.
535
- * - `CLOSED` (2) — permanently closed.
536
- */
537
- declare enum CollectionStateEnum {
538
- OPEN = 0,
539
- PAUSED = 1,
540
- CLOSED = 2
541
- }
542
- /**
543
- * A single coin amount. Mirrors `cosmos.base.v1beta1.Coin`. `amount` is the
544
- * integer base-denom amount carried as a string (no `Long`/`bigint` at this
545
- * boundary).
546
- */
547
- interface CollectionCoin {
548
- denom: string;
549
- amount: string;
550
- }
551
- /**
552
- * A CW20 token payment leg. Mirrors `ixo.claims.v1beta1.CW20Payment`.
553
- */
554
- interface CollectionCW20Payment {
555
- address: string;
556
- /** Integer amount carried as a string. */
557
- amount: string;
558
- }
559
- /**
560
- * A CW1155 contract payment leg. Mirrors `ixo.claims.v1beta1.Contract1155Payment`.
561
- */
562
- interface CollectionContract1155Payment {
563
- address: string;
564
- tokenId: string;
565
- /** Integer amount carried as a string. */
566
- amount: string;
567
- }
568
- /**
569
- * One payment leg of a collection (submission / evaluation / approval /
570
- * rejection). Mirrors `ixo.claims.v1beta1.Payment`.
571
- *
572
- * Optional/empty legs are represented by an empty `amount` array. The consumer
573
- * handler fills `account` with the collection admin address when creating.
574
- */
575
- interface CollectionPayment {
576
- /** Destination/charging account address. */
577
- account: string;
578
- /** Native-coin amounts. Empty when this leg charges nothing in native coin. */
579
- amount: CollectionCoin[];
580
- /** Optional CW20 payment legs. */
581
- cw20Payment?: CollectionCW20Payment[];
582
- /** Optional CW1155 contract payment. */
583
- contract_1155Payment?: CollectionContract1155Payment;
584
- /** Optional payment timeout in nanoseconds, carried as a string. */
585
- timeoutNs?: string;
586
- /** Whether this leg is paid by the oracle rather than the claimant. */
587
- isOraclePayment?: boolean;
588
- }
589
- /**
590
- * The four payment legs of a collection. Mirrors `ixo.claims.v1beta1.Payments`.
591
- */
592
- interface Payments {
593
- submission?: CollectionPayment;
594
- evaluation?: CollectionPayment;
595
- approval?: CollectionPayment;
596
- rejection?: CollectionPayment;
597
- }
598
- /**
599
- * Per-intent configuration for a collection. Mirrors the
600
- * `ixo.claims.v1beta1.CollectionIntentOptions` shape — controls whether/how
601
- * claimants can declare an intent before submitting.
602
- */
603
- interface CollectionIntentOptions {
604
- /** Whether intents are enabled on this collection. */
605
- allowed?: boolean;
606
- /** Optional intent timeout in nanoseconds, carried as a string. */
607
- timeoutNs?: string;
608
- /** Optional per-intent payment override. */
609
- payment?: CollectionPayment;
610
- }
611
- /**
612
- * Parameters for creating a collection (`MsgCreateCollection`).
613
- *
614
- * `entity` and `protocol` are template configuration; the consumer resolves the
615
- * `signer`/admin from its own wallet context, so it is not part of this
616
- * boundary. `quota` is carried as a string (`0` = unlimited).
617
- */
618
- interface CollectionCreateParams {
619
- /** Entity (deed) DID the collection belongs to. */
620
- entity: string;
621
- /** Protocol DID/id the collection follows. */
622
- protocol: string;
623
- /** Initial lifecycle state. Defaults to OPEN if omitted by the consumer. */
624
- state?: CollectionStateEnum;
625
- /** ISO-8601 start date. */
626
- startDate?: string;
627
- /** ISO-8601 end date. */
628
- endDate?: string;
629
- /** Max number of claims; `0` = unlimited. Carried as a string. */
630
- quota?: string;
631
- /** Payment configuration for the four claim legs. */
632
- payments?: Payments;
633
- /** Intent configuration. */
634
- intents?: CollectionIntentOptions;
635
- }
636
- /**
637
- * The full, canonical on-chain state of a collection, returned by every
638
- * `collection.*` operation (read or write) and stored verbatim as
639
- * `runtime.output`. It is never a delta — see IXO-2573: `output` always holds
640
- * the latest full on-chain collection state.
641
- *
642
- * Field names mirror `ixo.claims.v1beta1.Collection`. Numeric chain types
643
- * (`Long`/uint64) are carried as strings; `state` is the numeric enum.
644
- */
645
- interface CollectionState {
646
- /** Collection identifier (the chain-assigned id). */
647
- collectionId: string;
648
- /** Entity (deed) DID the collection belongs to. */
649
- entity: string;
650
- /** Protocol DID/id the collection follows. */
651
- protocol: string;
652
- /** Admin address authorised to mutate the collection. */
653
- admin?: string;
654
- /** Current lifecycle state. */
655
- state: CollectionStateEnum;
656
- /** ISO-8601 start date, if set. */
657
- startDate?: string;
658
- /** ISO-8601 end date, if set. */
659
- endDate?: string;
660
- /** Max number of claims; `0` = unlimited. Carried as a string. */
661
- quota: string;
662
- /** Number of claims submitted so far. Carried as a string. */
663
- count: string;
664
- /** Number of claims evaluated so far. Carried as a string. */
665
- evaluated?: string;
666
- /** Number of approved claims. Carried as a string. */
667
- approved?: string;
668
- /** Number of rejected claims. Carried as a string. */
669
- rejected?: string;
670
- /** Number of disputed claims. Carried as a string. */
671
- disputed?: string;
672
- /** Payment configuration for the four claim legs. */
673
- payments?: Payments;
674
- /** Intent configuration. */
675
- intents?: CollectionIntentOptions;
676
- }
677
- /**
678
- * Role a grantee holds on a claim collection. Drives which custom claims-module
679
- * authorization is granted: `submit` → `SubmitClaimAuthorization`,
680
- * `evaluate` → `EvaluateClaimAuthorization` (each carries `[]constraints`, one
681
- * per collection). See IXO-2586.
682
- */
683
- type CollectionUserRole = 'submit' | 'evaluate';
684
- /**
685
- * One per-collection authorization constraint held by a grantee for a role.
686
- * Carries the LIVE (decremented) limits as read back from chain — the revoke
687
- * read-modify-write must preserve these verbatim (IXO-2590), so re-granting
688
- * from a template would wrongly reset spent quota.
689
- */
690
- interface CollectionGrantee {
691
- /** Grantee bech32 address. */
692
- address: string;
693
- /** Optional resolved DID (display / audit). */
694
- did?: string;
695
- /** Role this grant confers. */
696
- role: CollectionUserRole;
697
- /** Remaining agent quota; `0` = unlimited. Carried as a string. */
698
- agentQuota?: string;
699
- /** Per-claim max amount cap (evaluate role). */
700
- maxAmount?: CollectionCoin[];
701
- /** Intent duration in nanoseconds, carried as a string. */
702
- intentDurationNs?: string;
703
- }
704
- /**
705
- * A member enumerated from a group account, used for grant fan-out. Mirrors the
706
- * `PODMember` shape produced by the `pod/memberMultiSelect` enumeration
707
- * (abstracts cw4 members / token-staking stakers / nft-staking / multisig
708
- * signers).
709
- */
710
- interface CollectionMember {
711
- address: string;
712
- did?: string;
713
- role?: string;
714
- votingPower?: number;
715
- }
716
- /**
717
- * DAO DAO classification of an address. On IXO both user accounts and CosmWasm
718
- * contracts share the `ixo1…` prefix, so classification is layered: bech32
719
- * byte-length heuristic → Wasm `ContractInfo` query → cw2 `{ "info": {} }`
720
- * smart query (IXO-2592).
721
- */
722
- interface AddressClassification {
723
- /** `user` = plain account; `contract` = CosmWasm contract / module account. */
724
- kind: 'user' | 'contract';
725
- /** Present when `kind === 'contract'` and cw2 info resolved a DAO DAO group type. */
726
- daodao?: {
727
- /** cw2 contract name family, e.g. `dao-dao-core`, `cw4-group`, `dao-voting-cw4`. */
728
- type: string;
729
- /** Whether the contract can itself exercise a granted authz (only dao-core can MsgExec). */
730
- canExerciseGrant: boolean;
731
- };
732
- }
733
- /**
734
- * Provenance/identity of a carbon batch (= a CARBON token group; the batch id
735
- * is the on-chain token id). `entityDid` + `adminAddress` identify the entity
736
- * admin account the batch was minted from — both are REQUIRED to construct a
737
- * harvest (the authz grant + exec transfer target that account). The host
738
- * `loadBatches` handler performs provenance recovery for transferred batches so
739
- * these are populated before the editor ever sees them. See the carbon-credit
740
- * technical doc §4–§5 (IXO-2675).
741
- */
742
- interface CarbonBatchRef {
743
- /** Token/batch id. */
744
- id: string;
745
- /** Minter entity DID. */
746
- entityDid: string;
747
- /** Entity admin account address (the FROM account for a harvest transfer). */
748
- adminAddress: string;
749
- /** Human-readable entity name, for display. */
750
- alsoKnownAs?: string;
751
- }
752
- /**
753
- * A harvestable batch: held on an entity admin account the user owns but not
754
- * yet pulled into their wallet. `claimable` = the admin-held amount that
755
- * becomes the user's on harvest.
756
- */
757
- interface CarbonHarvestableBatch extends CarbonBatchRef {
758
- /** Harvestable amount (admin-held; becomes user `amount` after harvest). */
759
- claimable: number;
760
- }
761
- /**
762
- * A retireable batch: credits the user already holds in their wallet and can
763
- * burn/offset. `entityDid` is best-effort (display/provenance) and not required
764
- * to retire — retirement is a single owner-signed message.
765
- */
766
- interface CarbonRetireableBatch {
767
- /** Token/batch id. */
768
- id: string;
769
- /** Amount available in the user's wallet to retire. */
770
- amount: number;
771
- /** Minter entity DID, when known. */
772
- entityDid?: string;
773
- /** Human-readable entity name, for display. */
774
- alsoKnownAs?: string;
775
- }
776
- interface HttpService {
777
- request: (params: {
778
- url: string;
779
- method: string;
780
- headers?: Record<string, string>;
781
- body?: any;
782
- }) => Promise<{
783
- status: number;
784
- headers: Record<string, string>;
785
- data: any;
786
- }>;
787
- }
788
- interface EmailService {
789
- send: (params: {
790
- to: string;
791
- subject: string;
792
- template: string;
793
- templateVersion?: string;
794
- variables?: Record<string, any>;
795
- cc?: string;
796
- bcc?: string;
797
- replyTo?: string;
798
- }) => Promise<{
799
- messageId: string;
800
- sentAt: string;
801
- }>;
802
- }
803
- interface NotifyService {
804
- send: (params: {
805
- channel: string;
806
- to: string[];
807
- cc?: string[];
808
- bcc?: string[];
809
- subject?: string;
810
- body?: string;
811
- bodyType?: 'text' | 'html';
812
- from?: string;
813
- replyTo?: string;
814
- }) => Promise<{
815
- messageId: string;
816
- sentAt: string;
817
- }>;
818
- }
819
- interface BidService {
820
- submitBid: (params: {
821
- collectionId: string;
822
- role: string;
823
- surveyAnswers: Record<string, any>;
824
- entityDid?: string;
825
- onBehalfOfAddress?: string;
826
- }) => Promise<any>;
827
- approveBid: (params: {
828
- bidId: string;
829
- collectionId: string;
830
- did: string;
831
- entityDid?: string;
832
- }) => Promise<any>;
833
- rejectBid: (params: {
834
- bidId: string;
835
- collectionId: string;
836
- did: string;
837
- reason: string;
838
- entityDid?: string;
839
- }) => Promise<any>;
840
- approveServiceAgentApplication: (params: {
841
- adminAddress: string;
842
- collectionId: string;
843
- agentQuota: number;
844
- deedDid: string;
845
- currentUserAddress: string;
846
- }) => Promise<void>;
847
- approveEvaluatorApplication: (params: {
848
- adminAddress: string;
849
- collectionId: string;
850
- deedDid: string;
851
- evaluatorAddress: string;
852
- agentQuota?: number;
853
- claimIds?: string[];
854
- maxAmounts?: Array<{
855
- denom: string;
856
- amount: string;
857
- }>;
858
- }) => Promise<void>;
859
- }
860
- interface ClaimService {
861
- requestPin: (config?: {
862
- title?: string;
863
- description?: string;
864
- submitText?: string;
865
- }) => Promise<string>;
866
- submitClaim: (params: {
867
- surveyData: any;
868
- deedDid: string;
869
- collectionId: string;
870
- adminAddress: string;
871
- pin: string;
872
- entityDid?: string;
873
- }) => Promise<{
874
- transactionHash: string;
875
- claimId: string;
876
- }>;
877
- evaluateClaim: (granteeAddress: string, did: string, payload: {
878
- claimId: string;
879
- collectionId: string;
880
- adminAddress: string;
881
- status?: number;
882
- verificationProof: string;
883
- amount?: {
884
- denom: string;
885
- amount: string;
886
- };
887
- }) => Promise<{
888
- code: number;
889
- transactionHash: string;
890
- rawLog?: string;
891
- height?: number;
892
- txIndex?: number;
893
- gasWanted?: bigint;
894
- gasUsed?: bigint;
895
- }>;
896
- disputeClaim?: (granteeAddress: string, did: string, payload: {
897
- subjectId: string;
898
- disputeType: number;
899
- reason: string;
900
- }) => Promise<any>;
901
- getCurrentUser: () => {
902
- address: string;
903
- did?: string;
904
- };
905
- createUdid?: (params: any) => Promise<any>;
906
- }
907
- /**
908
- * Claims-module collection lifecycle service. The editor declares the
909
- * contract only; the consumer app implements each method (broadcast on chain,
910
- * resolve admin from its wallet context, map string<->Long).
911
- *
912
- * Per IXO-2573, each write op should broadcast then the dispatcher re-fetches
913
- * via `get(...)` so `runtime.output` always holds the latest full
914
- * `CollectionState`. `get` is the read-only `refresh` primitive.
915
- */
916
- interface CollectionService {
917
- /** Read the full current on-chain state of a collection. */
918
- get: (params: {
919
- collectionId: string;
920
- }) => Promise<CollectionState>;
921
- /** Broadcast `MsgCreateCollection`. Returns the new collectionId + tx hash. */
922
- create: (params: CollectionCreateParams) => Promise<{
923
- transactionHash: string;
924
- collectionId: string;
925
- }>;
926
- /** Broadcast `MsgUpdateCollectionState`. */
927
- updateState: (params: {
928
- collectionId: string;
929
- state: CollectionStateEnum;
930
- adminAddress: string;
931
- }) => Promise<{
932
- transactionHash: string;
933
- }>;
934
- /** Broadcast `MsgUpdateCollectionDates`. */
935
- updateDates: (params: {
936
- collectionId: string;
937
- startDate?: string;
938
- endDate?: string;
939
- adminAddress: string;
940
- }) => Promise<{
941
- transactionHash: string;
942
- }>;
943
- /** Broadcast `MsgUpdateCollectionQuota`. `quota` carried as a string; `0` = unlimited. */
944
- updateQuota: (params: {
945
- collectionId: string;
946
- quota: string;
947
- adminAddress: string;
948
- }) => Promise<{
949
- transactionHash: string;
950
- }>;
951
- /** Broadcast `MsgUpdateCollectionPayments`. */
952
- updatePayments: (params: {
953
- collectionId: string;
954
- payments: Payments;
955
- adminAddress: string;
956
- }) => Promise<{
957
- transactionHash: string;
958
- }>;
959
- /** Broadcast `MsgUpdateCollectionIntents`. */
960
- updateIntents: (params: {
961
- collectionId: string;
962
- intents: CollectionIntentOptions;
963
- adminAddress: string;
964
- }) => Promise<{
965
- transactionHash: string;
966
- }>;
967
- }
968
- /**
969
- * Claim-collection user-management service (IXO-2586). The editor declares the
970
- * contract only; the consumer app implements each method (build/broadcast the
971
- * claims-module authz messages, query authz grants, classify addresses,
972
- * enumerate group members). Extends → replaces the reactive `bid` service.
973
- */
974
- interface CollectionUsersService {
975
- /**
976
- * Grant submit/evaluate authz for ONE collection to a grantee. The handler
977
- * reads the grantee's existing authz for the role's msgTypeUrl and APPENDS a
978
- * per-collection constraint (preserving other collections' live values),
979
- * then broadcasts `MsgCreateClaimAuthorization` routed via
980
- * `MsgGrantEntityAccountAuthz` (entity admin = granter). See IXO-2589.
981
- */
982
- grant: (params: {
983
- granterAdminAddress: string;
984
- granteeAddress: string;
985
- collectionId: string;
986
- role: CollectionUserRole;
987
- agentQuota?: string;
988
- maxAmount?: CollectionCoin[];
989
- intentDurationNs?: string;
990
- deedDid?: string;
991
- }) => Promise<{
992
- transactionHash: string;
993
- }>;
994
- /**
995
- * Per-collection read-modify-write revoke (IXO-2590). Reads the grantee's
996
- * live authz, drops the target collection's constraint, and — when other
997
- * constraints remain — broadcasts a single atomic tx ordered
998
- * `[MsgRevokeEntityAccountAuthz, then one MsgCreateClaimAuthorization per
999
- * remaining constraint]`, preserving each remaining constraint's live
1000
- * (decremented) quota/limits. Short-circuits to a plain revoke when the
1001
- * target was the only constraint.
1002
- */
1003
- revoke: (params: {
1004
- granterAdminAddress: string;
1005
- granteeAddress: string;
1006
- collectionId: string;
1007
- role: CollectionUserRole;
1008
- }) => Promise<{
1009
- transactionHash: string;
1010
- }>;
1011
- /**
1012
- * List the grantees holding a submit/evaluate constraint for a collection.
1013
- * Queries authz grants against the entity admin account, decodes the
1014
- * authorizations, and filters constraints by `collectionId` (IXO-2591).
1015
- */
1016
- list: (params: {
1017
- granterAdminAddress: string;
1018
- collectionId: string;
1019
- }) => Promise<{
1020
- grantees: CollectionGrantee[];
1021
- }>;
1022
- /** Classify an address as a plain user vs a DAO DAO contract (IXO-2592). */
1023
- classifyAddress: (params: {
1024
- address: string;
1025
- }) => Promise<AddressClassification>;
1026
- /** Enumerate the members of a group account for grant fan-out (IXO-2592). */
1027
- enumerateMembers: (params: {
1028
- groupAddress: string;
1029
- }) => Promise<{
1030
- members: CollectionMember[];
1031
- }>;
1032
- }
1033
- interface MatrixCredentialService {
1034
- storeCredential: (params: {
1035
- roomId: string;
1036
- credentialKey: string;
1037
- credential: Record<string, any>;
1038
- cid: string;
1039
- }) => Promise<{
1040
- storedAt: string;
1041
- duplicate: boolean;
1042
- }>;
1043
- }
1044
- /** Result of any integration tool execution (direct or via a binding). */
1045
- interface IntegrationExecuteOutcome {
1046
- successful: boolean;
1047
- data?: Record<string, unknown>;
1048
- error?: string;
1049
- code?: 'OK' | 'VALIDATION' | 'AUTH_EXPIRED' | 'UPSTREAM_4XX' | 'UPSTREAM_5XX' | 'RATE_LIMIT' | 'UNKNOWN';
1050
- }
1051
- interface IntegrationsService {
1052
- executeTool: (args: {
1053
- toolSlug: string;
1054
- connectedAccountId: string;
1055
- arguments: Record<string, unknown>;
1056
- }) => Promise<IntegrationExecuteOutcome>;
1057
- fetchCurrentState?: (args: {
1058
- toolSlug: string;
1059
- connectedAccountId: string;
1060
- arguments: Record<string, unknown>;
1061
- }) => Promise<Record<string, unknown>>;
1062
- getEntityDid?: () => string | undefined;
1063
- /**
1064
- * Execute a tool on the template author's behalf via an opaque, server-side
1065
- * binding (delegated blocks). The runner never holds the author's
1066
- * credential — `bindingId` selects it on the worker. Returns the same
1067
- * outcome shape as `executeTool`.
1068
- */
1069
- executeBinding?: (args: {
1070
- bindingId: string;
1071
- toolSlug: string;
1072
- arguments: Record<string, unknown>;
1073
- }) => Promise<IntegrationExecuteOutcome>;
1074
- }
1075
- interface OracleService {
1076
- generateWallet: () => Promise<{
1077
- address: string;
1078
- did: string;
1079
- pubKey: string;
1080
- mnemonic: string;
1081
- }>;
1082
- fundWallet: (params: {
1083
- address: string;
1084
- amount: number;
1085
- }) => Promise<{
1086
- transactionHash: string;
1087
- }>;
1088
- createIidDocument: (params: {
1089
- mnemonic: string;
1090
- did: string;
1091
- address: string;
1092
- pubKey: string;
1093
- }) => Promise<{
1094
- did: string;
1095
- transactionHash: string;
1096
- }>;
1097
- registerMatrixAccount: (params: {
1098
- mnemonic: string;
1099
- address: string;
1100
- did: string;
1101
- pin: string;
1102
- oracleName: string;
1103
- avatarUrl?: string;
1104
- }) => Promise<{
1105
- matrixUserId: string;
1106
- matrixAccessToken: string;
1107
- matrixRoomId: string;
1108
- matrixDeviceId: string;
1109
- matrixMnemonic: string;
1110
- matrixPassword: string;
1111
- matrixRecoveryPhrase: string;
1112
- matrixHomeServerUrl: string;
1113
- }>;
1114
- createOracleEntity: (params: {
1115
- mnemonic: string;
1116
- address: string;
1117
- did: string;
1118
- pubKey: string;
1119
- pin: string;
1120
- matrixAccessToken: string;
1121
- matrixRoomId: string;
1122
- oracleName: string;
1123
- orgName: string;
1124
- description: string;
1125
- location: string;
1126
- logoUrl: string;
1127
- coverImageUrl: string;
1128
- apiUrl: string;
1129
- price: number;
1130
- llmModel: string;
1131
- opening?: string;
1132
- communicationStyle?: string;
1133
- capabilities?: string;
1134
- mcpConfig?: any;
1135
- parentProtocol?: string;
1136
- }) => Promise<{
1137
- entityDid: string;
1138
- transactionHash: string;
1139
- /** Multibase-encoded P-256 public key registered as a keyAgreement vm on the oracle entity DID. */
1140
- encryptionPublicKeyMultibase: string;
1141
- /** DID verification method id of the P-256 keyAgreement key. */
1142
- encryptionVerificationMethodId: string;
1143
- }>;
1144
- /**
1145
- * Contract the oracle: ensure the user↔oracle Matrix DM room exists and
1146
- * the user has joined it. Pure Matrix work — no chain calls, no key setup.
1147
- * Returns the user↔oracle room id which downstream steps (storeSecrets,
1148
- * storeConfig) write into.
1149
- */
1150
- contract: (params: {
1151
- oracleEntityDid: string;
1152
- }) => Promise<{
1153
- userOracleRoomId: string;
1154
- userOracleRoomAlias: string;
1155
- }>;
1156
- provisionSandbox: (params: {
1157
- entityDid: string;
1158
- matrixRoomId: string;
1159
- }) => Promise<{
1160
- sandboxUrl: string;
1161
- status: string;
1162
- }>;
1163
- storeSecrets: (params: {
1164
- matrixRoomId: string;
1165
- publicKeyMultibase: string;
1166
- verificationMethodId: string;
1167
- matrixHomeServerUrl: string;
1168
- matrixUsername: string;
1169
- matrixPassword: string;
1170
- secrets: Record<string, string>;
1171
- preEncryptedSecrets?: Record<string, string>;
1172
- }) => Promise<{
1173
- storedSecrets: string[];
1174
- roomId: string;
1175
- freshAccessToken?: string;
1176
- }>;
1177
- /** JWE-encrypts a single plaintext value to the oracle's P-256 public key (multibase).
1178
- * Used by storeSecrets FlowDetail to encrypt user-typed OpenRouter key at-rest. */
1179
- encryptForOracle: (params: {
1180
- plaintext: string;
1181
- publicKeyMultibase: string;
1182
- }) => Promise<{
1183
- jwe: string;
1184
- }>;
1185
- /** Reads `ixo.room.secret.index` state events from the matrix room and returns the
1186
- * list of secret names already stored. Used for idempotency checks. */
1187
- readStoredSecrets: (params: {
1188
- matrixRoomId: string;
1189
- }) => Promise<{
1190
- secretNames: string[];
1191
- }>;
1192
- /** Returns the network-derived .env constants (RPC URL, matrix homeserver, etc.)
1193
- * for the consumer's currently configured network. Used by the storeSecrets
1194
- * FlowDetail's "Additional Configuration" display section, and merged into the
1195
- * storeConfig state event by the consumer handler. Must be deterministic per network. */
1196
- getNetworkConstants: (params: {
1197
- oracleName: string;
1198
- }) => Promise<{
1199
- constants: Record<string, string>;
1200
- }>;
1201
- validateMcpServer: (params: {
1202
- url: string;
1203
- authType?: 'bearer' | 'api-key' | 'none';
1204
- authToken?: string;
1205
- }) => Promise<{
1206
- success: boolean;
1207
- tools?: Array<{
1208
- name: string;
1209
- description?: string;
1210
- }>;
1211
- error?: string;
1212
- }>;
1213
- storeConfig: (params: {
1214
- matrixRoomId: string;
1215
- config: {
1216
- oracleName: string;
1217
- orgName: string;
1218
- description: string;
1219
- location: string;
1220
- price: number;
1221
- apiUrl: string;
1222
- entityDid: string;
1223
- logoUrl: string;
1224
- llmModel: string;
1225
- opening?: string;
1226
- communicationStyle?: string;
1227
- capabilities?: string;
1228
- skills?: string[];
1229
- mcpServers?: Array<{
1230
- name: string;
1231
- url: string;
1232
- description?: string;
1233
- authEnvVar?: string;
1234
- }>;
1235
- matrixUserId?: string;
1236
- matrixAccountRoomId?: string;
1237
- oracleAddress?: string;
1238
- oracleDid?: string;
1239
- };
1240
- }) => Promise<{
1241
- configStored: boolean;
1242
- roomId: string;
1243
- }>;
1244
- deploySetup: (params: {
1245
- name: string;
1246
- config: Record<string, any>;
1247
- roomId: string;
1248
- secrets?: Record<string, string>;
1249
- }) => Promise<{
1250
- setupComplete: boolean;
1251
- stdout?: string;
1252
- stderr?: string;
1253
- }>;
1254
- deployStart: (params: {
1255
- name: string;
1256
- entityDid: string;
1257
- roomId: string;
1258
- secrets?: Record<string, string>;
1259
- }) => Promise<{
1260
- processId: string;
1261
- status: string;
1262
- url?: string;
1263
- }>;
1264
- updateOracleDomain: (params: {
1265
- entityDid: string;
1266
- newApiUrl: string;
1267
- }) => Promise<{
1268
- transactionHash: string;
1269
- }>;
1270
- }
1271
- /**
1272
- * Carbon credit batch service (IXO-2675). The editor declares the contract
1273
- * only; the consumer app implements each method (run the owner/admin
1274
- * reconciliation read, build + broadcast the harvest grant/exec pair and the
1275
- * retire message, sign via its own wallet/SignX). Both writes are USER-signed
1276
- * — the editor never signs on the user's behalf.
1277
- */
1278
- interface CarbonService {
1279
- /**
1280
- * Reconcile the user's owner-side and entity-admin-side batches into the
1281
- * unified view. Pure read (no signing). Performs provenance recovery for
1282
- * transferred batches so every `harvestableBatch` carries `entityDid` +
1283
- * `adminAddress`. See technical doc §3–§4.
1284
- */
1285
- loadBatches: (params: {
1286
- ownerAddress: string;
1287
- }) => Promise<{
1288
- harvestableBatches: CarbonHarvestableBatch[];
1289
- retireableBatches: CarbonRetireableBatch[];
1290
- totalClaimable: number;
1291
- totalAvailable: number;
1292
- totalRetired: number;
1293
- }>;
1294
- /**
1295
- * Harvest (claim) the given batches: per entity, grant the owner authz to
1296
- * transfer out of the entity admin account, then exec that transfer into
1297
- * the owner's wallet (ordered pairs, 30-min grant). User-signed. See §5.2.
1298
- */
1299
- harvest: (params: {
1300
- ownerAddress: string;
1301
- tokens: Array<{
1302
- id: string;
1303
- entityDid: string;
1304
- adminAddress: string;
1305
- claimable: number;
1306
- }>;
1307
- }) => Promise<{
1308
- transactionHash: string;
1309
- harvestedBatchIds: string[];
1310
- harvestedAmount: number;
1311
- }>;
1312
- /**
1313
- * Retire (burn/offset) the given amounts from the owner's wallet. Single
1314
- * owner-signed `MsgRetireToken`. Irreversible. `jurisdiction` arrives
1315
- * pre-composed as a string (default "Global"); `reason` defaults to
1316
- * "offset". See §5.1.
1317
- */
1318
- retire: (params: {
1319
- owner: string;
1320
- reason?: string;
1321
- jurisdiction?: string;
1322
- tokens: Array<{
1323
- id: string;
1324
- amount: number;
1325
- }>;
1326
- }) => Promise<{
1327
- transactionHash: string;
1328
- retiredBatchIds: string[];
1329
- retiredAmount: number;
1330
- }>;
1331
- }
1332
- /**
1333
- * Entity (domain) ownership service (IXO-2696). The editor declares the
1334
- * contract only; the consumer app implements `transfer` — resolve a group
1335
- * recipient to its DAO controller, ensure the recipient has an IID document,
1336
- * build + broadcast `MsgTransferEntity`, and sign via its own wallet/SignX.
1337
- * USER-signed and IRREVERSIBLE — the editor never signs on the user's behalf.
1338
- */
1339
- interface EntityService {
1340
- /**
1341
- * Transfer ownership of `entityDid` to `recipientDid`. The consumer resolves
1342
- * a `did:ixo:entity:` group recipient to its `did:ixo:wasm:` controller
1343
- * (reported back as `recipientResolved` when changed) and creates the
1344
- * recipient's IID document first if it is missing (`createdRecipientIid`).
1345
- * `ownerDid`/`ownerAddress` default to the connected user inside the host.
1346
- * Proof of a real transfer is the returned `transactionHash`.
1347
- */
1348
- transfer: (params: {
1349
- entityDid: string;
1350
- recipientDid: string;
1351
- ownerDid?: string;
1352
- ownerAddress?: string;
1353
- }) => Promise<{
1354
- transactionHash: string;
1355
- recipientResolved?: string;
1356
- createdRecipientIid?: boolean;
1357
- }>;
1358
- }
1359
- /**
1360
- * KYC verification service (qi/kyc.verify). The editor declares the contract
1361
- * only; the consumer app implements each method against its KYC server
1362
- * (create/read the ComplyCube evaluation, mint the hosted verification URL,
1363
- * persist the SD-JWT credential to the user's Matrix vault). The server's
1364
- * status is the single source of truth for the lifecycle
1365
- * (`verify → review → clear → issuing → issued → complete`, failure states
1366
- * `rejected|attention|error`, plus `unknown`) — the editor only polls it.
1367
- *
1368
- * PII boundary: survey answers flow INTO `initiate` but never back out —
1369
- * action outputs carry only `credentialCid`, `credentialType`, `protocolId`,
1370
- * and `status`.
1371
- */
1372
- interface KycService {
1373
- /**
1374
- * Load the KYC protocol's details form + the user's current server-side
1375
- * state. `credentialType` is the vault index key of the credential this
1376
- * protocol issues (e.g. 'kycamllevel1' | 'kycamllevel2'); hosts default it
1377
- * to level 1 when omitted — `hasExistingCredential` refers to THAT type
1378
- * only, so a level-2 flow is never satisfied by a level-1 credential.
1379
- */
1380
- loadForm(params: {
1381
- protocolDid: string;
1382
- credentialType?: string;
1383
- }): Promise<{
1384
- protocolId: string;
1385
- claimCollectionId?: string;
1386
- deedOfferId?: string;
1387
- surveyJson: Record<string, unknown>;
1388
- hasExistingCredential: boolean;
1389
- /** Non-PII metadata of matching Vault credentials, oldest first. */
1390
- existingCredentials?: Array<{
1391
- cid: string;
1392
- credentialType: string;
1393
- storedAt?: string;
1394
- issuerDid?: string;
1395
- }>;
1396
- status: string;
1397
- }>;
1398
- /** Submit the details form; the server creates the ComplyCube evaluation. */
1399
- initiate(params: {
1400
- protocolId: string;
1401
- claimCollectionId?: string;
1402
- deedOfferId?: string;
1403
- data: Record<string, unknown>;
1404
- }): Promise<{
1405
- status: string;
1406
- }>;
1407
- /** Mint the hosted-webview verification URL for the user's evaluation. */
1408
- getVerificationUrl(params: {
1409
- protocolId: string;
1410
- }): Promise<{
1411
- url: string;
1412
- }>;
1413
- /** Read the current server-side lifecycle status. */
1414
- getStatus(params: {
1415
- protocolId: string;
1416
- }): Promise<{
1417
- status: string;
1418
- }>;
1419
- /**
1420
- * Save the issued SD-JWT credential to the user's Matrix vault room and
1421
- * move the server status to `complete`. Idempotent — re-saving an
1422
- * already-saved credential of the same `credentialType` returns the
1423
- * existing CID (defaults to level 1 when omitted).
1424
- */
1425
- saveCredential(params: {
1426
- protocolId: string;
1427
- credentialType?: string;
1428
- credentialCid?: string;
1429
- }): Promise<{
1430
- credentialCid: string;
1431
- credentialType: string;
1432
- }>;
1433
- }
1434
- interface BlueprintService {
1435
- execute(params: {
1436
- action: string;
1437
- inputs: Record<string, unknown>;
1438
- actorDid: string;
1439
- flowId: string;
1440
- nodeId: string;
1441
- }): Promise<{
1442
- receiptRef: string;
1443
- result?: Record<string, unknown>;
1444
- }>;
1445
- }
1446
- /**
1447
- * The full service contract an action execution context can carry. Composed
1448
- * from the per-domain service interfaces above so consumers can implement and
1449
- * type one domain at a time; the runtime shape is unchanged.
1450
- */
1451
- interface ActionServices {
1452
- blueprint?: BlueprintService;
1453
- http?: HttpService;
1454
- email?: EmailService;
1455
- notify?: NotifyService;
1456
- bid?: BidService;
1457
- claim?: ClaimService;
1458
- collection?: CollectionService;
1459
- collectionUsers?: CollectionUsersService;
1460
- matrix?: MatrixCredentialService;
1461
- integrations?: IntegrationsService;
1462
- oracle?: OracleService;
1463
- carbon?: CarbonService;
1464
- entity?: EntityService;
1465
- kyc?: KycService;
1466
- }
1467
- interface OutputSchemaField {
1468
- path: string;
1469
- displayName: string;
1470
- type: 'string' | 'number' | 'boolean' | 'object' | 'array';
1471
- description?: string;
1472
- /**
1473
- * For `type === 'array'`: the shape of each element. Drives item-scoped
1474
- * reference pickers (e.g. the Xero invoice LineItems iterative mapper,
1475
- * where each cell refs into `{{item.<field>}}`).
1476
- */
1477
- itemSchema?: OutputSchemaField[];
1478
- }
1479
- /**
1480
- * A typed event that an action can emit when it runs.
1481
- *
1482
- * Events drive the trigger/listener model: another block can declare a
1483
- * `block.event` trigger on a (sourceBlockId, eventName) pair, and when this
1484
- * action emits a matching event, a pending invocation is queued on the
1485
- * listener block. See `docs/flow-engine/events-and-triggers-plan.md` for the full model.
1486
- */
1487
- interface ActionEventDefinition {
1488
- /** Stable identifier — used in trigger declarations and ref strings. */
1489
- name: string;
1490
- /** Human-readable label shown in the trigger picker UI. */
1491
- displayName: string;
1492
- /** Short description shown as inline hint in the trigger picker. */
1493
- description: string;
1494
- /** Schema of the event payload. Same shape as `outputSchema`. */
1495
- payloadSchema: OutputSchemaField[];
1496
- /**
1497
- * Field paths from `payloadSchema` (in order) shown inline in the
1498
- * pending-invocation list so the assignee can distinguish queued
1499
- * invocations at a glance. E.g. `['claimId', 'evaluatedAt']`.
1500
- */
1501
- pendingDisplayFields?: string[];
1502
- }
1503
- /**
1504
- * Declares what counts as proof that this action's side effect actually
1505
- * happened. Enforced centrally by `executeActionBlock`: a run that returns
1506
- * success without satisfying its proof declaration is recorded as
1507
- * `state: 'failed'` (code `PROOF_MISSING`), never as `completed`.
1508
- *
1509
- * - `{ fields }` — at least one of the listed output paths (dot notation
1510
- * allowed) must be truthy. Empty arrays and `false` do not count.
1511
- * - `{ validate }` — custom predicate over the raw output.
1512
- * - `'none'` — explicit opt-out for actions with no side effect to prove
1513
- * (pure selection/config actions). Must be stated, not omitted.
1514
- */
1515
- type ActionProofDeclaration = {
1516
- fields: string[];
1517
- } | {
1518
- validate: (output: Record<string, unknown>) => boolean;
1519
- } | 'none';
1520
- interface ActionDefinition<TInputs extends Record<string, any> = Record<string, any>> {
1521
- type: string;
1522
- /** UCAN-style ability string used by the flow compiler, e.g., "bid/submit". */
1523
- can?: string;
1524
- sideEffect: boolean;
1525
- defaultRequiresConfirmation: boolean;
1526
- requiredCapability?: string;
1527
- /**
1528
- * Who performs the execution once inputs are complete.
1529
- *
1530
- * - 'agent' (the default) — a headless orchestrator may run `run()` itself
1531
- * or delegate it to a capable oracle.
1532
- * - 'human' — only a human surface (Portal FlowDetail) may execute: the
1533
- * side effect needs an authority the orchestrator does not hold, e.g. a
1534
- * chain transaction signed as the entity admin. Orchestrators still
1535
- * gather inputs and notify the human, but must never run or delegate
1536
- * the action themselves.
1537
- */
1538
- executionOwner?: 'agent' | 'human';
1539
- /** Proof-of-execution declaration. See {@link ActionProofDeclaration}. */
1540
- proof: ActionProofDeclaration;
1541
- /**
1542
- * How many times this action is meant to run within a single flow.
1543
- *
1544
- * - 'once' (the default) — a one-shot step that reaches a terminal
1545
- * `completed` state and is then Done.
1546
- * - 'many' — a standing, repeatable capability that can fire any number of
1547
- * times on a cadence the flow (not the action) decides — e.g. submitting a
1548
- * claim every month. A repeatable block never latches to a terminal Done:
1549
- * a `completed` runtime entry means "has fired at least once", and its real
1550
- * progress is the count of successful runs in the audit trail, not this
1551
- * single summary entry. Such blocks never withhold the flow.
1552
- */
1553
- cardinality?: 'once' | 'many';
1554
- /**
1555
- * How dynamic resolver results combine with the static `events` /
1556
- * `outputSchema` baselines. 'merge' (the default) dedupes by event name /
1557
- * field path with the dynamic entry winning; 'replace' hands the resolver
1558
- * full control of the vocabulary (needed e.g. to hide the baseline until
1559
- * configuration is complete).
1560
- */
1561
- dynamicResolutionMode?: 'merge' | 'replace';
1562
- inputSchema?: object;
1563
- /**
1564
- * Machine-readable mirror of the required-input preamble in `run()`: given a
1565
- * fully-merged inputs object, returns the names of inputs still missing or
1566
- * blank (empty array = ready to execute). External orchestrators call this
1567
- * via `getMissingActionInputs` BEFORE queuing execution so a missing input
1568
- * becomes a prompt to a human rather than a failed run.
1569
- *
1570
- * Only define this when requiredness is conditional — it branches on other
1571
- * inputs (skip flags, group types, either-of-two-fields) and therefore
1572
- * cannot be derived from `inputSchema.required`, which is the default
1573
- * derivation. Keep it directly above `run()` and keep the two in lockstep:
1574
- * every presence throw in `run()` must be predicted here. Presence only —
1575
- * value validity (ranges, formats, duplicates) stays in `run()`.
1576
- */
1577
- getMissingInputs?: (inputs: TInputs) => string[];
1578
- /** Static output schema for action types with predictable output (e.g. email.send).
1579
- * For action types with dynamic output (e.g. http.request), the schema is user-defined in inputs. */
1580
- outputSchema?: OutputSchemaField[];
1581
- /**
1582
- * Typed vocabulary of events this action can emit. Drives the trigger
1583
- * picker UI and compile-time validation of `block.event` triggers.
1584
- */
1585
- events?: ActionEventDefinition[];
1586
- /**
1587
- * Optional per-block event resolver. Called with the block's current
1588
- * template inputs; returns the event vocabulary that applies to this
1589
- * specific block.
1590
- *
1591
- * Use this when the event schema depends on configuration the designer
1592
- * picks at template time. For example, `qi/claim.submit` only knows the
1593
- * shape of `surveyAnswers` once a claim collection has been chosen —
1594
- * returning `[]` until then hides the block from the trigger picker.
1595
- *
1596
- * Consumers (trigger picker, flow compiler, event payload picker) prefer
1597
- * `getDynamicEvents(inputs)` when defined and fall back to static `events`
1598
- * otherwise. By default the result is MERGED with the static `events`
1599
- * baseline (deduped by name, dynamic wins). Set
1600
- * `dynamicResolutionMode: 'replace'` when the resolver must control the
1601
- * full vocabulary (e.g. returning [] to hide the baseline).
1602
- */
1603
- getDynamicEvents?: (inputs: TInputs) => ActionEventDefinition[];
1604
- /**
1605
- * Optional per-block output-schema resolver. Symmetric to `getDynamicEvents`
1606
- * but for `outputSchema` — drives the reference picker for `${block.field}`
1607
- * refs so survey-derived fields like `output.surveyAnswers.<question>` show
1608
- * up alongside the static baseline.
1609
- *
1610
- * By default the returned array is MERGED with the static `outputSchema`
1611
- * baseline (deduped by path, dynamic wins); `dynamicResolutionMode:
1612
- * 'replace'` gives the resolver full control.
1613
- */
1614
- getDynamicOutputSchema?: (inputs: TInputs) => OutputSchemaField[];
1615
- /**
1616
- * Whether this action can be wired to a `block.event` trigger.
1617
- * False (the default) for user-interaction-driven actions like forms,
1618
- * claims, and evaluations — they always run as `manual`. True for actions
1619
- * where it makes sense for an event to nudge a human assignee to invoke
1620
- * them (email, http, notify).
1621
- *
1622
- * The trigger picker UI is hidden for blocks whose action type has this
1623
- * set to false.
1624
- */
1625
- eligibleForEventTrigger?: boolean;
1626
- run: (inputs: TInputs, ctx: ActionContext) => Promise<ActionResult>;
1627
- }
1628
- /**
1629
- * Result returned by an action's `run()` function.
1630
- *
1631
- * The optional `events` array is the explicit emission surface — actions
1632
- * declare which named events they're emitting on this particular run, with
1633
- * the payload by value. The runtime persists these as part of the run record
1634
- * and the reconciliation loop turns them into pending invocations on
1635
- * subscribed listener blocks.
1636
- */
1637
- interface ActionResult {
1638
- output: Record<string, any>;
1639
- events?: Array<{
1640
- name: string;
1641
- payload: Record<string, any>;
1642
- }>;
1643
- completion?: {
1644
- state?: 'completed' | 'awaiting_readback';
1645
- readBack?: Record<string, any>;
1646
- };
1647
- }
1648
-
1649
- interface NodeActionResult {
1650
- claimId?: string;
1651
- evaluationStatus?: EvaluationStatus;
1652
- submittedByDid?: string;
1653
- payload?: any;
1654
- }
1655
- interface ExecutionContext {
1656
- runtime: FlowRuntimeStateManager;
1657
- /** UCAN service — optional for v0.x flows, required for v1.0.0+ */
1658
- ucanService?: UcanService;
1659
- /** Invocation store — optional for v0.x flows */
1660
- invocationStore?: InvocationStore;
1661
- flowUri: string;
1662
- flowId: string;
1663
- flowOwnerDid: string;
1664
- /** Flow schema version. When set, controls whether UCAN is enforced. */
1665
- schemaVersion?: string;
1666
- now?: () => number;
1667
- }
1668
- interface ExecutionOutcome {
1669
- success: boolean;
1670
- stage: 'authorization' | 'claim' | 'action' | 'complete';
1671
- error?: string;
1672
- result?: NodeActionResult;
1673
- capabilityId?: string;
1674
- invocationCid?: string;
1675
- }
1676
- interface ExecuteNodeParams {
1677
- node: FlowNode;
1678
- actorDid: string;
1679
- actorType: 'entity' | 'user';
1680
- entityRoomId?: string;
1681
- context: ExecutionContext;
1682
- action: () => Promise<NodeActionResult>;
1683
- pin: string;
1684
- }
1685
- /**
1686
- * Execute a node.
1687
- *
1688
- * The pipeline adapts based on the flow's schema version (via context.schemaVersion):
1689
- *
1690
- * **v0.x (legacy):** activation → action → runtime update.
1691
- * UCAN authorization and invocations are skipped when ucanService is not available.
1692
- *
1693
- * **v1.0.0+:** activation → UCAN authorization → invocation → action → runtime update.
1694
- * Requires a configured ucanService with valid delegation chains.
1695
- */
1696
- declare const executeNode: ({ node, actorDid, actorType, entityRoomId, context, action, pin }: ExecuteNodeParams) => Promise<ExecutionOutcome>;
1697
-
1698
- type ActionExecutionCompletionState = 'completed' | 'failed' | 'awaiting_readback' | 'needs_verification';
1699
-
1700
- interface AuthorizationResult {
1701
- authorized: boolean;
1702
- reason?: string;
1703
- capabilityId?: string;
1704
- proofCids?: string[];
1705
- }
1706
- /**
1707
- * Check if an actor is authorized to execute a block.
1708
- *
1709
- * Behaviour depends on the flow's schema version:
1710
- * - v0.x (or no version): UCAN is optional. If ucanService is unavailable,
1711
- * execution is allowed without a delegation chain.
1712
- * - v1.0.0+: UCAN is required. A valid delegation chain must exist.
1713
- */
1714
- declare const isAuthorized: (blockId: string, actorDid: string, ucanService: UcanService | undefined, flowUri: string, schemaVersion?: string) => Promise<AuthorizationResult>;
1715
-
1716
- /** Registry interface expected by the compiler (keeps it pure / testable). */
1717
- interface CompilerRegistry {
1718
- getActionByCan(can: string): ActionDefinition | undefined;
1719
- }
1720
- /**
1721
- * Compile a Base UCAN flow plan into blocks, graph state, and metadata.
1722
- *
1723
- * This is a **pure function** — no React, no Yjs, no side effects.
1724
- * The output is consumed by `hydrateFlowFromPlan()`.
1725
- */
1726
- declare function compileBaseUcanFlow(plan: BaseUcanFlow, registry: CompilerRegistry): CompiledFlow;
1727
-
1728
- /** Describes what changed when merging two compiled flows. */
1729
- interface MergeResult {
1730
- /** The merged compiled flow (full state). */
1731
- merged: CompiledFlow;
1732
- /** Node IDs that were added (new in incoming, not in existing). */
1733
- added: string[];
1734
- /** Node IDs that were replaced (patch only — existed and was overwritten). */
1735
- replaced: string[];
1736
- /** Node IDs that were kept unchanged from existing. */
1737
- kept: string[];
1738
- }
1739
- /**
1740
- * Merge an incoming compiled flow into an existing one.
1741
- *
1742
- * This is a **pure function** — no Yjs, no side effects.
1743
- *
1744
- * Strategies:
1745
- * - `merge`: existing nodes win on ID collision. Incoming nodes with new IDs
1746
- * are added. Existing nodes are never modified.
1747
- * - `patch`: incoming nodes overwrite existing nodes on ID collision. Incoming
1748
- * nodes with new IDs are added. Existing nodes not in incoming are kept.
1749
- *
1750
- * Edges in the merged result are the union of edges from both sides, filtered
1751
- * to those whose source and target both exist in the merged node set, with
1752
- * duplicates collapsed by edge id. Order is the merged node insertion order
1753
- * (existing first, then newly added) — there is no topological sort because
1754
- * there is no inferred dependency relationship.
1755
- */
1756
- declare function mergeCompiledFlows(existing: CompiledFlow, incoming: CompiledFlow, strategy: 'merge' | 'patch'): MergeResult;
1757
-
1758
- interface SetupFlowOptions {
1759
- /** The Base UCAN flow plan to compile. */
1760
- plan: BaseUcanFlow;
1761
- /** Matrix room ID to hydrate the flow into. */
1762
- roomId: string;
1763
- /** Authenticated Matrix client. */
1764
- matrixClient: MatrixClient;
1765
- /** DID of the user setting up the flow. */
1766
- creatorDid: string;
1767
- /** Optional doc ID override (defaults to plan.flowId). */
1768
- docId?: string;
1769
- /**
1770
- * Room ID of the template this flow was instantiated from, if any.
1771
- * Recorded into the root map as `source_template_id` for lineage tracking.
1772
- */
1773
- templateId?: string;
1774
- /**
1775
- * How to apply the plan to the existing document.
1776
- * - `full` (default): wipe existing flow state and rebuild entirely.
1777
- * - `merge`: keep existing blocks, add new capabilities from the plan.
1778
- * - `patch`: replace matching nodes, add new ones, keep the rest.
1779
- */
1780
- strategy?: FlowStrategy;
1781
- }
1782
- interface SetupFlowResult {
1783
- /** The compiled flow artifacts. */
1784
- compiled: CompiledFlow;
1785
- /** The room ID (same as input, for convenience). */
1786
- roomId: string;
1787
- /** The flow ID from the plan. */
1788
- flowId: string;
1789
- }
1790
- interface ReadFlowOptions {
1791
- /** Matrix room ID to read from. */
1792
- roomId: string;
1793
- /** Authenticated Matrix client. */
1794
- matrixClient: MatrixClient;
1795
- }
1796
- interface ReadFlowResult {
1797
- /** The current flow plan in BaseUcanFlow format (what the agent reads/writes). */
1798
- plan: BaseUcanFlow;
1799
- /** The compiled flow state (lower-level representation). */
1800
- compiled: CompiledFlow;
1801
- /** The room ID (same as input, for convenience). */
1802
- roomId: string;
1803
- }
1804
- /**
1805
- * Read the current Base UCAN flow plan from a Matrix room.
1806
- *
1807
- * Connects to the room, reads the Y.Doc, decompiles the flow state
1808
- * back into a `BaseUcanFlow`, and disconnects. Returns `null` if the
1809
- * room has no flow state.
1810
- *
1811
- * **This is the lower-level API.** It exists for cases where you need
1812
- * to read a flow from a room you are NOT currently editing — e.g.
1813
- * cross-room operations or background reads. For the common case of
1814
- * "read the flow the user is currently looking at," use
1815
- * `readFlowFromEditor(editor)` instead. That function takes no
1816
- * parameters from the agent and reads from the editor's existing
1817
- * Y.Doc directly — no Matrix connection, no async, no room ID
1818
- * resolution. The browser tool that exposes `read_flow` to the AI
1819
- * agent should wrap `readFlowFromEditor`, not this function.
1820
- */
1821
- declare function readFlowAsBaseUcan(options: ReadFlowOptions): Promise<ReadFlowResult | null>;
1822
- /**
1823
- * Minimal editor shape required by `readFlowFromEditor` and the active
1824
- * editor registry. The full `IxoEditorType` is fine to pass — this is
1825
- * just a structural lower bound so test harnesses can construct fake
1826
- * editors without pulling in React dependencies.
1827
- */
1828
- interface ReadableEditor {
1829
- _yDoc?: Y.Doc;
1830
- getRoomId?: () => string;
1831
- }
1832
- /**
1833
- * Read the current flow from a specific editor instance, synchronously.
1834
- *
1835
- * Use this when you have an editor reference in hand (e.g. from inside a
1836
- * React component, a test, or a multi-editor host that needs to target a
1837
- * specific instance). For the common case of "read the flow the user is
1838
- * currently looking at," prefer the parameterless `readFlow()` below — it
1839
- * uses the active editor registry so you don't have to thread an editor
1840
- * reference through your call sites.
1841
- *
1842
- * Returns `null` ONLY when the editor's Y.Doc has no flow state at all
1843
- * (no nodes AND no meta). An empty `flowId` string is no longer treated
1844
- * as "no flow" — that was the historical bug where successful
1845
- * `setup_flow` calls authored with `flowId: ""` (the documented agent
1846
- * convention) showed up as null on subsequent reads.
1847
- */
1848
- declare function readFlowFromEditor(editor: ReadableEditor): ReadFlowResult | null;
1849
- /**
1850
- * Register an editor as the current active editor. Called by the editor's
1851
- * mount hook when the document is connected and ready. Pass `null` on
1852
- * unmount to clear the registry.
1853
- *
1854
- * If a different editor is already registered, it is replaced silently —
1855
- * the most recent registration wins. This matches the single-editor
1856
- * assumption above.
1857
- */
1858
- declare function setActiveEditor(editor: ReadableEditor | null): void;
1859
- /**
1860
- * Get the currently registered active editor, or null if none is set.
1861
- * Provided for cases where a caller wants to check the registry directly
1862
- * (e.g. for diagnostics) without going through `readFlow()`.
1863
- */
1864
- declare function getActiveEditor(): ReadableEditor | null;
1865
- /**
1866
- * Read the current flow from the active editor, with no parameters at all.
1867
- *
1868
- * This is the parameterless API the AI agent's `read_flow` browser tool
1869
- * should wrap. The browser tool literally becomes `read_flow: () => readFlow()`.
1870
- *
1871
- * Returns `null` if there is no active editor registered (e.g. the editor
1872
- * hasn't finished mounting yet, or no editor is open in this JS context),
1873
- * OR if the active editor's Y.Doc has no flow state at all.
1874
- *
1875
- * If `null` is returned and the user is referencing an existing flow, that
1876
- * is a hard signal to STOP and report to the user — never silently rebuild,
1877
- * because the duplicate-blocks bug is the inevitable consequence.
1878
- */
1879
- declare function readFlow(): ReadFlowResult | null;
1880
- /**
1881
- * One-shot function that compiles a Base UCAN flow plan and writes it
1882
- * into a Matrix room's Y.Doc. After this completes, the room is a
1883
- * normal flow that anyone can open via `useCreateCollaborativeIxoEditor`.
1884
- *
1885
- * Supports three strategies:
1886
- * - `full` (default): clears any existing flow and rebuilds from scratch.
1887
- * - `merge`: adds new capabilities alongside existing ones.
1888
- * - `patch`: replaces matching nodes and adds new ones.
1889
- */
1890
- declare function setupFlowFromBaseUcan(options: SetupFlowOptions): Promise<SetupFlowResult>;
1891
-
1892
- /**
1893
- * Read the current compiled flow state from a live Y.Doc.
1894
- *
1895
- * This is the inverse of `hydrateYDocFromCompiledFlow`. It extracts the flow
1896
- * graph state from Yjs maps so that the pure merge/patch logic can operate
1897
- * on plain objects.
1898
- *
1899
- * Returns `null` if the document has no flow state.
1900
- */
1901
- declare function readCompiledFlowFromYDoc(yDoc: Doc): CompiledFlow | null;
1902
-
1903
- /**
1904
- * Reconstruct a BaseUcanFlow plan from a CompiledFlow.
1905
- *
1906
- * This is the inverse of `compileBaseUcanFlow`. It allows the AI agent to
1907
- * read the current flow in the same format it writes — a plain capability
1908
- * list it can reason about, modify, and pass back to the compiler.
1909
- *
1910
- * This is a **pure function** — no Yjs, no side effects.
1911
- *
1912
- * Note: some information is lossy (e.g. conditions are stored as a JSON
1913
- * string in props and are not fully round-tripped back to ConditionRef).
1914
- * The core capability data (can, with, nb, trigger, actor, ttl, metadata)
1915
- * is fully preserved.
1916
- */
1917
- declare function decompileToBaseUcanFlow(compiled: CompiledFlow): BaseUcanFlow;
1918
-
1919
- type FlowAgentPublicNodeState = 'Pending' | 'Blocked' | 'Overdue' | 'Done';
1920
- type FlowAgentRunPhase = 'Running' | 'Validating' | 'Failed' | 'Archived';
1921
- type FlowAgentBlockerCause = 'missing_input' | 'failed_upstream' | 'missing_ucan' | 'stale_config' | 'service_error' | 'external_confirmation_pending' | 'validation_mismatch' | 'unverified_completion' | 'awaiting_verification' | 'unknown';
1922
- type FlowAgentCommandType = 'diagnose_blocker' | 'assign_actor' | 'notify_actor' | 'execute_action' | 'validate_external_state' | 'archive_flow' | 'propose_config_change';
1923
- type FlowAgentCommandStatus = 'queued' | 'leased' | 'running' | 'confirmed' | 'awaiting_readback' | 'failed' | 'skipped';
1924
- type FlowAgentLedgerEventType = 'agent.decision' | 'agent.command' | 'agent.validation' | 'agent.escalation' | 'agent.memory';
1925
- interface FlowAgentActor {
1926
- did: string;
1927
- matrixUserId?: string;
1928
- displayName?: string;
1929
- skills?: string[];
1930
- }
1931
- interface FlowAgentLease {
1932
- id: string;
1933
- commandId: string;
1934
- nodeId: string;
1935
- actorDid: string;
1936
- acquiredAt: number;
1937
- expiresAt: number;
1938
- epoch: number;
1939
- }
1940
- interface FlowAgentNodeSnapshot {
1941
- nodeId: string;
1942
- blockType: string;
1943
- actionType?: string;
1944
- title?: string;
1945
- runtime: FlowNodeRuntimeState;
1946
- publicState: FlowAgentPublicNodeState;
1947
- blockerCause?: FlowAgentBlockerCause;
1948
- assigneeDid?: string;
1949
- dueAt?: number;
1950
- pendingInvocationCount: number;
1951
- }
1952
- interface FlowAgentCommandBase {
1953
- id: string;
1954
- type: FlowAgentCommandType;
1955
- flowId: string;
1956
- flowUri: string;
1957
- nodeId: string;
1958
- actorDid: string;
1959
- status: FlowAgentCommandStatus;
1960
- capability: UcanCapability;
1961
- idempotencyKey: string;
1962
- createdAt: number;
1963
- updatedAt: number;
1964
- reason: string;
1965
- payload: Record<string, unknown>;
1966
- lease?: FlowAgentLease;
1967
- error?: string;
1968
- }
1969
- type FlowAgentCommand = FlowAgentCommandBase;
1970
- interface FlowAgentLedgerEvent {
1971
- id: string;
1972
- type: FlowAgentLedgerEventType;
1973
- flowId: string;
1974
- nodeId?: string;
1975
- commandId?: string;
1976
- actorDid: string;
1977
- timestamp: number;
1978
- details: Record<string, unknown>;
1979
- }
1980
- interface FlowAgentMaps {
1981
- outbox: Map<FlowAgentCommand>;
1982
- leases: Map<FlowAgentLease>;
1983
- }
1984
- interface FlowAgentPolicyDecision {
1985
- allowed: boolean;
1986
- reason: string;
1987
- capability: UcanCapability;
1988
- proofCids: string[];
1989
- }
1990
- interface FlowAgentContext {
1991
- yDoc: Doc;
1992
- editor?: IxoEditorType;
1993
- blocks?: unknown[];
1994
- flowId: string;
1995
- flowUri: string;
1996
- actor: FlowAgentActor;
1997
- now?: () => number;
1998
- }
1999
- interface FlowAgentCommandResult {
2000
- commandId: string;
2001
- success: boolean;
2002
- output?: Record<string, unknown>;
2003
- confirmed?: boolean;
2004
- completionState?: ActionExecutionCompletionState;
2005
- status?: FlowAgentCommandStatus;
2006
- error?: string;
2007
- }
2008
- interface FlowAgentExecutor {
2009
- executeAction?: (command: FlowAgentCommand, context: FlowAgentContext) => Promise<FlowAgentCommandResult>;
2010
- assignActor?: (command: FlowAgentCommand, context: FlowAgentContext) => Promise<FlowAgentCommandResult>;
2011
- notifyActor?: (command: FlowAgentCommand, context: FlowAgentContext) => Promise<FlowAgentCommandResult>;
2012
- validateExternalState?: (command: FlowAgentCommand, context: FlowAgentContext) => Promise<FlowAgentCommandResult>;
2013
- archiveFlow?: (command: FlowAgentCommand, context: FlowAgentContext) => Promise<FlowAgentCommandResult>;
2014
- proposeConfigChange?: (command: FlowAgentCommand, context: FlowAgentContext) => Promise<FlowAgentCommandResult>;
2015
- diagnoseBlocker?: (command: FlowAgentCommand, context: FlowAgentContext) => Promise<FlowAgentCommandResult>;
2016
- }
2017
- interface FlowAgentTickResult {
2018
- flowDone: boolean;
2019
- snapshots: FlowAgentNodeSnapshot[];
2020
- queuedCommands: FlowAgentCommand[];
2021
- executedCommands: FlowAgentCommandResult[];
2022
- }
2023
-
2024
- interface CreateAgentCommandParams {
2025
- type: FlowAgentCommandType;
2026
- flowId: string;
2027
- flowUri: string;
2028
- nodeId: string;
2029
- actor: FlowAgentActor;
2030
- reason: string;
2031
- payload?: Record<string, unknown>;
2032
- now?: number;
2033
- }
2034
- declare function createAgentCommand({ type, flowId, flowUri, nodeId, actor, reason, payload, now }: CreateAgentCommandParams): FlowAgentCommand;
2035
- declare function validateAgentCommand(command: FlowAgentCommand): {
2036
- valid: boolean;
2037
- error?: string;
2038
- };
2039
- declare function isExternalMutation(type: FlowAgentCommandType): boolean;
2040
-
2041
- interface BuildFlowAgentContextParams {
2042
- yDoc: Doc;
2043
- flowId: string;
2044
- flowUri?: string;
2045
- actor: FlowAgentActor;
2046
- blocks?: unknown[];
2047
- editor?: IxoEditorType;
2048
- now?: () => number;
2049
- }
2050
- /**
2051
- * Builds the host-facing runtime context expected by the Flow Agent.
2052
- *
2053
- * Headless hosts own Matrix login, room joins, and Y.Doc sync. Once a host has
2054
- * a live room document and an agent identity, this helper gives it the stable
2055
- * context shape to pass into `tickFlowAgent` or `FlowAgentService`.
2056
- */
2057
- declare function buildFlowAgentContext({ yDoc, flowId, flowUri, actor, blocks, editor, now }: BuildFlowAgentContextParams): FlowAgentContext;
2058
-
2059
- interface AcquireFlowAgentLeaseParams {
2060
- leases: Map<FlowAgentLease>;
2061
- commandId: string;
2062
- nodeId: string;
2063
- actorDid: string;
2064
- now?: number;
2065
- ttlMs?: number;
2066
- }
2067
- declare function acquireFlowAgentLease({ leases, commandId, nodeId, actorDid, now, ttlMs, }: AcquireFlowAgentLeaseParams): FlowAgentLease | null;
2068
- declare function validateFlowAgentLease(leases: Map<FlowAgentLease>, lease: FlowAgentLease, now?: number): boolean;
2069
- declare function releaseFlowAgentLease(leases: Map<FlowAgentLease>, lease: FlowAgentLease): boolean;
2070
- declare function cleanupExpiredFlowAgentLeases(leases: Map<FlowAgentLease>, now?: number): FlowAgentLease[];
2071
-
2072
- declare function requiredCapabilityForCommand(type: FlowAgentCommandType, flowUri: string, nodeId: string): UcanCapability;
2073
- declare function isCapabilityMatch(granted: UcanCapability, required: UcanCapability): boolean;
2074
- declare function canMatches(granted: string, required: string): boolean;
2075
- declare function resourceMatches(granted: string, required: string): boolean;
2076
- interface EvaluateFlowAgentPolicyParams {
2077
- actorDid: string;
2078
- commandType: FlowAgentCommandType;
2079
- flowUri: string;
2080
- nodeId: string;
2081
- delegationStore?: UcanDelegationStore;
2082
- delegations?: StoredDelegation[];
2083
- now?: number;
2084
- }
2085
- declare function evaluateFlowAgentPolicy({ actorDid, commandType, flowUri, nodeId, delegationStore, delegations, now, }: EvaluateFlowAgentPolicyParams): FlowAgentPolicyDecision;
2086
-
2087
- interface FlowAgentOrchestratorOptions {
2088
- delegationStore?: UcanDelegationStore;
2089
- delegations?: StoredDelegation[];
2090
- candidateActors?: FlowAgentActor[];
2091
- executor?: FlowAgentExecutor;
2092
- leaseTtlMs?: number;
2093
- archiveWhenDone?: boolean;
2094
- }
2095
- declare function planRalphLoopCommands(context: FlowAgentContext, options?: FlowAgentOrchestratorOptions): {
2096
- snapshots: FlowAgentNodeSnapshot[];
2097
- queuedCommands: FlowAgentCommand[];
2098
- flowDone: boolean;
2099
- };
2100
- declare function executeQueuedAgentCommands(context: FlowAgentContext, options?: FlowAgentOrchestratorOptions): Promise<FlowAgentCommandResult[]>;
2101
- declare function tickFlowAgent(context: FlowAgentContext, options?: FlowAgentOrchestratorOptions): Promise<FlowAgentTickResult>;
2102
-
2103
- interface FlowAgentServiceOptions extends FlowAgentOrchestratorOptions {
2104
- intervalMs?: number;
2105
- onTick?: (result: FlowAgentTickResult) => void | Promise<void>;
2106
- onError?: (error: unknown) => void;
2107
- }
2108
- /**
2109
- * Headless-service adapter boundary.
2110
- *
2111
- * Host applications own Matrix login, room joins, and Y.Doc sync. Once they
2112
- * have a live Y.Doc/editor snapshot, this service provides the deterministic
2113
- * Ralph-loop tick and command execution cycle.
2114
- */
2115
- declare class FlowAgentService {
2116
- private readonly context;
2117
- private readonly options;
2118
- private timer;
2119
- private running;
2120
- constructor(context: FlowAgentContext, options?: FlowAgentServiceOptions);
2121
- tick(): Promise<FlowAgentTickResult>;
2122
- start(): void;
2123
- stop(): void;
2124
- }
2125
-
2126
- declare function getFlowAgentMaps(yDoc: Doc): FlowAgentMaps;
2127
- declare function computeAgentCommandId(params: {
2128
- flowId: string;
2129
- nodeId: string;
2130
- type: string;
2131
- payload: Record<string, unknown>;
2132
- }): string;
2133
- declare function queueAgentCommand(yDoc: Doc, command: FlowAgentCommand): {
2134
- command: FlowAgentCommand;
2135
- created: boolean;
2136
- };
2137
- declare function readQueuedAgentCommands(yDoc: Doc): FlowAgentCommand[];
2138
- declare function updateAgentCommand(yDoc: Doc, commandId: string, patch: Partial<FlowAgentCommand>): FlowAgentCommand | null;
2139
- declare function appendAgentLedgerEvent(yDoc: Doc, event: Omit<FlowAgentLedgerEvent, 'id'> & {
2140
- id?: string;
2141
- }): FlowAgentLedgerEvent;
2142
- declare function readAgentLedgerEvents(yDoc: Doc, eventType?: FlowAgentLedgerEventType): FlowAgentLedgerEvent[];
2143
-
2144
- export { type FlowAgentContext as $, type AuthorizationResult as A, type BaseUcanFlow as B, type CompilerRegistry as C, buildFlowAgentContext as D, type ExecuteNodeParams as E, type FlowRuntimeStateManager as F, cleanupExpiredFlowAgentLeases as G, createAgentCommand as H, evaluateFlowAgentPolicy as I, executeQueuedAgentCommands as J, getFlowAgentMaps as K, planRalphLoopCommands as L, type MergeResult as M, type NodeActionResult as N, queueAgentCommand as O, readAgentLedgerEvents as P, readQueuedAgentCommands as Q, type ReadFlowOptions as R, type SetupFlowOptions as S, releaseFlowAgentLease as T, tickFlowAgent as U, validateAgentCommand as V, validateFlowAgentLease as W, type BuildFlowAgentContextParams as X, type FlowAgentActor as Y, type FlowAgentCommand as Z, type FlowAgentCommandResult as _, buildAuthzFromProps as a, type FlowAgentRunPhase as a$, type FlowAgentExecutor as a0, type FlowAgentLease as a1, type FlowAgentNodeSnapshot as a2, type FlowAgentPublicNodeState as a3, type FlowAgentTickResult as a4, type ActionDefinition as a5, type ActionEventDefinition as a6, type OutputSchemaField as a7, type ActionServices as a8, type ActionProofDeclaration as a9, removePendingInvocation as aA, findFailedListenersForSourceRun as aB, replayFailedListenerRun as aC, snapshotInputRefs as aD, computePendingInvocationId as aE, RUN_RECORD_AUDIT_TYPE as aF, type PendingInvocation as aG, type FailedListenerRun as aH, canMatches as aI, computeAgentCommandId as aJ, isCapabilityMatch as aK, isExternalMutation as aL, requiredCapabilityForCommand as aM, resourceMatches as aN, updateAgentCommand as aO, type AcquireFlowAgentLeaseParams as aP, type CreateAgentCommandParams as aQ, type EvaluateFlowAgentPolicyParams as aR, type FlowAgentOrchestratorOptions as aS, type FlowAgentServiceOptions as aT, type FlowAgentCommandBase as aU, type FlowAgentCommandStatus as aV, type FlowAgentCommandType as aW, type FlowAgentLedgerEvent as aX, type FlowAgentLedgerEventType as aY, type FlowAgentMaps as aZ, type FlowAgentPolicyDecision as a_, type RunRecordDetails as aa, type CompiledBlock as ab, type CompiledEdge as ac, type ActionHandlers as ad, type FlowAgentBlockerCause as ae, clearRuntimeForTemplateClone as af, type ActionContext as ag, type HttpService as ah, type EmailService as ai, type NotifyService as aj, type BidService as ak, type ClaimService as al, type CollectionService as am, type CollectionUsersService as an, type MatrixCredentialService as ao, type IntegrationsService as ap, type OracleService as aq, type CarbonService as ar, type EntityService as as, type ActionResult as at, appendRunRecord as au, readRunRecords as av, getPendingInvocationsMap as aw, getOrCreateBlockPendingMap as ax, readPendingInvocations as ay, queuePendingInvocation as az, buildFlowNodeFromBlock as b, type ConditionRef as b0, type ActorConstraint as b1, type TTLConstraint as b2, type RuntimeRef as b3, type CompiledFlowNode as b4, type TriggerSpec as b5, isRuntimeRef as b6, createRuntimeStateManager as c, type ExecutionOutcome as d, executeNode as e, type ExecutionContext as f, readFlowFromEditor as g, readFlow as h, isAuthorized as i, setActiveEditor as j, getActiveEditor as k, compileBaseUcanFlow as l, readCompiledFlowFromYDoc as m, mergeCompiledFlows as n, decompileToBaseUcanFlow as o, type SetupFlowResult as p, type ReadFlowResult as q, readFlowAsBaseUcan as r, setupFlowFromBaseUcan as s, type ReadableEditor as t, type FlowCapability as u, type CompiledFlow as v, type FlowStrategy as w, FlowAgentService as x, acquireFlowAgentLease as y, appendAgentLedgerEvent as z };