vidspotai-shared 1.0.85 → 1.0.87

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 (55) hide show
  1. package/lib/globals/aiModels/providers/runway.d.ts.map +1 -1
  2. package/lib/globals/aiModels/providers/runway.js +12 -7
  3. package/lib/globals/types.d.ts +10 -0
  4. package/lib/globals/types.d.ts.map +1 -1
  5. package/lib/globals/types.js +11 -0
  6. package/lib/models/agent.model.d.ts +129 -1
  7. package/lib/models/agent.model.d.ts.map +1 -1
  8. package/lib/schemas/agentRunJob.schema.d.ts +21 -0
  9. package/lib/schemas/agentRunJob.schema.d.ts.map +1 -1
  10. package/lib/schemas/agentRunJob.schema.js +35 -3
  11. package/lib/schemas/videoPlan.schema.d.ts +1 -0
  12. package/lib/schemas/videoPlan.schema.d.ts.map +1 -1
  13. package/lib/schemas/videoPlan.schema.js +8 -0
  14. package/lib/services/agent/executor/core.d.ts.map +1 -1
  15. package/lib/services/agent/executor/core.js +21 -1
  16. package/lib/services/agent/executor/types.d.ts +10 -0
  17. package/lib/services/agent/executor/types.d.ts.map +1 -1
  18. package/lib/services/agent/index.d.ts +3 -0
  19. package/lib/services/agent/index.d.ts.map +1 -1
  20. package/lib/services/agent/index.js +3 -0
  21. package/lib/services/agent/planner/plannerMessages.d.ts.map +1 -1
  22. package/lib/services/agent/planner/plannerMessages.js +7 -0
  23. package/lib/services/agent/providerFallback/chains.d.ts +2 -0
  24. package/lib/services/agent/providerFallback/chains.d.ts.map +1 -1
  25. package/lib/services/agent/providerFallback/chains.js +1 -0
  26. package/lib/services/agent/recovery/degradeLadder.d.ts +74 -0
  27. package/lib/services/agent/recovery/degradeLadder.d.ts.map +1 -0
  28. package/lib/services/agent/recovery/degradeLadder.js +133 -0
  29. package/lib/services/agent/repair/engine.d.ts +38 -0
  30. package/lib/services/agent/repair/engine.d.ts.map +1 -0
  31. package/lib/services/agent/repair/engine.js +175 -0
  32. package/lib/services/agent/repair/index.d.ts +20 -0
  33. package/lib/services/agent/repair/index.d.ts.map +1 -0
  34. package/lib/services/agent/repair/index.js +49 -0
  35. package/lib/services/agent/repair/strategies/llmRepair.strategy.d.ts +6 -0
  36. package/lib/services/agent/repair/strategies/llmRepair.strategy.d.ts.map +1 -0
  37. package/lib/services/agent/repair/strategies/llmRepair.strategy.js +210 -0
  38. package/lib/services/agent/repair/strategies/paramRepair.strategy.d.ts +3 -0
  39. package/lib/services/agent/repair/strategies/paramRepair.strategy.d.ts.map +1 -0
  40. package/lib/services/agent/repair/strategies/paramRepair.strategy.js +151 -0
  41. package/lib/services/agent/repair/types.d.ts +92 -0
  42. package/lib/services/agent/repair/types.d.ts.map +1 -0
  43. package/lib/services/agent/repair/types.js +2 -0
  44. package/lib/services/agent/runPlanning.d.ts +96 -0
  45. package/lib/services/agent/runPlanning.d.ts.map +1 -0
  46. package/lib/services/agent/runPlanning.js +233 -0
  47. package/lib/services/agent/tools/planVideo.tool.d.ts +1 -0
  48. package/lib/services/agent/tools/planVideo.tool.d.ts.map +1 -1
  49. package/lib/services/aiGen/providers/runway/types.d.ts +14 -0
  50. package/lib/services/aiGen/providers/runway/types.d.ts.map +1 -1
  51. package/lib/services/aiGen/providers/runway/types.js +22 -1
  52. package/lib/services/firestore.service.d.ts +7 -1
  53. package/lib/services/firestore.service.d.ts.map +1 -1
  54. package/lib/services/firestore.service.js +8 -0
  55. package/package.json +1 -1
@@ -119,6 +119,13 @@ function buildPlannerMessages(brief, persona, brandKit, styleMemory, bible, last
119
119
  bibleSection,
120
120
  brandKitSection,
121
121
  styleMemorySection,
122
+ "",
123
+ "Title — set plan.title to a concise, human-friendly name for the whole",
124
+ "video (≤ 8 words, Title Case, no trailing punctuation, no surrounding",
125
+ "quotes). It should read like a video/episode title a creator would use,",
126
+ "derived from the brief's subject and angle — NOT a restatement of the raw",
127
+ "prompt. Examples: \"5 Morning Habits That Boost Focus\", \"Meet the New",
128
+ "Aurora Smartwatch\", \"Why Your Plants Keep Dying\".",
122
129
  ]
