lua-cli 3.35.0 → 3.37.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.
@@ -658,6 +658,274 @@ function isDesktopFileSessionId(value3) {
658
658
  }
659
659
  __name(isDesktopFileSessionId, "isDesktopFileSessionId");
660
660
  __name2(isDesktopFileSessionId, "isDesktopFileSessionId");
661
+ var WORKFLOW_RETRY_BACKOFFS = [
662
+ "fixed",
663
+ "exponential"
664
+ ];
665
+ var WORKFLOW_RETRY_MIN_ATTEMPTS = 1;
666
+ var WORKFLOW_RETRY_POLICY_KEYS = [
667
+ "maxAttempts",
668
+ "backoffSeconds",
669
+ "backoff",
670
+ "maxBackoffSeconds"
671
+ ];
672
+ var WORKFLOW_RETRY_MAX_ATTEMPTS = 20;
673
+ function workflowRetryMaxAttemptsMessage(got) {
674
+ const tail = got === void 0 ? "" : ` (got ${JSON.stringify(got)})`;
675
+ return `\`retry.maxAttempts\` must be an integer ${WORKFLOW_RETRY_MIN_ATTEMPTS}..${WORKFLOW_RETRY_MAX_ATTEMPTS}${tail}`;
676
+ }
677
+ __name(workflowRetryMaxAttemptsMessage, "workflowRetryMaxAttemptsMessage");
678
+ __name2(workflowRetryMaxAttemptsMessage, "workflowRetryMaxAttemptsMessage");
679
+ function isWithinWorkflowRetryAttempts(value3) {
680
+ return typeof value3 === "number" && Number.isInteger(value3) && value3 >= WORKFLOW_RETRY_MIN_ATTEMPTS && value3 <= WORKFLOW_RETRY_MAX_ATTEMPTS;
681
+ }
682
+ __name(isWithinWorkflowRetryAttempts, "isWithinWorkflowRetryAttempts");
683
+ __name2(isWithinWorkflowRetryAttempts, "isWithinWorkflowRetryAttempts");
684
+ var WORKFLOW_RETRY_ENGINE_KEYS = [
685
+ "budgetBaseAttempt"
686
+ ];
687
+ function workflowRetryUnknownMembersMessage(keys) {
688
+ const named = keys.map((k) => {
689
+ const engine = WORKFLOW_RETRY_ENGINE_KEYS.includes(k);
690
+ return `\`${k}\`${engine ? " (engine-owned \u2014 stamped by resetAttempts, never authored)" : ""}`;
691
+ });
692
+ return `\`retry\` has no member ${named.join(", ")}; members: ${WORKFLOW_RETRY_POLICY_KEYS.join(", ")}`;
693
+ }
694
+ __name(workflowRetryUnknownMembersMessage, "workflowRetryUnknownMembersMessage");
695
+ __name2(workflowRetryUnknownMembersMessage, "workflowRetryUnknownMembersMessage");
696
+ function unknownWorkflowRetryMembers(retry) {
697
+ if (!retry || typeof retry !== "object" || Array.isArray(retry)) return [];
698
+ return Object.keys(retry).filter((k) => !WORKFLOW_RETRY_POLICY_KEYS.includes(k));
699
+ }
700
+ __name(unknownWorkflowRetryMembers, "unknownWorkflowRetryMembers");
701
+ __name2(unknownWorkflowRetryMembers, "unknownWorkflowRetryMembers");
702
+ function authoredRetryPolicy(retry) {
703
+ if (!retry || typeof retry !== "object" || Array.isArray(retry)) return void 0;
704
+ const src = retry;
705
+ const out = {};
706
+ for (const k of WORKFLOW_RETRY_POLICY_KEYS) if (src[k] !== void 0) out[k] = src[k];
707
+ return Object.keys(out).length ? out : void 0;
708
+ }
709
+ __name(authoredRetryPolicy, "authoredRetryPolicy");
710
+ __name2(authoredRetryPolicy, "authoredRetryPolicy");
711
+ function retryBudgetBaseAttempt(row) {
712
+ const base = row.retry?.budgetBaseAttempt;
713
+ return typeof base === "number" && Number.isSafeInteger(base) && base > 0 ? base : 0;
714
+ }
715
+ __name(retryBudgetBaseAttempt, "retryBudgetBaseAttempt");
716
+ __name2(retryBudgetBaseAttempt, "retryBudgetBaseAttempt");
717
+ function retryBudgetAttempt(row) {
718
+ return Math.max(0, row.attempt - retryBudgetBaseAttempt(row));
719
+ }
720
+ __name(retryBudgetAttempt, "retryBudgetAttempt");
721
+ __name2(retryBudgetAttempt, "retryBudgetAttempt");
722
+ function retryBudgetMaxAttempts(row) {
723
+ const max = row.retry?.maxAttempts;
724
+ return typeof max === "number" && Number.isFinite(max) && max >= 1 ? max : 1;
725
+ }
726
+ __name(retryBudgetMaxAttempts, "retryBudgetMaxAttempts");
727
+ __name2(retryBudgetMaxAttempts, "retryBudgetMaxAttempts");
728
+ function retryBudgetRemaining(row) {
729
+ return retryBudgetAttempt(row) < retryBudgetMaxAttempts(row);
730
+ }
731
+ __name(retryBudgetRemaining, "retryBudgetRemaining");
732
+ __name2(retryBudgetRemaining, "retryBudgetRemaining");
733
+ function retriesRemaining(row) {
734
+ return Math.max(0, retryBudgetMaxAttempts(row) - retryBudgetAttempt(row));
735
+ }
736
+ __name(retriesRemaining, "retriesRemaining");
737
+ __name2(retriesRemaining, "retriesRemaining");
738
+ var WORKFLOW_JOB_RESOURCES = [
739
+ "small",
740
+ "medium",
741
+ "large"
742
+ ];
743
+ var WORKFLOW_SIDE_EFFECTS = [
744
+ "none",
745
+ "external"
746
+ ];
747
+ var WORKFLOW_MODEL_CLASSES = [
748
+ "fast",
749
+ "balanced",
750
+ "strong"
751
+ ];
752
+ function workflowModelCostComparison(estimate, onAgentModel, agentModel) {
753
+ if (agentModel === void 0 || onAgentModel === void 0 || !(onAgentModel > 0)) return void 0;
754
+ const ratio = Math.round(estimate / onAgentModel * 10) / 10;
755
+ return `\u2248 ${ratio}\xD7 the cost of running every step on ${agentModel}`;
756
+ }
757
+ __name(workflowModelCostComparison, "workflowModelCostComparison");
758
+ __name2(workflowModelCostComparison, "workflowModelCostComparison");
759
+ var WORKFLOW_DEFAULT_TASK_CLASS_MAP = Object.freeze({
760
+ classify: "fast",
761
+ extract: "fast",
762
+ transform: "fast",
763
+ draft: "balanced",
764
+ research: "balanced",
765
+ judge: "balanced",
766
+ reason: "strong",
767
+ code: "strong"
768
+ });
769
+ var WORKFLOW_MODELS_MAX_CLASS_DEFAULT = WORKFLOW_MODEL_CLASSES[WORKFLOW_MODEL_CLASSES.length - 1];
770
+ function modelClassRank(modelClass) {
771
+ return WORKFLOW_MODEL_CLASSES.indexOf(modelClass);
772
+ }
773
+ __name(modelClassRank, "modelClassRank");
774
+ __name2(modelClassRank, "modelClassRank");
775
+ function modelClassesAtOrBelow(maxClass) {
776
+ const ceiling = modelClassRank(maxClass);
777
+ return WORKFLOW_MODEL_CLASSES.filter((c) => modelClassRank(c) <= ceiling);
778
+ }
779
+ __name(modelClassesAtOrBelow, "modelClassesAtOrBelow");
780
+ __name2(modelClassesAtOrBelow, "modelClassesAtOrBelow");
781
+ var WORKFLOW_AUTONOMY_NUMERIC_KEYS = [
782
+ "maxCredits",
783
+ "maxSteps",
784
+ "maxDurationSeconds",
785
+ "maxActions",
786
+ "maxRunsPerHour"
787
+ ];
788
+ var WORKFLOW_AUTONOMY_ENVELOPE_KEYS = [
789
+ "enabled",
790
+ ...WORKFLOW_AUTONOMY_NUMERIC_KEYS,
791
+ "forms"
792
+ ];
793
+ var WORKFLOW_AUTONOMY_DEFAULTS = Object.freeze({
794
+ maxCredits: 20,
795
+ maxSteps: 15,
796
+ maxDurationSeconds: 86400,
797
+ maxRunsPerHour: 20
798
+ });
799
+ var WORKFLOW_AUTONOMY_CEILINGS = Object.freeze({
800
+ maxSteps: 40,
801
+ maxDurationSeconds: 604800
802
+ });
803
+ var WORKFLOW_AUTONOMY_MAX_RUNS_PER_HOUR_ENV = "LUA_WF_AUTONOMY_MAX_RUNS_PER_HOUR";
804
+ var WORKFLOW_AUTONOMY_MAX_RUNS_PER_HOUR_CEILING = 200;
805
+ function workflowAutonomyMaxRunsPerHourCeiling(env) {
806
+ const raw = Number((env ?? process.env)[WORKFLOW_AUTONOMY_MAX_RUNS_PER_HOUR_ENV]);
807
+ return Number.isFinite(raw) && raw > 0 ? raw : WORKFLOW_AUTONOMY_MAX_RUNS_PER_HOUR_CEILING;
808
+ }
809
+ __name(workflowAutonomyMaxRunsPerHourCeiling, "workflowAutonomyMaxRunsPerHourCeiling");
810
+ __name2(workflowAutonomyMaxRunsPerHourCeiling, "workflowAutonomyMaxRunsPerHourCeiling");
811
+ var WORKFLOW_AUTONOMY_FORMS_DEFAULT = Object.freeze([
812
+ "graph",
813
+ "static"
814
+ ]);
815
+ var WORKFLOW_AUTONOMY_MIN_VALUE = 1;
816
+ function isWithinWorkflowAutonomyRange(value3, ceiling) {
817
+ return typeof value3 === "number" && Number.isInteger(value3) && value3 >= WORKFLOW_AUTONOMY_MIN_VALUE && value3 <= ceiling;
818
+ }
819
+ __name(isWithinWorkflowAutonomyRange, "isWithinWorkflowAutonomyRange");
820
+ __name2(isWithinWorkflowAutonomyRange, "isWithinWorkflowAutonomyRange");
821
+ function workflowAutonomyRangeMessage(key, ceiling) {
822
+ return `\`${key}\` must be an integer ${WORKFLOW_AUTONOMY_MIN_VALUE}..${ceiling}`;
823
+ }
824
+ __name(workflowAutonomyRangeMessage, "workflowAutonomyRangeMessage");
825
+ __name2(workflowAutonomyRangeMessage, "workflowAutonomyRangeMessage");
826
+ var WORKFLOW_JOB_RANGES = Object.freeze({
827
+ /** Coding-turn cap (`claude -p --max-turns`); absent ⇒ the cluster default (LUA_WF_JOB_MAX_TURNS). */
828
+ maxTurns: Object.freeze({
829
+ min: 1,
830
+ max: 500
831
+ }),
832
+ /** Harness messages per attempt (one per content block); absent ⇒ the cluster default (400). */
833
+ maxMessages: Object.freeze({
834
+ min: 1,
835
+ max: 5e3
836
+ }),
837
+ /** Input-side tokens per attempt (prompt + cache); absent ⇒ the cluster default (4M — LUA-708, was 30M). */
838
+ maxInputTokens: Object.freeze({
839
+ min: 1e6,
840
+ max: 5e8
841
+ })
842
+ });
843
+ var WORKFLOW_JOB_RANGE_MEMBERS = Object.keys(WORKFLOW_JOB_RANGES);
844
+ function isWithinWorkflowJobRange(member, value3) {
845
+ const { min, max } = WORKFLOW_JOB_RANGES[member];
846
+ return typeof value3 === "number" && Number.isInteger(value3) && value3 >= min && value3 <= max;
847
+ }
848
+ __name(isWithinWorkflowJobRange, "isWithinWorkflowJobRange");
849
+ __name2(isWithinWorkflowJobRange, "isWithinWorkflowJobRange");
850
+ function workflowJobRangeMessage(member) {
851
+ const { min, max } = WORKFLOW_JOB_RANGES[member];
852
+ return `\`${member}\` must be an integer ${min}..${max}`;
853
+ }
854
+ __name(workflowJobRangeMessage, "workflowJobRangeMessage");
855
+ __name2(workflowJobRangeMessage, "workflowJobRangeMessage");
856
+ var WORKFLOW_SINGLE_STEP_TYPES = [
857
+ "agent",
858
+ "tool",
859
+ "workflow",
860
+ "step"
861
+ ];
862
+ var WORKFLOW_HITL_ENTRY_TYPES = [
863
+ "approval",
864
+ "waitForSignal"
865
+ ];
866
+ var WORKFLOW_ARM_ENTRY_TYPES = [
867
+ ...WORKFLOW_SINGLE_STEP_TYPES,
868
+ ...WORKFLOW_HITL_ENTRY_TYPES
869
+ ];
870
+ var WORKFLOW_HITL_ARM_CONTAINERS = [
871
+ "parallel",
872
+ "conditional",
873
+ "foreach"
874
+ ];
875
+ function isWorkflowSingleStepType(type) {
876
+ return typeof type === "string" && WORKFLOW_SINGLE_STEP_TYPES.includes(type);
877
+ }
878
+ __name(isWorkflowSingleStepType, "isWorkflowSingleStepType");
879
+ __name2(isWorkflowSingleStepType, "isWorkflowSingleStepType");
880
+ function isWorkflowHitlEntryType(type) {
881
+ return typeof type === "string" && WORKFLOW_HITL_ENTRY_TYPES.includes(type);
882
+ }
883
+ __name(isWorkflowHitlEntryType, "isWorkflowHitlEntryType");
884
+ __name2(isWorkflowHitlEntryType, "isWorkflowHitlEntryType");
885
+ function isWorkflowArmEntryType(type) {
886
+ return typeof type === "string" && WORKFLOW_ARM_ENTRY_TYPES.includes(type);
887
+ }
888
+ __name(isWorkflowArmEntryType, "isWorkflowArmEntryType");
889
+ __name2(isWorkflowArmEntryType, "isWorkflowArmEntryType");
890
+ function workflowContainerRunsHitlArm(container) {
891
+ return typeof container === "string" && WORKFLOW_HITL_ARM_CONTAINERS.includes(container);
892
+ }
893
+ __name(workflowContainerRunsHitlArm, "workflowContainerRunsHitlArm");
894
+ __name2(workflowContainerRunsHitlArm, "workflowContainerRunsHitlArm");
895
+ function workflowHitlArmUnsupportedMessage(type, id, container) {
896
+ const legal = WORKFLOW_HITL_ARM_CONTAINERS.map((c) => `\`${c}\``).join(" / ");
897
+ return `the engine does not run \`${type}\` inside a \`${container}\` yet (node "${id}") \u2014 place it at the top level, as a ${legal} arm, or inside a child \`workflow\``;
898
+ }
899
+ __name(workflowHitlArmUnsupportedMessage, "workflowHitlArmUnsupportedMessage");
900
+ __name2(workflowHitlArmUnsupportedMessage, "workflowHitlArmUnsupportedMessage");
901
+ function workflowHitlArmShapeMessage(type, id, shape) {
902
+ return shape === "mapped-arm" ? `\`${type}\` arm "${id}" takes the previous output as its payload \u2014 it cannot head a [mapping, step] chain; map before the container instead` : `a chunked foreach hands each child a slice of items, not one \u2014 \`${type}\` body "${id}" takes one item; drop \`chunk\``;
903
+ }
904
+ __name(workflowHitlArmShapeMessage, "workflowHitlArmShapeMessage");
905
+ __name2(workflowHitlArmShapeMessage, "workflowHitlArmShapeMessage");
906
+ var WORKFLOW_GRAPH_ENTRY_STEP_KINDS = Object.freeze({
907
+ agent: "agent",
908
+ tool: "tool",
909
+ workflow: "subrun",
910
+ step: "code",
911
+ mapping: "map",
912
+ sleep: "sleep",
913
+ sleepUntil: "sleepUntil",
914
+ parallel: null,
915
+ conditional: "branch",
916
+ foreach: "foreach",
917
+ loop: "loop",
918
+ approval: "approval",
919
+ waitForSignal: "signal"
920
+ });
921
+ var WORKFLOW_ARM_ENTRY_STEP_KINDS = Object.freeze(Object.fromEntries(WORKFLOW_ARM_ENTRY_TYPES.map((t) => [
922
+ t,
923
+ WORKFLOW_GRAPH_ENTRY_STEP_KINDS[t]
924
+ ])));
925
+ var WORKFLOW_BUDGET_MAX_DURATION_SECONDS = Object.freeze({
926
+ min: 60,
927
+ max: 2592e3
928
+ });
661
929
  var MODEL_ID_BYOK_PROVIDERS = [
662
930
  "azure",
663
931
  "bedrock"
@@ -668,6 +936,25 @@ function isModelIdSentinel(input) {
668
936
  }
669
937
  __name(isModelIdSentinel, "isModelIdSentinel");
670
938
  __name2(isModelIdSentinel, "isModelIdSentinel");
939
+ var MODEL_CLASS_REF_PREFIX = "class/";
940
+ function isModelClassRef(input) {
941
+ return modelClassOf(input) !== void 0;
942
+ }
943
+ __name(isModelClassRef, "isModelClassRef");
944
+ __name2(isModelClassRef, "isModelClassRef");
945
+ function modelClassOf(input) {
946
+ const lower = (input ?? "").trim().toLowerCase();
947
+ if (!lower.startsWith(MODEL_CLASS_REF_PREFIX)) return void 0;
948
+ const c = lower.slice(MODEL_CLASS_REF_PREFIX.length);
949
+ return WORKFLOW_MODEL_CLASSES.includes(c) ? c : void 0;
950
+ }
951
+ __name(modelClassOf, "modelClassOf");
952
+ __name2(modelClassOf, "modelClassOf");
953
+ function modelClassRef(modelClass) {
954
+ return `${MODEL_CLASS_REF_PREFIX}${modelClass}`;
955
+ }
956
+ __name(modelClassRef, "modelClassRef");
957
+ __name2(modelClassRef, "modelClassRef");
671
958
  function normalizeModelId(input, registry) {
672
959
  const requested = typeof input === "string" ? input.trim() : "";
673
960
  if (!requested) return {
@@ -682,6 +969,11 @@ function normalizeModelId(input, registry) {
682
969
  id: lower,
683
970
  form: "sentinel"
684
971
  };
972
+ if (modelClassOf(lower) !== void 0) return {
973
+ ok: true,
974
+ id: lower,
975
+ form: "class"
976
+ };
685
977
  const slash = requested.indexOf("/");
686
978
  const malformed = slash === 0;
687
979
  const provider = slash > 0 ? lower.slice(0, slash) : void 0;
@@ -746,6 +1038,11 @@ function modelUnresolvedMessage(r) {
746
1038
  }
747
1039
  __name(modelUnresolvedMessage, "modelUnresolvedMessage");
748
1040
  __name2(modelUnresolvedMessage, "modelUnresolvedMessage");
1041
+ function modelClassUnresolvedMessage(ref) {
1042
+ return `model "${ref.trim()}" is a model-class request that was not resolved before dispatch \u2014 a class is resolved to a concrete approved model by the class map at dispatch, and is never sent to a provider as written; this step refuses rather than run on a substituted model`;
1043
+ }
1044
+ __name(modelClassUnresolvedMessage, "modelClassUnresolvedMessage");
1045
+ __name2(modelClassUnresolvedMessage, "modelClassUnresolvedMessage");
749
1046
  function providerModelId(code) {
750
1047
  const requested = typeof code === "string" ? code.trim() : "";
751
1048
  if (!requested || isModelIdSentinel(requested)) return requested;
@@ -1599,7 +1896,15 @@ var ProjectedOrgSchema = z3.object({
1599
1896
  "org-grant",
1600
1897
  "agent-grant-only"
1601
1898
  ]).describe("For user and staff principals, grant provenance: org-grant means a stored org grant produced the row. For owner-ceiling API keys, effective provenance: org-grant means the credential-owner intersection has org-level capability; agent-grant-only means the intersection reaches only an exact agent inside the org."),
1602
- anomalies: z3.array(ProjectionAnomalySchema).optional()
1899
+ anomalies: z3.array(ProjectionAnomalySchema).optional(),
1900
+ /**
1901
+ * How many agents and Spaces in this org the caller can read — the size of
1902
+ * the org's resource page under the same discovery rule, without paging it.
1903
+ */
1904
+ resourceCounts: z3.object({
1905
+ agents: z3.number().int().nonnegative(),
1906
+ spaces: z3.number().int().nonnegative()
1907
+ }).optional()
1603
1908
  }).passthrough();
1604
1909
  var ProjectedResourceSchema = z3.object({
1605
1910
  resourceType: z3.literal("agent"),
@@ -1638,7 +1943,21 @@ var ProjectedResourceSchema = z3.object({
1638
1943
  id: z3.string().min(1).max(256),
1639
1944
  name: z3.string().optional(),
1640
1945
  email: z3.string().optional()
1641
- }).optional()
1946
+ }).optional(),
1947
+ /**
1948
+ * Presentation enrichment (PRO-1994), product data only — never influences
1949
+ * discovery. These moved off the O(orgs) `/context` roster onto the bounded
1950
+ * per-active-org resource page so Desktop stops paying an org-count-scaled
1951
+ * cost at sign-in. `persona`/`avatar` are loose (`PersonaText` / `AgentAvatar`
1952
+ * are structured-or-string), `platform` marks the org's Designer agent
1953
+ * (previously stamped only by `/context`; retires with PRO-1657).
1954
+ */
1955
+ persona: z3.unknown().optional(),
1956
+ description: z3.string().optional(),
1957
+ avatar: z3.unknown().nullish(),
1958
+ platform: z3.boolean().optional(),
1959
+ /** A Space's supervised agent ids (`kind: 'space'` rows only). */
1960
+ supervisedAgents: z3.array(z3.string()).optional()
1642
1961
  }).passthrough();
