@odla-ai/cli 0.25.19 → 0.25.20

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.cjs CHANGED
@@ -1028,6 +1028,7 @@ var import_node_process8 = __toESM(require("process"), 1);
1028
1028
  var import_node_fs4 = require("fs");
1029
1029
  var import_node_path4 = require("path");
1030
1030
  var import_node_url = require("url");
1031
+ var import_apps = require("@odla-ai/apps");
1031
1032
 
1032
1033
  // src/integration-validation.ts
1033
1034
  function validateIntegrations(cfg, path, defaultServices) {
@@ -1115,6 +1116,7 @@ async function loadProjectConfig(configPath = "odla.config.mjs") {
1115
1116
  const dbEndpoint = trimSlash(process.env.ODLA_DB_ENDPOINT || raw.dbEndpoint || platformUrl);
1116
1117
  const envs = unique2(raw.envs?.length ? raw.envs : DEFAULT_ENVS);
1117
1118
  const services = unique2(raw.services?.length ? raw.services : DEFAULT_SERVICES);
1119
+ validateServices(services, resolved);
1118
1120
  validateCalendarConfig(raw, envs, services, resolved);
1119
1121
  const local = {
1120
1122
  tokenFile: (0, import_node_path4.resolve)(rootDir, raw.local?.tokenFile ?? ".odla/dev-token.json"),
@@ -1270,7 +1272,19 @@ function validateCalendarConfig(cfg, envs, services, path) {
1270
1272
  }
1271
1273
  }
1272
1274
  }
1273
- if (enabled && !services.includes("db")) throw new Error(`${path}: calendar service requires the db service`);
1275
+ }
1276
+ function validateServices(services, path) {
1277
+ for (const service of services) {
1278
+ const definition = (0, import_apps.appServiceDefinition)(service);
1279
+ if (!definition) {
1280
+ throw new Error(`${path}: unknown service "${service}" (known: ${(0, import_apps.appServiceIds)().join(", ")})`);
1281
+ }
1282
+ for (const dependency of definition.requires) {
1283
+ if (!services.includes(dependency)) {
1284
+ throw new Error(`${path}: ${service} service requires the ${dependency} service`);
1285
+ }
1286
+ }
1287
+ }
1274
1288
  }
