crewly 1.20.274 → 1.20.276

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 (118) hide show
  1. package/config/roles/team-leader/tl-addon.md +7 -0
  2. package/config/skills/team-leader/propose-tier-change/SKILL.md +62 -0
  3. package/config/skills/team-leader/propose-tier-change/execute.sh +64 -0
  4. package/config/skills/team-leader/propose-tier-change/execute.test.sh +75 -0
  5. package/dist/backend/backend/src/constants.d.ts +46 -0
  6. package/dist/backend/backend/src/constants.d.ts.map +1 -1
  7. package/dist/backend/backend/src/constants.js +53 -0
  8. package/dist/backend/backend/src/constants.js.map +1 -1
  9. package/dist/backend/backend/src/controllers/request-types.d.ts +2 -0
  10. package/dist/backend/backend/src/controllers/request-types.d.ts.map +1 -1
  11. package/dist/backend/backend/src/controllers/team/team-model-tiers.controller.d.ts +41 -0
  12. package/dist/backend/backend/src/controllers/team/team-model-tiers.controller.d.ts.map +1 -0
  13. package/dist/backend/backend/src/controllers/team/team-model-tiers.controller.js +112 -0
  14. package/dist/backend/backend/src/controllers/team/team-model-tiers.controller.js.map +1 -0
  15. package/dist/backend/backend/src/controllers/team/team.controller.d.ts.map +1 -1
  16. package/dist/backend/backend/src/controllers/team/team.controller.js +12 -0
  17. package/dist/backend/backend/src/controllers/team/team.controller.js.map +1 -1
  18. package/dist/backend/backend/src/controllers/team/team.routes.d.ts.map +1 -1
  19. package/dist/backend/backend/src/controllers/team/team.routes.js +6 -0
  20. package/dist/backend/backend/src/controllers/team/team.routes.js.map +1 -1
  21. package/dist/backend/backend/src/index.d.ts.map +1 -1
  22. package/dist/backend/backend/src/index.js +5 -0
  23. package/dist/backend/backend/src/index.js.map +1 -1
  24. package/dist/backend/backend/src/services/ai/prompt-builder.service.d.ts.map +1 -1
  25. package/dist/backend/backend/src/services/ai/prompt-builder.service.js +16 -0
  26. package/dist/backend/backend/src/services/ai/prompt-builder.service.js.map +1 -1
  27. package/dist/backend/backend/src/services/ai/prompt-modules/index.d.ts +1 -0
  28. package/dist/backend/backend/src/services/ai/prompt-modules/index.d.ts.map +1 -1
  29. package/dist/backend/backend/src/services/ai/prompt-modules/index.js +1 -0
  30. package/dist/backend/backend/src/services/ai/prompt-modules/index.js.map +1 -1
  31. package/dist/backend/backend/src/services/ai/prompt-modules/model-tiers.module.d.ts +34 -0
  32. package/dist/backend/backend/src/services/ai/prompt-modules/model-tiers.module.d.ts.map +1 -0
  33. package/dist/backend/backend/src/services/ai/prompt-modules/model-tiers.module.js +54 -0
  34. package/dist/backend/backend/src/services/ai/prompt-modules/model-tiers.module.js.map +1 -0
  35. package/dist/backend/backend/src/services/ai/prompt-modules/prompt-assembly.service.d.ts.map +1 -1
  36. package/dist/backend/backend/src/services/ai/prompt-modules/prompt-assembly.service.js +2 -0
  37. package/dist/backend/backend/src/services/ai/prompt-modules/prompt-assembly.service.js.map +1 -1
  38. package/dist/backend/backend/src/services/ai/prompt-modules/prompt-module.interface.d.ts +13 -0
  39. package/dist/backend/backend/src/services/ai/prompt-modules/prompt-module.interface.d.ts.map +1 -1
  40. package/dist/backend/backend/src/services/ai/prompt-modules/prompt-module.interface.js.map +1 -1
  41. package/dist/backend/backend/src/services/decisions/decision.service.d.ts +2 -0
  42. package/dist/backend/backend/src/services/decisions/decision.service.d.ts.map +1 -1
  43. package/dist/backend/backend/src/services/decisions/decision.service.js +1 -0
  44. package/dist/backend/backend/src/services/decisions/decision.service.js.map +1 -1
  45. package/dist/backend/backend/src/services/model-tiers/model-tier.service.d.ts +251 -0
  46. package/dist/backend/backend/src/services/model-tiers/model-tier.service.d.ts.map +1 -0
  47. package/dist/backend/backend/src/services/model-tiers/model-tier.service.js +701 -0
  48. package/dist/backend/backend/src/services/model-tiers/model-tier.service.js.map +1 -0
  49. package/dist/backend/backend/src/services/model-tiers/model-tier.store.d.ts +82 -0
  50. package/dist/backend/backend/src/services/model-tiers/model-tier.store.d.ts.map +1 -0
  51. package/dist/backend/backend/src/services/model-tiers/model-tier.store.js +80 -0
  52. package/dist/backend/backend/src/services/model-tiers/model-tier.store.js.map +1 -0
  53. package/dist/backend/backend/src/services/model-tiers/model-tier.wiring.d.ts +28 -0
  54. package/dist/backend/backend/src/services/model-tiers/model-tier.wiring.d.ts.map +1 -0
  55. package/dist/backend/backend/src/services/model-tiers/model-tier.wiring.js +56 -0
  56. package/dist/backend/backend/src/services/model-tiers/model-tier.wiring.js.map +1 -0
  57. package/dist/backend/backend/src/services/model-tiers/tier-quality.d.ts +102 -0
  58. package/dist/backend/backend/src/services/model-tiers/tier-quality.d.ts.map +1 -0
  59. package/dist/backend/backend/src/services/model-tiers/tier-quality.js +116 -0
  60. package/dist/backend/backend/src/services/model-tiers/tier-quality.js.map +1 -0
  61. package/dist/backend/backend/src/services/model-tiers/tier-usage-report.d.ts +86 -0
  62. package/dist/backend/backend/src/services/model-tiers/tier-usage-report.d.ts.map +1 -0
  63. package/dist/backend/backend/src/services/model-tiers/tier-usage-report.js +148 -0
  64. package/dist/backend/backend/src/services/model-tiers/tier-usage-report.js.map +1 -0
  65. package/dist/backend/backend/src/services/skill/skill-permission.service.d.ts.map +1 -1
  66. package/dist/backend/backend/src/services/skill/skill-permission.service.js +1 -0
  67. package/dist/backend/backend/src/services/skill/skill-permission.service.js.map +1 -1
  68. package/dist/backend/backend/src/types/decision.types.d.ts +41 -1
  69. package/dist/backend/backend/src/types/decision.types.d.ts.map +1 -1
  70. package/dist/backend/backend/src/types/index.d.ts +20 -0
  71. package/dist/backend/backend/src/types/index.d.ts.map +1 -1
  72. package/dist/backend/backend/src/types/index.js.map +1 -1
  73. package/dist/backend/backend/src/utils/member-default-model.utils.d.ts +24 -8
  74. package/dist/backend/backend/src/utils/member-default-model.utils.d.ts.map +1 -1
  75. package/dist/backend/backend/src/utils/member-default-model.utils.js +33 -7
  76. package/dist/backend/backend/src/utils/member-default-model.utils.js.map +1 -1
  77. package/dist/backend/backend/src/utils/model-tier.utils.d.ts +68 -0
  78. package/dist/backend/backend/src/utils/model-tier.utils.d.ts.map +1 -0
  79. package/dist/backend/backend/src/utils/model-tier.utils.js +111 -0
  80. package/dist/backend/backend/src/utils/model-tier.utils.js.map +1 -0
  81. package/dist/backend/build-info.json +2 -2
  82. package/dist/cli/backend/src/constants.d.ts +46 -0
  83. package/dist/cli/backend/src/constants.d.ts.map +1 -1
  84. package/dist/cli/backend/src/constants.js +53 -0
  85. package/dist/cli/backend/src/constants.js.map +1 -1
  86. package/dist/cli/backend/src/services/ai/prompt-builder.service.d.ts.map +1 -1
  87. package/dist/cli/backend/src/services/ai/prompt-builder.service.js +16 -0
  88. package/dist/cli/backend/src/services/ai/prompt-builder.service.js.map +1 -1
  89. package/dist/cli/backend/src/services/ai/prompt-modules/model-tiers.module.d.ts +34 -0
  90. package/dist/cli/backend/src/services/ai/prompt-modules/model-tiers.module.d.ts.map +1 -0
  91. package/dist/cli/backend/src/services/ai/prompt-modules/model-tiers.module.js +54 -0
  92. package/dist/cli/backend/src/services/ai/prompt-modules/model-tiers.module.js.map +1 -0
  93. package/dist/cli/backend/src/services/ai/prompt-modules/prompt-assembly.service.d.ts.map +1 -1
  94. package/dist/cli/backend/src/services/ai/prompt-modules/prompt-assembly.service.js +2 -0
  95. package/dist/cli/backend/src/services/ai/prompt-modules/prompt-assembly.service.js.map +1 -1
  96. package/dist/cli/backend/src/services/ai/prompt-modules/prompt-module.interface.d.ts +13 -0
  97. package/dist/cli/backend/src/services/ai/prompt-modules/prompt-module.interface.d.ts.map +1 -1
  98. package/dist/cli/backend/src/services/ai/prompt-modules/prompt-module.interface.js.map +1 -1
  99. package/dist/cli/backend/src/services/decisions/decision.service.d.ts +2 -0
  100. package/dist/cli/backend/src/services/decisions/decision.service.d.ts.map +1 -1
  101. package/dist/cli/backend/src/services/decisions/decision.service.js +1 -0
  102. package/dist/cli/backend/src/services/decisions/decision.service.js.map +1 -1
  103. package/dist/cli/backend/src/types/decision.types.d.ts +41 -1
  104. package/dist/cli/backend/src/types/decision.types.d.ts.map +1 -1
  105. package/dist/cli/backend/src/types/index.d.ts +20 -0
  106. package/dist/cli/backend/src/types/index.d.ts.map +1 -1
  107. package/dist/cli/backend/src/types/index.js.map +1 -1
  108. package/dist/cli/backend/src/utils/member-default-model.utils.d.ts +24 -8
  109. package/dist/cli/backend/src/utils/member-default-model.utils.d.ts.map +1 -1
  110. package/dist/cli/backend/src/utils/member-default-model.utils.js +33 -7
  111. package/dist/cli/backend/src/utils/member-default-model.utils.js.map +1 -1
  112. package/dist/cli/backend/src/utils/model-tier.utils.d.ts +68 -0
  113. package/dist/cli/backend/src/utils/model-tier.utils.d.ts.map +1 -0
  114. package/dist/cli/backend/src/utils/model-tier.utils.js +111 -0
  115. package/dist/cli/backend/src/utils/model-tier.utils.js.map +1 -0
  116. package/frontend/dist/assets/{index-7e5ebf78.js → index-368419df.js} +266 -266
  117. package/frontend/dist/index.html +1 -1
  118. package/package.json +1 -1
