opendevbrowser 0.0.27 → 0.0.28
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 +1 -1
- package/dist/browser/canvas-manager.d.ts.map +1 -1
- package/dist/canvas/document-store.d.ts.map +1 -1
- package/dist/canvas/guidance.d.ts +22 -0
- package/dist/canvas/guidance.d.ts.map +1 -0
- package/dist/{chunk-MWBDO2L5.js → chunk-I5ZCOZZV.js} +224 -80
- package/dist/chunk-I5ZCOZZV.js.map +1 -0
- package/dist/{chunk-V5DJUSPV.js → chunk-T3VVHJTK.js} +1381 -318
- package/dist/chunk-T3VVHJTK.js.map +1 -0
- package/dist/cli/commands/inspiredesign.d.ts +2 -0
- package/dist/cli/commands/inspiredesign.d.ts.map +1 -1
- package/dist/cli/commands/macro-resolve.d.ts +2 -0
- package/dist/cli/commands/macro-resolve.d.ts.map +1 -1
- package/dist/cli/commands/product-video.d.ts +2 -0
- package/dist/cli/commands/product-video.d.ts.map +1 -1
- package/dist/cli/commands/research.d.ts +2 -0
- package/dist/cli/commands/research.d.ts.map +1 -1
- package/dist/cli/daemon-commands.d.ts.map +1 -1
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/index.js +125 -28
- package/dist/cli/index.js.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/daemon-fingerprint.json +1 -1
- package/dist/index.js +39 -15
- package/dist/index.js.map +1 -1
- package/dist/inspiredesign/contract.d.ts +52 -1
- package/dist/inspiredesign/contract.d.ts.map +1 -1
- package/dist/inspiredesign/handoff.d.ts +12 -0
- package/dist/inspiredesign/handoff.d.ts.map +1 -1
- package/dist/inspiredesign/reference-pattern-board.d.ts +1 -0
- package/dist/inspiredesign/reference-pattern-board.d.ts.map +1 -1
- package/dist/macros/execute-runtime.d.ts +2 -1
- package/dist/macros/execute-runtime.d.ts.map +1 -1
- package/dist/macros/execute.d.ts +4 -2
- package/dist/macros/execute.d.ts.map +1 -1
- package/dist/opendevbrowser.js +39 -15
- package/dist/opendevbrowser.js.map +1 -1
- package/dist/providers/browser-fallback.d.ts +7 -0
- package/dist/providers/browser-fallback.d.ts.map +1 -1
- package/dist/providers/community/index.d.ts.map +1 -1
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/renderer.d.ts.map +1 -1
- package/dist/providers/research-compiler.d.ts.map +1 -1
- package/dist/providers/runtime-bundle.d.ts +1 -1
- package/dist/providers/runtime-bundle.d.ts.map +1 -1
- package/dist/providers/runtime-factory.d.ts.map +1 -1
- package/dist/providers/shopping/index.d.ts.map +1 -1
- package/dist/providers/social/platform.d.ts.map +1 -1
- package/dist/providers/social/search-quality.d.ts.map +1 -1
- package/dist/providers/social/youtube.d.ts.map +1 -1
- package/dist/providers/workflow-handoff.d.ts +18 -1
- package/dist/providers/workflow-handoff.d.ts.map +1 -1
- package/dist/providers/workflows.d.ts +3 -0
- package/dist/providers/workflows.d.ts.map +1 -1
- package/dist/{providers-TR3DUJZV.js → providers-QF2RFB4J.js} +2 -2
- package/dist/public-surface/generated-manifest.d.ts +6 -6
- package/dist/public-surface/generated-manifest.d.ts.map +1 -1
- package/dist/public-surface/source.d.ts +8 -8
- package/dist/public-surface/source.d.ts.map +1 -1
- package/dist/tools/inspiredesign_run.d.ts.map +1 -1
- package/dist/tools/macro_resolve.d.ts.map +1 -1
- package/dist/tools/product_video_run.d.ts.map +1 -1
- package/dist/tools/research_run.d.ts.map +1 -1
- package/dist/tools/shopping_run.d.ts.map +1 -1
- package/extension/manifest.json +1 -1
- package/package.json +1 -1
- package/skills/opendevbrowser-best-practices/SKILL.md +6 -6
- package/skills/opendevbrowser-design-agent/SKILL.md +5 -0
- package/skills/opendevbrowser-design-agent/artifacts/design-contract-playbook.md +6 -1
- package/skills/opendevbrowser-design-agent/assets/templates/design-contract.v1.json +15 -1
- package/skills/opendevbrowser-design-agent/assets/templates/inspiredesign-advanced-brief.v1.json +5 -2
- package/skills/opendevbrowser-design-agent/assets/templates/reference-pattern-board.v1.json +2 -0
- package/dist/chunk-MWBDO2L5.js.map +0 -1
- package/dist/chunk-V5DJUSPV.js.map +0 -1
- /package/dist/{providers-TR3DUJZV.js.map → providers-QF2RFB4J.js.map} +0 -0
|
@@ -3595,7 +3595,7 @@ var readFallbackRecord = (details, key) => {
|
|
|
3595
3595
|
};
|
|
3596
3596
|
var readFallbackString = (output, key) => {
|
|
3597
3597
|
const value = output?.[key];
|
|
3598
|
-
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
3598
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
3599
3599
|
};
|
|
3600
3600
|
var fallbackDispositionMessage = (fallback, url) => {
|
|
3601
3601
|
if (typeof fallback.details?.message === "string" && fallback.details.message.trim().length > 0) {
|
|
@@ -3610,32 +3610,67 @@ var fallbackDispositionMessage = (fallback, url) => {
|
|
|
3610
3610
|
return `Browser fallback failed for ${url}`;
|
|
3611
3611
|
}
|
|
3612
3612
|
};
|
|
3613
|
+
var fallbackErrorDetails = (args) => ({
|
|
3614
|
+
url: args.url,
|
|
3615
|
+
disposition: args.fallback.disposition,
|
|
3616
|
+
...args.fallback.mode ? { browserFallbackMode: args.fallback.mode } : {},
|
|
3617
|
+
...args.fallback.challenge ? { challenge: toJsonRecord(args.fallback.challenge) } : {},
|
|
3618
|
+
...args.fallback.preservedSessionId ? { preservedSessionId: args.fallback.preservedSessionId } : {},
|
|
3619
|
+
...args.fallback.preservedTargetId ? { preservedTargetId: args.fallback.preservedTargetId } : {},
|
|
3620
|
+
...toJsonRecord(args.fallback.details ?? {}),
|
|
3621
|
+
...args.extra ?? {}
|
|
3622
|
+
});
|
|
3623
|
+
var addProviderIssueGuidance = (args) => {
|
|
3624
|
+
const hint = readProviderIssueHint({
|
|
3625
|
+
reasonCode: args.reasonCode,
|
|
3626
|
+
details: args.details
|
|
3627
|
+
});
|
|
3628
|
+
const guidanceDetails = args.includeCompleted ? { ...args.details, disposition: "failed" } : args.details;
|
|
3629
|
+
const guidance = hint ? buildProviderIssueGuidance({ provider: args.provider, hint, details: guidanceDetails }) : void 0;
|
|
3630
|
+
return guidance ? { ...args.details, guidance } : args.details;
|
|
3631
|
+
};
|
|
3613
3632
|
var toProviderFallbackError = (args) => {
|
|
3614
3633
|
const { fallback } = args;
|
|
3615
3634
|
const reasonCode = fallback.reasonCode;
|
|
3616
|
-
const details = {
|
|
3635
|
+
const details = fallbackErrorDetails({ url: args.url, fallback });
|
|
3636
|
+
return new ProviderRuntimeError(
|
|
3637
|
+
providerErrorCodeFromReasonCode(reasonCode),
|
|
3638
|
+
fallbackDispositionMessage(fallback, args.url),
|
|
3639
|
+
{
|
|
3640
|
+
provider: args.provider,
|
|
3641
|
+
source: args.source,
|
|
3642
|
+
retryable: reasonCode === "rate_limited",
|
|
3643
|
+
reasonCode,
|
|
3644
|
+
details: addProviderIssueGuidance({
|
|
3645
|
+
provider: args.provider,
|
|
3646
|
+
reasonCode,
|
|
3647
|
+
details
|
|
3648
|
+
})
|
|
3649
|
+
}
|
|
3650
|
+
);
|
|
3651
|
+
};
|
|
3652
|
+
var toCompletedFallbackOutputError = (args) => {
|
|
3653
|
+
const { fallback } = args;
|
|
3654
|
+
const reasonCode = fallback.reasonCode;
|
|
3655
|
+
const details = fallbackErrorDetails({
|
|
3617
3656
|
url: args.url,
|
|
3618
|
-
|
|
3619
|
-
|
|
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
|
|
3657
|
+
fallback,
|
|
3658
|
+
extra: { fallbackOutputReason: args.outputReason }
|
|
3628
3659
|
});
|
|
3629
|
-
const guidance = hint ? buildProviderIssueGuidance({ provider: args.provider, hint, details }) : void 0;
|
|
3630
3660
|
return new ProviderRuntimeError(
|
|
3631
3661
|
providerErrorCodeFromReasonCode(reasonCode),
|
|
3632
|
-
|
|
3662
|
+
`Browser fallback completed for ${args.url} without usable HTML content.`,
|
|
3633
3663
|
{
|
|
3634
3664
|
provider: args.provider,
|
|
3635
3665
|
source: args.source,
|
|
3636
3666
|
retryable: reasonCode === "rate_limited",
|
|
3637
3667
|
reasonCode,
|
|
3638
|
-
details:
|
|
3668
|
+
details: addProviderIssueGuidance({
|
|
3669
|
+
provider: args.provider,
|
|
3670
|
+
reasonCode,
|
|
3671
|
+
details,
|
|
3672
|
+
includeCompleted: true
|
|
3673
|
+
})
|
|
3639
3674
|
}
|
|
3640
3675
|
);
|
|
3641
3676
|
};
|
|
@@ -5070,6 +5105,10 @@ var toPositiveInt = (value, fallback) => {
|
|
|
5070
5105
|
if (typeof value !== "number" || Number.isNaN(value)) return fallback;
|
|
5071
5106
|
return Math.max(1, Math.floor(value));
|
|
5072
5107
|
};
|
|
5108
|
+
var toNonNegativeInt = (value, fallback) => {
|
|
5109
|
+
if (typeof value !== "number" || Number.isNaN(value)) return fallback;
|
|
5110
|
+
return Math.max(0, Math.floor(value));
|
|
5111
|
+
};
|
|
5073
5112
|
var isHttpUrl2 = (value) => {
|
|
5074
5113
|
try {
|
|
5075
5114
|
const protocol = new URL(value).protocol;
|
|
@@ -5115,11 +5154,11 @@ var mergedTraversal = (options, input) => {
|
|
|
5115
5154
|
asNumber(filters.pageLimit) ?? options.defaultTraversal?.pageLimit,
|
|
5116
5155
|
DEFAULT_TRAVERSAL.pageLimit
|
|
5117
5156
|
),
|
|
5118
|
-
hopLimit:
|
|
5157
|
+
hopLimit: toNonNegativeInt(
|
|
5119
5158
|
asNumber(filters.hopLimit) ?? options.defaultTraversal?.hopLimit,
|
|
5120
5159
|
DEFAULT_TRAVERSAL.hopLimit
|
|
5121
5160
|
),
|
|
5122
|
-
expansionPerRecord:
|
|
5161
|
+
expansionPerRecord: toNonNegativeInt(
|
|
5123
5162
|
asNumber(filters.expansionPerRecord) ?? options.defaultTraversal?.expansionPerRecord,
|
|
5124
5163
|
DEFAULT_TRAVERSAL.expansionPerRecord
|
|
5125
5164
|
),
|
|
@@ -5428,7 +5467,7 @@ var createCommunityProvider = (options = {}) => {
|
|
|
5428
5467
|
};
|
|
5429
5468
|
|
|
5430
5469
|
// src/providers/social/search-quality.ts
|
|
5431
|
-
var TARGETED_PLATFORMS = /* @__PURE__ */ new Set(["x", "bluesky", "reddit", "facebook"]);
|
|
5470
|
+
var TARGETED_PLATFORMS = /* @__PURE__ */ new Set(["x", "bluesky", "reddit", "facebook", "threads"]);
|
|
5432
5471
|
var SOCIAL_JS_REQUIRED_RE = /\b(?:javascript (?:is not available|required|is disabled(?: in this browser)?)|you need to enable javascript|please enable javascript)\b/i;
|
|
5433
5472
|
var BLUESKY_LOGGED_OUT_SEARCH_RE = /\bsearch is currently unavailable when logged out\b/i;
|
|
5434
5473
|
var BLUESKY_EMPTY_SEARCH_SHELL_RE = /\b(?:follow 10 people to get started|find people to follow)\b/i;
|
|
@@ -5496,6 +5535,10 @@ var isPrimaryFacebookHost = (host) => {
|
|
|
5496
5535
|
const normalized = host.toLowerCase();
|
|
5497
5536
|
return normalized === "www.facebook.com" || normalized === "facebook.com" || normalized === "m.facebook.com";
|
|
5498
5537
|
};
|
|
5538
|
+
var isPrimaryThreadsHost = (host) => {
|
|
5539
|
+
const normalized = host.toLowerCase();
|
|
5540
|
+
return normalized === "www.threads.net" || normalized === "threads.net";
|
|
5541
|
+
};
|
|
5499
5542
|
var isFacebookSearchLikePath = (pathname) => pathname === "/watch/search" || pathname === "/watch/search/" || pathname.startsWith("/watch/explore/") || pathname.startsWith("/search/") || pathname.startsWith("/public/") || pathname.startsWith("/hashtag/");
|
|
5500
5543
|
var isBlockedFacebookNonContentUrl = (parsed, options) => {
|
|
5501
5544
|
if (!isPrimaryFacebookHost(parsed.hostname)) {
|
|
@@ -5522,7 +5565,7 @@ var isBlockedRedditNonContentUrl = (parsed, options) => {
|
|
|
5522
5565
|
return false;
|
|
5523
5566
|
}
|
|
5524
5567
|
const pathname = parsed.pathname.toLowerCase();
|
|
5525
|
-
if (pathname === "/" || pathname === "/login" || options.includeSearchRoute && pathname === "/search") {
|
|
5568
|
+
if (pathname === "/" || pathname === "/login" || pathname === "/login/" || options.includeSearchRoute && (pathname === "/search" || pathname === "/search/")) {
|
|
5526
5569
|
return true;
|
|
5527
5570
|
}
|
|
5528
5571
|
const pathSegment = firstPathSegment(pathname);
|
|
@@ -5540,6 +5583,8 @@ var isRootShellUrl = (platform, parsed) => {
|
|
|
5540
5583
|
return isBlockedRedditNonContentUrl(parsed, { includeSearchRoute: false });
|
|
5541
5584
|
case "facebook":
|
|
5542
5585
|
return isBlockedFacebookNonContentUrl(parsed, { includeSearchRoute: false });
|
|
5586
|
+
case "threads":
|
|
5587
|
+
return isPrimaryThreadsHost(host) && (pathname === "/" || pathname === "/login" || pathname === "/login/");
|
|
5543
5588
|
default:
|
|
5544
5589
|
return false;
|
|
5545
5590
|
}
|
|
@@ -5556,6 +5601,8 @@ var isBlockedExpansionPath = (platform, parsed) => {
|
|
|
5556
5601
|
return isBlockedRedditNonContentUrl(parsed, { includeSearchRoute: true });
|
|
5557
5602
|
case "facebook":
|
|
5558
5603
|
return isBlockedFacebookNonContentUrl(parsed, { includeSearchRoute: true });
|
|
5604
|
+
case "threads":
|
|
5605
|
+
return isPrimaryThreadsHost(host) && (pathname === "/" || pathname === "/login" || pathname === "/search" || pathname === "/search/" || isStaticMetadataPath(pathname));
|
|
5559
5606
|
default:
|
|
5560
5607
|
return false;
|
|
5561
5608
|
}
|
|
@@ -5569,9 +5616,11 @@ var isFirstPartySearchRoute = (platform, parsed) => {
|
|
|
5569
5616
|
case "bluesky":
|
|
5570
5617
|
return host === "bsky.app" && pathname === "/search";
|
|
5571
5618
|
case "reddit":
|
|
5572
|
-
return isPrimaryRedditHost(host) && pathname === "/search";
|
|
5619
|
+
return isPrimaryRedditHost(host) && (pathname === "/search" || pathname === "/search/");
|
|
5573
5620
|
case "facebook":
|
|
5574
5621
|
return isPrimaryFacebookHost(host) && isFacebookSearchLikePath(pathname);
|
|
5622
|
+
case "threads":
|
|
5623
|
+
return isPrimaryThreadsHost(host) && (pathname === "/search" || pathname === "/search/");
|
|
5575
5624
|
default:
|
|
5576
5625
|
return false;
|
|
5577
5626
|
}
|
|
@@ -5648,6 +5697,10 @@ var isUsableFacebookSearchEvidenceUrl = (url) => {
|
|
|
5648
5697
|
}
|
|
5649
5698
|
return /^\/reel\/[^/]+\/?$/.test(pathname) || /^\/groups\/[^/]+\/posts\/[^/]+\/?$/.test(pathname) || /^\/[^/]+\/videos\/[^/]+\/?$/.test(pathname) || /^\/share\/v\/[^/]+\/?$/.test(pathname) || (pathname === "/permalink.php" || pathname === "/story.php") && parsed.searchParams.has("story_fbid") || pathname === "/photo/" && parsed.searchParams.has("fbid");
|
|
5650
5699
|
};
|
|
5700
|
+
var isUsableThreadsSearchEvidenceUrl = (url) => {
|
|
5701
|
+
const parsed = parseUrl(url);
|
|
5702
|
+
return parsed !== null && isPrimaryThreadsHost(parsed.hostname) && /^\/@[^/]+\/post\/[^/]+\/?$/.test(parsed.pathname.toLowerCase());
|
|
5703
|
+
};
|
|
5651
5704
|
var isRetainableFacebookSearchSupportUrl = (url) => {
|
|
5652
5705
|
const parsed = parseUrl(url);
|
|
5653
5706
|
if (parsed === null || !isPrimaryFacebookHost(parsed.hostname)) {
|
|
@@ -5670,17 +5723,18 @@ var hasFacebookSearchResultSignals = (input) => {
|
|
|
5670
5723
|
const hasSearchHeading = FACEBOOK_SEARCH_RESULTS_HEADING_RE.test(combined);
|
|
5671
5724
|
const markerCount = FACEBOOK_SEARCH_RESULT_MARKERS.filter((pattern) => pattern.test(combined)).length;
|
|
5672
5725
|
const evidence = collectSocialSearchLinkEvidence("facebook", parsed.toString(), Array.isArray(input.links) ? input.links : []);
|
|
5726
|
+
const hasContentEvidence = evidence.usableContentLinks.length > 0;
|
|
5673
5727
|
const supportLinkCount = evidence.usableLinks.filter(isRetainableFacebookSearchSupportUrl).length;
|
|
5674
|
-
if (markerCount >= 2) {
|
|
5728
|
+
if (markerCount >= 2 && hasContentEvidence) {
|
|
5675
5729
|
return true;
|
|
5676
5730
|
}
|
|
5677
5731
|
if (!hasSearchHeading) {
|
|
5678
5732
|
return false;
|
|
5679
5733
|
}
|
|
5680
|
-
if (markerCount >= 1) {
|
|
5734
|
+
if (markerCount >= 1 && hasContentEvidence) {
|
|
5681
5735
|
return true;
|
|
5682
5736
|
}
|
|
5683
|
-
return supportLinkCount >= 2;
|
|
5737
|
+
return supportLinkCount >= 2 && hasContentEvidence;
|
|
5684
5738
|
};
|
|
5685
5739
|
var isUsableSocialSearchContentUrl = (platform, url) => {
|
|
5686
5740
|
switch (platform) {
|
|
@@ -5692,6 +5746,8 @@ var isUsableSocialSearchContentUrl = (platform, url) => {
|
|
|
5692
5746
|
return isUsableRedditSearchEvidenceUrl(url);
|
|
5693
5747
|
case "facebook":
|
|
5694
5748
|
return isUsableFacebookSearchEvidenceUrl(url);
|
|
5749
|
+
case "threads":
|
|
5750
|
+
return isUsableThreadsSearchEvidenceUrl(url);
|
|
5695
5751
|
default:
|
|
5696
5752
|
return false;
|
|
5697
5753
|
}
|
|
@@ -5865,6 +5921,10 @@ var toPositiveInt2 = (value, fallback) => {
|
|
|
5865
5921
|
if (typeof value !== "number" || Number.isNaN(value)) return fallback;
|
|
5866
5922
|
return Math.max(1, Math.floor(value));
|
|
5867
5923
|
};
|
|
5924
|
+
var toNonNegativeInt2 = (value, fallback) => {
|
|
5925
|
+
if (typeof value !== "number" || Number.isNaN(value)) return fallback;
|
|
5926
|
+
return Math.max(0, Math.floor(value));
|
|
5927
|
+
};
|
|
5868
5928
|
var isHttpUrl3 = (value) => {
|
|
5869
5929
|
try {
|
|
5870
5930
|
const protocol = new URL(value).protocol;
|
|
@@ -5954,11 +6014,11 @@ var mergedTraversal2 = (input, options) => {
|
|
|
5954
6014
|
asNumber2(filters.pageLimit) ?? options.defaultTraversal?.pageLimit,
|
|
5955
6015
|
DEFAULT_TRAVERSAL2.pageLimit
|
|
5956
6016
|
),
|
|
5957
|
-
hopLimit:
|
|
6017
|
+
hopLimit: toNonNegativeInt2(
|
|
5958
6018
|
asNumber2(filters.hopLimit) ?? options.defaultTraversal?.hopLimit,
|
|
5959
6019
|
DEFAULT_TRAVERSAL2.hopLimit
|
|
5960
6020
|
),
|
|
5961
|
-
expansionPerRecord:
|
|
6021
|
+
expansionPerRecord: toNonNegativeInt2(
|
|
5962
6022
|
asNumber2(filters.expansionPerRecord) ?? options.defaultTraversal?.expansionPerRecord,
|
|
5963
6023
|
DEFAULT_TRAVERSAL2.expansionPerRecord
|
|
5964
6024
|
),
|
|
@@ -7412,6 +7472,47 @@ var normalizeYouTubeVideoLink = (url) => {
|
|
|
7412
7472
|
}
|
|
7413
7473
|
};
|
|
7414
7474
|
var YOUTUBE_SEARCH_SHELL_RE = /\b(?:about press copyright contact us creators advertise developers terms privacy policy|google for developers skip to main content youtube)\b/i;
|
|
7475
|
+
var YOUTUBE_FALLBACK_MIN_TEXT_CHARS = 40;
|
|
7476
|
+
var YOUTUBE_CONTENT_MARKER_RE = /"videoId"\s*:|"captionTracks"\s*:|itemprop="author"|itemprop="datePublished"|"viewCount"\s*:/i;
|
|
7477
|
+
var hasYouTubeFallbackEvidence = (html, url) => {
|
|
7478
|
+
if (YOUTUBE_CONTENT_MARKER_RE.test(html)) return true;
|
|
7479
|
+
return extractStructuredContent(html, url).links.some((link) => normalizeYouTubeVideoLink(link) !== null);
|
|
7480
|
+
};
|
|
7481
|
+
var reviewedFallback = (fallback, reasonCode) => ({
|
|
7482
|
+
...fallback,
|
|
7483
|
+
reasonCode: reasonCode ?? fallback.reasonCode
|
|
7484
|
+
});
|
|
7485
|
+
var assertUsableYouTubeFallbackPage = (url, fallback, html) => {
|
|
7486
|
+
const extracted = extractStructuredContent(html, url);
|
|
7487
|
+
const text = extracted.text.trim();
|
|
7488
|
+
const blocker = classifyBlockerSignal({
|
|
7489
|
+
source: "runtime_fetch",
|
|
7490
|
+
url,
|
|
7491
|
+
message: text,
|
|
7492
|
+
status: 200,
|
|
7493
|
+
providerErrorCode: "unavailable",
|
|
7494
|
+
retryable: true
|
|
7495
|
+
});
|
|
7496
|
+
if (blocker && blocker.type !== "unknown") {
|
|
7497
|
+
throw toCompletedFallbackOutputError({
|
|
7498
|
+
provider: "social/youtube",
|
|
7499
|
+
source: "social",
|
|
7500
|
+
url,
|
|
7501
|
+
fallback: reviewedFallback(fallback, blocker.reasonCode),
|
|
7502
|
+
outputReason: blocker.type
|
|
7503
|
+
});
|
|
7504
|
+
}
|
|
7505
|
+
if (hasYouTubeFallbackEvidence(html, url)) return;
|
|
7506
|
+
if (text.length < YOUTUBE_FALLBACK_MIN_TEXT_CHARS || YOUTUBE_SEARCH_SHELL_RE.test(text)) {
|
|
7507
|
+
throw toCompletedFallbackOutputError({
|
|
7508
|
+
provider: "social/youtube",
|
|
7509
|
+
source: "social",
|
|
7510
|
+
url,
|
|
7511
|
+
fallback,
|
|
7512
|
+
outputReason: "youtube_shell_or_metadata"
|
|
7513
|
+
});
|
|
7514
|
+
}
|
|
7515
|
+
};
|
|
7415
7516
|
var extractSearchResultSegment = (html, videoId) => {
|
|
7416
7517
|
const marker = new RegExp(`"videoId"\\s*:\\s*"${escapeRegExp(videoId)}"`);
|
|
7417
7518
|
const match = marker.exec(html);
|
|
@@ -7514,7 +7615,7 @@ var summarizeTranscript = (transcript) => {
|
|
|
7514
7615
|
const lines = transcript.split(/\n+/).map((line) => line.trim()).filter(Boolean);
|
|
7515
7616
|
return lines.slice(0, 8).join(" ").slice(0, 800);
|
|
7516
7617
|
};
|
|
7517
|
-
var
|
|
7618
|
+
var fetchPageDirect = async (url, context) => {
|
|
7518
7619
|
let response;
|
|
7519
7620
|
try {
|
|
7520
7621
|
response = await fetch(url, {
|
|
@@ -7567,6 +7668,108 @@ var fetchPage = async (url, context) => {
|
|
|
7567
7668
|
html: await response.text()
|
|
7568
7669
|
};
|
|
7569
7670
|
};
|
|
7671
|
+
var forcedFallbackReasonCode = (context) => {
|
|
7672
|
+
const policy = context.runtimePolicy;
|
|
7673
|
+
if (policy?.cookies.policy === "required") return "auth_required";
|
|
7674
|
+
return "env_limited";
|
|
7675
|
+
};
|
|
7676
|
+
var fallbackReasonCodeForPageError = (error, context) => {
|
|
7677
|
+
if (!isProviderRuntimeError(error)) return "env_limited";
|
|
7678
|
+
if (error.code === "auth") {
|
|
7679
|
+
return context.runtimePolicy?.cookies.policy === "required" ? "auth_required" : "token_required";
|
|
7680
|
+
}
|
|
7681
|
+
if (error.code === "rate_limited") return "rate_limited";
|
|
7682
|
+
if (error.code === "network" || error.code === "timeout") return "env_limited";
|
|
7683
|
+
if (error.code === "upstream") return "ip_blocked";
|
|
7684
|
+
if (error.reasonCode === "ip_blocked" || error.reasonCode === "challenge_detected") return error.reasonCode;
|
|
7685
|
+
return null;
|
|
7686
|
+
};
|
|
7687
|
+
var fallbackDetailsForError = (error) => {
|
|
7688
|
+
if (!isProviderRuntimeError(error)) return {};
|
|
7689
|
+
return {
|
|
7690
|
+
errorCode: error.code,
|
|
7691
|
+
message: error.message,
|
|
7692
|
+
...error.details ?? {}
|
|
7693
|
+
};
|
|
7694
|
+
};
|
|
7695
|
+
var pageFromFallback = (url, fallback) => {
|
|
7696
|
+
const html = readFallbackString(fallback.output, "html");
|
|
7697
|
+
if (!html) {
|
|
7698
|
+
throw toCompletedFallbackOutputError({
|
|
7699
|
+
provider: "social/youtube",
|
|
7700
|
+
source: "social",
|
|
7701
|
+
url,
|
|
7702
|
+
fallback,
|
|
7703
|
+
outputReason: "missing_or_empty_html"
|
|
7704
|
+
});
|
|
7705
|
+
}
|
|
7706
|
+
assertUsableYouTubeFallbackPage(url, fallback, html);
|
|
7707
|
+
return {
|
|
7708
|
+
status: 200,
|
|
7709
|
+
url: readFallbackString(fallback.output, "url") ?? url,
|
|
7710
|
+
html,
|
|
7711
|
+
browserFallback: toBrowserFallbackObservation(fallback)
|
|
7712
|
+
};
|
|
7713
|
+
};
|
|
7714
|
+
var resolveFallbackPage = async (args) => {
|
|
7715
|
+
const fallback = await resolveProviderBrowserFallback({
|
|
7716
|
+
browserFallbackPort: args.context.browserFallbackPort ?? args.options.browserFallbackPort,
|
|
7717
|
+
provider: "social/youtube",
|
|
7718
|
+
source: "social",
|
|
7719
|
+
operation: args.operation,
|
|
7720
|
+
reasonCode: args.reasonCode,
|
|
7721
|
+
url: args.url,
|
|
7722
|
+
context: args.context,
|
|
7723
|
+
details: args.details,
|
|
7724
|
+
recoveryHints: args.options.recoveryHints?.()
|
|
7725
|
+
});
|
|
7726
|
+
if (!fallback) return null;
|
|
7727
|
+
if (fallback.disposition !== "completed") {
|
|
7728
|
+
throw toProviderFallbackError({
|
|
7729
|
+
provider: "social/youtube",
|
|
7730
|
+
source: "social",
|
|
7731
|
+
url: args.url,
|
|
7732
|
+
fallback
|
|
7733
|
+
});
|
|
7734
|
+
}
|
|
7735
|
+
return pageFromFallback(args.url, fallback);
|
|
7736
|
+
};
|
|
7737
|
+
var fetchPage = async (url, context, options, operation) => {
|
|
7738
|
+
if (context.runtimePolicy?.browser.forceTransport) {
|
|
7739
|
+
const page = await resolveFallbackPage({
|
|
7740
|
+
url,
|
|
7741
|
+
context,
|
|
7742
|
+
options,
|
|
7743
|
+
operation,
|
|
7744
|
+
reasonCode: forcedFallbackReasonCode(context),
|
|
7745
|
+
details: { message: "Direct browser transport was selected for this YouTube provider run." }
|
|
7746
|
+
});
|
|
7747
|
+
if (page) return page;
|
|
7748
|
+
throw new ProviderRuntimeError(providerErrorCodeFromReasonCode(forcedFallbackReasonCode(context)), "Direct browser transport is required for this YouTube provider run, but no browser transport is available.", {
|
|
7749
|
+
provider: "social/youtube",
|
|
7750
|
+
source: "social",
|
|
7751
|
+
retryable: false,
|
|
7752
|
+
reasonCode: forcedFallbackReasonCode(context),
|
|
7753
|
+
details: { browserTransportRequired: true }
|
|
7754
|
+
});
|
|
7755
|
+
}
|
|
7756
|
+
try {
|
|
7757
|
+
return await fetchPageDirect(url, context);
|
|
7758
|
+
} catch (error) {
|
|
7759
|
+
const reasonCode = fallbackReasonCodeForPageError(error, context);
|
|
7760
|
+
if (!reasonCode) throw error;
|
|
7761
|
+
const page = await resolveFallbackPage({
|
|
7762
|
+
url,
|
|
7763
|
+
context,
|
|
7764
|
+
options,
|
|
7765
|
+
operation,
|
|
7766
|
+
reasonCode,
|
|
7767
|
+
details: fallbackDetailsForError(error)
|
|
7768
|
+
});
|
|
7769
|
+
if (page) return page;
|
|
7770
|
+
throw error;
|
|
7771
|
+
}
|
|
7772
|
+
};
|
|
7570
7773
|
var parseBooleanFilter = (value, fallback = false) => {
|
|
7571
7774
|
if (typeof value === "boolean") return value;
|
|
7572
7775
|
if (typeof value === "string") {
|
|
@@ -7609,7 +7812,7 @@ var resolveTranscriptStrategyDetail = (transcript) => {
|
|
|
7609
7812
|
return transcript.attemptChain.at(-1)?.strategy;
|
|
7610
7813
|
};
|
|
7611
7814
|
var buildSearch = (options) => {
|
|
7612
|
-
if (options) return options;
|
|
7815
|
+
if (options.search) return options.search;
|
|
7613
7816
|
return async (input, context) => {
|
|
7614
7817
|
assertYouTubeLegalReviewChecklist();
|
|
7615
7818
|
const query = input.query.trim();
|
|
@@ -7622,7 +7825,7 @@ var buildSearch = (options) => {
|
|
|
7622
7825
|
}
|
|
7623
7826
|
const lookupUrl = isHttpUrl4(query) ? query : `https://www.youtube.com/results?search_query=${encodeURIComponent(query)}`;
|
|
7624
7827
|
const directUrlQuery = isHttpUrl4(query);
|
|
7625
|
-
const page = await fetchPage(lookupUrl, context);
|
|
7828
|
+
const page = await fetchPage(lookupUrl, context, options, "search");
|
|
7626
7829
|
const extracted = extractStructuredContent(page.html, page.url);
|
|
7627
7830
|
const extractedVideoLinks = [...new Set(
|
|
7628
7831
|
extracted.links.map((link) => normalizeYouTubeVideoLink(link)).filter((link) => typeof link === "string" && link.length > 0)
|
|
@@ -7668,7 +7871,8 @@ var buildSearch = (options) => {
|
|
|
7668
7871
|
retrievalPath: isHttpUrl4(query) ? "social:youtube:search:url" : "social:youtube:search:index",
|
|
7669
7872
|
video_id: resolvedVideoId,
|
|
7670
7873
|
...primaryResult?.channel ? { channel: primaryResult.channel } : {},
|
|
7671
|
-
links: extractedVideoLinks.slice(0, 20)
|
|
7874
|
+
links: extractedVideoLinks.slice(0, 20),
|
|
7875
|
+
...browserFallbackObservationAttributes(page.browserFallback)
|
|
7672
7876
|
}
|
|
7673
7877
|
}];
|
|
7674
7878
|
};
|
|
@@ -7677,7 +7881,7 @@ var buildFetch = (options) => {
|
|
|
7677
7881
|
if (options.fetch) return options.fetch;
|
|
7678
7882
|
return async (input, context) => {
|
|
7679
7883
|
assertYouTubeLegalReviewChecklist();
|
|
7680
|
-
const page = await fetchPage(input.url, context);
|
|
7884
|
+
const page = await fetchPage(input.url, context, options, "fetch");
|
|
7681
7885
|
const extracted = extractStructuredContent(page.html, page.url);
|
|
7682
7886
|
const includeFullTranscript = parseBooleanFilter(input.filters?.include_full_transcript, false);
|
|
7683
7887
|
const requireTranscript = parseBooleanFilter(input.filters?.requireTranscript, false);
|
|
@@ -7692,7 +7896,7 @@ var buildFetch = (options) => {
|
|
|
7692
7896
|
legalChecklist: YOUTUBE_LEGAL_REVIEW_CHECKLIST,
|
|
7693
7897
|
config: transcriptConfig,
|
|
7694
7898
|
mode: requestedMode,
|
|
7695
|
-
browserFallbackPort: options.browserFallbackPort,
|
|
7899
|
+
browserFallbackPort: context.browserFallbackPort ?? options.browserFallbackPort,
|
|
7696
7900
|
recoveryHints,
|
|
7697
7901
|
allowBrowserFallbackEscalation: options.antiBotPolicy?.allowBrowserEscalation ?? true,
|
|
7698
7902
|
asrTranscribe: options.asrTranscribe
|
|
@@ -7747,6 +7951,7 @@ var buildFetch = (options) => {
|
|
|
7747
7951
|
transcript_mode: transcript.mode,
|
|
7748
7952
|
translation_applied: translationApplied,
|
|
7749
7953
|
transcript_summary: transcriptSummary,
|
|
7954
|
+
...browserFallbackObservationAttributes(page.browserFallback),
|
|
7750
7955
|
...includeFullTranscript ? { transcript_full: transcriptContent } : {},
|
|
7751
7956
|
...transcriptStrategyDetail ? { transcript_strategy_detail: transcriptStrategyDetail } : {},
|
|
7752
7957
|
...transcript.ok ? {
|
|
@@ -7789,7 +7994,7 @@ var withDefaultYouTubeOptions = (options = {}) => {
|
|
|
7789
7994
|
};
|
|
7790
7995
|
return {
|
|
7791
7996
|
...resolvedOptions,
|
|
7792
|
-
search: buildSearch(resolvedOptions
|
|
7997
|
+
search: buildSearch(resolvedOptions),
|
|
7793
7998
|
fetch: buildFetch(resolvedOptions)
|
|
7794
7999
|
};
|
|
7795
8000
|
};
|
|
@@ -7989,6 +8194,73 @@ var getShoppingRegionSupportDiagnostics = (providerIds, region) => {
|
|
|
7989
8194
|
});
|
|
7990
8195
|
};
|
|
7991
8196
|
var hasValues2 = (values) => values.some((value) => value.trim().length > 0);
|
|
8197
|
+
var FALLBACK_HEAD_RE = /<head\b[^>]*>[\s\S]*?<\/head>/i;
|
|
8198
|
+
var FALLBACK_BODY_RE = /<body\b[^>]*>([\s\S]*?)<\/body>/i;
|
|
8199
|
+
var SHOPPING_FALLBACK_EVIDENCE_LIMIT = 1;
|
|
8200
|
+
var extractShoppingFallbackBodyText = (html) => {
|
|
8201
|
+
const body = FALLBACK_BODY_RE.exec(html)?.[1];
|
|
8202
|
+
return extractText(body ?? html.replace(FALLBACK_HEAD_RE, " "));
|
|
8203
|
+
};
|
|
8204
|
+
var hasShoppingMetadataEvidence = (extracted) => {
|
|
8205
|
+
return extracted.metadata.price !== void 0;
|
|
8206
|
+
};
|
|
8207
|
+
var hasShoppingOfferTextEvidence = (text) => {
|
|
8208
|
+
const price = parsePrice(text);
|
|
8209
|
+
if (price.amount <= 0) return false;
|
|
8210
|
+
return parseRating(text) > 0 || parseReviews(text) > 0 || parseAvailability(text) !== "unknown" || /\b(?:add to cart|buy now|shipping|pickup|deal|save)\b/i.test(text);
|
|
8211
|
+
};
|
|
8212
|
+
var hasShoppingBlockingPageEvidence = (url, extracted) => {
|
|
8213
|
+
const blocker = classifyBlockerSignal({
|
|
8214
|
+
source: "runtime_fetch",
|
|
8215
|
+
url,
|
|
8216
|
+
finalUrl: url,
|
|
8217
|
+
title: typeof extracted.metadata.title === "string" ? extracted.metadata.title : void 0,
|
|
8218
|
+
message: extracted.text,
|
|
8219
|
+
status: 200,
|
|
8220
|
+
providerErrorCode: "unavailable",
|
|
8221
|
+
retryable: true
|
|
8222
|
+
});
|
|
8223
|
+
return blocker?.type === "auth_required" || blocker?.type === "anti_bot_challenge";
|
|
8224
|
+
};
|
|
8225
|
+
var hasShoppingFallbackEvidence = (args) => {
|
|
8226
|
+
return args.extracted.links.some((link) => isLikelyProductUrl(canonicalizeUrl(link), args.profile)) || extractSearchCandidates(args.html, args.url, args.profile, SHOPPING_FALLBACK_EVIDENCE_LIMIT).length > 0 || hasShoppingMetadataEvidence(args.extracted) || hasShoppingOfferTextEvidence(extractShoppingFallbackBodyText(args.html)) || hasShoppingBlockingPageEvidence(args.url, args.extracted);
|
|
8227
|
+
};
|
|
8228
|
+
var toFallbackShellIssueError = (args) => {
|
|
8229
|
+
const issue = classifyProviderIssue({
|
|
8230
|
+
url: args.url,
|
|
8231
|
+
title: args.requirement.title,
|
|
8232
|
+
message: args.requirement.message,
|
|
8233
|
+
providerShell: args.requirement.reason,
|
|
8234
|
+
browserRequired: true,
|
|
8235
|
+
status: 200
|
|
8236
|
+
});
|
|
8237
|
+
const reasonCode = issue?.reasonCode ?? "env_limited";
|
|
8238
|
+
const extracted = extractStructuredContent(args.html, args.url);
|
|
8239
|
+
return new ProviderRuntimeError(
|
|
8240
|
+
providerErrorCodeFromReasonCode(reasonCode),
|
|
8241
|
+
reasonCode === "challenge_detected" ? `Detected anti-bot challenge while retrieving ${args.url}` : `Browser assistance required for ${args.url}`,
|
|
8242
|
+
{
|
|
8243
|
+
provider: args.provider,
|
|
8244
|
+
source: SHOPPING_SOURCE,
|
|
8245
|
+
retryable: reasonCode === "env_limited",
|
|
8246
|
+
reasonCode,
|
|
8247
|
+
details: {
|
|
8248
|
+
...applyProviderIssueHint({
|
|
8249
|
+
status: 200,
|
|
8250
|
+
url: args.url,
|
|
8251
|
+
...args.requirement.title ? { title: args.requirement.title } : {},
|
|
8252
|
+
...args.requirement.message ? { message: args.requirement.message } : {},
|
|
8253
|
+
providerShell: args.requirement.reason,
|
|
8254
|
+
browserRequired: true,
|
|
8255
|
+
extractionFocus: args.profile.extractionFocus,
|
|
8256
|
+
extractedTextLength: extracted.text.length,
|
|
8257
|
+
extractedLinkCount: extracted.links.length
|
|
8258
|
+
}, issue),
|
|
8259
|
+
...browserFallbackObservationDetails(toBrowserFallbackObservation(args.fallback))
|
|
8260
|
+
}
|
|
8261
|
+
}
|
|
8262
|
+
);
|
|
8263
|
+
};
|
|
7992
8264
|
var parseIsoDate2 = (value) => {
|
|
7993
8265
|
const parsed = Date.parse(value);
|
|
7994
8266
|
return Number.isNaN(parsed) ? NaN : parsed;
|
|
@@ -8120,11 +8392,47 @@ var resolveBrowserFallback = async (args) => {
|
|
|
8120
8392
|
};
|
|
8121
8393
|
}
|
|
8122
8394
|
const resolvedUrl = canonicalizeUrl(readFallbackString(fallback.output, "url") ?? args.url);
|
|
8395
|
+
const html = readFallbackString(fallback.output, "html");
|
|
8396
|
+
if (!html) {
|
|
8397
|
+
throw toCompletedFallbackOutputError({
|
|
8398
|
+
provider: args.provider,
|
|
8399
|
+
source: SHOPPING_SOURCE,
|
|
8400
|
+
url: resolvedUrl,
|
|
8401
|
+
fallback,
|
|
8402
|
+
outputReason: "missing_or_empty_html"
|
|
8403
|
+
});
|
|
8404
|
+
}
|
|
8405
|
+
const extracted = extractStructuredContent(html, resolvedUrl);
|
|
8406
|
+
const browserRequirement = requiresBrowserAssistance(args.profile, resolvedUrl, html);
|
|
8407
|
+
if (browserRequirement) {
|
|
8408
|
+
throw toFallbackShellIssueError({
|
|
8409
|
+
provider: args.provider,
|
|
8410
|
+
url: resolvedUrl,
|
|
8411
|
+
html,
|
|
8412
|
+
fallback,
|
|
8413
|
+
profile: args.profile,
|
|
8414
|
+
requirement: browserRequirement
|
|
8415
|
+
});
|
|
8416
|
+
}
|
|
8417
|
+
if (!hasShoppingFallbackEvidence({
|
|
8418
|
+
html,
|
|
8419
|
+
url: resolvedUrl,
|
|
8420
|
+
extracted,
|
|
8421
|
+
profile: args.profile
|
|
8422
|
+
})) {
|
|
8423
|
+
throw toCompletedFallbackOutputError({
|
|
8424
|
+
provider: args.provider,
|
|
8425
|
+
source: SHOPPING_SOURCE,
|
|
8426
|
+
url: resolvedUrl,
|
|
8427
|
+
fallback,
|
|
8428
|
+
outputReason: "empty_extracted_content"
|
|
8429
|
+
});
|
|
8430
|
+
}
|
|
8123
8431
|
return {
|
|
8124
8432
|
record: {
|
|
8125
8433
|
status: 200,
|
|
8126
8434
|
url: resolvedUrl,
|
|
8127
|
-
html
|
|
8435
|
+
html,
|
|
8128
8436
|
browserFallback: toBrowserFallbackObservation(fallback)
|
|
8129
8437
|
}
|
|
8130
8438
|
};
|
|
@@ -8237,6 +8545,7 @@ var defaultFetcher = async ({ url, signal, provider, operation, context }) => {
|
|
|
8237
8545
|
error,
|
|
8238
8546
|
url,
|
|
8239
8547
|
provider: providerId,
|
|
8548
|
+
profile,
|
|
8240
8549
|
operation,
|
|
8241
8550
|
recoveryHints,
|
|
8242
8551
|
context
|
|
@@ -8644,8 +8953,7 @@ var requiresBrowserAssistance = (profile, responseUrl, html) => {
|
|
|
8644
8953
|
}
|
|
8645
8954
|
return null;
|
|
8646
8955
|
};
|
|
8647
|
-
var classifySearchPageIssue = (profile, fetched, extracted, content) => {
|
|
8648
|
-
const providerShell = requiresBrowserAssistance(profile, fetched.url, fetched.html);
|
|
8956
|
+
var classifySearchPageIssue = (profile, fetched, extracted, content, providerShell = requiresBrowserAssistance(profile, fetched.url, fetched.html)) => {
|
|
8649
8957
|
return classifyProviderIssue({
|
|
8650
8958
|
url: fetched.url,
|
|
8651
8959
|
title: providerShell?.title ?? (typeof extracted.metadata.title === "string" ? extracted.metadata.title : void 0),
|
|
@@ -8657,6 +8965,51 @@ var classifySearchPageIssue = (profile, fetched, extracted, content) => {
|
|
|
8657
8965
|
retryable: true
|
|
8658
8966
|
});
|
|
8659
8967
|
};
|
|
8968
|
+
var toExplicitProviderShellIssue = (providerShell, content) => ({
|
|
8969
|
+
reasonCode: "env_limited",
|
|
8970
|
+
blockerType: "env_limited",
|
|
8971
|
+
constraint: {
|
|
8972
|
+
kind: "render_required",
|
|
8973
|
+
evidenceCode: providerShell.reason,
|
|
8974
|
+
providerShell: providerShell.reason,
|
|
8975
|
+
...content ? { message: content } : {}
|
|
8976
|
+
}
|
|
8977
|
+
});
|
|
8978
|
+
var ensureProviderShellIssue = (issue, providerShell, content) => {
|
|
8979
|
+
if (!issue || issue.reasonCode === "env_limited" && !issue.constraint) {
|
|
8980
|
+
return toExplicitProviderShellIssue(providerShell, content);
|
|
8981
|
+
}
|
|
8982
|
+
return issue;
|
|
8983
|
+
};
|
|
8984
|
+
var toShoppingPageIssueMessage = (reasonCode, url) => {
|
|
8985
|
+
if (reasonCode === "token_required") return `Authentication required for ${url}`;
|
|
8986
|
+
if (reasonCode === "env_limited") return `Browser assistance required for ${url}`;
|
|
8987
|
+
return `Detected anti-bot challenge while retrieving ${url}`;
|
|
8988
|
+
};
|
|
8989
|
+
var throwShoppingPageIssue = (args) => {
|
|
8990
|
+
const reasonCode = args.pageIssue.reasonCode;
|
|
8991
|
+
throw new ProviderRuntimeError(
|
|
8992
|
+
providerErrorCodeFromReasonCode(reasonCode),
|
|
8993
|
+
toShoppingPageIssueMessage(reasonCode, args.fetched.url),
|
|
8994
|
+
{
|
|
8995
|
+
provider: args.providerId,
|
|
8996
|
+
source: SHOPPING_SOURCE,
|
|
8997
|
+
retryable: reasonCode === "env_limited",
|
|
8998
|
+
reasonCode,
|
|
8999
|
+
details: {
|
|
9000
|
+
...applyProviderIssueHint({
|
|
9001
|
+
status: args.fetched.status,
|
|
9002
|
+
url: args.fetched.url,
|
|
9003
|
+
...typeof args.extracted.metadata.title === "string" ? { title: args.extracted.metadata.title } : {},
|
|
9004
|
+
...args.content ? { message: args.content } : {},
|
|
9005
|
+
...args.providerShell?.reason ? { providerShell: args.providerShell.reason } : {}
|
|
9006
|
+
}, args.pageIssue),
|
|
9007
|
+
...args.providerShell?.reason ? { browserRequired: true } : {},
|
|
9008
|
+
...browserFallbackObservationDetails(args.fetched.browserFallback)
|
|
9009
|
+
}
|
|
9010
|
+
}
|
|
9011
|
+
);
|
|
9012
|
+
};
|
|
8660
9013
|
var unwrapTrackingUrl = (url, profile) => {
|
|
8661
9014
|
const normalizedUrl = decodeHrefValue(url);
|
|
8662
9015
|
try {
|
|
@@ -9054,6 +9407,7 @@ var createDefaultSearch = (profile, providerId, fetcher) => async (input, contex
|
|
|
9054
9407
|
context
|
|
9055
9408
|
});
|
|
9056
9409
|
const extracted = extractStructuredContent(fetched.html, fetched.url);
|
|
9410
|
+
const providerShell = requiresBrowserAssistance(profile, fetched.url, fetched.html);
|
|
9057
9411
|
const limit = Math.max(1, Math.min(input.limit ?? 10, 20));
|
|
9058
9412
|
const links = dedupeLinks(
|
|
9059
9413
|
extracted.links.filter((link) => isLikelyProductUrl(canonicalizeUrl(link), profile)),
|
|
@@ -9061,7 +9415,17 @@ var createDefaultSearch = (profile, providerId, fetcher) => async (input, contex
|
|
|
9061
9415
|
);
|
|
9062
9416
|
const content = toSnippet(extracted.text, 2e3);
|
|
9063
9417
|
const candidates = extractSearchCandidates(fetched.html, fetched.url, profile, limit);
|
|
9064
|
-
const pageIssue = candidates.length === 0 ? classifySearchPageIssue(profile, fetched, extracted, content) : null;
|
|
9418
|
+
const pageIssue = providerShell ? classifySearchPageIssue(profile, fetched, extracted, content, providerShell) : candidates.length === 0 ? classifySearchPageIssue(profile, fetched, extracted, content, providerShell) : null;
|
|
9419
|
+
if (providerShell) {
|
|
9420
|
+
throwShoppingPageIssue({
|
|
9421
|
+
providerId,
|
|
9422
|
+
fetched,
|
|
9423
|
+
extracted,
|
|
9424
|
+
content,
|
|
9425
|
+
pageIssue: ensureProviderShellIssue(pageIssue, providerShell, content),
|
|
9426
|
+
providerShell
|
|
9427
|
+
});
|
|
9428
|
+
}
|
|
9065
9429
|
if (candidates.length > 0) {
|
|
9066
9430
|
return candidates.map((candidate, index) => ({
|
|
9067
9431
|
url: candidate.url,
|
|
@@ -9096,28 +9460,7 @@ var createDefaultSearch = (profile, providerId, fetcher) => async (input, contex
|
|
|
9096
9460
|
}));
|
|
9097
9461
|
}
|
|
9098
9462
|
if (pageIssue && (pageIssue.reasonCode !== "env_limited" || pageIssue.constraint)) {
|
|
9099
|
-
|
|
9100
|
-
const providerShell = requiresBrowserAssistance(profile, fetched.url, fetched.html);
|
|
9101
|
-
throw new ProviderRuntimeError(
|
|
9102
|
-
providerErrorCodeFromReasonCode(reasonCode),
|
|
9103
|
-
reasonCode === "token_required" ? `Authentication required for ${fetched.url}` : `Detected anti-bot challenge while retrieving ${fetched.url}`,
|
|
9104
|
-
{
|
|
9105
|
-
provider: providerId,
|
|
9106
|
-
source: SHOPPING_SOURCE,
|
|
9107
|
-
retryable: reasonCode === "env_limited",
|
|
9108
|
-
reasonCode,
|
|
9109
|
-
details: {
|
|
9110
|
-
...applyProviderIssueHint({
|
|
9111
|
-
status: fetched.status,
|
|
9112
|
-
url: fetched.url,
|
|
9113
|
-
...typeof extracted.metadata.title === "string" ? { title: extracted.metadata.title } : {},
|
|
9114
|
-
...content ? { message: content } : {},
|
|
9115
|
-
...providerShell?.reason ? { providerShell: providerShell.reason } : {}
|
|
9116
|
-
}, pageIssue),
|
|
9117
|
-
...browserFallbackObservationDetails(fetched.browserFallback)
|
|
9118
|
-
}
|
|
9119
|
-
}
|
|
9120
|
-
);
|
|
9463
|
+
throwShoppingPageIssue({ providerId, fetched, extracted, content, pageIssue, providerShell });
|
|
9121
9464
|
}
|
|
9122
9465
|
const rows = [
|
|
9123
9466
|
{
|
|
@@ -10023,7 +10366,13 @@ var design_contract_v1_default = {
|
|
|
10023
10366
|
"section reveal",
|
|
10024
10367
|
"primary CTA feedback"
|
|
10025
10368
|
],
|
|
10026
|
-
parallaxPolicy: "off unless explicitly justified"
|
|
10369
|
+
parallaxPolicy: "off unless explicitly justified",
|
|
10370
|
+
advancedMotionAdvisory: [
|
|
10371
|
+
"Advisory shader-like gradient depth: describe intent only; implement with approved runtime primitives unless a separate runtime change authorizes more.",
|
|
10372
|
+
"Advisory WebGL-style spatial reveal: document depth and hierarchy without implying WebGL runtime support.",
|
|
10373
|
+
"Advisory Spline-style product orbit: document scene posture and static fallback without approving custom 3D runtime dependencies.",
|
|
10374
|
+
"Runtime boundary: libraryPolicy.motion and libraryPolicy.threeD stay empty unless separately approved."
|
|
10375
|
+
]
|
|
10027
10376
|
},
|
|
10028
10377
|
performanceModel: {
|
|
10029
10378
|
renderHotspots: [
|
|
@@ -10116,6 +10465,14 @@ var design_contract_v1_default = {
|
|
|
10116
10465
|
"spinner-stacking",
|
|
10117
10466
|
"scan-surface-jank"
|
|
10118
10467
|
]
|
|
10468
|
+
},
|
|
10469
|
+
designVectors: {
|
|
10470
|
+
advancedMotionAdvisory: [
|
|
10471
|
+
"Advisory shader-like gradient depth",
|
|
10472
|
+
"Advisory WebGL-style spatial reveal",
|
|
10473
|
+
"Advisory Spline-style product orbit",
|
|
10474
|
+
"Runtime support: none. Library policy authorization: none."
|
|
10475
|
+
]
|
|
10119
10476
|
}
|
|
10120
10477
|
}
|
|
10121
10478
|
};
|
|
@@ -10159,6 +10516,172 @@ var INSPIREDESIGN_HANDOFF_GUIDANCE = {
|
|
|
10159
10516
|
prepareCanvasPlanRequest: `Fill canvasSessionId, leaseId, and documentId in ${INSPIREDESIGN_HANDOFF_FILES.canvasPlanRequest} before running ${INSPIREDESIGN_HANDOFF_COMMANDS.continueInCanvas}.`,
|
|
10160
10517
|
deepCaptureRecommendation: "Any inspiredesign run with reference URLs already uses captureMode=deep. Rerun with the same URLs only when you need refreshed DOM/layout evidence, restored session state, or capture-specific debugging."
|
|
10161
10518
|
};
|
|
10519
|
+
var INSPIREDESIGN_ARTIFACT_GUIDE = {
|
|
10520
|
+
[INSPIREDESIGN_HANDOFF_FILES.advancedBrief]: {
|
|
10521
|
+
purpose: "Authoritative reference-first brief for the downstream design agent.",
|
|
10522
|
+
expectedContents: ["Selected prompt format", "reference pattern board", "route guardrails"],
|
|
10523
|
+
howToUse: ["Read first", "treat captured evidence as creative priority", "use guardrails to avoid route drift"],
|
|
10524
|
+
mustNot: ["Do not treat defaults as stronger than captured references"]
|
|
10525
|
+
},
|
|
10526
|
+
[INSPIREDESIGN_HANDOFF_FILES.designMarkdown]: {
|
|
10527
|
+
purpose: "Human-readable design specification and implementation narrative.",
|
|
10528
|
+
expectedContents: ["inspiration analysis", "unified direction", "governance summary", "deliverables"],
|
|
10529
|
+
howToUse: ["Use as the readable project brief", "cross-check implementation choices against its sections"],
|
|
10530
|
+
mustNot: ["Do not use prose as a substitute for the JSON contract when patching Canvas"]
|
|
10531
|
+
},
|
|
10532
|
+
[INSPIREDESIGN_HANDOFF_FILES.designContract]: {
|
|
10533
|
+
purpose: "Narrowed Canvas governance contract for design decisions.",
|
|
10534
|
+
expectedContents: ["emitted governance blocks", "motion system", "library policy", "runtime budgets"],
|
|
10535
|
+
howToUse: ["Patch only emitted governance blocks", "compare implementation against this contract before shipping"],
|
|
10536
|
+
mustNot: ["Do not add navigation, async, or performance context as Canvas governance patches"]
|
|
10537
|
+
},
|
|
10538
|
+
[INSPIREDESIGN_HANDOFF_FILES.canvasPlanRequest]: {
|
|
10539
|
+
purpose: "Ready-to-fill request payload for `canvas.plan.set`.",
|
|
10540
|
+
expectedContents: ["request ids", "Canvas session ids", "mutation-safe generationPlan"],
|
|
10541
|
+
howToUse: ["Fill canvasSessionId, leaseId, and documentId", "submit with the provided canvas.plan.set command"],
|
|
10542
|
+
mustNot: ["Do not add handoff-only fields or reference-only analysis to generationPlan"]
|
|
10543
|
+
},
|
|
10544
|
+
[INSPIREDESIGN_HANDOFF_FILES.designAgentHandoff]: {
|
|
10545
|
+
purpose: "Downstream index for artifact usage, skills, commands, and omitted implementation context.",
|
|
10546
|
+
expectedContents: ["skills", "commands", "contract scope", "implementation context", "artifact and section guides"],
|
|
10547
|
+
howToUse: ["Use as the navigation map for the bundle", "load recommended skills before implementation"],
|
|
10548
|
+
mustNot: ["Do not treat handoff context as runtime Canvas schema"]
|
|
10549
|
+
},
|
|
10550
|
+
[INSPIREDESIGN_HANDOFF_FILES.generationPlan]: {
|
|
10551
|
+
purpose: "Full generated plan for reasoning about design intent.",
|
|
10552
|
+
expectedContents: ["Canvas plan fields", "design vectors", "reference analysis when available"],
|
|
10553
|
+
howToUse: ["Use for agent reasoning and audit traceability", "compare with canvas-plan.request.json for runtime subset"],
|
|
10554
|
+
mustNot: ["Do not submit this file directly to Canvas when it contains non-request context"]
|
|
10555
|
+
},
|
|
10556
|
+
[INSPIREDESIGN_HANDOFF_FILES.implementationPlanMarkdown]: {
|
|
10557
|
+
purpose: "Human-readable engineering sequence for the first implementation pass.",
|
|
10558
|
+
expectedContents: ["build sequence", "component plan", "token strategy", "QA and risk checks"],
|
|
10559
|
+
howToUse: ["Convert sections into implementation tasks", "keep tests and browser validation aligned to the plan"],
|
|
10560
|
+
mustNot: ["Do not implement sections unsupported by brief or reference evidence"]
|
|
10561
|
+
},
|
|
10562
|
+
[INSPIREDESIGN_HANDOFF_FILES.implementationPlan]: {
|
|
10563
|
+
purpose: "Machine-readable implementation plan matching the Markdown plan.",
|
|
10564
|
+
expectedContents: ["architecture steps", "component inventory", "state and validation tasks"],
|
|
10565
|
+
howToUse: ["Use for structured task extraction", "keep it synchronized with implementation-plan.md"],
|
|
10566
|
+
mustNot: ["Do not treat it as a Canvas document patch payload"]
|
|
10567
|
+
},
|
|
10568
|
+
[INSPIREDESIGN_HANDOFF_FILES.evidence]: {
|
|
10569
|
+
purpose: "Evidence digest for brief, reference, capture, and design-vector provenance.",
|
|
10570
|
+
expectedContents: ["brief expansion", "reference outcomes", "capture attempts", "design vectors"],
|
|
10571
|
+
howToUse: ["Audit why choices were made", "prefer evidence over generic template defaults"],
|
|
10572
|
+
mustNot: ["Do not ignore failed or skipped capture statuses when judging confidence"]
|
|
10573
|
+
},
|
|
10574
|
+
[INSPIREDESIGN_HANDOFF_FILES.prototypeGuidance]: {
|
|
10575
|
+
purpose: "Optional first prototype guidance when the workflow requests prototype output.",
|
|
10576
|
+
expectedContents: ["prototype structure", "design-vector guidance", "browser proof checklist"],
|
|
10577
|
+
howToUse: ["Use only for the first prototype pass", "promote proven ideas back into contract-aligned work"],
|
|
10578
|
+
mustNot: ["Do not treat prototype guidance as final implementation authority"]
|
|
10579
|
+
}
|
|
10580
|
+
};
|
|
10581
|
+
var INSPIREDESIGN_CONTRACT_SECTION_GUIDE = {
|
|
10582
|
+
intent: {
|
|
10583
|
+
purpose: "Define why the design exists and what success means.",
|
|
10584
|
+
expectedContents: ["audience", "task", "success criteria", "trust posture"],
|
|
10585
|
+
howToUse: ["Validate the primary user job before styling", "reject sections that do not serve the task"],
|
|
10586
|
+
mustNot: ["Do not start visual polish before the audience and task are clear"]
|
|
10587
|
+
},
|
|
10588
|
+
generationPlan: {
|
|
10589
|
+
purpose: "Mutation-safe subset accepted by Canvas planning.",
|
|
10590
|
+
expectedContents: ["target outcome", "visual, layout, content, component, motion, responsive, accessibility posture"],
|
|
10591
|
+
howToUse: ["Submit only through canvas-plan.request.json", "repair generationPlanIssues before mutation"],
|
|
10592
|
+
mustNot: ["Do not add handoff-only guide fields to the Canvas generation plan"]
|
|
10593
|
+
},
|
|
10594
|
+
designLanguage: {
|
|
10595
|
+
purpose: "Name the coherent visual direction and token ownership.",
|
|
10596
|
+
expectedContents: ["direction", "style axes", "semantic token source", "approved libraries"],
|
|
10597
|
+
howToUse: ["Keep one design language per task", "align repeated components to semantic tokens"],
|
|
10598
|
+
mustNot: ["Do not mix unrelated visual families inside one surface"]
|
|
10599
|
+
},
|
|
10600
|
+
contentModel: {
|
|
10601
|
+
purpose: "Define real content, message hierarchy, and UI states.",
|
|
10602
|
+
expectedContents: ["primary message", "supporting messages", "states", "loading, empty, and error behavior"],
|
|
10603
|
+
howToUse: ["Use real content first", "plan non-happy-path states before polish"],
|
|
10604
|
+
mustNot: ["Do not ship placeholder copy as product content"]
|
|
10605
|
+
},
|
|
10606
|
+
layoutSystem: {
|
|
10607
|
+
purpose: "Describe page architecture and section rhythm.",
|
|
10608
|
+
expectedContents: ["grid", "containers", "spacing rhythm", "alignment rules"],
|
|
10609
|
+
howToUse: ["Use to place sections and scan units consistently", "verify desktop and mobile structure"],
|
|
10610
|
+
mustNot: ["Do not invent one-off layout rules for repeated sections"]
|
|
10611
|
+
},
|
|
10612
|
+
typographySystem: {
|
|
10613
|
+
purpose: "Define type families, scale, measure, and loading behavior.",
|
|
10614
|
+
expectedContents: ["families", "scale", "measure", "fallback policy", "loading strategy"],
|
|
10615
|
+
howToUse: ["Apply type hierarchy consistently", "avoid layout shift from font loading"],
|
|
10616
|
+
mustNot: ["Do not default to unapproved system stacks for a distinctive design"]
|
|
10617
|
+
},
|
|
10618
|
+
colorSystem: {
|
|
10619
|
+
purpose: "Define semantic color roles and theme behavior.",
|
|
10620
|
+
expectedContents: ["primary roles", "surface roles", "text roles", "state colors"],
|
|
10621
|
+
howToUse: ["Map repeated UI to semantic tokens", "validate contrast in every required theme"],
|
|
10622
|
+
mustNot: ["Do not scatter raw color values across leaf components"]
|
|
10623
|
+
},
|
|
10624
|
+
surfaceSystem: {
|
|
10625
|
+
purpose: "Define material, depth, borders, and background behavior.",
|
|
10626
|
+
expectedContents: ["surface hierarchy", "border rules", "shadow rules", "material effects"],
|
|
10627
|
+
howToUse: ["Use depth only to clarify hierarchy", "align material effects with design vectors"],
|
|
10628
|
+
mustNot: ["Do not turn every content group into a card by default"]
|
|
10629
|
+
},
|
|
10630
|
+
iconSystem: {
|
|
10631
|
+
purpose: "Define icon usage and decorative asset boundaries.",
|
|
10632
|
+
expectedContents: ["icon family", "stroke policy", "labeling rules", "decorative rules"],
|
|
10633
|
+
howToUse: ["Use icons to clarify actions", "keep accessible names on icon-only controls"],
|
|
10634
|
+
mustNot: ["Do not rely on icons as the only explanation for critical actions"]
|
|
10635
|
+
},
|
|
10636
|
+
motionSystem: {
|
|
10637
|
+
purpose: "Define motion that supports comprehension.",
|
|
10638
|
+
expectedContents: ["timing", "interaction moments", "reduced-motion posture", "advanced motion advisory"],
|
|
10639
|
+
howToUse: ["Keep shader, WebGL, and Spline cues advisory", "provide reduced-motion replacements"],
|
|
10640
|
+
mustNot: ["Do not use motion cues to authorize new runtime libraries"]
|
|
10641
|
+
},
|
|
10642
|
+
responsiveSystem: {
|
|
10643
|
+
purpose: "Define authored behavior across desktop, tablet, and mobile.",
|
|
10644
|
+
expectedContents: ["breakpoints", "adaptation rules", "touch policy", "overflow policy"],
|
|
10645
|
+
howToUse: ["Validate the primary action at every viewport", "collapse structure before copy becomes cramped"],
|
|
10646
|
+
mustNot: ["Do not assume desktop layouts naturally scale down"]
|
|
10647
|
+
},
|
|
10648
|
+
accessibilityPolicy: {
|
|
10649
|
+
purpose: "Set accessibility requirements before implementation.",
|
|
10650
|
+
expectedContents: ["WCAG target", "keyboard requirements", "focus policy", "semantic requirements"],
|
|
10651
|
+
howToUse: ["Block release on contrast or keyboard regressions", "validate focus on every interactive state"],
|
|
10652
|
+
mustNot: ["Do not defer accessibility until after visual implementation"]
|
|
10653
|
+
},
|
|
10654
|
+
libraryPolicy: {
|
|
10655
|
+
purpose: "Declare approved implementation libraries and runtime boundaries.",
|
|
10656
|
+
expectedContents: ["components", "icons", "styling", "motion", "threeD"],
|
|
10657
|
+
howToUse: ["Use as the dependency authorization boundary", "keep motion and threeD empty unless separately approved"],
|
|
10658
|
+
mustNot: ["Do not infer WebGL, shader, Spline, or 3D runtime support from advisory motion"]
|
|
10659
|
+
},
|
|
10660
|
+
runtimeBudgets: {
|
|
10661
|
+
purpose: "Set practical limits for sections, actions, interaction latency, and preview cost.",
|
|
10662
|
+
expectedContents: ["section budgets", "action budgets", "latency budgets", "preview notes"],
|
|
10663
|
+
howToUse: ["Use as a constraint during implementation", "validate slow or animation-heavy surfaces against it"],
|
|
10664
|
+
mustNot: ["Do not add decorative weight that violates the budget"]
|
|
10665
|
+
},
|
|
10666
|
+
navigationModel: {
|
|
10667
|
+
purpose: "Implementation-only context for route, tab, overlay, and deep-link ownership.",
|
|
10668
|
+
expectedContents: ["route owner", "deep-link policy", "invalid route fallback", "overlay entry points"],
|
|
10669
|
+
howToUse: ["Use from design-agent-handoff.json when wiring implementation state"],
|
|
10670
|
+
mustNot: ["Do not patch this omitted block into Canvas governance"]
|
|
10671
|
+
},
|
|
10672
|
+
asyncModel: {
|
|
10673
|
+
purpose: "Implementation-only context for loading, restart, cancellation, and URL-owned query state.",
|
|
10674
|
+
expectedContents: ["owner", "load trigger", "restart triggers", "cancellation policy"],
|
|
10675
|
+
howToUse: ["Use when wiring fetch/search state and stale-request handling"],
|
|
10676
|
+
mustNot: ["Do not let components invent independent async ownership"]
|
|
10677
|
+
},
|
|
10678
|
+
performanceModel: {
|
|
10679
|
+
purpose: "Implementation-only context for render hotspots and measurement posture.",
|
|
10680
|
+
expectedContents: ["render hotspots", "stable identity policy", "list strategy", "measurement plan"],
|
|
10681
|
+
howToUse: ["Use before building scan-heavy or motion-heavy surfaces"],
|
|
10682
|
+
mustNot: ["Do not ship heavy interaction surfaces without measurement evidence"]
|
|
10683
|
+
}
|
|
10684
|
+
};
|
|
10162
10685
|
var buildInspiredesignFollowthroughSummary = () => `Read ${INSPIREDESIGN_HANDOFF_FILES.advancedBrief} first, then continue in OpenDevBrowser Canvas with ${INSPIREDESIGN_HANDOFF_FILES.canvasPlanRequest} and ${INSPIREDESIGN_HANDOFF_FILES.designAgentHandoff}, load ${INSPIREDESIGN_HANDOFF_RECOMMENDED_SKILLS[0]} plus ${INSPIREDESIGN_HANDOFF_RECOMMENDED_SKILLS[1]} before implementation, and note that any supplied reference URL already uses captureMode=deep.`;
|
|
10163
10686
|
var buildInspiredesignNextStep = () => `Read ${INSPIREDESIGN_HANDOFF_FILES.advancedBrief} first. ${INSPIREDESIGN_HANDOFF_GUIDANCE.prepareCanvasPlanRequest} Then run ${INSPIREDESIGN_HANDOFF_COMMANDS.continueInCanvas}, confirm planStatus=accepted, then patch only the governance blocks listed in ${INSPIREDESIGN_HANDOFF_FILES.designAgentHandoff}.`;
|
|
10164
10687
|
|
|
@@ -10169,11 +10692,14 @@ var inspiredesign_advanced_brief_v1_default = {
|
|
|
10169
10692
|
commonRules: [
|
|
10170
10693
|
"Preserve only the product, brand, audience, platform, and tone cues that are explicitly present in the source brief.",
|
|
10171
10694
|
"Treat missing details as open constraints instead of inventing brand facts or user needs.",
|
|
10172
|
-
"Use inspiration references to extract transferable design logic rather than copying a single layout, visual treatment, or narrative beat literally."
|
|
10695
|
+
"Use inspiration references to extract transferable design logic rather than copying a single layout, visual treatment, or narrative beat literally.",
|
|
10696
|
+
"Treat shader, WebGL, Spline-style, and 3D motion ideas as advisory design cues only, not as runtime support or dependency approval.",
|
|
10697
|
+
"Carry accepted advanced motion cues in designVectors and motionSystem as intent, and keep libraryPolicy authorization separate."
|
|
10173
10698
|
],
|
|
10174
10699
|
outputRequirements: [
|
|
10175
10700
|
"Return a reusable design contract that can drive design.md, implementation-plan artifacts, and a Canvas-ready prototype path.",
|
|
10176
|
-
"Keep the direction premium, specific, and implementable instead of generic or template-driven."
|
|
10701
|
+
"Keep the direction premium, specific, and implementable instead of generic or template-driven.",
|
|
10702
|
+
"Keep libraryPolicy.motion and libraryPolicy.threeD empty in generated samples unless a separate runtime change explicitly approves those libraries."
|
|
10177
10703
|
],
|
|
10178
10704
|
formats: [
|
|
10179
10705
|
{
|
|
@@ -11765,6 +12291,13 @@ var expandInspiredesignBrief = (brief, preferredFormatId) => {
|
|
|
11765
12291
|
var SIGNAL_LIMIT = 5;
|
|
11766
12292
|
var SIGNAL_CLIP = 180;
|
|
11767
12293
|
var PATTERN_LIMIT = 6;
|
|
12294
|
+
var ADVANCED_MOTION_FIELDS = [
|
|
12295
|
+
"Advisory shader-style gradients: specify effect type, uniforms, static fallback, and reduced-motion replacement as design language only.",
|
|
12296
|
+
"Advisory WebGL-style depth cues: describe layered depth, camera-like parallax, and spatial hierarchy without requiring WebGL runtime.",
|
|
12297
|
+
"Advisory Spline-style staging: describe object-like hero composition, scene count, camera posture, depth model, asset source, and spatial sequencing as implementation guidance only.",
|
|
12298
|
+
"Advanced motion performance policy: define frame budget, lazy loading, offscreen pause behavior, and vestibular risk before implementation.",
|
|
12299
|
+
"Runtime boundary: implement with approved CSS and Canvas-safe primitives unless explicit source-owned runtime support is added later."
|
|
12300
|
+
];
|
|
11768
12301
|
var trimText = (value) => value.trim().replace(/\s+/g, " ");
|
|
11769
12302
|
var clipText = (value, maxLength) => {
|
|
11770
12303
|
if (value.length <= maxLength) return value;
|
|
@@ -12125,6 +12658,7 @@ var buildInspiredesignDesignVectors = (format, board) => {
|
|
|
12125
12658
|
interactionDensity: buildInteractionDensity(format, board),
|
|
12126
12659
|
interactionMoments: buildInteractionMoments(format, board),
|
|
12127
12660
|
materialEffects: buildMaterialEffects(board),
|
|
12661
|
+
advancedMotionAdvisory: [...ADVANCED_MOTION_FIELDS],
|
|
12128
12662
|
referenceInfluence: influence,
|
|
12129
12663
|
patternsToBorrow: board.references.flatMap((entry) => entry.patternsToBorrow).slice(0, 8),
|
|
12130
12664
|
patternsToReject: board.references.flatMap((entry) => entry.patternsToReject).slice(0, 8),
|
|
@@ -12512,7 +13046,8 @@ var renderReferenceFirstAdvancedBrief = (briefExpansion, board, vectors, referen
|
|
|
12512
13046
|
`motionPosture: ${vectors.motionPosture.join(" ")}`,
|
|
12513
13047
|
`sectionArchitecture: ${vectors.sectionArchitecture.join(" ")}`,
|
|
12514
13048
|
`interactionMoments: ${vectors.interactionMoments.join(" ")}`,
|
|
12515
|
-
`materialEffects: ${vectors.materialEffects.join(" ")}
|
|
13049
|
+
`materialEffects: ${vectors.materialEffects.join(" ")}`,
|
|
13050
|
+
`advancedMotionAdvisory: ${vectors.advancedMotionAdvisory.join(" ")}`
|
|
12516
13051
|
]),
|
|
12517
13052
|
"",
|
|
12518
13053
|
"Fixed format guardrails:",
|
|
@@ -12598,7 +13133,8 @@ var summarizeDesignVectors = (designVectors) => [
|
|
|
12598
13133
|
`sections: ${designVectors.sectionArchitecture.join(" ")}`,
|
|
12599
13134
|
`motion: ${designVectors.motionPosture.slice(0, 1).join(" ")}`,
|
|
12600
13135
|
`interactions: ${designVectors.interactionMoments.slice(0, 1).join(" ")}`,
|
|
12601
|
-
`materials: ${designVectors.materialEffects.slice(0, 1).join(" ")}
|
|
13136
|
+
`materials: ${designVectors.materialEffects.slice(0, 1).join(" ")}`,
|
|
13137
|
+
`advancedMotion: ${designVectors.advancedMotionAdvisory.slice(0, 1).join(" ")}`
|
|
12602
13138
|
].join(" ");
|
|
12603
13139
|
var isReferenceFirstPublicLanding = (designVectors) => {
|
|
12604
13140
|
return designVectors.sourcePriority === "reference-evidence-first" && designVectors.surfaceIntent.toLowerCase().includes("public landing page");
|
|
@@ -12620,20 +13156,244 @@ var buildEvidenceDerivedFormat = (format, designVectors) => {
|
|
|
12620
13156
|
}
|
|
12621
13157
|
};
|
|
12622
13158
|
};
|
|
12623
|
-
var
|
|
13159
|
+
var TARGET_KIND_ORDER = ["page", "component", "asset"];
|
|
13160
|
+
var TARGET_CONFIDENCE = {
|
|
13161
|
+
defaultPage: 0.55,
|
|
13162
|
+
pageIntentStep: 0.05,
|
|
13163
|
+
nonPageBase: 0.55,
|
|
13164
|
+
intentStep: 0.08,
|
|
13165
|
+
supportingStep: 0.05,
|
|
13166
|
+
maxPage: 0.7,
|
|
13167
|
+
maxNonPage: 0.95
|
|
13168
|
+
};
|
|
13169
|
+
var TARGET_SIGNAL_PROFILES = {
|
|
13170
|
+
page: {
|
|
13171
|
+
intent: ["page", "landing page", "website", "homepage", "dashboard", "workspace", "screen", "flow", "surface", "microsite"],
|
|
13172
|
+
supporting: ["section", "sections", "navigation", "footer", "hero section", "conversion flow"],
|
|
13173
|
+
incidental: ["card", "cards", "button", "buttons", "image", "images", "media", "hero", "cta", "background"]
|
|
13174
|
+
},
|
|
13175
|
+
component: {
|
|
13176
|
+
intent: ["component", "component family", "reusable component", "component prototype", "hero component", "card component", "storybook"],
|
|
13177
|
+
supporting: ["prop", "props", "slot", "slots", "variant", "variants", "state matrix", "hover", "focus", "disabled", "loading", "error", "fixture", "fixtures", "arg", "args"],
|
|
13178
|
+
incidental: ["card", "cards", "button", "buttons", "form", "modal", "drawer", "navbar", "hero", "input", "tabs", "cta"]
|
|
13179
|
+
},
|
|
13180
|
+
asset: {
|
|
13181
|
+
intent: ["asset", "asset pack", "visual asset", "icon pack", "logo pack", "illustration set", "artwork set"],
|
|
13182
|
+
supporting: ["responsive variant", "responsive variants", "responsive artwork", "provenance", "usage rules", "alt text", "replacement rules", "tokenized usage", "source asset", "source assets"],
|
|
13183
|
+
incidental: ["icon", "icons", "illustration", "illustrations", "logo", "logos", "media", "image", "images", "background", "texture", "sprite", "artwork"]
|
|
13184
|
+
}
|
|
13185
|
+
};
|
|
13186
|
+
var buildTargetCorpus = (brief, references, synthesis) => [
|
|
12624
13187
|
brief,
|
|
12625
|
-
|
|
12626
|
-
|
|
12627
|
-
|
|
12628
|
-
|
|
12629
|
-
|
|
12630
|
-
const
|
|
12631
|
-
|
|
12632
|
-
|
|
12633
|
-
|
|
12634
|
-
|
|
12635
|
-
|
|
12636
|
-
|
|
13188
|
+
synthesis.lines.join(" "),
|
|
13189
|
+
...references.filter(hasInspiredesignUsableReferenceEvidence).flatMap((reference) => getInspiredesignReferenceSignals(reference))
|
|
13190
|
+
].join(" ").toLowerCase();
|
|
13191
|
+
var escapeRegex = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
13192
|
+
var matchesTargetSignal = (corpus, signal) => {
|
|
13193
|
+
const pattern = escapeRegex(signal.toLowerCase()).replace(/\s+/g, "\\s+");
|
|
13194
|
+
return new RegExp(`(^|[^a-z0-9])${pattern}([^a-z0-9]|$)`).test(corpus);
|
|
13195
|
+
};
|
|
13196
|
+
var findTargetSignalIndex = (corpus, signal) => {
|
|
13197
|
+
const pattern = escapeRegex(signal.toLowerCase()).replace(/\s+/g, "\\s+");
|
|
13198
|
+
return new RegExp(`(^|[^a-z0-9])${pattern}([^a-z0-9]|$)`).exec(corpus)?.index ?? null;
|
|
13199
|
+
};
|
|
13200
|
+
var findFirstBriefTargetKind = (brief) => {
|
|
13201
|
+
const corpus = brief.toLowerCase();
|
|
13202
|
+
const hits = TARGET_KIND_ORDER.flatMap((kind) => TARGET_SIGNAL_PROFILES[kind].intent.map((signal) => findTargetSignalIndex(corpus, signal)).filter((index) => index !== null).map((index) => ({ kind, index })));
|
|
13203
|
+
return hits.sort((left, right) => left.index - right.index)[0]?.kind ?? null;
|
|
13204
|
+
};
|
|
13205
|
+
var collectTargetSignals = (corpus) => {
|
|
13206
|
+
const collect = (kind) => {
|
|
13207
|
+
const profile = TARGET_SIGNAL_PROFILES[kind];
|
|
13208
|
+
return {
|
|
13209
|
+
intent: profile.intent.filter((signal) => matchesTargetSignal(corpus, signal)),
|
|
13210
|
+
supporting: profile.supporting.filter((signal) => matchesTargetSignal(corpus, signal)),
|
|
13211
|
+
incidental: profile.incidental.filter((signal) => matchesTargetSignal(corpus, signal))
|
|
13212
|
+
};
|
|
13213
|
+
};
|
|
13214
|
+
return {
|
|
13215
|
+
page: collect("page"),
|
|
13216
|
+
component: collect("component"),
|
|
13217
|
+
asset: collect("asset")
|
|
13218
|
+
};
|
|
13219
|
+
};
|
|
13220
|
+
var clampTargetConfidence = (value, max) => Math.min(max, Number(value.toFixed(2)));
|
|
13221
|
+
var buildPageConfidence = (signals) => {
|
|
13222
|
+
return clampTargetConfidence(
|
|
13223
|
+
TARGET_CONFIDENCE.defaultPage + signals.intent.length * TARGET_CONFIDENCE.pageIntentStep,
|
|
13224
|
+
TARGET_CONFIDENCE.maxPage
|
|
13225
|
+
);
|
|
13226
|
+
};
|
|
13227
|
+
var buildTargetEligibility = (kind, briefSignals, supportSignals) => {
|
|
13228
|
+
const eligible = briefSignals.intent.length > 0 && supportSignals.supporting.length > 0;
|
|
13229
|
+
const confidence = eligible ? clampTargetConfidence(
|
|
13230
|
+
TARGET_CONFIDENCE.nonPageBase + briefSignals.intent.length * TARGET_CONFIDENCE.intentStep + supportSignals.supporting.length * TARGET_CONFIDENCE.supportingStep,
|
|
13231
|
+
TARGET_CONFIDENCE.maxNonPage
|
|
13232
|
+
) : 0;
|
|
13233
|
+
return {
|
|
13234
|
+
kind,
|
|
13235
|
+
eligible,
|
|
13236
|
+
confidence,
|
|
13237
|
+
triggeringSignals: [
|
|
13238
|
+
...briefSignals.intent.map((signal) => `${kind} intent: ${signal}`),
|
|
13239
|
+
...supportSignals.supporting.map((signal) => `${kind} support: ${signal}`)
|
|
13240
|
+
]
|
|
13241
|
+
};
|
|
13242
|
+
};
|
|
13243
|
+
var choosePrimaryTargetKind = (pageConfidence, pageSignals, firstBriefTargetKind, component, asset) => {
|
|
13244
|
+
const eligibleTargets = [component, asset].filter((target) => target.eligible);
|
|
13245
|
+
if (eligibleTargets.length === 0) return { primaryKind: "page", reason: "no_non_page_gate" };
|
|
13246
|
+
if (firstBriefTargetKind === "page" && pageSignals.intent.length > 0) {
|
|
13247
|
+
return { primaryKind: "page", reason: "page_first_brief_target" };
|
|
13248
|
+
}
|
|
13249
|
+
const [first, second] = eligibleTargets.sort((left, right) => right.confidence - left.confidence);
|
|
13250
|
+
if (!first || first.confidence <= pageConfidence) {
|
|
13251
|
+
return { primaryKind: "page", reason: "non_page_did_not_beat_page" };
|
|
13252
|
+
}
|
|
13253
|
+
if (second && first.confidence === second.confidence && pageSignals.intent.length > 0) {
|
|
13254
|
+
return { primaryKind: "page", reason: "page_tie_break" };
|
|
13255
|
+
}
|
|
13256
|
+
return { primaryKind: first.kind, reason: "non_page_selected" };
|
|
13257
|
+
};
|
|
13258
|
+
var chooseTargetKinds = (primaryKind, component, asset) => {
|
|
13259
|
+
if (primaryKind === "page") return ["page"];
|
|
13260
|
+
const eligible = new Set([component, asset].filter((target) => target.eligible).map((target) => target.kind));
|
|
13261
|
+
const secondaryKinds = TARGET_KIND_ORDER.filter((kind) => kind !== primaryKind && eligible.has(kind));
|
|
13262
|
+
return [primaryKind, ...secondaryKinds];
|
|
13263
|
+
};
|
|
13264
|
+
var buildTriggeringSignals = (decision, signals, component, asset) => {
|
|
13265
|
+
const pageSignals = signals.page.intent.map((signal) => `page intent: ${signal}`);
|
|
13266
|
+
const eligibleTargets = [component, asset].filter((target) => target.eligible);
|
|
13267
|
+
const targetIntents = eligibleTargets.flatMap((target) => target.triggeringSignals.filter((signal) => signal.includes(" intent: ")));
|
|
13268
|
+
const targetSupport = eligibleTargets.flatMap((target) => target.triggeringSignals.filter((signal) => signal.includes(" support: ")));
|
|
13269
|
+
const defaultSignal = decision.primaryKind === "page" ? [buildPageDecisionSignal(decision.reason)] : [];
|
|
13270
|
+
return [...pageSignals, ...targetIntents, ...targetSupport, ...defaultSignal].slice(0, 12);
|
|
13271
|
+
};
|
|
13272
|
+
var buildPageDecisionSignal = (reason) => {
|
|
13273
|
+
if (reason === "no_non_page_gate") return "page default: non-page targets did not clear brief intent plus support gates";
|
|
13274
|
+
if (reason === "non_page_did_not_beat_page") return "page default: non-page targets did not beat page confidence";
|
|
13275
|
+
if (reason === "page_first_brief_target") return "page default: page was the first explicit target in the brief";
|
|
13276
|
+
if (reason === "page_tie_break") return "page default: page intent won a tied non-page confidence score";
|
|
13277
|
+
return "page default: page selected";
|
|
13278
|
+
};
|
|
13279
|
+
var getTargetConfidence = (primaryKind, pageConfidence, component, asset) => {
|
|
13280
|
+
if (primaryKind === "component") return component.confidence;
|
|
13281
|
+
if (primaryKind === "asset") return asset.confidence;
|
|
13282
|
+
return pageConfidence;
|
|
13283
|
+
};
|
|
13284
|
+
var buildTargetEvidenceBuckets = (primaryKind, format, designVectors) => ({
|
|
13285
|
+
anatomy: [`Map ${primaryKind} anatomy before styling: root, content hierarchy, interaction zones, and supporting regions.`],
|
|
13286
|
+
propsSlots: [`Define props/slots from ${format.componentGrammar}; separate data props, content slots, and visual variant controls.`],
|
|
13287
|
+
stateMatrix: ["Cover default, hover, focus, active, disabled, loading, empty, error, success, and selected where relevant."],
|
|
13288
|
+
tokens: [`Resolve typography, color, spacing, radius, shadow, motion, and z-index through semantic tokens for ${format.paletteIntent}.`],
|
|
13289
|
+
assets: [`Inventory source assets, derived assets, usage rights, responsive variants, and replacement notes for ${primaryKind} prototypes.`],
|
|
13290
|
+
accessibility: ["Validate keyboard order, visible focus, accessible names, ARIA pattern fit, contrast, and WCAG 2.2 states."],
|
|
13291
|
+
motion: [`Use ${format.motionGrammar}; include reduced-motion alternatives for ${designVectors.motionPosture.join(" ") || "all transitions"}.`],
|
|
13292
|
+
previewFixtures: [`Build isolated preview fixtures for ${primaryKind} default, responsive, reduced-motion, and failure states.`]
|
|
13293
|
+
});
|
|
13294
|
+
var buildComponentTargetAnalysis = (briefHash, format) => ({
|
|
13295
|
+
canvasType: "CanvasComponentInventoryItem",
|
|
13296
|
+
inventoryItems: [{
|
|
13297
|
+
id: `component_${briefHash}`,
|
|
13298
|
+
name: `${format.label} Component`,
|
|
13299
|
+
componentName: `${format.route.profile.replace(/-/g, "")}PrototypeComponent`,
|
|
13300
|
+
description: `Reusable component prototype derived from ${format.componentGrammar}.`,
|
|
13301
|
+
sourceFamily: "framework_component",
|
|
13302
|
+
origin: "code_sync",
|
|
13303
|
+
variants: [{
|
|
13304
|
+
id: "default",
|
|
13305
|
+
name: "Default",
|
|
13306
|
+
selector: { interaction: "default" },
|
|
13307
|
+
description: "Default preview fixture.",
|
|
13308
|
+
metadata: {}
|
|
13309
|
+
}],
|
|
13310
|
+
props: [
|
|
13311
|
+
{ name: "variant", type: "string", required: false, description: "Visual variant key.", metadata: {} },
|
|
13312
|
+
{ name: "state", type: "string", required: false, description: "Interaction state fixture.", metadata: {} }
|
|
13313
|
+
],
|
|
13314
|
+
slots: [
|
|
13315
|
+
{ name: "media", description: "Optional visual or icon slot.", allowedKinds: ["asset", "image", "icon"], metadata: {} },
|
|
13316
|
+
{ name: "content", description: "Primary text or rich content slot.", allowedKinds: ["text", "rich-text"], metadata: {} }
|
|
13317
|
+
],
|
|
13318
|
+
events: [{ name: "onPrimaryAction", description: "Primary interaction callback.", payloadShape: {}, metadata: {} }],
|
|
13319
|
+
content: { acceptsText: true, acceptsRichText: true, slotNames: ["media", "content"], metadata: {} },
|
|
13320
|
+
metadata: { targetKind: "component" }
|
|
13321
|
+
}],
|
|
13322
|
+
prototypeGuidance: [
|
|
13323
|
+
"Component prototype target: document anatomy, props/slots, variant rules, and interaction state fixtures before page composition.",
|
|
13324
|
+
"Use Storybook-style args and interaction checks when converting this guidance into executable component previews."
|
|
13325
|
+
]
|
|
13326
|
+
});
|
|
13327
|
+
var buildAssetTargetAnalysis = (briefHash) => ({
|
|
13328
|
+
canvasType: "CanvasAsset",
|
|
13329
|
+
assets: [{
|
|
13330
|
+
id: `asset_${briefHash}`,
|
|
13331
|
+
sourceType: "page-derived",
|
|
13332
|
+
kind: "visual-asset",
|
|
13333
|
+
url: null,
|
|
13334
|
+
status: "needs-production-source",
|
|
13335
|
+
provenanceNotes: ["Derived from brief/reference evidence; recreate rather than copy proprietary source assets."],
|
|
13336
|
+
usageNotes: ["Define responsive variants, token usage, alt text, and replacement rules before implementation."],
|
|
13337
|
+
metadata: { targetKind: "asset" }
|
|
13338
|
+
}],
|
|
13339
|
+
prototypeGuidance: [
|
|
13340
|
+
"Asset prototype target: catalog provenance, variants, token usage, responsive behavior, and replacement rules.",
|
|
13341
|
+
"Pair each visual asset with preview fixtures for default, high contrast, and reduced-motion contexts when relevant."
|
|
13342
|
+
]
|
|
13343
|
+
});
|
|
13344
|
+
var buildPageTargetAnalysis = (format, designVectors) => ({
|
|
13345
|
+
canvasType: "CanvasPage",
|
|
13346
|
+
assemblyFocus: [
|
|
13347
|
+
format.layoutArchetype,
|
|
13348
|
+
...designVectors.sectionArchitecture
|
|
13349
|
+
],
|
|
13350
|
+
implementationNotes: [
|
|
13351
|
+
"Page prototype target: validate section order, navigation model, CTA visibility, responsive collapse, and reduced-motion behavior.",
|
|
13352
|
+
"Use component primitives before page-specific wrappers."
|
|
13353
|
+
]
|
|
13354
|
+
});
|
|
13355
|
+
var buildTargetAnalysis = (brief, format, references, synthesis, designVectors) => {
|
|
13356
|
+
const briefSignals = collectTargetSignals(brief.toLowerCase());
|
|
13357
|
+
const supportSignals = collectTargetSignals(buildTargetCorpus(brief, references, synthesis));
|
|
13358
|
+
const pageConfidence = buildPageConfidence(briefSignals.page);
|
|
13359
|
+
const component = buildTargetEligibility("component", briefSignals.component, supportSignals.component);
|
|
13360
|
+
const asset = buildTargetEligibility("asset", briefSignals.asset, supportSignals.asset);
|
|
13361
|
+
const decision = choosePrimaryTargetKind(
|
|
13362
|
+
pageConfidence,
|
|
13363
|
+
briefSignals.page,
|
|
13364
|
+
findFirstBriefTargetKind(brief),
|
|
13365
|
+
component,
|
|
13366
|
+
asset
|
|
13367
|
+
);
|
|
13368
|
+
const primaryKind = decision.primaryKind;
|
|
13369
|
+
const kinds = chooseTargetKinds(primaryKind, component, asset);
|
|
13370
|
+
const briefHash = referenceFingerprint(brief);
|
|
13371
|
+
return {
|
|
13372
|
+
primaryKind,
|
|
13373
|
+
kinds,
|
|
13374
|
+
confidence: getTargetConfidence(primaryKind, pageConfidence, component, asset),
|
|
13375
|
+
triggeringSignals: buildTriggeringSignals(decision, briefSignals, component, asset),
|
|
13376
|
+
evidenceBuckets: buildTargetEvidenceBuckets(primaryKind, format, designVectors),
|
|
13377
|
+
...kinds.includes("page") ? { page: buildPageTargetAnalysis(format, designVectors) } : {},
|
|
13378
|
+
...kinds.includes("component") ? { component: buildComponentTargetAnalysis(briefHash, format) } : {},
|
|
13379
|
+
...kinds.includes("asset") ? { asset: buildAssetTargetAnalysis(briefHash) } : {}
|
|
13380
|
+
};
|
|
13381
|
+
};
|
|
13382
|
+
var buildGenerationPlan = ({
|
|
13383
|
+
brief,
|
|
13384
|
+
format,
|
|
13385
|
+
synthesis,
|
|
13386
|
+
referencePatternBoard,
|
|
13387
|
+
designVectors,
|
|
13388
|
+
targetAnalysis
|
|
13389
|
+
}) => {
|
|
13390
|
+
const plan = cloneTemplate(BASE_GENERATION_PLAN);
|
|
13391
|
+
const profile = format.route.profile;
|
|
13392
|
+
const vectorSummary = summarizeDesignVectors(designVectors);
|
|
13393
|
+
plan.targetOutcome.summary = clipText2(
|
|
13394
|
+
`${summarizeBrief(brief)} Reference cues: ${synthesis.summary} ${vectorSummary}`,
|
|
13395
|
+
GENERATION_PLAN_REFERENCE_CLIP_LENGTH
|
|
13396
|
+
);
|
|
12637
13397
|
plan.visualDirection.profile = profile;
|
|
12638
13398
|
plan.visualDirection.themeStrategy = format.route.themeStrategy;
|
|
12639
13399
|
plan.layoutStrategy.approach = format.route.layoutApproach;
|
|
@@ -12652,6 +13412,7 @@ var buildGenerationPlan = ({
|
|
|
12652
13412
|
...plan,
|
|
12653
13413
|
referencePatternBoard,
|
|
12654
13414
|
designVectors,
|
|
13415
|
+
targetAnalysis,
|
|
12655
13416
|
interactionMoments: [...designVectors.interactionMoments],
|
|
12656
13417
|
materialEffects: [...designVectors.materialEffects]
|
|
12657
13418
|
};
|
|
@@ -12770,6 +13531,8 @@ var buildMotionSystemBlock = (format, designVectors) => {
|
|
|
12770
13531
|
posture: [...designVectors.motionPosture],
|
|
12771
13532
|
interactionMoments: [...designVectors.interactionMoments],
|
|
12772
13533
|
materialEffects: [...designVectors.materialEffects],
|
|
13534
|
+
advancedMotionAdvisory: [...designVectors.advancedMotionAdvisory],
|
|
13535
|
+
advancedMotionRuntimePolicy: "Advanced motion fields are advisory contract metadata only and do not authorize shader, WebGL, Spline, R3F, Pixi, Babylon, or GLSL runtime support.",
|
|
12773
13536
|
parallaxPolicy: "Use parallax only as a restrained hierarchy cue and remove transform-based depth for reduced-motion users.",
|
|
12774
13537
|
hoverPolicy: "Hover effects must clarify clickability without becoming the only visible affordance.",
|
|
12775
13538
|
cursorPolicy: "Cursor effects are allowed only on premium hero or CTA moments and must not interfere with reading or form controls.",
|
|
@@ -12803,7 +13566,7 @@ var buildLibraryPolicyBlock = () => ({
|
|
|
12803
13566
|
components: ["shadcn"],
|
|
12804
13567
|
icons: ["tabler"],
|
|
12805
13568
|
styling: ["tailwindcss"],
|
|
12806
|
-
motion: [
|
|
13569
|
+
motion: [],
|
|
12807
13570
|
threeD: []
|
|
12808
13571
|
});
|
|
12809
13572
|
var buildRuntimeBudgetsBlock = (plan) => ({
|
|
@@ -12893,10 +13656,13 @@ var buildFollowthrough = ({
|
|
|
12893
13656
|
synthesis,
|
|
12894
13657
|
includePrototypeGuidance,
|
|
12895
13658
|
referencePatternBoard,
|
|
12896
|
-
designVectors
|
|
13659
|
+
designVectors,
|
|
13660
|
+
targetAnalysis
|
|
12897
13661
|
}) => ({
|
|
12898
13662
|
summary: buildInspiredesignFollowthroughSummary(),
|
|
12899
13663
|
nextStep: buildInspiredesignNextStep(),
|
|
13664
|
+
artifactGuide: INSPIREDESIGN_ARTIFACT_GUIDE,
|
|
13665
|
+
contractSectionGuide: INSPIREDESIGN_CONTRACT_SECTION_GUIDE,
|
|
12900
13666
|
briefExpansion: buildBriefExpansionMetadata(briefExpansion),
|
|
12901
13667
|
recommendedSkills: [...INSPIREDESIGN_HANDOFF_RECOMMENDED_SKILLS],
|
|
12902
13668
|
commandExamples: { ...INSPIREDESIGN_HANDOFF_COMMANDS },
|
|
@@ -12911,7 +13677,8 @@ var buildFollowthrough = ({
|
|
|
12911
13677
|
cues: synthesis.lines
|
|
12912
13678
|
},
|
|
12913
13679
|
referencePatternBoard,
|
|
12914
|
-
designVectors
|
|
13680
|
+
designVectors,
|
|
13681
|
+
targetAnalysis
|
|
12915
13682
|
}
|
|
12916
13683
|
});
|
|
12917
13684
|
var buildDesignContract = ({
|
|
@@ -13015,6 +13782,7 @@ var buildImplementationPlan = ({
|
|
|
13015
13782
|
...designVectors.motionPosture,
|
|
13016
13783
|
...designVectors.interactionMoments,
|
|
13017
13784
|
...designVectors.materialEffects,
|
|
13785
|
+
...designVectors.advancedMotionAdvisory,
|
|
13018
13786
|
"Implement hero entrance reveal, section scroll reveal, and CTA/focus feedback as the minimum motion system for landing pages.",
|
|
13019
13787
|
"Use @media (prefers-reduced-motion: reduce) to preserve hierarchy without motion.",
|
|
13020
13788
|
"Preserve layout during loading and keep transient confirmations out of the main flow.",
|
|
@@ -13237,7 +14005,32 @@ var renderImplementationMarkdown = (implementationPlan) => {
|
|
|
13237
14005
|
implementationPlan.buildSequence.map((step, index) => `${index + 1}. ${step}`).join("\n")
|
|
13238
14006
|
].join("\n");
|
|
13239
14007
|
};
|
|
13240
|
-
var
|
|
14008
|
+
var renderTargetAnalysisGuidance = (targetAnalysis) => {
|
|
14009
|
+
const targetGuidance = [
|
|
14010
|
+
...targetAnalysis.page?.implementationNotes ?? [],
|
|
14011
|
+
...targetAnalysis.component?.prototypeGuidance ?? [],
|
|
14012
|
+
...targetAnalysis.asset?.prototypeGuidance ?? []
|
|
14013
|
+
];
|
|
14014
|
+
return [
|
|
14015
|
+
"## 6.3 Target Analysis",
|
|
14016
|
+
formatBulletList2([
|
|
14017
|
+
`primary target: ${targetAnalysis.primaryKind}`,
|
|
14018
|
+
`target kinds: ${targetAnalysis.kinds.join(", ")}`,
|
|
14019
|
+
`confidence: ${targetAnalysis.confidence.toFixed(2)}`,
|
|
14020
|
+
`triggering signals: ${targetAnalysis.triggeringSignals.join("; ")}`,
|
|
14021
|
+
...targetGuidance,
|
|
14022
|
+
`anatomy: ${targetAnalysis.evidenceBuckets.anatomy.join(" ")}`,
|
|
14023
|
+
`props/slots: ${targetAnalysis.evidenceBuckets.propsSlots.join(" ")}`,
|
|
14024
|
+
`state matrix: ${targetAnalysis.evidenceBuckets.stateMatrix.join(" ")}`,
|
|
14025
|
+
`tokens: ${targetAnalysis.evidenceBuckets.tokens.join(" ")}`,
|
|
14026
|
+
`assets: ${targetAnalysis.evidenceBuckets.assets.join(" ")}`,
|
|
14027
|
+
`accessibility: ${targetAnalysis.evidenceBuckets.accessibility.join(" ")}`,
|
|
14028
|
+
`motion: ${targetAnalysis.evidenceBuckets.motion.join(" ")}`,
|
|
14029
|
+
`preview fixtures: ${targetAnalysis.evidenceBuckets.previewFixtures.join(" ")}`
|
|
14030
|
+
])
|
|
14031
|
+
].join("\n");
|
|
14032
|
+
};
|
|
14033
|
+
var renderPrototypeGuidance = (profile, synthesis, designVectors, targetAnalysis) => {
|
|
13241
14034
|
return [
|
|
13242
14035
|
"# 6. Optional Prototype Plan",
|
|
13243
14036
|
"",
|
|
@@ -13252,6 +14045,10 @@ var renderPrototypeGuidance = (profile, synthesis, designVectors) => {
|
|
|
13252
14045
|
`- interaction expectations: ${designVectors.interactionMoments.join(" ")}`,
|
|
13253
14046
|
`- motion expectations: ${designVectors.motionPosture.join(" ")}`,
|
|
13254
14047
|
`- material and depth expectations: ${designVectors.materialEffects.join(" ")}`,
|
|
14048
|
+
`- advisory advanced motion: ${designVectors.advancedMotionAdvisory.join(" ")}`,
|
|
14049
|
+
"",
|
|
14050
|
+
renderTargetAnalysisGuidance(targetAnalysis),
|
|
14051
|
+
"",
|
|
13255
14052
|
"- browser proof: capture desktop and mobile browser screenshots, verify reduced-motion behavior, inspect focus states, and confirm the primary CTA remains visible without overlap.",
|
|
13256
14053
|
"- HTML skeleton guidance: start with one main landmark, one primary CTA group, and semantic sections that follow the design vector section architecture instead of fixed industry-specific defaults.",
|
|
13257
14054
|
"- styling approach: define CSS variables for timing, easing, elevation, translucency, backdrop blur, cursor effects, hover effects, and parallax distance before mapping components to semantic tokens.",
|
|
@@ -13280,7 +14077,8 @@ var buildEvidencePayload = ({
|
|
|
13280
14077
|
urls,
|
|
13281
14078
|
references,
|
|
13282
14079
|
referencePatternBoard,
|
|
13283
|
-
designVectors
|
|
14080
|
+
designVectors,
|
|
14081
|
+
targetAnalysis
|
|
13284
14082
|
}) => ({
|
|
13285
14083
|
brief,
|
|
13286
14084
|
briefHash: referenceFingerprint(brief),
|
|
@@ -13294,7 +14092,8 @@ var buildEvidencePayload = ({
|
|
|
13294
14092
|
referenceCount: references.length,
|
|
13295
14093
|
references: references.map((reference) => toReferenceEvidenceJson(reference)),
|
|
13296
14094
|
referencePatternBoard,
|
|
13297
|
-
designVectors
|
|
14095
|
+
designVectors,
|
|
14096
|
+
targetAnalysis
|
|
13298
14097
|
});
|
|
13299
14098
|
var toCaptureEvidenceJson = (reference) => {
|
|
13300
14099
|
const normalized = normalizeInspiredesignCaptureEvidence(reference.capture);
|
|
@@ -13336,6 +14135,13 @@ var buildInspiredesignPacket = (input) => {
|
|
|
13336
14135
|
);
|
|
13337
14136
|
const designVectors = buildInspiredesignDesignVectors(selectedFormat, referencePatternBoard);
|
|
13338
14137
|
const effectiveFormat = buildEvidenceDerivedFormat(selectedFormat, designVectors);
|
|
14138
|
+
const targetAnalysis = buildTargetAnalysis(
|
|
14139
|
+
brief,
|
|
14140
|
+
effectiveFormat,
|
|
14141
|
+
references,
|
|
14142
|
+
synthesis,
|
|
14143
|
+
designVectors
|
|
14144
|
+
);
|
|
13339
14145
|
const effectiveBriefExpansion = {
|
|
13340
14146
|
...input.briefExpansion,
|
|
13341
14147
|
advancedBrief: isReferenceFirstPublicLanding(designVectors) ? renderEvidenceDerivedAdvancedBrief(input.briefExpansion, effectiveFormat) : input.briefExpansion.advancedBrief,
|
|
@@ -13352,7 +14158,8 @@ var buildInspiredesignPacket = (input) => {
|
|
|
13352
14158
|
format: effectiveFormat,
|
|
13353
14159
|
synthesis,
|
|
13354
14160
|
referencePatternBoard,
|
|
13355
|
-
designVectors
|
|
14161
|
+
designVectors,
|
|
14162
|
+
targetAnalysis
|
|
13356
14163
|
});
|
|
13357
14164
|
const profile = generationPlan.visualDirection.profile;
|
|
13358
14165
|
const canvasPlanRequest = buildCanvasPlanRequest(brief, generationPlan);
|
|
@@ -13369,7 +14176,8 @@ var buildInspiredesignPacket = (input) => {
|
|
|
13369
14176
|
synthesis,
|
|
13370
14177
|
includePrototypeGuidance,
|
|
13371
14178
|
referencePatternBoard,
|
|
13372
|
-
designVectors
|
|
14179
|
+
designVectors,
|
|
14180
|
+
targetAnalysis
|
|
13373
14181
|
});
|
|
13374
14182
|
const implementationPlan = buildImplementationPlan({
|
|
13375
14183
|
profile,
|
|
@@ -13380,7 +14188,7 @@ var buildInspiredesignPacket = (input) => {
|
|
|
13380
14188
|
});
|
|
13381
14189
|
const governanceMarkdown = renderGovernanceMarkdown(designContract, implementationPlan, effectiveFormat);
|
|
13382
14190
|
const implementationPlanMarkdown = renderImplementationMarkdown(implementationPlan);
|
|
13383
|
-
const prototypeGuidanceMarkdown = includePrototypeGuidance ? renderPrototypeGuidance(profile, synthesis, designVectors) : null;
|
|
14191
|
+
const prototypeGuidanceMarkdown = includePrototypeGuidance ? renderPrototypeGuidance(profile, synthesis, designVectors, targetAnalysis) : null;
|
|
13384
14192
|
const designMarkdown = [
|
|
13385
14193
|
"# 1. Executive Summary",
|
|
13386
14194
|
"",
|
|
@@ -13416,7 +14224,8 @@ var buildInspiredesignPacket = (input) => {
|
|
|
13416
14224
|
`motion posture: ${designVectors.motionPosture.join(" ")}`,
|
|
13417
14225
|
`section architecture: ${designVectors.sectionArchitecture.join(" ")}`,
|
|
13418
14226
|
`interaction moments: ${designVectors.interactionMoments.join(" ")}`,
|
|
13419
|
-
`material effects: ${designVectors.materialEffects.join(" ")}
|
|
14227
|
+
`material effects: ${designVectors.materialEffects.join(" ")}`,
|
|
14228
|
+
`advanced motion advisory: ${designVectors.advancedMotionAdvisory.join(" ")}`
|
|
13420
14229
|
]),
|
|
13421
14230
|
"",
|
|
13422
14231
|
"## 3.4 System Direction",
|
|
@@ -13462,11 +14271,167 @@ var buildInspiredesignPacket = (input) => {
|
|
|
13462
14271
|
urls,
|
|
13463
14272
|
references,
|
|
13464
14273
|
referencePatternBoard,
|
|
13465
|
-
designVectors
|
|
14274
|
+
designVectors,
|
|
14275
|
+
targetAnalysis
|
|
13466
14276
|
})
|
|
13467
14277
|
};
|
|
13468
14278
|
};
|
|
13469
14279
|
|
|
14280
|
+
// src/providers/workflow-handoff.ts
|
|
14281
|
+
var PRODUCT_VIDEO_BRIEF_HELPER_PATH = "./skills/opendevbrowser-product-presentation-asset/scripts/render-video-brief.sh";
|
|
14282
|
+
var PRODUCT_VIDEO_BRIEF_HELPER_COMMAND = `${PRODUCT_VIDEO_BRIEF_HELPER_PATH} <pack>/manifest.json`;
|
|
14283
|
+
var createSuccessHandoff = (followthroughSummary, suggestedNextAction, suggestedSteps) => ({
|
|
14284
|
+
followthroughSummary,
|
|
14285
|
+
suggestedNextAction,
|
|
14286
|
+
suggestedSteps
|
|
14287
|
+
});
|
|
14288
|
+
var cliExample = (command, args = "") => `npx opendevbrowser ${command}${args ? ` ${args}` : ""}`;
|
|
14289
|
+
var quoteCliValue = (value) => JSON.stringify(value);
|
|
14290
|
+
var buildResearchRerunCommand = (input) => cliExample(
|
|
14291
|
+
"research run",
|
|
14292
|
+
`--topic ${quoteCliValue(input.topic)} --days 14 --source-selection auto --sources web,community --browser-mode ${input.browserMode ?? "managed"} --mode json --output-format json`
|
|
14293
|
+
);
|
|
14294
|
+
var buildShoppingRerunCommand = (input) => {
|
|
14295
|
+
const providers = input.providers?.length ? ` --providers ${input.providers.join(",")}` : " --providers shopping/bestbuy,shopping/ebay";
|
|
14296
|
+
const budget = typeof input.budget === "number" ? ` --budget ${input.budget}` : "";
|
|
14297
|
+
const region = input.region ? ` --region ${quoteCliValue(input.region)}` : "";
|
|
14298
|
+
const browserMode = ` --browser-mode ${input.browserMode ?? "managed"}`;
|
|
14299
|
+
const sort = input.sort ? ` --sort ${input.sort}` : "";
|
|
14300
|
+
return cliExample(
|
|
14301
|
+
"shopping run",
|
|
14302
|
+
`--query ${quoteCliValue(input.query)}${providers}${budget}${region}${browserMode}${sort} --use-cookies --challenge-automation-mode browser_with_helper --mode json --output-format json`
|
|
14303
|
+
);
|
|
14304
|
+
};
|
|
14305
|
+
var buildProductVideoRerunCommand = (input = {}) => {
|
|
14306
|
+
const target = input.productUrl ? `--product-url ${quoteCliValue(input.productUrl)}` : `--product-name ${quoteCliValue(input.productName ?? "<product-name>")}`;
|
|
14307
|
+
const providerHint = input.providerHint ? ` --provider-hint ${input.providerHint}` : "";
|
|
14308
|
+
const screenshots = input.includeScreenshots ? " --include-screenshots" : "";
|
|
14309
|
+
const allImages = input.includeAllImages ? " --include-all-images" : "";
|
|
14310
|
+
const includeCopy = input.includeCopy ? " --include-copy" : "";
|
|
14311
|
+
const browserMode = ` --browser-mode ${input.browserMode ?? "managed"}`;
|
|
14312
|
+
return cliExample(
|
|
14313
|
+
"product-video run",
|
|
14314
|
+
`${target}${providerHint}${screenshots}${allImages}${includeCopy}${browserMode} --use-cookies --challenge-automation-mode browser_with_helper --output-format json`
|
|
14315
|
+
);
|
|
14316
|
+
};
|
|
14317
|
+
var buildMacroResolveArgs = (input, options) => {
|
|
14318
|
+
const defaultProvider = input.defaultProvider ? ` --default-provider ${input.defaultProvider}` : "";
|
|
14319
|
+
const execute = options?.execute ? " --execute" : "";
|
|
14320
|
+
const browserMode = options?.browserMode ? ` --browser-mode ${options.browserMode}` : "";
|
|
14321
|
+
const challenge = options?.challengeAutomationMode ? ` --challenge-automation-mode ${options.challengeAutomationMode}` : "";
|
|
14322
|
+
const outputFormat = options?.includeOutputFormat === false ? "" : " --output-format json";
|
|
14323
|
+
return `--expression ${quoteCliValue(input.expression)}${defaultProvider}${execute}${browserMode}${challenge}${outputFormat}`;
|
|
14324
|
+
};
|
|
14325
|
+
var buildMacroPreviewCommand = (input) => cliExample("macro-resolve", buildMacroResolveArgs(input));
|
|
14326
|
+
var buildMacroExecuteCommand = (input, challengeAutomationMode, browserMode) => cliExample("macro-resolve", buildMacroResolveArgs(input, {
|
|
14327
|
+
execute: true,
|
|
14328
|
+
browserMode,
|
|
14329
|
+
challengeAutomationMode
|
|
14330
|
+
}));
|
|
14331
|
+
var buildResearchSuccessHandoff = (input) => {
|
|
14332
|
+
const rerunCommand = buildResearchRerunCommand(input);
|
|
14333
|
+
return createSuccessHandoff(
|
|
14334
|
+
"Review the ranked records and artifact bundle before turning the result into a publishable claim.",
|
|
14335
|
+
`Open the returned artifact path, inspect the supporting records, and rerun ${rerunCommand} if you need a tighter evidence set.`,
|
|
14336
|
+
[
|
|
14337
|
+
{ reason: "Check which records actually support the final claim." },
|
|
14338
|
+
{
|
|
14339
|
+
reason: "Rerun with explicit sources and a narrower timebox if the evidence set is still too broad.",
|
|
14340
|
+
command: rerunCommand
|
|
14341
|
+
}
|
|
14342
|
+
]
|
|
14343
|
+
);
|
|
14344
|
+
};
|
|
14345
|
+
var buildShoppingSuccessHandoff = (input) => {
|
|
14346
|
+
const rerunCommand = buildShoppingRerunCommand(input);
|
|
14347
|
+
return createSuccessHandoff(
|
|
14348
|
+
"Review the offer set and diagnostics before calling any result a strong deal.",
|
|
14349
|
+
`Inspect the offers and meta.offerFilterDiagnostics, then rerun ${rerunCommand} if you need a tighter comparison.`,
|
|
14350
|
+
[
|
|
14351
|
+
{ reason: "Check which offers survived the workflow filters and why." },
|
|
14352
|
+
{
|
|
14353
|
+
reason: "Rerun with explicit providers or updated budget and region inputs if the comparison is still noisy.",
|
|
14354
|
+
command: rerunCommand
|
|
14355
|
+
}
|
|
14356
|
+
]
|
|
14357
|
+
);
|
|
14358
|
+
};
|
|
14359
|
+
var buildProductVideoSuccessHandoff = (input = {}) => {
|
|
14360
|
+
const rerunCommand = buildProductVideoRerunCommand(input);
|
|
14361
|
+
return createSuccessHandoff(
|
|
14362
|
+
"Review the generated asset pack to confirm whether it is visual-ready or metadata-first before briefing production.",
|
|
14363
|
+
"Open the returned pack path, inspect manifest.json plus copy and features, then run the product-video brief helper with that manifest path to generate production briefs and sourcing notes.",
|
|
14364
|
+
[
|
|
14365
|
+
{ reason: "Confirm whether the pack already includes enough images or screenshots for production." },
|
|
14366
|
+
{
|
|
14367
|
+
reason: "Run the product-presentation-asset brief helper on manifest.json to generate the production brief files.",
|
|
14368
|
+
command: PRODUCT_VIDEO_BRIEF_HELPER_COMMAND
|
|
14369
|
+
},
|
|
14370
|
+
{
|
|
14371
|
+
reason: "Rerun the asset workflow with adjusted provider or media flags when the current pack is too thin.",
|
|
14372
|
+
command: rerunCommand
|
|
14373
|
+
},
|
|
14374
|
+
{ reason: "Source or capture visuals before final handoff if the pack is metadata-first." }
|
|
14375
|
+
]
|
|
14376
|
+
);
|
|
14377
|
+
};
|
|
14378
|
+
var buildMacroResolveSuccessHandoff = (input) => {
|
|
14379
|
+
const previewCommand = buildMacroPreviewCommand(input);
|
|
14380
|
+
const executeCommand = buildMacroExecuteCommand(input);
|
|
14381
|
+
const browserRetryCommand = buildMacroExecuteCommand(input, "browser_with_helper", "extension");
|
|
14382
|
+
if (!input.execute) {
|
|
14383
|
+
return createSuccessHandoff(
|
|
14384
|
+
"Review the resolved provider action and provenance before executing the macro.",
|
|
14385
|
+
`Run ${executeCommand} when the resolved action looks correct.`,
|
|
14386
|
+
[
|
|
14387
|
+
{ reason: "Inspect resolution.action and resolution.provenance to confirm provider and query shaping." },
|
|
14388
|
+
{ reason: "Execute the resolved macro once the plan looks correct.", command: executeCommand },
|
|
14389
|
+
{ reason: "Add --default-provider only when you need to force a different provider lane.", command: previewCommand }
|
|
14390
|
+
]
|
|
14391
|
+
);
|
|
14392
|
+
}
|
|
14393
|
+
if (input.blocked) {
|
|
14394
|
+
return createSuccessHandoff(
|
|
14395
|
+
"Review execution.meta.blocker and failures before retrying the macro.",
|
|
14396
|
+
`Run ${browserRetryCommand} after checking execution.meta.blocker and the current recovery path.`,
|
|
14397
|
+
[
|
|
14398
|
+
{ reason: "Inspect execution.meta.blocker and execution.failures before retrying." },
|
|
14399
|
+
{ reason: "Retry with browser-scoped challenge automation when the blocker requires live follow-up.", command: browserRetryCommand },
|
|
14400
|
+
{ reason: "Preview the resolved action again if you need to switch providers before another execute attempt.", command: previewCommand }
|
|
14401
|
+
]
|
|
14402
|
+
);
|
|
14403
|
+
}
|
|
14404
|
+
return createSuccessHandoff(
|
|
14405
|
+
"Review execution.records and trace metadata before widening the macro or changing providers.",
|
|
14406
|
+
`Inspect execution.records and execution.meta, then rerun ${previewCommand} if you need a narrower plan.`,
|
|
14407
|
+
[
|
|
14408
|
+
{ reason: "Inspect execution.records and execution.meta to confirm the resolved action hit the expected lane." },
|
|
14409
|
+
{ reason: "Preview the macro again before changing providers or expression scope.", command: previewCommand },
|
|
14410
|
+
{ reason: "Re-execute with browser-scoped challenge automation when the target requires live browser recovery.", command: browserRetryCommand }
|
|
14411
|
+
]
|
|
14412
|
+
);
|
|
14413
|
+
};
|
|
14414
|
+
var buildInspiredesignSuccessHandoff = (input) => createSuccessHandoff(
|
|
14415
|
+
input.summary,
|
|
14416
|
+
input.nextStep,
|
|
14417
|
+
[
|
|
14418
|
+
{ reason: INSPIREDESIGN_HANDOFF_GUIDANCE.reviewAdvancedBrief },
|
|
14419
|
+
{
|
|
14420
|
+
reason: "Load the baseline workflow runbook before implementation.",
|
|
14421
|
+
command: input.commandExamples.loadBestPractices
|
|
14422
|
+
},
|
|
14423
|
+
{
|
|
14424
|
+
reason: "Load the Canvas contract lane before patching.",
|
|
14425
|
+
command: input.commandExamples.loadDesignAgent
|
|
14426
|
+
},
|
|
14427
|
+
{
|
|
14428
|
+
reason: INSPIREDESIGN_HANDOFF_GUIDANCE.prepareCanvasPlanRequest,
|
|
14429
|
+
command: input.commandExamples.continueInCanvas
|
|
14430
|
+
},
|
|
14431
|
+
{ reason: input.deepCaptureRecommendation }
|
|
14432
|
+
]
|
|
14433
|
+
);
|
|
14434
|
+
|
|
13470
14435
|
// src/providers/renderer.ts
|
|
13471
14436
|
var toCurrency = (value) => `$${value.toFixed(2)}`;
|
|
13472
14437
|
var primaryConstraintSummaryFromMeta = (meta) => {
|
|
@@ -13730,26 +14695,12 @@ var renderInspiredesign = (args) => {
|
|
|
13730
14695
|
evidence: args.evidence,
|
|
13731
14696
|
meta: args.meta
|
|
13732
14697
|
};
|
|
13733
|
-
const
|
|
13734
|
-
|
|
13735
|
-
|
|
13736
|
-
|
|
13737
|
-
|
|
13738
|
-
|
|
13739
|
-
command: args.designAgentHandoff.commandExamples.loadBestPractices
|
|
13740
|
-
},
|
|
13741
|
-
{
|
|
13742
|
-
reason: "Load the Canvas contract lane before patching.",
|
|
13743
|
-
command: args.designAgentHandoff.commandExamples.loadDesignAgent
|
|
13744
|
-
},
|
|
13745
|
-
{
|
|
13746
|
-
reason: INSPIREDESIGN_HANDOFF_GUIDANCE.prepareCanvasPlanRequest,
|
|
13747
|
-
command: args.designAgentHandoff.commandExamples.continueInCanvas
|
|
13748
|
-
},
|
|
13749
|
-
{
|
|
13750
|
-
reason: args.designAgentHandoff.deepCaptureRecommendation
|
|
13751
|
-
}
|
|
13752
|
-
];
|
|
14698
|
+
const handoff = buildInspiredesignSuccessHandoff({
|
|
14699
|
+
summary: followthroughSummary,
|
|
14700
|
+
nextStep: args.designAgentHandoff.nextStep,
|
|
14701
|
+
commandExamples: args.designAgentHandoff.commandExamples,
|
|
14702
|
+
deepCaptureRecommendation: args.designAgentHandoff.deepCaptureRecommendation
|
|
14703
|
+
});
|
|
13753
14704
|
const files = [
|
|
13754
14705
|
{ path: INSPIREDESIGN_HANDOFF_FILES.designMarkdown, content: args.designMarkdown },
|
|
13755
14706
|
{ path: INSPIREDESIGN_HANDOFF_FILES.advancedBrief, content: args.advancedBriefMarkdown },
|
|
@@ -13773,9 +14724,7 @@ var renderInspiredesign = (args) => {
|
|
|
13773
14724
|
response: {
|
|
13774
14725
|
mode: args.mode,
|
|
13775
14726
|
summary,
|
|
13776
|
-
|
|
13777
|
-
suggestedNextAction: args.designAgentHandoff.nextStep,
|
|
13778
|
-
suggestedSteps,
|
|
14727
|
+
...handoff,
|
|
13779
14728
|
...captureAttemptFields,
|
|
13780
14729
|
meta: args.meta
|
|
13781
14730
|
},
|
|
@@ -13796,9 +14745,7 @@ var renderInspiredesign = (args) => {
|
|
|
13796
14745
|
implementationPlan: args.implementationPlan,
|
|
13797
14746
|
prototypeGuidanceMarkdown: args.prototypeGuidanceMarkdown,
|
|
13798
14747
|
evidence: args.evidence,
|
|
13799
|
-
|
|
13800
|
-
suggestedNextAction: args.designAgentHandoff.nextStep,
|
|
13801
|
-
suggestedSteps,
|
|
14748
|
+
...handoff,
|
|
13802
14749
|
...captureAttemptFields,
|
|
13803
14750
|
meta: args.meta
|
|
13804
14751
|
},
|
|
@@ -13812,9 +14759,7 @@ var renderInspiredesign = (args) => {
|
|
|
13812
14759
|
markdown: args.designMarkdown,
|
|
13813
14760
|
implementationPlanMarkdown: args.implementationPlanMarkdown,
|
|
13814
14761
|
prototypeGuidanceMarkdown: args.prototypeGuidanceMarkdown,
|
|
13815
|
-
|
|
13816
|
-
suggestedNextAction: args.designAgentHandoff.nextStep,
|
|
13817
|
-
suggestedSteps,
|
|
14762
|
+
...handoff,
|
|
13818
14763
|
...captureAttemptFields,
|
|
13819
14764
|
meta: args.meta
|
|
13820
14765
|
},
|
|
@@ -13826,9 +14771,7 @@ var renderInspiredesign = (args) => {
|
|
|
13826
14771
|
response: {
|
|
13827
14772
|
mode: args.mode,
|
|
13828
14773
|
context: contextPayload,
|
|
13829
|
-
|
|
13830
|
-
suggestedNextAction: args.designAgentHandoff.nextStep,
|
|
13831
|
-
suggestedSteps,
|
|
14774
|
+
...handoff,
|
|
13832
14775
|
...captureAttemptFields,
|
|
13833
14776
|
meta: args.meta
|
|
13834
14777
|
},
|
|
@@ -13838,9 +14781,7 @@ var renderInspiredesign = (args) => {
|
|
|
13838
14781
|
return {
|
|
13839
14782
|
response: {
|
|
13840
14783
|
mode: "path",
|
|
13841
|
-
|
|
13842
|
-
suggestedNextAction: args.designAgentHandoff.nextStep,
|
|
13843
|
-
suggestedSteps,
|
|
14784
|
+
...handoff,
|
|
13844
14785
|
...captureAttemptFields,
|
|
13845
14786
|
meta: args.meta
|
|
13846
14787
|
},
|
|
@@ -13975,138 +14916,6 @@ var CANVAS_VALIDATION_TARGET_BLOCK_ON_CODES = [
|
|
|
13975
14916
|
];
|
|
13976
14917
|
var CANVAS_PUBLIC_WARNING_CLASSES = CANVAS_VALIDATION_TARGET_BLOCK_ON_CODES;
|
|
13977
14918
|
|
|
13978
|
-
// src/providers/workflow-handoff.ts
|
|
13979
|
-
var PRODUCT_VIDEO_BRIEF_HELPER_PATH = "./skills/opendevbrowser-product-presentation-asset/scripts/render-video-brief.sh";
|
|
13980
|
-
var PRODUCT_VIDEO_BRIEF_HELPER_COMMAND = `${PRODUCT_VIDEO_BRIEF_HELPER_PATH} <pack>/manifest.json`;
|
|
13981
|
-
var createSuccessHandoff = (followthroughSummary, suggestedNextAction, suggestedSteps) => ({
|
|
13982
|
-
followthroughSummary,
|
|
13983
|
-
suggestedNextAction,
|
|
13984
|
-
suggestedSteps
|
|
13985
|
-
});
|
|
13986
|
-
var cliExample = (command, args = "") => `npx opendevbrowser ${command}${args ? ` ${args}` : ""}`;
|
|
13987
|
-
var quoteCliValue = (value) => JSON.stringify(value);
|
|
13988
|
-
var buildResearchRerunCommand = (topic) => cliExample(
|
|
13989
|
-
"research run",
|
|
13990
|
-
`--topic ${quoteCliValue(topic)} --days 14 --source-selection auto --sources web,community --mode json --output-format json`
|
|
13991
|
-
);
|
|
13992
|
-
var buildShoppingRerunCommand = (input) => {
|
|
13993
|
-
const providers = input.providers?.length ? ` --providers ${input.providers.join(",")}` : " --providers shopping/bestbuy,shopping/ebay";
|
|
13994
|
-
const budget = typeof input.budget === "number" ? ` --budget ${input.budget}` : "";
|
|
13995
|
-
const region = input.region ? ` --region ${quoteCliValue(input.region)}` : "";
|
|
13996
|
-
const browserMode = ` --browser-mode ${input.browserMode ?? "managed"}`;
|
|
13997
|
-
const sort = input.sort ? ` --sort ${input.sort}` : "";
|
|
13998
|
-
return cliExample(
|
|
13999
|
-
"shopping run",
|
|
14000
|
-
`--query ${quoteCliValue(input.query)}${providers}${budget}${region}${browserMode}${sort} --mode json --output-format json`
|
|
14001
|
-
);
|
|
14002
|
-
};
|
|
14003
|
-
var buildProductVideoRerunCommand = (input = {}) => {
|
|
14004
|
-
const target = input.productUrl ? `--product-url ${quoteCliValue(input.productUrl)}` : `--product-name ${quoteCliValue(input.productName ?? "<product-name>")}`;
|
|
14005
|
-
const providerHint = input.providerHint ? ` --provider-hint ${input.providerHint}` : "";
|
|
14006
|
-
const screenshots = input.includeScreenshots ? " --include-screenshots" : "";
|
|
14007
|
-
const allImages = input.includeAllImages ? " --include-all-images" : "";
|
|
14008
|
-
const includeCopy = input.includeCopy ? " --include-copy" : "";
|
|
14009
|
-
return cliExample(
|
|
14010
|
-
"product-video run",
|
|
14011
|
-
`${target}${providerHint}${screenshots}${allImages}${includeCopy} --output-format json`
|
|
14012
|
-
);
|
|
14013
|
-
};
|
|
14014
|
-
var buildMacroResolveArgs = (input, options) => {
|
|
14015
|
-
const defaultProvider = input.defaultProvider ? ` --default-provider ${input.defaultProvider}` : "";
|
|
14016
|
-
const execute = options?.execute ? " --execute" : "";
|
|
14017
|
-
const challenge = options?.challengeAutomationMode ? ` --challenge-automation-mode ${options.challengeAutomationMode}` : "";
|
|
14018
|
-
const outputFormat = options?.includeOutputFormat === false ? "" : " --output-format json";
|
|
14019
|
-
return `--expression ${quoteCliValue(input.expression)}${defaultProvider}${execute}${challenge}${outputFormat}`;
|
|
14020
|
-
};
|
|
14021
|
-
var buildMacroPreviewCommand = (input) => cliExample("macro-resolve", buildMacroResolveArgs(input));
|
|
14022
|
-
var buildMacroExecuteCommand = (input, challengeAutomationMode) => cliExample("macro-resolve", buildMacroResolveArgs(input, {
|
|
14023
|
-
execute: true,
|
|
14024
|
-
challengeAutomationMode
|
|
14025
|
-
}));
|
|
14026
|
-
var buildResearchSuccessHandoff = (topic) => {
|
|
14027
|
-
const rerunCommand = buildResearchRerunCommand(topic);
|
|
14028
|
-
return createSuccessHandoff(
|
|
14029
|
-
"Review the ranked records and artifact bundle before turning the result into a publishable claim.",
|
|
14030
|
-
`Open the returned artifact path, inspect the supporting records, and rerun ${rerunCommand} if you need a tighter evidence set.`,
|
|
14031
|
-
[
|
|
14032
|
-
{ reason: "Check which records actually support the final claim." },
|
|
14033
|
-
{
|
|
14034
|
-
reason: "Rerun with explicit sources and a narrower timebox if the evidence set is still too broad.",
|
|
14035
|
-
command: rerunCommand
|
|
14036
|
-
}
|
|
14037
|
-
]
|
|
14038
|
-
);
|
|
14039
|
-
};
|
|
14040
|
-
var buildShoppingSuccessHandoff = (input) => {
|
|
14041
|
-
const rerunCommand = buildShoppingRerunCommand(input);
|
|
14042
|
-
return createSuccessHandoff(
|
|
14043
|
-
"Review the offer set and diagnostics before calling any result a strong deal.",
|
|
14044
|
-
`Inspect the offers and meta.offerFilterDiagnostics, then rerun ${rerunCommand} if you need a tighter comparison.`,
|
|
14045
|
-
[
|
|
14046
|
-
{ reason: "Check which offers survived the workflow filters and why." },
|
|
14047
|
-
{
|
|
14048
|
-
reason: "Rerun with explicit providers or updated budget and region inputs if the comparison is still noisy.",
|
|
14049
|
-
command: rerunCommand
|
|
14050
|
-
}
|
|
14051
|
-
]
|
|
14052
|
-
);
|
|
14053
|
-
};
|
|
14054
|
-
var buildProductVideoSuccessHandoff = (input = {}) => {
|
|
14055
|
-
const rerunCommand = buildProductVideoRerunCommand(input);
|
|
14056
|
-
return createSuccessHandoff(
|
|
14057
|
-
"Review the generated asset pack to confirm whether it is visual-ready or metadata-first before briefing production.",
|
|
14058
|
-
`Open the returned pack path, inspect manifest.json plus copy and features, then run ${PRODUCT_VIDEO_BRIEF_HELPER_COMMAND} to generate production briefs and sourcing notes.`,
|
|
14059
|
-
[
|
|
14060
|
-
{ reason: "Confirm whether the pack already includes enough images or screenshots for production." },
|
|
14061
|
-
{
|
|
14062
|
-
reason: "Run the product-presentation-asset brief helper on manifest.json to generate the production brief files.",
|
|
14063
|
-
command: PRODUCT_VIDEO_BRIEF_HELPER_COMMAND
|
|
14064
|
-
},
|
|
14065
|
-
{
|
|
14066
|
-
reason: "Rerun the asset workflow with adjusted provider or media flags when the current pack is too thin.",
|
|
14067
|
-
command: rerunCommand
|
|
14068
|
-
},
|
|
14069
|
-
{ reason: "Source or capture visuals before final handoff if the pack is metadata-first." }
|
|
14070
|
-
]
|
|
14071
|
-
);
|
|
14072
|
-
};
|
|
14073
|
-
var buildMacroResolveSuccessHandoff = (input) => {
|
|
14074
|
-
const previewCommand = buildMacroPreviewCommand(input);
|
|
14075
|
-
const executeCommand = buildMacroExecuteCommand(input);
|
|
14076
|
-
const browserRetryCommand = buildMacroExecuteCommand(input, "browser");
|
|
14077
|
-
if (!input.execute) {
|
|
14078
|
-
return createSuccessHandoff(
|
|
14079
|
-
"Review the resolved provider action and provenance before executing the macro.",
|
|
14080
|
-
`Run ${executeCommand} when the resolved action looks correct.`,
|
|
14081
|
-
[
|
|
14082
|
-
{ reason: "Inspect resolution.action and resolution.provenance to confirm provider and query shaping." },
|
|
14083
|
-
{ reason: "Execute the resolved macro once the plan looks correct.", command: executeCommand },
|
|
14084
|
-
{ reason: "Add --default-provider only when you need to force a different provider lane.", command: previewCommand }
|
|
14085
|
-
]
|
|
14086
|
-
);
|
|
14087
|
-
}
|
|
14088
|
-
if (input.blocked) {
|
|
14089
|
-
return createSuccessHandoff(
|
|
14090
|
-
"Review execution.meta.blocker and failures before retrying the macro.",
|
|
14091
|
-
`Run ${browserRetryCommand} after checking execution.meta.blocker and the current recovery path.`,
|
|
14092
|
-
[
|
|
14093
|
-
{ reason: "Inspect execution.meta.blocker and execution.failures before retrying." },
|
|
14094
|
-
{ reason: "Retry with browser-scoped challenge automation when the blocker requires live follow-up.", command: browserRetryCommand },
|
|
14095
|
-
{ reason: "Preview the resolved action again if you need to switch providers before another execute attempt.", command: previewCommand }
|
|
14096
|
-
]
|
|
14097
|
-
);
|
|
14098
|
-
}
|
|
14099
|
-
return createSuccessHandoff(
|
|
14100
|
-
"Review execution.records and trace metadata before widening the macro or changing providers.",
|
|
14101
|
-
`Inspect execution.records and execution.meta, then rerun ${previewCommand} if you need a narrower plan.`,
|
|
14102
|
-
[
|
|
14103
|
-
{ reason: "Inspect execution.records and execution.meta to confirm the resolved action hit the expected lane." },
|
|
14104
|
-
{ reason: "Preview the macro again before changing providers or expression scope.", command: previewCommand },
|
|
14105
|
-
{ reason: "Re-execute with browser-scoped challenge automation when the target requires live browser recovery.", command: browserRetryCommand }
|
|
14106
|
-
]
|
|
14107
|
-
);
|
|
14108
|
-
};
|
|
14109
|
-
|
|
14110
14919
|
// src/providers/shopping-postprocess.ts
|
|
14111
14920
|
import { createHash as createHash4 } from "crypto";
|
|
14112
14921
|
var LOOKS_LIKE_URL_RE = /^https?:\/\/\S+$/i;
|
|
@@ -15413,6 +16222,16 @@ var resolveResearchAutoExcludedProviders = (sourceSelection, resolvedSources, de
|
|
|
15413
16222
|
return source !== null && sourceSet.has(source);
|
|
15414
16223
|
}).sort((left, right) => left.localeCompare(right));
|
|
15415
16224
|
};
|
|
16225
|
+
var buildResearchSearchFilters = (source, args) => ({
|
|
16226
|
+
include_engagement: args.includeEngagement ?? false,
|
|
16227
|
+
timebox_from: args.timebox.from,
|
|
16228
|
+
timebox_to: args.timebox.to,
|
|
16229
|
+
...source === "community" || source === "social" ? {
|
|
16230
|
+
pageLimit: 1,
|
|
16231
|
+
hopLimit: 0,
|
|
16232
|
+
expansionPerRecord: 0
|
|
16233
|
+
} : {}
|
|
16234
|
+
});
|
|
15416
16235
|
var compileResearchExecutionPlan = (args) => {
|
|
15417
16236
|
const topic = args.input.topic?.trim();
|
|
15418
16237
|
if (!topic) {
|
|
@@ -15449,11 +16268,10 @@ var compileResearchExecutionPlan = (args) => {
|
|
|
15449
16268
|
source,
|
|
15450
16269
|
query: topic,
|
|
15451
16270
|
limit: searchLimit,
|
|
15452
|
-
filters: {
|
|
15453
|
-
|
|
15454
|
-
|
|
15455
|
-
|
|
15456
|
-
}
|
|
16271
|
+
filters: buildResearchSearchFilters(source, {
|
|
16272
|
+
includeEngagement: args.input.includeEngagement,
|
|
16273
|
+
timebox
|
|
16274
|
+
})
|
|
15457
16275
|
}
|
|
15458
16276
|
}));
|
|
15459
16277
|
return {
|
|
@@ -16261,6 +17079,7 @@ var workflowTestUtils = {
|
|
|
16261
17079
|
buildWorkflowResumePayload: (kind, input) => buildWorkflowResumePayload(kind, input)
|
|
16262
17080
|
};
|
|
16263
17081
|
var PRODUCT_ASSET_FETCH_TIMEOUT_MS = 15e3;
|
|
17082
|
+
var RESEARCH_PROVIDER_STEP_TIMEOUT_MS = 3e4;
|
|
16264
17083
|
var resolveAuxiliaryFetchTimeoutMs = (timeoutMs) => {
|
|
16265
17084
|
if (typeof timeoutMs !== "number" || !Number.isFinite(timeoutMs) || timeoutMs <= 0) {
|
|
16266
17085
|
return PRODUCT_ASSET_FETCH_TIMEOUT_MS;
|
|
@@ -16444,9 +17263,16 @@ var createRemainingTimeoutResolver = (timeoutMs) => {
|
|
|
16444
17263
|
return Math.max(1, timeoutMs - Math.max(0, Date.now() - startedAtMs));
|
|
16445
17264
|
};
|
|
16446
17265
|
};
|
|
17266
|
+
var resolveResearchProviderStepTimeoutMs = (timeoutMs) => {
|
|
17267
|
+
if (typeof timeoutMs !== "number" || !Number.isFinite(timeoutMs) || timeoutMs <= 0) {
|
|
17268
|
+
return void 0;
|
|
17269
|
+
}
|
|
17270
|
+
return Math.max(1, Math.min(timeoutMs, RESEARCH_PROVIDER_STEP_TIMEOUT_MS));
|
|
17271
|
+
};
|
|
16447
17272
|
var INSPIREDESIGN_RENDER_MODES = /* @__PURE__ */ new Set(["compact", "json", "md", "context", "path"]);
|
|
16448
17273
|
var INSPIREDESIGN_CAPTURE_MODES = /* @__PURE__ */ new Set(["off", "deep"]);
|
|
16449
17274
|
var INSPIREDESIGN_COOKIE_POLICIES = /* @__PURE__ */ new Set(["off", "auto", "required"]);
|
|
17275
|
+
var WORKFLOW_BROWSER_MODES = /* @__PURE__ */ new Set(["auto", "extension", "managed"]);
|
|
16450
17276
|
var isJsonRecord6 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
16451
17277
|
var INSPIREDESIGN_CAPTURE_UNAVAILABLE_FAILURE = "Deep capture requested, but browser capture is unavailable in this execution lane.";
|
|
16452
17278
|
var isCanvasVisualDirectionProfile = (value) => {
|
|
@@ -16469,6 +17295,7 @@ var serializeInspiredesignRunInput = (input) => ({
|
|
|
16469
17295
|
...typeof input.timeoutMs === "number" ? { timeoutMs: input.timeoutMs } : {},
|
|
16470
17296
|
...input.outputDir ? { outputDir: input.outputDir } : {},
|
|
16471
17297
|
...typeof input.ttlHours === "number" ? { ttlHours: input.ttlHours } : {},
|
|
17298
|
+
...input.browserMode ? { browserMode: input.browserMode } : {},
|
|
16472
17299
|
...typeof input.useCookies === "boolean" ? { useCookies: input.useCookies } : {},
|
|
16473
17300
|
...input.challengeAutomationMode ? { challengeAutomationMode: input.challengeAutomationMode } : {},
|
|
16474
17301
|
...input.cookiePolicyOverride ? { cookiePolicyOverride: input.cookiePolicyOverride } : {}
|
|
@@ -16543,6 +17370,7 @@ var parseInspiredesignEnvelopeInput = (input) => {
|
|
|
16543
17370
|
...typeof input.timeoutMs === "number" ? { timeoutMs: input.timeoutMs } : {},
|
|
16544
17371
|
...typeof input.outputDir === "string" && input.outputDir.length > 0 ? { outputDir: input.outputDir } : {},
|
|
16545
17372
|
...typeof input.ttlHours === "number" ? { ttlHours: input.ttlHours } : {},
|
|
17373
|
+
...typeof input.browserMode === "string" && WORKFLOW_BROWSER_MODES.has(input.browserMode) ? { browserMode: input.browserMode } : {},
|
|
16546
17374
|
...typeof input.useCookies === "boolean" ? { useCookies: input.useCookies } : {},
|
|
16547
17375
|
...isChallengeAutomationMode(input.challengeAutomationMode) ? { challengeAutomationMode: input.challengeAutomationMode } : {},
|
|
16548
17376
|
...typeof input.cookiePolicyOverride === "string" && INSPIREDESIGN_COOKIE_POLICIES.has(input.cookiePolicyOverride) ? { cookiePolicyOverride: input.cookiePolicyOverride } : {}
|
|
@@ -16636,10 +17464,13 @@ var buildInspiredesignStepEnvelope = (workflowInput, trace, stepIndex, url) => b
|
|
|
16636
17464
|
}
|
|
16637
17465
|
);
|
|
16638
17466
|
var buildInspiredesignFetchOptions = (workflowInput, envelope, timeoutMs) => withWorkflowResumeEnvelopeIntent(
|
|
16639
|
-
|
|
16640
|
-
|
|
16641
|
-
|
|
16642
|
-
|
|
17467
|
+
withBrowserModeOverride(
|
|
17468
|
+
withChallengeAutomationOverride(
|
|
17469
|
+
withCookieOverrides({
|
|
17470
|
+
...typeof timeoutMs === "number" ? { timeoutMs } : {}
|
|
17471
|
+
}, workflowInput),
|
|
17472
|
+
workflowInput
|
|
17473
|
+
),
|
|
16643
17474
|
workflowInput
|
|
16644
17475
|
),
|
|
16645
17476
|
"workflow.inspiredesign",
|
|
@@ -16880,6 +17711,7 @@ var buildInspiredesignMeta = (runtime, workflowInput, references, failures, foll
|
|
|
16880
17711
|
selection: {
|
|
16881
17712
|
urls: workflowInput.urls,
|
|
16882
17713
|
capture_mode: workflowInput.captureMode,
|
|
17714
|
+
...workflowInput.browserMode ? { requested_browser_mode: workflowInput.browserMode } : {},
|
|
16883
17715
|
include_prototype_guidance: Boolean(workflowInput.includePrototypeGuidance)
|
|
16884
17716
|
},
|
|
16885
17717
|
metrics: {
|
|
@@ -17434,10 +18266,17 @@ var runResearchWorkflow = async (runtime, input) => {
|
|
|
17434
18266
|
}
|
|
17435
18267
|
];
|
|
17436
18268
|
const buildResearchStepOptions = (step, stepEnvelope) => {
|
|
17437
|
-
const
|
|
17438
|
-
|
|
17439
|
-
|
|
17440
|
-
|
|
18269
|
+
const timeoutMs = resolveResearchProviderStepTimeoutMs(workflowInput.timeoutMs);
|
|
18270
|
+
const stepOptions = withBrowserModeOverride(
|
|
18271
|
+
withChallengeAutomationOverride(
|
|
18272
|
+
withCookieOverrides({
|
|
18273
|
+
source: step.input.source,
|
|
18274
|
+
...typeof timeoutMs === "number" ? { timeoutMs } : {}
|
|
18275
|
+
}, workflowInput),
|
|
18276
|
+
workflowInput
|
|
18277
|
+
),
|
|
18278
|
+
workflowInput
|
|
18279
|
+
);
|
|
17441
18280
|
return withWorkflowResumeEnvelopeIntent(
|
|
17442
18281
|
stepOptions,
|
|
17443
18282
|
"workflow.research",
|
|
@@ -17500,7 +18339,8 @@ var runResearchWorkflow = async (runtime, input) => {
|
|
|
17500
18339
|
timebox: resolvedTimebox,
|
|
17501
18340
|
selection: withExcludedProviders({
|
|
17502
18341
|
source_selection: plan.compiled.sourceSelection,
|
|
17503
|
-
resolved_sources: plan.compiled.resolvedSources
|
|
18342
|
+
resolved_sources: plan.compiled.resolvedSources,
|
|
18343
|
+
...workflowInput.browserMode ? { requested_browser_mode: workflowInput.browserMode } : {}
|
|
17504
18344
|
}, plan.compiled.autoExcludedProviders),
|
|
17505
18345
|
metrics: {
|
|
17506
18346
|
total_records: mergedRecords.length,
|
|
@@ -17527,7 +18367,10 @@ var runResearchWorkflow = async (runtime, input) => {
|
|
|
17527
18367
|
failures: mergedFailures,
|
|
17528
18368
|
alerts: buildWorkflowAlerts(runtime, mergedFailures)
|
|
17529
18369
|
}, primaryConstraintFailures);
|
|
17530
|
-
const handoff = buildResearchSuccessHandoff(
|
|
18370
|
+
const handoff = buildResearchSuccessHandoff({
|
|
18371
|
+
topic: plan.compiled.topic,
|
|
18372
|
+
browserMode: workflowInput.browserMode
|
|
18373
|
+
});
|
|
17531
18374
|
const responseMeta = withFollowthroughMeta(meta, handoff);
|
|
17532
18375
|
const rendered = renderResearch({
|
|
17533
18376
|
mode: workflowInput.mode,
|
|
@@ -17962,6 +18805,7 @@ var runProductVideoWorkflow = async (runtime, input, options = {}) => {
|
|
|
17962
18805
|
providers: providerHint ? [providerHint] : void 0,
|
|
17963
18806
|
mode: "json",
|
|
17964
18807
|
...timeoutOptions,
|
|
18808
|
+
browserMode: workflowInput.browserMode,
|
|
17965
18809
|
useCookies: workflowInput.useCookies,
|
|
17966
18810
|
challengeAutomationMode: workflowInput.challengeAutomationMode,
|
|
17967
18811
|
cookiePolicyOverride: workflowInput.cookiePolicyOverride
|
|
@@ -18040,12 +18884,15 @@ var runProductVideoWorkflow = async (runtime, input, options = {}) => {
|
|
|
18040
18884
|
details = await runtime.fetch(
|
|
18041
18885
|
{ url: productUrl },
|
|
18042
18886
|
withWorkflowResumeEnvelopeIntent(
|
|
18043
|
-
|
|
18044
|
-
|
|
18045
|
-
|
|
18046
|
-
|
|
18047
|
-
|
|
18048
|
-
|
|
18887
|
+
withBrowserModeOverride(
|
|
18888
|
+
withChallengeAutomationOverride(
|
|
18889
|
+
withCookieOverrides({
|
|
18890
|
+
source,
|
|
18891
|
+
providerIds: shoppingProviderId ? [shoppingProviderId] : void 0,
|
|
18892
|
+
...timeoutOptions
|
|
18893
|
+
}, workflowInput),
|
|
18894
|
+
workflowInput
|
|
18895
|
+
),
|
|
18049
18896
|
workflowInput
|
|
18050
18897
|
),
|
|
18051
18898
|
"workflow.product_video",
|
|
@@ -18195,14 +19042,16 @@ var runProductVideoWorkflow = async (runtime, input, options = {}) => {
|
|
|
18195
19042
|
productUrl,
|
|
18196
19043
|
productName: workflowInput.product_name,
|
|
18197
19044
|
providerHint,
|
|
19045
|
+
browserMode: workflowInput.browserMode,
|
|
18198
19046
|
includeScreenshots: workflowInput.include_screenshots,
|
|
18199
19047
|
includeAllImages: workflowInput.include_all_images,
|
|
18200
19048
|
includeCopy: workflowInput.include_copy
|
|
18201
19049
|
});
|
|
18202
19050
|
const meta = withFollowthroughMeta({
|
|
19051
|
+
...workflowInput.browserMode ? { selection: { requested_browser_mode: workflowInput.browserMode } } : {},
|
|
18203
19052
|
alerts: buildWorkflowAlerts(runtime, details.failures),
|
|
18204
19053
|
failures: details.failures,
|
|
18205
|
-
...primaryIssue ? { primaryConstraintSummary: primaryIssue.summary } : {},
|
|
19054
|
+
...primaryIssue ? { primaryConstraint: primaryIssue, primaryConstraintSummary: primaryIssue.summary } : {},
|
|
18206
19055
|
reasonCodeDistribution,
|
|
18207
19056
|
transcript_strategy_failures: transcriptStrategyFailures,
|
|
18208
19057
|
transcriptStrategyFailures,
|
|
@@ -18243,11 +19092,11 @@ var WORKFLOW_KIND_BY_SUSPENDED_INTENT_KIND2 = {
|
|
|
18243
19092
|
"workflow.inspiredesign": "inspiredesign",
|
|
18244
19093
|
"workflow.product_video": "product_video"
|
|
18245
19094
|
};
|
|
18246
|
-
var EXTENSION_FIRST_SOCIAL_FALLBACK_PLATFORMS = /* @__PURE__ */ new Set(["x", "reddit", "bluesky", "facebook", "linkedin"]);
|
|
19095
|
+
var EXTENSION_FIRST_SOCIAL_FALLBACK_PLATFORMS = /* @__PURE__ */ new Set(["x", "reddit", "bluesky", "facebook", "linkedin", "threads"]);
|
|
18247
19096
|
var EXTENSION_MINIMAL_TRAVERSAL_SOCIAL_PLATFORMS = /* @__PURE__ */ new Set(["linkedin"]);
|
|
18248
19097
|
var EXTENSION_FIRST_FALLBACK_MODES = ["extension", "managed_headed"];
|
|
18249
19098
|
var SOCIAL_BROWSER_RECOVERY_REASON_CODES = /* @__PURE__ */ new Set(["challenge_detected"]);
|
|
18250
|
-
var SEARCH_RENDER_RECOVERY_SOCIAL_PLATFORMS = /* @__PURE__ */ new Set(["x", "bluesky", "reddit", "facebook"]);
|
|
19099
|
+
var SEARCH_RENDER_RECOVERY_SOCIAL_PLATFORMS = /* @__PURE__ */ new Set(["x", "bluesky", "reddit", "facebook", "threads"]);
|
|
18251
19100
|
var withPrioritizedFallbackModes = (prioritized, existing) => [.../* @__PURE__ */ new Set([...prioritized, ...existing ?? []])];
|
|
18252
19101
|
var buildSocialRecoveryHints = (platform, options) => {
|
|
18253
19102
|
const existing = options?.recoveryHints?.();
|
|
@@ -18406,6 +19255,154 @@ var SOCIAL_SEARCH_ENDPOINTS = {
|
|
|
18406
19255
|
threads: (query, page) => `https://www.threads.net/search?q=${encodeURIComponent(query)}&page=${page}`,
|
|
18407
19256
|
youtube: (query, page) => `https://www.youtube.com/results?search_query=${encodeURIComponent(query)}&page=${page}`
|
|
18408
19257
|
};
|
|
19258
|
+
var FALLBACK_SHELL_LINK_SEGMENTS = /* @__PURE__ */ new Set([
|
|
19259
|
+
"account",
|
|
19260
|
+
"auth",
|
|
19261
|
+
"about",
|
|
19262
|
+
"cart",
|
|
19263
|
+
"categories",
|
|
19264
|
+
"category",
|
|
19265
|
+
"collections",
|
|
19266
|
+
"contact",
|
|
19267
|
+
"explore",
|
|
19268
|
+
"help",
|
|
19269
|
+
"home",
|
|
19270
|
+
"legal",
|
|
19271
|
+
"login",
|
|
19272
|
+
"policies",
|
|
19273
|
+
"product",
|
|
19274
|
+
"products",
|
|
19275
|
+
"privacy",
|
|
19276
|
+
"search",
|
|
19277
|
+
"settings",
|
|
19278
|
+
"shop",
|
|
19279
|
+
"signin",
|
|
19280
|
+
"sign-in",
|
|
19281
|
+
"sitemap",
|
|
19282
|
+
"store",
|
|
19283
|
+
"submit",
|
|
19284
|
+
"support",
|
|
19285
|
+
"terms"
|
|
19286
|
+
]);
|
|
19287
|
+
var FALLBACK_SHELL_TEXT_TOKENS = /* @__PURE__ */ new Set([
|
|
19288
|
+
"account",
|
|
19289
|
+
"ad",
|
|
19290
|
+
"ads",
|
|
19291
|
+
"about",
|
|
19292
|
+
"cart",
|
|
19293
|
+
"contact",
|
|
19294
|
+
"explore",
|
|
19295
|
+
"help",
|
|
19296
|
+
"home",
|
|
19297
|
+
"in",
|
|
19298
|
+
"legal",
|
|
19299
|
+
"log",
|
|
19300
|
+
"login",
|
|
19301
|
+
"policies",
|
|
19302
|
+
"product",
|
|
19303
|
+
"products",
|
|
19304
|
+
"privacy",
|
|
19305
|
+
"search",
|
|
19306
|
+
"settings",
|
|
19307
|
+
"sign",
|
|
19308
|
+
"signin",
|
|
19309
|
+
"submit",
|
|
19310
|
+
"support",
|
|
19311
|
+
"terms"
|
|
19312
|
+
]);
|
|
19313
|
+
var FALLBACK_HEAD_RE2 = /<head\b[^>]*>[\s\S]*?<\/head>/i;
|
|
19314
|
+
var FALLBACK_BODY_RE2 = /<body\b[^>]*>([\s\S]*?)<\/body>/i;
|
|
19315
|
+
var FALLBACK_MIN_MEANINGFUL_TEXT_CHARS = 20;
|
|
19316
|
+
var FALLBACK_MIN_MEANINGFUL_TOKENS = 3;
|
|
19317
|
+
var FALLBACK_SHELL_PHRASES_RE = /\b(?:search results?|please enable javascript|enable javascript|continue|welcome|accept cookies?|privacy policy|terms of service)\b/i;
|
|
19318
|
+
var extractFallbackBodyHtml = (html) => {
|
|
19319
|
+
const body = FALLBACK_BODY_RE2.exec(html)?.[1];
|
|
19320
|
+
return body ?? html.replace(FALLBACK_HEAD_RE2, " ");
|
|
19321
|
+
};
|
|
19322
|
+
var extractFallbackBodyText = (html) => {
|
|
19323
|
+
return extractText(extractFallbackBodyHtml(html));
|
|
19324
|
+
};
|
|
19325
|
+
var hasUsableFallbackText = (html) => {
|
|
19326
|
+
const text = extractFallbackBodyText(html);
|
|
19327
|
+
const blocker = classifyBlockerSignal({
|
|
19328
|
+
source: "runtime_fetch",
|
|
19329
|
+
message: text,
|
|
19330
|
+
status: 200,
|
|
19331
|
+
providerErrorCode: "unavailable",
|
|
19332
|
+
retryable: true
|
|
19333
|
+
});
|
|
19334
|
+
if (blocker && blocker.type !== "unknown") return false;
|
|
19335
|
+
if (text.length < FALLBACK_MIN_MEANINGFUL_TEXT_CHARS || FALLBACK_SHELL_PHRASES_RE.test(text)) {
|
|
19336
|
+
return false;
|
|
19337
|
+
}
|
|
19338
|
+
const tokens = text.toLowerCase().match(/[a-z0-9]+/g) ?? [];
|
|
19339
|
+
const meaningfulTokens = tokens.filter((token) => !FALLBACK_SHELL_TEXT_TOKENS.has(token));
|
|
19340
|
+
return meaningfulTokens.length >= FALLBACK_MIN_MEANINGFUL_TOKENS;
|
|
19341
|
+
};
|
|
19342
|
+
var isUsableFallbackLink = (link, documentUrl) => {
|
|
19343
|
+
try {
|
|
19344
|
+
const parsed = new URL(link);
|
|
19345
|
+
const source = new URL(documentUrl);
|
|
19346
|
+
const segments = parsed.pathname.toLowerCase().split("/").filter(Boolean);
|
|
19347
|
+
const firstSegment = segments[0];
|
|
19348
|
+
if (parsed.origin === source.origin && parsed.pathname === source.pathname) {
|
|
19349
|
+
return false;
|
|
19350
|
+
}
|
|
19351
|
+
if (segments.length === 0 && parsed.search.length === 0) {
|
|
19352
|
+
return false;
|
|
19353
|
+
}
|
|
19354
|
+
return firstSegment === void 0 || !FALLBACK_SHELL_LINK_SEGMENTS.has(firstSegment);
|
|
19355
|
+
} catch {
|
|
19356
|
+
return false;
|
|
19357
|
+
}
|
|
19358
|
+
};
|
|
19359
|
+
var hasUsableFallbackBodyLink = (documentUrl, html) => extractStructuredContent(extractFallbackBodyHtml(html), documentUrl).links.some((link) => isUsableFallbackLink(link, documentUrl));
|
|
19360
|
+
var hasUsableFallbackContent = (documentUrl, html) => hasUsableFallbackText(html) || hasUsableFallbackBodyLink(documentUrl, html);
|
|
19361
|
+
var isBlockedRedditFallbackLink = (link) => {
|
|
19362
|
+
try {
|
|
19363
|
+
const hostname = new URL(link).hostname.toLowerCase();
|
|
19364
|
+
const isReddit = hostname === "reddit.com" || hostname.endsWith(".reddit.com");
|
|
19365
|
+
return isReddit && !isAllowedSocialSearchExpansionUrl("reddit", link);
|
|
19366
|
+
} catch {
|
|
19367
|
+
return false;
|
|
19368
|
+
}
|
|
19369
|
+
};
|
|
19370
|
+
var shouldOwnerReviewCommunityRedditSearchFallback = (input) => input.providerId === "community/default" && input.source === "community" && input.operation === "search" && isFirstPartySocialSearchRoute("reddit", input.url) && input.extracted.links.length > 0 && input.extracted.links.every(isBlockedRedditFallbackLink);
|
|
19371
|
+
var shouldReturnCompletedFallbackForOwnerReview = (args) => args.document.browserFallback !== void 0 && args.ownerReview?.({
|
|
19372
|
+
providerId: args.providerId,
|
|
19373
|
+
source: args.source,
|
|
19374
|
+
operation: args.operation,
|
|
19375
|
+
url: args.document.url,
|
|
19376
|
+
html: args.document.html,
|
|
19377
|
+
extracted: extractStructuredContent(args.document.html, args.document.url)
|
|
19378
|
+
}) === true;
|
|
19379
|
+
var toCompletedFallbackDocument = (args) => {
|
|
19380
|
+
const resolvedUrl = canonicalizeUrl(readFallbackString(args.fallback.output, "url") ?? args.url);
|
|
19381
|
+
const html = readFallbackString(args.fallback.output, "html");
|
|
19382
|
+
if (!html) {
|
|
19383
|
+
throw toCompletedFallbackOutputError({ ...args, provider: args.providerId, url: resolvedUrl, outputReason: "missing_or_empty_html" });
|
|
19384
|
+
}
|
|
19385
|
+
const extracted = extractStructuredContent(html, resolvedUrl);
|
|
19386
|
+
const reviewInput = {
|
|
19387
|
+
providerId: args.providerId,
|
|
19388
|
+
source: args.source,
|
|
19389
|
+
operation: args.operation,
|
|
19390
|
+
url: resolvedUrl,
|
|
19391
|
+
html,
|
|
19392
|
+
extracted
|
|
19393
|
+
};
|
|
19394
|
+
if (!hasUsableFallbackContent(resolvedUrl, html) && !args.ownerReview?.(reviewInput)) {
|
|
19395
|
+
throw toCompletedFallbackOutputError({ ...args, provider: args.providerId, url: resolvedUrl, outputReason: "empty_extracted_content" });
|
|
19396
|
+
}
|
|
19397
|
+
return {
|
|
19398
|
+
url: resolvedUrl,
|
|
19399
|
+
status: 200,
|
|
19400
|
+
html,
|
|
19401
|
+
text: extracted.text,
|
|
19402
|
+
links: extracted.links,
|
|
19403
|
+
browserFallback: toBrowserFallbackObservation(args.fallback)
|
|
19404
|
+
};
|
|
19405
|
+
};
|
|
18409
19406
|
var describeDefaultFetchedIssue = (document) => {
|
|
18410
19407
|
const extracted = extractStructuredContent(document.html, document.url);
|
|
18411
19408
|
const title = typeof extracted.metadata.title === "string" ? extracted.metadata.title : void 0;
|
|
@@ -18467,6 +19464,9 @@ var resolveDefaultFallbackDocumentIfNeeded = async (args) => {
|
|
|
18467
19464
|
if (!initialIssue) {
|
|
18468
19465
|
return { document: currentDocument, ...described };
|
|
18469
19466
|
}
|
|
19467
|
+
if (shouldReturnCompletedFallbackForOwnerReview({ ...args, document: currentDocument })) {
|
|
19468
|
+
return { document: currentDocument, ...described };
|
|
19469
|
+
}
|
|
18470
19470
|
if (initialIssue.reasonCode === "env_limited" && !initialIssue.constraint) {
|
|
18471
19471
|
return { document: currentDocument, ...described };
|
|
18472
19472
|
}
|
|
@@ -18497,18 +19497,18 @@ var resolveDefaultFallbackDocumentIfNeeded = async (args) => {
|
|
|
18497
19497
|
fallback
|
|
18498
19498
|
});
|
|
18499
19499
|
}
|
|
18500
|
-
|
|
18501
|
-
|
|
18502
|
-
|
|
18503
|
-
|
|
18504
|
-
url:
|
|
18505
|
-
|
|
18506
|
-
|
|
18507
|
-
|
|
18508
|
-
links: extracted.links,
|
|
18509
|
-
browserFallback: toBrowserFallbackObservation(fallback)
|
|
18510
|
-
};
|
|
19500
|
+
currentDocument = toCompletedFallbackDocument({
|
|
19501
|
+
providerId: args.providerId,
|
|
19502
|
+
source: args.source,
|
|
19503
|
+
operation: args.operation,
|
|
19504
|
+
url: currentDocument.url,
|
|
19505
|
+
fallback,
|
|
19506
|
+
ownerReview: args.ownerReview
|
|
19507
|
+
});
|
|
18511
19508
|
described = describeDefaultFetchedIssue(currentDocument);
|
|
19509
|
+
if (shouldReturnCompletedFallbackForOwnerReview({ ...args, document: currentDocument })) {
|
|
19510
|
+
return { document: currentDocument, ...described };
|
|
19511
|
+
}
|
|
18512
19512
|
if (!described.issue || described.issue.reasonCode === "env_limited" && !described.issue.constraint) {
|
|
18513
19513
|
return { document: currentDocument, ...described };
|
|
18514
19514
|
}
|
|
@@ -18785,6 +19785,57 @@ var readResponseTextWithAbort = async (response, args) => {
|
|
|
18785
19785
|
}
|
|
18786
19786
|
};
|
|
18787
19787
|
var fetchRuntimeDocumentWithFallback = async (args) => {
|
|
19788
|
+
const fallbackPort = args.context?.browserFallbackPort ?? args.browserFallbackPort;
|
|
19789
|
+
const runtimePolicy = args.context?.runtimePolicy;
|
|
19790
|
+
const forcedBrowserTransport = runtimePolicy?.browser.forceTransport === true;
|
|
19791
|
+
const forcedReasonCode = runtimePolicy?.cookies.policy === "required" ? "auth_required" : "env_limited";
|
|
19792
|
+
if (forcedBrowserTransport) {
|
|
19793
|
+
const fallback = await resolveProviderBrowserFallback({
|
|
19794
|
+
browserFallbackPort: fallbackPort,
|
|
19795
|
+
provider: args.provider,
|
|
19796
|
+
source: args.source,
|
|
19797
|
+
operation: args.operation,
|
|
19798
|
+
reasonCode: forcedReasonCode,
|
|
19799
|
+
url: args.url,
|
|
19800
|
+
context: args.context,
|
|
19801
|
+
details: {
|
|
19802
|
+
message: "Direct browser transport was selected for this provider run."
|
|
19803
|
+
},
|
|
19804
|
+
recoveryHints: args.recoveryHints
|
|
19805
|
+
});
|
|
19806
|
+
if (!fallback) {
|
|
19807
|
+
throw new ProviderRuntimeError(
|
|
19808
|
+
providerErrorCodeFromReasonCode(forcedReasonCode),
|
|
19809
|
+
"Direct browser transport is required for this provider run, but no browser transport is available.",
|
|
19810
|
+
{
|
|
19811
|
+
provider: args.provider,
|
|
19812
|
+
source: args.source,
|
|
19813
|
+
retryable: false,
|
|
19814
|
+
reasonCode: forcedReasonCode,
|
|
19815
|
+
details: {
|
|
19816
|
+
reasonCode: forcedReasonCode,
|
|
19817
|
+
browserTransportRequired: true
|
|
19818
|
+
}
|
|
19819
|
+
}
|
|
19820
|
+
);
|
|
19821
|
+
}
|
|
19822
|
+
if (fallback.disposition !== "completed") {
|
|
19823
|
+
throw toProviderFallbackError({
|
|
19824
|
+
provider: args.provider,
|
|
19825
|
+
source: args.source,
|
|
19826
|
+
url: args.url,
|
|
19827
|
+
fallback
|
|
19828
|
+
});
|
|
19829
|
+
}
|
|
19830
|
+
return toCompletedFallbackDocument({
|
|
19831
|
+
providerId: args.provider,
|
|
19832
|
+
source: args.source,
|
|
19833
|
+
operation: args.operation,
|
|
19834
|
+
url: args.url,
|
|
19835
|
+
fallback,
|
|
19836
|
+
ownerReview: args.ownerReview
|
|
19837
|
+
});
|
|
19838
|
+
}
|
|
18788
19839
|
try {
|
|
18789
19840
|
return await fetchRuntimeDocument({
|
|
18790
19841
|
url: args.url,
|
|
@@ -18797,7 +19848,9 @@ var fetchRuntimeDocumentWithFallback = async (args) => {
|
|
|
18797
19848
|
provider: args.provider,
|
|
18798
19849
|
source: args.source
|
|
18799
19850
|
});
|
|
18800
|
-
|
|
19851
|
+
if (args.recoverRuntimeErrors === false) {
|
|
19852
|
+
throw error;
|
|
19853
|
+
}
|
|
18801
19854
|
if (!fallbackPort) {
|
|
18802
19855
|
throw error;
|
|
18803
19856
|
}
|
|
@@ -18831,17 +19884,14 @@ var fetchRuntimeDocumentWithFallback = async (args) => {
|
|
|
18831
19884
|
fallback
|
|
18832
19885
|
});
|
|
18833
19886
|
}
|
|
18834
|
-
|
|
18835
|
-
|
|
18836
|
-
|
|
18837
|
-
|
|
18838
|
-
url:
|
|
18839
|
-
|
|
18840
|
-
|
|
18841
|
-
|
|
18842
|
-
links: extracted.links,
|
|
18843
|
-
browserFallback: toBrowserFallbackObservation(fallback)
|
|
18844
|
-
};
|
|
19887
|
+
return toCompletedFallbackDocument({
|
|
19888
|
+
providerId: args.provider,
|
|
19889
|
+
source: args.source,
|
|
19890
|
+
operation: args.operation,
|
|
19891
|
+
url: args.url,
|
|
19892
|
+
fallback,
|
|
19893
|
+
ownerReview: args.ownerReview
|
|
19894
|
+
});
|
|
18845
19895
|
}
|
|
18846
19896
|
};
|
|
18847
19897
|
var ProviderRuntime = class {
|
|
@@ -19997,7 +21047,8 @@ var withDefaultCommunityOptions = (options, browserFallbackPort) => {
|
|
|
19997
21047
|
operation: "search",
|
|
19998
21048
|
signal: context.signal,
|
|
19999
21049
|
context,
|
|
20000
|
-
browserFallbackPort
|
|
21050
|
+
browserFallbackPort,
|
|
21051
|
+
ownerReview: shouldOwnerReviewCommunityRedditSearchFallback
|
|
20001
21052
|
});
|
|
20002
21053
|
const { document: resolvedDocument, pageMessage } = await resolveDefaultFallbackDocumentIfNeeded({
|
|
20003
21054
|
providerId,
|
|
@@ -20005,7 +21056,8 @@ var withDefaultCommunityOptions = (options, browserFallbackPort) => {
|
|
|
20005
21056
|
operation: "search",
|
|
20006
21057
|
document,
|
|
20007
21058
|
context,
|
|
20008
|
-
browserFallbackPort
|
|
21059
|
+
browserFallbackPort,
|
|
21060
|
+
ownerReview: shouldOwnerReviewCommunityRedditSearchFallback
|
|
20009
21061
|
});
|
|
20010
21062
|
const links = resolveCommunitySearchLinks(resolvedDocument, limit);
|
|
20011
21063
|
if (shouldRejectBlockedCommunityFallback(resolvedDocument, links)) {
|
|
@@ -20117,6 +21169,12 @@ var withDefaultSocialPlatformOptions = (platform, options, browserFallbackPort)
|
|
|
20117
21169
|
}
|
|
20118
21170
|
);
|
|
20119
21171
|
};
|
|
21172
|
+
const shouldOwnerReviewSocialFallback = (input) => input.source === "social" && input.operation === "search" && detectSocialSearchShell(platform, {
|
|
21173
|
+
url: input.url,
|
|
21174
|
+
title: typeof input.extracted.metadata.title === "string" ? input.extracted.metadata.title : void 0,
|
|
21175
|
+
content: toSnippet(stripUrls(input.extracted.text), 1600),
|
|
21176
|
+
links: input.extracted.links
|
|
21177
|
+
})?.browserRequired === true;
|
|
20120
21178
|
const resolveFallbackDocumentIfNeeded = async (operation, document, context) => {
|
|
20121
21179
|
let currentDocument = document;
|
|
20122
21180
|
let described = describeDocumentIssue(operation, currentDocument);
|
|
@@ -20151,23 +21209,24 @@ var withDefaultSocialPlatformOptions = (platform, options, browserFallbackPort)
|
|
|
20151
21209
|
});
|
|
20152
21210
|
}
|
|
20153
21211
|
const requestedUrl = currentDocument.url;
|
|
20154
|
-
const
|
|
20155
|
-
|
|
20156
|
-
|
|
21212
|
+
const fallbackDocument = toCompletedFallbackDocument({
|
|
21213
|
+
providerId,
|
|
21214
|
+
source: "social",
|
|
21215
|
+
operation,
|
|
21216
|
+
url: currentDocument.url,
|
|
21217
|
+
fallback,
|
|
21218
|
+
ownerReview: shouldOwnerReviewSocialFallback
|
|
21219
|
+
});
|
|
20157
21220
|
const effectiveUrl = resolveRecoveredSocialSearchDocumentUrl({
|
|
20158
21221
|
platform,
|
|
20159
21222
|
operation,
|
|
20160
21223
|
requestedUrl,
|
|
20161
|
-
recoveredUrl:
|
|
20162
|
-
recoveredLinks:
|
|
21224
|
+
recoveredUrl: fallbackDocument.url,
|
|
21225
|
+
recoveredLinks: fallbackDocument.links
|
|
20163
21226
|
});
|
|
20164
21227
|
currentDocument = {
|
|
20165
|
-
|
|
20166
|
-
|
|
20167
|
-
html,
|
|
20168
|
-
text: extracted.text,
|
|
20169
|
-
links: extracted.links,
|
|
20170
|
-
browserFallback: toBrowserFallbackObservation(fallback)
|
|
21228
|
+
...fallbackDocument,
|
|
21229
|
+
url: effectiveUrl
|
|
20171
21230
|
};
|
|
20172
21231
|
described = describeDocumentIssue(operation, currentDocument);
|
|
20173
21232
|
if (!described.issue || described.issue.reasonCode === "env_limited" && !described.issue.constraint) {
|
|
@@ -20191,7 +21250,9 @@ var withDefaultSocialPlatformOptions = (platform, options, browserFallbackPort)
|
|
|
20191
21250
|
signal: context.signal,
|
|
20192
21251
|
context,
|
|
20193
21252
|
browserFallbackPort,
|
|
20194
|
-
recoveryHints: extensionFirstRecoveryHints
|
|
21253
|
+
recoveryHints: extensionFirstRecoveryHints,
|
|
21254
|
+
recoverRuntimeErrors: EXTENSION_FIRST_SOCIAL_FALLBACK_PLATFORMS.has(platform),
|
|
21255
|
+
ownerReview: shouldOwnerReviewSocialFallback
|
|
20195
21256
|
});
|
|
20196
21257
|
const { document: resolvedDocument, extracted, pageMessage } = await resolveFallbackDocumentIfNeeded("search", document, context);
|
|
20197
21258
|
const links = dedupeLinks2(
|
|
@@ -20224,7 +21285,9 @@ var withDefaultSocialPlatformOptions = (platform, options, browserFallbackPort)
|
|
|
20224
21285
|
signal: context.signal,
|
|
20225
21286
|
context,
|
|
20226
21287
|
browserFallbackPort,
|
|
20227
|
-
recoveryHints: extensionFirstRecoveryHints
|
|
21288
|
+
recoveryHints: extensionFirstRecoveryHints,
|
|
21289
|
+
recoverRuntimeErrors: EXTENSION_FIRST_SOCIAL_FALLBACK_PLATFORMS.has(platform),
|
|
21290
|
+
ownerReview: shouldOwnerReviewSocialFallback
|
|
20228
21291
|
});
|
|
20229
21292
|
const { document: resolvedDocument, extracted } = await resolveFallbackDocumentIfNeeded("fetch", document, context);
|
|
20230
21293
|
const links = dedupeLinks2(resolvedDocument.links, resolvedDocument.url, 20);
|
|
@@ -20387,10 +21450,10 @@ export {
|
|
|
20387
21450
|
enrichResearchRecords,
|
|
20388
21451
|
INSPIREDESIGN_HANDOFF_COMMANDS,
|
|
20389
21452
|
INSPIREDESIGN_HANDOFF_GUIDANCE,
|
|
21453
|
+
buildMacroResolveSuccessHandoff,
|
|
20390
21454
|
renderResearch,
|
|
20391
21455
|
renderShopping,
|
|
20392
21456
|
renderInspiredesign,
|
|
20393
|
-
buildMacroResolveSuccessHandoff,
|
|
20394
21457
|
resolveInspiredesignCaptureMode,
|
|
20395
21458
|
workflowTestUtils,
|
|
20396
21459
|
runResearchWorkflow,
|
|
@@ -20402,4 +21465,4 @@ export {
|
|
|
20402
21465
|
createProviderRuntime,
|
|
20403
21466
|
createDefaultRuntime
|
|
20404
21467
|
};
|
|
20405
|
-
//# sourceMappingURL=chunk-
|
|
21468
|
+
//# sourceMappingURL=chunk-T3VVHJTK.js.map
|