Working on implementing batch commands for UE wingman
This commit is contained in:
@@ -19,10 +19,10 @@ class UWing_GraphNode_SearchTypes : public UWingHandler
|
|||||||
GENERATED_BODY()
|
GENERATED_BODY()
|
||||||
|
|
||||||
public:
|
public:
|
||||||
UPROPERTY(EditAnywhere, meta=(Description="Query string, can contain * wildcards"))
|
UPROPERTY(EditAnywhere, meta=(Description="Array of query strings; each may contain * wildcards"))
|
||||||
FString Query;
|
FWingJsonArray Queries;
|
||||||
|
|
||||||
UPROPERTY(EditAnywhere, meta=(Optional, Description="Maximum number of results (default 50)"))
|
UPROPERTY(EditAnywhere, meta=(Optional, Description="Maximum number of results per query (default 50)"))
|
||||||
int32 MaxResults = 50;
|
int32 MaxResults = 50;
|
||||||
|
|
||||||
UPROPERTY(EditAnywhere, meta=(Description="Target graph"))
|
UPROPERTY(EditAnywhere, meta=(Description="Target graph"))
|
||||||
@@ -40,7 +40,24 @@ public:
|
|||||||
UEdGraph* TargetGraph = F.Walk(Graph).Cast<UEdGraph>();
|
UEdGraph* TargetGraph = F.Walk(Graph).Cast<UEdGraph>();
|
||||||
if (!TargetGraph) return;
|
if (!TargetGraph) return;
|
||||||
|
|
||||||
|
// Validate all entries are strings before running any searches.
|
||||||
|
TArray<FString> QueryStrings;
|
||||||
|
QueryStrings.Reserve(Queries.Array.Num());
|
||||||
|
for (const TSharedPtr<FJsonValue>& QueryVal : Queries.Array)
|
||||||
|
{
|
||||||
|
FString QueryStr;
|
||||||
|
if (!QueryVal->TryGetString(QueryStr))
|
||||||
|
{
|
||||||
|
WingOut::Stdout.Print(TEXT("ERROR: Queries must be an array of strings.\n"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QueryStrings.Add(QueryStr);
|
||||||
|
}
|
||||||
|
|
||||||
FWingGraphActions GraphActions(TargetGraph);
|
FWingGraphActions GraphActions(TargetGraph);
|
||||||
|
for (const FString& Query : QueryStrings)
|
||||||
|
{
|
||||||
|
WingOut::Stdout.Printf(TEXT("\n=== %s ===\n\n"), *Query);
|
||||||
TArray<FWingGraphAction*> Results = GraphActions.Search(Query, MaxResults, false);
|
TArray<FWingGraphAction*> Results = GraphActions.Search(Query, MaxResults, false);
|
||||||
for (const FWingGraphAction* Action : Results)
|
for (const FWingGraphAction* Action : Results)
|
||||||
{
|
{
|
||||||
@@ -56,4 +73,5 @@ public:
|
|||||||
WingOut::Stdout.Printf(TEXT("WARNING: Reached limit of %d results. You may specify MaxResults.\n"), MaxResults);
|
WingOut::Stdout.Printf(TEXT("WARNING: Reached limit of %d results. You may specify MaxResults.\n"), MaxResults);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -17,10 +17,10 @@ class UWing_Widget_SearchTypes : public UWingHandler
|
|||||||
GENERATED_BODY()
|
GENERATED_BODY()
|
||||||
|
|
||||||
public:
|
public:
|
||||||
UPROPERTY(EditAnywhere, meta=(Description="Query string, can contain *"))
|
UPROPERTY(EditAnywhere, meta=(Description="Array of query strings; each may contain *"))
|
||||||
FString Query;
|
FWingJsonArray Queries;
|
||||||
|
|
||||||
UPROPERTY(EditAnywhere, meta=(Optional, Description="Maximum number of results (default 50)"))
|
UPROPERTY(EditAnywhere, meta=(Optional, Description="Maximum number of results per query (default 50)"))
|
||||||
int32 MaxResults = 50;
|
int32 MaxResults = 50;
|
||||||
|
|
||||||
virtual void Register() override
|
virtual void Register() override
|
||||||
@@ -31,7 +31,24 @@ public:
|
|||||||
}
|
}
|
||||||
virtual void Handle() override
|
virtual void Handle() override
|
||||||
{
|
{
|
||||||
|
// Validate all entries are strings before running any searches.
|
||||||
|
TArray<FString> QueryStrings;
|
||||||
|
QueryStrings.Reserve(Queries.Array.Num());
|
||||||
|
for (const TSharedPtr<FJsonValue>& QueryVal : Queries.Array)
|
||||||
|
{
|
||||||
|
FString QueryStr;
|
||||||
|
if (!QueryVal->TryGetString(QueryStr))
|
||||||
|
{
|
||||||
|
WingOut::Stdout.Print(TEXT("ERROR: Queries must be an array of strings.\n"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QueryStrings.Add(QueryStr);
|
||||||
|
}
|
||||||
|
|
||||||
WingWidgets Widgets;
|
WingWidgets Widgets;
|
||||||
|
for (const FString& Query : QueryStrings)
|
||||||
|
{
|
||||||
|
WingOut::Stdout.Printf(TEXT("\n=== %s ===\n\n"), *Query);
|
||||||
TArray<WingWidgets::Type> Results = Widgets.Search(Query, MaxResults, false);
|
TArray<WingWidgets::Type> Results = Widgets.Search(Query, MaxResults, false);
|
||||||
for (const WingWidgets::Type& Entry : Results)
|
for (const WingWidgets::Type& Entry : Results)
|
||||||
{
|
{
|
||||||
@@ -47,4 +64,5 @@ public:
|
|||||||
WingOut::Stdout.Printf(TEXT("WARNING: Reached limit of %d results. You may specify MaxResults.\n"), MaxResults);
|
WingOut::Stdout.Printf(TEXT("WARNING: Reached limit of %d results. You may specify MaxResults.\n"), MaxResults);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -206,7 +206,19 @@ FString UWingServer::HandleRequest(const FString& Line)
|
|||||||
{
|
{
|
||||||
if (Result[i] == TEXT('\0')) Result[i] = TEXT(' ');
|
if (Result[i] == TEXT('\0')) Result[i] = TEXT(' ');
|
||||||
}
|
}
|
||||||
return Result;
|
|
||||||
|
// Wrap the text in an MCP content-block array: [{"type":"text","text":"..."}]
|
||||||
|
TSharedPtr<FJsonObject> Block = MakeShared<FJsonObject>();
|
||||||
|
Block->SetStringField(TEXT("type"), TEXT("text"));
|
||||||
|
Block->SetStringField(TEXT("text"), Result);
|
||||||
|
|
||||||
|
TArray<TSharedPtr<FJsonValue>> Blocks;
|
||||||
|
Blocks.Add(MakeShared<FJsonValueObject>(Block));
|
||||||
|
|
||||||
|
FString OutJson;
|
||||||
|
TSharedRef<TJsonWriter<>> Writer = TJsonWriterFactory<>::Create(&OutJson);
|
||||||
|
FJsonSerializer::Serialize(Blocks, Writer);
|
||||||
|
return OutJson;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UWingServer::TryCallHandler(const FString &Line)
|
void UWingServer::TryCallHandler(const FString &Line)
|
||||||
|
|||||||
@@ -128,11 +128,14 @@ def handle_message(msg):
|
|||||||
arguments = params.get("arguments", {})
|
arguments = params.get("arguments", {})
|
||||||
result = forward_to_editor(arguments)
|
result = forward_to_editor(arguments)
|
||||||
if isinstance(result, dict) and "error" in result:
|
if isinstance(result, dict) and "error" in result:
|
||||||
text = result["error"]
|
content = [{"type": "text", "text": result["error"]}]
|
||||||
else:
|
else:
|
||||||
text = result
|
try:
|
||||||
|
content = json.loads(result)
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
content = [{"type": "text", "text": "Malformed response from editor."}]
|
||||||
return make_jsonrpc(msg_id, {
|
return make_jsonrpc(msg_id, {
|
||||||
"content": [{"type": "text", "text": text}],
|
"content": content,
|
||||||
})
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -57,9 +57,21 @@ def main():
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
parsed = json.loads(result)
|
parsed = json.loads(result)
|
||||||
print(json.dumps(parsed, indent=2))
|
|
||||||
except json.JSONDecodeError:
|
except json.JSONDecodeError:
|
||||||
print(result)
|
print("Error: response is not valid JSON.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if not isinstance(parsed, list):
|
||||||
|
print("Error: response is not a list of content blocks.")
|
||||||
|
sys.exit(1)
|
||||||
|
for block in parsed:
|
||||||
|
if not (isinstance(block, dict)
|
||||||
|
and block.get("type") == "text"
|
||||||
|
and isinstance(block.get("text"), str)):
|
||||||
|
print("Error: response contains a non-text block.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
print("\n---\n".join(block["text"] for block in parsed))
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|||||||
Reference in New Issue
Block a user