@@ -8,12 +8,14 @@
8
8
  * `modelId` always wins, and the orchestrator is never touched.
9
9
  *
10
10
  * `CREWLY_MEMBER_DEFAULT_MODEL` replaces `sonnet`; `''` or `off` turns the
11
- * default off entirely.
11
+ * default off entirely. A member's tier (crewly#1173) comes before this
12
+ * default: explicit `modelId` > tier model > reviewed default > runtime default.
12
13
  *
13
14
  * @module utils/member-default-model
14
15
  */
15
16
  import { MEMBER_MODEL_DEFAULT_CONSTANTS, ORCHESTRATOR_SESSION_NAME, RUNTIME_TYPES } from '../constants.js';
16
17
  import { isTeamLead, pickTeamLead } from './team.utils.js';
18
+ import { resolveTierModel } from './model-tier.utils.js';
17
19
  /**
18
20
  * The model reviewed members get when they have none, after the env override.
19
21
  *
@@ -78,9 +80,24 @@ export function defaultModelForMember(team, member, env = process.env) {
78
80
  return null;
79
81
  return reviewedMemberDefaultModel(env);
80
82
  }
83
+ /**
84
+ * The model of a member's tier on a runtime (crewly#1173), or undefined when
85
+ * it has no tier or the runtime has no model for it.
86
+ *
87
+ * @param team - The member's team (its `tierModels` override the global map)
88
+ * @param member - The member
89
+ * @param runtime - Runtime that launches
90
+ * @returns Model id, or undefined
91
+ */
92
+ export function tierModelForMember(team, member, runtime) {
93
+ if (member.role === 'orchestrator' || member.sessionName === ORCHESTRATOR_SESSION_NAME)
94
+ return undefined;
95
+ return resolveTierModel(runtime, member.tier, team.tierModels);
96
+ }
81
97
  /**
82
98
  * The model id a member launches with: its own `modelId` when set, else the
83
- * reviewed-member default from {@link defaultModelForMember}.
99
+ * model of its tier on its runtime (crewly#1173), else the reviewed-member
100
+ * default from {@link defaultModelForMember}.
84
101
  *
85
102
  * @param team - The member's team
86
103
  * @param member - The member
@@ -90,6 +107,9 @@ export function defaultModelForMember(team, member, env = process.env) {
90
107
  export function effectiveMemberModelId(team, member, env = process.env) {
91
108
  if (member.modelId)
92
109
  return member.modelId;
110
+ const tiered = tierModelForMember(team, member, member.runtimeType ?? RUNTIME_TYPES.CLAUDE_CODE);
111
+ if (tiered)
112
+ return tiered;
93
113
  return defaultModelForMember(team, member, env) ?? undefined;
94
114
  }
95
115
  /** Model names Claude Code accepts: the aliases, or a full `claude-*` id. */
