@ethisyscore/extension-runtime 1.115.0 → 1.116.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 { d as BridgePushThemeEnvelope, c as BridgePushLocaleEnvelope, b as BridgePushDensityEnvelope, a as BridgePushA11yEnvelope, B as BridgeNavPushEnvelope, e as BridgeSessionTokenPushEnvelope } from './bridge-envelopes-DA6vxbyb.cjs';
1
+ import { d as BridgePushThemeEnvelope, c as BridgePushLocaleEnvelope, b as BridgePushDensityEnvelope, a as BridgePushA11yEnvelope, B as BridgeNavPushEnvelope, e as BridgeSessionTokenPushEnvelope } from './bridge-envelopes-DAuew-fU.cjs';
2
2
 
3
3
  /**
4
4
  * Plugin-side bridge client for the host ↔ plugin platform contract
@@ -1,4 +1,4 @@
1
- import { d as BridgePushThemeEnvelope, c as BridgePushLocaleEnvelope, b as BridgePushDensityEnvelope, a as BridgePushA11yEnvelope, B as BridgeNavPushEnvelope, e as BridgeSessionTokenPushEnvelope } from './bridge-envelopes-DA6vxbyb.js';
1
+ import { d as BridgePushThemeEnvelope, c as BridgePushLocaleEnvelope, b as BridgePushDensityEnvelope, a as BridgePushA11yEnvelope, B as BridgeNavPushEnvelope, e as BridgeSessionTokenPushEnvelope } from './bridge-envelopes-DAuew-fU.js';
2
2
 
3
3
  /**
4
4
  * Plugin-side bridge client for the host ↔ plugin platform contract
@@ -27,6 +27,40 @@ interface McpTransport {
27
27
  * Implementations should observe `signal` to abort in-flight work.
28
28
  */
29
29
  invokeTool<TReq, TRes>(name: string, args: TReq, signal?: AbortSignal): Promise<TRes>;
30
+ /**
31
+ * Invoke a canonical OPERATION on a catalogue module, letting the host resolve
32
+ * which application answers it from the operator's provider selection, and
33
+ * falling back to `fallbackToolName` when no provider has been chosen.
34
+ *
35
+ * **Why this exists alongside {@link invokeTool}.** A plugin surface cannot
36
+ * reach another extension's tool: the router refuses a surface capability
37
+ * token for cross-extension tools (EXT_MCP_008), so naming `hr:list-employees`
38
+ * here does not reach HR — it is refused, and the screen quietly does nothing.
39
+ * Until this seam existed the only remedy was a hand-written proxy tool per
40
+ * call site, owned by the calling plugin and forwarding server-side. That
41
+ * works and does not scale: six artefacts per call, in the plugin's own
42
+ * repository, multiplied across every plugin that reads another's data.
43
+ *
44
+ * Naming the operation instead makes the operator's selection the thing that
45
+ * decides, exactly as `IPluginModuleOperations.InvokeOrFallbackAsync` does for
46
+ * a plugin's backend, and keeps the consumer ignorant of which application
47
+ * answered.
48
+ *
49
+ * **Optional capability.** A transport that does not support it simply omits
50
+ * this member, and {@link "../../plugin-ui" useModuleTool} throws a clear
51
+ * runtime error when invoked against such a transport. Keeping it optional
52
+ * makes adding the seam a non-breaking, additive change for existing custom
53
+ * transports, exactly as `uploadDocument` was.
54
+ *
55
+ * @param moduleKey The catalogue module the operation belongs to.
56
+ * @param operationKey The canonical operation, e.g. `person-directory`.
57
+ * @param fallbackToolName The tool this call site invoked before it was
58
+ * converted, used verbatim while the module is unconfigured. It is the
59
+ * DEFAULT provider rather than dead metadata, which is what makes every
60
+ * conversion a no-op until an operator chooses something.
61
+ * @param args Canonical field values, keyed by canonical name.
62
+ */
63
+ invokeOperation?<TReq, TRes>(moduleKey: string, operationKey: string, fallbackToolName: string, args: TReq, signal?: AbortSignal): Promise<TRes>;
30
64
  /**
31
65
  * Upload a binary document to CORE storage via the host shell and resolve
32
66
  * the resulting {@link UploadDocumentResult} (a `StoredDocumentId` plus the
@@ -27,6 +27,40 @@ interface McpTransport {
27
27
  * Implementations should observe `signal` to abort in-flight work.
28
28
  */
