@itpay/cli 2.0.31 → 2.0.32
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/README.md +13 -3
- package/dist/src/commands/checkout.js +1 -1
- package/dist/src/commands/guidance.js +11 -412
- package/dist/src/commands/install.js +1 -1
- package/dist/src/commands/order.js +2 -2
- package/dist/src/commands/orders.js +1 -4
- package/dist/src/commands/readyz.js +2 -2
- package/dist/src/commands/services.js +28 -24
- package/dist/src/commands/vault.js +1 -1
- package/dist/src/main.js +24 -9
- package/dist/src/state/config.js +1 -1
- package/docs/agent/buyer/catalog-list.json +11 -8
- package/docs/agent/buyer/install-and-setup.json +15 -13
- package/docs/agent/buyer/orders-refunds.json +3 -3
- package/docs/agent/buyer/payment-flow.json +1 -2
- package/docs/agent/buyer/purchased-content.json +5 -0
- package/docs/agent/buyer/quickstart.json +22 -40
- package/docs/cli-reference/commands/checkout.md +1 -1
- package/docs/cli-reference/commands/install.md +3 -1
- package/docs/cli-reference/commands/order.md +1 -1
- package/docs/cli-reference/commands/readyz.md +3 -3
- package/docs/cli-reference/commands/services/action.md +1 -1
- package/docs/cli-reference/commands/services/invoke.md +5 -5
- package/docs/cli-reference/commands/services/list.md +3 -3
- package/docs/cli-reference/commands/services/next.md +5 -5
- package/docs/cli-reference/commands/vault/read.md +1 -1
- package/docs/cli-reference/conventions.md +27 -0
- package/package.json +1 -1
- package/skills/itpay/SKILL.md +59 -149
package/README.md
CHANGED
|
@@ -8,13 +8,23 @@ The official V3 CLI and the single ItPay entry point for services, purchases, ac
|
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
10
|
npm install -g @itpay/cli
|
|
11
|
-
itpay readyz --json
|
|
12
|
-
itpay skill show itpay --json
|
|
13
11
|
itpay install --json
|
|
14
12
|
itpay --agent-type codex-desktop readyz --json
|
|
15
|
-
#
|
|
13
|
+
# execute the returned next.command until the typed Skill is loaded
|
|
16
14
|
```
|
|
17
15
|
|
|
16
|
+
Official Agent install prompt(可直接复制给 Agent):
|
|
17
|
+
|
|
18
|
+
> 安装或更新官方 `@itpay/cli`。从 `itpay install --json` 开始,选择你真实
|
|
19
|
+
> 所在的平台,完整执行 iTPay 返回的每个 `next.command` 并读取内置 Skill。
|
|
20
|
+
> 初始化后,根据我的自然语言需求自行使用 iTPay,不要让我运行命令,也不要向
|
|
21
|
+
> 我讲解命令、内部 ID 或技术步骤。只有需要我选择、授权、付款、提供联系方式
|
|
22
|
+
> 或确认退款时,才用通俗语言询问我;展示官方操作入口后停止等待。不要猜命令、
|
|
23
|
+
> 切换身份或环境、绕过授权或重复创建资源。准备完成后只回复“iTPay 已就绪”。
|
|
24
|
+
|
|
25
|
+
Use a separate test prompt to set the exact official Dev Backend. Never put a
|
|
26
|
+
Dev override in the public install prompt.
|
|
27
|
+
|
|
18
28
|
The CLI defaults to the production Backend `https://app.itpay.ai`. Explicit tests may set `ITPAY_BACKEND_URL=https://dev.itpay.ai`; every other Backend URL is rejected before network or local state access.
|
|
19
29
|
|
|
20
30
|
## Output Contract
|
|
@@ -110,7 +110,7 @@ function terminalCheckoutEnvelope(presentation) {
|
|
|
110
110
|
const recovery = [];
|
|
111
111
|
if (payment === "verified") {
|
|
112
112
|
status = "completed";
|
|
113
|
-
instruction = "
|
|
113
|
+
instruction = "告诉用户:付款已经确认,订单已经记录,不需要再次付款;结果会在同一订单下继续准备,如果最终无法交付,可以从原订单申请退款,处理方式由内容是否已使用决定。然后只执行 next.command 读取同一笔服务;Agent 不再展示付款入口或创建新订单,也不承诺退款结果。";
|
|
114
114
|
next = serviceExecutionIDs.length === 1
|
|
115
115
|
? { command: `itpay services next ${serviceExecutionIDs[0]} --json`, reason: "读取同一笔已付款 Service Execution" }
|
|
116
116
|
: presentation.completed_order_id
|
|
@@ -57,49 +57,6 @@ export function writeCommandEnvelope(value, options = {}) {
|
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
|
-
export function attachAgentGuidance(payload, guidance) {
|
|
61
|
-
return {
|
|
62
|
-
...payload,
|
|
63
|
-
agent_guidance: guidance,
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
export function printAgentGuidance(guidance, output) {
|
|
67
|
-
const out = resolveOutput(output);
|
|
68
|
-
const agentType = declaredAgentType();
|
|
69
|
-
out(`${guidance.summary}\n`);
|
|
70
|
-
if (guidance.visible_results?.length) {
|
|
71
|
-
out("results:\n");
|
|
72
|
-
for (const item of guidance.visible_results) {
|
|
73
|
-
out(` ${item.rank}. ${item.title}\n`);
|
|
74
|
-
for (const [key, value] of Object.entries(item.safe_payload)) {
|
|
75
|
-
if (key === "name" || key === "company_name" || value === "" || value === undefined || value === null)
|
|
76
|
-
continue;
|
|
77
|
-
out(` ${key}: ${String(value)}\n`);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
if (guidance.next_actions.length === 0) {
|
|
82
|
-
out("next actions: none\n");
|
|
83
|
-
}
|
|
84
|
-
else {
|
|
85
|
-
out("next actions:\n");
|
|
86
|
-
for (const action of guidance.next_actions) {
|
|
87
|
-
out(` - ${action.label}\n`);
|
|
88
|
-
out(` ${qualifyBackendCommand(qualifyItPayCommand(action.command, agentType))}\n`);
|
|
89
|
-
if (action.requires_human)
|
|
90
|
-
out(" requires human confirmation\n");
|
|
91
|
-
if (action.reason)
|
|
92
|
-
out(` reason: ${action.reason}\n`);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
if (guidance.recovery.length > 0) {
|
|
96
|
-
out("recovery:\n");
|
|
97
|
-
for (const action of guidance.recovery) {
|
|
98
|
-
out(` - ${action.label}\n`);
|
|
99
|
-
out(` ${qualifyBackendCommand(qualifyItPayCommand(action.command, agentType))}\n`);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
60
|
function qualifyEnvelope(value, agentType) {
|
|
104
61
|
return {
|
|
105
62
|
...value,
|
|
@@ -110,181 +67,31 @@ function qualifyEnvelope(value, agentType) {
|
|
|
110
67
|
})),
|
|
111
68
|
};
|
|
112
69
|
}
|
|
113
|
-
export function buildCartGuidance(cart, serviceModel) {
|
|
114
|
-
const serviceLine = latestServiceLine(cart);
|
|
115
|
-
if (serviceLine?.service_execution_id) {
|
|
116
|
-
const serviceGuidance = serviceModel
|
|
117
|
-
? buildServiceReadModelGuidance(serviceModel)
|
|
118
|
-
: buildServiceHandleGuidance(serviceLine.service_execution_id, serviceLine.service_capability_id);
|
|
119
|
-
return {
|
|
120
|
-
...serviceGuidance,
|
|
121
|
-
kind: "cart_service_execution",
|
|
122
|
-
summary: `cart ${cart.cart_id}: service-backed line ${lineID(serviceLine)} is ready for Service Execution`,
|
|
123
|
-
state: {
|
|
124
|
-
...serviceGuidance.state,
|
|
125
|
-
cart_id: cart.cart_id,
|
|
126
|
-
cart_item_id: lineID(serviceLine),
|
|
127
|
-
service_capability_id: serviceLine.service_capability_id,
|
|
128
|
-
},
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
if (cart.items.length === 0) {
|
|
132
|
-
return {
|
|
133
|
-
kind: "empty_cart",
|
|
134
|
-
summary: `cart ${cart.cart_id}: empty`,
|
|
135
|
-
state: { cart_id: cart.cart_id, status: cart.status },
|
|
136
|
-
next_actions: [
|
|
137
|
-
{
|
|
138
|
-
id: "browse_catalog",
|
|
139
|
-
label: "Browse services",
|
|
140
|
-
command: "itpay catalog list",
|
|
141
|
-
},
|
|
142
|
-
],
|
|
143
|
-
recovery: [],
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
return {
|
|
147
|
-
kind: "cart_checkout_ready",
|
|
148
|
-
summary: `cart ${cart.cart_id}: ready for checkout`,
|
|
149
|
-
state: { cart_id: cart.cart_id, status: cart.status, amount_minor: cart.amount_minor, currency: cart.currency },
|
|
150
|
-
next_actions: [
|
|
151
|
-
{
|
|
152
|
-
id: "checkout_cart",
|
|
153
|
-
label: "Create ItPay checkout",
|
|
154
|
-
command: `itpay buy --cart ${cart.cart_id} --host <client> --contact-email <email>`,
|
|
155
|
-
requires_human: true,
|
|
156
|
-
reason: "The human must review and pay on the ItPay checkout page.",
|
|
157
|
-
},
|
|
158
|
-
],
|
|
159
|
-
recovery: [
|
|
160
|
-
{
|
|
161
|
-
id: "show_cart",
|
|
162
|
-
label: "Inspect current server cart",
|
|
163
|
-
command: "itpay cart show",
|
|
164
|
-
},
|
|
165
|
-
],
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
export function buildServiceStartedGuidance(response) {
|
|
169
|
-
return buildServiceGuidance({
|
|
170
|
-
execution: response.execution,
|
|
171
|
-
capabilities: response.capabilities,
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
export function buildServiceReadModelGuidance(model) {
|
|
175
|
-
return buildServiceGuidance({
|
|
176
|
-
execution: model.execution,
|
|
177
|
-
capabilities: model.capabilities,
|
|
178
|
-
resultItems: model.result_items,
|
|
179
|
-
checkoutBindings: model.checkout_bindings,
|
|
180
|
-
deliveryBindings: model.delivery_bindings,
|
|
181
|
-
});
|
|
182
|
-
}
|
|
183
|
-
export function buildServiceInvokedGuidance(response, capabilities = []) {
|
|
184
|
-
return buildServiceGuidance({
|
|
185
|
-
execution: response.execution,
|
|
186
|
-
capabilities,
|
|
187
|
-
resultItems: response.result_items,
|
|
188
|
-
...(response.next_actions ? { backendNextActions: response.next_actions } : {}),
|
|
189
|
-
...(response.effective_quota ? { effectiveQuota: response.effective_quota } : {}),
|
|
190
|
-
providerCalled: response.provider_called,
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
|
-
export function buildServiceActionGuidance(action) {
|
|
194
|
-
const serviceExecutionID = action.service_execution_id;
|
|
195
|
-
return {
|
|
196
|
-
kind: "service_action_recorded",
|
|
197
|
-
summary: `service execution ${serviceExecutionID}: action ${action.action_type} recorded`,
|
|
198
|
-
state: {
|
|
199
|
-
service_execution_id: serviceExecutionID,
|
|
200
|
-
action_type: action.action_type,
|
|
201
|
-
status: action.status,
|
|
202
|
-
result_item_id: action.result_item_id,
|
|
203
|
-
},
|
|
204
|
-
next_actions: [
|
|
205
|
-
{
|
|
206
|
-
id: "inspect_service_execution",
|
|
207
|
-
label: "Read updated Service Execution state",
|
|
208
|
-
command: `itpay services next ${serviceExecutionID} --json`,
|
|
209
|
-
},
|
|
210
|
-
],
|
|
211
|
-
recovery: [
|
|
212
|
-
{
|
|
213
|
-
id: "timeline",
|
|
214
|
-
label: "Inspect full timeline",
|
|
215
|
-
command: `itpay services get ${serviceExecutionID}`,
|
|
216
|
-
},
|
|
217
|
-
],
|
|
218
|
-
};
|
|
219
|
-
}
|
|
220
|
-
export function buildServiceHandleGuidance(serviceExecutionID, checkoutCapabilityID) {
|
|
221
|
-
const actions = [
|
|
222
|
-
{
|
|
223
|
-
id: "inspect_service_execution",
|
|
224
|
-
label: "Read Service Execution state and capabilities",
|
|
225
|
-
command: `itpay services next ${serviceExecutionID} --json`,
|
|
226
|
-
},
|
|
227
|
-
];
|
|
228
|
-
if (checkoutCapabilityID) {
|
|
229
|
-
actions.push({
|
|
230
|
-
id: "checkout_service",
|
|
231
|
-
label: "Create checkout after human confirmation",
|
|
232
|
-
command: `itpay services checkout ${serviceExecutionID} --capability ${checkoutCapabilityID} --json`,
|
|
233
|
-
requires_human: true,
|
|
234
|
-
reason: "Inspect the Service Execution first; the CLI will request delivery contact only when the selected capability requires it.",
|
|
235
|
-
});
|
|
236
|
-
}
|
|
237
|
-
return {
|
|
238
|
-
kind: "service_execution_handle",
|
|
239
|
-
summary: `service execution ${serviceExecutionID}: inspect before invoking`,
|
|
240
|
-
state: { service_execution_id: serviceExecutionID },
|
|
241
|
-
next_actions: actions,
|
|
242
|
-
recovery: [],
|
|
243
|
-
};
|
|
244
|
-
}
|
|
245
70
|
export function errorRecoveryActions(error) {
|
|
246
71
|
if (!(error instanceof HttpError))
|
|
247
72
|
return [];
|
|
248
73
|
if (error.code === "agent_identity_required") {
|
|
249
|
-
return [
|
|
250
|
-
{
|
|
251
|
-
id: "inspect_agent_setup",
|
|
252
|
-
label: "Inspect supported Agent Type setup",
|
|
253
|
-
command: "itpay install --json",
|
|
254
|
-
},
|
|
255
|
-
];
|
|
74
|
+
return [{ id: "inspect_agent_setup", label: "Inspect supported Agent Type setup", command: "itpay install --json" }];
|
|
256
75
|
}
|
|
257
76
|
if (error.code === "agent_device_session_required") {
|
|
258
|
-
return [
|
|
259
|
-
{
|
|
77
|
+
return [{
|
|
260
78
|
id: "read_agent_session_rules",
|
|
261
79
|
label: "Read ItPay identity and session recovery rules",
|
|
262
80
|
command: "itpay skill show itpay --json",
|
|
263
81
|
reason: "The CLI already attempted one automatic session renewal; do not rotate identity or loop retries.",
|
|
264
|
-
}
|
|
265
|
-
];
|
|
82
|
+
}];
|
|
266
83
|
}
|
|
267
84
|
if (error.code === "quota_exhausted" || error.code === "checkout_required") {
|
|
268
|
-
return [
|
|
269
|
-
{
|
|
85
|
+
return [{
|
|
270
86
|
id: "inspect_service_execution",
|
|
271
87
|
label: "Inspect Service Execution before checkout",
|
|
272
88
|
command: "itpay services next <service_execution_id> --json",
|
|
273
|
-
}
|
|
274
|
-
];
|
|
89
|
+
}];
|
|
275
90
|
}
|
|
276
91
|
if (error.code === "cart_item_locked" || error.status === 409) {
|
|
277
92
|
return [
|
|
278
|
-
{
|
|
279
|
-
|
|
280
|
-
label: "Inspect the canonical server cart",
|
|
281
|
-
command: "itpay cart show",
|
|
282
|
-
},
|
|
283
|
-
{
|
|
284
|
-
id: "continue_checkout",
|
|
285
|
-
label: "Continue the last locally remembered checkout",
|
|
286
|
-
command: "itpay checkout",
|
|
287
|
-
},
|
|
93
|
+
{ id: "show_cart", label: "Inspect the canonical server cart", command: "itpay cart show" },
|
|
94
|
+
{ id: "continue_checkout", label: "Continue the last locally remembered checkout", command: "itpay checkout" },
|
|
288
95
|
{
|
|
289
96
|
id: "recover_service_execution",
|
|
290
97
|
label: "List recoverable Service Executions if the local handoff is missing",
|
|
@@ -293,22 +100,18 @@ export function errorRecoveryActions(error) {
|
|
|
293
100
|
];
|
|
294
101
|
}
|
|
295
102
|
if (error.status === 404) {
|
|
296
|
-
return [
|
|
297
|
-
{
|
|
103
|
+
return [{
|
|
298
104
|
id: "recover_service_executions",
|
|
299
105
|
label: "List visible Service Executions and follow their next instruction",
|
|
300
106
|
command: "itpay services list",
|
|
301
|
-
}
|
|
302
|
-
];
|
|
107
|
+
}];
|
|
303
108
|
}
|
|
304
109
|
if (error.status === 502 || error.status === 503 || error.status === 504) {
|
|
305
|
-
return [
|
|
306
|
-
{
|
|
110
|
+
return [{
|
|
307
111
|
id: "retry_after_backend_recovers",
|
|
308
112
|
label: "Retry after the selected official Backend is reachable",
|
|
309
113
|
command: "itpay readyz",
|
|
310
|
-
}
|
|
311
|
-
];
|
|
114
|
+
}];
|
|
312
115
|
}
|
|
313
116
|
return [];
|
|
314
117
|
}
|
|
@@ -323,207 +126,3 @@ export function printErrorRecovery(error, output) {
|
|
|
323
126
|
out(` ${action.command}\n`);
|
|
324
127
|
}
|
|
325
128
|
}
|
|
326
|
-
function buildServiceGuidance(input) {
|
|
327
|
-
const execution = input.execution;
|
|
328
|
-
const capabilities = input.capabilities ?? [];
|
|
329
|
-
const prePurchase = firstPrePurchaseCapability(capabilities);
|
|
330
|
-
const paid = firstPaidCapability(capabilities);
|
|
331
|
-
const resultItem = input.resultItems?.[0];
|
|
332
|
-
const checkoutID = input.checkoutBindings?.at(-1)?.checkout_id;
|
|
333
|
-
const delivery = input.deliveryBindings?.[0];
|
|
334
|
-
const deliveryMode = String(delivery?.redacted_summary?.delivery_mode ?? (delivery?.vault_artifact_id ? "vault_artifact" : ""));
|
|
335
|
-
const backendCheckout = input.backendNextActions?.find((action) => action.kind === "create_checkout");
|
|
336
|
-
const nextActions = [];
|
|
337
|
-
const recovery = [
|
|
338
|
-
{
|
|
339
|
-
id: "timeline",
|
|
340
|
-
label: "Inspect full timeline",
|
|
341
|
-
command: `itpay services get ${execution.service_execution_id}`,
|
|
342
|
-
},
|
|
343
|
-
];
|
|
344
|
-
if (isTerminalServiceExecutionStatus(execution.status)) {
|
|
345
|
-
// Terminal executions are inspectable, but no command may advance or replay them.
|
|
346
|
-
}
|
|
347
|
-
else if (deliveryMode === "agent_visible_result" && (input.resultItems?.length ?? 0) > 0) {
|
|
348
|
-
nextActions.push({
|
|
349
|
-
id: "use_agent_visible_result",
|
|
350
|
-
label: "Use the safe candidate list shown above",
|
|
351
|
-
command: `itpay services next ${execution.service_execution_id} --json`,
|
|
352
|
-
reason: "This result is already visible to the agent. Do not call services read-result; that command is only for Vault deliveries authorized by a human.",
|
|
353
|
-
});
|
|
354
|
-
}
|
|
355
|
-
else if (execution.status === "completed" || execution.next_action === "completed") {
|
|
356
|
-
nextActions.push({
|
|
357
|
-
id: "inspect_order_or_grant",
|
|
358
|
-
label: "Inspect order, claim, or grant from the checkout/order owner",
|
|
359
|
-
command: "itpay orders --limit 20",
|
|
360
|
-
requires_human: true,
|
|
361
|
-
reason: "Delivery visibility is controlled by the human account and grant flow.",
|
|
362
|
-
});
|
|
363
|
-
}
|
|
364
|
-
else if (execution.phase === "delivery" || execution.next_action === "view_delivery") {
|
|
365
|
-
const grantStatus = String(delivery?.grant_status ?? "");
|
|
366
|
-
if (grantStatus === "active") {
|
|
367
|
-
nextActions.push({
|
|
368
|
-
id: "read_granted_result",
|
|
369
|
-
label: "Read the human-granted service result",
|
|
370
|
-
command: `itpay services read-result ${execution.service_execution_id}`,
|
|
371
|
-
reason: "The human granted temporary agent access to this delivery.",
|
|
372
|
-
});
|
|
373
|
-
}
|
|
374
|
-
else {
|
|
375
|
-
nextActions.push({
|
|
376
|
-
id: grantStatus === "expired" ? "ask_human_to_reauthorize" : "wait_for_human_agent_grant",
|
|
377
|
-
label: grantStatus === "expired" ? "Ask the human to authorize AI access again" : "Wait for human AI-access authorization",
|
|
378
|
-
command: `itpay services get ${execution.service_execution_id}`,
|
|
379
|
-
requires_human: true,
|
|
380
|
-
reason: grantStatus === "expired"
|
|
381
|
-
? "The 15 minute human grant expired."
|
|
382
|
-
: "The human must approve AI access on the Credential page.",
|
|
383
|
-
});
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
else if (execution.next_action === "pay_checkout" || execution.status === "checkout_pending") {
|
|
387
|
-
nextActions.push({
|
|
388
|
-
id: "open_existing_checkout",
|
|
389
|
-
label: "Open the existing ItPay checkout handoff",
|
|
390
|
-
command: `itpay services checkout ${execution.service_execution_id} --resume --json`,
|
|
391
|
-
requires_human: true,
|
|
392
|
-
reason: checkoutID
|
|
393
|
-
? `Checkout ${checkoutID} already exists; reissue a short-lived handoff without creating another checkout.`
|
|
394
|
-
: "Recover the existing checkout handoff from Service Execution owner facts.",
|
|
395
|
-
});
|
|
396
|
-
}
|
|
397
|
-
else if (execution.checkout_required || execution.next_action === "create_checkout") {
|
|
398
|
-
const capabilityID = backendCheckout?.capability_id ?? paid?.capability_id ?? input.checkoutCapabilityID ?? execution.current_capability_id;
|
|
399
|
-
if (capabilityID) {
|
|
400
|
-
const checkoutCapability = capabilities.find((capability) => capability.capability_id === capabilityID);
|
|
401
|
-
const emailRequired = checkoutCapability?.delivery_email_required === true;
|
|
402
|
-
nextActions.push({
|
|
403
|
-
id: "checkout_service",
|
|
404
|
-
label: "Create ItPay checkout for the paid service capability",
|
|
405
|
-
command: `itpay services checkout ${execution.service_execution_id} --capability ${capabilityID}${emailRequired ? " --email <email>" : ""} --json`,
|
|
406
|
-
requires_human: true,
|
|
407
|
-
reason: emailRequired
|
|
408
|
-
? deliveryEmailGuidance(checkoutCapability?.delivery_email_purpose)
|
|
409
|
-
: "This capability returns an agent-visible result after payment and does not require a delivery email.",
|
|
410
|
-
});
|
|
411
|
-
}
|
|
412
|
-
else {
|
|
413
|
-
nextActions.push({
|
|
414
|
-
id: "inspect_capabilities",
|
|
415
|
-
label: "Inspect capabilities before checkout",
|
|
416
|
-
command: `itpay services get ${execution.service_execution_id}`,
|
|
417
|
-
});
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
else if ((input.providerCalled || execution.next_action === "select_candidate") && (input.resultItems?.length ?? 0) === 0) {
|
|
421
|
-
// Terminal empty result: a later explicit human request starts a new flow.
|
|
422
|
-
}
|
|
423
|
-
else if (needsHumanSelection(execution, resultItem)) {
|
|
424
|
-
nextActions.push({
|
|
425
|
-
id: "select_result_item",
|
|
426
|
-
label: "Ask the human to select a result item, then submit the selection",
|
|
427
|
-
command: `itpay services action ${execution.service_execution_id} --action select_candidate --actor-type human --status approved --candidate <rank>`,
|
|
428
|
-
requires_human: true,
|
|
429
|
-
reason: "Do not choose a candidate without explicit human confirmation.",
|
|
430
|
-
});
|
|
431
|
-
}
|
|
432
|
-
else if (prePurchase) {
|
|
433
|
-
const action = {
|
|
434
|
-
id: "invoke_capability",
|
|
435
|
-
label: `Invoke ${prePurchase.capability_id}`,
|
|
436
|
-
command: `itpay services invoke ${execution.service_execution_id} --capability ${prePurchase.capability_id} --input key=value --json`,
|
|
437
|
-
};
|
|
438
|
-
if (prePurchase.free_quota_limit) {
|
|
439
|
-
action.reason = `One keyword per execution. Free quota limit: ${prePurchase.free_quota_limit} per ${prePurchase.quota_subject || "subject"}.`;
|
|
440
|
-
}
|
|
441
|
-
nextActions.push(action);
|
|
442
|
-
}
|
|
443
|
-
else {
|
|
444
|
-
nextActions.push({
|
|
445
|
-
id: "inspect_service_execution",
|
|
446
|
-
label: "Read Service Execution state",
|
|
447
|
-
command: `itpay services next ${execution.service_execution_id} --json`,
|
|
448
|
-
});
|
|
449
|
-
}
|
|
450
|
-
return {
|
|
451
|
-
kind: "service_execution",
|
|
452
|
-
summary: `service execution ${execution.service_execution_id}: ${execution.status}/${execution.phase}${input.effectiveQuota ? `, quota ${input.effectiveQuota.remaining}/${input.effectiveQuota.limit}` : ""}`,
|
|
453
|
-
state: {
|
|
454
|
-
service_execution_id: execution.service_execution_id,
|
|
455
|
-
service_id: execution.service_id,
|
|
456
|
-
status: execution.status,
|
|
457
|
-
phase: execution.phase,
|
|
458
|
-
current_capability_id: execution.current_capability_id,
|
|
459
|
-
checkout_required: execution.checkout_required,
|
|
460
|
-
next_action: execution.next_action,
|
|
461
|
-
delivery: delivery
|
|
462
|
-
? {
|
|
463
|
-
status: delivery.status,
|
|
464
|
-
delivery_mode: deliveryMode || undefined,
|
|
465
|
-
vault_artifact_id: delivery.vault_artifact_id,
|
|
466
|
-
vault_status: delivery.vault_status,
|
|
467
|
-
vault_payload_state: delivery.vault_payload_state,
|
|
468
|
-
reveal_status: delivery.reveal_status,
|
|
469
|
-
grant_status: delivery.grant_status ?? "missing",
|
|
470
|
-
grant_expires_at: delivery.grant_expires_at,
|
|
471
|
-
}
|
|
472
|
-
: undefined,
|
|
473
|
-
capabilities: capabilities.map((capability) => ({
|
|
474
|
-
capability_id: capability.capability_id,
|
|
475
|
-
agent_visible: capability.agent_visible,
|
|
476
|
-
requires_payment: capability.requires_payment,
|
|
477
|
-
vault_required: capability.vault_required,
|
|
478
|
-
delivery_email_required: capability.delivery_email_required,
|
|
479
|
-
delivery_email_purpose: capability.delivery_email_purpose,
|
|
480
|
-
price_amount_minor: capability.price_amount_minor,
|
|
481
|
-
price_currency: capability.price_currency,
|
|
482
|
-
free_quota_limit: capability.free_quota_limit,
|
|
483
|
-
})),
|
|
484
|
-
result_items: (input.resultItems ?? []).map((item) => ({
|
|
485
|
-
result_item_id: item.service_capability_result_item_id,
|
|
486
|
-
rank: item.rank,
|
|
487
|
-
display_title: item.display_title,
|
|
488
|
-
safe_payload: item.safe_payload,
|
|
489
|
-
})),
|
|
490
|
-
effective_quota: input.effectiveQuota,
|
|
491
|
-
},
|
|
492
|
-
next_actions: nextActions,
|
|
493
|
-
recovery,
|
|
494
|
-
...(input.resultItems?.length
|
|
495
|
-
? { visible_results: input.resultItems.map((item) => ({ rank: item.rank, title: item.display_title, safe_payload: item.safe_payload })) }
|
|
496
|
-
: {}),
|
|
497
|
-
};
|
|
498
|
-
}
|
|
499
|
-
function deliveryEmailGuidance(purpose) {
|
|
500
|
-
switch (purpose) {
|
|
501
|
-
case "receipt":
|
|
502
|
-
return "Ask the human for their email. It is used to send the order receipt; never invent or substitute an address.";
|
|
503
|
-
case "claim":
|
|
504
|
-
return "Ask the human for their email. It is used to send the protected result claim link; never invent or substitute an address.";
|
|
505
|
-
case "receipt_and_claim":
|
|
506
|
-
return "Ask the human for their email. It is used to send the order receipt and protected result claim link; never invent or substitute an address.";
|
|
507
|
-
default:
|
|
508
|
-
return "Ask the human for the required email and state only the Backend-declared purpose; never invent or substitute an address.";
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
function firstPrePurchaseCapability(capabilities) {
|
|
512
|
-
return capabilities.find((capability) => capability.agent_visible && !capability.requires_payment)
|
|
513
|
-
?? capabilities.find((capability) => capability.agent_visible);
|
|
514
|
-
}
|
|
515
|
-
function firstPaidCapability(capabilities) {
|
|
516
|
-
return (capabilities.find((capability) => capability.requires_payment && capability.vault_required) ??
|
|
517
|
-
capabilities.find((capability) => capability.requires_payment));
|
|
518
|
-
}
|
|
519
|
-
function needsHumanSelection(execution, resultItem) {
|
|
520
|
-
if (execution.phase !== "pre_purchase")
|
|
521
|
-
return false;
|
|
522
|
-
return execution.next_action === "select_candidate" || execution.next_action === "human_action_required" || resultItem !== undefined;
|
|
523
|
-
}
|
|
524
|
-
function latestServiceLine(cart) {
|
|
525
|
-
return [...cart.items].reverse().find((item) => item.service_execution_id);
|
|
526
|
-
}
|
|
527
|
-
function lineID(line) {
|
|
528
|
-
return line.cart_item_id ?? line.line_item_id ?? line.checkout_item_id ?? "<unknown_line>";
|
|
529
|
-
}
|
|
@@ -25,7 +25,7 @@ export function runInstall(target, options = {}) {
|
|
|
25
25
|
writeCommandEnvelope({
|
|
26
26
|
status: "install_targets",
|
|
27
27
|
result: { agent_types: agentTypes },
|
|
28
|
-
instruction: "
|
|
28
|
+
instruction: "识别当前真实运行平台,从 result.agent_types 选择对应 agent_type,并由 Agent 自行运行 itpay install <agent_type> --json;不要让用户运行命令,也不要临时更换 Agent Type。",
|
|
29
29
|
next: null,
|
|
30
30
|
recovery: [{ command: "itpay docs show install-and-setup", reason: "查看安装与环境说明" }],
|
|
31
31
|
}, {
|
|
@@ -19,13 +19,13 @@ function orderEnvelope(order, delivery, lockedRefund) {
|
|
|
19
19
|
let instruction = "订单状态已读取;当前没有可用交付入口。";
|
|
20
20
|
let next = null;
|
|
21
21
|
if (lockedRefund) {
|
|
22
|
-
instruction = "
|
|
22
|
+
instruction = "告诉用户退款处理中,原交付已按政策冻结。然后读取同一退款的权威状态;Agent 不读取交付、不创建授权或重复申请退款。";
|
|
23
23
|
if (!refundTerminal) {
|
|
24
24
|
next = { command: `itpay refund get ${lockedRefund.refund_request_id} --json`, reason: "读取退款的服务器状态" };
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
else if (delivery?.service_execution_id) {
|
|
28
|
-
instruction = "
|
|
28
|
+
instruction = "告诉用户订单已经找到并说明当前交付状态。然后使用返回的读取入口;Agent 不向用户提及 delivery_mode,也不从订单摘要猜测受保护内容。";
|
|
29
29
|
next = { command: `itpay services next ${delivery.service_execution_id} --json`, reason: "读取交付状态" };
|
|
30
30
|
}
|
|
31
31
|
else if (order.status === "failed") {
|
|
@@ -42,7 +42,6 @@ export async function runListOrders(backend, config, options) {
|
|
|
42
42
|
}
|
|
43
43
|
throw error;
|
|
44
44
|
}
|
|
45
|
-
const accountSession = "orders" in response;
|
|
46
45
|
const orders = "orders" in response
|
|
47
46
|
? response.orders.map((order) => ({
|
|
48
47
|
order_id: order.order_id,
|
|
@@ -69,9 +68,7 @@ export async function runListOrders(backend, config, options) {
|
|
|
69
68
|
: "当前账号没有符合条件的订单;不要猜测订单或自动开始购买。",
|
|
70
69
|
next: "items" in response && response.next_cursor
|
|
71
70
|
? { command: ordersPageCommand(response.next_cursor, options), reason: "读取下一页订单摘要" }
|
|
72
|
-
:
|
|
73
|
-
? { command: `itpay order ${latest.order_id} --json`, reason: "读取网页登录账号的最新订单" }
|
|
74
|
-
: null,
|
|
71
|
+
: null,
|
|
75
72
|
recovery: [],
|
|
76
73
|
};
|
|
77
74
|
writeCommandEnvelope(envelope, {
|
|
@@ -8,8 +8,8 @@ export async function runReadyz(backend, options = {}) {
|
|
|
8
8
|
status: response.status,
|
|
9
9
|
result: { backend: "available", backend_url: backendURL, environment, ...(options.agentType ? { agent_type: options.agentType } : {}) },
|
|
10
10
|
instruction: environment === "development"
|
|
11
|
-
? "ItPay dev
|
|
12
|
-
: "ItPay
|
|
11
|
+
? "ItPay dev 可用。先完整读取内置 Skill,再根据用户意图选择新服务、已购内容、订单或退款入口;后续必须执行返回的完整命令并保持同一 dev Backend。"
|
|
12
|
+
: "ItPay 可用。先完整读取内置 Skill,再根据用户意图选择新服务、已购内容、订单或退款入口;不要默认开始购买。",
|
|
13
13
|
next: { command: "itpay skill show itpay --json", reason: "加载完整操作与安全规则" },
|
|
14
14
|
recovery: [],
|
|
15
15
|
}, options);
|