@@ -98,8 +118,10 @@ const CLAUDE_MODEL_PATTERN = /^(sonnet|opus|haiku|opusplan|default|claude-[A-Za-
98
118
  * The model a member launches with when it runs on a fallback runtime (its
99
119
  * own runtime is out of usage). The member's `modelId` is kept only when the
100
120
  * fallback runtime can use it (a Claude alias / `claude-*` id for Claude Code;
101
- * a Codex `gpt-*` id is ignored). Otherwise the reviewed-member default for
102
- * that runtime applies. Other fallback runtimes get no model (their own default).
121
+ * a Codex `gpt-*` id is ignored). Otherwise its tier's model on the fallback
122
+ * runtime applies (a tier is runtime-neutral, crewly#1173), then the
123
+ * reviewed-member default for that runtime. Other fallback runtimes without a
124
+ * tier model get no model (their own default).
103
125
  *
104
126
  * @param team - The member's team
105
127
  * @param member - The member (its configured runtime does not matter here)
@@ -108,11 +130,15 @@ const CLAUDE_MODEL_PATTERN = /^(sonnet|opus|haiku|opusplan|default|claude-[A-Za-
108
130
  * @returns Model id for the fallback runtime, or undefined for its own default
109
131
  */
110
132
  export function fallbackRuntimeModelId(team, member, fallbackRuntime, env = process.env) {
111
- if (fallbackRuntime !== RUNTIME_TYPES.CLAUDE_CODE)
112
- return undefined;
113
- const own = member.modelId && CLAUDE_MODEL_PATTERN.test(member.modelId.trim()) ? member.modelId : undefined;
133
+ const isClaude = fallbackRuntime === RUNTIME_TYPES.CLAUDE_CODE;
134
+ const own = isClaude && member.modelId && CLAUDE_MODEL_PATTERN.test(member.modelId.trim()) ? member.modelId : undefined;
114
135
  if (own)
115
136
  return own;
137
+ const tiered = tierModelForMember(team, member, fallbackRuntime);
138
+ if (tiered)
139
+ return tiered;
140
+ if (!isClaude)
141
+ return undefined;
116
142
  return defaultModelForMember(team, { ...member, modelId: undefined, runtimeType: fallbackRuntime }, env) ?? undefined;
117
143
  }
118
144
  //# sourceMappingURL=member-default-model.utils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"member-default-model.utils.js","sourceRoot":"","sources":["../../../../../backend/src/utils/member-default-model.utils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"member-default-model.utils.js","sourceRoot":"","sources":["../../../../../backend/src/utils/member-default-model.utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Model tiers (crewly#1173, specs/2026-10-08-model-tiers.md).
3
+ *
4
+ * A member may carry a tier (`strong` | `mid` | `weak`) instead of a concrete
5
+ * model. At launch the tier resolves to a model for the runtime that really
6
+ * runs: the team's own map (`Team.tierModels`) first, then the global map
7
+ * (`MODEL_TIER_CONSTANTS.DEFAULT_TIER_MODELS`). A runtime without a `weak`
8
+ * model uses its `mid` model; any other unmapped tier resolves to nothing
9
+ * (the runtime's own default).
10
+ *
11
+ * @module utils/model-tier
12
+ */
13
+ import type { ModelTier, TeamTierModels } from '../types/index.js';
14
+ /** Tiers, strongest first. */
15
+ export declare const MODEL_TIERS: readonly ModelTier[];
16
+ /**
17
+ * Whether a value names a tier.
18
+ *
19
+ * @param value - Candidate
20
+ * @returns True for `strong`, `mid` or `weak`
21
+ */
22
+ export declare function isModelTier(value: unknown): value is ModelTier;
23
+ /**
24
+ * Rank of a tier: 2 = strong, 1 = mid, 0 = weak.
25
+ *
26
+ * @param tier - Tier
27
+ * @returns Rank (higher is stronger)
28
+ */
29
+ export declare function tierRank(tier: ModelTier): number;
30
+ /**
31
+ * The tier → model map for one runtime: the global map with the team's
32
+ * overrides on top. Overrides that are not shell-safe model ids are ignored.
33
+ *
34
+ * @param runtime - Runtime id (`claude-code`, `codex-cli`, …)
35
+ * @param overrides - The team's `tierModels`
36
+ * @returns Map with only the tiers that have a model
37
+ */
38
+ export declare function tierMapFor(runtime: string, overrides?: TeamTierModels): Partial<Record<ModelTier, string>>;
39
+ /**
40
+ * The model a tier runs on for a runtime.
41
+ *
42
+ * @param runtime - Runtime that launches
43
+ * @param tier - The member's tier
44
+ * @param overrides - The team's `tierModels`
45
+ * @returns Model id, or undefined for the runtime's own default
46
+ *
47
+ * @example
48
+ * ```typescript
49
+ * resolveTierModel('claude-code', 'weak'); // 'haiku'
50
+ * resolveTierModel('codex-cli', 'weak'); // 'gpt-5.4' (no weak model: mid)
51
+ * resolveTierModel('crewly-agent', 'strong'); // undefined
52
+ * ```
53
+ */
54
+ export declare function resolveTierModel(runtime: string, tier: ModelTier | undefined, overrides?: TeamTierModels): string | undefined;
55
+ /**
56
+ * Validate a team's `tierModels` payload.
57
+ *
58
+ * @param value - Candidate (`{ runtime: { tier: model } }`)
59
+ * @returns The cleaned map, or an error message
60
+ */
61
+ export declare function parseTierModels(value: unknown): {
62
+ ok: true;
63
+ value: TeamTierModels;
64
+ } | {
65
+ ok: false;
66
+ error: string;
67
+ };
68
+ //# sourceMappingURL=model-tier.utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-tier.utils.d.ts","sourceRoot":"","sources":["../../../../../backend/src/utils/model-tier.utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGnE,8BAA8B;AAC9B,eAAO,MAAM,WAAW,EAAE,SAAS,SAAS,EAA+B,CAAC;AAE5E;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,SAAS,CAE9D;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAEhD;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAS1G;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,SAAS,EAAE,SAAS,CAAC,EAAE,cAAc,GAAG,MAAM,GAAG,SAAS,CAM7H;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,cAAc,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAiBlH"}
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Model tiers (crewly#1173, specs/2026-10-08-model-tiers.md).
3
+ *
4
+ * A member may carry a tier (`strong` | `mid` | `weak`) instead of a concrete
5
+ * model. At launch the tier resolves to a model for the runtime that really
6
+ * runs: the team's own map (`Team.tierModels`) first, then the global map
7
+ * (`MODEL_TIER_CONSTANTS.DEFAULT_TIER_MODELS`). A runtime without a `weak`
8
+ * model uses its `mid` model; any other unmapped tier resolves to nothing
9
+ * (the runtime's own default).
10
+ *
11
+ * @module utils/model-tier
12
+ */
13
+ import { MODEL_TIER_CONSTANTS } from '../constants.js';
14
+ import { isSafeModelId } from './runtime-model-flags.utils.js';
15
+ /** Tiers, strongest first. */
16
+ export const MODEL_TIERS = MODEL_TIER_CONSTANTS.TIERS;
17
+ /**
18
+ * Whether a value names a tier.
19
+ *
20
+ * @param value - Candidate
21
+ * @returns True for `strong`, `mid` or `weak`
22
+ */
23
+ export function isModelTier(value) {
24
+ return typeof value === 'string' && MODEL_TIERS.includes(value);
25
+ }
26
+ /**
27
+ * Rank of a tier: 2 = strong, 1 = mid, 0 = weak.
28
+ *
29
+ * @param tier - Tier
30
+ * @returns Rank (higher is stronger)
31
+ */
32
+ export function tierRank(tier) {
33
+ return MODEL_TIERS.length - 1 - MODEL_TIERS.indexOf(tier);
34
+ }
35
+ /**
36
+ * The tier → model map for one runtime: the global map with the team's
37
+ * overrides on top. Overrides that are not shell-safe model ids are ignored.
38
+ *
39
+ * @param runtime - Runtime id (`claude-code`, `codex-cli`, …)
40
+ * @param overrides - The team's `tierModels`
41
+ * @returns Map with only the tiers that have a model
42
+ */
43
+ export function tierMapFor(runtime, overrides) {
44
+ const base = MODEL_TIER_CONSTANTS.DEFAULT_TIER_MODELS[runtime] ?? {};
45
+ const own = overrides?.[runtime] ?? {};
46
+ const out = {};
47
+ for (const tier of MODEL_TIERS) {
48
+ const candidate = typeof own[tier] === 'string' && own[tier].trim() && isSafeModelId(own[tier].trim()) ? own[tier].trim() : base[tier];
49
+ if (candidate)
50
+ out[tier] = candidate;
51
+ }
52
+ return out;
53
+ }
54
+ /**
55
+ * The model a tier runs on for a runtime.
56
+ *
57
+ * @param runtime - Runtime that launches
58
+ * @param tier - The member's tier
59
+ * @param overrides - The team's `tierModels`
60
+ * @returns Model id, or undefined for the runtime's own default
61
+ *
62
+ * @example
63
+ * ```typescript
64
+ * resolveTierModel('claude-code', 'weak'); // 'haiku'
65
+ * resolveTierModel('codex-cli', 'weak'); // 'gpt-5.4' (no weak model: mid)
66
+ * resolveTierModel('crewly-agent', 'strong'); // undefined
67
+ * ```
68
+ */
69
+ export function resolveTierModel(runtime, tier, overrides) {
70
+ if (!isModelTier(tier))
71
+ return undefined;
72
+ const map = tierMapFor(runtime, overrides);
73
+ if (map[tier])
74
+ return map[tier];
75
+ if (tier === 'weak')
76
+ return map.mid;
77
+ return undefined;
78
+ }
79
+ /**
80
+ * Validate a team's `tierModels` payload.
81
+ *
82
+ * @param value - Candidate (`{ runtime: { tier: model } }`)
83
+ * @returns The cleaned map, or an error message
84
+ */
85
+ export function parseTierModels(value) {
86
+ if (value === null || value === undefined)
87
+ return { ok: true, value: {} };
88
+ if (typeof value !== 'object' || Array.isArray(value))
89
+ return { ok: false, error: 'tierModels must be an object: { "<runtime>": { "strong"|"mid"|"weak": "<model>" } }' };
90
+ const out = {};
91
+ for (const [runtime, tiers] of Object.entries(value)) {
92
+ if (!/^[a-z][a-z0-9-]{1,40}$/.test(runtime))
93
+ return { ok: false, error: `Unknown runtime "${runtime}"` };
94
+ if (tiers === null || typeof tiers !== 'object' || Array.isArray(tiers))
95
+ return { ok: false, error: `tierModels.${runtime} must be an object of tier → model` };
96
+ const entry = {};
97
+ for (const [tier, model] of Object.entries(tiers)) {
98
+ if (!isModelTier(tier))
99
+ return { ok: false, error: `Unknown tier "${tier}" (use strong, mid or weak)` };
100
+ if (model === '' || model === null || model === undefined)
101
+ continue;
102
+ if (typeof model !== 'string' || !isSafeModelId(model.trim()))
103
+ return { ok: false, error: `Invalid model for ${runtime}.${tier}: use the model name as the runtime expects it` };
104
+ entry[tier] = model.trim();
105
+ }
106
+ if (Object.keys(entry).length > 0)
107
+ out[runtime] = entry;
108
+ }
109
+ return { ok: true, value: out };
110
+ }
111
+ //# sourceMappingURL=model-tier.utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-tier.utils.js","sourceRoot":"","sources":["../../../../../backend/src/utils/model-tier.utils.ts"],"names":[],"mappings":"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"}