@prompd/cli 0.4.10 → 0.5.0-beta.1

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.
Files changed (61) hide show
  1. package/README.md +1 -1
  2. package/dist/commands/ask.d.ts +3 -0
  3. package/dist/commands/ask.d.ts.map +1 -0
  4. package/dist/commands/ask.js +121 -0
  5. package/dist/commands/ask.js.map +1 -0
  6. package/dist/commands/mcp.d.ts.map +1 -1
  7. package/dist/commands/mcp.js +192 -42
  8. package/dist/commands/mcp.js.map +1 -1
  9. package/dist/commands/package.js +5 -5
  10. package/dist/commands/run.d.ts.map +1 -1
  11. package/dist/commands/run.js +62 -4
  12. package/dist/commands/run.js.map +1 -1
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +2 -0
  15. package/dist/index.js.map +1 -1
  16. package/dist/lib/commandExecutor.d.ts +2 -2
  17. package/dist/lib/commandExecutor.d.ts.map +1 -1
  18. package/dist/lib/commandExecutor.js +2 -2
  19. package/dist/lib/commandExecutor.js.map +1 -1
  20. package/dist/lib/compiler/package-resolver.d.ts.map +1 -1
  21. package/dist/lib/compiler/package-resolver.js +5 -1
  22. package/dist/lib/compiler/package-resolver.js.map +1 -1
  23. package/dist/lib/executor.d.ts +16 -6
  24. package/dist/lib/executor.d.ts.map +1 -1
  25. package/dist/lib/executor.js +121 -245
  26. package/dist/lib/executor.js.map +1 -1
  27. package/dist/lib/index.d.ts +4 -2
  28. package/dist/lib/index.d.ts.map +1 -1
  29. package/dist/lib/index.js +21 -4
  30. package/dist/lib/index.js.map +1 -1
  31. package/dist/lib/mcp.d.ts +13 -2
  32. package/dist/lib/mcp.d.ts.map +1 -1
  33. package/dist/lib/mcp.js +447 -77
  34. package/dist/lib/mcp.js.map +1 -1
  35. package/dist/lib/nodeTypeRegistry.d.ts +1 -1
  36. package/dist/lib/nodeTypeRegistry.d.ts.map +1 -1
  37. package/dist/lib/providers/base.d.ts +92 -0
  38. package/dist/lib/providers/base.d.ts.map +1 -0
  39. package/dist/lib/providers/base.js +741 -0
  40. package/dist/lib/providers/base.js.map +1 -0
  41. package/dist/lib/providers/factory.d.ts +37 -0
  42. package/dist/lib/providers/factory.d.ts.map +1 -0
  43. package/dist/lib/providers/factory.js +82 -0
  44. package/dist/lib/providers/factory.js.map +1 -0
  45. package/dist/lib/providers/index.d.ts +12 -0
  46. package/dist/lib/providers/index.d.ts.map +1 -0
  47. package/dist/lib/providers/index.js +25 -0
  48. package/dist/lib/providers/index.js.map +1 -0
  49. package/dist/lib/providers/types.d.ts +129 -0
  50. package/dist/lib/providers/types.d.ts.map +1 -0
  51. package/dist/lib/providers/types.js +156 -0
  52. package/dist/lib/providers/types.js.map +1 -0
  53. package/dist/lib/workflowExecutor.d.ts.map +1 -1
  54. package/dist/lib/workflowExecutor.js +88 -74
  55. package/dist/lib/workflowExecutor.js.map +1 -1
  56. package/dist/lib/workflowTypes.d.ts +2 -0
  57. package/dist/lib/workflowTypes.d.ts.map +1 -1
  58. package/dist/lib/workflowTypes.js.map +1 -1
  59. package/dist/types/index.d.ts +3 -0
  60. package/dist/types/index.d.ts.map +1 -1
  61. package/package.json +124 -119
@@ -1189,9 +1189,10 @@ async function executePromptNode(node, context, options, trace, state, workflowF
1189
1189
  },
1190
1190
  };
1191
1191
  await emitAgentCheckpoint(afterEvent, options, workflowFile);
