@lunnoa/client 1.0.0 → 1.2.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/README.md +27 -1
- package/dist/cli.js +832 -62
- package/dist/index.cjs +45 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1092 -932
- package/dist/index.d.ts +1092 -932
- package/dist/index.js +44 -2
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +28 -0
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +741 -630
- package/dist/react.d.ts +741 -630
- package/dist/react.js +28 -0
- package/dist/react.js.map +1 -1
- package/package.json +1 -1
- package/skills/lunnoa-client/SKILL.md +19 -3
- package/skills/lunnoa-solution-design/SKILL.md +9 -7
package/dist/cli.js
CHANGED
|
@@ -537,7 +537,8 @@ var DEFINE_KINDS = {
|
|
|
537
537
|
aiConnection: "aiConnection",
|
|
538
538
|
action: "action",
|
|
539
539
|
workflow: "workflow",
|
|
540
|
-
agent: "agent"
|
|
540
|
+
agent: "agent",
|
|
541
|
+
entityType: "entityType"
|
|
541
542
|
};
|
|
542
543
|
function resolveActionAppId(action) {
|
|
543
544
|
if (action.appId?.trim()) {
|
|
@@ -1016,6 +1017,21 @@ var EntitiesResource = class {
|
|
|
1016
1017
|
};
|
|
1017
1018
|
|
|
1018
1019
|
// src/resources/entity-types.ts
|
|
1020
|
+
function entityTypeDefinitionToUpsert(def) {
|
|
1021
|
+
return {
|
|
1022
|
+
slug: def.slug,
|
|
1023
|
+
name: def.name,
|
|
1024
|
+
namePlural: def.namePlural,
|
|
1025
|
+
description: def.description,
|
|
1026
|
+
icon: def.icon,
|
|
1027
|
+
color: def.color,
|
|
1028
|
+
attributeSchema: def.attributeSchema,
|
|
1029
|
+
stateSchema: def.stateSchema,
|
|
1030
|
+
isEnabled: def.isEnabled,
|
|
1031
|
+
allowUnknownAttributes: def.allowUnknownAttributes ?? false,
|
|
1032
|
+
managedByCode: true
|
|
1033
|
+
};
|
|
1034
|
+
}
|
|
1019
1035
|
var EntityTypesResource = class {
|
|
1020
1036
|
constructor(http) {
|
|
1021
1037
|
this.http = http;
|
|
@@ -1046,6 +1062,19 @@ var EntityTypesResource = class {
|
|
|
1046
1062
|
query: { expansion: serializeCsv(options.expansion) }
|
|
1047
1063
|
});
|
|
1048
1064
|
}
|
|
1065
|
+
/**
|
|
1066
|
+
* Creates or updates an entity type by workspace-scoped slug.
|
|
1067
|
+
* Prefer the CLI (`npx @lunnoa/client entity-types deploy`) for happy-path deploy.
|
|
1068
|
+
*/
|
|
1069
|
+
upsertBySlug(definition) {
|
|
1070
|
+
const payload = "kind" in definition && definition.kind === "entityType" ? entityTypeDefinitionToUpsert(definition) : definition;
|
|
1071
|
+
return this.http.post("/api/object-types/upsert", {
|
|
1072
|
+
body: payload,
|
|
1073
|
+
query: {
|
|
1074
|
+
expansion: "attributeSchema,stateSchema,description"
|
|
1075
|
+
}
|
|
1076
|
+
});
|
|
1077
|
+
}
|
|
1049
1078
|
};
|
|
1050
1079
|
|
|
1051
1080
|
// src/resources/approvals.ts
|
|
@@ -2020,7 +2049,655 @@ var LunnoaClient = class {
|
|
|
2020
2049
|
}
|
|
2021
2050
|
};
|
|
2022
2051
|
|
|
2052
|
+
// src/cli/args.ts
|
|
2053
|
+
var GROUPS_WITH_SUBCOMMAND = /* @__PURE__ */ new Set([
|
|
2054
|
+
"workflows",
|
|
2055
|
+
"agents",
|
|
2056
|
+
"entity-types",
|
|
2057
|
+
"tools",
|
|
2058
|
+
"apps",
|
|
2059
|
+
"connections",
|
|
2060
|
+
"projects"
|
|
2061
|
+
]);
|
|
2062
|
+
var VALUE_FLAGS = /* @__PURE__ */ new Set([
|
|
2063
|
+
"--url",
|
|
2064
|
+
"--api-key",
|
|
2065
|
+
"--access-token",
|
|
2066
|
+
"--project-id",
|
|
2067
|
+
"--out",
|
|
2068
|
+
"--app"
|
|
2069
|
+
]);
|
|
2070
|
+
function requireFlagValue(flag, value) {
|
|
2071
|
+
if (!value || value.startsWith("--")) {
|
|
2072
|
+
throw new Error(`Missing value for ${flag}`);
|
|
2073
|
+
}
|
|
2074
|
+
return value;
|
|
2075
|
+
}
|
|
2076
|
+
function parseArgs(argv) {
|
|
2077
|
+
const args = {
|
|
2078
|
+
command: argv[0],
|
|
2079
|
+
out: "./src/lunnoa",
|
|
2080
|
+
json: false,
|
|
2081
|
+
forAgent: false,
|
|
2082
|
+
help: false
|
|
2083
|
+
};
|
|
2084
|
+
let i = 1;
|
|
2085
|
+
if (args.command && GROUPS_WITH_SUBCOMMAND.has(args.command)) {
|
|
2086
|
+
const next = argv[1];
|
|
2087
|
+
if (next && !next.startsWith("--")) {
|
|
2088
|
+
args.subcommand = next;
|
|
2089
|
+
i = 2;
|
|
2090
|
+
if (argv[2] && !argv[2].startsWith("--")) {
|
|
2091
|
+
args.path = argv[2];
|
|
2092
|
+
i = 3;
|
|
2093
|
+
}
|
|
2094
|
+
}
|
|
2095
|
+
}
|
|
2096
|
+
for (; i < argv.length; i += 1) {
|
|
2097
|
+
const flag = argv[i];
|
|
2098
|
+
if (flag === "--help" || flag === "-h") {
|
|
2099
|
+
args.help = true;
|
|
2100
|
+
continue;
|
|
2101
|
+
}
|
|
2102
|
+
if (flag === "--json") {
|
|
2103
|
+
args.json = true;
|
|
2104
|
+
continue;
|
|
2105
|
+
}
|
|
2106
|
+
if (flag === "--for-agent") {
|
|
2107
|
+
args.forAgent = true;
|
|
2108
|
+
continue;
|
|
2109
|
+
}
|
|
2110
|
+
if (flag && VALUE_FLAGS.has(flag)) {
|
|
2111
|
+
const value = requireFlagValue(flag, argv[i + 1]);
|
|
2112
|
+
switch (flag) {
|
|
2113
|
+
case "--url":
|
|
2114
|
+
args.url = value;
|
|
2115
|
+
break;
|
|
2116
|
+
case "--api-key":
|
|
2117
|
+
args.apiKey = value;
|
|
2118
|
+
break;
|
|
2119
|
+
case "--access-token":
|
|
2120
|
+
args.accessToken = value;
|
|
2121
|
+
break;
|
|
2122
|
+
case "--project-id":
|
|
2123
|
+
args.projectId = value;
|
|
2124
|
+
break;
|
|
2125
|
+
case "--out":
|
|
2126
|
+
args.out = value;
|
|
2127
|
+
break;
|
|
2128
|
+
case "--app":
|
|
2129
|
+
args.app = value;
|
|
2130
|
+
break;
|
|
2131
|
+
default:
|
|
2132
|
+
break;
|
|
2133
|
+
}
|
|
2134
|
+
i += 1;
|
|
2135
|
+
continue;
|
|
2136
|
+
}
|
|
2137
|
+
if (flag && !flag.startsWith("--") && !args.path) {
|
|
2138
|
+
args.path = flag;
|
|
2139
|
+
continue;
|
|
2140
|
+
}
|
|
2141
|
+
throw new Error(`Unknown option: ${flag}`);
|
|
2142
|
+
}
|
|
2143
|
+
return args;
|
|
2144
|
+
}
|
|
2145
|
+
var USAGE = `Usage:
|
|
2146
|
+
npx @lunnoa/client codegen --url <url> --api-key <lna_key> [--out <dir>]
|
|
2147
|
+
|
|
2148
|
+
Discover (do not invent catalogue action ids):
|
|
2149
|
+
npx @lunnoa/client tools list [--app <appId>] [--for-agent] [--json]
|
|
2150
|
+
npx @lunnoa/client tools get <actionId> [--app <appId>] [--json]
|
|
2151
|
+
npx @lunnoa/client tools search <query> [--app <appId>] [--for-agent] [--json]
|
|
2152
|
+
npx @lunnoa/client apps list [--for-agent] [--json]
|
|
2153
|
+
npx @lunnoa/client apps get <appId> [--json]
|
|
2154
|
+
npx @lunnoa/client connections list [--app <appId>] [--json]
|
|
2155
|
+
npx @lunnoa/client connections get <connectionId> [--json]
|
|
2156
|
+
npx @lunnoa/client agents list [--json]
|
|
2157
|
+
npx @lunnoa/client workflows list [--json]
|
|
2158
|
+
npx @lunnoa/client entity-types list [--json]
|
|
2159
|
+
npx @lunnoa/client projects list [--json]
|
|
2160
|
+
npx @lunnoa/client features [--json]
|
|
2161
|
+
|
|
2162
|
+
Deploy (upsert by slug):
|
|
2163
|
+
npx @lunnoa/client workflows deploy <path> --url <url> --api-key <key> --project-id <uuid>
|
|
2164
|
+
npx @lunnoa/client agents deploy <path> --url <url> --api-key <key> --project-id <uuid>
|
|
2165
|
+
npx @lunnoa/client entity-types deploy <path> --url <url> --api-key <key>
|
|
2166
|
+
|
|
2167
|
+
Options:
|
|
2168
|
+
--url Base URL of the Lunnoa Automate deployment
|
|
2169
|
+
--api-key Machine API key (lna_...)
|
|
2170
|
+
--access-token User JWT as an alternative to --api-key
|
|
2171
|
+
--project-id Project UUID (required for workflow/agent deploy)
|
|
2172
|
+
--out Output directory for lunnoa.generated.ts (codegen; default: ./src/lunnoa)
|
|
2173
|
+
--app Restrict tools/connections to one workflow app id
|
|
2174
|
+
--for-agent Only catalogue entries with availableForAgent
|
|
2175
|
+
--json Machine-readable JSON (preferred for coding agents)
|
|
2176
|
+
--help Show this help
|
|
2177
|
+
|
|
2178
|
+
Environment: LUNNOA_URL, LUNNOA_API_KEY, LUNNOA_PROJECT_ID
|
|
2179
|
+
Optional config file: lunnoa.config.ts | .mjs | .js | .json
|
|
2180
|
+
|
|
2181
|
+
tools get prints inputConfig and a defineAction() sketch. tools list is compact;
|
|
2182
|
+
run tools get for the schema. Entity-type deploy is workspace-scoped (no
|
|
2183
|
+
--project-id). Unknown instance attributes are rejected unless
|
|
2184
|
+
allowUnknownAttributes is true; use extensions.
|
|
2185
|
+
`;
|
|
2186
|
+
|
|
2187
|
+
// src/cli/catalog.ts
|
|
2188
|
+
function asRecord(value) {
|
|
2189
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
2190
|
+
return value;
|
|
2191
|
+
}
|
|
2192
|
+
return void 0;
|
|
2193
|
+
}
|
|
2194
|
+
function flattenActions(apps) {
|
|
2195
|
+
const out = [];
|
|
2196
|
+
for (const app of apps) {
|
|
2197
|
+
const appId = typeof app.id === "string" ? app.id : "";
|
|
2198
|
+
if (!appId) {
|
|
2199
|
+
continue;
|
|
2200
|
+
}
|
|
2201
|
+
const actions = Array.isArray(app.actions) ? app.actions : [];
|
|
2202
|
+
for (const raw of actions) {
|
|
2203
|
+
const action = asRecord(raw);
|
|
2204
|
+
if (!action || typeof action.id !== "string" || !action.id) {
|
|
2205
|
+
continue;
|
|
2206
|
+
}
|
|
2207
|
+
const actionId = action.id;
|
|
2208
|
+
out.push({
|
|
2209
|
+
appId,
|
|
2210
|
+
appName: typeof app.name === "string" ? app.name : appId,
|
|
2211
|
+
actionId,
|
|
2212
|
+
name: typeof action.name === "string" ? action.name : actionId,
|
|
2213
|
+
description: typeof action.description === "string" ? action.description : "",
|
|
2214
|
+
availableForAgent: typeof action.availableForAgent === "boolean" ? action.availableForAgent : Boolean(app.availableForAgent),
|
|
2215
|
+
needsConnection: typeof action.needsConnection === "boolean" ? action.needsConnection : Boolean(app.needsConnection),
|
|
2216
|
+
inputConfig: action.inputConfig
|
|
2217
|
+
});
|
|
2218
|
+
}
|
|
2219
|
+
}
|
|
2220
|
+
return out;
|
|
2221
|
+
}
|
|
2222
|
+
function filterActions(actions, filter = {}) {
|
|
2223
|
+
const appId = filter.appId?.trim();
|
|
2224
|
+
const query = filter.query?.trim().toLowerCase();
|
|
2225
|
+
return actions.filter((action) => {
|
|
2226
|
+
if (appId && action.appId !== appId) {
|
|
2227
|
+
return false;
|
|
2228
|
+
}
|
|
2229
|
+
if (filter.forAgent && !action.availableForAgent) {
|
|
2230
|
+
return false;
|
|
2231
|
+
}
|
|
2232
|
+
if (query) {
|
|
2233
|
+
const haystack = [
|
|
2234
|
+
action.appId,
|
|
2235
|
+
action.appName,
|
|
2236
|
+
action.actionId,
|
|
2237
|
+
action.name,
|
|
2238
|
+
action.description
|
|
2239
|
+
].join(" ").toLowerCase();
|
|
2240
|
+
if (!haystack.includes(query)) {
|
|
2241
|
+
return false;
|
|
2242
|
+
}
|
|
2243
|
+
}
|
|
2244
|
+
return true;
|
|
2245
|
+
});
|
|
2246
|
+
}
|
|
2247
|
+
function parseActionRef(raw) {
|
|
2248
|
+
const trimmed = raw.trim();
|
|
2249
|
+
const dot = trimmed.indexOf(".");
|
|
2250
|
+
if (dot > 0) {
|
|
2251
|
+
const maybeApp = trimmed.slice(0, dot);
|
|
2252
|
+
const maybeAction = trimmed.slice(dot + 1);
|
|
2253
|
+
if (maybeApp && maybeAction && !maybeApp.includes("_action_")) {
|
|
2254
|
+
return { appId: maybeApp, actionId: maybeAction };
|
|
2255
|
+
}
|
|
2256
|
+
}
|
|
2257
|
+
return { actionId: trimmed };
|
|
2258
|
+
}
|
|
2259
|
+
function resolveAction(actions, rawRef, appId) {
|
|
2260
|
+
const parsed = parseActionRef(rawRef);
|
|
2261
|
+
const scope = appId?.trim() || parsed.appId;
|
|
2262
|
+
const matches = actions.filter((action) => {
|
|
2263
|
+
if (action.actionId !== parsed.actionId) {
|
|
2264
|
+
return false;
|
|
2265
|
+
}
|
|
2266
|
+
return scope ? action.appId === scope : true;
|
|
2267
|
+
});
|
|
2268
|
+
if (matches.length === 1) {
|
|
2269
|
+
return matches[0];
|
|
2270
|
+
}
|
|
2271
|
+
if (matches.length === 0) {
|
|
2272
|
+
const hint = scope ? `No action "${parsed.actionId}" on app "${scope}". Try: tools search ${parsed.actionId}` : `Unknown action "${parsed.actionId}". Try: tools search ${parsed.actionId}`;
|
|
2273
|
+
throw new Error(hint);
|
|
2274
|
+
}
|
|
2275
|
+
const apps = matches.map((m) => m.appId).join(", ");
|
|
2276
|
+
throw new Error(
|
|
2277
|
+
`Action "${parsed.actionId}" exists on multiple apps (${apps}). Pass --app <appId>.`
|
|
2278
|
+
);
|
|
2279
|
+
}
|
|
2280
|
+
function extractInputFields(inputConfig) {
|
|
2281
|
+
if (!inputConfig) {
|
|
2282
|
+
return [];
|
|
2283
|
+
}
|
|
2284
|
+
if (Array.isArray(inputConfig)) {
|
|
2285
|
+
return inputConfig.map((item) => fieldFromUnknown(item)).filter((field) => Boolean(field));
|
|
2286
|
+
}
|
|
2287
|
+
const record = asRecord(inputConfig);
|
|
2288
|
+
if (!record) {
|
|
2289
|
+
return [];
|
|
2290
|
+
}
|
|
2291
|
+
if (Array.isArray(record.fields)) {
|
|
2292
|
+
return extractInputFields(record.fields);
|
|
2293
|
+
}
|
|
2294
|
+
if (Array.isArray(record.sections)) {
|
|
2295
|
+
return record.sections.flatMap((section) => {
|
|
2296
|
+
const sectionRecord = asRecord(section);
|
|
2297
|
+
return extractInputFields(sectionRecord?.fields ?? section);
|
|
2298
|
+
});
|
|
2299
|
+
}
|
|
2300
|
+
return Object.entries(record).filter(([, value]) => value === null || typeof value !== "object" || !Array.isArray(value)).map(([id, value]) => {
|
|
2301
|
+
const field = asRecord(value);
|
|
2302
|
+
if (!field) {
|
|
2303
|
+
return { id };
|
|
2304
|
+
}
|
|
2305
|
+
return {
|
|
2306
|
+
id: typeof field.id === "string" ? field.id : id,
|
|
2307
|
+
label: typeof field.label === "string" ? field.label : void 0,
|
|
2308
|
+
type: typeof field.type === "string" ? field.type : typeof field.inputType === "string" ? field.inputType : void 0,
|
|
2309
|
+
required: typeof field.required === "boolean" ? field.required : void 0
|
|
2310
|
+
};
|
|
2311
|
+
});
|
|
2312
|
+
}
|
|
2313
|
+
function fieldFromUnknown(value) {
|
|
2314
|
+
const field = asRecord(value);
|
|
2315
|
+
if (!field || typeof field.id !== "string" || !field.id) {
|
|
2316
|
+
return void 0;
|
|
2317
|
+
}
|
|
2318
|
+
return {
|
|
2319
|
+
id: field.id,
|
|
2320
|
+
label: typeof field.label === "string" ? field.label : void 0,
|
|
2321
|
+
type: typeof field.type === "string" ? field.type : typeof field.inputType === "string" ? field.inputType : void 0,
|
|
2322
|
+
required: typeof field.required === "boolean" ? field.required : void 0
|
|
2323
|
+
};
|
|
2324
|
+
}
|
|
2325
|
+
function summarizeAction(action) {
|
|
2326
|
+
return {
|
|
2327
|
+
appId: action.appId,
|
|
2328
|
+
actionId: action.actionId,
|
|
2329
|
+
name: action.name,
|
|
2330
|
+
description: action.description,
|
|
2331
|
+
availableForAgent: action.availableForAgent,
|
|
2332
|
+
needsConnection: action.needsConnection
|
|
2333
|
+
};
|
|
2334
|
+
}
|
|
2335
|
+
function formatDefineActionSnippet(action) {
|
|
2336
|
+
const fields = extractInputFields(action.inputConfig);
|
|
2337
|
+
const inputBlock = fields.length === 0 ? " // no inputConfig fields advertised" : fields.map((field) => {
|
|
2338
|
+
const notes = [
|
|
2339
|
+
field.label && field.label !== field.id ? field.label : void 0,
|
|
2340
|
+
field.type,
|
|
2341
|
+
field.required ? "required" : void 0
|
|
2342
|
+
].filter(Boolean).join(", ");
|
|
2343
|
+
return notes ? ` // ${field.id}${notes ? ` \u2014 ${notes}` : ""}` : ` // ${field.id}`;
|
|
2344
|
+
}).join("\n");
|
|
2345
|
+
return [
|
|
2346
|
+
"defineAction({",
|
|
2347
|
+
` id: '${action.actionId}',`,
|
|
2348
|
+
` appId: '${action.appId}',`,
|
|
2349
|
+
" input: {",
|
|
2350
|
+
inputBlock,
|
|
2351
|
+
" },",
|
|
2352
|
+
"})"
|
|
2353
|
+
].join("\n");
|
|
2354
|
+
}
|
|
2355
|
+
function actionDetail(action) {
|
|
2356
|
+
return {
|
|
2357
|
+
...summarizeAction(action),
|
|
2358
|
+
inputFields: extractInputFields(action.inputConfig),
|
|
2359
|
+
inputConfig: action.inputConfig ?? null,
|
|
2360
|
+
defineAction: formatDefineActionSnippet(action)
|
|
2361
|
+
};
|
|
2362
|
+
}
|
|
2363
|
+
|
|
2364
|
+
// src/cli/print.ts
|
|
2365
|
+
function printJson(value) {
|
|
2366
|
+
console.log(JSON.stringify(value, null, 2));
|
|
2367
|
+
}
|
|
2368
|
+
function formatTable(rows, columns) {
|
|
2369
|
+
if (rows.length === 0) {
|
|
2370
|
+
return "No results.";
|
|
2371
|
+
}
|
|
2372
|
+
const widths = columns.map((col) => {
|
|
2373
|
+
let width = col.header.length;
|
|
2374
|
+
for (const row of rows) {
|
|
2375
|
+
width = Math.max(width, stringifyCell(row[col.key]).length);
|
|
2376
|
+
}
|
|
2377
|
+
return width;
|
|
2378
|
+
});
|
|
2379
|
+
const header = columns.map((col, i) => pad(col.header, widths[i])).join(" ");
|
|
2380
|
+
const divider = widths.map((w) => "-".repeat(w)).join(" ");
|
|
2381
|
+
const body = rows.map(
|
|
2382
|
+
(row) => columns.map((col, i) => pad(stringifyCell(row[col.key]), widths[i])).join(" ")
|
|
2383
|
+
);
|
|
2384
|
+
return [header, divider, ...body].join("\n");
|
|
2385
|
+
}
|
|
2386
|
+
function printTable(rows, columns) {
|
|
2387
|
+
console.log(formatTable(rows, columns));
|
|
2388
|
+
}
|
|
2389
|
+
function stringifyCell(value) {
|
|
2390
|
+
if (value === null || value === void 0) {
|
|
2391
|
+
return "";
|
|
2392
|
+
}
|
|
2393
|
+
if (typeof value === "boolean") {
|
|
2394
|
+
return value ? "yes" : "no";
|
|
2395
|
+
}
|
|
2396
|
+
return String(value);
|
|
2397
|
+
}
|
|
2398
|
+
function pad(value, width) {
|
|
2399
|
+
return value.length >= width ? value : `${value}${" ".repeat(width - value.length)}`;
|
|
2400
|
+
}
|
|
2401
|
+
|
|
2402
|
+
// src/cli/discover.ts
|
|
2403
|
+
function requireTarget(args, label) {
|
|
2404
|
+
const value = args.path?.trim();
|
|
2405
|
+
if (!value) {
|
|
2406
|
+
throw new Error(`Missing ${label}.`);
|
|
2407
|
+
}
|
|
2408
|
+
return value;
|
|
2409
|
+
}
|
|
2410
|
+
async function loadCatalog(client) {
|
|
2411
|
+
return flattenActions(await client.workflowApps.list());
|
|
2412
|
+
}
|
|
2413
|
+
async function runToolsList(client, args) {
|
|
2414
|
+
const actions = filterActions(await loadCatalog(client), {
|
|
2415
|
+
appId: args.app,
|
|
2416
|
+
forAgent: args.forAgent
|
|
2417
|
+
});
|
|
2418
|
+
const rows = actions.map(summarizeAction);
|
|
2419
|
+
if (args.json) {
|
|
2420
|
+
printJson(rows);
|
|
2421
|
+
return;
|
|
2422
|
+
}
|
|
2423
|
+
printTable(rows, [
|
|
2424
|
+
{ key: "appId", header: "APP" },
|
|
2425
|
+
{ key: "actionId", header: "ACTION" },
|
|
2426
|
+
{ key: "name", header: "NAME" },
|
|
2427
|
+
{ key: "availableForAgent", header: "FOR_AGENT" },
|
|
2428
|
+
{ key: "needsConnection", header: "NEEDS_CONN" }
|
|
2429
|
+
]);
|
|
2430
|
+
}
|
|
2431
|
+
async function runToolsGet(client, args) {
|
|
2432
|
+
const ref = requireTarget(args, "action id (example: tools get http_action_send-request)");
|
|
2433
|
+
const action = resolveAction(await loadCatalog(client), ref, args.app);
|
|
2434
|
+
const detail = actionDetail(action);
|
|
2435
|
+
if (args.json) {
|
|
2436
|
+
printJson(detail);
|
|
2437
|
+
return;
|
|
2438
|
+
}
|
|
2439
|
+
console.log(`appId: ${detail.appId}`);
|
|
2440
|
+
console.log(`actionId: ${detail.actionId}`);
|
|
2441
|
+
console.log(`name: ${detail.name}`);
|
|
2442
|
+
if (detail.description) {
|
|
2443
|
+
console.log(`description: ${detail.description}`);
|
|
2444
|
+
}
|
|
2445
|
+
console.log(`availableForAgent: ${detail.availableForAgent ? "yes" : "no"}`);
|
|
2446
|
+
console.log(`needsConnection: ${detail.needsConnection ? "yes" : "no"}`);
|
|
2447
|
+
console.log("");
|
|
2448
|
+
console.log("inputFields:");
|
|
2449
|
+
if (detail.inputFields.length === 0) {
|
|
2450
|
+
console.log(" (none advertised)");
|
|
2451
|
+
} else {
|
|
2452
|
+
for (const field of detail.inputFields) {
|
|
2453
|
+
const bits = [
|
|
2454
|
+
field.label && field.label !== field.id ? field.label : void 0,
|
|
2455
|
+
field.type,
|
|
2456
|
+
field.required ? "required" : void 0
|
|
2457
|
+
].filter(Boolean);
|
|
2458
|
+
console.log(` ${field.id}${bits.length ? ` (${bits.join(", ")})` : ""}`);
|
|
2459
|
+
}
|
|
2460
|
+
}
|
|
2461
|
+
console.log("");
|
|
2462
|
+
console.log("defineAction:");
|
|
2463
|
+
console.log(detail.defineAction);
|
|
2464
|
+
}
|
|
2465
|
+
async function runToolsSearch(client, args) {
|
|
2466
|
+
const query = requireTarget(args, "search query (example: tools search email)");
|
|
2467
|
+
const actions = filterActions(await loadCatalog(client), {
|
|
2468
|
+
appId: args.app,
|
|
2469
|
+
forAgent: args.forAgent,
|
|
2470
|
+
query
|
|
2471
|
+
});
|
|
2472
|
+
const rows = actions.map(summarizeAction);
|
|
2473
|
+
if (args.json) {
|
|
2474
|
+
printJson(rows);
|
|
2475
|
+
return;
|
|
2476
|
+
}
|
|
2477
|
+
printTable(rows, [
|
|
2478
|
+
{ key: "appId", header: "APP" },
|
|
2479
|
+
{ key: "actionId", header: "ACTION" },
|
|
2480
|
+
{ key: "name", header: "NAME" },
|
|
2481
|
+
{ key: "availableForAgent", header: "FOR_AGENT" },
|
|
2482
|
+
{ key: "needsConnection", header: "NEEDS_CONN" }
|
|
2483
|
+
]);
|
|
2484
|
+
}
|
|
2485
|
+
async function runAppsList(client, args) {
|
|
2486
|
+
const apps = await client.workflowApps.list();
|
|
2487
|
+
const rows = apps.filter((app) => args.forAgent ? Boolean(app.availableForAgent) : true).filter((app) => args.app ? app.id === args.app : true).map((app) => ({
|
|
2488
|
+
id: app.id ?? "",
|
|
2489
|
+
name: app.name ?? app.id ?? "",
|
|
2490
|
+
availableForAgent: Boolean(app.availableForAgent),
|
|
2491
|
+
needsConnection: Boolean(app.needsConnection),
|
|
2492
|
+
actions: Array.isArray(app.actions) ? app.actions.length : 0
|
|
2493
|
+
}));
|
|
2494
|
+
if (args.json) {
|
|
2495
|
+
printJson(rows);
|
|
2496
|
+
return;
|
|
2497
|
+
}
|
|
2498
|
+
printTable(rows, [
|
|
2499
|
+
{ key: "id", header: "APP" },
|
|
2500
|
+
{ key: "name", header: "NAME" },
|
|
2501
|
+
{ key: "availableForAgent", header: "FOR_AGENT" },
|
|
2502
|
+
{ key: "needsConnection", header: "NEEDS_CONN" },
|
|
2503
|
+
{ key: "actions", header: "ACTIONS" }
|
|
2504
|
+
]);
|
|
2505
|
+
}
|
|
2506
|
+
async function runAppsGet(client, args) {
|
|
2507
|
+
const appId = requireTarget(args, "app id (example: apps get http)");
|
|
2508
|
+
const apps = await client.workflowApps.list();
|
|
2509
|
+
const app = apps.find((item) => item.id === appId);
|
|
2510
|
+
if (!app) {
|
|
2511
|
+
throw new Error(`Unknown app "${appId}". Try: apps list`);
|
|
2512
|
+
}
|
|
2513
|
+
const actions = flattenActions([app]).map(summarizeAction);
|
|
2514
|
+
const payload = {
|
|
2515
|
+
id: app.id,
|
|
2516
|
+
name: app.name,
|
|
2517
|
+
description: app.description ?? "",
|
|
2518
|
+
availableForAgent: Boolean(app.availableForAgent),
|
|
2519
|
+
needsConnection: Boolean(app.needsConnection),
|
|
2520
|
+
isPublished: Boolean(app.isPublished),
|
|
2521
|
+
actions,
|
|
2522
|
+
connectionTypes: Array.isArray(app.connections) ? app.connections : []
|
|
2523
|
+
};
|
|
2524
|
+
if (args.json) {
|
|
2525
|
+
printJson(payload);
|
|
2526
|
+
return;
|
|
2527
|
+
}
|
|
2528
|
+
console.log(`id: ${payload.id}`);
|
|
2529
|
+
console.log(`name: ${payload.name}`);
|
|
2530
|
+
if (payload.description) {
|
|
2531
|
+
console.log(`description: ${payload.description}`);
|
|
2532
|
+
}
|
|
2533
|
+
console.log(`availableForAgent: ${payload.availableForAgent ? "yes" : "no"}`);
|
|
2534
|
+
console.log(`needsConnection: ${payload.needsConnection ? "yes" : "no"}`);
|
|
2535
|
+
console.log("");
|
|
2536
|
+
printTable(actions, [
|
|
2537
|
+
{ key: "actionId", header: "ACTION" },
|
|
2538
|
+
{ key: "name", header: "NAME" },
|
|
2539
|
+
{ key: "availableForAgent", header: "FOR_AGENT" },
|
|
2540
|
+
{ key: "needsConnection", header: "NEEDS_CONN" }
|
|
2541
|
+
]);
|
|
2542
|
+
}
|
|
2543
|
+
async function runConnectionsList(client, args) {
|
|
2544
|
+
const connections = await client.connections.list({
|
|
2545
|
+
expansion: ["workflowAppId", "connectionId", "createdAt"]
|
|
2546
|
+
});
|
|
2547
|
+
const rows = connections.filter(
|
|
2548
|
+
(connection) => args.app ? connection.workflowAppId === args.app : true
|
|
2549
|
+
).map((connection) => ({
|
|
2550
|
+
id: connection.id,
|
|
2551
|
+
name: connection.name,
|
|
2552
|
+
workflowAppId: connection.workflowAppId ?? "",
|
|
2553
|
+
connectionId: connection.connectionId ?? ""
|
|
2554
|
+
}));
|
|
2555
|
+
if (args.json) {
|
|
2556
|
+
printJson(rows);
|
|
2557
|
+
return;
|
|
2558
|
+
}
|
|
2559
|
+
printTable(rows, [
|
|
2560
|
+
{ key: "id", header: "ID" },
|
|
2561
|
+
{ key: "name", header: "NAME" },
|
|
2562
|
+
{ key: "workflowAppId", header: "APP" },
|
|
2563
|
+
{ key: "connectionId", header: "TYPE" }
|
|
2564
|
+
]);
|
|
2565
|
+
}
|
|
2566
|
+
async function runConnectionsGet(client, args) {
|
|
2567
|
+
const id = requireTarget(args, "connection id (example: connections get <uuid>)");
|
|
2568
|
+
const connection = await client.connections.get(id, {
|
|
2569
|
+
expansion: ["workflowAppId", "connectionId", "createdAt", "updatedAt"]
|
|
2570
|
+
});
|
|
2571
|
+
const payload = {
|
|
2572
|
+
id: connection.id,
|
|
2573
|
+
name: connection.name,
|
|
2574
|
+
workflowAppId: connection.workflowAppId ?? null,
|
|
2575
|
+
connectionId: connection.connectionId ?? null,
|
|
2576
|
+
createdAt: connection.createdAt ?? null,
|
|
2577
|
+
updatedAt: connection.updatedAt ?? null
|
|
2578
|
+
};
|
|
2579
|
+
if (args.json) {
|
|
2580
|
+
printJson(payload);
|
|
2581
|
+
return;
|
|
2582
|
+
}
|
|
2583
|
+
console.log(`id: ${payload.id}`);
|
|
2584
|
+
console.log(`name: ${payload.name}`);
|
|
2585
|
+
console.log(`workflowAppId: ${payload.workflowAppId ?? ""}`);
|
|
2586
|
+
console.log(`connectionId: ${payload.connectionId ?? ""}`);
|
|
2587
|
+
}
|
|
2588
|
+
async function runAgentsList(client, args) {
|
|
2589
|
+
const agents = await client.agents.list({
|
|
2590
|
+
expansion: ["description", "slug", "managedByCode"]
|
|
2591
|
+
});
|
|
2592
|
+
const rows = agents.map((agent) => ({
|
|
2593
|
+
id: agent.id,
|
|
2594
|
+
name: agent.name,
|
|
2595
|
+
slug: agent.slug ?? "",
|
|
2596
|
+
managedByCode: Boolean(agent.managedByCode),
|
|
2597
|
+
description: agent.description ?? ""
|
|
2598
|
+
}));
|
|
2599
|
+
if (args.json) {
|
|
2600
|
+
printJson(rows);
|
|
2601
|
+
return;
|
|
2602
|
+
}
|
|
2603
|
+
printTable(rows, [
|
|
2604
|
+
{ key: "id", header: "ID" },
|
|
2605
|
+
{ key: "slug", header: "SLUG" },
|
|
2606
|
+
{ key: "name", header: "NAME" },
|
|
2607
|
+
{ key: "managedByCode", header: "CODE" }
|
|
2608
|
+
]);
|
|
2609
|
+
}
|
|
2610
|
+
async function runWorkflowsList(client, args) {
|
|
2611
|
+
const workflows = await client.workflows.list({
|
|
2612
|
+
expansion: ["description", "isActive", "slug", "managedByCode"]
|
|
2613
|
+
});
|
|
2614
|
+
const rows = workflows.map((workflow) => ({
|
|
2615
|
+
id: workflow.id,
|
|
2616
|
+
name: workflow.name,
|
|
2617
|
+
slug: workflow.slug ?? "",
|
|
2618
|
+
isActive: Boolean(workflow.isActive),
|
|
2619
|
+
managedByCode: Boolean(workflow.managedByCode)
|
|
2620
|
+
}));
|
|
2621
|
+
if (args.json) {
|
|
2622
|
+
printJson(rows);
|
|
2623
|
+
return;
|
|
2624
|
+
}
|
|
2625
|
+
printTable(rows, [
|
|
2626
|
+
{ key: "id", header: "ID" },
|
|
2627
|
+
{ key: "slug", header: "SLUG" },
|
|
2628
|
+
{ key: "name", header: "NAME" },
|
|
2629
|
+
{ key: "isActive", header: "ACTIVE" },
|
|
2630
|
+
{ key: "managedByCode", header: "CODE" }
|
|
2631
|
+
]);
|
|
2632
|
+
}
|
|
2633
|
+
async function runEntityTypesList(client, args) {
|
|
2634
|
+
const types = await client.entityTypes.list({
|
|
2635
|
+
expansion: ["description"]
|
|
2636
|
+
});
|
|
2637
|
+
const rows = types.map((type) => ({
|
|
2638
|
+
id: type.id,
|
|
2639
|
+
slug: type.slug,
|
|
2640
|
+
name: type.name,
|
|
2641
|
+
managedByCode: Boolean(type.managedByCode)
|
|
2642
|
+
}));
|
|
2643
|
+
if (args.json) {
|
|
2644
|
+
printJson(rows);
|
|
2645
|
+
return;
|
|
2646
|
+
}
|
|
2647
|
+
printTable(rows, [
|
|
2648
|
+
{ key: "id", header: "ID" },
|
|
2649
|
+
{ key: "slug", header: "SLUG" },
|
|
2650
|
+
{ key: "name", header: "NAME" },
|
|
2651
|
+
{ key: "managedByCode", header: "CODE" }
|
|
2652
|
+
]);
|
|
2653
|
+
}
|
|
2654
|
+
async function runProjectsList(client, args) {
|
|
2655
|
+
const projects = await client.projects.list({
|
|
2656
|
+
expansion: ["description", "countAgents", "countWorkflows"]
|
|
2657
|
+
});
|
|
2658
|
+
const rows = projects.map((project) => ({
|
|
2659
|
+
id: project.id,
|
|
2660
|
+
name: project.name,
|
|
2661
|
+
description: project.description ?? "",
|
|
2662
|
+
agents: project._count?.agents ?? "",
|
|
2663
|
+
workflows: project._count?.workflows ?? ""
|
|
2664
|
+
}));
|
|
2665
|
+
if (args.json) {
|
|
2666
|
+
printJson(rows);
|
|
2667
|
+
return;
|
|
2668
|
+
}
|
|
2669
|
+
printTable(rows, [
|
|
2670
|
+
{ key: "id", header: "ID" },
|
|
2671
|
+
{ key: "name", header: "NAME" },
|
|
2672
|
+
{ key: "agents", header: "AGENTS" },
|
|
2673
|
+
{ key: "workflows", header: "WORKFLOWS" }
|
|
2674
|
+
]);
|
|
2675
|
+
}
|
|
2676
|
+
async function runFeatures(client, args) {
|
|
2677
|
+
const features = await client.discovery.enabledFeatures();
|
|
2678
|
+
if (args.json) {
|
|
2679
|
+
printJson(features);
|
|
2680
|
+
return;
|
|
2681
|
+
}
|
|
2682
|
+
const rows = Object.entries(features).filter(([, value]) => typeof value === "boolean").map(([key, value]) => ({
|
|
2683
|
+
feature: key,
|
|
2684
|
+
enabled: value
|
|
2685
|
+
}));
|
|
2686
|
+
printTable(rows, [
|
|
2687
|
+
{ key: "feature", header: "FEATURE" },
|
|
2688
|
+
{ key: "enabled", header: "ENABLED" }
|
|
2689
|
+
]);
|
|
2690
|
+
}
|
|
2691
|
+
|
|
2023
2692
|
// src/cli/generate.ts
|
|
2693
|
+
function computeDeploymentSchemaFingerprint(entityTypes) {
|
|
2694
|
+
const parts = [...entityTypes].map((type) => {
|
|
2695
|
+
const revision = type.schemaRevision ?? 1;
|
|
2696
|
+
const allowUnknown = type.allowUnknownAttributes ?? false;
|
|
2697
|
+
return `${type.slug}:${revision}:${allowUnknown ? 1 : 0}`;
|
|
2698
|
+
}).sort();
|
|
2699
|
+
return parts.join("|") || "empty";
|
|
2700
|
+
}
|
|
2024
2701
|
function toCamelCase(input) {
|
|
2025
2702
|
const parts = input.replace(/[^a-zA-Z0-9]+/g, " ").trim().split(/\s+/);
|
|
2026
2703
|
if (parts.length === 0 || parts[0] === "") {
|
|
@@ -2140,6 +2817,9 @@ function isFieldRequired(field) {
|
|
|
2140
2817
|
}
|
|
2141
2818
|
function generateDeploymentModule(definitions) {
|
|
2142
2819
|
const chunks = [];
|
|
2820
|
+
const schemaFingerprint = computeDeploymentSchemaFingerprint(
|
|
2821
|
+
definitions.entityTypes
|
|
2822
|
+
);
|
|
2143
2823
|
chunks.push(
|
|
2144
2824
|
`/* eslint-disable */
|
|
2145
2825
|
/**
|
|
@@ -2148,8 +2828,23 @@ function generateDeploymentModule(definitions) {
|
|
|
2148
2828
|
* Generated by \`npx @lunnoa/client codegen\` \u2014 do not edit by hand.
|
|
2149
2829
|
* Re-run codegen whenever entity types, workflows, or agents change on
|
|
2150
2830
|
* the deployment.
|
|
2831
|
+
*
|
|
2832
|
+
* Schema fingerprint: ${schemaFingerprint}
|
|
2151
2833
|
*/
|
|
2152
2834
|
import type { LunnoaClient, Entity, Execution, ExecuteWorkflowResult, PaginatedEntities, Task, AgentChatStream, WaitUntilFinishedOptions, ListEntitiesOptions, UIMessage } from '@lunnoa/client';
|
|
2835
|
+
|
|
2836
|
+
/** Fingerprint of entity-type schemas at codegen time (slug:revision:allowUnknown). */
|
|
2837
|
+
export const DEPLOYMENT_SCHEMA_FINGERPRINT = ${JSON.stringify(schemaFingerprint)};
|
|
2838
|
+
|
|
2839
|
+
/** Per-type schemaRevision values captured at codegen time. */
|
|
2840
|
+
export const ENTITY_TYPE_SCHEMA_REVISIONS = ${JSON.stringify(
|
|
2841
|
+
Object.fromEntries(
|
|
2842
|
+
definitions.entityTypes.map((type) => [
|
|
2843
|
+
type.slug,
|
|
2844
|
+
type.schemaRevision ?? 1
|
|
2845
|
+
])
|
|
2846
|
+
)
|
|
2847
|
+
)} as const;
|
|
2153
2848
|
`
|
|
2154
2849
|
);
|
|
2155
2850
|
chunks.push(GENERATED_RUNTIME_HELPERS);
|
|
@@ -2438,6 +3133,21 @@ function pickAgentDefinition(mod) {
|
|
|
2438
3133
|
"No defineAgent() export found. Export the definition as default or `agent`."
|
|
2439
3134
|
);
|
|
2440
3135
|
}
|
|
3136
|
+
function pickEntityTypeDefinition(mod) {
|
|
3137
|
+
const candidates = [
|
|
3138
|
+
mod.default,
|
|
3139
|
+
mod.entityType,
|
|
3140
|
+
...Object.values(mod)
|
|
3141
|
+
];
|
|
3142
|
+
for (const value of candidates) {
|
|
3143
|
+
if (value && typeof value === "object" && value.kind === DEFINE_KINDS.entityType) {
|
|
3144
|
+
return value;
|
|
3145
|
+
}
|
|
3146
|
+
}
|
|
3147
|
+
throw new Error(
|
|
3148
|
+
"No defineEntityType() export found. Export the definition as default or `entityType`."
|
|
3149
|
+
);
|
|
3150
|
+
}
|
|
2441
3151
|
async function loadOptionalConfig() {
|
|
2442
3152
|
const candidates = [
|
|
2443
3153
|
"lunnoa.config.ts",
|
|
@@ -2467,66 +3177,6 @@ async function loadOptionalConfig() {
|
|
|
2467
3177
|
}
|
|
2468
3178
|
|
|
2469
3179
|
// src/cli/index.ts
|
|
2470
|
-
function parseArgs(argv) {
|
|
2471
|
-
const args = { command: argv[0], out: "./src/lunnoa" };
|
|
2472
|
-
let i = 1;
|
|
2473
|
-
if (args.command === "workflows" || args.command === "agents") {
|
|
2474
|
-
args.subcommand = argv[1];
|
|
2475
|
-
i = 2;
|
|
2476
|
-
if (argv[2] && !argv[2].startsWith("--")) {
|
|
2477
|
-
args.path = argv[2];
|
|
2478
|
-
i = 3;
|
|
2479
|
-
}
|
|
2480
|
-
}
|
|
2481
|
-
for (; i < argv.length; i += 1) {
|
|
2482
|
-
const flag = argv[i];
|
|
2483
|
-
const value = argv[i + 1];
|
|
2484
|
-
switch (flag) {
|
|
2485
|
-
case "--url":
|
|
2486
|
-
args.url = value;
|
|
2487
|
-
i += 1;
|
|
2488
|
-
break;
|
|
2489
|
-
case "--api-key":
|
|
2490
|
-
args.apiKey = value;
|
|
2491
|
-
i += 1;
|
|
2492
|
-
break;
|
|
2493
|
-
case "--access-token":
|
|
2494
|
-
args.accessToken = value;
|
|
2495
|
-
i += 1;
|
|
2496
|
-
break;
|
|
2497
|
-
case "--project-id":
|
|
2498
|
-
args.projectId = value;
|
|
2499
|
-
i += 1;
|
|
2500
|
-
break;
|
|
2501
|
-
case "--out":
|
|
2502
|
-
args.out = value;
|
|
2503
|
-
i += 1;
|
|
2504
|
-
break;
|
|
2505
|
-
default:
|
|
2506
|
-
if (!args.path && !flag.startsWith("--")) {
|
|
2507
|
-
args.path = flag;
|
|
2508
|
-
break;
|
|
2509
|
-
}
|
|
2510
|
-
throw new Error(`Unknown option: ${flag}`);
|
|
2511
|
-
}
|
|
2512
|
-
}
|
|
2513
|
-
return args;
|
|
2514
|
-
}
|
|
2515
|
-
var USAGE = `Usage:
|
|
2516
|
-
npx @lunnoa/client codegen --url <deployment-url> --api-key <lna_key> [--out <dir>]
|
|
2517
|
-
npx @lunnoa/client workflows deploy <path> --url <url> --api-key <key> --project-id <uuid>
|
|
2518
|
-
npx @lunnoa/client agents deploy <path> --url <url> --api-key <key> --project-id <uuid>
|
|
2519
|
-
|
|
2520
|
-
Options:
|
|
2521
|
-
--url Base URL of the Lunnoa Automate deployment
|
|
2522
|
-
--api-key Machine API key (lna_...)
|
|
2523
|
-
--access-token User JWT as an alternative to --api-key
|
|
2524
|
-
--project-id Project UUID (required for deploy)
|
|
2525
|
-
--out Output directory for lunnoa.generated.ts (codegen; default: ./src/lunnoa)
|
|
2526
|
-
|
|
2527
|
-
Environment: LUNNOA_URL, LUNNOA_API_KEY, LUNNOA_PROJECT_ID
|
|
2528
|
-
Optional config file: lunnoa.config.ts | .mjs | .js | .json
|
|
2529
|
-
`;
|
|
2530
3180
|
async function bindClient(args) {
|
|
2531
3181
|
const fileConfig = await loadOptionalConfig();
|
|
2532
3182
|
const url = args.url ?? process.env.LUNNOA_URL ?? fileConfig.url;
|
|
@@ -2636,9 +3286,122 @@ async function deployAgent(args) {
|
|
|
2636
3286
|
const result = await client.agents.upsertBySlug(projectId, payload);
|
|
2637
3287
|
console.log(`Upserted agent ${result.id} (${payload.slug})`);
|
|
2638
3288
|
}
|
|
3289
|
+
async function deployEntityType(args) {
|
|
3290
|
+
if (!args.path) {
|
|
3291
|
+
throw new Error(
|
|
3292
|
+
"Missing definition path. Example: entity-types deploy ./entity-type.ts"
|
|
3293
|
+
);
|
|
3294
|
+
}
|
|
3295
|
+
const { client } = await bindClient(args);
|
|
3296
|
+
const mod = await loadDefinitionModule(args.path);
|
|
3297
|
+
const def = pickEntityTypeDefinition(mod);
|
|
3298
|
+
const payload = entityTypeDefinitionToUpsert(def);
|
|
3299
|
+
console.log(`Deploying entity type slug="${payload.slug}" ...`);
|
|
3300
|
+
const result = await client.entityTypes.upsertBySlug(payload);
|
|
3301
|
+
console.log(
|
|
3302
|
+
`Upserted entity type ${result.id} (${payload.slug})` + (typeof result.schemaRevision === "number" ? ` schemaRevision=${result.schemaRevision}` : "")
|
|
3303
|
+
);
|
|
3304
|
+
}
|
|
3305
|
+
var DISCOVERY_SUBCOMMANDS = {
|
|
3306
|
+
tools: ["list", "get", "search"],
|
|
3307
|
+
apps: ["list", "get"],
|
|
3308
|
+
connections: ["list", "get"],
|
|
3309
|
+
features: void 0,
|
|
3310
|
+
projects: ["list"]
|
|
3311
|
+
};
|
|
3312
|
+
function isDiscoveryCommand(args) {
|
|
3313
|
+
const { command, subcommand } = args;
|
|
3314
|
+
if (!command) {
|
|
3315
|
+
return false;
|
|
3316
|
+
}
|
|
3317
|
+
if (command === "features") {
|
|
3318
|
+
return true;
|
|
3319
|
+
}
|
|
3320
|
+
if (command === "projects" && (subcommand === "list" || !subcommand)) {
|
|
3321
|
+
return true;
|
|
3322
|
+
}
|
|
3323
|
+
if ((command === "agents" || command === "workflows" || command === "entity-types") && subcommand === "list") {
|
|
3324
|
+
return true;
|
|
3325
|
+
}
|
|
3326
|
+
const allowed = DISCOVERY_SUBCOMMANDS[command];
|
|
3327
|
+
return Array.isArray(allowed) && Boolean(subcommand && allowed.includes(subcommand));
|
|
3328
|
+
}
|
|
3329
|
+
function assertKnownDiscoveryShape(args) {
|
|
3330
|
+
const { command, subcommand } = args;
|
|
3331
|
+
const allowed = command ? DISCOVERY_SUBCOMMANDS[command] : void 0;
|
|
3332
|
+
if (!command || allowed === void 0) {
|
|
3333
|
+
return;
|
|
3334
|
+
}
|
|
3335
|
+
if (!subcommand || !allowed.includes(subcommand)) {
|
|
3336
|
+
throw new Error(
|
|
3337
|
+
`Unknown command: ${command} ${subcommand ?? ""}
|
|
3338
|
+
|
|
3339
|
+
${USAGE}`
|
|
3340
|
+
);
|
|
3341
|
+
}
|
|
3342
|
+
}
|
|
3343
|
+
async function runDiscovery(args) {
|
|
3344
|
+
const { command, subcommand } = args;
|
|
3345
|
+
if (command === "tools" || command === "apps" || command === "connections") {
|
|
3346
|
+
assertKnownDiscoveryShape(args);
|
|
3347
|
+
}
|
|
3348
|
+
if (!isDiscoveryCommand(args)) {
|
|
3349
|
+
return false;
|
|
3350
|
+
}
|
|
3351
|
+
const { client } = await bindClient(args);
|
|
3352
|
+
if (command === "tools" && subcommand === "list") {
|
|
3353
|
+
await runToolsList(client, args);
|
|
3354
|
+
return true;
|
|
3355
|
+
}
|
|
3356
|
+
if (command === "tools" && subcommand === "get") {
|
|
3357
|
+
await runToolsGet(client, args);
|
|
3358
|
+
return true;
|
|
3359
|
+
}
|
|
3360
|
+
if (command === "tools" && subcommand === "search") {
|
|
3361
|
+
await runToolsSearch(client, args);
|
|
3362
|
+
return true;
|
|
3363
|
+
}
|
|
3364
|
+
if (command === "apps" && subcommand === "list") {
|
|
3365
|
+
await runAppsList(client, args);
|
|
3366
|
+
return true;
|
|
3367
|
+
}
|
|
3368
|
+
if (command === "apps" && subcommand === "get") {
|
|
3369
|
+
await runAppsGet(client, args);
|
|
3370
|
+
return true;
|
|
3371
|
+
}
|
|
3372
|
+
if (command === "connections" && subcommand === "list") {
|
|
3373
|
+
await runConnectionsList(client, args);
|
|
3374
|
+
return true;
|
|
3375
|
+
}
|
|
3376
|
+
if (command === "connections" && subcommand === "get") {
|
|
3377
|
+
await runConnectionsGet(client, args);
|
|
3378
|
+
return true;
|
|
3379
|
+
}
|
|
3380
|
+
if (command === "agents" && subcommand === "list") {
|
|
3381
|
+
await runAgentsList(client, args);
|
|
3382
|
+
return true;
|
|
3383
|
+
}
|
|
3384
|
+
if (command === "workflows" && subcommand === "list") {
|
|
3385
|
+
await runWorkflowsList(client, args);
|
|
3386
|
+
return true;
|
|
3387
|
+
}
|
|
3388
|
+
if (command === "entity-types" && subcommand === "list") {
|
|
3389
|
+
await runEntityTypesList(client, args);
|
|
3390
|
+
return true;
|
|
3391
|
+
}
|
|
3392
|
+
if (command === "projects" && (subcommand === "list" || !subcommand)) {
|
|
3393
|
+
await runProjectsList(client, args);
|
|
3394
|
+
return true;
|
|
3395
|
+
}
|
|
3396
|
+
if (command === "features") {
|
|
3397
|
+
await runFeatures(client, args);
|
|
3398
|
+
return true;
|
|
3399
|
+
}
|
|
3400
|
+
return false;
|
|
3401
|
+
}
|
|
2639
3402
|
async function main() {
|
|
2640
3403
|
const args = parseArgs(process.argv.slice(2));
|
|
2641
|
-
if (!args.command || args.command === "--help" || args.command === "help") {
|
|
3404
|
+
if (!args.command || args.command === "--help" || args.command === "help" || args.help) {
|
|
2642
3405
|
console.log(USAGE);
|
|
2643
3406
|
return;
|
|
2644
3407
|
}
|
|
@@ -2646,6 +3409,9 @@ async function main() {
|
|
|
2646
3409
|
await runCodegen(args);
|
|
2647
3410
|
return;
|
|
2648
3411
|
}
|
|
3412
|
+
if (await runDiscovery(args)) {
|
|
3413
|
+
return;
|
|
3414
|
+
}
|
|
2649
3415
|
if (args.command === "workflows" && args.subcommand === "deploy") {
|
|
2650
3416
|
await deployWorkflow(args);
|
|
2651
3417
|
return;
|
|
@@ -2654,6 +3420,10 @@ async function main() {
|
|
|
2654
3420
|
await deployAgent(args);
|
|
2655
3421
|
return;
|
|
2656
3422
|
}
|
|
3423
|
+
if (args.command === "entity-types" && args.subcommand === "deploy") {
|
|
3424
|
+
await deployEntityType(args);
|
|
3425
|
+
return;
|
|
3426
|
+
}
|
|
2657
3427
|
console.error(`Unknown command: ${args.command} ${args.subcommand ?? ""}
|
|
2658
3428
|
`);
|
|
2659
3429
|
console.log(USAGE);
|