@dudousxd/nestjs-durable-dashboard 0.57.0 → 0.58.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,4 +1,4 @@
1
- import { HttpException, ExecutionContext, Type, ExceptionFilter, ArgumentsHost, CanActivate, Logger, DynamicModule, StreamableFile } from '@nestjs/common';
1
+ import { HttpException, ExecutionContext, Type, ExceptionFilter, ArgumentsHost, CanActivate, Logger, DynamicModule, StreamableFile, OnModuleInit, OnModuleDestroy } from '@nestjs/common';
2
2
  import { HttpAdapterHost, ModuleRef } from '@nestjs/core';
3
3
  import * as _dudousxd_nestjs_durable_core from '@dudousxd/nestjs-durable-core';
4
4
  import { RunGateway, StateStore, WorkflowEngine, ScheduleListQuery, ScheduleDescription, RunResult, RunQuery, RunListItem, RunFacetQuery, RunFacetRow, RunValueAxis, RunValueFacetOptions, RunValueFacetRow, DurableTopology, GroupHealth, RunDetailOptions, RunDetail, FanPageQuery, FanPage, RepublishLifecycleResult, WorkflowLifecycleLinks, UpdateResult, EngineEvent, AttributeFilter } from '@dudousxd/nestjs-durable-core';
@@ -8,8 +8,14 @@ import { Observable } from 'rxjs';
8
8
  import * as _dudousxd_nestjs_filter from '@dudousxd/nestjs-filter';
9
9
  import { FilterRunner } from '@dudousxd/nestjs-filter';
10
10
 
11
+ /**
12
+ * What an `authorize` check answers. An allow may name who it let in (`caller`, for example
13
+ * `'user:42'`): the dev MCP endpoint logs it as the caller of a developer tool. Never put a secret
14
+ * in it.
15
+ */
11
16
  type ConsoleAuthorizeResult = boolean | {
12
17
  allowed: true;
18
+ caller?: string;
13
19
  } | {
14
20
  allowed: false;
15
21
  reason?: 'unauthenticated' | 'forbidden';
@@ -31,6 +37,7 @@ type ConsoleAuthorize = ((context: ExecutionContext) => ConsoleAuthorizeResult |
31
37
  }>) | ConsolePolicyCheck | string;
32
38
  type ConsoleDecision = {
33
39
  allowed: true;
40
+ caller?: string;
34
41
  } | {
35
42
  allowed: false;
36
43
  reason: 'unauthenticated' | 'forbidden';
@@ -65,11 +72,23 @@ declare function resolveConsoleAuthorize(authorize: ConsoleAuthorize | undefined
65
72
  /**
66
73
  * Allows a request carrying `Authorization: Bearer <token>` (compared timing-safe); anything else
67
74
  * is `unauthenticated`. Header only: no query string, no custom header. Throws when `token` is
68
- * empty, so a missing env var fails at config time instead of opening the console.
75
+ * empty, so a missing env var fails at config time instead of opening the console. The allow names
76
+ * its caller `token:<first 12 hex of sha256(token)>`, never the token.
69
77
  */
70
78
  declare function authorizeByToken(options: {
71
79
  token: string | undefined;
72
80
  }): ConsoleAuthorize;
81
+ /**
82
+ * One `authorize` from several: allowed when any form allows (checked in order, stopping at the
83
+ * first that does, whose `caller` it keeps); otherwise `unauthenticated` when any form said so
84
+ * (keeping the first `redirectTo`), else `forbidden`. Each form is any `authorize` value: a
85
+ * function, a class, a lazy import, `{ policy, ability }` or a gate name.
86
+ *
87
+ * ```ts
88
+ * authorize: anyAuthorize(authorizeByToken({ token: process.env.CONSOLE_TOKEN }), AdminSessionAuthorizer)
89
+ * ```
90
+ */
91
+ declare function anyAuthorize(...forms: ConsoleAuthorize[]): ConsoleAuthorizerClass;
73
92
  /** DI token of the resolved {@link ConsoleDecide} the guard runs. */
74
93
  declare const CONSOLE_AUTHORIZE_DECIDE: unique symbol;
75
94
  /** Marks a controller as serving pages: a denied `GET` that accepts HTML gets a page, not JSON. */
@@ -241,6 +260,22 @@ declare class DashboardService {
241
260
  * rows behind or signal non-webhook tokens. Control-plane-only.
242
261
  */
243
262
  deliverWebhook(token: string, body: unknown): Promise<RunResult | null>;
263
+ /**
264
+ * What this deployment can serve: `controlPlane` (signals, run events, updates, metrics) and
265
+ * `schedules` (persisted schedules). Both are false on a store-less tenant.
266
+ */
267
+ capabilities(): {
268
+ controlPlane: boolean;
269
+ schedules: boolean;
270
+ };
271
+ /** Whether `runId` names a run the caller may see (tenancy applies). */
272
+ runExists(runId: string): Promise<boolean>;
273
+ /**
274
+ * Deliver `payload` to the run waiting on `token` (`engine.signal`). Null when no run the caller
275
+ * may see waits on it yet: the engine then buffers the payload for the run that waits next.
276
+ * Control-plane-only.
277
+ */
278
+ signal(token: string, payload: unknown): Promise<RunResult | null>;
244
279
  /** Side-effect-free read of a value a run published via `ctx.setEvent` (a live query). Control-plane-only. */
245
280
  getEvent(runId: string, key: string): Promise<unknown>;
246
281
  /** Deliver a validated `ctx.onUpdate` to a run; the validator may reject it (see UpdateResult). Control-plane-only. */
@@ -533,6 +568,12 @@ interface DurableDashboardOptions {
533
568
  * strings that keep their meaning (where the console lives) whether or not this module mounts it.
534
569
  */
535
570
  routes?: boolean;
571
+ /**
572
+ * Register the console's reads and run/schedule actions as developer tools on the agent MCP
573
+ * server's dev endpoint (`/mcp/aviary`), gated by this console's `authorize`. Default: on when
574
+ * the console's routes are mounted, off with `routes: false`.
575
+ */
576
+ devTools?: boolean;
536
577
  }
537
578
  /**
538
579
  * Holds the JSON API controller + its read service, mounted on its own path by `forRoot`. Its own
@@ -548,6 +589,8 @@ declare class DurableApiModule {
548
589
  decorators?: ClassDecorator[];
549
590
  /** See {@link DurableDashboardOptions.authorize}. */
550
591
  authorize?: ConsoleAuthorize;
592
+ /** See {@link DurableDashboardOptions.devTools}. Default: on when the routes are mounted. */
593
+ devTools?: boolean;
551
594
  }): DynamicModule;
552
595
  }
