@stalfh233/omc-cli 0.5.1 → 0.5.2

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.
@@ -14,6 +14,7 @@ import { writeTool } from "../write.js";
14
14
  import { registerPackageTool } from "../package-tool.js";
15
15
  import { defineTool, ToolInputError, ToolRefusalError } from "../tool-types.js";
16
16
  import { wireCall, wireRows, WireError } from "../wire.js";
17
+ import { readModelRecord } from "../model-record.js";
17
18
  import { MODEL_CREATE_BODY_DEFAULTS, MODEL_LANE_CONTRACT } from "./model-contract.js";
18
19
  const MODEL_LANE = MODEL_LANE_CONTRACT.lane;
19
20
  const MODEL_TOOLS = MODEL_LANE_CONTRACT.tools;
@@ -48,7 +49,7 @@ function modelRollbackSpec(toolName) {
48
49
  target: (args) => `model:${String(args.schemaCode ?? args.code ?? "")}`,
49
50
  read: async (session, args) => {
50
51
  const resolved = await resolveModelTreeNode(session, String(args.schemaCode ?? args.code));
51
- const record = (await wireCall(session, { path: ENDPOINTS.modelGet, query: { schemaCode: String(args.schemaCode ?? args.code) } })).data;
52
+ const record = await readModelRecord(session, String(args.schemaCode ?? args.code));
52
53
  if (!resolved.node && !record)
53
54
  return null;
54
55
  return { node: resolved.node ?? null, record: record ?? null };
@@ -386,7 +387,7 @@ export function registerModelLane(tools) {
386
387
  // bizmodels/get_all is keyed by the query, so a non-null object IS the
387
388
  // model (an absent one answers a business errcode — wireCall throws and
388
389
  // we fall through to create).
389
- const record = (await wireCall(session, { path: ENDPOINTS.modelGet, query: { schemaCode: args.code } })).data;
390
+ const record = await readModelRecord(session, args.code);
390
391
  if (record !== null && typeof record === "object") {
391
392
  throw new ToolRefusalError({
392
393
  status: "refused",
@@ -461,7 +462,7 @@ export function registerModelLane(tools) {
461
462
  async function modelDeleteDryRun(session, args) {
462
463
  const record = await (async () => {
463
464
  try {
464
- return (await wireCall(session, { path: ENDPOINTS.modelGet, query: { schemaCode: args.schemaCode } })).data ?? null;
465
+ return readModelRecord(session, args.schemaCode);
465
466
  }
466
467
  catch (error) {
467
468
  if (error instanceof WireError && error.kind === "business")
@@ -510,17 +511,7 @@ export function registerModelLane(tools) {
510
511
  writeTool(tools, "model.delete", MODEL_LANE, MODEL_TOOLS["model.delete"].scope, MODEL_TOOLS["model.delete"].description, { schemaCode: z.string().min(1), applicationCode: z.string().optional() }, async (session, args) => {
511
512
  // authoritative model record (bizmodels/get_all); the app-tree node id
512
513
  // may lag behind and is cleaned best-effort.
513
- const readRecord = async () => {
514
- try {
515
- const result = await wireCall(session, { path: ENDPOINTS.modelGet, query: { schemaCode: args.schemaCode } });
516
- return result.data ?? null;
517
- }
518
- catch (error) {
519
- if (error instanceof WireError && error.kind === "business")
520
- return null;
521
- throw error;
522
- }
523
- };
514
+ const readRecord = () => readModelRecord(session, args.schemaCode);
524
515
  const record = await readRecord();
525
516
  // Ticket 68: resolve the app-tree node across applications (the tree row
526
517
  // id IS the AppFunction id physically_delete needs). Never fall back to
@@ -673,17 +664,7 @@ export function registerModelLane(tools) {
673
664
  // every existing model in that single request after prechecking each
674
665
  // target's inbound references — a referenced model refuses the whole
675
666
  // batch with per-target evidence and ZERO side effects.
676
- const readRecord = async (schemaCode) => {
677
- try {
678
- const result = await wireCall(session, { path: ENDPOINTS.modelGet, query: { schemaCode } });
679
- return result.data ?? null;
680
- }
681
- catch (error) {
682
- if (error instanceof WireError && error.kind === "business")
683
- return null;
684
- throw error;
685
- }
686
- };
667
+ const readRecord = (schemaCode) => readModelRecord(session, schemaCode);
687
668
  const applicationCode = await resolveApplicationCode(session, args.applicationCode).catch(() => "");
688
669
  const targets = [...new Set(args.schemaCodes)];
689
670
  const alreadyAbsent = [];
@@ -885,8 +866,10 @@ export function registerModelLane(tools) {
885
866
  // NOT migrated by this endpoint (probe evidence).
886
867
  const after = await resolveModelTreeNode(session, args.schemaCode);
887
868
  const nodeAfter = after.node;
888
- const record = await wireCall(session, { path: ENDPOINTS.modelGet, query: { schemaCode: args.schemaCode } });
889
- const recordName = (record.data ?? {}).name ?? null;
869
+ // Informational only: the app-tree node is the authoritative face for a
870
+ // rename, so an unreadable record face must not fail the whole call.
871
+ const record = await readModelRecord(session, args.schemaCode).catch(() => null);
872
+ const recordName = record?.name ?? null;
890
873
  const nodeName = typeof nodeAfter?.name === "string" ? nodeAfter.name : null;
891
874
  return {
892
875
  performed: { errcode: performed.errcode },
@@ -27,6 +27,7 @@ import { CLI_EXIT_CODES, classifyResult, envelope, refusalText, requestId } from
27
27
  import { writeEnvelope } from "./cli-output.js";
28
28
  import { ENDPOINTS } from "./endpoints.js";
29
29
  import { wireCall, wireRows } from "./wire.js";
30
+ import { readModelRecord } from "./model-record.js";
30
31
  import { SessionManager } from "./session-manager.js";
31
32
  import { ConfigStore, defaultPaths } from "./config-store.js";
32
33
  async function sessionFor(environment) {
@@ -43,8 +44,7 @@ export async function planPurge(options, injected) {
43
44
  const session = injected ?? (await sessionFor(options.environment));
44
45
  let modelExists = true;
45
46
  try {
46
- const record = (await wireCall(session, { path: ENDPOINTS.modelGet, query: { schemaCode: options.schemaCode } })).data;
47
- modelExists = record !== null && record !== undefined;
47
+ modelExists = (await readModelRecord(session, options.schemaCode)) !== null;
48
48
  }
49
49
  catch {
50
50
  modelExists = false;
@@ -0,0 +1,40 @@
1
+ import { ENDPOINTS } from "./endpoints.js";
2
+ import { wireCall, wireRows, WireError } from "./wire.js";
3
+ /**
4
+ * Authoritative biz-model record, across platform versions.
5
+ *
6
+ * 8.6 serves `/api/api/app/bizmodels/get_all` (BizSchemaController resolves
7
+ * getBizSchemaBySchemaCode and answers 10011 on a miss). 8.0/8.1 deployments
8
+ * answer **HTTP 404** for that path (field report 2026-10-30, 8.1.108 /
9
+ * 上海电建) and expose the same rows through `/bizmodels/list_schema`, filtered
10
+ * by `schemaCode`. Pinning the 8.6 path made model.*, rule.* and the purge
11
+ * precheck die with a raw 404 before any of their own logic ran.
12
+ *
13
+ * Reads the primary face first; only a 404 (endpoint absent) falls back, so a
14
+ * genuine 401/500/transport failure still surfaces as itself. Returns null when
15
+ * the model is not there (business "not found" on either face).
16
+ */
17
+ export async function readModelRecord(session, schemaCode) {
18
+ try {
19
+ const result = await wireCall(session, { path: ENDPOINTS.modelGet, query: { schemaCode } });
20
+ return result.data ?? null;
21
+ }
22
+ catch (error) {
23
+ if (error instanceof WireError && error.kind === "business")
24
+ return null;
25
+ const endpointAbsent = error instanceof WireError && error.kind === "http-status" && error.diagnostic?.httpStatus === 404;
26
+ if (!endpointAbsent)
27
+ throw error;
28
+ }
29
+ try {
30
+ const rows = wireRows((await wireCall(session, { path: ENDPOINTS.modelList, query: { schemaCode } })).data);
31
+ const match = rows.find((row) => String(row.schemaCode ?? row.code ?? "") === schemaCode);
32
+ return match ?? null;
33
+ }
34
+ catch (error) {
35
+ if (error instanceof WireError && error.kind === "business")
36
+ return null;
37
+ throw error;
38
+ }
39
+ }
40
+ //# sourceMappingURL=model-record.js.map
@@ -1,6 +1,7 @@
1
1
  import { z } from "zod";
2
2
  import { wireCall, wireRows, WireError } from "./wire.js";
3
3
  import { ENDPOINTS } from "./endpoints.js";
4
+ import { readModelRecord } from "./model-record.js";
4
5
  import { ToolRefusalError } from "./tool-types.js";
5
6
  import { decodeJsonColumn, JSON_COLUMN_NULL_COALESCE } from "./json-column.js";
6
7
  import { RULE_BIZ_RULE_TYPE_DESCRIPTION, RULE_CREATE_BODY, RULE_ROUTES_DESCRIPTION, ruleNodeGraphDescription, schedulerSettingDescription, } from "./lanes/businessrule-contract.js";
@@ -602,17 +603,10 @@ export async function assertRuleSchemaExists(session, schemaCode) {
602
603
  // SCHEMA_NOT_FOUNT_ERR (10011 业务模型不存在) on miss — the same facade
603
604
  // primitive the rule faces rely on. The fake answers ok+null for an absent
604
605
  // schema, so BOTH signals decode as a miss.
605
- let missing = false;
606
- try {
607
- const probe = await wireCall(session, { path: ENDPOINTS.modelGet, query: { schemaCode } });
608
- missing = probe.data == null;
609
- }
610
- catch (error) {
611
- if (error instanceof WireError && error.kind === "business" && error.errcode === 10011)
612
- missing = true;
613
- else
614
- throw error;
615
- }
606
+ // Version-tolerant: 8.1 has no `/bizmodels/get_all` (404) and serves the same
607
+ // rows from `/bizmodels/list_schema`; see model-record.ts.
608
+ const record = await readModelRecord(session, schemaCode);
609
+ const missing = record === null;
616
610
  if (missing) {
617
611
  throw new ToolRefusalError({
618
612
  status: "refused",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stalfh233/omc-cli",
3
- "version": "0.5.1",
3
+ "version": "0.5.2",
4
4
  "description": "CloudPivot 8.6 configuration capability CLI — governed, fail-closed, coverage-manifest bounded.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -52,9 +52,9 @@
52
52
  "access": "public"
53
53
  },
54
54
  "dependencies": {
55
- "@stalfh233/omc-fake-platform": "0.5.1",
55
+ "@stalfh233/omc-fake-platform": "0.5.2",
56
56
  "commander": "14.0.3",
57
- "omc-core": "0.5.1",
57
+ "omc-core": "0.5.2",
58
58
  "proper-lockfile": "4.1.2",
59
59
  "write-file-atomic": "6.0.0",
60
60
  "zod": "^3.23.8",