@ethisyscore/extension-runtime 1.123.0 → 1.124.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,12 +1,12 @@
1
- import { M as McpTransport } from '../bridge-envelopes-DAuew-fU.cjs';
2
- export { U as UploadDocumentMeta, f as UploadDocumentResult } from '../bridge-envelopes-DAuew-fU.cjs';
1
+ import { M as McpTransport } from '../bridge-envelopes-M5a42rAy.cjs';
2
+ export { U as UploadDocumentMeta, f as UploadDocumentResult } from '../bridge-envelopes-M5a42rAy.cjs';
3
3
  import * as react from 'react';
4
4
  import { ReactNode } from 'react';
5
5
  import { SduiNode, RenderMode } from '@ethisyscore/protocol';
6
6
  export { PagedResponse, PaginatedEnvelope } from '@ethisyscore/protocol';
7
7
  import { RemoteConnection } from '@remote-dom/core';
8
- import { P as PortBridgeClient, T as ThemePayload, L as LocalePayload } from '../bridge-client-D0fogVGd.cjs';
9
- export { A as A11yPayload, B as BridgePortShim, D as DensityPayload, N as NavPayload, S as SessionTokenPayload, c as createPortBridgeClient } from '../bridge-client-D0fogVGd.cjs';
8
+ import { P as PortBridgeClient, T as ThemePayload, L as LocalePayload } from '../bridge-client-D9EYFq1l.cjs';
9
+ export { A as A11yPayload, B as BridgePortShim, D as DensityPayload, N as NavPayload, S as SessionTokenPayload, c as createPortBridgeClient } from '../bridge-client-D9EYFq1l.cjs';
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
11
 
12
12
  /**
@@ -230,8 +230,15 @@ interface UseModuleToolResult<TReq, TRes> {
230
230
  * Invoke the operation. Each call gets a fresh {@link AbortController} that is
231
231
  * aborted on unmount so unresolved promises cannot keep state alive after the
232
232
  * component is gone.
233
+ *
234
+ * `fallbackReq` is optional and is used ONLY if the declared fallback tool
235
+ * answers - see {@link McpTransport.invokeOperation}'s `fallbackArgs`. Omit it
236
+ * and the fallback receives `req`, which is what every call site did before
237
+ * this parameter existed. It travels beside `req` rather than being fixed on
238
+ * the hook because the fallback's arguments are normally a rename of the
239
+ * canonical ones, and those only exist at call time.
233
240
  */
234
- invoke: (req: TReq) => Promise<TRes>;
241
+ invoke: (req: TReq, fallbackReq?: unknown) => Promise<TRes>;
235
242
  loading: boolean;
236
243
  error: Error | undefined;
237
244
  }