553
596
  /**
@@ -565,9 +608,12 @@ declare class DurableDashboardModule {
565
608
  }
566
609
 
567
610
  /** DI token carrying the UI mount base (e.g. `/durable`). */
568
- declare const DASHBOARD_BASE_PATH: unique symbol;
611
+ declare const DASHBOARD_BASE_PATH: symbol;
569
612
  /** DI token carrying the JSON API base the SPA fetches from (e.g. `/api/durable`). */
570
- declare const DASHBOARD_API_PATH: unique symbol;
613
+ declare const DASHBOARD_API_PATH: symbol;
614
+
615
+ /** The id of the page's JSON config block. */
616
+ declare const DURABLE_DASHBOARD_CONFIG_ID = "durable-dashboard-config";
571
617
  /**
572
618
  * Serves the bundled control-plane SPA at the configured base (+ hashed assets at `<base>/assets`).
573
619
  * The controller routes are relative: the mounted {@link DurableUiController} gets its path from
@@ -585,6 +631,11 @@ declare class DurableUiControllerBase {
585
631
  private readonly dir;
586
632
  constructor(basePath: string, apiBasePath: string);
587
633
  index(): string;
634
+ /**
635
+ * The page's JSON config block (`durable-dashboard-config`, CSP-safe: data, not script). It
636
+ * carries `switcher` only when another Aviary console is registered.
637
+ */
638
+ private configBlock;
588
639
  asset(file: string): StreamableFile;
589
640
  }