29
29
  invokeTool<TReq, TRes>(name: string, args: TReq, signal?: AbortSignal): Promise<TRes>;
30
+ /**
31
+ * Invoke a canonical OPERATION on a catalogue module, letting the host resolve
32
+ * which application answers it from the operator's provider selection, and
33
+ * falling back to `fallbackToolName` when no provider has been chosen.
34
+ *
35
+ * **Why this exists alongside {@link invokeTool}.** A plugin surface cannot
36
+ * reach another extension's tool: the router refuses a surface capability
37
+ * token for cross-extension tools (EXT_MCP_008), so naming `hr:list-employees`
38
+ * here does not reach HR — it is refused, and the screen quietly does nothing.
39
+ * Until this seam existed the only remedy was a hand-written proxy tool per
40
+ * call site, owned by the calling plugin and forwarding server-side. That
41
+ * works and does not scale: six artefacts per call, in the plugin's own
42
+ * repository, multiplied across every plugin that reads another's data.
43
+ *
44
+ * Naming the operation instead makes the operator's selection the thing that
45
+ * decides, exactly as `IPluginModuleOperations.InvokeOrFallbackAsync` does for
46
+ * a plugin's backend, and keeps the consumer ignorant of which application
47
+ * answered.
48
+ *
49
+ * **Optional capability.** A transport that does not support it simply omits
50
+ * this member, and {@link "../../plugin-ui" useModuleTool} throws a clear
51
+ * runtime error when invoked against such a transport. Keeping it optional
52
+ * makes adding the seam a non-breaking, additive change for existing custom
53
+ * transports, exactly as `uploadDocument` was.
54
+ *
55
+ * @param moduleKey The catalogue module the operation belongs to.
56
+ * @param operationKey The canonical operation, e.g. `person-directory`.
57
+ * @param fallbackToolName The tool this call site invoked before it was
58
+ * converted, used verbatim while the module is unconfigured. It is the
59
+ * DEFAULT provider rather than dead metadata, which is what makes every
60
+ * conversion a no-op until an operator chooses something.
61
+ * @param args Canonical field values, keyed by canonical name.
62
+ */
63
+ invokeOperation?<TReq, TRes>(moduleKey: string, operationKey: string, fallbackToolName: string, args: TReq, signal?: AbortSignal): Promise<TRes>;
30
64
  /**
31
65
  * Upload a binary document to CORE storage via the host shell and resolve
32
66
  * the resulting {@link UploadDocumentResult} (a `StoredDocumentId` plus the
@@ -3,12 +3,12 @@ import { C as ComponentRegistry } from '../registry-DpCx_LxF.cjs';
3
3
  export { P as PrimitiveProps } from '../registry-DpCx_LxF.cjs';
4
4
  import { SduiNode } from '@ethisyscore/protocol';
5
5
  export { PrimitiveName, SduiNode } from '@ethisyscore/protocol';
6
- import { M as McpHttpClient, f as VersionSkew } from '../transport-C4xoMWBE.cjs';
7
- export { C as CAPABILITY_REJECTION_REASON_HEADER, D as DEFAULT_MAX_CONCURRENT_MCP_REQUESTS, E as EXTENSION_ACTIVE_VERSION_HEADER, a as EXTENSION_VERSION_HEADER, I as InputEventPayload, b as McpHttpRequest, c as McpHttpResponse, d as McpResponseMetadata, e as McpUploadRequest, V as VERSION_MISMATCH_REASON, g as VersionSkewSource, W as WORKER_TRANSPORT_PROTOCOL, h as WorkerCtor, i as WorkerHandshakePayload, j as WorkerLike, k as WorkerRemoteDomTransport, l as WorkerRemoteDomTransportOptions, m as detectVersionSkew } from '../transport-C4xoMWBE.cjs';
6
+ import { M as McpHttpClient, f as VersionSkew } from '../transport-Cjpb_qPo.cjs';
7
+ export { C as CAPABILITY_REJECTION_REASON_HEADER, D as DEFAULT_MAX_CONCURRENT_MCP_REQUESTS, E as EXTENSION_ACTIVE_VERSION_HEADER, a as EXTENSION_VERSION_HEADER, I as InputEventPayload, b as McpHttpRequest, c as McpHttpResponse, d as McpResponseMetadata, e as McpUploadRequest, V as VERSION_MISMATCH_REASON, g as VersionSkewSource, W as WORKER_TRANSPORT_PROTOCOL, h as WorkerCtor, i as WorkerHandshakePayload, j as WorkerLike, k as WorkerRemoteDomTransport, l as WorkerRemoteDomTransportOptions, m as detectVersionSkew } from '../transport-Cjpb_qPo.cjs';
8
8
  export { RemoteReceiver, RemoteReceiverComment, RemoteReceiverElement, RemoteReceiverNode, RemoteReceiverParent, RemoteReceiverRoot, RemoteReceiverText } from '@remote-dom/core/receivers';
9
9
  export { RemoteComponentRendererMap, RemoteComponentRendererProps, RemoteRootRenderer, RemoteRootRendererProps, createRemoteComponentRenderer } from '@remote-dom/react/host';
10
10
  export { M as MCP_ERROR_CODES, a as McpErrorCode, b as McpToolError, c as classifyHostError, d as classifyHostResponse, i as isMcpErrorCode, e as isMcpToolError, f as isRetryableMcpErrorCode, m as mcpErrorCodeFromHttpStatus } from '../mcp-error-CCZQd8Xl.cjs';
11
- import '../bridge-envelopes-DA6vxbyb.cjs';
11
+ import '../bridge-envelopes-DAuew-fU.cjs';
12
12
 
13
13
  /**
14
14
  * Resolution context for `var` references. Keys are looked up via dot-path
@@ -3,12 +3,12 @@ import { C as ComponentRegistry } from '../registry-DpCx_LxF.js';
3
3
  export { P as PrimitiveProps } from '../registry-DpCx_LxF.js';
4
4
  import { SduiNode } from '@ethisyscore/protocol';
5
5
  export { PrimitiveName, SduiNode } from '@ethisyscore/protocol';
6
- import { M as McpHttpClient, f as VersionSkew } from '../transport-BuX8gzq1.js';
7
- export { C as CAPABILITY_REJECTION_REASON_HEADER, D as DEFAULT_MAX_CONCURRENT_MCP_REQUESTS, E as EXTENSION_ACTIVE_VERSION_HEADER, a as EXTENSION_VERSION_HEADER, I as InputEventPayload, b as McpHttpRequest, c as McpHttpResponse, d as McpResponseMetadata, e as McpUploadRequest, V as VERSION_MISMATCH_REASON, g as VersionSkewSource, W as WORKER_TRANSPORT_PROTOCOL, h as WorkerCtor, i as WorkerHandshakePayload, j as WorkerLike, k as WorkerRemoteDomTransport, l as WorkerRemoteDomTransportOptions, m as detectVersionSkew } from '../transport-BuX8gzq1.js';
6
+ import { M as McpHttpClient, f as VersionSkew } from '../transport-B9mwIXYs.js';
7
+ export { C as CAPABILITY_REJECTION_REASON_HEADER, D as DEFAULT_MAX_CONCURRENT_MCP_REQUESTS, E as EXTENSION_ACTIVE_VERSION_HEADER, a as EXTENSION_VERSION_HEADER, I as InputEventPayload, b as McpHttpRequest, c as McpHttpResponse, d as McpResponseMetadata, e as McpUploadRequest, V as VERSION_MISMATCH_REASON, g as VersionSkewSource, W as WORKER_TRANSPORT_PROTOCOL, h as WorkerCtor, i as WorkerHandshakePayload, j as WorkerLike, k as WorkerRemoteDomTransport, l as WorkerRemoteDomTransportOptions, m as detectVersionSkew } from '../transport-B9mwIXYs.js';
8
8
  export { RemoteReceiver, RemoteReceiverComment, RemoteReceiverElement, RemoteReceiverNode, RemoteReceiverParent, RemoteReceiverRoot, RemoteReceiverText } from '@remote-dom/core/receivers';
9
9
  export { RemoteComponentRendererMap, RemoteComponentRendererProps, RemoteRootRenderer, RemoteRootRendererProps, createRemoteComponentRenderer } from '@remote-dom/react/host';
10
10
  export { M as MCP_ERROR_CODES, a as McpErrorCode, b as McpToolError, c as classifyHostError, d as classifyHostResponse, i as isMcpErrorCode, e as isMcpToolError, f as isRetryableMcpErrorCode, m as mcpErrorCodeFromHttpStatus } from '../mcp-error-CCZQd8Xl.js';
11
- import '../bridge-envelopes-DA6vxbyb.js';
11
+ import '../bridge-envelopes-DAuew-fU.js';
12
12
 
13
13
  /**
14
14
  * Resolution context for `var` references. Keys are looked up via dot-path
@@ -1,6 +1,6 @@
1
1
  import { SduiNode } from '@ethisyscore/protocol';
2
- import { h as WorkerCtor, M as McpHttpClient, k as WorkerRemoteDomTransport } from '../transport-C4xoMWBE.cjs';
3
- import '../bridge-envelopes-DA6vxbyb.cjs';
2
+ import { h as WorkerCtor, M as McpHttpClient, k as WorkerRemoteDomTransport } from '../transport-Cjpb_qPo.cjs';
3
+ import '../bridge-envelopes-DAuew-fU.cjs';
4
4
 
5
5
  /**
6
6
  * `npx mock-host <dir>` — standalone declarative-mock-host dev server.
@@ -1,6 +1,6 @@
1
1
  import { SduiNode } from '@ethisyscore/protocol';
2
- import { h as WorkerCtor, M as McpHttpClient, k as WorkerRemoteDomTransport } from '../transport-BuX8gzq1.js';
3
- import '../bridge-envelopes-DA6vxbyb.js';
2
+ import { h as WorkerCtor, M as McpHttpClient, k as WorkerRemoteDomTransport } from '../transport-B9mwIXYs.js';
3
+ import '../bridge-envelopes-DAuew-fU.js';
4
4
 
5
5
  /**
6
6
  * `npx mock-host <dir>` — standalone declarative-mock-host dev server.
@@ -1,8 +1,8 @@
1
1
  import { ReactNode, ReactElement } from 'react';
2
2
  import { C as ComponentRegistry } from '../registry-DpCx_LxF.cjs';
3
3
  import { SduiNode } from '@ethisyscore/protocol';
4
- import { M as McpTransport, U as UploadDocumentMeta, f as UploadDocumentResult } from '../bridge-envelopes-DA6vxbyb.cjs';
5
- import { P as PortBridgeClient, T as ThemePayload, L as LocalePayload, D as DensityPayload, A as A11yPayload, N as NavPayload, S as SessionTokenPayload } from '../bridge-client-DzRcKIJT.cjs';
4
+ import { M as McpTransport, U as UploadDocumentMeta, f as UploadDocumentResult } from '../bridge-envelopes-DAuew-fU.cjs';
5
+ import { P as PortBridgeClient, T as ThemePayload, L as LocalePayload, D as DensityPayload, A as A11yPayload, N as NavPayload, S as SessionTokenPayload } from '../bridge-client-D0fogVGd.cjs';
6
6
 
7
7
  /**
8
8
  * Handler for a mocked tool invocation. The handler receives the request
@@ -1,8 +1,8 @@
1
1
  import { ReactNode, ReactElement } from 'react';
2
2
  import { C as ComponentRegistry } from '../registry-DpCx_LxF.js';
3
3
  import { SduiNode } from '@ethisyscore/protocol';
4
- import { M as McpTransport, U as UploadDocumentMeta, f as UploadDocumentResult } from '../bridge-envelopes-DA6vxbyb.js';
5
- import { P as PortBridgeClient, T as ThemePayload, L as LocalePayload, D as DensityPayload, A as A11yPayload, N as NavPayload, S as SessionTokenPayload } from '../bridge-client-DD99netz.js';
4
+ import { M as McpTransport, U as UploadDocumentMeta, f as UploadDocumentResult } from '../bridge-envelopes-DAuew-fU.js';
5
+ import { P as PortBridgeClient, T as ThemePayload, L as LocalePayload, D as DensityPayload, A as A11yPayload, N as NavPayload, S as SessionTokenPayload } from '../bridge-client-tIK_iYT9.js';
6
6
 
7
7
  /**
8
8
  * Handler for a mocked tool invocation. The handler receives the request
@@ -64,6 +64,98 @@ function useOptionalExtensionRuntimeTransport(override) {
64
64
  const fromContext = react.useContext(ExtensionRuntimeContext);
65
65
  return override ?? fromContext ?? null;
66
66
  }
67
+ function useModuleTool(moduleKey, operationKey, fallbackToolName, opts) {
68
+ const transport = useExtensionRuntimeTransport(opts?.transport);
69
+ const [loading, setLoading] = react.useState(false);
70
+ const [error, setError] = react.useState(void 0);
71
+ const controllerRef = react.useRef(null);
72
+ const mountedRef = react.useRef(true);
73
+ react.useEffect(() => {
74
+ mountedRef.current = true;
75
+ return () => {
76
+ mountedRef.current = false;
77
+ controllerRef.current?.abort();
78
+ };
79
+ }, []);
80
+ const invoke = react.useCallback(
81
+ async (req) => {
82
+ const controller = new AbortController();
83
+ controllerRef.current?.abort();
84
+ controllerRef.current = controller;
85
+ setLoading(true);
86
+ setError(void 0);
87
+ try {
88
+ const invokeOperation = transport.invokeOperation;
89
+ if (typeof invokeOperation !== "function") {
90
+ throw new Error(
91
+ `This host's MCP transport does not support module operations, so ${moduleKey}/${operationKey} cannot be resolved to a provider. Upgrade the host, or call the plugin's own proxy tool with useMcpTool instead.`
92
+ );
93
+ }
94
+ const result = await invokeOperation.call(
95
+ transport,
96
+ moduleKey,
97
+ operationKey,
98
+ fallbackToolName,
99
+ req,
100
+ controller.signal
101
+ );
102
+ if (mountedRef.current && !controller.signal.aborted) {
103
+ setLoading(false);
104
+ }
105
+ return result;
106
+ } catch (err) {
107
+ const wrapped = err instanceof Error ? err : new Error(String(err));
108
+ if (mountedRef.current && !controller.signal.aborted) {
109
+ setError(wrapped);
110
+ setLoading(false);
111
+ }
112
+ throw wrapped;
113
+ }
114
+ },
115
+ [transport, moduleKey, operationKey, fallbackToolName]
116
+ );
117
+ return { invoke, loading, error };
118
+ }
119
+ function useModuleQuery(moduleKey, operationKey, fallbackToolName, args, options) {
120
+ const enabled = options?.enabled ?? true;
121
+ const { invoke } = useModuleTool(moduleKey, operationKey, fallbackToolName);
122
+ const [data, setData] = react.useState(void 0);
123
+ const [loading, setLoading] = react.useState(enabled);
124
+ const [error, setError] = react.useState(void 0);
125
+ const [tick, setTick] = react.useState(0);
126
+ const argsKey = JSON.stringify(args);
127
+ react.useEffect(() => {
128
+ if (!enabled) {
129
+ setLoading(false);
130
+ return;
131
+ }
132
+ let cancelled = false;
133
+ setLoading(true);
134
+ invoke(args).then((result) => {
135
+ if (cancelled) {
136
+ return;
137
+ }
138
+ setData(result);
139
+ setError(void 0);
140
+ setLoading(false);
141
+ }).catch((err) => {
142
+ if (cancelled) {
143
+ return;
144
+ }
145
+ setError(err instanceof Error ? err : new Error(String(err)));
146
+ setLoading(false);
147
+ });
148
+ return () => {
149
+ cancelled = true;
150
+ };
151
+ }, [argsKey, tick, invoke, enabled]);
152
+ return {
153
+ data,
154
+ loading,
155
+ error,
156
+ refetch: () => setTick((t) => t + 1)
157
+ };
158
+ }
67
159
  function useMcpResource(uri, opts) {
68
160
  const transport = useExtensionRuntimeTransport(opts?.transport);
69
161
  const [data, setData] = react.useState(void 0);
@@ -936,6 +1028,8 @@ exports.useHostIdentity = useHostIdentity;
936
1028
  exports.useMcpQuery = useMcpQuery;
937
1029
  exports.useMcpResource = useMcpResource;
938
1030
  exports.useMcpTool = useMcpTool;
1031
+ exports.useModuleQuery = useModuleQuery;
1032
+ exports.useModuleTool = useModuleTool;
939
1033
  exports.useOptionalExtensionRuntimeTransport = useOptionalExtensionRuntimeTransport;
940
1034
  exports.usePluginRealtimeSource = usePluginRealtimeSource;
941
1035
  //# sourceMappingURL=index.cjs.map