| 1609 | free(tool_raw); |
| 1610 | json_ws(&tp); |
| 1611 | if (*tp == ',') tp++; |
| 1612 | json_ws(&tp); |
| 1613 | } |
| 1614 | |
| 1615 | done: |
| 1616 | free(type); |
| 1617 | free(name); |
| 1618 | free(tools); |
| 1619 | return appended; |
| 1620 | } |
| 1621 | |
| 1622 | /* OpenAI wraps tools as {"type":"function","function":{...}}. Anthropic sends |
| 1623 | * the function schema directly as {"name":...,"input_schema":...}. The DS4 |
| 1624 | * prompt wants one raw function schema per line, so unwrap OpenAI tools and keep |
| 1625 | * already-direct schemas unchanged. Responses can additionally group tools in a |
| 1626 | * namespace item; those are flattened for DSML prompt rendering while preserving |
| 1627 | * their client-facing name and namespace for response output. */ |
| 1628 | static bool parse_tools_value(const char **p, char **out, tool_schema_orders *orders) { |
| 1629 | json_ws(p); |
| 1630 | if (json_lit(p, "null")) { |
| 1631 | *out = xstrdup(""); |
| 1632 | return true; |
| 1633 | } |
| 1634 | if (**p != '[') return false; |
| 1635 | (*p)++; |
| 1636 | buf schemas = {0}; |
| 1637 | |
| 1638 | json_ws(p); |
| 1639 | while (**p && **p != ']') { |
| 1640 | char *raw = NULL; |
| 1641 | if (!json_raw_value(p, &raw)) goto bad; |
| 1642 | char *function = openai_function_schema_from_tool(raw); |
| 1643 | if (function) { |
| 1644 | append_raw_json_line(&schemas, function); |
| 1645 | tool_schema_orders_add_json(orders, function); |
| 1646 | } else if (!append_responses_namespace_tool_schemas(&schemas, orders, raw)) { |
| 1647 | char *special = responses_special_schema_from_tool(raw); |
| 1648 | if (special) { |
| 1649 | append_raw_json_line(&schemas, special); |
| 1650 | tool_schema_orders_add_json_wire(orders, special, |
| 1651 | NULL, NULL, true); |
| 1652 | } else { |
| 1653 | append_raw_json_line(&schemas, raw); |
| 1654 | tool_schema_orders_add_json(orders, raw); |
| 1655 | } |
| 1656 | free(special); |
| 1657 | } |
| 1658 | free(function); |
| 1659 | free(raw); |
| 1660 | json_ws(p); |
| 1661 | if (**p == ',') (*p)++; |
| 1662 | json_ws(p); |
| 1663 | } |
| 1664 | if (**p != ']') goto bad; |
| 1665 | (*p)++; |
| 1666 | *out = buf_take(&schemas); |
| 1667 | return true; |
| 1668 | bad: |