590
641
  /**
@@ -596,4 +647,165 @@ declare class DurableUiControllerBase {
596
647
  declare class DurableUiController extends DurableUiControllerBase {
597
648
  }
598
649
 
599
- export { CONSOLE_AUTHORIZE_DECIDE, CONSOLE_AUTHORIZE_MISSING_WARNING, CONSOLE_GATE, CONSOLE_PAGE_METADATA, CONSOLE_PUBLIC_METADATA, ConsoleAccessDenied, type ConsoleAuthorize, ConsoleAuthorizeFilter, ConsoleAuthorizeGuard, type ConsoleAuthorizeResult, type ConsoleAuthorizer, type ConsoleAuthorizerClass, type ConsoleDecide, type ConsoleDecision, type ConsoleGate, ConsolePage, type ConsolePolicyCheck, ConsolePublic, DASHBOARD_API_PATH, DASHBOARD_BASE_PATH, DashboardService, DurableApiController, DurableApiControllerBase, DurableApiModule, DurableDashboardModule, type DurableDashboardOptions, DurableUiController, DurableUiControllerBase, UseConsoleAuthorize, type WorkflowLifecyclePage, authorizeByToken, normalizeConsoleResult, resolveConsoleAuthorize };
650
+ /** The process-wide slot `@dudousxd/nestjs-agent-mcp-server` serves on its dev MCP endpoint. */
651
+ declare const DEV_TOOLS_SLOT: symbol;
652
+ /** One property of a {@link DevToolInputSchema}. */
653
+ interface DevToolInputProperty {
654
+ type: 'string' | 'number' | 'integer' | 'boolean' | 'array';
655
+ description?: string;
656
+ enum?: readonly string[];
657
+ /** Arrays hold strings only. */
658
+ items?: {
659
+ type: 'string';
660
+ };
661
+ minimum?: number;
662
+ maximum?: number;
663
+ }
664
+ /** An object of scalar / enum / array-of-string properties. */
665
+ interface DevToolInputSchema {
666
+ type: 'object';
667
+ properties: Record<string, DevToolInputProperty>;
668
+ required?: string[];
669
+ }
670
+ /** What the slot's `authorize` answers: the console's resolved decision. */
671
+ type DevToolsDecision = {
672
+ allowed: true;
673
+ caller?: string;
674
+ } | {
675
+ allowed: false;
676
+ reason: 'unauthenticated' | 'forbidden';
677
+ redirectTo?: string;
678
+ };
679
+ /** What a tool's `run` receives besides its input. */
680
+ interface DevToolCall {
681
+ context: ExecutionContext;
682
+ caller: {
683
+ id: string;
684
+ via: 'token' | 'session' | 'open';
685
+ };
686
+ limits: {
687
+ maxRows: number;
688
+ maxBytes: number;
689
+ };
690
+ }
691
+ /** One developer tool, as the dev-tools slot takes it. */
692
+ interface DurableDevTool {
693
+ /** `durable_<verb>_<noun>`. */
694
+ name: string;
695
+ /** `read` tools are listed by default; `action` tools only when the app opts in. */
696
+ kind: 'read' | 'action';
697
+ description: string;
698
+ input: DevToolInputSchema;
699
+ /** Set on actions that cancel. */
700
+ destructive?: boolean;
701
+ /** Capability, not access: hides a tool this deployment cannot run. */
702
+ available?(): boolean | Promise<boolean>;
703
+ run(input: Record<string, unknown>, call?: DevToolCall): Promise<unknown>;
704
+ }
705
+ /** Runs `durable_retry_run` / `durable_cancel_run` act on at most per call. */
706
+ declare const MAX_RUN_IDS = 100;
707
+ /**
708
+ * The durable developer tools (lib `durable`): the console's reads and its run and schedule
709
+ * actions, through the same {@link DashboardService} methods its API serves, so tenancy and the
710
+ * app's redaction apply. Signals, run events and schedules are available only on the control plane.
711
+ */
712
+ declare function durableDevTools(service: DashboardService): DurableDevTool[];
713
+ /**
714
+ * Registers the durable tools into the dev-tools slot, gated by the console's own resolved
715
+ * `authorize`, when the console is mounted (or `devTools: true`). Removed again on shutdown.
716
+ */
717
+ declare class DurableDevToolsRegistration implements OnModuleInit, OnModuleDestroy {
718
+ #private;
719
+ private readonly enabled;
720
+ private readonly service;
721
+ private readonly decide;
722
+ constructor(enabled: boolean, service: DashboardService, decide: ConsoleDecide);
723
+ onModuleInit(): void;
724
+ onModuleDestroy(): void;
725
+ }
726
+
727
+ /** The process-wide slot every Aviary console registers into (created by whichever boots first). */
728
+ declare const AVIARY_CONSOLES_SLOT: symbol;
729
+ /** The icon a console shows in the switcher. An unknown value renders as `generic`. */
730
+ type AviaryConsoleIcon = 'workflow' | 'telescope' | 'media' | 'payments' | 'agent' | 'identity' | 'generic';
731
+ /** What a console's `authorize` answers; only `allowed: true` lists it. */
732
+ interface AviaryConsoleDecision {
733
+ allowed: boolean;
734
+ reason?: string;
735
+ redirectTo?: string;
736
+ }
737
+ /** One console the switcher can list. */
738
+ interface AviaryConsoleEntry {
739
+ /** `/^[a-z][a-z0-9-]*$/`: `'durable'`, `'telescope'`, `'agent'`, `'media'`, … */
740
+ id: string;
741
+ /** Product title: `'Workflows'`, `'Telescope'`, `'Agents'`, `'Media'`. */
742
+ title: string;
743
+ icon: AviaryConsoleIcon;
744
+ /** Same-origin absolute path of the console's page (`/durable`). */
745
+ path: string;
746
+ /** Sort key: durable 10, telescope 20, agent 30, media 50. */
747
+ order: number;
748
+ /** The console's resolved gate (what its own routes run). Never throws. */
749
+ authorize(context: ExecutionContext): Promise<AviaryConsoleDecision>;
750
+ }
751
+ /** The value at {@link AVIARY_CONSOLES_SLOT}. Data only, so every console's copy is identical. */
752
+ interface AviaryConsoleRegistry {
753
+ readonly version: 1;
754
+ readonly entries: AviaryConsoleEntry[];
755
+ }
756
+ /** One console as `GET <api>/consoles` returns it. */
757
+ interface VisibleConsole {
758
+ id: string;
759
+ title: string;
760
+ icon: AviaryConsoleIcon;
761
+ href: string;
762
+ }
763
+ /** The answer of `GET <api>/consoles`. */
764
+ interface VisibleConsoles {
765
+ version: 1;
766
+ current: string;
767
+ consoles: VisibleConsole[];
768
+ }
769
+ /** How long another console's `authorize` may take before it is left out. */
770
+ declare const CONSOLE_PROBE_TIMEOUT_MS: number;
771
+ /**
772
+ * Adds a console to the process's switcher registry, creating it when absent. Returns a function
773
+ * that removes the entry again, or `undefined` when it was not added (another registry version, or
774
+ * the id is taken: logged as a warning). A bad `id` or `path` throws.
775
+ */
776
+ declare function registerAviaryConsole(entry: AviaryConsoleEntry, logger?: {
777
+ warn(message: string): void;
778
+ }): (() => void) | undefined;
779
+ /**
780
+ * The consoles other than `selfId` the viewer may open, by `order` then `id`. Every other entry's
781
+ * `authorize` runs in parallel, each given `timeoutMs`; a timeout, a rejection or any denial hides
782
+ * it. No reason is ever returned.
783
+ */
784
+ declare function listVisibleConsoles(registry: AviaryConsoleRegistry | undefined, selfId: string, context: ExecutionContext, timeoutMs?: number): Promise<VisibleConsoles>;
785
+ /** The durable console's id in the registry. */
786
+ declare const DURABLE_CONSOLE_ID: string;
787
+ /**
788
+ * Registers the durable console into the switcher registry (the console's page path, gated by its
789
+ * resolved `authorize`). Provided only when the console's routes are mounted; removed on shutdown.
790
+ */
791
+ declare class DurableConsoleRegistration implements OnModuleInit, OnModuleDestroy {
792
+ #private;
793
+ private readonly basePath;
794
+ private readonly decide;
795
+ constructor(basePath: string, decide: ConsoleDecide);
796
+ onModuleInit(): void;
797
+ onModuleDestroy(): void;
798
+ }
799
+ /** What the route hands on to the other consoles' `authorize`: this request's `ExecutionContext`. */
800
+ interface CurrentContext {
801
+ context: ExecutionContext;
802
+ }
803
+ /**
804
+ * `GET <api>/consoles`: the other Aviary consoles this viewer may open. Behind the console's own
805
+ * access check, like every API route, so only someone who may open this console learns the list.
806
+ */
807
+ declare class DurableConsolesController {
808
+ consoles(current: CurrentContext): Promise<VisibleConsoles>;
809
+ }
810
+
811
+ export { AVIARY_CONSOLES_SLOT, type AviaryConsoleDecision, type AviaryConsoleEntry, type AviaryConsoleIcon, type AviaryConsoleRegistry, CONSOLE_AUTHORIZE_DECIDE, CONSOLE_AUTHORIZE_MISSING_WARNING, CONSOLE_GATE, CONSOLE_PAGE_METADATA, CONSOLE_PROBE_TIMEOUT_MS, CONSOLE_PUBLIC_METADATA, ConsoleAccessDenied, type ConsoleAuthorize, ConsoleAuthorizeFilter, ConsoleAuthorizeGuard, type ConsoleAuthorizeResult, type ConsoleAuthorizer, type ConsoleAuthorizerClass, type ConsoleDecide, type ConsoleDecision, type ConsoleGate, ConsolePage, type ConsolePolicyCheck, ConsolePublic, DASHBOARD_API_PATH, DASHBOARD_BASE_PATH, DEV_TOOLS_SLOT, DURABLE_CONSOLE_ID, DURABLE_DASHBOARD_CONFIG_ID, DashboardService, type DevToolCall, type DevToolInputProperty, type DevToolInputSchema, type DevToolsDecision, DurableApiController, DurableApiControllerBase, DurableApiModule, DurableConsoleRegistration, DurableConsolesController, DurableDashboardModule, type DurableDashboardOptions, type DurableDevTool, DurableDevToolsRegistration, DurableUiController, DurableUiControllerBase, MAX_RUN_IDS, UseConsoleAuthorize, type VisibleConsole, type VisibleConsoles, type WorkflowLifecyclePage, anyAuthorize, authorizeByToken, durableDevTools, listVisibleConsoles, normalizeConsoleResult, registerAviaryConsole, resolveConsoleAuthorize };
@@ -1,4 +1,4 @@
1
- import { HttpException, ExecutionContext, Type, ExceptionFilter, ArgumentsHost, CanActivate, Logger, DynamicModule, StreamableFile } from '@nestjs/common';
1
+ import { HttpException, ExecutionContext, Type, ExceptionFilter, ArgumentsHost, CanActivate, Logger, DynamicModule, StreamableFile, OnModuleInit, OnModuleDestroy } from '@nestjs/common';
2
2
  import { HttpAdapterHost, ModuleRef } from '@nestjs/core';
