llmist 1.1.0 → 1.2.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.
- package/dist/{chunk-VXPZQZF5.js → chunk-KORMY3CD.js} +693 -375
- package/dist/chunk-KORMY3CD.js.map +1 -0
- package/dist/{chunk-OIPLYP7M.js → chunk-LELPPETT.js} +2 -2
- package/dist/cli.cjs +639 -321
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +2 -2
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +638 -320
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +2 -2
- package/dist/testing/index.cjs +638 -320
- package/dist/testing/index.cjs.map +1 -1
- package/dist/testing/index.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-VXPZQZF5.js.map +0 -1
- /package/dist/{chunk-OIPLYP7M.js.map → chunk-LELPPETT.js.map} +0 -0
|
@@ -1346,302 +1346,241 @@ var init_exceptions = __esm({
|
|
|
1346
1346
|
}
|
|
1347
1347
|
});
|
|
1348
1348
|
|
|
1349
|
-
// src/gadgets/
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1349
|
+
// src/gadgets/schema-introspector.ts
|
|
1350
|
+
function getDef(schema) {
|
|
1351
|
+
return schema._def;
|
|
1352
|
+
}
|
|
1353
|
+
function getTypeName(schema) {
|
|
1354
|
+
const def = getDef(schema);
|
|
1355
|
+
return def?.type ?? def?.typeName;
|
|
1356
|
+
}
|
|
1357
|
+
function getShape(schema) {
|
|
1358
|
+
const def = getDef(schema);
|
|
1359
|
+
if (typeof def?.shape === "function") {
|
|
1360
|
+
return def.shape();
|
|
1361
|
+
}
|
|
1362
|
+
return def?.shape;
|
|
1363
|
+
}
|
|
1364
|
+
var SchemaIntrospector;
|
|
1365
|
+
var init_schema_introspector = __esm({
|
|
1366
|
+
"src/gadgets/schema-introspector.ts"() {
|
|
1353
1367
|
"use strict";
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
constructor(options = {}) {
|
|
1360
|
-
this.argPrefix = options.argPrefix ?? GADGET_ARG_PREFIX;
|
|
1361
|
-
this.startPrefix = options.startPrefix ?? GADGET_START_PREFIX;
|
|
1362
|
-
this.endPrefix = options.endPrefix ?? GADGET_END_PREFIX;
|
|
1363
|
-
}
|
|
1364
|
-
/**
|
|
1365
|
-
* Format a Zod validation error with full gadget instructions.
|
|
1366
|
-
*
|
|
1367
|
-
* @param gadgetName - Name of the gadget that was called
|
|
1368
|
-
* @param zodError - The Zod validation error
|
|
1369
|
-
* @param gadget - The gadget instance (for generating instructions)
|
|
1370
|
-
* @returns Formatted error message with usage instructions
|
|
1371
|
-
*/
|
|
1372
|
-
formatValidationError(gadgetName, zodError, gadget) {
|
|
1373
|
-
const parts = [];
|
|
1374
|
-
parts.push(`Error: Invalid parameters for '${gadgetName}':`);
|
|
1375
|
-
for (const issue of zodError.issues) {
|
|
1376
|
-
const path = issue.path.join(".") || "root";
|
|
1377
|
-
parts.push(` - ${path}: ${issue.message}`);
|
|
1378
|
-
}
|
|
1379
|
-
parts.push("");
|
|
1380
|
-
parts.push("Gadget Usage:");
|
|
1381
|
-
parts.push(gadget.getInstruction(this.argPrefix));
|
|
1382
|
-
return parts.join("\n");
|
|
1383
|
-
}
|
|
1384
|
-
/**
|
|
1385
|
-
* Format a parse error with block format reference.
|
|
1386
|
-
*
|
|
1387
|
-
* @param gadgetName - Name of the gadget that was called
|
|
1388
|
-
* @param parseError - The parse error message
|
|
1389
|
-
* @param gadget - The gadget instance if found (for generating instructions)
|
|
1390
|
-
* @returns Formatted error message with format reference
|
|
1391
|
-
*/
|
|
1392
|
-
formatParseError(gadgetName, parseError, gadget) {
|
|
1393
|
-
const parts = [];
|
|
1394
|
-
parts.push(`Error: Failed to parse parameters for '${gadgetName}':`);
|
|
1395
|
-
parts.push(` ${parseError}`);
|
|
1396
|
-
if (gadget) {
|
|
1397
|
-
parts.push("");
|
|
1398
|
-
parts.push("Gadget Usage:");
|
|
1399
|
-
parts.push(gadget.getInstruction(this.argPrefix));
|
|
1400
|
-
}
|
|
1401
|
-
parts.push("");
|
|
1402
|
-
parts.push("Block Format Reference:");
|
|
1403
|
-
parts.push(` ${this.startPrefix}${gadgetName}`);
|
|
1404
|
-
parts.push(` ${this.argPrefix}parameterName`);
|
|
1405
|
-
parts.push(" parameter value here");
|
|
1406
|
-
parts.push(` ${this.endPrefix}`);
|
|
1407
|
-
return parts.join("\n");
|
|
1368
|
+
SchemaIntrospector = class {
|
|
1369
|
+
schema;
|
|
1370
|
+
cache = /* @__PURE__ */ new Map();
|
|
1371
|
+
constructor(schema) {
|
|
1372
|
+
this.schema = schema;
|
|
1408
1373
|
}
|
|
1409
1374
|
/**
|
|
1410
|
-
*
|
|
1375
|
+
* Get the expected type at a JSON pointer path.
|
|
1411
1376
|
*
|
|
1412
|
-
* @param
|
|
1413
|
-
* @
|
|
1414
|
-
* @returns Formatted error message with available gadgets
|
|
1377
|
+
* @param pointer - JSON pointer path without leading / (e.g., "config/timeout", "items/0")
|
|
1378
|
+
* @returns Type hint for coercion decision
|
|
1415
1379
|
*/
|
|
1416
|
-
|
|
1417
|
-
const
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
parts.push("");
|
|
1421
|
-
parts.push(`Available gadgets: ${availableGadgets.join(", ")}`);
|
|
1422
|
-
} else {
|
|
1423
|
-
parts.push("");
|
|
1424
|
-
parts.push("No gadgets are currently registered.");
|
|
1380
|
+
getTypeAtPath(pointer) {
|
|
1381
|
+
const cached = this.cache.get(pointer);
|
|
1382
|
+
if (cached !== void 0) {
|
|
1383
|
+
return cached;
|
|
1425
1384
|
}
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
}
|
|
1430
|
-
});
|
|
1431
|
-
|
|
1432
|
-
// src/gadgets/executor.ts
|
|
1433
|
-
var GadgetExecutor;
|
|
1434
|
-
var init_executor = __esm({
|
|
1435
|
-
"src/gadgets/executor.ts"() {
|
|
1436
|
-
"use strict";
|
|
1437
|
-
init_logger();
|
|
1438
|
-
init_error_formatter();
|
|
1439
|
-
init_exceptions();
|
|
1440
|
-
GadgetExecutor = class {
|
|
1441
|
-
constructor(registry, onHumanInputRequired, logger, defaultGadgetTimeoutMs, errorFormatterOptions) {
|
|
1442
|
-
this.registry = registry;
|
|
1443
|
-
this.onHumanInputRequired = onHumanInputRequired;
|
|
1444
|
-
this.defaultGadgetTimeoutMs = defaultGadgetTimeoutMs;
|
|
1445
|
-
this.logger = logger ?? createLogger({ name: "llmist:executor" });
|
|
1446
|
-
this.errorFormatter = new GadgetErrorFormatter(errorFormatterOptions);
|
|
1385
|
+
const result = this.resolveTypeAtPath(pointer);
|
|
1386
|
+
this.cache.set(pointer, result);
|
|
1387
|
+
return result;
|
|
1447
1388
|
}
|
|
1448
|
-
logger;
|
|
1449
|
-
errorFormatter;
|
|
1450
1389
|
/**
|
|
1451
|
-
*
|
|
1390
|
+
* Internal method to resolve type at path without caching.
|
|
1452
1391
|
*/
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
parameters: call.parameters
|
|
1467
|
-
});
|
|
1468
|
-
const rawParameters = call.parameters ?? {};
|
|
1469
|
-
let validatedParameters = rawParameters;
|
|
1470
|
-
try {
|
|
1471
|
-
const gadget = this.registry.get(call.gadgetName);
|
|
1472
|
-
if (!gadget) {
|
|
1473
|
-
this.logger.error("Gadget not found", { gadgetName: call.gadgetName });
|
|
1474
|
-
const availableGadgets = this.registry.getNames();
|
|
1475
|
-
return {
|
|
1476
|
-
gadgetName: call.gadgetName,
|
|
1477
|
-
invocationId: call.invocationId,
|
|
1478
|
-
parameters: call.parameters ?? {},
|
|
1479
|
-
error: this.errorFormatter.formatRegistryError(call.gadgetName, availableGadgets),
|
|
1480
|
-
executionTimeMs: Date.now() - startTime
|
|
1481
|
-
};
|
|
1482
|
-
}
|
|
1483
|
-
if (call.parseError || !call.parameters) {
|
|
1484
|
-
this.logger.error("Gadget parameter parse error", {
|
|
1485
|
-
gadgetName: call.gadgetName,
|
|
1486
|
-
parseError: call.parseError,
|
|
1487
|
-
rawParameters: call.parametersRaw
|
|
1488
|
-
});
|
|
1489
|
-
const parseErrorMessage = call.parseError ?? "Failed to parse parameters";
|
|
1490
|
-
return {
|
|
1491
|
-
gadgetName: call.gadgetName,
|
|
1492
|
-
invocationId: call.invocationId,
|
|
1493
|
-
parameters: {},
|
|
1494
|
-
error: this.errorFormatter.formatParseError(call.gadgetName, parseErrorMessage, gadget),
|
|
1495
|
-
executionTimeMs: Date.now() - startTime
|
|
1496
|
-
};
|
|
1497
|
-
}
|
|
1498
|
-
if (gadget.parameterSchema) {
|
|
1499
|
-
const validationResult = gadget.parameterSchema.safeParse(rawParameters);
|
|
1500
|
-
if (!validationResult.success) {
|
|
1501
|
-
const validationError = this.errorFormatter.formatValidationError(
|
|
1502
|
-
call.gadgetName,
|
|
1503
|
-
validationResult.error,
|
|
1504
|
-
gadget
|
|
1505
|
-
);
|
|
1506
|
-
this.logger.error("Gadget parameter validation failed", {
|
|
1507
|
-
gadgetName: call.gadgetName,
|
|
1508
|
-
issueCount: validationResult.error.issues.length
|
|
1509
|
-
});
|
|
1510
|
-
return {
|
|
1511
|
-
gadgetName: call.gadgetName,
|
|
1512
|
-
invocationId: call.invocationId,
|
|
1513
|
-
parameters: rawParameters,
|
|
1514
|
-
error: validationError,
|
|
1515
|
-
executionTimeMs: Date.now() - startTime
|
|
1516
|
-
};
|
|
1392
|
+
resolveTypeAtPath(pointer) {
|
|
1393
|
+
if (!pointer) {
|
|
1394
|
+
return this.getBaseType(this.schema);
|
|
1395
|
+
}
|
|
1396
|
+
const segments = pointer.split("/");
|
|
1397
|
+
let current = this.schema;
|
|
1398
|
+
for (const segment of segments) {
|
|
1399
|
+
current = this.unwrapSchema(current);
|
|
1400
|
+
const typeName = getTypeName(current);
|
|
1401
|
+
if (typeName === "object" || typeName === "ZodObject") {
|
|
1402
|
+
const shape = getShape(current);
|
|
1403
|
+
if (!shape || !(segment in shape)) {
|
|
1404
|
+
return "unknown";
|
|
1517
1405
|
}
|
|
1518
|
-
|
|
1519
|
-
}
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
if (timeoutMs && timeoutMs > 0) {
|
|
1523
|
-
this.logger.debug("Executing gadget with timeout", {
|
|
1524
|
-
gadgetName: call.gadgetName,
|
|
1525
|
-
timeoutMs
|
|
1526
|
-
});
|
|
1527
|
-
result = await Promise.race([
|
|
1528
|
-
Promise.resolve(gadget.execute(validatedParameters)),
|
|
1529
|
-
this.createTimeoutPromise(call.gadgetName, timeoutMs)
|
|
1530
|
-
]);
|
|
1531
|
-
} else {
|
|
1532
|
-
result = await Promise.resolve(gadget.execute(validatedParameters));
|
|
1533
|
-
}
|
|
1534
|
-
const executionTimeMs = Date.now() - startTime;
|
|
1535
|
-
this.logger.info("Gadget executed successfully", {
|
|
1536
|
-
gadgetName: call.gadgetName,
|
|
1537
|
-
invocationId: call.invocationId,
|
|
1538
|
-
executionTimeMs
|
|
1539
|
-
});
|
|
1540
|
-
this.logger.debug("Gadget result", {
|
|
1541
|
-
gadgetName: call.gadgetName,
|
|
1542
|
-
invocationId: call.invocationId,
|
|
1543
|
-
parameters: validatedParameters,
|
|
1544
|
-
result,
|
|
1545
|
-
executionTimeMs
|
|
1546
|
-
});
|
|
1547
|
-
return {
|
|
1548
|
-
gadgetName: call.gadgetName,
|
|
1549
|
-
invocationId: call.invocationId,
|
|
1550
|
-
parameters: validatedParameters,
|
|
1551
|
-
result,
|
|
1552
|
-
executionTimeMs
|
|
1553
|
-
};
|
|
1554
|
-
} catch (error) {
|
|
1555
|
-
if (error instanceof BreakLoopException) {
|
|
1556
|
-
this.logger.info("Gadget requested loop termination", {
|
|
1557
|
-
gadgetName: call.gadgetName,
|
|
1558
|
-
message: error.message
|
|
1559
|
-
});
|
|
1560
|
-
return {
|
|
1561
|
-
gadgetName: call.gadgetName,
|
|
1562
|
-
invocationId: call.invocationId,
|
|
1563
|
-
parameters: validatedParameters,
|
|
1564
|
-
result: error.message,
|
|
1565
|
-
breaksLoop: true,
|
|
1566
|
-
executionTimeMs: Date.now() - startTime
|
|
1567
|
-
};
|
|
1568
|
-
}
|
|
1569
|
-
if (error instanceof TimeoutException) {
|
|
1570
|
-
this.logger.error("Gadget execution timed out", {
|
|
1571
|
-
gadgetName: call.gadgetName,
|
|
1572
|
-
timeoutMs: error.timeoutMs,
|
|
1573
|
-
executionTimeMs: Date.now() - startTime
|
|
1574
|
-
});
|
|
1575
|
-
return {
|
|
1576
|
-
gadgetName: call.gadgetName,
|
|
1577
|
-
invocationId: call.invocationId,
|
|
1578
|
-
parameters: validatedParameters,
|
|
1579
|
-
error: error.message,
|
|
1580
|
-
executionTimeMs: Date.now() - startTime
|
|
1581
|
-
};
|
|
1582
|
-
}
|
|
1583
|
-
if (error instanceof HumanInputException) {
|
|
1584
|
-
this.logger.info("Gadget requested human input", {
|
|
1585
|
-
gadgetName: call.gadgetName,
|
|
1586
|
-
question: error.question
|
|
1587
|
-
});
|
|
1588
|
-
if (this.onHumanInputRequired) {
|
|
1589
|
-
try {
|
|
1590
|
-
const answer = await this.onHumanInputRequired(error.question);
|
|
1591
|
-
this.logger.debug("Human input received", {
|
|
1592
|
-
gadgetName: call.gadgetName,
|
|
1593
|
-
answerLength: answer.length
|
|
1594
|
-
});
|
|
1595
|
-
return {
|
|
1596
|
-
gadgetName: call.gadgetName,
|
|
1597
|
-
invocationId: call.invocationId,
|
|
1598
|
-
parameters: validatedParameters,
|
|
1599
|
-
result: answer,
|
|
1600
|
-
executionTimeMs: Date.now() - startTime
|
|
1601
|
-
};
|
|
1602
|
-
} catch (inputError) {
|
|
1603
|
-
this.logger.error("Human input callback error", {
|
|
1604
|
-
gadgetName: call.gadgetName,
|
|
1605
|
-
error: inputError instanceof Error ? inputError.message : String(inputError)
|
|
1606
|
-
});
|
|
1607
|
-
return {
|
|
1608
|
-
gadgetName: call.gadgetName,
|
|
1609
|
-
invocationId: call.invocationId,
|
|
1610
|
-
parameters: validatedParameters,
|
|
1611
|
-
error: inputError instanceof Error ? inputError.message : String(inputError),
|
|
1612
|
-
executionTimeMs: Date.now() - startTime
|
|
1613
|
-
};
|
|
1614
|
-
}
|
|
1406
|
+
current = shape[segment];
|
|
1407
|
+
} else if (typeName === "array" || typeName === "ZodArray") {
|
|
1408
|
+
if (!/^\d+$/.test(segment)) {
|
|
1409
|
+
return "unknown";
|
|
1615
1410
|
}
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
}
|
|
1411
|
+
const def = getDef(current);
|
|
1412
|
+
const elementType = def?.element ?? def?.type;
|
|
1413
|
+
if (!elementType) {
|
|
1414
|
+
return "unknown";
|
|
1415
|
+
}
|
|
1416
|
+
current = elementType;
|
|
1417
|
+
} else if (typeName === "tuple" || typeName === "ZodTuple") {
|
|
1418
|
+
if (!/^\d+$/.test(segment)) {
|
|
1419
|
+
return "unknown";
|
|
1420
|
+
}
|
|
1421
|
+
const index = parseInt(segment, 10);
|
|
1422
|
+
const def = getDef(current);
|
|
1423
|
+
const items = def?.items;
|
|
1424
|
+
if (!items || index >= items.length) {
|
|
1425
|
+
return "unknown";
|
|
1426
|
+
}
|
|
1427
|
+
current = items[index];
|
|
1428
|
+
} else if (typeName === "record" || typeName === "ZodRecord") {
|
|
1429
|
+
const def = getDef(current);
|
|
1430
|
+
const valueType = def?.valueType;
|
|
1431
|
+
if (!valueType) {
|
|
1432
|
+
return "unknown";
|
|
1433
|
+
}
|
|
1434
|
+
current = valueType;
|
|
1435
|
+
} else {
|
|
1436
|
+
return "unknown";
|
|
1626
1437
|
}
|
|
1627
|
-
const executionTimeMs = Date.now() - startTime;
|
|
1628
|
-
this.logger.error("Gadget execution failed", {
|
|
1629
|
-
gadgetName: call.gadgetName,
|
|
1630
|
-
error: error instanceof Error ? error.message : String(error),
|
|
1631
|
-
executionTimeMs
|
|
1632
|
-
});
|
|
1633
|
-
return {
|
|
1634
|
-
gadgetName: call.gadgetName,
|
|
1635
|
-
invocationId: call.invocationId,
|
|
1636
|
-
parameters: validatedParameters,
|
|
1637
|
-
error: error instanceof Error ? error.message : String(error),
|
|
1638
|
-
executionTimeMs
|
|
1639
|
-
};
|
|
1640
1438
|
}
|
|
1439
|
+
return this.getBaseType(current);
|
|
1641
1440
|
}
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1441
|
+
/**
|
|
1442
|
+
* Unwrap schema modifiers (optional, default, nullable, branded, etc.)
|
|
1443
|
+
* to get to the underlying type.
|
|
1444
|
+
*/
|
|
1445
|
+
unwrapSchema(schema) {
|
|
1446
|
+
let current = schema;
|
|
1447
|
+
let iterations = 0;
|
|
1448
|
+
const maxIterations = 20;
|
|
1449
|
+
while (iterations < maxIterations) {
|
|
1450
|
+
const typeName = getTypeName(current);
|
|
1451
|
+
const wrapperTypes = [
|
|
1452
|
+
"optional",
|
|
1453
|
+
"nullable",
|
|
1454
|
+
"default",
|
|
1455
|
+
"catch",
|
|
1456
|
+
"branded",
|
|
1457
|
+
"readonly",
|
|
1458
|
+
"pipeline",
|
|
1459
|
+
"ZodOptional",
|
|
1460
|
+
"ZodNullable",
|
|
1461
|
+
"ZodDefault",
|
|
1462
|
+
"ZodCatch",
|
|
1463
|
+
"ZodBranded",
|
|
1464
|
+
"ZodReadonly",
|
|
1465
|
+
"ZodPipeline"
|
|
1466
|
+
];
|
|
1467
|
+
if (typeName && wrapperTypes.includes(typeName)) {
|
|
1468
|
+
const def = getDef(current);
|
|
1469
|
+
const inner = def?.innerType ?? def?.in ?? def?.type;
|
|
1470
|
+
if (!inner || inner === current) break;
|
|
1471
|
+
current = inner;
|
|
1472
|
+
iterations++;
|
|
1473
|
+
continue;
|
|
1474
|
+
}
|
|
1475
|
+
break;
|
|
1476
|
+
}
|
|
1477
|
+
return current;
|
|
1478
|
+
}
|
|
1479
|
+
/**
|
|
1480
|
+
* Get the primitive type hint from an unwrapped schema.
|
|
1481
|
+
*/
|
|
1482
|
+
getBaseType(schema) {
|
|
1483
|
+
const unwrapped = this.unwrapSchema(schema);
|
|
1484
|
+
const typeName = getTypeName(unwrapped);
|
|
1485
|
+
switch (typeName) {
|
|
1486
|
+
// Primitive types
|
|
1487
|
+
case "string":
|
|
1488
|
+
case "ZodString":
|
|
1489
|
+
return "string";
|
|
1490
|
+
case "number":
|
|
1491
|
+
case "ZodNumber":
|
|
1492
|
+
case "bigint":
|
|
1493
|
+
case "ZodBigInt":
|
|
1494
|
+
return "number";
|
|
1495
|
+
case "boolean":
|
|
1496
|
+
case "ZodBoolean":
|
|
1497
|
+
return "boolean";
|
|
1498
|
+
// Literal types - check the literal value type
|
|
1499
|
+
case "literal":
|
|
1500
|
+
case "ZodLiteral": {
|
|
1501
|
+
const def = getDef(unwrapped);
|
|
1502
|
+
const values = def?.values;
|
|
1503
|
+
const value = values?.[0] ?? def?.value;
|
|
1504
|
+
if (typeof value === "string") return "string";
|
|
1505
|
+
if (typeof value === "number" || typeof value === "bigint")
|
|
1506
|
+
return "number";
|
|
1507
|
+
if (typeof value === "boolean") return "boolean";
|
|
1508
|
+
return "unknown";
|
|
1509
|
+
}
|
|
1510
|
+
// Enum - always string keys
|
|
1511
|
+
case "enum":
|
|
1512
|
+
case "ZodEnum":
|
|
1513
|
+
case "nativeEnum":
|
|
1514
|
+
case "ZodNativeEnum":
|
|
1515
|
+
return "string";
|
|
1516
|
+
// Union - return 'unknown' to let auto-coercion decide
|
|
1517
|
+
// Since multiple types are valid, we can't definitively say what the LLM intended
|
|
1518
|
+
// Auto-coercion will handle common cases (numbers, booleans) appropriately
|
|
1519
|
+
case "union":
|
|
1520
|
+
case "ZodUnion":
|
|
1521
|
+
return "unknown";
|
|
1522
|
+
// Discriminated union - complex, return unknown
|
|
1523
|
+
case "discriminatedUnion":
|
|
1524
|
+
case "ZodDiscriminatedUnion":
|
|
1525
|
+
return "unknown";
|
|
1526
|
+
// Intersection - check both sides
|
|
1527
|
+
case "intersection":
|
|
1528
|
+
case "ZodIntersection": {
|
|
1529
|
+
const def = getDef(unwrapped);
|
|
1530
|
+
const left = def?.left;
|
|
1531
|
+
const right = def?.right;
|
|
1532
|
+
if (!left || !right) return "unknown";
|
|
1533
|
+
const leftType = this.getBaseType(left);
|
|
1534
|
+
const rightType = this.getBaseType(right);
|
|
1535
|
+
if (leftType === rightType) return leftType;
|
|
1536
|
+
if (leftType === "string" || rightType === "string") return "string";
|
|
1537
|
+
return "unknown";
|
|
1538
|
+
}
|
|
1539
|
+
// Effects/transforms - return unknown to let Zod handle it
|
|
1540
|
+
case "effects":
|
|
1541
|
+
case "ZodEffects":
|
|
1542
|
+
return "unknown";
|
|
1543
|
+
// Lazy - can't resolve without evaluating
|
|
1544
|
+
case "lazy":
|
|
1545
|
+
case "ZodLazy":
|
|
1546
|
+
return "unknown";
|
|
1547
|
+
// Complex types - return unknown
|
|
1548
|
+
case "object":
|
|
1549
|
+
case "ZodObject":
|
|
1550
|
+
case "array":
|
|
1551
|
+
case "ZodArray":
|
|
1552
|
+
case "tuple":
|
|
1553
|
+
case "ZodTuple":
|
|
1554
|
+
case "record":
|
|
1555
|
+
case "ZodRecord":
|
|
1556
|
+
case "map":
|
|
1557
|
+
case "ZodMap":
|
|
1558
|
+
case "set":
|
|
1559
|
+
case "ZodSet":
|
|
1560
|
+
case "function":
|
|
1561
|
+
case "ZodFunction":
|
|
1562
|
+
case "promise":
|
|
1563
|
+
case "ZodPromise":
|
|
1564
|
+
case "date":
|
|
1565
|
+
case "ZodDate":
|
|
1566
|
+
return "unknown";
|
|
1567
|
+
// Unknown/any/never/void/undefined/null
|
|
1568
|
+
case "unknown":
|
|
1569
|
+
case "ZodUnknown":
|
|
1570
|
+
case "any":
|
|
1571
|
+
case "ZodAny":
|
|
1572
|
+
case "never":
|
|
1573
|
+
case "ZodNever":
|
|
1574
|
+
case "void":
|
|
1575
|
+
case "ZodVoid":
|
|
1576
|
+
case "undefined":
|
|
1577
|
+
case "ZodUndefined":
|
|
1578
|
+
case "null":
|
|
1579
|
+
case "ZodNull":
|
|
1580
|
+
return "unknown";
|
|
1581
|
+
default:
|
|
1582
|
+
return "unknown";
|
|
1583
|
+
}
|
|
1645
1584
|
}
|
|
1646
1585
|
};
|
|
1647
1586
|
}
|
|
@@ -1652,6 +1591,7 @@ function parseBlockParams(content, options) {
|
|
|
1652
1591
|
const argPrefix = options?.argPrefix ?? GADGET_ARG_PREFIX;
|
|
1653
1592
|
const result = {};
|
|
1654
1593
|
const seenPointers = /* @__PURE__ */ new Set();
|
|
1594
|
+
const introspector = options?.schema ? new SchemaIntrospector(options.schema) : void 0;
|
|
1655
1595
|
const parts = content.split(argPrefix);
|
|
1656
1596
|
for (let i = 1; i < parts.length; i++) {
|
|
1657
1597
|
const part = parts[i];
|
|
@@ -1663,7 +1603,7 @@ function parseBlockParams(content, options) {
|
|
|
1663
1603
|
throw new Error(`Duplicate pointer: ${pointer2}`);
|
|
1664
1604
|
}
|
|
1665
1605
|
seenPointers.add(pointer2);
|
|
1666
|
-
setByPointer(result, pointer2, "");
|
|
1606
|
+
setByPointer(result, pointer2, "", introspector);
|
|
1667
1607
|
}
|
|
1668
1608
|
continue;
|
|
1669
1609
|
}
|
|
@@ -1679,15 +1619,30 @@ function parseBlockParams(content, options) {
|
|
|
1679
1619
|
throw new Error(`Duplicate pointer: ${pointer}`);
|
|
1680
1620
|
}
|
|
1681
1621
|
seenPointers.add(pointer);
|
|
1682
|
-
setByPointer(result, pointer, value);
|
|
1622
|
+
setByPointer(result, pointer, value, introspector);
|
|
1683
1623
|
}
|
|
1684
1624
|
return result;
|
|
1685
1625
|
}
|
|
1686
|
-
function coerceValue(value) {
|
|
1626
|
+
function coerceValue(value, expectedType) {
|
|
1687
1627
|
if (value.includes("\n")) {
|
|
1688
1628
|
return value;
|
|
1689
1629
|
}
|
|
1690
1630
|
const trimmed = value.trim();
|
|
1631
|
+
if (expectedType === "string") {
|
|
1632
|
+
return value;
|
|
1633
|
+
}
|
|
1634
|
+
if (expectedType === "boolean") {
|
|
1635
|
+
if (trimmed === "true") return true;
|
|
1636
|
+
if (trimmed === "false") return false;
|
|
1637
|
+
return value;
|
|
1638
|
+
}
|
|
1639
|
+
if (expectedType === "number") {
|
|
1640
|
+
const num = Number(trimmed);
|
|
1641
|
+
if (!isNaN(num) && isFinite(num) && trimmed !== "") {
|
|
1642
|
+
return num;
|
|
1643
|
+
}
|
|
1644
|
+
return value;
|
|
1645
|
+
}
|
|
1691
1646
|
if (trimmed === "true") return true;
|
|
1692
1647
|
if (trimmed === "false") return false;
|
|
1693
1648
|
if (trimmed !== "" && /^-?\d+(\.\d+)?$/.test(trimmed)) {
|
|
@@ -1698,7 +1653,7 @@ function coerceValue(value) {
|
|
|
1698
1653
|
}
|
|
1699
1654
|
return value;
|
|
1700
1655
|
}
|
|
1701
|
-
function setByPointer(obj, pointer, value) {
|
|
1656
|
+
function setByPointer(obj, pointer, value, introspector) {
|
|
1702
1657
|
const segments = pointer.split("/");
|
|
1703
1658
|
let current = obj;
|
|
1704
1659
|
for (let i = 0; i < segments.length - 1; i++) {
|
|
@@ -1726,7 +1681,8 @@ function setByPointer(obj, pointer, value) {
|
|
|
1726
1681
|
}
|
|
1727
1682
|
}
|
|
1728
1683
|
const lastSegment = segments[segments.length - 1];
|
|
1729
|
-
const
|
|
1684
|
+
const expectedType = introspector?.getTypeAtPath(pointer);
|
|
1685
|
+
const coercedValue = coerceValue(value, expectedType);
|
|
1730
1686
|
if (Array.isArray(current)) {
|
|
1731
1687
|
const index = parseInt(lastSegment, 10);
|
|
1732
1688
|
if (isNaN(index) || index < 0) {
|
|
@@ -1744,6 +1700,7 @@ var init_block_params = __esm({
|
|
|
1744
1700
|
"src/gadgets/block-params.ts"() {
|
|
1745
1701
|
"use strict";
|
|
1746
1702
|
init_constants();
|
|
1703
|
+
init_schema_introspector();
|
|
1747
1704
|
}
|
|
1748
1705
|
});
|
|
1749
1706
|
|
|
@@ -1823,102 +1780,462 @@ var init_parser = __esm({
|
|
|
1823
1780
|
if (textBefore !== void 0) {
|
|
1824
1781
|
yield { type: "text", content: textBefore };
|
|
1825
1782
|
}
|
|
1826
|
-
const metadataStartIndex = partStartIndex + this.startPrefix.length;
|
|
1827
|
-
const metadataEndIndex = this.buffer.indexOf("\n", metadataStartIndex);
|
|
1828
|
-
if (metadataEndIndex === -1) break;
|
|
1829
|
-
const gadgetName = this.buffer.substring(metadataStartIndex, metadataEndIndex).trim();
|
|
1830
|
-
const { actualName: actualGadgetName, invocationId } = this.parseGadgetName(gadgetName);
|
|
1831
|
-
const contentStartIndex = metadataEndIndex + 1;
|
|
1832
|
-
let partEndIndex;
|
|
1833
|
-
let endMarkerLength = 0;
|
|
1834
|
-
if (gadgetName.includes(":")) {
|
|
1835
|
-
const oldEndMarker = `${this.endPrefix + actualGadgetName}:${invocationId}`;
|
|
1836
|
-
partEndIndex = this.buffer.indexOf(oldEndMarker, contentStartIndex);
|
|
1837
|
-
if (partEndIndex === -1) break;
|
|
1838
|
-
endMarkerLength = oldEndMarker.length;
|
|
1839
|
-
} else {
|
|
1840
|
-
const nextStartPos = this.buffer.indexOf(this.startPrefix, contentStartIndex);
|
|
1841
|
-
let validEndPos = -1;
|
|
1842
|
-
let searchPos = contentStartIndex;
|
|
1843
|
-
while (true) {
|
|
1844
|
-
const endPos = this.buffer.indexOf(this.endPrefix, searchPos);
|
|
1845
|
-
if (endPos === -1) break;
|
|
1846
|
-
const afterEnd = this.buffer.substring(endPos + this.endPrefix.length);
|
|
1847
|
-
if (afterEnd.startsWith("\n") || afterEnd.startsWith("\r") || afterEnd.startsWith(this.startPrefix) || afterEnd.length === 0) {
|
|
1848
|
-
validEndPos = endPos;
|
|
1849
|
-
break;
|
|
1783
|
+
const metadataStartIndex = partStartIndex + this.startPrefix.length;
|
|
1784
|
+
const metadataEndIndex = this.buffer.indexOf("\n", metadataStartIndex);
|
|
1785
|
+
if (metadataEndIndex === -1) break;
|
|
1786
|
+
const gadgetName = this.buffer.substring(metadataStartIndex, metadataEndIndex).trim();
|
|
1787
|
+
const { actualName: actualGadgetName, invocationId } = this.parseGadgetName(gadgetName);
|
|
1788
|
+
const contentStartIndex = metadataEndIndex + 1;
|
|
1789
|
+
let partEndIndex;
|
|
1790
|
+
let endMarkerLength = 0;
|
|
1791
|
+
if (gadgetName.includes(":")) {
|
|
1792
|
+
const oldEndMarker = `${this.endPrefix + actualGadgetName}:${invocationId}`;
|
|
1793
|
+
partEndIndex = this.buffer.indexOf(oldEndMarker, contentStartIndex);
|
|
1794
|
+
if (partEndIndex === -1) break;
|
|
1795
|
+
endMarkerLength = oldEndMarker.length;
|
|
1796
|
+
} else {
|
|
1797
|
+
const nextStartPos = this.buffer.indexOf(this.startPrefix, contentStartIndex);
|
|
1798
|
+
let validEndPos = -1;
|
|
1799
|
+
let searchPos = contentStartIndex;
|
|
1800
|
+
while (true) {
|
|
1801
|
+
const endPos = this.buffer.indexOf(this.endPrefix, searchPos);
|
|
1802
|
+
if (endPos === -1) break;
|
|
1803
|
+
const afterEnd = this.buffer.substring(endPos + this.endPrefix.length);
|
|
1804
|
+
if (afterEnd.startsWith("\n") || afterEnd.startsWith("\r") || afterEnd.startsWith(this.startPrefix) || afterEnd.length === 0) {
|
|
1805
|
+
validEndPos = endPos;
|
|
1806
|
+
break;
|
|
1807
|
+
} else {
|
|
1808
|
+
searchPos = endPos + this.endPrefix.length;
|
|
1809
|
+
}
|
|
1810
|
+
}
|
|
1811
|
+
if (nextStartPos !== -1 && (validEndPos === -1 || nextStartPos < validEndPos)) {
|
|
1812
|
+
partEndIndex = nextStartPos;
|
|
1813
|
+
endMarkerLength = 0;
|
|
1814
|
+
} else if (validEndPos !== -1) {
|
|
1815
|
+
partEndIndex = validEndPos;
|
|
1816
|
+
endMarkerLength = this.endPrefix.length;
|
|
1817
|
+
} else {
|
|
1818
|
+
break;
|
|
1819
|
+
}
|
|
1820
|
+
}
|
|
1821
|
+
const parametersRaw = this.buffer.substring(contentStartIndex, partEndIndex).trim();
|
|
1822
|
+
const { parameters, parseError } = this.parseParameters(parametersRaw);
|
|
1823
|
+
yield {
|
|
1824
|
+
type: "gadget_call",
|
|
1825
|
+
call: {
|
|
1826
|
+
gadgetName: actualGadgetName,
|
|
1827
|
+
invocationId,
|
|
1828
|
+
parametersRaw,
|
|
1829
|
+
parameters,
|
|
1830
|
+
parseError
|
|
1831
|
+
}
|
|
1832
|
+
};
|
|
1833
|
+
startIndex = partEndIndex + endMarkerLength;
|
|
1834
|
+
this.lastReportedTextLength = startIndex;
|
|
1835
|
+
}
|
|
1836
|
+
if (startIndex > 0) {
|
|
1837
|
+
this.buffer = this.buffer.substring(startIndex);
|
|
1838
|
+
this.lastReportedTextLength = 0;
|
|
1839
|
+
}
|
|
1840
|
+
}
|
|
1841
|
+
// Finalize parsing and return remaining text or incomplete gadgets
|
|
1842
|
+
*finalize() {
|
|
1843
|
+
const startIndex = this.buffer.indexOf(this.startPrefix, this.lastReportedTextLength);
|
|
1844
|
+
if (startIndex !== -1) {
|
|
1845
|
+
const textBefore = this.takeTextUntil(startIndex);
|
|
1846
|
+
if (textBefore !== void 0) {
|
|
1847
|
+
yield { type: "text", content: textBefore };
|
|
1848
|
+
}
|
|
1849
|
+
const metadataStartIndex = startIndex + this.startPrefix.length;
|
|
1850
|
+
const metadataEndIndex = this.buffer.indexOf("\n", metadataStartIndex);
|
|
1851
|
+
if (metadataEndIndex !== -1) {
|
|
1852
|
+
const gadgetName = this.buffer.substring(metadataStartIndex, metadataEndIndex).trim();
|
|
1853
|
+
const { actualName: actualGadgetName, invocationId } = this.parseGadgetName(gadgetName);
|
|
1854
|
+
const contentStartIndex = metadataEndIndex + 1;
|
|
1855
|
+
const parametersRaw = this.buffer.substring(contentStartIndex).trim();
|
|
1856
|
+
const { parameters, parseError } = this.parseParameters(parametersRaw);
|
|
1857
|
+
yield {
|
|
1858
|
+
type: "gadget_call",
|
|
1859
|
+
call: {
|
|
1860
|
+
gadgetName: actualGadgetName,
|
|
1861
|
+
invocationId,
|
|
1862
|
+
parametersRaw,
|
|
1863
|
+
parameters,
|
|
1864
|
+
parseError
|
|
1865
|
+
}
|
|
1866
|
+
};
|
|
1867
|
+
return;
|
|
1868
|
+
}
|
|
1869
|
+
}
|
|
1870
|
+
const remainingText = this.takeTextUntil(this.buffer.length);
|
|
1871
|
+
if (remainingText !== void 0) {
|
|
1872
|
+
yield { type: "text", content: remainingText };
|
|
1873
|
+
}
|
|
1874
|
+
}
|
|
1875
|
+
// Reset parser state (note: global invocation counter is NOT reset to ensure unique IDs)
|
|
1876
|
+
reset() {
|
|
1877
|
+
this.buffer = "";
|
|
1878
|
+
this.lastReportedTextLength = 0;
|
|
1879
|
+
}
|
|
1880
|
+
};
|
|
1881
|
+
}
|
|
1882
|
+
});
|
|
1883
|
+
|
|
1884
|
+
// src/gadgets/error-formatter.ts
|
|
1885
|
+
var GadgetErrorFormatter;
|
|
1886
|
+
var init_error_formatter = __esm({
|
|
1887
|
+
"src/gadgets/error-formatter.ts"() {
|
|
1888
|
+
"use strict";
|
|
1889
|
+
init_constants();
|
|
1890
|
+
GadgetErrorFormatter = class {
|
|
1891
|
+
argPrefix;
|
|
1892
|
+
startPrefix;
|
|
1893
|
+
endPrefix;
|
|
1894
|
+
constructor(options = {}) {
|
|
1895
|
+
this.argPrefix = options.argPrefix ?? GADGET_ARG_PREFIX;
|
|
1896
|
+
this.startPrefix = options.startPrefix ?? GADGET_START_PREFIX;
|
|
1897
|
+
this.endPrefix = options.endPrefix ?? GADGET_END_PREFIX;
|
|
1898
|
+
}
|
|
1899
|
+
/**
|
|
1900
|
+
* Format a Zod validation error with full gadget instructions.
|
|
1901
|
+
*
|
|
1902
|
+
* @param gadgetName - Name of the gadget that was called
|
|
1903
|
+
* @param zodError - The Zod validation error
|
|
1904
|
+
* @param gadget - The gadget instance (for generating instructions)
|
|
1905
|
+
* @returns Formatted error message with usage instructions
|
|
1906
|
+
*/
|
|
1907
|
+
formatValidationError(gadgetName, zodError, gadget) {
|
|
1908
|
+
const parts = [];
|
|
1909
|
+
parts.push(`Error: Invalid parameters for '${gadgetName}':`);
|
|
1910
|
+
for (const issue of zodError.issues) {
|
|
1911
|
+
const path = issue.path.join(".") || "root";
|
|
1912
|
+
parts.push(` - ${path}: ${issue.message}`);
|
|
1913
|
+
}
|
|
1914
|
+
parts.push("");
|
|
1915
|
+
parts.push("Gadget Usage:");
|
|
1916
|
+
parts.push(gadget.getInstruction(this.argPrefix));
|
|
1917
|
+
return parts.join("\n");
|
|
1918
|
+
}
|
|
1919
|
+
/**
|
|
1920
|
+
* Format a parse error with block format reference.
|
|
1921
|
+
*
|
|
1922
|
+
* @param gadgetName - Name of the gadget that was called
|
|
1923
|
+
* @param parseError - The parse error message
|
|
1924
|
+
* @param gadget - The gadget instance if found (for generating instructions)
|
|
1925
|
+
* @returns Formatted error message with format reference
|
|
1926
|
+
*/
|
|
1927
|
+
formatParseError(gadgetName, parseError, gadget) {
|
|
1928
|
+
const parts = [];
|
|
1929
|
+
parts.push(`Error: Failed to parse parameters for '${gadgetName}':`);
|
|
1930
|
+
parts.push(` ${parseError}`);
|
|
1931
|
+
if (gadget) {
|
|
1932
|
+
parts.push("");
|
|
1933
|
+
parts.push("Gadget Usage:");
|
|
1934
|
+
parts.push(gadget.getInstruction(this.argPrefix));
|
|
1935
|
+
}
|
|
1936
|
+
parts.push("");
|
|
1937
|
+
parts.push("Block Format Reference:");
|
|
1938
|
+
parts.push(` ${this.startPrefix}${gadgetName}`);
|
|
1939
|
+
parts.push(` ${this.argPrefix}parameterName`);
|
|
1940
|
+
parts.push(" parameter value here");
|
|
1941
|
+
parts.push(` ${this.endPrefix}`);
|
|
1942
|
+
return parts.join("\n");
|
|
1943
|
+
}
|
|
1944
|
+
/**
|
|
1945
|
+
* Format a registry error (gadget not found) with available gadgets list.
|
|
1946
|
+
*
|
|
1947
|
+
* @param gadgetName - Name of the gadget that was not found
|
|
1948
|
+
* @param availableGadgets - List of available gadget names
|
|
1949
|
+
* @returns Formatted error message with available gadgets
|
|
1950
|
+
*/
|
|
1951
|
+
formatRegistryError(gadgetName, availableGadgets) {
|
|
1952
|
+
const parts = [];
|
|
1953
|
+
parts.push(`Error: Gadget '${gadgetName}' not found.`);
|
|
1954
|
+
if (availableGadgets.length > 0) {
|
|
1955
|
+
parts.push("");
|
|
1956
|
+
parts.push(`Available gadgets: ${availableGadgets.join(", ")}`);
|
|
1957
|
+
} else {
|
|
1958
|
+
parts.push("");
|
|
1959
|
+
parts.push("No gadgets are currently registered.");
|
|
1960
|
+
}
|
|
1961
|
+
return parts.join("\n");
|
|
1962
|
+
}
|
|
1963
|
+
};
|
|
1964
|
+
}
|
|
1965
|
+
});
|
|
1966
|
+
|
|
1967
|
+
// src/gadgets/executor.ts
|
|
1968
|
+
var GadgetExecutor;
|
|
1969
|
+
var init_executor = __esm({
|
|
1970
|
+
"src/gadgets/executor.ts"() {
|
|
1971
|
+
"use strict";
|
|
1972
|
+
init_constants();
|
|
1973
|
+
init_logger();
|
|
1974
|
+
init_block_params();
|
|
1975
|
+
init_error_formatter();
|
|
1976
|
+
init_exceptions();
|
|
1977
|
+
init_parser();
|
|
1978
|
+
GadgetExecutor = class {
|
|
1979
|
+
constructor(registry, onHumanInputRequired, logger, defaultGadgetTimeoutMs, errorFormatterOptions) {
|
|
1980
|
+
this.registry = registry;
|
|
1981
|
+
this.onHumanInputRequired = onHumanInputRequired;
|
|
1982
|
+
this.defaultGadgetTimeoutMs = defaultGadgetTimeoutMs;
|
|
1983
|
+
this.logger = logger ?? createLogger({ name: "llmist:executor" });
|
|
1984
|
+
this.errorFormatter = new GadgetErrorFormatter(errorFormatterOptions);
|
|
1985
|
+
this.argPrefix = errorFormatterOptions?.argPrefix ?? GADGET_ARG_PREFIX;
|
|
1986
|
+
}
|
|
1987
|
+
logger;
|
|
1988
|
+
errorFormatter;
|
|
1989
|
+
argPrefix;
|
|
1990
|
+
/**
|
|
1991
|
+
* Creates a promise that rejects with a TimeoutException after the specified timeout.
|
|
1992
|
+
*/
|
|
1993
|
+
createTimeoutPromise(gadgetName, timeoutMs) {
|
|
1994
|
+
return new Promise((_, reject) => {
|
|
1995
|
+
setTimeout(() => {
|
|
1996
|
+
reject(new TimeoutException(gadgetName, timeoutMs));
|
|
1997
|
+
}, timeoutMs);
|
|
1998
|
+
});
|
|
1999
|
+
}
|
|
2000
|
+
// Execute a gadget call asynchronously
|
|
2001
|
+
async execute(call) {
|
|
2002
|
+
const startTime = Date.now();
|
|
2003
|
+
this.logger.debug("Executing gadget", {
|
|
2004
|
+
gadgetName: call.gadgetName,
|
|
2005
|
+
invocationId: call.invocationId,
|
|
2006
|
+
parameters: call.parameters
|
|
2007
|
+
});
|
|
2008
|
+
const rawParameters = call.parameters ?? {};
|
|
2009
|
+
let validatedParameters = rawParameters;
|
|
2010
|
+
try {
|
|
2011
|
+
const gadget = this.registry.get(call.gadgetName);
|
|
2012
|
+
if (!gadget) {
|
|
2013
|
+
this.logger.error("Gadget not found", { gadgetName: call.gadgetName });
|
|
2014
|
+
const availableGadgets = this.registry.getNames();
|
|
2015
|
+
return {
|
|
2016
|
+
gadgetName: call.gadgetName,
|
|
2017
|
+
invocationId: call.invocationId,
|
|
2018
|
+
parameters: call.parameters ?? {},
|
|
2019
|
+
error: this.errorFormatter.formatRegistryError(call.gadgetName, availableGadgets),
|
|
2020
|
+
executionTimeMs: Date.now() - startTime
|
|
2021
|
+
};
|
|
2022
|
+
}
|
|
2023
|
+
if (call.parseError || !call.parameters) {
|
|
2024
|
+
this.logger.error("Gadget parameter parse error", {
|
|
2025
|
+
gadgetName: call.gadgetName,
|
|
2026
|
+
parseError: call.parseError,
|
|
2027
|
+
rawParameters: call.parametersRaw
|
|
2028
|
+
});
|
|
2029
|
+
const parseErrorMessage = call.parseError ?? "Failed to parse parameters";
|
|
2030
|
+
return {
|
|
2031
|
+
gadgetName: call.gadgetName,
|
|
2032
|
+
invocationId: call.invocationId,
|
|
2033
|
+
parameters: {},
|
|
2034
|
+
error: this.errorFormatter.formatParseError(call.gadgetName, parseErrorMessage, gadget),
|
|
2035
|
+
executionTimeMs: Date.now() - startTime
|
|
2036
|
+
};
|
|
2037
|
+
}
|
|
2038
|
+
let schemaAwareParameters = rawParameters;
|
|
2039
|
+
const hasBlockFormat = call.parametersRaw?.includes(this.argPrefix);
|
|
2040
|
+
if (gadget.parameterSchema && hasBlockFormat) {
|
|
2041
|
+
try {
|
|
2042
|
+
const cleanedRaw = stripMarkdownFences(call.parametersRaw);
|
|
2043
|
+
const initialParse = parseBlockParams(cleanedRaw, { argPrefix: this.argPrefix });
|
|
2044
|
+
const parametersWereModified = !this.deepEquals(rawParameters, initialParse);
|
|
2045
|
+
if (parametersWereModified) {
|
|
2046
|
+
this.logger.debug("Parameters modified by interceptor, skipping re-parse", {
|
|
2047
|
+
gadgetName: call.gadgetName
|
|
2048
|
+
});
|
|
2049
|
+
schemaAwareParameters = rawParameters;
|
|
1850
2050
|
} else {
|
|
1851
|
-
|
|
2051
|
+
schemaAwareParameters = parseBlockParams(cleanedRaw, {
|
|
2052
|
+
argPrefix: this.argPrefix,
|
|
2053
|
+
schema: gadget.parameterSchema
|
|
2054
|
+
});
|
|
2055
|
+
this.logger.debug("Re-parsed parameters with schema", {
|
|
2056
|
+
gadgetName: call.gadgetName,
|
|
2057
|
+
original: rawParameters,
|
|
2058
|
+
schemaAware: schemaAwareParameters
|
|
2059
|
+
});
|
|
1852
2060
|
}
|
|
1853
|
-
}
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
endMarkerLength = this.endPrefix.length;
|
|
1860
|
-
} else {
|
|
1861
|
-
break;
|
|
2061
|
+
} catch (error) {
|
|
2062
|
+
this.logger.warn("Schema-aware re-parsing failed, using original parameters", {
|
|
2063
|
+
gadgetName: call.gadgetName,
|
|
2064
|
+
error: error instanceof Error ? error.message : String(error)
|
|
2065
|
+
});
|
|
2066
|
+
schemaAwareParameters = rawParameters;
|
|
1862
2067
|
}
|
|
1863
2068
|
}
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
2069
|
+
if (gadget.parameterSchema) {
|
|
2070
|
+
const validationResult = gadget.parameterSchema.safeParse(schemaAwareParameters);
|
|
2071
|
+
if (!validationResult.success) {
|
|
2072
|
+
const validationError = this.errorFormatter.formatValidationError(
|
|
2073
|
+
call.gadgetName,
|
|
2074
|
+
validationResult.error,
|
|
2075
|
+
gadget
|
|
2076
|
+
);
|
|
2077
|
+
this.logger.error("Gadget parameter validation failed", {
|
|
2078
|
+
gadgetName: call.gadgetName,
|
|
2079
|
+
issueCount: validationResult.error.issues.length
|
|
2080
|
+
});
|
|
2081
|
+
return {
|
|
2082
|
+
gadgetName: call.gadgetName,
|
|
2083
|
+
invocationId: call.invocationId,
|
|
2084
|
+
parameters: schemaAwareParameters,
|
|
2085
|
+
error: validationError,
|
|
2086
|
+
executionTimeMs: Date.now() - startTime
|
|
2087
|
+
};
|
|
1874
2088
|
}
|
|
2089
|
+
validatedParameters = validationResult.data;
|
|
2090
|
+
} else {
|
|
2091
|
+
validatedParameters = schemaAwareParameters;
|
|
2092
|
+
}
|
|
2093
|
+
const timeoutMs = gadget.timeoutMs ?? this.defaultGadgetTimeoutMs;
|
|
2094
|
+
let result;
|
|
2095
|
+
if (timeoutMs && timeoutMs > 0) {
|
|
2096
|
+
this.logger.debug("Executing gadget with timeout", {
|
|
2097
|
+
gadgetName: call.gadgetName,
|
|
2098
|
+
timeoutMs
|
|
2099
|
+
});
|
|
2100
|
+
result = await Promise.race([
|
|
2101
|
+
Promise.resolve(gadget.execute(validatedParameters)),
|
|
2102
|
+
this.createTimeoutPromise(call.gadgetName, timeoutMs)
|
|
2103
|
+
]);
|
|
2104
|
+
} else {
|
|
2105
|
+
result = await Promise.resolve(gadget.execute(validatedParameters));
|
|
2106
|
+
}
|
|
2107
|
+
const executionTimeMs = Date.now() - startTime;
|
|
2108
|
+
this.logger.info("Gadget executed successfully", {
|
|
2109
|
+
gadgetName: call.gadgetName,
|
|
2110
|
+
invocationId: call.invocationId,
|
|
2111
|
+
executionTimeMs
|
|
2112
|
+
});
|
|
2113
|
+
this.logger.debug("Gadget result", {
|
|
2114
|
+
gadgetName: call.gadgetName,
|
|
2115
|
+
invocationId: call.invocationId,
|
|
2116
|
+
parameters: validatedParameters,
|
|
2117
|
+
result,
|
|
2118
|
+
executionTimeMs
|
|
2119
|
+
});
|
|
2120
|
+
return {
|
|
2121
|
+
gadgetName: call.gadgetName,
|
|
2122
|
+
invocationId: call.invocationId,
|
|
2123
|
+
parameters: validatedParameters,
|
|
2124
|
+
result,
|
|
2125
|
+
executionTimeMs
|
|
1875
2126
|
};
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
yield { type: "text", content: textBefore };
|
|
2127
|
+
} catch (error) {
|
|
2128
|
+
if (error instanceof BreakLoopException) {
|
|
2129
|
+
this.logger.info("Gadget requested loop termination", {
|
|
2130
|
+
gadgetName: call.gadgetName,
|
|
2131
|
+
message: error.message
|
|
2132
|
+
});
|
|
2133
|
+
return {
|
|
2134
|
+
gadgetName: call.gadgetName,
|
|
2135
|
+
invocationId: call.invocationId,
|
|
2136
|
+
parameters: validatedParameters,
|
|
2137
|
+
result: error.message,
|
|
2138
|
+
breaksLoop: true,
|
|
2139
|
+
executionTimeMs: Date.now() - startTime
|
|
2140
|
+
};
|
|
1891
2141
|
}
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
2142
|
+
if (error instanceof TimeoutException) {
|
|
2143
|
+
this.logger.error("Gadget execution timed out", {
|
|
2144
|
+
gadgetName: call.gadgetName,
|
|
2145
|
+
timeoutMs: error.timeoutMs,
|
|
2146
|
+
executionTimeMs: Date.now() - startTime
|
|
2147
|
+
});
|
|
2148
|
+
return {
|
|
2149
|
+
gadgetName: call.gadgetName,
|
|
2150
|
+
invocationId: call.invocationId,
|
|
2151
|
+
parameters: validatedParameters,
|
|
2152
|
+
error: error.message,
|
|
2153
|
+
executionTimeMs: Date.now() - startTime
|
|
2154
|
+
};
|
|
2155
|
+
}
|
|
2156
|
+
if (error instanceof HumanInputException) {
|
|
2157
|
+
this.logger.info("Gadget requested human input", {
|
|
2158
|
+
gadgetName: call.gadgetName,
|
|
2159
|
+
question: error.question
|
|
2160
|
+
});
|
|
2161
|
+
if (this.onHumanInputRequired) {
|
|
2162
|
+
try {
|
|
2163
|
+
const answer = await this.onHumanInputRequired(error.question);
|
|
2164
|
+
this.logger.debug("Human input received", {
|
|
2165
|
+
gadgetName: call.gadgetName,
|
|
2166
|
+
answerLength: answer.length
|
|
2167
|
+
});
|
|
2168
|
+
return {
|
|
2169
|
+
gadgetName: call.gadgetName,
|
|
2170
|
+
invocationId: call.invocationId,
|
|
2171
|
+
parameters: validatedParameters,
|
|
2172
|
+
result: answer,
|
|
2173
|
+
executionTimeMs: Date.now() - startTime
|
|
2174
|
+
};
|
|
2175
|
+
} catch (inputError) {
|
|
2176
|
+
this.logger.error("Human input callback error", {
|
|
2177
|
+
gadgetName: call.gadgetName,
|
|
2178
|
+
error: inputError instanceof Error ? inputError.message : String(inputError)
|
|
2179
|
+
});
|
|
2180
|
+
return {
|
|
2181
|
+
gadgetName: call.gadgetName,
|
|
2182
|
+
invocationId: call.invocationId,
|
|
2183
|
+
parameters: validatedParameters,
|
|
2184
|
+
error: inputError instanceof Error ? inputError.message : String(inputError),
|
|
2185
|
+
executionTimeMs: Date.now() - startTime
|
|
2186
|
+
};
|
|
1908
2187
|
}
|
|
2188
|
+
}
|
|
2189
|
+
this.logger.warn("Human input required but no callback provided", {
|
|
2190
|
+
gadgetName: call.gadgetName
|
|
2191
|
+
});
|
|
2192
|
+
return {
|
|
2193
|
+
gadgetName: call.gadgetName,
|
|
2194
|
+
invocationId: call.invocationId,
|
|
2195
|
+
parameters: validatedParameters,
|
|
2196
|
+
error: "Human input required but not available (stdin is not interactive)",
|
|
2197
|
+
executionTimeMs: Date.now() - startTime
|
|
1909
2198
|
};
|
|
1910
|
-
return;
|
|
1911
2199
|
}
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
2200
|
+
const executionTimeMs = Date.now() - startTime;
|
|
2201
|
+
this.logger.error("Gadget execution failed", {
|
|
2202
|
+
gadgetName: call.gadgetName,
|
|
2203
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2204
|
+
executionTimeMs
|
|
2205
|
+
});
|
|
2206
|
+
return {
|
|
2207
|
+
gadgetName: call.gadgetName,
|
|
2208
|
+
invocationId: call.invocationId,
|
|
2209
|
+
parameters: validatedParameters,
|
|
2210
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2211
|
+
executionTimeMs
|
|
2212
|
+
};
|
|
1916
2213
|
}
|
|
1917
2214
|
}
|
|
1918
|
-
//
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
2215
|
+
// Execute multiple gadget calls in parallel
|
|
2216
|
+
async executeAll(calls) {
|
|
2217
|
+
return Promise.all(calls.map((call) => this.execute(call)));
|
|
2218
|
+
}
|
|
2219
|
+
/**
|
|
2220
|
+
* Deep equality check for objects/arrays.
|
|
2221
|
+
* Used to detect if parameters were modified by an interceptor.
|
|
2222
|
+
*/
|
|
2223
|
+
deepEquals(a, b) {
|
|
2224
|
+
if (a === b) return true;
|
|
2225
|
+
if (a === null || b === null) return a === b;
|
|
2226
|
+
if (typeof a !== typeof b) return false;
|
|
2227
|
+
if (typeof a !== "object") return a === b;
|
|
2228
|
+
if (Array.isArray(a) !== Array.isArray(b)) return false;
|
|
2229
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
2230
|
+
if (a.length !== b.length) return false;
|
|
2231
|
+
return a.every((val, i) => this.deepEquals(val, b[i]));
|
|
2232
|
+
}
|
|
2233
|
+
const aObj = a;
|
|
2234
|
+
const bObj = b;
|
|
2235
|
+
const aKeys = Object.keys(aObj);
|
|
2236
|
+
const bKeys = Object.keys(bObj);
|
|
2237
|
+
if (aKeys.length !== bKeys.length) return false;
|
|
2238
|
+
return aKeys.every((key) => this.deepEquals(aObj[key], bObj[key]));
|
|
1922
2239
|
}
|
|
1923
2240
|
};
|
|
1924
2241
|
}
|
|
@@ -2115,7 +2432,8 @@ var init_stream_processor = __esm({
|
|
|
2115
2432
|
options.registry,
|
|
2116
2433
|
options.onHumanInputRequired,
|
|
2117
2434
|
this.logger.getSubLogger({ name: "executor" }),
|
|
2118
|
-
options.defaultGadgetTimeoutMs
|
|
2435
|
+
options.defaultGadgetTimeoutMs,
|
|
2436
|
+
{ argPrefix: options.gadgetArgPrefix }
|
|
2119
2437
|
);
|
|
2120
2438
|
}
|
|
2121
2439
|
/**
|
|
@@ -5613,10 +5931,10 @@ export {
|
|
|
5613
5931
|
BreakLoopException,
|
|
5614
5932
|
HumanInputException,
|
|
5615
5933
|
init_exceptions,
|
|
5616
|
-
GadgetExecutor,
|
|
5617
|
-
init_executor,
|
|
5618
5934
|
StreamParser,
|
|
5619
5935
|
init_parser,
|
|
5936
|
+
GadgetExecutor,
|
|
5937
|
+
init_executor,
|
|
5620
5938
|
StreamProcessor,
|
|
5621
5939
|
init_stream_processor,
|
|
5622
5940
|
FALLBACK_CHARS_PER_TOKEN,
|
|
@@ -5644,4 +5962,4 @@ export {
|
|
|
5644
5962
|
AgentBuilder,
|
|
5645
5963
|
init_builder
|
|
5646
5964
|
};
|
|
5647
|
-
//# sourceMappingURL=chunk-
|
|
5965
|
+
//# sourceMappingURL=chunk-KORMY3CD.js.map
|