@runtypelabs/cli 2.16.18 → 2.16.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.
Files changed (2) hide show
  1. package/dist/index.js +535 -290
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -615,292 +615,6 @@ function loadBrandConfig(env) {
615
615
  var BRAND = loadBrandConfig();
616
616
  var DEFAULT_BRAND_CONFIG = BRAND_CONFIGS[DEFAULT_BRAND_NAME];
617
617
 
618
- // ../shared/dist/chunk-3BMGMHHD.mjs
619
- function getNestedValue(obj, path16) {
620
- let normalizedPath = path16;
621
- normalizedPath = normalizedPath.replace(/^\$\.?/, "");
622
- normalizedPath = normalizedPath.replace(/\[(\d+)\]/g, ".$1");
623
- normalizedPath = normalizedPath.replace(/\[['"]([^'"\]]+)['"]\]/g, ".$1");
624
- normalizedPath = normalizedPath.replace(/\[([^'"\]]+)\]/g, ".$1");
625
- normalizedPath = normalizedPath.replace(/^\./, "");
626
- const keys = normalizedPath.split(".");
627
- let current = obj;
628
- for (let i = 0; i < keys.length; i++) {
629
- const key = keys[i];
630
- if (current === null || current === void 0 || key === void 0) {
631
- return void 0;
632
- }
633
- if (Array.isArray(current)) {
634
- if (/^\d+$/.test(key)) {
635
- const index = parseInt(key, 10);
636
- if (index >= 0 && index < current.length) {
637
- current = current[index];
638
- } else {
639
- return void 0;
640
- }
641
- } else {
642
- return void 0;
643
- }
644
- } else if (current && typeof current === "object") {
645
- if (DANGEROUS_KEYS.has(key)) return void 0;
646
- current = current[key];
647
- } else {
648
- return void 0;
649
- }
650
- }
651
- return current;
652
- }
653
- var DANGEROUS_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
654
- var TEMPLATE_EXPRESSION_PATTERN = /\{\{([^{}]+)\}\}/g;
655
- function parseTemplateExpression(expr) {
656
- const tokens = tokenizeFallbackExpression(expr);
657
- if (tokens) {
658
- return {
659
- kind: "fallback",
660
- operator: tokens.operator,
661
- operands: tokens.rawOperands.map(parseOperand)
662
- };
663
- }
664
- const trimmed = expr.trim();
665
- const pipeIndex = trimmed.indexOf("|");
666
- if (pipeIndex === -1) {
667
- return { kind: "legacy", variable: trimmed };
668
- }
669
- return {
670
- kind: "legacy",
671
- variable: trimmed.slice(0, pipeIndex).trim(),
672
- defaultValue: trimmed.slice(pipeIndex + 1).trim()
673
- };
674
- }
675
- function tokenizeFallbackExpression(expr) {
676
- const operands = [];
677
- let current = "";
678
- let quote = null;
679
- let operator = null;
680
- for (let i = 0; i < expr.length; i++) {
681
- const ch = expr[i];
682
- if (quote) {
683
- current += ch;
684
- if (ch === quote && countTrailingBackslashes(expr, i) % 2 === 0) {
685
- quote = null;
686
- }
687
- continue;
688
- }
689
- if (ch === '"' || ch === "'") {
690
- quote = ch;
691
- current += ch;
692
- continue;
693
- }
694
- if (ch === "|" && expr[i + 1] === "|") {
695
- if (operator === "??") {
696
- throw new Error(
697
- `Cannot mix '||' and '??' in template expression: "${expr}". Use one operator or wrap branches in separate {{...}} blocks.`
698
- );
699
- }
700
- operator = "||";
701
- operands.push(current);
702
- current = "";
703
- i++;
704
- continue;
705
- }
706
- if (ch === "?" && expr[i + 1] === "?") {
707
- if (operator === "||") {
708
- throw new Error(
709
- `Cannot mix '||' and '??' in template expression: "${expr}". Use one operator or wrap branches in separate {{...}} blocks.`
710
- );
711
- }
712
- operator = "??";
713
- operands.push(current);
714
- current = "";
715
- i++;
716
- continue;
717
- }
718
- current += ch;
719
- }
720
- if (operator === null) return null;
721
- operands.push(current);
722
- return { rawOperands: operands, operator };
723
- }
724
- function parseOperand(raw) {
725
- const t = raw.trim();
726
- if (t.startsWith('"') && t.endsWith('"') && t.length >= 2 || t.startsWith("'") && t.endsWith("'") && t.length >= 2) {
727
- const inner = t.slice(1, -1);
728
- return { kind: "literal", value: inner.replace(/\\(.)/g, "$1") };
729
- }
730
- if (/^-?\d+(\.\d+)?$/.test(t)) {
731
- return { kind: "literal", value: Number(t) };
732
- }
733
- if (t === "true") return { kind: "literal", value: true };
734
- if (t === "false") return { kind: "literal", value: false };
735
- if (t === "null") return { kind: "literal", value: null };
736
- return { kind: "path", path: t };
737
- }
738
- function evaluateOperand(operand, context) {
739
- if (operand.kind === "literal") return operand.value;
740
- return getNestedValue(context, operand.path);
741
- }
742
- function countTrailingBackslashes(s, i) {
743
- let n = 0;
744
- let j2 = i - 1;
745
- while (j2 >= 0 && s[j2] === "\\") {
746
- n++;
747
- j2--;
748
- }
749
- return n;
750
- }
751
- function passesOperator(value, operator) {
752
- if (operator === "||") return Boolean(value);
753
- return value !== null && value !== void 0;
754
- }
755
- function stringifyValue(value) {
756
- if (value === null || value === void 0) return "";
757
- if (typeof value === "object") return JSON.stringify(value);
758
- return String(value);
759
- }
760
- var _SimpleTemplateEngine = class _SimpleTemplateEngine2 {
761
- substitute(template, context = {}) {
762
- const usedVariables = [];
763
- const usedDefaults = [];
764
- const missingVariables = [];
765
- const result = template.replace(_SimpleTemplateEngine2.EXPRESSION_PATTERN, (match, expr) => {
766
- let parsed;
767
- try {
768
- parsed = parseTemplateExpression(expr);
769
- } catch {
770
- return match;
771
- }
772
- if (parsed.kind === "legacy") {
773
- return resolveLegacy(parsed, context, {
774
- usedVariables,
775
- usedDefaults,
776
- missingVariables,
777
- match
778
- });
779
- }
780
- return resolveFallback(parsed, context, {
781
- usedVariables,
782
- missingVariables,
783
- match
784
- });
785
- });
786
- return {
787
- result,
788
- usedVariables,
789
- usedDefaults,
790
- missingVariables
791
- };
792
- }
793
- /**
794
- * Extract all variable references from a template.
795
- * Each `{{ ... }}` produces one entry; for fallback expressions the entry
796
- * carries every path operand under `paths`, and `hasDefault: true` whenever
797
- * the chain has any non-path terminal (literal) the user can fall back to.
798
- */
799
- extractVariables(template) {
800
- const out = [];
801
- const pattern = new RegExp(_SimpleTemplateEngine2.EXPRESSION_PATTERN.source, "g");
802
- let match;
803
- while (match = pattern.exec(template)) {
804
- const expr = match[1];
805
- if (!expr) continue;
806
- let parsed;
807
- try {
808
- parsed = parseTemplateExpression(expr);
809
- } catch {
810
- continue;
811
- }
812
- if (parsed.kind === "legacy") {
813
- if (!parsed.variable) continue;
814
- out.push({
815
- variable: parsed.variable,
816
- hasDefault: parsed.defaultValue !== void 0,
817
- defaultValue: parsed.defaultValue
818
- });
819
- continue;
820
- }
821
- const paths = parsed.operands.filter((o) => o.kind === "path").map((o) => o.path);
822
- const hasLiteralFallback = parsed.operands.some((o) => o.kind === "literal");
823
- const primary = paths[0] ?? "";
824
- out.push({
825
- variable: primary,
826
- hasDefault: hasLiteralFallback,
827
- paths
828
- });
829
- }
830
- return out;
831
- }
832
- /**
833
- * Validate that a template can be processed with given context.
834
- * Returns warnings and errors.
835
- */
836
- validate(template, context = {}) {
837
- const warnings = [];
838
- const errors = [];
839
- try {
840
- const result = this.substitute(template, context);
841
- if (result.usedDefaults.length > 0) {
842
- warnings.push(
843
- `Used ${result.usedDefaults.length} default values: ${result.usedDefaults.map((d) => d.variable).join(", ")}`
844
- );
845
- }
846
- if (result.missingVariables.length > 0) {
847
- errors.push(`Missing variables without defaults: ${result.missingVariables.join(", ")}`);
848
- }
849
- return {
850
- isValid: errors.length === 0,
851
- warnings,
852
- errors
853
- };
854
- } catch (error51) {
855
- return {
856
- isValid: false,
857
- warnings,
858
- errors: [`Template parsing error: ${error51}`]
859
- };
860
- }
861
- }
862
- };
863
- _SimpleTemplateEngine.EXPRESSION_PATTERN = TEMPLATE_EXPRESSION_PATTERN;
864
- var SimpleTemplateEngine = _SimpleTemplateEngine;
865
- function resolveLegacy(parsed, context, tracking) {
866
- const value = getNestedValue(context, parsed.variable);
867
- if (value !== void 0 && value !== null) {
868
- tracking.usedVariables.push(parsed.variable);
869
- return stringifyValue(value);
870
- }
871
- if (parsed.defaultValue !== void 0) {
872
- tracking.usedDefaults.push({
873
- variable: parsed.variable,
874
- defaultValue: parsed.defaultValue
875
- });
876
- return parsed.defaultValue;
877
- }
878
- tracking.missingVariables.push(parsed.variable);
879
- return tracking.match;
880
- }
881
- function resolveFallback(parsed, context, tracking) {
882
- let chosen = null;
883
- for (const operand of parsed.operands) {
884
- const value = evaluateOperand(operand, context);
885
- if (operand.kind === "path" && value !== void 0) {
886
- tracking.usedVariables.push(operand.path);
887
- }
888
- if (chosen === null && passesOperator(value, parsed.operator)) {
889
- chosen = { value, isPath: operand.kind === "path" };
890
- }
891
- }
892
- if (chosen) return stringifyValue(chosen.value);
893
- const last = parsed.operands[parsed.operands.length - 1];
894
- if (last && last.kind === "literal") {
895
- return stringifyValue(last.value);
896
- }
897
- for (const operand of parsed.operands) {
898
- if (operand.kind === "path") tracking.missingVariables.push(operand.path);
899
- }
900
- return tracking.match;
901
- }
902
- var templateEngine = new SimpleTemplateEngine();
903
-
904
618
  // ../../node_modules/.pnpm/zod@4.4.2/node_modules/zod/v4/classic/external.js
905
619
  var external_exports = {};
906
620
  __export(external_exports, {
@@ -15409,6 +15123,328 @@ function date4(params) {
15409
15123
  // ../../node_modules/.pnpm/zod@4.4.2/node_modules/zod/v4/classic/external.js
15410
15124
  config(en_default());
15411
15125
 
15126
+ // ../shared/dist/chunk-TWJN5HII.mjs
15127
+ var apiReleaseChannelSchema = external_exports.enum(["staging", "production"]);
15128
+ var API_ARTIFACT_SCRIPT_PATTERN = /^api-[a-z0-9][a-z0-9-]{0,62}$/;
15129
+ var apiArtifactScriptNameSchema = external_exports.string().regex(
15130
+ API_ARTIFACT_SCRIPT_PATTERN,
15131
+ "API artifact script names look like api-<sha12> or api-<sha12>-<suffix> (lowercase alphanumeric and dashes)"
15132
+ );
15133
+ var apiHeaderOverrideModeSchema = external_exports.enum(["open", "token"]);
15134
+ var apiArtifactStatusSchema = external_exports.enum([
15135
+ "uploaded",
15136
+ "active",
15137
+ "superseded",
15138
+ "pinned",
15139
+ "failed",
15140
+ "deleted"
15141
+ ]);
15142
+ var apiCanaryConfigSchema = external_exports.object({
15143
+ script: apiArtifactScriptNameSchema,
15144
+ percent: external_exports.number().int().min(1).max(100)
15145
+ });
15146
+ var apiRoutingDocSchema = external_exports.object({
15147
+ version: external_exports.number().int().nonnegative(),
15148
+ updatedAt: external_exports.string().min(1),
15149
+ api: external_exports.object({
15150
+ activeScript: apiArtifactScriptNameSchema.nullable(),
15151
+ previousScript: apiArtifactScriptNameSchema.nullable(),
15152
+ canary: apiCanaryConfigSchema.nullable(),
15153
+ pinsEnabled: external_exports.boolean(),
15154
+ legacyFallback: external_exports.boolean(),
15155
+ headerOverride: apiHeaderOverrideModeSchema
15156
+ })
15157
+ }).refine((doc) => doc.api.activeScript !== null || doc.api.legacyFallback, {
15158
+ message: "activeScript may only be null while legacyFallback is true",
15159
+ path: ["api", "activeScript"]
15160
+ });
15161
+
15162
+ // ../shared/dist/chunk-3V2W6XMX.mjs
15163
+ function getNestedValue(obj, path16) {
15164
+ let normalizedPath = path16;
15165
+ normalizedPath = normalizedPath.replace(/^\$\.?/, "");
15166
+ normalizedPath = normalizedPath.replace(/\[(\d+)\]/g, ".$1");
15167
+ normalizedPath = normalizedPath.replace(/\[['"]([^'"\]]+)['"]\]/g, ".$1");
15168
+ normalizedPath = normalizedPath.replace(/\[([^'"\]]+)\]/g, ".$1");
15169
+ normalizedPath = normalizedPath.replace(/^\./, "");
15170
+ const keys = normalizedPath.split(".");
15171
+ let current = obj;
15172
+ for (let i = 0; i < keys.length; i++) {
15173
+ const key = keys[i];
15174
+ if (current === null || current === void 0 || key === void 0) {
15175
+ return void 0;
15176
+ }
15177
+ if (Array.isArray(current)) {
15178
+ if (/^\d+$/.test(key)) {
15179
+ const index = parseInt(key, 10);
15180
+ if (index >= 0 && index < current.length) {
15181
+ current = current[index];
15182
+ } else {
15183
+ return void 0;
15184
+ }
15185
+ } else {
15186
+ return void 0;
15187
+ }
15188
+ } else if (current && typeof current === "object") {
15189
+ if (DANGEROUS_KEYS.has(key)) return void 0;
15190
+ current = current[key];
15191
+ } else {
15192
+ return void 0;
15193
+ }
15194
+ }
15195
+ return current;
15196
+ }
15197
+ var DANGEROUS_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
15198
+ var TEMPLATE_EXPRESSION_PATTERN = /\{\{([^{}]+)\}\}/g;
15199
+ function parseTemplateExpression(expr) {
15200
+ const tokens = tokenizeFallbackExpression(expr);
15201
+ if (tokens) {
15202
+ return {
15203
+ kind: "fallback",
15204
+ operator: tokens.operator,
15205
+ operands: tokens.rawOperands.map(parseOperand)
15206
+ };
15207
+ }
15208
+ const trimmed = expr.trim();
15209
+ const pipeIndex = trimmed.indexOf("|");
15210
+ if (pipeIndex === -1) {
15211
+ return { kind: "legacy", variable: trimmed };
15212
+ }
15213
+ return {
15214
+ kind: "legacy",
15215
+ variable: trimmed.slice(0, pipeIndex).trim(),
15216
+ defaultValue: trimmed.slice(pipeIndex + 1).trim()
15217
+ };
15218
+ }
15219
+ function tokenizeFallbackExpression(expr) {
15220
+ const operands = [];
15221
+ let current = "";
15222
+ let quote = null;
15223
+ let operator = null;
15224
+ for (let i = 0; i < expr.length; i++) {
15225
+ const ch = expr[i];
15226
+ if (quote) {
15227
+ current += ch;
15228
+ if (ch === quote && countTrailingBackslashes(expr, i) % 2 === 0) {
15229
+ quote = null;
15230
+ }
15231
+ continue;
15232
+ }
15233
+ if (ch === '"' || ch === "'") {
15234
+ quote = ch;
15235
+ current += ch;
15236
+ continue;
15237
+ }
15238
+ if (ch === "|" && expr[i + 1] === "|") {
15239
+ if (operator === "??") {
15240
+ throw new Error(
15241
+ `Cannot mix '||' and '??' in template expression: "${expr}". Use one operator or wrap branches in separate {{...}} blocks.`
15242
+ );
15243
+ }
15244
+ operator = "||";
15245
+ operands.push(current);
15246
+ current = "";
15247
+ i++;
15248
+ continue;
15249
+ }
15250
+ if (ch === "?" && expr[i + 1] === "?") {
15251
+ if (operator === "||") {
15252
+ throw new Error(
15253
+ `Cannot mix '||' and '??' in template expression: "${expr}". Use one operator or wrap branches in separate {{...}} blocks.`
15254
+ );
15255
+ }
15256
+ operator = "??";
15257
+ operands.push(current);
15258
+ current = "";
15259
+ i++;
15260
+ continue;
15261
+ }
15262
+ current += ch;
15263
+ }
15264
+ if (operator === null) return null;
15265
+ operands.push(current);
15266
+ return { rawOperands: operands, operator };
15267
+ }
15268
+ function parseOperand(raw) {
15269
+ const t = raw.trim();
15270
+ if (t.startsWith('"') && t.endsWith('"') && t.length >= 2 || t.startsWith("'") && t.endsWith("'") && t.length >= 2) {
15271
+ const inner = t.slice(1, -1);
15272
+ return { kind: "literal", value: inner.replace(/\\(.)/g, "$1") };
15273
+ }
15274
+ if (/^-?\d+(\.\d+)?$/.test(t)) {
15275
+ return { kind: "literal", value: Number(t) };
15276
+ }
15277
+ if (t === "true") return { kind: "literal", value: true };
15278
+ if (t === "false") return { kind: "literal", value: false };
15279
+ if (t === "null") return { kind: "literal", value: null };
15280
+ return { kind: "path", path: t };
15281
+ }
15282
+ function evaluateOperand(operand, context) {
15283
+ if (operand.kind === "literal") return operand.value;
15284
+ return getNestedValue(context, operand.path);
15285
+ }
15286
+ function countTrailingBackslashes(s, i) {
15287
+ let n = 0;
15288
+ let j2 = i - 1;
15289
+ while (j2 >= 0 && s[j2] === "\\") {
15290
+ n++;
15291
+ j2--;
15292
+ }
15293
+ return n;
15294
+ }
15295
+ function passesOperator(value, operator) {
15296
+ if (operator === "||") return Boolean(value);
15297
+ return value !== null && value !== void 0;
15298
+ }
15299
+ function stringifyValue(value) {
15300
+ if (value === null || value === void 0) return "";
15301
+ if (typeof value === "object") return JSON.stringify(value);
15302
+ return String(value);
15303
+ }
15304
+ var _SimpleTemplateEngine = class _SimpleTemplateEngine2 {
15305
+ substitute(template, context = {}) {
15306
+ const usedVariables = [];
15307
+ const usedDefaults = [];
15308
+ const missingVariables = [];
15309
+ const result = template.replace(_SimpleTemplateEngine2.EXPRESSION_PATTERN, (match, expr) => {
15310
+ let parsed;
15311
+ try {
15312
+ parsed = parseTemplateExpression(expr);
15313
+ } catch {
15314
+ return match;
15315
+ }
15316
+ if (parsed.kind === "legacy") {
15317
+ return resolveLegacy(parsed, context, {
15318
+ usedVariables,
15319
+ usedDefaults,
15320
+ missingVariables,
15321
+ match
15322
+ });
15323
+ }
15324
+ return resolveFallback(parsed, context, {
15325
+ usedVariables,
15326
+ missingVariables,
15327
+ match
15328
+ });
15329
+ });
15330
+ return {
15331
+ result,
15332
+ usedVariables,
15333
+ usedDefaults,
15334
+ missingVariables
15335
+ };
15336
+ }
15337
+ /**
15338
+ * Extract all variable references from a template.
15339
+ * Each `{{ ... }}` produces one entry; for fallback expressions the entry
15340
+ * carries every path operand under `paths`, and `hasDefault: true` whenever
15341
+ * the chain has any non-path terminal (literal) the user can fall back to.
15342
+ */
15343
+ extractVariables(template) {
15344
+ const out = [];
15345
+ const pattern = new RegExp(_SimpleTemplateEngine2.EXPRESSION_PATTERN.source, "g");
15346
+ let match;
15347
+ while (match = pattern.exec(template)) {
15348
+ const expr = match[1];
15349
+ if (!expr) continue;
15350
+ let parsed;
15351
+ try {
15352
+ parsed = parseTemplateExpression(expr);
15353
+ } catch {
15354
+ continue;
15355
+ }
15356
+ if (parsed.kind === "legacy") {
15357
+ if (!parsed.variable) continue;
15358
+ out.push({
15359
+ variable: parsed.variable,
15360
+ hasDefault: parsed.defaultValue !== void 0,
15361
+ defaultValue: parsed.defaultValue
15362
+ });
15363
+ continue;
15364
+ }
15365
+ const paths = parsed.operands.filter((o) => o.kind === "path").map((o) => o.path);
15366
+ const hasLiteralFallback = parsed.operands.some((o) => o.kind === "literal");
15367
+ const primary = paths[0] ?? "";
15368
+ out.push({
15369
+ variable: primary,
15370
+ hasDefault: hasLiteralFallback,
15371
+ paths
15372
+ });
15373
+ }
15374
+ return out;
15375
+ }
15376
+ /**
15377
+ * Validate that a template can be processed with given context.
15378
+ * Returns warnings and errors.
15379
+ */
15380
+ validate(template, context = {}) {
15381
+ const warnings = [];
15382
+ const errors = [];
15383
+ try {
15384
+ const result = this.substitute(template, context);
15385
+ if (result.usedDefaults.length > 0) {
15386
+ warnings.push(
15387
+ `Used ${result.usedDefaults.length} default values: ${result.usedDefaults.map((d) => d.variable).join(", ")}`
15388
+ );
15389
+ }
15390
+ if (result.missingVariables.length > 0) {
15391
+ errors.push(`Missing variables without defaults: ${result.missingVariables.join(", ")}`);
15392
+ }
15393
+ return {
15394
+ isValid: errors.length === 0,
15395
+ warnings,
15396
+ errors
15397
+ };
15398
+ } catch (error51) {
15399
+ return {
15400
+ isValid: false,
15401
+ warnings,
15402
+ errors: [`Template parsing error: ${error51}`]
15403
+ };
15404
+ }
15405
+ }
15406
+ };
15407
+ _SimpleTemplateEngine.EXPRESSION_PATTERN = TEMPLATE_EXPRESSION_PATTERN;
15408
+ var SimpleTemplateEngine = _SimpleTemplateEngine;
15409
+ function resolveLegacy(parsed, context, tracking) {
15410
+ const value = getNestedValue(context, parsed.variable);
15411
+ if (value !== void 0 && value !== null) {
15412
+ tracking.usedVariables.push(parsed.variable);
15413
+ return stringifyValue(value);
15414
+ }
15415
+ if (parsed.defaultValue !== void 0) {
15416
+ tracking.usedDefaults.push({
15417
+ variable: parsed.variable,
15418
+ defaultValue: parsed.defaultValue
15419
+ });
15420
+ return parsed.defaultValue;
15421
+ }
15422
+ tracking.missingVariables.push(parsed.variable);
15423
+ return tracking.match;
15424
+ }
15425
+ function resolveFallback(parsed, context, tracking) {
15426
+ let chosen = null;
15427
+ for (const operand of parsed.operands) {
15428
+ const value = evaluateOperand(operand, context);
15429
+ if (operand.kind === "path" && value !== void 0) {
15430
+ tracking.usedVariables.push(operand.path);
15431
+ }
15432
+ if (chosen === null && passesOperator(value, parsed.operator)) {
15433
+ chosen = { value, isPath: operand.kind === "path" };
15434
+ }
15435
+ }
15436
+ if (chosen) return stringifyValue(chosen.value);
15437
+ const last = parsed.operands[parsed.operands.length - 1];
15438
+ if (last && last.kind === "literal") {
15439
+ return stringifyValue(last.value);
15440
+ }
15441
+ for (const operand of parsed.operands) {
15442
+ if (operand.kind === "path") tracking.missingVariables.push(operand.path);
15443
+ }
15444
+ return tracking.match;
15445
+ }
15446
+ var templateEngine = new SimpleTemplateEngine();
15447
+
15412
15448
  // ../shared/dist/index.mjs
15413
15449
  var mediaAnnotationsSchema = external_exports.object({
15414
15450
  audience: external_exports.array(external_exports.enum(["user", "assistant"])).optional()
@@ -16135,7 +16171,7 @@ var productConfigurationSummarySchema = external_exports.object({
16135
16171
  configurationUrl: external_exports.string(),
16136
16172
  handoff: secretHandoffSchema.optional()
16137
16173
  });
16138
- var ORGANIZATION_INTEGRATION_PROVIDERS = ["slack", "telegram", "discord", "linear", "github"];
16174
+ var ORGANIZATION_INTEGRATION_PROVIDERS = ["slack", "telegram", "discord", "linear", "github", "granola"];
16139
16175
  var integrationProviderSchema = external_exports.enum(ORGANIZATION_INTEGRATION_PROVIDERS);
16140
16176
  var integrationStatusSchema = external_exports.enum(["active", "revoked", "pending"]);
16141
16177
  var FILTER_OPERATORS = [
@@ -33283,13 +33319,124 @@ var IMESSAGE_INTEGRATION = {
33283
33319
  }
33284
33320
  ]
33285
33321
  };
33322
+ var GRANOLA_INTEGRATION = {
33323
+ id: "granola",
33324
+ name: "Granola",
33325
+ description: "Read meeting notes, transcripts, and folders from Granola",
33326
+ transport: "http",
33327
+ url: "",
33328
+ // Direct API calls - no external proxy needed
33329
+ requiredCredentials: [],
33330
+ category: MCPServerCategory.PRODUCTIVITY,
33331
+ documentationUrl: "https://docs.granola.ai",
33332
+ icon: "granola",
33333
+ tools: [
33334
+ {
33335
+ name: "list_meeting_notes",
33336
+ description: "List Granola meeting notes, newest first, with cursor pagination. Only notes whose AI summary has been generated are returned. Use updated_after with an ISO 8601 timestamp to fetch notes changed since a checkpoint (e.g. a schedule\u2019s last run time).",
33337
+ parametersSchema: {
33338
+ type: "object",
33339
+ properties: {
33340
+ // @snake-case-ok-start: tool input fields use snake_case for LLM ergonomics
33341
+ created_after: {
33342
+ type: "string",
33343
+ description: "Only return notes created after this ISO 8601 timestamp."
33344
+ },
33345
+ created_before: {
33346
+ type: "string",
33347
+ description: "Only return notes created before this ISO 8601 timestamp."
33348
+ },
33349
+ updated_after: {
33350
+ type: "string",
33351
+ description: "Only return notes updated after this ISO 8601 timestamp."
33352
+ },
33353
+ cursor: {
33354
+ type: "string",
33355
+ description: "Pagination cursor from a previous response."
33356
+ },
33357
+ page_size: {
33358
+ type: "number",
33359
+ description: "Notes per page (1-30, default 10).",
33360
+ minimum: 1,
33361
+ maximum: 30
33362
+ }
33363
+ // @snake-case-ok-end
33364
+ },
33365
+ required: []
33366
+ }
33367
+ },
33368
+ {
33369
+ name: "get_meeting_note",
33370
+ description: "Fetch a single Granola meeting note: AI summary, attendees, calendar event, and folder membership. Returns a not-yet-processed error for meetings whose summary has not been generated. Set include_transcript to also fetch the raw transcript (transcript access is plan-gated by Granola).",
33371
+ parametersSchema: {
33372
+ type: "object",
33373
+ properties: {
33374
+ // @snake-case-ok-start: tool input fields use snake_case for LLM ergonomics
33375
+ note_id: {
33376
+ type: "string",
33377
+ description: "Granola note ID (e.g. not_1d3tmYTlCICgjy)."
33378
+ },
33379
+ include_transcript: {
33380
+ type: "boolean",
33381
+ description: "Include the meeting transcript in the response."
33382
+ }
33383
+ // @snake-case-ok-end
33384
+ },
33385
+ required: ["note_id"]
33386
+ }
33387
+ },
33388
+ {
33389
+ name: "get_meeting_transcript",
33390
+ description: "Fetch only the transcript of a Granola meeting note. Transcript access is plan-gated by Granola (Business/Enterprise).",
33391
+ parametersSchema: {
33392
+ type: "object",
33393
+ properties: {
33394
+ // @snake-case-ok: tool input fields use snake_case for LLM ergonomics
33395
+ note_id: {
33396
+ type: "string",
33397
+ description: "Granola note ID (e.g. not_1d3tmYTlCICgjy)."
33398
+ }
33399
+ },
33400
+ required: ["note_id"]
33401
+ }
33402
+ },
33403
+ {
33404
+ name: "list_folders",
33405
+ description: "List Granola folders accessible to the connected API key.",
33406
+ parametersSchema: {
33407
+ type: "object",
33408
+ properties: {},
33409
+ required: []
33410
+ }
33411
+ },
33412
+ {
33413
+ name: "find_meeting_notes",
33414
+ description: "Search recent Granola meeting notes by title or participant (owner/attendee) name/email. Granola has no server-side search endpoint, so this pages through recent notes (bounded) and filters client-side.",
33415
+ parametersSchema: {
33416
+ type: "object",
33417
+ properties: {
33418
+ query: {
33419
+ type: "string",
33420
+ description: "Text matched case-insensitively against note titles and participant (owner/attendee) names/emails."
33421
+ },
33422
+ since: {
33423
+ type: "string",
33424
+ description: "Only search notes created after this ISO 8601 timestamp (default: last 30 days)."
33425
+ }
33426
+ },
33427
+ required: ["query"]
33428
+ }
33429
+ }
33430
+ ]
33431
+ };
33286
33432
  var INTEGRATIONS_REGISTRY = [
33287
33433
  SLACK_INTEGRATION,
33288
33434
  GOOGLE_INTEGRATION,
33289
33435
  LINEAR_INTEGRATION,
33290
33436
  GITHUB_INTEGRATION,
33291
33437
  TELEGRAM_INTEGRATION,
33292
- IMESSAGE_INTEGRATION
33438
+ IMESSAGE_INTEGRATION,
33439
+ GRANOLA_INTEGRATION
33293
33440
  ];
33294
33441
  function getAllIntegrations() {
33295
33442
  return INTEGRATIONS_REGISTRY;
@@ -33326,6 +33473,18 @@ var DEFAULT_MODELS_FOR_NEW_ACCOUNTS = [
33326
33473
  { provider: "runtype", modelId: "gemma-4-26b-a4b-it", isDefault: false }
33327
33474
  ];
33328
33475
  var DEFAULT_MODEL_ID = DEFAULT_MODELS_FOR_NEW_ACCOUNTS.find((m2) => m2.isDefault)?.modelId ?? "qwen/qwen3.5-9b";
33476
+ var userProfileFeaturesSchema = external_exports.object({
33477
+ enableAgentSkills: external_exports.boolean(),
33478
+ // Routed model id the product generator dispatches with. Driven by the
33479
+ // `product-generator-model` string flag; defaults to `kimi-k2.6`.
33480
+ productGeneratorModel: external_exports.string(),
33481
+ // Gates the WebMCP-powered dashboard assistant (copilot panel + chat
33482
+ // proxy). Driven by the `enable-dashboard-assistant` boolean flag.
33483
+ enableDashboardAssistant: external_exports.boolean(),
33484
+ // Routed model id the dashboard assistant dispatches with. Driven by the
33485
+ // `dashboard-assistant-model` string flag.
33486
+ dashboardAssistantModel: external_exports.string()
33487
+ });
33329
33488
  var MODEL_FAMILY_PROVIDER_IDS = {
33330
33489
  "claude-4-opus": {
33331
33490
  "vercel": "anthropic/claude-4-opus"
@@ -37143,7 +37302,7 @@ var FLOW_STEP_TYPE_METADATA = {
37143
37302
  description: "Execute JavaScript code in a sandboxed environment. Access flow variables via the `input` object and return a result.",
37144
37303
  category: "data",
37145
37304
  isPrompt: false,
37146
- configHints: "script, outputVariable, sandboxProvider (cloudflare-worker (default)|quickjs|runtype-sandbox|daytona), language (required for runtype-sandbox: javascript|typescript|python)"
37305
+ configHints: "script, outputVariable, sandboxProvider (cloudflare-worker (default)|quickjs|runtype-sandbox|daytona), language (required for runtype-sandbox: javascript|typescript|python). Each flow variable is also injected as a top-level `const` in the script scope under cloudflare-worker and daytona \u2014 do NOT `const`/`let`/`var` a same-named variable (throws `SyntaxError: Identifier already declared` at sandbox-load time). Prefer reading flow variables as `input.X` for clarity and forward compatibility."
37147
37306
  },
37148
37307
  template: {
37149
37308
  description: "Render a Liquid template into HTML, email-html, markdown, PDF, or text. Prefer over a prompt step when the output is a structured document (invoice, receipt, email body, report) and the data is already available.",
@@ -37951,13 +38110,92 @@ For agent-driven dynamic spawning, set \`subagentConfig\` on the agent's \`tools
37951
38110
  - Integration tools require the user to have connected the integration in Settings > Integrations
37952
38111
  - Orthogonal tools are available to all users via platform keys`;
37953
38112
  })();
38113
+ var TOOL_SELECTION_SUMMARY = (() => {
38114
+ const integrations = getAllIntegrations();
38115
+ const integrationLines = integrations.map((integration) => {
38116
+ const toolNames = integration.tools.map((t) => `${t.name}`).join(", ");
38117
+ return `- **${integration.name}** (\`builtin:${integration.id}:<tool>\`): ${toolNames}`;
38118
+ });
38119
+ const vendorSlugs = /* @__PURE__ */ new Set();
38120
+ for (const tool of ORTHOGONAL_PLATFORM_TOOLS) {
38121
+ if (tool.hidden || tool.deprecated || !tool.managedExecution.verified) continue;
38122
+ vendorSlugs.add(tool.managedExecution.apiSlug);
38123
+ }
38124
+ const vendorNames = [...vendorSlugs].sort().map((slug) => ORTHOGONAL_API_NAMES[slug] ?? slug).join(", ");
38125
+ return `## Tool Selection Summary
38126
+
38127
+ Tools are added to prompt steps via \`tools: { toolIds: ["<id>"] }\`. The AI model autonomously decides when to call each tool during generation. Pick from the guide below; fetch the full catalogs only when you need parameter details.
38128
+
38129
+ ### Tool Selection Guide
38130
+
38131
+ - **Image generation** \u2192 \`builtin:gpt-image-2\`
38132
+ - **Web search (provider-native, inline citations)** \u2192 see the Provider-Native Search section
38133
+ - **Web search (standalone, AI-powered)** \u2192 \`builtin:exa\`
38134
+ - **Simple web scraping to markdown** \u2192 \`builtin:firecrawl\`
38135
+ - **Rendered web pages, screenshots, structured extraction, or link harvesting** \u2192 \`builtin:browser:markdown\`, \`builtin:browser:snapshot\`, \`builtin:browser:json\`, \`builtin:browser:scrape\`, \`builtin:browser:links\` (stateless, one-shot)
38136
+ - **Autonomous browsing (just want the outcome)** \u2192 \`builtin:browser:agent\` with a natural-language \`goal\` plus \`startUrl\` or \`sessionId\` \u2014 try this BEFORE the manual session tools
38137
+ - **Interactive browsing (precise control)** \u2192 \`builtin:browser:open\`, then \`builtin:browser:click\` / \`type\` / \`scroll\` / \`session-screenshot\` / \`evaluate\` / \`navigate\`, and \`builtin:browser:close\` when done
38138
+ - **Multi-page rendered crawling** \u2192 use the flow \`crawl\` step instead of repeated \`browser:*\` calls
38139
+ - **Find people / company enrichment** \u2192 \`platform:orthogonal:apollo:people_match\`, \`platform:orthogonal:apollo:organization_enrich\`
38140
+ - **Send Slack message** \u2192 \`builtin:slack:send_message\`
38141
+ - **Send email via Gmail** \u2192 \`builtin:google:gmail_send\`
38142
+ - **Create Linear issue** \u2192 \`builtin:linear:create_issue\`
38143
+ - **Create GitHub PR** \u2192 \`builtin:github:create_pull_request\`
38144
+ - **Host a file (public CDN URL or signed private URL)** \u2192 \`builtin:store_asset\`
38145
+ - **Publish an HTML page that renders in the browser** \u2192 \`builtin:publish_page\` (shareable 7-day \`/preview/\` URL)
38146
+ - **Semantic vector search** \u2192 \`builtin:vector-search\`
38147
+ - **Text-to-speech / speech-to-text** \u2192 \`builtin:elevenlabs-tts\` / \`builtin:elevenlabs-stt\`
38148
+ - **Emit rich content** \u2192 \`builtin:emit_artifact_markdown\`, \`builtin:emit_artifact_component\`
38149
+ - **Record CRUD** \u2192 \`builtin:runtype_record_upsert\`, \`builtin:runtype_record_get\`, \`builtin:runtype_record_list\`, \`builtin:runtype_record_delete\`
38150
+ - **Agent memory (persist + recall across sessions)** \u2192 \`builtin:save_memory\`, \`builtin:recall_memory\`, \`builtin:memory_summary\`
38151
+ - **E-commerce checkout** \u2192 \`builtin:ucp_discover\`, \`builtin:ucp_search_catalog\`, \`builtin:ucp_create_checkout\`
38152
+
38153
+ ### Integration Tools (require connected credentials)
38154
+
38155
+ ${integrationLines.join("\n")}
38156
+
38157
+ ### Third-Party API Tools (Orthogonal)
38158
+
38159
+ Platform-managed API tools \u2014 no API key needed. Vendors: ${vendorNames}. Tool ID format: \`platform:orthogonal:<vendor>:<tool>\`.
38160
+
38161
+ ### Custom MCP Servers (saved by the user)
38162
+
38163
+ Reference saved MCP servers in \`toolIds\` as \`mcp:<serverName>:<toolName>\`, or use the wildcard \`mcp:<serverName>:*\` to attach every tool the server exposes (wildcard wins if both forms are present).
38164
+
38165
+ ### Subagent Runtime Tools
38166
+
38167
+ Subagent tools are not catalog entries \u2014 they are runtime tools defined inline on a prompt step's \`tools.runtimeTools\` array with \`toolType: 'subagent'\` (config: \`agentId\` or inline \`agent\`, plus \`allowedTools\`). For agent-driven dynamic spawning, set \`subagentConfig\` on the agent's tools config. Fetch the \`subagent-delegation\` documentation topic for the full guide.
38168
+
38169
+ ### Drill-down
38170
+
38171
+ For full tool descriptions and parameter schemas, fetch the \`builtin-tools\` and \`orthogonal-tools\` documentation topics (or read \`runtype://catalog/builtin-tools\`, \`runtype://catalog/orthogonal-tools\`, and the per-vendor \`runtype://catalog/orthogonal-tools/{vendor}\` resources).`;
38172
+ })();
38173
+ function renderGoldenPathSentence(names) {
38174
+ return `validate with \`${names.validateFlow}\`/\`${names.validateProduct}\` before creating, and test with \`${names.executeAgent}\`/\`${names.runFlow}\` before sharing a result`;
38175
+ }
38176
+ var GOLDEN_PATH_SENTENCE = renderGoldenPathSentence({
38177
+ validateFlow: "validate_flow",
38178
+ validateProduct: "validate_product",
38179
+ executeAgent: "execute_agent",
38180
+ runFlow: "run_flow"
38181
+ });
38182
+ var GOLDEN_PATH_SENTENCE_CODE_MODE = renderGoldenPathSentence({
38183
+ validateFlow: "validateFlow",
38184
+ validateProduct: "validateProduct",
38185
+ executeAgent: "executeAgent",
38186
+ runFlow: "runFlow"
38187
+ });
37954
38188
  var DOCUMENTATION_TOPIC_MAP = {
38189
+ // `index` is intentionally FIRST so it leads the enum in the tool schema —
38190
+ // weak models should discover the task→topic table before anything else.
38191
+ index: "runtype://catalog/topic-index",
37955
38192
  "platform-catalog": "runtype://catalog/platform",
37956
38193
  "surface-types": "runtype://catalog/surface-types",
37957
38194
  "flow-step-types": "runtype://catalog/flow-step-types",
37958
38195
  models: "runtype://catalog/models",
37959
38196
  "product-schema": "runtype://schema/fpo",
37960
38197
  "types-fpo": "runtype://types/fpo",
38198
+ "types-fpo-template": "runtype://types/fpo-template",
37961
38199
  "types-flow-steps": "runtype://types/flow-steps",
37962
38200
  "types-entities": "runtype://types/entities",
37963
38201
  "types-surface-configs": "runtype://types/surface-configs",
@@ -37965,8 +38203,13 @@ var DOCUMENTATION_TOPIC_MAP = {
37965
38203
  "builtin-tools": "runtype://catalog/builtin-tools",
37966
38204
  "agent-skills": "runtype://catalog/skills",
37967
38205
  "external-tools": "runtype://guide/external-tools",
38206
+ "validation-errors": "runtype://guide/validation-errors",
38207
+ "subagent-delegation": "runtype://guide/subagent-delegation",
38208
+ limits: "runtype://catalog/limits",
38209
+ "provider-native-search": "runtype://catalog/provider-native-search",
37968
38210
  "dashboard-links": "runtype://catalog/dashboard-links",
37969
38211
  "mock-ecommerce": "runtype://catalog/mock-ecommerce",
38212
+ "ucp-commerce": "runtype://catalog/ucp-commerce",
37970
38213
  "persona-embed": "runtype://catalog/persona-embed",
37971
38214
  "persona-fullscreen-assistant": "runtype://guide/persona-fullscreen-assistant",
37972
38215
  "sdk-reference": "runtype://types/sdk-reference"
@@ -37986,7 +38229,9 @@ var NON_AI_PROVIDER_IDS = /* @__PURE__ */ new Set([
37986
38229
  // Audio / Speech
37987
38230
  "elevenlabs",
37988
38231
  // Observability
37989
- "braintrust"
38232
+ "braintrust",
38233
+ // Meeting Notes
38234
+ "granola"
37990
38235
  ]);
37991
38236
  function isNonAIProvider(id) {
37992
38237
  const normalized = id.trim().toLowerCase();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@runtypelabs/cli",
3
- "version": "2.16.18",
3
+ "version": "2.16.19",
4
4
  "description": "Command-line interface for Runtype AI platform",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -22,7 +22,7 @@
22
22
  "rosie-skills": "0.8.1",
23
23
  "yaml": "^2.9.0",
24
24
  "@runtypelabs/ink-components": "0.3.2",
25
- "@runtypelabs/sdk": "4.8.0",
25
+ "@runtypelabs/sdk": "4.8.1",
26
26
  "@runtypelabs/terminal-animations": "0.2.1"
27
27
  },
28
28
  "devDependencies": {
@@ -37,7 +37,7 @@
37
37
  "tsx": "^4.7.1",
38
38
  "typescript": "^5.3.3",
39
39
  "vitest": "^4.1.0",
40
- "@runtypelabs/shared": "1.17.1"
40
+ "@runtypelabs/shared": "1.21.0"
41
41
  },
42
42
  "engines": {
43
43
  "node": ">=22.0.0"