@stalfh233/omc-cli 0.0.0-stage → 0.4.0
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/LICENSE +21 -0
- package/README.md +304 -3
- package/coverage/m1-coverage-manifest-v1.json +1278 -0
- package/dist/approval-token.js +102 -0
- package/dist/args.js +25 -0
- package/dist/artifacts.js +119 -0
- package/dist/bench/call-face-eval.js +256 -0
- package/dist/bench/context-attribution.js +151 -0
- package/dist/bench/discovery-cost-eval.js +230 -0
- package/dist/bench/driver.js +81 -0
- package/dist/bench/evals.js +236 -0
- package/dist/bench/fake-http-server.js +65 -0
- package/dist/bench/instrument.js +87 -0
- package/dist/bench/intent-face-eval.js +343 -0
- package/dist/bench/run.js +166 -0
- package/dist/bench/scenario.js +343 -0
- package/dist/bench/types.js +76 -0
- package/dist/bi-wire.js +41 -0
- package/dist/bizservice-config.js +581 -0
- package/dist/call.js +153 -0
- package/dist/capability-absences.js +23 -0
- package/dist/capability-overview.js +492 -0
- package/dist/capability-shape.js +154 -0
- package/dist/cli-contract.js +70 -0
- package/dist/cli-output.js +73 -0
- package/dist/cli.js +1418 -0
- package/dist/code-rules.js +69 -0
- package/dist/command-transport.js +155 -0
- package/dist/config-store.js +195 -0
- package/dist/context.js +21 -0
- package/dist/contract-consistency.js +66 -0
- package/dist/contract-resources.js +62 -0
- package/dist/coverage-consistency.js +62 -0
- package/dist/coverage-registry.js +76 -0
- package/dist/coverage.js +130 -0
- package/dist/data-list-filter.js +114 -0
- package/dist/discovery.js +390 -0
- package/dist/endpoints.js +154 -0
- package/dist/environment-policy.js +26 -0
- package/dist/execution-metadata.js +1092 -0
- package/dist/fake/app.js +45 -0
- package/dist/fake/b2-registration.js +594 -0
- package/dist/fake/businessrule.js +242 -0
- package/dist/fake/datarule.js +72 -0
- package/dist/fake/dictionary.js +108 -0
- package/dist/fake/environment.js +30 -0
- package/dist/fake/field.js +167 -0
- package/dist/fake/form.js +101 -0
- package/dist/fake/index.js +121 -0
- package/dist/fake/list-view.js +289 -0
- package/dist/fake/model.js +136 -0
- package/dist/fake/online-js.js +18 -0
- package/dist/fake/report.js +253 -0
- package/dist/fake/routes.js +47 -0
- package/dist/fake/rule-lifecycle.js +37 -0
- package/dist/fake/runtime-data.js +367 -0
- package/dist/fake/state.js +67 -0
- package/dist/fake/workflow.js +364 -0
- package/dist/field-change.js +200 -0
- package/dist/field-families.js +896 -0
- package/dist/form-layout.js +111 -0
- package/dist/form-support.js +821 -0
- package/dist/goal-routes.js +468 -0
- package/dist/governed-execution.js +87 -0
- package/dist/human-summary.js +212 -0
- package/dist/identity.js +62 -0
- package/dist/intent/baseline.js +57 -0
- package/dist/intent/capabilities/bizservice.js +274 -0
- package/dist/intent/capabilities/businessrule.js +493 -0
- package/dist/intent/capabilities/datarule.js +187 -0
- package/dist/intent/capabilities/field.js +545 -0
- package/dist/intent/capabilities/form.js +136 -0
- package/dist/intent/capabilities/index.js +64 -0
- package/dist/intent/capabilities/listview.js +157 -0
- package/dist/intent/capabilities/model.js +100 -0
- package/dist/intent/capabilities/onlinejs.js +108 -0
- package/dist/intent/capabilities/report.js +355 -0
- package/dist/intent/capabilities/workflow.js +458 -0
- package/dist/intent/capability.js +6 -0
- package/dist/intent/cli.js +91 -0
- package/dist/intent/compare.js +56 -0
- package/dist/intent/compiler.js +79 -0
- package/dist/intent/dsl.js +129 -0
- package/dist/intent/plan-file.js +63 -0
- package/dist/intent/readback.js +65 -0
- package/dist/intent/schema.js +158 -0
- package/dist/intent/validation.js +30 -0
- package/dist/intent/yaml.js +315 -0
- package/dist/json-column.js +68 -0
- package/dist/lanes/app-contract.js +95 -0
- package/dist/lanes/app-coverage.js +16 -0
- package/dist/lanes/app.js +174 -0
- package/dist/lanes/apply-changes.js +231 -0
- package/dist/lanes/b2-registration-contract.js +292 -0
- package/dist/lanes/b2-registration-coverage.js +48 -0
- package/dist/lanes/b2-registration.js +1187 -0
- package/dist/lanes/businessrule-contract.js +232 -0
- package/dist/lanes/businessrule-coverage.js +16 -0
- package/dist/lanes/businessrule.js +221 -0
- package/dist/lanes/contract-support.js +65 -0
- package/dist/lanes/coverage-declaration.js +9 -0
- package/dist/lanes/datarule-contract.js +155 -0
- package/dist/lanes/datarule-coverage.js +19 -0
- package/dist/lanes/datarule-protocol.js +308 -0
- package/dist/lanes/datarule.js +818 -0
- package/dist/lanes/dictionary-contract.js +78 -0
- package/dist/lanes/dictionary-coverage.js +24 -0
- package/dist/lanes/dictionary.js +235 -0
- package/dist/lanes/environment-contract.js +70 -0
- package/dist/lanes/environment-coverage.js +14 -0
- package/dist/lanes/environment.js +163 -0
- package/dist/lanes/field-contract.js +223 -0
- package/dist/lanes/field-coverage.js +27 -0
- package/dist/lanes/field.js +374 -0
- package/dist/lanes/form-contract.js +97 -0
- package/dist/lanes/form-coverage.js +16 -0
- package/dist/lanes/form.js +185 -0
- package/dist/lanes/lane-ids.js +34 -0
- package/dist/lanes/list-view-contract.js +175 -0
- package/dist/lanes/list-view-coverage.js +20 -0
- package/dist/lanes/list-view-shapes.js +1207 -0
- package/dist/lanes/list-view.js +578 -0
- package/dist/lanes/meta-contract.js +85 -0
- package/dist/lanes/meta.js +255 -0
- package/dist/lanes/model-contract.js +168 -0
- package/dist/lanes/model-coverage.js +20 -0
- package/dist/lanes/model.js +986 -0
- package/dist/lanes/online-js-contract.js +99 -0
- package/dist/lanes/online-js-coverage.js +28 -0
- package/dist/lanes/online-js.js +127 -0
- package/dist/lanes/report-contract.js +144 -0
- package/dist/lanes/report-coverage.js +21 -0
- package/dist/lanes/report.js +476 -0
- package/dist/lanes/rule-graph.js +1846 -0
- package/dist/lanes/rule-lifecycle-contract.js +92 -0
- package/dist/lanes/rule-lifecycle-coverage.js +20 -0
- package/dist/lanes/rule-lifecycle.js +176 -0
- package/dist/lanes/runtime-data-contract.js +264 -0
- package/dist/lanes/runtime-data-coverage.js +25 -0
- package/dist/lanes/runtime-data.js +1054 -0
- package/dist/lanes/workflow-contract.js +223 -0
- package/dist/lanes/workflow-coverage.js +40 -0
- package/dist/lanes/workflow.js +1813 -0
- package/dist/online-js-layout.js +58 -0
- package/dist/online-js-source.js +276 -0
- package/dist/package-tool.js +51 -0
- package/dist/package.js +73 -0
- package/dist/plan.js +73 -0
- package/dist/read.js +144 -0
- package/dist/redact.js +28 -0
- package/dist/rule-support.js +587 -0
- package/dist/runtime-support.js +134 -0
- package/dist/server.js +92 -0
- package/dist/session-manager.js +30 -0
- package/dist/session.js +149 -0
- package/dist/skills.js +112 -0
- package/dist/support.js +98 -0
- package/dist/tool-types.js +127 -0
- package/dist/tools.js +59 -0
- package/dist/usage-log.js +197 -0
- package/dist/wire.js +287 -0
- package/dist/workflow-support.js +99 -0
- package/dist/write-lease.js +26 -0
- package/dist/write-lock.js +109 -0
- package/dist/write.js +176 -0
- package/dist/zip.js +156 -0
- package/docs/tool-surface-map.md +42 -0
- package/package.json +71 -6
- package/skills/omc-acceptance-criteria.md +47 -0
- package/skills/omc-business-configuration.md +257 -0
- package/skills/omc-capabilities.md +197 -0
- package/skills/omc-capability-scouting.md +55 -0
- package/skills/omc-config-draft-review.md +171 -0
- package/skills/omc-five-piece-flow.md +35 -0
- package/skills/omc-glossary.md +86 -0
- package/skills/omc-refusals.md +110 -0
- package/skills/omc-requirement-analysis.md +161 -0
- package/skills/omc-requirement-vocabulary.md +51 -0
- package/skills/omc-start-here.md +82 -0
- package/skills/omc-tool-selection.md +119 -0
- package/skills/omc-write-hazards.md +87 -0
package/dist/call.js
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { openSync, readSync, closeSync } from "node:fs";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { buildToolRegistry, makeToolContext } from "./tools.js";
|
|
4
|
+
import { SessionManager } from "./session-manager.js";
|
|
5
|
+
import { ConfigStore, defaultPaths } from "./config-store.js";
|
|
6
|
+
import { redact } from "./redact.js";
|
|
7
|
+
import { assertSafeInputPath } from "./artifacts.js";
|
|
8
|
+
import { parseToolInput, ToolInputError } from "./tool-types.js";
|
|
9
|
+
import { absencePointer } from "./capability-absences.js";
|
|
10
|
+
export const CALL_EXIT_CODES = { ok: 0, failed: 1, unknownTool: 2, invalidInput: 10 };
|
|
11
|
+
export const CLI_ARGS_MAX_BYTES = 1024 * 1024;
|
|
12
|
+
function readBounded(fd, label) {
|
|
13
|
+
const chunks = [];
|
|
14
|
+
let total = 0;
|
|
15
|
+
try {
|
|
16
|
+
while (true) {
|
|
17
|
+
const remaining = CLI_ARGS_MAX_BYTES + 1 - total;
|
|
18
|
+
if (remaining <= 0)
|
|
19
|
+
throw new Error(`${label} exceeds ${CLI_ARGS_MAX_BYTES} bytes`);
|
|
20
|
+
const chunk = Buffer.alloc(Math.min(64 * 1024, remaining));
|
|
21
|
+
const bytes = readSync(fd, chunk, 0, chunk.length, null);
|
|
22
|
+
if (bytes === 0)
|
|
23
|
+
break;
|
|
24
|
+
total += bytes;
|
|
25
|
+
if (total > CLI_ARGS_MAX_BYTES)
|
|
26
|
+
throw new Error(`${label} exceeds ${CLI_ARGS_MAX_BYTES} bytes`);
|
|
27
|
+
chunks.push(chunk.subarray(0, bytes));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
finally {
|
|
31
|
+
if (fd !== 0)
|
|
32
|
+
closeSync(fd);
|
|
33
|
+
}
|
|
34
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
35
|
+
}
|
|
36
|
+
function parseJsonArgs(text, label) {
|
|
37
|
+
try {
|
|
38
|
+
const parsed = JSON.parse(text);
|
|
39
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
40
|
+
throw new Error(`${label} must be a JSON object`);
|
|
41
|
+
}
|
|
42
|
+
return parsed;
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
throw new Error(`${label}: ${error instanceof Error ? error.message : String(error)}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
export function readStdinArgs() {
|
|
49
|
+
return parseJsonArgs(readBounded(0, "--args -"), "--args -");
|
|
50
|
+
}
|
|
51
|
+
export function readArgsFile(path, root = resolve(process.env.OMC_CONFIG_HOME ?? process.cwd())) {
|
|
52
|
+
const safePath = assertSafeInputPath(root, path, "--args-file");
|
|
53
|
+
const fd = openSync(safePath, "r");
|
|
54
|
+
return parseJsonArgs(readBounded(fd, "--args-file"), "--args-file");
|
|
55
|
+
}
|
|
56
|
+
export async function runToolCall(toolName, options = {}) {
|
|
57
|
+
const print = options.print ?? ((line) => console.log(line));
|
|
58
|
+
const context = options.context ?? makeToolContext({ sessions: new SessionManager(new ConfigStore(defaultPaths())) });
|
|
59
|
+
const registry = buildToolRegistry();
|
|
60
|
+
const tool = registry.find((definition) => definition.name === toolName);
|
|
61
|
+
if (!tool) {
|
|
62
|
+
// Round 4: return the closest candidates, not the whole inventory. A live
|
|
63
|
+
// run burned a call on `model.exists` and then received every tool name.
|
|
64
|
+
const names = registry.map((definition) => definition.name);
|
|
65
|
+
const segment = toolName.split(".")[0] ?? toolName;
|
|
66
|
+
const candidates = names.filter((name) => name === segment || name.startsWith(`${segment}.`) || name.includes(toolName)).slice(0, 8);
|
|
67
|
+
// A requested operation the PLATFORM itself does not expose (e.g.
|
|
68
|
+
// dictionary.delete) must not read as an OMC gap: name the real recovery
|
|
69
|
+
// path and the documented absence instead of only the nearest tools.
|
|
70
|
+
const absence = absencePointer(toolName);
|
|
71
|
+
const result = {
|
|
72
|
+
status: "unknown-tool",
|
|
73
|
+
tool: toolName,
|
|
74
|
+
...(candidates.length > 0 ? { candidates } : {}),
|
|
75
|
+
...(absence ? { platformAbsence: absence.replace(/^;/, "") } : {}),
|
|
76
|
+
hint: "工具名见 `omc commands --json --compact --lane <lane>`;用 next/recipe 定位",
|
|
77
|
+
};
|
|
78
|
+
print(JSON.stringify(result, null, 2));
|
|
79
|
+
return { exitCode: CALL_EXIT_CODES.unknownTool, result };
|
|
80
|
+
}
|
|
81
|
+
let args = { ...(options.args ?? {}) };
|
|
82
|
+
if (options.environment && args.environment === undefined)
|
|
83
|
+
args.environment = options.environment;
|
|
84
|
+
if (options.requestId)
|
|
85
|
+
args.requestId = options.requestId;
|
|
86
|
+
if (options.dryRun)
|
|
87
|
+
args.dryRun = true;
|
|
88
|
+
try {
|
|
89
|
+
args = parseToolInput(tool, args);
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
const result = error instanceof ToolInputError ? error.payload : { status: "error", message: error instanceof Error ? error.message : String(error) };
|
|
93
|
+
print(redact(result, []));
|
|
94
|
+
return { exitCode: CALL_EXIT_CODES.invalidInput, result };
|
|
95
|
+
}
|
|
96
|
+
const invoke = async () => {
|
|
97
|
+
try {
|
|
98
|
+
return (await tool.handler(context, args, tool));
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
const payload = error.payload;
|
|
102
|
+
if (payload)
|
|
103
|
+
return payload;
|
|
104
|
+
return { status: "error", message: error instanceof Error ? error.message : String(error) };
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
const result = options.timeoutMs === undefined
|
|
108
|
+
? await invoke()
|
|
109
|
+
: await Promise.race([
|
|
110
|
+
invoke(),
|
|
111
|
+
new Promise((resolve) => setTimeout(() => resolve({ status: "uncertain", blocker: "cli-timeout", nextAction: "read back the requestId before retrying; retry only after the outcome is established", retryable: true }), options.timeoutMs)),
|
|
112
|
+
]);
|
|
113
|
+
// The stderr line is a human diagnostic, NOT a second copy of the result: the
|
|
114
|
+
// stdout envelope is the single machine truth. Dumping the whole result here
|
|
115
|
+
// doubled every call's payload on stderr (unbounded and un-sanitized — it also
|
|
116
|
+
// leaked the raw `detailFile` path; live 2026-09-25). Print the short summary a
|
|
117
|
+
// write already carries, or the (small) error payload; stay silent on a bare
|
|
118
|
+
// successful read.
|
|
119
|
+
const humanLine = humanResultLine(result);
|
|
120
|
+
if (humanLine !== null)
|
|
121
|
+
print(humanLine);
|
|
122
|
+
const status = String(result?.status ?? "ok");
|
|
123
|
+
const exitCode = status === "ok" ? CALL_EXIT_CODES.ok : result?.blocker === "tool-input-invalid" ? CALL_EXIT_CODES.invalidInput : CALL_EXIT_CODES.failed;
|
|
124
|
+
return { exitCode, result };
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* The single stderr diagnostic line for a call result, or null when the result
|
|
128
|
+
* is a bare success (the envelope already carries it). Errors keep their payload
|
|
129
|
+
* because it is small and useful; a write's `summary` is the human-facing line.
|
|
130
|
+
*/
|
|
131
|
+
function humanResultLine(result) {
|
|
132
|
+
if (typeof result.summary === "string" && result.summary.trim().length > 0)
|
|
133
|
+
return result.summary;
|
|
134
|
+
const status = String(result?.status ?? "ok");
|
|
135
|
+
if (status !== "ok")
|
|
136
|
+
return redact(result, []);
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
export function validateAgentPaths(args) {
|
|
140
|
+
const root = resolve(process.env.OMC_CONFIG_HOME ?? process.cwd());
|
|
141
|
+
const visit = (value, key) => {
|
|
142
|
+
if (key === "zipPath" && typeof value === "string")
|
|
143
|
+
assertSafeInputPath(root, value, "zipPath");
|
|
144
|
+
if (Array.isArray(value))
|
|
145
|
+
for (const entry of value)
|
|
146
|
+
visit(entry);
|
|
147
|
+
else if (value && typeof value === "object")
|
|
148
|
+
for (const [entryKey, entry] of Object.entries(value))
|
|
149
|
+
visit(entry, entryKey);
|
|
150
|
+
};
|
|
151
|
+
visit(args);
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=call.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const ABSENCES = [
|
|
2
|
+
{
|
|
3
|
+
requested: "dictionary.delete",
|
|
4
|
+
recovery: "omc call dictionary.status --args '{\"target\":\"dictionary\",\"id\":\"<dictionaryId>\",\"status\":false}',再对每条记录 dictionary.status target=record(停用后运行时 getEnableRecords* 返回空)",
|
|
5
|
+
evidence: "DataDictionaryController (cloudpivot-engine-8.6.26) 只有 saveDictionary / updateDictionaryStatus / deleteDictionaryClass(Batch);DictionaryFacade 的 deleteDictionaryRecord 无任何 controller 接线;apppackage/physically_delete 的 NodeType 分派只处理 Page/CustomPage/BizModel/Report,不含 DATA_DICTIONARY。管理端 UI 对字典本身只有「禁用」",
|
|
6
|
+
message: "平台没有删除数据字典的操作(只有启用/停用)。字典的清理手段是 dictionary.status 停用字典与记录",
|
|
7
|
+
},
|
|
8
|
+
];
|
|
9
|
+
const BY_REQUESTED = new Map(ABSENCES.map((entry) => [entry.requested, entry]));
|
|
10
|
+
/** The absence entry for a requested tool name, or undefined. Aliases resolve by exact name. */
|
|
11
|
+
export function capabilityAbsence(requested) {
|
|
12
|
+
const direct = BY_REQUESTED.get(requested);
|
|
13
|
+
if (direct)
|
|
14
|
+
return direct;
|
|
15
|
+
// Tolerate a family wildcard the caller may write loosely (dictionary.deleteDictionary, delete.dictionary…).
|
|
16
|
+
return ABSENCES.find((entry) => requested.includes(entry.requested) || (requested.startsWith("dictionary.") && requested.includes("delete")));
|
|
17
|
+
}
|
|
18
|
+
/** A `;…` suffix for an error message, or "" when the request names no known absence. */
|
|
19
|
+
export function absencePointer(requested) {
|
|
20
|
+
const entry = capabilityAbsence(requested);
|
|
21
|
+
return entry ? `;${entry.message}。改用 \`${entry.recovery}\`。证据:${entry.evidence}` : "";
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=capability-absences.js.map
|