1275
1289
  function assertOnly(value, allowed, label) {
1276
1290
  const extra = Object.keys(value).find((key) => !allowed.includes(key));
@@ -1594,7 +1608,7 @@ async function adminCommand(parsed, deps = {}) {
1594
1608
  }
1595
1609
 
1596
1610
  // src/tenant.ts
1597
- var import_apps = require("@odla-ai/apps");
1611
+ var import_apps2 = require("@odla-ai/apps");
1598
1612
  function resolveEnv(cfg, requested) {
1599
1613
  const env = requested ?? (cfg.envs.includes("dev") ? "dev" : cfg.envs[0]);
1600
1614
  if (!env || !cfg.envs.includes(env)) {
@@ -1604,7 +1618,7 @@ function resolveEnv(cfg, requested) {
1604
1618
  }
1605
1619
  function resolveTenant(cfg, requested) {
1606
1620
  const env = resolveEnv(cfg, requested);
1607
- return { env, tenant: (0, import_apps.tenantIdFor)(cfg.app.id, env) };
1621
+ return { env, tenant: (0, import_apps2.tenantIdFor)(cfg.app.id, env) };
1608
1622
  }
1609
1623
  function bothTenants(cfg) {
1610
1624
  for (const env of ["dev", "prod"]) {
@@ -1614,7 +1628,7 @@ function bothTenants(cfg) {
1614
1628
  );
1615
1629
  }
1616
1630
  }
1617
- return { sandbox: (0, import_apps.tenantIdFor)(cfg.app.id, "dev"), live: (0, import_apps.tenantIdFor)(cfg.app.id, "prod") };
1631
+ return { sandbox: (0, import_apps2.tenantIdFor)(cfg.app.id, "dev"), live: (0, import_apps2.tenantIdFor)(cfg.app.id, "prod") };
1618
1632
  }
1619
1633
 
1620
1634
  // src/agent-command.ts
@@ -3150,6 +3164,7 @@ function harnessOption(value, flag) {
3150
3164
  // src/init.ts
3151
3165
  var import_node_fs11 = require("fs");
3152
3166
  var import_node_path9 = require("path");
3167
+ var import_apps3 = require("@odla-ai/apps");
3153
3168
  function initProject(options) {
3154
3169
  const out = options.stdout ?? console;
3155
3170
  const rootDir = (0, import_node_path9.resolve)(options.rootDir ?? process.cwd());
@@ -3162,7 +3177,13 @@ function initProject(options) {
3162
3177
  }
3163
3178
  const envs = options.envs?.length ? options.envs : ["dev"];
3164
3179
  const services = options.services?.length ? options.services : ["db", "ai"];
3165
- if (services.includes("calendar") && !services.includes("db")) throw new Error("--services calendar requires db");
3180
+ for (const service of services) {
3181
+ const definition = (0, import_apps3.appServiceDefinition)(service);
3182
+ if (!definition) throw new Error(`--services contains unknown service "${service}" (known: ${(0, import_apps3.appServiceIds)().join(", ")})`);
3183
+ for (const dependency of definition.requires) {
3184
+ if (!services.includes(dependency)) throw new Error(`--services ${service} requires ${dependency}`);
3185
+ }
3186
+ }
3166
3187
  const aiProvider = options.aiProvider ?? "anthropic";
3167
3188
  (0, import_node_fs11.mkdirSync)((0, import_node_path9.dirname)(configPath), { recursive: true });
3168
3189
  (0, import_node_fs11.mkdirSync)((0, import_node_path9.resolve)(rootDir, "src/odla"), { recursive: true });
@@ -3352,7 +3373,7 @@ function assertWranglerConfig(cfg) {
3352
3373
 
3353
3374
  // src/secrets-set.ts
3354
3375
  var import_ai = require("@odla-ai/ai");
3355
- var import_apps2 = require("@odla-ai/apps");
3376
+ var import_apps4 = require("@odla-ai/apps");
3356
3377
  var PROD_ENV_NAMES2 = /* @__PURE__ */ new Set(["prod", "production"]);
3357
3378
  async function secretsSet(options) {
3358
3379
  const name = (options.name ?? "").trim();
@@ -3404,7 +3425,7 @@ async function resolveVaultWrite(options) {
3404
3425
  throw new Error(`refusing to store a secret for "${options.env}" without --yes`);
3405
3426
  }
3406
3427
  const value = await secretInputValue(options, "secret");
3407
- return { cfg, tenantId: (0, import_apps2.tenantIdFor)(cfg.app.id, options.env), value, doFetch, out };
3428
+ return { cfg, tenantId: (0, import_apps4.tenantIdFor)(cfg.app.id, options.env), value, doFetch, out };
3408
3429
  }
3409
3430
 
3410
3431
  // src/skill.ts
@@ -9032,7 +9053,7 @@ async function read2(url, headers, doFetch) {
9032
9053
  }
9033
9054
 
9034
9055
  // src/provision.ts
9035
- var import_apps5 = require("@odla-ai/apps");
9056
+ var import_apps7 = require("@odla-ai/apps");
9036
9057
  var import_ai3 = require("@odla-ai/ai");
9037
9058
  var import_node_process10 = __toESM(require("process"), 1);
9038
9059
 
@@ -9089,9 +9110,9 @@ async function responseText(res) {
9089
9110
  }
9090
9111
 
9091
9112
  // src/provision-credentials.ts
9092
- var import_apps3 = require("@odla-ai/apps");
9113
+ var import_apps5 = require("@odla-ai/apps");
9093
9114
  async function provisionEnvCredentials(opts) {
9094
- const tenantId = (0, import_apps3.tenantIdFor)(opts.cfg.app.id, opts.env);
9115
+ const tenantId = (0, import_apps5.tenantIdFor)(opts.cfg.app.id, opts.env);
9095
9116
  const prior = opts.credentials?.envs[opts.env];
9096
9117
  let credentials = opts.credentials;
9097
9118
  let dbKey = opts.cfg.services.includes("db") && !opts.rotateDb ? prior?.dbKey : void 0;
@@ -9185,18 +9206,13 @@ async function safeText4(res) {
9185
9206
 
9186
9207
  // src/provision-helpers.ts
9187
9208
  var import_ai2 = require("@odla-ai/ai");
9188
- var import_apps4 = require("@odla-ai/apps");
9189
- function serviceRank(service) {
9190
- if (service === "db") return 0;
9191
- if (service === "calendar") return 2;
9192
- return 1;
9193
- }
9209
+ var import_apps6 = require("@odla-ai/apps");
9194
9210
  function defaultSecretName(provider) {
9195
9211
  const names = import_ai2.DEFAULT_SECRET_NAMES;
9196
9212
  return names[provider] ?? `${provider}_api_key`;
9197
9213
  }
9198
9214
  async function assertTenantAdminAccess(doFetch, cfg, env, token) {
9199
- const tenantId = (0, import_apps4.tenantIdFor)(cfg.app.id, env);
9215
+ const tenantId = (0, import_apps6.tenantIdFor)(cfg.app.id, env);
9200
9216
  const res = await doFetch(`${cfg.dbEndpoint}/admin/apps/${encodeURIComponent(tenantId)}/entitlements`, {
9201
9217
  headers: { authorization: `Bearer ${token}` }
9202
9218
  });
@@ -9305,7 +9321,7 @@ async function provision(options) {
9305
9321
  }
9306
9322
  const doFetch = options.fetch ?? fetch;
9307
9323
  const token = await getDeveloperToken(cfg, options, doFetch, out);
9308
- const apps = (0, import_apps5.createAppsClient)({ endpoint: cfg.platformUrl, token, fetcher: { fetch: doFetch } });
9324
+ const apps = (0, import_apps7.createAppsClient)({ endpoint: cfg.platformUrl, token, fetcher: { fetch: doFetch } });
9309
9325
  const existing = await apps.resolveApp(cfg.app.id);
9310
9326
  if (existing) {
9311
9327
  out.log(`app: ${cfg.app.id} already exists`);
@@ -9316,7 +9332,7 @@ async function provision(options) {
9316
9332
  for (const env of cfg.envs) {
9317
9333
  await assertTenantAdminAccess(doFetch, cfg, env, token);
9318
9334
  }
9319
- const serviceOrder = [...cfg.services].sort((a, b) => serviceRank(a) - serviceRank(b));
9335
+ const serviceOrder = (0, import_apps7.orderAppServices)(cfg.services);
9320
9336
  for (const env of cfg.envs) {
9321
9337
  for (const service of serviceOrder) {
9322
9338
  if (service === "ai") {
@@ -9349,7 +9365,7 @@ async function provision(options) {
9349
9365
  }
9350
9366
  }
9351
9367
  for (const env of cfg.envs) {
9352
- const tenantId = (0, import_apps5.tenantIdFor)(cfg.app.id, env);
9368
+ const tenantId = (0, import_apps7.tenantIdFor)(cfg.app.id, env);
9353
9369
  credentials = await provisionEnvCredentials({
9354
9370
  cfg,
9355
9371
  env,