@dazitech/cli 3.1.0 → 3.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.
Files changed (65) hide show
  1. package/README.md +1 -1
  2. package/dist/clis/dazi-app.js +2 -2
  3. package/dist/clis/dazi-flow.js +2 -2
  4. package/dist/clis/dazi-onto.js +318 -40
  5. package/dist/clis/dazi.js +407 -185
  6. package/dist/docs/flow/flow-project-guide.md +1 -1
  7. package/dist/docs/guides/cli-reference.md +16 -3
  8. package/dist/docs/guides/troubleshooting.md +1 -1
  9. package/dist/docs/index.json +1 -13
  10. package/dist/docs/onto/dazi_script_sdk_reference.md +1 -1
  11. package/dist/docs/onto/dazi_script_seed_data_guide.md +1 -1
  12. package/dist/docs/onto/function-guide.md +6 -6
  13. package/dist/docs/onto//346/234/254/344/275/223/345/210/206/347/261/273/350/247/204/345/210/222/344/270/216SDK/346/211/251/345/261/225/346/226/271/346/241/210.md +169 -169
  14. package/dist/docs/onto//346/234/254/344/275/223/345/221/275/345/220/215/350/247/204/350/214/203_/347/211/251/347/220/206/350/241/250Cube/344/270/216/345/257/271/350/261/241.md +3 -2
  15. package/dist/docs/onto//346/234/254/344/275/223/345/274/200/345/217/221/344/274/230/345/214/226/346/200/273/347/273/223.md +257 -242
  16. package/dist/docs/onto//346/234/254/344/275/223/350/204/232/346/234/254/347/274/226/345/206/231/346/214/207/345/215/227.md +12 -12
  17. package/dist/docs/onto//346/234/254/344/275/223/350/247/204/345/210/222/346/214/207/345/215/227.md +14 -13
  18. package/dist/docs/onto//350/204/232/346/234/254/350/277/220/350/241/214/345/270/270/350/247/201/351/224/231/350/257/257/345/244/204/347/220/206.md +70 -15
  19. package/dist/examples/index.json +222 -6
  20. package/dist/examples/onto/README.md +34 -36
  21. package/dist/examples/onto/_templates/onto_preflight.ps1 +84 -0
  22. package/dist/examples/onto/index.json +53 -0
  23. package/dist/examples/onto/index.yaml +29 -0
  24. package/dist/examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/README.md +23 -0
  25. package/dist/examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/functions/save_test_arguments.ps1 +12 -11
  26. package/dist/{docs/onto → examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/plans}//350/247/204/345/210/222/347/244/272/344/276/213_/345/210/251/346/266/246/345/210/206/346/236/220/346/234/254/344/275/223/346/226/271/346/241/210.md +4 -4
  27. package/dist/examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/setup/profit_category_mount.py +1 -1
  28. package/dist/examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/setup/profit_ontology_init.py +1 -1
  29. package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/README.md +24 -0
  30. package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/equip_ops_fn_availability_analysis.py +84 -0
  31. package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/equip_ops_fn_downtime_breakdown.py +119 -0
  32. package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/equip_ops_fn_energy_intensity.py +98 -0
  33. package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/equip_ops_fn_get_summary.py +125 -0
  34. package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/equip_ops_fn_maintenance_compliance.py +77 -0
  35. package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/equip_ops_fn_mom_analysis.py +118 -0
  36. package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/equip_ops_fn_oee_analysis.py +126 -0
  37. package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/equip_ops_fn_plan_vs_actual.py +105 -0
  38. package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/equip_ops_fn_top_fault_equipment.py +104 -0
  39. package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/equip_ops_fn_unit_comparison.py +120 -0
  40. package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/equip_ops_fn_yoy_analysis.py +115 -0
  41. package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/save_test_arguments.ps1 +42 -0
  42. package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/test_arguments/equip_ops.fn.availability_analysis.json +7 -0
  43. package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/test_arguments/equip_ops.fn.downtime_breakdown.json +8 -0
  44. package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/test_arguments/equip_ops.fn.energy_intensity.json +8 -0
  45. package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/test_arguments/equip_ops.fn.get_summary.json +7 -0
  46. package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/test_arguments/equip_ops.fn.maintenance_compliance.json +7 -0
  47. package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/test_arguments/equip_ops.fn.mom_analysis.json +8 -0
  48. package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/test_arguments/equip_ops.fn.oee_analysis.json +8 -0
  49. package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/test_arguments/equip_ops.fn.plan_vs_actual.json +8 -0
  50. package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/test_arguments/equip_ops.fn.top_fault_equipment.json +8 -0
  51. package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/test_arguments/equip_ops.fn.unit_comparison.json +8 -0
  52. package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/test_arguments/equip_ops.fn.yoy_analysis.json +8 -0
  53. package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/plans//345/214/226/345/267/245/350/256/276/345/244/207/350/277/220/350/220/245/345/210/206/346/236/220/346/234/254/344/275/223/346/226/271/346/241/210.md +735 -0
  54. package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/setup/equip_ops_category_mount.py +106 -0
  55. package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/setup/equip_ops_ontology_init.py +1077 -0
  56. package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/setup/equip_ops_seed_data.py +552 -0
  57. package/dist/examples/onto//351/224/200/345/224/256/347/244/272/344/276/213/README.md +23 -0
  58. package/dist/examples/onto//351/224/200/345/224/256/347/244/272/344/276/213/functions/save_test_arguments.ps1 +13 -12
  59. package/dist/{docs/onto → examples/onto//351/224/200/345/224/256/347/244/272/344/276/213/plans}//350/247/204/345/210/222/347/244/272/344/276/213_/344/272/247/345/223/201/351/224/200/345/224/256/346/234/254/344/275/223/350/247/204/345/210/222/346/226/271/346/241/210.md +2 -2
  60. package/dist/examples/onto//351/224/200/345/224/256/347/244/272/344/276/213/setup/sales_category_mount.py +1 -1
  61. package/dist/examples/onto//351/224/200/345/224/256/347/244/272/344/276/213/setup/sales_ontology_init.py +1 -1
  62. package/dist/prompts/index.json +1 -1
  63. package/dist/prompts/onto/planning-design.md +226 -104
  64. package/dist/prompts/onto/script-publish-run.md +8 -6
  65. package/package.json +1 -1
package/README.md CHANGED
@@ -78,7 +78,7 @@ pnpm run publish:cli
78
78
 
79
79
  ```powershell
80
80
  # 全局
81
- pnpm add -g @dazitech/cli@3.1.0
81
+ pnpm add -g @dazitech/cli@3.1.1
82
82
 
83
83
  # 确认 PATH(pnpm 全局 bin)
84
84
  pnpm bin -g
@@ -13076,8 +13076,8 @@ var {
13076
13076
  Help
13077
13077
  } = import_index.default;
13078
13078
 
13079
- // cli/shared/src/version.ts
13080
- var DAZI_VERSION = true ? "3.1.0" : readDevVersion();
13079
+ // cli/shared/src/version.js
13080
+ var DAZI_VERSION = true ? "3.1.1" : readDevVersion();
13081
13081
 
13082
13082
  // cli/dazi-app/src/lib/httpClient.ts
13083
13083
  init_config();
@@ -4981,8 +4981,8 @@ function resolveWorkspace(cwd = process.cwd()) {
4981
4981
  };
4982
4982
  }
4983
4983
 
4984
- // cli/shared/src/version.ts
4985
- var DAZI_VERSION = true ? "3.1.0" : readDevVersion();
4984
+ // cli/shared/src/version.js
4985
+ var DAZI_VERSION = true ? "3.1.1" : readDevVersion();
4986
4986
 
4987
4987
  // cli/dazi-flow/src/commands/flows.ts
4988
4988
  var import_path3 = __toESM(require("path"), 1);
@@ -3215,13 +3215,14 @@ function resolveWorkspace(cwd = process.cwd()) {
3215
3215
  };
3216
3216
  }
3217
3217
 
3218
- // cli/shared/src/version.ts
3219
- var DAZI_VERSION = true ? "3.1.0" : readDevVersion();
3218
+ // cli/shared/src/version.js
3219
+ var DAZI_VERSION = true ? "3.1.1" : readDevVersion();
3220
3220
 
3221
- // cli/shared/src/ontoWorkspaceAudit.ts
3221
+ // cli/shared/src/ontoWorkspaceAudit.js
3222
3222
  function ontoItemSubdirForScriptType(scriptType) {
3223
3223
  const t = (scriptType ?? "").toLowerCase();
3224
- if (t === "ontology_function" || t === "ontology_action") return "functions";
3224
+ if (t === "ontology_function" || t === "ontology_action")
3225
+ return "functions";
3225
3226
  return "setup";
3226
3227
  }
3227
3228
 
@@ -3318,14 +3319,246 @@ function makeSpaceCommand() {
3318
3319
  // cli/dazi-onto/src/commands/function.ts
3319
3320
  var import_path4 = __toESM(require("path"), 1);
3320
3321
  var import_fs3 = __toESM(require("fs"), 1);
3322
+
3323
+ // cli/dazi-onto/src/lib/ontologyFunctionLint.ts
3324
+ function extractTestArgumentsParams(code) {
3325
+ const block = extractPythonAssignDict(code, "TEST_ARGUMENTS");
3326
+ if (!block) return null;
3327
+ const argsBlock = extractDictValueForKey(block, "arguments");
3328
+ if (!argsBlock) return null;
3329
+ try {
3330
+ return JSON.parse(pythonDictFragmentToJson(argsBlock));
3331
+ } catch {
3332
+ return null;
3333
+ }
3334
+ }
3335
+ function extractPythonAssignDict(code, varName) {
3336
+ const re = new RegExp(`(?:^|\\n)${varName}\\s*=\\s*\\{`, "m");
3337
+ const m = re.exec(code);
3338
+ if (!m) return null;
3339
+ const start = m.index + m[0].length - 1;
3340
+ return extractBalancedBraces(code, start);
3341
+ }
3342
+ function extractDictValueForKey(dictStr, key) {
3343
+ const re = new RegExp(`["']${key}["']\\s*:\\s*\\{`);
3344
+ const m = re.exec(dictStr);
3345
+ if (!m) return null;
3346
+ const start = m.index + m[0].length - 1;
3347
+ return extractBalancedBraces(dictStr, start);
3348
+ }
3349
+ function extractBalancedBraces(text, openIndex) {
3350
+ if (text[openIndex] !== "{") return null;
3351
+ let depth = 0;
3352
+ for (let i = openIndex; i < text.length; i++) {
3353
+ const ch = text[i];
3354
+ if (ch === "{") depth++;
3355
+ else if (ch === "}") {
3356
+ depth--;
3357
+ if (depth === 0) return text.slice(openIndex, i + 1);
3358
+ }
3359
+ }
3360
+ return null;
3361
+ }
3362
+ function pythonDictFragmentToJson(fragment) {
3363
+ return fragment.replace(/\bTrue\b/g, "true").replace(/\bFalse\b/g, "false").replace(/\bNone\b/g, "null").replace(/,\s*}/g, "}").replace(/,\s*]/g, "]").replace(/'/g, '"');
3364
+ }
3365
+ function lineOf(code, index) {
3366
+ return code.slice(0, index).split("\n").length;
3367
+ }
3368
+ function lintOntologyFunctionCode(code, filePath) {
3369
+ const issues = [];
3370
+ const label = filePath ? pathBasename(filePath) : "\u811A\u672C";
3371
+ if (/output\.print_json\s*\(/.test(code)) {
3372
+ issues.push({
3373
+ severity: "error",
3374
+ rule: "no-print-json",
3375
+ message: `${label}: \u7981\u6B62 output.print_json()\uFF1B\u987B return p.function_result(...)`
3376
+ });
3377
+ }
3378
+ if (/def\s+main\s*\(\s*params/.test(code)) {
3379
+ issues.push({
3380
+ severity: "error",
3381
+ rule: "main-no-params",
3382
+ message: `${label}: main() \u4E0D\u5F97\u5E26 params \u5F62\u53C2\uFF1B\u987B def main():`
3383
+ });
3384
+ } else if (!/def\s+main\s*\(\s*\)\s*:/.test(code)) {
3385
+ issues.push({
3386
+ severity: "error",
3387
+ rule: "main-required",
3388
+ message: `${label}: \u7F3A\u5C11 def main(): \u5165\u53E3`
3389
+ });
3390
+ }
3391
+ if (!/function_result\s*\(/.test(code)) {
3392
+ issues.push({
3393
+ severity: "error",
3394
+ rule: "function-result-required",
3395
+ message: `${label}: \u987B\u8C03\u7528 p.function_result(...) \u8FD4\u56DE\u7ED3\u6784\u5316\u7ED3\u679C`
3396
+ });
3397
+ }
3398
+ const frPos = /function_result\s*\(\s*\{/.exec(code);
3399
+ if (frPos) {
3400
+ issues.push({
3401
+ severity: "error",
3402
+ rule: "function-result-kwargs",
3403
+ message: `${label}: function_result \u987B\u7528\u5173\u952E\u5B57\u53C2\u6570 columns=/data=/row_count=\uFF0C\u52FF\u4F20 dict positional`,
3404
+ line: lineOf(code, frPos.index)
3405
+ });
3406
+ }
3407
+ if (!/return\s+/.test(code)) {
3408
+ issues.push({
3409
+ severity: "warn",
3410
+ rule: "return-missing",
3411
+ message: `${label}: main() \u5EFA\u8BAE return _ontology_fn_body(p)`
3412
+ });
3413
+ }
3414
+ if (!/TEST_ARGUMENTS\s*=/.test(code)) {
3415
+ issues.push({
3416
+ severity: "warn",
3417
+ rule: "test-arguments-missing",
3418
+ message: `${label}: \u5EFA\u8BAE\u5B9A\u4E49 TEST_ARGUMENTS\uFF08function run \u65E0\u53C2\u65F6\u56DE\u9000\uFF09`
3419
+ });
3420
+ } else {
3421
+ const args = extractTestArgumentsParams(code);
3422
+ if (!args || Object.keys(args).length === 0) {
3423
+ issues.push({
3424
+ severity: "warn",
3425
+ rule: "test-arguments-empty",
3426
+ message: `${label}: TEST_ARGUMENTS.arguments \u4E3A\u7A7A\uFF0C\u9996\u6B21 function run \u53EF\u80FD\u5931\u8D25`
3427
+ });
3428
+ }
3429
+ }
3430
+ const emptyDate = /\.get\s*\(\s*["'](?:start_date|end_date)["']\s*,\s*["']['"]\s*\)/g;
3431
+ let dm;
3432
+ while ((dm = emptyDate.exec(code)) !== null) {
3433
+ issues.push({
3434
+ severity: "warn",
3435
+ rule: "empty-date-default",
3436
+ message: `${label}: params.get("start_date/end_date", "") \u7A7A\u4E32\u6613\u5BFC\u81F4 strptime \u5931\u8D25\uFF1B\u5EFA\u8BAE\u975E\u7A7A\u9ED8\u8BA4\u6216\u6821\u9A8C`,
3437
+ line: lineOf(code, dm.index)
3438
+ });
3439
+ }
3440
+ return issues;
3441
+ }
3442
+ function lintOntologySetupInitCode(code, filePath) {
3443
+ const issues = [];
3444
+ const label = filePath ? pathBasename(filePath) : "\u811A\u672C";
3445
+ const base = label.toLowerCase();
3446
+ if (base.includes("category_mount")) return issues;
3447
+ const isInit = /init/i.test(base) && !base.includes("seed");
3448
+ if (!isInit) return issues;
3449
+ const applyMatch = /\.categories\.apply_registry\s*\(/.exec(code);
3450
+ if (applyMatch) {
3451
+ issues.push({
3452
+ severity: "error",
3453
+ rule: "init-no-apply-registry",
3454
+ message: `${label}: init \u811A\u672C\u7981\u6B62 apply_registry\uFF1B\u8BF7\u5C06 CATEGORY_REGISTRY \u8FC1\u81F3 *_category_mount.py\uFF0C\u6D41\u7A0B\uFF1Ainit \u2192 seed \u2192 \u51FD\u6570 publish \u2192 category_mount`,
3455
+ line: lineOf(code, applyMatch.index)
3456
+ });
3457
+ }
3458
+ if (/^CATEGORY_REGISTRY\s*=/m.test(code) && applyMatch) {
3459
+ issues.push({
3460
+ severity: "warn",
3461
+ rule: "init-category-registry-inline",
3462
+ message: `${label}: CATEGORY_REGISTRY \u5E94\u653E\u5728\u72EC\u7ACB *_category_mount.py\uFF0C\u52FF\u4E0E init \u540C\u6587\u4EF6`
3463
+ });
3464
+ }
3465
+ return issues;
3466
+ }
3467
+ function lintOntologyScriptCode(code, scriptType, filePath) {
3468
+ if (scriptType === "ontology_function") {
3469
+ return lintOntologyFunctionCode(code, filePath);
3470
+ }
3471
+ if (scriptType === "setup") {
3472
+ return lintOntologySetupInitCode(code, filePath);
3473
+ }
3474
+ return [];
3475
+ }
3476
+ function formatLintReport(issues) {
3477
+ if (!issues.length) return "";
3478
+ return issues.map((i) => {
3479
+ const tag = i.severity === "error" ? "\u2717" : "\u26A0";
3480
+ const loc = i.line ? ` (\u884C ${i.line})` : "";
3481
+ return ` ${tag} [${i.rule}]${loc} ${i.message}`;
3482
+ }).join("\n");
3483
+ }
3484
+ function lintHasErrors(issues) {
3485
+ return issues.some((i) => i.severity === "error");
3486
+ }
3487
+ function pathBasename(p) {
3488
+ return p.replace(/\\/g, "/").split("/").pop() ?? p;
3489
+ }
3490
+
3491
+ // cli/dazi-onto/src/lib/functionHelpers.ts
3492
+ function isParamsEmpty(params) {
3493
+ if (params == null) return true;
3494
+ if (typeof params !== "object") return false;
3495
+ return Object.keys(params).length === 0;
3496
+ }
3497
+ async function resolveFunctionRunParams(fn, explicitParams, fetchScriptCode3) {
3498
+ if (!isParamsEmpty(explicitParams)) {
3499
+ return { params: explicitParams, source: "explicit" };
3500
+ }
3501
+ const ta = fn.test_arguments;
3502
+ if (ta && typeof ta === "object" && !Array.isArray(ta)) {
3503
+ const args = ta.arguments;
3504
+ if (args && typeof args === "object" && Object.keys(args).length > 0) {
3505
+ return { params: { ...args }, source: "test_arguments" };
3506
+ }
3507
+ }
3508
+ const scriptId = fn.script_id ?? fn.adapter_config?.script_id;
3509
+ if (scriptId) {
3510
+ try {
3511
+ const code = await fetchScriptCode3(scriptId);
3512
+ const fromScript = extractTestArgumentsParams(code);
3513
+ if (fromScript && Object.keys(fromScript).length > 0) {
3514
+ return { params: fromScript, source: "script_test_arguments" };
3515
+ }
3516
+ } catch {
3517
+ }
3518
+ }
3519
+ return { params: explicitParams };
3520
+ }
3521
+ function resolveFunctionDef(fns, idOrFunctionId) {
3522
+ const key = idOrFunctionId.trim();
3523
+ if (!key) return void 0;
3524
+ const byRowId = fns.find((f) => f.id === key);
3525
+ if (byRowId) return byRowId;
3526
+ return fns.find((f) => f.function_id === key);
3527
+ }
3528
+ function isFunctionIdAlias(value) {
3529
+ return value.includes(".fn.") || !value.startsWith("ofn_") && value.includes(".");
3530
+ }
3531
+ function enrichFunctionListItem(fn, spaceId) {
3532
+ const fnId = fn.function_id ?? fn.id;
3533
+ const jsonFile = `functions/test_arguments/${fnId}.json`;
3534
+ const saveCommand = `dazi onto function save-test-arguments ${fn.id} --space ${spaceId} --arguments-json-file <\u9879\u76EE\u8DEF\u5F84>/${jsonFile}`;
3535
+ const saveByAlias = fn.function_id ? `dazi onto function save-test-arguments --function-id ${fn.function_id} --space ${spaceId} --arguments-json-file <\u9879\u76EE\u8DEF\u5F84>/${jsonFile}` : saveCommand;
3536
+ return {
3537
+ ...fn,
3538
+ save_command: saveByAlias
3539
+ };
3540
+ }
3541
+
3542
+ // cli/dazi-onto/src/commands/function.ts
3543
+ async function fetchScriptCode(scriptId) {
3544
+ const detail = await apiRequest(`/api/scripts/${encodeURIComponent(scriptId)}`);
3545
+ return detail.code ?? "";
3546
+ }
3547
+ async function listFunctionDefs(spaceId) {
3548
+ return apiRequest(`/api/ontology-v2/spaces/${spaceId}/function-defs`);
3549
+ }
3550
+ function wantsJsonOutput(opts) {
3551
+ return Boolean(opts.json || opts.output === "json");
3552
+ }
3321
3553
  function makeFunctionCommand() {
3322
3554
  const cmd = new Command("function").description("\u672C\u4F53\u51FD\u6570\u7BA1\u7406");
3323
- cmd.command("list").description("\u5217\u51FA\u51FD\u6570\u5B9A\u4E49").requiredOption("--space <spaceId>", "\u7A7A\u95F4 ID").option("--json", "\u8F93\u51FA JSON").action(async (opts) => {
3555
+ cmd.command("list").description("\u5217\u51FA\u51FD\u6570\u5B9A\u4E49").requiredOption("--space <spaceId>", "\u7A7A\u95F4 ID").option("--json", "\u8F93\u51FA JSON").option("--output <format>", "\u8F93\u51FA\u683C\u5F0F\uFF08json\uFF0C\u4E0E --json \u7B49\u4EF7\uFF09").action(async (opts) => {
3324
3556
  try {
3325
- const fns = await apiRequest(`/api/ontology-v2/spaces/${opts.space}/function-defs`);
3326
- if (opts.json) {
3327
- console.log(JSON.stringify(fns, null, 2));
3328
- ok({ functions: fns });
3557
+ const fns = await listFunctionDefs(opts.space);
3558
+ const enriched = fns.map((f) => enrichFunctionListItem(f, opts.space));
3559
+ if (wantsJsonOutput(opts)) {
3560
+ console.log(JSON.stringify(enriched, null, 2));
3561
+ ok({ functions: enriched });
3329
3562
  return;
3330
3563
  }
3331
3564
  if (!fns.length) {
@@ -3333,42 +3566,57 @@ function makeFunctionCommand() {
3333
3566
  ok({ functions: [] });
3334
3567
  return;
3335
3568
  }
3336
- for (const f of fns) {
3569
+ for (const f of enriched) {
3337
3570
  const fnId = (f.function_id ?? f.id ?? "").padEnd(40);
3338
3571
  const name = (f.display_name ?? "").padEnd(24);
3339
3572
  const adapter = f.adapter ?? "dazi_script";
3340
- console.log(` ${fnId} ${name} [${adapter}]`);
3573
+ console.log(` ${fnId} ${name} [${adapter}] id=${f.id}`);
3341
3574
  }
3342
- ok({ functions: fns });
3575
+ ok({ functions: enriched });
3343
3576
  } catch (err) {
3344
3577
  handleError(err);
3345
3578
  }
3346
3579
  });
3347
- cmd.command("get <functionId>").description("\u67E5\u770B\u51FD\u6570\u8BE6\u60C5").requiredOption("--space <spaceId>", "\u7A7A\u95F4 ID").action(async (functionId, opts) => {
3580
+ cmd.command("get <functionId>").description("\u67E5\u770B\u51FD\u6570\u8BE6\u60C5\uFF08\u652F\u6301 function_id \u6216 ofn \u884C id\uFF09").requiredOption("--space <spaceId>", "\u7A7A\u95F4 ID").action(async (functionId, opts) => {
3348
3581
  try {
3349
- const fns = await apiRequest(`/api/ontology-v2/spaces/${opts.space}/function-defs`);
3350
- const fn = fns.find((f) => f.function_id === functionId);
3582
+ const fns = await listFunctionDefs(opts.space);
3583
+ const fn = resolveFunctionDef(fns, functionId);
3351
3584
  if (!fn) {
3352
3585
  console.error(`\u672A\u627E\u5230\u51FD\u6570: ${functionId}`);
3353
3586
  process.exit(1);
3354
3587
  }
3355
- console.log(JSON.stringify(fn, null, 2));
3588
+ console.log(JSON.stringify(enrichFunctionListItem(fn, opts.space), null, 2));
3356
3589
  ok({ function: fn });
3357
3590
  } catch (err) {
3358
3591
  handleError(err);
3359
3592
  }
3360
3593
  });
3361
- cmd.command("run <functionId>").description("\u6267\u884C\u672C\u4F53\u51FD\u6570").requiredOption("--space <spaceId>", "\u7A7A\u95F4 ID").option("--params <json>", "\u53C2\u6570 JSON \u5B57\u7B26\u4E32", "{}").option("--dry-run", "\u4EC5\u6821\u9A8C\uFF0C\u4E0D\u5B9E\u9645\u6267\u884C").option("--json", "\u8F93\u51FA JSON").action(async (functionId, opts) => {
3594
+ cmd.command("run <functionId>").description("\u6267\u884C\u672C\u4F53\u51FD\u6570\uFF08\u65E0 --params \u65F6\u56DE\u9000 test_arguments / \u811A\u672C TEST_ARGUMENTS\uFF09").requiredOption("--space <spaceId>", "\u7A7A\u95F4 ID").option("--params <json>", "\u53C2\u6570 JSON \u5B57\u7B26\u4E32", "{}").option("--dry-run", "\u4EC5\u6821\u9A8C\uFF0C\u4E0D\u5B9E\u9645\u6267\u884C").option("--json", "\u8F93\u51FA JSON").action(async (functionId, opts) => {
3362
3595
  try {
3363
- const params = JSON.parse(opts.params);
3364
- const fns = await apiRequest(`/api/ontology-v2/spaces/${opts.space}/function-defs`);
3365
- const fn = fns.find((f) => f.function_id === functionId);
3366
- const scriptId = fn?.script_id ?? fn?.adapter_config?.script_id;
3596
+ const explicitParams = JSON.parse(opts.params);
3597
+ const fns = await listFunctionDefs(opts.space);
3598
+ const fn = resolveFunctionDef(fns, functionId);
3599
+ if (!fn) {
3600
+ console.error(`\u672A\u627E\u5230\u51FD\u6570: ${functionId}`);
3601
+ process.exit(1);
3602
+ }
3603
+ const scriptId = fn.script_id ?? fn.adapter_config?.script_id;
3367
3604
  if (!scriptId) {
3368
- console.error(`\u672A\u627E\u5230\u51FD\u6570\u6216\u672A\u7ED1\u5B9A\u811A\u672C: ${functionId}`);
3605
+ console.error(`\u672A\u627E\u5230\u51FD\u6570\u6216\u672A\u7ED1\u5B9A\u811A\u672C: ${fn.function_id ?? functionId}`);
3369
3606
  process.exit(1);
3370
3607
  }
3371
- console.log(`${opts.dryRun ? "[dry-run] " : ""}\u6267\u884C\u51FD\u6570: ${functionId} (script: ${scriptId})`);
3608
+ const { params, source } = await resolveFunctionRunParams(
3609
+ fn,
3610
+ explicitParams,
3611
+ fetchScriptCode
3612
+ );
3613
+ if (source === "test_arguments") {
3614
+ console.log("\u2139 \u672A\u4F20 --params\uFF0C\u4F7F\u7528\u5DF2\u4FDD\u5B58 test_arguments.arguments");
3615
+ } else if (source === "script_test_arguments") {
3616
+ console.log("\u2139 \u672A\u4F20 --params\uFF0C\u56DE\u9000\u811A\u672C\u5185 TEST_ARGUMENTS.arguments");
3617
+ }
3618
+ const runFnId = fn.function_id ?? functionId;
3619
+ console.log(`${opts.dryRun ? "[dry-run] " : ""}\u6267\u884C\u51FD\u6570: ${runFnId} (script: ${scriptId})`);
3372
3620
  const result = await apiRequest(
3373
3621
  `/api/scripts/${scriptId}/execute`,
3374
3622
  {
@@ -3376,7 +3624,7 @@ function makeFunctionCommand() {
3376
3624
  body: {
3377
3625
  params,
3378
3626
  dryRun: opts.dryRun ?? false,
3379
- ontology_function_id: functionId
3627
+ ontology_function_id: runFnId
3380
3628
  }
3381
3629
  }
3382
3630
  );
@@ -3389,12 +3637,12 @@ function makeFunctionCommand() {
3389
3637
  result.logs.forEach((l) => console.log(" " + l));
3390
3638
  }
3391
3639
  }
3392
- ok({ functionId, result });
3640
+ ok({ functionId: runFnId, paramsSource: source, result });
3393
3641
  } catch (err) {
3394
3642
  handleError(err);
3395
3643
  }
3396
3644
  });
3397
- cmd.command("publish <file>").description("\u53D1\u5E03\u51FD\u6570\u811A\u672C\u5230\u5E93").requiredOption("--space <spaceId>", "\u7A7A\u95F4 ID").option("--function-id <id>", "\u7ED1\u5B9A/\u8986\u76D6\u6307\u5B9A\u51FD\u6570 ID").option("--display-name <name>", "\u51FD\u6570\u663E\u793A\u540D").option("--entry <entryPoint>", "\u5165\u53E3\u51FD\u6570\u540D").option("--object-type-id <id>", "\u5BF9\u8C61\u7C7B\u578B ID").option("--dry-run", "\u4EC5\u9884\u68C0\uFF0C\u4E0D\u5199\u5E93").option("--json", "\u8F93\u51FA JSON").action(async (file, opts) => {
3645
+ cmd.command("publish <file>").description("\u53D1\u5E03\u51FD\u6570\u811A\u672C\u5230\u5E93").requiredOption("--space <spaceId>", "\u7A7A\u95F4 ID").option("--function-id <id>", "\u7ED1\u5B9A/\u8986\u76D6\u6307\u5B9A\u51FD\u6570 ID").option("--display-name <name>", "\u51FD\u6570\u663E\u793A\u540D").option("--entry <entryPoint>", "\u5165\u53E3\u51FD\u6570\u540D").option("--object-type-id <id>", "\u5BF9\u8C61\u7C7B\u578B ID").option("--dry-run", "\u4EC5\u9884\u68C0\uFF0C\u4E0D\u5B9E\u9645\u6267\u884C").option("--json", "\u8F93\u51FA JSON").action(async (file, opts) => {
3398
3646
  try {
3399
3647
  const filePath = import_path4.default.resolve(file);
3400
3648
  if (!import_fs3.default.existsSync(filePath)) {
@@ -3411,9 +3659,8 @@ function makeFunctionCommand() {
3411
3659
  objectTypeId: opts.objectTypeId,
3412
3660
  dryRun: opts.dryRun ?? false
3413
3661
  };
3414
- const endpoint = opts.dryRun ? `/api/scripts` : `/api/scripts`;
3415
3662
  const result = await apiRequest(
3416
- endpoint,
3663
+ `/api/scripts`,
3417
3664
  { method: "POST", body }
3418
3665
  );
3419
3666
  if (opts.json) {
@@ -3501,7 +3748,7 @@ function makeFunctionCommand() {
3501
3748
  if (opts.dryRun) params.set("dryRun", "true");
3502
3749
  const result = await apiRequest(
3503
3750
  `/api/ontology-v2/spaces/${opts.space}/function-defs?${params}`,
3504
- { method: "DELETE" }
3751
+ { method: opts.dryRun ? "GET" : "DELETE", body: opts.dryRun ? void 0 : {} }
3505
3752
  );
3506
3753
  console.log(`${opts.dryRun ? "[dry-run] " : ""}\u5220\u9664 ${result.count} \u4E2A\u51FD\u6570`);
3507
3754
  ok({ count: result.count, dryRun: opts.dryRun });
@@ -3509,20 +3756,33 @@ function makeFunctionCommand() {
3509
3756
  handleError(err);
3510
3757
  }
3511
3758
  });
3512
- cmd.command("save-test-arguments <functionId>").description("\u4FDD\u5B58\u51FD\u6570\u6D4B\u8BD5\u53C2\u6570").requiredOption("--space <spaceId>", "\u7A7A\u95F4 ID").option("--params <json>", "\u53C2\u6570 JSON \u5B57\u7B26\u4E32", "{}").option("--arguments-json-file <file>", "\u4ECE JSON \u6587\u4EF6\u8BFB\u53D6\u53C2\u6570").action(async (functionId, opts) => {
3759
+ cmd.command("save-test-arguments [functionDefId]").description("\u4FDD\u5B58\u51FD\u6570\u6D4B\u8BD5\u53C2\u6570\uFF08\u652F\u6301 ofn_xxx \u6216 --function-id domain.fn.name\uFF09").requiredOption("--space <spaceId>", "\u7A7A\u95F4 ID").option("--function-id <id>", "function_id \u522B\u540D\uFF08\u5982 sales.fn.get_summary\uFF09").option("--params <json>", "\u53C2\u6570 JSON \u5B57\u7B26\u4E32", "{}").option("--arguments-json-file <file>", "\u4ECE JSON \u6587\u4EF6\u8BFB\u53D6\u53C2\u6570").action(async (functionDefId, opts) => {
3513
3760
  try {
3514
- let params;
3761
+ const lookupKey = (opts.functionId ?? functionDefId ?? "").trim();
3762
+ if (!lookupKey) {
3763
+ console.error("\u987B\u63D0\u4F9B ofn_xxx \u6216 --function-id <domain.fn.name>");
3764
+ process.exit(1);
3765
+ }
3766
+ let payload;
3515
3767
  if (opts.argumentsJsonFile) {
3516
- params = JSON.parse(import_fs3.default.readFileSync(import_path4.default.resolve(opts.argumentsJsonFile), "utf-8"));
3768
+ payload = JSON.parse(import_fs3.default.readFileSync(import_path4.default.resolve(opts.argumentsJsonFile), "utf-8"));
3517
3769
  } else {
3518
- params = JSON.parse(opts.params);
3770
+ payload = JSON.parse(opts.params);
3519
3771
  }
3520
- await apiRequest(`/api/ontology-v2/spaces/${opts.space}/function-defs/${functionId}`, {
3772
+ const fns = await listFunctionDefs(opts.space);
3773
+ const fn = resolveFunctionDef(fns, lookupKey);
3774
+ if (!fn) {
3775
+ const hint = isFunctionIdAlias(lookupKey) ? "\u8BF7\u786E\u8BA4\u5DF2 publish --register-function-id" : "\u8BF7\u7528 function list \u67E5\u770B id \u5B57\u6BB5";
3776
+ console.error(`\u672A\u627E\u5230\u51FD\u6570: ${lookupKey}\uFF08${hint}\uFF09`);
3777
+ process.exit(1);
3778
+ }
3779
+ await apiRequest(`/api/ontology-v2/spaces/${opts.space}/function-defs/${fn.id}`, {
3521
3780
  method: "PATCH",
3522
- body: { test_arguments: params }
3781
+ body: { test_arguments: payload }
3523
3782
  });
3524
- console.log(`\u2705 \u6D4B\u8BD5\u53C2\u6570\u5DF2\u4FDD\u5B58: ${functionId}`);
3525
- ok({ functionId, saved: true });
3783
+ const label = fn.function_id ?? fn.id;
3784
+ console.log(`\u2705 \u6D4B\u8BD5\u53C2\u6570\u5DF2\u4FDD\u5B58: ${label} (${fn.id})`);
3785
+ ok({ functionId: fn.function_id, functionDefId: fn.id, saved: true });
3526
3786
  } catch (err) {
3527
3787
  handleError(err);
3528
3788
  }
@@ -3712,7 +3972,7 @@ function makeRuleCommand() {
3712
3972
  // cli/dazi-onto/src/commands/script.ts
3713
3973
  var import_path6 = __toESM(require("path"), 1);
3714
3974
  var import_fs5 = __toESM(require("fs"), 1);
3715
- async function fetchScriptCode(scriptId) {
3975
+ async function fetchScriptCode2(scriptId) {
3716
3976
  const detail = await apiRequest(`/api/scripts/${encodeURIComponent(scriptId)}`);
3717
3977
  return detail.code ?? "";
3718
3978
  }
@@ -3762,6 +4022,18 @@ function buildSpacesRelPath(filePath, spaceId, scriptType) {
3762
4022
  const dir = workspaceDirForScriptType(scriptType);
3763
4023
  return `spaces/${spaceId}/editorial/scripts/${dir}/${stem}.py`;
3764
4024
  }
4025
+ function runOntologyScriptLocalLint(filePath, scriptType) {
4026
+ const code = import_fs5.default.readFileSync(filePath, "utf-8");
4027
+ const issues = lintOntologyScriptCode(code, scriptType, filePath);
4028
+ if (!issues.length) return;
4029
+ console.log("\u672C\u4F53\u811A\u672C\u9759\u6001\u9884\u68C0\uFF1A");
4030
+ console.log(formatLintReport(issues));
4031
+ if (lintHasErrors(issues)) {
4032
+ console.error("\u2717 \u9884\u68C0\u5931\u8D25\uFF1A\u8BF7\u5148\u4FEE\u590D\u4E0A\u8FF0 error \u9879");
4033
+ process.exit(1);
4034
+ }
4035
+ console.log("\u26A0 \u5B58\u5728 warn \u9879\uFF0C\u53EF\u7EE7\u7EED\u53D1\u5E03");
4036
+ }
3765
4037
  function buildPublishFromSpacesBody(filePath, opts) {
3766
4038
  const code = import_fs5.default.readFileSync(filePath, "utf-8");
3767
4039
  const scriptType = inferScriptTypeFromPath(filePath, opts.type);
@@ -3880,7 +4152,7 @@ function makeScriptCommand() {
3880
4152
  continue;
3881
4153
  }
3882
4154
  if (!import_fs5.default.existsSync(outDir)) import_fs5.default.mkdirSync(outDir, { recursive: true });
3883
- const code = s.code?.length ? s.code : await fetchScriptCode(s.id);
4155
+ const code = s.code?.length ? s.code : await fetchScriptCode2(s.id);
3884
4156
  if (!code.trim()) {
3885
4157
  console.warn(` \u26A0 \u8DF3\u8FC7 ${s.id}\uFF1A\u65E0\u811A\u672C\u4EE3\u7801`);
3886
4158
  continue;
@@ -3907,6 +4179,10 @@ function makeScriptCommand() {
3907
4179
  console.error(`\u6587\u4EF6\u4E0D\u5B58\u5728: ${filePath}`);
3908
4180
  process.exit(1);
3909
4181
  }
4182
+ const scriptType = inferScriptTypeFromPath(filePath, opts.type);
4183
+ if (opts.dryRun || scriptType === "ontology_function" || scriptType === "setup") {
4184
+ runOntologyScriptLocalLint(filePath, scriptType);
4185
+ }
3910
4186
  const body = buildPublishFromSpacesBody(filePath, opts);
3911
4187
  const endpoint = opts.dryRun ? "/api/scripts/example-files/publish-preview" : "/api/scripts/example-files/publish-from-spaces";
3912
4188
  const result = await apiRequest(endpoint, { method: "POST", body });
@@ -3934,9 +4210,11 @@ function makeScriptCommand() {
3934
4210
  console.error(`\u6587\u4EF6\u4E0D\u5B58\u5728: ${filePath}`);
3935
4211
  process.exit(1);
3936
4212
  }
4213
+ const scriptType = inferScriptTypeFromPath(filePath, opts.type);
4214
+ runOntologyScriptLocalLint(filePath, scriptType);
3937
4215
  const body = buildPublishFromSpacesBody(filePath, { ...opts, registerFunctionId: opts.registerFunctionId });
3938
4216
  const result = await apiRequest("/api/scripts/example-files/publish-preview", { method: "POST", body });
3939
- console.log("\u2705 \u9884\u68C0\u901A\u8FC7");
4217
+ console.log("\u2705 \u670D\u52A1\u7AEF\u9884\u68C0\u901A\u8FC7");
3940
4218
  if (result && typeof result === "object") {
3941
4219
  console.log(JSON.stringify(result, null, 2));
3942
4220
  }