pi-codemcp 1.3.2 → 1.3.3
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/package.json +1 -1
- package/sidecar/executor.py +21 -5
- package/sidecar/gateway.py +1 -0
- package/sidecar/sandbox_api.py +1 -1
- package/sidecar/stats.py +3 -0
- package/sidecar/tool_catalog.py +2 -1
- package/src/execution-rendering.ts +6 -0
package/package.json
CHANGED
package/sidecar/executor.py
CHANGED
|
@@ -50,9 +50,10 @@ INSPECT_BYTE_LIMIT = 8 * 1024
|
|
|
50
50
|
CHAIN_INPUT_EXTERNAL = "__codemcp_saved_chain_input"
|
|
51
51
|
|
|
52
52
|
|
|
53
|
-
type FailureStage = Literal["preflight", "runtime", "timeout", "cancelled", "result"]
|
|
53
|
+
type FailureStage = Literal["preflight", "arguments", "runtime", "timeout", "cancelled", "result"]
|
|
54
54
|
type FailureKind = Literal[
|
|
55
55
|
"preflight",
|
|
56
|
+
"argument_validation",
|
|
56
57
|
"result",
|
|
57
58
|
"result_reference",
|
|
58
59
|
"sandbox_runtime",
|
|
@@ -487,7 +488,18 @@ class MontyExecutor:
|
|
|
487
488
|
raise RuntimeError(
|
|
488
489
|
f"Call limit exceeded: maximum {context.settings.max_calls} total calls"
|
|
489
490
|
)
|
|
490
|
-
|
|
491
|
+
try:
|
|
492
|
+
validated = catalog.validate_arguments(name, arguments)
|
|
493
|
+
except (TypeError, ValidationError, ValueError) as error:
|
|
494
|
+
message = f"{spec.call}: invalid arguments: {error}"
|
|
495
|
+
context.failure = ExecutionFailureInfo(
|
|
496
|
+
kind="argument_validation",
|
|
497
|
+
server=spec.server,
|
|
498
|
+
tool=spec.backend_name,
|
|
499
|
+
retryable=False,
|
|
500
|
+
message=message,
|
|
501
|
+
)
|
|
502
|
+
raise ValueError(message) from error
|
|
491
503
|
if spec.kind == "saved_chain":
|
|
492
504
|
context.chain_calls += 1
|
|
493
505
|
return await context.call_tool(name, validated, context)
|
|
@@ -624,8 +636,10 @@ class MontyExecutor:
|
|
|
624
636
|
context.metrics.runtime_ms += _elapsed_ms(runtime_started)
|
|
625
637
|
message = error.display("type-msg").strip()
|
|
626
638
|
lowered = message.lower()
|
|
627
|
-
stage: Literal["runtime", "timeout"] = (
|
|
628
|
-
"
|
|
639
|
+
stage: Literal["arguments", "runtime", "timeout"] = (
|
|
640
|
+
"arguments"
|
|
641
|
+
if context.failure is not None and context.failure.kind == "argument_validation"
|
|
642
|
+
else "timeout"
|
|
629
643
|
if (context.failure is not None and context.failure.kind == "upstream_timeout")
|
|
630
644
|
or "duration" in lowered
|
|
631
645
|
or "timed out" in lowered
|
|
@@ -728,7 +742,7 @@ class MontyExecutor:
|
|
|
728
742
|
@staticmethod
|
|
729
743
|
def _failure(
|
|
730
744
|
context: ExecutionContext,
|
|
731
|
-
stage:
|
|
745
|
+
stage: FailureStage,
|
|
732
746
|
error: str,
|
|
733
747
|
) -> ExecutionResponse:
|
|
734
748
|
failure = context.failure or _execution_failure_info(stage, error)
|
|
@@ -749,6 +763,8 @@ def _execution_failure_info(
|
|
|
749
763
|
) -> ExecutionFailureInfo:
|
|
750
764
|
if stage == "preflight":
|
|
751
765
|
kind: FailureKind = "preflight"
|
|
766
|
+
elif stage == "arguments":
|
|
767
|
+
kind = "argument_validation"
|
|
752
768
|
elif stage == "result":
|
|
753
769
|
kind = "result"
|
|
754
770
|
elif stage == "timeout":
|
package/sidecar/gateway.py
CHANGED
|
@@ -1511,6 +1511,7 @@ def _execution_failure_subtype(response: ExecutionResponse) -> str:
|
|
|
1511
1511
|
failure = response.failure
|
|
1512
1512
|
if failure is not None and failure.kind in {
|
|
1513
1513
|
"result_reference",
|
|
1514
|
+
"argument_validation",
|
|
1514
1515
|
"sandbox_timeout",
|
|
1515
1516
|
"upstream",
|
|
1516
1517
|
"upstream_transport",
|
package/sidecar/sandbox_api.py
CHANGED
|
@@ -14,7 +14,7 @@ SANDBOX_FUNCTION_EXTERNALS = {
|
|
|
14
14
|
EXPECT_INTEGER_NAME: "__codemcp_expect_integer",
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
STUB_IMPORTS = "from typing import Literal, Never, NotRequired, TypeAlias, TypedDict"
|
|
17
|
+
STUB_IMPORTS = "from typing import Literal, Mapping, Never, NotRequired, TypeAlias, TypedDict"
|
|
18
18
|
JSON_TYPE_STUBS = (
|
|
19
19
|
"JsonScalar: TypeAlias = bool | int | float | str | None",
|
|
20
20
|
'JsonValue: TypeAlias = JsonScalar | list["JsonValue"] | dict[str, "JsonValue"]',
|
package/sidecar/stats.py
CHANGED
|
@@ -98,6 +98,7 @@ DISTINCT_NAME_QUERIES = {
|
|
|
98
98
|
FailureOutcome = Literal[
|
|
99
99
|
"success",
|
|
100
100
|
"preflight_rejection",
|
|
101
|
+
"argument_rejection",
|
|
101
102
|
"result_refinement",
|
|
102
103
|
"upstream_failure",
|
|
103
104
|
"transport_failure",
|
|
@@ -996,6 +997,8 @@ def _operation_outcome(
|
|
|
996
997
|
return "internal_error"
|
|
997
998
|
if failure.stage == "preflight":
|
|
998
999
|
return "preflight_rejection"
|
|
1000
|
+
if failure.stage == "arguments":
|
|
1001
|
+
return "argument_rejection"
|
|
999
1002
|
if failure.stage == "result":
|
|
1000
1003
|
return "result_refinement"
|
|
1001
1004
|
if failure.stage == "cancelled":
|
package/sidecar/tool_catalog.py
CHANGED
|
@@ -426,7 +426,8 @@ class ToolCatalog(BaseModel):
|
|
|
426
426
|
for spec in specs:
|
|
427
427
|
definitions.extend(spec.stub.split("\n\n") if spec.stub else [])
|
|
428
428
|
facade_methods.setdefault(spec.namespace, []).append(
|
|
429
|
-
f" async def {spec.method}(self, arguments:
|
|
429
|
+
f" async def {spec.method}(self, arguments: "
|
|
430
|
+
f"{spec.input_type_name} | Mapping[str, JsonValue]) "
|
|
430
431
|
f"-> {spec.output_type_name}: ..."
|
|
431
432
|
)
|
|
432
433
|
facades: list[str] = []
|
|
@@ -114,6 +114,9 @@ function renderCompactFailure(
|
|
|
114
114
|
if (stage === "preflight") {
|
|
115
115
|
return theme.fg("warning", `✗ Preflight · code not run · ${summary}`);
|
|
116
116
|
}
|
|
117
|
+
if (stage === "arguments") {
|
|
118
|
+
return theme.fg("warning", `✗ Argument validation · code run · ${summary}`);
|
|
119
|
+
}
|
|
117
120
|
if (stage === "timeout") {
|
|
118
121
|
return theme.fg("error", `✗ Timeout · stopped after ${summary}`);
|
|
119
122
|
}
|
|
@@ -131,6 +134,9 @@ function failureHeading(stage: string, calls: number, chainCalls: number, theme:
|
|
|
131
134
|
if (stage === "preflight") {
|
|
132
135
|
return `${theme.fg("warning", theme.bold("Preflight failed"))}\n${theme.fg("muted", "Code was not executed; no upstream side effects")}`;
|
|
133
136
|
}
|
|
137
|
+
if (stage === "arguments") {
|
|
138
|
+
return `${theme.fg("warning", theme.bold("Argument validation failed"))}\n${theme.fg("muted", "Code ran; no invalid MCP call was sent")}`;
|
|
139
|
+
}
|
|
134
140
|
if (stage === "timeout") {
|
|
135
141
|
return `${theme.fg("error", theme.bold("Execution timed out"))}\n${theme.fg("muted", `Stopped after ${summary}`)}`;
|
|
136
142
|
}
|