@agentwonderland/mcp 0.1.23 → 0.1.25
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/dist/core/__tests__/amount-utils.test.d.ts +1 -0
- package/dist/core/__tests__/amount-utils.test.js +11 -0
- package/dist/core/__tests__/card-setup.test.d.ts +1 -0
- package/dist/core/__tests__/card-setup.test.js +99 -0
- package/dist/core/__tests__/formatters.test.d.ts +1 -0
- package/dist/core/__tests__/formatters.test.js +15 -0
- package/dist/core/__tests__/passes.test.d.ts +1 -0
- package/dist/core/__tests__/passes.test.js +82 -0
- package/dist/core/__tests__/payments.test.d.ts +1 -0
- package/dist/core/__tests__/payments.test.js +101 -0
- package/dist/core/__tests__/principal.test.d.ts +1 -0
- package/dist/core/__tests__/principal.test.js +67 -0
- package/dist/core/__tests__/spend-policy.test.d.ts +1 -0
- package/dist/core/__tests__/spend-policy.test.js +40 -0
- package/dist/core/amount-utils.d.ts +1 -0
- package/dist/core/amount-utils.js +4 -0
- package/dist/core/api-client.d.ts +9 -4
- package/dist/core/api-client.js +52 -22
- package/dist/core/base-charge.js +3 -2
- package/dist/core/card-setup.d.ts +20 -13
- package/dist/core/card-setup.js +85 -29
- package/dist/core/config.d.ts +22 -0
- package/dist/core/config.js +46 -2
- package/dist/core/formatters.d.ts +4 -3
- package/dist/core/formatters.js +10 -8
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.js +2 -0
- package/dist/core/ows-adapter.d.ts +10 -2
- package/dist/core/ows-adapter.js +54 -10
- package/dist/core/passes.d.ts +40 -0
- package/dist/core/passes.js +32 -0
- package/dist/core/payments.d.ts +8 -0
- package/dist/core/payments.js +111 -17
- package/dist/core/principal.d.ts +2 -0
- package/dist/core/principal.js +109 -0
- package/dist/core/solana-charge.d.ts +9 -0
- package/dist/core/solana-charge.js +96 -0
- package/dist/core/spend-policy.d.ts +12 -0
- package/dist/core/spend-policy.js +53 -0
- package/dist/core/types.d.ts +11 -2
- package/dist/index.js +11 -3
- package/dist/prompts/index.js +4 -2
- package/dist/resources/agents.js +1 -1
- package/dist/resources/wallet.js +8 -1
- package/dist/tools/__tests__/_payment-confirmation.test.d.ts +1 -0
- package/dist/tools/__tests__/_payment-confirmation.test.js +30 -0
- package/dist/tools/_payment-confirmation.d.ts +6 -0
- package/dist/tools/_payment-confirmation.js +28 -0
- package/dist/tools/agent-info.js +16 -2
- package/dist/tools/favorites.js +1 -1
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/index.js +1 -0
- package/dist/tools/observability.d.ts +2 -0
- package/dist/tools/observability.js +20 -0
- package/dist/tools/passes.d.ts +2 -0
- package/dist/tools/passes.js +157 -0
- package/dist/tools/run.js +127 -53
- package/dist/tools/solve.js +115 -51
- package/dist/tools/wallet.js +110 -59
- package/package.json +3 -1
- package/src/core/__tests__/amount-utils.test.ts +13 -0
- package/src/core/__tests__/card-setup.test.ts +118 -0
- package/src/core/__tests__/formatters.test.ts +17 -0
- package/src/core/__tests__/passes.test.ts +94 -0
- package/src/core/__tests__/payments.test.ts +122 -0
- package/src/core/__tests__/principal.test.ts +87 -0
- package/src/core/__tests__/spend-policy.test.ts +58 -0
- package/src/core/amount-utils.ts +5 -0
- package/src/core/api-client.ts +70 -23
- package/src/core/base-charge.ts +3 -2
- package/src/core/card-setup.ts +109 -34
- package/src/core/config.ts +74 -3
- package/src/core/formatters.ts +13 -9
- package/src/core/index.ts +2 -0
- package/src/core/ows-adapter.ts +74 -8
- package/src/core/passes.ts +74 -0
- package/src/core/payments.ts +130 -17
- package/src/core/principal.ts +128 -0
- package/src/core/solana-charge.ts +150 -0
- package/src/core/spend-policy.ts +69 -0
- package/src/core/types.ts +11 -2
- package/src/index.ts +11 -3
- package/src/prompts/index.ts +4 -2
- package/src/resources/agents.ts +1 -1
- package/src/resources/wallet.ts +8 -1
- package/src/tools/__tests__/_payment-confirmation.test.ts +45 -0
- package/src/tools/_payment-confirmation.ts +52 -0
- package/src/tools/agent-info.ts +25 -2
- package/src/tools/favorites.ts +1 -4
- package/src/tools/index.ts +1 -0
- package/src/tools/observability.ts +43 -0
- package/src/tools/passes.ts +228 -0
- package/src/tools/run.ts +174 -57
- package/src/tools/solve.ts +147 -59
- package/src/tools/wallet.ts +132 -62
package/src/tools/run.ts
CHANGED
|
@@ -2,18 +2,36 @@ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { apiGet, apiPost, apiPostWithPayment } from "../core/api-client.js";
|
|
4
4
|
import { uploadLocalFiles } from "../core/file-upload.js";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
formatCreditPackOffer,
|
|
7
|
+
getActiveCreditPack,
|
|
8
|
+
getCreditPackInventory,
|
|
9
|
+
getCreditPackProgram,
|
|
10
|
+
} from "../core/passes.js";
|
|
11
|
+
import {
|
|
12
|
+
getCompatiblePaymentMethods,
|
|
13
|
+
getConfiguredMethods,
|
|
14
|
+
hasWalletConfigured,
|
|
15
|
+
getWalletAddress,
|
|
16
|
+
normalizePaymentMethod,
|
|
17
|
+
} from "../core/payments.js";
|
|
6
18
|
import { requiresSpendConfirmation, getDefaultTipAmount } from "../core/config.js";
|
|
7
19
|
import { formatRunResult } from "../core/formatters.js";
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
20
|
+
import { canSpend, recordSpend, requiresPolicyConfirmation } from "../core/spend-policy.js";
|
|
21
|
+
import { storeFeedbackToken } from "./_token-cache.js";
|
|
22
|
+
import { getOrCreatePendingCardSetup, formatCardSetupBlocks } from "../core/card-setup.js";
|
|
23
|
+
import {
|
|
24
|
+
formatPaymentLabel,
|
|
25
|
+
formatRunConfirmationCommand,
|
|
26
|
+
resolveConfirmationMethod,
|
|
27
|
+
} from "./_payment-confirmation.js";
|
|
28
|
+
import type { AgentRecord } from "../core/types.js";
|
|
10
29
|
|
|
11
30
|
const POLL_INTERVAL_MS = 3000;
|
|
12
|
-
const POLL_MAX_MS = 120000;
|
|
31
|
+
const POLL_MAX_MS = 120000;
|
|
13
32
|
|
|
14
33
|
async function pollJobUntilDone(
|
|
15
34
|
jobId: string,
|
|
16
|
-
agentName: string,
|
|
17
35
|
): Promise<{ status: string; output?: unknown; error_code?: string }> {
|
|
18
36
|
const deadline = Date.now() + POLL_MAX_MS;
|
|
19
37
|
const walletAddress = await getWalletAddress();
|
|
@@ -34,9 +52,8 @@ async function pollJobUntilDone(
|
|
|
34
52
|
if (job.status === "failed") {
|
|
35
53
|
return { status: "failed", output: job.output, error_code: job.error_code };
|
|
36
54
|
}
|
|
37
|
-
// Still processing — continue polling
|
|
38
55
|
} catch {
|
|
39
|
-
// Ignore poll errors
|
|
56
|
+
// Ignore poll errors until timeout.
|
|
40
57
|
}
|
|
41
58
|
}
|
|
42
59
|
|
|
@@ -51,71 +68,130 @@ function multiText(...blocks: string[]) {
|
|
|
51
68
|
return { content: blocks.map((t) => ({ type: "text" as const, text: t })) };
|
|
52
69
|
}
|
|
53
70
|
|
|
54
|
-
// Pending confirmations: agent_id → { agent, input, method }
|
|
55
71
|
const pendingRuns = new Map<string, {
|
|
56
72
|
agent: { id: string; name: string; price: number };
|
|
57
73
|
input: Record<string, unknown>;
|
|
58
74
|
method?: string;
|
|
59
75
|
}>();
|
|
60
76
|
|
|
77
|
+
function buildCreditPackOfferLines(agent: AgentRecord): string[] {
|
|
78
|
+
const program = getCreditPackProgram(agent);
|
|
79
|
+
if (!program?.packs?.length) return [];
|
|
80
|
+
|
|
81
|
+
return [
|
|
82
|
+
"Discounted credit packs:",
|
|
83
|
+
...program.packs.map((pack) => formatCreditPackOffer({
|
|
84
|
+
pack_id: pack.key ?? "",
|
|
85
|
+
label: pack.name ?? pack.key ?? "Credit Pack",
|
|
86
|
+
included_units: pack.included_units ?? 0,
|
|
87
|
+
price_usd: pack.price_usd ?? "0.00",
|
|
88
|
+
effective_price_per_unit_usd: (pack.included_units ?? 0) > 0 && pack.price_usd
|
|
89
|
+
? (Number(pack.price_usd) / (pack.included_units ?? 1)).toFixed(6)
|
|
90
|
+
: undefined,
|
|
91
|
+
})).map((line) => ` ${line}`),
|
|
92
|
+
` Buy one with buy_agent_credit_pack({ agent_id: "${agent.id}", pack_id: "<pack_id>" })`,
|
|
93
|
+
];
|
|
94
|
+
}
|
|
95
|
+
|
|
61
96
|
export function registerRunTools(server: McpServer): void {
|
|
62
97
|
server.tool(
|
|
63
98
|
"run_agent",
|
|
64
|
-
"Run an AI agent from the marketplace. Pays automatically via configured wallet. Returns the agent's output, cost, and job ID for tracking. If spending confirmation is enabled, first call returns a price quote — call again with confirmed: true to execute. Local file paths in the input (e.g. /Users/.../photo.jpg) are automatically uploaded to temporary storage and replaced with download URLs
|
|
99
|
+
"Run an AI agent from the marketplace. Pays automatically via configured wallet. Returns the agent's output, cost, and job ID for tracking. If spending confirmation is enabled, first call returns a price quote — call again with confirmed: true to execute. Local file paths in the input (e.g. /Users/.../photo.jpg) are automatically uploaded to temporary storage and replaced with download URLs before execution.",
|
|
65
100
|
{
|
|
66
101
|
agent_id: z.string().describe("Agent ID (UUID, slug, or name)"),
|
|
67
102
|
input: z.record(z.unknown()).describe("Input payload for the agent"),
|
|
68
|
-
pay_with: z.string().
|
|
103
|
+
pay_with: z.string().trim().min(1).describe("Required payment method — wallet ID, chain name (tempo, base, etc.), or 'card'. Use wallet_status to see configured options."),
|
|
69
104
|
confirmed: z.boolean().optional().describe("Set to true to confirm spending after seeing the price quote."),
|
|
70
105
|
},
|
|
71
106
|
async ({ agent_id, input, pay_with, confirmed }) => {
|
|
72
107
|
if (!hasWalletConfigured()) {
|
|
73
108
|
try {
|
|
74
|
-
const {
|
|
75
|
-
|
|
76
|
-
return multiText(...blocks);
|
|
109
|
+
const { url } = await getOrCreatePendingCardSetup();
|
|
110
|
+
return multiText(...formatCardSetupBlocks(url));
|
|
77
111
|
} catch {
|
|
78
112
|
return text(
|
|
79
113
|
"No payment method configured.\n\n" +
|
|
80
114
|
"To add a credit card: wallet_setup({ action: \"add-card\" })\n" +
|
|
81
|
-
"To use crypto: wallet_setup({ action: \"create\" })"
|
|
115
|
+
"To use crypto: wallet_setup({ action: \"create\" })",
|
|
82
116
|
);
|
|
83
117
|
}
|
|
84
118
|
}
|
|
85
119
|
|
|
86
|
-
|
|
87
|
-
let agent: { id: string; name?: string; pricePer1kTokens?: string; successRate?: number };
|
|
120
|
+
let agent: AgentRecord;
|
|
88
121
|
try {
|
|
89
|
-
agent = await apiGet<
|
|
122
|
+
agent = await apiGet<AgentRecord>(`/agents/${agent_id}`);
|
|
90
123
|
} catch {
|
|
91
124
|
return text(`Agent "${agent_id}" not found. Use search_agents to find available agents.`);
|
|
92
125
|
}
|
|
93
126
|
|
|
94
|
-
const price = parseFloat(agent.
|
|
127
|
+
const price = parseFloat(agent.pricePerRunUsd ?? "0.01");
|
|
95
128
|
const agentName = agent.name ?? agent_id;
|
|
129
|
+
const creditPackInventory = await getCreditPackInventory(agent.id);
|
|
130
|
+
const activeCreditPack = getActiveCreditPack(creditPackInventory);
|
|
131
|
+
const compatibleMethods = getCompatiblePaymentMethods(agent, getConfiguredMethods());
|
|
132
|
+
const pending = pendingRuns.get(agent.id);
|
|
133
|
+
const requestedMethod = pay_with;
|
|
134
|
+
const normalizedRequestedMethod = normalizePaymentMethod(requestedMethod);
|
|
135
|
+
|
|
136
|
+
if (!normalizedRequestedMethod) {
|
|
137
|
+
return text(
|
|
138
|
+
`Payment method "${requestedMethod}" is not configured.\n\n` +
|
|
139
|
+
"Use wallet_status to review your current payment methods.",
|
|
140
|
+
);
|
|
141
|
+
}
|
|
96
142
|
|
|
97
|
-
|
|
98
|
-
|
|
143
|
+
if (!compatibleMethods.includes(normalizedRequestedMethod)) {
|
|
144
|
+
return text(
|
|
145
|
+
`This agent cannot be paid with "${requestedMethod}".\n\n` +
|
|
146
|
+
`Available payment methods for this agent: ${compatibleMethods.join(", ") || "none"}.\n` +
|
|
147
|
+
"Use get_agent to inspect the agent details or choose another payment method.",
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const method = resolveConfirmationMethod(pay_with, pending?.method, compatibleMethods);
|
|
152
|
+
const spendCheckMethod = method ?? normalizedRequestedMethod;
|
|
153
|
+
|
|
154
|
+
if (!activeCreditPack) {
|
|
155
|
+
const spendCheck = canSpend({
|
|
156
|
+
method: spendCheckMethod,
|
|
157
|
+
amountUsd: price,
|
|
158
|
+
});
|
|
159
|
+
if (!spendCheck.ok) {
|
|
160
|
+
return text(spendCheck.message);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const needsPolicyConfirmation = !activeCreditPack && requiresPolicyConfirmation(spendCheckMethod, price);
|
|
165
|
+
if (!activeCreditPack && (requiresSpendConfirmation() || needsPolicyConfirmation) && !confirmed) {
|
|
99
166
|
pendingRuns.set(agent.id, {
|
|
100
167
|
agent: { id: agent.id, name: agentName, price },
|
|
101
168
|
input,
|
|
102
|
-
method
|
|
169
|
+
method,
|
|
103
170
|
});
|
|
104
171
|
|
|
105
|
-
|
|
172
|
+
const quoteLines = [
|
|
106
173
|
`Ready to run ${agentName}`,
|
|
107
174
|
"",
|
|
108
175
|
` Cost: $${price.toFixed(2)}`,
|
|
109
|
-
` Payment: ${
|
|
176
|
+
` Payment: ${formatPaymentLabel(method)}`,
|
|
177
|
+
];
|
|
178
|
+
|
|
179
|
+
const creditPackLines = buildCreditPackOfferLines(agent);
|
|
180
|
+
if (creditPackLines.length > 0) {
|
|
181
|
+
quoteLines.push("", ...creditPackLines);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
quoteLines.push(
|
|
110
185
|
"",
|
|
111
186
|
"To proceed, call:",
|
|
112
|
-
|
|
187
|
+
formatRunConfirmationCommand(agent.id, method),
|
|
113
188
|
"",
|
|
114
189
|
"To cancel, do nothing.",
|
|
115
|
-
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
return text(quoteLines.join("\n"));
|
|
116
193
|
}
|
|
117
194
|
|
|
118
|
-
const method = pay_with;
|
|
119
195
|
let processedInput: Record<string, unknown>;
|
|
120
196
|
let uploadSummary = "";
|
|
121
197
|
try {
|
|
@@ -123,30 +199,59 @@ export function registerRunTools(server: McpServer): void {
|
|
|
123
199
|
processedInput = uploadResult.input;
|
|
124
200
|
if (uploadResult.uploads.length > 0) {
|
|
125
201
|
uploadSummary = uploadResult.uploads
|
|
126
|
-
.map((
|
|
202
|
+
.map((upload) => `Uploaded ${upload.field}: ${upload.originalPath} → ${upload.url}`)
|
|
127
203
|
.join("\n");
|
|
128
204
|
}
|
|
129
205
|
} catch (err) {
|
|
130
206
|
const msg = err instanceof Error ? err.message : "File upload failed";
|
|
131
207
|
return text(`Error: ${msg}`);
|
|
132
208
|
}
|
|
209
|
+
|
|
133
210
|
let result: Record<string, unknown>;
|
|
211
|
+
let usedPaidMethod = !activeCreditPack;
|
|
134
212
|
try {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
213
|
+
if (activeCreditPack) {
|
|
214
|
+
try {
|
|
215
|
+
result = await apiPost<Record<string, unknown>>(
|
|
216
|
+
`/agents/${agent.id}/run`,
|
|
217
|
+
{ input: processedInput },
|
|
218
|
+
{ ensureConsumerPrincipal: true },
|
|
219
|
+
);
|
|
220
|
+
} catch (packErr) {
|
|
221
|
+
const packApiErr = packErr as { status?: number };
|
|
222
|
+
if (packApiErr?.status !== 402) throw packErr;
|
|
223
|
+
result = await apiPostWithPayment<Record<string, unknown>>(
|
|
224
|
+
`/agents/${agent.id}/run`,
|
|
225
|
+
{ input: processedInput },
|
|
226
|
+
method,
|
|
227
|
+
);
|
|
228
|
+
usedPaidMethod = true;
|
|
229
|
+
}
|
|
230
|
+
} else {
|
|
231
|
+
result = await apiPostWithPayment<Record<string, unknown>>(
|
|
232
|
+
`/agents/${agent.id}/run`,
|
|
233
|
+
{ input: processedInput },
|
|
234
|
+
method,
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
if (usedPaidMethod) {
|
|
238
|
+
recordSpend(spendCheckMethod, price);
|
|
239
|
+
}
|
|
140
240
|
} catch (err: unknown) {
|
|
141
241
|
const apiErr = err as { status?: number; message?: string };
|
|
142
242
|
if (apiErr?.status === 402) {
|
|
143
243
|
const allMethods = getConfiguredMethods();
|
|
144
244
|
const methodName = method ?? allMethods[0] ?? "auto";
|
|
245
|
+
const creditPackLines = buildCreditPackOfferLines(agent);
|
|
145
246
|
return text(
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
247
|
+
[
|
|
248
|
+
`Payment failed — "${methodName}" payment was rejected.`,
|
|
249
|
+
"",
|
|
250
|
+
"Check your payment method and try again.",
|
|
251
|
+
...(allMethods.length > 0 ? [`Configured methods: ${allMethods.join(", ")}`] : []),
|
|
252
|
+
"Use wallet_status to check your current payment methods.",
|
|
253
|
+
...(creditPackLines.length > 0 ? ["", ...creditPackLines] : []),
|
|
254
|
+
].join("\n"),
|
|
150
255
|
);
|
|
151
256
|
}
|
|
152
257
|
const msg = apiErr?.message ?? "Failed to run agent";
|
|
@@ -156,7 +261,6 @@ export function registerRunTools(server: McpServer): void {
|
|
|
156
261
|
return text(`Error: ${msg}`);
|
|
157
262
|
}
|
|
158
263
|
|
|
159
|
-
// Clean up pending confirmation
|
|
160
264
|
pendingRuns.delete(agent.id);
|
|
161
265
|
|
|
162
266
|
const formatted = formatRunResult(result, {
|
|
@@ -171,10 +275,10 @@ export function registerRunTools(server: McpServer): void {
|
|
|
171
275
|
|
|
172
276
|
const actualCost = result.cost as number | undefined;
|
|
173
277
|
const status = result.status as string;
|
|
278
|
+
const usedCreditPack = result.consumption_mode === "credit_pack";
|
|
174
279
|
|
|
175
|
-
// Async agent — poll until complete
|
|
176
280
|
if (status === "processing") {
|
|
177
|
-
const pollResult = await pollJobUntilDone(jobId
|
|
281
|
+
const pollResult = await pollJobUntilDone(jobId);
|
|
178
282
|
if (pollResult.status === "completed") {
|
|
179
283
|
const asyncFormatted = formatRunResult({
|
|
180
284
|
...result,
|
|
@@ -182,14 +286,15 @@ export function registerRunTools(server: McpServer): void {
|
|
|
182
286
|
output: pollResult.output,
|
|
183
287
|
}, { paymentMethod: method ?? getConfiguredMethods()[0] });
|
|
184
288
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
289
|
+
const asyncSpendLine = usedCreditPack
|
|
290
|
+
? "This run used your available credit pack."
|
|
291
|
+
: actualCost != null
|
|
292
|
+
? `Paid $${actualCost.toFixed(actualCost < 0.01 ? 4 : 2)}.`
|
|
293
|
+
: "This run completed successfully.";
|
|
188
294
|
|
|
189
|
-
const asyncCostLine = actualCost != null ? `Paid $${actualCost.toFixed(actualCost < 0.01 ? 4 : 2)}.` : "";
|
|
190
295
|
const asyncFeedbackAsk = [
|
|
191
|
-
|
|
192
|
-
`"${
|
|
296
|
+
"IMPORTANT: After presenting the result above, you MUST ask the user:",
|
|
297
|
+
`"${asyncSpendLine} Was this result helpful? I can rate it (1-5 stars) or tip the builder for you."`,
|
|
193
298
|
"",
|
|
194
299
|
`If the user wants to rate: rate_agent({ job_id: "${jobId}", rating: <1-5>, comment: "..." })`,
|
|
195
300
|
`If the user wants to tip: tip_agent({ job_id: "${jobId}", agent_id: "${resultAgentId}", amount: 0.25 })`,
|
|
@@ -202,7 +307,6 @@ export function registerRunTools(server: McpServer): void {
|
|
|
202
307
|
);
|
|
203
308
|
}
|
|
204
309
|
|
|
205
|
-
// Async agent failed
|
|
206
310
|
const failedFormatted = formatRunResult({
|
|
207
311
|
...result,
|
|
208
312
|
status: "failed",
|
|
@@ -212,11 +316,12 @@ export function registerRunTools(server: McpServer): void {
|
|
|
212
316
|
|
|
213
317
|
return multiText(
|
|
214
318
|
uploadSummary ? `${uploadSummary}\n\n${failedFormatted}` : failedFormatted,
|
|
215
|
-
|
|
319
|
+
usedCreditPack
|
|
320
|
+
? "The agent execution failed and your reserved credit-pack unit was released automatically."
|
|
321
|
+
: "The agent execution failed. A refund has been initiated automatically.",
|
|
216
322
|
);
|
|
217
323
|
}
|
|
218
324
|
|
|
219
|
-
// Auto-tip if configured and run succeeded
|
|
220
325
|
const defaultTip = getDefaultTipAmount();
|
|
221
326
|
let tipLine = "";
|
|
222
327
|
if (status === "success" && defaultTip > 0 && result.feedback_token) {
|
|
@@ -236,20 +341,24 @@ export function registerRunTools(server: McpServer): void {
|
|
|
236
341
|
if (status !== "success") {
|
|
237
342
|
return multiText(
|
|
238
343
|
uploadSummary ? `${uploadSummary}\n\n${formatted}` : formatted,
|
|
239
|
-
|
|
344
|
+
usedCreditPack
|
|
345
|
+
? "The agent execution failed and your reserved credit-pack unit was released automatically."
|
|
346
|
+
: "The agent execution failed. A refund has been initiated automatically.",
|
|
240
347
|
);
|
|
241
348
|
}
|
|
242
349
|
|
|
243
|
-
const costLine =
|
|
350
|
+
const costLine = usedCreditPack
|
|
351
|
+
? ""
|
|
352
|
+
: actualCost != null
|
|
353
|
+
? `Paid $${actualCost.toFixed(actualCost < 0.01 ? 4 : 2)}.`
|
|
354
|
+
: "";
|
|
355
|
+
const spendLine = usedCreditPack ? "This run used your available credit pack." : (costLine || "This run completed successfully.");
|
|
244
356
|
|
|
245
|
-
// Separate the feedback ask into its own content block so the LLM
|
|
246
|
-
// surfaces it to the user as a distinct follow-up question, rather than
|
|
247
|
-
// burying it inside a collapsed tool output.
|
|
248
357
|
const feedbackAsk = [
|
|
249
|
-
`--- Job ${jobId} | ${agentName} | ${costLine} ---`,
|
|
358
|
+
`--- Job ${jobId} | ${agentName} | ${usedCreditPack ? "covered by credit pack" : (costLine || "completed")} ---`,
|
|
250
359
|
"",
|
|
251
|
-
|
|
252
|
-
`"${
|
|
360
|
+
"IMPORTANT: After presenting the result above, you MUST ask the user:",
|
|
361
|
+
`"${spendLine} Was this result helpful? I can rate it (1-5 stars) or tip the builder for you."`,
|
|
253
362
|
tipLine,
|
|
254
363
|
"",
|
|
255
364
|
`If the user wants to rate: rate_agent({ job_id: "${jobId}", rating: <1-5>, comment: "..." })`,
|
|
@@ -259,7 +368,15 @@ export function registerRunTools(server: McpServer): void {
|
|
|
259
368
|
`To save for later: favorite_agent({ agent_id: "${resultAgentId}" })`,
|
|
260
369
|
].join("\n");
|
|
261
370
|
|
|
262
|
-
|
|
371
|
+
const supplementalLines = !usedCreditPack
|
|
372
|
+
? buildCreditPackOfferLines(agent)
|
|
373
|
+
: [];
|
|
374
|
+
|
|
375
|
+
const primaryBlock = uploadSummary ? `${uploadSummary}\n\n${formatted}` : formatted;
|
|
376
|
+
return multiText(
|
|
377
|
+
supplementalLines.length > 0 ? `${primaryBlock}\n\n${supplementalLines.join("\n")}` : primaryBlock,
|
|
378
|
+
feedbackAsk,
|
|
379
|
+
);
|
|
263
380
|
},
|
|
264
381
|
);
|
|
265
382
|
}
|