1643
1962
  var CapabilityProfilesSchema = z3.record(z3.string().min(1).max(64), z3.array(ProjectedScopeSchema));
1644
1963
  var RoleCatalogSchema = z3.record(z3.string().min(1).max(128), z3.object({
@@ -1824,7 +2143,8 @@ var WORKFLOW_RUN_GATE_KINDS = [
1824
2143
  "org_archived",
1825
2144
  "disabled",
1826
2145
  "exception",
1827
- "budget"
2146
+ "budget",
2147
+ "model_policy"
1828
2148
  ];
1829
2149
  var WORKFLOW_STEP_STATUSES = [
1830
2150
  "pending",
@@ -1959,6 +2279,19 @@ function workflowOrgSlotKey(orgId, kind) {
1959
2279
  __name(workflowOrgSlotKey, "workflowOrgSlotKey");
1960
2280
  __name2(workflowOrgSlotKey, "workflowOrgSlotKey");
1961
2281
  var WORKFLOW_CONNECTION_KEY_RE = /^[a-z][a-z0-9_-]{0,63}$/;
2282
+ var WORKFLOW_JOB_MODEL_SOURCE_LABELS = {
2283
+ stamp: "lease stamp",
2284
+ initData: "run input",
2285
+ default: "placeholder default",
2286
+ node: "node.model",
2287
+ env: "platform default",
2288
+ org: "org default"
2289
+ };
2290
+ function workflowJobModelSourceLabel(source) {
2291
+ return WORKFLOW_JOB_MODEL_SOURCE_LABELS[source];
2292
+ }
2293
+ __name(workflowJobModelSourceLabel, "workflowJobModelSourceLabel");
2294
+ __name2(workflowJobModelSourceLabel, "workflowJobModelSourceLabel");
1962
2295
  function scheduledTimeKey(scheduledTime) {
1963
2296
  return scheduledTime.replace(/[^0-9TZ]/g, "");
1964
2297
  }
@@ -1981,195 +2314,6 @@ var WORKFLOW_RUN_NOTIFICATION_SUSPENDED_KINDS = [
1981
2314
  ];
1982
2315
  var WORKFLOW_SIGNAL_PAYLOAD_MAX_BYTES = 64 * 1024;
1983
2316
  var WORKFLOW_RESOLVE_OUTPUT_MAX_BYTES = 256 * 1024;
1984
- var WORKFLOW_RETRY_BACKOFFS = [
1985
- "fixed",
1986
- "exponential"
1987
- ];
1988
- var WORKFLOW_RETRY_MIN_ATTEMPTS = 1;
1989
- var WORKFLOW_RETRY_POLICY_KEYS = [
1990
- "maxAttempts",
1991
- "backoffSeconds",
1992
- "backoff",
1993
- "maxBackoffSeconds"
1994
- ];
1995
- var WORKFLOW_RETRY_MAX_ATTEMPTS = 20;
1996
- function workflowRetryMaxAttemptsMessage(got) {
1997
- const tail = got === void 0 ? "" : ` (got ${JSON.stringify(got)})`;
1998
- return `\`retry.maxAttempts\` must be an integer ${WORKFLOW_RETRY_MIN_ATTEMPTS}..${WORKFLOW_RETRY_MAX_ATTEMPTS}${tail}`;
1999
- }
2000
- __name(workflowRetryMaxAttemptsMessage, "workflowRetryMaxAttemptsMessage");
2001
- __name2(workflowRetryMaxAttemptsMessage, "workflowRetryMaxAttemptsMessage");
2002
- function isWithinWorkflowRetryAttempts(value3) {
2003
- return typeof value3 === "number" && Number.isInteger(value3) && value3 >= WORKFLOW_RETRY_MIN_ATTEMPTS && value3 <= WORKFLOW_RETRY_MAX_ATTEMPTS;
2004
- }
2005
- __name(isWithinWorkflowRetryAttempts, "isWithinWorkflowRetryAttempts");
2006
- __name2(isWithinWorkflowRetryAttempts, "isWithinWorkflowRetryAttempts");
2007
- var WORKFLOW_RETRY_ENGINE_KEYS = [
2008
- "budgetBaseAttempt"
2009
- ];
2010
- function workflowRetryUnknownMembersMessage(keys) {
2011
- const named = keys.map((k) => {
2012
- const engine = WORKFLOW_RETRY_ENGINE_KEYS.includes(k);
2013
- return `\`${k}\`${engine ? " (engine-owned \u2014 stamped by resetAttempts, never authored)" : ""}`;
2014
- });
2015
- return `\`retry\` has no member ${named.join(", ")}; members: ${WORKFLOW_RETRY_POLICY_KEYS.join(", ")}`;
2016
- }
2017
- __name(workflowRetryUnknownMembersMessage, "workflowRetryUnknownMembersMessage");
2018
- __name2(workflowRetryUnknownMembersMessage, "workflowRetryUnknownMembersMessage");
2019
- function unknownWorkflowRetryMembers(retry) {
2020
- if (!retry || typeof retry !== "object" || Array.isArray(retry)) return [];
2021
- return Object.keys(retry).filter((k) => !WORKFLOW_RETRY_POLICY_KEYS.includes(k));
2022
- }
2023
- __name(unknownWorkflowRetryMembers, "unknownWorkflowRetryMembers");
2024
- __name2(unknownWorkflowRetryMembers, "unknownWorkflowRetryMembers");
2025
- function authoredRetryPolicy(retry) {
2026
- if (!retry || typeof retry !== "object" || Array.isArray(retry)) return void 0;
2027
- const src = retry;
2028
- const out = {};
2029
- for (const k of WORKFLOW_RETRY_POLICY_KEYS) if (src[k] !== void 0) out[k] = src[k];
2030
- return Object.keys(out).length ? out : void 0;
2031
- }
2032
- __name(authoredRetryPolicy, "authoredRetryPolicy");
2033
- __name2(authoredRetryPolicy, "authoredRetryPolicy");
2034
- function retryBudgetBaseAttempt(row) {
2035
- const base = row.retry?.budgetBaseAttempt;
2036
- return typeof base === "number" && Number.isSafeInteger(base) && base > 0 ? base : 0;
2037
- }
2038
- __name(retryBudgetBaseAttempt, "retryBudgetBaseAttempt");
2039
- __name2(retryBudgetBaseAttempt, "retryBudgetBaseAttempt");
2040
- function retryBudgetAttempt(row) {
2041
- return Math.max(0, row.attempt - retryBudgetBaseAttempt(row));
2042
- }
2043
- __name(retryBudgetAttempt, "retryBudgetAttempt");
2044
- __name2(retryBudgetAttempt, "retryBudgetAttempt");
2045
- function retryBudgetMaxAttempts(row) {
2046
- const max = row.retry?.maxAttempts;
2047
- return typeof max === "number" && Number.isFinite(max) && max >= 1 ? max : 1;
2048
- }
2049
- __name(retryBudgetMaxAttempts, "retryBudgetMaxAttempts");
2050
- __name2(retryBudgetMaxAttempts, "retryBudgetMaxAttempts");
2051
- function retryBudgetRemaining(row) {
2052
- return retryBudgetAttempt(row) < retryBudgetMaxAttempts(row);
2053
- }
2054
- __name(retryBudgetRemaining, "retryBudgetRemaining");
2055
- __name2(retryBudgetRemaining, "retryBudgetRemaining");
2056
- function retriesRemaining(row) {
2057
- return Math.max(0, retryBudgetMaxAttempts(row) - retryBudgetAttempt(row));
2058
- }
2059
- __name(retriesRemaining, "retriesRemaining");
2060
- __name2(retriesRemaining, "retriesRemaining");
2061
- var WORKFLOW_JOB_RESOURCES = [
2062
- "small",
2063
- "medium",
2064
- "large"
2065
- ];
2066
- var WORKFLOW_SIDE_EFFECTS = [
2067
- "none",
2068
- "external"
2069
- ];
2070
- var WORKFLOW_JOB_RANGES = Object.freeze({
2071
- /** Coding-turn cap (`claude -p --max-turns`); absent ⇒ the cluster default (LUA_WF_JOB_MAX_TURNS). */
2072
- maxTurns: Object.freeze({
2073
- min: 1,
2074
- max: 500
2075
- }),
2076
- /** Harness messages per attempt (one per content block); absent ⇒ the cluster default (400). */
2077
- maxMessages: Object.freeze({
2078
- min: 1,
2079
- max: 5e3
2080
- }),
2081
- /** Input-side tokens per attempt (prompt + cache); absent ⇒ the cluster default (4M — LUA-708, was 30M). */
2082
- maxInputTokens: Object.freeze({
2083
- min: 1e6,
2084
- max: 5e8
2085
- })
2086
- });
2087
- var WORKFLOW_JOB_RANGE_MEMBERS = Object.keys(WORKFLOW_JOB_RANGES);
2088
- function isWithinWorkflowJobRange(member, value3) {
2089
- const { min, max } = WORKFLOW_JOB_RANGES[member];
2090
- return typeof value3 === "number" && Number.isInteger(value3) && value3 >= min && value3 <= max;
2091
- }
2092
- __name(isWithinWorkflowJobRange, "isWithinWorkflowJobRange");
2093
- __name2(isWithinWorkflowJobRange, "isWithinWorkflowJobRange");
2094
- function workflowJobRangeMessage(member) {
2095
- const { min, max } = WORKFLOW_JOB_RANGES[member];
2096
- return `\`${member}\` must be an integer ${min}..${max}`;
2097
- }
2098
- __name(workflowJobRangeMessage, "workflowJobRangeMessage");
2099
- __name2(workflowJobRangeMessage, "workflowJobRangeMessage");
2100
- var WORKFLOW_SINGLE_STEP_TYPES = [
2101
- "agent",
2102
- "tool",
2103
- "workflow",
2104
- "step"
2105
- ];
2106
- var WORKFLOW_HITL_ENTRY_TYPES = [
2107
- "approval",
2108
- "waitForSignal"
2109
- ];
2110
- var WORKFLOW_ARM_ENTRY_TYPES = [
2111
- ...WORKFLOW_SINGLE_STEP_TYPES,
2112
- ...WORKFLOW_HITL_ENTRY_TYPES
2113
- ];
2114
- var WORKFLOW_HITL_ARM_CONTAINERS = [
2115
- "parallel",
2116
- "conditional",
2117
- "foreach"
2118
- ];
2119
- function isWorkflowSingleStepType(type) {
2120
- return typeof type === "string" && WORKFLOW_SINGLE_STEP_TYPES.includes(type);
2121
- }
2122
- __name(isWorkflowSingleStepType, "isWorkflowSingleStepType");
2123
- __name2(isWorkflowSingleStepType, "isWorkflowSingleStepType");
2124
- function isWorkflowHitlEntryType(type) {
2125
- return typeof type === "string" && WORKFLOW_HITL_ENTRY_TYPES.includes(type);
2126
- }
2127
- __name(isWorkflowHitlEntryType, "isWorkflowHitlEntryType");
2128
- __name2(isWorkflowHitlEntryType, "isWorkflowHitlEntryType");
2129
- function isWorkflowArmEntryType(type) {
2130
- return typeof type === "string" && WORKFLOW_ARM_ENTRY_TYPES.includes(type);
2131
- }
2132
- __name(isWorkflowArmEntryType, "isWorkflowArmEntryType");
2133
- __name2(isWorkflowArmEntryType, "isWorkflowArmEntryType");
2134
- function workflowContainerRunsHitlArm(container) {
2135
- return typeof container === "string" && WORKFLOW_HITL_ARM_CONTAINERS.includes(container);
2136
- }
2137
- __name(workflowContainerRunsHitlArm, "workflowContainerRunsHitlArm");
2138
- __name2(workflowContainerRunsHitlArm, "workflowContainerRunsHitlArm");
2139
- function workflowHitlArmUnsupportedMessage(type, id, container) {
2140
- const legal = WORKFLOW_HITL_ARM_CONTAINERS.map((c) => `\`${c}\``).join(" / ");
2141
- return `the engine does not run \`${type}\` inside a \`${container}\` yet (node "${id}") \u2014 place it at the top level, as a ${legal} arm, or inside a child \`workflow\``;
2142
- }
2143
- __name(workflowHitlArmUnsupportedMessage, "workflowHitlArmUnsupportedMessage");
2144
- __name2(workflowHitlArmUnsupportedMessage, "workflowHitlArmUnsupportedMessage");
2145
- function workflowHitlArmShapeMessage(type, id, shape) {
2146
- return shape === "mapped-arm" ? `\`${type}\` arm "${id}" takes the previous output as its payload \u2014 it cannot head a [mapping, step] chain; map before the container instead` : `a chunked foreach hands each child a slice of items, not one \u2014 \`${type}\` body "${id}" takes one item; drop \`chunk\``;
2147
- }
2148
- __name(workflowHitlArmShapeMessage, "workflowHitlArmShapeMessage");
2149
- __name2(workflowHitlArmShapeMessage, "workflowHitlArmShapeMessage");
2150
- var WORKFLOW_GRAPH_ENTRY_STEP_KINDS = Object.freeze({
2151
- agent: "agent",
2152
- tool: "tool",
2153
- workflow: "subrun",
2154
- step: "code",
2155
- mapping: "map",
2156
- sleep: "sleep",
2157
- sleepUntil: "sleepUntil",
2158
- parallel: null,
2159
- conditional: "branch",
2160
- foreach: "foreach",
2161
- loop: "loop",
2162
- approval: "approval",
2163
- waitForSignal: "signal"
2164
- });
2165
- var WORKFLOW_ARM_ENTRY_STEP_KINDS = Object.freeze(Object.fromEntries(WORKFLOW_ARM_ENTRY_TYPES.map((t) => [
2166
- t,
2167
- WORKFLOW_GRAPH_ENTRY_STEP_KINDS[t]
2168
- ])));
2169
- var WORKFLOW_BUDGET_MAX_DURATION_SECONDS = Object.freeze({
2170
- min: 60,
2171
- max: 2592e3
2172
- });
2173
2317
  var WORKFLOW_GOAL_JUDGE_SELF = "$self";
2174
2318
  function workflowGoalJudgeKind(judge) {
2175
2319
  return judge && typeof judge === "object" && judge.predicate !== void 0 ? "predicate" : "agent";
@@ -2457,7 +2601,36 @@ var WORKFLOW_AUDIT_EVENTS = [
2457
2601
  "workflow.export.auto_pushed",
2458
2602
  "workflow.retention.restamped",
2459
2603
  "workflow.retention.reaped",
2460
- "workflow.run.schema_migrated"
2604
+ "workflow.run.schema_migrated",
2605
+ // --- per-step model selection (Workflow Model Selection plan 6.5 / Appendix C.4) ---
2606
+ /** A `PATCH /admin/orgs/:orgId/workflow-policy` that changed the `models` block (who, what moved). */
2607
+ "workflow.policy.models_changed",
2608
+ /** A step's invocation hopped to another leg of its class — `{from, to, reason}`, priced at the served model. */
2609
+ "workflow.step.model_fallback",
2610
+ // --- autonomy envelope (Workflow autonomy plan A1; research/consent-gates.md §H2) ---
2611
+ /**
2612
+ * A start the consent ladder would have PARKED was admitted by `workflowPolicy.autonomy` instead —
2613
+ * `WorkflowRunAutonomyAppliedPayload`. Deliberately NOT `workflow.run.gate_cleared`: nothing was
2614
+ * gated and nobody approved it, and conflating the two would make "who approved this run"
2615
+ * unanswerable for every run of either kind (§H2 "Audit").
2616
+ */
2617
+ "workflow.run.autonomy_applied",
2618
+ // --- run budget cap enforcement (Job-tier billing plan D4; BAC-677) ---
2619
+ /**
2620
+ * The audit twin of the `run.budget_exceeded` run event (WJB-B2a): the run overshot its
2621
+ * `budget.maxCredits` on its LAST step and completed anyway, `budget.exceeded: true`. The budget family
2622
+ * already mirrors run events here — `workflow.run.budget_parked` / `workflow.run.budget_raised` are the
2623
+ * twins of `run.budget_parked` / `run.budget_raised` — and an organisation reviewing what it was charged
2624
+ * needs the overshoot in the audit store beside the raise that preceded it, not only in the run's own
2625
+ * event stream.
2626
+ *
2627
+ * Declared with the run event rather than after it because the emitter port
2628
+ * (`WorkflowAuditPort.action`, typed `workflow.run.${string}`) does not check against this tuple: a name
2629
+ * that is NOT declared here is written to the audit store all the same and no compiler says so.
2630
+ * Declaring it is what makes the later emitter checkable. `workflow.run.budget_parked` is likewise
2631
+ * declared and not yet emitted.
2632
+ */
2633
+ "workflow.run.budget_exceeded"
2461
2634
  ];
2462
2635
  var WORKFLOW_AUDIT_METADATA_MAX_BYTES = 4 * 1024;
2463
2636
  function isWorkflowAuditEvent(action) {
@@ -3233,7 +3406,7 @@ function modelTemplateInvalidMessage(model, why) {
3233
3406
  __name(modelTemplateInvalidMessage, "modelTemplateInvalidMessage");
3234
3407
  __name4(modelTemplateInvalidMessage, "modelTemplateInvalidMessage");
3235
3408
  function modelTemplateDefaultRequiredMessage(model) {
3236
- return `model "${model}" runs on the Job tier, so its placeholder needs a default \u2014 the harness / provider gates (harness:'claude-code' needs an Anthropic model) classify it at push; write ${model.replace(/\}$/, "|<provider/model>}")}`;
3409
+ return `model "${model}" runs on the Job tier, so its placeholder needs a default \u2014 the harness / provider gates (harness:'claude-code' needs an Anthropic model) classify it at push; write ${model.replace(/\}$/, "|<provider/model>}")} or a class reference (|class/fast, |class/balanced, |class/strong)`;
3237
3410
  }
3238
3411
  __name(modelTemplateDefaultRequiredMessage, "modelTemplateDefaultRequiredMessage");
3239
3412
  __name4(modelTemplateDefaultRequiredMessage, "modelTemplateDefaultRequiredMessage");
@@ -4008,6 +4181,21 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
4008
4181
  err("required-connection-unknown", `requiredConnections ${JSON.stringify(unknown)} are neither declared connections[].key values nor connections the owner can mount`, `${path}.requiredConnections`, singleId(node));
4009
4182
  }
4010
4183
  }, "checkRequiredConnections");
4184
+ const jobClassifiablePin = /* @__PURE__ */ __name4((model) => {
4185
+ const pin = staticModelPin(model);
4186
+ const modelClass = modelClassOf(pin);
4187
+ if (modelClass === void 0) return pin;
4188
+ const codes = opts.classMap?.[modelClass];
4189
+ if (!codes) return void 0;
4190
+ const jobProviders = opts.policy?.jobProviders;
4191
+ for (const code of codes) {
4192
+ const p = classifyModelProvider(code);
4193
+ if (p === null) continue;
4194
+ if (jobProviders && !jobProviders.includes(p)) continue;
4195
+ return code;
4196
+ }
4197
+ return void 0;
4198
+ }, "jobClassifiablePin");
4011
4199
  const checkTier = /* @__PURE__ */ __name4((node, path) => {
4012
4200
  const id = singleId(node);
4013
4201
  if (node.workspace && node.workspace !== "inherit" && node.tier !== void 0 && node.tier !== "job") {
@@ -4016,7 +4204,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
4016
4204
  if (node.harness !== void 0 && node.tier !== "job") {
4017
4205
  err("harness-requires-job-tier", "`harness` is only legal on a tier:'job' agent step", `${path}.harness`, id);
4018
4206
  }
4019
- const provider = node.type === "agent" ? classifyModelProvider(staticModelPin(node.model)) : null;
4207
+ const provider = node.type === "agent" ? classifyModelProvider(jobClassifiablePin(node.model)) : null;
4020
4208
  if (node.harness === "claude-code" && provider !== null && provider !== "anthropic") {
4021
4209
  err("harness-provider-mismatch", `harness:'claude-code' needs an Anthropic model (model "${node.type === "agent" ? node.model : ""}" is ${provider})`, `${path}.harness`, id);
4022
4210
  }
@@ -4040,6 +4228,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
4040
4228
  }
4041
4229
  const pin = parsed.kind === "template" ? parsed.template.default : node.model;
4042
4230
  if (pin === void 0) return;
4231
+ if (isModelClassRef(pin)) return;
4043
4232
  const inContext = /* @__PURE__ */ __name4((message) => parsed.kind === "template" ? `${message} (the default of ${parsed.template.placeholder})` : message, "inContext");
4044
4233
  const registry = opts.approvedModels;
4045
4234
  if (registry === void 0) return;
@@ -4053,6 +4242,12 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
4053
4242
  const resolved = normalizeModelId(pin, registry);
4054
4243
  if (!resolved.ok) err("model-unresolved", inContext(modelUnresolvedMessage(resolved)), `${path}.model`, id);
4055
4244
  }, "checkModel");
4245
+ const checkTaskClass = /* @__PURE__ */ __name4((node, path) => {
4246
+ if (node.type !== "agent" || node.taskClass === void 0) return;
4247
+ if (!opts.static) return;
4248
+ if (typeof node.model === "string" && node.model.trim()) return;
4249
+ err("task-class-without-model", `taskClass '${String(node.taskClass)}' needs a \`model\` on a pushed definition \u2014 write a class (model: 'class/fast' | 'class/balanced' | 'class/strong') or an approved provider/model code; nothing maps a task class to a model at dispatch, so a step with neither would run on the agent\u2019s own model`, `${path}.taskClass`, singleId(node));
4250
+ }, "checkTaskClass");
4056
4251
  const checkWorkspace = /* @__PURE__ */ __name4((node, path) => {
4057
4252
  const id = singleId(node);
4058
4253
  const ws = workspaceOf(node);
@@ -4139,6 +4334,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
4139
4334
  checkTimeout(node, path);
4140
4335
  checkTier(node, path);
4141
4336
  checkModel(node, path);
4337
+ checkTaskClass(node, path);
4142
4338
  checkRetry(node, path);
4143
4339
  checkWorkspace(node, path);
4144
4340
  if (!opts.static) {
@@ -7078,6 +7274,55 @@ function graphHasJobTierStep(envelopeOrGraph) {
7078
7274
  }
7079
7275
  __name(graphHasJobTierStep, "graphHasJobTierStep");
7080
7276
  __name4(graphHasJobTierStep, "graphHasJobTierStep");
7277
+ function jobTierSteps(envelopeOrGraph) {
7278
+ const out = [];
7279
+ if (!envelopeOrGraph || typeof envelopeOrGraph !== "object") return out;
7280
+ const env = envelopeOrGraph;
7281
+ const graph = Array.isArray(envelopeOrGraph) ? envelopeOrGraph : env.definition?.graph ?? [];
7282
+ if (!Array.isArray(graph)) return out;
7283
+ for (const entry of graph) collectJobTierSteps(entry, out);
7284
+ return out;
7285
+ }
7286
+ __name(jobTierSteps, "jobTierSteps");
7287
+ __name4(jobTierSteps, "jobTierSteps");
7288
+ function jobTierStepIds(envelopeOrGraph) {
7289
+ return jobTierSteps(envelopeOrGraph).map((s) => s.stepId);
7290
+ }
7291
+ __name(jobTierStepIds, "jobTierStepIds");
7292
+ __name4(jobTierStepIds, "jobTierStepIds");
7293
+ function collectJobTierSteps(entry, out) {
7294
+ const n2 = armEntry2(entry);
7295
+ if (!n2 || typeof n2 !== "object") return;
7296
+ const node = n2;
7297
+ const ws = node.workspace;
7298
+ if (node.tier === "job" || ws !== void 0 && ws !== "inherit") {
7299
+ const stepId = typeof node.id === "string" && node.id ? node.id : "(unnamed)";
7300
+ const model = typeof node.model === "string" && node.model.trim() ? node.model.trim() : void 0;
7301
+ out.push(model === void 0 ? {
7302
+ stepId
7303
+ } : {
7304
+ stepId,
7305
+ model
7306
+ });
7307
+ }
7308
+ switch (node.type) {
7309
+ case "parallel":
7310
+ if (Array.isArray(node.steps)) for (const s of node.steps) collectJobTierSteps(s, out);
7311
+ return;
7312
+ case "conditional":
7313
+ if (Array.isArray(node.steps)) for (const s of node.steps) collectJobTierSteps(s, out);
7314
+ if (node.otherwise !== void 0) collectJobTierSteps(node.otherwise, out);
7315
+ return;
7316
+ case "foreach":
7317
+ case "loop":
7318
+ collectJobTierSteps(node.step, out);
7319
+ return;
7320
+ default:
7321
+ return;
7322
+ }
7323
+ }
7324
+ __name(collectJobTierSteps, "collectJobTierSteps");
7325
+ __name4(collectJobTierSteps, "collectJobTierSteps");
7081
7326
 
7082
7327
  // src/types/workflow.ts
7083
7328
  function createStep(s) {
@@ -7294,6 +7539,10 @@ var LuaWorkflow = class {
7294
7539
  maxDurationSeconds: cfg.budget?.maxDurationSeconds ?? (hitl ? WORKFLOW_HITL_MAX_DURATION_SECONDS : WORKFLOW_DEFAULT_MAX_DURATION_SECONDS)
7295
7540
  });
7296
7541
  const envelope = {
7542
+ // A plain build/push is ALWAYS marker 1 (plan 6.4's compatibility row: "a CLI test that a plain push of
7543
+ // such a definition stays at 1"). Moving a definition to 2 — the effort marker — is an explicit act
7544
+ // (`lua push --apply-effort`, or a new compose while assignment is on), never a side effect of the SDK
7545
+ // gaining an `effort` member.
7297
7546
  luaWorkflow: 1,
7298
7547
  budget,
7299
7548
  definition: defined({
@@ -7688,6 +7937,10 @@ var WorkflowBuilderImpl = class WorkflowBuilderImpl2 {
7688
7937
  promptTemplate: templateText(opts.prompt),
7689
7938
  outputSchema: schemaToJson(opts.outputSchema),
7690
7939
  model: opts.model,
7940
+ taskClass: opts.taskClass,
7941
+ requires: opts.requires,
7942
+ modelReason: opts.modelReason,
7943
+ effort: opts.effort,
7691
7944
  toolScope: opts.toolScope,
7692
7945
  systemPrompt: opts.systemPrompt,
7693
7946
  timeoutSeconds: opts.timeoutSeconds,