opendevbrowser 0.0.18 → 0.0.20
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.
- package/README.md +36 -27
- package/dist/automation/coordinator.d.ts +61 -2
- package/dist/automation/coordinator.d.ts.map +1 -1
- package/dist/browser/browser-manager.d.ts +6 -1
- package/dist/browser/browser-manager.d.ts.map +1 -1
- package/dist/browser/canvas-manager.d.ts +4 -0
- package/dist/browser/canvas-manager.d.ts.map +1 -1
- package/dist/browser/manager-types.d.ts +6 -1
- package/dist/browser/manager-types.d.ts.map +1 -1
- package/dist/browser/ops-browser-manager.d.ts +6 -1
- package/dist/browser/ops-browser-manager.d.ts.map +1 -1
- package/dist/browser/screencast-recorder.d.ts.map +1 -1
- package/dist/browser/session-inspector.d.ts +39 -0
- package/dist/browser/session-inspector.d.ts.map +1 -1
- package/dist/canvas/document-store.d.ts +14 -5
- package/dist/canvas/document-store.d.ts.map +1 -1
- package/dist/canvas/starters/catalog.d.ts.map +1 -1
- package/dist/canvas/types.d.ts +120 -9
- package/dist/canvas/types.d.ts.map +1 -1
- package/dist/challenges/action-loop.d.ts +2 -1
- package/dist/challenges/action-loop.d.ts.map +1 -1
- package/dist/challenges/capture.d.ts +14 -0
- package/dist/challenges/capture.d.ts.map +1 -0
- package/dist/challenges/index.d.ts +3 -1
- package/dist/challenges/index.d.ts.map +1 -1
- package/dist/challenges/inspect-plan.d.ts +40 -0
- package/dist/challenges/inspect-plan.d.ts.map +1 -0
- package/dist/challenges/orchestrator.d.ts.map +1 -1
- package/dist/challenges/types.d.ts +34 -0
- package/dist/challenges/types.d.ts.map +1 -1
- package/dist/{chunk-YBQECXZX.js → chunk-3VA6XR25.js} +3 -3
- package/dist/chunk-3VA6XR25.js.map +1 -0
- package/dist/{chunk-5FZQJRBQ.js → chunk-C6QUKABT.js} +2789 -992
- package/dist/chunk-C6QUKABT.js.map +1 -0
- package/dist/{chunk-L57D35TB.js → chunk-LMNFPJRI.js} +4255 -2752
- package/dist/chunk-LMNFPJRI.js.map +1 -0
- package/dist/cli/commands/challenge-automation-mode.d.ts +3 -0
- package/dist/cli/commands/challenge-automation-mode.d.ts.map +1 -0
- package/dist/cli/commands/inspiredesign.d.ts +25 -0
- package/dist/cli/commands/inspiredesign.d.ts.map +1 -0
- package/dist/cli/commands/macro-resolve.d.ts.map +1 -1
- package/dist/cli/commands/nav/review-desktop.d.ts +7 -0
- package/dist/cli/commands/nav/review-desktop.d.ts.map +1 -0
- package/dist/cli/commands/nav/review-shared.d.ts +10 -0
- package/dist/cli/commands/nav/review-shared.d.ts.map +1 -0
- package/dist/cli/commands/nav/review.d.ts.map +1 -1
- package/dist/cli/commands/serve.d.ts.map +1 -1
- package/dist/cli/commands/session/inspector-audit.d.ts +7 -0
- package/dist/cli/commands/session/inspector-audit.d.ts.map +1 -0
- package/dist/cli/commands/session/inspector-plan.d.ts +7 -0
- package/dist/cli/commands/session/inspector-plan.d.ts.map +1 -0
- package/dist/cli/commands/session/inspector-shared.d.ts +11 -0
- package/dist/cli/commands/session/inspector-shared.d.ts.map +1 -0
- package/dist/cli/commands/session/inspector.d.ts +1 -11
- package/dist/cli/commands/session/inspector.d.ts.map +1 -1
- package/dist/cli/commands/status-capabilities.d.ts +7 -0
- package/dist/cli/commands/status-capabilities.d.ts.map +1 -0
- package/dist/cli/daemon-client.d.ts.map +1 -1
- package/dist/cli/daemon-commands.d.ts.map +1 -1
- package/dist/cli/daemon-status.d.ts +5 -0
- package/dist/cli/daemon-status.d.ts.map +1 -1
- package/dist/cli/daemon.d.ts +5 -0
- package/dist/cli/daemon.d.ts.map +1 -1
- package/dist/cli/help.d.ts +2 -0
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/index.js +620 -242
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/remote-manager.d.ts +6 -0
- package/dist/cli/remote-manager.d.ts.map +1 -1
- package/dist/cli/utils/parse.d.ts +1 -0
- package/dist/cli/utils/parse.d.ts.map +1 -1
- package/dist/cli/utils/skills.d.ts +1 -1
- package/dist/cli/utils/skills.d.ts.map +1 -1
- package/dist/cli/utils/workflow-message.d.ts +3 -0
- package/dist/cli/utils/workflow-message.d.ts.map +1 -1
- package/dist/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/core/bootstrap.d.ts.map +1 -1
- package/dist/core/runtime-assemblies.d.ts +2 -1
- package/dist/core/runtime-assemblies.d.ts.map +1 -1
- package/dist/core/types.d.ts +1 -1
- package/dist/core/types.d.ts.map +1 -1
- package/dist/desktop/runtime.d.ts +1 -0
- package/dist/desktop/runtime.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +728 -447
- package/dist/index.js.map +1 -1
- package/dist/opendevbrowser.d.ts.map +1 -1
- package/dist/opendevbrowser.js +728 -447
- package/dist/opendevbrowser.js.map +1 -1
- package/dist/providers/browser-fallback.d.ts.map +1 -1
- package/dist/providers/constraint.d.ts +11 -0
- package/dist/providers/constraint.d.ts.map +1 -1
- package/dist/providers/cookie-source.d.ts +8 -0
- package/dist/providers/cookie-source.d.ts.map +1 -0
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/inspiredesign-capture.d.ts +17 -0
- package/dist/providers/inspiredesign-capture.d.ts.map +1 -0
- package/dist/providers/inspiredesign-contract.d.ts +77 -0
- package/dist/providers/inspiredesign-contract.d.ts.map +1 -0
- package/dist/providers/renderer.d.ts +21 -0
- package/dist/providers/renderer.d.ts.map +1 -1
- package/dist/providers/runtime-bundle.d.ts +2 -1
- package/dist/providers/runtime-bundle.d.ts.map +1 -1
- package/dist/providers/runtime-factory.d.ts +4 -2
- package/dist/providers/runtime-factory.d.ts.map +1 -1
- package/dist/providers/shopping/index.d.ts +1 -1
- package/dist/providers/types.d.ts +3 -2
- package/dist/providers/types.d.ts.map +1 -1
- package/dist/providers/workflow-contracts.d.ts +1 -1
- package/dist/providers/workflow-contracts.d.ts.map +1 -1
- package/dist/providers/workflows.d.ts +21 -2
- package/dist/providers/workflows.d.ts.map +1 -1
- package/dist/{providers-G36AM3Z2.js → providers-3VBLTNAX.js} +6 -2
- package/dist/public-surface/generated-manifest.d.ts +143 -7
- package/dist/public-surface/generated-manifest.d.ts.map +1 -1
- package/dist/public-surface/source.d.ts +102 -3
- package/dist/public-surface/source.d.ts.map +1 -1
- package/dist/relay/protocol.d.ts +1 -1
- package/dist/relay/protocol.d.ts.map +1 -1
- package/dist/relay/relay-server.d.ts +1 -0
- package/dist/relay/relay-server.d.ts.map +1 -1
- package/dist/skills/skill-loader.js +1 -1
- package/dist/tools/automation-shared.d.ts +6 -0
- package/dist/tools/automation-shared.d.ts.map +1 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/inspiredesign_run.d.ts +4 -0
- package/dist/tools/inspiredesign_run.d.ts.map +1 -0
- package/dist/tools/review_desktop.d.ts +4 -0
- package/dist/tools/review_desktop.d.ts.map +1 -0
- package/dist/tools/session_inspector.d.ts.map +1 -1
- package/dist/tools/session_inspector_audit.d.ts +4 -0
- package/dist/tools/session_inspector_audit.d.ts.map +1 -0
- package/dist/tools/session_inspector_plan.d.ts +4 -0
- package/dist/tools/session_inspector_plan.d.ts.map +1 -0
- package/dist/tools/status_capabilities.d.ts +4 -0
- package/dist/tools/status_capabilities.d.ts.map +1 -0
- package/extension/dist/background.js +70 -10
- package/extension/dist/canvas/canvas-runtime.js +14 -1
- package/extension/dist/ops/ops-runtime.js +18 -1
- package/extension/dist/popup.js +29 -16
- package/extension/dist/services/ConnectionManager.js +27 -2
- package/extension/manifest.json +1 -1
- package/extension/popup.html +11 -0
- package/package.json +5 -5
- package/skills/AGENTS.md +2 -2
- package/skills/opendevbrowser-best-practices/SKILL.md +50 -15
- package/skills/opendevbrowser-best-practices/artifacts/canvas-governance-playbook.md +31 -12
- package/skills/opendevbrowser-best-practices/artifacts/command-channel-reference.md +64 -15
- package/skills/opendevbrowser-best-practices/artifacts/provider-workflows.md +4 -0
- package/skills/opendevbrowser-best-practices/artifacts/skill-runtime-surface-matrix.md +11 -10
- package/skills/opendevbrowser-best-practices/assets/templates/canvas-blocker-checklist.json +28 -22
- package/skills/opendevbrowser-best-practices/assets/templates/canvas-generation-plan.v1.json +18 -17
- package/skills/opendevbrowser-best-practices/assets/templates/canvas-handshake-example.json +135 -17
- package/skills/opendevbrowser-best-practices/assets/templates/skill-runtime-pack-matrix.json +55 -8
- package/skills/opendevbrowser-best-practices/assets/templates/surface-audit-checklist.json +18 -4
- package/skills/opendevbrowser-best-practices/scripts/odb-workflow.sh +16 -4
- package/skills/opendevbrowser-best-practices/scripts/run-robustness-audit.sh +3 -1
- package/skills/opendevbrowser-best-practices/scripts/validate-skill-assets.sh +68 -25
- package/skills/opendevbrowser-design-agent/SKILL.md +9 -4
- package/skills/opendevbrowser-design-agent/artifacts/design-workflows.md +15 -6
- package/skills/opendevbrowser-design-agent/assets/templates/canvas-generation-plan.design.v1.json +18 -17
- package/skills/opendevbrowser-design-agent/scripts/design-workflow.sh +11 -0
- package/skills/opendevbrowser-design-agent/scripts/validate-skill-assets.sh +57 -0
- package/dist/chunk-5FZQJRBQ.js.map +0 -1
- package/dist/chunk-L57D35TB.js.map +0 -1
- package/dist/chunk-YBQECXZX.js.map +0 -1
- /package/dist/{providers-G36AM3Z2.js.map → providers-3VBLTNAX.js.map} +0 -0
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
ProviderRuntimeError,
|
|
3
3
|
createProviderError,
|
|
4
4
|
isProviderReasonCode,
|
|
5
|
+
isProviderRuntimeError,
|
|
5
6
|
normalizeProviderReasonCode,
|
|
6
7
|
providerErrorCodeFromReasonCode,
|
|
7
8
|
toProviderError
|
|
@@ -796,6 +797,12 @@ var applyProviderIssueHint = (details, hint) => {
|
|
|
796
797
|
if (hint.constraint && !isProviderConstraint(next.constraint)) {
|
|
797
798
|
next.constraint = hint.constraint;
|
|
798
799
|
}
|
|
800
|
+
if (typeof next.guidance === "undefined") {
|
|
801
|
+
const guidance = buildProviderIssueGuidance({ hint, details: next });
|
|
802
|
+
if (guidance) {
|
|
803
|
+
next.guidance = guidance;
|
|
804
|
+
}
|
|
805
|
+
}
|
|
799
806
|
return next;
|
|
800
807
|
};
|
|
801
808
|
var providerLabel = (provider) => {
|
|
@@ -805,6 +812,77 @@ var providerLabel = (provider) => {
|
|
|
805
812
|
const tail = separator >= 0 ? normalized.slice(separator + 1) : normalized;
|
|
806
813
|
return tail.charAt(0).toUpperCase() + tail.slice(1);
|
|
807
814
|
};
|
|
815
|
+
var hasPreservedBrowserState = (details) => {
|
|
816
|
+
return typeof details?.preservedSessionId === "string" || typeof details?.preservedTargetId === "string";
|
|
817
|
+
};
|
|
818
|
+
var buildGuidance = (reason, recommendedNextCommands) => ({
|
|
819
|
+
reason,
|
|
820
|
+
recommendedNextCommands
|
|
821
|
+
});
|
|
822
|
+
var buildAuthGuidance = (subject, preservedBrowserState) => {
|
|
823
|
+
return preservedBrowserState ? buildGuidance(
|
|
824
|
+
`${subject} preserved browser state that can finish authentication.`,
|
|
825
|
+
[
|
|
826
|
+
"Complete the login or account checkpoint in the preserved browser session.",
|
|
827
|
+
"Rerun the same provider or workflow after the session is fully authenticated."
|
|
828
|
+
]
|
|
829
|
+
) : buildGuidance(
|
|
830
|
+
`${subject} needs an authenticated session before retrying.`,
|
|
831
|
+
[
|
|
832
|
+
"Reuse an authenticated browser session, import logged-in cookies, or use the provider sign-in flow.",
|
|
833
|
+
"Rerun the same provider or workflow once the session is active."
|
|
834
|
+
]
|
|
835
|
+
);
|
|
836
|
+
};
|
|
837
|
+
var buildChallengeGuidance = (subject, preservedBrowserState) => {
|
|
838
|
+
return preservedBrowserState ? buildGuidance(
|
|
839
|
+
`${subject} preserved browser state that can complete the current challenge.`,
|
|
840
|
+
[
|
|
841
|
+
"Finish the login or anti-bot challenge in the preserved browser session.",
|
|
842
|
+
"Rerun the same provider or workflow after the page unlocks."
|
|
843
|
+
]
|
|
844
|
+
) : buildGuidance(
|
|
845
|
+
`${subject} hit a challenge that still needs browser-assisted follow-up.`,
|
|
846
|
+
[
|
|
847
|
+
"Retry with browser assistance so the challenge can be completed interactively.",
|
|
848
|
+
"Only ask for manual credentials if browser-assisted recovery still cannot unlock the page."
|
|
849
|
+
]
|
|
850
|
+
);
|
|
851
|
+
};
|
|
852
|
+
var buildRenderGuidance = (subject, preservedBrowserState) => {
|
|
853
|
+
return preservedBrowserState ? buildGuidance(
|
|
854
|
+
`${subject} still needs a live browser-rendered page, but browser state is already preserved.`,
|
|
855
|
+
[
|
|
856
|
+
"Inspect the preserved browser session until usable content is visible.",
|
|
857
|
+
"Rerun the same provider or workflow after the rendered page is ready."
|
|
858
|
+
]
|
|
859
|
+
) : buildGuidance(
|
|
860
|
+
`${subject} needs a live browser-rendered page before retrying.`,
|
|
861
|
+
[
|
|
862
|
+
"Retry with browser assistance or a headed browser session.",
|
|
863
|
+
"Rerun the same provider or workflow after the rendered page is ready."
|
|
864
|
+
]
|
|
865
|
+
);
|
|
866
|
+
};
|
|
867
|
+
var buildProviderIssueGuidance = (args) => {
|
|
868
|
+
const subject = providerLabel(args.provider);
|
|
869
|
+
const preservedBrowserState = hasPreservedBrowserState(args.details);
|
|
870
|
+
const disposition = toNonEmptyString(args.details?.disposition);
|
|
871
|
+
if (disposition === "completed") return void 0;
|
|
872
|
+
if (disposition === "challenge_preserved") {
|
|
873
|
+
return buildChallengeGuidance(subject, true);
|
|
874
|
+
}
|
|
875
|
+
if (args.hint.reasonCode === "token_required" || args.hint.reasonCode === "auth_required") {
|
|
876
|
+
return buildAuthGuidance(subject, preservedBrowserState);
|
|
877
|
+
}
|
|
878
|
+
if (args.hint.reasonCode === "challenge_detected") {
|
|
879
|
+
return buildChallengeGuidance(subject, preservedBrowserState);
|
|
880
|
+
}
|
|
881
|
+
if (args.hint.constraint?.kind === "render_required" || args.hint.reasonCode === "env_limited") {
|
|
882
|
+
return buildRenderGuidance(subject, preservedBrowserState);
|
|
883
|
+
}
|
|
884
|
+
return void 0;
|
|
885
|
+
};
|
|
808
886
|
var summaryPriority = (hint) => {
|
|
809
887
|
if (hint.reasonCode === "token_required" || hint.reasonCode === "auth_required") return 3;
|
|
810
888
|
if (hint.reasonCode === "challenge_detected") return 2;
|
|
@@ -836,10 +914,16 @@ var summarizePrimaryProviderIssue = (failures) => {
|
|
|
836
914
|
});
|
|
837
915
|
if (!hint) continue;
|
|
838
916
|
const summary = summarizeProviderIssue({ provider: failure.provider, hint });
|
|
917
|
+
const guidance = buildProviderIssueGuidance({
|
|
918
|
+
provider: failure.provider,
|
|
919
|
+
hint,
|
|
920
|
+
details: failure.error?.details
|
|
921
|
+
});
|
|
839
922
|
const candidate = {
|
|
840
923
|
provider: failure.provider,
|
|
841
924
|
summary,
|
|
842
|
-
...hint
|
|
925
|
+
...hint,
|
|
926
|
+
...guidance ? { guidance } : {}
|
|
843
927
|
};
|
|
844
928
|
if (!best || summaryPriority(candidate) > summaryPriority(best)) {
|
|
845
929
|
best = candidate;
|
|
@@ -1983,6 +2067,138 @@ var verifyChallengeProgress = async (args) => {
|
|
|
1983
2067
|
};
|
|
1984
2068
|
};
|
|
1985
2069
|
|
|
2070
|
+
// src/challenges/capability-matrix.ts
|
|
2071
|
+
var buildCapabilityMatrix = (bundle, interpretation, gate) => {
|
|
2072
|
+
const hasActionables = bundle.actionables.length > 0;
|
|
2073
|
+
const helperActionRefs = [
|
|
2074
|
+
...bundle.continuity.loginRefs,
|
|
2075
|
+
...bundle.continuity.sessionReuseRefs,
|
|
2076
|
+
...bundle.continuity.humanVerificationRefs,
|
|
2077
|
+
...bundle.continuity.checkpointRefs,
|
|
2078
|
+
...bundle.interaction?.clickRefs ?? [],
|
|
2079
|
+
...bundle.interaction?.holdRefs ?? [],
|
|
2080
|
+
...bundle.interaction?.dragRefs ?? []
|
|
2081
|
+
];
|
|
2082
|
+
const authLaneRelevant = interpretation.classification === "auth_required" || interpretation.classification === "existing_session_reuse" || bundle.continuity.likelyLoginPage || bundle.continuity.likelySessionPicker;
|
|
2083
|
+
const canNavigateToAuth = gate.allowedActions.includes("auth_navigation") && authLaneRelevant && (bundle.continuity.loginRefs.length > 0 || typeof bundle.url === "string");
|
|
2084
|
+
const canReuseExistingSession = gate.allowedActions.includes("session_reuse") && (bundle.continuity.hasPreservedSession || bundle.continuity.attachedSession || bundle.continuity.sessionReuseRefs.length > 0);
|
|
2085
|
+
const canReuseCookies = gate.allowedActions.includes("cookie_reuse") && authLaneRelevant && (bundle.continuity.canReuseExistingCookies || bundle.continuity.canImportCookies);
|
|
2086
|
+
const canFillNonSecretFields = gate.allowedActions.includes("non_secret_form_fill") && bundle.continuity.hasNonSecretTaskData && bundle.continuity.nonSecretFieldRefs.length > 0;
|
|
2087
|
+
const canExploreClicks = gate.allowedActions.includes("click_path") && (hasActionables || bundle.continuity.loginRefs.length > 0 || bundle.continuity.sessionReuseRefs.length > 0 || bundle.continuity.checkpointRefs.length > 0);
|
|
2088
|
+
const mustYield = interpretation.humanBoundary === "secret_entry" || interpretation.humanBoundary === "mfa" || interpretation.humanBoundary === "explicit_consent" || interpretation.humanBoundary === "exhausted_no_progress";
|
|
2089
|
+
const mustDefer = interpretation.humanBoundary === "policy_blocked" || !bundle.blocker && bundle.blockerState === "clear";
|
|
2090
|
+
let helperEligibility = gate.helperEligibility ?? (gate.optionalComputerUseBridge ? {
|
|
2091
|
+
allowed: true,
|
|
2092
|
+
reason: "Optional helper bridge remains eligible after policy resolution."
|
|
2093
|
+
} : {
|
|
2094
|
+
allowed: false,
|
|
2095
|
+
reason: "Optional computer-use bridge is disabled by policy.",
|
|
2096
|
+
standDownReason: "helper_disabled_by_policy"
|
|
2097
|
+
});
|
|
2098
|
+
if (helperEligibility.allowed && interpretation.humanBoundary !== "none") {
|
|
2099
|
+
helperEligibility = {
|
|
2100
|
+
allowed: false,
|
|
2101
|
+
reason: `Helper bridge is blocked by human boundary: ${interpretation.humanBoundary}.`,
|
|
2102
|
+
standDownReason: "helper_blocked_by_human_boundary"
|
|
2103
|
+
};
|
|
2104
|
+
} else if (helperEligibility.allowed && helperActionRefs.length === 0) {
|
|
2105
|
+
helperEligibility = {
|
|
2106
|
+
allowed: false,
|
|
2107
|
+
reason: "Canonical evidence did not expose any safe browser-scoped helper actions.",
|
|
2108
|
+
standDownReason: "helper_no_safe_actions"
|
|
2109
|
+
};
|
|
2110
|
+
}
|
|
2111
|
+
return {
|
|
2112
|
+
canNavigateToAuth,
|
|
2113
|
+
canReuseExistingSession,
|
|
2114
|
+
canReuseCookies,
|
|
2115
|
+
canFillNonSecretFields,
|
|
2116
|
+
canExploreClicks,
|
|
2117
|
+
canUseOwnedEnvironmentFixture: interpretation.classification === "owned_environment_test_challenge" && gate.governedLanes.includes("owned_environment_fixture"),
|
|
2118
|
+
canUseSanctionedIdentity: gate.governedLanes.includes("sanctioned_identity"),
|
|
2119
|
+
canUseServiceAdapter: gate.governedLanes.includes("service_adapter"),
|
|
2120
|
+
canUseComputerUseBridge: helperEligibility.allowed,
|
|
2121
|
+
helperEligibility,
|
|
2122
|
+
mustYield,
|
|
2123
|
+
mustDefer
|
|
2124
|
+
};
|
|
2125
|
+
};
|
|
2126
|
+
|
|
2127
|
+
// src/challenges/capture.ts
|
|
2128
|
+
async function captureChallengeEvidence(args) {
|
|
2129
|
+
const status = await args.handle.status(args.sessionId);
|
|
2130
|
+
const effectiveTargetId = args.targetId ?? status.activeTargetId ?? null;
|
|
2131
|
+
const snapshot = await args.handle.snapshot(
|
|
2132
|
+
args.sessionId,
|
|
2133
|
+
"actionables",
|
|
2134
|
+
2400,
|
|
2135
|
+
void 0,
|
|
2136
|
+
effectiveTargetId
|
|
2137
|
+
);
|
|
2138
|
+
const debugTrace = await args.handle.debugTraceSnapshot(args.sessionId, { max: 50 });
|
|
2139
|
+
const cookies = status.url ? await args.handle.cookieList(args.sessionId, [status.url]) : { count: 0 };
|
|
2140
|
+
return buildChallengeEvidenceBundle({
|
|
2141
|
+
status,
|
|
2142
|
+
snapshot: {
|
|
2143
|
+
snapshotId: snapshot.snapshotId,
|
|
2144
|
+
content: snapshot.content,
|
|
2145
|
+
warnings: snapshot.warnings
|
|
2146
|
+
},
|
|
2147
|
+
debugTrace,
|
|
2148
|
+
cookieCount: cookies.count,
|
|
2149
|
+
canImportCookies: args.canImportCookies,
|
|
2150
|
+
fallbackDisposition: args.fallbackDisposition,
|
|
2151
|
+
registryPressure: args.registryPressure,
|
|
2152
|
+
taskData: args.taskData
|
|
2153
|
+
});
|
|
2154
|
+
}
|
|
2155
|
+
|
|
2156
|
+
// src/challenges/human-yield-gate.ts
|
|
2157
|
+
var shouldYieldToHuman = (args) => {
|
|
2158
|
+
if (args.noProgressExhausted) {
|
|
2159
|
+
return {
|
|
2160
|
+
yield: true,
|
|
2161
|
+
reason: "exhausted_no_progress"
|
|
2162
|
+
};
|
|
2163
|
+
}
|
|
2164
|
+
return {
|
|
2165
|
+
yield: args.interpretation.humanBoundary !== "none",
|
|
2166
|
+
reason: args.interpretation.humanBoundary
|
|
2167
|
+
};
|
|
2168
|
+
};
|
|
2169
|
+
var buildHumanYieldPacket = (args) => {
|
|
2170
|
+
const challengeId = args.bundle.challengeId ?? `challenge-${Date.now()}`;
|
|
2171
|
+
const targetHints = [
|
|
2172
|
+
...args.bundle.continuity.loginRefs,
|
|
2173
|
+
...args.bundle.continuity.sessionReuseRefs,
|
|
2174
|
+
...args.bundle.continuity.humanVerificationRefs,
|
|
2175
|
+
...args.bundle.continuity.checkpointRefs
|
|
2176
|
+
];
|
|
2177
|
+
return {
|
|
2178
|
+
challengeId,
|
|
2179
|
+
classification: args.interpretation.classification,
|
|
2180
|
+
reason: args.reason,
|
|
2181
|
+
sessionId: args.sessionId,
|
|
2182
|
+
targetId: args.targetId ?? args.bundle.activeTargetId,
|
|
2183
|
+
ownerSurface: args.bundle.challenge?.ownerSurface ?? args.bundle.ownerSurface,
|
|
2184
|
+
url: args.bundle.url,
|
|
2185
|
+
title: args.bundle.title,
|
|
2186
|
+
requiredHumanStep: args.reason === "mfa" ? "Complete MFA or passkey verification, then continue." : args.reason === "secret_entry" ? "Enter the required secret-bearing credentials, then continue." : args.reason === "unsupported_third_party" ? "Complete the unsupported third-party challenge manually, then continue." : "Review the page state and continue when ready.",
|
|
2187
|
+
targetHints,
|
|
2188
|
+
expectedPostAuthCheckpoint: args.interpretation.likelyCheckpoint,
|
|
2189
|
+
preserveUntil: args.bundle.challenge?.preserveUntil,
|
|
2190
|
+
verifyUntil: args.bundle.challenge?.verifyUntil,
|
|
2191
|
+
traceRequestId: args.bundle.diagnostics.traceRequestId,
|
|
2192
|
+
...args.verification ? {
|
|
2193
|
+
lastVerificationStatus: args.verification.status,
|
|
2194
|
+
lastVerificationReason: args.verification.reason
|
|
2195
|
+
} : {},
|
|
2196
|
+
evidenceSummary: args.interpretation.summary,
|
|
2197
|
+
reclaimHint: "Resume the preserved session and re-run verification after the human step completes.",
|
|
2198
|
+
resumeRule: "Re-run manager-owned verification after the human step completes before resuming automation."
|
|
2199
|
+
};
|
|
2200
|
+
};
|
|
2201
|
+
|
|
1986
2202
|
// src/challenges/optional-computer-use-bridge.ts
|
|
1987
2203
|
var OPTIONAL_BRIDGE_SUGGESTION_REASON = "Optional bridge suggested a browser-scoped click follow-up from canonical evidence.";
|
|
1988
2204
|
var buildComputerUseSuggestions = (bundle, maxSuggestions) => {
|
|
@@ -2027,907 +2243,955 @@ var suggestComputerUseActions = (args) => {
|
|
|
2027
2243
|
};
|
|
2028
2244
|
};
|
|
2029
2245
|
|
|
2030
|
-
// src/challenges/
|
|
2031
|
-
var
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2246
|
+
// src/challenges/policy-gate.ts
|
|
2247
|
+
var ALL_ACTIONS = [
|
|
2248
|
+
"wait",
|
|
2249
|
+
"auth_navigation",
|
|
2250
|
+
"session_reuse",
|
|
2251
|
+
"cookie_reuse",
|
|
2252
|
+
"element_discovery",
|
|
2253
|
+
"click_path",
|
|
2254
|
+
"click_and_hold",
|
|
2255
|
+
"non_secret_form_fill",
|
|
2256
|
+
"dropdown",
|
|
2257
|
+
"scroll",
|
|
2258
|
+
"hover",
|
|
2259
|
+
"press",
|
|
2260
|
+
"pointer",
|
|
2261
|
+
"drag",
|
|
2262
|
+
"verification",
|
|
2263
|
+
"debug_trace"
|
|
2264
|
+
];
|
|
2265
|
+
var DEFAULT_HANDOFF_TRIGGERS = [
|
|
2266
|
+
"secret_entry",
|
|
2267
|
+
"mfa",
|
|
2268
|
+
"explicit_consent",
|
|
2269
|
+
"policy_blocked",
|
|
2270
|
+
"unsupported_third_party",
|
|
2271
|
+
"exhausted_no_progress"
|
|
2272
|
+
];
|
|
2273
|
+
var buildResolvedPolicy = (mode, source) => {
|
|
2274
|
+
if (mode === "off") {
|
|
2275
|
+
return {
|
|
2276
|
+
mode,
|
|
2277
|
+
source,
|
|
2278
|
+
standDownReason: "challenge_automation_off"
|
|
2279
|
+
};
|
|
2047
2280
|
}
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
for (const [key, value] of entries) {
|
|
2055
|
-
if (SENSITIVE_FIELD_RE.test(key) || SENSITIVE_FIELD_RE.test(name)) {
|
|
2056
|
-
continue;
|
|
2057
|
-
}
|
|
2058
|
-
if (!name.includes(key.toLowerCase())) {
|
|
2059
|
-
continue;
|
|
2060
|
-
}
|
|
2061
|
-
switch (typeof value) {
|
|
2062
|
-
case "string":
|
|
2063
|
-
case "number":
|
|
2064
|
-
case "boolean":
|
|
2065
|
-
return String(value);
|
|
2066
|
-
default:
|
|
2067
|
-
break;
|
|
2068
|
-
}
|
|
2281
|
+
if (mode === "browser") {
|
|
2282
|
+
return {
|
|
2283
|
+
mode,
|
|
2284
|
+
source,
|
|
2285
|
+
standDownReason: "helper_disabled_for_browser_mode"
|
|
2286
|
+
};
|
|
2069
2287
|
}
|
|
2070
|
-
return
|
|
2071
|
-
};
|
|
2072
|
-
var nextUnusedRef = (refs, steps, kind) => {
|
|
2073
|
-
return refs.find((ref) => !hasExecuted(steps, kind, ref));
|
|
2288
|
+
return { mode, source };
|
|
2074
2289
|
};
|
|
2075
|
-
var
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
return void 0;
|
|
2079
|
-
}
|
|
2080
|
-
if (interaction.preferredAction === "click" && decision.allowedActionFamilies.includes("click_path")) {
|
|
2081
|
-
const clickRef = nextUnusedRef(interaction.clickRefs, executedSteps, "click");
|
|
2082
|
-
if (clickRef) {
|
|
2083
|
-
return {
|
|
2084
|
-
kind: "click",
|
|
2085
|
-
ref: clickRef,
|
|
2086
|
-
reason: "Visible popup or interstitial exposes a bounded click path."
|
|
2087
|
-
};
|
|
2088
|
-
}
|
|
2290
|
+
var resolveChallengeAutomationPolicy = (args) => {
|
|
2291
|
+
if (args.runMode) {
|
|
2292
|
+
return buildResolvedPolicy(args.runMode, "run");
|
|
2089
2293
|
}
|
|
2090
|
-
if (
|
|
2091
|
-
|
|
2092
|
-
if (holdRef || !hasExecuted(executedSteps, "click_and_hold")) {
|
|
2093
|
-
return {
|
|
2094
|
-
kind: "click_and_hold",
|
|
2095
|
-
...holdRef ? { ref: holdRef } : {},
|
|
2096
|
-
...typeof interaction.holdMs === "number" ? { holdMs: interaction.holdMs } : {},
|
|
2097
|
-
reason: "Visible challenge requests a bounded click-and-hold gesture."
|
|
2098
|
-
};
|
|
2099
|
-
}
|
|
2294
|
+
if (args.sessionMode) {
|
|
2295
|
+
return buildResolvedPolicy(args.sessionMode, "session");
|
|
2100
2296
|
}
|
|
2101
|
-
|
|
2102
|
-
return {
|
|
2103
|
-
kind: "drag",
|
|
2104
|
-
...interaction.dragRefs[0] ? { ref: interaction.dragRefs[0] } : {},
|
|
2105
|
-
coordinates: { x: 640, y: 360 },
|
|
2106
|
-
reason: "Visible challenge requests a bounded drag gesture."
|
|
2107
|
-
};
|
|
2108
|
-
}
|
|
2109
|
-
return void 0;
|
|
2297
|
+
return buildResolvedPolicy(args.configMode, "config");
|
|
2110
2298
|
};
|
|
2111
|
-
var
|
|
2112
|
-
|
|
2113
|
-
if (sessionRef) {
|
|
2299
|
+
var resolveHelperEligibility = (config, policy) => {
|
|
2300
|
+
if (policy.mode === "off") {
|
|
2114
2301
|
return {
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2302
|
+
allowed: false,
|
|
2303
|
+
reason: "Challenge automation mode is off; detection and reporting remain active.",
|
|
2304
|
+
standDownReason: "challenge_automation_off"
|
|
2118
2305
|
};
|
|
2119
2306
|
}
|
|
2120
|
-
|
|
2121
|
-
if (decision.allowedActionFamilies.includes("auth_navigation") && loginRef) {
|
|
2307
|
+
if (policy.mode === "browser") {
|
|
2122
2308
|
return {
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2309
|
+
allowed: false,
|
|
2310
|
+
reason: "Browser mode keeps the optional helper bridge disabled.",
|
|
2311
|
+
standDownReason: "helper_disabled_for_browser_mode"
|
|
2126
2312
|
};
|
|
2127
2313
|
}
|
|
2128
|
-
if (
|
|
2129
|
-
const loginUrl = deriveAuthUrls(bundle.url).find((candidate) => !hasExecuted(executedSteps, "goto", void 0, candidate));
|
|
2130
|
-
if (loginUrl) {
|
|
2131
|
-
return {
|
|
2132
|
-
kind: "goto",
|
|
2133
|
-
url: loginUrl,
|
|
2134
|
-
reason: "Try a conventional auth-navigation URL on the current origin."
|
|
2135
|
-
};
|
|
2136
|
-
}
|
|
2137
|
-
}
|
|
2138
|
-
const fieldRef = nextUnusedRef(bundle.continuity.nonSecretFieldRefs, executedSteps, "type");
|
|
2139
|
-
const fieldValue = fieldRef ? resolveTaskValue(bundle, fieldRef) : void 0;
|
|
2140
|
-
if (decision.allowedActionFamilies.includes("non_secret_form_fill") && fieldRef && fieldValue) {
|
|
2314
|
+
if (!config.optionalComputerUseBridge.enabled) {
|
|
2141
2315
|
return {
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
reason: "Fill a non-secret field from caller-provided task data."
|
|
2316
|
+
allowed: false,
|
|
2317
|
+
reason: "Optional computer-use bridge is disabled by policy.",
|
|
2318
|
+
standDownReason: "helper_disabled_by_policy"
|
|
2146
2319
|
};
|
|
2147
2320
|
}
|
|
2148
|
-
|
|
2149
|
-
|
|
2321
|
+
return {
|
|
2322
|
+
allowed: true,
|
|
2323
|
+
reason: "Optional helper bridge remains eligible after mode resolution."
|
|
2324
|
+
};
|
|
2325
|
+
};
|
|
2326
|
+
var buildChallengePolicyGate = (config, interpretation, resolvedPolicy = resolveChallengeAutomationPolicy({
|
|
2327
|
+
configMode: config.mode
|
|
2328
|
+
})) => {
|
|
2329
|
+
const helperEligibility = resolveHelperEligibility(config, resolvedPolicy);
|
|
2330
|
+
if (resolvedPolicy.mode === "off") {
|
|
2150
2331
|
return {
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2332
|
+
resolvedPolicy,
|
|
2333
|
+
allowedActions: [],
|
|
2334
|
+
forbiddenActions: [...ALL_ACTIONS],
|
|
2335
|
+
handoffTriggers: [...DEFAULT_HANDOFF_TRIGGERS],
|
|
2336
|
+
governedLanes: [],
|
|
2337
|
+
optionalComputerUseBridge: false,
|
|
2338
|
+
helperEligibility
|
|
2154
2339
|
};
|
|
2155
2340
|
}
|
|
2156
|
-
const
|
|
2157
|
-
if (
|
|
2158
|
-
|
|
2159
|
-
kind: "hover",
|
|
2160
|
-
ref: hoverRef,
|
|
2161
|
-
reason: "Hover a likely action target to reveal hidden menus or session pickers."
|
|
2162
|
-
};
|
|
2341
|
+
const allowed = /* @__PURE__ */ new Set(["wait", "verification", "debug_trace"]);
|
|
2342
|
+
if (config.allowAuthNavigation) {
|
|
2343
|
+
allowed.add("auth_navigation");
|
|
2163
2344
|
}
|
|
2164
|
-
if (
|
|
2165
|
-
|
|
2166
|
-
kind: "scroll",
|
|
2167
|
-
dy: 900,
|
|
2168
|
-
reason: "Scroll down to uncover the next actionable region."
|
|
2169
|
-
};
|
|
2345
|
+
if (config.allowSessionReuse) {
|
|
2346
|
+
allowed.add("session_reuse");
|
|
2170
2347
|
}
|
|
2171
|
-
if (
|
|
2172
|
-
|
|
2173
|
-
kind: "scroll",
|
|
2174
|
-
dy: -450,
|
|
2175
|
-
reason: "Scroll back up to re-evaluate the visible challenge state."
|
|
2176
|
-
};
|
|
2348
|
+
if (config.allowCookieReuse) {
|
|
2349
|
+
allowed.add("cookie_reuse");
|
|
2177
2350
|
}
|
|
2178
|
-
if (
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
text: "Tab",
|
|
2182
|
-
reason: "Advance focus through the challenge surface."
|
|
2183
|
-
};
|
|
2351
|
+
if (config.allowNonSecretFormFill) {
|
|
2352
|
+
allowed.add("non_secret_form_fill");
|
|
2353
|
+
allowed.add("dropdown");
|
|
2184
2354
|
}
|
|
2185
|
-
if (
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2355
|
+
if (config.allowInteractionExploration) {
|
|
2356
|
+
allowed.add("element_discovery");
|
|
2357
|
+
allowed.add("click_path");
|
|
2358
|
+
allowed.add("click_and_hold");
|
|
2359
|
+
allowed.add("scroll");
|
|
2360
|
+
allowed.add("hover");
|
|
2361
|
+
allowed.add("press");
|
|
2362
|
+
allowed.add("pointer");
|
|
2363
|
+
allowed.add("drag");
|
|
2191
2364
|
}
|
|
2192
|
-
if (
|
|
2193
|
-
|
|
2194
|
-
kind: "drag",
|
|
2195
|
-
coordinates: { x: 640, y: 360 },
|
|
2196
|
-
reason: "Attempt one bounded vertical drag across the visible surface."
|
|
2197
|
-
};
|
|
2365
|
+
if (interpretation.humanBoundary === "secret_entry" || interpretation.humanBoundary === "mfa") {
|
|
2366
|
+
allowed.delete("non_secret_form_fill");
|
|
2198
2367
|
}
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
reason: "Give the page a short bounded settle window before yielding."
|
|
2203
|
-
};
|
|
2368
|
+
const governedLanes = [];
|
|
2369
|
+
if (config.governed.allowOwnedEnvironmentFixtures) {
|
|
2370
|
+
governedLanes.push("owned_environment_fixture");
|
|
2204
2371
|
}
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
var resolveStepPoint = async (args) => {
|
|
2208
|
-
if (!args.step.ref) {
|
|
2209
|
-
return args.step.coordinates ?? args.fallback;
|
|
2372
|
+
if (config.governed.allowSanctionedIdentity) {
|
|
2373
|
+
governedLanes.push("sanctioned_identity");
|
|
2210
2374
|
}
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
var executeStep = async (args) => {
|
|
2214
|
-
const timeoutMs = args.config.stepTimeoutMs;
|
|
2215
|
-
switch (args.step.kind) {
|
|
2216
|
-
case "goto":
|
|
2217
|
-
if (args.step.url) {
|
|
2218
|
-
await args.handle.goto(args.sessionId, args.step.url, "domcontentloaded", timeoutMs, void 0, args.targetId);
|
|
2219
|
-
}
|
|
2220
|
-
return;
|
|
2221
|
-
case "click":
|
|
2222
|
-
if (args.step.ref) {
|
|
2223
|
-
await args.handle.click(args.sessionId, args.step.ref, args.targetId);
|
|
2224
|
-
}
|
|
2225
|
-
return;
|
|
2226
|
-
case "click_and_hold": {
|
|
2227
|
-
const point = await resolveStepPoint({
|
|
2228
|
-
handle: args.handle,
|
|
2229
|
-
sessionId: args.sessionId,
|
|
2230
|
-
step: args.step,
|
|
2231
|
-
targetId: args.targetId,
|
|
2232
|
-
fallback: { x: 640, y: 360 }
|
|
2233
|
-
});
|
|
2234
|
-
await args.handle.pointerMove(args.sessionId, point.x, point.y, args.targetId, 12);
|
|
2235
|
-
await args.handle.pointerDown(args.sessionId, point.x, point.y, args.targetId, "left", 1);
|
|
2236
|
-
await new Promise((resolve2) => setTimeout(resolve2, Math.max(250, args.step.holdMs ?? DEFAULT_HOLD_MS2)));
|
|
2237
|
-
await args.handle.pointerUp(args.sessionId, point.x, point.y, args.targetId, "left", 1);
|
|
2238
|
-
return;
|
|
2239
|
-
}
|
|
2240
|
-
case "hover":
|
|
2241
|
-
if (args.step.ref) {
|
|
2242
|
-
await args.handle.hover(args.sessionId, args.step.ref, args.targetId);
|
|
2243
|
-
}
|
|
2244
|
-
return;
|
|
2245
|
-
case "press":
|
|
2246
|
-
await args.handle.press(args.sessionId, args.step.text ?? "Tab", void 0, args.targetId);
|
|
2247
|
-
return;
|
|
2248
|
-
case "type":
|
|
2249
|
-
if (args.step.ref && typeof args.step.text === "string") {
|
|
2250
|
-
await args.handle.type(args.sessionId, args.step.ref, args.step.text, true, false, args.targetId);
|
|
2251
|
-
}
|
|
2252
|
-
return;
|
|
2253
|
-
case "select":
|
|
2254
|
-
if (args.step.ref && args.step.values?.length) {
|
|
2255
|
-
await args.handle.select(args.sessionId, args.step.ref, args.step.values, args.targetId);
|
|
2256
|
-
}
|
|
2257
|
-
return;
|
|
2258
|
-
case "scroll":
|
|
2259
|
-
await args.handle.scroll(args.sessionId, args.step.dy ?? 600, void 0, args.targetId);
|
|
2260
|
-
return;
|
|
2261
|
-
case "pointer":
|
|
2262
|
-
await args.handle.pointerMove(
|
|
2263
|
-
args.sessionId,
|
|
2264
|
-
args.step.coordinates?.x ?? 640,
|
|
2265
|
-
args.step.coordinates?.y ?? 360,
|
|
2266
|
-
args.targetId,
|
|
2267
|
-
12
|
|
2268
|
-
);
|
|
2269
|
-
return;
|
|
2270
|
-
case "drag":
|
|
2271
|
-
{
|
|
2272
|
-
const point = await resolveStepPoint({
|
|
2273
|
-
handle: args.handle,
|
|
2274
|
-
sessionId: args.sessionId,
|
|
2275
|
-
step: args.step,
|
|
2276
|
-
targetId: args.targetId,
|
|
2277
|
-
fallback: args.step.coordinates ?? { x: 640, y: 360 }
|
|
2278
|
-
});
|
|
2279
|
-
await args.handle.drag(
|
|
2280
|
-
args.sessionId,
|
|
2281
|
-
point,
|
|
2282
|
-
{
|
|
2283
|
-
x: point.x,
|
|
2284
|
-
y: point.y + 260
|
|
2285
|
-
},
|
|
2286
|
-
args.targetId,
|
|
2287
|
-
16
|
|
2288
|
-
);
|
|
2289
|
-
}
|
|
2290
|
-
return;
|
|
2291
|
-
case "cookie_list":
|
|
2292
|
-
await args.handle.cookieList(args.sessionId, args.step.url ? [args.step.url] : void 0);
|
|
2293
|
-
return;
|
|
2294
|
-
case "cookie_import":
|
|
2295
|
-
await args.handle.cookieImport(args.sessionId, args.step.cookies ?? [], true);
|
|
2296
|
-
return;
|
|
2297
|
-
case "snapshot":
|
|
2298
|
-
await args.handle.snapshot(
|
|
2299
|
-
args.sessionId,
|
|
2300
|
-
"actionables",
|
|
2301
|
-
args.step.snapshotChars ?? 2400,
|
|
2302
|
-
void 0,
|
|
2303
|
-
args.targetId
|
|
2304
|
-
);
|
|
2305
|
-
return;
|
|
2306
|
-
case "debug_trace":
|
|
2307
|
-
await args.handle.debugTraceSnapshot(args.sessionId, { max: args.step.traceMax ?? 50 });
|
|
2308
|
-
return;
|
|
2309
|
-
case "wait":
|
|
2310
|
-
await args.handle.waitForLoad(args.sessionId, "networkidle", Math.min(timeoutMs, 3e3), args.targetId);
|
|
2311
|
-
return;
|
|
2312
|
-
default:
|
|
2313
|
-
return;
|
|
2375
|
+
if (config.governed.allowServiceAdapters) {
|
|
2376
|
+
governedLanes.push("service_adapter");
|
|
2314
2377
|
}
|
|
2378
|
+
return {
|
|
2379
|
+
resolvedPolicy,
|
|
2380
|
+
allowedActions: ALL_ACTIONS.filter((action) => allowed.has(action)),
|
|
2381
|
+
forbiddenActions: ALL_ACTIONS.filter((action) => !allowed.has(action)),
|
|
2382
|
+
handoffTriggers: [...DEFAULT_HANDOFF_TRIGGERS],
|
|
2383
|
+
governedLanes,
|
|
2384
|
+
optionalComputerUseBridge: helperEligibility.allowed,
|
|
2385
|
+
helperEligibility
|
|
2386
|
+
};
|
|
2315
2387
|
};
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2388
|
+
|
|
2389
|
+
// src/challenges/strategy-selector.ts
|
|
2390
|
+
var buildDecision = (config, lane, rationale, allowedActionFamilies, verificationLevel, stopConditions, governedLane) => ({
|
|
2391
|
+
lane,
|
|
2392
|
+
...governedLane ? { governedLane } : {},
|
|
2393
|
+
rationale,
|
|
2394
|
+
attemptBudget: config.attemptBudget,
|
|
2395
|
+
noProgressLimit: config.noProgressLimit,
|
|
2396
|
+
verificationLevel,
|
|
2397
|
+
stopConditions,
|
|
2398
|
+
allowedActionFamilies: [...allowedActionFamilies]
|
|
2399
|
+
});
|
|
2400
|
+
var selectChallengeStrategy = (args) => {
|
|
2401
|
+
const { config, bundle, capabilityMatrix, gate, interpretation } = args;
|
|
2402
|
+
const registryCooldownActive = (bundle.registryPressure?.cooldownUntilMs ?? 0) > Date.now();
|
|
2403
|
+
const registryPressureElevated = (bundle.registryPressure?.activeChallenges ?? 0) > 0 || (bundle.registryPressure?.recentChallengeRatio ?? 0) >= 0.5 || (bundle.registryPressure?.recentRateLimitRatio ?? 0) >= 0.5;
|
|
2404
|
+
const stopConditions = [
|
|
2405
|
+
"manager_verification_clears_blocker",
|
|
2406
|
+
"policy_gate_denies_next_action",
|
|
2407
|
+
"human_boundary_detected",
|
|
2408
|
+
"no_progress_budget_exhausted"
|
|
2409
|
+
];
|
|
2410
|
+
const { mode, standDownReason } = gate.resolvedPolicy;
|
|
2411
|
+
if (mode === "off") {
|
|
2412
|
+
return buildDecision(
|
|
2413
|
+
config,
|
|
2414
|
+
"defer",
|
|
2415
|
+
"Challenge automation mode is off; challenge handling is detect-and-report only.",
|
|
2416
|
+
[],
|
|
2417
|
+
"light",
|
|
2418
|
+
[standDownReason ?? "challenge_automation_off"]
|
|
2419
|
+
);
|
|
2420
|
+
}
|
|
2421
|
+
if (capabilityMatrix.mustDefer) {
|
|
2422
|
+
return buildDecision(
|
|
2423
|
+
config,
|
|
2424
|
+
"defer",
|
|
2425
|
+
"Current policy or blocker state requires deferral before further automation.",
|
|
2426
|
+
gate.allowedActions,
|
|
2427
|
+
interpretation.requiredVerification,
|
|
2428
|
+
["policy_blocked_or_clear_state"]
|
|
2429
|
+
);
|
|
2430
|
+
}
|
|
2431
|
+
if (registryCooldownActive && !capabilityMatrix.canReuseExistingSession && !capabilityMatrix.canReuseCookies && !capabilityMatrix.canNavigateToAuth) {
|
|
2432
|
+
return buildDecision(
|
|
2433
|
+
config,
|
|
2434
|
+
"defer",
|
|
2435
|
+
"Registry cooldown is still active and no legitimate continuity or auth-navigation lane is currently available.",
|
|
2436
|
+
gate.allowedActions,
|
|
2437
|
+
interpretation.requiredVerification,
|
|
2438
|
+
["registry_cooldown_active"]
|
|
2439
|
+
);
|
|
2440
|
+
}
|
|
2441
|
+
if (capabilityMatrix.canUseOwnedEnvironmentFixture) {
|
|
2442
|
+
return buildDecision(
|
|
2443
|
+
config,
|
|
2444
|
+
"owned_environment_fixture",
|
|
2445
|
+
"Owned-environment fixture detected and explicitly allowlisted.",
|
|
2446
|
+
gate.allowedActions,
|
|
2447
|
+
interpretation.requiredVerification,
|
|
2448
|
+
stopConditions,
|
|
2449
|
+
"owned_environment_fixture"
|
|
2450
|
+
);
|
|
2451
|
+
}
|
|
2452
|
+
if (capabilityMatrix.mustYield) {
|
|
2453
|
+
return buildDecision(
|
|
2454
|
+
config,
|
|
2455
|
+
"human_yield",
|
|
2456
|
+
`Human authority boundary reached: ${interpretation.humanBoundary}.`,
|
|
2457
|
+
gate.allowedActions,
|
|
2458
|
+
interpretation.requiredVerification,
|
|
2459
|
+
[...stopConditions, "human_authority_required"]
|
|
2460
|
+
);
|
|
2461
|
+
}
|
|
2462
|
+
if (capabilityMatrix.canNavigateToAuth || capabilityMatrix.canReuseExistingSession || capabilityMatrix.canReuseCookies || capabilityMatrix.canFillNonSecretFields || capabilityMatrix.canExploreClicks) {
|
|
2463
|
+
return buildDecision(
|
|
2464
|
+
config,
|
|
2465
|
+
"generic_browser_autonomy",
|
|
2466
|
+
registryPressureElevated ? "Registry pressure is elevated, but legitimate browser continuity remains available for one bounded generic autonomy pass." : "Existing browser controls can attempt bounded auth navigation, session reuse, non-secret fill, or interaction exploration.",
|
|
2467
|
+
gate.allowedActions,
|
|
2468
|
+
interpretation.requiredVerification,
|
|
2469
|
+
registryPressureElevated ? [...stopConditions, "registry_pressure_elevated"] : stopConditions
|
|
2470
|
+
);
|
|
2471
|
+
}
|
|
2472
|
+
if (capabilityMatrix.canUseComputerUseBridge) {
|
|
2473
|
+
return buildDecision(
|
|
2474
|
+
config,
|
|
2475
|
+
"optional_computer_use_bridge",
|
|
2476
|
+
"DOM-native autonomy is exhausted, but the optional browser-scoped bridge is enabled.",
|
|
2477
|
+
gate.allowedActions,
|
|
2478
|
+
interpretation.requiredVerification,
|
|
2479
|
+
stopConditions
|
|
2480
|
+
);
|
|
2481
|
+
}
|
|
2482
|
+
if (capabilityMatrix.canUseSanctionedIdentity) {
|
|
2483
|
+
return buildDecision(
|
|
2484
|
+
config,
|
|
2485
|
+
"sanctioned_identity",
|
|
2486
|
+
"Sanctioned identity lane is enabled and generic browser autonomy is insufficient.",
|
|
2487
|
+
gate.allowedActions,
|
|
2488
|
+
interpretation.requiredVerification,
|
|
2489
|
+
stopConditions,
|
|
2490
|
+
"sanctioned_identity"
|
|
2491
|
+
);
|
|
2492
|
+
}
|
|
2493
|
+
if (capabilityMatrix.canUseServiceAdapter) {
|
|
2494
|
+
return buildDecision(
|
|
2495
|
+
config,
|
|
2496
|
+
"service_adapter",
|
|
2497
|
+
"Governed service-adapter lane is enabled as the last non-human option.",
|
|
2498
|
+
gate.allowedActions,
|
|
2499
|
+
interpretation.requiredVerification,
|
|
2500
|
+
stopConditions,
|
|
2501
|
+
"service_adapter"
|
|
2502
|
+
);
|
|
2503
|
+
}
|
|
2504
|
+
return buildDecision(
|
|
2505
|
+
config,
|
|
2506
|
+
"human_yield",
|
|
2507
|
+
`No legitimate autonomous lane remains after applying policy and continuity checks. ${capabilityMatrix.helperEligibility.reason}`,
|
|
2508
|
+
gate.allowedActions,
|
|
2509
|
+
interpretation.requiredVerification,
|
|
2510
|
+
[...stopConditions, "no_legitimate_lane_remaining"]
|
|
2511
|
+
);
|
|
2512
|
+
};
|
|
2513
|
+
|
|
2514
|
+
// src/challenges/inspect-plan.ts
|
|
2515
|
+
var SENSITIVE_FIELD_RE = /\b(password|passcode|secret|otp|mfa|token|verification code|passkey)\b/i;
|
|
2516
|
+
var hasExecuted = (steps, kind, ref, url) => {
|
|
2517
|
+
return steps.some((step) => step.kind === kind && step.ref === ref && step.url === url);
|
|
2518
|
+
};
|
|
2519
|
+
var getActionable = (bundle, ref) => {
|
|
2520
|
+
return bundle.actionables.find((entry) => entry.ref === ref);
|
|
2521
|
+
};
|
|
2522
|
+
var deriveAuthUrls = (url) => {
|
|
2523
|
+
if (!url) {
|
|
2524
|
+
return [];
|
|
2525
|
+
}
|
|
2526
|
+
try {
|
|
2527
|
+
const current = new URL(url);
|
|
2528
|
+
const candidates = [
|
|
2529
|
+
"/login",
|
|
2530
|
+
"/signin",
|
|
2531
|
+
"/sign-in",
|
|
2532
|
+
"/account/login",
|
|
2533
|
+
"/session",
|
|
2534
|
+
"/auth/login"
|
|
2535
|
+
];
|
|
2536
|
+
return candidates.map((path2) => new URL(path2, current.origin).toString());
|
|
2537
|
+
} catch {
|
|
2538
|
+
return [];
|
|
2539
|
+
}
|
|
2540
|
+
};
|
|
2541
|
+
var resolveTaskValue = (bundle, ref) => {
|
|
2542
|
+
const actionable = getActionable(bundle, ref);
|
|
2543
|
+
const name = actionable?.name?.toLowerCase();
|
|
2544
|
+
if (!name || !bundle.taskData) {
|
|
2545
|
+
return void 0;
|
|
2546
|
+
}
|
|
2547
|
+
for (const [key, value] of Object.entries(bundle.taskData)) {
|
|
2548
|
+
if (SENSITIVE_FIELD_RE.test(key) || SENSITIVE_FIELD_RE.test(name)) {
|
|
2549
|
+
continue;
|
|
2361
2550
|
}
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
reusedExistingSession = true;
|
|
2551
|
+
if (!name.includes(key.toLowerCase())) {
|
|
2552
|
+
continue;
|
|
2365
2553
|
}
|
|
2366
|
-
if (
|
|
2367
|
-
|
|
2554
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
2555
|
+
return String(value);
|
|
2368
2556
|
}
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2557
|
+
}
|
|
2558
|
+
return void 0;
|
|
2559
|
+
};
|
|
2560
|
+
var nextUnusedRef = (refs, steps, kind) => {
|
|
2561
|
+
return refs.find((ref) => !hasExecuted(steps, kind, ref));
|
|
2562
|
+
};
|
|
2563
|
+
var planInteractionStep = (bundle, decision, executedSteps) => {
|
|
2564
|
+
const interaction = bundle.interaction;
|
|
2565
|
+
if (!interaction || interaction.preferredAction === "unknown") {
|
|
2566
|
+
return void 0;
|
|
2567
|
+
}
|
|
2568
|
+
if (interaction.preferredAction === "click" && decision.allowedActionFamilies.includes("click_path")) {
|
|
2569
|
+
const clickRef = nextUnusedRef(interaction.clickRefs, executedSteps, "click");
|
|
2570
|
+
if (clickRef) {
|
|
2382
2571
|
return {
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
executedSteps,
|
|
2387
|
-
verification,
|
|
2388
|
-
reusedExistingSession,
|
|
2389
|
-
reusedCookies
|
|
2572
|
+
kind: "click",
|
|
2573
|
+
ref: clickRef,
|
|
2574
|
+
reason: "Visible popup or interstitial exposes a bounded click path."
|
|
2390
2575
|
};
|
|
2391
2576
|
}
|
|
2392
|
-
|
|
2577
|
+
}
|
|
2578
|
+
if (interaction.preferredAction === "click_and_hold" && decision.allowedActionFamilies.includes("click_and_hold")) {
|
|
2579
|
+
const holdRef = nextUnusedRef(interaction.holdRefs, executedSteps, "click_and_hold");
|
|
2580
|
+
if (holdRef || !hasExecuted(executedSteps, "click_and_hold")) {
|
|
2393
2581
|
return {
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
verification,
|
|
2399
|
-
reusedExistingSession,
|
|
2400
|
-
reusedCookies
|
|
2582
|
+
kind: "click_and_hold",
|
|
2583
|
+
...holdRef ? { ref: holdRef } : {},
|
|
2584
|
+
...typeof interaction.holdMs === "number" ? { holdMs: interaction.holdMs } : {},
|
|
2585
|
+
reason: "Visible challenge requests a bounded click-and-hold gesture."
|
|
2401
2586
|
};
|
|
2402
2587
|
}
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2588
|
+
}
|
|
2589
|
+
if (interaction.preferredAction === "drag" && decision.allowedActionFamilies.includes("drag") && !hasExecuted(executedSteps, "drag")) {
|
|
2590
|
+
return {
|
|
2591
|
+
kind: "drag",
|
|
2592
|
+
...interaction.dragRefs[0] ? { ref: interaction.dragRefs[0] } : {},
|
|
2593
|
+
coordinates: { x: 640, y: 360 },
|
|
2594
|
+
reason: "Visible challenge requests a bounded drag gesture."
|
|
2595
|
+
};
|
|
2596
|
+
}
|
|
2597
|
+
return void 0;
|
|
2598
|
+
};
|
|
2599
|
+
var planGenericStep = (bundle, decision, executedSteps) => {
|
|
2600
|
+
const sessionRef = nextUnusedRef(
|
|
2601
|
+
bundle.continuity.sessionReuseRefs,
|
|
2602
|
+
executedSteps,
|
|
2603
|
+
"click"
|
|
2604
|
+
);
|
|
2605
|
+
if (sessionRef) {
|
|
2606
|
+
return {
|
|
2607
|
+
kind: "click",
|
|
2608
|
+
ref: sessionRef,
|
|
2609
|
+
reason: "Try the existing-session or account-selection path first."
|
|
2610
|
+
};
|
|
2611
|
+
}
|
|
2612
|
+
const loginRef = nextUnusedRef(bundle.continuity.loginRefs, executedSteps, "click");
|
|
2613
|
+
if (decision.allowedActionFamilies.includes("auth_navigation") && loginRef) {
|
|
2614
|
+
return {
|
|
2615
|
+
kind: "click",
|
|
2616
|
+
ref: loginRef,
|
|
2617
|
+
reason: "Try the visible auth-navigation entrypoint."
|
|
2618
|
+
};
|
|
2619
|
+
}
|
|
2620
|
+
if (decision.allowedActionFamilies.includes("auth_navigation")) {
|
|
2621
|
+
const loginUrl = deriveAuthUrls(bundle.url).find((candidate) => {
|
|
2622
|
+
return !hasExecuted(executedSteps, "goto", void 0, candidate);
|
|
2623
|
+
});
|
|
2624
|
+
if (loginUrl) {
|
|
2420
2625
|
return {
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
executedSteps,
|
|
2425
|
-
verification,
|
|
2426
|
-
reusedExistingSession,
|
|
2427
|
-
reusedCookies
|
|
2626
|
+
kind: "goto",
|
|
2627
|
+
url: loginUrl,
|
|
2628
|
+
reason: "Try a conventional auth-navigation URL on the current origin."
|
|
2428
2629
|
};
|
|
2429
2630
|
}
|
|
2430
2631
|
}
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
attempts: args.decision.attemptBudget,
|
|
2434
|
-
noProgressCount,
|
|
2632
|
+
const fieldRef = nextUnusedRef(
|
|
2633
|
+
bundle.continuity.nonSecretFieldRefs,
|
|
2435
2634
|
executedSteps,
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
title: currentBundle.title
|
|
2446
|
-
},
|
|
2447
|
-
reusedExistingSession,
|
|
2448
|
-
reusedCookies
|
|
2449
|
-
};
|
|
2450
|
-
};
|
|
2451
|
-
|
|
2452
|
-
// src/challenges/capability-matrix.ts
|
|
2453
|
-
var buildCapabilityMatrix = (bundle, interpretation, gate) => {
|
|
2454
|
-
const hasActionables = bundle.actionables.length > 0;
|
|
2455
|
-
const helperActionRefs = [
|
|
2456
|
-
...bundle.continuity.loginRefs,
|
|
2457
|
-
...bundle.continuity.sessionReuseRefs,
|
|
2458
|
-
...bundle.continuity.humanVerificationRefs,
|
|
2459
|
-
...bundle.continuity.checkpointRefs,
|
|
2460
|
-
...bundle.interaction?.clickRefs ?? [],
|
|
2461
|
-
...bundle.interaction?.holdRefs ?? [],
|
|
2462
|
-
...bundle.interaction?.dragRefs ?? []
|
|
2463
|
-
];
|
|
2464
|
-
const authLaneRelevant = interpretation.classification === "auth_required" || interpretation.classification === "existing_session_reuse" || bundle.continuity.likelyLoginPage || bundle.continuity.likelySessionPicker;
|
|
2465
|
-
const canNavigateToAuth = gate.allowedActions.includes("auth_navigation") && authLaneRelevant && (bundle.continuity.loginRefs.length > 0 || typeof bundle.url === "string");
|
|
2466
|
-
const canReuseExistingSession = gate.allowedActions.includes("session_reuse") && (bundle.continuity.hasPreservedSession || bundle.continuity.attachedSession || bundle.continuity.sessionReuseRefs.length > 0);
|
|
2467
|
-
const canReuseCookies = gate.allowedActions.includes("cookie_reuse") && authLaneRelevant && (bundle.continuity.canReuseExistingCookies || bundle.continuity.canImportCookies);
|
|
2468
|
-
const canFillNonSecretFields = gate.allowedActions.includes("non_secret_form_fill") && bundle.continuity.hasNonSecretTaskData && bundle.continuity.nonSecretFieldRefs.length > 0;
|
|
2469
|
-
const canExploreClicks = gate.allowedActions.includes("click_path") && (hasActionables || bundle.continuity.loginRefs.length > 0 || bundle.continuity.sessionReuseRefs.length > 0 || bundle.continuity.checkpointRefs.length > 0);
|
|
2470
|
-
const mustYield = interpretation.humanBoundary === "secret_entry" || interpretation.humanBoundary === "mfa" || interpretation.humanBoundary === "explicit_consent" || interpretation.humanBoundary === "exhausted_no_progress";
|
|
2471
|
-
const mustDefer = interpretation.humanBoundary === "policy_blocked" || !bundle.blocker && bundle.blockerState === "clear";
|
|
2472
|
-
let helperEligibility = gate.helperEligibility ?? (gate.optionalComputerUseBridge ? {
|
|
2473
|
-
allowed: true,
|
|
2474
|
-
reason: "Optional helper bridge remains eligible after policy resolution."
|
|
2475
|
-
} : {
|
|
2476
|
-
allowed: false,
|
|
2477
|
-
reason: "Optional computer-use bridge is disabled by policy.",
|
|
2478
|
-
standDownReason: "helper_disabled_by_policy"
|
|
2479
|
-
});
|
|
2480
|
-
if (helperEligibility.allowed && interpretation.humanBoundary !== "none") {
|
|
2481
|
-
helperEligibility = {
|
|
2482
|
-
allowed: false,
|
|
2483
|
-
reason: `Helper bridge is blocked by human boundary: ${interpretation.humanBoundary}.`,
|
|
2484
|
-
standDownReason: "helper_blocked_by_human_boundary"
|
|
2635
|
+
"type"
|
|
2636
|
+
);
|
|
2637
|
+
const fieldValue = fieldRef ? resolveTaskValue(bundle, fieldRef) : void 0;
|
|
2638
|
+
if (decision.allowedActionFamilies.includes("non_secret_form_fill") && fieldRef && fieldValue) {
|
|
2639
|
+
return {
|
|
2640
|
+
kind: "type",
|
|
2641
|
+
ref: fieldRef,
|
|
2642
|
+
text: fieldValue,
|
|
2643
|
+
reason: "Fill a non-secret field from caller-provided task data."
|
|
2485
2644
|
};
|
|
2486
|
-
}
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2645
|
+
}
|
|
2646
|
+
const checkpointRef = nextUnusedRef(
|
|
2647
|
+
bundle.continuity.checkpointRefs,
|
|
2648
|
+
executedSteps,
|
|
2649
|
+
"click"
|
|
2650
|
+
);
|
|
2651
|
+
if (decision.allowedActionFamilies.includes("click_path") && checkpointRef) {
|
|
2652
|
+
return {
|
|
2653
|
+
kind: "click",
|
|
2654
|
+
ref: checkpointRef,
|
|
2655
|
+
reason: "Try the next visible checkpoint or continue action."
|
|
2491
2656
|
};
|
|
2492
2657
|
}
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2658
|
+
const hoverRef = nextUnusedRef(
|
|
2659
|
+
[...bundle.continuity.loginRefs, ...bundle.continuity.checkpointRefs],
|
|
2660
|
+
executedSteps,
|
|
2661
|
+
"hover"
|
|
2662
|
+
);
|
|
2663
|
+
if (decision.allowedActionFamilies.includes("hover") && hoverRef) {
|
|
2664
|
+
return {
|
|
2665
|
+
kind: "hover",
|
|
2666
|
+
ref: hoverRef,
|
|
2667
|
+
reason: "Hover a likely action target to reveal hidden menus or session pickers."
|
|
2668
|
+
};
|
|
2669
|
+
}
|
|
2670
|
+
if (decision.allowedActionFamilies.includes("scroll") && !hasExecuted(executedSteps, "scroll")) {
|
|
2671
|
+
return {
|
|
2672
|
+
kind: "scroll",
|
|
2673
|
+
dy: 900,
|
|
2674
|
+
reason: "Scroll down to uncover the next actionable region."
|
|
2675
|
+
};
|
|
2676
|
+
}
|
|
2677
|
+
if (decision.allowedActionFamilies.includes("scroll") && executedSteps.filter((step) => step.kind === "scroll").length === 1) {
|
|
2678
|
+
return {
|
|
2679
|
+
kind: "scroll",
|
|
2680
|
+
dy: -450,
|
|
2681
|
+
reason: "Scroll back up to re-evaluate the visible challenge state."
|
|
2682
|
+
};
|
|
2683
|
+
}
|
|
2684
|
+
if (decision.allowedActionFamilies.includes("press") && !hasExecuted(executedSteps, "press")) {
|
|
2685
|
+
return {
|
|
2686
|
+
kind: "press",
|
|
2687
|
+
text: "Tab",
|
|
2688
|
+
reason: "Advance focus through the challenge surface."
|
|
2689
|
+
};
|
|
2690
|
+
}
|
|
2691
|
+
if (decision.allowedActionFamilies.includes("pointer") && !hasExecuted(executedSteps, "pointer")) {
|
|
2692
|
+
return {
|
|
2693
|
+
kind: "pointer",
|
|
2694
|
+
coordinates: { x: 640, y: 360 },
|
|
2695
|
+
reason: "Move the pointer through the center of the current browser surface."
|
|
2696
|
+
};
|
|
2697
|
+
}
|
|
2698
|
+
if (decision.allowedActionFamilies.includes("drag") && !hasExecuted(executedSteps, "drag")) {
|
|
2699
|
+
return {
|
|
2700
|
+
kind: "drag",
|
|
2701
|
+
coordinates: { x: 640, y: 360 },
|
|
2702
|
+
reason: "Attempt one bounded vertical drag across the visible surface."
|
|
2703
|
+
};
|
|
2704
|
+
}
|
|
2705
|
+
if (!hasExecuted(executedSteps, "wait")) {
|
|
2706
|
+
return {
|
|
2707
|
+
kind: "wait",
|
|
2708
|
+
reason: "Give the page a short bounded settle window before yielding."
|
|
2709
|
+
};
|
|
2710
|
+
}
|
|
2711
|
+
return void 0;
|
|
2507
2712
|
};
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2713
|
+
var pendingSteps = (steps, executedSteps) => {
|
|
2714
|
+
return (steps ?? []).filter((step) => {
|
|
2715
|
+
return !hasExecuted(executedSteps, step.kind, step.ref, step.url);
|
|
2716
|
+
});
|
|
2717
|
+
};
|
|
2718
|
+
var dedupeSteps = (steps) => {
|
|
2719
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2720
|
+
return steps.filter((step) => {
|
|
2721
|
+
const key = JSON.stringify([
|
|
2722
|
+
step.kind,
|
|
2723
|
+
step.ref ?? null,
|
|
2724
|
+
step.url ?? null,
|
|
2725
|
+
step.text ?? null,
|
|
2726
|
+
step.reason
|
|
2727
|
+
]);
|
|
2728
|
+
if (seen.has(key)) {
|
|
2729
|
+
return false;
|
|
2520
2730
|
}
|
|
2521
|
-
|
|
2731
|
+
seen.add(key);
|
|
2732
|
+
return true;
|
|
2733
|
+
});
|
|
2522
2734
|
};
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2735
|
+
var buildChallengeActionSuggestions = (args) => {
|
|
2736
|
+
const executedSteps = args.executedSteps ?? [];
|
|
2737
|
+
const helper = suggestComputerUseActions({
|
|
2738
|
+
helperEligibility: args.helperEligibility,
|
|
2739
|
+
bundle: args.bundle,
|
|
2740
|
+
maxSuggestions: args.config.optionalComputerUseBridge.maxSuggestions
|
|
2741
|
+
});
|
|
2742
|
+
const preferredSteps = pendingSteps(args.preferredSteps, executedSteps);
|
|
2743
|
+
const interactionStep = planInteractionStep(args.bundle, args.decision, executedSteps);
|
|
2744
|
+
const genericStep = planGenericStep(args.bundle, args.decision, executedSteps);
|
|
2745
|
+
const helperSteps = pendingSteps(helper.suggestedSteps, executedSteps);
|
|
2746
|
+
const suggestedSteps = args.decision.lane === "optional_computer_use_bridge" ? dedupeSteps([...preferredSteps, ...helperSteps]) : dedupeSteps([
|
|
2747
|
+
...preferredSteps,
|
|
2748
|
+
...interactionStep ? [interactionStep] : [],
|
|
2749
|
+
...genericStep ? [genericStep] : [],
|
|
2750
|
+
...helperSteps
|
|
2751
|
+
]);
|
|
2528
2752
|
return {
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
reason: approved ? "Sanctioned identity lane approved by explicit entitlement." : "Sanctioned identity lane requires explicit entitlement metadata.",
|
|
2532
|
-
auditMetadata: {
|
|
2533
|
-
approved,
|
|
2534
|
-
...approved ? { entitlement } : {}
|
|
2535
|
-
}
|
|
2753
|
+
helper,
|
|
2754
|
+
suggestedSteps
|
|
2536
2755
|
};
|
|
2537
2756
|
};
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
const
|
|
2757
|
+
var selectChallengeActionStep = (args) => {
|
|
2758
|
+
return buildChallengeActionSuggestions(args).suggestedSteps[0];
|
|
2759
|
+
};
|
|
2760
|
+
function buildChallengeInspectPlan(args) {
|
|
2761
|
+
const interpretation = interpretChallengeEvidence(args.bundle);
|
|
2762
|
+
const policy = resolveChallengeAutomationPolicy({
|
|
2763
|
+
runMode: args.runMode,
|
|
2764
|
+
sessionMode: args.sessionMode,
|
|
2765
|
+
configMode: args.config.mode
|
|
2766
|
+
});
|
|
2767
|
+
const gate = buildChallengePolicyGate(args.config, interpretation, policy);
|
|
2768
|
+
const capabilityMatrix = buildCapabilityMatrix(args.bundle, interpretation, gate);
|
|
2769
|
+
const decision = selectChallengeStrategy({
|
|
2770
|
+
config: args.config,
|
|
2771
|
+
bundle: args.bundle,
|
|
2772
|
+
interpretation,
|
|
2773
|
+
capabilityMatrix,
|
|
2774
|
+
gate
|
|
2775
|
+
});
|
|
2776
|
+
const actionSuggestions = buildChallengeActionSuggestions({
|
|
2777
|
+
bundle: args.bundle,
|
|
2778
|
+
decision,
|
|
2779
|
+
helperEligibility: capabilityMatrix.helperEligibility,
|
|
2780
|
+
config: args.config,
|
|
2781
|
+
preferredSteps: args.preferredSteps,
|
|
2782
|
+
executedSteps: args.executedSteps
|
|
2783
|
+
});
|
|
2784
|
+
const yieldDecision = shouldYieldToHuman({
|
|
2785
|
+
interpretation,
|
|
2786
|
+
noProgressExhausted: false
|
|
2787
|
+
});
|
|
2788
|
+
const standDownReason = capabilityMatrix.helperEligibility.standDownReason ?? gate.resolvedPolicy.standDownReason ?? actionSuggestions.helper.standDownReason;
|
|
2543
2789
|
return {
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2790
|
+
challengeId: args.bundle.challengeId,
|
|
2791
|
+
...args.bundle.mode ? { sessionMode: args.bundle.mode } : {},
|
|
2792
|
+
classification: interpretation.classification,
|
|
2793
|
+
authState: interpretation.authState,
|
|
2794
|
+
summary: interpretation.summary,
|
|
2795
|
+
mode: gate.resolvedPolicy.mode,
|
|
2796
|
+
source: gate.resolvedPolicy.source,
|
|
2797
|
+
helperEligibility: capabilityMatrix.helperEligibility,
|
|
2798
|
+
...standDownReason ? { standDownReason } : {},
|
|
2799
|
+
yield: {
|
|
2800
|
+
required: yieldDecision.yield,
|
|
2801
|
+
reason: yieldDecision.reason
|
|
2802
|
+
},
|
|
2803
|
+
decision,
|
|
2804
|
+
allowedActionFamilies: gate.allowedActions,
|
|
2805
|
+
forbiddenActionFamilies: gate.forbiddenActions,
|
|
2806
|
+
governedLanes: gate.governedLanes,
|
|
2807
|
+
capabilityMatrix,
|
|
2808
|
+
helper: actionSuggestions.helper,
|
|
2809
|
+
suggestedSteps: actionSuggestions.suggestedSteps,
|
|
2810
|
+
evidence: {
|
|
2811
|
+
blockerState: args.bundle.blockerState,
|
|
2812
|
+
...args.bundle.blocker?.type ? { blockerType: args.bundle.blocker.type } : {},
|
|
2813
|
+
...args.bundle.url ? { url: args.bundle.url } : {},
|
|
2814
|
+
...args.bundle.title ? { title: args.bundle.title } : {},
|
|
2815
|
+
...typeof args.bundle.activeTargetId !== "undefined" ? { activeTargetId: args.bundle.activeTargetId } : {},
|
|
2816
|
+
...args.bundle.snapshotId ? { snapshotId: args.bundle.snapshotId } : {},
|
|
2817
|
+
loginRefs: args.bundle.continuity.loginRefs,
|
|
2818
|
+
sessionReuseRefs: args.bundle.continuity.sessionReuseRefs,
|
|
2819
|
+
humanVerificationRefs: args.bundle.continuity.humanVerificationRefs,
|
|
2820
|
+
checkpointRefs: args.bundle.continuity.checkpointRefs
|
|
2550
2821
|
}
|
|
2551
2822
|
};
|
|
2552
|
-
}
|
|
2823
|
+
}
|
|
2824
|
+
async function inspectChallengePlanFromRuntime(args) {
|
|
2825
|
+
const bundle = await captureChallengeEvidence({
|
|
2826
|
+
handle: args.handle,
|
|
2827
|
+
sessionId: args.sessionId,
|
|
2828
|
+
targetId: args.targetId,
|
|
2829
|
+
canImportCookies: args.canImportCookies ?? true
|
|
2830
|
+
});
|
|
2831
|
+
return buildChallengeInspectPlan({
|
|
2832
|
+
bundle,
|
|
2833
|
+
config: args.config,
|
|
2834
|
+
runMode: args.runMode,
|
|
2835
|
+
sessionMode: args.sessionMode
|
|
2836
|
+
});
|
|
2837
|
+
}
|
|
2553
2838
|
|
|
2554
|
-
// src/challenges/
|
|
2555
|
-
var
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
lane: request.lane,
|
|
2560
|
-
reason: "Challenge automation mode is off.",
|
|
2561
|
-
auditMetadata: {}
|
|
2562
|
-
};
|
|
2839
|
+
// src/challenges/action-loop.ts
|
|
2840
|
+
var DEFAULT_HOLD_MS2 = 1500;
|
|
2841
|
+
var resolveStepPoint = async (args) => {
|
|
2842
|
+
if (!args.step.ref) {
|
|
2843
|
+
return args.step.coordinates ?? args.fallback;
|
|
2563
2844
|
}
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
};
|
|
2845
|
+
return await args.handle.resolveRefPoint(args.sessionId, args.step.ref, args.targetId);
|
|
2846
|
+
};
|
|
2847
|
+
var executeStep = async (args) => {
|
|
2848
|
+
const timeoutMs = args.config.stepTimeoutMs;
|
|
2849
|
+
switch (args.step.kind) {
|
|
2850
|
+
case "goto":
|
|
2851
|
+
if (args.step.url) {
|
|
2852
|
+
await args.handle.goto(args.sessionId, args.step.url, "domcontentloaded", timeoutMs, void 0, args.targetId);
|
|
2573
2853
|
}
|
|
2574
|
-
return
|
|
2575
|
-
case "
|
|
2576
|
-
if (
|
|
2577
|
-
|
|
2578
|
-
status: "blocked",
|
|
2579
|
-
lane: request.lane,
|
|
2580
|
-
reason: "Sanctioned identity is disabled by policy.",
|
|
2581
|
-
auditMetadata: {}
|
|
2582
|
-
};
|
|
2854
|
+
return;
|
|
2855
|
+
case "click":
|
|
2856
|
+
if (args.step.ref) {
|
|
2857
|
+
await args.handle.click(args.sessionId, args.step.ref, args.targetId);
|
|
2583
2858
|
}
|
|
2584
|
-
return
|
|
2585
|
-
case "
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2859
|
+
return;
|
|
2860
|
+
case "click_and_hold": {
|
|
2861
|
+
const point = await resolveStepPoint({
|
|
2862
|
+
handle: args.handle,
|
|
2863
|
+
sessionId: args.sessionId,
|
|
2864
|
+
step: args.step,
|
|
2865
|
+
targetId: args.targetId,
|
|
2866
|
+
fallback: { x: 640, y: 360 }
|
|
2867
|
+
});
|
|
2868
|
+
await args.handle.pointerMove(args.sessionId, point.x, point.y, args.targetId, 12);
|
|
2869
|
+
await args.handle.pointerDown(args.sessionId, point.x, point.y, args.targetId, "left", 1);
|
|
2870
|
+
await new Promise((resolve2) => setTimeout(resolve2, Math.max(250, args.step.holdMs ?? DEFAULT_HOLD_MS2)));
|
|
2871
|
+
await args.handle.pointerUp(args.sessionId, point.x, point.y, args.targetId, "left", 1);
|
|
2872
|
+
return;
|
|
2873
|
+
}
|
|
2874
|
+
case "hover":
|
|
2875
|
+
if (args.step.ref) {
|
|
2876
|
+
await args.handle.hover(args.sessionId, args.step.ref, args.targetId);
|
|
2593
2877
|
}
|
|
2594
|
-
return
|
|
2878
|
+
return;
|
|
2879
|
+
case "press":
|
|
2880
|
+
await args.handle.press(args.sessionId, args.step.text ?? "Tab", void 0, args.targetId);
|
|
2881
|
+
return;
|
|
2882
|
+
case "type":
|
|
2883
|
+
if (args.step.ref && typeof args.step.text === "string") {
|
|
2884
|
+
await args.handle.type(args.sessionId, args.step.ref, args.step.text, true, false, args.targetId);
|
|
2885
|
+
}
|
|
2886
|
+
return;
|
|
2887
|
+
case "select":
|
|
2888
|
+
if (args.step.ref && args.step.values?.length) {
|
|
2889
|
+
await args.handle.select(args.sessionId, args.step.ref, args.step.values, args.targetId);
|
|
2890
|
+
}
|
|
2891
|
+
return;
|
|
2892
|
+
case "scroll":
|
|
2893
|
+
await args.handle.scroll(args.sessionId, args.step.dy ?? 600, void 0, args.targetId);
|
|
2894
|
+
return;
|
|
2895
|
+
case "pointer":
|
|
2896
|
+
await args.handle.pointerMove(
|
|
2897
|
+
args.sessionId,
|
|
2898
|
+
args.step.coordinates?.x ?? 640,
|
|
2899
|
+
args.step.coordinates?.y ?? 360,
|
|
2900
|
+
args.targetId,
|
|
2901
|
+
12
|
|
2902
|
+
);
|
|
2903
|
+
return;
|
|
2904
|
+
case "drag":
|
|
2905
|
+
{
|
|
2906
|
+
const point = await resolveStepPoint({
|
|
2907
|
+
handle: args.handle,
|
|
2908
|
+
sessionId: args.sessionId,
|
|
2909
|
+
step: args.step,
|
|
2910
|
+
targetId: args.targetId,
|
|
2911
|
+
fallback: args.step.coordinates ?? { x: 640, y: 360 }
|
|
2912
|
+
});
|
|
2913
|
+
await args.handle.drag(
|
|
2914
|
+
args.sessionId,
|
|
2915
|
+
point,
|
|
2916
|
+
{
|
|
2917
|
+
x: point.x,
|
|
2918
|
+
y: point.y + 260
|
|
2919
|
+
},
|
|
2920
|
+
args.targetId,
|
|
2921
|
+
16
|
|
2922
|
+
);
|
|
2923
|
+
}
|
|
2924
|
+
return;
|
|
2925
|
+
case "cookie_list":
|
|
2926
|
+
await args.handle.cookieList(args.sessionId, args.step.url ? [args.step.url] : void 0);
|
|
2927
|
+
return;
|
|
2928
|
+
case "cookie_import":
|
|
2929
|
+
await args.handle.cookieImport(args.sessionId, args.step.cookies ?? [], true);
|
|
2930
|
+
return;
|
|
2931
|
+
case "snapshot":
|
|
2932
|
+
await args.handle.snapshot(
|
|
2933
|
+
args.sessionId,
|
|
2934
|
+
"actionables",
|
|
2935
|
+
args.step.snapshotChars ?? 2400,
|
|
2936
|
+
void 0,
|
|
2937
|
+
args.targetId
|
|
2938
|
+
);
|
|
2939
|
+
return;
|
|
2940
|
+
case "debug_trace":
|
|
2941
|
+
await args.handle.debugTraceSnapshot(args.sessionId, { max: args.step.traceMax ?? 50 });
|
|
2942
|
+
return;
|
|
2943
|
+
case "wait":
|
|
2944
|
+
await args.handle.waitForLoad(args.sessionId, "networkidle", Math.min(timeoutMs, 3e3), args.targetId);
|
|
2945
|
+
return;
|
|
2946
|
+
default:
|
|
2947
|
+
return;
|
|
2595
2948
|
}
|
|
2596
2949
|
};
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2950
|
+
var runChallengeActionLoop = async (args) => {
|
|
2951
|
+
let currentBundle = args.initialBundle;
|
|
2952
|
+
let currentTargetId = args.targetId ?? args.initialBundle.activeTargetId ?? null;
|
|
2953
|
+
const executedSteps = [];
|
|
2954
|
+
let noProgressCount = 0;
|
|
2955
|
+
let reusedExistingSession = false;
|
|
2956
|
+
let reusedCookies = false;
|
|
2957
|
+
for (let attempt = 1; attempt <= args.decision.attemptBudget; attempt += 1) {
|
|
2958
|
+
const step = selectChallengeActionStep({
|
|
2959
|
+
bundle: currentBundle,
|
|
2960
|
+
decision: args.decision,
|
|
2961
|
+
helperEligibility: args.helperEligibility,
|
|
2962
|
+
config: args.config,
|
|
2963
|
+
preferredSteps: args.suggestedSteps,
|
|
2964
|
+
executedSteps
|
|
2965
|
+
});
|
|
2966
|
+
if (!step) {
|
|
2967
|
+
return {
|
|
2968
|
+
status: "no_progress",
|
|
2969
|
+
attempts: attempt - 1,
|
|
2970
|
+
noProgressCount,
|
|
2971
|
+
executedSteps,
|
|
2972
|
+
verification: {
|
|
2973
|
+
status: "still_blocked",
|
|
2974
|
+
blockerState: currentBundle.blockerState,
|
|
2975
|
+
blocker: currentBundle.blocker,
|
|
2976
|
+
challenge: currentBundle.challenge,
|
|
2977
|
+
bundle: currentBundle,
|
|
2978
|
+
changed: false,
|
|
2979
|
+
reason: "No additional safe browser action remained.",
|
|
2980
|
+
url: currentBundle.url,
|
|
2981
|
+
title: currentBundle.title
|
|
2982
|
+
},
|
|
2983
|
+
reusedExistingSession,
|
|
2984
|
+
reusedCookies
|
|
2985
|
+
};
|
|
2986
|
+
}
|
|
2987
|
+
try {
|
|
2988
|
+
await executeStep({
|
|
2989
|
+
handle: args.handle,
|
|
2990
|
+
sessionId: args.sessionId,
|
|
2991
|
+
targetId: currentTargetId,
|
|
2992
|
+
step,
|
|
2993
|
+
config: args.config
|
|
2994
|
+
});
|
|
2995
|
+
} catch {
|
|
2996
|
+
}
|
|
2997
|
+
executedSteps.push(step);
|
|
2998
|
+
if (step.ref && currentBundle.continuity.sessionReuseRefs.includes(step.ref)) {
|
|
2999
|
+
reusedExistingSession = true;
|
|
3000
|
+
}
|
|
3001
|
+
if (step.kind === "goto" && currentBundle.continuity.canReuseExistingCookies) {
|
|
3002
|
+
reusedCookies = true;
|
|
3003
|
+
}
|
|
3004
|
+
const verification = await verifyChallengeProgress({
|
|
3005
|
+
handle: args.handle,
|
|
3006
|
+
sessionId: args.sessionId,
|
|
3007
|
+
targetId: currentTargetId,
|
|
3008
|
+
previous: currentBundle,
|
|
3009
|
+
canImportCookies: currentBundle.continuity.canImportCookies,
|
|
3010
|
+
fallbackDisposition: currentBundle.fallbackDisposition,
|
|
3011
|
+
registryPressure: currentBundle.registryPressure,
|
|
3012
|
+
taskData: currentBundle.taskData
|
|
3013
|
+
});
|
|
3014
|
+
currentBundle = verification.bundle ?? currentBundle;
|
|
3015
|
+
currentTargetId = verification.bundle?.activeTargetId ?? currentTargetId;
|
|
3016
|
+
if (verification.status === "clear") {
|
|
3017
|
+
return {
|
|
3018
|
+
status: "resolved",
|
|
3019
|
+
attempts: attempt,
|
|
3020
|
+
noProgressCount,
|
|
3021
|
+
executedSteps,
|
|
3022
|
+
verification,
|
|
3023
|
+
reusedExistingSession,
|
|
3024
|
+
reusedCookies
|
|
3025
|
+
};
|
|
3026
|
+
}
|
|
3027
|
+
if (verification.status === "yield_required") {
|
|
3028
|
+
return {
|
|
3029
|
+
status: "yield_required",
|
|
3030
|
+
attempts: attempt,
|
|
3031
|
+
noProgressCount,
|
|
3032
|
+
executedSteps,
|
|
3033
|
+
verification,
|
|
3034
|
+
reusedExistingSession,
|
|
3035
|
+
reusedCookies
|
|
3036
|
+
};
|
|
3037
|
+
}
|
|
3038
|
+
if (verification.status === "deferred") {
|
|
3039
|
+
return {
|
|
3040
|
+
status: "deferred",
|
|
3041
|
+
attempts: attempt,
|
|
3042
|
+
noProgressCount,
|
|
3043
|
+
executedSteps,
|
|
3044
|
+
verification,
|
|
3045
|
+
reusedExistingSession,
|
|
3046
|
+
reusedCookies
|
|
3047
|
+
};
|
|
3048
|
+
}
|
|
3049
|
+
if (verification.changed) {
|
|
3050
|
+
noProgressCount = 0;
|
|
3051
|
+
continue;
|
|
3052
|
+
}
|
|
3053
|
+
noProgressCount += 1;
|
|
3054
|
+
if (noProgressCount >= args.decision.noProgressLimit) {
|
|
3055
|
+
return {
|
|
3056
|
+
status: "no_progress",
|
|
3057
|
+
attempts: attempt,
|
|
3058
|
+
noProgressCount,
|
|
3059
|
+
executedSteps,
|
|
3060
|
+
verification,
|
|
3061
|
+
reusedExistingSession,
|
|
3062
|
+
reusedCookies
|
|
3063
|
+
};
|
|
3064
|
+
}
|
|
2605
3065
|
}
|
|
2606
3066
|
return {
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
targetId: args.targetId ?? args.bundle.activeTargetId,
|
|
2625
|
-
ownerSurface: args.bundle.challenge?.ownerSurface ?? args.bundle.ownerSurface,
|
|
2626
|
-
url: args.bundle.url,
|
|
2627
|
-
title: args.bundle.title,
|
|
2628
|
-
requiredHumanStep: args.reason === "mfa" ? "Complete MFA or passkey verification, then continue." : args.reason === "secret_entry" ? "Enter the required secret-bearing credentials, then continue." : args.reason === "unsupported_third_party" ? "Complete the unsupported third-party challenge manually, then continue." : "Review the page state and continue when ready.",
|
|
2629
|
-
targetHints,
|
|
2630
|
-
expectedPostAuthCheckpoint: args.interpretation.likelyCheckpoint,
|
|
2631
|
-
preserveUntil: args.bundle.challenge?.preserveUntil,
|
|
2632
|
-
verifyUntil: args.bundle.challenge?.verifyUntil,
|
|
2633
|
-
traceRequestId: args.bundle.diagnostics.traceRequestId,
|
|
2634
|
-
...args.verification ? {
|
|
2635
|
-
lastVerificationStatus: args.verification.status,
|
|
2636
|
-
lastVerificationReason: args.verification.reason
|
|
2637
|
-
} : {},
|
|
2638
|
-
evidenceSummary: args.interpretation.summary,
|
|
2639
|
-
reclaimHint: "Resume the preserved session and re-run verification after the human step completes.",
|
|
2640
|
-
resumeRule: "Re-run manager-owned verification after the human step completes before resuming automation."
|
|
3067
|
+
status: "still_blocked",
|
|
3068
|
+
attempts: args.decision.attemptBudget,
|
|
3069
|
+
noProgressCount,
|
|
3070
|
+
executedSteps,
|
|
3071
|
+
verification: {
|
|
3072
|
+
status: "still_blocked",
|
|
3073
|
+
blockerState: currentBundle.blockerState,
|
|
3074
|
+
blocker: currentBundle.blocker,
|
|
3075
|
+
challenge: currentBundle.challenge,
|
|
3076
|
+
bundle: currentBundle,
|
|
3077
|
+
changed: false,
|
|
3078
|
+
reason: "Attempt budget exhausted without clearing the blocker.",
|
|
3079
|
+
url: currentBundle.url,
|
|
3080
|
+
title: currentBundle.title
|
|
3081
|
+
},
|
|
3082
|
+
reusedExistingSession,
|
|
3083
|
+
reusedCookies
|
|
2641
3084
|
};
|
|
2642
3085
|
};
|
|
2643
3086
|
|
|
2644
|
-
// src/challenges/
|
|
2645
|
-
var
|
|
2646
|
-
var
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
const key = record.challengeId ?? "__untracked__";
|
|
2650
|
-
const existing = this.records.get(key) ?? [];
|
|
2651
|
-
const next = [...existing, record].slice(-MAX_RECORDS_PER_CHALLENGE);
|
|
2652
|
-
this.records.set(key, next);
|
|
2653
|
-
}
|
|
2654
|
-
latest(challengeId) {
|
|
2655
|
-
if (!challengeId) return void 0;
|
|
2656
|
-
const entries = this.records.get(challengeId);
|
|
2657
|
-
return entries?.[entries.length - 1];
|
|
2658
|
-
}
|
|
2659
|
-
read(challengeId) {
|
|
2660
|
-
if (!challengeId) return [];
|
|
2661
|
-
return [...this.records.get(challengeId) ?? []];
|
|
2662
|
-
}
|
|
2663
|
-
};
|
|
2664
|
-
|
|
2665
|
-
// src/challenges/policy-gate.ts
|
|
2666
|
-
var ALL_ACTIONS = [
|
|
2667
|
-
"wait",
|
|
2668
|
-
"auth_navigation",
|
|
2669
|
-
"session_reuse",
|
|
2670
|
-
"cookie_reuse",
|
|
2671
|
-
"element_discovery",
|
|
2672
|
-
"click_path",
|
|
2673
|
-
"click_and_hold",
|
|
2674
|
-
"non_secret_form_fill",
|
|
2675
|
-
"dropdown",
|
|
2676
|
-
"scroll",
|
|
2677
|
-
"hover",
|
|
2678
|
-
"press",
|
|
2679
|
-
"pointer",
|
|
2680
|
-
"drag",
|
|
2681
|
-
"verification",
|
|
2682
|
-
"debug_trace"
|
|
2683
|
-
];
|
|
2684
|
-
var DEFAULT_HANDOFF_TRIGGERS = [
|
|
2685
|
-
"secret_entry",
|
|
2686
|
-
"mfa",
|
|
2687
|
-
"explicit_consent",
|
|
2688
|
-
"policy_blocked",
|
|
2689
|
-
"unsupported_third_party",
|
|
2690
|
-
"exhausted_no_progress"
|
|
2691
|
-
];
|
|
2692
|
-
var buildResolvedPolicy = (mode, source) => {
|
|
2693
|
-
if (mode === "off") {
|
|
2694
|
-
return {
|
|
2695
|
-
mode,
|
|
2696
|
-
source,
|
|
2697
|
-
standDownReason: "challenge_automation_off"
|
|
2698
|
-
};
|
|
2699
|
-
}
|
|
2700
|
-
if (mode === "browser") {
|
|
2701
|
-
return {
|
|
2702
|
-
mode,
|
|
2703
|
-
source,
|
|
2704
|
-
standDownReason: "helper_disabled_for_browser_mode"
|
|
2705
|
-
};
|
|
2706
|
-
}
|
|
2707
|
-
return { mode, source };
|
|
2708
|
-
};
|
|
2709
|
-
var resolveChallengeAutomationPolicy = (args) => {
|
|
2710
|
-
if (args.runMode) {
|
|
2711
|
-
return buildResolvedPolicy(args.runMode, "run");
|
|
2712
|
-
}
|
|
2713
|
-
if (args.sessionMode) {
|
|
2714
|
-
return buildResolvedPolicy(args.sessionMode, "session");
|
|
2715
|
-
}
|
|
2716
|
-
return buildResolvedPolicy(args.configMode, "config");
|
|
2717
|
-
};
|
|
2718
|
-
var resolveHelperEligibility = (config, policy) => {
|
|
2719
|
-
if (policy.mode === "off") {
|
|
2720
|
-
return {
|
|
2721
|
-
allowed: false,
|
|
2722
|
-
reason: "Challenge automation mode is off; detection and reporting remain active.",
|
|
2723
|
-
standDownReason: "challenge_automation_off"
|
|
2724
|
-
};
|
|
2725
|
-
}
|
|
2726
|
-
if (policy.mode === "browser") {
|
|
2727
|
-
return {
|
|
2728
|
-
allowed: false,
|
|
2729
|
-
reason: "Browser mode keeps the optional helper bridge disabled.",
|
|
2730
|
-
standDownReason: "helper_disabled_for_browser_mode"
|
|
2731
|
-
};
|
|
2732
|
-
}
|
|
2733
|
-
if (!config.optionalComputerUseBridge.enabled) {
|
|
2734
|
-
return {
|
|
2735
|
-
allowed: false,
|
|
2736
|
-
reason: "Optional computer-use bridge is disabled by policy.",
|
|
2737
|
-
standDownReason: "helper_disabled_by_policy"
|
|
2738
|
-
};
|
|
2739
|
-
}
|
|
2740
|
-
return {
|
|
2741
|
-
allowed: true,
|
|
2742
|
-
reason: "Optional helper bridge remains eligible after mode resolution."
|
|
2743
|
-
};
|
|
2744
|
-
};
|
|
2745
|
-
var buildChallengePolicyGate = (config, interpretation, resolvedPolicy = resolveChallengeAutomationPolicy({
|
|
2746
|
-
configMode: config.mode
|
|
2747
|
-
})) => {
|
|
2748
|
-
const helperEligibility = resolveHelperEligibility(config, resolvedPolicy);
|
|
2749
|
-
if (resolvedPolicy.mode === "off") {
|
|
2750
|
-
return {
|
|
2751
|
-
resolvedPolicy,
|
|
2752
|
-
allowedActions: [],
|
|
2753
|
-
forbiddenActions: [...ALL_ACTIONS],
|
|
2754
|
-
handoffTriggers: [...DEFAULT_HANDOFF_TRIGGERS],
|
|
2755
|
-
governedLanes: [],
|
|
2756
|
-
optionalComputerUseBridge: false,
|
|
2757
|
-
helperEligibility
|
|
2758
|
-
};
|
|
2759
|
-
}
|
|
2760
|
-
const allowed = /* @__PURE__ */ new Set(["wait", "verification", "debug_trace"]);
|
|
2761
|
-
if (config.allowAuthNavigation) {
|
|
2762
|
-
allowed.add("auth_navigation");
|
|
2763
|
-
}
|
|
2764
|
-
if (config.allowSessionReuse) {
|
|
2765
|
-
allowed.add("session_reuse");
|
|
2766
|
-
}
|
|
2767
|
-
if (config.allowCookieReuse) {
|
|
2768
|
-
allowed.add("cookie_reuse");
|
|
2769
|
-
}
|
|
2770
|
-
if (config.allowNonSecretFormFill) {
|
|
2771
|
-
allowed.add("non_secret_form_fill");
|
|
2772
|
-
allowed.add("dropdown");
|
|
2773
|
-
}
|
|
2774
|
-
if (config.allowInteractionExploration) {
|
|
2775
|
-
allowed.add("element_discovery");
|
|
2776
|
-
allowed.add("click_path");
|
|
2777
|
-
allowed.add("click_and_hold");
|
|
2778
|
-
allowed.add("scroll");
|
|
2779
|
-
allowed.add("hover");
|
|
2780
|
-
allowed.add("press");
|
|
2781
|
-
allowed.add("pointer");
|
|
2782
|
-
allowed.add("drag");
|
|
2783
|
-
}
|
|
2784
|
-
if (interpretation.humanBoundary === "secret_entry" || interpretation.humanBoundary === "mfa") {
|
|
2785
|
-
allowed.delete("non_secret_form_fill");
|
|
2786
|
-
}
|
|
2787
|
-
const governedLanes = [];
|
|
2788
|
-
if (config.governed.allowOwnedEnvironmentFixtures) {
|
|
2789
|
-
governedLanes.push("owned_environment_fixture");
|
|
2790
|
-
}
|
|
2791
|
-
if (config.governed.allowSanctionedIdentity) {
|
|
2792
|
-
governedLanes.push("sanctioned_identity");
|
|
2793
|
-
}
|
|
2794
|
-
if (config.governed.allowServiceAdapters) {
|
|
2795
|
-
governedLanes.push("service_adapter");
|
|
2796
|
-
}
|
|
3087
|
+
// src/challenges/owned-environment-lane.ts
|
|
3088
|
+
var APPROVED_FIXTURE_RE = /\b(turnstile-checkbox|recaptcha-v2-checkbox|1x00000000000000000000AA|6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI)\b/i;
|
|
3089
|
+
var runOwnedEnvironmentLane = (request) => {
|
|
3090
|
+
const haystack = [request.bundle.url, request.bundle.title, request.bundle.snapshotText].filter((value) => typeof value === "string" && value.length > 0).join(" ");
|
|
3091
|
+
const approved = APPROVED_FIXTURE_RE.test(haystack);
|
|
2797
3092
|
return {
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
}
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
"
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
"
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
interpretation.requiredVerification,
|
|
2847
|
-
["policy_blocked_or_clear_state"]
|
|
2848
|
-
);
|
|
2849
|
-
}
|
|
2850
|
-
if (registryCooldownActive && !capabilityMatrix.canReuseExistingSession && !capabilityMatrix.canReuseCookies && !capabilityMatrix.canNavigateToAuth) {
|
|
2851
|
-
return buildDecision(
|
|
2852
|
-
config,
|
|
2853
|
-
"defer",
|
|
2854
|
-
"Registry cooldown is still active and no legitimate continuity or auth-navigation lane is currently available.",
|
|
2855
|
-
gate.allowedActions,
|
|
2856
|
-
interpretation.requiredVerification,
|
|
2857
|
-
["registry_cooldown_active"]
|
|
2858
|
-
);
|
|
2859
|
-
}
|
|
2860
|
-
if (capabilityMatrix.canUseOwnedEnvironmentFixture) {
|
|
2861
|
-
return buildDecision(
|
|
2862
|
-
config,
|
|
2863
|
-
"owned_environment_fixture",
|
|
2864
|
-
"Owned-environment fixture detected and explicitly allowlisted.",
|
|
2865
|
-
gate.allowedActions,
|
|
2866
|
-
interpretation.requiredVerification,
|
|
2867
|
-
stopConditions,
|
|
2868
|
-
"owned_environment_fixture"
|
|
2869
|
-
);
|
|
2870
|
-
}
|
|
2871
|
-
if (capabilityMatrix.mustYield) {
|
|
2872
|
-
return buildDecision(
|
|
2873
|
-
config,
|
|
2874
|
-
"human_yield",
|
|
2875
|
-
`Human authority boundary reached: ${interpretation.humanBoundary}.`,
|
|
2876
|
-
gate.allowedActions,
|
|
2877
|
-
interpretation.requiredVerification,
|
|
2878
|
-
[...stopConditions, "human_authority_required"]
|
|
2879
|
-
);
|
|
3093
|
+
status: approved ? "executed" : "blocked",
|
|
3094
|
+
lane: "owned_environment_fixture",
|
|
3095
|
+
reason: approved ? "Approved owned-environment fixture detected." : "Owned-environment lane requires an approved vendor test fixture.",
|
|
3096
|
+
auditMetadata: {
|
|
3097
|
+
approvedFixture: approved
|
|
3098
|
+
}
|
|
3099
|
+
};
|
|
3100
|
+
};
|
|
3101
|
+
|
|
3102
|
+
// src/challenges/sanctioned-identity-lane.ts
|
|
3103
|
+
var runSanctionedIdentityLane = (request) => {
|
|
3104
|
+
const entitlement = request.auditContext?.identityEntitlement;
|
|
3105
|
+
const approved = typeof entitlement === "string" && entitlement.trim().length > 0;
|
|
3106
|
+
return {
|
|
3107
|
+
status: approved ? "executed" : "blocked",
|
|
3108
|
+
lane: "sanctioned_identity",
|
|
3109
|
+
reason: approved ? "Sanctioned identity lane approved by explicit entitlement." : "Sanctioned identity lane requires explicit entitlement metadata.",
|
|
3110
|
+
auditMetadata: {
|
|
3111
|
+
approved,
|
|
3112
|
+
...approved ? { entitlement } : {}
|
|
3113
|
+
}
|
|
3114
|
+
};
|
|
3115
|
+
};
|
|
3116
|
+
|
|
3117
|
+
// src/challenges/service-adapter-lane.ts
|
|
3118
|
+
var runServiceAdapterLane = (request) => {
|
|
3119
|
+
const adapter = request.auditContext?.adapterId;
|
|
3120
|
+
const approved = typeof adapter === "string" && adapter.trim().length > 0;
|
|
3121
|
+
return {
|
|
3122
|
+
status: approved ? "executed" : "blocked",
|
|
3123
|
+
lane: "service_adapter",
|
|
3124
|
+
reason: approved ? "Governed service adapter approved by explicit adapter metadata." : "Service-adapter lane requires an explicit adapter identifier and entitlement.",
|
|
3125
|
+
auditMetadata: {
|
|
3126
|
+
approved,
|
|
3127
|
+
...approved ? { adapterId: adapter } : {}
|
|
3128
|
+
}
|
|
3129
|
+
};
|
|
3130
|
+
};
|
|
3131
|
+
|
|
3132
|
+
// src/challenges/governed-adapter-gateway.ts
|
|
3133
|
+
var evaluateGovernedLane = (config, request) => {
|
|
3134
|
+
if (config.mode === "off") {
|
|
3135
|
+
return {
|
|
3136
|
+
status: "blocked",
|
|
3137
|
+
lane: request.lane,
|
|
3138
|
+
reason: "Challenge automation mode is off.",
|
|
3139
|
+
auditMetadata: {}
|
|
3140
|
+
};
|
|
2880
3141
|
}
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
config
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
3142
|
+
switch (request.lane) {
|
|
3143
|
+
case "owned_environment_fixture":
|
|
3144
|
+
if (!config.governed.allowOwnedEnvironmentFixtures) {
|
|
3145
|
+
return {
|
|
3146
|
+
status: "blocked",
|
|
3147
|
+
lane: request.lane,
|
|
3148
|
+
reason: "Owned-environment fixtures are disabled by policy.",
|
|
3149
|
+
auditMetadata: {}
|
|
3150
|
+
};
|
|
3151
|
+
}
|
|
3152
|
+
return runOwnedEnvironmentLane(request);
|
|
3153
|
+
case "sanctioned_identity":
|
|
3154
|
+
if (!config.governed.allowSanctionedIdentity) {
|
|
3155
|
+
return {
|
|
3156
|
+
status: "blocked",
|
|
3157
|
+
lane: request.lane,
|
|
3158
|
+
reason: "Sanctioned identity is disabled by policy.",
|
|
3159
|
+
auditMetadata: {}
|
|
3160
|
+
};
|
|
3161
|
+
}
|
|
3162
|
+
return runSanctionedIdentityLane(request);
|
|
3163
|
+
case "service_adapter":
|
|
3164
|
+
if (!config.governed.allowServiceAdapters) {
|
|
3165
|
+
return {
|
|
3166
|
+
status: "blocked",
|
|
3167
|
+
lane: request.lane,
|
|
3168
|
+
reason: "Service adapters are disabled by policy.",
|
|
3169
|
+
auditMetadata: {}
|
|
3170
|
+
};
|
|
3171
|
+
}
|
|
3172
|
+
return runServiceAdapterLane(request);
|
|
2890
3173
|
}
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
);
|
|
3174
|
+
};
|
|
3175
|
+
|
|
3176
|
+
// src/challenges/outcome-recorder.ts
|
|
3177
|
+
var MAX_RECORDS_PER_CHALLENGE = 25;
|
|
3178
|
+
var OutcomeRecorder = class {
|
|
3179
|
+
records = /* @__PURE__ */ new Map();
|
|
3180
|
+
record(record) {
|
|
3181
|
+
const key = record.challengeId ?? "__untracked__";
|
|
3182
|
+
const existing = this.records.get(key) ?? [];
|
|
3183
|
+
const next = [...existing, record].slice(-MAX_RECORDS_PER_CHALLENGE);
|
|
3184
|
+
this.records.set(key, next);
|
|
2900
3185
|
}
|
|
2901
|
-
|
|
2902
|
-
return
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
"Sanctioned identity lane is enabled and generic browser autonomy is insufficient.",
|
|
2906
|
-
gate.allowedActions,
|
|
2907
|
-
interpretation.requiredVerification,
|
|
2908
|
-
stopConditions,
|
|
2909
|
-
"sanctioned_identity"
|
|
2910
|
-
);
|
|
3186
|
+
latest(challengeId) {
|
|
3187
|
+
if (!challengeId) return void 0;
|
|
3188
|
+
const entries = this.records.get(challengeId);
|
|
3189
|
+
return entries?.[entries.length - 1];
|
|
2911
3190
|
}
|
|
2912
|
-
|
|
2913
|
-
return
|
|
2914
|
-
|
|
2915
|
-
"service_adapter",
|
|
2916
|
-
"Governed service-adapter lane is enabled as the last non-human option.",
|
|
2917
|
-
gate.allowedActions,
|
|
2918
|
-
interpretation.requiredVerification,
|
|
2919
|
-
stopConditions,
|
|
2920
|
-
"service_adapter"
|
|
2921
|
-
);
|
|
3191
|
+
read(challengeId) {
|
|
3192
|
+
if (!challengeId) return [];
|
|
3193
|
+
return [...this.records.get(challengeId) ?? []];
|
|
2922
3194
|
}
|
|
2923
|
-
return buildDecision(
|
|
2924
|
-
config,
|
|
2925
|
-
"human_yield",
|
|
2926
|
-
`No legitimate autonomous lane remains after applying policy and continuity checks. ${capabilityMatrix.helperEligibility.reason}`,
|
|
2927
|
-
gate.allowedActions,
|
|
2928
|
-
interpretation.requiredVerification,
|
|
2929
|
-
[...stopConditions, "no_legitimate_lane_remaining"]
|
|
2930
|
-
);
|
|
2931
3195
|
};
|
|
2932
3196
|
|
|
2933
3197
|
// src/challenges/orchestrator.ts
|
|
@@ -2999,25 +3263,7 @@ var ChallengeOrchestrator = class {
|
|
|
2999
3263
|
return this.recorder;
|
|
3000
3264
|
}
|
|
3001
3265
|
async captureEvidence(args) {
|
|
3002
|
-
|
|
3003
|
-
const effectiveTargetId = status.activeTargetId ?? args.targetId ?? null;
|
|
3004
|
-
const snapshot = await args.handle.snapshot(args.sessionId, "actionables", 2400, void 0, effectiveTargetId);
|
|
3005
|
-
const debugTrace = await args.handle.debugTraceSnapshot(args.sessionId, { max: 50 });
|
|
3006
|
-
const cookies = status.url ? await args.handle.cookieList(args.sessionId, [status.url]) : { count: 0 };
|
|
3007
|
-
return buildChallengeEvidenceBundle({
|
|
3008
|
-
status,
|
|
3009
|
-
snapshot: {
|
|
3010
|
-
snapshotId: snapshot.snapshotId,
|
|
3011
|
-
content: snapshot.content,
|
|
3012
|
-
warnings: snapshot.warnings
|
|
3013
|
-
},
|
|
3014
|
-
debugTrace,
|
|
3015
|
-
cookieCount: cookies.count,
|
|
3016
|
-
canImportCookies: args.canImportCookies,
|
|
3017
|
-
fallbackDisposition: args.fallbackDisposition,
|
|
3018
|
-
registryPressure: args.registryPressure,
|
|
3019
|
-
taskData: args.taskData
|
|
3020
|
-
});
|
|
3266
|
+
return captureChallengeEvidence(args);
|
|
3021
3267
|
}
|
|
3022
3268
|
async orchestrate(args) {
|
|
3023
3269
|
const bundle = await this.captureEvidence({
|
|
@@ -3204,6 +3450,7 @@ var ChallengeOrchestrator = class {
|
|
|
3204
3450
|
targetId: args.targetId,
|
|
3205
3451
|
initialBundle: bundle,
|
|
3206
3452
|
decision,
|
|
3453
|
+
helperEligibility: capabilityMatrix.helperEligibility,
|
|
3207
3454
|
config: this.config,
|
|
3208
3455
|
suggestedSteps
|
|
3209
3456
|
});
|
|
@@ -3366,6 +3613,20 @@ var fallbackDispositionMessage = (fallback, url) => {
|
|
|
3366
3613
|
var toProviderFallbackError = (args) => {
|
|
3367
3614
|
const { fallback } = args;
|
|
3368
3615
|
const reasonCode = fallback.reasonCode;
|
|
3616
|
+
const details = {
|
|
3617
|
+
url: args.url,
|
|
3618
|
+
disposition: fallback.disposition,
|
|
3619
|
+
...fallback.mode ? { browserFallbackMode: fallback.mode } : {},
|
|
3620
|
+
...fallback.challenge ? { challenge: toJsonRecord(fallback.challenge) } : {},
|
|
3621
|
+
...fallback.preservedSessionId ? { preservedSessionId: fallback.preservedSessionId } : {},
|
|
3622
|
+
...fallback.preservedTargetId ? { preservedTargetId: fallback.preservedTargetId } : {},
|
|
3623
|
+
...toJsonRecord(fallback.details ?? {})
|
|
3624
|
+
};
|
|
3625
|
+
const hint = readProviderIssueHint({
|
|
3626
|
+
reasonCode,
|
|
3627
|
+
details
|
|
3628
|
+
});
|
|
3629
|
+
const guidance = hint ? buildProviderIssueGuidance({ provider: args.provider, hint, details }) : void 0;
|
|
3369
3630
|
return new ProviderRuntimeError(
|
|
3370
3631
|
providerErrorCodeFromReasonCode(reasonCode),
|
|
3371
3632
|
fallbackDispositionMessage(fallback, args.url),
|
|
@@ -3374,15 +3635,7 @@ var toProviderFallbackError = (args) => {
|
|
|
3374
3635
|
source: args.source,
|
|
3375
3636
|
retryable: reasonCode === "rate_limited",
|
|
3376
3637
|
reasonCode,
|
|
3377
|
-
details: {
|
|
3378
|
-
url: args.url,
|
|
3379
|
-
disposition: fallback.disposition,
|
|
3380
|
-
...fallback.mode ? { browserFallbackMode: fallback.mode } : {},
|
|
3381
|
-
...fallback.challenge ? { challenge: toJsonRecord(fallback.challenge) } : {},
|
|
3382
|
-
...fallback.preservedSessionId ? { preservedSessionId: fallback.preservedSessionId } : {},
|
|
3383
|
-
...fallback.preservedTargetId ? { preservedTargetId: fallback.preservedTargetId } : {},
|
|
3384
|
-
...toJsonRecord(fallback.details ?? {})
|
|
3385
|
-
}
|
|
3638
|
+
details: guidance ? { ...details, guidance } : details
|
|
3386
3639
|
}
|
|
3387
3640
|
);
|
|
3388
3641
|
};
|
|
@@ -9173,7 +9426,7 @@ var isJsonRecord = (value) => typeof value === "object" && value !== null && !Ar
|
|
|
9173
9426
|
var isWorkflowStage = (value) => value === "compile" || value === "execute" || value === "postprocess" || value === "resume";
|
|
9174
9427
|
var isWorkflowCheckpoint = (value) => isJsonRecord(value) && isWorkflowStage(value.stage) && (value.stepId === void 0 || typeof value.stepId === "string") && (value.stepIndex === void 0 || typeof value.stepIndex === "number") && (value.state === void 0 || isJsonRecord(value.state)) && (value.updatedAt === void 0 || typeof value.updatedAt === "string");
|
|
9175
9428
|
var isWorkflowTraceEntry = (value) => isJsonRecord(value) && typeof value.at === "string" && isWorkflowStage(value.stage) && typeof value.event === "string" && (value.details === void 0 || isJsonRecord(value.details));
|
|
9176
|
-
var isWorkflowKind = (value) => value === "research" || value === "shopping" || value === "product_video";
|
|
9429
|
+
var isWorkflowKind = (value) => value === "research" || value === "shopping" || value === "product_video" || value === "inspiredesign";
|
|
9177
9430
|
var buildWorkflowResumeEnvelope = (kind, input, options = {}) => ({
|
|
9178
9431
|
kind,
|
|
9179
9432
|
input,
|
|
@@ -9184,7 +9437,7 @@ var isWorkflowResumeEnvelope = (value) => isJsonRecord(value) && isWorkflowKind(
|
|
|
9184
9437
|
var isWorkflowResumePayload = (value) => isJsonRecord(value) && isWorkflowResumeEnvelope(value.workflow);
|
|
9185
9438
|
|
|
9186
9439
|
// src/providers/workflows.ts
|
|
9187
|
-
import { createHash as
|
|
9440
|
+
import { createHash as createHash7 } from "crypto";
|
|
9188
9441
|
|
|
9189
9442
|
// src/providers/artifacts.ts
|
|
9190
9443
|
import { mkdir, readdir as readdir2, readFile, rm as rm2, stat, writeFile } from "fs/promises";
|
|
@@ -9503,11 +9756,111 @@ var compactResearchLines = (records, meta) => {
|
|
|
9503
9756
|
return `${index + 1}. ${title} (${record.source}/${record.provider}) score=${record.confidence.toFixed(2)} engagement=${engagement}`;
|
|
9504
9757
|
});
|
|
9505
9758
|
};
|
|
9506
|
-
var renderResearch = (args) => {
|
|
9507
|
-
const lines = compactResearchLines(args.records, args.meta);
|
|
9508
|
-
const summary = lines.join("\n");
|
|
9759
|
+
var renderResearch = (args) => {
|
|
9760
|
+
const lines = compactResearchLines(args.records, args.meta);
|
|
9761
|
+
const summary = lines.join("\n");
|
|
9762
|
+
const markdown = [
|
|
9763
|
+
`# Research: ${args.topic}`,
|
|
9764
|
+
"",
|
|
9765
|
+
...lines,
|
|
9766
|
+
"",
|
|
9767
|
+
"## Metadata",
|
|
9768
|
+
"```json",
|
|
9769
|
+
JSON.stringify(args.meta, null, 2),
|
|
9770
|
+
"```"
|
|
9771
|
+
].join("\n");
|
|
9772
|
+
const contextPayload = {
|
|
9773
|
+
topic: args.topic,
|
|
9774
|
+
highlights: lines,
|
|
9775
|
+
records: args.records,
|
|
9776
|
+
meta: args.meta
|
|
9777
|
+
};
|
|
9778
|
+
const files = [
|
|
9779
|
+
{ path: "summary.md", content: markdown },
|
|
9780
|
+
{ path: "records.json", content: { records: args.records } },
|
|
9781
|
+
{ path: "context.json", content: contextPayload },
|
|
9782
|
+
{ path: "meta.json", content: args.meta }
|
|
9783
|
+
];
|
|
9784
|
+
if (args.mode === "compact") {
|
|
9785
|
+
return {
|
|
9786
|
+
response: {
|
|
9787
|
+
mode: args.mode,
|
|
9788
|
+
summary,
|
|
9789
|
+
meta: args.meta
|
|
9790
|
+
},
|
|
9791
|
+
files
|
|
9792
|
+
};
|
|
9793
|
+
}
|
|
9794
|
+
if (args.mode === "json") {
|
|
9795
|
+
return {
|
|
9796
|
+
response: {
|
|
9797
|
+
mode: args.mode,
|
|
9798
|
+
records: args.records,
|
|
9799
|
+
meta: args.meta
|
|
9800
|
+
},
|
|
9801
|
+
files
|
|
9802
|
+
};
|
|
9803
|
+
}
|
|
9804
|
+
if (args.mode === "md") {
|
|
9805
|
+
return {
|
|
9806
|
+
response: {
|
|
9807
|
+
mode: args.mode,
|
|
9808
|
+
markdown,
|
|
9809
|
+
meta: args.meta
|
|
9810
|
+
},
|
|
9811
|
+
files
|
|
9812
|
+
};
|
|
9813
|
+
}
|
|
9814
|
+
if (args.mode === "context") {
|
|
9815
|
+
return {
|
|
9816
|
+
response: {
|
|
9817
|
+
mode: args.mode,
|
|
9818
|
+
context: contextPayload,
|
|
9819
|
+
meta: args.meta
|
|
9820
|
+
},
|
|
9821
|
+
files
|
|
9822
|
+
};
|
|
9823
|
+
}
|
|
9824
|
+
return {
|
|
9825
|
+
response: {
|
|
9826
|
+
mode: "path",
|
|
9827
|
+
meta: args.meta
|
|
9828
|
+
},
|
|
9829
|
+
files
|
|
9830
|
+
};
|
|
9831
|
+
};
|
|
9832
|
+
var toComparisonCsv = (offers) => {
|
|
9833
|
+
const header = ["provider", "title", "price", "shipping", "deal_score", "availability", "url"].join(",");
|
|
9834
|
+
const rows = offers.map((offer) => {
|
|
9835
|
+
return [
|
|
9836
|
+
offer.provider,
|
|
9837
|
+
JSON.stringify(offer.title),
|
|
9838
|
+
offer.price.amount.toFixed(2),
|
|
9839
|
+
offer.shipping.amount.toFixed(2),
|
|
9840
|
+
offer.deal_score.toFixed(4),
|
|
9841
|
+
offer.availability,
|
|
9842
|
+
canonicalizeUrl(offer.url)
|
|
9843
|
+
].join(",");
|
|
9844
|
+
});
|
|
9845
|
+
return [header, ...rows].join("\n");
|
|
9846
|
+
};
|
|
9847
|
+
var compactShoppingLines = (offers, meta) => {
|
|
9848
|
+
if (offers.length === 0) {
|
|
9849
|
+
const summary = primaryConstraintSummaryFromMeta(meta);
|
|
9850
|
+
return summary ? [
|
|
9851
|
+
"No offers available from the selected providers.",
|
|
9852
|
+
`Primary constraint: ${summary}`
|
|
9853
|
+
] : ["No offers available from the selected providers."];
|
|
9854
|
+
}
|
|
9855
|
+
return offers.slice(0, 10).map((offer, index) => {
|
|
9856
|
+
const total = offer.price.amount + offer.shipping.amount;
|
|
9857
|
+
return `${index + 1}. ${offer.title} - ${toCurrency(total)} (${offer.provider}, deal=${offer.deal_score.toFixed(2)})`;
|
|
9858
|
+
});
|
|
9859
|
+
};
|
|
9860
|
+
var renderShopping = (args) => {
|
|
9861
|
+
const lines = compactShoppingLines(args.offers, args.meta);
|
|
9509
9862
|
const markdown = [
|
|
9510
|
-
`#
|
|
9863
|
+
`# Shopping: ${args.query}`,
|
|
9511
9864
|
"",
|
|
9512
9865
|
...lines,
|
|
9513
9866
|
"",
|
|
@@ -9516,23 +9869,25 @@ var renderResearch = (args) => {
|
|
|
9516
9869
|
JSON.stringify(args.meta, null, 2),
|
|
9517
9870
|
"```"
|
|
9518
9871
|
].join("\n");
|
|
9872
|
+
const comparisonCsv = toComparisonCsv(args.offers);
|
|
9519
9873
|
const contextPayload = {
|
|
9520
|
-
|
|
9874
|
+
query: args.query,
|
|
9521
9875
|
highlights: lines,
|
|
9522
|
-
|
|
9876
|
+
offers: args.offers,
|
|
9523
9877
|
meta: args.meta
|
|
9524
9878
|
};
|
|
9525
9879
|
const files = [
|
|
9526
|
-
{ path: "
|
|
9527
|
-
{ path: "
|
|
9528
|
-
{ path: "
|
|
9529
|
-
{ path: "meta.json", content: args.meta }
|
|
9880
|
+
{ path: "deals.md", content: markdown },
|
|
9881
|
+
{ path: "offers.json", content: { offers: args.offers } },
|
|
9882
|
+
{ path: "comparison.csv", content: comparisonCsv },
|
|
9883
|
+
{ path: "meta.json", content: args.meta },
|
|
9884
|
+
{ path: "deals-context.json", content: contextPayload }
|
|
9530
9885
|
];
|
|
9531
9886
|
if (args.mode === "compact") {
|
|
9532
9887
|
return {
|
|
9533
9888
|
response: {
|
|
9534
9889
|
mode: args.mode,
|
|
9535
|
-
summary,
|
|
9890
|
+
summary: lines.join("\n"),
|
|
9536
9891
|
meta: args.meta
|
|
9537
9892
|
},
|
|
9538
9893
|
files
|
|
@@ -9542,7 +9897,7 @@ var renderResearch = (args) => {
|
|
|
9542
9897
|
return {
|
|
9543
9898
|
response: {
|
|
9544
9899
|
mode: args.mode,
|
|
9545
|
-
|
|
9900
|
+
offers: args.offers,
|
|
9546
9901
|
meta: args.meta
|
|
9547
9902
|
},
|
|
9548
9903
|
files
|
|
@@ -9576,111 +9931,1183 @@ var renderResearch = (args) => {
|
|
|
9576
9931
|
files
|
|
9577
9932
|
};
|
|
9578
9933
|
};
|
|
9579
|
-
var
|
|
9580
|
-
const
|
|
9581
|
-
|
|
9582
|
-
|
|
9583
|
-
|
|
9584
|
-
|
|
9585
|
-
|
|
9586
|
-
|
|
9587
|
-
|
|
9588
|
-
|
|
9589
|
-
|
|
9590
|
-
|
|
9591
|
-
|
|
9592
|
-
|
|
9934
|
+
var renderInspiredesign = (args) => {
|
|
9935
|
+
const summary = [
|
|
9936
|
+
`Brief: ${args.brief}`,
|
|
9937
|
+
`References: ${args.urls.length}`,
|
|
9938
|
+
`Profile: ${args.generationPlan.visualDirection.profile}`
|
|
9939
|
+
].join("\n");
|
|
9940
|
+
const contextPayload = {
|
|
9941
|
+
brief: args.brief,
|
|
9942
|
+
urls: args.urls,
|
|
9943
|
+
designContract: args.designContract,
|
|
9944
|
+
generationPlan: args.generationPlan,
|
|
9945
|
+
implementationPlan: args.implementationPlan,
|
|
9946
|
+
designMarkdown: args.designMarkdown,
|
|
9947
|
+
implementationPlanMarkdown: args.implementationPlanMarkdown,
|
|
9948
|
+
prototypeGuidanceMarkdown: args.prototypeGuidanceMarkdown,
|
|
9949
|
+
evidence: args.evidence,
|
|
9950
|
+
meta: args.meta
|
|
9951
|
+
};
|
|
9952
|
+
const files = [
|
|
9953
|
+
{ path: "design.md", content: args.designMarkdown },
|
|
9954
|
+
{ path: "design-contract.json", content: args.designContract },
|
|
9955
|
+
{ path: "generation-plan.json", content: args.generationPlan },
|
|
9956
|
+
{ path: "implementation-plan.md", content: args.implementationPlanMarkdown },
|
|
9957
|
+
{ path: "implementation-plan.json", content: args.implementationPlan },
|
|
9958
|
+
{ path: "evidence.json", content: args.evidence }
|
|
9959
|
+
];
|
|
9960
|
+
if (args.prototypeGuidanceMarkdown) {
|
|
9961
|
+
files.push({ path: "prototype-guidance.md", content: args.prototypeGuidanceMarkdown });
|
|
9962
|
+
}
|
|
9963
|
+
if (args.mode === "compact") {
|
|
9964
|
+
return {
|
|
9965
|
+
response: {
|
|
9966
|
+
mode: args.mode,
|
|
9967
|
+
summary,
|
|
9968
|
+
meta: args.meta
|
|
9969
|
+
},
|
|
9970
|
+
files
|
|
9971
|
+
};
|
|
9972
|
+
}
|
|
9973
|
+
if (args.mode === "json") {
|
|
9974
|
+
return {
|
|
9975
|
+
response: {
|
|
9976
|
+
mode: args.mode,
|
|
9977
|
+
brief: args.brief,
|
|
9978
|
+
urls: args.urls,
|
|
9979
|
+
designContract: args.designContract,
|
|
9980
|
+
generationPlan: args.generationPlan,
|
|
9981
|
+
implementationPlan: args.implementationPlan,
|
|
9982
|
+
prototypeGuidanceMarkdown: args.prototypeGuidanceMarkdown,
|
|
9983
|
+
evidence: args.evidence,
|
|
9984
|
+
meta: args.meta
|
|
9985
|
+
},
|
|
9986
|
+
files
|
|
9987
|
+
};
|
|
9988
|
+
}
|
|
9989
|
+
if (args.mode === "md") {
|
|
9990
|
+
return {
|
|
9991
|
+
response: {
|
|
9992
|
+
mode: args.mode,
|
|
9993
|
+
markdown: args.designMarkdown,
|
|
9994
|
+
implementationPlanMarkdown: args.implementationPlanMarkdown,
|
|
9995
|
+
prototypeGuidanceMarkdown: args.prototypeGuidanceMarkdown,
|
|
9996
|
+
meta: args.meta
|
|
9997
|
+
},
|
|
9998
|
+
files
|
|
9999
|
+
};
|
|
10000
|
+
}
|
|
10001
|
+
if (args.mode === "context") {
|
|
10002
|
+
return {
|
|
10003
|
+
response: {
|
|
10004
|
+
mode: args.mode,
|
|
10005
|
+
context: contextPayload,
|
|
10006
|
+
meta: args.meta
|
|
10007
|
+
},
|
|
10008
|
+
files
|
|
10009
|
+
};
|
|
10010
|
+
}
|
|
10011
|
+
return {
|
|
10012
|
+
response: {
|
|
10013
|
+
mode: "path",
|
|
10014
|
+
meta: args.meta
|
|
10015
|
+
},
|
|
10016
|
+
files
|
|
10017
|
+
};
|
|
9593
10018
|
};
|
|
9594
|
-
|
|
9595
|
-
|
|
9596
|
-
|
|
9597
|
-
|
|
9598
|
-
|
|
9599
|
-
|
|
9600
|
-
|
|
10019
|
+
|
|
10020
|
+
// src/providers/inspiredesign-contract.ts
|
|
10021
|
+
import { createHash as createHash3 } from "crypto";
|
|
10022
|
+
|
|
10023
|
+
// skills/opendevbrowser-design-agent/assets/templates/canvas-generation-plan.design.v1.json
|
|
10024
|
+
var canvas_generation_plan_design_v1_default = {
|
|
10025
|
+
requestId: "req_plan_design_01",
|
|
10026
|
+
canvasSessionId: "<canvas-session-id>",
|
|
10027
|
+
leaseId: "<lease-id>",
|
|
10028
|
+
documentId: "<document-id>",
|
|
10029
|
+
generationPlan: {
|
|
10030
|
+
targetOutcome: {
|
|
10031
|
+
mode: "high-fi-live-edit",
|
|
10032
|
+
summary: "Clarify hierarchy, trust, and action flow"
|
|
10033
|
+
},
|
|
10034
|
+
visualDirection: {
|
|
10035
|
+
profile: "product-story",
|
|
10036
|
+
themeStrategy: "single-theme"
|
|
10037
|
+
},
|
|
10038
|
+
layoutStrategy: {
|
|
10039
|
+
approach: "hero-led-grid",
|
|
10040
|
+
navigationModel: "global-header"
|
|
10041
|
+
},
|
|
10042
|
+
contentStrategy: {
|
|
10043
|
+
source: "real-content-first"
|
|
10044
|
+
},
|
|
10045
|
+
componentStrategy: {
|
|
10046
|
+
mode: "reuse-first",
|
|
10047
|
+
interactionStates: [
|
|
10048
|
+
"default",
|
|
10049
|
+
"hover",
|
|
10050
|
+
"focus",
|
|
10051
|
+
"disabled"
|
|
10052
|
+
]
|
|
10053
|
+
},
|
|
10054
|
+
motionPosture: {
|
|
10055
|
+
level: "subtle",
|
|
10056
|
+
reducedMotion: "respect-user-preference"
|
|
10057
|
+
},
|
|
10058
|
+
responsivePosture: {
|
|
10059
|
+
primaryViewport: "desktop",
|
|
10060
|
+
requiredViewports: [
|
|
10061
|
+
"desktop",
|
|
10062
|
+
"tablet",
|
|
10063
|
+
"mobile"
|
|
10064
|
+
]
|
|
10065
|
+
},
|
|
10066
|
+
accessibilityPosture: {
|
|
10067
|
+
target: "WCAG_2_2_AA",
|
|
10068
|
+
keyboardNavigation: "full"
|
|
10069
|
+
},
|
|
10070
|
+
validationTargets: {
|
|
10071
|
+
blockOn: [
|
|
10072
|
+
"contrast-failure",
|
|
10073
|
+
"responsive-mismatch"
|
|
10074
|
+
],
|
|
10075
|
+
requiredThemes: [
|
|
10076
|
+
"light"
|
|
10077
|
+
],
|
|
10078
|
+
browserValidation: "required",
|
|
10079
|
+
maxInteractionLatencyMs: 160
|
|
10080
|
+
}
|
|
9601
10081
|
}
|
|
9602
|
-
return offers.slice(0, 10).map((offer, index) => {
|
|
9603
|
-
const total = offer.price.amount + offer.shipping.amount;
|
|
9604
|
-
return `${index + 1}. ${offer.title} - ${toCurrency(total)} (${offer.provider}, deal=${offer.deal_score.toFixed(2)})`;
|
|
9605
|
-
});
|
|
9606
10082
|
};
|
|
9607
|
-
|
|
9608
|
-
|
|
9609
|
-
|
|
9610
|
-
|
|
10083
|
+
|
|
10084
|
+
// skills/opendevbrowser-design-agent/assets/templates/design-contract.v1.json
|
|
10085
|
+
var design_contract_v1_default = {
|
|
10086
|
+
intent: {
|
|
10087
|
+
audience: "Operators evaluating a new OpenDevBrowser design flow",
|
|
10088
|
+
task: "Understand the primary page value and complete the intended action quickly",
|
|
10089
|
+
successCriteria: [
|
|
10090
|
+
"Primary action is obvious within 5 seconds",
|
|
10091
|
+
"Layout remains coherent on desktop, tablet, and mobile"
|
|
10092
|
+
],
|
|
10093
|
+
trustPosture: "clear and confident"
|
|
10094
|
+
},
|
|
10095
|
+
designLanguage: {
|
|
10096
|
+
direction: "product-led clarity",
|
|
10097
|
+
styleAxes: {
|
|
10098
|
+
contrast: "high",
|
|
10099
|
+
density: "airy",
|
|
10100
|
+
shapeLanguage: "rounded-structured",
|
|
10101
|
+
depth: "subtle",
|
|
10102
|
+
texture: "minimal",
|
|
10103
|
+
motion: "purposeful"
|
|
10104
|
+
},
|
|
10105
|
+
approvedLibraries: {
|
|
10106
|
+
components: [
|
|
10107
|
+
"shadcn"
|
|
10108
|
+
],
|
|
10109
|
+
icons: [
|
|
10110
|
+
"tabler"
|
|
10111
|
+
],
|
|
10112
|
+
styling: [
|
|
10113
|
+
"tailwindcss"
|
|
10114
|
+
]
|
|
10115
|
+
},
|
|
10116
|
+
semanticTokenSource: {
|
|
10117
|
+
owner: "app-shell theme provider",
|
|
10118
|
+
tokens: [
|
|
10119
|
+
"color",
|
|
10120
|
+
"typography",
|
|
10121
|
+
"spacing",
|
|
10122
|
+
"radius",
|
|
10123
|
+
"shadow",
|
|
10124
|
+
"motion"
|
|
10125
|
+
],
|
|
10126
|
+
rule: "Use semantic tokens in repeated UI; reserve raw values for rare one-off illustration"
|
|
10127
|
+
}
|
|
10128
|
+
},
|
|
10129
|
+
contentModel: {
|
|
10130
|
+
primaryMessage: "Show the core value immediately with real copy",
|
|
10131
|
+
supportingMessages: [
|
|
10132
|
+
"Reinforce trust",
|
|
10133
|
+
"Clarify the primary action",
|
|
10134
|
+
"Reduce ambiguity"
|
|
10135
|
+
],
|
|
10136
|
+
realContentRequired: true,
|
|
10137
|
+
states: [
|
|
10138
|
+
"default",
|
|
10139
|
+
"hover",
|
|
10140
|
+
"focus",
|
|
10141
|
+
"empty",
|
|
10142
|
+
"loading",
|
|
10143
|
+
"success",
|
|
10144
|
+
"error"
|
|
10145
|
+
],
|
|
10146
|
+
loadingStrategy: "Preserve the final layout with 3-6 placeholders or one section-level loader when structure cannot be previewed",
|
|
10147
|
+
emptyStateStrategy: "Explain why nothing is shown and provide the next useful action",
|
|
10148
|
+
errorStateStrategy: "Keep retry or recovery actions close to the failed region",
|
|
10149
|
+
transientFeedbackStrategy: "Use short, non-blocking overlays for confirmations instead of reflowing the main layout",
|
|
10150
|
+
avoidPlaceholderCopy: true
|
|
10151
|
+
},
|
|
10152
|
+
navigationModel: {
|
|
10153
|
+
owner: "feature shell route controller",
|
|
10154
|
+
primaryRouteModel: "One canonical route map translates tabs, selected records, and editor modes into URL-backed state",
|
|
10155
|
+
deepLinkPolicy: "Shareable tabs, filters, sort, and selected entities stay in the URL with a safe fallback when params are stale or incomplete",
|
|
10156
|
+
invalidRouteFallback: "Recover to the closest safe baseline view instead of leaving the screen in a partially initialized state",
|
|
10157
|
+
overlayEntryPoints: [
|
|
10158
|
+
"route-owned detail drawer",
|
|
10159
|
+
"feature-owned confirmation modal"
|
|
10160
|
+
]
|
|
10161
|
+
},
|
|
10162
|
+
asyncModel: {
|
|
10163
|
+
owner: "feature-local controller with URL-owned query state when sharing or refresh matters",
|
|
10164
|
+
loadTrigger: "load-on-enter for the first view; debounced restart on query, scope, or sort change",
|
|
10165
|
+
restartTriggers: [
|
|
10166
|
+
"query",
|
|
10167
|
+
"scope",
|
|
10168
|
+
"sort"
|
|
10169
|
+
],
|
|
10170
|
+
debounceMs: 250,
|
|
10171
|
+
emptyQueryBehavior: "Reset to the baseline or empty state without a remote fetch unless the product explicitly needs default results",
|
|
10172
|
+
cancellationPolicy: "Treat stale requests as normal and do not surface cancellation as a user-facing error",
|
|
10173
|
+
moveToServiceWhen: [
|
|
10174
|
+
"work must survive dismissal",
|
|
10175
|
+
"caching or retry policy becomes shared",
|
|
10176
|
+
"multiple screens depend on the same in-flight state"
|
|
10177
|
+
],
|
|
10178
|
+
urlOwnership: "Put query, filter, and sort in the URL when the state should survive refresh, sharing, or handoff"
|
|
10179
|
+
},
|
|
10180
|
+
layoutSystem: {
|
|
10181
|
+
grid: "12-column responsive grid",
|
|
10182
|
+
containers: "max-width sections with asymmetric emphasis",
|
|
10183
|
+
spacingRhythm: "8px base with larger section jumps",
|
|
10184
|
+
alignmentRules: [
|
|
10185
|
+
"Primary content aligns to a consistent reading column",
|
|
10186
|
+
"Actions stay near the message they complete"
|
|
10187
|
+
]
|
|
10188
|
+
},
|
|
10189
|
+
typographySystem: {
|
|
10190
|
+
families: [
|
|
10191
|
+
"Space Grotesk",
|
|
10192
|
+
"Source Sans 3"
|
|
10193
|
+
],
|
|
10194
|
+
scale: [
|
|
10195
|
+
"12",
|
|
10196
|
+
"14",
|
|
10197
|
+
"16",
|
|
10198
|
+
"20",
|
|
10199
|
+
"28",
|
|
10200
|
+
"40",
|
|
10201
|
+
"56"
|
|
10202
|
+
],
|
|
10203
|
+
measure: "60-72 characters for dense reading blocks",
|
|
10204
|
+
fallbackPolicy: "Use repo-native or licensed alternatives when these families are unavailable",
|
|
10205
|
+
loadingStrategy: "Avoid layout shift and keep fallback metrics close"
|
|
10206
|
+
},
|
|
10207
|
+
motionSystem: {
|
|
10208
|
+
timing: "short and decisive",
|
|
10209
|
+
reducedMotionPolicy: "Preserve meaning with reduced movement",
|
|
10210
|
+
interactionMoments: [
|
|
10211
|
+
"page entry",
|
|
10212
|
+
"section reveal",
|
|
10213
|
+
"primary CTA feedback"
|
|
10214
|
+
],
|
|
10215
|
+
parallaxPolicy: "off unless explicitly justified"
|
|
10216
|
+
},
|
|
10217
|
+
performanceModel: {
|
|
10218
|
+
renderHotspots: [
|
|
10219
|
+
"scan-heavy collection region",
|
|
10220
|
+
"secondary inspector or preview pane"
|
|
10221
|
+
],
|
|
10222
|
+
stableIdentityPolicy: "Rows, cards, tabs, and overlays use stable domain ids instead of array indexes",
|
|
10223
|
+
listStrategy: "Use the smallest structure that stays fast with realistic data; choose progressive reveal, lazy containers, or virtualization deliberately",
|
|
10224
|
+
secondaryPanelPolicy: "Heavy inspectors, previews, and editors load on demand when they are not required for first paint",
|
|
10225
|
+
measurementPlan: "Validate realistic data volume with browser traces and the framework profiler before claiming the surface is performant"
|
|
10226
|
+
},
|
|
10227
|
+
responsiveSystem: {
|
|
10228
|
+
breakpoints: [
|
|
10229
|
+
"mobile",
|
|
10230
|
+
"tablet",
|
|
10231
|
+
"desktop"
|
|
10232
|
+
],
|
|
10233
|
+
adaptationRules: [
|
|
10234
|
+
"Collapse multicolumn sections before copy becomes cramped",
|
|
10235
|
+
"Preserve primary CTA prominence on the smallest viewport"
|
|
10236
|
+
],
|
|
10237
|
+
touchPolicy: "Comfortable targets and low-friction scroll paths",
|
|
10238
|
+
overflowPolicy: "No horizontal scroll for primary content"
|
|
10239
|
+
},
|
|
10240
|
+
accessibilityPolicy: {
|
|
10241
|
+
target: "WCAG 2.2 AA",
|
|
10242
|
+
keyboardRequirements: [
|
|
10243
|
+
"Visible focus",
|
|
10244
|
+
"Logical tab order"
|
|
10245
|
+
],
|
|
10246
|
+
focusPolicy: "Focus rings must remain visible against every background",
|
|
10247
|
+
semanticRequirements: [
|
|
10248
|
+
"Landmarks are explicit",
|
|
10249
|
+
"Headings remain hierarchical"
|
|
10250
|
+
]
|
|
10251
|
+
},
|
|
10252
|
+
generationPlan: {
|
|
10253
|
+
targetOutcome: {
|
|
10254
|
+
mode: "high-fi-live-edit",
|
|
10255
|
+
summary: "Improve hierarchy, clarity, and conversion confidence"
|
|
10256
|
+
},
|
|
10257
|
+
visualDirection: {
|
|
10258
|
+
profile: "product-led-clarity",
|
|
10259
|
+
styleAxes: {
|
|
10260
|
+
contrast: "high",
|
|
10261
|
+
density: "airy"
|
|
10262
|
+
}
|
|
10263
|
+
},
|
|
10264
|
+
layoutStrategy: {
|
|
10265
|
+
approach: "hero-led-grid"
|
|
10266
|
+
},
|
|
10267
|
+
contentStrategy: {
|
|
10268
|
+
source: "real-content-first"
|
|
10269
|
+
},
|
|
10270
|
+
componentStrategy: {
|
|
10271
|
+
mode: "reuse-first",
|
|
10272
|
+
approvedLibraries: [
|
|
10273
|
+
"shadcn"
|
|
10274
|
+
]
|
|
10275
|
+
},
|
|
10276
|
+
motionPosture: {
|
|
10277
|
+
level: "subtle",
|
|
10278
|
+
allow3D: false,
|
|
10279
|
+
allowParallax: false,
|
|
10280
|
+
allowCustomSmoothScroll: false
|
|
10281
|
+
},
|
|
10282
|
+
responsivePosture: {
|
|
10283
|
+
primaryViewport: "desktop",
|
|
10284
|
+
requiredViewports: [
|
|
10285
|
+
"desktop",
|
|
10286
|
+
"tablet",
|
|
10287
|
+
"mobile"
|
|
10288
|
+
]
|
|
10289
|
+
},
|
|
10290
|
+
accessibilityPosture: {
|
|
10291
|
+
target: "WCAG_2_2_AA",
|
|
10292
|
+
reducedMotion: "required",
|
|
10293
|
+
keyboardParity: true
|
|
10294
|
+
},
|
|
10295
|
+
validationTargets: {
|
|
10296
|
+
blockOn: [
|
|
10297
|
+
"contrast-failure",
|
|
10298
|
+
"keyboard-regression",
|
|
10299
|
+
"stale-search-results",
|
|
10300
|
+
"invalid-route-recovery-failure"
|
|
10301
|
+
],
|
|
10302
|
+
warnOn: [
|
|
10303
|
+
"responsive-mismatch",
|
|
10304
|
+
"layout-shift",
|
|
10305
|
+
"spinner-stacking",
|
|
10306
|
+
"scan-surface-jank"
|
|
10307
|
+
]
|
|
10308
|
+
}
|
|
10309
|
+
}
|
|
10310
|
+
};
|
|
10311
|
+
|
|
10312
|
+
// src/providers/inspiredesign-contract.ts
|
|
10313
|
+
var BASE_CONTRACT_TEMPLATE = design_contract_v1_default;
|
|
10314
|
+
var BASE_GENERATION_PLAN = canvas_generation_plan_design_v1_default.generationPlan;
|
|
10315
|
+
var PROFILE_MATCHERS = [
|
|
10316
|
+
{ profile: "auth-focused", keywords: ["auth", "login", "signin", "sign-in", "signup", "sign-up", "onboarding"] },
|
|
10317
|
+
{ profile: "settings-system", keywords: ["settings", "preferences", "account", "profile", "billing"] },
|
|
10318
|
+
{ profile: "ops-control", keywords: ["dashboard", "admin", "control", "analytics", "monitor", "reporting"] },
|
|
10319
|
+
{ profile: "documentation", keywords: ["docs", "documentation", "knowledge base", "reference", "guide"] },
|
|
10320
|
+
{ profile: "commerce-system", keywords: ["shop", "commerce", "pricing", "checkout", "product page", "catalog"] }
|
|
10321
|
+
];
|
|
10322
|
+
var PROFILE_CONFIG = {
|
|
10323
|
+
"clean-room": {
|
|
10324
|
+
direction: "clean-room execution",
|
|
10325
|
+
visualPersonality: "disciplined, quiet, system-first",
|
|
10326
|
+
brandTone: "neutral and exacting",
|
|
10327
|
+
hierarchyPrinciples: ["Keep one message per section.", "Use spacing, not ornament, to separate priority."],
|
|
10328
|
+
interactionPhilosophy: "Minimal motion, zero ambiguity, strong focus affordances.",
|
|
10329
|
+
navigationModel: "contextual",
|
|
10330
|
+
layoutApproach: "modular-grid",
|
|
10331
|
+
pagePatterns: ["Single-message hero", "Dense decision panel", "Clean spec sheet"],
|
|
10332
|
+
componentSequence: ["Buttons", "Inputs", "Decision cards", "Structured tables"],
|
|
10333
|
+
colors: {
|
|
10334
|
+
primary: "#0F172A",
|
|
10335
|
+
accent: "#0F766E",
|
|
10336
|
+
accentSurface: "#E6FFFB",
|
|
10337
|
+
background: "#F8FAFC",
|
|
10338
|
+
surface: "#FFFFFF",
|
|
10339
|
+
border: "#CBD5E1",
|
|
10340
|
+
text: "#0F172A",
|
|
10341
|
+
mutedText: "#475569",
|
|
10342
|
+
success: "#15803D",
|
|
10343
|
+
warning: "#B45309",
|
|
10344
|
+
danger: "#B91C1C"
|
|
10345
|
+
}
|
|
10346
|
+
},
|
|
10347
|
+
"cinematic-minimal": {
|
|
10348
|
+
direction: "cinematic restraint",
|
|
10349
|
+
visualPersonality: "dramatic, sparse, image-led",
|
|
10350
|
+
brandTone: "premium and deliberate",
|
|
10351
|
+
hierarchyPrinciples: ["Let the visual plane carry atmosphere.", "Keep copy short and decisive."],
|
|
10352
|
+
interactionPhilosophy: "Use motion for presence, not explanation.",
|
|
10353
|
+
navigationModel: "immersive",
|
|
10354
|
+
layoutApproach: "full-bleed-hero",
|
|
10355
|
+
pagePatterns: ["Full-bleed hero", "Editorial feature strip", "High-contrast CTA block"],
|
|
10356
|
+
componentSequence: ["Hero shell", "CTA buttons", "Image-led sections", "Minimal footer"],
|
|
10357
|
+
colors: {
|
|
10358
|
+
primary: "#111827",
|
|
10359
|
+
accent: "#C2410C",
|
|
10360
|
+
accentSurface: "#FFF7ED",
|
|
10361
|
+
background: "#F8F5F0",
|
|
10362
|
+
surface: "#FFFFFF",
|
|
10363
|
+
border: "#D6D3D1",
|
|
10364
|
+
text: "#111827",
|
|
10365
|
+
mutedText: "#57534E",
|
|
10366
|
+
success: "#15803D",
|
|
10367
|
+
warning: "#B45309",
|
|
10368
|
+
danger: "#B91C1C"
|
|
10369
|
+
}
|
|
10370
|
+
},
|
|
10371
|
+
"product-story": {
|
|
10372
|
+
direction: "product-led clarity",
|
|
10373
|
+
visualPersonality: "confident, editorial, product-first",
|
|
10374
|
+
brandTone: "clear and ambitious",
|
|
10375
|
+
hierarchyPrinciples: ["Lead with value before proof.", "Keep action close to the message it completes."],
|
|
10376
|
+
interactionPhilosophy: "Short, decisive motion with obvious focus states.",
|
|
10377
|
+
navigationModel: "global-header",
|
|
10378
|
+
layoutApproach: "hero-led-grid",
|
|
10379
|
+
pagePatterns: ["Hero with anchored CTA", "Feature narrative strip", "Proof and conversion band"],
|
|
10380
|
+
componentSequence: ["Hero", "Buttons", "Cards", "Feature sections", "Footer"],
|
|
10381
|
+
colors: {
|
|
10382
|
+
primary: "#0B6BFF",
|
|
10383
|
+
accent: "#F97316",
|
|
10384
|
+
accentSurface: "#FFF7ED",
|
|
10385
|
+
background: "#F5F7FB",
|
|
10386
|
+
surface: "#FFFFFF",
|
|
10387
|
+
border: "#D7E3F4",
|
|
10388
|
+
text: "#111827",
|
|
10389
|
+
mutedText: "#475569",
|
|
10390
|
+
success: "#15803D",
|
|
10391
|
+
warning: "#B45309",
|
|
10392
|
+
danger: "#B91C1C"
|
|
10393
|
+
}
|
|
10394
|
+
},
|
|
10395
|
+
"commerce-system": {
|
|
10396
|
+
direction: "trust-driven commerce",
|
|
10397
|
+
visualPersonality: "decisive, reassuring, conversion-aware",
|
|
10398
|
+
brandTone: "credible and practical",
|
|
10399
|
+
hierarchyPrinciples: ["Keep purchasing signals scannable.", "Surface trust proof before commitment moments."],
|
|
10400
|
+
interactionPhilosophy: "Fast feedback, strong affordances, no ambiguous states.",
|
|
10401
|
+
navigationModel: "global-header",
|
|
10402
|
+
layoutApproach: "commerce-grid",
|
|
10403
|
+
pagePatterns: ["Merchandising hero", "Offer comparison band", "Decision-support detail section"],
|
|
10404
|
+
componentSequence: ["Hero", "Offer cards", "Buttons", "Trust badges", "Comparison table"],
|
|
10405
|
+
colors: {
|
|
10406
|
+
primary: "#0F766E",
|
|
10407
|
+
accent: "#D97706",
|
|
10408
|
+
accentSurface: "#FFFBEB",
|
|
10409
|
+
background: "#F8FAFC",
|
|
10410
|
+
surface: "#FFFFFF",
|
|
10411
|
+
border: "#D1D5DB",
|
|
10412
|
+
text: "#111827",
|
|
10413
|
+
mutedText: "#4B5563",
|
|
10414
|
+
success: "#15803D",
|
|
10415
|
+
warning: "#B45309",
|
|
10416
|
+
danger: "#B91C1C"
|
|
10417
|
+
}
|
|
10418
|
+
},
|
|
10419
|
+
"control-room": {
|
|
10420
|
+
direction: "high-signal control room",
|
|
10421
|
+
visualPersonality: "dense, sharp, operational",
|
|
10422
|
+
brandTone: "authoritative and fast",
|
|
10423
|
+
hierarchyPrinciples: ["Use structure to reduce scanning cost.", "Separate primary metrics from diagnostics."],
|
|
10424
|
+
interactionPhilosophy: "Fast updates, explicit states, motion only when it clarifies change.",
|
|
10425
|
+
navigationModel: "sidebar",
|
|
10426
|
+
layoutApproach: "panel-grid",
|
|
10427
|
+
pagePatterns: ["Metric summary rail", "Split-pane workspace", "Diagnostic detail panel"],
|
|
10428
|
+
componentSequence: ["Sidebar", "Stat blocks", "Tables", "Filters", "Panels"],
|
|
10429
|
+
colors: {
|
|
10430
|
+
primary: "#155EEF",
|
|
10431
|
+
accent: "#0F766E",
|
|
10432
|
+
accentSurface: "#ECFDF3",
|
|
10433
|
+
background: "#F8FAFC",
|
|
10434
|
+
surface: "#FFFFFF",
|
|
10435
|
+
border: "#CBD5E1",
|
|
10436
|
+
text: "#0F172A",
|
|
10437
|
+
mutedText: "#475569",
|
|
10438
|
+
success: "#15803D",
|
|
10439
|
+
warning: "#B45309",
|
|
10440
|
+
danger: "#B91C1C"
|
|
10441
|
+
}
|
|
10442
|
+
},
|
|
10443
|
+
"ops-control": {
|
|
10444
|
+
direction: "operational precision",
|
|
10445
|
+
visualPersonality: "structured, dense, high-confidence",
|
|
10446
|
+
brandTone: "decisive and exact",
|
|
10447
|
+
hierarchyPrinciples: ["Pin the primary metric and action path.", "Separate overview from detail panes."],
|
|
10448
|
+
interactionPhilosophy: "Low-latency controls, strong state contrast, keyboard-friendly flows.",
|
|
10449
|
+
navigationModel: "sidebar",
|
|
10450
|
+
layoutApproach: "workspace-shell",
|
|
10451
|
+
pagePatterns: ["KPI overview bar", "Filterable data shell", "Detail drawer or inspector"],
|
|
10452
|
+
componentSequence: ["Sidebar", "Toolbar", "Data table", "Filters", "Detail panel"],
|
|
10453
|
+
colors: {
|
|
10454
|
+
primary: "#155EEF",
|
|
10455
|
+
accent: "#0891B2",
|
|
10456
|
+
accentSurface: "#ECFEFF",
|
|
10457
|
+
background: "#F8FAFC",
|
|
10458
|
+
surface: "#FFFFFF",
|
|
10459
|
+
border: "#CBD5E1",
|
|
10460
|
+
text: "#0F172A",
|
|
10461
|
+
mutedText: "#475569",
|
|
10462
|
+
success: "#15803D",
|
|
10463
|
+
warning: "#B45309",
|
|
10464
|
+
danger: "#B91C1C"
|
|
10465
|
+
}
|
|
10466
|
+
},
|
|
10467
|
+
"auth-focused": {
|
|
10468
|
+
direction: "trust-forward entry flow",
|
|
10469
|
+
visualPersonality: "calm, direct, reassuring",
|
|
10470
|
+
brandTone: "safe and premium",
|
|
10471
|
+
hierarchyPrinciples: ["One job per screen.", "Trust and recovery paths must be visible without clutter."],
|
|
10472
|
+
interactionPhilosophy: "Low-friction focus flow with immediate validation feedback.",
|
|
10473
|
+
navigationModel: "contextual",
|
|
10474
|
+
layoutApproach: "two-panel-auth",
|
|
10475
|
+
pagePatterns: ["Auth split layout", "Trust panel", "Recovery and help strip"],
|
|
10476
|
+
componentSequence: ["Auth form", "Inputs", "Buttons", "Alerts", "Trust panel"],
|
|
10477
|
+
colors: {
|
|
10478
|
+
primary: "#1D4ED8",
|
|
10479
|
+
accent: "#0F766E",
|
|
10480
|
+
accentSurface: "#ECFDF5",
|
|
10481
|
+
background: "#F8FAFC",
|
|
10482
|
+
surface: "#FFFFFF",
|
|
10483
|
+
border: "#D1D5DB",
|
|
10484
|
+
text: "#111827",
|
|
10485
|
+
mutedText: "#4B5563",
|
|
10486
|
+
success: "#15803D",
|
|
10487
|
+
warning: "#B45309",
|
|
10488
|
+
danger: "#B91C1C"
|
|
10489
|
+
}
|
|
10490
|
+
},
|
|
10491
|
+
"settings-system": {
|
|
10492
|
+
direction: "calm settings system",
|
|
10493
|
+
visualPersonality: "ordered, practical, quietly premium",
|
|
10494
|
+
brandTone: "confident and low-friction",
|
|
10495
|
+
hierarchyPrinciples: ["Group related decisions tightly.", "Keep destructive actions isolated and explicit."],
|
|
10496
|
+
interactionPhilosophy: "Prefer clear toggles and inline explanations over hidden complexity.",
|
|
10497
|
+
navigationModel: "tabbed",
|
|
10498
|
+
layoutApproach: "settings-grid",
|
|
10499
|
+
pagePatterns: ["Sectioned settings page", "Inline form groups", "Preference summary rail"],
|
|
10500
|
+
componentSequence: ["Tabs", "Forms", "Inputs", "Alerts", "Confirmation modal"],
|
|
10501
|
+
colors: {
|
|
10502
|
+
primary: "#1D4ED8",
|
|
10503
|
+
accent: "#0F766E",
|
|
10504
|
+
accentSurface: "#ECFDF5",
|
|
10505
|
+
background: "#F8FAFC",
|
|
10506
|
+
surface: "#FFFFFF",
|
|
10507
|
+
border: "#D1D5DB",
|
|
10508
|
+
text: "#111827",
|
|
10509
|
+
mutedText: "#475569",
|
|
10510
|
+
success: "#15803D",
|
|
10511
|
+
warning: "#B45309",
|
|
10512
|
+
danger: "#B91C1C"
|
|
10513
|
+
}
|
|
10514
|
+
},
|
|
10515
|
+
"documentation": {
|
|
10516
|
+
direction: "reference-first documentation",
|
|
10517
|
+
visualPersonality: "legible, calm, highly structured",
|
|
10518
|
+
brandTone: "expert and accessible",
|
|
10519
|
+
hierarchyPrinciples: ["Make scanning effortless.", "Keep code, steps, and warnings visually distinct."],
|
|
10520
|
+
interactionPhilosophy: "Light motion, sticky wayfinding, strong anchor visibility.",
|
|
10521
|
+
navigationModel: "sidebar",
|
|
10522
|
+
layoutApproach: "docs-shell",
|
|
10523
|
+
pagePatterns: ["Docs shell", "Procedure section", "Reference table block"],
|
|
10524
|
+
componentSequence: ["Sidebar", "Search", "Anchored headings", "Code blocks", "Callouts"],
|
|
10525
|
+
colors: {
|
|
10526
|
+
primary: "#1D4ED8",
|
|
10527
|
+
accent: "#0F766E",
|
|
10528
|
+
accentSurface: "#ECFDF5",
|
|
10529
|
+
background: "#F8FAFC",
|
|
10530
|
+
surface: "#FFFFFF",
|
|
10531
|
+
border: "#CBD5E1",
|
|
10532
|
+
text: "#0F172A",
|
|
10533
|
+
mutedText: "#475569",
|
|
10534
|
+
success: "#15803D",
|
|
10535
|
+
warning: "#B45309",
|
|
10536
|
+
danger: "#B91C1C"
|
|
10537
|
+
}
|
|
10538
|
+
}
|
|
10539
|
+
};
|
|
10540
|
+
var trimText = (value) => {
|
|
10541
|
+
return value.trim().replace(/\s+/g, " ");
|
|
10542
|
+
};
|
|
10543
|
+
var clipText = (value, maxLength) => {
|
|
10544
|
+
if (value.length <= maxLength) return value;
|
|
10545
|
+
return `${value.slice(0, Math.max(0, maxLength - 3)).trimEnd()}...`;
|
|
10546
|
+
};
|
|
10547
|
+
var cloneTemplate = (value) => structuredClone(value);
|
|
10548
|
+
var referenceFingerprint = (value) => {
|
|
10549
|
+
return createHash3("sha256").update(value).digest("hex").slice(0, 12);
|
|
10550
|
+
};
|
|
10551
|
+
var hasKeyword = (value, keywords) => {
|
|
10552
|
+
const haystack = value.toLowerCase();
|
|
10553
|
+
return keywords.some((keyword) => haystack.includes(keyword));
|
|
10554
|
+
};
|
|
10555
|
+
var classifyProfile = (brief, references) => {
|
|
10556
|
+
const combined = [brief, ...references.map((reference) => `${reference.title ?? ""} ${reference.excerpt ?? ""}`)].join(" ").toLowerCase();
|
|
10557
|
+
return PROFILE_MATCHERS.find((matcher) => hasKeyword(combined, matcher.keywords))?.profile ?? "product-story";
|
|
10558
|
+
};
|
|
10559
|
+
var resolveThemeStrategy = (brief, references) => {
|
|
10560
|
+
const combined = `${brief} ${references.map((reference) => reference.excerpt ?? "").join(" ")}`.toLowerCase();
|
|
10561
|
+
return combined.includes("dark") ? "light-dark-parity" : "single-theme";
|
|
10562
|
+
};
|
|
10563
|
+
var summarizeBrief = (brief) => {
|
|
10564
|
+
const normalized = trimText(brief);
|
|
10565
|
+
const sentence = normalized.split(/[.!?]/).map((part) => part.trim()).find(Boolean);
|
|
10566
|
+
return clipText(sentence ?? normalized, 140);
|
|
10567
|
+
};
|
|
10568
|
+
var buildSupportingMessages = (references) => {
|
|
10569
|
+
const messages = references.map((reference) => reference.title ?? reference.excerpt ?? "").map((value) => clipText(trimText(value), 72)).filter((value) => value.length > 0);
|
|
10570
|
+
return messages.slice(0, 3);
|
|
10571
|
+
};
|
|
10572
|
+
var buildGenerationPlan = (brief, profile, references) => {
|
|
10573
|
+
const plan = cloneTemplate(BASE_GENERATION_PLAN);
|
|
10574
|
+
plan.targetOutcome.summary = summarizeBrief(brief);
|
|
10575
|
+
plan.visualDirection.profile = profile;
|
|
10576
|
+
plan.visualDirection.themeStrategy = resolveThemeStrategy(brief, references);
|
|
10577
|
+
plan.layoutStrategy.approach = PROFILE_CONFIG[profile].layoutApproach;
|
|
10578
|
+
plan.layoutStrategy.navigationModel = PROFILE_CONFIG[profile].navigationModel;
|
|
10579
|
+
plan.componentStrategy.interactionStates = ["default", "hover", "focus", "disabled", "loading"];
|
|
10580
|
+
plan.validationTargets.requiredThemes = plan.visualDirection.themeStrategy === "light-dark-parity" ? ["light", "dark"] : ["light"];
|
|
10581
|
+
return plan;
|
|
10582
|
+
};
|
|
10583
|
+
var buildIntentBlock = (brief, urls, references) => {
|
|
10584
|
+
const intent = cloneTemplate(BASE_CONTRACT_TEMPLATE.intent);
|
|
10585
|
+
return {
|
|
10586
|
+
...intent,
|
|
10587
|
+
task: summarizeBrief(brief),
|
|
10588
|
+
brief,
|
|
10589
|
+
briefHash: referenceFingerprint(brief),
|
|
10590
|
+
referenceCount: references.length,
|
|
10591
|
+
referenceUrls: urls,
|
|
10592
|
+
evidenceStatus: {
|
|
10593
|
+
fetched: references.filter((reference) => reference.fetchStatus === "captured").length,
|
|
10594
|
+
captured: references.filter((reference) => reference.captureStatus === "captured").length
|
|
10595
|
+
}
|
|
10596
|
+
};
|
|
10597
|
+
};
|
|
10598
|
+
var buildDesignLanguageBlock = (profile) => {
|
|
10599
|
+
const block = cloneTemplate(BASE_CONTRACT_TEMPLATE.designLanguage);
|
|
10600
|
+
const config = PROFILE_CONFIG[profile];
|
|
10601
|
+
return {
|
|
10602
|
+
...block,
|
|
10603
|
+
direction: config.direction,
|
|
10604
|
+
visualPersonality: config.visualPersonality,
|
|
10605
|
+
brandTone: config.brandTone
|
|
10606
|
+
};
|
|
10607
|
+
};
|
|
10608
|
+
var buildContentModelBlock = (brief, references) => {
|
|
10609
|
+
const block = cloneTemplate(BASE_CONTRACT_TEMPLATE.contentModel);
|
|
10610
|
+
return {
|
|
10611
|
+
...block,
|
|
10612
|
+
primaryMessage: summarizeBrief(brief),
|
|
10613
|
+
supportingMessages: buildSupportingMessages(references)
|
|
10614
|
+
};
|
|
10615
|
+
};
|
|
10616
|
+
var buildLayoutSystemBlock = (profile) => {
|
|
10617
|
+
const block = cloneTemplate(BASE_CONTRACT_TEMPLATE.layoutSystem);
|
|
10618
|
+
return {
|
|
10619
|
+
...block,
|
|
10620
|
+
pagePatterns: PROFILE_CONFIG[profile].pagePatterns
|
|
10621
|
+
};
|
|
10622
|
+
};
|
|
10623
|
+
var buildTypographySystemBlock = () => {
|
|
10624
|
+
const block = cloneTemplate(BASE_CONTRACT_TEMPLATE.typographySystem);
|
|
10625
|
+
return {
|
|
10626
|
+
...block,
|
|
10627
|
+
tokens: {
|
|
10628
|
+
display: "56/1.0",
|
|
10629
|
+
h1: "40/1.05",
|
|
10630
|
+
h2: "28/1.1",
|
|
10631
|
+
h3: "20/1.2",
|
|
10632
|
+
body: "16/1.6",
|
|
10633
|
+
label: "14/1.4",
|
|
10634
|
+
caption: "12/1.4"
|
|
10635
|
+
}
|
|
10636
|
+
};
|
|
10637
|
+
};
|
|
10638
|
+
var buildColorSystemBlock = (profile) => {
|
|
10639
|
+
const colors = PROFILE_CONFIG[profile].colors;
|
|
10640
|
+
return {
|
|
10641
|
+
paletteName: `${profile}-default`,
|
|
10642
|
+
tokens: colors,
|
|
10643
|
+
contrastRequirements: {
|
|
10644
|
+
bodyText: "4.5:1",
|
|
10645
|
+
largeText: "3:1",
|
|
10646
|
+
focusRing: "3:1"
|
|
10647
|
+
}
|
|
10648
|
+
};
|
|
10649
|
+
};
|
|
10650
|
+
var buildSurfaceSystemBlock = () => ({
|
|
10651
|
+
radiusScale: {
|
|
10652
|
+
xs: "6px",
|
|
10653
|
+
sm: "10px",
|
|
10654
|
+
md: "16px",
|
|
10655
|
+
lg: "24px"
|
|
10656
|
+
},
|
|
10657
|
+
borderPolicy: "Use 1px neutral strokes before adding elevation.",
|
|
10658
|
+
shadowPolicy: {
|
|
10659
|
+
sm: "0 1px 2px rgba(15, 23, 42, 0.06)",
|
|
10660
|
+
md: "0 10px 30px rgba(15, 23, 42, 0.10)",
|
|
10661
|
+
lg: "0 24px 60px rgba(15, 23, 42, 0.14)"
|
|
10662
|
+
}
|
|
10663
|
+
});
|
|
10664
|
+
var buildIconSystemBlock = () => ({
|
|
10665
|
+
family: "tabler",
|
|
10666
|
+
strokeWidth: 1.5,
|
|
10667
|
+
style: "rounded-linear",
|
|
10668
|
+
usageRules: [
|
|
10669
|
+
"Use icons to reinforce labels, not replace them.",
|
|
10670
|
+
"Decorative icons should remain visually lighter than primary copy."
|
|
10671
|
+
]
|
|
10672
|
+
});
|
|
10673
|
+
var buildMotionSystemBlock = () => {
|
|
10674
|
+
const block = cloneTemplate(BASE_CONTRACT_TEMPLATE.motionSystem);
|
|
10675
|
+
return {
|
|
10676
|
+
...block,
|
|
10677
|
+
durations: {
|
|
10678
|
+
quick: "120ms",
|
|
10679
|
+
standard: "180ms",
|
|
10680
|
+
emphasis: "240ms"
|
|
10681
|
+
}
|
|
10682
|
+
};
|
|
10683
|
+
};
|
|
10684
|
+
var buildResponsiveSystemBlock = () => {
|
|
10685
|
+
const block = cloneTemplate(BASE_CONTRACT_TEMPLATE.responsiveSystem);
|
|
10686
|
+
return {
|
|
10687
|
+
...block,
|
|
10688
|
+
breakpoints: {
|
|
10689
|
+
mobile: "0-639px",
|
|
10690
|
+
tablet: "640-1023px",
|
|
10691
|
+
desktop: "1024px+"
|
|
10692
|
+
}
|
|
10693
|
+
};
|
|
10694
|
+
};
|
|
10695
|
+
var buildAccessibilityBlock = () => {
|
|
10696
|
+
const block = cloneTemplate(BASE_CONTRACT_TEMPLATE.accessibilityPolicy);
|
|
10697
|
+
return {
|
|
10698
|
+
...block,
|
|
10699
|
+
reducedMotion: "Respect user preference and preserve information without animation."
|
|
10700
|
+
};
|
|
10701
|
+
};
|
|
10702
|
+
var buildLibraryPolicyBlock = () => ({
|
|
10703
|
+
components: ["shadcn"],
|
|
10704
|
+
icons: ["tabler"],
|
|
10705
|
+
styling: ["tailwindcss"],
|
|
10706
|
+
motion: ["css"],
|
|
10707
|
+
threeD: []
|
|
10708
|
+
});
|
|
10709
|
+
var buildRuntimeBudgetsBlock = (plan) => ({
|
|
10710
|
+
maxHeroActions: 2,
|
|
10711
|
+
maxPrimarySections: 8,
|
|
10712
|
+
maxInteractionLatencyMs: plan.validationTargets.maxInteractionLatencyMs,
|
|
10713
|
+
previewBudgetMs: 1500,
|
|
10714
|
+
notes: [
|
|
10715
|
+
"Keep above-the-fold content inside one visual composition.",
|
|
10716
|
+
"Avoid heavyweight decorative animation before interaction clarity is established."
|
|
10717
|
+
]
|
|
10718
|
+
});
|
|
10719
|
+
var buildDesignContract = (brief, urls, references, plan) => ({
|
|
10720
|
+
intent: buildIntentBlock(brief, urls, references),
|
|
10721
|
+
generationPlan: plan,
|
|
10722
|
+
designLanguage: buildDesignLanguageBlock(plan.visualDirection.profile),
|
|
10723
|
+
contentModel: buildContentModelBlock(brief, references),
|
|
10724
|
+
layoutSystem: buildLayoutSystemBlock(plan.visualDirection.profile),
|
|
10725
|
+
typographySystem: buildTypographySystemBlock(),
|
|
10726
|
+
colorSystem: buildColorSystemBlock(plan.visualDirection.profile),
|
|
10727
|
+
surfaceSystem: buildSurfaceSystemBlock(),
|
|
10728
|
+
iconSystem: buildIconSystemBlock(),
|
|
10729
|
+
motionSystem: buildMotionSystemBlock(),
|
|
10730
|
+
responsiveSystem: buildResponsiveSystemBlock(),
|
|
10731
|
+
accessibilityPolicy: buildAccessibilityBlock(),
|
|
10732
|
+
libraryPolicy: buildLibraryPolicyBlock(),
|
|
10733
|
+
runtimeBudgets: buildRuntimeBudgetsBlock(plan)
|
|
10734
|
+
});
|
|
10735
|
+
var buildTokenStrategy = (profile) => ({
|
|
10736
|
+
colors: PROFILE_CONFIG[profile].colors,
|
|
10737
|
+
typography: {
|
|
10738
|
+
display: "font-display text-[56px] leading-[1.0]",
|
|
10739
|
+
h1: "font-display text-[40px] leading-[1.05]",
|
|
10740
|
+
h2: "font-display text-[28px] leading-[1.1]",
|
|
10741
|
+
h3: "font-display text-[20px] leading-[1.2]",
|
|
10742
|
+
body: "font-body text-[16px] leading-[1.6]",
|
|
10743
|
+
label: "font-body text-[14px] leading-[1.4]",
|
|
10744
|
+
caption: "font-body text-[12px] leading-[1.4]"
|
|
10745
|
+
},
|
|
10746
|
+
spacing: {
|
|
10747
|
+
xs: "4px",
|
|
10748
|
+
sm: "8px",
|
|
10749
|
+
md: "16px",
|
|
10750
|
+
lg: "24px",
|
|
10751
|
+
xl: "40px",
|
|
10752
|
+
section: "96px"
|
|
10753
|
+
},
|
|
10754
|
+
radius: {
|
|
10755
|
+
xs: "6px",
|
|
10756
|
+
sm: "10px",
|
|
10757
|
+
md: "16px",
|
|
10758
|
+
lg: "24px"
|
|
10759
|
+
},
|
|
10760
|
+
shadow: {
|
|
10761
|
+
sm: "0 1px 2px rgba(15, 23, 42, 0.06)",
|
|
10762
|
+
md: "0 10px 30px rgba(15, 23, 42, 0.10)",
|
|
10763
|
+
lg: "0 24px 60px rgba(15, 23, 42, 0.14)"
|
|
10764
|
+
},
|
|
10765
|
+
motion: {
|
|
10766
|
+
quick: "120ms ease-out",
|
|
10767
|
+
standard: "180ms ease-out",
|
|
10768
|
+
emphasis: "240ms cubic-bezier(0.22, 1, 0.36, 1)"
|
|
10769
|
+
},
|
|
10770
|
+
zIndex: {
|
|
10771
|
+
base: 0,
|
|
10772
|
+
sticky: 20,
|
|
10773
|
+
overlay: 40,
|
|
10774
|
+
modal: 60,
|
|
10775
|
+
toast: 70
|
|
10776
|
+
},
|
|
10777
|
+
breakpoints: {
|
|
10778
|
+
mobile: "640px",
|
|
10779
|
+
tablet: "1024px",
|
|
10780
|
+
desktop: "1280px"
|
|
10781
|
+
}
|
|
10782
|
+
});
|
|
10783
|
+
var buildComponentBuildPlan = (profile) => {
|
|
10784
|
+
return PROFILE_CONFIG[profile].componentSequence.map((name) => ({
|
|
10785
|
+
name,
|
|
10786
|
+
purpose: `Establish the ${name.toLowerCase()} pattern as a reusable system primitive.`,
|
|
10787
|
+
states: ["default", "hover", "focus", "disabled"],
|
|
10788
|
+
implementationNote: "Use semantic tokens first and keep copy/state logic outside the visual component."
|
|
10789
|
+
}));
|
|
10790
|
+
};
|
|
10791
|
+
var buildImplementationPlan = (brief, profile, references) => ({
|
|
10792
|
+
architectureRecommendation: "Implement the surface as token-first components using shared semantic CSS variables, then compose page sections from those primitives before adding any page-specific polish.",
|
|
10793
|
+
tokenStrategy: buildTokenStrategy(profile),
|
|
10794
|
+
componentBuildPlan: buildComponentBuildPlan(profile),
|
|
10795
|
+
pageAssemblyPlan: [
|
|
10796
|
+
"Start with the shell and primary navigation pattern.",
|
|
10797
|
+
"Compose the hero or primary decision section before supporting sections.",
|
|
10798
|
+
"Add proof, utility, and footer sections only after the top-level hierarchy is stable."
|
|
10799
|
+
],
|
|
10800
|
+
stateAndInteractionPlan: [
|
|
10801
|
+
"Keep hover, focus, loading, success, and error states visually distinct.",
|
|
10802
|
+
"Preserve layout during loading and keep transient confirmations out of the main flow.",
|
|
10803
|
+
"Use reduced-motion-safe transitions for reveals and CTA feedback."
|
|
10804
|
+
],
|
|
10805
|
+
accessibilityChecklist: [
|
|
10806
|
+
"Maintain 4.5:1 body text contrast across all surfaces.",
|
|
10807
|
+
"Preserve visible focus rings on every interactive element.",
|
|
10808
|
+
"Keep landmarks and heading levels explicit and sequential."
|
|
10809
|
+
],
|
|
10810
|
+
responsiveChecklist: [
|
|
10811
|
+
"Collapse multicolumn layouts before text measure becomes cramped.",
|
|
10812
|
+
"Keep the primary CTA visible without overlap on narrow screens.",
|
|
10813
|
+
"Avoid horizontal scrolling for primary content."
|
|
10814
|
+
],
|
|
10815
|
+
risksAndAmbiguities: [
|
|
10816
|
+
references.length === 0 ? "No live references were supplied, so visual cues are derived entirely from the written brief." : "Live references were reduced into reusable patterns; unique brand assets should still be recreated, not copied.",
|
|
10817
|
+
"Any missing interaction states must be validated during visual QA."
|
|
10818
|
+
],
|
|
10819
|
+
buildSequence: [
|
|
10820
|
+
"Define semantic tokens and typography.",
|
|
10821
|
+
"Build the shell, navigation, and primary CTA components.",
|
|
10822
|
+
"Implement section-level patterns and proof blocks.",
|
|
10823
|
+
"Add loading, empty, and error states.",
|
|
10824
|
+
"Run accessibility, responsive, and browser QA before final polish."
|
|
10825
|
+
]
|
|
10826
|
+
});
|
|
10827
|
+
var formatBulletList = (items) => items.map((item) => `- ${item}`).join("\n");
|
|
10828
|
+
var formatRecordList = (record) => {
|
|
10829
|
+
return Object.entries(record).map(([key, value]) => `- \`${key}\`: ${value}`).join("\n");
|
|
10830
|
+
};
|
|
10831
|
+
var referenceContribution = (reference) => {
|
|
10832
|
+
if (reference.captureStatus === "captured") return "Live hierarchy and component evidence captured from the page.";
|
|
10833
|
+
if (reference.fetchStatus === "captured") return "Content and structural cues inferred from fetched page data.";
|
|
10834
|
+
return "Only operator brief context was available for this reference.";
|
|
10835
|
+
};
|
|
10836
|
+
var referenceMotionNote = (reference) => {
|
|
10837
|
+
if (reference.capture?.snapshot?.warnings?.length) {
|
|
10838
|
+
return `Capture warnings: ${reference.capture.snapshot.warnings.join(", ")}`;
|
|
10839
|
+
}
|
|
10840
|
+
if (reference.captureStatus === "captured") return "Motion should remain subtle until validated against the live capture.";
|
|
10841
|
+
return "Motion is inferred from the brief rather than directly observed.";
|
|
10842
|
+
};
|
|
10843
|
+
var renderReferenceMarkdown = (reference, index) => {
|
|
10844
|
+
const excerpt = reference.excerpt ? clipText(reference.excerpt, 220) : "No fetched excerpt captured.";
|
|
10845
|
+
const title = reference.title ?? reference.url;
|
|
10846
|
+
return [
|
|
10847
|
+
`### Source ${index + 1}: ${title}`,
|
|
10848
|
+
`- what it contributes: ${referenceContribution(reference)}`,
|
|
10849
|
+
`- notable UI patterns: ${reference.capture?.snapshot ? "Primary hierarchy and actionables were captured from the live page." : "Patterns inferred from brief and fetched content."}`,
|
|
10850
|
+
`- typography observations: ${reference.title ? "Headline density and copy hierarchy were inferred from the fetched title and excerpt." : "Typography is inferred."}`,
|
|
10851
|
+
`- color and theme observations: ${reference.captureStatus === "captured" ? "Color posture should be validated against the captured page before cloning brand treatment." : "Color posture remains a synthesis decision."}`,
|
|
10852
|
+
`- layout and hierarchy observations: ${reference.capture?.snapshot ? clipText(reference.capture.snapshot.content, 180) : excerpt}`,
|
|
10853
|
+
`- component patterns: ${reference.capture?.clone ? "Buttons, cards, or layout wrappers can be inferred from the captured clone preview." : "Component families were inferred from available reference text."}`,
|
|
10854
|
+
`- motion/interaction observations: ${referenceMotionNote(reference)}`,
|
|
10855
|
+
`- accessibility/responsiveness notes: ${reference.captureStatus === "captured" ? "Validate focus order, CTA prominence, and stacked layouts during build QA." : "Accessibility and responsiveness are inferred from system defaults."}`,
|
|
10856
|
+
`- what should be adopted, adapted, or avoided: adopt layout hierarchy, adapt it to the new brand tokens, avoid copying proprietary copy or visual assets directly.`
|
|
10857
|
+
].join("\n");
|
|
10858
|
+
};
|
|
10859
|
+
var resolveProfileConfigFromGenerationPlan = (generationPlan) => {
|
|
10860
|
+
if (!generationPlan || typeof generationPlan !== "object" || !("visualDirection" in generationPlan)) {
|
|
10861
|
+
throw new Error("Inspiredesign design contract requires a generation plan.");
|
|
10862
|
+
}
|
|
10863
|
+
const visualDirection = generationPlan.visualDirection;
|
|
10864
|
+
if (!visualDirection || typeof visualDirection !== "object" || !("profile" in visualDirection)) {
|
|
10865
|
+
throw new Error("Inspiredesign design contract requires a visual direction profile.");
|
|
10866
|
+
}
|
|
10867
|
+
const profile = visualDirection.profile;
|
|
10868
|
+
if (typeof profile !== "string" || !(profile in PROFILE_CONFIG)) {
|
|
10869
|
+
throw new Error("Inspiredesign design contract profile is invalid.");
|
|
10870
|
+
}
|
|
10871
|
+
return PROFILE_CONFIG[profile];
|
|
10872
|
+
};
|
|
10873
|
+
var renderGovernanceMarkdown = (designContract, implementationPlan) => {
|
|
10874
|
+
const profileConfig = resolveProfileConfigFromGenerationPlan(designContract.generationPlan);
|
|
10875
|
+
return [
|
|
10876
|
+
"## 4.1 Design Intent",
|
|
10877
|
+
formatBulletList([
|
|
10878
|
+
`Purpose: ${designContract.intent.task || ""}`,
|
|
10879
|
+
"Capture the reusable visual logic from the references without cloning proprietary brand assets.",
|
|
10880
|
+
"Keep the resulting system executable for downstream build agents."
|
|
10881
|
+
]),
|
|
10882
|
+
"",
|
|
10883
|
+
"## 4.2 Core UX Principles",
|
|
10884
|
+
formatBulletList(profileConfig.hierarchyPrinciples),
|
|
10885
|
+
"",
|
|
10886
|
+
"## 4.3 Visual Identity",
|
|
10887
|
+
formatBulletList([
|
|
10888
|
+
`Aesthetic style: ${profileConfig.visualPersonality}`,
|
|
10889
|
+
`Brand tone: ${profileConfig.brandTone}`,
|
|
10890
|
+
`Quality posture: ${profileConfig.direction}`,
|
|
10891
|
+
"Direction: modern, system-led, and implementation-aware."
|
|
10892
|
+
]),
|
|
10893
|
+
"",
|
|
10894
|
+
"## 4.4 Color System",
|
|
10895
|
+
formatRecordList(implementationPlan.tokenStrategy.colors),
|
|
10896
|
+
"",
|
|
10897
|
+
"## 4.5 Typography System",
|
|
10898
|
+
formatRecordList(implementationPlan.tokenStrategy.typography),
|
|
10899
|
+
"",
|
|
10900
|
+
"## 4.6 Spacing and Layout System",
|
|
10901
|
+
formatRecordList(implementationPlan.tokenStrategy.spacing),
|
|
10902
|
+
"",
|
|
10903
|
+
"## 4.7 Shape, Border, and Elevation Rules",
|
|
10904
|
+
[
|
|
10905
|
+
formatRecordList(implementationPlan.tokenStrategy.radius),
|
|
10906
|
+
formatRecordList(implementationPlan.tokenStrategy.shadow)
|
|
10907
|
+
].join("\n"),
|
|
10908
|
+
"",
|
|
10909
|
+
"## 4.8 Motion and Interaction Rules",
|
|
10910
|
+
formatRecordList(implementationPlan.tokenStrategy.motion),
|
|
10911
|
+
"",
|
|
10912
|
+
"## 4.9 Component System",
|
|
10913
|
+
implementationPlan.componentBuildPlan.map((component) => [
|
|
10914
|
+
`### ${component.name}`,
|
|
10915
|
+
formatBulletList([
|
|
10916
|
+
`purpose: ${component.purpose}`,
|
|
10917
|
+
`structure: build from semantic tokens and keep state visuals explicit`,
|
|
10918
|
+
`visual style: ${profileConfig.direction}`,
|
|
10919
|
+
`states: ${component.states.join(", ")}`,
|
|
10920
|
+
"spacing: keep internal padding on the 8px rhythm",
|
|
10921
|
+
"accessibility notes: preserve focus visibility and keyboard parity",
|
|
10922
|
+
"responsive behavior: stack content before line length becomes cramped",
|
|
10923
|
+
`implementation notes: ${component.implementationNote}`
|
|
10924
|
+
])
|
|
10925
|
+
].join("\n")).join("\n\n"),
|
|
10926
|
+
"",
|
|
10927
|
+
"## 4.10 Page or Section Patterns",
|
|
10928
|
+
formatBulletList(profileConfig.pagePatterns),
|
|
10929
|
+
"",
|
|
10930
|
+
"## 4.11 Accessibility Requirements",
|
|
10931
|
+
formatBulletList(implementationPlan.accessibilityChecklist),
|
|
10932
|
+
"",
|
|
10933
|
+
"## 4.12 Responsiveness Requirements",
|
|
10934
|
+
formatBulletList(implementationPlan.responsiveChecklist),
|
|
10935
|
+
"",
|
|
10936
|
+
"## 4.13 Content and Microcopy Guidance",
|
|
10937
|
+
formatBulletList([
|
|
10938
|
+
"Use direct, confident labels and short CTA copy.",
|
|
10939
|
+
"Keep error and success messages specific to the affected region.",
|
|
10940
|
+
"Prefer descriptive button copy over generic verbs."
|
|
10941
|
+
]),
|
|
10942
|
+
"",
|
|
10943
|
+
"## 4.14 Do / Don't Rules",
|
|
10944
|
+
formatBulletList([
|
|
10945
|
+
"Do preserve one dominant message per section.",
|
|
10946
|
+
"Do encode repeated visual rules into semantic tokens.",
|
|
10947
|
+
"Don't copy proprietary logos, screenshots, or brand-only illustrations.",
|
|
10948
|
+
"Don't hide important actions inside ambiguous hover-only affordances."
|
|
10949
|
+
]),
|
|
10950
|
+
"",
|
|
10951
|
+
"## 4.15 Acceptance Criteria",
|
|
10952
|
+
formatBulletList([
|
|
10953
|
+
"Primary action is obvious within one viewport.",
|
|
10954
|
+
"Color, typography, spacing, and elevation all resolve through named tokens.",
|
|
10955
|
+
"Keyboard, focus, and reduced-motion behavior remain intact across breakpoints."
|
|
10956
|
+
])
|
|
10957
|
+
].join("\n");
|
|
10958
|
+
};
|
|
10959
|
+
var renderImplementationMarkdown = (implementationPlan) => {
|
|
10960
|
+
return [
|
|
10961
|
+
"# 5. Implementation Plan",
|
|
9611
10962
|
"",
|
|
9612
|
-
|
|
10963
|
+
"## 5.1 Architecture Recommendation",
|
|
10964
|
+
implementationPlan.architectureRecommendation,
|
|
9613
10965
|
"",
|
|
9614
|
-
"##
|
|
9615
|
-
|
|
9616
|
-
|
|
9617
|
-
|
|
10966
|
+
"## 5.2 Design Token Strategy",
|
|
10967
|
+
formatRecordList(implementationPlan.tokenStrategy.colors),
|
|
10968
|
+
"",
|
|
10969
|
+
formatRecordList(implementationPlan.tokenStrategy.typography),
|
|
10970
|
+
"",
|
|
10971
|
+
"## 5.3 Component Build Plan",
|
|
10972
|
+
implementationPlan.componentBuildPlan.map((component, index) => `${index + 1}. ${component.name}: ${component.purpose}`).join("\n"),
|
|
10973
|
+
"",
|
|
10974
|
+
"## 5.4 Page Assembly Plan",
|
|
10975
|
+
formatBulletList(implementationPlan.pageAssemblyPlan),
|
|
10976
|
+
"",
|
|
10977
|
+
"## 5.5 State and Interaction Plan",
|
|
10978
|
+
formatBulletList(implementationPlan.stateAndInteractionPlan),
|
|
10979
|
+
"",
|
|
10980
|
+
"## 5.6 Accessibility Implementation Checklist",
|
|
10981
|
+
formatBulletList(implementationPlan.accessibilityChecklist),
|
|
10982
|
+
"",
|
|
10983
|
+
"## 5.7 Responsive Implementation Checklist",
|
|
10984
|
+
formatBulletList(implementationPlan.responsiveChecklist),
|
|
10985
|
+
"",
|
|
10986
|
+
"## 5.8 Risks and Ambiguities",
|
|
10987
|
+
formatBulletList(implementationPlan.risksAndAmbiguities),
|
|
10988
|
+
"",
|
|
10989
|
+
"## 5.9 Recommended Build Sequence",
|
|
10990
|
+
implementationPlan.buildSequence.map((step, index) => `${index + 1}. ${step}`).join("\n")
|
|
9618
10991
|
].join("\n");
|
|
9619
|
-
|
|
9620
|
-
|
|
9621
|
-
|
|
9622
|
-
|
|
9623
|
-
|
|
9624
|
-
|
|
9625
|
-
|
|
9626
|
-
|
|
9627
|
-
|
|
9628
|
-
|
|
9629
|
-
|
|
9630
|
-
|
|
9631
|
-
|
|
10992
|
+
};
|
|
10993
|
+
var renderPrototypeGuidance = (profile) => {
|
|
10994
|
+
return [
|
|
10995
|
+
"# 6. Optional Prototype Plan",
|
|
10996
|
+
"",
|
|
10997
|
+
"- page structure: establish the shell, hero or primary action zone, proof sections, and footer in that order.",
|
|
10998
|
+
`- section order: ${PROFILE_CONFIG[profile].pagePatterns.join(" -> ")}`,
|
|
10999
|
+
"- component composition: reuse button, card, input, and navigation primitives before page-specific wrappers.",
|
|
11000
|
+
"- interaction expectations: provide visible focus, compact hover feedback, and reduced-motion-safe entry transitions.",
|
|
11001
|
+
"- HTML skeleton guidance: start with one main landmark, one primary CTA group, and semantic sections for proof or detail bands.",
|
|
11002
|
+
"- styling approach: define CSS variables first, then map components to semantic tokens rather than raw values.",
|
|
11003
|
+
"- first prototype should include vs omit: include shell, hero, CTA, one proof section, and one form or action cluster; omit analytics, heavy animation, and tertiary content until hierarchy is proven."
|
|
11004
|
+
].join("\n");
|
|
11005
|
+
};
|
|
11006
|
+
var renderDeliverablesSummary = (includePrototypeGuidance) => {
|
|
11007
|
+
const deliverables = [
|
|
11008
|
+
"Structured `designContract` JSON aligned to canvas governance",
|
|
11009
|
+
"Valid `generationPlan` JSON aligned to the canvas generation plan contract",
|
|
11010
|
+
"Human-readable `design.md` design specification",
|
|
11011
|
+
"Engineering implementation plan in JSON and Markdown"
|
|
9632
11012
|
];
|
|
9633
|
-
if (
|
|
9634
|
-
|
|
9635
|
-
|
|
9636
|
-
|
|
9637
|
-
|
|
9638
|
-
|
|
9639
|
-
|
|
9640
|
-
|
|
9641
|
-
|
|
9642
|
-
|
|
9643
|
-
|
|
9644
|
-
|
|
9645
|
-
|
|
9646
|
-
|
|
9647
|
-
|
|
9648
|
-
meta: args.meta
|
|
9649
|
-
},
|
|
9650
|
-
files
|
|
9651
|
-
};
|
|
9652
|
-
}
|
|
9653
|
-
if (args.mode === "md") {
|
|
9654
|
-
return {
|
|
9655
|
-
response: {
|
|
9656
|
-
mode: args.mode,
|
|
9657
|
-
markdown,
|
|
9658
|
-
meta: args.meta
|
|
9659
|
-
},
|
|
9660
|
-
files
|
|
9661
|
-
};
|
|
9662
|
-
}
|
|
9663
|
-
if (args.mode === "context") {
|
|
9664
|
-
return {
|
|
9665
|
-
response: {
|
|
9666
|
-
mode: args.mode,
|
|
9667
|
-
context: contextPayload,
|
|
9668
|
-
meta: args.meta
|
|
9669
|
-
},
|
|
9670
|
-
files
|
|
9671
|
-
};
|
|
9672
|
-
}
|
|
11013
|
+
if (includePrototypeGuidance) {
|
|
11014
|
+
deliverables.push("Prototype guidance Markdown for the first HTML pass");
|
|
11015
|
+
}
|
|
11016
|
+
deliverables.push("Evidence digest describing brief, references, fetch outcomes, and capture outcomes");
|
|
11017
|
+
return formatBulletList(deliverables);
|
|
11018
|
+
};
|
|
11019
|
+
var buildEvidencePayload = (brief, urls, references) => ({
|
|
11020
|
+
brief,
|
|
11021
|
+
briefHash: referenceFingerprint(brief),
|
|
11022
|
+
urls,
|
|
11023
|
+
referenceCount: references.length,
|
|
11024
|
+
references: references.map((reference) => toReferenceEvidenceJson(reference))
|
|
11025
|
+
});
|
|
11026
|
+
var toCaptureEvidenceJson = (capture) => {
|
|
11027
|
+
if (!capture) return null;
|
|
9673
11028
|
return {
|
|
9674
|
-
|
|
9675
|
-
|
|
9676
|
-
|
|
9677
|
-
}
|
|
9678
|
-
|
|
11029
|
+
...capture.title ? { title: capture.title } : {},
|
|
11030
|
+
...capture.snapshot ? { snapshot: capture.snapshot } : {},
|
|
11031
|
+
...capture.dom ? { dom: capture.dom } : {},
|
|
11032
|
+
...capture.clone ? { clone: capture.clone } : {}
|
|
11033
|
+
};
|
|
11034
|
+
};
|
|
11035
|
+
var toReferenceEvidenceJson = (reference) => ({
|
|
11036
|
+
id: reference.id,
|
|
11037
|
+
url: reference.url,
|
|
11038
|
+
...reference.title ? { title: reference.title } : {},
|
|
11039
|
+
...reference.excerpt ? { excerpt: reference.excerpt } : {},
|
|
11040
|
+
fetchStatus: reference.fetchStatus,
|
|
11041
|
+
captureStatus: reference.captureStatus,
|
|
11042
|
+
...reference.fetchFailure ? { fetchFailure: reference.fetchFailure } : {},
|
|
11043
|
+
...reference.captureFailure ? { captureFailure: reference.captureFailure } : {},
|
|
11044
|
+
capture: toCaptureEvidenceJson(reference.capture)
|
|
11045
|
+
});
|
|
11046
|
+
var buildInspiredesignPacket = (input) => {
|
|
11047
|
+
const brief = trimText(input.brief);
|
|
11048
|
+
const urls = [...new Set(input.urls.map((url) => trimText(url)).filter(Boolean))];
|
|
11049
|
+
const references = input.references.map((reference) => ({
|
|
11050
|
+
...reference,
|
|
11051
|
+
title: reference.title ? trimText(reference.title) : void 0,
|
|
11052
|
+
excerpt: reference.excerpt ? trimText(reference.excerpt) : void 0
|
|
11053
|
+
}));
|
|
11054
|
+
const profile = classifyProfile(brief, references);
|
|
11055
|
+
const generationPlan = buildGenerationPlan(brief, profile, references);
|
|
11056
|
+
const designContract = buildDesignContract(brief, urls, references, generationPlan);
|
|
11057
|
+
const implementationPlan = buildImplementationPlan(brief, profile, references);
|
|
11058
|
+
const governanceMarkdown = renderGovernanceMarkdown(designContract, implementationPlan);
|
|
11059
|
+
const implementationPlanMarkdown = renderImplementationMarkdown(implementationPlan);
|
|
11060
|
+
const prototypeGuidanceMarkdown = input.includePrototypeGuidance ? renderPrototypeGuidance(profile) : null;
|
|
11061
|
+
const designMarkdown = [
|
|
11062
|
+
"# 1. Executive Summary",
|
|
11063
|
+
"",
|
|
11064
|
+
formatBulletList([
|
|
11065
|
+
`Analyzed brief plus ${references.length || 0} inspiration reference(s).`,
|
|
11066
|
+
`Chosen design direction: ${PROFILE_CONFIG[profile].direction}.`,
|
|
11067
|
+
"Final outcome: a reusable design contract, engineering plan, and optional prototype guidance.",
|
|
11068
|
+
`Scope mode: ${references.length > 1 ? "full-site synthesis" : "single-surface synthesis"}.`
|
|
11069
|
+
]),
|
|
11070
|
+
"",
|
|
11071
|
+
"# 2. Inspiration Analysis",
|
|
11072
|
+
"",
|
|
11073
|
+
references.length > 0 ? references.map(renderReferenceMarkdown).join("\n\n") : "- No live inspiration source was provided. The system is derived entirely from the brief.",
|
|
11074
|
+
"",
|
|
11075
|
+
"# 3. Unified Design Direction",
|
|
11076
|
+
"",
|
|
11077
|
+
formatBulletList([
|
|
11078
|
+
`visual personality: ${PROFILE_CONFIG[profile].visualPersonality}`,
|
|
11079
|
+
`tone: ${PROFILE_CONFIG[profile].brandTone}`,
|
|
11080
|
+
`UX principles: ${PROFILE_CONFIG[profile].hierarchyPrinciples.join(" ")}`,
|
|
11081
|
+
`interaction philosophy: ${PROFILE_CONFIG[profile].interactionPhilosophy}`,
|
|
11082
|
+
"branding posture: preserve the intent of the references without cloning brand-only assets.",
|
|
11083
|
+
"system coherence rules: encode tokens first, keep one dominant idea per section, and keep states explicit."
|
|
11084
|
+
]),
|
|
11085
|
+
"",
|
|
11086
|
+
"# 4. Design Governance (`design.md`)",
|
|
11087
|
+
"",
|
|
11088
|
+
renderGovernanceMarkdown(designContract, implementationPlan),
|
|
11089
|
+
"",
|
|
11090
|
+
renderImplementationMarkdown(implementationPlan),
|
|
11091
|
+
"",
|
|
11092
|
+
prototypeGuidanceMarkdown ?? "# 6. Optional Prototype Plan\n\n- Prototype guidance omitted for this run.",
|
|
11093
|
+
"",
|
|
11094
|
+
"# 7. Deliverables Summary",
|
|
11095
|
+
"",
|
|
11096
|
+
renderDeliverablesSummary(Boolean(input.includePrototypeGuidance))
|
|
11097
|
+
].join("\n");
|
|
11098
|
+
return {
|
|
11099
|
+
designContract,
|
|
11100
|
+
generationPlan,
|
|
11101
|
+
designMarkdown,
|
|
11102
|
+
implementationPlan,
|
|
11103
|
+
implementationPlanMarkdown,
|
|
11104
|
+
prototypeGuidanceMarkdown,
|
|
11105
|
+
evidence: buildEvidencePayload(brief, urls, references)
|
|
9679
11106
|
};
|
|
9680
11107
|
};
|
|
9681
11108
|
|
|
9682
11109
|
// src/providers/shopping-postprocess.ts
|
|
9683
|
-
import { createHash as
|
|
11110
|
+
import { createHash as createHash4 } from "crypto";
|
|
9684
11111
|
var LOOKS_LIKE_URL_RE = /^https?:\/\/\S+$/i;
|
|
9685
11112
|
var PRICE_TOKEN_RE = /((?:US\$|CA\$|C\$|USD|CAD|EUR|GBP|[$€£]))\s*([0-9]{1,4}(?:[.,][0-9]{3})*(?:[.,][0-9]{1,2})?)/gi;
|
|
9686
11113
|
var CONTEXTUAL_PRICE_TOKEN_RE = /(?:connect to any carrier later|starting at|starts at|starting from|from|buy now for|buy for)\s*((?:US\$|CA\$|C\$|USD|CAD|EUR|GBP|[$€£]))\s*([0-9]{1,4}(?:[.,][0-9]{3})*(?:[.,][0-9]{1,2})?)/gi;
|
|
@@ -9766,7 +11193,7 @@ var REGION_CURRENCY_BY_REGION = {
|
|
|
9766
11193
|
uk: "GBP",
|
|
9767
11194
|
eu: "EUR"
|
|
9768
11195
|
};
|
|
9769
|
-
var hash = (value) =>
|
|
11196
|
+
var hash = (value) => createHash4("sha1").update(value).digest("hex").slice(0, 16);
|
|
9770
11197
|
var normalizePlainText = (value) => {
|
|
9771
11198
|
if (!value) return "";
|
|
9772
11199
|
return extractText(value).replace(/[\u0000-\u001F\u007F-\u009F]+/g, " ").replace(/\s+/g, " ").trim();
|
|
@@ -10395,7 +11822,7 @@ var compileShoppingWorkflow = (input, options = {}) => {
|
|
|
10395
11822
|
};
|
|
10396
11823
|
|
|
10397
11824
|
// src/providers/shopping-compiler.ts
|
|
10398
|
-
import { createHash as
|
|
11825
|
+
import { createHash as createHash5 } from "crypto";
|
|
10399
11826
|
var DEFAULT_SHOPPING_SEARCH_LIMIT = 8;
|
|
10400
11827
|
var SHOPPING_FETCH_RECOVERY_LIMIT = 2;
|
|
10401
11828
|
var SEARCH_INDEX_RETRIEVAL_PATHS = /* @__PURE__ */ new Set(["shopping:search:index", "shopping:search:link"]);
|
|
@@ -10412,7 +11839,7 @@ var emptyCheckpointState = () => ({
|
|
|
10412
11839
|
step_results_by_id: {}
|
|
10413
11840
|
});
|
|
10414
11841
|
var createShoppingSearchStepId = (providerId) => `search:${providerId}`;
|
|
10415
|
-
var createShoppingFetchStepId = (providerId, url) => `fetch:${providerId}:${
|
|
11842
|
+
var createShoppingFetchStepId = (providerId, url) => `fetch:${providerId}:${createHash5("sha1").update(canonicalizeUrl(url)).digest("hex").slice(0, 16)}`;
|
|
10416
11843
|
var serializeShoppingCheckpointState = (state) => ({
|
|
10417
11844
|
completed_step_ids: [...state.completed_step_ids],
|
|
10418
11845
|
step_results_by_id: state.step_results_by_id
|
|
@@ -10898,7 +12325,7 @@ var compileProductVideoExecutionPlan = (args) => {
|
|
|
10898
12325
|
};
|
|
10899
12326
|
|
|
10900
12327
|
// src/providers/research-compiler.ts
|
|
10901
|
-
import { createHash as
|
|
12328
|
+
import { createHash as createHash6 } from "crypto";
|
|
10902
12329
|
var RESEARCH_AUTO_SOURCES = ["web", "community", "social"];
|
|
10903
12330
|
var RESEARCH_ALL_SOURCES = [...RESEARCH_AUTO_SOURCES];
|
|
10904
12331
|
var DEFAULT_RESEARCH_SEARCH_LIMIT = 10;
|
|
@@ -10923,7 +12350,7 @@ var toProviderSource = (providerId) => {
|
|
|
10923
12350
|
return null;
|
|
10924
12351
|
};
|
|
10925
12352
|
var createResearchSearchStepId = (source) => `search:${source}`;
|
|
10926
|
-
var createResearchFetchStepId = (url) => `fetch:web:${
|
|
12353
|
+
var createResearchFetchStepId = (url) => `fetch:web:${createHash6("sha1").update(canonicalizeUrl(url)).digest("hex").slice(0, 16)}`;
|
|
10927
12354
|
var serializeResearchCheckpointState = (state) => ({
|
|
10928
12355
|
completed_step_ids: [...state.completed_step_ids],
|
|
10929
12356
|
step_results_by_id: state.step_results_by_id
|
|
@@ -11509,24 +12936,54 @@ var withPrimaryConstraintMeta = (meta, failures) => {
|
|
|
11509
12936
|
const primaryIssue = summarizePrimaryProviderIssue(failures);
|
|
11510
12937
|
return primaryIssue ? {
|
|
11511
12938
|
...meta,
|
|
11512
|
-
primary_constraint: primaryIssue,
|
|
11513
12939
|
primaryConstraint: primaryIssue,
|
|
11514
12940
|
primaryConstraintSummary: primaryIssue.summary
|
|
11515
12941
|
} : meta;
|
|
11516
12942
|
};
|
|
11517
|
-
var
|
|
12943
|
+
var withCamelCasePrimaryConstraintMeta = withPrimaryConstraintMeta;
|
|
12944
|
+
var readPrimaryConstraintGuidance = (constraint) => {
|
|
12945
|
+
const guidance = constraint.guidance;
|
|
12946
|
+
return guidance && typeof guidance === "object" && !Array.isArray(guidance) ? guidance : void 0;
|
|
12947
|
+
};
|
|
12948
|
+
var withPrimaryConstraintSummaryOverride = (meta, summary, guidance) => {
|
|
11518
12949
|
const currentPrimaryConstraint = meta.primaryConstraint;
|
|
11519
|
-
const
|
|
11520
|
-
|
|
12950
|
+
const baseConstraint = currentPrimaryConstraint && typeof currentPrimaryConstraint === "object" && !Array.isArray(currentPrimaryConstraint) ? currentPrimaryConstraint : { reasonCode: "env_limited" };
|
|
12951
|
+
const existingGuidance = readPrimaryConstraintGuidance(baseConstraint);
|
|
12952
|
+
const { guidance: _existingGuidance, ...nextPrimaryConstraintBase } = baseConstraint;
|
|
12953
|
+
const nextGuidance = guidance ?? existingGuidance;
|
|
12954
|
+
const nextPrimaryConstraint = nextGuidance ? {
|
|
12955
|
+
...nextPrimaryConstraintBase,
|
|
12956
|
+
summary,
|
|
12957
|
+
guidance: nextGuidance
|
|
12958
|
+
} : {
|
|
12959
|
+
...nextPrimaryConstraintBase,
|
|
11521
12960
|
summary
|
|
11522
|
-
}
|
|
12961
|
+
};
|
|
11523
12962
|
return {
|
|
11524
12963
|
...meta,
|
|
11525
|
-
primary_constraint: nextPrimaryConstraint,
|
|
11526
12964
|
primaryConstraint: nextPrimaryConstraint,
|
|
11527
12965
|
primaryConstraintSummary: summary
|
|
11528
12966
|
};
|
|
11529
12967
|
};
|
|
12968
|
+
var withReasonCodeDistributionMeta = (meta, reasonCodeDistribution) => {
|
|
12969
|
+
const metrics = meta.metrics;
|
|
12970
|
+
const nextMetrics = metrics && typeof metrics === "object" && !Array.isArray(metrics) ? {
|
|
12971
|
+
...metrics,
|
|
12972
|
+
reasonCodeDistribution
|
|
12973
|
+
} : { reasonCodeDistribution };
|
|
12974
|
+
return {
|
|
12975
|
+
...meta,
|
|
12976
|
+
metrics: nextMetrics,
|
|
12977
|
+
reasonCodeDistribution
|
|
12978
|
+
};
|
|
12979
|
+
};
|
|
12980
|
+
var incrementReasonCodeDistribution = (reasonCodeDistribution, reasonCode, count) => {
|
|
12981
|
+
if (count <= 0) return reasonCodeDistribution;
|
|
12982
|
+
return Object.fromEntries(Object.entries({
|
|
12983
|
+
...reasonCodeDistribution,
|
|
12984
|
+
[reasonCode]: (reasonCodeDistribution[reasonCode] ?? 0) + count
|
|
12985
|
+
}).sort(([left], [right]) => left.localeCompare(right)));
|
|
12986
|
+
};
|
|
11530
12987
|
var summarizeShoppingOfferFilterConstraint = (args) => {
|
|
11531
12988
|
const primaryIssue = summarizePrimaryProviderIssue(args.failures);
|
|
11532
12989
|
if (primaryIssue && (primaryIssue.reasonCode !== "env_limited" || primaryIssue.constraint || primaryIssue.blockerType === "anti_bot_challenge")) {
|
|
@@ -11586,6 +13043,7 @@ var withBrowserModeOverride = (options, input) => {
|
|
|
11586
13043
|
var WORKFLOW_KIND_BY_SUSPENDED_INTENT_KIND = {
|
|
11587
13044
|
"workflow.research": "research",
|
|
11588
13045
|
"workflow.shopping": "shopping",
|
|
13046
|
+
"workflow.inspiredesign": "inspiredesign",
|
|
11589
13047
|
"workflow.product_video": "product_video"
|
|
11590
13048
|
};
|
|
11591
13049
|
var buildWorkflowResumePayload = (kind, input) => ({
|
|
@@ -11837,7 +13295,7 @@ var rankResearchRecords = (records) => {
|
|
|
11837
13295
|
return left.id.localeCompare(right.id);
|
|
11838
13296
|
});
|
|
11839
13297
|
};
|
|
11840
|
-
var hash2 = (value) =>
|
|
13298
|
+
var hash2 = (value) => createHash7("sha1").update(value).digest("hex").slice(0, 16);
|
|
11841
13299
|
var RESEARCH_ALWAYS_SANITIZED_PATHS = /* @__PURE__ */ new Set([
|
|
11842
13300
|
"community:search:index",
|
|
11843
13301
|
"social:search:index"
|
|
@@ -11956,6 +13414,229 @@ var createRemainingTimeoutResolver = (timeoutMs) => {
|
|
|
11956
13414
|
const startedAtMs = Date.now();
|
|
11957
13415
|
return () => Math.max(1, timeoutMs - Math.max(0, Date.now() - startedAtMs));
|
|
11958
13416
|
};
|
|
13417
|
+
var INSPIREDESIGN_RENDER_MODES = /* @__PURE__ */ new Set(["compact", "json", "md", "context", "path"]);
|
|
13418
|
+
var INSPIREDESIGN_CAPTURE_MODES = /* @__PURE__ */ new Set(["off", "deep"]);
|
|
13419
|
+
var INSPIREDESIGN_COOKIE_POLICIES = /* @__PURE__ */ new Set(["off", "auto", "required"]);
|
|
13420
|
+
var serializeInspiredesignRunInput = (input) => ({
|
|
13421
|
+
brief: input.brief,
|
|
13422
|
+
urls: input.urls,
|
|
13423
|
+
captureMode: input.captureMode,
|
|
13424
|
+
mode: input.mode,
|
|
13425
|
+
...input.includePrototypeGuidance !== void 0 ? { includePrototypeGuidance: input.includePrototypeGuidance } : {},
|
|
13426
|
+
...typeof input.timeoutMs === "number" ? { timeoutMs: input.timeoutMs } : {},
|
|
13427
|
+
...input.outputDir ? { outputDir: input.outputDir } : {},
|
|
13428
|
+
...typeof input.ttlHours === "number" ? { ttlHours: input.ttlHours } : {},
|
|
13429
|
+
...typeof input.useCookies === "boolean" ? { useCookies: input.useCookies } : {},
|
|
13430
|
+
...input.challengeAutomationMode ? { challengeAutomationMode: input.challengeAutomationMode } : {},
|
|
13431
|
+
...input.cookiePolicyOverride ? { cookiePolicyOverride: input.cookiePolicyOverride } : {}
|
|
13432
|
+
});
|
|
13433
|
+
var parseInspiredesignEnvelopeInput = (input) => ({
|
|
13434
|
+
brief: typeof input.brief === "string" ? input.brief : "",
|
|
13435
|
+
mode: typeof input.mode === "string" && INSPIREDESIGN_RENDER_MODES.has(input.mode) ? input.mode : "compact",
|
|
13436
|
+
...Array.isArray(input.urls) ? { urls: input.urls.filter((url) => typeof url === "string") } : {},
|
|
13437
|
+
...typeof input.captureMode === "string" && INSPIREDESIGN_CAPTURE_MODES.has(input.captureMode) ? { captureMode: input.captureMode } : {},
|
|
13438
|
+
...typeof input.includePrototypeGuidance === "boolean" ? { includePrototypeGuidance: input.includePrototypeGuidance } : {},
|
|
13439
|
+
...typeof input.timeoutMs === "number" ? { timeoutMs: input.timeoutMs } : {},
|
|
13440
|
+
...typeof input.outputDir === "string" && input.outputDir.length > 0 ? { outputDir: input.outputDir } : {},
|
|
13441
|
+
...typeof input.ttlHours === "number" ? { ttlHours: input.ttlHours } : {},
|
|
13442
|
+
...typeof input.useCookies === "boolean" ? { useCookies: input.useCookies } : {},
|
|
13443
|
+
...isChallengeAutomationMode(input.challengeAutomationMode) ? { challengeAutomationMode: input.challengeAutomationMode } : {},
|
|
13444
|
+
...typeof input.cookiePolicyOverride === "string" && INSPIREDESIGN_COOKIE_POLICIES.has(input.cookiePolicyOverride) ? { cookiePolicyOverride: input.cookiePolicyOverride } : {}
|
|
13445
|
+
});
|
|
13446
|
+
var normalizeInspiredesignUrls = (urls) => {
|
|
13447
|
+
if (!urls || urls.length === 0) return [];
|
|
13448
|
+
const normalized = urls.map((url) => url.trim()).filter(Boolean);
|
|
13449
|
+
const invalid = normalized.find((url) => !LOOKS_LIKE_URL_RE.test(url));
|
|
13450
|
+
if (invalid) {
|
|
13451
|
+
throw new Error(`Inspiredesign workflow received an invalid URL: ${invalid}`);
|
|
13452
|
+
}
|
|
13453
|
+
return [...new Set(normalized.map((url) => canonicalizeUrl(url)))];
|
|
13454
|
+
};
|
|
13455
|
+
var normalizeInspiredesignInput = (input) => {
|
|
13456
|
+
const brief = input.brief.trim();
|
|
13457
|
+
if (!brief) {
|
|
13458
|
+
throw new Error("Inspiredesign workflow requires a non-empty brief.");
|
|
13459
|
+
}
|
|
13460
|
+
return {
|
|
13461
|
+
...input,
|
|
13462
|
+
brief,
|
|
13463
|
+
urls: normalizeInspiredesignUrls(input.urls),
|
|
13464
|
+
captureMode: input.captureMode ?? "off",
|
|
13465
|
+
mode: input.mode ?? "compact"
|
|
13466
|
+
};
|
|
13467
|
+
};
|
|
13468
|
+
var isInspiredesignWorkflowEnvelopeInput = (input) => {
|
|
13469
|
+
return "kind" in input && "input" in input;
|
|
13470
|
+
};
|
|
13471
|
+
var buildInspiredesignEnvelope = (input) => {
|
|
13472
|
+
if (isInspiredesignWorkflowEnvelopeInput(input)) {
|
|
13473
|
+
if (!isWorkflowResumeEnvelope(input)) {
|
|
13474
|
+
throw new Error("Inspiredesign workflow envelope is invalid.");
|
|
13475
|
+
}
|
|
13476
|
+
if (input.kind !== "inspiredesign") {
|
|
13477
|
+
throw new Error(`Inspiredesign workflow envelope kind mismatch. Expected inspiredesign but received ${input.kind}.`);
|
|
13478
|
+
}
|
|
13479
|
+
return {
|
|
13480
|
+
envelope: input,
|
|
13481
|
+
workflowInput: normalizeInspiredesignInput(parseInspiredesignEnvelopeInput(input.input))
|
|
13482
|
+
};
|
|
13483
|
+
}
|
|
13484
|
+
const workflowInput = normalizeInspiredesignInput(input);
|
|
13485
|
+
return {
|
|
13486
|
+
envelope: buildWorkflowResumeEnvelope("inspiredesign", serializeInspiredesignRunInput(workflowInput)),
|
|
13487
|
+
workflowInput
|
|
13488
|
+
};
|
|
13489
|
+
};
|
|
13490
|
+
var appendWorkflowTrace = (trace, stage, event, details) => [
|
|
13491
|
+
...trace,
|
|
13492
|
+
{
|
|
13493
|
+
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
13494
|
+
stage,
|
|
13495
|
+
event,
|
|
13496
|
+
details
|
|
13497
|
+
}
|
|
13498
|
+
];
|
|
13499
|
+
var buildInspiredesignStepEnvelope = (workflowInput, trace, stepIndex, url) => buildWorkflowResumeEnvelope(
|
|
13500
|
+
"inspiredesign",
|
|
13501
|
+
serializeInspiredesignRunInput(workflowInput),
|
|
13502
|
+
{
|
|
13503
|
+
checkpoint: {
|
|
13504
|
+
stage: "execute",
|
|
13505
|
+
stepId: "fetch_reference",
|
|
13506
|
+
stepIndex,
|
|
13507
|
+
state: { url },
|
|
13508
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
13509
|
+
},
|
|
13510
|
+
trace
|
|
13511
|
+
}
|
|
13512
|
+
);
|
|
13513
|
+
var buildInspiredesignFetchOptions = (workflowInput, envelope, timeoutMs) => withWorkflowResumeEnvelopeIntent(
|
|
13514
|
+
withChallengeAutomationOverride(
|
|
13515
|
+
withCookieOverrides({
|
|
13516
|
+
...typeof timeoutMs === "number" ? { timeoutMs } : {}
|
|
13517
|
+
}, workflowInput),
|
|
13518
|
+
workflowInput
|
|
13519
|
+
),
|
|
13520
|
+
"workflow.inspiredesign",
|
|
13521
|
+
envelope
|
|
13522
|
+
);
|
|
13523
|
+
var hasInspiredesignCaptureEvidence = (capture) => {
|
|
13524
|
+
if (!capture) return false;
|
|
13525
|
+
return Boolean(capture.title || capture.snapshot || capture.dom || capture.clone);
|
|
13526
|
+
};
|
|
13527
|
+
var captureInspiredesignReference = async (url, captureMode, workflowInput, captureReference, timeoutMs) => {
|
|
13528
|
+
if (captureMode === "off") {
|
|
13529
|
+
return { captureStatus: "off" };
|
|
13530
|
+
}
|
|
13531
|
+
if (!captureReference) {
|
|
13532
|
+
return {
|
|
13533
|
+
captureStatus: "failed",
|
|
13534
|
+
captureFailure: "Deep capture requested, but no browser capture callback was available."
|
|
13535
|
+
};
|
|
13536
|
+
}
|
|
13537
|
+
try {
|
|
13538
|
+
const capture = await captureReference(url, {
|
|
13539
|
+
timeoutMs,
|
|
13540
|
+
useCookies: workflowInput.useCookies,
|
|
13541
|
+
challengeAutomationMode: workflowInput.challengeAutomationMode,
|
|
13542
|
+
cookiePolicyOverride: workflowInput.cookiePolicyOverride
|
|
13543
|
+
});
|
|
13544
|
+
if (!hasInspiredesignCaptureEvidence(capture)) {
|
|
13545
|
+
return {
|
|
13546
|
+
captureStatus: "failed",
|
|
13547
|
+
captureFailure: "Deep capture did not return usable snapshot, DOM, or clone evidence."
|
|
13548
|
+
};
|
|
13549
|
+
}
|
|
13550
|
+
return {
|
|
13551
|
+
captureStatus: "captured",
|
|
13552
|
+
capture
|
|
13553
|
+
};
|
|
13554
|
+
} catch (error) {
|
|
13555
|
+
return {
|
|
13556
|
+
captureStatus: "failed",
|
|
13557
|
+
captureFailure: error instanceof Error ? error.message : "Deep capture failed."
|
|
13558
|
+
};
|
|
13559
|
+
}
|
|
13560
|
+
};
|
|
13561
|
+
var getInspiredesignPrimaryRecord = (result, url) => {
|
|
13562
|
+
const canonicalUrl = canonicalizeUrl(url);
|
|
13563
|
+
return result.records.find((record) => record.url && canonicalizeUrl(record.url) === canonicalUrl) ?? result.records[0];
|
|
13564
|
+
};
|
|
13565
|
+
var summarizeInspiredesignFetchFailure = (result) => {
|
|
13566
|
+
return summarizePrimaryProviderIssue(result.failures)?.summary ?? result.error?.message;
|
|
13567
|
+
};
|
|
13568
|
+
var excerptFromInspiredesignRecord = (record) => {
|
|
13569
|
+
const content = normalizePlainText(record?.content);
|
|
13570
|
+
if (!content) return void 0;
|
|
13571
|
+
return toSnippet(content, 240);
|
|
13572
|
+
};
|
|
13573
|
+
var buildInspiredesignReference = (url, result, capture) => {
|
|
13574
|
+
const primary = getInspiredesignPrimaryRecord(result, url);
|
|
13575
|
+
const title = primary?.title ?? capture.capture?.title;
|
|
13576
|
+
const excerpt = excerptFromInspiredesignRecord(primary);
|
|
13577
|
+
const fetchStatus = result.records.length > 0 ? "captured" : "failed";
|
|
13578
|
+
return {
|
|
13579
|
+
id: createHash7("sha256").update(url).digest("hex").slice(0, 12),
|
|
13580
|
+
url,
|
|
13581
|
+
...title ? { title } : {},
|
|
13582
|
+
...excerpt ? { excerpt } : {},
|
|
13583
|
+
fetchStatus,
|
|
13584
|
+
captureStatus: capture.captureStatus,
|
|
13585
|
+
...fetchStatus === "failed" && summarizeInspiredesignFetchFailure(result) ? { fetchFailure: summarizeInspiredesignFetchFailure(result) } : {},
|
|
13586
|
+
...capture.captureFailure ? { captureFailure: capture.captureFailure } : {},
|
|
13587
|
+
...capture.capture ? { capture: capture.capture } : {}
|
|
13588
|
+
};
|
|
13589
|
+
};
|
|
13590
|
+
var summarizeInspiredesignCaptureConstraint = (references) => {
|
|
13591
|
+
const failedReferences = references.filter((reference) => reference.captureStatus === "failed");
|
|
13592
|
+
if (failedReferences.length === 0) {
|
|
13593
|
+
return void 0;
|
|
13594
|
+
}
|
|
13595
|
+
const summary = `Deep capture failed for ${failedReferences.length} ${failedReferences.length === 1 ? "reference" : "references"}.`;
|
|
13596
|
+
const retryUrls = failedReferences.slice(0, 2).map((reference) => `Retry deep capture for ${reference.url} after restoring the required browser session state.`);
|
|
13597
|
+
return {
|
|
13598
|
+
summary,
|
|
13599
|
+
guidance: {
|
|
13600
|
+
reason: summary,
|
|
13601
|
+
recommendedNextCommands: [
|
|
13602
|
+
"Rerun inspiredesign after configuring providers.cookieSource for the protected references you need to capture.",
|
|
13603
|
+
...retryUrls
|
|
13604
|
+
]
|
|
13605
|
+
}
|
|
13606
|
+
};
|
|
13607
|
+
};
|
|
13608
|
+
var buildInspiredesignMeta = (runtime, workflowInput, references, failures) => {
|
|
13609
|
+
const failedCaptures = references.filter((reference) => reference.captureStatus === "failed");
|
|
13610
|
+
let reasonCodeDistribution = summarizeReasonCodeDistribution(failures);
|
|
13611
|
+
let meta = withCamelCasePrimaryConstraintMeta(withReasonCodeDistributionMeta({
|
|
13612
|
+
selection: {
|
|
13613
|
+
urls: workflowInput.urls,
|
|
13614
|
+
capture_mode: workflowInput.captureMode,
|
|
13615
|
+
include_prototype_guidance: Boolean(workflowInput.includePrototypeGuidance)
|
|
13616
|
+
},
|
|
13617
|
+
metrics: {
|
|
13618
|
+
reference_count: references.length,
|
|
13619
|
+
fetched_references: references.filter((reference) => reference.fetchStatus === "captured").length,
|
|
13620
|
+
captured_references: references.filter((reference) => reference.captureStatus === "captured").length,
|
|
13621
|
+
failed_fetches: references.filter((reference) => reference.fetchStatus === "failed").length,
|
|
13622
|
+
failed_captures: failedCaptures.length
|
|
13623
|
+
},
|
|
13624
|
+
alerts: buildWorkflowAlerts(runtime, failures)
|
|
13625
|
+
}, reasonCodeDistribution), failures);
|
|
13626
|
+
if (!meta.primaryConstraint) {
|
|
13627
|
+
const captureConstraint = summarizeInspiredesignCaptureConstraint(references);
|
|
13628
|
+
if (captureConstraint) {
|
|
13629
|
+
reasonCodeDistribution = incrementReasonCodeDistribution(
|
|
13630
|
+
reasonCodeDistribution,
|
|
13631
|
+
"env_limited",
|
|
13632
|
+
failedCaptures.length
|
|
13633
|
+
);
|
|
13634
|
+
meta = withReasonCodeDistributionMeta(meta, reasonCodeDistribution);
|
|
13635
|
+
meta = withPrimaryConstraintSummaryOverride(meta, captureConstraint.summary, captureConstraint.guidance);
|
|
13636
|
+
}
|
|
13637
|
+
}
|
|
13638
|
+
return meta;
|
|
13639
|
+
};
|
|
11959
13640
|
var inferBrandFromContent = (content) => {
|
|
11960
13641
|
const normalized = normalizePlainText(content);
|
|
11961
13642
|
if (!normalized) return void 0;
|
|
@@ -12759,6 +14440,96 @@ var runShoppingWorkflow = async (runtime, input) => {
|
|
|
12759
14440
|
}
|
|
12760
14441
|
};
|
|
12761
14442
|
};
|
|
14443
|
+
var runInspiredesignWorkflow = async (runtime, input, options = {}) => {
|
|
14444
|
+
const { envelope, workflowInput } = buildInspiredesignEnvelope(input);
|
|
14445
|
+
const remainingTimeoutMs = createRemainingTimeoutResolver(workflowInput.timeoutMs);
|
|
14446
|
+
let trace = appendWorkflowTrace(envelope.trace ?? [], "compile", "compile_started", {
|
|
14447
|
+
kind: "inspiredesign"
|
|
14448
|
+
});
|
|
14449
|
+
trace = appendWorkflowTrace(trace, "compile", "compile_completed", {
|
|
14450
|
+
kind: "inspiredesign",
|
|
14451
|
+
urlCount: workflowInput.urls.length,
|
|
14452
|
+
captureMode: workflowInput.captureMode
|
|
14453
|
+
});
|
|
14454
|
+
const references = [];
|
|
14455
|
+
const failures = [];
|
|
14456
|
+
for (const [index, url] of workflowInput.urls.entries()) {
|
|
14457
|
+
const stepTrace = appendWorkflowTrace(trace, "execute", "reference_started", {
|
|
14458
|
+
stepIndex: index,
|
|
14459
|
+
url
|
|
14460
|
+
});
|
|
14461
|
+
const fetchTimeoutMs = remainingTimeoutMs();
|
|
14462
|
+
const result = await runtime.fetch(
|
|
14463
|
+
{ url },
|
|
14464
|
+
buildInspiredesignFetchOptions(
|
|
14465
|
+
workflowInput,
|
|
14466
|
+
buildInspiredesignStepEnvelope(workflowInput, stepTrace, index, url),
|
|
14467
|
+
fetchTimeoutMs
|
|
14468
|
+
)
|
|
14469
|
+
);
|
|
14470
|
+
observeWorkflowSignals(runtime, result);
|
|
14471
|
+
failures.push(...result.failures);
|
|
14472
|
+
const captureTimeoutMs = remainingTimeoutMs();
|
|
14473
|
+
const capture = await captureInspiredesignReference(
|
|
14474
|
+
url,
|
|
14475
|
+
workflowInput.captureMode,
|
|
14476
|
+
workflowInput,
|
|
14477
|
+
options.captureReference,
|
|
14478
|
+
captureTimeoutMs
|
|
14479
|
+
);
|
|
14480
|
+
references.push(buildInspiredesignReference(url, result, capture));
|
|
14481
|
+
trace = appendWorkflowTrace(stepTrace, "execute", "reference_completed", {
|
|
14482
|
+
stepIndex: index,
|
|
14483
|
+
url,
|
|
14484
|
+
fetchStatus: result.records.length > 0 ? "captured" : "failed",
|
|
14485
|
+
captureStatus: capture.captureStatus
|
|
14486
|
+
});
|
|
14487
|
+
}
|
|
14488
|
+
const meta = buildInspiredesignMeta(runtime, workflowInput, references, failures);
|
|
14489
|
+
const packet = buildInspiredesignPacket({
|
|
14490
|
+
brief: workflowInput.brief,
|
|
14491
|
+
urls: workflowInput.urls,
|
|
14492
|
+
references,
|
|
14493
|
+
includePrototypeGuidance: workflowInput.includePrototypeGuidance
|
|
14494
|
+
});
|
|
14495
|
+
const rendered = renderInspiredesign({
|
|
14496
|
+
mode: workflowInput.mode,
|
|
14497
|
+
brief: workflowInput.brief,
|
|
14498
|
+
urls: workflowInput.urls,
|
|
14499
|
+
designContract: packet.designContract,
|
|
14500
|
+
generationPlan: packet.generationPlan,
|
|
14501
|
+
implementationPlan: packet.implementationPlan,
|
|
14502
|
+
designMarkdown: packet.designMarkdown,
|
|
14503
|
+
implementationPlanMarkdown: packet.implementationPlanMarkdown,
|
|
14504
|
+
prototypeGuidanceMarkdown: packet.prototypeGuidanceMarkdown,
|
|
14505
|
+
evidence: packet.evidence,
|
|
14506
|
+
meta
|
|
14507
|
+
});
|
|
14508
|
+
const bundle = await createArtifactBundle({
|
|
14509
|
+
namespace: "inspiredesign",
|
|
14510
|
+
outputDir: workflowInput.outputDir,
|
|
14511
|
+
ttlHours: workflowInput.ttlHours,
|
|
14512
|
+
files: rendered.files
|
|
14513
|
+
});
|
|
14514
|
+
if (workflowInput.mode === "path") {
|
|
14515
|
+
return {
|
|
14516
|
+
...rendered.response,
|
|
14517
|
+
path: bundle.basePath,
|
|
14518
|
+
meta: {
|
|
14519
|
+
...meta,
|
|
14520
|
+
artifact_manifest: bundle.manifest
|
|
14521
|
+
}
|
|
14522
|
+
};
|
|
14523
|
+
}
|
|
14524
|
+
return {
|
|
14525
|
+
...rendered.response,
|
|
14526
|
+
artifact_path: bundle.basePath,
|
|
14527
|
+
meta: {
|
|
14528
|
+
...meta,
|
|
14529
|
+
artifact_manifest: bundle.manifest
|
|
14530
|
+
}
|
|
14531
|
+
};
|
|
14532
|
+
};
|
|
12762
14533
|
var runProductVideoWorkflow = async (runtime, input, options = {}) => {
|
|
12763
14534
|
const envelope = isWorkflowResumeEnvelope(input) ? input : buildWorkflowResumeEnvelope("product_video", input);
|
|
12764
14535
|
if (envelope.kind !== "product_video") {
|
|
@@ -13140,6 +14911,7 @@ var DEFAULT_PROVIDER_SUSPENDED_INTENT_KIND = {
|
|
|
13140
14911
|
var WORKFLOW_KIND_BY_SUSPENDED_INTENT_KIND2 = {
|
|
13141
14912
|
"workflow.research": "research",
|
|
13142
14913
|
"workflow.shopping": "shopping",
|
|
14914
|
+
"workflow.inspiredesign": "inspiredesign",
|
|
13143
14915
|
"workflow.product_video": "product_video"
|
|
13144
14916
|
};
|
|
13145
14917
|
var EXTENSION_FIRST_SOCIAL_FALLBACK_PLATFORMS = /* @__PURE__ */ new Set(["x", "reddit", "bluesky", "linkedin"]);
|
|
@@ -14586,6 +16358,14 @@ var ProviderRuntime = class {
|
|
|
14586
16358
|
input
|
|
14587
16359
|
)
|
|
14588
16360
|
);
|
|
16361
|
+
case "workflow.inspiredesign":
|
|
16362
|
+
return runInspiredesignWorkflow(
|
|
16363
|
+
this,
|
|
16364
|
+
unwrapWorkflowResumeEnvelope(
|
|
16365
|
+
WORKFLOW_KIND_BY_SUSPENDED_INTENT_KIND2[intent.kind],
|
|
16366
|
+
input
|
|
16367
|
+
)
|
|
16368
|
+
);
|
|
14589
16369
|
case "workflow.product_video":
|
|
14590
16370
|
return runProductVideoWorkflow(
|
|
14591
16371
|
this,
|
|
@@ -14743,25 +16523,38 @@ var ProviderRuntime = class {
|
|
|
14743
16523
|
}
|
|
14744
16524
|
async withTimeout(timeoutMs, task) {
|
|
14745
16525
|
const controller = new AbortController();
|
|
14746
|
-
const
|
|
14747
|
-
|
|
14748
|
-
|
|
16526
|
+
const createTimeoutError = (cause) => {
|
|
16527
|
+
return new ProviderRuntimeError("timeout", `Provider request timed out after ${timeoutMs}ms`, {
|
|
16528
|
+
retryable: true,
|
|
16529
|
+
...cause !== void 0 ? { cause } : {}
|
|
16530
|
+
});
|
|
16531
|
+
};
|
|
16532
|
+
const taskPromise = Promise.resolve().then(() => task(controller.signal));
|
|
16533
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
16534
|
+
const timeoutId = setTimeout(() => {
|
|
16535
|
+
controller.abort("timeout");
|
|
16536
|
+
reject(createTimeoutError());
|
|
16537
|
+
}, timeoutMs);
|
|
16538
|
+
controller.signal.addEventListener("abort", () => clearTimeout(timeoutId), { once: true });
|
|
16539
|
+
});
|
|
14749
16540
|
try {
|
|
14750
|
-
|
|
14751
|
-
|
|
14752
|
-
|
|
14753
|
-
|
|
14754
|
-
|
|
16541
|
+
return await Promise.race([
|
|
16542
|
+
taskPromise.catch((error) => {
|
|
16543
|
+
if (controller.signal.aborted) {
|
|
16544
|
+
throw createTimeoutError(error);
|
|
16545
|
+
}
|
|
16546
|
+
throw error;
|
|
16547
|
+
}),
|
|
16548
|
+
timeoutPromise
|
|
16549
|
+
]);
|
|
14755
16550
|
} catch (error) {
|
|
16551
|
+
if (isProviderRuntimeError(error) && error.code === "timeout") {
|
|
16552
|
+
throw error;
|
|
16553
|
+
}
|
|
14756
16554
|
if (controller.signal.aborted) {
|
|
14757
|
-
throw
|
|
14758
|
-
retryable: true,
|
|
14759
|
-
cause: error
|
|
14760
|
-
});
|
|
16555
|
+
throw createTimeoutError(error);
|
|
14761
16556
|
}
|
|
14762
16557
|
throw error;
|
|
14763
|
-
} finally {
|
|
14764
|
-
clearTimeout(timeoutId);
|
|
14765
16558
|
}
|
|
14766
16559
|
}
|
|
14767
16560
|
};
|
|
@@ -15189,6 +16982,7 @@ var mergeBudgets = (base, partial) => {
|
|
|
15189
16982
|
};
|
|
15190
16983
|
|
|
15191
16984
|
export {
|
|
16985
|
+
redactSensitive,
|
|
15192
16986
|
createRequestId,
|
|
15193
16987
|
stderrSink,
|
|
15194
16988
|
setDefaultLogSink,
|
|
@@ -15204,6 +16998,7 @@ export {
|
|
|
15204
16998
|
CHALLENGE_AUTOMATION_MODES,
|
|
15205
16999
|
isChallengeAutomationMode,
|
|
15206
17000
|
resolveChallengeAutomationPolicy,
|
|
17001
|
+
inspectChallengePlanFromRuntime,
|
|
15207
17002
|
ChallengeOrchestrator,
|
|
15208
17003
|
summarizePrimaryProviderIssue,
|
|
15209
17004
|
createTraceContext,
|
|
@@ -15244,13 +17039,15 @@ export {
|
|
|
15244
17039
|
enrichResearchRecords,
|
|
15245
17040
|
renderResearch,
|
|
15246
17041
|
renderShopping,
|
|
17042
|
+
renderInspiredesign,
|
|
15247
17043
|
workflowTestUtils,
|
|
15248
17044
|
runResearchWorkflow,
|
|
15249
17045
|
runShoppingWorkflow,
|
|
17046
|
+
runInspiredesignWorkflow,
|
|
15250
17047
|
runProductVideoWorkflow,
|
|
15251
17048
|
DEFAULT_PROVIDER_BUDGETS,
|
|
15252
17049
|
ProviderRuntime,
|
|
15253
17050
|
createProviderRuntime,
|
|
15254
17051
|
createDefaultRuntime
|
|
15255
17052
|
};
|
|
15256
|
-
//# sourceMappingURL=chunk-
|
|
17053
|
+
//# sourceMappingURL=chunk-C6QUKABT.js.map
|