@matatbread/matbot-core 0.4.12 → 0.4.13

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.
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "node",
5
5
  "browser"
6
6
  ],
7
- "version": "0.4.12",
7
+ "version": "0.4.13",
8
8
  "engines": {
9
9
  "node": ">=24.0.0"
10
10
  },
@@ -35,7 +35,7 @@
35
35
  "access": "public"
36
36
  },
37
37
  "dependencies": {
38
- "@matatbread/matbot-plugin-api": "^0.4.12"
38
+ "@matatbread/matbot-plugin-api": "^0.4.13"
39
39
  },
40
40
  "devDependencies": {
41
41
  "typescript": "^6.0.3"
package/src/index.ts CHANGED
@@ -19,6 +19,10 @@ export type {
19
19
  MediaRejectedError, InvalidSecretNameError, MatbotErrorKind,
20
20
  } from '@matatbread/matbot-plugin-api';
21
21
  export { applyCreateSecret, assertStorableKey, unreferenceableKey, REFERENCEABLE_KEY_RULE } from '@matatbread/matbot-plugin-api';
22
+ // The `provider update` patch policy, alongside the vault's: written once in plugin-api so the hosts
23
+ // that apply one cannot differ on what a patch MEANS, and re-exported here so an app needs no direct
24
+ // plugin-api dependency to get it.
25
+ export { applyProviderPatch, patchedFields } from '@matatbread/matbot-plugin-api';
22
26
  export { isTruncatedToolResult, notifyingStore, ItemChangeKind, RegistryChangeKind } from '@matatbread/matbot-plugin-api';
23
27
  // Ambient security principal: the interface is a type (carried by `export type *`); these are the values.
24
28
  export { currentPrincipal, tryCurrentPrincipal, runAs, lastActivityAt } from '@matatbread/matbot-plugin-api';
package/src/loader.ts CHANGED
@@ -176,9 +176,20 @@ export async function loadPlugins(
176
176
  // from a `'load'` failure (import rejection — a bad path, a syntax error). Only the former is
177
177
  // permanently-not-a-plugin: it throws NotAPluginError so the `add` flow can roll back the config
178
178
  // write, where an import failure may be a fixable typo and is left in config.
179
- const failLoad = (spec: string, rawReason: string, kind: 'load' | 'shape' = 'load'): void => {
179
+ const failLoad = (spec: string, rawReason: string, kind: 'load' | 'shape' = 'load', cause?: unknown): void => {
180
180
  const reason = withNotes(spec, rawReason);
181
- if (onLoadError === 'throw') throw kind === 'shape' ? notAPluginError(spec, reason) : new Error(reason);
181
+ if (onLoadError === 'throw') {
182
+ if (kind === 'shape') throw notAPluginError(spec, reason);
183
+ // The wrapper carries the original's `cause` AND its `code`. A caller that recognises the failure
184
+ // is asking about what went wrong, not about this frame: the `plugin` tool reads
185
+ // ERR_MODULE_NOT_FOUND to name the package an http plugin is missing and offer to install it, and a
186
+ // bare `new Error(message)` dropped the code, so that branch was unreachable — silently, because
187
+ // the wording it also matches on was still in the message.
188
+ const err = new Error(reason, cause !== undefined ? { cause } : undefined);
189
+ const code = (cause as { code?: unknown } | undefined)?.code;
190
+ if (typeof code === 'string') (err as { code?: string }).code = code;
191
+ throw err;
192
+ }
182
193
  console.warn(`[matbot] Skipping plugin "${spec}": ${reason}`);
183
194
  recordFailedPlugin({ specifier: spec, error: reason });
184
195
  };
@@ -196,7 +207,7 @@ export async function loadPlugins(
196
207
  continue;
197
208
  }
198
209
  console.error(`[matbot] Failed to load plugin "${spec}":`, result.reason);
199
- failLoad(spec, `Could not load plugin "${spec}": ${reason}`);
210
+ failLoad(spec, `Could not load plugin "${spec}": ${reason}`, 'load', result.reason);
200
211
  continue;
201
212
  }
202
213