@delexec/ops 0.1.0 → 0.1.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.
package/README.md CHANGED
@@ -1,3 +1,19 @@
1
1
  # @delexec/ops
2
2
 
3
3
  Unified operator CLI for delegated execution clients.
4
+
5
+ ## Paid Hotline Drafts
6
+
7
+ Responder operators can declare a fixed-price Hotline while creating the local registration draft:
8
+
9
+ ```bash
10
+ delexec-ops responder add-hotline \
11
+ --type process \
12
+ --hotline-id opc.summary.v1 \
13
+ --cmd "node worker.js" \
14
+ --fixed-price-cents 50 \
15
+ --currency PTS \
16
+ --billing-disclosure-url "https://callanything.xyz/marketplace/responders/opc-summary"
17
+ ```
18
+
19
+ The generated draft keeps the `pricing_hint`, and `delexec-ops submit-review` submits it to the connected platform catalog.
package/README.zh-CN.md CHANGED
@@ -4,3 +4,19 @@
4
4
  > 说明:中文文档为准。
5
5
 
6
6
  面向委托执行客户端的统一运维 CLI。
7
+
8
+ ## 付费 Hotline Draft
9
+
10
+ Responder operator 可以在创建本地 registration draft 时声明固定价格:
11
+
12
+ ```bash
13
+ delexec-ops responder add-hotline \
14
+ --type process \
15
+ --hotline-id opc.summary.v1 \
16
+ --cmd "node worker.js" \
17
+ --fixed-price-cents 50 \
18
+ --currency PTS \
19
+ --billing-disclosure-url "https://callanything.xyz/marketplace/responders/opc-summary"
20
+ ```
21
+
22
+ 生成的 draft 会保留 `pricing_hint`,随后 `delexec-ops submit-review` 会把该价格信息提交到已连接的 platform catalog。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@delexec/ops",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Unified operator CLI for delegated execution clients",
5
5
  "type": "module",
