@exellix/ai-tasks 8.5.0 → 8.5.3

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 (58) hide show
  1. package/.docs/ai-tasks-model-profile-aliases-7x.md +27 -5
  2. package/CHANGELOG.md +6 -10
  3. package/README.md +7 -6
  4. package/RUNTASK_REQUEST.md +1 -1
  5. package/dist/core/task-sdk.d.ts.map +1 -1
  6. package/dist/core/task-sdk.js +16 -14
  7. package/dist/core/task-sdk.js.map +1 -1
  8. package/dist/errors/runTaskExecutionError.d.ts +1 -1
  9. package/dist/errors/runTaskExecutionError.d.ts.map +1 -1
  10. package/dist/errors/runTaskExecutionError.js +4 -1
  11. package/dist/errors/runTaskExecutionError.js.map +1 -1
  12. package/dist/errors/runTaskModelResolutionError.d.ts +39 -0
  13. package/dist/errors/runTaskModelResolutionError.d.ts.map +1 -0
  14. package/dist/errors/runTaskModelResolutionError.js +92 -0
  15. package/dist/errors/runTaskModelResolutionError.js.map +1 -0
  16. package/dist/index.d.ts +2 -0
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +1 -0
  19. package/dist/index.js.map +1 -1
  20. package/dist/logxer/aiTasksDiagnosticCodes.d.ts +3 -0
  21. package/dist/logxer/aiTasksDiagnosticCodes.d.ts.map +1 -1
  22. package/dist/logxer/aiTasksDiagnosticCodes.js +3 -0
  23. package/dist/logxer/aiTasksDiagnosticCodes.js.map +1 -1
  24. package/dist/observability/classifyRunTaskFailure.d.ts +1 -1
  25. package/dist/observability/classifyRunTaskFailure.d.ts.map +1 -1
  26. package/dist/observability/classifyRunTaskFailure.js +12 -0
  27. package/dist/observability/classifyRunTaskFailure.js.map +1 -1
  28. package/dist/observability/logRunTaskFailure.d.ts.map +1 -1
  29. package/dist/observability/logRunTaskFailure.js +26 -8
  30. package/dist/observability/logRunTaskFailure.js.map +1 -1
  31. package/dist/planWebScopeQuestions/index.d.ts.map +1 -1
  32. package/dist/planWebScopeQuestions/index.js +6 -1
  33. package/dist/planWebScopeQuestions/index.js.map +1 -1
  34. package/dist/post-steps/audit/auditChecklistFuncxEnvelope.d.ts +57 -0
  35. package/dist/post-steps/audit/auditChecklistFuncxEnvelope.d.ts.map +1 -0
  36. package/dist/post-steps/audit/auditChecklistFuncxEnvelope.js +80 -0
  37. package/dist/post-steps/audit/auditChecklistFuncxEnvelope.js.map +1 -0
  38. package/dist/task-strategies/normalize.d.ts.map +1 -1
  39. package/dist/task-strategies/normalize.js +3 -0
  40. package/dist/task-strategies/normalize.js.map +1 -1
  41. package/dist/utils/concreteModelId.d.ts.map +1 -1
  42. package/dist/utils/concreteModelId.js +4 -1
  43. package/dist/utils/concreteModelId.js.map +1 -1
  44. package/dist/utils/resolveAiProfileModel.d.ts +6 -1
  45. package/dist/utils/resolveAiProfileModel.d.ts.map +1 -1
  46. package/dist/utils/resolveAiProfileModel.js +11 -2
  47. package/dist/utils/resolveAiProfileModel.js.map +1 -1
  48. package/dist/utils/resolveRunTaskModelReferences.d.ts.map +1 -1
  49. package/dist/utils/resolveRunTaskModelReferences.js +93 -30
  50. package/dist/utils/resolveRunTaskModelReferences.js.map +1 -1
  51. package/dist/validation/helpers.js +1 -1
  52. package/dist/validation/helpers.js.map +1 -1
  53. package/documenations/funcx-catalog-hosting-checklist.md +12 -8
  54. package/documenations/funcx-scoping-integration-gaps.md +10 -8
  55. package/documenations/upstream-feature-requests/README.md +9 -0
  56. package/documenations/upstream-feature-requests/funcx-generic-xynthesis-hosting.md +268 -0
  57. package/documenations/upstream-feature-requests/funcx-pre-post-sidekick-actions.md +213 -0
  58. package/package.json +3 -9