3
3
  import * as _dudousxd_nestjs_durable_core from '@dudousxd/nestjs-durable-core';
4
4
  import { RunGateway, StateStore, WorkflowEngine, ScheduleListQuery, ScheduleDescription, RunResult, RunQuery, RunListItem, RunFacetQuery, RunFacetRow, RunValueAxis, RunValueFacetOptions, RunValueFacetRow, DurableTopology, GroupHealth, RunDetailOptions, RunDetail, FanPageQuery, FanPage, RepublishLifecycleResult, WorkflowLifecycleLinks, UpdateResult, EngineEvent, AttributeFilter } from '@dudousxd/nestjs-durable-core';
@@ -8,8 +8,14 @@ import { Observable } from 'rxjs';
8
8
  import * as _dudousxd_nestjs_filter from '@dudousxd/nestjs-filter';
9
9
  import { FilterRunner } from '@dudousxd/nestjs-filter';
10
10
 
11
+ /**
12
+ * What an `authorize` check answers. An allow may name who it let in (`caller`, for example
13
+ * `'user:42'`): the dev MCP endpoint logs it as the caller of a developer tool. Never put a secret
14
+ * in it.
15
+ */
11
16
  type ConsoleAuthorizeResult = boolean | {
12
17
  allowed: true;
18
+ caller?: string;
13
19
  } | {
14
20
  allowed: false;
15
21
  reason?: 'unauthenticated' | 'forbidden';
@@ -31,6 +37,7 @@ type ConsoleAuthorize = ((context: ExecutionContext) => ConsoleAuthorizeResult |
31
37
  }>) | ConsolePolicyCheck | string;