@@ -252,8 +259,18 @@ interface UseModuleToolResult<TReq, TRes> {
252
259
  * call through a per-organisation lookup is the failure that emptied the onboarding
253
260
  * admin picker for every SDK-hosted plugin.
254
261
  *
262
+ * **When the fallback tool does not speak canonical.** `invoke(req)` sends `req`
263
+ * to whichever rung answers. An in-house fallback tool need not declare the
264
+ * canonical field names, so pass the tool's own shape as the second argument -
265
+ * `invoke({ personIds }, { employeeIds: personIds })` - and it is used only if
266
+ * the fallback answers. This is the browser twin of `ModuleFallback`'s second
267
+ * argument on the backend, and it matters now rather than later: no organisation
268
+ * has chosen a provider, so the fallback rung is the production path for every
269
+ * call a conversion makes.
270
+ *
255
271
  * `invoke` is a stable reference across renders for the same module, operation,
256
- * fallback and transport, making it safe to use inside `useEffect` deps.
272
+ * fallback and transport, making it safe to use inside `useEffect` deps. The
273
+ * fallback arguments travel per call and so do not affect that identity.
257
274
  */
258
275
  declare function useModuleTool<TReq, TRes>(moduleKey: string, operationKey: string, fallbackToolName: string, opts?: UseModuleToolOptions): UseModuleToolResult<TReq, TRes>;
259
276
 
@@ -264,6 +281,29 @@ interface UseModuleQueryOptions {
264
281
  * violating the rules of hooks. Defaults to `true`.
265
282
  */
266
283
  enabled?: boolean;
284
+ /**
285
+ * Arguments for the FALLBACK rung only, used verbatim in place of `args` when
286
+ * the declared fallback tool answers. Omit it and the fallback receives
287
+ * `args`, which is what every call did before this option existed.
288
+ *
289
+ * It exists because an in-house fallback tool need not declare the canonical
290
+ * field names: `hr:get-employee-absences` wants `employeeIds` where the
291
+ * canonical operation says `personIds`. This is the browser twin of
292
+ * `ModuleFallback`'s second argument on the backend, and it is load-bearing
293
+ * today rather than later - no organisation has chosen a provider, so the
294
+ * fallback rung answers every call a converted read makes.
295
+ *
296
+ * It is an option rather than a hook parameter for the same reason `args` is
297
+ * a parameter here and an `invoke` argument on {@link useModuleTool}: the
298
+ * fallback's arguments travel wherever the canonical ones travel. Like
299
+ * `args`, a change to its CONTENTS refetches; a new object with identical
300
+ * contents does not.
301
+ *
302
+ * It carries no authority and cannot change which tool runs. The tool NAME is
303
+ * still `fallbackToolName`, still checked against the calling extension's
304
+ * installed manifest by the host before the fallback rung runs.
305
+ */
306
+ fallbackArgs?: unknown;
267
307
  }
268
308
  interface UseModuleQueryResult<TRes> {
269
309
  data: TRes | undefined;
@@ -1,12 +1,12 @@
1
- import { M as McpTransport } from '../bridge-envelopes-DAuew-fU.js';
2
- export { U as UploadDocumentMeta, f as UploadDocumentResult } from '../bridge-envelopes-DAuew-fU.js';
1
+ import { M as McpTransport } from '../bridge-envelopes-M5a42rAy.js';
2
+ export { U as UploadDocumentMeta, f as UploadDocumentResult } from '../bridge-envelopes-M5a42rAy.js';
3
3
  import * as react from 'react';
4
4
  import { ReactNode } from 'react';
5
5
  import { SduiNode, RenderMode } from '@ethisyscore/protocol';
6
6
  export { PagedResponse, PaginatedEnvelope } from '@ethisyscore/protocol';
7
7
  import { RemoteConnection } from '@remote-dom/core';
8
- import { P as PortBridgeClient, T as ThemePayload, L as LocalePayload } from '../bridge-client-tIK_iYT9.js';
9
- export { A as A11yPayload, B as BridgePortShim, D as DensityPayload, N as NavPayload, S as SessionTokenPayload, c as createPortBridgeClient } from '../bridge-client-tIK_iYT9.js';
8
+ import { P as PortBridgeClient, T as ThemePayload, L as LocalePayload } from '../bridge-client-RJOl8WlU.js';
9
+ export { A as A11yPayload, B as BridgePortShim, D as DensityPayload, N as NavPayload, S as SessionTokenPayload, c as createPortBridgeClient } from '../bridge-client-RJOl8WlU.js';
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
11
 
12
12
  /**
@@ -230,8 +230,15 @@ interface UseModuleToolResult<TReq, TRes> {
230
230
  * Invoke the operation. Each call gets a fresh {@link AbortController} that is
231
231
  * aborted on unmount so unresolved promises cannot keep state alive after the
232
232
  * component is gone.
233
+ *
234
+ * `fallbackReq` is optional and is used ONLY if the declared fallback tool
235
+ * answers - see {@link McpTransport.invokeOperation}'s `fallbackArgs`. Omit it
236
+ * and the fallback receives `req`, which is what every call site did before
237
+ * this parameter existed. It travels beside `req` rather than being fixed on
238
+ * the hook because the fallback's arguments are normally a rename of the
239
+ * canonical ones, and those only exist at call time.
233
240
  */
234
- invoke: (req: TReq) => Promise<TRes>;
241
+ invoke: (req: TReq, fallbackReq?: unknown) => Promise<TRes>;
235
242
  loading: boolean;
236
243
  error: Error | undefined;
237
244
  }
@@ -252,8 +259,18 @@ interface UseModuleToolResult<TReq, TRes> {
252
259
  * call through a per-organisation lookup is the failure that emptied the onboarding
253
260
  * admin picker for every SDK-hosted plugin.
254
261
  *
262
+ * **When the fallback tool does not speak canonical.** `invoke(req)` sends `req`
263
+ * to whichever rung answers. An in-house fallback tool need not declare the
264
+ * canonical field names, so pass the tool's own shape as the second argument -
265
+ * `invoke({ personIds }, { employeeIds: personIds })` - and it is used only if
266
+ * the fallback answers. This is the browser twin of `ModuleFallback`'s second
267
+ * argument on the backend, and it matters now rather than later: no organisation
268
+ * has chosen a provider, so the fallback rung is the production path for every
269
+ * call a conversion makes.
270
+ *
255
271
  * `invoke` is a stable reference across renders for the same module, operation,
256
- * fallback and transport, making it safe to use inside `useEffect` deps.
272
+ * fallback and transport, making it safe to use inside `useEffect` deps. The
273
+ * fallback arguments travel per call and so do not affect that identity.
257
274
  */
258
275
  declare function useModuleTool<TReq, TRes>(moduleKey: string, operationKey: string, fallbackToolName: string, opts?: UseModuleToolOptions): UseModuleToolResult<TReq, TRes>;
259
276
 
@@ -264,6 +281,29 @@ interface UseModuleQueryOptions {
264
281
  * violating the rules of hooks. Defaults to `true`.
265
282
  */
266
283
  enabled?: boolean;
284
+ /**
285
+ * Arguments for the FALLBACK rung only, used verbatim in place of `args` when
286
+ * the declared fallback tool answers. Omit it and the fallback receives
287
+ * `args`, which is what every call did before this option existed.
288
+ *
289
+ * It exists because an in-house fallback tool need not declare the canonical
290
+ * field names: `hr:get-employee-absences` wants `employeeIds` where the
291
+ * canonical operation says `personIds`. This is the browser twin of
292
+ * `ModuleFallback`'s second argument on the backend, and it is load-bearing
293
+ * today rather than later - no organisation has chosen a provider, so the
294
+ * fallback rung answers every call a converted read makes.
295
+ *
296
+ * It is an option rather than a hook parameter for the same reason `args` is
297
+ * a parameter here and an `invoke` argument on {@link useModuleTool}: the
298
+ * fallback's arguments travel wherever the canonical ones travel. Like
299
+ * `args`, a change to its CONTENTS refetches; a new object with identical
300
+ * contents does not.
301
+ *
302
+ * It carries no authority and cannot change which tool runs. The tool NAME is
303
+ * still `fallbackToolName`, still checked against the calling extension's
304
+ * installed manifest by the host before the fallback rung runs.
305
+ */
306
+ fallbackArgs?: unknown;
267
307
  }
268
308
  interface UseModuleQueryResult<TRes> {
269
309
  data: TRes | undefined;
@@ -72,7 +72,7 @@ function useModuleTool(moduleKey, operationKey, fallbackToolName, opts) {
72
72
  };
73
73
  }, []);
74
74
  const invoke = useCallback(
75
- async (req) => {
75
+ async (req, fallbackReq) => {
76
76
  const controller = new AbortController();
77
77
  controllerRef.current?.abort();
78
78
  controllerRef.current = controller;
@@ -91,7 +91,8 @@ function useModuleTool(moduleKey, operationKey, fallbackToolName, opts) {
91
91
  operationKey,
92
92
  fallbackToolName,
93
93
  req,
94
- controller.signal
94
+ controller.signal,
95
+ fallbackReq
95
96
  );
96
97
  if (mountedRef.current && !controller.signal.aborted) {
97
98
  setLoading(false);
@@ -112,12 +113,13 @@ function useModuleTool(moduleKey, operationKey, fallbackToolName, opts) {
112
113
  }
113
114
  function useModuleQuery(moduleKey, operationKey, fallbackToolName, args, options) {
114
115
  const enabled = options?.enabled ?? true;
116
+ const fallbackArgs = options?.fallbackArgs;
115
117
  const { invoke } = useModuleTool(moduleKey, operationKey, fallbackToolName);
116
118
  const [data, setData] = useState(void 0);
117
119
  const [loading, setLoading] = useState(enabled);
118
120
  const [error, setError] = useState(void 0);
119
121
  const [tick, setTick] = useState(0);
120
- const argsKey = JSON.stringify(args);
122
+ const argsKey = JSON.stringify([args, fallbackArgs]);
121
123
  useEffect(() => {
122
124
  if (!enabled) {
123
125
  setLoading(false);
@@ -125,7 +127,7 @@ function useModuleQuery(moduleKey, operationKey, fallbackToolName, args, options
125
127
  }
126
128
  let cancelled = false;
127
129
  setLoading(true);
128
- invoke(args).then((result) => {
130
+ invoke(args, fallbackArgs).then((result) => {
129
131
  if (cancelled) {
130
132
  return;
131
133
  }
@@ -731,12 +733,17 @@ function createPortMcpTransport(port, options = {}) {
731
733
  const data = await send(WIRE_INVOKE_TOOL_REQUEST, { name, args }, signal);
732
734
  return data;
733
735
  },
734
- async invokeOperation(moduleKey, operationKey, fallbackToolName, args, signal) {
735
- const data = await send(
736
- WIRE_INVOKE_OPERATION_REQUEST,
737
- { moduleKey, operationKey, fallbackToolName, args },
738
- signal
739
- );
736
+ async invokeOperation(moduleKey, operationKey, fallbackToolName, args, signal, fallbackArgs) {
737
+ const body = {
738
+ moduleKey,
739
+ operationKey,
740
+ fallbackToolName,
741
+ args
742
+ };
743
+ if (fallbackArgs !== void 0) {
744
+ body.fallbackArgs = fallbackArgs;
745
+ }
746
+ const data = await send(WIRE_INVOKE_OPERATION_REQUEST, body, signal);
740
747
  return data;
741
748
  },
742
749
  async uploadDocument(meta, buffer, signal) {