@@ -41,18 +41,39 @@ Unknown profile keys fail at **`resolveAIProfile`** with a clear error.
41
41
 
42
42
  ## Resolution boundaries
43
43
 
44
- | Path | Fields | Normalized by |
45
- |------|--------|---------------|
46
- | Xynthesis (PRE/POST/scoping/utilities) | `preActionModel`, `postActionModel`, step `llmCall.model` | `resolveModelReferenceForXynthesis` → `toStrictAiProfileResolveInput` |
47
- | ai-skills MAIN | `skillModel`, `RunTaskRequest.llmCall.model` | `resolveModelReference` → concrete `provider/model` |
44
+ | Path | Fields at ingress (before `resolveRunTaskModelReferences`) | Internal transform |
45
+ |------|----------------------------------------------------------|--------------------|
46
+ | **PRE / POST (xynthesis)** | `preActionModel`, `postActionModel`, step `llmCall.model` — **ai-profiles alias required** | `resolveModelReferenceForXynthesis` → `profile/choice` keys only |
47
+ | **MAIN (ai-skills)** | `skillModel`, root `llmCall.model` — alias **or** concrete provider id | `resolveModelReference` → concrete `provider/model` for gateway |
48
48
 
49
49
  Concrete ids (`openrouter/...`, `anthropic/claude-...`, `openai/gpt-5`) pass through on **`skillModel`** only. PRE/POST must stay ai-profiles aliases under `@exellix/xynthesis` ≥ 4.3.1.
50
50
 
51
+ ### Ingress rule for hosts (graph-engine, studio BFF)
52
+
53
+ > **Do not** pre-resolve `preActionModel` or `postActionModel` to OpenRouter/OpenAI model ids. Pass through profile keys, `profile/choice`, or shortcut keys (e.g. `cheap`, `cheap/default`).
54
+
55
+ > **`skillModel`** may still be a concrete provider id at ingress.
56
+
57
+ ### Internal rule (ai-tasks)
58
+
59
+ > `resolveRunTaskModelReferences` is the **only** place that transforms aliases on xynthesis paths at `runTask` entry. If a concrete id is detected on a xynthesis slot, ai-tasks fails with stable code **`XYNTHESIS_CONCRETE_MODEL_REJECTED`** (typed `RunTaskModelResolutionError`, not a generic wrapper).
60
+
61
+ ### Stable pre-MAIN error codes
62
+
63
+ | Condition | `error.code` |
64
+ |-----------|--------------|
65
+ | Concrete id on xynthesis slot | `XYNTHESIS_CONCRETE_MODEL_REJECTED` |
66
+ | Unknown / unresolvable alias | `XYNTHESIS_ALIAS_RESOLUTION_FAILED` |
67
+ | PRE synthesis enabled but required paths empty | `SYNTHESIS_INPUT_EMPTY` |
68
+
69
+ Failures emit logxer diagnostics with `failureClassification.role: "cause"` and event ids such as `xynthesis_concrete_model_rejected`. Hosts (graph-engine CR-7) should preserve `error.code` and `failureClassification` on attempt records instead of collapsing to `TASK_RUN_FAILED` / `classification: other`.
70
+
51
71
  ## graph-engine guidance
52
72
 
53
73
  - Send the triplet on every node/task compile — no env defaults, no `"balanced"` fallback.
54
74
  - Prefer explicit **`profile/choice`** keys in compiled payloads; bare profile keys are OK (ai-tasks normalizes before xynthesis).
55
- - Optional: pre-resolve aliases in graph-engine for diagnostics; ai-tasks re-resolves at invoke (idempotent for concrete ids).
75
+ - **Do not** pre-resolve `preActionModel` / `postActionModel` to concrete provider ids — pass aliases and let ai-tasks normalize at `runTask` entry (see ingress rule above).
76
+ - Optional: pre-resolve **`skillModel`** aliases for diagnostics; ai-tasks re-resolves at invoke (idempotent for concrete ids).
56
77
  - Do **not** npm-override `@x12i/ai-profiles` or pin `<2.1`.
