mirror of
https://github.com/simstudioai/sim.git
synced 2026-04-28 03:00:29 -04:00
fix(docs): resolve missing tool outputs for spread-inherited V2 tools (#4020)
* fix(docs): resolve missing tool outputs for spread-inherited V2 tools * fix(docs): add word boundary to baseToolRegex to prevent false matches * fix(docs): remove unnecessary case-insensitive flag from baseToolRegex
This commit is contained in:
@@ -53,6 +53,27 @@ interface BlockConfig {
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the position after the matching close delimiter for an opening delimiter.
|
||||
* Assumes `content[openPos]` is the opening char (e.g. `{` or `[`).
|
||||
* Returns the index one past the matching close char, or -1 if unbalanced.
|
||||
*/
|
||||
function findMatchingClose(
|
||||
content: string,
|
||||
openPos: number,
|
||||
openChar = '{',
|
||||
closeChar = '}'
|
||||
): number {
|
||||
let count = 1
|
||||
let pos = openPos + 1
|
||||
while (pos < content.length && count > 0) {
|
||||
if (content[pos] === openChar) count++
|
||||
else if (content[pos] === closeChar) count--
|
||||
pos++
|
||||
}
|
||||
return count === 0 ? pos : -1
|
||||
}
|
||||
|
||||
interface TriggerInfo {
|
||||
id: string
|
||||
name: string
|
||||
@@ -134,16 +155,9 @@ async function generateIconMapping(): Promise<Record<string, string>> {
|
||||
const startIndex = match.index + match[0].length - 1
|
||||
|
||||
// Extract the block content
|
||||
let braceCount = 1
|
||||
let endIndex = startIndex + 1
|
||||
const endIndex = findMatchingClose(fileContent, startIndex)
|
||||
|
||||
while (endIndex < fileContent.length && braceCount > 0) {
|
||||
if (fileContent[endIndex] === '{') braceCount++
|
||||
else if (fileContent[endIndex] === '}') braceCount--
|
||||
endIndex++
|
||||
}
|
||||
|
||||
if (braceCount === 0) {
|
||||
if (endIndex !== -1) {
|
||||
const blockContent = fileContent.substring(startIndex, endIndex)
|
||||
|
||||
// Check hideFromToolbar - skip hidden blocks for docs but NOT for icon mapping
|
||||
@@ -272,26 +286,16 @@ function extractOperationsFromContent(blockContent: string): { label: string; id
|
||||
|
||||
// Locate the opening '[' of the subBlocks array
|
||||
const arrayStart = subBlocksMatch.index + subBlocksMatch[0].length - 1
|
||||
let bracketCount = 1
|
||||
let pos = arrayStart + 1
|
||||
while (pos < blockContent.length && bracketCount > 0) {
|
||||
if (blockContent[pos] === '[') bracketCount++
|
||||
else if (blockContent[pos] === ']') bracketCount--
|
||||
pos++
|
||||
}
|
||||
const subBlocksContent = blockContent.substring(arrayStart + 1, pos - 1)
|
||||
const arrayEnd = findMatchingClose(blockContent, arrayStart, '[', ']')
|
||||
if (arrayEnd === -1) return []
|
||||
const subBlocksContent = blockContent.substring(arrayStart + 1, arrayEnd - 1)
|
||||
|
||||
// Iterate over top-level objects in the subBlocks array, looking for id: 'operation'
|
||||
let i = 0
|
||||
while (i < subBlocksContent.length) {
|
||||
if (subBlocksContent[i] === '{') {
|
||||
let braceCount = 1
|
||||
let j = i + 1
|
||||
while (j < subBlocksContent.length && braceCount > 0) {
|
||||
if (subBlocksContent[j] === '{') braceCount++
|
||||
else if (subBlocksContent[j] === '}') braceCount--
|
||||
j++
|
||||
}
|
||||
const j = findMatchingClose(subBlocksContent, i)
|
||||
if (j === -1) break
|
||||
const objContent = subBlocksContent.substring(i, j)
|
||||
|
||||
if (/\bid\s*:\s*['"]operation['"]/.test(objContent)) {
|
||||
@@ -299,14 +303,9 @@ function extractOperationsFromContent(blockContent: string): { label: string; id
|
||||
if (!optionsMatch) return []
|
||||
|
||||
const optArrayStart = optionsMatch.index + optionsMatch[0].length - 1
|
||||
let bc = 1
|
||||
let op = optArrayStart + 1
|
||||
while (op < objContent.length && bc > 0) {
|
||||
if (objContent[op] === '[') bc++
|
||||
else if (objContent[op] === ']') bc--
|
||||
op++
|
||||
}
|
||||
const optionsContent = objContent.substring(optArrayStart + 1, op - 1)
|
||||
const optArrayEnd = findMatchingClose(objContent, optArrayStart, '[', ']')
|
||||
if (optArrayEnd === -1) return []
|
||||
const optionsContent = objContent.substring(optArrayStart + 1, optArrayEnd - 1)
|
||||
|
||||
// Extract { label, id } pairs from each option object
|
||||
const pairs: { label: string; id: string }[] = []
|
||||
@@ -442,14 +441,9 @@ function extractTriggersAvailable(blockContent: string): string[] {
|
||||
if (!triggersMatch) return []
|
||||
|
||||
const start = triggersMatch.index + triggersMatch[0].length - 1
|
||||
let braceCount = 1
|
||||
let pos = start + 1
|
||||
while (pos < blockContent.length && braceCount > 0) {
|
||||
if (blockContent[pos] === '{') braceCount++
|
||||
else if (blockContent[pos] === '}') braceCount--
|
||||
pos++
|
||||
}
|
||||
const triggersContent = blockContent.substring(start, pos)
|
||||
const trigEnd = findMatchingClose(blockContent, start)
|
||||
if (trigEnd === -1) return []
|
||||
const triggersContent = blockContent.substring(start, trigEnd)
|
||||
|
||||
if (!/enabled\s*:\s*true/.test(triggersContent)) return []
|
||||
|
||||
@@ -457,14 +451,9 @@ function extractTriggersAvailable(blockContent: string): string[] {
|
||||
if (!availableMatch) return []
|
||||
|
||||
const arrayStart = availableMatch.index + availableMatch[0].length - 1
|
||||
let bracketCount = 1
|
||||
let ap = arrayStart + 1
|
||||
while (ap < triggersContent.length && bracketCount > 0) {
|
||||
if (triggersContent[ap] === '[') bracketCount++
|
||||
else if (triggersContent[ap] === ']') bracketCount--
|
||||
ap++
|
||||
}
|
||||
const arrayContent = triggersContent.substring(arrayStart + 1, ap - 1)
|
||||
const arrayEnd = findMatchingClose(triggersContent, arrayStart, '[', ']')
|
||||
if (arrayEnd === -1) return []
|
||||
const arrayContent = triggersContent.substring(arrayStart + 1, arrayEnd - 1)
|
||||
|
||||
const ids: string[] = []
|
||||
const idRegex = /['"]([^'"]+)['"]/g
|
||||
@@ -731,16 +720,9 @@ function extractAllBlockConfigs(fileContent: string): BlockConfig[] {
|
||||
const startIndex = match.index + match[0].length - 1 // Position of opening brace
|
||||
|
||||
// Extract the block content by matching braces
|
||||
let braceCount = 1
|
||||
let endIndex = startIndex + 1
|
||||
const endIndex = findMatchingClose(fileContent, startIndex)
|
||||
|
||||
while (endIndex < fileContent.length && braceCount > 0) {
|
||||
if (fileContent[endIndex] === '{') braceCount++
|
||||
else if (fileContent[endIndex] === '}') braceCount--
|
||||
endIndex++
|
||||
}
|
||||
|
||||
if (braceCount === 0) {
|
||||
if (endIndex !== -1) {
|
||||
const blockContent = fileContent.substring(startIndex, endIndex)
|
||||
|
||||
// Check if this block has hideFromToolbar: true
|
||||
@@ -798,16 +780,9 @@ function extractBlockConfigFromContent(
|
||||
|
||||
if (baseMatch) {
|
||||
const startIndex = baseMatch.index + baseMatch[0].length - 1
|
||||
let braceCount = 1
|
||||
let endIndex = startIndex + 1
|
||||
const endIndex = findMatchingClose(fileContent, startIndex)
|
||||
|
||||
while (endIndex < fileContent.length && braceCount > 0) {
|
||||
if (fileContent[endIndex] === '{') braceCount++
|
||||
else if (fileContent[endIndex] === '}') braceCount--
|
||||
endIndex++
|
||||
}
|
||||
|
||||
if (braceCount === 0) {
|
||||
if (endIndex !== -1) {
|
||||
const baseBlockContent = fileContent.substring(startIndex, endIndex)
|
||||
// Recursively extract base config (but don't pass fileContent to avoid infinite loops)
|
||||
baseConfig = extractBlockConfigFromContent(
|
||||
@@ -1015,62 +990,42 @@ function extractOutputsFromContent(content: string): Record<string, any> {
|
||||
const openBracePos = content.indexOf('{', outputsStart)
|
||||
if (openBracePos === -1) return {}
|
||||
|
||||
let braceCount = 1
|
||||
let pos = openBracePos + 1
|
||||
const pos = findMatchingClose(content, openBracePos)
|
||||
if (pos === -1) return {}
|
||||
|
||||
while (pos < content.length && braceCount > 0) {
|
||||
if (content[pos] === '{') braceCount++
|
||||
else if (content[pos] === '}') braceCount--
|
||||
pos++
|
||||
const outputsContent = content.substring(openBracePos + 1, pos - 1).trim()
|
||||
const outputs: Record<string, any> = {}
|
||||
|
||||
const fieldRegex = /(\w+)\s*:\s*{/g
|
||||
let match
|
||||
const fieldPositions: Array<{ name: string; start: number }> = []
|
||||
|
||||
while ((match = fieldRegex.exec(outputsContent)) !== null) {
|
||||
fieldPositions.push({
|
||||
name: match[1],
|
||||
start: match.index + match[0].length - 1,
|
||||
})
|
||||
}
|
||||
|
||||
if (braceCount === 0) {
|
||||
const outputsContent = content.substring(openBracePos + 1, pos - 1).trim()
|
||||
const outputs: Record<string, any> = {}
|
||||
fieldPositions.forEach((field) => {
|
||||
const endPos = findMatchingClose(outputsContent, field.start)
|
||||
|
||||
const fieldRegex = /(\w+)\s*:\s*{/g
|
||||
let match
|
||||
const fieldPositions: Array<{ name: string; start: number }> = []
|
||||
if (endPos !== -1) {
|
||||
const fieldContent = outputsContent.substring(field.start + 1, endPos - 1).trim()
|
||||
|
||||
while ((match = fieldRegex.exec(outputsContent)) !== null) {
|
||||
fieldPositions.push({
|
||||
name: match[1],
|
||||
start: match.index + match[0].length - 1,
|
||||
})
|
||||
}
|
||||
const typeMatch = fieldContent.match(/type\s*:\s*['"](.*?)['"]/)
|
||||
const description = extractDescription(fieldContent)
|
||||
|
||||
fieldPositions.forEach((field) => {
|
||||
const startPos = field.start
|
||||
let braceCount = 1
|
||||
let endPos = startPos + 1
|
||||
|
||||
while (endPos < outputsContent.length && braceCount > 0) {
|
||||
if (outputsContent[endPos] === '{') braceCount++
|
||||
else if (outputsContent[endPos] === '}') braceCount--
|
||||
endPos++
|
||||
}
|
||||
|
||||
if (braceCount === 0) {
|
||||
const fieldContent = outputsContent.substring(startPos + 1, endPos - 1).trim()
|
||||
|
||||
const typeMatch = fieldContent.match(/type\s*:\s*['"](.*?)['"]/)
|
||||
const description = extractDescription(fieldContent)
|
||||
|
||||
if (typeMatch) {
|
||||
outputs[field.name] = {
|
||||
type: typeMatch[1],
|
||||
description: description || `${field.name} output from the block`,
|
||||
}
|
||||
if (typeMatch) {
|
||||
outputs[field.name] = {
|
||||
type: typeMatch[1],
|
||||
description: description || `${field.name} output from the block`,
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if (Object.keys(outputs).length > 0) {
|
||||
return outputs
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return {}
|
||||
return outputs
|
||||
}
|
||||
|
||||
function extractToolsAccessFromContent(content: string): string[] {
|
||||
@@ -1148,16 +1103,9 @@ function resolveConstReference(
|
||||
|
||||
// Extract the const content
|
||||
const startIndex = constMatch.index + constMatch[0].length - 1
|
||||
let braceCount = 1
|
||||
let endIndex = startIndex + 1
|
||||
const endIndex = findMatchingClose(typesContent, startIndex)
|
||||
|
||||
while (endIndex < typesContent.length && braceCount > 0) {
|
||||
if (typesContent[endIndex] === '{') braceCount++
|
||||
else if (typesContent[endIndex] === '}') braceCount--
|
||||
endIndex++
|
||||
}
|
||||
|
||||
if (braceCount !== 0) {
|
||||
if (endIndex === -1) {
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -1242,14 +1190,8 @@ function parseConstProperties(
|
||||
if ((propName === 'properties' || propName === 'type') && !constRef) {
|
||||
// Peek at what's inside the braces
|
||||
const startPos = match.index + match[0].length - 1
|
||||
let braceCount = 1
|
||||
let endPos = startPos + 1
|
||||
while (endPos < content.length && braceCount > 0) {
|
||||
if (content[endPos] === '{') braceCount++
|
||||
else if (content[endPos] === '}') braceCount--
|
||||
endPos++
|
||||
}
|
||||
if (braceCount === 0) {
|
||||
const endPos = findMatchingClose(content, startPos)
|
||||
if (endPos !== -1) {
|
||||
const propContent = content.substring(startPos + 1, endPos - 1).trim()
|
||||
// If it starts with 'type:', it's an output field definition - process it
|
||||
if (propContent.match(/^\s*type\s*:/)) {
|
||||
@@ -1272,17 +1214,9 @@ function parseConstProperties(
|
||||
} else {
|
||||
// This property has inline definition
|
||||
const startPos = match.index + match[0].length - 1
|
||||
const endPos = findMatchingClose(content, startPos)
|
||||
|
||||
let braceCount = 1
|
||||
let endPos = startPos + 1
|
||||
|
||||
while (endPos < content.length && braceCount > 0) {
|
||||
if (content[endPos] === '{') braceCount++
|
||||
else if (content[endPos] === '}') braceCount--
|
||||
endPos++
|
||||
}
|
||||
|
||||
if (braceCount === 0) {
|
||||
if (endPos !== -1) {
|
||||
const propContent = content.substring(startPos + 1, endPos - 1).trim()
|
||||
const parsedProp = parseConstFieldContent(propContent, toolPrefix, typesContent, depth)
|
||||
if (parsedProp) {
|
||||
@@ -1324,16 +1258,9 @@ function resolveConstFromTypesContent(
|
||||
}
|
||||
|
||||
const startIndex = constMatch.index + constMatch[0].length - 1
|
||||
let braceCount = 1
|
||||
let endIndex = startIndex + 1
|
||||
const endIndex = findMatchingClose(typesContent, startIndex)
|
||||
|
||||
while (endIndex < typesContent.length && braceCount > 0) {
|
||||
if (typesContent[endIndex] === '{') braceCount++
|
||||
else if (typesContent[endIndex] === '}') braceCount--
|
||||
endIndex++
|
||||
}
|
||||
|
||||
if (braceCount !== 0) return null
|
||||
if (endIndex === -1) return null
|
||||
|
||||
const constContent = typesContent.substring(startIndex + 1, endIndex - 1).trim()
|
||||
|
||||
@@ -1414,16 +1341,9 @@ function parseConstFieldContent(
|
||||
const propertiesStart = fieldContent.search(/properties\s*:\s*\{/)
|
||||
if (propertiesStart !== -1) {
|
||||
const braceStart = fieldContent.indexOf('{', propertiesStart)
|
||||
let braceCount = 1
|
||||
let braceEnd = braceStart + 1
|
||||
const braceEnd = findMatchingClose(fieldContent, braceStart)
|
||||
|
||||
while (braceEnd < fieldContent.length && braceCount > 0) {
|
||||
if (fieldContent[braceEnd] === '{') braceCount++
|
||||
else if (fieldContent[braceEnd] === '}') braceCount--
|
||||
braceEnd++
|
||||
}
|
||||
|
||||
if (braceCount === 0) {
|
||||
if (braceEnd !== -1) {
|
||||
const propertiesContent = fieldContent.substring(braceStart + 1, braceEnd - 1).trim()
|
||||
result.properties = parseConstProperties(
|
||||
propertiesContent,
|
||||
@@ -1452,16 +1372,9 @@ function parseConstFieldContent(
|
||||
const itemsStart = fieldContent.search(/items\s*:\s*\{/)
|
||||
if (itemsStart !== -1) {
|
||||
const braceStart = fieldContent.indexOf('{', itemsStart)
|
||||
let braceCount = 1
|
||||
let braceEnd = braceStart + 1
|
||||
const braceEnd = findMatchingClose(fieldContent, braceStart)
|
||||
|
||||
while (braceEnd < fieldContent.length && braceCount > 0) {
|
||||
if (fieldContent[braceEnd] === '{') braceCount++
|
||||
else if (fieldContent[braceEnd] === '}') braceCount--
|
||||
braceEnd++
|
||||
}
|
||||
|
||||
if (braceCount === 0) {
|
||||
if (braceEnd !== -1) {
|
||||
const itemsContent = fieldContent.substring(braceStart + 1, braceEnd - 1).trim()
|
||||
const itemsType = itemsContent.match(/type\s*:\s*['"]([^'"]+)['"]/)
|
||||
const itemsDesc = extractDescription(itemsContent)
|
||||
@@ -1516,6 +1429,40 @@ function parseConstFieldContent(
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract outputs from a tool content block by trying:
|
||||
* 1. Const reference (e.g., `outputs: GIT_REF_OUTPUT_PROPERTIES,`)
|
||||
* 2. Inline object (e.g., `outputs: { id: { type: 'string', ... } }`)
|
||||
*/
|
||||
function extractOutputsFromToolContent(
|
||||
content: string,
|
||||
toolPrefix: string
|
||||
): Record<string, any> {
|
||||
const constMatch = content.match(
|
||||
/(?<![a-zA-Z_])outputs\s*:\s*([A-Z][A-Z_0-9]+)\s*(?:,|\}|$)/
|
||||
)
|
||||
if (constMatch) {
|
||||
const resolved = resolveConstReference(constMatch[1], toolPrefix)
|
||||
if (resolved && typeof resolved === 'object') {
|
||||
return resolved
|
||||
}
|
||||
}
|
||||
|
||||
const outputsStart = content.search(/(?<![a-zA-Z_])outputs\s*:\s*{/)
|
||||
if (outputsStart !== -1) {
|
||||
const openBracePos = content.indexOf('{', outputsStart)
|
||||
if (openBracePos !== -1) {
|
||||
const closePos = findMatchingClose(content, openBracePos)
|
||||
if (closePos !== -1) {
|
||||
const outputsContent = content.substring(openBracePos + 1, closePos - 1).trim()
|
||||
return parseToolOutputsField(outputsContent, toolPrefix)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {}
|
||||
}
|
||||
|
||||
function extractToolInfo(
|
||||
toolName: string,
|
||||
fileContent: string
|
||||
@@ -1539,16 +1486,9 @@ function extractToolInfo(
|
||||
|
||||
if (exportMatch && exportMatch.index !== undefined) {
|
||||
const startIndex = exportMatch.index + exportMatch[0].length - 1
|
||||
let braceCount = 1
|
||||
let endIndex = startIndex + 1
|
||||
const endIndex = findMatchingClose(fileContent, startIndex)
|
||||
|
||||
while (endIndex < fileContent.length && braceCount > 0) {
|
||||
if (fileContent[endIndex] === '{') braceCount++
|
||||
else if (fileContent[endIndex] === '}') braceCount--
|
||||
endIndex++
|
||||
}
|
||||
|
||||
if (braceCount === 0) {
|
||||
if (endIndex !== -1) {
|
||||
toolContent = fileContent.substring(startIndex, endIndex)
|
||||
}
|
||||
}
|
||||
@@ -1650,19 +1590,9 @@ function extractToolInfo(
|
||||
continue
|
||||
}
|
||||
|
||||
let braceCount = 1
|
||||
let endPos = startPos + 1
|
||||
const endPos = findMatchingClose(paramsContent, startPos)
|
||||
|
||||
while (endPos < paramsContent.length && braceCount > 0) {
|
||||
if (paramsContent[endPos] === '{') {
|
||||
braceCount++
|
||||
} else if (paramsContent[endPos] === '}') {
|
||||
braceCount--
|
||||
}
|
||||
endPos++
|
||||
}
|
||||
|
||||
if (braceCount === 0) {
|
||||
if (endPos !== -1) {
|
||||
const paramBlock = paramsContent.substring(startPos + 1, endPos - 1).trim()
|
||||
paramPositions.push({ name: paramName, start: startPos, content: paramBlock })
|
||||
}
|
||||
@@ -1704,36 +1634,43 @@ function extractToolInfo(
|
||||
// Get the tool prefix for resolving const references
|
||||
const toolPrefix = getToolPrefixFromName(toolName)
|
||||
|
||||
let outputs: Record<string, any> = {}
|
||||
let outputs = extractOutputsFromToolContent(toolContent, toolPrefix)
|
||||
|
||||
// Pattern 1: outputs directly assigned to a const (e.g., "outputs: GIT_REF_OUTPUT_PROPERTIES,")
|
||||
const directConstMatch = toolContent.match(
|
||||
/(?<![a-zA-Z_])outputs\s*:\s*([A-Z][A-Z_0-9]+)\s*(?:,|\}|$)/
|
||||
)
|
||||
if (directConstMatch) {
|
||||
const constName = directConstMatch[1]
|
||||
const resolvedConst = resolveConstReference(constName, toolPrefix)
|
||||
if (resolvedConst && typeof resolvedConst === 'object') {
|
||||
outputs = resolvedConst
|
||||
}
|
||||
}
|
||||
|
||||
// Pattern 2: outputs is an object with properties (e.g., "outputs: { ... }")
|
||||
// If no outputs found, check for spread inheritance (e.g., "...extendParserTool")
|
||||
// toolContent may be narrowed past the spread line, so reconstruct the full block
|
||||
if (Object.keys(outputs).length === 0) {
|
||||
const outputsStart = toolContent.search(/(?<![a-zA-Z_])outputs\s*:\s*{/)
|
||||
if (outputsStart !== -1) {
|
||||
const openBracePos = toolContent.indexOf('{', outputsStart)
|
||||
if (openBracePos !== -1) {
|
||||
let braceCount = 1
|
||||
let pos = openBracePos + 1
|
||||
while (pos < toolContent.length && braceCount > 0) {
|
||||
if (toolContent[pos] === '{') braceCount++
|
||||
else if (toolContent[pos] === '}') braceCount--
|
||||
pos++
|
||||
let fullToolBlock = toolContent
|
||||
if (toolIdMatch && toolIdMatch.index !== undefined) {
|
||||
const beforeId = fileContent.substring(0, toolIdMatch.index)
|
||||
const exportRegex = /export\s+const\s+\w+[^=]*=\s*\{/g
|
||||
let lastExportMatch: RegExpExecArray | null = null
|
||||
let m: RegExpExecArray | null = null
|
||||
while ((m = exportRegex.exec(beforeId)) !== null) {
|
||||
lastExportMatch = m
|
||||
}
|
||||
if (lastExportMatch && lastExportMatch.index !== undefined) {
|
||||
const bracePos =
|
||||
lastExportMatch.index + lastExportMatch[0].length - 1
|
||||
const ep = findMatchingClose(fileContent, bracePos)
|
||||
if (ep !== -1) {
|
||||
fullToolBlock = fileContent.substring(bracePos, ep)
|
||||
}
|
||||
if (braceCount === 0) {
|
||||
const outputsContent = toolContent.substring(openBracePos + 1, pos - 1).trim()
|
||||
outputs = parseToolOutputsField(outputsContent, toolPrefix)
|
||||
}
|
||||
}
|
||||
const spreadMatch = fullToolBlock.match(/\.\.\.(\w+(?:Tool|Base)\w*)/)
|
||||
if (spreadMatch) {
|
||||
const baseVarName = spreadMatch[1]
|
||||
const baseToolRegex = new RegExp(
|
||||
`export\\s+const\\s+${baseVarName}(?=[^a-zA-Z0-9_]|$)[^=]*=\\s*\\{`
|
||||
)
|
||||
const baseToolMatch = fileContent.match(baseToolRegex)
|
||||
if (baseToolMatch && baseToolMatch.index !== undefined) {
|
||||
const baseStart =
|
||||
baseToolMatch.index + baseToolMatch[0].length - 1
|
||||
const endIdx = findMatchingClose(fileContent, baseStart)
|
||||
if (endIdx !== -1) {
|
||||
const baseToolContent = fileContent.substring(baseStart, endIdx)
|
||||
outputs = extractOutputsFromToolContent(baseToolContent, toolPrefix)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1921,24 +1858,15 @@ function parseToolOutputsField(outputsContent: string, toolPrefix?: string): Rec
|
||||
|
||||
const openBrace = braces.find((b) => b.type === 'open' && b.pos === bracePos)
|
||||
if (openBrace) {
|
||||
let braceCount = 1
|
||||
let endPos = bracePos + 1
|
||||
|
||||
while (endPos < outputsContent.length && braceCount > 0) {
|
||||
if (outputsContent[endPos] === '{') {
|
||||
braceCount++
|
||||
} else if (outputsContent[endPos] === '}') {
|
||||
braceCount--
|
||||
}
|
||||
endPos++
|
||||
const endPos = findMatchingClose(outputsContent, bracePos)
|
||||
if (endPos !== -1) {
|
||||
fieldPositions.push({
|
||||
name: fieldName,
|
||||
start: bracePos,
|
||||
end: endPos,
|
||||
level: openBrace.level,
|
||||
})
|
||||
}
|
||||
|
||||
fieldPositions.push({
|
||||
name: fieldName,
|
||||
start: bracePos,
|
||||
end: endPos,
|
||||
level: openBrace.level,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2001,16 +1929,9 @@ function parseFieldContent(fieldContent: string, toolPrefix?: string): any {
|
||||
|
||||
if (propertiesStart !== -1) {
|
||||
const braceStart = fieldContent.indexOf('{', propertiesStart)
|
||||
let braceCount = 1
|
||||
let braceEnd = braceStart + 1
|
||||
const braceEnd = findMatchingClose(fieldContent, braceStart)
|
||||
|
||||
while (braceEnd < fieldContent.length && braceCount > 0) {
|
||||
if (fieldContent[braceEnd] === '{') braceCount++
|
||||
else if (fieldContent[braceEnd] === '}') braceCount--
|
||||
braceEnd++
|
||||
}
|
||||
|
||||
if (braceCount === 0) {
|
||||
if (braceEnd !== -1) {
|
||||
const propertiesContent = fieldContent.substring(braceStart + 1, braceEnd - 1).trim()
|
||||
result.properties = parsePropertiesContent(propertiesContent, toolPrefix)
|
||||
}
|
||||
@@ -2031,16 +1952,9 @@ function parseFieldContent(fieldContent: string, toolPrefix?: string): any {
|
||||
|
||||
if (itemsStart !== -1) {
|
||||
const braceStart = fieldContent.indexOf('{', itemsStart)
|
||||
let braceCount = 1
|
||||
let braceEnd = braceStart + 1
|
||||
const braceEnd = findMatchingClose(fieldContent, braceStart)
|
||||
|
||||
while (braceEnd < fieldContent.length && braceCount > 0) {
|
||||
if (fieldContent[braceEnd] === '{') braceCount++
|
||||
else if (fieldContent[braceEnd] === '}') braceCount--
|
||||
braceEnd++
|
||||
}
|
||||
|
||||
if (braceCount === 0) {
|
||||
if (braceEnd !== -1) {
|
||||
const itemsContent = fieldContent.substring(braceStart + 1, braceEnd - 1).trim()
|
||||
const itemsType = itemsContent.match(/type\s*:\s*['"]([^'"]+)['"]/)
|
||||
|
||||
@@ -2213,19 +2127,9 @@ function parsePropertiesContent(
|
||||
|
||||
const startPos = match.index + match[0].length - 1
|
||||
|
||||
let braceCount = 1
|
||||
let endPos = startPos + 1
|
||||
const endPos = findMatchingClose(propertiesContent, startPos)
|
||||
|
||||
while (endPos < propertiesContent.length && braceCount > 0) {
|
||||
if (propertiesContent[endPos] === '{') {
|
||||
braceCount++
|
||||
} else if (propertiesContent[endPos] === '}') {
|
||||
braceCount--
|
||||
}
|
||||
endPos++
|
||||
}
|
||||
|
||||
if (braceCount === 0) {
|
||||
if (endPos !== -1) {
|
||||
const propContent = propertiesContent.substring(startPos + 1, endPos - 1).trim()
|
||||
|
||||
const hasDescription = /description\s*:\s*/.test(propContent)
|
||||
@@ -2729,16 +2633,9 @@ async function getHiddenAndVisibleBlockTypes(): Promise<{
|
||||
const startIndex = match.index + match[0].length - 1
|
||||
|
||||
// Extract the block content
|
||||
let braceCount = 1
|
||||
let endIndex = startIndex + 1
|
||||
const endIndex = findMatchingClose(fileContent, startIndex)
|
||||
|
||||
while (endIndex < fileContent.length && braceCount > 0) {
|
||||
if (fileContent[endIndex] === '{') braceCount++
|
||||
else if (fileContent[endIndex] === '}') braceCount--
|
||||
endIndex++
|
||||
}
|
||||
|
||||
if (braceCount === 0) {
|
||||
if (endIndex !== -1) {
|
||||
const blockContent = fileContent.substring(startIndex, endIndex)
|
||||
const blockType = extractStringPropertyFromContent(blockContent, 'type', true)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user