@matatbread/matbot-core 0.4.14 → 0.4.15

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.14",
7
+ "version": "0.4.15",
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.14"
38
+ "@matatbread/matbot-plugin-api": "^0.4.15"
39
39
  },
40
40
  "devDependencies": {
41
41
  "typescript": "^6.0.3"
@@ -21,6 +21,12 @@ export interface MatbotConfig {
21
21
  * config rather than data. A stored value always wins; `delete` reverts to the default here.
22
22
  */
23
23
  defaultSettings?: ReadonlyMap<string, Readonly<Record<string, unknown>>>;
24
+ /**
25
+ * Longest a `tool_function` body may run synchronously — without awaiting — before it is stopped
26
+ * (`function_timeout_ms`). Absent ⇒ the host's default. `0` ⇒ no limit at all, for testing: bodies run
27
+ * directly, and a loop that never awaits freezes the process.
28
+ */
29
+ functionTimeoutMs?: number;
24
30
  }
25
31
 
26
32
  function asString(v: YamlValue | undefined, label: string): string {
@@ -123,6 +129,17 @@ export function parseConfig(
123
129
  }
124
130
  }
125
131
 
132
+ const functionTimeoutRaw = doc['function_timeout_ms'];
133
+ let functionTimeoutMs: number | undefined;
134
+ if (functionTimeoutRaw !== undefined && functionTimeoutRaw !== null) {
135
+ functionTimeoutMs = asNumber(functionTimeoutRaw, 'function_timeout_ms');
136
+ // Refused rather than clamped, like maxRounds: a negative or fractional limit is a typo, and `0` already
137
+ // means something of its own.
138
+ if (!Number.isInteger(functionTimeoutMs) || functionTimeoutMs < 0) {
139
+ throw new Error(`Config: "function_timeout_ms" must be a non-negative integer (milliseconds; 0 removes the limit), got ${functionTimeoutMs}`);
140
+ }
141
+ }
142
+
126
143
  const prompt = typeof doc['prompt'] === 'string' ? doc['prompt'] : undefined;
127
144
  const ephemeral = doc['ephemeral'] === true ? true : undefined;
128
145
  const defaultProvider = typeof doc['default_provider'] === 'string' ? doc['default_provider'] : undefined;
@@ -136,6 +153,7 @@ export function parseConfig(
136
153
  ...(defaultProvider !== undefined ? { defaultProvider } : {}),
137
154
  ...(principal !== undefined ? { principal } : {}),
138
155
  ...(defaultSettings.size > 0 ? { defaultSettings } : {}),
156
+ ...(functionTimeoutMs !== undefined ? { functionTimeoutMs } : {}),
139
157
  };
140
158
  }
141
159
 
package/src/index.ts CHANGED
@@ -23,7 +23,7 @@ export { applyCreateSecret, assertStorableKey, unreferenceableKey, REFERENCEABLE
23
23
  // that apply one cannot differ on what a patch MEANS, and re-exported here so an app needs no direct
24
24
  // plugin-api dependency to get it.
25
25
  export { applyProviderPatch, patchedFields } from '@matatbread/matbot-plugin-api';
26
- export { isTruncatedToolResult, notifyingStore, ItemChangeKind, RegistryChangeKind } from '@matatbread/matbot-plugin-api';
26
+ export { isTruncatedToolResult, notifyingStore, ItemChangeKind, RegistryChangeKind, FUNCTION_TIMEOUT } from '@matatbread/matbot-plugin-api';
27
27
  // The canonical `type: 'confirm'` answers. Same reason as the patch policy above: an app implementing a
28
28
  // PromptFn (or a test standing one in) has to speak them, and must not hard-code the rendered label.
29
29
  export { CONFIRM_YES, CONFIRM_NO } from '@matatbread/matbot-plugin-api';