@molecule/api-ai-tools 1.5.0 → 1.5.1

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 +1 @@
1
- {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAoB9C,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAgCnE;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,eAAe,GAAG,MAAM,EAAE,CAu3CxF"}
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AA2B9C,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAgCnE;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,eAAe,GAAG,MAAM,EAAE,CAg6CxF"}
package/dist/tools.js CHANGED
@@ -16,6 +16,13 @@ import { TOOL_SCHEMAS } from './schemas.js';
16
16
  const stuckAfterMs = () => Number(process.env.MOL_AI_BG_STUCK_AFTER_MS) || 5 * 60 * 1000;
17
17
  /** Cumulative wait_for_task time per task id, this process. */
18
18
  const waitedByTask = new Map();
19
+ /**
20
+ * Each waited task's log size at the end of its last wait. A command whose log
21
+ * keeps growing is slow, not stuck: a serial 139-test suite was called stuck at
22
+ * 560 s and the executor was told to kill it while its log still grew (X1 run
23
+ * m21, 2026-10-15).
24
+ */
25
+ const logBytesByTask = new Map();
19
26
  import { checkBlockedCommand, declaredBudgetSeconds, DEFAULT_SEARCH_EXCLUDED_DIRS, directoryReadHint, isEnvFilePath, isOutsideRoot, isValidGlob, MAX_BATCH_READ_BYTES, MAX_BATCH_READ_FILES, MAX_FIND_RESULTS, MAX_OUTPUT_SIZE, MAX_READ_RETURN_CHARS, MAX_READ_SIZE, MAX_SEARCH_CONTEXT_LINES, MAX_SEARCH_RESULTS, MAX_WRITE_SIZE, outputIsWithheldUntilExit, parseCheckCommand, parseCheckProblem, pathArgError, redactSecrets, redactSecretsInCode, resolvePath, shellQuote, sliceLines, stripControlChars, truncateMiddle, whitespaceTolerantReplace, } from './utilities.js';
20
27
  /**
21
28
  * Build a complete set of AI agent tools bound to an execution backend.
@@ -1152,7 +1159,33 @@ export function buildTools(backend, config) {
1152
1159
  // exiting is not going to: on one run the executor waited five times,
1153
1160
  // 120 s each, on an e2e suite that could never start (no browser page
1154
1161
  // attached). Say so once, name the pid, and refuse to wait on it again.
1155
- const waitedBefore = waitedByTask.get(taskId) ?? 0;
1162
+ let waitedBefore = waitedByTask.get(taskId) ?? 0;
1163
+ // Output since the last wait means the command is working: the stuck
1164
+ // clock starts again from here.
1165
+ const logBytes = async () => {
1166
+ if (!/^mol-bg-[a-z0-9]+-[a-z0-9]+$/.test(taskId))
1167
+ return null;
1168
+ let r;
1169
+ try {
1170
+ r = await backend.run(`wc -c < /tmp/${taskId}.log 2>/dev/null`, { timeout: 5_000 });
1171
+ }
1172
+ catch (_error) {
1173
+ // No answer about the log: treat the size as unknown, which keeps the
1174
+ // stuck verdict exactly as before.
1175
+ r = null;
1176
+ }
1177
+ const n = Number.parseInt(r?.stdout?.trim() ?? '', 10);
1178
+ return Number.isFinite(n) ? n : null;
1179
+ };
1180
+ if (taskId && waitedBefore >= stuckAfterMs()) {
1181
+ const now = await logBytes();
1182
+ const before = logBytesByTask.get(taskId);
1183
+ if (now !== null && before !== undefined && now > before) {
1184
+ logBytesByTask.set(taskId, now);
1185
+ waitedByTask.set(taskId, 0);
1186
+ waitedBefore = 0;
1187
+ }
1188
+ }
1156
1189
  if (taskId && waitedBefore >= stuckAfterMs()) {
1157
1190
  return {
1158
1191
  taskId,
@@ -1198,6 +1231,22 @@ export function buildTools(backend, config) {
1198
1231
  const waitedMs = Date.now() - startedAt;
1199
1232
  waitedByTask.set(taskId, waitedBefore + waitedMs);
1200
1233
  if (exitCode === null) {
1234
+ const grownTo = await logBytes();
1235
+ const lastSize = logBytesByTask.get(taskId);
1236
+ if (grownTo !== null)
1237
+ logBytesByTask.set(taskId, grownTo);
1238
+ const stillWriting = grownTo !== null && (lastSize === undefined ? grownTo > 0 : grownTo > lastSize);
1239
+ if (stillWriting && waitedBefore + waitedMs >= stuckAfterMs()) {
1240
+ waitedByTask.set(taskId, 0);
1241
+ return {
1242
+ taskId,
1243
+ status: 'running',
1244
+ waitedMs,
1245
+ note: `Still running after ${Math.round((waitedBefore + waitedMs) / 1000)}s of waiting, and its ` +
1246
+ `output is still growing (${grownTo} bytes) — slow, not stuck. Call wait_for_task again to ` +
1247
+ `keep waiting; peek with exec_command: tail ${log}.`,
1248
+ };
1249
+ }
1201
1250
  if (waitedBefore + waitedMs >= stuckAfterMs()) {
1202
1251
  return {
1203
1252
  taskId,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@molecule/api-ai-tools",
3
- "version": "1.5.0",
3
+ "version": "1.5.1",
4
4
  "description": "Shared AI agent tools with backend abstraction for sandbox and local execution",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",