@ethisyscore/plugin-ui 1.123.0 → 1.125.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.
@@ -1087,6 +1087,116 @@ declare function createReactRouterShim(options?: ReactRouterShimOptions): {
1087
1087
  */
1088
1088
  declare function usePluginRealtime(typeCode: string, handler: (payload: unknown) => void): void;
1089
1089
 
1090
+ /**
1091
+ * A background operation as a plugin surface sees it through the host's `plugin-operations:*`
1092
+ * tools and the plugin-group push. `kind` and `parentEntityType` are the plugin's own LOCAL names:
1093
+ * the host strips its namespacing before anything reaches a surface.
1094
+ */
1095
+ interface PluginOperation {
1096
+ operationId: string;
1097
+ kind: string;
1098
+ status: PluginOperationStatus | string;
1099
+ currentStageCode?: string | null;
1100
+ currentStageLabel?: string | null;
1101
+ stageIndex?: number | null;
1102
+ currentStageOrdinal?: number | null;
1103
+ totalStages?: number | null;
1104
+ stageProgressCurrent?: number | null;
1105
+ stageProgressTotal?: number | null;
1106
+ message?: string | null;
1107
+ errorMessage?: string | null;
1108
+ errorCode?: string | null;
1109
+ parentEntityType?: string | null;
1110
+ parentEntityId?: string | null;
1111
+ retryAttempt?: number;
1112
+ startedUtc?: string | null;
1113
+ completedUtc?: string | null;
1114
+ lastUpdatedUtc?: string;
1115
+ estimatedCompletionUtc?: string | null;
1116
+ eventSequence: number;
1117
+ /** Only populated by `plugin-operations:get` (and so by {@link useBackgroundOperation}). */
1118
+ resultPayloadJson?: string | null;
1119
+ }
1120
+ /** The statuses the host records. Terminal ones are `Succeeded`, `Failed` and `Cancelled`. */
1121
+ type PluginOperationStatus = "Pending" | "Running" | "PausedRateLimited" | "Succeeded" | "Failed" | "Cancelled";
1122
+ /** Payload of the `operations.plugin-operation.state-changed` push. */
1123
+ interface PluginOperationStateChanged extends Omit<PluginOperation, "resultPayloadJson"> {
1124
+ extensionId: string;
1125
+ previousStatus: string;
1126
+ }
1127
+ /** Type code of the host's plugin-group push for a plugin's own operation state changes. */
1128
+ declare const PLUGIN_OPERATION_STATE_CHANGED = "operations.plugin-operation.state-changed";
1129
+ /** The host tools the hooks read through. Declare the ones you use under `McpToolDependencies`. */
1130
+ declare const PLUGIN_OPERATION_TOOLS: {
1131
+ readonly get: "plugin-operations:get";
1132
+ readonly listByParent: "plugin-operations:list-by-parent";
1133
+ readonly listActive: "plugin-operations:list-active";
1134
+ readonly latestTerminalByParent: "plugin-operations:latest-terminal-by-parent";
1135
+ };
1136
+ /** Poll cadence used ONLY when the host supplies no realtime source (matches the host web). */
1137
+ declare const OPERATION_FALLBACK_POLL_MS = 8000;
1138
+
1139
+ /**
1140
+ * Follows one of this plugin's own background operations by id: its stage, progress, outcome and,
1141
+ * once it has finished, the result payload the plugin recorded.
1142
+ *
1143
+ * Reads through `plugin-operations:get` and then follows the host's push, merging each state change
1144
+ * by `eventSequence` so a late delivery cannot move the operation backwards. When the operation
1145
+ * reaches a terminal state it refetches once, because the push carries no result payload. Polls
1146
+ * every 8 s only when the host supplied no realtime source and the operation is still running.
1147
+ *
1148
+ * The data is `PluginOperation | null`; a missing operation, or one that belongs to another app,
1149
+ * surfaces as the query's error.
1150
+ */
1151
+ declare function useBackgroundOperation(operationId: string | null | undefined): _tanstack_react_query.UseQueryResult<NoInfer<PluginOperation | null>, Error>;
1152
+
1153
+ /**
1154
+ * Follows this plugin's own background operations against one parent entity (for example every
1155
+ * import of one repository), newest first, at most 50.
1156
+ *
1157
+ * `parentEntityType` is the plugin's LOCAL type name, the one it passed when starting the
1158
+ * operation. Reads through `plugin-operations:list-by-parent`, then merges each pushed state change
1159
+ * for this parent by `eventSequence`, prepending operations that start after the first read. Polls
1160
+ * every 8 s only when the host supplied no realtime source and some operation is still running.
1161
+ */
1162
+ declare function useOperationsByParent(parentEntityType: string, parentEntityId: string | null | undefined): _tanstack_react_query.UseQueryResult<NoInfer<PluginOperation[]>, Error>;
1163
+
1164
+ /**
1165
+ * The newest FINISHED operation (succeeded, failed or cancelled) of this plugin against one parent
1166
+ * entity, or null: the "last import failed at 10:42" line on a detail page.
1167
+ *
1168
+ * Reads through `plugin-operations:latest-terminal-by-parent` and refetches when a pushed state
1169
+ * change for this parent reaches a terminal status. A finished row cannot change, so there is no
1170
+ * fallback poll; without a realtime source the value refreshes on the query's own refetches.
1171
+ */
1172
+ declare function useLatestTerminalOperationByParent(parentEntityType: string, parentEntityId: string | null | undefined): _tanstack_react_query.UseQueryResult<NoInfer<PluginOperation | null>, Error>;
1173
+
1174
+ /**
1175
+ * Matches an operation's kind against the plugin's own (unscoped) kind. Mirrors the .NET
1176
+ * `HasKind` / `BackgroundOperationScope.Matches` rule (analyser ECP0016): the host-namespaced
1177
+ * form `p:{extensionId}:` is stripped before comparing, so the check is right whether the value
1178
+ * came from the de-namespacing `plugin-operations:*` tools or anywhere else. Never compare kinds
1179
+ * with `===`.
1180
+ */
1181
+ declare function hasKind(operation: {
1182
+ kind: string;
1183
+ } | string | null | undefined, unscopedKind: string): boolean;
1184
+ /** The parent-type counterpart of {@link hasKind}; strips `po:{scopeHash}:` before comparing. */
1185
+ declare function hasParentEntityType(operation: {
1186
+ parentEntityType?: string | null;
1187
+ } | string | null | undefined, unscopedParentEntityType: string): boolean;
1188
+
1189
+ /** Whether an operation has finished: succeeded, failed or cancelled. */
1190
+ declare function isTerminalOperationStatus(status: string | null | undefined): boolean;
1191
+
1192
+ /** Query keys for the operation hooks. The plugin's own query client already isolates the realm. */
1193
+ declare const pluginOperationKeys: {
1194
+ all: readonly ["plugin-operations"];
1195
+ byId: (operationId: string) => readonly ["plugin-operations", "get", string];
1196
+ byParent: (parentEntityType: string, parentEntityId: string) => readonly ["plugin-operations", "by-parent", string, string];
1197
+ latestTerminalByParent: (parentEntityType: string, parentEntityId: string) => readonly ["plugin-operations", "latest-terminal", string, string];
1198
+ };
1199
+
1090
1200
  /**
1091
1201
  * Advisory client-side upload ceiling (UX only). The kernel's streaming route
1092
1202
  * applies the authoritative size cap mid-stream; this default lets the hook
@@ -1458,4 +1568,4 @@ interface MenuConfigHostSidebarOptions {
1458
1568
  */
1459
1569
  declare function menuConfigToHostSidebarInput(config: HeaderMenuItem[], opts: MenuConfigHostSidebarOptions): HostSidebarHookInput;
1460
1570
 
1461
- export { type AuthenticatedQueryResult, type CurrencyInfo, type CurrencySelector, DEFAULT_MAX_UPLOAD_BYTES, type DefinePlatformReactPluginOverlayOptions, type DefinePlatformReactPluginPageOptions, EHX_PLUGIN_PORTAL_ATTR, EHX_PLUGIN_PORTAL_CLASS, EHX_PLUGIN_ROOT_CLASS, HostSidebarHookInput, HostSidebarInput, type InsetLease, LIST_CURRENCIES_TOOL, type ManagedLifecycle, type McpToolArgs, type McpToolContract, type McpToolContracts, type McpToolResult, type MenuConfigHostSidebarOptions, MissingViewFallback, ORGANISATION_SETTINGS_URI, OVERLAY_HOST_CONTRACT_VERSION, type OverlayHostApi, type OverlayHostCapabilities, OverlayHostContext, type PlatformReactOverlayProps, type PluginOverlayDefinerConfig, type PluginPageDefinerConfig, PluginPortalScope, type PluginQueryMeta, PluginStyleScope, REPORTING_CURRENCY_TOOL, type ReactRouterShimOptions, SurfaceBaseContext, type SurfaceBaseValue, TemplateContext, type TemplateManifest, type ToHostSidebarInputOptions, ToolInvoker, TypedMcpService, type UseCurrencyResult, type UseMcpUploadOptions, type UseMcpUploadResult, type UseMcpUploadTarget, type ViewComponent, buildSurfaceUrl, createPluginOverlayDefiner, createPluginPageDefiner, createPluginQueryClient, createReactRouterShim, createUseView, definePlatformReactPluginOverlay, definePlatformReactPluginPage, deriveHostEntityToken, injectPluginStyles, isComponent, mcpTool, menuConfigToHostSidebarInput, normaliseSlug, resolveSurfaceBase, surfacePathFor, toHostSidebarInput, useAuthenticatedQueries, useAuthenticatedQuery, useCurrency, useManagedLifecycle, useMcpUpload, useOrgFormatSync, useOverlayHost, usePluginRealtime, useReportingCurrencySync, useSurfaceQueryClient, useSurfaceUrl, useTypedToolInvokerMap, useView };
1571
+ export { type AuthenticatedQueryResult, type CurrencyInfo, type CurrencySelector, DEFAULT_MAX_UPLOAD_BYTES, type DefinePlatformReactPluginOverlayOptions, type DefinePlatformReactPluginPageOptions, EHX_PLUGIN_PORTAL_ATTR, EHX_PLUGIN_PORTAL_CLASS, EHX_PLUGIN_ROOT_CLASS, HostSidebarHookInput, HostSidebarInput, type InsetLease, LIST_CURRENCIES_TOOL, type ManagedLifecycle, type McpToolArgs, type McpToolContract, type McpToolContracts, type McpToolResult, type MenuConfigHostSidebarOptions, MissingViewFallback, OPERATION_FALLBACK_POLL_MS, ORGANISATION_SETTINGS_URI, OVERLAY_HOST_CONTRACT_VERSION, type OverlayHostApi, type OverlayHostCapabilities, OverlayHostContext, PLUGIN_OPERATION_STATE_CHANGED, PLUGIN_OPERATION_TOOLS, type PlatformReactOverlayProps, type PluginOperation, type PluginOperationStateChanged, type PluginOperationStatus, type PluginOverlayDefinerConfig, type PluginPageDefinerConfig, PluginPortalScope, type PluginQueryMeta, PluginStyleScope, REPORTING_CURRENCY_TOOL, type ReactRouterShimOptions, SurfaceBaseContext, type SurfaceBaseValue, TemplateContext, type TemplateManifest, type ToHostSidebarInputOptions, ToolInvoker, TypedMcpService, type UseCurrencyResult, type UseMcpUploadOptions, type UseMcpUploadResult, type UseMcpUploadTarget, type ViewComponent, buildSurfaceUrl, createPluginOverlayDefiner, createPluginPageDefiner, createPluginQueryClient, createReactRouterShim, createUseView, definePlatformReactPluginOverlay, definePlatformReactPluginPage, deriveHostEntityToken, hasKind, hasParentEntityType, injectPluginStyles, isComponent, isTerminalOperationStatus, mcpTool, menuConfigToHostSidebarInput, normaliseSlug, pluginOperationKeys, resolveSurfaceBase, surfacePathFor, toHostSidebarInput, useAuthenticatedQueries, useAuthenticatedQuery, useBackgroundOperation, useCurrency, useLatestTerminalOperationByParent, useManagedLifecycle, useMcpUpload, useOperationsByParent, useOrgFormatSync, useOverlayHost, usePluginRealtime, useReportingCurrencySync, useSurfaceQueryClient, useSurfaceUrl, useTypedToolInvokerMap, useView };
@@ -1087,6 +1087,116 @@ declare function createReactRouterShim(options?: ReactRouterShimOptions): {
1087
1087
  */
1088
1088
  declare function usePluginRealtime(typeCode: string, handler: (payload: unknown) => void): void;
1089
1089
 
1090
+ /**
1091
+ * A background operation as a plugin surface sees it through the host's `plugin-operations:*`
1092
+ * tools and the plugin-group push. `kind` and `parentEntityType` are the plugin's own LOCAL names:
1093
+ * the host strips its namespacing before anything reaches a surface.
1094
+ */
1095
+ interface PluginOperation {
1096
+ operationId: string;
1097
+ kind: string;
1098
+ status: PluginOperationStatus | string;
1099
+ currentStageCode?: string | null;
1100
+ currentStageLabel?: string | null;
1101
+ stageIndex?: number | null;
1102
+ currentStageOrdinal?: number | null;
1103
+ totalStages?: number | null;
1104
+ stageProgressCurrent?: number | null;
1105
+ stageProgressTotal?: number | null;
1106
+ message?: string | null;
1107
+ errorMessage?: string | null;
1108
+ errorCode?: string | null;
1109
+ parentEntityType?: string | null;
1110
+ parentEntityId?: string | null;
1111
+ retryAttempt?: number;
1112
+ startedUtc?: string | null;
1113
+ completedUtc?: string | null;
1114
+ lastUpdatedUtc?: string;
1115
+ estimatedCompletionUtc?: string | null;
1116
+ eventSequence: number;
1117
+ /** Only populated by `plugin-operations:get` (and so by {@link useBackgroundOperation}). */
1118
+ resultPayloadJson?: string | null;
1119
+ }
1120
+ /** The statuses the host records. Terminal ones are `Succeeded`, `Failed` and `Cancelled`. */
1121
+ type PluginOperationStatus = "Pending" | "Running" | "PausedRateLimited" | "Succeeded" | "Failed" | "Cancelled";
1122
+ /** Payload of the `operations.plugin-operation.state-changed` push. */
1123
+ interface PluginOperationStateChanged extends Omit<PluginOperation, "resultPayloadJson"> {
1124
+ extensionId: string;
1125
+ previousStatus: string;
1126
+ }
1127
+ /** Type code of the host's plugin-group push for a plugin's own operation state changes. */
1128
+ declare const PLUGIN_OPERATION_STATE_CHANGED = "operations.plugin-operation.state-changed";
1129
+ /** The host tools the hooks read through. Declare the ones you use under `McpToolDependencies`. */
1130
+ declare const PLUGIN_OPERATION_TOOLS: {
1131
+ readonly get: "plugin-operations:get";
1132
+ readonly listByParent: "plugin-operations:list-by-parent";
1133
+ readonly listActive: "plugin-operations:list-active";
1134
+ readonly latestTerminalByParent: "plugin-operations:latest-terminal-by-parent";
1135
+ };
1136
+ /** Poll cadence used ONLY when the host supplies no realtime source (matches the host web). */
1137
+ declare const OPERATION_FALLBACK_POLL_MS = 8000;
1138
+
1139
+ /**
1140
+ * Follows one of this plugin's own background operations by id: its stage, progress, outcome and,
1141
+ * once it has finished, the result payload the plugin recorded.
1142
+ *
1143
+ * Reads through `plugin-operations:get` and then follows the host's push, merging each state change
1144
+ * by `eventSequence` so a late delivery cannot move the operation backwards. When the operation
1145
+ * reaches a terminal state it refetches once, because the push carries no result payload. Polls
1146
+ * every 8 s only when the host supplied no realtime source and the operation is still running.
1147
+ *
1148
+ * The data is `PluginOperation | null`; a missing operation, or one that belongs to another app,
1149
+ * surfaces as the query's error.
1150
+ */
1151
+ declare function useBackgroundOperation(operationId: string | null | undefined): _tanstack_react_query.UseQueryResult<NoInfer<PluginOperation | null>, Error>;
1152
+
1153
+ /**
1154
+ * Follows this plugin's own background operations against one parent entity (for example every
1155
+ * import of one repository), newest first, at most 50.
1156
+ *
1157
+ * `parentEntityType` is the plugin's LOCAL type name, the one it passed when starting the
1158
+ * operation. Reads through `plugin-operations:list-by-parent`, then merges each pushed state change
1159
+ * for this parent by `eventSequence`, prepending operations that start after the first read. Polls
1160
+ * every 8 s only when the host supplied no realtime source and some operation is still running.
1161
+ */
1162
+ declare function useOperationsByParent(parentEntityType: string, parentEntityId: string | null | undefined): _tanstack_react_query.UseQueryResult<NoInfer<PluginOperation[]>, Error>;
1163
+
1164
+ /**
1165
+ * The newest FINISHED operation (succeeded, failed or cancelled) of this plugin against one parent
1166
+ * entity, or null: the "last import failed at 10:42" line on a detail page.
1167
+ *
1168
+ * Reads through `plugin-operations:latest-terminal-by-parent` and refetches when a pushed state
1169
+ * change for this parent reaches a terminal status. A finished row cannot change, so there is no
1170
+ * fallback poll; without a realtime source the value refreshes on the query's own refetches.
1171
+ */
1172
+ declare function useLatestTerminalOperationByParent(parentEntityType: string, parentEntityId: string | null | undefined): _tanstack_react_query.UseQueryResult<NoInfer<PluginOperation | null>, Error>;
1173
+
1174
+ /**
1175
+ * Matches an operation's kind against the plugin's own (unscoped) kind. Mirrors the .NET
1176
+ * `HasKind` / `BackgroundOperationScope.Matches` rule (analyser ECP0016): the host-namespaced
1177
+ * form `p:{extensionId}:` is stripped before comparing, so the check is right whether the value
1178
+ * came from the de-namespacing `plugin-operations:*` tools or anywhere else. Never compare kinds
1179
+ * with `===`.
1180
+ */
1181
+ declare function hasKind(operation: {
1182
+ kind: string;
1183
+ } | string | null | undefined, unscopedKind: string): boolean;
1184
+ /** The parent-type counterpart of {@link hasKind}; strips `po:{scopeHash}:` before comparing. */
1185
+ declare function hasParentEntityType(operation: {
1186
+ parentEntityType?: string | null;
1187
+ } | string | null | undefined, unscopedParentEntityType: string): boolean;
1188
+
1189
+ /** Whether an operation has finished: succeeded, failed or cancelled. */
1190
+ declare function isTerminalOperationStatus(status: string | null | undefined): boolean;
1191
+
1192
+ /** Query keys for the operation hooks. The plugin's own query client already isolates the realm. */
1193
+ declare const pluginOperationKeys: {
1194
+ all: readonly ["plugin-operations"];
1195
+ byId: (operationId: string) => readonly ["plugin-operations", "get", string];
1196
+ byParent: (parentEntityType: string, parentEntityId: string) => readonly ["plugin-operations", "by-parent", string, string];
1197
+ latestTerminalByParent: (parentEntityType: string, parentEntityId: string) => readonly ["plugin-operations", "latest-terminal", string, string];
1198
+ };
1199
+
1090
1200
  /**
1091
1201
  * Advisory client-side upload ceiling (UX only). The kernel's streaming route
1092
1202
  * applies the authoritative size cap mid-stream; this default lets the hook
@@ -1458,4 +1568,4 @@ interface MenuConfigHostSidebarOptions {
1458
1568
  */
1459
1569
  declare function menuConfigToHostSidebarInput(config: HeaderMenuItem[], opts: MenuConfigHostSidebarOptions): HostSidebarHookInput;
1460
1570
 
1461
- export { type AuthenticatedQueryResult, type CurrencyInfo, type CurrencySelector, DEFAULT_MAX_UPLOAD_BYTES, type DefinePlatformReactPluginOverlayOptions, type DefinePlatformReactPluginPageOptions, EHX_PLUGIN_PORTAL_ATTR, EHX_PLUGIN_PORTAL_CLASS, EHX_PLUGIN_ROOT_CLASS, HostSidebarHookInput, HostSidebarInput, type InsetLease, LIST_CURRENCIES_TOOL, type ManagedLifecycle, type McpToolArgs, type McpToolContract, type McpToolContracts, type McpToolResult, type MenuConfigHostSidebarOptions, MissingViewFallback, ORGANISATION_SETTINGS_URI, OVERLAY_HOST_CONTRACT_VERSION, type OverlayHostApi, type OverlayHostCapabilities, OverlayHostContext, type PlatformReactOverlayProps, type PluginOverlayDefinerConfig, type PluginPageDefinerConfig, PluginPortalScope, type PluginQueryMeta, PluginStyleScope, REPORTING_CURRENCY_TOOL, type ReactRouterShimOptions, SurfaceBaseContext, type SurfaceBaseValue, TemplateContext, type TemplateManifest, type ToHostSidebarInputOptions, ToolInvoker, TypedMcpService, type UseCurrencyResult, type UseMcpUploadOptions, type UseMcpUploadResult, type UseMcpUploadTarget, type ViewComponent, buildSurfaceUrl, createPluginOverlayDefiner, createPluginPageDefiner, createPluginQueryClient, createReactRouterShim, createUseView, definePlatformReactPluginOverlay, definePlatformReactPluginPage, deriveHostEntityToken, injectPluginStyles, isComponent, mcpTool, menuConfigToHostSidebarInput, normaliseSlug, resolveSurfaceBase, surfacePathFor, toHostSidebarInput, useAuthenticatedQueries, useAuthenticatedQuery, useCurrency, useManagedLifecycle, useMcpUpload, useOrgFormatSync, useOverlayHost, usePluginRealtime, useReportingCurrencySync, useSurfaceQueryClient, useSurfaceUrl, useTypedToolInvokerMap, useView };
1571
+ export { type AuthenticatedQueryResult, type CurrencyInfo, type CurrencySelector, DEFAULT_MAX_UPLOAD_BYTES, type DefinePlatformReactPluginOverlayOptions, type DefinePlatformReactPluginPageOptions, EHX_PLUGIN_PORTAL_ATTR, EHX_PLUGIN_PORTAL_CLASS, EHX_PLUGIN_ROOT_CLASS, HostSidebarHookInput, HostSidebarInput, type InsetLease, LIST_CURRENCIES_TOOL, type ManagedLifecycle, type McpToolArgs, type McpToolContract, type McpToolContracts, type McpToolResult, type MenuConfigHostSidebarOptions, MissingViewFallback, OPERATION_FALLBACK_POLL_MS, ORGANISATION_SETTINGS_URI, OVERLAY_HOST_CONTRACT_VERSION, type OverlayHostApi, type OverlayHostCapabilities, OverlayHostContext, PLUGIN_OPERATION_STATE_CHANGED, PLUGIN_OPERATION_TOOLS, type PlatformReactOverlayProps, type PluginOperation, type PluginOperationStateChanged, type PluginOperationStatus, type PluginOverlayDefinerConfig, type PluginPageDefinerConfig, PluginPortalScope, type PluginQueryMeta, PluginStyleScope, REPORTING_CURRENCY_TOOL, type ReactRouterShimOptions, SurfaceBaseContext, type SurfaceBaseValue, TemplateContext, type TemplateManifest, type ToHostSidebarInputOptions, ToolInvoker, TypedMcpService, type UseCurrencyResult, type UseMcpUploadOptions, type UseMcpUploadResult, type UseMcpUploadTarget, type ViewComponent, buildSurfaceUrl, createPluginOverlayDefiner, createPluginPageDefiner, createPluginQueryClient, createReactRouterShim, createUseView, definePlatformReactPluginOverlay, definePlatformReactPluginPage, deriveHostEntityToken, hasKind, hasParentEntityType, injectPluginStyles, isComponent, isTerminalOperationStatus, mcpTool, menuConfigToHostSidebarInput, normaliseSlug, pluginOperationKeys, resolveSurfaceBase, surfacePathFor, toHostSidebarInput, useAuthenticatedQueries, useAuthenticatedQuery, useBackgroundOperation, useCurrency, useLatestTerminalOperationByParent, useManagedLifecycle, useMcpUpload, useOperationsByParent, useOrgFormatSync, useOverlayHost, usePluginRealtime, useReportingCurrencySync, useSurfaceQueryClient, useSurfaceUrl, useTypedToolInvokerMap, useView };
@@ -1,6 +1,6 @@
1
1
  import { createContext, useContext, useEffect, useState, useMemo, useRef, createElement, useCallback, useSyncExternalStore } from 'react';
2
2
  import * as reactQuery from '@tanstack/react-query';
3
- import { QueryClient, MutationCache, QueryCache, useQuery, useQueries, QueryClientProvider } from '@tanstack/react-query';
3
+ import { QueryClient, MutationCache, QueryCache, useQuery, useQueries, useQueryClient, QueryClientProvider } from '@tanstack/react-query';
4
4
  import { definePlatformReactPage, emitNavigation } from '@ethisyscore/components-react';
5
5
  import * as extensionRuntime from '@ethisyscore/extension-runtime/plugin';
6
6
  import { useHostIdentity, useMcpTool, useOptionalExtensionRuntimeTransport, usePluginRealtimeSource, useExtensionRuntimeTransport } from '@ethisyscore/extension-runtime/plugin';
@@ -745,6 +745,147 @@ function usePluginRealtime(typeCode, handler) {
745
745
  return source.subscribe(typeCode, (payload) => ref.current(payload));
746
746
  }, [source, typeCode]);
747
747
  }