6
6
  "bin": {
package/src/cli.js CHANGED
@@ -29,6 +29,10 @@ const DEFAULT_CONSOLE_HOST = "127.0.0.1";
29
29
  const DEFAULT_CONSOLE_PORT = 4173;
30
30
  const DEFAULT_UI_READY_TIMEOUT_MS = 120000;
31
31
  const OPS_SESSION_HEADER = "X-Ops-Session";
32
+ const FIXED_PRICE_MODEL = "fixed_price";
33
+ const DEFAULT_PRICING_CURRENCY = "PTS";
34
+ const DEFAULT_TRUST_TIER = "untrusted";
35
+ const TRUST_TIERS = Object.freeze(["untrusted", "trusted", "verified"]);
32
36
 
33
37
  function getOpsSessionFile() {
34
38
  return path.join(ensureOpsDirectories(), "run", "session.json");
@@ -44,7 +48,7 @@ function usage() {
44
48
  delexec-ops mcp spec
45
49
  delexec-ops auth register --email <email> [--local] [--platform <url>]
46
50
  delexec-ops enable-responder [--responder-id <id>] [--display-name <name>]
47
- delexec-ops add-hotline --type <process|http> --hotline-id <id> [--cmd <command> | --url <url>] [--cwd <path>] [--env KEY=VALUE]
51
+ delexec-ops add-hotline --type <process|http> --hotline-id <id> [--cmd <command> | --url <url>] [--cwd <path>] [--env KEY=VALUE] [--fixed-price-cents <amount>] [--currency <code>] [--billing-disclosure-url <url>]
48
52
  delexec-ops attach-project --project-path <path> [--project-name <name>] [--project-description <text>] [--hotline-id <id>] [--cmd <command> | --url <url>] [--cwd <path>] [--env KEY=VALUE] [--task-type <type>] [--capability <capability>]
49
53
  delexec-ops add-example-hotline
50
54
  delexec-ops remove-hotline --hotline-id <id>
@@ -249,6 +253,44 @@ function parsePort(value, fallback) {
249
253
  return Math.trunc(parsed);
250
254
  }
251
255
 
256
+ function parseOptionalNonNegativeInteger(value, fieldName) {
257
+ if (value === undefined || value === null || value === false) {
258
+ return null;
259
+ }
260
+ const parsed = Number(value);
261
+ if (!Number.isSafeInteger(parsed) || parsed < 0) {
262
+ throw new Error(`${fieldName}_must_be_non_negative_integer`);
263
+ }
264
+ return parsed;
265
+ }
266
+
267
+ function parsePricingHint(args = {}) {
268
+ const fixedPriceCents = parseOptionalNonNegativeInteger(args["fixed-price-cents"], "fixed_price_cents");
269
+ if (fixedPriceCents === null) {
270
+ return undefined;
271
+ }
272
+ const maxTotalCents = parseOptionalNonNegativeInteger(args["max-total-cents"], "max_total_cents") ?? fixedPriceCents;
273
+ if (maxTotalCents < fixedPriceCents) {
274
+ throw new Error("max_total_cents_must_be_greater_than_or_equal_to_fixed_price_cents");
275
+ }
276
+ const trustTier = String(args["trust-tier"] || DEFAULT_TRUST_TIER).trim() || DEFAULT_TRUST_TIER;
277
+ if (!TRUST_TIERS.includes(trustTier)) {
278
+ throw new Error("trust_tier_unsupported");
279
+ }
280
+ const pricingHint = {
281
+ pricing_model: FIXED_PRICE_MODEL,
282
+ currency: String(args.currency || DEFAULT_PRICING_CURRENCY).trim() || DEFAULT_PRICING_CURRENCY,
283
+ fixed_price_cents: fixedPriceCents,
284
+ max_total_cents: maxTotalCents,
285
+ trust_tier: trustTier
286
+ };
287
+ const billingDisclosureUrl = String(args["billing-disclosure-url"] || "").trim();
288
+ if (billingDisclosureUrl) {
289
+ pricingHint.billing_disclosure_url = billingDisclosureUrl;
290
+ }
291
+ return pricingHint;
292
+ }
293
+
252
294
  function resolveUiConfig(args = {}) {
253
295
  return {
254
296
  host: String(args["ui-host"] || args.host || process.env.DELEXEC_OPS_UI_HOST || DEFAULT_CONSOLE_HOST).trim() || DEFAULT_CONSOLE_HOST,
@@ -473,6 +515,7 @@ function parseHotlineDefinition(args) {
473
515
  soft_timeout_s: Number(args["soft-timeout-s"] || 60),
474
516
  hard_timeout_s: Number(args["hard-timeout-s"] || 180)
475
517
  },
518
+ pricing_hint: parsePricingHint(args),
476
519
  review_status: "local_only",
477
520
  submitted_for_review: false
478
521
  };
package/src/config.js CHANGED
@@ -1027,6 +1027,7 @@ export function buildHotlineRegistrationDraft(state, definition, existingDraft =
1027
1027
  "recommended_for",
1028
1028
  "not_recommended_for",
1029
1029
  "limitations",
1030
+ "pricing_hint",
1030
1031
  "contact_email",
1031
1032
  "support_email"
1032
1033
  ]
@@ -1050,6 +1051,7 @@ export function buildHotlineRegistrationDraft(state, definition, existingDraft =
1050
1051
  recommended_for: Array.isArray(profile.recommended_for) ? profile.recommended_for : [],
1051
1052
  not_recommended_for: Array.isArray(profile.not_recommended_for) ? profile.not_recommended_for : [],
1052
1053
  limitations: Array.isArray(profile.limitations) ? profile.limitations : [],
1054
+ pricing_hint: definition.pricing_hint === undefined ? null : definition.pricing_hint,
1053
1055
  contact_email: fallbackContactEmail,
1054
1056
  support_email: null
1055
1057
  };
@@ -1064,7 +1066,13 @@ export function buildHotlineRegistrationDraft(state, definition, existingDraft =
1064
1066
  display_name: reusableDraft?.display_name || definition.display_name || definition.hotline_id,
1065
1067
  task_types: taskTypes,
1066
1068
  capabilities,
1067
- tags
1069
+ tags,
1070
+ pricing_hint:
1071
+ definition.pricing_hint === undefined
1072
+ ? reusableDraft?.pricing_hint === undefined
1073
+ ? generated.pricing_hint
1074
+ : reusableDraft.pricing_hint
1075
+ : definition.pricing_hint
1068
1076
  };
1069
1077
  }
1070
1078
 
@@ -1171,6 +1179,7 @@ export function buildHotlineOnboardingBody(state, hotline, responderIdentity) {
1171
1179
  recommended_for: Array.isArray(source.recommended_for) ? source.recommended_for : null,
1172
1180
  not_recommended_for: Array.isArray(source.not_recommended_for) ? source.not_recommended_for : null,
1173
1181
  limitations: Array.isArray(source.limitations) ? source.limitations : null,
1182
+ pricing_hint: source.pricing_hint === undefined ? undefined : source.pricing_hint,
1174
1183
  input_summary: source.input_summary || null,
1175
1184
  output_summary: source.output_summary || null,
1176
1185
  contact_email: source.contact_email || state?.config?.caller?.contact_email || null,