MCPcopy
hub / github.com/coder/mux / createStopWhenCondition

Method createStopWhenCondition

src/node/services/streamManager.ts:1459–1513  ·  view source on GitHub ↗
(
    request: Pick<StreamRequestConfig, "hasQueuedMessages" | "toolPolicy">
  )

Source from the content-addressed store, hash-verified

1457 }
1458
1459 private createStopWhenCondition(
1460 request: Pick<StreamRequestConfig, "hasQueuedMessages" | "toolPolicy">
1461 ): Array<ReturnType<typeof stepCountIs>> {
1462 // Completion-tool stop check: completion/routing tools use explicit
1463 // success/ok markers (agent_report, propose_plan).
1464 // When a marker is present, respect it — success:false means the tool
1465 // should be retried, so don't stop. When no marker is present (e.g.,
1466 // MCP tools, arbitrary required tools), treat non-null object results
1467 // as successful completion unless the result is error-shaped.
1468 const isSuccessfulOutput = (output: unknown): boolean => {
1469 if (typeof output !== "object" || output === null) {
1470 return false;
1471 }
1472 const parsedOutput = output as Record<string, unknown>;
1473 if ("success" in parsedOutput) {
1474 return parsedOutput.success === true;
1475 }
1476 if ("ok" in parsedOutput) {
1477 return parsedOutput.ok === true;
1478 }
1479 if (parsedOutput.error != null || parsedOutput.isError === true) {
1480 return false;
1481 }
1482 return true;
1483 };
1484
1485 const requiredPatterns = (request.toolPolicy ?? [])
1486 .filter((filter) => filter.action === "require")
1487 .map((filter) => {
1488 // Strip existing anchors to avoid double-anchoring recovery policies
1489 // (e.g. "^agent_report$" would otherwise become "^^agent_report$$").
1490 const rawPattern = filter.regex_match.replace(/^\^/, "").replace(/\$$/, "");
1491 return new RegExp(`^${rawPattern}$`);
1492 });
1493
1494 const hasSuccessfulRequiredToolResult: ReturnType<typeof stepCountIs> = ({ steps }) => {
1495 if (requiredPatterns.length === 0) {
1496 return false;
1497 }
1498 const lastStep = steps[steps.length - 1];
1499 return (
1500 lastStep?.toolResults?.some(
1501 (toolResult) =>
1502 requiredPatterns.some((pattern) => pattern.test(toolResult.toolName)) &&
1503 isSuccessfulOutput(toolResult.output)
1504 ) ?? false
1505 );
1506 };
1507
1508 return [
1509 stepCountIs(100000),
1510 () => request.hasQueuedMessages?.("tool-end") ?? false,
1511 hasSuccessfulRequiredToolResult,
1512 ];
1513 }
1514
1515 private createStreamResult(
1516 request: StreamRequestConfig,

Callers 1

createStreamResultMethod · 0.95

Calls 1

hasQueuedMessagesMethod · 0.45

Tested by

no test coverage detected