748
+
749
+ // src/platform-react/operations/asStateChanged.ts
750
+ function asStateChanged(payload) {
751
+ if (payload == null || typeof payload !== "object") {
752
+ return null;
753
+ }
754
+ const candidate = payload;
755
+ return typeof candidate.operationId === "string" && typeof candidate.eventSequence === "number" ? candidate : null;
756
+ }
757
+
758
+ // src/platform-react/operations/mergeOperation.ts
759
+ function mergeOperation(current, event) {
760
+ if (current && current.eventSequence >= event.eventSequence) {
761
+ return current;
762
+ }
763
+ const { extensionId: _extensionId, previousStatus: _previousStatus, ...fields } = event;
764
+ return { ...fields, resultPayloadJson: current?.resultPayloadJson ?? null };
765
+ }
766
+ function mergeIntoList(current, event) {
767
+ const rows = current ?? [];
768
+ const index = rows.findIndex((r) => r.operationId === event.operationId);
769
+ if (index < 0) {
770
+ return [mergeOperation(null, event), ...rows];
771
+ }
772
+ const merged = mergeOperation(rows[index], event);
773
+ if (merged === rows[index]) {
774
+ return rows;
775
+ }
776
+ const next = rows.slice();
777
+ next[index] = merged;
778
+ return next;
779
+ }
780
+
781
+ // src/platform-react/operations/queryKeys.ts
782
+ var pluginOperationKeys = {
783
+ all: ["plugin-operations"],
784
+ byId: (operationId) => ["plugin-operations", "get", operationId],
785
+ byParent: (parentEntityType, parentEntityId) => ["plugin-operations", "by-parent", parentEntityType, parentEntityId],
786
+ latestTerminalByParent: (parentEntityType, parentEntityId) => ["plugin-operations", "latest-terminal", parentEntityType, parentEntityId]
787
+ };
788
+
789
+ // src/platform-react/operations/status.ts
790
+ var TERMINAL = /* @__PURE__ */ new Set(["Succeeded", "Failed", "Cancelled"]);
791
+ function isTerminalOperationStatus(status) {
792
+ return status != null && TERMINAL.has(status);
793
+ }
794
+
795
+ // src/platform-react/operations/types.ts
796
+ var PLUGIN_OPERATION_STATE_CHANGED = "operations.plugin-operation.state-changed";
797
+ var PLUGIN_OPERATION_TOOLS = {
798
+ get: "plugin-operations:get",
799
+ listByParent: "plugin-operations:list-by-parent",
800
+ listActive: "plugin-operations:list-active",
801
+ latestTerminalByParent: "plugin-operations:latest-terminal-by-parent"
802
+ };
803
+ var OPERATION_FALLBACK_POLL_MS = 8e3;
804
+
805
+ // src/platform-react/operations/useBackgroundOperation.ts
806
+ function useBackgroundOperation(operationId) {
807
+ const queryClient = useQueryClient();
808
+ const realtime = usePluginRealtimeSource();
809
+ const { invoke } = useMcpTool(PLUGIN_OPERATION_TOOLS.get);
810
+ const query = useQuery({
811
+ queryKey: pluginOperationKeys.byId(operationId ?? ""),
812
+ enabled: Boolean(operationId),
813
+ // Never undefined: TanStack Query rejects an undefined result.
814
+ queryFn: async () => await invoke({ operationId }) ?? null,
815
+ refetchInterval: (q) => realtime === null && q.state.data != null && !isTerminalOperationStatus(q.state.data.status) ? OPERATION_FALLBACK_POLL_MS : false
816
+ });
817
+ usePluginRealtime(PLUGIN_OPERATION_STATE_CHANGED, (payload) => {
818
+ const event = asStateChanged(payload);
819
+ if (!operationId || event?.operationId !== operationId) {
820
+ return;
821
+ }
822
+ const key = pluginOperationKeys.byId(operationId);
823
+ const before = queryClient.getQueryData(key);
824
+ const merged = mergeOperation(before, event);
825
+ queryClient.setQueryData(key, merged);
826
+ if (merged !== before && isTerminalOperationStatus(merged.status)) {
827
+ void queryClient.invalidateQueries({ queryKey: key });
828
+ }
829
+ });
830
+ return query;
831
+ }
832
+
833
+ // src/platform-react/operations/hasKind.ts
834
+ var KIND_SCOPE = /^p:[0-9a-f]{32}:/i;
835
+ var PARENT_SCOPE = /^po:[0-9A-F]{32}:/i;
836
+ function hasKind(operation, unscopedKind) {
837
+ const kind = typeof operation === "string" ? operation : operation?.kind;
838
+ return kind != null && kind.replace(KIND_SCOPE, "") === unscopedKind;
839
+ }
840
+ function hasParentEntityType(operation, unscopedParentEntityType) {
841
+ const parentType = typeof operation === "string" ? operation : operation?.parentEntityType;
842
+ return parentType != null && parentType.replace(PARENT_SCOPE, "") === unscopedParentEntityType;
843
+ }
844
+
845
+ // src/platform-react/operations/useOperationsByParent.ts
846
+ function useOperationsByParent(parentEntityType, parentEntityId) {
847
+ const queryClient = useQueryClient();
848
+ const realtime = usePluginRealtimeSource();
849
+ const { invoke } = useMcpTool(
850
+ PLUGIN_OPERATION_TOOLS.listByParent
851
+ );
852
+ const query = useQuery({
853
+ queryKey: pluginOperationKeys.byParent(parentEntityType, parentEntityId ?? ""),
854
+ enabled: Boolean(parentEntityId),
855
+ queryFn: async () => (await invoke({ parentEntityType, parentEntityId }))?.items ?? [],
856
+ refetchInterval: (q) => realtime === null && (q.state.data ?? []).some((op) => !isTerminalOperationStatus(op.status)) ? OPERATION_FALLBACK_POLL_MS : false
857
+ });
858
+ usePluginRealtime(PLUGIN_OPERATION_STATE_CHANGED, (payload) => {
859
+ const event = asStateChanged(payload);
860
+ if (!parentEntityId || event == null || event.parentEntityId !== parentEntityId || !hasParentEntityType(event, parentEntityType)) {
861
+ return;
862
+ }
863
+ queryClient.setQueryData(
864
+ pluginOperationKeys.byParent(parentEntityType, parentEntityId),
865
+ (current) => mergeIntoList(current, event)
866
+ );
867
+ });
868
+ return query;
869
+ }
870
+ function useLatestTerminalOperationByParent(parentEntityType, parentEntityId) {
871
+ const queryClient = useQueryClient();
872
+ const { invoke } = useMcpTool(
873
+ PLUGIN_OPERATION_TOOLS.latestTerminalByParent
874
+ );
875
+ const key = pluginOperationKeys.latestTerminalByParent(parentEntityType, parentEntityId ?? "");
876
+ const query = useQuery({
877
+ queryKey: key,
878
+ enabled: Boolean(parentEntityId),
879
+ queryFn: async () => (await invoke({ parentEntityType, parentEntityId }))?.item ?? null
880
+ });
881
+ usePluginRealtime(PLUGIN_OPERATION_STATE_CHANGED, (payload) => {
882
+ const event = asStateChanged(payload);
883
+ if (parentEntityId && event != null && event.parentEntityId === parentEntityId && hasParentEntityType(event, parentEntityType) && isTerminalOperationStatus(event.status)) {
884
+ void queryClient.invalidateQueries({ queryKey: key });
885
+ }
886
+ });
887
+ return query;
888
+ }
748
889
  var DEFAULT_MAX_UPLOAD_BYTES = 30 * 1024 * 1024;