57
78
 
58
79
  ## Stack minimums
@@ -69,6 +90,7 @@ Concrete ids (`openrouter/...`, `anthropic/claude-...`, `openai/gpt-5`) pass thr
69
90
  - `toStrictAiProfileResolveInput` — bare profile → `profile/default`
70
91
  - `resolveModelReference` / `resolveModelReferenceForXynthesis`
71
92
  - `isResolvableModelAlias` — true for known **`profile/choice`** keys only
93
+ - `RunTaskModelResolutionError`, `isRunTaskModelResolutionError` — stable pre-MAIN model slot failures
72
94
  - `listAiTasksProfileChoices`, `listAiTasksProfiles`, `listAiTasksProfileChoiceKeys`
73
95
 
74
96
  See [README — Model profile aliases](../README.md#model-profile-aliases-x12iai-profiles).
package/CHANGELOG.md CHANGED
@@ -20,21 +20,17 @@ The published **npm version** always matches **`version`** in [`package.json`](p
20
20
 
21
21
  - `setFuncxExecutionStrategyInvoker`, `setResearchPlanQuestionsFuncxInvoker`, direct `@x12i/funcx` dependency.
22
22
 
23
- ## [Unreleased]
23
+ ## [8.5.3] - 2026-06-04
24
24
 
25
- ### Changed (breaking)
26
-
27
- - **`RunTaskRequest.modelConfig` is required** on every `runTask()` call (all three slots). No env-based or hardcoded model defaults (`SYNTHESIS_MODEL`, `AUDIT_MODEL`, `POST_STEP_MODEL`, `"balanced"`, etc.) for model selection.
28
-
29
- ### Fixed
25
+ ### Changed
30
26
 
31
- - **PRE/MAIN model routing:** Root `RunTaskRequest.llmCall` is **MAIN-only** no longer copied into PRE synthesis compile. When `llmCall.model` duplicates `preActionModel` while `skillModel` differs (graph-engine PRE leakage), MAIN uses `skillModel`. Validation warning `MODEL_CONFIG_LLM_CALL_PRE_MAIN_COLLISION`.
27
+ - Bumped **`@exellix/xynthesis`** to **^4.4.5** and **`@exellix/ai-skills`** to **^6.0.2** for Optimixer **max-token retry** on PRE/POST (xynthesis) and MAIN (ai-skills): one automatic re-invoke when output hits the token limit and Optimixer returns **`retryPrediction`** (no host **`maxTokens`** required).
32
28
 
33
- ## [8.4.0] - 2026-06-01
29
+ ### Added
34
30
 
35
- ### Changed (breaking)
31
+ - Unit test **`runPostStepLlmCall.maxTokenRetry.test.ts`** (mock Optimixer + synthesis invoker; no live LLM).
36
32
 
37
- - **`RunTaskRequest.modelConfig`:** **3-slot triplet only** — `preActionModel`, `skillModel`, `postActionModel`. **`xynthesisModel` removed** (validation rejects with `NON_CANONICAL_MODEL_CONFIG`). PRE uses `preActionModel`; POST uses `postActionModel`.
33
+ ## [8.4.0] - 2026-06-01 — `preActionModel`, `skillModel`, `postActionModel`. **`xynthesisModel` removed** (validation rejects with `NON_CANONICAL_MODEL_CONFIG`). PRE uses `preActionModel`; POST uses `postActionModel`.
38
34
  - **`@x12i/ai-profiles` ^2.0.0:** Required `catalogLane` on profile resolution; ai-tasks defaults `"text"` ( `"image"` for `vision` ). Registry source defaults to `auto`.
39
35
  - **`@exellix/xynthesis` ^4.2.1:** Minimum for ai-profiles v2 alignment.
40
36
 
package/README.md CHANGED
@@ -1071,8 +1071,8 @@ Orchestrators send **model** + **sampling** + **`reasoningEffort`** + (for xynth
1071
1071
 
1072
1072
  | Phase | Package | Caller sends | Package owns |
1073
1073
  |-------|---------|--------------|--------------|
1074
- | **MAIN** | `@exellix/ai-skills` ≥6 | `modelConfig` → `{ model, temperature, topP, reasoningEffort, … }` | Optimixer + Catalox skill catalog (`maxTokens` on `ModelConfig` is rejected) |
1075
- | **PRE / POST / scoping / utility** | `@exellix/xynthesis` ≥4.3 | `outputExpectation` (required on every hop), optional `reasoningEffort`, `temperature`, `topP` | `resolveEffectiveMaxTokens` inside `executeXynthesisAction` |
1074
+ | **MAIN** | `@exellix/ai-skills` ≥6 | `modelConfig` → `{ model, temperature, topP, reasoningEffort, … }` | Optimixer + Catalox skill catalog (`maxTokens` on `ModelConfig` is rejected); **one automatic re-invoke** when output hits token limit and Optimixer returns `retryPrediction` |
1075
+ | **PRE / POST / scoping / utility** | `@exellix/xynthesis` ≥4.3 | `outputExpectation` (required on every hop), optional `reasoningEffort`, `temperature`, `topP` | `resolveEffectiveMaxTokens` inside `executeXynthesisAction`; **same one-shot max-token retry** via Optimixer `retryPrediction` |
1076
1076
 
1077
1077
  **Xynthesis `outputExpectation`** is sizing/density **intent** for Optimixer — not a literal token count. ai-tasks resolves a per-stage default when the caller omits it (`resolveOutputExpectation` / `resolveLlmOutputExpectationForXynthesis`).
1078
1078
 
@@ -1123,10 +1123,11 @@ Concrete ids (`openrouter/...`, `anthropic/claude-sonnet-4`, `openai/gpt-5`, …
1123
1123
 
1124
1124
  **Client impact:**
1125
1125
 
1126
- - **No change** if you already send concrete provider model ids.
1127
- - **New:** you may send ai-profiles aliases on `modelConfig`, `llmCall.model`, and pipeline step configs graph-engine no longer has to pre-resolve every alias before `runTask` (hosts that already resolve can keep doing so; double resolution is a no-op for concrete ids).
1128
- - **Validation:** alias tokens on `modelConfig` slots are accepted; unknown aliases fail at resolution with a clear error.
1129
- - **Helpers:** `resolveModelReference`, `resolveRunTaskModelReferences`, `isResolvableModelAlias` (true only for **`profile/choice`** keys bare profile keys are resolved at invoke, not sync-listed).
1126
+ - **`skillModel` / MAIN `llmCall.model`:** concrete provider ids pass through unchanged (alias or concrete accepted).
1127
+ - **`preActionModel` / `postActionModel`:** must be ai-profiles aliases — **do not** send concrete OpenRouter/OpenAI ids (rejected with `XYNTHESIS_CONCRETE_MODEL_REJECTED`).
1128
+ - **New:** you may send ai-profiles aliases on `modelConfig`, `llmCall.model`, and pipeline step configs graph-engine must not pre-resolve xynthesis slots to concrete ids.
1129
+ - **Validation:** alias tokens on `modelConfig` slots are accepted; unknown aliases fail at resolution with `XYNTHESIS_ALIAS_RESOLUTION_FAILED`.
1130
+ - **Helpers:** `resolveModelReference`, `resolveRunTaskModelReferences`, `isRunTaskModelResolutionError`, `isResolvableModelAlias` (true only for **`profile/choice`** keys — bare profile keys are resolved at invoke, not sync-listed).
1130
1131
 
1131
1132
  Resolution uses the ai-profiles registry (`auto`: remote refresh with bundled fallback). See [`.docs/ai-tasks-model-profile-aliases-7x.md`](.docs/ai-tasks-model-profile-aliases-7x.md).
1132
1133
 
@@ -95,7 +95,7 @@ Properties are classified for **default MAIN path** unless noted. Inherited **`R
95
95
  | `inputs` | Optional plural task payload (`string` or object). Dual-root parity with `input`; smart-input **`inputs.*`** resolves here (not `executionMemory.inputs`). |
96
96
  | `variables` | Job/graph template bucket; forwarded as-is on MAIN (see [Canonical input bucket](#canonical-input-bucket)). |
97
97
  | `jobMemory`, `taskMemory` | Enriched and forwarded; see executor payload. |
98
- | `modelConfig` | **Canonical slots:** `preActionModel` + `skillModel` + `postActionModel`. **Aliases accepted on wire** (ai-profiles names + legacy tiers); resolved inside `runTask()` via [`resolveRunTaskModelReferences`](src/utils/resolveRunTaskModelReferences.ts). **`skillModel`** → concrete id for ai-skills MAIN; **`preActionModel`** / **`postActionModel`** → **alias only** for xynthesis PRE/POST (concrete ids rejected under `@exellix/xynthesis` ≥4). Legacy `model` and **`xynthesisModel`** rejected. |
98
+ | `modelConfig` | **Canonical slots:** `preActionModel` + `skillModel` + `postActionModel`. **Aliases accepted on wire** (ai-profiles names + legacy tiers); resolved inside `runTask()` via [`resolveRunTaskModelReferences`](src/utils/resolveRunTaskModelReferences.ts). **`skillModel`** → concrete id for ai-skills MAIN; **`preActionModel`** / **`postActionModel`** → **alias only** for xynthesis PRE/POST (concrete ids rejected under `@exellix/xynthesis` ≥4 with code **`XYNTHESIS_CONCRETE_MODEL_REJECTED`**). Legacy `model` and **`xynthesisModel`** rejected. See [`.docs/ai-tasks-model-profile-aliases-7x.md`](.docs/ai-tasks-model-profile-aliases-7x.md). |
99
99
  | `llmCall` | **MAIN override only** at root (`llmCall.model` wins over `skillModel` unless it duplicates `preActionModel` while `skillModel` differs — see collision guard). Not copied into PRE synthesis compile; use `preActionModel` or `executionPipeline[pre].config.llmCall` for PRE. Merged into ai-skills `modelConfig` at MAIN execution boundary. |
100
100
  | `timeoutMs` | Forwarded when set (also overlaid from `llmCall.timeoutMs`). |
101
101
  | `coreSkillId` | Maps to `skillId` on `RunSkillRequest` for gateway. |
@@ -1 +1 @@
1
- {"version":3,"file":"task-sdk.d.ts","sourceRoot":"","sources":["../../src/core/task-sdk.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAazD,OAAO,EAAE,cAAc,EAAE,eAAe,EAAuB,MAAM,mBAAmB,CAAC;AA2BzF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AA2OxD,KAAK,iBAAiB,GAAG,mBAAmB,CAAC;AA0S7C;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,uBAAuB,GAAG;IACpC,+FAA+F;IAC/F,OAAO,CAAC,EAAE,mBAAmB,CAAC;CAC/B,CAAC;AAEF,qBAAa,gBAAgB;IAIzB,SAAS,CAAC,QAAQ,CAAC,YAAY,EAAE,iBAAiB;IAClD,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAJ3B,SAAS,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,mBAAmB,CAAC;gBAGjC,YAAY,EAAE,iBAAiB,EACjC,QAAQ,EAAE;QACzB,OAAO,CAAC,OAAO,GAAG,GAAG,EACnB,KAAK,EAAE,GAAG,EACV,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GACzC,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;KACtC,EACD,OAAO,CAAC,EAAE,uBAAuB;IAQ7B,OAAO,CAAC,OAAO,GAAG,GAAG,EAAE,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;IAkmDtF;;OAEG;YACW,6BAA6B;IAshB3C;;;;;OAKG;YACW,cAAc;CAyR7B"}
1
+ {"version":3,"file":"task-sdk.d.ts","sourceRoot":"","sources":["../../src/core/task-sdk.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAazD,OAAO,EAAE,cAAc,EAAE,eAAe,EAAuB,MAAM,mBAAmB,CAAC;AA2BzF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AA4OxD,KAAK,iBAAiB,GAAG,mBAAmB,CAAC;AA0S7C;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,uBAAuB,GAAG;IACpC,+FAA+F;IAC/F,OAAO,CAAC,EAAE,mBAAmB,CAAC;CAC/B,CAAC;AAEF,qBAAa,gBAAgB;IAIzB,SAAS,CAAC,QAAQ,CAAC,YAAY,EAAE,iBAAiB;IAClD,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAJ3B,SAAS,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,mBAAmB,CAAC;gBAGjC,YAAY,EAAE,iBAAiB,EACjC,QAAQ,EAAE;QACzB,OAAO,CAAC,OAAO,GAAG,GAAG,EACnB,KAAK,EAAE,GAAG,EACV,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GACzC,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;KACtC,EACD,OAAO,CAAC,EAAE,uBAAuB;IAQ7B,OAAO,CAAC,OAAO,GAAG,GAAG,EAAE,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;IAkmDtF;;OAEG;YACW,6BAA6B;IAshB3C;;;;;OAKG;YACW,cAAc;CAyR7B"}
@@ -47,6 +47,7 @@ import { llmCallEnvPrefix, resolveLlmCall } from "../post-steps/resolvePostStepC
47
47
  import { buildXynthesisWorkScopeIdentity } from "../internal/buildXynthesisWorkScopeIdentity.js";
48
48
  import { getPostActionModelFromSlots, resolvePreActionModel } from "../utils/routeModelConfigSlots.js";
49
49
  import { assertPhaseModelAlias } from "../errors/modelConfigRequiredError.js";
50
+ import { isRunTaskModelResolutionError } from "../errors/runTaskModelResolutionError.js";
50
51
  import { resolveRunTaskModelReferences } from "../utils/resolveRunTaskModelReferences.js";
51
52
  import { runPostStepLlmCall } from "../internal/runPostStepLlmCall.js";
52
53
  registerBuiltInLocalTasks();
@@ -439,11 +440,6 @@ export class WorexClientTasks {
439
440
  }
440
441
  }
441
442
  async runTask(input) {
442
- const compiled = compileTaskConfigurationOnRunTaskRequest(input);
443
- input = await resolveRunTaskModelReferences(compiled.request);
444
- emitRunTaskRequestWarnings(input);
445
- assertRequiredRunSkillCorrelation(input);
446
- assertValidSmartInputConfig(input.smartInput, input.skillKey);
447
443
  const traceCollector = input.executionMode === "trace" ? createDebugTraceCollector() : null;
448
444
  const withTrace = (result) => {
449
445
  if (!traceCollector)
@@ -454,16 +450,21 @@ export class WorexClientTasks {
454
450
  };
455
451
  };
456
452
  return runAiTasksWithObservabilityContext({ logging: this.stackLogging }, async () => {
457
- const failContext = () => ({
458
- skillKey: input.skillKey,
459
- jobId: input.jobId,
460
- taskId: input.taskId,
461
- graphId: input.graphId,
462
- nodeId: input.nodeId,
463
- agentId: input.agentId,
464
- modelConfig: input.modelConfig,
453
+ const failContext = (req) => ({
454
+ skillKey: req.skillKey,
455
+ jobId: req.jobId,
456
+ taskId: req.taskId,
457
+ graphId: req.graphId,
458
+ nodeId: req.nodeId,
459
+ agentId: req.agentId,
460
+ modelConfig: req.modelConfig,
465
461
  });
466
462
  try {
463
+ const compiled = compileTaskConfigurationOnRunTaskRequest(input);
464
+ input = await resolveRunTaskModelReferences(compiled.request);
465
+ emitRunTaskRequestWarnings(input);
466
+ assertRequiredRunSkillCorrelation(input);
467
+ assertValidSmartInputConfig(input.smartInput, input.skillKey);
467
468
  // `@exellix/ai-skills` requires stable ids on each gateway request; callers may omit for simple runs.
468
469
  const taskId = input.taskId?.trim() ? input.taskId : randomUUID();
469
470
  const jobId = input.jobId?.trim() ? input.jobId : randomUUID();
@@ -1801,7 +1802,8 @@ export class WorexClientTasks {
1801
1802
  catch (error) {
1802
1803
  throw logAndEnrichRunTaskFailure({
1803
1804
  cause: error,
1804
- ...failContext(),
1805
+ ...(isRunTaskModelResolutionError(error) ? { phase: "model-resolution" } : {}),
1806
+ ...failContext(input),
1805
1807
  });
1806
1808
  }
1807
1809
  });