123
130
  .filter(Boolean)
124
131
  .join("\n");
@@ -50,6 +50,8 @@ export interface VideoCapabilityRequest {
50
50
  hasInputImage?: boolean;
51
51
  }
52
52
  export declare function isVideoModelCapable(model: EVideoGenModels, req: VideoCapabilityRequest): boolean;
53
+ /** Reduce a "W:H" or "WxH" ratio to lowest terms, e.g. "1280:720" → "16:9". */
54
+ export declare function normalizeAspect(a: string): string;
53
55
  /**
54
56
  * Build a chain that puts the planner's pick first, then the rest of the
55
57
  * tier-appropriate chain (deduped). Honors the planner's intent while still
@@ -1 +1 @@
1
- {"version":3,"file":"chains.d.ts","sourceRoot":"","sources":["../../../../src/services/agent/providerFallback/chains.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,eAAe,EACf,eAAe,EACf,aAAa,EAEb,KAAK,cAAc,EACpB,MAAM,2BAA2B,CAAC;AAGnC;;;;;;;;;;;;GAYG;AAGH,eAAO,MAAM,sBAAsB,EAAE,SAAS,eAAe,EAM5D,CAAC;AAKF,eAAO,MAAM,sBAAsB,EAAE,SAAS,eAAe,EAQ5D,CAAC;AAQF,eAAO,MAAM,uBAAuB,EAAE,SAAS,eAAe,EAQ7D,CAAC;AAKF,eAAO,MAAM,uBAAuB,EAAE,SAAS,eAAe,EAM7D,CAAC;AAGF,eAAO,MAAM,kBAAkB,EAAE,SAAS,eAAe,EAExD,CAAC;AAGF,eAAO,MAAM,WAAW,EAAE,SAAS,eAAe,EAGjD,CAAC;AAGF,eAAO,MAAM,SAAS,EAAE,SAAS,aAAa,EAE7C,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,qDAAqD;IACrD,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,+EAA+E;IAC/E,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,wCAAwC;IACxC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,eAAe,EACtB,GAAG,EAAE,sBAAsB,GAC1B,OAAO,CAuCT;AAyDD;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,WAAW,EAAE,eAAe,EAC5B,aAAa,EAAE,SAAS,eAAe,EAAE,GACxC,eAAe,EAAE,CAMnB;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,WAAW,mBAAmB;IAClC,4CAA4C;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB;IACjC,8CAA8C;IAC9C,YAAY,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,UAAU,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,QAAQ,EAAE,MAAM,CAAC;IACjB,2EAA2E;IAC3E,aAAa,EAAE,OAAO,CAAC;CACxB;AAED,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,GAAG,eAAe,EAC/B,WAAW,EAAE,MAAM,EACnB,IAAI,GAAE,mBAAwB,GAC7B,kBAAkB,GAAG,IAAI,CAyB3B"}
1
+ {"version":3,"file":"chains.d.ts","sourceRoot":"","sources":["../../../../src/services/agent/providerFallback/chains.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,eAAe,EACf,eAAe,EACf,aAAa,EAEb,KAAK,cAAc,EACpB,MAAM,2BAA2B,CAAC;AAGnC;;;;;;;;;;;;GAYG;AAGH,eAAO,MAAM,sBAAsB,EAAE,SAAS,eAAe,EAM5D,CAAC;AAKF,eAAO,MAAM,sBAAsB,EAAE,SAAS,eAAe,EAQ5D,CAAC;AAQF,eAAO,MAAM,uBAAuB,EAAE,SAAS,eAAe,EAQ7D,CAAC;AAKF,eAAO,MAAM,uBAAuB,EAAE,SAAS,eAAe,EAM7D,CAAC;AAGF,eAAO,MAAM,kBAAkB,EAAE,SAAS,eAAe,EAExD,CAAC;AAGF,eAAO,MAAM,WAAW,EAAE,SAAS,eAAe,EAGjD,CAAC;AAGF,eAAO,MAAM,SAAS,EAAE,SAAS,aAAa,EAE7C,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,qDAAqD;IACrD,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,+EAA+E;IAC/E,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,wCAAwC;IACxC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,eAAe,EACtB,GAAG,EAAE,sBAAsB,GAC1B,OAAO,CAuCT;AAED,+EAA+E;AAC/E,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CASjD;AA6CD;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,WAAW,EAAE,eAAe,EAC5B,aAAa,EAAE,SAAS,eAAe,EAAE,GACxC,eAAe,EAAE,CAMnB;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,WAAW,mBAAmB;IAClC,4CAA4C;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB;IACjC,8CAA8C;IAC9C,YAAY,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,UAAU,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,QAAQ,EAAE,MAAM,CAAC;IACjB,2EAA2E;IAC3E,aAAa,EAAE,OAAO,CAAC;CACxB;AAED,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,GAAG,eAAe,EAC/B,WAAW,EAAE,MAAM,EACnB,IAAI,GAAE,mBAAwB,GAC7B,kBAAkB,GAAG,IAAI,CAyB3B"}
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SFX_CHAIN = exports.MUSIC_CHAIN = exports.AVATAR_VIDEO_CHAIN = exports.T3_IMAGE_TO_VIDEO_CHAIN = exports.T2_IMAGE_TO_VIDEO_CHAIN = exports.T2_TEXT_TO_VIDEO_CHAIN = exports.T3_TEXT_TO_VIDEO_CHAIN = void 0;
4
4
  exports.isVideoModelCapable = isVideoModelCapable;
5
+ exports.normalizeAspect = normalizeAspect;
5
6
  exports.buildVideoChain = buildVideoChain;
6
7
  exports.snapDurationForModel = snapDurationForModel;
7
8
  const aiModels_1 = require("../../../globals/aiModels");
@@ -0,0 +1,74 @@
1
+ import { SceneAssetStrategy, VideoPlan } from "../../../schemas/videoPlan.schema";
2
+ import { FailureClass } from "../repair/types";
3
+ export declare function isStockStrategy(strategy: SceneAssetStrategy): boolean;
4
+ /**
5
+ * The ordered list of fallback strategies to try for a scene that failed, most
6
+ * intent-preserving first. Empty when nothing sensible exists (already stock /
7
+ * avatar).
8
+ *
9
+ * Failure-class aware: a `safety` (content-moderation) block came from the
10
+ * GENERATIVE step, so any remaining AI rung would just be blocked again — skip
11
+ * straight to the non-generative stock rungs (stock search has no prompt to
12
+ * moderate). All other classes step down the full ladder.
13
+ */
14
+ export declare function degradeLadderFor(strategy: SceneAssetStrategy, failureClass: FailureClass | undefined): SceneAssetStrategy[];
15
+ /**
16
+ * Produce a copy of `plan` with exactly one scene's strategy changed. Pure — no
17
+ * mutation of the input. The rest of the scene (prompt, duration, bible refs) is
18
+ * preserved so the degraded render still reflects the planned content.
19
+ */
20
+ export declare function planWithDegradedScene(plan: VideoPlan, sceneIndex: number, newStrategy: SceneAssetStrategy): VideoPlan;
21
+ /**
22
+ * Phase 2b — a proposed scene-recovery, computed WITHOUT executing it. The
23
+ * autonomous path (`recoverFailedScenes`) walks the ladder and re-runs each
24
+ * rung; in `manual` autonomy we instead surface this proposal on the approval
25
+ * card and pause. `toStrategy` is the most intent-preserving rung; `ladder`
26
+ * is the full remaining fallback chain (shown as "what happens if this also
27
+ * fails").
28
+ */
29
+ export interface RecoveryProposal {
30
+ sceneIndex: number;
31
+ fromStrategy: SceneAssetStrategy;
32
+ toStrategy: SceneAssetStrategy;
33
+ ladder: SceneAssetStrategy[];
34
+ failureClass: FailureClass | undefined;
35
+ reason: string;
36
+ }
37
+ /**
38
+ * Minimal structural view of a failed scene outcome. Kept structural (rather
39
+ * than importing `SceneOutcome` from the executor) so this pure module stays
40
+ * free of the executor import graph — `SceneOutcome` is assignable to it.
41
+ */
42
+ export interface FailedSceneLike {
43
+ scene: {
44
+ sceneIndex: number;
45
+ strategy: SceneAssetStrategy;
46
+ };
47
+ error?: {
48
+ classification?: FailureClass;
49
+ };
50
+ }
51
+ /**
52
+ * PURE — compute the recovery proposal for each failed scene without running
53
+ * anything. One proposal per scene that HAS a (failure-class-aware) degrade
54
+ * path; scenes whose ladder is empty (already stock / avatar / terminal) are
55
+ * omitted — there is nothing to approve, so the run just hard-fails them.
56
+ *
57
+ * This is the data the worker persists onto `run.pendingApproval` when it
58
+ * pauses for sign-off, and the basis the approve path mutates the plan with.
59
+ */
60
+ export declare function planSceneRecovery(failed: FailedSceneLike[]): RecoveryProposal[];
61
+ /**
62
+ * PURE — apply a set of approved recovery proposals to a plan, returning a new
63
+ * plan with each proposal's scene degraded to its `toStrategy`. Used on the
64
+ * approval-resume pass: the resumed executor then regenerates exactly those
65
+ * scenes with the new strategy while every already-succeeded scene replays
66
+ * from the providerTaskCache. No mutation of the input.
67
+ */
68
+ export declare function applyRecoveryProposals(plan: VideoPlan, proposals: Array<{
69
+ sceneIndex: number;
70
+ toStrategy: string;
71
+ }>): VideoPlan;
72
+ /** Human-readable one-liner for trace + the approval card. */
73
+ export declare function describeDegrade(sceneIndex: number, from: SceneAssetStrategy, to: SceneAssetStrategy, failureClass: FailureClass | undefined): string;
74
+ //# sourceMappingURL=degradeLadder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"degradeLadder.d.ts","sourceRoot":"","sources":["../../../../src/services/agent/recovery/degradeLadder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,mCAAmC,CAAC;AAClF,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AA4C/C,wBAAgB,eAAe,CAAC,QAAQ,EAAE,kBAAkB,GAAG,OAAO,CAErE;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,kBAAkB,EAC5B,YAAY,EAAE,YAAY,GAAG,SAAS,GACrC,kBAAkB,EAAE,CAItB;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,SAAS,EACf,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,kBAAkB,GAC9B,SAAS,CAOX;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,kBAAkB,CAAC;IACjC,UAAU,EAAE,kBAAkB,CAAC;IAC/B,MAAM,EAAE,kBAAkB,EAAE,CAAC;IAC7B,YAAY,EAAE,YAAY,GAAG,SAAS,CAAC;IACvC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,kBAAkB,CAAA;KAAE,CAAC;IAC5D,KAAK,CAAC,EAAE;QAAE,cAAc,CAAC,EAAE,YAAY,CAAA;KAAE,CAAC;CAC3C;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,eAAe,EAAE,GAAG,gBAAgB,EAAE,CAkB/E;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,SAAS,EACf,SAAS,EAAE,KAAK,CAAC;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,GAC3D,SAAS,CASX;AAED,8DAA8D;AAC9D,wBAAgB,eAAe,CAC7B,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,kBAAkB,EACxB,EAAE,EAAE,kBAAkB,EACtB,YAAY,EAAE,YAAY,GAAG,SAAS,GACrC,MAAM,CAUR"}
@@ -0,0 +1,133 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isStockStrategy = isStockStrategy;
4
+ exports.degradeLadderFor = degradeLadderFor;
5
+ exports.planWithDegradedScene = planWithDegradedScene;
6
+ exports.planSceneRecovery = planSceneRecovery;
7
+ exports.applyRecoveryProposals = applyRecoveryProposals;
8
+ exports.describeDegrade = describeDegrade;
9
+ /**
10
+ * PLAN-LEVEL recovery — scene-strategy degrade.
11
+ *
12
+ * The tool-level repair engine reworks a single tool's INPUT (param/prompt/model)
13
+ * and re-runs the SAME tool. When that's exhausted — every video model failed,
14
+ * the prompt is unfixably blocked, the provider can't do it at all — the only
15
+ * remaining move is to change the scene's STRATEGY: render it a cheaper way that
16
+ * still fills the slot (AI video → stock footage → ken-burns still) rather than
17
+ * letting one scene fail the whole video.
18
+ *
19
+ * This is intentionally a PLAN mutation, not a tool-input repair, so it lives at
20
+ * the orchestrator layer (the worker), not inside the per-tool repair loop. A
21
+ * strategy change always materially alters the scene, so it is classified as a
22
+ * `significant` decision — exactly the kind the human-in-the-loop approval gate
23
+ * (Phase 2b) pauses on when autonomy is set to manual.
24
+ */
25
+ /** Ordered fallbacks for each strategy, most-intent-preserving first. */
26
+ const DEGRADE_LADDER = {
27
+ // Pure text-to-video has no source still to fall back on → go to motion stock,
28
+ // then a static stock image with ken-burns motion.
29
+ "ai-text-to-video": ["stock-video", "stock-image-ken-burns"],
30
+ // Image-to-video: first drop the (failed) animation but keep the AI still,
31
+ // then fall back to stock footage, then a stock still.
32
+ "ai-image-to-video": ["ai-image-static", "stock-video", "stock-image-ken-burns"],
33
+ "ai-image-motion": ["ai-image-static", "stock-image-ken-burns", "stock-video"],
34
+ "ai-image-static": ["stock-image-ken-burns", "stock-video"],
35
+ "stock-video": ["stock-image-ken-burns"],
36
+ // Already the cheapest visual — nothing left to degrade to.
37
+ "stock-image-ken-burns": [],
38
+ // The executor already self-falls-back user-asset → stock; mirror it here.
39
+ "user-asset": ["stock-video", "stock-image-ken-burns"],
40
+ // Avatar needs a face + VO; there is no sensible automatic substitute.
41
+ "talking-head-avatar": [],
42
+ };
43
+ const STOCK_STRATEGIES = new Set([
44
+ "stock-video",
45
+ "stock-image-ken-burns",
46
+ "user-asset",
47
+ ]);
48
+ function isStockStrategy(strategy) {
49
+ return STOCK_STRATEGIES.has(strategy);
50
+ }
51
+ /**
52
+ * The ordered list of fallback strategies to try for a scene that failed, most
53
+ * intent-preserving first. Empty when nothing sensible exists (already stock /
54
+ * avatar).
55
+ *
56
+ * Failure-class aware: a `safety` (content-moderation) block came from the
57
+ * GENERATIVE step, so any remaining AI rung would just be blocked again — skip
58
+ * straight to the non-generative stock rungs (stock search has no prompt to
59
+ * moderate). All other classes step down the full ladder.
60
+ */
61
+ function degradeLadderFor(strategy, failureClass) {
62
+ const base = DEGRADE_LADDER[strategy] ?? [];
63
+ if (failureClass === "safety")
64
+ return base.filter(isStockStrategy);
65
+ return base;
66
+ }
67
+ /**
68
+ * Produce a copy of `plan` with exactly one scene's strategy changed. Pure — no
69
+ * mutation of the input. The rest of the scene (prompt, duration, bible refs) is
70
+ * preserved so the degraded render still reflects the planned content.
71
+ */
72
+ function planWithDegradedScene(plan, sceneIndex, newStrategy) {
73
+ return {
74
+ ...plan,
75
+ scenes: plan.scenes.map((s) => s.sceneIndex === sceneIndex ? { ...s, strategy: newStrategy } : s),
76
+ };
77
+ }
78
+ /**
79
+ * PURE — compute the recovery proposal for each failed scene without running
80
+ * anything. One proposal per scene that HAS a (failure-class-aware) degrade
81
+ * path; scenes whose ladder is empty (already stock / avatar / terminal) are
82
+ * omitted — there is nothing to approve, so the run just hard-fails them.
83
+ *
84
+ * This is the data the worker persists onto `run.pendingApproval` when it
85
+ * pauses for sign-off, and the basis the approve path mutates the plan with.
86
+ */
87
+ function planSceneRecovery(failed) {
88
+ const proposals = [];
89
+ for (const outcome of failed) {
90
+ const fromStrategy = outcome.scene.strategy;
91
+ const failureClass = outcome.error?.classification;
92
+ const ladder = degradeLadderFor(fromStrategy, failureClass);
93
+ if (!ladder.length)
94
+ continue; // terminal — nothing to propose
95
+ const toStrategy = ladder[0];
96
+ proposals.push({
97
+ sceneIndex: outcome.scene.sceneIndex,
98
+ fromStrategy,
99
+ toStrategy,
100
+ ladder,
101
+ failureClass,
102
+ reason: describeDegrade(outcome.scene.sceneIndex, fromStrategy, toStrategy, failureClass),
103
+ });
104
+ }
105
+ return proposals;
106
+ }
107
+ /**
108
+ * PURE — apply a set of approved recovery proposals to a plan, returning a new
109
+ * plan with each proposal's scene degraded to its `toStrategy`. Used on the
110
+ * approval-resume pass: the resumed executor then regenerates exactly those
111
+ * scenes with the new strategy while every already-succeeded scene replays
112
+ * from the providerTaskCache. No mutation of the input.
113
+ */
114
+ function applyRecoveryProposals(plan, proposals) {
115
+ if (!proposals.length)
116
+ return plan;
117
+ const target = new Map(proposals.map((p) => [p.sceneIndex, p.toStrategy]));
118
+ return {
119
+ ...plan,
120
+ scenes: plan.scenes.map((s) => target.has(s.sceneIndex) ? { ...s, strategy: target.get(s.sceneIndex) } : s),
121
+ };
122
+ }
123
+ /** Human-readable one-liner for trace + the approval card. */
124
+ function describeDegrade(sceneIndex, from, to, failureClass) {
125
+ const why = failureClass === "safety"
126
+ ? "content was blocked by the provider's moderation"
127
+ : failureClass === "capability"
128
+ ? "no available model could generate it"
129
+ : failureClass === "quota"
130
+ ? "provider quota was exhausted"
131
+ : "generation failed after retries";
132
+ return `Scene ${sceneIndex}: ${why} — fall back from "${from}" to "${to}".`;
133
+ }
@@ -0,0 +1,38 @@
1
+ import { ToolContext, ToolOutcome } from "../toolRegistry";
2
+ import { RepairContext, RepairProposal, RepairStrategy, RepairableRunToolFn, RunWithRepairOptions } from "./types";
3
+ /**
4
+ * RepairEngine — the generic, reactive, escalating retry brain.
5
+ *
6
+ * It owns an ordered set of strategies and a single loop, `runWithRepair`,
7
+ * that the executor uses in place of a raw `runTool`. The loop:
8
+ *
9
+ * run tool → ok? return it.
10
+ * else → ask strategies (narrowest first) for a repaired input → retry.
11
+ * repeat until ok, no strategy can help, or the retry budget is spent.
12
+ *
13
+ * Everything specific (which field to snap, whether moderation is fixable,
14
+ * whether to swap models) lives in the strategies. The engine only sequences
15
+ * them, guards against repeating an input, and records history.
16
+ */
17
+ export declare class RepairEngine {
18
+ private readonly strategies;
19
+ constructor(strategies: RepairStrategy[]);
20
+ /** Strategies, narrowest-first (read-only view, for trace/introspection). */
21
+ get strategyNames(): string[];
22
+ /**
23
+ * Walk strategies in ascending rank; the first that `applies` and returns a
24
+ * non-null proposal wins. A strategy that throws is logged and skipped (a
25
+ * broken strategy must never sink the whole repair — the next one still runs).
26
+ */
27
+ diagnose(rc: RepairContext): Promise<RepairProposal | null>;
28
+ /**
29
+ * Reactive bounded retry loop. Runs the tool; on failure, escalates through
30
+ * the strategies and retries with the repaired input. Returns the first OK
31
+ * outcome, or the LAST failure once the budget is spent / nothing can help.
32
+ *
33
+ * Terminal `auth` failures short-circuit immediately — a missing/invalid key
34
+ * is a deploy bug, not something a different input can fix.
35
+ */
36
+ runWithRepair<O = unknown>(runTool: RepairableRunToolFn, toolName: string, input: Record<string, unknown>, ctx: ToolContext, opts?: RunWithRepairOptions): Promise<ToolOutcome<O>>;
37
+ }
38
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../../src/services/agent/repair/engine.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE3D,OAAO,EAEL,aAAa,EAEb,cAAc,EACd,cAAc,EACd,mBAAmB,EACnB,oBAAoB,EACrB,MAAM,SAAS,CAAC;AAEjB;;;;;;;;;;;;;GAaG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAmB;gBAElC,UAAU,EAAE,cAAc,EAAE;IAKxC,6EAA6E;IAC7E,IAAI,aAAa,IAAI,MAAM,EAAE,CAE5B;IAED;;;;OAIG;IACG,QAAQ,CAAC,EAAE,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IA2BjE;;;;;;;OAOG;IACG,aAAa,CAAC,CAAC,GAAG,OAAO,EAC7B,OAAO,EAAE,mBAAmB,EAC5B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,GAAG,EAAE,WAAW,EAChB,IAAI,GAAE,oBAAyB,GAC9B,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;CAyF3B"}
@@ -0,0 +1,175 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RepairEngine = void 0;
4
+ const logger_1 = require("../../../utils/logger");
5
+ const providerTaskCache_1 = require("../providerTaskCache");
6
+ /**
7
+ * RepairEngine — the generic, reactive, escalating retry brain.
8
+ *
9
+ * It owns an ordered set of strategies and a single loop, `runWithRepair`,
10
+ * that the executor uses in place of a raw `runTool`. The loop:
11
+ *
12
+ * run tool → ok? return it.
13
+ * else → ask strategies (narrowest first) for a repaired input → retry.
14
+ * repeat until ok, no strategy can help, or the retry budget is spent.
15
+ *
16
+ * Everything specific (which field to snap, whether moderation is fixable,
17
+ * whether to swap models) lives in the strategies. The engine only sequences
18
+ * them, guards against repeating an input, and records history.
19
+ */
20
+ class RepairEngine {
21
+ constructor(strategies) {
22
+ // Ascending invasiveness — narrowest fix consulted first.
23
+ this.strategies = [...strategies].sort((a, b) => a.rank - b.rank);
24
+ }
25
+ /** Strategies, narrowest-first (read-only view, for trace/introspection). */
26
+ get strategyNames() {
27
+ return this.strategies.map((s) => s.name);
28
+ }
29
+ /**
30
+ * Walk strategies in ascending rank; the first that `applies` and returns a
31
+ * non-null proposal wins. A strategy that throws is logged and skipped (a
32
+ * broken strategy must never sink the whole repair — the next one still runs).
33
+ */
34
+ async diagnose(rc) {
35
+ for (const strategy of this.strategies) {
36
+ let relevant = false;
37
+ try {
38
+ relevant = strategy.applies(rc);
39
+ }
40
+ catch (err) {
41
+ logger_1.logger.warn("repair: strategy.applies threw — skipping", {
42
+ strategy: strategy.name,
43
+ err: err instanceof Error ? err.message : String(err),
44
+ });
45
+ continue;
46
+ }
47
+ if (!relevant)
48
+ continue;
49
+ try {
50
+ const proposal = await strategy.propose(rc);
51
+ if (proposal)
52
+ return proposal;
53
+ }
54
+ catch (err) {
55
+ logger_1.logger.warn("repair: strategy.propose threw — escalating to next", {
56
+ strategy: strategy.name,
57
+ toolName: rc.toolName,
58
+ err: err instanceof Error ? err.message : String(err),
59
+ });
60
+ }
61
+ }
62
+ return null;
63
+ }
64
+ /**
65
+ * Reactive bounded retry loop. Runs the tool; on failure, escalates through
66
+ * the strategies and retries with the repaired input. Returns the first OK
67
+ * outcome, or the LAST failure once the budget is spent / nothing can help.
68
+ *
69
+ * Terminal `auth` failures short-circuit immediately — a missing/invalid key
70
+ * is a deploy bug, not something a different input can fix.
71
+ */
72
+ async runWithRepair(runTool, toolName, input, ctx, opts = {}) {
73
+ const maxRepairs = opts.maxRepairs ?? 3;
74
+ const log = ctx.log ?? (() => { });
75
+ let currentInput = input;
76
+ let outcome = await runTool(toolName, currentInput, ctx);
77
+ if (outcome.ok)
78
+ return outcome;
79
+ const history = [];
80
+ // Guard against proposing an input we've already run (incl. the original).
81
+ const tried = new Set([safeHash(currentInput)]);
82
+ for (let attempt = 1; attempt <= maxRepairs; attempt++) {
83
+ const failure = toRepairFailure(outcome);
84
+ // Unfixable-by-input class — bail without burning the LLM budget.
85
+ if (failure.classification === "auth") {
86
+ log("repair_skip", { reason: "auth_class_terminal", toolName });
87
+ break;
88
+ }
89
+ const rc = {
90
+ toolName,
91
+ input: currentInput,
92
+ failure,
93
+ attempt,
94
+ history: [...history],
95
+ ctx,
96
+ };
97
+ const proposal = await this.diagnose(rc);
98
+ if (!proposal) {
99
+ log("repair_exhausted", {
100
+ toolName,
101
+ attempt,
102
+ classification: failure.classification,
103
+ reason: "no_strategy_could_repair",
104
+ });
105
+ break;
106
+ }
107
+ const proposedHash = safeHash(proposal.repairedInput);
108
+ if (tried.has(proposedHash)) {
109
+ // A strategy re-proposed something already attempted — stop rather than
110
+ // spin. (Distinct from maxRepairs: this catches a 2-cycle early.)
111
+ log("repair_loop_guard", {
112
+ toolName,
113
+ attempt,
114
+ strategy: proposal.strategy,
115
+ reason: "duplicate_input_proposed",
116
+ });
117
+ break;
118
+ }
119
+ tried.add(proposedHash);
120
+ history.push({ strategy: "original", input: currentInput, failure });
121
+ logger_1.logger.info("repair: retrying with repaired input", {
122
+ toolName,
123
+ attempt,
124
+ strategy: proposal.strategy,
125
+ qualityImpact: proposal.qualityImpact,
126
+ rationale: proposal.rationale,
127
+ priorClassification: failure.classification,
128
+ agentRunId: ctx.agentRunId,
129
+ });
130
+ log("repair_attempt", {
131
+ toolName,
132
+ attempt,
133
+ strategy: proposal.strategy,
134
+ qualityImpact: proposal.qualityImpact,
135
+ rationale: proposal.rationale,
136
+ });
137
+ currentInput = proposal.repairedInput;
138
+ outcome = await runTool(toolName, currentInput, ctx);
139
+ if (outcome.ok) {
140
+ logger_1.logger.info("repair: succeeded", {
141
+ toolName,
142
+ attempt,
143
+ strategy: proposal.strategy,
144
+ agentRunId: ctx.agentRunId,
145
+ });
146
+ log("repair_success", { toolName, attempt, strategy: proposal.strategy });
147
+ return outcome;
148
+ }
149
+ }
150
+ return outcome;
151
+ }
152
+ }
153
+ exports.RepairEngine = RepairEngine;
154
+ function toRepairFailure(outcome) {
155
+ if (outcome.ok) {
156
+ // Defensive — callers only pass failures here.
157
+ return { code: "UNKNOWN", message: "no error" };
158
+ }
159
+ return {
160
+ code: outcome.error.code,
161
+ message: outcome.error.message,
162
+ classification: outcome.error.classification,
163
+ attemptedProviders: outcome.error.attemptedProviders,
164
+ };
165
+ }
166
+ function safeHash(input) {
167
+ try {
168
+ return (0, providerTaskCache_1.hashTaskInputs)(input);
169
+ }
170
+ catch {
171
+ // Non-canonicalizable input (shouldn't happen for tool inputs) — fall back
172
+ // to a best-effort string so the loop guard still functions.
173
+ return JSON.stringify(input).slice(0, 64);
174
+ }
175
+ }
@@ -0,0 +1,20 @@
1
+ import { RepairEngine } from "./engine";
2
+ export * from "./types";
3
+ export { RepairEngine } from "./engine";
4
+ export { paramRepairStrategy } from "./strategies/paramRepair.strategy";
5
+ export { llmNarrowRepairStrategy, llmWideRepairStrategy, } from "./strategies/llmRepair.strategy";
6
+ /**
7
+ * The default escalation ladder, narrowest-first:
8
+ * rank 0 param-repair — deterministic single-field snap (free, instant)
9
+ * rank 10 llm-repair-narrow — agentic, fix the offending field only
10
+ * rank 20 llm-repair-wide — agentic, may swap model / restructure
11
+ *
12
+ * Engine sorts by rank, so registration order here is cosmetic.
13
+ */
14
+ export declare function createDefaultRepairEngine(): RepairEngine;
15
+ /**
16
+ * Process-wide default engine. The Executor uses this when the host doesn't
17
+ * inject its own, so self-healing is on by default everywhere the executor runs.
18
+ */
19
+ export declare const defaultRepairEngine: RepairEngine;
20
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/services/agent/repair/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAOxC,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,EACL,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,iCAAiC,CAAC;AAEzC;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,IAAI,YAAY,CAMxD;AAED;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,YAA0C,CAAC"}
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.defaultRepairEngine = exports.llmWideRepairStrategy = exports.llmNarrowRepairStrategy = exports.paramRepairStrategy = exports.RepairEngine = void 0;
18
+ exports.createDefaultRepairEngine = createDefaultRepairEngine;
19
+ const engine_1 = require("./engine");
20
+ const paramRepair_strategy_1 = require("./strategies/paramRepair.strategy");
21
+ const llmRepair_strategy_1 = require("./strategies/llmRepair.strategy");
22
+ __exportStar(require("./types"), exports);
23
+ var engine_2 = require("./engine");
24
+ Object.defineProperty(exports, "RepairEngine", { enumerable: true, get: function () { return engine_2.RepairEngine; } });
25
+ var paramRepair_strategy_2 = require("./strategies/paramRepair.strategy");
26
+ Object.defineProperty(exports, "paramRepairStrategy", { enumerable: true, get: function () { return paramRepair_strategy_2.paramRepairStrategy; } });
27
+ var llmRepair_strategy_2 = require("./strategies/llmRepair.strategy");
28
+ Object.defineProperty(exports, "llmNarrowRepairStrategy", { enumerable: true, get: function () { return llmRepair_strategy_2.llmNarrowRepairStrategy; } });
29
+ Object.defineProperty(exports, "llmWideRepairStrategy", { enumerable: true, get: function () { return llmRepair_strategy_2.llmWideRepairStrategy; } });
30
+ /**
31
+ * The default escalation ladder, narrowest-first:
32
+ * rank 0 param-repair — deterministic single-field snap (free, instant)
33
+ * rank 10 llm-repair-narrow — agentic, fix the offending field only
34
+ * rank 20 llm-repair-wide — agentic, may swap model / restructure
35
+ *
36
+ * Engine sorts by rank, so registration order here is cosmetic.
37
+ */
38
+ function createDefaultRepairEngine() {
39
+ return new engine_1.RepairEngine([
40
+ paramRepair_strategy_1.paramRepairStrategy,
41
+ llmRepair_strategy_1.llmNarrowRepairStrategy,
42
+ llmRepair_strategy_1.llmWideRepairStrategy,
43
+ ]);
44
+ }
45
+ /**
46
+ * Process-wide default engine. The Executor uses this when the host doesn't
47
+ * inject its own, so self-healing is on by default everywhere the executor runs.
48
+ */
49
+ exports.defaultRepairEngine = createDefaultRepairEngine();
@@ -0,0 +1,6 @@
1
+ import { RepairStrategy } from "../types";
2
+ /** Tier 1 — narrow agentic fix (offending field only, no model change). */
3
+ export declare const llmNarrowRepairStrategy: RepairStrategy;
4
+ /** Tier 2 — wide agentic fix (may swap model / restructure). */
5
+ export declare const llmWideRepairStrategy: RepairStrategy;
6
+ //# sourceMappingURL=llmRepair.strategy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llmRepair.strategy.d.ts","sourceRoot":"","sources":["../../../../../src/services/agent/repair/strategies/llmRepair.strategy.ts"],"names":[],"mappings":"AAOA,OAAO,EAAiC,cAAc,EAAE,MAAM,UAAU,CAAC;AAwOzE,2EAA2E;AAC3E,eAAO,MAAM,uBAAuB,gBAAsC,CAAC;AAC3E,gEAAgE;AAChE,eAAO,MAAM,qBAAqB,gBAAoC,CAAC"}