32
38
  type ConsoleDecision = {
33
39
  allowed: true;
40
+ caller?: string;
34
41
  } | {
35
42
  allowed: false;
36
43
  reason: 'unauthenticated' | 'forbidden';
@@ -65,11 +72,23 @@ declare function resolveConsoleAuthorize(authorize: ConsoleAuthorize | undefined
65
72
  /**
66
73
  * Allows a request carrying `Authorization: Bearer <token>` (compared timing-safe); anything else
67
74
  * is `unauthenticated`. Header only: no query string, no custom header. Throws when `token` is
68
- * empty, so a missing env var fails at config time instead of opening the console.
75
+ * empty, so a missing env var fails at config time instead of opening the console. The allow names
76
+ * its caller `token:<first 12 hex of sha256(token)>`, never the token.
69
77
  */
70
78
  declare function authorizeByToken(options: {
71
79
  token: string | undefined;
72
80
  }): ConsoleAuthorize;
81
+ /**
82
+ * One `authorize` from several: allowed when any form allows (checked in order, stopping at the
83
+ * first that does, whose `caller` it keeps); otherwise `unauthenticated` when any form said so
84
+ * (keeping the first `redirectTo`), else `forbidden`. Each form is any `authorize` value: a
85
+ * function, a class, a lazy import, `{ policy, ability }` or a gate name.
86
+ *
87
+ * ```ts
88
+ * authorize: anyAuthorize(authorizeByToken({ token: process.env.CONSOLE_TOKEN }), AdminSessionAuthorizer)
89
+ * ```
90
+ */
91
+ declare function anyAuthorize(...forms: ConsoleAuthorize[]): ConsoleAuthorizerClass;
73
92
  /** DI token of the resolved {@link ConsoleDecide} the guard runs. */
74
93
  declare const CONSOLE_AUTHORIZE_DECIDE: unique symbol;
75
94
  /** Marks a controller as serving pages: a denied `GET` that accepts HTML gets a page, not JSON. */
@@ -241,6 +260,22 @@ declare class DashboardService {
241
260
  * rows behind or signal non-webhook tokens. Control-plane-only.
242
261
  */
243
262
  deliverWebhook(token: string, body: unknown): Promise<RunResult | null>;
263
+ /**
264
+ * What this deployment can serve: `controlPlane` (signals, run events, updates, metrics) and
265
+ * `schedules` (persisted schedules). Both are false on a store-less tenant.
266
+ */
267
+ capabilities(): {
268
+ controlPlane: boolean;
269
+ schedules: boolean;
270
+ };
271
+ /** Whether `runId` names a run the caller may see (tenancy applies). */
272
+ runExists(runId: string): Promise<boolean>;
273
+ /**
274
+ * Deliver `payload` to the run waiting on `token` (`engine.signal`). Null when no run the caller
275
+ * may see waits on it yet: the engine then buffers the payload for the run that waits next.
276
+ * Control-plane-only.
277
+ */
278
+ signal(token: string, payload: unknown): Promise<RunResult | null>;
244
279
  /** Side-effect-free read of a value a run published via `ctx.setEvent` (a live query). Control-plane-only. */
245
280
  getEvent(runId: string, key: string): Promise<unknown>;
246
281
  /** Deliver a validated `ctx.onUpdate` to a run; the validator may reject it (see UpdateResult). Control-plane-only. */
@@ -533,6 +568,12 @@ interface DurableDashboardOptions {
533
568
  * strings that keep their meaning (where the console lives) whether or not this module mounts it.
534
569
  */
535
570
  routes?: boolean;
571
+ /**
572
+ * Register the console's reads and run/schedule actions as developer tools on the agent MCP
573
+ * server's dev endpoint (`/mcp/aviary`), gated by this console's `authorize`. Default: on when
574
+ * the console's routes are mounted, off with `routes: false`.
575
+ */
576
+ devTools?: boolean;
536
577
  }
537
578
  /**
538
579
  * Holds the JSON API controller + its read service, mounted on its own path by `forRoot`. Its own
@@ -548,6 +589,8 @@ declare class DurableApiModule {
548
589
  decorators?: ClassDecorator[];
549
590
  /** See {@link DurableDashboardOptions.authorize}. */
550
591
  authorize?: ConsoleAuthorize;
592
+ /** See {@link DurableDashboardOptions.devTools}. Default: on when the routes are mounted. */
593
+ devTools?: boolean;
551
594
  }): DynamicModule;
552
595
  }
