@kaelen-ai/cli 0.1.17 → 0.1.19
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/index.js +136 -37
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -837,6 +837,7 @@ var BINDING_SCOPES = /* @__PURE__ */ new Set(["project", "principal"]);
|
|
|
837
837
|
var CREDENTIAL_SOURCES = /* @__PURE__ */ new Set(["none", "platform", "secret_bundle"]);
|
|
838
838
|
var TARGET_EXECUTION_KEYS = /* @__PURE__ */ new Set([
|
|
839
839
|
"applications",
|
|
840
|
+
"application_bindings",
|
|
840
841
|
"endpoints",
|
|
841
842
|
"secret_names",
|
|
842
843
|
"timeout_ms",
|
|
@@ -860,6 +861,16 @@ var SECRET_HEADER_NAMES = /* @__PURE__ */ new Set([
|
|
|
860
861
|
]);
|
|
861
862
|
var HTTP_LIKE_KINDS = /* @__PURE__ */ new Set(["http", "graphql", "httpApi", "graphqlApi"]);
|
|
862
863
|
var OP_RESOURCE_KINDS = /* @__PURE__ */ new Set(["httpApi", "graphqlApi"]);
|
|
864
|
+
var PRINCIPAL_RESOLUTION_MATCHES = /* @__PURE__ */ new Set(["principal_id", "external_id"]);
|
|
865
|
+
var WEBHOOK_PRINCIPAL_SOURCES = /* @__PURE__ */ new Set(["body", "headers", "query"]);
|
|
866
|
+
var QUEUE_PRINCIPAL_SOURCES = /* @__PURE__ */ new Set(["message", "attributes"]);
|
|
867
|
+
var PRINCIPAL_BOUND_QUEUE_KINDS = /* @__PURE__ */ new Set([
|
|
868
|
+
"kafka",
|
|
869
|
+
"rabbitmq",
|
|
870
|
+
"redis",
|
|
871
|
+
"pubsub",
|
|
872
|
+
"sqs"
|
|
873
|
+
]);
|
|
863
874
|
function countPlaceholders(format) {
|
|
864
875
|
let count = 0;
|
|
865
876
|
let idx = 0;
|
|
@@ -1057,6 +1068,51 @@ function validateHttpLikeConfig(appName, resourceName, resourceKind, config, sec
|
|
|
1057
1068
|
}
|
|
1058
1069
|
}
|
|
1059
1070
|
}
|
|
1071
|
+
function validatePrincipalResolution(appName, resourceName, resourceKind, signals2, config, errors) {
|
|
1072
|
+
const requiresPrincipalResolution = resourceKind === "webhook" || PRINCIPAL_BOUND_QUEUE_KINDS.has(resourceKind) && signals2.length > 0;
|
|
1073
|
+
if (!requiresPrincipalResolution) return;
|
|
1074
|
+
const owner = `resource "${appName}/${resourceName}"`;
|
|
1075
|
+
if (!isRecord2(config)) {
|
|
1076
|
+
errors.push(`${owner} config must be an object with principal_resolution`);
|
|
1077
|
+
return;
|
|
1078
|
+
}
|
|
1079
|
+
const rule = config.principal_resolution;
|
|
1080
|
+
if (!isRecord2(rule)) {
|
|
1081
|
+
errors.push(`${owner} config.principal_resolution is required`);
|
|
1082
|
+
return;
|
|
1083
|
+
}
|
|
1084
|
+
const from = stringField2(rule, "from");
|
|
1085
|
+
const match = stringField2(rule, "match");
|
|
1086
|
+
const allowedSources = resourceKind === "webhook" ? WEBHOOK_PRINCIPAL_SOURCES : QUEUE_PRINCIPAL_SOURCES;
|
|
1087
|
+
if (!from || !allowedSources.has(from)) {
|
|
1088
|
+
errors.push(
|
|
1089
|
+
`${owner} principal_resolution.from must be one of ${Array.from(
|
|
1090
|
+
allowedSources
|
|
1091
|
+
).join(", ")}`
|
|
1092
|
+
);
|
|
1093
|
+
}
|
|
1094
|
+
if (!match || !PRINCIPAL_RESOLUTION_MATCHES.has(match)) {
|
|
1095
|
+
errors.push(
|
|
1096
|
+
`${owner} principal_resolution.match must be principal_id or external_id`
|
|
1097
|
+
);
|
|
1098
|
+
}
|
|
1099
|
+
if (from === "body" || from === "query" || from === "message") {
|
|
1100
|
+
if (!stringField2(rule, "path")) {
|
|
1101
|
+
errors.push(`${owner} principal_resolution.path is required for ${from}`);
|
|
1102
|
+
}
|
|
1103
|
+
if (rule.name !== void 0) {
|
|
1104
|
+
errors.push(`${owner} principal_resolution.name is not valid for ${from}`);
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
if (from === "headers" || from === "attributes") {
|
|
1108
|
+
if (!stringField2(rule, "name")) {
|
|
1109
|
+
errors.push(`${owner} principal_resolution.name is required for ${from}`);
|
|
1110
|
+
}
|
|
1111
|
+
if (rule.path !== void 0) {
|
|
1112
|
+
errors.push(`${owner} principal_resolution.path is not valid for ${from}`);
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
}
|
|
1060
1116
|
function isRecord2(value) {
|
|
1061
1117
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
1062
1118
|
}
|
|
@@ -1129,6 +1185,13 @@ function validateTargetExecution(target, declaredApps, declaredEndpoints, errors
|
|
|
1129
1185
|
errors.push(`${owner} references undeclared application "${ref}"`);
|
|
1130
1186
|
}
|
|
1131
1187
|
}
|
|
1188
|
+
validateApplicationBindings(
|
|
1189
|
+
owner,
|
|
1190
|
+
executionRecord.application_bindings,
|
|
1191
|
+
applicationRefs,
|
|
1192
|
+
declaredApps,
|
|
1193
|
+
errors
|
|
1194
|
+
);
|
|
1132
1195
|
const endpointRefs = validateScopeList(
|
|
1133
1196
|
owner,
|
|
1134
1197
|
"execution.endpoints",
|
|
@@ -1161,6 +1224,60 @@ function validateTargetExecution(target, declaredApps, declaredEndpoints, errors
|
|
|
1161
1224
|
errors.push(`${owner} endpoints is no longer supported; use execution.endpoints`);
|
|
1162
1225
|
}
|
|
1163
1226
|
}
|
|
1227
|
+
function validateApplicationBindings(owner, value, applicationRefs, declaredApps, errors) {
|
|
1228
|
+
if (value === void 0) {
|
|
1229
|
+
if (applicationRefs.length > 0) {
|
|
1230
|
+
errors.push(`${owner} execution.application_bindings is required when execution.applications is set`);
|
|
1231
|
+
}
|
|
1232
|
+
return;
|
|
1233
|
+
}
|
|
1234
|
+
if (!Array.isArray(value)) {
|
|
1235
|
+
errors.push(`${owner} execution.application_bindings must be an array`);
|
|
1236
|
+
return;
|
|
1237
|
+
}
|
|
1238
|
+
const applicationRefSet = new Set(applicationRefs);
|
|
1239
|
+
const boundApplicationNames = /* @__PURE__ */ new Set();
|
|
1240
|
+
const seenAliases = /* @__PURE__ */ new Set();
|
|
1241
|
+
for (const entry of value) {
|
|
1242
|
+
if (!isRecord2(entry)) {
|
|
1243
|
+
errors.push(`${owner} execution.application_bindings entry must be an object`);
|
|
1244
|
+
continue;
|
|
1245
|
+
}
|
|
1246
|
+
for (const key of Object.keys(entry)) {
|
|
1247
|
+
if (key !== "application_name" && key !== "application_alias") {
|
|
1248
|
+
errors.push(
|
|
1249
|
+
`${owner} execution.application_bindings entry contains unsupported key "${key}"`
|
|
1250
|
+
);
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1253
|
+
const applicationName = stringField2(entry, "application_name");
|
|
1254
|
+
const applicationAlias = stringField2(entry, "application_alias");
|
|
1255
|
+
if (!applicationName) {
|
|
1256
|
+
errors.push(`${owner} execution.application_bindings entry application_name is required`);
|
|
1257
|
+
continue;
|
|
1258
|
+
}
|
|
1259
|
+
if (!applicationAlias) {
|
|
1260
|
+
errors.push(`${owner} execution.application_bindings entry application_alias is required`);
|
|
1261
|
+
continue;
|
|
1262
|
+
}
|
|
1263
|
+
if (!declaredApps.has(applicationName)) {
|
|
1264
|
+
errors.push(`${owner} execution.application_bindings references undeclared application "${applicationName}"`);
|
|
1265
|
+
}
|
|
1266
|
+
if (!applicationRefSet.has(applicationName)) {
|
|
1267
|
+
errors.push(`${owner} execution.application_bindings references application "${applicationName}" not present in execution.applications`);
|
|
1268
|
+
}
|
|
1269
|
+
if (seenAliases.has(applicationAlias)) {
|
|
1270
|
+
errors.push(`${owner} execution.application_bindings duplicates application_alias "${applicationAlias}"`);
|
|
1271
|
+
}
|
|
1272
|
+
seenAliases.add(applicationAlias);
|
|
1273
|
+
boundApplicationNames.add(applicationName);
|
|
1274
|
+
}
|
|
1275
|
+
for (const ref of applicationRefs) {
|
|
1276
|
+
if (!boundApplicationNames.has(ref)) {
|
|
1277
|
+
errors.push(`${owner} execution.application_bindings is missing application "${ref}"`);
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1164
1281
|
function validateRateBudget(owner, value, errors) {
|
|
1165
1282
|
if (value === void 0) return;
|
|
1166
1283
|
if (!isRecord2(value)) {
|
|
@@ -1364,6 +1481,14 @@ function validateManifest(manifest) {
|
|
|
1364
1481
|
validateResourceCapability(appName, resourceName, capability, errors);
|
|
1365
1482
|
}
|
|
1366
1483
|
const resourceKindForConfig = stringField2(resource, "kind") ?? "";
|
|
1484
|
+
validatePrincipalResolution(
|
|
1485
|
+
appName,
|
|
1486
|
+
resourceName,
|
|
1487
|
+
resourceKindForConfig,
|
|
1488
|
+
signals2,
|
|
1489
|
+
resource.config,
|
|
1490
|
+
errors
|
|
1491
|
+
);
|
|
1367
1492
|
validateHttpLikeConfig(
|
|
1368
1493
|
appName,
|
|
1369
1494
|
resourceName,
|
|
@@ -2471,18 +2596,11 @@ ${stdout || "(empty)"}`
|
|
|
2471
2596
|
|
|
2472
2597
|
// src/build/manifest.ts
|
|
2473
2598
|
async function generateManifest(input) {
|
|
2474
|
-
const entrypoints = {};
|
|
2475
|
-
for (const b of input.behaviorBundles) {
|
|
2476
|
-
entrypoints[b.name] = `behaviors/${b.name}.js`;
|
|
2477
|
-
}
|
|
2478
|
-
for (const c of input.conversationBundles) {
|
|
2479
|
-
entrypoints[c.name] = `conversations/${c.name}.js`;
|
|
2480
|
-
}
|
|
2481
2599
|
const m = await evaluateAndEmitManifest({
|
|
2482
2600
|
cwd: input.cwd,
|
|
2483
2601
|
outDir: input.outDir,
|
|
2484
2602
|
userFiles: input.userFiles,
|
|
2485
|
-
entrypoints
|
|
2603
|
+
entrypoints: input.entrypoints
|
|
2486
2604
|
});
|
|
2487
2605
|
await writeFile(
|
|
2488
2606
|
join(input.outDir, "manifest.json"),
|
|
@@ -2946,7 +3064,6 @@ var INTERNAL_RUN = "__io_cli_compiled_run";
|
|
|
2946
3064
|
var INTERNAL_ON_START = "__io_cli_compiled_on_start";
|
|
2947
3065
|
var INTERNAL_ON_MESSAGE = "__io_cli_compiled_on_message";
|
|
2948
3066
|
var INTERNAL_ON_END = "__io_cli_compiled_on_end";
|
|
2949
|
-
var INTERNAL_APPLICATIONS = "__io_cli_compiled_applications";
|
|
2950
3067
|
function conversationChannel(name) {
|
|
2951
3068
|
return `session:${name}`;
|
|
2952
3069
|
}
|
|
@@ -3048,13 +3165,6 @@ function functionSourceFromProperty(source, prop, label) {
|
|
|
3048
3165
|
}
|
|
3049
3166
|
return source.slice(value.start, value.end);
|
|
3050
3167
|
}
|
|
3051
|
-
function expressionSourceFromProperty(source, prop, label) {
|
|
3052
|
-
const value = prop.value;
|
|
3053
|
-
if (!value) {
|
|
3054
|
-
throw new BuildError(`compiled target is missing ${label} value`);
|
|
3055
|
-
}
|
|
3056
|
-
return source.slice(value.start, value.end);
|
|
3057
|
-
}
|
|
3058
3168
|
function replaceRange(source, start, end, text) {
|
|
3059
3169
|
return `${source.slice(0, start)}${text}${source.slice(end)}`;
|
|
3060
3170
|
}
|
|
@@ -3392,8 +3502,6 @@ function buildBehaviorReplacement(source, spec, behavior) {
|
|
|
3392
3502
|
}
|
|
3393
3503
|
const execution = compactExecution(behavior.execution);
|
|
3394
3504
|
const runSource = functionSourceFromProperty(source, run, "run");
|
|
3395
|
-
const applications = findProperty(spec, "applications");
|
|
3396
|
-
const applicationsSource = applications ? expressionSourceFromProperty(source, applications, "applications") : void 0;
|
|
3397
3505
|
const configEntries = [
|
|
3398
3506
|
`kind: "behavior"`,
|
|
3399
3507
|
`name: ${JSON.stringify(behavior.name)}`,
|
|
@@ -3402,13 +3510,9 @@ function buildBehaviorReplacement(source, spec, behavior) {
|
|
|
3402
3510
|
if (execution) {
|
|
3403
3511
|
configEntries.push(`execution: ${JSON.stringify(execution)}`);
|
|
3404
3512
|
}
|
|
3405
|
-
if (applicationsSource) {
|
|
3406
|
-
configEntries.push(`applications: ${INTERNAL_APPLICATIONS}`);
|
|
3407
|
-
}
|
|
3408
3513
|
const configSource = `Object.freeze({ ${configEntries.join(", ")} })`;
|
|
3409
3514
|
return {
|
|
3410
3515
|
replacement: [
|
|
3411
|
-
...applicationsSource ? [`const ${INTERNAL_APPLICATIONS} = ${applicationsSource};`] : [],
|
|
3412
3516
|
`const ${INTERNAL_CONFIG} = ${configSource};`,
|
|
3413
3517
|
`const ${INTERNAL_RUN} = ${runSource};`,
|
|
3414
3518
|
`export { ${INTERNAL_CONFIG} as config, ${INTERNAL_RUN} as run };`
|
|
@@ -3416,9 +3520,7 @@ function buildBehaviorReplacement(source, spec, behavior) {
|
|
|
3416
3520
|
refs: /* @__PURE__ */ new Set([
|
|
3417
3521
|
INTERNAL_CONFIG,
|
|
3418
3522
|
INTERNAL_RUN,
|
|
3419
|
-
...
|
|
3420
|
-
...refsFromExpressionSource(runSource),
|
|
3421
|
-
...applicationsSource ? refsFromExpressionSource(applicationsSource) : []
|
|
3523
|
+
...refsFromExpressionSource(runSource)
|
|
3422
3524
|
])
|
|
3423
3525
|
};
|
|
3424
3526
|
}
|
|
@@ -3433,11 +3535,9 @@ function buildConversationReplacement(source, spec, conversation) {
|
|
|
3433
3535
|
const execution = compactExecution(conversation.execution);
|
|
3434
3536
|
const onStart = findProperty(spec, "onStart");
|
|
3435
3537
|
const onEnd = findProperty(spec, "onEnd");
|
|
3436
|
-
const applications = findProperty(spec, "applications");
|
|
3437
3538
|
const onMessageSource = functionSourceFromProperty(source, onMessage, "onMessage");
|
|
3438
3539
|
const onStartSource = onStart ? functionSourceFromProperty(source, onStart, "onStart") : void 0;
|
|
3439
3540
|
const onEndSource = onEnd ? functionSourceFromProperty(source, onEnd, "onEnd") : void 0;
|
|
3440
|
-
const applicationsSource = applications ? expressionSourceFromProperty(source, applications, "applications") : void 0;
|
|
3441
3541
|
const configEntries = [
|
|
3442
3542
|
`kind: "conversation"`,
|
|
3443
3543
|
`name: ${JSON.stringify(conversation.name)}`,
|
|
@@ -3447,24 +3547,18 @@ function buildConversationReplacement(source, spec, conversation) {
|
|
|
3447
3547
|
if (execution) {
|
|
3448
3548
|
configEntries.push(`execution: ${JSON.stringify(execution)}`);
|
|
3449
3549
|
}
|
|
3450
|
-
if (applicationsSource) {
|
|
3451
|
-
configEntries.push(`applications: ${INTERNAL_APPLICATIONS}`);
|
|
3452
|
-
}
|
|
3453
3550
|
const configSource = `Object.freeze({ ${configEntries.join(", ")} })`;
|
|
3454
3551
|
const refs = /* @__PURE__ */ new Set([
|
|
3455
3552
|
INTERNAL_CONFIG,
|
|
3456
3553
|
INTERNAL_ON_START,
|
|
3457
3554
|
INTERNAL_ON_MESSAGE,
|
|
3458
3555
|
INTERNAL_ON_END,
|
|
3459
|
-
...applicationsSource ? [INTERNAL_APPLICATIONS] : [],
|
|
3460
3556
|
...refsFromExpressionSource(onMessageSource),
|
|
3461
3557
|
...onStartSource ? refsFromExpressionSource(onStartSource) : [],
|
|
3462
|
-
...onEndSource ? refsFromExpressionSource(onEndSource) : []
|
|
3463
|
-
...applicationsSource ? refsFromExpressionSource(applicationsSource) : []
|
|
3558
|
+
...onEndSource ? refsFromExpressionSource(onEndSource) : []
|
|
3464
3559
|
]);
|
|
3465
3560
|
return {
|
|
3466
3561
|
replacement: [
|
|
3467
|
-
...applicationsSource ? [`const ${INTERNAL_APPLICATIONS} = ${applicationsSource};`] : [],
|
|
3468
3562
|
`const ${INTERNAL_CONFIG} = ${configSource};`,
|
|
3469
3563
|
`const ${INTERNAL_ON_START} = ${onStartSource ?? "undefined"};`,
|
|
3470
3564
|
`const ${INTERNAL_ON_MESSAGE} = ${onMessageSource};`,
|
|
@@ -3549,12 +3643,17 @@ async function buildPipeline(config, cwd = process.cwd(), minify = false, buildD
|
|
|
3549
3643
|
bundleAll(allBehaviorSources, outDir, "behaviors", minify),
|
|
3550
3644
|
bundleAll(allConversationSources, outDir, "conversations", minify)
|
|
3551
3645
|
]);
|
|
3646
|
+
const entrypoints = Object.fromEntries(
|
|
3647
|
+
[...behaviorBundles, ...conversationBundles].map((bundle) => [
|
|
3648
|
+
bundle.name,
|
|
3649
|
+
relative(outDir, bundle.outFile).split("\\").join("/")
|
|
3650
|
+
])
|
|
3651
|
+
);
|
|
3552
3652
|
const manifest = await generateManifest({
|
|
3553
3653
|
cwd,
|
|
3554
3654
|
userFiles: files,
|
|
3555
3655
|
outDir,
|
|
3556
|
-
|
|
3557
|
-
conversationBundles
|
|
3656
|
+
entrypoints
|
|
3558
3657
|
});
|
|
3559
3658
|
validateManifest(manifest);
|
|
3560
3659
|
const { catalog: catalog2, warnings } = generateCatalog(manifest);
|
|
@@ -6681,7 +6780,7 @@ async function catalogShowCommand(options) {
|
|
|
6681
6780
|
|
|
6682
6781
|
// src/index.ts
|
|
6683
6782
|
var program = new Command();
|
|
6684
|
-
program.name("io").description("IO CLI \u2014 build and deploy behaviors").version("0.1.
|
|
6783
|
+
program.name("io").description("IO CLI \u2014 build and deploy behaviors").version("0.1.19");
|
|
6685
6784
|
program.command("init").description("Initialize io.config.json for the current project").option("--yes", "Overwrite existing config without prompting").action(initCommand);
|
|
6686
6785
|
program.command("build").description("Build behaviors from the io/ directory").option("--dir <path>", "Source directory", "io").option("--minify", "Minify bundles", false).action(buildCommand);
|
|
6687
6786
|
program.command("deploy").description("Build and package for deployment").option("--dir <path>", "Source directory", "io").option("--no-minify", "Skip minification").option("--yes", "Skip confirmation prompt").option("--watch", "Tail deployment status until it reaches a terminal state").action(deployCommand);
|