@itpay/cli 2.1.6 → 2.1.7

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.
@@ -57,18 +57,28 @@ const WORKFLOW_STEP_GUIDANCE = {
57
57
  input: { meaning: "输入校验", hint: "对照服务声明的输入契约补齐字段后重新发起" },
58
58
  quota: { meaning: "额度检查", hint: "免费额度或限流未通过;登录或稍后重试" },
59
59
  geo: { meaning: "位置解析", hint: "检查 origin/destination 是否为真实地名;可附 origin_city 或坐标对象提示" },
60
+ geo_confirm: { meaning: "确认后位置解析", hint: "用户确认的地点仍未解析成功;重新执行并让用户从候选项中按名称+坐标选择" },
61
+ resolved: { meaning: "位置解析复核", hint: "位置解析未满足继续条件;检查 origin/destination 后新建执行重试" },
62
+ resolved_after_confirm: { meaning: "位置确认复核", hint: "确认后的位置仍未通过复核;重新执行并核对用户所选候选项" },
60
63
  search: { meaning: "供应商车次检索", hint: "最常见是字段名错误(必须是 travel_date)或站名不存在;按 itpay docs show rail-booking 核对输入" },
61
64
  catalog: { meaning: "可行车次计算", hint: "位置已解析但无可行车次;换日期或换站点重试" },
62
65
  recommend: { meaning: "方案推荐", hint: "候选集无法产出推荐;放宽条件或换日期重试" },
63
66
  delivery: { meaning: "交付", hint: "结果组装失败;稍后重试或联系运营" },
64
67
  };
65
- function failedWorkflowStep(steps) {
68
+ function failedWorkflowStep(steps, errorCode) {
66
69
  if (!steps)
67
70
  return undefined;
68
71
  for (const [step, status] of Object.entries(steps)) {
69
72
  if (status === "failure" && step !== "failure")
70
73
  return step;
71
74
  }
75
+ // Only a backend-recorded condition_unmet proves a false branch routed to failure.
76
+ if (errorCode === "condition_unmet") {
77
+ for (const [step, status] of Object.entries(steps)) {
78
+ if (status === "false" && step !== "failure")
79
+ return step;
80
+ }
81
+ }
72
82
  return undefined;
73
83
  }
74
84
  export async function runServicesStart(backend, serviceID, options = {}) {
@@ -996,11 +1006,44 @@ function servicesNextEnvelope(model) {
996
1006
  };
997
1007
  }
998
1008
  if (state === "human_action" && model.workflow?.human_action) {
1009
+ const action = model.workflow.human_action;
1010
+ const requiredFields = requiredInputFields(action.input_schema);
1011
+ const rawPlaces = action.context?.places;
1012
+ // Only the location-confirmation action carries origin/destination places;
1013
+ // every other human action keeps the generic envelope.
1014
+ const isLocationConfirmation = !!rawPlaces && typeof rawPlaces === "object" &&
1015
+ ("origin" in rawPlaces || "destination" in rawPlaces);
1016
+ if (isLocationConfirmation) {
1017
+ const places = rawPlaces;
1018
+ const sides = ["origin", "destination"].map((side) => {
1019
+ const place = places[side];
1020
+ const candidates = Array.isArray(place?.resolution_candidates) ? place.resolution_candidates : [];
1021
+ const name = (item) => item.poi_name ?? item.query ?? item.formatted_address;
1022
+ return {
1023
+ side,
1024
+ status: place?.resolution_status,
1025
+ ...(place?.resolution_status === "resolved"
1026
+ ? { resolved_place: { name: name(place), location: place.location } }
1027
+ : {}),
1028
+ ...(candidates.length
1029
+ ? { candidates: candidates.slice(0, 5).map((item) => ({ name: name(item), location: item.location })) }
1030
+ : {}),
1031
+ };
1032
+ });
1033
+ return {
1034
+ status: "confirmation_required",
1035
+ result: { service_execution_id: id, service_id: execution.service_id, human_action: action,
1036
+ required_fields: requiredFields, sides },
1037
+ instruction: "向用户展示 sides 中 status=needs_confirmation 一端的候选(名称+坐标),请用户选定后按 required_fields 逐项各传一个 --input:名称取候选 name,坐标取候选 location 的 [lng,lat];已 resolved 的一端把其 resolved_place 原样填入。继续同一执行,不重新查询;这一步不是购买确认。",
1038
+ next: { command: `itpay services action ${id} --action ${action.action_type} --actor-type human --status approved${requiredFields.map((field) => ` --input ${field}=<值>`).join("")} --json`, reason: "用户确认后继续当前查询" },
1039
+ recovery: [],
1040
+ };
1041
+ }
999
1042
  return {
1000
1043
  status: "confirmation_required",
1001
- result: { service_execution_id: id, service_id: execution.service_id, human_action: model.workflow.human_action },
1002
- instruction: "请展示待确认的位置,请用户明确确认后,按 input_schema 填写 --input 字段。继续同一执行,不重新查询;这一步不是购买确认。",
1003
- next: { command: `itpay services action ${id} --action ${model.workflow.human_action.action_type} --actor-type human --status approved --input <key=value> --json`, reason: "用户确认后继续当前查询" },
1044
+ result: { service_execution_id: id, service_id: execution.service_id, human_action: action },
1045
+ instruction: "请展示待确认的内容,请用户明确确认后,按 input_schema 填写 --input 字段。继续同一执行,不重新查询;这一步不是购买确认。",
1046
+ next: { command: `itpay services action ${id} --action ${action.action_type} --actor-type human --status approved${requiredFields.map((field) => ` --input ${field}=<值>`).join("")} --json`, reason: "用户确认后继续当前查询" },
1004
1047
  recovery: [],
1005
1048
  };
1006
1049
  }
@@ -1011,7 +1054,7 @@ function servicesNextEnvelope(model) {
1011
1054
  if (state === "input_required")
1012
1055
  command = `itpay services run ${execution.service_id} --execution ${id} --input-json <file> --json`;
1013
1056
  const guidance = railServiceGuidance(execution.service_id);
1014
- const failedStep = recovery ? failedWorkflowStep(model.workflow?.steps) : undefined;
1057
+ const failedStep = recovery ? failedWorkflowStep(model.workflow?.steps, model.workflow?.error_code) : undefined;
1015
1058
  const failedStepGuidance = failedStep ? WORKFLOW_STEP_GUIDANCE[failedStep] : undefined;
1016
1059
  const failedInvocation = recovery
1017
1060
  ? [...model.provider_invocations].reverse().find((item) => typeof item.status === "string" && item.status.startsWith("failed"))
@@ -15,7 +15,7 @@ import { OperationJournal } from "./operation_journal.js";
15
15
  export const DEFAULT_BASE_URL = "https://app.itpay.ai";
16
16
  export const DEV_BASE_URL = "https://dev.itpay.ai";
17
17
  export const SANDBOX_BASE_URL = "https://sandbox.itpay.ai";
18
- export const CLI_VERSION = "2.1.6";
18
+ export const CLI_VERSION = "2.1.7";
19
19
  export const API_CONTRACT_REVISION = "sha256:42659989d533d5a43c4ab92eb2455bcbbc6456e799fa4c2b6587de77f06b95f7";
20
20
  const CART_SESSION_DEFAULT_DIR = ".itpay-v3";
21
21
  const CART_SESSION_FILENAME = "cart.json";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itpay/cli",
3
- "version": "2.1.6",
3
+ "version": "2.1.7",
4
4
  "description": "The ItPay CLI for services, orders, and human-authorized purchased content.",
5
5
  "type": "module",
6
6
  "bin": {