553
596
  /**
@@ -565,9 +608,12 @@ declare class DurableDashboardModule {
565
608
  }
566
609
 
567
610
  /** DI token carrying the UI mount base (e.g. `/durable`). */
568
- declare const DASHBOARD_BASE_PATH: unique symbol;
611
+ declare const DASHBOARD_BASE_PATH: symbol;
569
612
  /** DI token carrying the JSON API base the SPA fetches from (e.g. `/api/durable`). */
570
- declare const DASHBOARD_API_PATH: unique symbol;
613
+ declare const DASHBOARD_API_PATH: symbol;
614
+
615
+ /** The id of the page's JSON config block. */
616
+ declare const DURABLE_DASHBOARD_CONFIG_ID = "durable-dashboard-config";
571
617
  /**
572
618
  * Serves the bundled control-plane SPA at the configured base (+ hashed assets at `<base>/assets`).
573
619
  * The controller routes are relative: the mounted {@link DurableUiController} gets its path from
@@ -585,6 +631,11 @@ declare class DurableUiControllerBase {
585
631
  private readonly dir;
586
632
  constructor(basePath: string, apiBasePath: string);
587
633
  index(): string;
634
+ /**
635
+ * The page's JSON config block (`durable-dashboard-config`, CSP-safe: data, not script). It
636
+ * carries `switcher` only when another Aviary console is registered.
637
+ */
638
+ private configBlock;
588
639
  asset(file: string): StreamableFile;
589
640
  }