749
890
  function useMcpUpload(opts) {
750
891
  const transport = useExtensionRuntimeTransport(opts?.transport);
@@ -1252,6 +1393,6 @@ function withActiveNavHref(input, activeNavHref) {
1252
1393
  return { ...input, activeNavHref };
1253
1394
  }
1254
1395
 
1255
- export { BaseMcpService, DEFAULT_MAX_UPLOAD_BYTES, EHX_PLUGIN_PORTAL_ATTR, EHX_PLUGIN_PORTAL_CLASS, EHX_PLUGIN_ROOT_CLASS, HOST_CHROME_CONTRACT_VERSION, HostSidebarActionsContext, LIST_CURRENCIES_TOOL, MissingViewFallback, ORGANISATION_SETTINGS_URI, OVERLAY_HOST_CONTRACT_VERSION, OverlayHostContext, PluginPortalScope, PluginStyleScope, REPORTING_CURRENCY_TOOL2 as REPORTING_CURRENCY_TOOL, SIDEBAR_MODE, SurfaceBaseContext, TemplateContext, TypedMcpService, buildSurfaceUrl, createPluginOverlayDefiner, createPluginPageDefiner, createPluginQueryClient, createReactRouterShim, createUseView, definePlatformReactPluginOverlay, definePlatformReactPluginPage, deriveHostEntityToken, injectPluginStyles, isComponent, isHostChromeCompatible, mcpTool, menuConfigToHostSidebarInput, normaliseSlug, notViaMcp, reportHostChromeDiagnostic, resolveActiveNavHref, resolveSurfaceBase, setHostChromeDiagnosticSink, surfacePathFor, toHostSidebarInput, useAuthenticatedQueries, useAuthenticatedQuery, useCurrency, useHostSidebarActions, useManagedLifecycle, useMcpUpload, useOrgFormatSync, useOverlayHost, usePluginRealtime, useReportingCurrencySync, useSurfaceQueryClient, useSurfaceUrl, useToolInvoker, useToolInvokerMap, useTypedToolInvokerMap, useView, withActiveNavHref };
1396
+ export { BaseMcpService, DEFAULT_MAX_UPLOAD_BYTES, EHX_PLUGIN_PORTAL_ATTR, EHX_PLUGIN_PORTAL_CLASS, EHX_PLUGIN_ROOT_CLASS, HOST_CHROME_CONTRACT_VERSION, HostSidebarActionsContext, LIST_CURRENCIES_TOOL, MissingViewFallback, OPERATION_FALLBACK_POLL_MS, ORGANISATION_SETTINGS_URI, OVERLAY_HOST_CONTRACT_VERSION, OverlayHostContext, PLUGIN_OPERATION_STATE_CHANGED, PLUGIN_OPERATION_TOOLS, PluginPortalScope, PluginStyleScope, REPORTING_CURRENCY_TOOL2 as REPORTING_CURRENCY_TOOL, SIDEBAR_MODE, SurfaceBaseContext, TemplateContext, TypedMcpService, buildSurfaceUrl, createPluginOverlayDefiner, createPluginPageDefiner, createPluginQueryClient, createReactRouterShim, createUseView, definePlatformReactPluginOverlay, definePlatformReactPluginPage, deriveHostEntityToken, hasKind, hasParentEntityType, injectPluginStyles, isComponent, isHostChromeCompatible, isTerminalOperationStatus, mcpTool, menuConfigToHostSidebarInput, normaliseSlug, notViaMcp, pluginOperationKeys, reportHostChromeDiagnostic, resolveActiveNavHref, resolveSurfaceBase, setHostChromeDiagnosticSink, surfacePathFor, toHostSidebarInput, useAuthenticatedQueries, useAuthenticatedQuery, useBackgroundOperation, useCurrency, useHostSidebarActions, useLatestTerminalOperationByParent, useManagedLifecycle, useMcpUpload, useOperationsByParent, useOrgFormatSync, useOverlayHost, usePluginRealtime, useReportingCurrencySync, useSurfaceQueryClient, useSurfaceUrl, useToolInvoker, useToolInvokerMap, useTypedToolInvokerMap, useView, withActiveNavHref };
1256
1397
  //# sourceMappingURL=index.js.map
1257
1398
  //# sourceMappingURL=index.js.map