@thinkingai/ae-cli 6.0.28 → 6.0.30
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/dist/capability-KVA55RMK.js +227 -0
- package/dist/capability-LKHLZQPD.js +227 -0
- package/dist/chunk-CWZUGF2J.js +26 -0
- package/dist/{chunk-YNQFYBDB.js → chunk-OJR23CIK.js} +12 -0
- package/dist/chunk-OO6XR6LK.js +26 -0
- package/dist/{chunk-C4DH76LX.js → chunk-P2JRP6HJ.js} +4 -21
- package/dist/{chunk-LG5YT7P7.js → chunk-S5XN6KEX.js} +4 -21
- package/dist/{chunk-BXMXMUD7.js → chunk-THBBNYXI.js} +12 -0
- package/dist/index.js +22 -11
- package/dist/{metadata-IPSPQBX3.js → metadata-6CCFV4K5.js} +11 -8
- package/dist/{metadata-N5REJ7R7.js → metadata-PDOIWH5O.js} +11 -8
- package/dist/{te-agent-QLIVKRUN.js → te-agent-FAIBM3SA.js} +5 -5
- package/dist/{te-analysis-5WZKVFHI.js → te-analysis-DDXGM7WM.js} +173 -260
- package/dist/{te-analysis-KAEZXLNS.js → te-analysis-HCDNYI7E.js} +173 -260
- package/dist/{te-audience-XMRMVD2V.js → te-audience-ECFS4GF4.js} +11 -10
- package/dist/{te-audience-PVMKQAFH.js → te-audience-WO377T2J.js} +11 -10
- package/dist/{te-engage-AGREUOW7.js → te-engage-545HJL6J.js} +4 -4
- package/dist/{te-engage-MIIUKY6M.js → te-engage-M7JQSJDP.js} +4 -4
- package/dist/{te-kb-KQJ53M3A.js → te-kb-NT33UHAE.js} +1 -1
- package/dist/{te-meta-QLANJ4B4.js → te-meta-FADFLTDM.js} +3 -3
- package/dist/{te-meta-TOA6FWDE.js → te-meta-PKT27OTN.js} +3 -3
- package/dist/{te-team-TQGMNHQQ.js → te-team-RG75PR5D.js} +1 -1
- package/package.json +2 -1
- package/skills/ae-agent/SKILL.md +4 -3
- package/skills/ae-analysis/SKILL.md +35 -16
- package/skills/ae-analysis/references/analysis_gateway_assets.md +42 -9
- package/skills/ae-analysis/references/asset_abnormal_get.md +3 -3
- package/skills/ae-analysis/references/asset_abnormal_list.md +3 -3
- package/skills/ae-analysis/references/asset_authentication_list.md +3 -3
- package/skills/ae-analysis/references/asset_authentication_update.md +3 -3
- package/skills/ae-analysis/references/asset_recent_list.md +3 -3
- package/skills/ae-analysis/references/asset_search.md +3 -3
- package/skills/ae-analysis/references/build_event_analysis_qp.md +1 -1
- package/skills/ae-analysis/references/build_funnel_analysis_qp.md +1 -1
- package/skills/ae-analysis/references/build_prop_analysis_qp.md +1 -1
- package/skills/ae-analysis/references/build_retention_analysis_qp.md +1 -1
- package/skills/ae-analysis/references/cancel_query.md +1 -1
- package/skills/ae-analysis/references/datatable_columns_get.md +3 -3
- package/skills/ae-analysis/references/datatable_influence_list.md +3 -3
- package/skills/ae-analysis/references/datatable_version_get.md +3 -3
- package/skills/ae-analysis/references/datatable_version_list.md +3 -3
- package/skills/ae-analysis/references/drilldown_user_events.md +4 -4
- package/skills/ae-analysis/references/event_changelog_list.md +3 -3
- package/skills/ae-analysis/references/event_create.md +3 -3
- package/skills/ae-analysis/references/event_delete.md +3 -3
- package/skills/ae-analysis/references/event_get.md +3 -3
- package/skills/ae-analysis/references/event_hide_update.md +3 -3
- package/skills/ae-analysis/references/event_influence_list.md +3 -3
- package/skills/ae-analysis/references/event_list.md +3 -3
- package/skills/ae-analysis/references/event_relation_update.md +3 -3
- package/skills/ae-analysis/references/event_update.md +3 -3
- package/skills/ae-analysis/references/exchange_config_update.md +3 -3
- package/skills/ae-analysis/references/exchange_rate_refresh.md +3 -3
- package/skills/ae-analysis/references/exchange_rule_list.md +3 -3
- package/skills/ae-analysis/references/exchange_rule_update.md +3 -3
- package/skills/ae-analysis/references/exchange_rule_validate.md +3 -3
- package/skills/ae-analysis/references/folder_create.md +18 -6
- package/skills/ae-analysis/references/folder_delete.md +21 -6
- package/skills/ae-analysis/references/folder_share.md +16 -6
- package/skills/ae-analysis/references/get_analysis_query_schema.md +17 -18
- package/skills/ae-analysis/references/get_report_definition.md +1 -1
- package/skills/ae-analysis/references/list_events.md +1 -1
- package/skills/ae-analysis/references/list_metrics.md +1 -1
- package/skills/ae-analysis/references/list_properties.md +1 -1
- package/skills/ae-analysis/references/metric_create.md +3 -3
- package/skills/ae-analysis/references/metric_delete.md +3 -3
- package/skills/ae-analysis/references/metric_get.md +3 -3
- package/skills/ae-analysis/references/metric_list.md +3 -3
- package/skills/ae-analysis/references/metric_update.md +3 -3
- package/skills/ae-analysis/references/project_space_create.md +19 -5
- package/skills/ae-analysis/references/project_space_delete.md +23 -6
- package/skills/ae-analysis/references/project_space_share.md +16 -6
- package/skills/ae-analysis/references/property_changelog_list.md +3 -3
- package/skills/ae-analysis/references/property_create.md +3 -3
- package/skills/ae-analysis/references/property_delete.md +3 -3
- package/skills/ae-analysis/references/property_get.md +3 -3
- package/skills/ae-analysis/references/property_hide_update.md +3 -3
- package/skills/ae-analysis/references/property_influence_list.md +3 -3
- package/skills/ae-analysis/references/property_list.md +3 -3
- package/skills/ae-analysis/references/property_related_events.md +3 -3
- package/skills/ae-analysis/references/property_relation_update.md +3 -3
- package/skills/ae-analysis/references/property_update.md +3 -3
- package/skills/ae-analysis/references/query_adhoc.md +34 -21
- package/skills/ae-analysis/references/super_metadata_export.md +4 -4
- package/skills/ae-analysis/references/super_metadata_import.md +3 -3
- package/skills/ae-analysis/references/update_report.md +3 -3
- package/skills/ae-analysis/references/virtual_event_create.md +3 -3
- package/skills/ae-analysis/references/virtual_event_delete.md +3 -3
- package/skills/ae-analysis/references/virtual_event_get.md +3 -3
- package/skills/ae-analysis/references/virtual_property_create.md +3 -3
- package/skills/ae-analysis/references/virtual_property_sql_rule_delete.md +3 -3
- package/skills/ae-analysis/references/virtual_property_sql_rule_update.md +3 -3
- package/skills/ae-capability/SKILL.md +103 -0
- package/skills/ae-community/SKILL.md +1 -1
- package/skills/ae-data-integration-helper/SKILL.md +1 -1
- package/skills/ae-dataops/references/dataops-integration.md +3 -3
- package/skills/ae-engage/SKILL.md +5 -5
- package/skills/ae-generate-tracking-code/SKILL.md +1 -1
- package/skills/ae-generate-tracking-plan/SKILL.md +1 -1
- package/skills/ae-metadata/references/metadata_data_table_sql_write.md +60 -8
- package/skills/ae-team/SKILL.md +1 -1
- package/skills/ae-analysis/references/folder_members.md +0 -15
- package/skills/ae-analysis/references/project_space_members.md +0 -15
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import {
|
|
2
|
+
normalizeRiskLevel,
|
|
3
|
+
requiresConfirmation
|
|
4
|
+
} from "./chunk-OO6XR6LK.js";
|
|
5
|
+
import {
|
|
6
|
+
printError,
|
|
7
|
+
printOutput
|
|
8
|
+
} from "./chunk-ZAOL36CG.js";
|
|
9
|
+
import {
|
|
10
|
+
findGatewayDomain
|
|
11
|
+
} from "./chunk-CWZUGF2J.js";
|
|
12
|
+
import {
|
|
13
|
+
CapabilityGatewayError,
|
|
14
|
+
dryRunCapability,
|
|
15
|
+
executeCapability,
|
|
16
|
+
inspectCapability,
|
|
17
|
+
listCapabilities
|
|
18
|
+
} from "./chunk-OJR23CIK.js";
|
|
19
|
+
import {
|
|
20
|
+
PermissionError
|
|
21
|
+
} from "./chunk-NOO24N7W.js";
|
|
22
|
+
import "./chunk-2NDGFQHW.js";
|
|
23
|
+
import {
|
|
24
|
+
SecureStoreAuthError,
|
|
25
|
+
resolveHost
|
|
26
|
+
} from "./chunk-AJTH7LT3.js";
|
|
27
|
+
import {
|
|
28
|
+
safeJsonParse
|
|
29
|
+
} from "./chunk-YCLVYFK7.js";
|
|
30
|
+
|
|
31
|
+
// src/commands/capability/index.ts
|
|
32
|
+
import * as readline from "readline";
|
|
33
|
+
|
|
34
|
+
// src/commands/capability/helpers.ts
|
|
35
|
+
import { readFileSync } from "fs";
|
|
36
|
+
var CapabilityCommandValidationError = class extends Error {
|
|
37
|
+
constructor(message, hint) {
|
|
38
|
+
super(message);
|
|
39
|
+
this.hint = hint;
|
|
40
|
+
this.name = "CapabilityCommandValidationError";
|
|
41
|
+
}
|
|
42
|
+
hint;
|
|
43
|
+
};
|
|
44
|
+
function capabilityNamespace(capabilityId) {
|
|
45
|
+
return capabilityId.split(".")[0] ?? "";
|
|
46
|
+
}
|
|
47
|
+
function resolveCapabilityGatewayDomain(capabilityId, domainOverride) {
|
|
48
|
+
const cliDomain = domainOverride?.trim() || capabilityNamespace(capabilityId);
|
|
49
|
+
if (!cliDomain) {
|
|
50
|
+
throw new CapabilityCommandValidationError(
|
|
51
|
+
"Cannot determine the capability domain.",
|
|
52
|
+
"Pass --domain <domain>."
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
return findGatewayDomain(cliDomain) ?? cliDomain;
|
|
56
|
+
}
|
|
57
|
+
function normalizeCapabilityList(value) {
|
|
58
|
+
if (!Array.isArray(value)) {
|
|
59
|
+
throw new Error("Capability gateway returned an invalid catalog: expected an array.");
|
|
60
|
+
}
|
|
61
|
+
return value.filter((item) => {
|
|
62
|
+
return item !== null && typeof item === "object" && typeof item.id === "string";
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
function filterCapabilities(capabilities, domain, query) {
|
|
66
|
+
const prefix = `${domain.toLowerCase()}.`;
|
|
67
|
+
const terms = query?.trim().toLowerCase().split(/\s+/).filter(Boolean) ?? [];
|
|
68
|
+
return capabilities.filter((capability) => {
|
|
69
|
+
if (!capability.id.toLowerCase().startsWith(prefix)) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
if (terms.length === 0) {
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
const searchable = `${capability.id} ${capability.description ?? ""}`.toLowerCase();
|
|
76
|
+
return terms.every((term) => searchable.includes(term));
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
function parseCapabilityInput(raw) {
|
|
80
|
+
if (!raw) {
|
|
81
|
+
return {};
|
|
82
|
+
}
|
|
83
|
+
const trimmed = raw.trim();
|
|
84
|
+
let parsed;
|
|
85
|
+
try {
|
|
86
|
+
if (trimmed === "-") {
|
|
87
|
+
parsed = safeJsonParse(readFileSync(0, "utf8"));
|
|
88
|
+
} else if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
|
|
89
|
+
parsed = safeJsonParse(trimmed);
|
|
90
|
+
} else {
|
|
91
|
+
const path = trimmed.startsWith("@") ? trimmed.slice(1) : trimmed;
|
|
92
|
+
parsed = safeJsonParse(readFileSync(path, "utf8"));
|
|
93
|
+
}
|
|
94
|
+
} catch (error) {
|
|
95
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
96
|
+
throw new CapabilityCommandValidationError(
|
|
97
|
+
`Invalid capability input: ${message}`,
|
|
98
|
+
"Pass an inline JSON object, a JSON file path, @<path>, or - for stdin."
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
102
|
+
throw new CapabilityCommandValidationError(
|
|
103
|
+
"Capability input must be a JSON object.",
|
|
104
|
+
`Example: --input '{"project_id":1}'`
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
return parsed;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// src/commands/capability/index.ts
|
|
111
|
+
function registerCapability(program) {
|
|
112
|
+
const capability = program.command("capability").description("Discover and invoke capability gateway operations").action(() => {
|
|
113
|
+
printError("validation", "Missing subcommand.", "Run: ae-cli capability --help");
|
|
114
|
+
process.exitCode = 1;
|
|
115
|
+
});
|
|
116
|
+
capability.command("list").description("List capability summaries in a domain").requiredOption("--domain <domain>", "Capability namespace, such as analysis or metadata").action(async (opts) => {
|
|
117
|
+
await executeAndPrint(program, async (host) => {
|
|
118
|
+
const gatewayDomain = findGatewayDomain(opts.domain) ?? opts.domain;
|
|
119
|
+
const catalog = normalizeCapabilityList(await listCapabilities(host, gatewayDomain));
|
|
120
|
+
const capabilities = filterCapabilities(catalog, opts.domain);
|
|
121
|
+
return { domain: opts.domain, count: capabilities.length, capabilities };
|
|
122
|
+
});
|
|
123
|
+
}).addHelpText("after", "\nExample:\n ae-cli capability list --domain analysis");
|
|
124
|
+
capability.command("search").description("Search capability IDs and descriptions in a domain").argument("<query>", "Case-insensitive search terms").requiredOption("--domain <domain>", "Capability namespace, such as analysis or metadata").action(async (query, opts) => {
|
|
125
|
+
await executeAndPrint(program, async (host) => {
|
|
126
|
+
const gatewayDomain = findGatewayDomain(opts.domain) ?? opts.domain;
|
|
127
|
+
const catalog = normalizeCapabilityList(await listCapabilities(host, gatewayDomain));
|
|
128
|
+
const capabilities = filterCapabilities(catalog, opts.domain, query);
|
|
129
|
+
return { domain: opts.domain, query, count: capabilities.length, capabilities };
|
|
130
|
+
});
|
|
131
|
+
}).addHelpText("after", '\nExample:\n ae-cli capability search "dashboard list" --domain analysis');
|
|
132
|
+
capability.command("inspect").description("Inspect one capability schema, risk, auth, and output metadata").argument("<capability-id>", "Capability ID, such as analysis.report.list").option("--domain <domain>", "Override the capability namespace used for gateway routing").action(async (capabilityId, opts) => {
|
|
133
|
+
await executeAndPrint(program, async (host) => {
|
|
134
|
+
const gatewayDomain = resolveCapabilityGatewayDomain(capabilityId, opts.domain);
|
|
135
|
+
return inspectCapability(host, gatewayDomain, capabilityId);
|
|
136
|
+
});
|
|
137
|
+
}).addHelpText("after", "\nExample:\n ae-cli capability inspect analysis.dashboard.list");
|
|
138
|
+
capability.command("dry-run").description("Validate and preview one capability invocation without executing it").argument("<capability-id>", "Capability ID, such as analysis.query.export").option("--domain <domain>", "Override the capability namespace used for gateway routing").option("--input <json-or-path>", "Input JSON object, file path, @<path>, or - for stdin").action(async (capabilityId, opts) => {
|
|
139
|
+
await executeAndPrint(program, async (host) => {
|
|
140
|
+
const gatewayDomain = resolveCapabilityGatewayDomain(capabilityId, opts.domain);
|
|
141
|
+
return dryRunCapability(host, gatewayDomain, capabilityId, parseCapabilityInput(opts.input));
|
|
142
|
+
});
|
|
143
|
+
}).addHelpText(
|
|
144
|
+
"after",
|
|
145
|
+
`
|
|
146
|
+
Examples:
|
|
147
|
+
ae-cli capability dry-run analysis.dashboard.list --input '{"project_id":1}'
|
|
148
|
+
ae-cli capability dry-run analysis.dashboard.list --input input.json`
|
|
149
|
+
);
|
|
150
|
+
capability.command("run").description("Execute one capability by ID").argument("<capability-id>", "Capability ID, such as analysis.report.list").option("--domain <domain>", "Override the capability namespace used for gateway routing").option("--input <json-or-path>", "Input JSON object, file path, @<path>, or - for stdin").action(async (capabilityId, opts) => {
|
|
151
|
+
await executeAndPrint(program, async (host, globalOpts) => {
|
|
152
|
+
const gatewayDomain = resolveCapabilityGatewayDomain(capabilityId, opts.domain);
|
|
153
|
+
const input = parseCapabilityInput(opts.input);
|
|
154
|
+
if (globalOpts.dryRun) {
|
|
155
|
+
return dryRunCapability(host, gatewayDomain, capabilityId, input);
|
|
156
|
+
}
|
|
157
|
+
if (!globalOpts.yes) {
|
|
158
|
+
const metadata = await inspectCapability(host, gatewayDomain, capabilityId);
|
|
159
|
+
const risk = normalizeRiskLevel(typeof metadata?.risk === "string" ? metadata.risk : void 0);
|
|
160
|
+
if (requiresConfirmation(risk)) {
|
|
161
|
+
const confirmed = await confirm(`This capability is marked ${risk} (${capabilityId}). Continue?`);
|
|
162
|
+
if (!confirmed) {
|
|
163
|
+
process.stderr.write("Aborted.\n");
|
|
164
|
+
return void 0;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return executeCapability(host, gatewayDomain, capabilityId, input);
|
|
169
|
+
});
|
|
170
|
+
}).addHelpText(
|
|
171
|
+
"after",
|
|
172
|
+
`
|
|
173
|
+
Examples:
|
|
174
|
+
ae-cli capability run analysis.dashboard.list --input '{"project_id":1}'
|
|
175
|
+
ae-cli capability run analysis.dashboard.list --input input.json --yes`
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
async function executeAndPrint(program, action) {
|
|
179
|
+
const globalOpts = program.opts();
|
|
180
|
+
const host = resolveHost(globalOpts.host);
|
|
181
|
+
if (!host) {
|
|
182
|
+
printError("config", "No AE host configured.", "Run: ae-cli config set-host <url>");
|
|
183
|
+
process.exitCode = 1;
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
try {
|
|
187
|
+
const result = await action(host, globalOpts);
|
|
188
|
+
if (result !== void 0) {
|
|
189
|
+
printOutput(result, globalOpts.format ?? "json", globalOpts.jq);
|
|
190
|
+
}
|
|
191
|
+
} catch (error) {
|
|
192
|
+
printCapabilityError(error);
|
|
193
|
+
process.exitCode = 1;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
function printCapabilityError(error) {
|
|
197
|
+
if (error instanceof CapabilityCommandValidationError) {
|
|
198
|
+
printError("validation", error.message, error.hint);
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
if (error instanceof SecureStoreAuthError) {
|
|
202
|
+
printError("auth", error.message, "Run: ae-cli auth login");
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
if (error instanceof PermissionError) {
|
|
206
|
+
printError("permission", error.message);
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
if (error instanceof CapabilityGatewayError) {
|
|
210
|
+
printError("api", error.message, error.hint, error.code);
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
214
|
+
printError("api", message);
|
|
215
|
+
}
|
|
216
|
+
async function confirm(message) {
|
|
217
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
|
|
218
|
+
return new Promise((resolve) => {
|
|
219
|
+
rl.question(`${message} [y/N] `, (answer) => {
|
|
220
|
+
rl.close();
|
|
221
|
+
resolve(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
export {
|
|
226
|
+
registerCapability
|
|
227
|
+
};
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import {
|
|
2
|
+
normalizeRiskLevel,
|
|
3
|
+
requiresConfirmation
|
|
4
|
+
} from "./chunk-OO6XR6LK.js";
|
|
5
|
+
import {
|
|
6
|
+
printError,
|
|
7
|
+
printOutput
|
|
8
|
+
} from "./chunk-ZAOL36CG.js";
|
|
9
|
+
import {
|
|
10
|
+
findGatewayDomain
|
|
11
|
+
} from "./chunk-CWZUGF2J.js";
|
|
12
|
+
import {
|
|
13
|
+
CapabilityGatewayError,
|
|
14
|
+
dryRunCapability,
|
|
15
|
+
executeCapability,
|
|
16
|
+
inspectCapability,
|
|
17
|
+
listCapabilities
|
|
18
|
+
} from "./chunk-THBBNYXI.js";
|
|
19
|
+
import {
|
|
20
|
+
PermissionError
|
|
21
|
+
} from "./chunk-NOO24N7W.js";
|
|
22
|
+
import "./chunk-2NDGFQHW.js";
|
|
23
|
+
import {
|
|
24
|
+
SecureStoreAuthError,
|
|
25
|
+
resolveHost
|
|
26
|
+
} from "./chunk-AJTH7LT3.js";
|
|
27
|
+
import {
|
|
28
|
+
safeJsonParse
|
|
29
|
+
} from "./chunk-YCLVYFK7.js";
|
|
30
|
+
|
|
31
|
+
// src/commands/capability/index.ts
|
|
32
|
+
import * as readline from "readline";
|
|
33
|
+
|
|
34
|
+
// src/commands/capability/helpers.ts
|
|
35
|
+
import { readFileSync } from "fs";
|
|
36
|
+
var CapabilityCommandValidationError = class extends Error {
|
|
37
|
+
constructor(message, hint) {
|
|
38
|
+
super(message);
|
|
39
|
+
this.hint = hint;
|
|
40
|
+
this.name = "CapabilityCommandValidationError";
|
|
41
|
+
}
|
|
42
|
+
hint;
|
|
43
|
+
};
|
|
44
|
+
function capabilityNamespace(capabilityId) {
|
|
45
|
+
return capabilityId.split(".")[0] ?? "";
|
|
46
|
+
}
|
|
47
|
+
function resolveCapabilityGatewayDomain(capabilityId, domainOverride) {
|
|
48
|
+
const cliDomain = domainOverride?.trim() || capabilityNamespace(capabilityId);
|
|
49
|
+
if (!cliDomain) {
|
|
50
|
+
throw new CapabilityCommandValidationError(
|
|
51
|
+
"Cannot determine the capability domain.",
|
|
52
|
+
"Pass --domain <domain>."
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
return findGatewayDomain(cliDomain) ?? cliDomain;
|
|
56
|
+
}
|
|
57
|
+
function normalizeCapabilityList(value) {
|
|
58
|
+
if (!Array.isArray(value)) {
|
|
59
|
+
throw new Error("Capability gateway returned an invalid catalog: expected an array.");
|
|
60
|
+
}
|
|
61
|
+
return value.filter((item) => {
|
|
62
|
+
return item !== null && typeof item === "object" && typeof item.id === "string";
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
function filterCapabilities(capabilities, domain, query) {
|
|
66
|
+
const prefix = `${domain.toLowerCase()}.`;
|
|
67
|
+
const terms = query?.trim().toLowerCase().split(/\s+/).filter(Boolean) ?? [];
|
|
68
|
+
return capabilities.filter((capability) => {
|
|
69
|
+
if (!capability.id.toLowerCase().startsWith(prefix)) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
if (terms.length === 0) {
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
const searchable = `${capability.id} ${capability.description ?? ""}`.toLowerCase();
|
|
76
|
+
return terms.every((term) => searchable.includes(term));
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
function parseCapabilityInput(raw) {
|
|
80
|
+
if (!raw) {
|
|
81
|
+
return {};
|
|
82
|
+
}
|
|
83
|
+
const trimmed = raw.trim();
|
|
84
|
+
let parsed;
|
|
85
|
+
try {
|
|
86
|
+
if (trimmed === "-") {
|
|
87
|
+
parsed = safeJsonParse(readFileSync(0, "utf8"));
|
|
88
|
+
} else if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
|
|
89
|
+
parsed = safeJsonParse(trimmed);
|
|
90
|
+
} else {
|
|
91
|
+
const path = trimmed.startsWith("@") ? trimmed.slice(1) : trimmed;
|
|
92
|
+
parsed = safeJsonParse(readFileSync(path, "utf8"));
|
|
93
|
+
}
|
|
94
|
+
} catch (error) {
|
|
95
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
96
|
+
throw new CapabilityCommandValidationError(
|
|
97
|
+
`Invalid capability input: ${message}`,
|
|
98
|
+
"Pass an inline JSON object, a JSON file path, @<path>, or - for stdin."
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
102
|
+
throw new CapabilityCommandValidationError(
|
|
103
|
+
"Capability input must be a JSON object.",
|
|
104
|
+
`Example: --input '{"project_id":1}'`
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
return parsed;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// src/commands/capability/index.ts
|
|
111
|
+
function registerCapability(program) {
|
|
112
|
+
const capability = program.command("capability").description("Discover and invoke capability gateway operations").action(() => {
|
|
113
|
+
printError("validation", "Missing subcommand.", "Run: ae-cli capability --help");
|
|
114
|
+
process.exitCode = 1;
|
|
115
|
+
});
|
|
116
|
+
capability.command("list").description("List capability summaries in a domain").requiredOption("--domain <domain>", "Capability namespace, such as analysis or metadata").action(async (opts) => {
|
|
117
|
+
await executeAndPrint(program, async (host) => {
|
|
118
|
+
const gatewayDomain = findGatewayDomain(opts.domain) ?? opts.domain;
|
|
119
|
+
const catalog = normalizeCapabilityList(await listCapabilities(host, gatewayDomain));
|
|
120
|
+
const capabilities = filterCapabilities(catalog, opts.domain);
|
|
121
|
+
return { domain: opts.domain, count: capabilities.length, capabilities };
|
|
122
|
+
});
|
|
123
|
+
}).addHelpText("after", "\nExample:\n ae-cli capability list --domain analysis");
|
|
124
|
+
capability.command("search").description("Search capability IDs and descriptions in a domain").argument("<query>", "Case-insensitive search terms").requiredOption("--domain <domain>", "Capability namespace, such as analysis or metadata").action(async (query, opts) => {
|
|
125
|
+
await executeAndPrint(program, async (host) => {
|
|
126
|
+
const gatewayDomain = findGatewayDomain(opts.domain) ?? opts.domain;
|
|
127
|
+
const catalog = normalizeCapabilityList(await listCapabilities(host, gatewayDomain));
|
|
128
|
+
const capabilities = filterCapabilities(catalog, opts.domain, query);
|
|
129
|
+
return { domain: opts.domain, query, count: capabilities.length, capabilities };
|
|
130
|
+
});
|
|
131
|
+
}).addHelpText("after", '\nExample:\n ae-cli capability search "dashboard list" --domain analysis');
|
|
132
|
+
capability.command("inspect").description("Inspect one capability schema, risk, auth, and output metadata").argument("<capability-id>", "Capability ID, such as analysis.report.list").option("--domain <domain>", "Override the capability namespace used for gateway routing").action(async (capabilityId, opts) => {
|
|
133
|
+
await executeAndPrint(program, async (host) => {
|
|
134
|
+
const gatewayDomain = resolveCapabilityGatewayDomain(capabilityId, opts.domain);
|
|
135
|
+
return inspectCapability(host, gatewayDomain, capabilityId);
|
|
136
|
+
});
|
|
137
|
+
}).addHelpText("after", "\nExample:\n ae-cli capability inspect analysis.dashboard.list");
|
|
138
|
+
capability.command("dry-run").description("Validate and preview one capability invocation without executing it").argument("<capability-id>", "Capability ID, such as analysis.query.export").option("--domain <domain>", "Override the capability namespace used for gateway routing").option("--input <json-or-path>", "Input JSON object, file path, @<path>, or - for stdin").action(async (capabilityId, opts) => {
|
|
139
|
+
await executeAndPrint(program, async (host) => {
|
|
140
|
+
const gatewayDomain = resolveCapabilityGatewayDomain(capabilityId, opts.domain);
|
|
141
|
+
return dryRunCapability(host, gatewayDomain, capabilityId, parseCapabilityInput(opts.input));
|
|
142
|
+
});
|
|
143
|
+
}).addHelpText(
|
|
144
|
+
"after",
|
|
145
|
+
`
|
|
146
|
+
Examples:
|
|
147
|
+
ae-cli capability dry-run analysis.dashboard.list --input '{"project_id":1}'
|
|
148
|
+
ae-cli capability dry-run analysis.dashboard.list --input input.json`
|
|
149
|
+
);
|
|
150
|
+
capability.command("run").description("Execute one capability by ID").argument("<capability-id>", "Capability ID, such as analysis.report.list").option("--domain <domain>", "Override the capability namespace used for gateway routing").option("--input <json-or-path>", "Input JSON object, file path, @<path>, or - for stdin").action(async (capabilityId, opts) => {
|
|
151
|
+
await executeAndPrint(program, async (host, globalOpts) => {
|
|
152
|
+
const gatewayDomain = resolveCapabilityGatewayDomain(capabilityId, opts.domain);
|
|
153
|
+
const input = parseCapabilityInput(opts.input);
|
|
154
|
+
if (globalOpts.dryRun) {
|
|
155
|
+
return dryRunCapability(host, gatewayDomain, capabilityId, input);
|
|
156
|
+
}
|
|
157
|
+
if (!globalOpts.yes) {
|
|
158
|
+
const metadata = await inspectCapability(host, gatewayDomain, capabilityId);
|
|
159
|
+
const risk = normalizeRiskLevel(typeof metadata?.risk === "string" ? metadata.risk : void 0);
|
|
160
|
+
if (requiresConfirmation(risk)) {
|
|
161
|
+
const confirmed = await confirm(`This capability is marked ${risk} (${capabilityId}). Continue?`);
|
|
162
|
+
if (!confirmed) {
|
|
163
|
+
process.stderr.write("Aborted.\n");
|
|
164
|
+
return void 0;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return executeCapability(host, gatewayDomain, capabilityId, input);
|
|
169
|
+
});
|
|
170
|
+
}).addHelpText(
|
|
171
|
+
"after",
|
|
172
|
+
`
|
|
173
|
+
Examples:
|
|
174
|
+
ae-cli capability run analysis.dashboard.list --input '{"project_id":1}'
|
|
175
|
+
ae-cli capability run analysis.dashboard.list --input input.json --yes`
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
async function executeAndPrint(program, action) {
|
|
179
|
+
const globalOpts = program.opts();
|
|
180
|
+
const host = resolveHost(globalOpts.host);
|
|
181
|
+
if (!host) {
|
|
182
|
+
printError("config", "No AE host configured.", "Run: ae-cli config set-host <url>");
|
|
183
|
+
process.exitCode = 1;
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
try {
|
|
187
|
+
const result = await action(host, globalOpts);
|
|
188
|
+
if (result !== void 0) {
|
|
189
|
+
printOutput(result, globalOpts.format ?? "json", globalOpts.jq);
|
|
190
|
+
}
|
|
191
|
+
} catch (error) {
|
|
192
|
+
printCapabilityError(error);
|
|
193
|
+
process.exitCode = 1;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
function printCapabilityError(error) {
|
|
197
|
+
if (error instanceof CapabilityCommandValidationError) {
|
|
198
|
+
printError("validation", error.message, error.hint);
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
if (error instanceof SecureStoreAuthError) {
|
|
202
|
+
printError("auth", error.message, "Run: ae-cli auth login");
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
if (error instanceof PermissionError) {
|
|
206
|
+
printError("permission", error.message);
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
if (error instanceof CapabilityGatewayError) {
|
|
210
|
+
printError("api", error.message, error.hint, error.code);
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
214
|
+
printError("api", message);
|
|
215
|
+
}
|
|
216
|
+
async function confirm(message) {
|
|
217
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
|
|
218
|
+
return new Promise((resolve) => {
|
|
219
|
+
rl.question(`${message} [y/N] `, (answer) => {
|
|
220
|
+
rl.close();
|
|
221
|
+
resolve(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
export {
|
|
226
|
+
registerCapability
|
|
227
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// src/core/capability-routing.ts
|
|
2
|
+
var cliServiceRoutes = /* @__PURE__ */ new Map();
|
|
3
|
+
function registerCapabilityGatewayRoute(cliService, route) {
|
|
4
|
+
cliServiceRoutes.set(cliService, route);
|
|
5
|
+
}
|
|
6
|
+
function findGatewayDomain(cliService) {
|
|
7
|
+
return cliServiceRoutes.get(cliService)?.gatewayDomain;
|
|
8
|
+
}
|
|
9
|
+
function resolveGatewayDomain(cliService, override) {
|
|
10
|
+
if (override !== void 0) {
|
|
11
|
+
return override;
|
|
12
|
+
}
|
|
13
|
+
const route = cliServiceRoutes.get(cliService);
|
|
14
|
+
if (!route) {
|
|
15
|
+
throw new Error(
|
|
16
|
+
`Capability gateway route not registered for CLI service '${cliService}'. Call registerCapabilityGatewayRoute() in commands/${cliService}/index.ts.`
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
return route.gatewayDomain;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export {
|
|
23
|
+
registerCapabilityGatewayRoute,
|
|
24
|
+
findGatewayDomain,
|
|
25
|
+
resolveGatewayDomain
|
|
26
|
+
};
|
|
@@ -159,9 +159,18 @@ async function callGateway(host, domain, pathAfterV1, method, body) {
|
|
|
159
159
|
}
|
|
160
160
|
return unwrapCapabilityEnvelope(parseCapabilityResponse(await resp.text()));
|
|
161
161
|
}
|
|
162
|
+
async function listCapabilities(host, domain) {
|
|
163
|
+
return callGateway(host, domain, "capabilities", "GET");
|
|
164
|
+
}
|
|
165
|
+
async function inspectCapability(host, domain, capabilityId) {
|
|
166
|
+
return callGateway(host, domain, `capabilities/${capabilityId}`, "GET");
|
|
167
|
+
}
|
|
162
168
|
async function executeCapability(host, domain, capabilityId, input = {}) {
|
|
163
169
|
return callGateway(host, domain, `capabilities/${capabilityId}/execute`, "POST", { input });
|
|
164
170
|
}
|
|
171
|
+
async function dryRunCapability(host, domain, capabilityId, input = {}) {
|
|
172
|
+
return callGateway(host, domain, `capabilities/${capabilityId}/dry-run`, "POST", { input });
|
|
173
|
+
}
|
|
165
174
|
async function uploadInputFile(host, domain, projectId, purpose, filePath) {
|
|
166
175
|
const fileBytes = await readFile(filePath);
|
|
167
176
|
return uploadInputFileBytes(host, domain, projectId, purpose, fileBytes, basename(filePath));
|
|
@@ -243,7 +252,10 @@ async function callCapabilityApi(host, domain, action, method = "POST", params =
|
|
|
243
252
|
export {
|
|
244
253
|
CapabilityGatewayError,
|
|
245
254
|
buildCapabilityGatewayUrl,
|
|
255
|
+
listCapabilities,
|
|
256
|
+
inspectCapability,
|
|
246
257
|
executeCapability,
|
|
258
|
+
dryRunCapability,
|
|
247
259
|
uploadInputFile,
|
|
248
260
|
uploadInputFileBytes,
|
|
249
261
|
downloadCapabilityArtifact,
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// src/core/capability-risk.ts
|
|
2
|
+
var HIGH_RISK_LEVELS = /* @__PURE__ */ new Set(["high-risk-write"]);
|
|
3
|
+
function normalizeRiskLevel(risk) {
|
|
4
|
+
switch (risk) {
|
|
5
|
+
case "read":
|
|
6
|
+
return "read";
|
|
7
|
+
case "high-risk-write":
|
|
8
|
+
return "high-risk-write";
|
|
9
|
+
case "delete":
|
|
10
|
+
return "high-risk-write";
|
|
11
|
+
case "create":
|
|
12
|
+
case "update":
|
|
13
|
+
case "write":
|
|
14
|
+
return "write";
|
|
15
|
+
default:
|
|
16
|
+
return "write";
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function requiresConfirmation(risk) {
|
|
20
|
+
return HIGH_RISK_LEVELS.has(normalizeRiskLevel(risk));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export {
|
|
24
|
+
normalizeRiskLevel,
|
|
25
|
+
requiresConfirmation
|
|
26
|
+
};
|
|
@@ -1,25 +1,10 @@
|
|
|
1
|
+
import {
|
|
2
|
+
resolveGatewayDomain
|
|
3
|
+
} from "./chunk-CWZUGF2J.js";
|
|
1
4
|
import {
|
|
2
5
|
buildCapabilityGatewayUrl,
|
|
3
6
|
executeCapability
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
|
|
6
|
-
// src/core/capability-routing.ts
|
|
7
|
-
var cliServiceRoutes = /* @__PURE__ */ new Map();
|
|
8
|
-
function registerCapabilityGatewayRoute(cliService, route) {
|
|
9
|
-
cliServiceRoutes.set(cliService, route);
|
|
10
|
-
}
|
|
11
|
-
function resolveGatewayDomain(cliService, override) {
|
|
12
|
-
if (override !== void 0) {
|
|
13
|
-
return override;
|
|
14
|
-
}
|
|
15
|
-
const route = cliServiceRoutes.get(cliService);
|
|
16
|
-
if (!route) {
|
|
17
|
-
throw new Error(
|
|
18
|
-
`Capability gateway route not registered for CLI service '${cliService}'. Call registerCapabilityGatewayRoute() in commands/${cliService}/index.ts.`
|
|
19
|
-
);
|
|
20
|
-
}
|
|
21
|
-
return route.gatewayDomain;
|
|
22
|
-
}
|
|
7
|
+
} from "./chunk-THBBNYXI.js";
|
|
23
8
|
|
|
24
9
|
// src/core/capability-command.ts
|
|
25
10
|
function createCapabilityCommand(config) {
|
|
@@ -53,7 +38,5 @@ function createCapabilityCommand(config) {
|
|
|
53
38
|
}
|
|
54
39
|
|
|
55
40
|
export {
|
|
56
|
-
registerCapabilityGatewayRoute,
|
|
57
|
-
resolveGatewayDomain,
|
|
58
41
|
createCapabilityCommand
|
|
59
42
|
};
|
|
@@ -1,25 +1,10 @@
|
|
|
1
|
+
import {
|
|
2
|
+
resolveGatewayDomain
|
|
3
|
+
} from "./chunk-CWZUGF2J.js";
|
|
1
4
|
import {
|
|
2
5
|
buildCapabilityGatewayUrl,
|
|
3
6
|
executeCapability
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
|
|
6
|
-
// src/core/capability-routing.ts
|
|
7
|
-
var cliServiceRoutes = /* @__PURE__ */ new Map();
|
|
8
|
-
function registerCapabilityGatewayRoute(cliService, route) {
|
|
9
|
-
cliServiceRoutes.set(cliService, route);
|
|
10
|
-
}
|
|
11
|
-
function resolveGatewayDomain(cliService, override) {
|
|
12
|
-
if (override !== void 0) {
|
|
13
|
-
return override;
|
|
14
|
-
}
|
|
15
|
-
const route = cliServiceRoutes.get(cliService);
|
|
16
|
-
if (!route) {
|
|
17
|
-
throw new Error(
|
|
18
|
-
`Capability gateway route not registered for CLI service '${cliService}'. Call registerCapabilityGatewayRoute() in commands/${cliService}/index.ts.`
|
|
19
|
-
);
|
|
20
|
-
}
|
|
21
|
-
return route.gatewayDomain;
|
|
22
|
-
}
|
|
7
|
+
} from "./chunk-OJR23CIK.js";
|
|
23
8
|
|
|
24
9
|
// src/core/capability-command.ts
|
|
25
10
|
function createCapabilityCommand(config) {
|
|
@@ -53,7 +38,5 @@ function createCapabilityCommand(config) {
|
|
|
53
38
|
}
|
|
54
39
|
|
|
55
40
|
export {
|
|
56
|
-
registerCapabilityGatewayRoute,
|
|
57
|
-
resolveGatewayDomain,
|
|
58
41
|
createCapabilityCommand
|
|
59
42
|
};
|
|
@@ -162,9 +162,18 @@ async function callGateway(host, domain, pathAfterV1, method, body) {
|
|
|
162
162
|
}
|
|
163
163
|
return unwrapCapabilityEnvelope(parseCapabilityResponse(await resp.text()));
|
|
164
164
|
}
|
|
165
|
+
async function listCapabilities(host, domain) {
|
|
166
|
+
return callGateway(host, domain, "capabilities", "GET");
|
|
167
|
+
}
|
|
168
|
+
async function inspectCapability(host, domain, capabilityId) {
|
|
169
|
+
return callGateway(host, domain, `capabilities/${capabilityId}`, "GET");
|
|
170
|
+
}
|
|
165
171
|
async function executeCapability(host, domain, capabilityId, input = {}) {
|
|
166
172
|
return callGateway(host, domain, `capabilities/${capabilityId}/execute`, "POST", { input });
|
|
167
173
|
}
|
|
174
|
+
async function dryRunCapability(host, domain, capabilityId, input = {}) {
|
|
175
|
+
return callGateway(host, domain, `capabilities/${capabilityId}/dry-run`, "POST", { input });
|
|
176
|
+
}
|
|
168
177
|
async function uploadInputFile(host, domain, projectId, purpose, filePath) {
|
|
169
178
|
const fileBytes = await readFile(filePath);
|
|
170
179
|
return uploadInputFileBytes(host, domain, projectId, purpose, fileBytes, basename(filePath));
|
|
@@ -246,7 +255,10 @@ async function callCapabilityApi(host, domain, action, method = "POST", params =
|
|
|
246
255
|
export {
|
|
247
256
|
CapabilityGatewayError,
|
|
248
257
|
buildCapabilityGatewayUrl,
|
|
258
|
+
listCapabilities,
|
|
259
|
+
inspectCapability,
|
|
249
260
|
executeCapability,
|
|
261
|
+
dryRunCapability,
|
|
250
262
|
uploadInputFile,
|
|
251
263
|
uploadInputFileBytes,
|
|
252
264
|
downloadCapabilityArtifact,
|