590
641
  /**
@@ -596,4 +647,165 @@ declare class DurableUiControllerBase {
596
647
  declare class DurableUiController extends DurableUiControllerBase {
597
648
  }
598
649
 
599
- export { CONSOLE_AUTHORIZE_DECIDE, CONSOLE_AUTHORIZE_MISSING_WARNING, CONSOLE_GATE, CONSOLE_PAGE_METADATA, CONSOLE_PUBLIC_METADATA, ConsoleAccessDenied, type ConsoleAuthorize, ConsoleAuthorizeFilter, ConsoleAuthorizeGuard, type ConsoleAuthorizeResult, type ConsoleAuthorizer, type ConsoleAuthorizerClass, type ConsoleDecide, type ConsoleDecision, type ConsoleGate, ConsolePage, type ConsolePolicyCheck, ConsolePublic, DASHBOARD_API_PATH, DASHBOARD_BASE_PATH, DashboardService, DurableApiController, DurableApiControllerBase, DurableApiModule, DurableDashboardModule, type DurableDashboardOptions, DurableUiController, DurableUiControllerBase, UseConsoleAuthorize, type WorkflowLifecyclePage, authorizeByToken, normalizeConsoleResult, resolveConsoleAuthorize };
650
+ /** The process-wide slot `@dudousxd/nestjs-agent-mcp-server` serves on its dev MCP endpoint. */
651
+ declare const DEV_TOOLS_SLOT: symbol;
652
+ /** One property of a {@link DevToolInputSchema}. */
653
+ interface DevToolInputProperty {
654
+ type: 'string' | 'number' | 'integer' | 'boolean' | 'array';
655
+ description?: string;
656
+ enum?: readonly string[];
657
+ /** Arrays hold strings only. */
658
+ items?: {
659
+ type: 'string';
660
+ };
661
+ minimum?: number;
662
+ maximum?: number;
663
+ }
664
+ /** An object of scalar / enum / array-of-string properties. */
665
+ interface DevToolInputSchema {
666
+ type: 'object';
667
+ properties: Record<string, DevToolInputProperty>;
668
+ required?: string[];
669
+ }
670
+ /** What the slot's `authorize` answers: the console's resolved decision. */
671
+ type DevToolsDecision = {
672
+ allowed: true;
673
+ caller?: string;
674
+ } | {
675
+ allowed: false;
676
+ reason: 'unauthenticated' | 'forbidden';
677
+ redirectTo?: string;
678
+ };
679
+ /** What a tool's `run` receives besides its input. */
680
+ interface DevToolCall {
681
+ context: ExecutionContext;
682
+ caller: {
683
+ id: string;
684
+ via: 'token' | 'session' | 'open';
685
+ };
686
+ limits: {
687
+ maxRows: number;
688
+ maxBytes: number;
689
+ };
690
+ }
691
+ /** One developer tool, as the dev-tools slot takes it. */
692
+ interface DurableDevTool {
693
+ /** `durable_<verb>_<noun>`. */
694
+ name: string;
695
+ /** `read` tools are listed by default; `action` tools only when the app opts in. */
696
+ kind: 'read' | 'action';
697
+ description: string;
698
+ input: DevToolInputSchema;
699
+ /** Set on actions that cancel. */
700
+ destructive?: boolean;
701
+ /** Capability, not access: hides a tool this deployment cannot run. */
702
+ available?(): boolean | Promise<boolean>;
703
+ run(input: Record<string, unknown>, call?: DevToolCall): Promise<unknown>;
704
+ }
705
+ /** Runs `durable_retry_run` / `durable_cancel_run` act on at most per call. */
706
+ declare const MAX_RUN_IDS = 100;
707
+ /**
708
+ * The durable developer tools (lib `durable`): the console's reads and its run and schedule
709
+ * actions, through the same {@link DashboardService} methods its API serves, so tenancy and the
710
+ * app's redaction apply. Signals, run events and schedules are available only on the control plane.
711
+ */
712
+ declare function durableDevTools(service: DashboardService): DurableDevTool[];
713
+ /**
714
+ * Registers the durable tools into the dev-tools slot, gated by the console's own resolved
715
+ * `authorize`, when the console is mounted (or `devTools: true`). Removed again on shutdown.
716
+ */
717
+ declare class DurableDevToolsRegistration implements OnModuleInit, OnModuleDestroy {
718
+ #private;
719
+ private readonly enabled;
720
+ private readonly service;
721
+ private readonly decide;
722
+ constructor(enabled: boolean, service: DashboardService, decide: ConsoleDecide);
723
+ onModuleInit(): void;
724
+ onModuleDestroy(): void;
725
+ }
726
+
727
+ /** The process-wide slot every Aviary console registers into (created by whichever boots first). */
728
+ declare const AVIARY_CONSOLES_SLOT: symbol;
729
+ /** The icon a console shows in the switcher. An unknown value renders as `generic`. */
730
+ type AviaryConsoleIcon = 'workflow' | 'telescope' | 'media' | 'payments' | 'agent' | 'identity' | 'generic';
731
+ /** What a console's `authorize` answers; only `allowed: true` lists it. */
732
+ interface AviaryConsoleDecision {
733
+ allowed: boolean;
734
+ reason?: string;
735
+ redirectTo?: string;
736
+ }
737
+ /** One console the switcher can list. */
738
+ interface AviaryConsoleEntry {
739
+ /** `/^[a-z][a-z0-9-]*$/`: `'durable'`, `'telescope'`, `'agent'`, `'media'`, … */
740
+ id: string;
741
+ /** Product title: `'Workflows'`, `'Telescope'`, `'Agents'`, `'Media'`. */
742
+ title: string;
743
+ icon: AviaryConsoleIcon;
744
+ /** Same-origin absolute path of the console's page (`/durable`). */
745
+ path: string;
746
+ /** Sort key: durable 10, telescope 20, agent 30, media 50. */
747
+ order: number;
748
+ /** The console's resolved gate (what its own routes run). Never throws. */
749
+ authorize(context: ExecutionContext): Promise<AviaryConsoleDecision>;
750
+ }
751
+ /** The value at {@link AVIARY_CONSOLES_SLOT}. Data only, so every console's copy is identical. */
752
+ interface AviaryConsoleRegistry {
753
+ readonly version: 1;
754
+ readonly entries: AviaryConsoleEntry[];
755
+ }
756
+ /** One console as `GET <api>/consoles` returns it. */
757
+ interface VisibleConsole {
758
+ id: string;
759
+ title: string;
760
+ icon: AviaryConsoleIcon;
761
+ href: string;
762
+ }
763
+ /** The answer of `GET <api>/consoles`. */
764
+ interface VisibleConsoles {
765
+ version: 1;
766
+ current: string;
767
+ consoles: VisibleConsole[];
768
+ }
769
+ /** How long another console's `authorize` may take before it is left out. */
770
+ declare const CONSOLE_PROBE_TIMEOUT_MS: number;
771
+ /**
772
+ * Adds a console to the process's switcher registry, creating it when absent. Returns a function
773
+ * that removes the entry again, or `undefined` when it was not added (another registry version, or
774
+ * the id is taken: logged as a warning). A bad `id` or `path` throws.
775
+ */
776
+ declare function registerAviaryConsole(entry: AviaryConsoleEntry, logger?: {
777
+ warn(message: string): void;
778
+ }): (() => void) | undefined;
779
+ /**
780
+ * The consoles other than `selfId` the viewer may open, by `order` then `id`. Every other entry's
781
+ * `authorize` runs in parallel, each given `timeoutMs`; a timeout, a rejection or any denial hides
782
+ * it. No reason is ever returned.
783
+ */
784
+ declare function listVisibleConsoles(registry: AviaryConsoleRegistry | undefined, selfId: string, context: ExecutionContext, timeoutMs?: number): Promise<VisibleConsoles>;
785
+ /** The durable console's id in the registry. */
786
+ declare const DURABLE_CONSOLE_ID: string;
787
+ /**
788
+ * Registers the durable console into the switcher registry (the console's page path, gated by its
789
+ * resolved `authorize`). Provided only when the console's routes are mounted; removed on shutdown.
790
+ */
791
+ declare class DurableConsoleRegistration implements OnModuleInit, OnModuleDestroy {
792
+ #private;
793
+ private readonly basePath;
794
+ private readonly decide;
795
+ constructor(basePath: string, decide: ConsoleDecide);
796
+ onModuleInit(): void;
797
+ onModuleDestroy(): void;
798
+ }
799
+ /** What the route hands on to the other consoles' `authorize`: this request's `ExecutionContext`. */
800
+ interface CurrentContext {
801
+ context: ExecutionContext;
802
+ }
803
+ /**
804
+ * `GET <api>/consoles`: the other Aviary consoles this viewer may open. Behind the console's own
805
+ * access check, like every API route, so only someone who may open this console learns the list.
806
+ */
807
+ declare class DurableConsolesController {
808
+ consoles(current: CurrentContext): Promise<VisibleConsoles>;
809
+ }
810
+
811
+ export { AVIARY_CONSOLES_SLOT, type AviaryConsoleDecision, type AviaryConsoleEntry, type AviaryConsoleIcon, type AviaryConsoleRegistry, CONSOLE_AUTHORIZE_DECIDE, CONSOLE_AUTHORIZE_MISSING_WARNING, CONSOLE_GATE, CONSOLE_PAGE_METADATA, CONSOLE_PROBE_TIMEOUT_MS, CONSOLE_PUBLIC_METADATA, ConsoleAccessDenied, type ConsoleAuthorize, ConsoleAuthorizeFilter, ConsoleAuthorizeGuard, type ConsoleAuthorizeResult, type ConsoleAuthorizer, type ConsoleAuthorizerClass, type ConsoleDecide, type ConsoleDecision, type ConsoleGate, ConsolePage, type ConsolePolicyCheck, ConsolePublic, DASHBOARD_API_PATH, DASHBOARD_BASE_PATH, DEV_TOOLS_SLOT, DURABLE_CONSOLE_ID, DURABLE_DASHBOARD_CONFIG_ID, DashboardService, type DevToolCall, type DevToolInputProperty, type DevToolInputSchema, type DevToolsDecision, DurableApiController, DurableApiControllerBase, DurableApiModule, DurableConsoleRegistration, DurableConsolesController, DurableDashboardModule, type DurableDashboardOptions, type DurableDevTool, DurableDevToolsRegistration, DurableUiController, DurableUiControllerBase, MAX_RUN_IDS, UseConsoleAuthorize, type VisibleConsole, type VisibleConsoles, type WorkflowLifecyclePage, anyAuthorize, authorizeByToken, durableDevTools, listVisibleConsoles, normalizeConsoleResult, registerAviaryConsole, resolveConsoleAuthorize };