@kaelen-ai/cli 0.1.16 → 0.1.18

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 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",
@@ -1129,6 +1130,13 @@ function validateTargetExecution(target, declaredApps, declaredEndpoints, errors
1129
1130
  errors.push(`${owner} references undeclared application "${ref}"`);
1130
1131
  }
1131
1132
  }
1133
+ validateApplicationBindings(
1134
+ owner,
1135
+ executionRecord.application_bindings,
1136
+ applicationRefs,
1137
+ declaredApps,
1138
+ errors
1139
+ );
1132
1140
  const endpointRefs = validateScopeList(
1133
1141
  owner,
1134
1142
  "execution.endpoints",
@@ -1161,6 +1169,60 @@ function validateTargetExecution(target, declaredApps, declaredEndpoints, errors
1161
1169
  errors.push(`${owner} endpoints is no longer supported; use execution.endpoints`);
1162
1170
  }
1163
1171
  }
1172
+ function validateApplicationBindings(owner, value, applicationRefs, declaredApps, errors) {
1173
+ if (value === void 0) {
1174
+ if (applicationRefs.length > 0) {
1175
+ errors.push(`${owner} execution.application_bindings is required when execution.applications is set`);
1176
+ }
1177
+ return;
1178
+ }
1179
+ if (!Array.isArray(value)) {
1180
+ errors.push(`${owner} execution.application_bindings must be an array`);
1181
+ return;
1182
+ }
1183
+ const applicationRefSet = new Set(applicationRefs);
1184
+ const boundApplicationNames = /* @__PURE__ */ new Set();
1185
+ const seenAliases = /* @__PURE__ */ new Set();
1186
+ for (const entry of value) {
1187
+ if (!isRecord2(entry)) {
1188
+ errors.push(`${owner} execution.application_bindings entry must be an object`);
1189
+ continue;
1190
+ }
1191
+ for (const key of Object.keys(entry)) {
1192
+ if (key !== "application_name" && key !== "application_alias") {
1193
+ errors.push(
1194
+ `${owner} execution.application_bindings entry contains unsupported key "${key}"`
1195
+ );
1196
+ }
1197
+ }
1198
+ const applicationName = stringField2(entry, "application_name");
1199
+ const applicationAlias = stringField2(entry, "application_alias");
1200
+ if (!applicationName) {
1201
+ errors.push(`${owner} execution.application_bindings entry application_name is required`);
1202
+ continue;
1203
+ }
1204
+ if (!applicationAlias) {
1205
+ errors.push(`${owner} execution.application_bindings entry application_alias is required`);
1206
+ continue;
1207
+ }
1208
+ if (!declaredApps.has(applicationName)) {
1209
+ errors.push(`${owner} execution.application_bindings references undeclared application "${applicationName}"`);
1210
+ }
1211
+ if (!applicationRefSet.has(applicationName)) {
1212
+ errors.push(`${owner} execution.application_bindings references application "${applicationName}" not present in execution.applications`);
1213
+ }
1214
+ if (seenAliases.has(applicationAlias)) {
1215
+ errors.push(`${owner} execution.application_bindings duplicates application_alias "${applicationAlias}"`);
1216
+ }
1217
+ seenAliases.add(applicationAlias);
1218
+ boundApplicationNames.add(applicationName);
1219
+ }
1220
+ for (const ref of applicationRefs) {
1221
+ if (!boundApplicationNames.has(ref)) {
1222
+ errors.push(`${owner} execution.application_bindings is missing application "${ref}"`);
1223
+ }
1224
+ }
1225
+ }
1164
1226
  function validateRateBudget(owner, value, errors) {
1165
1227
  if (value === void 0) return;
1166
1228
  if (!isRecord2(value)) {
@@ -1231,11 +1293,14 @@ function validateToolCapability(appName, resourceName, tool, errors, seenCapabil
1231
1293
  errors.push(`tool "${expected}" capability mode does not match the tool mode`);
1232
1294
  }
1233
1295
  const audit = stringField2(capability, "audit");
1234
- if (mode === "write" && audit !== "sync") {
1235
- errors.push(`write tool "${expected}" must use sync audit`);
1296
+ if (audit !== "finish_only" && audit !== "pre_call") {
1297
+ errors.push(`tool "${expected}" capability audit must be finish_only or pre_call`);
1298
+ }
1299
+ if (mode === "write" && audit !== "pre_call") {
1300
+ errors.push(`write tool "${expected}" must use pre_call audit`);
1236
1301
  }
1237
- if (mode === "read" && audit !== "async") {
1238
- errors.push(`read tool "${expected}" must use async audit`);
1302
+ if (mode === "read" && audit !== "finish_only") {
1303
+ errors.push(`read tool "${expected}" must use finish_only audit`);
1239
1304
  }
1240
1305
  const exposure = stringField2(capability, "credential_exposure");
1241
1306
  if (exposure !== "none" && exposure !== "stdlib") {
@@ -2468,18 +2533,11 @@ ${stdout || "(empty)"}`
2468
2533
 
2469
2534
  // src/build/manifest.ts
2470
2535
  async function generateManifest(input) {
2471
- const entrypoints = {};
2472
- for (const b of input.behaviorBundles) {
2473
- entrypoints[b.name] = `behaviors/${b.name}.js`;
2474
- }
2475
- for (const c of input.conversationBundles) {
2476
- entrypoints[c.name] = `conversations/${c.name}.js`;
2477
- }
2478
2536
  const m = await evaluateAndEmitManifest({
2479
2537
  cwd: input.cwd,
2480
2538
  outDir: input.outDir,
2481
2539
  userFiles: input.userFiles,
2482
- entrypoints
2540
+ entrypoints: input.entrypoints
2483
2541
  });
2484
2542
  await writeFile(
2485
2543
  join(input.outDir, "manifest.json"),
@@ -2510,7 +2568,7 @@ function canonicalize(value) {
2510
2568
  }
2511
2569
 
2512
2570
  // src/build/catalog.ts
2513
- var CATALOG_CONTRACT_VERSION = "io.invocation.v2";
2571
+ var CATALOG_CONTRACT_VERSION = "io.catalog.v1";
2514
2572
  var CATALOG_SNAPSHOT_VERSION = "io_runtime.snapshot.v2";
2515
2573
  var WEBHOOK_RESOURCE_KIND = "webhook";
2516
2574
  var PLATFORM_TOOL_KINDS = /* @__PURE__ */ new Set(["email", "calendar", "contacts"]);
@@ -2943,7 +3001,6 @@ var INTERNAL_RUN = "__io_cli_compiled_run";
2943
3001
  var INTERNAL_ON_START = "__io_cli_compiled_on_start";
2944
3002
  var INTERNAL_ON_MESSAGE = "__io_cli_compiled_on_message";
2945
3003
  var INTERNAL_ON_END = "__io_cli_compiled_on_end";
2946
- var INTERNAL_APPLICATIONS = "__io_cli_compiled_applications";
2947
3004
  function conversationChannel(name) {
2948
3005
  return `session:${name}`;
2949
3006
  }
@@ -3045,13 +3102,6 @@ function functionSourceFromProperty(source, prop, label) {
3045
3102
  }
3046
3103
  return source.slice(value.start, value.end);
3047
3104
  }
3048
- function expressionSourceFromProperty(source, prop, label) {
3049
- const value = prop.value;
3050
- if (!value) {
3051
- throw new BuildError(`compiled target is missing ${label} value`);
3052
- }
3053
- return source.slice(value.start, value.end);
3054
- }
3055
3105
  function replaceRange(source, start, end, text) {
3056
3106
  return `${source.slice(0, start)}${text}${source.slice(end)}`;
3057
3107
  }
@@ -3389,8 +3439,6 @@ function buildBehaviorReplacement(source, spec, behavior) {
3389
3439
  }
3390
3440
  const execution = compactExecution(behavior.execution);
3391
3441
  const runSource = functionSourceFromProperty(source, run, "run");
3392
- const applications = findProperty(spec, "applications");
3393
- const applicationsSource = applications ? expressionSourceFromProperty(source, applications, "applications") : void 0;
3394
3442
  const configEntries = [
3395
3443
  `kind: "behavior"`,
3396
3444
  `name: ${JSON.stringify(behavior.name)}`,
@@ -3399,13 +3447,9 @@ function buildBehaviorReplacement(source, spec, behavior) {
3399
3447
  if (execution) {
3400
3448
  configEntries.push(`execution: ${JSON.stringify(execution)}`);
3401
3449
  }
3402
- if (applicationsSource) {
3403
- configEntries.push(`applications: ${INTERNAL_APPLICATIONS}`);
3404
- }
3405
3450
  const configSource = `Object.freeze({ ${configEntries.join(", ")} })`;
3406
3451
  return {
3407
3452
  replacement: [
3408
- ...applicationsSource ? [`const ${INTERNAL_APPLICATIONS} = ${applicationsSource};`] : [],
3409
3453
  `const ${INTERNAL_CONFIG} = ${configSource};`,
3410
3454
  `const ${INTERNAL_RUN} = ${runSource};`,
3411
3455
  `export { ${INTERNAL_CONFIG} as config, ${INTERNAL_RUN} as run };`
@@ -3413,9 +3457,7 @@ function buildBehaviorReplacement(source, spec, behavior) {
3413
3457
  refs: /* @__PURE__ */ new Set([
3414
3458
  INTERNAL_CONFIG,
3415
3459
  INTERNAL_RUN,
3416
- ...applicationsSource ? [INTERNAL_APPLICATIONS] : [],
3417
- ...refsFromExpressionSource(runSource),
3418
- ...applicationsSource ? refsFromExpressionSource(applicationsSource) : []
3460
+ ...refsFromExpressionSource(runSource)
3419
3461
  ])
3420
3462
  };
3421
3463
  }
@@ -3430,11 +3472,9 @@ function buildConversationReplacement(source, spec, conversation) {
3430
3472
  const execution = compactExecution(conversation.execution);
3431
3473
  const onStart = findProperty(spec, "onStart");
3432
3474
  const onEnd = findProperty(spec, "onEnd");
3433
- const applications = findProperty(spec, "applications");
3434
3475
  const onMessageSource = functionSourceFromProperty(source, onMessage, "onMessage");
3435
3476
  const onStartSource = onStart ? functionSourceFromProperty(source, onStart, "onStart") : void 0;
3436
3477
  const onEndSource = onEnd ? functionSourceFromProperty(source, onEnd, "onEnd") : void 0;
3437
- const applicationsSource = applications ? expressionSourceFromProperty(source, applications, "applications") : void 0;
3438
3478
  const configEntries = [
3439
3479
  `kind: "conversation"`,
3440
3480
  `name: ${JSON.stringify(conversation.name)}`,
@@ -3444,24 +3484,18 @@ function buildConversationReplacement(source, spec, conversation) {
3444
3484
  if (execution) {
3445
3485
  configEntries.push(`execution: ${JSON.stringify(execution)}`);
3446
3486
  }
3447
- if (applicationsSource) {
3448
- configEntries.push(`applications: ${INTERNAL_APPLICATIONS}`);
3449
- }
3450
3487
  const configSource = `Object.freeze({ ${configEntries.join(", ")} })`;
3451
3488
  const refs = /* @__PURE__ */ new Set([
3452
3489
  INTERNAL_CONFIG,
3453
3490
  INTERNAL_ON_START,
3454
3491
  INTERNAL_ON_MESSAGE,
3455
3492
  INTERNAL_ON_END,
3456
- ...applicationsSource ? [INTERNAL_APPLICATIONS] : [],
3457
3493
  ...refsFromExpressionSource(onMessageSource),
3458
3494
  ...onStartSource ? refsFromExpressionSource(onStartSource) : [],
3459
- ...onEndSource ? refsFromExpressionSource(onEndSource) : [],
3460
- ...applicationsSource ? refsFromExpressionSource(applicationsSource) : []
3495
+ ...onEndSource ? refsFromExpressionSource(onEndSource) : []
3461
3496
  ]);
3462
3497
  return {
3463
3498
  replacement: [
3464
- ...applicationsSource ? [`const ${INTERNAL_APPLICATIONS} = ${applicationsSource};`] : [],
3465
3499
  `const ${INTERNAL_CONFIG} = ${configSource};`,
3466
3500
  `const ${INTERNAL_ON_START} = ${onStartSource ?? "undefined"};`,
3467
3501
  `const ${INTERNAL_ON_MESSAGE} = ${onMessageSource};`,
@@ -3546,12 +3580,17 @@ async function buildPipeline(config, cwd = process.cwd(), minify = false, buildD
3546
3580
  bundleAll(allBehaviorSources, outDir, "behaviors", minify),
3547
3581
  bundleAll(allConversationSources, outDir, "conversations", minify)
3548
3582
  ]);
3583
+ const entrypoints = Object.fromEntries(
3584
+ [...behaviorBundles, ...conversationBundles].map((bundle) => [
3585
+ bundle.name,
3586
+ relative(outDir, bundle.outFile).split("\\").join("/")
3587
+ ])
3588
+ );
3549
3589
  const manifest = await generateManifest({
3550
3590
  cwd,
3551
3591
  userFiles: files,
3552
3592
  outDir,
3553
- behaviorBundles,
3554
- conversationBundles
3593
+ entrypoints
3555
3594
  });
3556
3595
  validateManifest(manifest);
3557
3596
  const { catalog: catalog2, warnings } = generateCatalog(manifest);
@@ -4127,7 +4166,7 @@ function isPlainObject(value) {
4127
4166
  }
4128
4167
  function isCatalogShape(value) {
4129
4168
  if (!isPlainObject(value)) return false;
4130
- return value.contract_version === "io.invocation.v2" && value.snapshot_version === "io_runtime.snapshot.v2" && typeof value.catalog_hash === "string" && isPlainObject(value.resources) && isPlainObject(value.signals) && isPlainObject(value.tools) && isPlainObject(value.schemas);
4169
+ return value.contract_version === "io.catalog.v1" && value.snapshot_version === "io_runtime.snapshot.v2" && typeof value.catalog_hash === "string" && isPlainObject(value.resources) && isPlainObject(value.signals) && isPlainObject(value.tools) && isPlainObject(value.schemas);
4131
4170
  }
4132
4171
  function isManifestShape(value) {
4133
4172
  if (!isPlainObject(value)) return false;
@@ -4144,7 +4183,7 @@ function parseRemoteCatalog(catalogJson) {
4144
4183
  }
4145
4184
  if (!isCatalogShape(parsed)) {
4146
4185
  throw new ConfigError(
4147
- "Remote deployment catalog does not match the io.invocation.v2 catalog shape."
4186
+ "Remote deployment catalog does not match the io.catalog.v1 catalog shape."
4148
4187
  );
4149
4188
  }
4150
4189
  return parsed;
@@ -4192,6 +4231,15 @@ async function executeGraphQLUnauth(apiUrl, query, variables, headers = {}) {
4192
4231
  }
4193
4232
  return payload.data;
4194
4233
  }
4234
+ function serializePrincipalInput(input) {
4235
+ return {
4236
+ ...input.externalId !== void 0 ? { externalId: input.externalId } : {},
4237
+ ...input.state !== void 0 ? {
4238
+ state: input.state.toUpperCase()
4239
+ } : {},
4240
+ ...input.metadata !== void 0 ? { metadata: input.metadata } : {}
4241
+ };
4242
+ }
4195
4243
  async function refreshAndSave(apiUrl, refreshToken) {
4196
4244
  let data;
4197
4245
  try {
@@ -4441,7 +4489,10 @@ function createClient(config) {
4441
4489
  }
4442
4490
  }
4443
4491
  `,
4444
- { projectId: projectIdValue, input }
4492
+ {
4493
+ projectId: projectIdValue,
4494
+ input: serializePrincipalInput(input)
4495
+ }
4445
4496
  );
4446
4497
  return data.createPrincipal;
4447
4498
  }
@@ -4460,7 +4511,11 @@ function createClient(config) {
4460
4511
  }
4461
4512
  }
4462
4513
  `,
4463
- { projectId: projectIdValue, id, input }
4514
+ {
4515
+ projectId: projectIdValue,
4516
+ id,
4517
+ input: serializePrincipalInput(input)
4518
+ }
4464
4519
  );
4465
4520
  return data.updatePrincipal ?? null;
4466
4521
  }
@@ -4644,7 +4699,6 @@ function createClient(config) {
4644
4699
  eventName,
4645
4700
  payloadJson: JSON.stringify(input.payload ?? {}),
4646
4701
  metadataJson: JSON.stringify(input.metadata ?? {}),
4647
- correlationId: input.correlationId,
4648
4702
  causationId: input.causationId,
4649
4703
  idempotencyKey: input.idempotencyKey,
4650
4704
  sourceName: input.sourceName
@@ -6387,7 +6441,6 @@ async function signalEmitCommand(name, options) {
6387
6441
  principalId: options.principalId,
6388
6442
  payload,
6389
6443
  metadata,
6390
- correlationId: options.correlationId,
6391
6444
  causationId: options.causationId,
6392
6445
  idempotencyKey: options.idempotencyKey,
6393
6446
  sourceName: options.sourceName
@@ -6516,7 +6569,7 @@ function isRecord4(value) {
6516
6569
  }
6517
6570
  function isCatalogShape2(value) {
6518
6571
  if (!isRecord4(value)) return false;
6519
- return value.contract_version === "io.invocation.v2" && value.snapshot_version === "io_runtime.snapshot.v2" && typeof value.catalog_hash === "string" && isRecord4(value.resources) && isRecord4(value.signals) && isRecord4(value.tools) && isRecord4(value.schemas);
6572
+ return value.contract_version === "io.catalog.v1" && value.snapshot_version === "io_runtime.snapshot.v2" && typeof value.catalog_hash === "string" && isRecord4(value.resources) && isRecord4(value.signals) && isRecord4(value.tools) && isRecord4(value.schemas);
6520
6573
  }
6521
6574
  async function readLocalCatalog(buildDir) {
6522
6575
  const path = resolve(process.cwd(), buildDir, "catalog.json");
@@ -6543,7 +6596,7 @@ async function readLocalCatalog(buildDir) {
6543
6596
  }
6544
6597
  if (!isCatalogShape2(parsed)) {
6545
6598
  throw new CliError(
6546
- `Local catalog at ${path} does not match the io.invocation.v2 catalog shape.`,
6599
+ `Local catalog at ${path} does not match the io.catalog.v1 catalog shape.`,
6547
6600
  "CATALOG_SHAPE_MISMATCH"
6548
6601
  );
6549
6602
  }
@@ -6664,7 +6717,7 @@ async function catalogShowCommand(options) {
6664
6717
 
6665
6718
  // src/index.ts
6666
6719
  var program = new Command();
6667
- program.name("io").description("IO CLI \u2014 build and deploy behaviors").version("0.1.16");
6720
+ program.name("io").description("IO CLI \u2014 build and deploy behaviors").version("0.1.18");
6668
6721
  program.command("init").description("Initialize io.config.json for the current project").option("--yes", "Overwrite existing config without prompting").action(initCommand);
6669
6722
  program.command("build").description("Build behaviors from the io/ directory").option("--dir <path>", "Source directory", "io").option("--minify", "Minify bundles", false).action(buildCommand);
6670
6723
  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);
@@ -6685,7 +6738,7 @@ principals.command("create <external-id>").description("Create a principal in th
6685
6738
  principals.command("update <id>").description("Update a principal").option("--project-id <id>", "Override the configured project ID").option("--external-id <external-id>", "Replace the external ID").option("--state <state>", "Principal state: active, inactive, or archived").option("--metadata <json>", "Replace principal metadata with a JSON object").action(principalsUpdateCommand);
6686
6739
  principals.command("delete <id>").description("Delete a principal").option("--project-id <id>", "Override the configured project ID").action(principalsDeleteCommand);
6687
6740
  var signals = program.command("signals").description("Emit runtime signals");
6688
- signals.command("emit <name>").description("Emit a signal into the active project's event stream").option("--payload <json>", "Signal payload as a JSON object", "{}").option("--metadata <json>", "Signal metadata as a JSON object", "{}").option("--project-id <id>", "Override the configured project ID").requiredOption("--principal-id <id>", "Project principal ID for the emitted signal").option("--correlation-id <id>", "Correlation ID to attach to the signal").option("--causation-id <id>", "Causation ID to attach to the signal").option("--idempotency-key <key>", "Optional idempotency key").option("--source-name <name>", "Optional source name for the emitted signal").option("--json", "Print the raw emitted event as JSON", false).action(signalEmitCommand);
6741
+ signals.command("emit <name>").description("Emit a signal into the active project's event stream").option("--payload <json>", "Signal payload as a JSON object", "{}").option("--metadata <json>", "Signal metadata as a JSON object", "{}").option("--project-id <id>", "Override the configured project ID").requiredOption("--principal-id <id>", "Project principal ID for the emitted signal").option("--causation-id <id>", "Causation ID to attach to the signal").option("--idempotency-key <key>", "Optional idempotency key").option("--source-name <name>", "Optional source name for the emitted signal").option("--json", "Print the raw emitted event as JSON", false).action(signalEmitCommand);
6689
6742
  program.command("quota").description("Show current quota usage for the active organization").action(quotaCommand);
6690
6743
  program.command("logs").description("Show recent activity events").option("--limit <count>", "Number of events to show", "50").option("--type <types...>", "Filter by event types").option("--since <duration>", "Show events since (e.g. 15m, 1h, 7d)").option("--follow", "Tail events in real-time").action(logsCommand);
6691
6744
  program.command("reconcile").description("Force runtime to reconcile resources for the active project").option("--project-id <id>", "Override the configured project ID").option("--watch", "Tail activity events after the reconcile request").action(reconcileCommand);