1192
- // Apply guardrail validation if configured
1193
- if (data.guardrail) {
1192
+ // Apply guardrail validation if configured and enabled
1193
+ if (data.guardrail && data.guardrail.enabled !== false) {
1194
1194
  const guardrail = data.guardrail;
1195
+ const originalLlmResult = result; // Preserve LLM response before guardrail may modify it
1195
1196
  let isRejected = false;
1196
1197
  // Evaluate rejection condition
1197
1198
  if (guardrail.rejectionExpression) {
@@ -1276,8 +1277,8 @@ async function executePromptNode(node, context, options, trace, state, workflowF
1276
1277
  message: `Guardrail PASSED content, outputMode=${outputMode}`,
1277
1278
  }, options);
1278
1279
  if (outputMode === 'original') {
1279
- // Return the original input that was sent to the guardrail prompt
1280
- result = context.previous_output;
1280
+ // Return the original LLM response (before guardrail evaluation)
1281
+ result = originalLlmResult;
1281
1282
  }
1282
1283
  else if (outputMode === 'reject-message') {
1283
1284
  // Return custom message even on pass (useful for custom routing)
@@ -1357,30 +1358,30 @@ async function executeGuardrailNode(node, context, options, trace, workflowFile)
1357
1358
  : JSON.stringify(inputToValidate, null, 2);
1358
1359
  // Create a raw prompt that validates the input
1359
1360
  // The system prompt should instruct the LLM to analyze and return a structured response
1360
- const validationPrompt = `---
1361
- id: guardrail-validation
1362
- name: Guardrail Validation
1363
- version: 1.0.0
1364
- description: Validates input against guardrail criteria
1365
- ---
1366
-
1367
- # System
1368
- ${data.systemPrompt}
1369
-
1370
- # Input to Validate
1371
- \`\`\`
1372
- ${inputStr}
1373
- \`\`\`
1374
-
1375
- # Instructions
1376
- Analyze the input above according to the system criteria. Return your analysis as a JSON object with the following structure:
1377
- \`\`\`json
1378
- {
1379
- "analysis": "Your analysis of the input",
1380
- "score": 0.0 to 1.0,
1381
- "rejected": true or false
1382
- }
1383
- \`\`\`
1361
+ const validationPrompt = `---
1362
+ id: guardrail-validation
1363
+ name: Guardrail Validation
1364
+ version: 1.0.0
1365
+ description: Validates input against guardrail criteria
1366
+ ---
1367
+
1368
+ # System
1369
+ ${data.systemPrompt}
1370
+
1371
+ # Input to Validate
1372
+ \`\`\`
1373
+ ${inputStr}
1374
+ \`\`\`
1375
+
1376
+ # Instructions
1377
+ Analyze the input above according to the system criteria. Return your analysis as a JSON object with the following structure:
1378
+ \`\`\`json
1379
+ {
1380
+ "analysis": "Your analysis of the input",
1381
+ "score": 0.0 to 1.0,
1382
+ "rejected": true or false
1383
+ }
1384
+ \`\`\`
1384
1385
  `;
1385
1386
  // Emit beforeValidation checkpoint event
1386
1387
  const beforeEvent = {
@@ -4102,6 +4103,10 @@ async function executeAgentNode(node, context, options, trace, state, workflowFi
4102
4103
  const lastAssistantMessage = conversationHistory.filter(m => m.role === 'assistant').pop();
4103
4104
  finalResponse = lastAssistantMessage?.content || 'Agent reached maximum iterations without completing.';
4104
4105
  }
4106
+ // Strip any unexecuted <tool_call> XML from final response so raw tags don't leak to output
4107
+ if (finalResponse) {
4108
+ finalResponse = finalResponse.replace(/<tool_call>[\s\S]*?<\/tool_call>/gi, '').trim();
4109
+ }
4105
4110
  // Determine output based on outputMode
4106
4111
  let output;
4107
4112
  switch (data.outputMode) {
@@ -4471,29 +4476,29 @@ async function executeChatAgentNode(node, context, options, trace, state, workfl
4471
4476
  }
4472
4477
  // Build guardrail validation prompt
4473
4478
  const inputStr = typeof currentInput === 'string' ? currentInput : JSON.stringify(currentInput, null, 2);
4474
- const validationPrompt = `---
4475
- id: chat-agent-guardrail
4476
- name: Chat Agent Guardrail
4477
- version: 1.0.0
4478
- ---
4479
-
4480
- # System
4481
- ${data.guardrailSystemPrompt}
4482
-
4483
- # Input to Validate
4484
- \`\`\`
4485
- ${inputStr}
4486
- \`\`\`
4487
-
4488
- # Instructions
4489
- Analyze the input above. Return a JSON object:
4490
- \`\`\`json
4491
- {
4492
- "analysis": "Your analysis",
4493
- "score": 0.0 to 1.0,
4494
- "rejected": true or false
4495
- }
4496
- \`\`\`
4479
+ const validationPrompt = `---
4480
+ id: chat-agent-guardrail
4481
+ name: Chat Agent Guardrail
4482
+ version: 1.0.0
4483
+ ---
4484
+
4485
+ # System
4486
+ ${data.guardrailSystemPrompt}
4487
+
4488
+ # Input to Validate
4489
+ \`\`\`
4490
+ ${inputStr}
4491
+ \`\`\`
4492
+
4493
+ # Instructions
4494
+ Analyze the input above. Return a JSON object:
4495
+ \`\`\`json
4496
+ {
4497
+ "analysis": "Your analysis",
4498
+ "score": 0.0 to 1.0,
4499
+ "rejected": true or false
4500
+ }
4501
+ \`\`\`
4497
4502
  `;
4498
4503
  if (!options.executePrompt) {
4499
4504
  throw new Error('No executePrompt function provided for guardrail validation');
@@ -5112,6 +5117,10 @@ Analyze the input above. Return a JSON object:
5112
5117
  const lastAssistantMessage = conversationHistory.filter(m => m.role === 'assistant').pop();
5113
5118
  finalResponse = lastAssistantMessage?.content || 'Agent reached maximum iterations.';
5114
5119
  }
5120
+ // Strip any unexecuted <tool_call> XML from final response so raw tags don't leak to output
5121
+ if (finalResponse) {
5122
+ finalResponse = finalResponse.replace(/<tool_call>[\s\S]*?<\/tool_call>/gi, '').trim();
5123
+ }
5115
5124
  // Emit onAgentComplete checkpoint
5116
5125
  await emitChatAgentCheckpoint('onAgentComplete', {
5117
5126
  finalResponse,
@@ -5169,28 +5178,28 @@ function buildSystemPromptWithTools(systemPrompt, tools, format) {
5169
5178
  const toolDescriptions = tools.map(t => `- ${t.name}: ${t.description}${t.parameters?.properties ? ` (params: ${Object.keys(t.parameters.properties).join(', ')})` : ''}`).join('\n');
5170
5179
  let formatInstructions = '';
5171
5180
  if (format === 'xml' || format === 'auto') {
5172
- formatInstructions = `
5173
-
5174
- To use a tool, respond with XML in this format:
5175
- <tool_call>
5176
- <name>tool_name</name>
5177
- <params>{"param1": "value1"}</params>
5178
- </tool_call>
5179
-
5181
+ formatInstructions = `
5182
+
5183
+ To use a tool, respond with XML in this format:
5184
+ <tool_call>
5185
+ <name>tool_name</name>
5186
+ <params>{"param1": "value1"}</params>
5187
+ </tool_call>
5188
+
5180
5189
  When you have the final answer and don't need any more tools, respond normally without XML tags.`;
5181
5190
  }
5182
5191
  else if (format === 'json') {
5183
- formatInstructions = `
5184
-
5185
- To use a tool, respond with JSON in this format:
5186
- {"tool": "tool_name", "parameters": {"param1": "value1"}}
5187
-
5192
+ formatInstructions = `
5193
+
5194
+ To use a tool, respond with JSON in this format:
5195
+ {"tool": "tool_name", "parameters": {"param1": "value1"}}
5196
+
5188
5197
  When you have the final answer and don't need any more tools, respond with plain text (no JSON).`;
5189
5198
  }
5190
- return `${systemPrompt}
5191
-
5192
- You have access to the following tools:
5193
- ${toolDescriptions}
5199
+ return `${systemPrompt}
5200
+
5201
+ You have access to the following tools:
5202
+ ${toolDescriptions}
5194
5203
  ${formatInstructions}`;
5195
5204
  }
5196
5205
  /**
@@ -5203,17 +5212,22 @@ function parseToolCall(response, format, allowedTools) {
5203
5212
  toolParameters: null,
5204
5213
  };
5205
5214
  const responseText = typeof response === 'string' ? response : JSON.stringify(response);
5206
- // Try XML format
5215
+ // Try XML format — match first <tool_call> block, <params> is optional
5207
5216
  if (format === 'auto' || format === 'xml') {
5208
- const xmlMatch = responseText.match(/<tool_call>\s*<name>([^<]+)<\/name>\s*<params>([\s\S]*?)<\/params>\s*<\/tool_call>/i);
5217
+ const xmlMatch = responseText.match(/<tool_call>\s*<name>([^<]+)<\/name>(?:\s*<params>([\s\S]*?)<\/params>)?\s*<\/tool_call>/i);
5209
5218
  if (xmlMatch) {
5210
5219
  result.hasToolCall = true;
5211
5220
  result.toolName = xmlMatch[1].trim();
5212
- try {
5213
- result.toolParameters = JSON.parse(xmlMatch[2].trim());
5221
+ if (xmlMatch[2]) {
5222
+ try {
5223
+ result.toolParameters = JSON.parse(xmlMatch[2].trim());
5224
+ }
5225
+ catch {
5226
+ result.toolParameters = { raw: xmlMatch[2].trim() };
5227
+ }
5214
5228
  }
5215
- catch {
5216
- result.toolParameters = { raw: xmlMatch[2].trim() };
5229
+ else {
5230
+ result.toolParameters = {};
5217
5231
  }
5218
5232
  return result;
5219
5233
  }