opendevbrowser 0.0.19 → 0.0.21
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 +32 -24
- package/dist/automation/coordinator.d.ts +61 -2
- package/dist/automation/coordinator.d.ts.map +1 -1
- package/dist/browser/browser-manager.d.ts +6 -1
- package/dist/browser/browser-manager.d.ts.map +1 -1
- package/dist/browser/canvas-manager.d.ts +4 -0
- package/dist/browser/canvas-manager.d.ts.map +1 -1
- package/dist/browser/manager-types.d.ts +6 -1
- package/dist/browser/manager-types.d.ts.map +1 -1
- package/dist/browser/ops-browser-manager.d.ts +6 -1
- package/dist/browser/ops-browser-manager.d.ts.map +1 -1
- package/dist/browser/screencast-recorder.d.ts.map +1 -1
- package/dist/browser/session-inspector.d.ts +39 -0
- package/dist/browser/session-inspector.d.ts.map +1 -1
- package/dist/canvas/document-store.d.ts +14 -5
- package/dist/canvas/document-store.d.ts.map +1 -1
- package/dist/canvas/starters/catalog.d.ts.map +1 -1
- package/dist/canvas/types.d.ts +120 -9
- package/dist/canvas/types.d.ts.map +1 -1
- package/dist/challenges/action-loop.d.ts +2 -1
- package/dist/challenges/action-loop.d.ts.map +1 -1
- package/dist/challenges/capture.d.ts +14 -0
- package/dist/challenges/capture.d.ts.map +1 -0
- package/dist/challenges/index.d.ts +3 -1
- package/dist/challenges/index.d.ts.map +1 -1
- package/dist/challenges/inspect-plan.d.ts +40 -0
- package/dist/challenges/inspect-plan.d.ts.map +1 -0
- package/dist/challenges/orchestrator.d.ts.map +1 -1
- package/dist/challenges/types.d.ts +34 -0
- package/dist/challenges/types.d.ts.map +1 -1
- package/dist/{chunk-YBQECXZX.js → chunk-3VA6XR25.js} +3 -3
- package/dist/chunk-3VA6XR25.js.map +1 -0
- package/dist/{chunk-W4IHGDXV.js → chunk-4KVXCXV3.js} +25778 -24279
- package/dist/chunk-4KVXCXV3.js.map +1 -0
- package/dist/{chunk-5FZQJRBQ.js → chunk-ZE2E7ZGH.js} +3013 -1010
- package/dist/chunk-ZE2E7ZGH.js.map +1 -0
- package/dist/cli/commands/challenge-automation-mode.d.ts +3 -0
- package/dist/cli/commands/challenge-automation-mode.d.ts.map +1 -0
- package/dist/cli/commands/inspiredesign.d.ts +25 -0
- package/dist/cli/commands/inspiredesign.d.ts.map +1 -0
- package/dist/cli/commands/macro-resolve.d.ts.map +1 -1
- package/dist/cli/commands/nav/review-desktop.d.ts +7 -0
- package/dist/cli/commands/nav/review-desktop.d.ts.map +1 -0
- package/dist/cli/commands/nav/review-shared.d.ts +10 -0
- package/dist/cli/commands/nav/review-shared.d.ts.map +1 -0
- package/dist/cli/commands/nav/review.d.ts.map +1 -1
- package/dist/cli/commands/serve.d.ts.map +1 -1
- package/dist/cli/commands/session/inspector-audit.d.ts +7 -0
- package/dist/cli/commands/session/inspector-audit.d.ts.map +1 -0
- package/dist/cli/commands/session/inspector-plan.d.ts +7 -0
- package/dist/cli/commands/session/inspector-plan.d.ts.map +1 -0
- package/dist/cli/commands/session/inspector-shared.d.ts +11 -0
- package/dist/cli/commands/session/inspector-shared.d.ts.map +1 -0
- package/dist/cli/commands/session/inspector.d.ts +1 -11
- package/dist/cli/commands/session/inspector.d.ts.map +1 -1
- package/dist/cli/commands/status-capabilities.d.ts +7 -0
- package/dist/cli/commands/status-capabilities.d.ts.map +1 -0
- package/dist/cli/daemon-client.d.ts.map +1 -1
- package/dist/cli/daemon-commands.d.ts.map +1 -1
- package/dist/cli/daemon-status.d.ts +5 -0
- package/dist/cli/daemon-status.d.ts.map +1 -1
- package/dist/cli/daemon.d.ts +5 -0
- package/dist/cli/daemon.d.ts.map +1 -1
- package/dist/cli/help.d.ts +2 -0
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/index.js +660 -244
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/remote-manager.d.ts +6 -0
- package/dist/cli/remote-manager.d.ts.map +1 -1
- package/dist/cli/utils/parse.d.ts +1 -0
- package/dist/cli/utils/parse.d.ts.map +1 -1
- package/dist/cli/utils/skills.d.ts +1 -1
- package/dist/cli/utils/skills.d.ts.map +1 -1
- package/dist/cli/utils/workflow-message.d.ts +3 -0
- package/dist/cli/utils/workflow-message.d.ts.map +1 -1
- package/dist/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/core/bootstrap.d.ts.map +1 -1
- package/dist/core/runtime-assemblies.d.ts +2 -1
- package/dist/core/runtime-assemblies.d.ts.map +1 -1
- package/dist/core/types.d.ts +1 -1
- package/dist/core/types.d.ts.map +1 -1
- package/dist/desktop/runtime.d.ts +1 -0
- package/dist/desktop/runtime.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +729 -448
- package/dist/index.js.map +1 -1
- package/dist/inspiredesign/handoff.d.ts +34 -0
- package/dist/inspiredesign/handoff.d.ts.map +1 -0
- package/dist/opendevbrowser.d.ts.map +1 -1
- package/dist/opendevbrowser.js +729 -448
- package/dist/opendevbrowser.js.map +1 -1
- package/dist/providers/browser-fallback.d.ts.map +1 -1
- package/dist/providers/constraint.d.ts +11 -0
- package/dist/providers/constraint.d.ts.map +1 -1
- package/dist/providers/cookie-source.d.ts +8 -0
- package/dist/providers/cookie-source.d.ts.map +1 -0
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/inspiredesign-capture.d.ts +17 -0
- package/dist/providers/inspiredesign-capture.d.ts.map +1 -0
- package/dist/providers/inspiredesign-contract.d.ts +110 -0
- package/dist/providers/inspiredesign-contract.d.ts.map +1 -0
- package/dist/providers/renderer.d.ts +23 -0
- package/dist/providers/renderer.d.ts.map +1 -1
- package/dist/providers/runtime-bundle.d.ts +2 -1
- package/dist/providers/runtime-bundle.d.ts.map +1 -1
- package/dist/providers/runtime-factory.d.ts +4 -2
- package/dist/providers/runtime-factory.d.ts.map +1 -1
- package/dist/providers/shopping/index.d.ts +1 -1
- package/dist/providers/types.d.ts +3 -2
- package/dist/providers/types.d.ts.map +1 -1
- package/dist/providers/workflow-contracts.d.ts +1 -1
- package/dist/providers/workflow-contracts.d.ts.map +1 -1
- package/dist/providers/workflow-handoff.d.ts +14 -0
- package/dist/providers/workflow-handoff.d.ts.map +1 -0
- package/dist/providers/workflows.d.ts +21 -2
- package/dist/providers/workflows.d.ts.map +1 -1
- package/dist/{providers-G36AM3Z2.js → providers-ZIVHHH4F.js} +6 -2
- package/dist/public-surface/generated-manifest.d.ts +143 -7
- package/dist/public-surface/generated-manifest.d.ts.map +1 -1
- package/dist/public-surface/source.d.ts +102 -3
- package/dist/public-surface/source.d.ts.map +1 -1
- package/dist/relay/protocol.d.ts +1 -1
- package/dist/relay/protocol.d.ts.map +1 -1
- package/dist/relay/relay-server.d.ts +1 -0
- package/dist/relay/relay-server.d.ts.map +1 -1
- package/dist/skills/skill-loader.js +1 -1
- package/dist/tools/automation-shared.d.ts +6 -0
- package/dist/tools/automation-shared.d.ts.map +1 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/inspiredesign_run.d.ts +4 -0
- package/dist/tools/inspiredesign_run.d.ts.map +1 -0
- package/dist/tools/review_desktop.d.ts +4 -0
- package/dist/tools/review_desktop.d.ts.map +1 -0
- package/dist/tools/session_inspector.d.ts.map +1 -1
- package/dist/tools/session_inspector_audit.d.ts +4 -0
- package/dist/tools/session_inspector_audit.d.ts.map +1 -0
- package/dist/tools/session_inspector_plan.d.ts +4 -0
- package/dist/tools/session_inspector_plan.d.ts.map +1 -0
- package/dist/tools/status_capabilities.d.ts +4 -0
- package/dist/tools/status_capabilities.d.ts.map +1 -0
- package/extension/dist/background.js +70 -10
- package/extension/dist/canvas/canvas-runtime.js +14 -1
- package/extension/dist/ops/ops-runtime.js +18 -1
- package/extension/dist/popup.js +29 -16
- package/extension/dist/services/ConnectionManager.js +27 -2
- package/extension/manifest.json +1 -1
- package/extension/popup.html +11 -0
- package/package.json +5 -5
- package/skills/AGENTS.md +2 -2
- package/skills/opendevbrowser-best-practices/SKILL.md +50 -15
- package/skills/opendevbrowser-best-practices/artifacts/canvas-governance-playbook.md +31 -12
- package/skills/opendevbrowser-best-practices/artifacts/command-channel-reference.md +64 -15
- package/skills/opendevbrowser-best-practices/artifacts/provider-workflows.md +4 -0
- package/skills/opendevbrowser-best-practices/artifacts/skill-runtime-surface-matrix.md +11 -10
- package/skills/opendevbrowser-best-practices/assets/templates/canvas-blocker-checklist.json +28 -22
- package/skills/opendevbrowser-best-practices/assets/templates/canvas-generation-plan.v1.json +18 -17
- package/skills/opendevbrowser-best-practices/assets/templates/canvas-handshake-example.json +135 -17
- package/skills/opendevbrowser-best-practices/assets/templates/skill-runtime-pack-matrix.json +55 -8
- package/skills/opendevbrowser-best-practices/assets/templates/surface-audit-checklist.json +18 -4
- package/skills/opendevbrowser-best-practices/scripts/odb-workflow.sh +16 -4
- package/skills/opendevbrowser-best-practices/scripts/run-robustness-audit.sh +3 -1
- package/skills/opendevbrowser-best-practices/scripts/validate-skill-assets.sh +68 -25
- package/skills/opendevbrowser-design-agent/SKILL.md +9 -4
- package/skills/opendevbrowser-design-agent/artifacts/design-workflows.md +15 -6
- package/skills/opendevbrowser-design-agent/assets/templates/canvas-generation-plan.design.v1.json +18 -17
- package/skills/opendevbrowser-design-agent/scripts/design-workflow.sh +11 -0
- package/skills/opendevbrowser-design-agent/scripts/validate-skill-assets.sh +57 -0
- package/skills/opendevbrowser-product-presentation-asset/SKILL.md +2 -2
- package/dist/chunk-5FZQJRBQ.js.map +0 -1
- package/dist/chunk-W4IHGDXV.js.map +0 -1
- package/dist/chunk-YBQECXZX.js.map +0 -1
- /package/dist/{providers-G36AM3Z2.js.map → providers-ZIVHHH4F.js.map} +0 -0
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
ProviderRuntimeError,
|
|
3
3
|
createProviderError,
|
|
4
4
|
isProviderReasonCode,
|
|
5
|
+
isProviderRuntimeError,
|
|
5
6
|
normalizeProviderReasonCode,
|
|
6
7
|
providerErrorCodeFromReasonCode,
|
|
7
8
|
toProviderError
|
|
@@ -796,6 +797,12 @@ var applyProviderIssueHint = (details, hint) => {
|
|
|
796
797
|
if (hint.constraint && !isProviderConstraint(next.constraint)) {
|
|
797
798
|
next.constraint = hint.constraint;
|
|
798
799
|
}
|
|
800
|
+
if (typeof next.guidance === "undefined") {
|
|
801
|
+
const guidance = buildProviderIssueGuidance({ hint, details: next });
|
|
802
|
+
if (guidance) {
|
|
803
|
+
next.guidance = guidance;
|
|
804
|
+
}
|
|
805
|
+
}
|
|
799
806
|
return next;
|
|
800
807
|
};
|
|
801
808
|
var providerLabel = (provider) => {
|
|
@@ -805,6 +812,77 @@ var providerLabel = (provider) => {
|
|
|
805
812
|
const tail = separator >= 0 ? normalized.slice(separator + 1) : normalized;
|
|
806
813
|
return tail.charAt(0).toUpperCase() + tail.slice(1);
|
|
807
814
|
};
|
|
815
|
+
var hasPreservedBrowserState = (details) => {
|
|
816
|
+
return typeof details?.preservedSessionId === "string" || typeof details?.preservedTargetId === "string";
|
|
817
|
+
};
|
|
818
|
+
var buildGuidance = (reason, recommendedNextCommands) => ({
|
|
819
|
+
reason,
|
|
820
|
+
recommendedNextCommands
|
|
821
|
+
});
|
|
822
|
+
var buildAuthGuidance = (subject, preservedBrowserState) => {
|
|
823
|
+
return preservedBrowserState ? buildGuidance(
|
|
824
|
+
`${subject} preserved browser state that can finish authentication.`,
|
|
825
|
+
[
|
|
826
|
+
"Complete the login or account checkpoint in the preserved browser session.",
|
|
827
|
+
"Rerun the same provider or workflow after the session is fully authenticated."
|
|
828
|
+
]
|
|
829
|
+
) : buildGuidance(
|
|
830
|
+
`${subject} needs an authenticated session before retrying.`,
|
|
831
|
+
[
|
|
832
|
+
"Reuse an authenticated browser session, import logged-in cookies, or use the provider sign-in flow.",
|
|
833
|
+
"Rerun the same provider or workflow once the session is active."
|
|
834
|
+
]
|
|
835
|
+
);
|
|
836
|
+
};
|
|
837
|
+
var buildChallengeGuidance = (subject, preservedBrowserState) => {
|
|
838
|
+
return preservedBrowserState ? buildGuidance(
|
|
839
|
+
`${subject} preserved browser state that can complete the current challenge.`,
|
|
840
|
+
[
|
|
841
|
+
"Finish the login or anti-bot challenge in the preserved browser session.",
|
|
842
|
+
"Rerun the same provider or workflow after the page unlocks."
|
|
843
|
+
]
|
|
844
|
+
) : buildGuidance(
|
|
845
|
+
`${subject} hit a challenge that still needs browser-assisted follow-up.`,
|
|
846
|
+
[
|
|
847
|
+
"Retry with browser assistance so the challenge can be completed interactively.",
|
|
848
|
+
"Only ask for manual credentials if browser-assisted recovery still cannot unlock the page."
|
|
849
|
+
]
|
|
850
|
+
);
|
|
851
|
+
};
|
|
852
|
+
var buildRenderGuidance = (subject, preservedBrowserState) => {
|
|
853
|
+
return preservedBrowserState ? buildGuidance(
|
|
854
|
+
`${subject} still needs a live browser-rendered page, but browser state is already preserved.`,
|
|
855
|
+
[
|
|
856
|
+
"Inspect the preserved browser session until usable content is visible.",
|
|
857
|
+
"Rerun the same provider or workflow after the rendered page is ready."
|
|
858
|
+
]
|
|
859
|
+
) : buildGuidance(
|
|
860
|
+
`${subject} needs a live browser-rendered page before retrying.`,
|
|
861
|
+
[
|
|
862
|
+
"Retry with browser assistance or a headed browser session.",
|
|
863
|
+
"Rerun the same provider or workflow after the rendered page is ready."
|
|
864
|
+
]
|
|
865
|
+
);
|
|
866
|
+
};
|
|
867
|
+
var buildProviderIssueGuidance = (args) => {
|
|
868
|
+
const subject = providerLabel(args.provider);
|
|
869
|
+
const preservedBrowserState = hasPreservedBrowserState(args.details);
|
|
870
|
+
const disposition = toNonEmptyString(args.details?.disposition);
|
|
871
|
+
if (disposition === "completed") return void 0;
|
|
872
|
+
if (disposition === "challenge_preserved") {
|
|
873
|
+
return buildChallengeGuidance(subject, true);
|
|
874
|
+
}
|
|
875
|
+
if (args.hint.reasonCode === "token_required" || args.hint.reasonCode === "auth_required") {
|
|
876
|
+
return buildAuthGuidance(subject, preservedBrowserState);
|
|
877
|
+
}
|
|
878
|
+
if (args.hint.reasonCode === "challenge_detected") {
|
|
879
|
+
return buildChallengeGuidance(subject, preservedBrowserState);
|
|
880
|
+
}
|
|
881
|
+
if (args.hint.constraint?.kind === "render_required" || args.hint.reasonCode === "env_limited") {
|
|
882
|
+
return buildRenderGuidance(subject, preservedBrowserState);
|
|
883
|
+
}
|
|
884
|
+
return void 0;
|
|
885
|
+
};
|
|
808
886
|
var summaryPriority = (hint) => {
|
|
809
887
|
if (hint.reasonCode === "token_required" || hint.reasonCode === "auth_required") return 3;
|
|
810
888
|
if (hint.reasonCode === "challenge_detected") return 2;
|
|
@@ -836,10 +914,16 @@ var summarizePrimaryProviderIssue = (failures) => {
|
|
|
836
914
|
});
|
|
837
915
|
if (!hint) continue;
|
|
838
916
|
const summary = summarizeProviderIssue({ provider: failure.provider, hint });
|
|
917
|
+
const guidance = buildProviderIssueGuidance({
|
|
918
|
+
provider: failure.provider,
|
|
919
|
+
hint,
|
|
920
|
+
details: failure.error?.details
|
|
921
|
+
});
|
|
839
922
|
const candidate = {
|
|
840
923
|
provider: failure.provider,
|
|
841
924
|
summary,
|
|
842
|
-
...hint
|
|
925
|
+
...hint,
|
|
926
|
+
...guidance ? { guidance } : {}
|
|
843
927
|
};
|
|
844
928
|
if (!best || summaryPriority(candidate) > summaryPriority(best)) {
|
|
845
929
|
best = candidate;
|
|
@@ -1983,6 +2067,138 @@ var verifyChallengeProgress = async (args) => {
|
|
|
1983
2067
|
};
|
|
1984
2068
|
};
|
|
1985
2069
|
|
|
2070
|
+
// src/challenges/capability-matrix.ts
|
|
2071
|
+
var buildCapabilityMatrix = (bundle, interpretation, gate) => {
|
|
2072
|
+
const hasActionables = bundle.actionables.length > 0;
|
|
2073
|
+
const helperActionRefs = [
|
|
2074
|
+
...bundle.continuity.loginRefs,
|
|
2075
|
+
...bundle.continuity.sessionReuseRefs,
|
|
2076
|
+
...bundle.continuity.humanVerificationRefs,
|
|
2077
|
+
...bundle.continuity.checkpointRefs,
|
|
2078
|
+
...bundle.interaction?.clickRefs ?? [],
|
|
2079
|
+
...bundle.interaction?.holdRefs ?? [],
|
|
2080
|
+
...bundle.interaction?.dragRefs ?? []
|
|
2081
|
+
];
|
|
2082
|
+
const authLaneRelevant = interpretation.classification === "auth_required" || interpretation.classification === "existing_session_reuse" || bundle.continuity.likelyLoginPage || bundle.continuity.likelySessionPicker;
|
|
2083
|
+
const canNavigateToAuth = gate.allowedActions.includes("auth_navigation") && authLaneRelevant && (bundle.continuity.loginRefs.length > 0 || typeof bundle.url === "string");
|
|
2084
|
+
const canReuseExistingSession = gate.allowedActions.includes("session_reuse") && (bundle.continuity.hasPreservedSession || bundle.continuity.attachedSession || bundle.continuity.sessionReuseRefs.length > 0);
|
|
2085
|
+
const canReuseCookies = gate.allowedActions.includes("cookie_reuse") && authLaneRelevant && (bundle.continuity.canReuseExistingCookies || bundle.continuity.canImportCookies);
|
|
2086
|
+
const canFillNonSecretFields = gate.allowedActions.includes("non_secret_form_fill") && bundle.continuity.hasNonSecretTaskData && bundle.continuity.nonSecretFieldRefs.length > 0;
|
|
2087
|
+
const canExploreClicks = gate.allowedActions.includes("click_path") && (hasActionables || bundle.continuity.loginRefs.length > 0 || bundle.continuity.sessionReuseRefs.length > 0 || bundle.continuity.checkpointRefs.length > 0);
|
|
2088
|
+
const mustYield = interpretation.humanBoundary === "secret_entry" || interpretation.humanBoundary === "mfa" || interpretation.humanBoundary === "explicit_consent" || interpretation.humanBoundary === "exhausted_no_progress";
|
|
2089
|
+
const mustDefer = interpretation.humanBoundary === "policy_blocked" || !bundle.blocker && bundle.blockerState === "clear";
|
|
2090
|
+
let helperEligibility = gate.helperEligibility ?? (gate.optionalComputerUseBridge ? {
|
|
2091
|
+
allowed: true,
|
|
2092
|
+
reason: "Optional helper bridge remains eligible after policy resolution."
|
|
2093
|
+
} : {
|
|
2094
|
+
allowed: false,
|
|
2095
|
+
reason: "Optional computer-use bridge is disabled by policy.",
|
|
2096
|
+
standDownReason: "helper_disabled_by_policy"
|
|
2097
|
+
});
|
|
2098
|
+
if (helperEligibility.allowed && interpretation.humanBoundary !== "none") {
|
|
2099
|
+
helperEligibility = {
|
|
2100
|
+
allowed: false,
|
|
2101
|
+
reason: `Helper bridge is blocked by human boundary: ${interpretation.humanBoundary}.`,
|
|
2102
|
+
standDownReason: "helper_blocked_by_human_boundary"
|
|
2103
|
+
};
|
|
2104
|
+
} else if (helperEligibility.allowed && helperActionRefs.length === 0) {
|
|
2105
|
+
helperEligibility = {
|
|
2106
|
+
allowed: false,
|
|
2107
|
+
reason: "Canonical evidence did not expose any safe browser-scoped helper actions.",
|
|
2108
|
+
standDownReason: "helper_no_safe_actions"
|
|
2109
|
+
};
|
|
2110
|
+
}
|
|
2111
|
+
return {
|
|
2112
|
+
canNavigateToAuth,
|
|
2113
|
+
canReuseExistingSession,
|
|
2114
|
+
canReuseCookies,
|
|
2115
|
+
canFillNonSecretFields,
|
|
2116
|
+
canExploreClicks,
|
|
2117
|
+
canUseOwnedEnvironmentFixture: interpretation.classification === "owned_environment_test_challenge" && gate.governedLanes.includes("owned_environment_fixture"),
|
|
2118
|
+
canUseSanctionedIdentity: gate.governedLanes.includes("sanctioned_identity"),
|
|
2119
|
+
canUseServiceAdapter: gate.governedLanes.includes("service_adapter"),
|
|
2120
|
+
canUseComputerUseBridge: helperEligibility.allowed,
|
|
2121
|
+
helperEligibility,
|
|
2122
|
+
mustYield,
|
|
2123
|
+
mustDefer
|
|
2124
|
+
};
|
|
2125
|
+
};
|
|
2126
|
+
|
|
2127
|
+
// src/challenges/capture.ts
|
|
2128
|
+
async function captureChallengeEvidence(args) {
|
|
2129
|
+
const status = await args.handle.status(args.sessionId);
|
|
2130
|
+
const effectiveTargetId = args.targetId ?? status.activeTargetId ?? null;
|
|
2131
|
+
const snapshot = await args.handle.snapshot(
|
|
2132
|
+
args.sessionId,
|
|
2133
|
+
"actionables",
|
|
2134
|
+
2400,
|
|
2135
|
+
void 0,
|
|
2136
|
+
effectiveTargetId
|
|
2137
|
+
);
|
|
2138
|
+
const debugTrace = await args.handle.debugTraceSnapshot(args.sessionId, { max: 50 });
|
|
2139
|
+
const cookies = status.url ? await args.handle.cookieList(args.sessionId, [status.url]) : { count: 0 };
|
|
2140
|
+
return buildChallengeEvidenceBundle({
|
|
2141
|
+
status,
|
|
2142
|
+
snapshot: {
|
|
2143
|
+
snapshotId: snapshot.snapshotId,
|
|
2144
|
+
content: snapshot.content,
|
|
2145
|
+
warnings: snapshot.warnings
|
|
2146
|
+
},
|
|
2147
|
+
debugTrace,
|
|
2148
|
+
cookieCount: cookies.count,
|
|
2149
|
+
canImportCookies: args.canImportCookies,
|
|
2150
|
+
fallbackDisposition: args.fallbackDisposition,
|
|
2151
|
+
registryPressure: args.registryPressure,
|
|
2152
|
+
taskData: args.taskData
|
|
2153
|
+
});
|
|
2154
|
+
}
|
|
2155
|
+
|
|
2156
|
+
// src/challenges/human-yield-gate.ts
|
|
2157
|
+
var shouldYieldToHuman = (args) => {
|
|
2158
|
+
if (args.noProgressExhausted) {
|
|
2159
|
+
return {
|
|
2160
|
+
yield: true,
|
|
2161
|
+
reason: "exhausted_no_progress"
|
|
2162
|
+
};
|
|
2163
|
+
}
|
|
2164
|
+
return {
|
|
2165
|
+
yield: args.interpretation.humanBoundary !== "none",
|
|
2166
|
+
reason: args.interpretation.humanBoundary
|
|
2167
|
+
};
|
|
2168
|
+
};
|
|
2169
|
+
var buildHumanYieldPacket = (args) => {
|
|
2170
|
+
const challengeId = args.bundle.challengeId ?? `challenge-${Date.now()}`;
|
|
2171
|
+
const targetHints = [
|
|
2172
|
+
...args.bundle.continuity.loginRefs,
|
|
2173
|
+
...args.bundle.continuity.sessionReuseRefs,
|
|
2174
|
+
...args.bundle.continuity.humanVerificationRefs,
|
|
2175
|
+
...args.bundle.continuity.checkpointRefs
|
|
2176
|
+
];
|
|
2177
|
+
return {
|
|
2178
|
+
challengeId,
|
|
2179
|
+
classification: args.interpretation.classification,
|
|
2180
|
+
reason: args.reason,
|
|
2181
|
+
sessionId: args.sessionId,
|
|
2182
|
+
targetId: args.targetId ?? args.bundle.activeTargetId,
|
|
2183
|
+
ownerSurface: args.bundle.challenge?.ownerSurface ?? args.bundle.ownerSurface,
|
|
2184
|
+
url: args.bundle.url,
|
|
2185
|
+
title: args.bundle.title,
|
|
2186
|
+
requiredHumanStep: args.reason === "mfa" ? "Complete MFA or passkey verification, then continue." : args.reason === "secret_entry" ? "Enter the required secret-bearing credentials, then continue." : args.reason === "unsupported_third_party" ? "Complete the unsupported third-party challenge manually, then continue." : "Review the page state and continue when ready.",
|
|
2187
|
+
targetHints,
|
|
2188
|
+
expectedPostAuthCheckpoint: args.interpretation.likelyCheckpoint,
|
|
2189
|
+
preserveUntil: args.bundle.challenge?.preserveUntil,
|
|
2190
|
+
verifyUntil: args.bundle.challenge?.verifyUntil,
|
|
2191
|
+
traceRequestId: args.bundle.diagnostics.traceRequestId,
|
|
2192
|
+
...args.verification ? {
|
|
2193
|
+
lastVerificationStatus: args.verification.status,
|
|
2194
|
+
lastVerificationReason: args.verification.reason
|
|
2195
|
+
} : {},
|
|
2196
|
+
evidenceSummary: args.interpretation.summary,
|
|
2197
|
+
reclaimHint: "Resume the preserved session and re-run verification after the human step completes.",
|
|
2198
|
+
resumeRule: "Re-run manager-owned verification after the human step completes before resuming automation."
|
|
2199
|
+
};
|
|
2200
|
+
};
|
|
2201
|
+
|
|
1986
2202
|
// src/challenges/optional-computer-use-bridge.ts
|
|
1987
2203
|
var OPTIONAL_BRIDGE_SUGGESTION_REASON = "Optional bridge suggested a browser-scoped click follow-up from canonical evidence.";
|
|
1988
2204
|
var buildComputerUseSuggestions = (bundle, maxSuggestions) => {
|
|
@@ -2027,907 +2243,955 @@ var suggestComputerUseActions = (args) => {
|
|
|
2027
2243
|
};
|
|
2028
2244
|
};
|
|
2029
2245
|
|
|
2030
|
-
// src/challenges/
|
|
2031
|
-
var
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2246
|
+
// src/challenges/policy-gate.ts
|
|
2247
|
+
var ALL_ACTIONS = [
|
|
2248
|
+
"wait",
|
|
2249
|
+
"auth_navigation",
|
|
2250
|
+
"session_reuse",
|
|
2251
|
+
"cookie_reuse",
|
|
2252
|
+
"element_discovery",
|
|
2253
|
+
"click_path",
|
|
2254
|
+
"click_and_hold",
|
|
2255
|
+
"non_secret_form_fill",
|
|
2256
|
+
"dropdown",
|
|
2257
|
+
"scroll",
|
|
2258
|
+
"hover",
|
|
2259
|
+
"press",
|
|
2260
|
+
"pointer",
|
|
2261
|
+
"drag",
|
|
2262
|
+
"verification",
|
|
2263
|
+
"debug_trace"
|
|
2264
|
+
];
|
|
2265
|
+
var DEFAULT_HANDOFF_TRIGGERS = [
|
|
2266
|
+
"secret_entry",
|
|
2267
|
+
"mfa",
|
|
2268
|
+
"explicit_consent",
|
|
2269
|
+
"policy_blocked",
|
|
2270
|
+
"unsupported_third_party",
|
|
2271
|
+
"exhausted_no_progress"
|
|
2272
|
+
];
|
|
2273
|
+
var buildResolvedPolicy = (mode, source) => {
|
|
2274
|
+
if (mode === "off") {
|
|
2275
|
+
return {
|
|
2276
|
+
mode,
|
|
2277
|
+
source,
|
|
2278
|
+
standDownReason: "challenge_automation_off"
|
|
2279
|
+
};
|
|
2047
2280
|
}
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
for (const [key, value] of entries) {
|
|
2055
|
-
if (SENSITIVE_FIELD_RE.test(key) || SENSITIVE_FIELD_RE.test(name)) {
|
|
2056
|
-
continue;
|
|
2057
|
-
}
|
|
2058
|
-
if (!name.includes(key.toLowerCase())) {
|
|
2059
|
-
continue;
|
|
2060
|
-
}
|
|
2061
|
-
switch (typeof value) {
|
|
2062
|
-
case "string":
|
|
2063
|
-
case "number":
|
|
2064
|
-
case "boolean":
|
|
2065
|
-
return String(value);
|
|
2066
|
-
default:
|
|
2067
|
-
break;
|
|
2068
|
-
}
|
|
2281
|
+
if (mode === "browser") {
|
|
2282
|
+
return {
|
|
2283
|
+
mode,
|
|
2284
|
+
source,
|
|
2285
|
+
standDownReason: "helper_disabled_for_browser_mode"
|
|
2286
|
+
};
|
|
2069
2287
|
}
|
|
2070
|
-
return
|
|
2071
|
-
};
|
|
2072
|
-
var nextUnusedRef = (refs, steps, kind) => {
|
|
2073
|
-
return refs.find((ref) => !hasExecuted(steps, kind, ref));
|
|
2288
|
+
return { mode, source };
|
|
2074
2289
|
};
|
|
2075
|
-
var
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
return void 0;
|
|
2079
|
-
}
|
|
2080
|
-
if (interaction.preferredAction === "click" && decision.allowedActionFamilies.includes("click_path")) {
|
|
2081
|
-
const clickRef = nextUnusedRef(interaction.clickRefs, executedSteps, "click");
|
|
2082
|
-
if (clickRef) {
|
|
2083
|
-
return {
|
|
2084
|
-
kind: "click",
|
|
2085
|
-
ref: clickRef,
|
|
2086
|
-
reason: "Visible popup or interstitial exposes a bounded click path."
|
|
2087
|
-
};
|
|
2088
|
-
}
|
|
2290
|
+
var resolveChallengeAutomationPolicy = (args) => {
|
|
2291
|
+
if (args.runMode) {
|
|
2292
|
+
return buildResolvedPolicy(args.runMode, "run");
|
|
2089
2293
|
}
|
|
2090
|
-
if (
|
|
2091
|
-
|
|
2092
|
-
if (holdRef || !hasExecuted(executedSteps, "click_and_hold")) {
|
|
2093
|
-
return {
|
|
2094
|
-
kind: "click_and_hold",
|
|
2095
|
-
...holdRef ? { ref: holdRef } : {},
|
|
2096
|
-
...typeof interaction.holdMs === "number" ? { holdMs: interaction.holdMs } : {},
|
|
2097
|
-
reason: "Visible challenge requests a bounded click-and-hold gesture."
|
|
2098
|
-
};
|
|
2099
|
-
}
|
|
2294
|
+
if (args.sessionMode) {
|
|
2295
|
+
return buildResolvedPolicy(args.sessionMode, "session");
|
|
2100
2296
|
}
|
|
2101
|
-
|
|
2102
|
-
return {
|
|
2103
|
-
kind: "drag",
|
|
2104
|
-
...interaction.dragRefs[0] ? { ref: interaction.dragRefs[0] } : {},
|
|
2105
|
-
coordinates: { x: 640, y: 360 },
|
|
2106
|
-
reason: "Visible challenge requests a bounded drag gesture."
|
|
2107
|
-
};
|
|
2108
|
-
}
|
|
2109
|
-
return void 0;
|
|
2297
|
+
return buildResolvedPolicy(args.configMode, "config");
|
|
2110
2298
|
};
|
|
2111
|
-
var
|
|
2112
|
-
|
|
2113
|
-
if (sessionRef) {
|
|
2299
|
+
var resolveHelperEligibility = (config, policy) => {
|
|
2300
|
+
if (policy.mode === "off") {
|
|
2114
2301
|
return {
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2302
|
+
allowed: false,
|
|
2303
|
+
reason: "Challenge automation mode is off; detection and reporting remain active.",
|
|
2304
|
+
standDownReason: "challenge_automation_off"
|
|
2118
2305
|
};
|
|
2119
2306
|
}
|
|
2120
|
-
|
|
2121
|
-
if (decision.allowedActionFamilies.includes("auth_navigation") && loginRef) {
|
|
2307
|
+
if (policy.mode === "browser") {
|
|
2122
2308
|
return {
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2309
|
+
allowed: false,
|
|
2310
|
+
reason: "Browser mode keeps the optional helper bridge disabled.",
|
|
2311
|
+
standDownReason: "helper_disabled_for_browser_mode"
|
|
2126
2312
|
};
|
|
2127
2313
|
}
|
|
2128
|
-
if (
|
|
2129
|
-
const loginUrl = deriveAuthUrls(bundle.url).find((candidate) => !hasExecuted(executedSteps, "goto", void 0, candidate));
|
|
2130
|
-
if (loginUrl) {
|
|
2131
|
-
return {
|
|
2132
|
-
kind: "goto",
|
|
2133
|
-
url: loginUrl,
|
|
2134
|
-
reason: "Try a conventional auth-navigation URL on the current origin."
|
|
2135
|
-
};
|
|
2136
|
-
}
|
|
2137
|
-
}
|
|
2138
|
-
const fieldRef = nextUnusedRef(bundle.continuity.nonSecretFieldRefs, executedSteps, "type");
|
|
2139
|
-
const fieldValue = fieldRef ? resolveTaskValue(bundle, fieldRef) : void 0;
|
|
2140
|
-
if (decision.allowedActionFamilies.includes("non_secret_form_fill") && fieldRef && fieldValue) {
|
|
2314
|
+
if (!config.optionalComputerUseBridge.enabled) {
|
|
2141
2315
|
return {
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
reason: "Fill a non-secret field from caller-provided task data."
|
|
2316
|
+
allowed: false,
|
|
2317
|
+
reason: "Optional computer-use bridge is disabled by policy.",
|
|
2318
|
+
standDownReason: "helper_disabled_by_policy"
|
|
2146
2319
|
};
|
|
2147
2320
|
}
|
|
2148
|
-
|
|
2149
|
-
|
|
2321
|
+
return {
|
|
2322
|
+
allowed: true,
|
|
2323
|
+
reason: "Optional helper bridge remains eligible after mode resolution."
|
|
2324
|
+
};
|
|
2325
|
+
};
|
|
2326
|
+
var buildChallengePolicyGate = (config, interpretation, resolvedPolicy = resolveChallengeAutomationPolicy({
|
|
2327
|
+
configMode: config.mode
|
|
2328
|
+
})) => {
|
|
2329
|
+
const helperEligibility = resolveHelperEligibility(config, resolvedPolicy);
|
|
2330
|
+
if (resolvedPolicy.mode === "off") {
|
|
2150
2331
|
return {
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2332
|
+
resolvedPolicy,
|
|
2333
|
+
allowedActions: [],
|
|
2334
|
+
forbiddenActions: [...ALL_ACTIONS],
|
|
2335
|
+
handoffTriggers: [...DEFAULT_HANDOFF_TRIGGERS],
|
|
2336
|
+
governedLanes: [],
|
|
2337
|
+
optionalComputerUseBridge: false,
|
|
2338
|
+
helperEligibility
|
|
2154
2339
|
};
|
|
2155
2340
|
}
|
|
2156
|
-
const
|
|
2157
|
-
if (
|
|
2158
|
-
|
|
2159
|
-
kind: "hover",
|
|
2160
|
-
ref: hoverRef,
|
|
2161
|
-
reason: "Hover a likely action target to reveal hidden menus or session pickers."
|
|
2162
|
-
};
|
|
2341
|
+
const allowed = /* @__PURE__ */ new Set(["wait", "verification", "debug_trace"]);
|
|
2342
|
+
if (config.allowAuthNavigation) {
|
|
2343
|
+
allowed.add("auth_navigation");
|
|
2163
2344
|
}
|
|
2164
|
-
if (
|
|
2165
|
-
|
|
2166
|
-
kind: "scroll",
|
|
2167
|
-
dy: 900,
|
|
2168
|
-
reason: "Scroll down to uncover the next actionable region."
|
|
2169
|
-
};
|
|
2345
|
+
if (config.allowSessionReuse) {
|
|
2346
|
+
allowed.add("session_reuse");
|
|
2170
2347
|
}
|
|
2171
|
-
if (
|
|
2172
|
-
|
|
2173
|
-
kind: "scroll",
|
|
2174
|
-
dy: -450,
|
|
2175
|
-
reason: "Scroll back up to re-evaluate the visible challenge state."
|
|
2176
|
-
};
|
|
2348
|
+
if (config.allowCookieReuse) {
|
|
2349
|
+
allowed.add("cookie_reuse");
|
|
2177
2350
|
}
|
|
2178
|
-
if (
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
text: "Tab",
|
|
2182
|
-
reason: "Advance focus through the challenge surface."
|
|
2183
|
-
};
|
|
2351
|
+
if (config.allowNonSecretFormFill) {
|
|
2352
|
+
allowed.add("non_secret_form_fill");
|
|
2353
|
+
allowed.add("dropdown");
|
|
2184
2354
|
}
|
|
2185
|
-
if (
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2355
|
+
if (config.allowInteractionExploration) {
|
|
2356
|
+
allowed.add("element_discovery");
|
|
2357
|
+
allowed.add("click_path");
|
|
2358
|
+
allowed.add("click_and_hold");
|
|
2359
|
+
allowed.add("scroll");
|
|
2360
|
+
allowed.add("hover");
|
|
2361
|
+
allowed.add("press");
|
|
2362
|
+
allowed.add("pointer");
|
|
2363
|
+
allowed.add("drag");
|
|
2191
2364
|
}
|
|
2192
|
-
if (
|
|
2193
|
-
|
|
2194
|
-
kind: "drag",
|
|
2195
|
-
coordinates: { x: 640, y: 360 },
|
|
2196
|
-
reason: "Attempt one bounded vertical drag across the visible surface."
|
|
2197
|
-
};
|
|
2365
|
+
if (interpretation.humanBoundary === "secret_entry" || interpretation.humanBoundary === "mfa") {
|
|
2366
|
+
allowed.delete("non_secret_form_fill");
|
|
2198
2367
|
}
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
reason: "Give the page a short bounded settle window before yielding."
|
|
2203
|
-
};
|
|
2368
|
+
const governedLanes = [];
|
|
2369
|
+
if (config.governed.allowOwnedEnvironmentFixtures) {
|
|
2370
|
+
governedLanes.push("owned_environment_fixture");
|
|
2204
2371
|
}
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
var resolveStepPoint = async (args) => {
|
|
2208
|
-
if (!args.step.ref) {
|
|
2209
|
-
return args.step.coordinates ?? args.fallback;
|
|
2372
|
+
if (config.governed.allowSanctionedIdentity) {
|
|
2373
|
+
governedLanes.push("sanctioned_identity");
|
|
2210
2374
|
}
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
var executeStep = async (args) => {
|
|
2214
|
-
const timeoutMs = args.config.stepTimeoutMs;
|
|
2215
|
-
switch (args.step.kind) {
|
|
2216
|
-
case "goto":
|
|
2217
|
-
if (args.step.url) {
|
|
2218
|
-
await args.handle.goto(args.sessionId, args.step.url, "domcontentloaded", timeoutMs, void 0, args.targetId);
|
|
2219
|
-
}
|
|
2220
|
-
return;
|
|
2221
|
-
case "click":
|
|
2222
|
-
if (args.step.ref) {
|
|
2223
|
-
await args.handle.click(args.sessionId, args.step.ref, args.targetId);
|
|
2224
|
-
}
|
|
2225
|
-
return;
|
|
2226
|
-
case "click_and_hold": {
|
|
2227
|
-
const point = await resolveStepPoint({
|
|
2228
|
-
handle: args.handle,
|
|
2229
|
-
sessionId: args.sessionId,
|
|
2230
|
-
step: args.step,
|
|
2231
|
-
targetId: args.targetId,
|
|
2232
|
-
fallback: { x: 640, y: 360 }
|
|
2233
|
-
});
|
|
2234
|
-
await args.handle.pointerMove(args.sessionId, point.x, point.y, args.targetId, 12);
|
|
2235
|
-
await args.handle.pointerDown(args.sessionId, point.x, point.y, args.targetId, "left", 1);
|
|
2236
|
-
await new Promise((resolve2) => setTimeout(resolve2, Math.max(250, args.step.holdMs ?? DEFAULT_HOLD_MS2)));
|
|
2237
|
-
await args.handle.pointerUp(args.sessionId, point.x, point.y, args.targetId, "left", 1);
|
|
2238
|
-
return;
|
|
2239
|
-
}
|
|
2240
|
-
case "hover":
|
|
2241
|
-
if (args.step.ref) {
|
|
2242
|
-
await args.handle.hover(args.sessionId, args.step.ref, args.targetId);
|
|
2243
|
-
}
|
|
2244
|
-
return;
|
|
2245
|
-
case "press":
|
|
2246
|
-
await args.handle.press(args.sessionId, args.step.text ?? "Tab", void 0, args.targetId);
|
|
2247
|
-
return;
|
|
2248
|
-
case "type":
|
|
2249
|
-
if (args.step.ref && typeof args.step.text === "string") {
|
|
2250
|
-
await args.handle.type(args.sessionId, args.step.ref, args.step.text, true, false, args.targetId);
|
|
2251
|
-
}
|
|
2252
|
-
return;
|
|
2253
|
-
case "select":
|
|
2254
|
-
if (args.step.ref && args.step.values?.length) {
|
|
2255
|
-
await args.handle.select(args.sessionId, args.step.ref, args.step.values, args.targetId);
|
|
2256
|
-
}
|
|
2257
|
-
return;
|
|
2258
|
-
case "scroll":
|
|
2259
|
-
await args.handle.scroll(args.sessionId, args.step.dy ?? 600, void 0, args.targetId);
|
|
2260
|
-
return;
|
|
2261
|
-
case "pointer":
|
|
2262
|
-
await args.handle.pointerMove(
|
|
2263
|
-
args.sessionId,
|
|
2264
|
-
args.step.coordinates?.x ?? 640,
|
|
2265
|
-
args.step.coordinates?.y ?? 360,
|
|
2266
|
-
args.targetId,
|
|
2267
|
-
12
|
|
2268
|
-
);
|
|
2269
|
-
return;
|
|
2270
|
-
case "drag":
|
|
2271
|
-
{
|
|
2272
|
-
const point = await resolveStepPoint({
|
|
2273
|
-
handle: args.handle,
|
|
2274
|
-
sessionId: args.sessionId,
|
|
2275
|
-
step: args.step,
|
|
2276
|
-
targetId: args.targetId,
|
|
2277
|
-
fallback: args.step.coordinates ?? { x: 640, y: 360 }
|
|
2278
|
-
});
|
|
2279
|
-
await args.handle.drag(
|
|
2280
|
-
args.sessionId,
|
|
2281
|
-
point,
|
|
2282
|
-
{
|
|
2283
|
-
x: point.x,
|
|
2284
|
-
y: point.y + 260
|
|
2285
|
-
},
|
|
2286
|
-
args.targetId,
|
|
2287
|
-
16
|
|
2288
|
-
);
|
|
2289
|
-
}
|
|
2290
|
-
return;
|
|
2291
|
-
case "cookie_list":
|
|
2292
|
-
await args.handle.cookieList(args.sessionId, args.step.url ? [args.step.url] : void 0);
|
|
2293
|
-
return;
|
|
2294
|
-
case "cookie_import":
|
|
2295
|
-
await args.handle.cookieImport(args.sessionId, args.step.cookies ?? [], true);
|
|
2296
|
-
return;
|
|
2297
|
-
case "snapshot":
|
|
2298
|
-
await args.handle.snapshot(
|
|
2299
|
-
args.sessionId,
|
|
2300
|
-
"actionables",
|
|
2301
|
-
args.step.snapshotChars ?? 2400,
|
|
2302
|
-
void 0,
|
|
2303
|
-
args.targetId
|
|
2304
|
-
);
|
|
2305
|
-
return;
|
|
2306
|
-
case "debug_trace":
|
|
2307
|
-
await args.handle.debugTraceSnapshot(args.sessionId, { max: args.step.traceMax ?? 50 });
|
|
2308
|
-
return;
|
|
2309
|
-
case "wait":
|
|
2310
|
-
await args.handle.waitForLoad(args.sessionId, "networkidle", Math.min(timeoutMs, 3e3), args.targetId);
|
|
2311
|
-
return;
|
|
2312
|
-
default:
|
|
2313
|
-
return;
|
|
2375
|
+
if (config.governed.allowServiceAdapters) {
|
|
2376
|
+
governedLanes.push("service_adapter");
|
|
2314
2377
|
}
|
|
2378
|
+
return {
|
|
2379
|
+
resolvedPolicy,
|
|
2380
|
+
allowedActions: ALL_ACTIONS.filter((action) => allowed.has(action)),
|
|
2381
|
+
forbiddenActions: ALL_ACTIONS.filter((action) => !allowed.has(action)),
|
|
2382
|
+
handoffTriggers: [...DEFAULT_HANDOFF_TRIGGERS],
|
|
2383
|
+
governedLanes,
|
|
2384
|
+
optionalComputerUseBridge: helperEligibility.allowed,
|
|
2385
|
+
helperEligibility
|
|
2386
|
+
};
|
|
2315
2387
|
};
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2388
|
+
|
|
2389
|
+
// src/challenges/strategy-selector.ts
|
|
2390
|
+
var buildDecision = (config, lane, rationale, allowedActionFamilies, verificationLevel, stopConditions, governedLane) => ({
|
|
2391
|
+
lane,
|
|
2392
|
+
...governedLane ? { governedLane } : {},
|
|
2393
|
+
rationale,
|
|
2394
|
+
attemptBudget: config.attemptBudget,
|
|
2395
|
+
noProgressLimit: config.noProgressLimit,
|
|
2396
|
+
verificationLevel,
|
|
2397
|
+
stopConditions,
|
|
2398
|
+
allowedActionFamilies: [...allowedActionFamilies]
|
|
2399
|
+
});
|
|
2400
|
+
var selectChallengeStrategy = (args) => {
|
|
2401
|
+
const { config, bundle, capabilityMatrix, gate, interpretation } = args;
|
|
2402
|
+
const registryCooldownActive = (bundle.registryPressure?.cooldownUntilMs ?? 0) > Date.now();
|
|
2403
|
+
const registryPressureElevated = (bundle.registryPressure?.activeChallenges ?? 0) > 0 || (bundle.registryPressure?.recentChallengeRatio ?? 0) >= 0.5 || (bundle.registryPressure?.recentRateLimitRatio ?? 0) >= 0.5;
|
|
2404
|
+
const stopConditions = [
|
|
2405
|
+
"manager_verification_clears_blocker",
|
|
2406
|
+
"policy_gate_denies_next_action",
|
|
2407
|
+
"human_boundary_detected",
|
|
2408
|
+
"no_progress_budget_exhausted"
|
|
2409
|
+
];
|
|
2410
|
+
const { mode, standDownReason } = gate.resolvedPolicy;
|
|
2411
|
+
if (mode === "off") {
|
|
2412
|
+
return buildDecision(
|
|
2413
|
+
config,
|
|
2414
|
+
"defer",
|
|
2415
|
+
"Challenge automation mode is off; challenge handling is detect-and-report only.",
|
|
2416
|
+
[],
|
|
2417
|
+
"light",
|
|
2418
|
+
[standDownReason ?? "challenge_automation_off"]
|
|
2419
|
+
);
|
|
2420
|
+
}
|
|
2421
|
+
if (capabilityMatrix.mustDefer) {
|
|
2422
|
+
return buildDecision(
|
|
2423
|
+
config,
|
|
2424
|
+
"defer",
|
|
2425
|
+
"Current policy or blocker state requires deferral before further automation.",
|
|
2426
|
+
gate.allowedActions,
|
|
2427
|
+
interpretation.requiredVerification,
|
|
2428
|
+
["policy_blocked_or_clear_state"]
|
|
2429
|
+
);
|
|
2430
|
+
}
|
|
2431
|
+
if (registryCooldownActive && !capabilityMatrix.canReuseExistingSession && !capabilityMatrix.canReuseCookies && !capabilityMatrix.canNavigateToAuth) {
|
|
2432
|
+
return buildDecision(
|
|
2433
|
+
config,
|
|
2434
|
+
"defer",
|
|
2435
|
+
"Registry cooldown is still active and no legitimate continuity or auth-navigation lane is currently available.",
|
|
2436
|
+
gate.allowedActions,
|
|
2437
|
+
interpretation.requiredVerification,
|
|
2438
|
+
["registry_cooldown_active"]
|
|
2439
|
+
);
|
|
2440
|
+
}
|
|
2441
|
+
if (capabilityMatrix.canUseOwnedEnvironmentFixture) {
|
|
2442
|
+
return buildDecision(
|
|
2443
|
+
config,
|
|
2444
|
+
"owned_environment_fixture",
|
|
2445
|
+
"Owned-environment fixture detected and explicitly allowlisted.",
|
|
2446
|
+
gate.allowedActions,
|
|
2447
|
+
interpretation.requiredVerification,
|
|
2448
|
+
stopConditions,
|
|
2449
|
+
"owned_environment_fixture"
|
|
2450
|
+
);
|
|
2451
|
+
}
|
|
2452
|
+
if (capabilityMatrix.mustYield) {
|
|
2453
|
+
return buildDecision(
|
|
2454
|
+
config,
|
|
2455
|
+
"human_yield",
|
|
2456
|
+
`Human authority boundary reached: ${interpretation.humanBoundary}.`,
|
|
2457
|
+
gate.allowedActions,
|
|
2458
|
+
interpretation.requiredVerification,
|
|
2459
|
+
[...stopConditions, "human_authority_required"]
|
|
2460
|
+
);
|
|
2461
|
+
}
|
|
2462
|
+
if (capabilityMatrix.canNavigateToAuth || capabilityMatrix.canReuseExistingSession || capabilityMatrix.canReuseCookies || capabilityMatrix.canFillNonSecretFields || capabilityMatrix.canExploreClicks) {
|
|
2463
|
+
return buildDecision(
|
|
2464
|
+
config,
|
|
2465
|
+
"generic_browser_autonomy",
|
|
2466
|
+
registryPressureElevated ? "Registry pressure is elevated, but legitimate browser continuity remains available for one bounded generic autonomy pass." : "Existing browser controls can attempt bounded auth navigation, session reuse, non-secret fill, or interaction exploration.",
|
|
2467
|
+
gate.allowedActions,
|
|
2468
|
+
interpretation.requiredVerification,
|
|
2469
|
+
registryPressureElevated ? [...stopConditions, "registry_pressure_elevated"] : stopConditions
|
|
2470
|
+
);
|
|
2471
|
+
}
|
|
2472
|
+
if (capabilityMatrix.canUseComputerUseBridge) {
|
|
2473
|
+
return buildDecision(
|
|
2474
|
+
config,
|
|
2475
|
+
"optional_computer_use_bridge",
|
|
2476
|
+
"DOM-native autonomy is exhausted, but the optional browser-scoped bridge is enabled.",
|
|
2477
|
+
gate.allowedActions,
|
|
2478
|
+
interpretation.requiredVerification,
|
|
2479
|
+
stopConditions
|
|
2480
|
+
);
|
|
2481
|
+
}
|
|
2482
|
+
if (capabilityMatrix.canUseSanctionedIdentity) {
|
|
2483
|
+
return buildDecision(
|
|
2484
|
+
config,
|
|
2485
|
+
"sanctioned_identity",
|
|
2486
|
+
"Sanctioned identity lane is enabled and generic browser autonomy is insufficient.",
|
|
2487
|
+
gate.allowedActions,
|
|
2488
|
+
interpretation.requiredVerification,
|
|
2489
|
+
stopConditions,
|
|
2490
|
+
"sanctioned_identity"
|
|
2491
|
+
);
|
|
2492
|
+
}
|
|
2493
|
+
if (capabilityMatrix.canUseServiceAdapter) {
|
|
2494
|
+
return buildDecision(
|
|
2495
|
+
config,
|
|
2496
|
+
"service_adapter",
|
|
2497
|
+
"Governed service-adapter lane is enabled as the last non-human option.",
|
|
2498
|
+
gate.allowedActions,
|
|
2499
|
+
interpretation.requiredVerification,
|
|
2500
|
+
stopConditions,
|
|
2501
|
+
"service_adapter"
|
|
2502
|
+
);
|
|
2503
|
+
}
|
|
2504
|
+
return buildDecision(
|
|
2505
|
+
config,
|
|
2506
|
+
"human_yield",
|
|
2507
|
+
`No legitimate autonomous lane remains after applying policy and continuity checks. ${capabilityMatrix.helperEligibility.reason}`,
|
|
2508
|
+
gate.allowedActions,
|
|
2509
|
+
interpretation.requiredVerification,
|
|
2510
|
+
[...stopConditions, "no_legitimate_lane_remaining"]
|
|
2511
|
+
);
|
|
2512
|
+
};
|
|
2513
|
+
|
|
2514
|
+
// src/challenges/inspect-plan.ts
|
|
2515
|
+
var SENSITIVE_FIELD_RE = /\b(password|passcode|secret|otp|mfa|token|verification code|passkey)\b/i;
|
|
2516
|
+
var hasExecuted = (steps, kind, ref, url) => {
|
|
2517
|
+
return steps.some((step) => step.kind === kind && step.ref === ref && step.url === url);
|
|
2518
|
+
};
|
|
2519
|
+
var getActionable = (bundle, ref) => {
|
|
2520
|
+
return bundle.actionables.find((entry) => entry.ref === ref);
|
|
2521
|
+
};
|
|
2522
|
+
var deriveAuthUrls = (url) => {
|
|
2523
|
+
if (!url) {
|
|
2524
|
+
return [];
|
|
2525
|
+
}
|
|
2526
|
+
try {
|
|
2527
|
+
const current = new URL(url);
|
|
2528
|
+
const candidates = [
|
|
2529
|
+
"/login",
|
|
2530
|
+
"/signin",
|
|
2531
|
+
"/sign-in",
|
|
2532
|
+
"/account/login",
|
|
2533
|
+
"/session",
|
|
2534
|
+
"/auth/login"
|
|
2535
|
+
];
|
|
2536
|
+
return candidates.map((path2) => new URL(path2, current.origin).toString());
|
|
2537
|
+
} catch {
|
|
2538
|
+
return [];
|
|
2539
|
+
}
|
|
2540
|
+
};
|
|
2541
|
+
var resolveTaskValue = (bundle, ref) => {
|
|
2542
|
+
const actionable = getActionable(bundle, ref);
|
|
2543
|
+
const name = actionable?.name?.toLowerCase();
|
|
2544
|
+
if (!name || !bundle.taskData) {
|
|
2545
|
+
return void 0;
|
|
2546
|
+
}
|
|
2547
|
+
for (const [key, value] of Object.entries(bundle.taskData)) {
|
|
2548
|
+
if (SENSITIVE_FIELD_RE.test(key) || SENSITIVE_FIELD_RE.test(name)) {
|
|
2549
|
+
continue;
|
|
2361
2550
|
}
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
reusedExistingSession = true;
|
|
2551
|
+
if (!name.includes(key.toLowerCase())) {
|
|
2552
|
+
continue;
|
|
2365
2553
|
}
|
|
2366
|
-
if (
|
|
2367
|
-
|
|
2554
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
2555
|
+
return String(value);
|
|
2368
2556
|
}
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2557
|
+
}
|
|
2558
|
+
return void 0;
|
|
2559
|
+
};
|
|
2560
|
+
var nextUnusedRef = (refs, steps, kind) => {
|
|
2561
|
+
return refs.find((ref) => !hasExecuted(steps, kind, ref));
|
|
2562
|
+
};
|
|
2563
|
+
var planInteractionStep = (bundle, decision, executedSteps) => {
|
|
2564
|
+
const interaction = bundle.interaction;
|
|
2565
|
+
if (!interaction || interaction.preferredAction === "unknown") {
|
|
2566
|
+
return void 0;
|
|
2567
|
+
}
|
|
2568
|
+
if (interaction.preferredAction === "click" && decision.allowedActionFamilies.includes("click_path")) {
|
|
2569
|
+
const clickRef = nextUnusedRef(interaction.clickRefs, executedSteps, "click");
|
|
2570
|
+
if (clickRef) {
|
|
2382
2571
|
return {
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
executedSteps,
|
|
2387
|
-
verification,
|
|
2388
|
-
reusedExistingSession,
|
|
2389
|
-
reusedCookies
|
|
2572
|
+
kind: "click",
|
|
2573
|
+
ref: clickRef,
|
|
2574
|
+
reason: "Visible popup or interstitial exposes a bounded click path."
|
|
2390
2575
|
};
|
|
2391
2576
|
}
|
|
2392
|
-
|
|
2577
|
+
}
|
|
2578
|
+
if (interaction.preferredAction === "click_and_hold" && decision.allowedActionFamilies.includes("click_and_hold")) {
|
|
2579
|
+
const holdRef = nextUnusedRef(interaction.holdRefs, executedSteps, "click_and_hold");
|
|
2580
|
+
if (holdRef || !hasExecuted(executedSteps, "click_and_hold")) {
|
|
2393
2581
|
return {
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
verification,
|
|
2399
|
-
reusedExistingSession,
|
|
2400
|
-
reusedCookies
|
|
2582
|
+
kind: "click_and_hold",
|
|
2583
|
+
...holdRef ? { ref: holdRef } : {},
|
|
2584
|
+
...typeof interaction.holdMs === "number" ? { holdMs: interaction.holdMs } : {},
|
|
2585
|
+
reason: "Visible challenge requests a bounded click-and-hold gesture."
|
|
2401
2586
|
};
|
|
2402
2587
|
}
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2588
|
+
}
|
|
2589
|
+
if (interaction.preferredAction === "drag" && decision.allowedActionFamilies.includes("drag") && !hasExecuted(executedSteps, "drag")) {
|
|
2590
|
+
return {
|
|
2591
|
+
kind: "drag",
|
|
2592
|
+
...interaction.dragRefs[0] ? { ref: interaction.dragRefs[0] } : {},
|
|
2593
|
+
coordinates: { x: 640, y: 360 },
|
|
2594
|
+
reason: "Visible challenge requests a bounded drag gesture."
|
|
2595
|
+
};
|
|
2596
|
+
}
|
|
2597
|
+
return void 0;
|
|
2598
|
+
};
|
|
2599
|
+
var planGenericStep = (bundle, decision, executedSteps) => {
|
|
2600
|
+
const sessionRef = nextUnusedRef(
|
|
2601
|
+
bundle.continuity.sessionReuseRefs,
|
|
2602
|
+
executedSteps,
|
|
2603
|
+
"click"
|
|
2604
|
+
);
|
|
2605
|
+
if (sessionRef) {
|
|
2606
|
+
return {
|
|
2607
|
+
kind: "click",
|
|
2608
|
+
ref: sessionRef,
|
|
2609
|
+
reason: "Try the existing-session or account-selection path first."
|
|
2610
|
+
};
|
|
2611
|
+
}
|
|
2612
|
+
const loginRef = nextUnusedRef(bundle.continuity.loginRefs, executedSteps, "click");
|
|
2613
|
+
if (decision.allowedActionFamilies.includes("auth_navigation") && loginRef) {
|
|
2614
|
+
return {
|
|
2615
|
+
kind: "click",
|
|
2616
|
+
ref: loginRef,
|
|
2617
|
+
reason: "Try the visible auth-navigation entrypoint."
|
|
2618
|
+
};
|
|
2619
|
+
}
|
|
2620
|
+
if (decision.allowedActionFamilies.includes("auth_navigation")) {
|
|
2621
|
+
const loginUrl = deriveAuthUrls(bundle.url).find((candidate) => {
|
|
2622
|
+
return !hasExecuted(executedSteps, "goto", void 0, candidate);
|
|
2623
|
+
});
|
|
2624
|
+
if (loginUrl) {
|
|
2420
2625
|
return {
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
executedSteps,
|
|
2425
|
-
verification,
|
|
2426
|
-
reusedExistingSession,
|
|
2427
|
-
reusedCookies
|
|
2626
|
+
kind: "goto",
|
|
2627
|
+
url: loginUrl,
|
|
2628
|
+
reason: "Try a conventional auth-navigation URL on the current origin."
|
|
2428
2629
|
};
|
|
2429
2630
|
}
|
|
2430
2631
|
}
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
attempts: args.decision.attemptBudget,
|
|
2434
|
-
noProgressCount,
|
|
2632
|
+
const fieldRef = nextUnusedRef(
|
|
2633
|
+
bundle.continuity.nonSecretFieldRefs,
|
|
2435
2634
|
executedSteps,
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
title: currentBundle.title
|
|
2446
|
-
},
|
|
2447
|
-
reusedExistingSession,
|
|
2448
|
-
reusedCookies
|
|
2449
|
-
};
|
|
2450
|
-
};
|
|
2451
|
-
|
|
2452
|
-
// src/challenges/capability-matrix.ts
|
|
2453
|
-
var buildCapabilityMatrix = (bundle, interpretation, gate) => {
|
|
2454
|
-
const hasActionables = bundle.actionables.length > 0;
|
|
2455
|
-
const helperActionRefs = [
|
|
2456
|
-
...bundle.continuity.loginRefs,
|
|
2457
|
-
...bundle.continuity.sessionReuseRefs,
|
|
2458
|
-
...bundle.continuity.humanVerificationRefs,
|
|
2459
|
-
...bundle.continuity.checkpointRefs,
|
|
2460
|
-
...bundle.interaction?.clickRefs ?? [],
|
|
2461
|
-
...bundle.interaction?.holdRefs ?? [],
|
|
2462
|
-
...bundle.interaction?.dragRefs ?? []
|
|
2463
|
-
];
|
|
2464
|
-
const authLaneRelevant = interpretation.classification === "auth_required" || interpretation.classification === "existing_session_reuse" || bundle.continuity.likelyLoginPage || bundle.continuity.likelySessionPicker;
|
|
2465
|
-
const canNavigateToAuth = gate.allowedActions.includes("auth_navigation") && authLaneRelevant && (bundle.continuity.loginRefs.length > 0 || typeof bundle.url === "string");
|
|
2466
|
-
const canReuseExistingSession = gate.allowedActions.includes("session_reuse") && (bundle.continuity.hasPreservedSession || bundle.continuity.attachedSession || bundle.continuity.sessionReuseRefs.length > 0);
|
|
2467
|
-
const canReuseCookies = gate.allowedActions.includes("cookie_reuse") && authLaneRelevant && (bundle.continuity.canReuseExistingCookies || bundle.continuity.canImportCookies);
|
|
2468
|
-
const canFillNonSecretFields = gate.allowedActions.includes("non_secret_form_fill") && bundle.continuity.hasNonSecretTaskData && bundle.continuity.nonSecretFieldRefs.length > 0;
|
|
2469
|
-
const canExploreClicks = gate.allowedActions.includes("click_path") && (hasActionables || bundle.continuity.loginRefs.length > 0 || bundle.continuity.sessionReuseRefs.length > 0 || bundle.continuity.checkpointRefs.length > 0);
|
|
2470
|
-
const mustYield = interpretation.humanBoundary === "secret_entry" || interpretation.humanBoundary === "mfa" || interpretation.humanBoundary === "explicit_consent" || interpretation.humanBoundary === "exhausted_no_progress";
|
|
2471
|
-
const mustDefer = interpretation.humanBoundary === "policy_blocked" || !bundle.blocker && bundle.blockerState === "clear";
|
|
2472
|
-
let helperEligibility = gate.helperEligibility ?? (gate.optionalComputerUseBridge ? {
|
|
2473
|
-
allowed: true,
|
|
2474
|
-
reason: "Optional helper bridge remains eligible after policy resolution."
|
|
2475
|
-
} : {
|
|
2476
|
-
allowed: false,
|
|
2477
|
-
reason: "Optional computer-use bridge is disabled by policy.",
|
|
2478
|
-
standDownReason: "helper_disabled_by_policy"
|
|
2479
|
-
});
|
|
2480
|
-
if (helperEligibility.allowed && interpretation.humanBoundary !== "none") {
|
|
2481
|
-
helperEligibility = {
|
|
2482
|
-
allowed: false,
|
|
2483
|
-
reason: `Helper bridge is blocked by human boundary: ${interpretation.humanBoundary}.`,
|
|
2484
|
-
standDownReason: "helper_blocked_by_human_boundary"
|
|
2635
|
+
"type"
|
|
2636
|
+
);
|
|
2637
|
+
const fieldValue = fieldRef ? resolveTaskValue(bundle, fieldRef) : void 0;
|
|
2638
|
+
if (decision.allowedActionFamilies.includes("non_secret_form_fill") && fieldRef && fieldValue) {
|
|
2639
|
+
return {
|
|
2640
|
+
kind: "type",
|
|
2641
|
+
ref: fieldRef,
|
|
2642
|
+
text: fieldValue,
|
|
2643
|
+
reason: "Fill a non-secret field from caller-provided task data."
|
|
2485
2644
|
};
|
|
2486
|
-
}
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2645
|
+
}
|
|
2646
|
+
const checkpointRef = nextUnusedRef(
|
|
2647
|
+
bundle.continuity.checkpointRefs,
|
|
2648
|
+
executedSteps,
|
|
2649
|
+
"click"
|
|
2650
|
+
);
|
|
2651
|
+
if (decision.allowedActionFamilies.includes("click_path") && checkpointRef) {
|
|
2652
|
+
return {
|
|
2653
|
+
kind: "click",
|
|
2654
|
+
ref: checkpointRef,
|
|
2655
|
+
reason: "Try the next visible checkpoint or continue action."
|
|
2491
2656
|
};
|
|
2492
2657
|
}
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2658
|
+
const hoverRef = nextUnusedRef(
|
|
2659
|
+
[...bundle.continuity.loginRefs, ...bundle.continuity.checkpointRefs],
|
|
2660
|
+
executedSteps,
|
|
2661
|
+
"hover"
|
|
2662
|
+
);
|
|
2663
|
+
if (decision.allowedActionFamilies.includes("hover") && hoverRef) {
|
|
2664
|
+
return {
|
|
2665
|
+
kind: "hover",
|
|
2666
|
+
ref: hoverRef,
|
|
2667
|
+
reason: "Hover a likely action target to reveal hidden menus or session pickers."
|
|
2668
|
+
};
|
|
2669
|
+
}
|
|
2670
|
+
if (decision.allowedActionFamilies.includes("scroll") && !hasExecuted(executedSteps, "scroll")) {
|
|
2671
|
+
return {
|
|
2672
|
+
kind: "scroll",
|
|
2673
|
+
dy: 900,
|
|
2674
|
+
reason: "Scroll down to uncover the next actionable region."
|
|
2675
|
+
};
|
|
2676
|
+
}
|
|
2677
|
+
if (decision.allowedActionFamilies.includes("scroll") && executedSteps.filter((step) => step.kind === "scroll").length === 1) {
|
|
2678
|
+
return {
|
|
2679
|
+
kind: "scroll",
|
|
2680
|
+
dy: -450,
|
|
2681
|
+
reason: "Scroll back up to re-evaluate the visible challenge state."
|
|
2682
|
+
};
|
|
2683
|
+
}
|
|
2684
|
+
if (decision.allowedActionFamilies.includes("press") && !hasExecuted(executedSteps, "press")) {
|
|
2685
|
+
return {
|
|
2686
|
+
kind: "press",
|
|
2687
|
+
text: "Tab",
|
|
2688
|
+
reason: "Advance focus through the challenge surface."
|
|
2689
|
+
};
|
|
2690
|
+
}
|
|
2691
|
+
if (decision.allowedActionFamilies.includes("pointer") && !hasExecuted(executedSteps, "pointer")) {
|
|
2692
|
+
return {
|
|
2693
|
+
kind: "pointer",
|
|
2694
|
+
coordinates: { x: 640, y: 360 },
|
|
2695
|
+
reason: "Move the pointer through the center of the current browser surface."
|
|
2696
|
+
};
|
|
2697
|
+
}
|
|
2698
|
+
if (decision.allowedActionFamilies.includes("drag") && !hasExecuted(executedSteps, "drag")) {
|
|
2699
|
+
return {
|
|
2700
|
+
kind: "drag",
|
|
2701
|
+
coordinates: { x: 640, y: 360 },
|
|
2702
|
+
reason: "Attempt one bounded vertical drag across the visible surface."
|
|
2703
|
+
};
|
|
2704
|
+
}
|
|
2705
|
+
if (!hasExecuted(executedSteps, "wait")) {
|
|
2706
|
+
return {
|
|
2707
|
+
kind: "wait",
|
|
2708
|
+
reason: "Give the page a short bounded settle window before yielding."
|
|
2709
|
+
};
|
|
2710
|
+
}
|
|
2711
|
+
return void 0;
|
|
2507
2712
|
};
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2713
|
+
var pendingSteps = (steps, executedSteps) => {
|
|
2714
|
+
return (steps ?? []).filter((step) => {
|
|
2715
|
+
return !hasExecuted(executedSteps, step.kind, step.ref, step.url);
|
|
2716
|
+
});
|
|
2717
|
+
};
|
|
2718
|
+
var dedupeSteps = (steps) => {
|
|
2719
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2720
|
+
return steps.filter((step) => {
|
|
2721
|
+
const key = JSON.stringify([
|
|
2722
|
+
step.kind,
|
|
2723
|
+
step.ref ?? null,
|
|
2724
|
+
step.url ?? null,
|
|
2725
|
+
step.text ?? null,
|
|
2726
|
+
step.reason
|
|
2727
|
+
]);
|
|
2728
|
+
if (seen.has(key)) {
|
|
2729
|
+
return false;
|
|
2520
2730
|
}
|
|
2521
|
-
|
|
2731
|
+
seen.add(key);
|
|
2732
|
+
return true;
|
|
2733
|
+
});
|
|
2522
2734
|
};
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2735
|
+
var buildChallengeActionSuggestions = (args) => {
|
|
2736
|
+
const executedSteps = args.executedSteps ?? [];
|
|
2737
|
+
const helper = suggestComputerUseActions({
|
|
2738
|
+
helperEligibility: args.helperEligibility,
|
|
2739
|
+
bundle: args.bundle,
|
|
2740
|
+
maxSuggestions: args.config.optionalComputerUseBridge.maxSuggestions
|
|
2741
|
+
});
|
|
2742
|
+
const preferredSteps = pendingSteps(args.preferredSteps, executedSteps);
|
|
2743
|
+
const interactionStep = planInteractionStep(args.bundle, args.decision, executedSteps);
|
|
2744
|
+
const genericStep = planGenericStep(args.bundle, args.decision, executedSteps);
|
|
2745
|
+
const helperSteps = pendingSteps(helper.suggestedSteps, executedSteps);
|
|
2746
|
+
const suggestedSteps = args.decision.lane === "optional_computer_use_bridge" ? dedupeSteps([...preferredSteps, ...helperSteps]) : dedupeSteps([
|
|
2747
|
+
...preferredSteps,
|
|
2748
|
+
...interactionStep ? [interactionStep] : [],
|
|
2749
|
+
...genericStep ? [genericStep] : [],
|
|
2750
|
+
...helperSteps
|
|
2751
|
+
]);
|
|
2528
2752
|
return {
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
reason: approved ? "Sanctioned identity lane approved by explicit entitlement." : "Sanctioned identity lane requires explicit entitlement metadata.",
|
|
2532
|
-
auditMetadata: {
|
|
2533
|
-
approved,
|
|
2534
|
-
...approved ? { entitlement } : {}
|
|
2535
|
-
}
|
|
2753
|
+
helper,
|
|
2754
|
+
suggestedSteps
|
|
2536
2755
|
};
|
|
2537
2756
|
};
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
const
|
|
2757
|
+
var selectChallengeActionStep = (args) => {
|
|
2758
|
+
return buildChallengeActionSuggestions(args).suggestedSteps[0];
|
|
2759
|
+
};
|
|
2760
|
+
function buildChallengeInspectPlan(args) {
|
|
2761
|
+
const interpretation = interpretChallengeEvidence(args.bundle);
|
|
2762
|
+
const policy = resolveChallengeAutomationPolicy({
|
|
2763
|
+
runMode: args.runMode,
|
|
2764
|
+
sessionMode: args.sessionMode,
|
|
2765
|
+
configMode: args.config.mode
|
|
2766
|
+
});
|
|
2767
|
+
const gate = buildChallengePolicyGate(args.config, interpretation, policy);
|
|
2768
|
+
const capabilityMatrix = buildCapabilityMatrix(args.bundle, interpretation, gate);
|
|
2769
|
+
const decision = selectChallengeStrategy({
|
|
2770
|
+
config: args.config,
|
|
2771
|
+
bundle: args.bundle,
|
|
2772
|
+
interpretation,
|
|
2773
|
+
capabilityMatrix,
|
|
2774
|
+
gate
|
|
2775
|
+
});
|
|
2776
|
+
const actionSuggestions = buildChallengeActionSuggestions({
|
|
2777
|
+
bundle: args.bundle,
|
|
2778
|
+
decision,
|
|
2779
|
+
helperEligibility: capabilityMatrix.helperEligibility,
|
|
2780
|
+
config: args.config,
|
|
2781
|
+
preferredSteps: args.preferredSteps,
|
|
2782
|
+
executedSteps: args.executedSteps
|
|
2783
|
+
});
|
|
2784
|
+
const yieldDecision = shouldYieldToHuman({
|
|
2785
|
+
interpretation,
|
|
2786
|
+
noProgressExhausted: false
|
|
2787
|
+
});
|
|
2788
|
+
const standDownReason = capabilityMatrix.helperEligibility.standDownReason ?? gate.resolvedPolicy.standDownReason ?? actionSuggestions.helper.standDownReason;
|
|
2543
2789
|
return {
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2790
|
+
challengeId: args.bundle.challengeId,
|
|
2791
|
+
...args.bundle.mode ? { sessionMode: args.bundle.mode } : {},
|
|
2792
|
+
classification: interpretation.classification,
|
|
2793
|
+
authState: interpretation.authState,
|
|
2794
|
+
summary: interpretation.summary,
|
|
2795
|
+
mode: gate.resolvedPolicy.mode,
|
|
2796
|
+
source: gate.resolvedPolicy.source,
|
|
2797
|
+
helperEligibility: capabilityMatrix.helperEligibility,
|
|
2798
|
+
...standDownReason ? { standDownReason } : {},
|
|
2799
|
+
yield: {
|
|
2800
|
+
required: yieldDecision.yield,
|
|
2801
|
+
reason: yieldDecision.reason
|
|
2802
|
+
},
|
|
2803
|
+
decision,
|
|
2804
|
+
allowedActionFamilies: gate.allowedActions,
|
|
2805
|
+
forbiddenActionFamilies: gate.forbiddenActions,
|
|
2806
|
+
governedLanes: gate.governedLanes,
|
|
2807
|
+
capabilityMatrix,
|
|
2808
|
+
helper: actionSuggestions.helper,
|
|
2809
|
+
suggestedSteps: actionSuggestions.suggestedSteps,
|
|
2810
|
+
evidence: {
|
|
2811
|
+
blockerState: args.bundle.blockerState,
|
|
2812
|
+
...args.bundle.blocker?.type ? { blockerType: args.bundle.blocker.type } : {},
|
|
2813
|
+
...args.bundle.url ? { url: args.bundle.url } : {},
|
|
2814
|
+
...args.bundle.title ? { title: args.bundle.title } : {},
|
|
2815
|
+
...typeof args.bundle.activeTargetId !== "undefined" ? { activeTargetId: args.bundle.activeTargetId } : {},
|
|
2816
|
+
...args.bundle.snapshotId ? { snapshotId: args.bundle.snapshotId } : {},
|
|
2817
|
+
loginRefs: args.bundle.continuity.loginRefs,
|
|
2818
|
+
sessionReuseRefs: args.bundle.continuity.sessionReuseRefs,
|
|
2819
|
+
humanVerificationRefs: args.bundle.continuity.humanVerificationRefs,
|
|
2820
|
+
checkpointRefs: args.bundle.continuity.checkpointRefs
|
|
2550
2821
|
}
|
|
2551
2822
|
};
|
|
2552
|
-
}
|
|
2823
|
+
}
|
|
2824
|
+
async function inspectChallengePlanFromRuntime(args) {
|
|
2825
|
+
const bundle = await captureChallengeEvidence({
|
|
2826
|
+
handle: args.handle,
|
|
2827
|
+
sessionId: args.sessionId,
|
|
2828
|
+
targetId: args.targetId,
|
|
2829
|
+
canImportCookies: args.canImportCookies ?? true
|
|
2830
|
+
});
|
|
2831
|
+
return buildChallengeInspectPlan({
|
|
2832
|
+
bundle,
|
|
2833
|
+
config: args.config,
|
|
2834
|
+
runMode: args.runMode,
|
|
2835
|
+
sessionMode: args.sessionMode
|
|
2836
|
+
});
|
|
2837
|
+
}
|
|
2553
2838
|
|
|
2554
|
-
// src/challenges/
|
|
2555
|
-
var
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
lane: request.lane,
|
|
2560
|
-
reason: "Challenge automation mode is off.",
|
|
2561
|
-
auditMetadata: {}
|
|
2562
|
-
};
|
|
2839
|
+
// src/challenges/action-loop.ts
|
|
2840
|
+
var DEFAULT_HOLD_MS2 = 1500;
|
|
2841
|
+
var resolveStepPoint = async (args) => {
|
|
2842
|
+
if (!args.step.ref) {
|
|
2843
|
+
return args.step.coordinates ?? args.fallback;
|
|
2563
2844
|
}
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
};
|
|
2845
|
+
return await args.handle.resolveRefPoint(args.sessionId, args.step.ref, args.targetId);
|
|
2846
|
+
};
|
|
2847
|
+
var executeStep = async (args) => {
|
|
2848
|
+
const timeoutMs = args.config.stepTimeoutMs;
|
|
2849
|
+
switch (args.step.kind) {
|
|
2850
|
+
case "goto":
|
|
2851
|
+
if (args.step.url) {
|
|
2852
|
+
await args.handle.goto(args.sessionId, args.step.url, "domcontentloaded", timeoutMs, void 0, args.targetId);
|
|
2573
2853
|
}
|
|
2574
|
-
return
|
|
2575
|
-
case "
|
|
2576
|
-
if (
|
|
2577
|
-
|
|
2578
|
-
status: "blocked",
|
|
2579
|
-
lane: request.lane,
|
|
2580
|
-
reason: "Sanctioned identity is disabled by policy.",
|
|
2581
|
-
auditMetadata: {}
|
|
2582
|
-
};
|
|
2854
|
+
return;
|
|
2855
|
+
case "click":
|
|
2856
|
+
if (args.step.ref) {
|
|
2857
|
+
await args.handle.click(args.sessionId, args.step.ref, args.targetId);
|
|
2583
2858
|
}
|
|
2584
|
-
return
|
|
2585
|
-
case "
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2859
|
+
return;
|
|
2860
|
+
case "click_and_hold": {
|
|
2861
|
+
const point = await resolveStepPoint({
|
|
2862
|
+
handle: args.handle,
|
|
2863
|
+
sessionId: args.sessionId,
|
|
2864
|
+
step: args.step,
|
|
2865
|
+
targetId: args.targetId,
|
|
2866
|
+
fallback: { x: 640, y: 360 }
|
|
2867
|
+
});
|
|
2868
|
+
await args.handle.pointerMove(args.sessionId, point.x, point.y, args.targetId, 12);
|
|
2869
|
+
await args.handle.pointerDown(args.sessionId, point.x, point.y, args.targetId, "left", 1);
|
|
2870
|
+
await new Promise((resolve2) => setTimeout(resolve2, Math.max(250, args.step.holdMs ?? DEFAULT_HOLD_MS2)));
|
|
2871
|
+
await args.handle.pointerUp(args.sessionId, point.x, point.y, args.targetId, "left", 1);
|
|
2872
|
+
return;
|
|
2873
|
+
}
|
|
2874
|
+
case "hover":
|
|
2875
|
+
if (args.step.ref) {
|
|
2876
|
+
await args.handle.hover(args.sessionId, args.step.ref, args.targetId);
|
|
2593
2877
|
}
|
|
2594
|
-
return
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2878
|
+
return;
|
|
2879
|
+
case "press":
|
|
2880
|
+
await args.handle.press(args.sessionId, args.step.text ?? "Tab", void 0, args.targetId);
|
|
2881
|
+
return;
|
|
2882
|
+
case "type":
|
|
2883
|
+
if (args.step.ref && typeof args.step.text === "string") {
|
|
2884
|
+
await args.handle.type(args.sessionId, args.step.ref, args.step.text, true, false, args.targetId);
|
|
2885
|
+
}
|
|
2886
|
+
return;
|
|
2887
|
+
case "select":
|
|
2888
|
+
if (args.step.ref && args.step.values?.length) {
|
|
2889
|
+
await args.handle.select(args.sessionId, args.step.ref, args.step.values, args.targetId);
|
|
2890
|
+
}
|
|
2891
|
+
return;
|
|
2892
|
+
case "scroll":
|
|
2893
|
+
await args.handle.scroll(args.sessionId, args.step.dy ?? 600, void 0, args.targetId);
|
|
2894
|
+
return;
|
|
2895
|
+
case "pointer":
|
|
2896
|
+
await args.handle.pointerMove(
|
|
2897
|
+
args.sessionId,
|
|
2898
|
+
args.step.coordinates?.x ?? 640,
|
|
2899
|
+
args.step.coordinates?.y ?? 360,
|
|
2900
|
+
args.targetId,
|
|
2901
|
+
12
|
|
2902
|
+
);
|
|
2903
|
+
return;
|
|
2904
|
+
case "drag":
|
|
2905
|
+
{
|
|
2906
|
+
const point = await resolveStepPoint({
|
|
2907
|
+
handle: args.handle,
|
|
2908
|
+
sessionId: args.sessionId,
|
|
2909
|
+
step: args.step,
|
|
2910
|
+
targetId: args.targetId,
|
|
2911
|
+
fallback: args.step.coordinates ?? { x: 640, y: 360 }
|
|
2912
|
+
});
|
|
2913
|
+
await args.handle.drag(
|
|
2914
|
+
args.sessionId,
|
|
2915
|
+
point,
|
|
2916
|
+
{
|
|
2917
|
+
x: point.x,
|
|
2918
|
+
y: point.y + 260
|
|
2919
|
+
},
|
|
2920
|
+
args.targetId,
|
|
2921
|
+
16
|
|
2922
|
+
);
|
|
2923
|
+
}
|
|
2924
|
+
return;
|
|
2925
|
+
case "cookie_list":
|
|
2926
|
+
await args.handle.cookieList(args.sessionId, args.step.url ? [args.step.url] : void 0);
|
|
2927
|
+
return;
|
|
2928
|
+
case "cookie_import":
|
|
2929
|
+
await args.handle.cookieImport(args.sessionId, args.step.cookies ?? [], true);
|
|
2930
|
+
return;
|
|
2931
|
+
case "snapshot":
|
|
2932
|
+
await args.handle.snapshot(
|
|
2933
|
+
args.sessionId,
|
|
2934
|
+
"actionables",
|
|
2935
|
+
args.step.snapshotChars ?? 2400,
|
|
2936
|
+
void 0,
|
|
2937
|
+
args.targetId
|
|
2938
|
+
);
|
|
2939
|
+
return;
|
|
2940
|
+
case "debug_trace":
|
|
2941
|
+
await args.handle.debugTraceSnapshot(args.sessionId, { max: args.step.traceMax ?? 50 });
|
|
2942
|
+
return;
|
|
2943
|
+
case "wait":
|
|
2944
|
+
await args.handle.waitForLoad(args.sessionId, "networkidle", Math.min(timeoutMs, 3e3), args.targetId);
|
|
2945
|
+
return;
|
|
2946
|
+
default:
|
|
2947
|
+
return;
|
|
2662
2948
|
}
|
|
2663
2949
|
};
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2950
|
+
var runChallengeActionLoop = async (args) => {
|
|
2951
|
+
let currentBundle = args.initialBundle;
|
|
2952
|
+
let currentTargetId = args.targetId ?? args.initialBundle.activeTargetId ?? null;
|
|
2953
|
+
const executedSteps = [];
|
|
2954
|
+
let noProgressCount = 0;
|
|
2955
|
+
let reusedExistingSession = false;
|
|
2956
|
+
let reusedCookies = false;
|
|
2957
|
+
for (let attempt = 1; attempt <= args.decision.attemptBudget; attempt += 1) {
|
|
2958
|
+
const step = selectChallengeActionStep({
|
|
2959
|
+
bundle: currentBundle,
|
|
2960
|
+
decision: args.decision,
|
|
2961
|
+
helperEligibility: args.helperEligibility,
|
|
2962
|
+
config: args.config,
|
|
2963
|
+
preferredSteps: args.suggestedSteps,
|
|
2964
|
+
executedSteps
|
|
2965
|
+
});
|
|
2966
|
+
if (!step) {
|
|
2967
|
+
return {
|
|
2968
|
+
status: "no_progress",
|
|
2969
|
+
attempts: attempt - 1,
|
|
2970
|
+
noProgressCount,
|
|
2971
|
+
executedSteps,
|
|
2972
|
+
verification: {
|
|
2973
|
+
status: "still_blocked",
|
|
2974
|
+
blockerState: currentBundle.blockerState,
|
|
2975
|
+
blocker: currentBundle.blocker,
|
|
2976
|
+
challenge: currentBundle.challenge,
|
|
2977
|
+
bundle: currentBundle,
|
|
2978
|
+
changed: false,
|
|
2979
|
+
reason: "No additional safe browser action remained.",
|
|
2980
|
+
url: currentBundle.url,
|
|
2981
|
+
title: currentBundle.title
|
|
2982
|
+
},
|
|
2983
|
+
reusedExistingSession,
|
|
2984
|
+
reusedCookies
|
|
2985
|
+
};
|
|
2986
|
+
}
|
|
2987
|
+
try {
|
|
2988
|
+
await executeStep({
|
|
2989
|
+
handle: args.handle,
|
|
2990
|
+
sessionId: args.sessionId,
|
|
2991
|
+
targetId: currentTargetId,
|
|
2992
|
+
step,
|
|
2993
|
+
config: args.config
|
|
2994
|
+
});
|
|
2995
|
+
} catch {
|
|
2996
|
+
}
|
|
2997
|
+
executedSteps.push(step);
|
|
2998
|
+
if (step.ref && currentBundle.continuity.sessionReuseRefs.includes(step.ref)) {
|
|
2999
|
+
reusedExistingSession = true;
|
|
3000
|
+
}
|
|
3001
|
+
if (step.kind === "goto" && currentBundle.continuity.canReuseExistingCookies) {
|
|
3002
|
+
reusedCookies = true;
|
|
3003
|
+
}
|
|
3004
|
+
const verification = await verifyChallengeProgress({
|
|
3005
|
+
handle: args.handle,
|
|
3006
|
+
sessionId: args.sessionId,
|
|
3007
|
+
targetId: currentTargetId,
|
|
3008
|
+
previous: currentBundle,
|
|
3009
|
+
canImportCookies: currentBundle.continuity.canImportCookies,
|
|
3010
|
+
fallbackDisposition: currentBundle.fallbackDisposition,
|
|
3011
|
+
registryPressure: currentBundle.registryPressure,
|
|
3012
|
+
taskData: currentBundle.taskData
|
|
3013
|
+
});
|
|
3014
|
+
currentBundle = verification.bundle ?? currentBundle;
|
|
3015
|
+
currentTargetId = verification.bundle?.activeTargetId ?? currentTargetId;
|
|
3016
|
+
if (verification.status === "clear") {
|
|
3017
|
+
return {
|
|
3018
|
+
status: "resolved",
|
|
3019
|
+
attempts: attempt,
|
|
3020
|
+
noProgressCount,
|
|
3021
|
+
executedSteps,
|
|
3022
|
+
verification,
|
|
3023
|
+
reusedExistingSession,
|
|
3024
|
+
reusedCookies
|
|
3025
|
+
};
|
|
3026
|
+
}
|
|
3027
|
+
if (verification.status === "yield_required") {
|
|
3028
|
+
return {
|
|
3029
|
+
status: "yield_required",
|
|
3030
|
+
attempts: attempt,
|
|
3031
|
+
noProgressCount,
|
|
3032
|
+
executedSteps,
|
|
3033
|
+
verification,
|
|
3034
|
+
reusedExistingSession,
|
|
3035
|
+
reusedCookies
|
|
3036
|
+
};
|
|
3037
|
+
}
|
|
3038
|
+
if (verification.status === "deferred") {
|
|
3039
|
+
return {
|
|
3040
|
+
status: "deferred",
|
|
3041
|
+
attempts: attempt,
|
|
3042
|
+
noProgressCount,
|
|
3043
|
+
executedSteps,
|
|
3044
|
+
verification,
|
|
3045
|
+
reusedExistingSession,
|
|
3046
|
+
reusedCookies
|
|
3047
|
+
};
|
|
3048
|
+
}
|
|
3049
|
+
if (verification.changed) {
|
|
3050
|
+
noProgressCount = 0;
|
|
3051
|
+
continue;
|
|
3052
|
+
}
|
|
3053
|
+
noProgressCount += 1;
|
|
3054
|
+
if (noProgressCount >= args.decision.noProgressLimit) {
|
|
3055
|
+
return {
|
|
3056
|
+
status: "no_progress",
|
|
3057
|
+
attempts: attempt,
|
|
3058
|
+
noProgressCount,
|
|
3059
|
+
executedSteps,
|
|
3060
|
+
verification,
|
|
3061
|
+
reusedExistingSession,
|
|
3062
|
+
reusedCookies
|
|
3063
|
+
};
|
|
3064
|
+
}
|
|
2706
3065
|
}
|
|
2707
|
-
return {
|
|
3066
|
+
return {
|
|
3067
|
+
status: "still_blocked",
|
|
3068
|
+
attempts: args.decision.attemptBudget,
|
|
3069
|
+
noProgressCount,
|
|
3070
|
+
executedSteps,
|
|
3071
|
+
verification: {
|
|
3072
|
+
status: "still_blocked",
|
|
3073
|
+
blockerState: currentBundle.blockerState,
|
|
3074
|
+
blocker: currentBundle.blocker,
|
|
3075
|
+
challenge: currentBundle.challenge,
|
|
3076
|
+
bundle: currentBundle,
|
|
3077
|
+
changed: false,
|
|
3078
|
+
reason: "Attempt budget exhausted without clearing the blocker.",
|
|
3079
|
+
url: currentBundle.url,
|
|
3080
|
+
title: currentBundle.title
|
|
3081
|
+
},
|
|
3082
|
+
reusedExistingSession,
|
|
3083
|
+
reusedCookies
|
|
3084
|
+
};
|
|
2708
3085
|
};
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
3086
|
+
|
|
3087
|
+
// src/challenges/owned-environment-lane.ts
|
|
3088
|
+
var APPROVED_FIXTURE_RE = /\b(turnstile-checkbox|recaptcha-v2-checkbox|1x00000000000000000000AA|6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI)\b/i;
|
|
3089
|
+
var runOwnedEnvironmentLane = (request) => {
|
|
3090
|
+
const haystack = [request.bundle.url, request.bundle.title, request.bundle.snapshotText].filter((value) => typeof value === "string" && value.length > 0).join(" ");
|
|
3091
|
+
const approved = APPROVED_FIXTURE_RE.test(haystack);
|
|
3092
|
+
return {
|
|
3093
|
+
status: approved ? "executed" : "blocked",
|
|
3094
|
+
lane: "owned_environment_fixture",
|
|
3095
|
+
reason: approved ? "Approved owned-environment fixture detected." : "Owned-environment lane requires an approved vendor test fixture.",
|
|
3096
|
+
auditMetadata: {
|
|
3097
|
+
approvedFixture: approved
|
|
3098
|
+
}
|
|
3099
|
+
};
|
|
2717
3100
|
};
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
standDownReason: "challenge_automation_off"
|
|
2724
|
-
};
|
|
2725
|
-
}
|
|
2726
|
-
if (policy.mode === "browser") {
|
|
2727
|
-
return {
|
|
2728
|
-
allowed: false,
|
|
2729
|
-
reason: "Browser mode keeps the optional helper bridge disabled.",
|
|
2730
|
-
standDownReason: "helper_disabled_for_browser_mode"
|
|
2731
|
-
};
|
|
2732
|
-
}
|
|
2733
|
-
if (!config.optionalComputerUseBridge.enabled) {
|
|
2734
|
-
return {
|
|
2735
|
-
allowed: false,
|
|
2736
|
-
reason: "Optional computer-use bridge is disabled by policy.",
|
|
2737
|
-
standDownReason: "helper_disabled_by_policy"
|
|
2738
|
-
};
|
|
2739
|
-
}
|
|
3101
|
+
|
|
3102
|
+
// src/challenges/sanctioned-identity-lane.ts
|
|
3103
|
+
var runSanctionedIdentityLane = (request) => {
|
|
3104
|
+
const entitlement = request.auditContext?.identityEntitlement;
|
|
3105
|
+
const approved = typeof entitlement === "string" && entitlement.trim().length > 0;
|
|
2740
3106
|
return {
|
|
2741
|
-
|
|
2742
|
-
|
|
3107
|
+
status: approved ? "executed" : "blocked",
|
|
3108
|
+
lane: "sanctioned_identity",
|
|
3109
|
+
reason: approved ? "Sanctioned identity lane approved by explicit entitlement." : "Sanctioned identity lane requires explicit entitlement metadata.",
|
|
3110
|
+
auditMetadata: {
|
|
3111
|
+
approved,
|
|
3112
|
+
...approved ? { entitlement } : {}
|
|
3113
|
+
}
|
|
2743
3114
|
};
|
|
2744
3115
|
};
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
const
|
|
2749
|
-
|
|
2750
|
-
return {
|
|
2751
|
-
resolvedPolicy,
|
|
2752
|
-
allowedActions: [],
|
|
2753
|
-
forbiddenActions: [...ALL_ACTIONS],
|
|
2754
|
-
handoffTriggers: [...DEFAULT_HANDOFF_TRIGGERS],
|
|
2755
|
-
governedLanes: [],
|
|
2756
|
-
optionalComputerUseBridge: false,
|
|
2757
|
-
helperEligibility
|
|
2758
|
-
};
|
|
2759
|
-
}
|
|
2760
|
-
const allowed = /* @__PURE__ */ new Set(["wait", "verification", "debug_trace"]);
|
|
2761
|
-
if (config.allowAuthNavigation) {
|
|
2762
|
-
allowed.add("auth_navigation");
|
|
2763
|
-
}
|
|
2764
|
-
if (config.allowSessionReuse) {
|
|
2765
|
-
allowed.add("session_reuse");
|
|
2766
|
-
}
|
|
2767
|
-
if (config.allowCookieReuse) {
|
|
2768
|
-
allowed.add("cookie_reuse");
|
|
2769
|
-
}
|
|
2770
|
-
if (config.allowNonSecretFormFill) {
|
|
2771
|
-
allowed.add("non_secret_form_fill");
|
|
2772
|
-
allowed.add("dropdown");
|
|
2773
|
-
}
|
|
2774
|
-
if (config.allowInteractionExploration) {
|
|
2775
|
-
allowed.add("element_discovery");
|
|
2776
|
-
allowed.add("click_path");
|
|
2777
|
-
allowed.add("click_and_hold");
|
|
2778
|
-
allowed.add("scroll");
|
|
2779
|
-
allowed.add("hover");
|
|
2780
|
-
allowed.add("press");
|
|
2781
|
-
allowed.add("pointer");
|
|
2782
|
-
allowed.add("drag");
|
|
2783
|
-
}
|
|
2784
|
-
if (interpretation.humanBoundary === "secret_entry" || interpretation.humanBoundary === "mfa") {
|
|
2785
|
-
allowed.delete("non_secret_form_fill");
|
|
2786
|
-
}
|
|
2787
|
-
const governedLanes = [];
|
|
2788
|
-
if (config.governed.allowOwnedEnvironmentFixtures) {
|
|
2789
|
-
governedLanes.push("owned_environment_fixture");
|
|
2790
|
-
}
|
|
2791
|
-
if (config.governed.allowSanctionedIdentity) {
|
|
2792
|
-
governedLanes.push("sanctioned_identity");
|
|
2793
|
-
}
|
|
2794
|
-
if (config.governed.allowServiceAdapters) {
|
|
2795
|
-
governedLanes.push("service_adapter");
|
|
2796
|
-
}
|
|
3116
|
+
|
|
3117
|
+
// src/challenges/service-adapter-lane.ts
|
|
3118
|
+
var runServiceAdapterLane = (request) => {
|
|
3119
|
+
const adapter = request.auditContext?.adapterId;
|
|
3120
|
+
const approved = typeof adapter === "string" && adapter.trim().length > 0;
|
|
2797
3121
|
return {
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
3122
|
+
status: approved ? "executed" : "blocked",
|
|
3123
|
+
lane: "service_adapter",
|
|
3124
|
+
reason: approved ? "Governed service adapter approved by explicit adapter metadata." : "Service-adapter lane requires an explicit adapter identifier and entitlement.",
|
|
3125
|
+
auditMetadata: {
|
|
3126
|
+
approved,
|
|
3127
|
+
...approved ? { adapterId: adapter } : {}
|
|
3128
|
+
}
|
|
2805
3129
|
};
|
|
2806
3130
|
};
|
|
2807
3131
|
|
|
2808
|
-
// src/challenges/
|
|
2809
|
-
var
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
allowedActionFamilies: [...allowedActionFamilies]
|
|
2818
|
-
});
|
|
2819
|
-
var selectChallengeStrategy = (args) => {
|
|
2820
|
-
const { config, bundle, capabilityMatrix, gate, interpretation } = args;
|
|
2821
|
-
const registryCooldownActive = (bundle.registryPressure?.cooldownUntilMs ?? 0) > Date.now();
|
|
2822
|
-
const registryPressureElevated = (bundle.registryPressure?.activeChallenges ?? 0) > 0 || (bundle.registryPressure?.recentChallengeRatio ?? 0) >= 0.5 || (bundle.registryPressure?.recentRateLimitRatio ?? 0) >= 0.5;
|
|
2823
|
-
const stopConditions = [
|
|
2824
|
-
"manager_verification_clears_blocker",
|
|
2825
|
-
"policy_gate_denies_next_action",
|
|
2826
|
-
"human_boundary_detected",
|
|
2827
|
-
"no_progress_budget_exhausted"
|
|
2828
|
-
];
|
|
2829
|
-
const { mode, standDownReason } = gate.resolvedPolicy;
|
|
2830
|
-
if (mode === "off") {
|
|
2831
|
-
return buildDecision(
|
|
2832
|
-
config,
|
|
2833
|
-
"defer",
|
|
2834
|
-
"Challenge automation mode is off; challenge handling is detect-and-report only.",
|
|
2835
|
-
[],
|
|
2836
|
-
"light",
|
|
2837
|
-
[standDownReason ?? "challenge_automation_off"]
|
|
2838
|
-
);
|
|
2839
|
-
}
|
|
2840
|
-
if (capabilityMatrix.mustDefer) {
|
|
2841
|
-
return buildDecision(
|
|
2842
|
-
config,
|
|
2843
|
-
"defer",
|
|
2844
|
-
"Current policy or blocker state requires deferral before further automation.",
|
|
2845
|
-
gate.allowedActions,
|
|
2846
|
-
interpretation.requiredVerification,
|
|
2847
|
-
["policy_blocked_or_clear_state"]
|
|
2848
|
-
);
|
|
2849
|
-
}
|
|
2850
|
-
if (registryCooldownActive && !capabilityMatrix.canReuseExistingSession && !capabilityMatrix.canReuseCookies && !capabilityMatrix.canNavigateToAuth) {
|
|
2851
|
-
return buildDecision(
|
|
2852
|
-
config,
|
|
2853
|
-
"defer",
|
|
2854
|
-
"Registry cooldown is still active and no legitimate continuity or auth-navigation lane is currently available.",
|
|
2855
|
-
gate.allowedActions,
|
|
2856
|
-
interpretation.requiredVerification,
|
|
2857
|
-
["registry_cooldown_active"]
|
|
2858
|
-
);
|
|
2859
|
-
}
|
|
2860
|
-
if (capabilityMatrix.canUseOwnedEnvironmentFixture) {
|
|
2861
|
-
return buildDecision(
|
|
2862
|
-
config,
|
|
2863
|
-
"owned_environment_fixture",
|
|
2864
|
-
"Owned-environment fixture detected and explicitly allowlisted.",
|
|
2865
|
-
gate.allowedActions,
|
|
2866
|
-
interpretation.requiredVerification,
|
|
2867
|
-
stopConditions,
|
|
2868
|
-
"owned_environment_fixture"
|
|
2869
|
-
);
|
|
2870
|
-
}
|
|
2871
|
-
if (capabilityMatrix.mustYield) {
|
|
2872
|
-
return buildDecision(
|
|
2873
|
-
config,
|
|
2874
|
-
"human_yield",
|
|
2875
|
-
`Human authority boundary reached: ${interpretation.humanBoundary}.`,
|
|
2876
|
-
gate.allowedActions,
|
|
2877
|
-
interpretation.requiredVerification,
|
|
2878
|
-
[...stopConditions, "human_authority_required"]
|
|
2879
|
-
);
|
|
3132
|
+
// src/challenges/governed-adapter-gateway.ts
|
|
3133
|
+
var evaluateGovernedLane = (config, request) => {
|
|
3134
|
+
if (config.mode === "off") {
|
|
3135
|
+
return {
|
|
3136
|
+
status: "blocked",
|
|
3137
|
+
lane: request.lane,
|
|
3138
|
+
reason: "Challenge automation mode is off.",
|
|
3139
|
+
auditMetadata: {}
|
|
3140
|
+
};
|
|
2880
3141
|
}
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
config
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
3142
|
+
switch (request.lane) {
|
|
3143
|
+
case "owned_environment_fixture":
|
|
3144
|
+
if (!config.governed.allowOwnedEnvironmentFixtures) {
|
|
3145
|
+
return {
|
|
3146
|
+
status: "blocked",
|
|
3147
|
+
lane: request.lane,
|
|
3148
|
+
reason: "Owned-environment fixtures are disabled by policy.",
|
|
3149
|
+
auditMetadata: {}
|
|
3150
|
+
};
|
|
3151
|
+
}
|
|
3152
|
+
return runOwnedEnvironmentLane(request);
|
|
3153
|
+
case "sanctioned_identity":
|
|
3154
|
+
if (!config.governed.allowSanctionedIdentity) {
|
|
3155
|
+
return {
|
|
3156
|
+
status: "blocked",
|
|
3157
|
+
lane: request.lane,
|
|
3158
|
+
reason: "Sanctioned identity is disabled by policy.",
|
|
3159
|
+
auditMetadata: {}
|
|
3160
|
+
};
|
|
3161
|
+
}
|
|
3162
|
+
return runSanctionedIdentityLane(request);
|
|
3163
|
+
case "service_adapter":
|
|
3164
|
+
if (!config.governed.allowServiceAdapters) {
|
|
3165
|
+
return {
|
|
3166
|
+
status: "blocked",
|
|
3167
|
+
lane: request.lane,
|
|
3168
|
+
reason: "Service adapters are disabled by policy.",
|
|
3169
|
+
auditMetadata: {}
|
|
3170
|
+
};
|
|
3171
|
+
}
|
|
3172
|
+
return runServiceAdapterLane(request);
|
|
2890
3173
|
}
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
);
|
|
3174
|
+
};
|
|
3175
|
+
|
|
3176
|
+
// src/challenges/outcome-recorder.ts
|
|
3177
|
+
var MAX_RECORDS_PER_CHALLENGE = 25;
|
|
3178
|
+
var OutcomeRecorder = class {
|
|
3179
|
+
records = /* @__PURE__ */ new Map();
|
|
3180
|
+
record(record) {
|
|
3181
|
+
const key = record.challengeId ?? "__untracked__";
|
|
3182
|
+
const existing = this.records.get(key) ?? [];
|
|
3183
|
+
const next = [...existing, record].slice(-MAX_RECORDS_PER_CHALLENGE);
|
|
3184
|
+
this.records.set(key, next);
|
|
2900
3185
|
}
|
|
2901
|
-
|
|
2902
|
-
return
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
"Sanctioned identity lane is enabled and generic browser autonomy is insufficient.",
|
|
2906
|
-
gate.allowedActions,
|
|
2907
|
-
interpretation.requiredVerification,
|
|
2908
|
-
stopConditions,
|
|
2909
|
-
"sanctioned_identity"
|
|
2910
|
-
);
|
|
3186
|
+
latest(challengeId) {
|
|
3187
|
+
if (!challengeId) return void 0;
|
|
3188
|
+
const entries = this.records.get(challengeId);
|
|
3189
|
+
return entries?.[entries.length - 1];
|
|
2911
3190
|
}
|
|
2912
|
-
|
|
2913
|
-
return
|
|
2914
|
-
|
|
2915
|
-
"service_adapter",
|
|
2916
|
-
"Governed service-adapter lane is enabled as the last non-human option.",
|
|
2917
|
-
gate.allowedActions,
|
|
2918
|
-
interpretation.requiredVerification,
|
|
2919
|
-
stopConditions,
|
|
2920
|
-
"service_adapter"
|
|
2921
|
-
);
|
|
3191
|
+
read(challengeId) {
|
|
3192
|
+
if (!challengeId) return [];
|
|
3193
|
+
return [...this.records.get(challengeId) ?? []];
|
|
2922
3194
|
}
|
|
2923
|
-
return buildDecision(
|
|
2924
|
-
config,
|
|
2925
|
-
"human_yield",
|
|
2926
|
-
`No legitimate autonomous lane remains after applying policy and continuity checks. ${capabilityMatrix.helperEligibility.reason}`,
|
|
2927
|
-
gate.allowedActions,
|
|
2928
|
-
interpretation.requiredVerification,
|
|
2929
|
-
[...stopConditions, "no_legitimate_lane_remaining"]
|
|
2930
|
-
);
|
|
2931
3195
|
};
|
|
2932
3196
|
|
|
2933
3197
|
// src/challenges/orchestrator.ts
|
|
@@ -2999,25 +3263,7 @@ var ChallengeOrchestrator = class {
|
|
|
2999
3263
|
return this.recorder;
|
|
3000
3264
|
}
|
|
3001
3265
|
async captureEvidence(args) {
|
|
3002
|
-
|
|
3003
|
-
const effectiveTargetId = status.activeTargetId ?? args.targetId ?? null;
|
|
3004
|
-
const snapshot = await args.handle.snapshot(args.sessionId, "actionables", 2400, void 0, effectiveTargetId);
|
|
3005
|
-
const debugTrace = await args.handle.debugTraceSnapshot(args.sessionId, { max: 50 });
|
|
3006
|
-
const cookies = status.url ? await args.handle.cookieList(args.sessionId, [status.url]) : { count: 0 };
|
|
3007
|
-
return buildChallengeEvidenceBundle({
|
|
3008
|
-
status,
|
|
3009
|
-
snapshot: {
|
|
3010
|
-
snapshotId: snapshot.snapshotId,
|
|
3011
|
-
content: snapshot.content,
|
|
3012
|
-
warnings: snapshot.warnings
|
|
3013
|
-
},
|
|
3014
|
-
debugTrace,
|
|
3015
|
-
cookieCount: cookies.count,
|
|
3016
|
-
canImportCookies: args.canImportCookies,
|
|
3017
|
-
fallbackDisposition: args.fallbackDisposition,
|
|
3018
|
-
registryPressure: args.registryPressure,
|
|
3019
|
-
taskData: args.taskData
|
|
3020
|
-
});
|
|
3266
|
+
return captureChallengeEvidence(args);
|
|
3021
3267
|
}
|
|
3022
3268
|
async orchestrate(args) {
|
|
3023
3269
|
const bundle = await this.captureEvidence({
|
|
@@ -3204,6 +3450,7 @@ var ChallengeOrchestrator = class {
|
|
|
3204
3450
|
targetId: args.targetId,
|
|
3205
3451
|
initialBundle: bundle,
|
|
3206
3452
|
decision,
|
|
3453
|
+
helperEligibility: capabilityMatrix.helperEligibility,
|
|
3207
3454
|
config: this.config,
|
|
3208
3455
|
suggestedSteps
|
|
3209
3456
|
});
|
|
@@ -3366,6 +3613,20 @@ var fallbackDispositionMessage = (fallback, url) => {
|
|
|
3366
3613
|
var toProviderFallbackError = (args) => {
|
|
3367
3614
|
const { fallback } = args;
|
|
3368
3615
|
const reasonCode = fallback.reasonCode;
|
|
3616
|
+
const details = {
|
|
3617
|
+
url: args.url,
|
|
3618
|
+
disposition: fallback.disposition,
|
|
3619
|
+
...fallback.mode ? { browserFallbackMode: fallback.mode } : {},
|
|
3620
|
+
...fallback.challenge ? { challenge: toJsonRecord(fallback.challenge) } : {},
|
|
3621
|
+
...fallback.preservedSessionId ? { preservedSessionId: fallback.preservedSessionId } : {},
|
|
3622
|
+
...fallback.preservedTargetId ? { preservedTargetId: fallback.preservedTargetId } : {},
|
|
3623
|
+
...toJsonRecord(fallback.details ?? {})
|
|
3624
|
+
};
|
|
3625
|
+
const hint = readProviderIssueHint({
|
|
3626
|
+
reasonCode,
|
|
3627
|
+
details
|
|
3628
|
+
});
|
|
3629
|
+
const guidance = hint ? buildProviderIssueGuidance({ provider: args.provider, hint, details }) : void 0;
|
|
3369
3630
|
return new ProviderRuntimeError(
|
|
3370
3631
|
providerErrorCodeFromReasonCode(reasonCode),
|
|
3371
3632
|
fallbackDispositionMessage(fallback, args.url),
|
|
@@ -3374,15 +3635,7 @@ var toProviderFallbackError = (args) => {
|
|
|
3374
3635
|
source: args.source,
|
|
3375
3636
|
retryable: reasonCode === "rate_limited",
|
|
3376
3637
|
reasonCode,
|
|
3377
|
-
details: {
|
|
3378
|
-
url: args.url,
|
|
3379
|
-
disposition: fallback.disposition,
|
|
3380
|
-
...fallback.mode ? { browserFallbackMode: fallback.mode } : {},
|
|
3381
|
-
...fallback.challenge ? { challenge: toJsonRecord(fallback.challenge) } : {},
|
|
3382
|
-
...fallback.preservedSessionId ? { preservedSessionId: fallback.preservedSessionId } : {},
|
|
3383
|
-
...fallback.preservedTargetId ? { preservedTargetId: fallback.preservedTargetId } : {},
|
|
3384
|
-
...toJsonRecord(fallback.details ?? {})
|
|
3385
|
-
}
|
|
3638
|
+
details: guidance ? { ...details, guidance } : details
|
|
3386
3639
|
}
|
|
3387
3640
|
);
|
|
3388
3641
|
};
|
|
@@ -9173,7 +9426,7 @@ var isJsonRecord = (value) => typeof value === "object" && value !== null && !Ar
|
|
|
9173
9426
|
var isWorkflowStage = (value) => value === "compile" || value === "execute" || value === "postprocess" || value === "resume";
|
|
9174
9427
|
var isWorkflowCheckpoint = (value) => isJsonRecord(value) && isWorkflowStage(value.stage) && (value.stepId === void 0 || typeof value.stepId === "string") && (value.stepIndex === void 0 || typeof value.stepIndex === "number") && (value.state === void 0 || isJsonRecord(value.state)) && (value.updatedAt === void 0 || typeof value.updatedAt === "string");
|
|
9175
9428
|
var isWorkflowTraceEntry = (value) => isJsonRecord(value) && typeof value.at === "string" && isWorkflowStage(value.stage) && typeof value.event === "string" && (value.details === void 0 || isJsonRecord(value.details));
|
|
9176
|
-
var isWorkflowKind = (value) => value === "research" || value === "shopping" || value === "product_video";
|
|
9429
|
+
var isWorkflowKind = (value) => value === "research" || value === "shopping" || value === "product_video" || value === "inspiredesign";
|
|
9177
9430
|
var buildWorkflowResumeEnvelope = (kind, input, options = {}) => ({
|
|
9178
9431
|
kind,
|
|
9179
9432
|
input,
|
|
@@ -9184,7 +9437,7 @@ var isWorkflowResumeEnvelope = (value) => isJsonRecord(value) && isWorkflowKind(
|
|
|
9184
9437
|
var isWorkflowResumePayload = (value) => isJsonRecord(value) && isWorkflowResumeEnvelope(value.workflow);
|
|
9185
9438
|
|
|
9186
9439
|
// src/providers/workflows.ts
|
|
9187
|
-
import { createHash as
|
|
9440
|
+
import { createHash as createHash7 } from "crypto";
|
|
9188
9441
|
|
|
9189
9442
|
// src/providers/artifacts.ts
|
|
9190
9443
|
import { mkdir, readdir as readdir2, readFile, rm as rm2, stat, writeFile } from "fs/promises";
|
|
@@ -9483,6 +9736,46 @@ var enrichResearchRecords = (records, timebox, now = /* @__PURE__ */ new Date())
|
|
|
9483
9736
|
return records.map((record) => toResearchRecord(record, timebox, now));
|
|
9484
9737
|
};
|
|
9485
9738
|
|
|
9739
|
+
// src/inspiredesign/handoff.ts
|
|
9740
|
+
var INSPIREDESIGN_HANDOFF_FILES = {
|
|
9741
|
+
designMarkdown: "design.md",
|
|
9742
|
+
designContract: "design-contract.json",
|
|
9743
|
+
canvasPlanRequest: "canvas-plan.request.json",
|
|
9744
|
+
designAgentHandoff: "design-agent-handoff.json",
|
|
9745
|
+
generationPlan: "generation-plan.json",
|
|
9746
|
+
implementationPlanMarkdown: "implementation-plan.md",
|
|
9747
|
+
implementationPlan: "implementation-plan.json",
|
|
9748
|
+
evidence: "evidence.json",
|
|
9749
|
+
prototypeGuidance: "prototype-guidance.md"
|
|
9750
|
+
};
|
|
9751
|
+
var INSPIREDESIGN_HANDOFF_SKILLS = {
|
|
9752
|
+
bestPractices: {
|
|
9753
|
+
name: "opendevbrowser-best-practices",
|
|
9754
|
+
topic: "quick start"
|
|
9755
|
+
},
|
|
9756
|
+
designAgent: {
|
|
9757
|
+
name: "opendevbrowser-design-agent",
|
|
9758
|
+
topic: "canvas-contract"
|
|
9759
|
+
}
|
|
9760
|
+
};
|
|
9761
|
+
var formatSkillReference = (skill) => `${skill.name} "${skill.topic}"`;
|
|
9762
|
+
var formatSkillLoadCommand = (skill) => `opendevbrowser_skill_load ${skill.name} "${skill.topic}"`;
|
|
9763
|
+
var INSPIREDESIGN_HANDOFF_COMMANDS = {
|
|
9764
|
+
loadBestPractices: formatSkillLoadCommand(INSPIREDESIGN_HANDOFF_SKILLS.bestPractices),
|
|
9765
|
+
loadDesignAgent: formatSkillLoadCommand(INSPIREDESIGN_HANDOFF_SKILLS.designAgent),
|
|
9766
|
+
continueInCanvas: `opendevbrowser canvas --command canvas.plan.set --params-file ./${INSPIREDESIGN_HANDOFF_FILES.canvasPlanRequest}`
|
|
9767
|
+
};
|
|
9768
|
+
var INSPIREDESIGN_HANDOFF_RECOMMENDED_SKILLS = [
|
|
9769
|
+
formatSkillReference(INSPIREDESIGN_HANDOFF_SKILLS.bestPractices),
|
|
9770
|
+
formatSkillReference(INSPIREDESIGN_HANDOFF_SKILLS.designAgent)
|
|
9771
|
+
];
|
|
9772
|
+
var INSPIREDESIGN_HANDOFF_GUIDANCE = {
|
|
9773
|
+
prepareCanvasPlanRequest: `Fill canvasSessionId, leaseId, and documentId in ${INSPIREDESIGN_HANDOFF_FILES.canvasPlanRequest} before running ${INSPIREDESIGN_HANDOFF_COMMANDS.continueInCanvas}.`,
|
|
9774
|
+
deepCaptureRecommendation: "Rerun inspiredesign with captureMode=deep only when you need richer evidence for visual hierarchy, protected references, or capture-specific debugging."
|
|
9775
|
+
};
|
|
9776
|
+
var buildInspiredesignFollowthroughSummary = () => `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 rerun with captureMode=deep only when you need richer evidence.`;
|
|
9777
|
+
var buildInspiredesignNextStep = () => `${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}.`;
|
|
9778
|
+
|
|
9486
9779
|
// src/providers/renderer.ts
|
|
9487
9780
|
var toCurrency = (value) => `$${value.toFixed(2)}`;
|
|
9488
9781
|
var primaryConstraintSummaryFromMeta = (meta) => {
|
|
@@ -9517,22 +9810,225 @@ var renderResearch = (args) => {
|
|
|
9517
9810
|
"```"
|
|
9518
9811
|
].join("\n");
|
|
9519
9812
|
const contextPayload = {
|
|
9520
|
-
topic: args.topic,
|
|
9521
|
-
highlights: lines,
|
|
9522
|
-
records: args.records,
|
|
9813
|
+
topic: args.topic,
|
|
9814
|
+
highlights: lines,
|
|
9815
|
+
records: args.records,
|
|
9816
|
+
meta: args.meta
|
|
9817
|
+
};
|
|
9818
|
+
const files = [
|
|
9819
|
+
{ path: "summary.md", content: markdown },
|
|
9820
|
+
{ path: "records.json", content: { records: args.records } },
|
|
9821
|
+
{ path: "context.json", content: contextPayload },
|
|
9822
|
+
{ path: "meta.json", content: args.meta }
|
|
9823
|
+
];
|
|
9824
|
+
if (args.mode === "compact") {
|
|
9825
|
+
return {
|
|
9826
|
+
response: {
|
|
9827
|
+
mode: args.mode,
|
|
9828
|
+
summary,
|
|
9829
|
+
meta: args.meta
|
|
9830
|
+
},
|
|
9831
|
+
files
|
|
9832
|
+
};
|
|
9833
|
+
}
|
|
9834
|
+
if (args.mode === "json") {
|
|
9835
|
+
return {
|
|
9836
|
+
response: {
|
|
9837
|
+
mode: args.mode,
|
|
9838
|
+
records: args.records,
|
|
9839
|
+
meta: args.meta
|
|
9840
|
+
},
|
|
9841
|
+
files
|
|
9842
|
+
};
|
|
9843
|
+
}
|
|
9844
|
+
if (args.mode === "md") {
|
|
9845
|
+
return {
|
|
9846
|
+
response: {
|
|
9847
|
+
mode: args.mode,
|
|
9848
|
+
markdown,
|
|
9849
|
+
meta: args.meta
|
|
9850
|
+
},
|
|
9851
|
+
files
|
|
9852
|
+
};
|
|
9853
|
+
}
|
|
9854
|
+
if (args.mode === "context") {
|
|
9855
|
+
return {
|
|
9856
|
+
response: {
|
|
9857
|
+
mode: args.mode,
|
|
9858
|
+
context: contextPayload,
|
|
9859
|
+
meta: args.meta
|
|
9860
|
+
},
|
|
9861
|
+
files
|
|
9862
|
+
};
|
|
9863
|
+
}
|
|
9864
|
+
return {
|
|
9865
|
+
response: {
|
|
9866
|
+
mode: "path",
|
|
9867
|
+
meta: args.meta
|
|
9868
|
+
},
|
|
9869
|
+
files
|
|
9870
|
+
};
|
|
9871
|
+
};
|
|
9872
|
+
var toComparisonCsv = (offers) => {
|
|
9873
|
+
const header = ["provider", "title", "price", "shipping", "deal_score", "availability", "url"].join(",");
|
|
9874
|
+
const rows = offers.map((offer) => {
|
|
9875
|
+
return [
|
|
9876
|
+
offer.provider,
|
|
9877
|
+
JSON.stringify(offer.title),
|
|
9878
|
+
offer.price.amount.toFixed(2),
|
|
9879
|
+
offer.shipping.amount.toFixed(2),
|
|
9880
|
+
offer.deal_score.toFixed(4),
|
|
9881
|
+
offer.availability,
|
|
9882
|
+
canonicalizeUrl(offer.url)
|
|
9883
|
+
].join(",");
|
|
9884
|
+
});
|
|
9885
|
+
return [header, ...rows].join("\n");
|
|
9886
|
+
};
|
|
9887
|
+
var compactShoppingLines = (offers, meta) => {
|
|
9888
|
+
if (offers.length === 0) {
|
|
9889
|
+
const summary = primaryConstraintSummaryFromMeta(meta);
|
|
9890
|
+
return summary ? [
|
|
9891
|
+
"No offers available from the selected providers.",
|
|
9892
|
+
`Primary constraint: ${summary}`
|
|
9893
|
+
] : ["No offers available from the selected providers."];
|
|
9894
|
+
}
|
|
9895
|
+
return offers.slice(0, 10).map((offer, index) => {
|
|
9896
|
+
const total = offer.price.amount + offer.shipping.amount;
|
|
9897
|
+
return `${index + 1}. ${offer.title} - ${toCurrency(total)} (${offer.provider}, deal=${offer.deal_score.toFixed(2)})`;
|
|
9898
|
+
});
|
|
9899
|
+
};
|
|
9900
|
+
var renderShopping = (args) => {
|
|
9901
|
+
const lines = compactShoppingLines(args.offers, args.meta);
|
|
9902
|
+
const markdown = [
|
|
9903
|
+
`# Shopping: ${args.query}`,
|
|
9904
|
+
"",
|
|
9905
|
+
...lines,
|
|
9906
|
+
"",
|
|
9907
|
+
"## Metadata",
|
|
9908
|
+
"```json",
|
|
9909
|
+
JSON.stringify(args.meta, null, 2),
|
|
9910
|
+
"```"
|
|
9911
|
+
].join("\n");
|
|
9912
|
+
const comparisonCsv = toComparisonCsv(args.offers);
|
|
9913
|
+
const contextPayload = {
|
|
9914
|
+
query: args.query,
|
|
9915
|
+
highlights: lines,
|
|
9916
|
+
offers: args.offers,
|
|
9917
|
+
meta: args.meta
|
|
9918
|
+
};
|
|
9919
|
+
const files = [
|
|
9920
|
+
{ path: "deals.md", content: markdown },
|
|
9921
|
+
{ path: "offers.json", content: { offers: args.offers } },
|
|
9922
|
+
{ path: "comparison.csv", content: comparisonCsv },
|
|
9923
|
+
{ path: "meta.json", content: args.meta },
|
|
9924
|
+
{ path: "deals-context.json", content: contextPayload }
|
|
9925
|
+
];
|
|
9926
|
+
if (args.mode === "compact") {
|
|
9927
|
+
return {
|
|
9928
|
+
response: {
|
|
9929
|
+
mode: args.mode,
|
|
9930
|
+
summary: lines.join("\n"),
|
|
9931
|
+
meta: args.meta
|
|
9932
|
+
},
|
|
9933
|
+
files
|
|
9934
|
+
};
|
|
9935
|
+
}
|
|
9936
|
+
if (args.mode === "json") {
|
|
9937
|
+
return {
|
|
9938
|
+
response: {
|
|
9939
|
+
mode: args.mode,
|
|
9940
|
+
offers: args.offers,
|
|
9941
|
+
meta: args.meta
|
|
9942
|
+
},
|
|
9943
|
+
files
|
|
9944
|
+
};
|
|
9945
|
+
}
|
|
9946
|
+
if (args.mode === "md") {
|
|
9947
|
+
return {
|
|
9948
|
+
response: {
|
|
9949
|
+
mode: args.mode,
|
|
9950
|
+
markdown,
|
|
9951
|
+
meta: args.meta
|
|
9952
|
+
},
|
|
9953
|
+
files
|
|
9954
|
+
};
|
|
9955
|
+
}
|
|
9956
|
+
if (args.mode === "context") {
|
|
9957
|
+
return {
|
|
9958
|
+
response: {
|
|
9959
|
+
mode: args.mode,
|
|
9960
|
+
context: contextPayload,
|
|
9961
|
+
meta: args.meta
|
|
9962
|
+
},
|
|
9963
|
+
files
|
|
9964
|
+
};
|
|
9965
|
+
}
|
|
9966
|
+
return {
|
|
9967
|
+
response: {
|
|
9968
|
+
mode: "path",
|
|
9969
|
+
meta: args.meta
|
|
9970
|
+
},
|
|
9971
|
+
files
|
|
9972
|
+
};
|
|
9973
|
+
};
|
|
9974
|
+
var renderInspiredesign = (args) => {
|
|
9975
|
+
const summary = [
|
|
9976
|
+
`Brief: ${args.brief}`,
|
|
9977
|
+
`References: ${args.urls.length}`,
|
|
9978
|
+
`Profile: ${args.generationPlan.visualDirection.profile}`
|
|
9979
|
+
].join("\n");
|
|
9980
|
+
const contextPayload = {
|
|
9981
|
+
brief: args.brief,
|
|
9982
|
+
urls: args.urls,
|
|
9983
|
+
designContract: args.designContract,
|
|
9984
|
+
canvasPlanRequest: args.canvasPlanRequest,
|
|
9985
|
+
designAgentHandoff: args.designAgentHandoff,
|
|
9986
|
+
generationPlan: args.generationPlan,
|
|
9987
|
+
implementationPlan: args.implementationPlan,
|
|
9988
|
+
designMarkdown: args.designMarkdown,
|
|
9989
|
+
implementationPlanMarkdown: args.implementationPlanMarkdown,
|
|
9990
|
+
prototypeGuidanceMarkdown: args.prototypeGuidanceMarkdown,
|
|
9991
|
+
evidence: args.evidence,
|
|
9523
9992
|
meta: args.meta
|
|
9524
9993
|
};
|
|
9994
|
+
const suggestedSteps = [
|
|
9995
|
+
{
|
|
9996
|
+
reason: "Load the baseline workflow runbook before implementation.",
|
|
9997
|
+
command: args.designAgentHandoff.commandExamples.loadBestPractices
|
|
9998
|
+
},
|
|
9999
|
+
{
|
|
10000
|
+
reason: "Load the Canvas contract lane before patching.",
|
|
10001
|
+
command: args.designAgentHandoff.commandExamples.loadDesignAgent
|
|
10002
|
+
},
|
|
10003
|
+
{
|
|
10004
|
+
reason: INSPIREDESIGN_HANDOFF_GUIDANCE.prepareCanvasPlanRequest,
|
|
10005
|
+
command: args.designAgentHandoff.commandExamples.continueInCanvas
|
|
10006
|
+
},
|
|
10007
|
+
{
|
|
10008
|
+
reason: args.designAgentHandoff.deepCaptureRecommendation
|
|
10009
|
+
}
|
|
10010
|
+
];
|
|
9525
10011
|
const files = [
|
|
9526
|
-
{ path:
|
|
9527
|
-
{ path:
|
|
9528
|
-
{ path:
|
|
9529
|
-
{ path:
|
|
10012
|
+
{ path: INSPIREDESIGN_HANDOFF_FILES.designMarkdown, content: args.designMarkdown },
|
|
10013
|
+
{ path: INSPIREDESIGN_HANDOFF_FILES.designContract, content: args.designContract },
|
|
10014
|
+
{ path: INSPIREDESIGN_HANDOFF_FILES.canvasPlanRequest, content: args.canvasPlanRequest },
|
|
10015
|
+
{ path: INSPIREDESIGN_HANDOFF_FILES.designAgentHandoff, content: args.designAgentHandoff },
|
|
10016
|
+
{ path: INSPIREDESIGN_HANDOFF_FILES.generationPlan, content: args.generationPlan },
|
|
10017
|
+
{ path: INSPIREDESIGN_HANDOFF_FILES.implementationPlanMarkdown, content: args.implementationPlanMarkdown },
|
|
10018
|
+
{ path: INSPIREDESIGN_HANDOFF_FILES.implementationPlan, content: args.implementationPlan },
|
|
10019
|
+
{ path: INSPIREDESIGN_HANDOFF_FILES.evidence, content: args.evidence }
|
|
9530
10020
|
];
|
|
10021
|
+
if (args.prototypeGuidanceMarkdown) {
|
|
10022
|
+
files.push({ path: INSPIREDESIGN_HANDOFF_FILES.prototypeGuidance, content: args.prototypeGuidanceMarkdown });
|
|
10023
|
+
}
|
|
9531
10024
|
if (args.mode === "compact") {
|
|
9532
10025
|
return {
|
|
9533
10026
|
response: {
|
|
9534
10027
|
mode: args.mode,
|
|
9535
10028
|
summary,
|
|
10029
|
+
followthroughSummary: args.designAgentHandoff.summary,
|
|
10030
|
+
suggestedNextAction: args.designAgentHandoff.nextStep,
|
|
10031
|
+
suggestedSteps,
|
|
9536
10032
|
meta: args.meta
|
|
9537
10033
|
},
|
|
9538
10034
|
files
|
|
@@ -9542,7 +10038,18 @@ var renderResearch = (args) => {
|
|
|
9542
10038
|
return {
|
|
9543
10039
|
response: {
|
|
9544
10040
|
mode: args.mode,
|
|
9545
|
-
|
|
10041
|
+
brief: args.brief,
|
|
10042
|
+
urls: args.urls,
|
|
10043
|
+
canvasPlanRequest: args.canvasPlanRequest,
|
|
10044
|
+
designAgentHandoff: args.designAgentHandoff,
|
|
10045
|
+
designContract: args.designContract,
|
|
10046
|
+
generationPlan: args.generationPlan,
|
|
10047
|
+
implementationPlan: args.implementationPlan,
|
|
10048
|
+
prototypeGuidanceMarkdown: args.prototypeGuidanceMarkdown,
|
|
10049
|
+
evidence: args.evidence,
|
|
10050
|
+
followthroughSummary: args.designAgentHandoff.summary,
|
|
10051
|
+
suggestedNextAction: args.designAgentHandoff.nextStep,
|
|
10052
|
+
suggestedSteps,
|
|
9546
10053
|
meta: args.meta
|
|
9547
10054
|
},
|
|
9548
10055
|
files
|
|
@@ -9552,7 +10059,12 @@ var renderResearch = (args) => {
|
|
|
9552
10059
|
return {
|
|
9553
10060
|
response: {
|
|
9554
10061
|
mode: args.mode,
|
|
9555
|
-
markdown,
|
|
10062
|
+
markdown: args.designMarkdown,
|
|
10063
|
+
implementationPlanMarkdown: args.implementationPlanMarkdown,
|
|
10064
|
+
prototypeGuidanceMarkdown: args.prototypeGuidanceMarkdown,
|
|
10065
|
+
followthroughSummary: args.designAgentHandoff.summary,
|
|
10066
|
+
suggestedNextAction: args.designAgentHandoff.nextStep,
|
|
10067
|
+
suggestedSteps,
|
|
9556
10068
|
meta: args.meta
|
|
9557
10069
|
},
|
|
9558
10070
|
files
|
|
@@ -9563,6 +10075,9 @@ var renderResearch = (args) => {
|
|
|
9563
10075
|
response: {
|
|
9564
10076
|
mode: args.mode,
|
|
9565
10077
|
context: contextPayload,
|
|
10078
|
+
followthroughSummary: args.designAgentHandoff.summary,
|
|
10079
|
+
suggestedNextAction: args.designAgentHandoff.nextStep,
|
|
10080
|
+
suggestedSteps,
|
|
9566
10081
|
meta: args.meta
|
|
9567
10082
|
},
|
|
9568
10083
|
files
|
|
@@ -9571,116 +10086,1209 @@ var renderResearch = (args) => {
|
|
|
9571
10086
|
return {
|
|
9572
10087
|
response: {
|
|
9573
10088
|
mode: "path",
|
|
10089
|
+
followthroughSummary: args.designAgentHandoff.summary,
|
|
10090
|
+
suggestedNextAction: args.designAgentHandoff.nextStep,
|
|
10091
|
+
suggestedSteps,
|
|
9574
10092
|
meta: args.meta
|
|
9575
10093
|
},
|
|
9576
10094
|
files
|
|
9577
10095
|
};
|
|
9578
10096
|
};
|
|
9579
|
-
|
|
9580
|
-
|
|
9581
|
-
|
|
9582
|
-
|
|
9583
|
-
|
|
9584
|
-
|
|
9585
|
-
|
|
9586
|
-
|
|
9587
|
-
|
|
9588
|
-
|
|
9589
|
-
|
|
9590
|
-
|
|
9591
|
-
|
|
9592
|
-
|
|
10097
|
+
|
|
10098
|
+
// src/providers/inspiredesign-contract.ts
|
|
10099
|
+
import { createHash as createHash3 } from "crypto";
|
|
10100
|
+
|
|
10101
|
+
// skills/opendevbrowser-design-agent/assets/templates/canvas-generation-plan.design.v1.json
|
|
10102
|
+
var canvas_generation_plan_design_v1_default = {
|
|
10103
|
+
requestId: "req_plan_design_01",
|
|
10104
|
+
canvasSessionId: "<canvas-session-id>",
|
|
10105
|
+
leaseId: "<lease-id>",
|
|
10106
|
+
documentId: "<document-id>",
|
|
10107
|
+
generationPlan: {
|
|
10108
|
+
targetOutcome: {
|
|
10109
|
+
mode: "high-fi-live-edit",
|
|
10110
|
+
summary: "Clarify hierarchy, trust, and action flow"
|
|
10111
|
+
},
|
|
10112
|
+
visualDirection: {
|
|
10113
|
+
profile: "product-story",
|
|
10114
|
+
themeStrategy: "single-theme"
|
|
10115
|
+
},
|
|
10116
|
+
layoutStrategy: {
|
|
10117
|
+
approach: "hero-led-grid",
|
|
10118
|
+
navigationModel: "global-header"
|
|
10119
|
+
},
|
|
10120
|
+
contentStrategy: {
|
|
10121
|
+
source: "real-content-first"
|
|
10122
|
+
},
|
|
10123
|
+
componentStrategy: {
|
|
10124
|
+
mode: "reuse-first",
|
|
10125
|
+
interactionStates: [
|
|
10126
|
+
"default",
|
|
10127
|
+
"hover",
|
|
10128
|
+
"focus",
|
|
10129
|
+
"disabled"
|
|
10130
|
+
]
|
|
10131
|
+
},
|
|
10132
|
+
motionPosture: {
|
|
10133
|
+
level: "subtle",
|
|
10134
|
+
reducedMotion: "respect-user-preference"
|
|
10135
|
+
},
|
|
10136
|
+
responsivePosture: {
|
|
10137
|
+
primaryViewport: "desktop",
|
|
10138
|
+
requiredViewports: [
|
|
10139
|
+
"desktop",
|
|
10140
|
+
"tablet",
|
|
10141
|
+
"mobile"
|
|
10142
|
+
]
|
|
10143
|
+
},
|
|
10144
|
+
accessibilityPosture: {
|
|
10145
|
+
target: "WCAG_2_2_AA",
|
|
10146
|
+
keyboardNavigation: "full"
|
|
10147
|
+
},
|
|
10148
|
+
validationTargets: {
|
|
10149
|
+
blockOn: [
|
|
10150
|
+
"contrast-failure",
|
|
10151
|
+
"responsive-mismatch"
|
|
10152
|
+
],
|
|
10153
|
+
requiredThemes: [
|
|
10154
|
+
"light"
|
|
10155
|
+
],
|
|
10156
|
+
browserValidation: "required",
|
|
10157
|
+
maxInteractionLatencyMs: 160
|
|
10158
|
+
}
|
|
10159
|
+
}
|
|
9593
10160
|
};
|
|
9594
|
-
|
|
9595
|
-
|
|
9596
|
-
|
|
9597
|
-
|
|
9598
|
-
|
|
9599
|
-
|
|
9600
|
-
|
|
10161
|
+
|
|
10162
|
+
// skills/opendevbrowser-design-agent/assets/templates/design-contract.v1.json
|
|
10163
|
+
var design_contract_v1_default = {
|
|
10164
|
+
intent: {
|
|
10165
|
+
audience: "Operators evaluating a new OpenDevBrowser design flow",
|
|
10166
|
+
task: "Understand the primary page value and complete the intended action quickly",
|
|
10167
|
+
successCriteria: [
|
|
10168
|
+
"Primary action is obvious within 5 seconds",
|
|
10169
|
+
"Layout remains coherent on desktop, tablet, and mobile"
|
|
10170
|
+
],
|
|
10171
|
+
trustPosture: "clear and confident"
|
|
10172
|
+
},
|
|
10173
|
+
designLanguage: {
|
|
10174
|
+
direction: "product-led clarity",
|
|
10175
|
+
styleAxes: {
|
|
10176
|
+
contrast: "high",
|
|
10177
|
+
density: "airy",
|
|
10178
|
+
shapeLanguage: "rounded-structured",
|
|
10179
|
+
depth: "subtle",
|
|
10180
|
+
texture: "minimal",
|
|
10181
|
+
motion: "purposeful"
|
|
10182
|
+
},
|
|
10183
|
+
approvedLibraries: {
|
|
10184
|
+
components: [
|
|
10185
|
+
"shadcn"
|
|
10186
|
+
],
|
|
10187
|
+
icons: [
|
|
10188
|
+
"tabler"
|
|
10189
|
+
],
|
|
10190
|
+
styling: [
|
|
10191
|
+
"tailwindcss"
|
|
10192
|
+
]
|
|
10193
|
+
},
|
|
10194
|
+
semanticTokenSource: {
|
|
10195
|
+
owner: "app-shell theme provider",
|
|
10196
|
+
tokens: [
|
|
10197
|
+
"color",
|
|
10198
|
+
"typography",
|
|
10199
|
+
"spacing",
|
|
10200
|
+
"radius",
|
|
10201
|
+
"shadow",
|
|
10202
|
+
"motion"
|
|
10203
|
+
],
|
|
10204
|
+
rule: "Use semantic tokens in repeated UI; reserve raw values for rare one-off illustration"
|
|
10205
|
+
}
|
|
10206
|
+
},
|
|
10207
|
+
contentModel: {
|
|
10208
|
+
primaryMessage: "Show the core value immediately with real copy",
|
|
10209
|
+
supportingMessages: [
|
|
10210
|
+
"Reinforce trust",
|
|
10211
|
+
"Clarify the primary action",
|
|
10212
|
+
"Reduce ambiguity"
|
|
10213
|
+
],
|
|
10214
|
+
realContentRequired: true,
|
|
10215
|
+
states: [
|
|
10216
|
+
"default",
|
|
10217
|
+
"hover",
|
|
10218
|
+
"focus",
|
|
10219
|
+
"empty",
|
|
10220
|
+
"loading",
|
|
10221
|
+
"success",
|
|
10222
|
+
"error"
|
|
10223
|
+
],
|
|
10224
|
+
loadingStrategy: "Preserve the final layout with 3-6 placeholders or one section-level loader when structure cannot be previewed",
|
|
10225
|
+
emptyStateStrategy: "Explain why nothing is shown and provide the next useful action",
|
|
10226
|
+
errorStateStrategy: "Keep retry or recovery actions close to the failed region",
|
|
10227
|
+
transientFeedbackStrategy: "Use short, non-blocking overlays for confirmations instead of reflowing the main layout",
|
|
10228
|
+
avoidPlaceholderCopy: true
|
|
10229
|
+
},
|
|
10230
|
+
navigationModel: {
|
|
10231
|
+
owner: "feature shell route controller",
|
|
10232
|
+
primaryRouteModel: "One canonical route map translates tabs, selected records, and editor modes into URL-backed state",
|
|
10233
|
+
deepLinkPolicy: "Shareable tabs, filters, sort, and selected entities stay in the URL with a safe fallback when params are stale or incomplete",
|
|
10234
|
+
invalidRouteFallback: "Recover to the closest safe baseline view instead of leaving the screen in a partially initialized state",
|
|
10235
|
+
overlayEntryPoints: [
|
|
10236
|
+
"route-owned detail drawer",
|
|
10237
|
+
"feature-owned confirmation modal"
|
|
10238
|
+
]
|
|
10239
|
+
},
|
|
10240
|
+
asyncModel: {
|
|
10241
|
+
owner: "feature-local controller with URL-owned query state when sharing or refresh matters",
|
|
10242
|
+
loadTrigger: "load-on-enter for the first view; debounced restart on query, scope, or sort change",
|
|
10243
|
+
restartTriggers: [
|
|
10244
|
+
"query",
|
|
10245
|
+
"scope",
|
|
10246
|
+
"sort"
|
|
10247
|
+
],
|
|
10248
|
+
debounceMs: 250,
|
|
10249
|
+
emptyQueryBehavior: "Reset to the baseline or empty state without a remote fetch unless the product explicitly needs default results",
|
|
10250
|
+
cancellationPolicy: "Treat stale requests as normal and do not surface cancellation as a user-facing error",
|
|
10251
|
+
moveToServiceWhen: [
|
|
10252
|
+
"work must survive dismissal",
|
|
10253
|
+
"caching or retry policy becomes shared",
|
|
10254
|
+
"multiple screens depend on the same in-flight state"
|
|
10255
|
+
],
|
|
10256
|
+
urlOwnership: "Put query, filter, and sort in the URL when the state should survive refresh, sharing, or handoff"
|
|
10257
|
+
},
|
|
10258
|
+
layoutSystem: {
|
|
10259
|
+
grid: "12-column responsive grid",
|
|
10260
|
+
containers: "max-width sections with asymmetric emphasis",
|
|
10261
|
+
spacingRhythm: "8px base with larger section jumps",
|
|
10262
|
+
alignmentRules: [
|
|
10263
|
+
"Primary content aligns to a consistent reading column",
|
|
10264
|
+
"Actions stay near the message they complete"
|
|
10265
|
+
]
|
|
10266
|
+
},
|
|
10267
|
+
typographySystem: {
|
|
10268
|
+
families: [
|
|
10269
|
+
"Space Grotesk",
|
|
10270
|
+
"Source Sans 3"
|
|
10271
|
+
],
|
|
10272
|
+
scale: [
|
|
10273
|
+
"12",
|
|
10274
|
+
"14",
|
|
10275
|
+
"16",
|
|
10276
|
+
"20",
|
|
10277
|
+
"28",
|
|
10278
|
+
"40",
|
|
10279
|
+
"56"
|
|
10280
|
+
],
|
|
10281
|
+
measure: "60-72 characters for dense reading blocks",
|
|
10282
|
+
fallbackPolicy: "Use repo-native or licensed alternatives when these families are unavailable",
|
|
10283
|
+
loadingStrategy: "Avoid layout shift and keep fallback metrics close"
|
|
10284
|
+
},
|
|
10285
|
+
motionSystem: {
|
|
10286
|
+
timing: "short and decisive",
|
|
10287
|
+
reducedMotionPolicy: "Preserve meaning with reduced movement",
|
|
10288
|
+
interactionMoments: [
|
|
10289
|
+
"page entry",
|
|
10290
|
+
"section reveal",
|
|
10291
|
+
"primary CTA feedback"
|
|
10292
|
+
],
|
|
10293
|
+
parallaxPolicy: "off unless explicitly justified"
|
|
10294
|
+
},
|
|
10295
|
+
performanceModel: {
|
|
10296
|
+
renderHotspots: [
|
|
10297
|
+
"scan-heavy collection region",
|
|
10298
|
+
"secondary inspector or preview pane"
|
|
10299
|
+
],
|
|
10300
|
+
stableIdentityPolicy: "Rows, cards, tabs, and overlays use stable domain ids instead of array indexes",
|
|
10301
|
+
listStrategy: "Use the smallest structure that stays fast with realistic data; choose progressive reveal, lazy containers, or virtualization deliberately",
|
|
10302
|
+
secondaryPanelPolicy: "Heavy inspectors, previews, and editors load on demand when they are not required for first paint",
|
|
10303
|
+
measurementPlan: "Validate realistic data volume with browser traces and the framework profiler before claiming the surface is performant"
|
|
10304
|
+
},
|
|
10305
|
+
responsiveSystem: {
|
|
10306
|
+
breakpoints: [
|
|
10307
|
+
"mobile",
|
|
10308
|
+
"tablet",
|
|
10309
|
+
"desktop"
|
|
10310
|
+
],
|
|
10311
|
+
adaptationRules: [
|
|
10312
|
+
"Collapse multicolumn sections before copy becomes cramped",
|
|
10313
|
+
"Preserve primary CTA prominence on the smallest viewport"
|
|
10314
|
+
],
|
|
10315
|
+
touchPolicy: "Comfortable targets and low-friction scroll paths",
|
|
10316
|
+
overflowPolicy: "No horizontal scroll for primary content"
|
|
10317
|
+
},
|
|
10318
|
+
accessibilityPolicy: {
|
|
10319
|
+
target: "WCAG 2.2 AA",
|
|
10320
|
+
keyboardRequirements: [
|
|
10321
|
+
"Visible focus",
|
|
10322
|
+
"Logical tab order"
|
|
10323
|
+
],
|
|
10324
|
+
focusPolicy: "Focus rings must remain visible against every background",
|
|
10325
|
+
semanticRequirements: [
|
|
10326
|
+
"Landmarks are explicit",
|
|
10327
|
+
"Headings remain hierarchical"
|
|
10328
|
+
]
|
|
10329
|
+
},
|
|
10330
|
+
generationPlan: {
|
|
10331
|
+
targetOutcome: {
|
|
10332
|
+
mode: "high-fi-live-edit",
|
|
10333
|
+
summary: "Improve hierarchy, clarity, and conversion confidence"
|
|
10334
|
+
},
|
|
10335
|
+
visualDirection: {
|
|
10336
|
+
profile: "product-led-clarity",
|
|
10337
|
+
styleAxes: {
|
|
10338
|
+
contrast: "high",
|
|
10339
|
+
density: "airy"
|
|
10340
|
+
}
|
|
10341
|
+
},
|
|
10342
|
+
layoutStrategy: {
|
|
10343
|
+
approach: "hero-led-grid"
|
|
10344
|
+
},
|
|
10345
|
+
contentStrategy: {
|
|
10346
|
+
source: "real-content-first"
|
|
10347
|
+
},
|
|
10348
|
+
componentStrategy: {
|
|
10349
|
+
mode: "reuse-first",
|
|
10350
|
+
approvedLibraries: [
|
|
10351
|
+
"shadcn"
|
|
10352
|
+
]
|
|
10353
|
+
},
|
|
10354
|
+
motionPosture: {
|
|
10355
|
+
level: "subtle",
|
|
10356
|
+
allow3D: false,
|
|
10357
|
+
allowParallax: false,
|
|
10358
|
+
allowCustomSmoothScroll: false
|
|
10359
|
+
},
|
|
10360
|
+
responsivePosture: {
|
|
10361
|
+
primaryViewport: "desktop",
|
|
10362
|
+
requiredViewports: [
|
|
10363
|
+
"desktop",
|
|
10364
|
+
"tablet",
|
|
10365
|
+
"mobile"
|
|
10366
|
+
]
|
|
10367
|
+
},
|
|
10368
|
+
accessibilityPosture: {
|
|
10369
|
+
target: "WCAG_2_2_AA",
|
|
10370
|
+
reducedMotion: "required",
|
|
10371
|
+
keyboardParity: true
|
|
10372
|
+
},
|
|
10373
|
+
validationTargets: {
|
|
10374
|
+
blockOn: [
|
|
10375
|
+
"contrast-failure",
|
|
10376
|
+
"keyboard-regression",
|
|
10377
|
+
"stale-search-results",
|
|
10378
|
+
"invalid-route-recovery-failure"
|
|
10379
|
+
],
|
|
10380
|
+
warnOn: [
|
|
10381
|
+
"responsive-mismatch",
|
|
10382
|
+
"layout-shift",
|
|
10383
|
+
"spinner-stacking",
|
|
10384
|
+
"scan-surface-jank"
|
|
10385
|
+
]
|
|
10386
|
+
}
|
|
9601
10387
|
}
|
|
9602
|
-
return offers.slice(0, 10).map((offer, index) => {
|
|
9603
|
-
const total = offer.price.amount + offer.shipping.amount;
|
|
9604
|
-
return `${index + 1}. ${offer.title} - ${toCurrency(total)} (${offer.provider}, deal=${offer.deal_score.toFixed(2)})`;
|
|
9605
|
-
});
|
|
9606
10388
|
};
|
|
9607
|
-
|
|
9608
|
-
|
|
9609
|
-
|
|
9610
|
-
|
|
10389
|
+
|
|
10390
|
+
// src/providers/inspiredesign-contract.ts
|
|
10391
|
+
var BASE_CONTRACT_TEMPLATE = design_contract_v1_default;
|
|
10392
|
+
var BASE_PLAN_REQUEST_TEMPLATE = canvas_generation_plan_design_v1_default;
|
|
10393
|
+
var BASE_GENERATION_PLAN = BASE_PLAN_REQUEST_TEMPLATE.generationPlan;
|
|
10394
|
+
var PROFILE_MATCHERS = [
|
|
10395
|
+
{ profile: "auth-focused", keywords: ["auth", "login", "signin", "sign-in", "signup", "sign-up", "onboarding"] },
|
|
10396
|
+
{ profile: "settings-system", keywords: ["settings", "preferences", "account", "profile", "billing"] },
|
|
10397
|
+
{ profile: "ops-control", keywords: ["dashboard", "admin", "control", "analytics", "monitor", "reporting"] },
|
|
10398
|
+
{ profile: "documentation", keywords: ["docs", "documentation", "knowledge base", "reference", "guide"] },
|
|
10399
|
+
{ profile: "commerce-system", keywords: ["shop", "commerce", "pricing", "checkout", "product page", "catalog"] }
|
|
10400
|
+
];
|
|
10401
|
+
var PROFILE_CONFIG = {
|
|
10402
|
+
"clean-room": {
|
|
10403
|
+
direction: "clean-room execution",
|
|
10404
|
+
visualPersonality: "disciplined, quiet, system-first",
|
|
10405
|
+
brandTone: "neutral and exacting",
|
|
10406
|
+
hierarchyPrinciples: ["Keep one message per section.", "Use spacing, not ornament, to separate priority."],
|
|
10407
|
+
interactionPhilosophy: "Minimal motion, zero ambiguity, strong focus affordances.",
|
|
10408
|
+
navigationModel: "contextual",
|
|
10409
|
+
layoutApproach: "modular-grid",
|
|
10410
|
+
pagePatterns: ["Single-message hero", "Dense decision panel", "Clean spec sheet"],
|
|
10411
|
+
componentSequence: ["Buttons", "Inputs", "Decision cards", "Structured tables"],
|
|
10412
|
+
colors: {
|
|
10413
|
+
primary: "#0F172A",
|
|
10414
|
+
accent: "#0F766E",
|
|
10415
|
+
accentSurface: "#E6FFFB",
|
|
10416
|
+
background: "#F8FAFC",
|
|
10417
|
+
surface: "#FFFFFF",
|
|
10418
|
+
border: "#CBD5E1",
|
|
10419
|
+
text: "#0F172A",
|
|
10420
|
+
mutedText: "#475569",
|
|
10421
|
+
success: "#15803D",
|
|
10422
|
+
warning: "#B45309",
|
|
10423
|
+
danger: "#B91C1C"
|
|
10424
|
+
}
|
|
10425
|
+
},
|
|
10426
|
+
"cinematic-minimal": {
|
|
10427
|
+
direction: "cinematic restraint",
|
|
10428
|
+
visualPersonality: "dramatic, sparse, image-led",
|
|
10429
|
+
brandTone: "premium and deliberate",
|
|
10430
|
+
hierarchyPrinciples: ["Let the visual plane carry atmosphere.", "Keep copy short and decisive."],
|
|
10431
|
+
interactionPhilosophy: "Use motion for presence, not explanation.",
|
|
10432
|
+
navigationModel: "immersive",
|
|
10433
|
+
layoutApproach: "full-bleed-hero",
|
|
10434
|
+
pagePatterns: ["Full-bleed hero", "Editorial feature strip", "High-contrast CTA block"],
|
|
10435
|
+
componentSequence: ["Hero shell", "CTA buttons", "Image-led sections", "Minimal footer"],
|
|
10436
|
+
colors: {
|
|
10437
|
+
primary: "#111827",
|
|
10438
|
+
accent: "#C2410C",
|
|
10439
|
+
accentSurface: "#FFF7ED",
|
|
10440
|
+
background: "#F8F5F0",
|
|
10441
|
+
surface: "#FFFFFF",
|
|
10442
|
+
border: "#D6D3D1",
|
|
10443
|
+
text: "#111827",
|
|
10444
|
+
mutedText: "#57534E",
|
|
10445
|
+
success: "#15803D",
|
|
10446
|
+
warning: "#B45309",
|
|
10447
|
+
danger: "#B91C1C"
|
|
10448
|
+
}
|
|
10449
|
+
},
|
|
10450
|
+
"product-story": {
|
|
10451
|
+
direction: "product-led clarity",
|
|
10452
|
+
visualPersonality: "confident, editorial, product-first",
|
|
10453
|
+
brandTone: "clear and ambitious",
|
|
10454
|
+
hierarchyPrinciples: ["Lead with value before proof.", "Keep action close to the message it completes."],
|
|
10455
|
+
interactionPhilosophy: "Short, decisive motion with obvious focus states.",
|
|
10456
|
+
navigationModel: "global-header",
|
|
10457
|
+
layoutApproach: "hero-led-grid",
|
|
10458
|
+
pagePatterns: ["Hero with anchored CTA", "Feature narrative strip", "Proof and conversion band"],
|
|
10459
|
+
componentSequence: ["Hero", "Buttons", "Cards", "Feature sections", "Footer"],
|
|
10460
|
+
colors: {
|
|
10461
|
+
primary: "#0B6BFF",
|
|
10462
|
+
accent: "#F97316",
|
|
10463
|
+
accentSurface: "#FFF7ED",
|
|
10464
|
+
background: "#F5F7FB",
|
|
10465
|
+
surface: "#FFFFFF",
|
|
10466
|
+
border: "#D7E3F4",
|
|
10467
|
+
text: "#111827",
|
|
10468
|
+
mutedText: "#475569",
|
|
10469
|
+
success: "#15803D",
|
|
10470
|
+
warning: "#B45309",
|
|
10471
|
+
danger: "#B91C1C"
|
|
10472
|
+
}
|
|
10473
|
+
},
|
|
10474
|
+
"commerce-system": {
|
|
10475
|
+
direction: "trust-driven commerce",
|
|
10476
|
+
visualPersonality: "decisive, reassuring, conversion-aware",
|
|
10477
|
+
brandTone: "credible and practical",
|
|
10478
|
+
hierarchyPrinciples: ["Keep purchasing signals scannable.", "Surface trust proof before commitment moments."],
|
|
10479
|
+
interactionPhilosophy: "Fast feedback, strong affordances, no ambiguous states.",
|
|
10480
|
+
navigationModel: "global-header",
|
|
10481
|
+
layoutApproach: "commerce-grid",
|
|
10482
|
+
pagePatterns: ["Merchandising hero", "Offer comparison band", "Decision-support detail section"],
|
|
10483
|
+
componentSequence: ["Hero", "Offer cards", "Buttons", "Trust badges", "Comparison table"],
|
|
10484
|
+
colors: {
|
|
10485
|
+
primary: "#0F766E",
|
|
10486
|
+
accent: "#D97706",
|
|
10487
|
+
accentSurface: "#FFFBEB",
|
|
10488
|
+
background: "#F8FAFC",
|
|
10489
|
+
surface: "#FFFFFF",
|
|
10490
|
+
border: "#D1D5DB",
|
|
10491
|
+
text: "#111827",
|
|
10492
|
+
mutedText: "#4B5563",
|
|
10493
|
+
success: "#15803D",
|
|
10494
|
+
warning: "#B45309",
|
|
10495
|
+
danger: "#B91C1C"
|
|
10496
|
+
}
|
|
10497
|
+
},
|
|
10498
|
+
"control-room": {
|
|
10499
|
+
direction: "high-signal control room",
|
|
10500
|
+
visualPersonality: "dense, sharp, operational",
|
|
10501
|
+
brandTone: "authoritative and fast",
|
|
10502
|
+
hierarchyPrinciples: ["Use structure to reduce scanning cost.", "Separate primary metrics from diagnostics."],
|
|
10503
|
+
interactionPhilosophy: "Fast updates, explicit states, motion only when it clarifies change.",
|
|
10504
|
+
navigationModel: "sidebar",
|
|
10505
|
+
layoutApproach: "panel-grid",
|
|
10506
|
+
pagePatterns: ["Metric summary rail", "Split-pane workspace", "Diagnostic detail panel"],
|
|
10507
|
+
componentSequence: ["Sidebar", "Stat blocks", "Tables", "Filters", "Panels"],
|
|
10508
|
+
colors: {
|
|
10509
|
+
primary: "#155EEF",
|
|
10510
|
+
accent: "#0F766E",
|
|
10511
|
+
accentSurface: "#ECFDF3",
|
|
10512
|
+
background: "#F8FAFC",
|
|
10513
|
+
surface: "#FFFFFF",
|
|
10514
|
+
border: "#CBD5E1",
|
|
10515
|
+
text: "#0F172A",
|
|
10516
|
+
mutedText: "#475569",
|
|
10517
|
+
success: "#15803D",
|
|
10518
|
+
warning: "#B45309",
|
|
10519
|
+
danger: "#B91C1C"
|
|
10520
|
+
}
|
|
10521
|
+
},
|
|
10522
|
+
"ops-control": {
|
|
10523
|
+
direction: "operational precision",
|
|
10524
|
+
visualPersonality: "structured, dense, high-confidence",
|
|
10525
|
+
brandTone: "decisive and exact",
|
|
10526
|
+
hierarchyPrinciples: ["Pin the primary metric and action path.", "Separate overview from detail panes."],
|
|
10527
|
+
interactionPhilosophy: "Low-latency controls, strong state contrast, keyboard-friendly flows.",
|
|
10528
|
+
navigationModel: "sidebar",
|
|
10529
|
+
layoutApproach: "workspace-shell",
|
|
10530
|
+
pagePatterns: ["KPI overview bar", "Filterable data shell", "Detail drawer or inspector"],
|
|
10531
|
+
componentSequence: ["Sidebar", "Toolbar", "Data table", "Filters", "Detail panel"],
|
|
10532
|
+
colors: {
|
|
10533
|
+
primary: "#155EEF",
|
|
10534
|
+
accent: "#0891B2",
|
|
10535
|
+
accentSurface: "#ECFEFF",
|
|
10536
|
+
background: "#F8FAFC",
|
|
10537
|
+
surface: "#FFFFFF",
|
|
10538
|
+
border: "#CBD5E1",
|
|
10539
|
+
text: "#0F172A",
|
|
10540
|
+
mutedText: "#475569",
|
|
10541
|
+
success: "#15803D",
|
|
10542
|
+
warning: "#B45309",
|
|
10543
|
+
danger: "#B91C1C"
|
|
10544
|
+
}
|
|
10545
|
+
},
|
|
10546
|
+
"auth-focused": {
|
|
10547
|
+
direction: "trust-forward entry flow",
|
|
10548
|
+
visualPersonality: "calm, direct, reassuring",
|
|
10549
|
+
brandTone: "safe and premium",
|
|
10550
|
+
hierarchyPrinciples: ["One job per screen.", "Trust and recovery paths must be visible without clutter."],
|
|
10551
|
+
interactionPhilosophy: "Low-friction focus flow with immediate validation feedback.",
|
|
10552
|
+
navigationModel: "contextual",
|
|
10553
|
+
layoutApproach: "two-panel-auth",
|
|
10554
|
+
pagePatterns: ["Auth split layout", "Trust panel", "Recovery and help strip"],
|
|
10555
|
+
componentSequence: ["Auth form", "Inputs", "Buttons", "Alerts", "Trust panel"],
|
|
10556
|
+
colors: {
|
|
10557
|
+
primary: "#1D4ED8",
|
|
10558
|
+
accent: "#0F766E",
|
|
10559
|
+
accentSurface: "#ECFDF5",
|
|
10560
|
+
background: "#F8FAFC",
|
|
10561
|
+
surface: "#FFFFFF",
|
|
10562
|
+
border: "#D1D5DB",
|
|
10563
|
+
text: "#111827",
|
|
10564
|
+
mutedText: "#4B5563",
|
|
10565
|
+
success: "#15803D",
|
|
10566
|
+
warning: "#B45309",
|
|
10567
|
+
danger: "#B91C1C"
|
|
10568
|
+
}
|
|
10569
|
+
},
|
|
10570
|
+
"settings-system": {
|
|
10571
|
+
direction: "calm settings system",
|
|
10572
|
+
visualPersonality: "ordered, practical, quietly premium",
|
|
10573
|
+
brandTone: "confident and low-friction",
|
|
10574
|
+
hierarchyPrinciples: ["Group related decisions tightly.", "Keep destructive actions isolated and explicit."],
|
|
10575
|
+
interactionPhilosophy: "Prefer clear toggles and inline explanations over hidden complexity.",
|
|
10576
|
+
navigationModel: "tabbed",
|
|
10577
|
+
layoutApproach: "settings-grid",
|
|
10578
|
+
pagePatterns: ["Sectioned settings page", "Inline form groups", "Preference summary rail"],
|
|
10579
|
+
componentSequence: ["Tabs", "Forms", "Inputs", "Alerts", "Confirmation modal"],
|
|
10580
|
+
colors: {
|
|
10581
|
+
primary: "#1D4ED8",
|
|
10582
|
+
accent: "#0F766E",
|
|
10583
|
+
accentSurface: "#ECFDF5",
|
|
10584
|
+
background: "#F8FAFC",
|
|
10585
|
+
surface: "#FFFFFF",
|
|
10586
|
+
border: "#D1D5DB",
|
|
10587
|
+
text: "#111827",
|
|
10588
|
+
mutedText: "#475569",
|
|
10589
|
+
success: "#15803D",
|
|
10590
|
+
warning: "#B45309",
|
|
10591
|
+
danger: "#B91C1C"
|
|
10592
|
+
}
|
|
10593
|
+
},
|
|
10594
|
+
"documentation": {
|
|
10595
|
+
direction: "reference-first documentation",
|
|
10596
|
+
visualPersonality: "legible, calm, highly structured",
|
|
10597
|
+
brandTone: "expert and accessible",
|
|
10598
|
+
hierarchyPrinciples: ["Make scanning effortless.", "Keep code, steps, and warnings visually distinct."],
|
|
10599
|
+
interactionPhilosophy: "Light motion, sticky wayfinding, strong anchor visibility.",
|
|
10600
|
+
navigationModel: "sidebar",
|
|
10601
|
+
layoutApproach: "docs-shell",
|
|
10602
|
+
pagePatterns: ["Docs shell", "Procedure section", "Reference table block"],
|
|
10603
|
+
componentSequence: ["Sidebar", "Search", "Anchored headings", "Code blocks", "Callouts"],
|
|
10604
|
+
colors: {
|
|
10605
|
+
primary: "#1D4ED8",
|
|
10606
|
+
accent: "#0F766E",
|
|
10607
|
+
accentSurface: "#ECFDF5",
|
|
10608
|
+
background: "#F8FAFC",
|
|
10609
|
+
surface: "#FFFFFF",
|
|
10610
|
+
border: "#CBD5E1",
|
|
10611
|
+
text: "#0F172A",
|
|
10612
|
+
mutedText: "#475569",
|
|
10613
|
+
success: "#15803D",
|
|
10614
|
+
warning: "#B45309",
|
|
10615
|
+
danger: "#B91C1C"
|
|
10616
|
+
}
|
|
10617
|
+
}
|
|
10618
|
+
};
|
|
10619
|
+
var trimText = (value) => {
|
|
10620
|
+
return value.trim().replace(/\s+/g, " ");
|
|
10621
|
+
};
|
|
10622
|
+
var clipText = (value, maxLength) => {
|
|
10623
|
+
if (value.length <= maxLength) return value;
|
|
10624
|
+
return `${value.slice(0, Math.max(0, maxLength - 3)).trimEnd()}...`;
|
|
10625
|
+
};
|
|
10626
|
+
var cloneTemplate = (value) => structuredClone(value);
|
|
10627
|
+
var referenceFingerprint = (value) => {
|
|
10628
|
+
return createHash3("sha256").update(value).digest("hex").slice(0, 12);
|
|
10629
|
+
};
|
|
10630
|
+
var hasKeyword = (value, keywords) => {
|
|
10631
|
+
const haystack = value.toLowerCase();
|
|
10632
|
+
return keywords.some((keyword) => haystack.includes(keyword));
|
|
10633
|
+
};
|
|
10634
|
+
var classifyProfile = (brief, references) => {
|
|
10635
|
+
const combined = [brief, ...references.map((reference) => `${reference.title ?? ""} ${reference.excerpt ?? ""}`)].join(" ").toLowerCase();
|
|
10636
|
+
return PROFILE_MATCHERS.find((matcher) => hasKeyword(combined, matcher.keywords))?.profile ?? "product-story";
|
|
10637
|
+
};
|
|
10638
|
+
var resolveThemeStrategy = (brief, references) => {
|
|
10639
|
+
const combined = `${brief} ${references.map((reference) => reference.excerpt ?? "").join(" ")}`.toLowerCase();
|
|
10640
|
+
return combined.includes("dark") ? "light-dark-parity" : "single-theme";
|
|
10641
|
+
};
|
|
10642
|
+
var summarizeBrief = (brief) => {
|
|
10643
|
+
const normalized = trimText(brief);
|
|
10644
|
+
const sentence = normalized.split(/[.!?]/).map((part) => part.trim()).find(Boolean);
|
|
10645
|
+
return clipText(sentence ?? normalized, 140);
|
|
10646
|
+
};
|
|
10647
|
+
var buildSupportingMessages = (references) => {
|
|
10648
|
+
const messages = references.map((reference) => reference.title ?? reference.excerpt ?? "").map((value) => clipText(trimText(value), 72)).filter((value) => value.length > 0);
|
|
10649
|
+
return messages.slice(0, 3);
|
|
10650
|
+
};
|
|
10651
|
+
var buildGenerationPlan = (brief, profile, references) => {
|
|
10652
|
+
const plan = cloneTemplate(BASE_GENERATION_PLAN);
|
|
10653
|
+
plan.targetOutcome.summary = summarizeBrief(brief);
|
|
10654
|
+
plan.visualDirection.profile = profile;
|
|
10655
|
+
plan.visualDirection.themeStrategy = resolveThemeStrategy(brief, references);
|
|
10656
|
+
plan.layoutStrategy.approach = PROFILE_CONFIG[profile].layoutApproach;
|
|
10657
|
+
plan.layoutStrategy.navigationModel = PROFILE_CONFIG[profile].navigationModel;
|
|
10658
|
+
plan.componentStrategy.interactionStates = ["default", "hover", "focus", "disabled", "loading"];
|
|
10659
|
+
plan.validationTargets.requiredThemes = plan.visualDirection.themeStrategy === "light-dark-parity" ? ["light", "dark"] : ["light"];
|
|
10660
|
+
return plan;
|
|
10661
|
+
};
|
|
10662
|
+
var buildIntentBlock = (brief, urls, references) => {
|
|
10663
|
+
const intent = cloneTemplate(BASE_CONTRACT_TEMPLATE.intent);
|
|
10664
|
+
return {
|
|
10665
|
+
...intent,
|
|
10666
|
+
task: summarizeBrief(brief),
|
|
10667
|
+
brief,
|
|
10668
|
+
briefHash: referenceFingerprint(brief),
|
|
10669
|
+
referenceCount: references.length,
|
|
10670
|
+
referenceUrls: urls,
|
|
10671
|
+
evidenceStatus: {
|
|
10672
|
+
fetched: references.filter((reference) => reference.fetchStatus === "captured").length,
|
|
10673
|
+
captured: references.filter((reference) => reference.captureStatus === "captured").length
|
|
10674
|
+
}
|
|
10675
|
+
};
|
|
10676
|
+
};
|
|
10677
|
+
var buildDesignLanguageBlock = (profile) => {
|
|
10678
|
+
const block = cloneTemplate(BASE_CONTRACT_TEMPLATE.designLanguage);
|
|
10679
|
+
const config = PROFILE_CONFIG[profile];
|
|
10680
|
+
return {
|
|
10681
|
+
...block,
|
|
10682
|
+
direction: config.direction,
|
|
10683
|
+
visualPersonality: config.visualPersonality,
|
|
10684
|
+
brandTone: config.brandTone
|
|
10685
|
+
};
|
|
10686
|
+
};
|
|
10687
|
+
var buildContentModelBlock = (brief, references) => {
|
|
10688
|
+
const block = cloneTemplate(BASE_CONTRACT_TEMPLATE.contentModel);
|
|
10689
|
+
return {
|
|
10690
|
+
...block,
|
|
10691
|
+
primaryMessage: summarizeBrief(brief),
|
|
10692
|
+
supportingMessages: buildSupportingMessages(references)
|
|
10693
|
+
};
|
|
10694
|
+
};
|
|
10695
|
+
var buildLayoutSystemBlock = (profile) => {
|
|
10696
|
+
const block = cloneTemplate(BASE_CONTRACT_TEMPLATE.layoutSystem);
|
|
10697
|
+
return {
|
|
10698
|
+
...block,
|
|
10699
|
+
pagePatterns: PROFILE_CONFIG[profile].pagePatterns
|
|
10700
|
+
};
|
|
10701
|
+
};
|
|
10702
|
+
var buildTypographySystemBlock = () => {
|
|
10703
|
+
const block = cloneTemplate(BASE_CONTRACT_TEMPLATE.typographySystem);
|
|
10704
|
+
return {
|
|
10705
|
+
...block,
|
|
10706
|
+
tokens: {
|
|
10707
|
+
display: "56/1.0",
|
|
10708
|
+
h1: "40/1.05",
|
|
10709
|
+
h2: "28/1.1",
|
|
10710
|
+
h3: "20/1.2",
|
|
10711
|
+
body: "16/1.6",
|
|
10712
|
+
label: "14/1.4",
|
|
10713
|
+
caption: "12/1.4"
|
|
10714
|
+
}
|
|
10715
|
+
};
|
|
10716
|
+
};
|
|
10717
|
+
var buildColorSystemBlock = (profile) => {
|
|
10718
|
+
const colors = PROFILE_CONFIG[profile].colors;
|
|
10719
|
+
return {
|
|
10720
|
+
paletteName: `${profile}-default`,
|
|
10721
|
+
tokens: colors,
|
|
10722
|
+
contrastRequirements: {
|
|
10723
|
+
bodyText: "4.5:1",
|
|
10724
|
+
largeText: "3:1",
|
|
10725
|
+
focusRing: "3:1"
|
|
10726
|
+
}
|
|
10727
|
+
};
|
|
10728
|
+
};
|
|
10729
|
+
var buildSurfaceSystemBlock = () => ({
|
|
10730
|
+
radiusScale: {
|
|
10731
|
+
xs: "6px",
|
|
10732
|
+
sm: "10px",
|
|
10733
|
+
md: "16px",
|
|
10734
|
+
lg: "24px"
|
|
10735
|
+
},
|
|
10736
|
+
borderPolicy: "Use 1px neutral strokes before adding elevation.",
|
|
10737
|
+
shadowPolicy: {
|
|
10738
|
+
sm: "0 1px 2px rgba(15, 23, 42, 0.06)",
|
|
10739
|
+
md: "0 10px 30px rgba(15, 23, 42, 0.10)",
|
|
10740
|
+
lg: "0 24px 60px rgba(15, 23, 42, 0.14)"
|
|
10741
|
+
}
|
|
10742
|
+
});
|
|
10743
|
+
var buildIconSystemBlock = () => ({
|
|
10744
|
+
family: "tabler",
|
|
10745
|
+
strokeWidth: 1.5,
|
|
10746
|
+
style: "rounded-linear",
|
|
10747
|
+
usageRules: [
|
|
10748
|
+
"Use icons to reinforce labels, not replace them.",
|
|
10749
|
+
"Decorative icons should remain visually lighter than primary copy."
|
|
10750
|
+
]
|
|
10751
|
+
});
|
|
10752
|
+
var buildMotionSystemBlock = () => {
|
|
10753
|
+
const block = cloneTemplate(BASE_CONTRACT_TEMPLATE.motionSystem);
|
|
10754
|
+
return {
|
|
10755
|
+
...block,
|
|
10756
|
+
durations: {
|
|
10757
|
+
quick: "120ms",
|
|
10758
|
+
standard: "180ms",
|
|
10759
|
+
emphasis: "240ms"
|
|
10760
|
+
}
|
|
10761
|
+
};
|
|
10762
|
+
};
|
|
10763
|
+
var buildResponsiveSystemBlock = () => {
|
|
10764
|
+
const block = cloneTemplate(BASE_CONTRACT_TEMPLATE.responsiveSystem);
|
|
10765
|
+
return {
|
|
10766
|
+
...block,
|
|
10767
|
+
breakpoints: {
|
|
10768
|
+
mobile: "0-639px",
|
|
10769
|
+
tablet: "640-1023px",
|
|
10770
|
+
desktop: "1024px+"
|
|
10771
|
+
}
|
|
10772
|
+
};
|
|
10773
|
+
};
|
|
10774
|
+
var buildAccessibilityBlock = () => {
|
|
10775
|
+
const block = cloneTemplate(BASE_CONTRACT_TEMPLATE.accessibilityPolicy);
|
|
10776
|
+
return {
|
|
10777
|
+
...block,
|
|
10778
|
+
reducedMotion: "Respect user preference and preserve information without animation."
|
|
10779
|
+
};
|
|
10780
|
+
};
|
|
10781
|
+
var buildLibraryPolicyBlock = () => ({
|
|
10782
|
+
components: ["shadcn"],
|
|
10783
|
+
icons: ["tabler"],
|
|
10784
|
+
styling: ["tailwindcss"],
|
|
10785
|
+
motion: ["css"],
|
|
10786
|
+
threeD: []
|
|
10787
|
+
});
|
|
10788
|
+
var buildRuntimeBudgetsBlock = (plan) => ({
|
|
10789
|
+
maxHeroActions: 2,
|
|
10790
|
+
maxPrimarySections: 8,
|
|
10791
|
+
maxInteractionLatencyMs: plan.validationTargets.maxInteractionLatencyMs,
|
|
10792
|
+
previewBudgetMs: 1500,
|
|
10793
|
+
notes: [
|
|
10794
|
+
"Keep above-the-fold content inside one visual composition.",
|
|
10795
|
+
"Avoid heavyweight decorative animation before interaction clarity is established."
|
|
10796
|
+
]
|
|
10797
|
+
});
|
|
10798
|
+
var EMITTED_GOVERNANCE_BLOCKS = [
|
|
10799
|
+
"intent",
|
|
10800
|
+
"generationPlan",
|
|
10801
|
+
"designLanguage",
|
|
10802
|
+
"contentModel",
|
|
10803
|
+
"layoutSystem",
|
|
10804
|
+
"typographySystem",
|
|
10805
|
+
"colorSystem",
|
|
10806
|
+
"surfaceSystem",
|
|
10807
|
+
"iconSystem",
|
|
10808
|
+
"motionSystem",
|
|
10809
|
+
"responsiveSystem",
|
|
10810
|
+
"accessibilityPolicy",
|
|
10811
|
+
"libraryPolicy",
|
|
10812
|
+
"runtimeBudgets"
|
|
10813
|
+
];
|
|
10814
|
+
var buildNavigationModelBlock = (profile) => {
|
|
10815
|
+
const block = cloneTemplate(BASE_CONTRACT_TEMPLATE.navigationModel);
|
|
10816
|
+
return {
|
|
10817
|
+
...block,
|
|
10818
|
+
primaryRouteModel: `Use a ${PROFILE_CONFIG[profile].navigationModel} route shell so the primary action remains stable through state changes.`
|
|
10819
|
+
};
|
|
10820
|
+
};
|
|
10821
|
+
var buildAsyncModelBlock = () => {
|
|
10822
|
+
return cloneTemplate(BASE_CONTRACT_TEMPLATE.asyncModel);
|
|
10823
|
+
};
|
|
10824
|
+
var buildPerformanceModelBlock = () => {
|
|
10825
|
+
return cloneTemplate(BASE_CONTRACT_TEMPLATE.performanceModel);
|
|
10826
|
+
};
|
|
10827
|
+
var buildCanvasPlanRequest = (brief, generationPlan) => ({
|
|
10828
|
+
...cloneTemplate(BASE_PLAN_REQUEST_TEMPLATE),
|
|
10829
|
+
requestId: `req_plan_${referenceFingerprint(brief).slice(0, 12)}`,
|
|
10830
|
+
generationPlan
|
|
10831
|
+
});
|
|
10832
|
+
var buildContractScope = () => ({
|
|
10833
|
+
emittedContract: "CanvasDesignGovernance",
|
|
10834
|
+
emittedGovernanceBlocks: [...EMITTED_GOVERNANCE_BLOCKS],
|
|
10835
|
+
omittedTemplateBlocks: ["navigationModel", "asyncModel", "performanceModel"],
|
|
10836
|
+
note: `${INSPIREDESIGN_HANDOFF_FILES.designContract} is the narrowed canvas governance contract. Use ${INSPIREDESIGN_HANDOFF_FILES.designAgentHandoff} for navigation, async, and performance context that informs implementation but does not belong in canvas governance patches.`
|
|
10837
|
+
});
|
|
10838
|
+
var buildFollowthrough = (generationPlan) => ({
|
|
10839
|
+
summary: buildInspiredesignFollowthroughSummary(),
|
|
10840
|
+
nextStep: buildInspiredesignNextStep(),
|
|
10841
|
+
recommendedSkills: [...INSPIREDESIGN_HANDOFF_RECOMMENDED_SKILLS],
|
|
10842
|
+
commandExamples: { ...INSPIREDESIGN_HANDOFF_COMMANDS },
|
|
10843
|
+
deepCaptureRecommendation: INSPIREDESIGN_HANDOFF_GUIDANCE.deepCaptureRecommendation,
|
|
10844
|
+
contractScope: buildContractScope(),
|
|
10845
|
+
implementationContext: {
|
|
10846
|
+
navigationModel: buildNavigationModelBlock(generationPlan.visualDirection.profile),
|
|
10847
|
+
asyncModel: buildAsyncModelBlock(),
|
|
10848
|
+
performanceModel: buildPerformanceModelBlock()
|
|
10849
|
+
}
|
|
10850
|
+
});
|
|
10851
|
+
var buildDesignContract = (brief, urls, references, plan) => ({
|
|
10852
|
+
intent: buildIntentBlock(brief, urls, references),
|
|
10853
|
+
generationPlan: plan,
|
|
10854
|
+
designLanguage: buildDesignLanguageBlock(plan.visualDirection.profile),
|
|
10855
|
+
contentModel: buildContentModelBlock(brief, references),
|
|
10856
|
+
layoutSystem: buildLayoutSystemBlock(plan.visualDirection.profile),
|
|
10857
|
+
typographySystem: buildTypographySystemBlock(),
|
|
10858
|
+
colorSystem: buildColorSystemBlock(plan.visualDirection.profile),
|
|
10859
|
+
surfaceSystem: buildSurfaceSystemBlock(),
|
|
10860
|
+
iconSystem: buildIconSystemBlock(),
|
|
10861
|
+
motionSystem: buildMotionSystemBlock(),
|
|
10862
|
+
responsiveSystem: buildResponsiveSystemBlock(),
|
|
10863
|
+
accessibilityPolicy: buildAccessibilityBlock(),
|
|
10864
|
+
libraryPolicy: buildLibraryPolicyBlock(),
|
|
10865
|
+
runtimeBudgets: buildRuntimeBudgetsBlock(plan)
|
|
10866
|
+
});
|
|
10867
|
+
var buildTokenStrategy = (profile) => ({
|
|
10868
|
+
colors: PROFILE_CONFIG[profile].colors,
|
|
10869
|
+
typography: {
|
|
10870
|
+
display: "font-display text-[56px] leading-[1.0]",
|
|
10871
|
+
h1: "font-display text-[40px] leading-[1.05]",
|
|
10872
|
+
h2: "font-display text-[28px] leading-[1.1]",
|
|
10873
|
+
h3: "font-display text-[20px] leading-[1.2]",
|
|
10874
|
+
body: "font-body text-[16px] leading-[1.6]",
|
|
10875
|
+
label: "font-body text-[14px] leading-[1.4]",
|
|
10876
|
+
caption: "font-body text-[12px] leading-[1.4]"
|
|
10877
|
+
},
|
|
10878
|
+
spacing: {
|
|
10879
|
+
xs: "4px",
|
|
10880
|
+
sm: "8px",
|
|
10881
|
+
md: "16px",
|
|
10882
|
+
lg: "24px",
|
|
10883
|
+
xl: "40px",
|
|
10884
|
+
section: "96px"
|
|
10885
|
+
},
|
|
10886
|
+
radius: {
|
|
10887
|
+
xs: "6px",
|
|
10888
|
+
sm: "10px",
|
|
10889
|
+
md: "16px",
|
|
10890
|
+
lg: "24px"
|
|
10891
|
+
},
|
|
10892
|
+
shadow: {
|
|
10893
|
+
sm: "0 1px 2px rgba(15, 23, 42, 0.06)",
|
|
10894
|
+
md: "0 10px 30px rgba(15, 23, 42, 0.10)",
|
|
10895
|
+
lg: "0 24px 60px rgba(15, 23, 42, 0.14)"
|
|
10896
|
+
},
|
|
10897
|
+
motion: {
|
|
10898
|
+
quick: "120ms ease-out",
|
|
10899
|
+
standard: "180ms ease-out",
|
|
10900
|
+
emphasis: "240ms cubic-bezier(0.22, 1, 0.36, 1)"
|
|
10901
|
+
},
|
|
10902
|
+
zIndex: {
|
|
10903
|
+
base: 0,
|
|
10904
|
+
sticky: 20,
|
|
10905
|
+
overlay: 40,
|
|
10906
|
+
modal: 60,
|
|
10907
|
+
toast: 70
|
|
10908
|
+
},
|
|
10909
|
+
breakpoints: {
|
|
10910
|
+
mobile: "640px",
|
|
10911
|
+
tablet: "1024px",
|
|
10912
|
+
desktop: "1280px"
|
|
10913
|
+
}
|
|
10914
|
+
});
|
|
10915
|
+
var buildComponentBuildPlan = (profile) => {
|
|
10916
|
+
return PROFILE_CONFIG[profile].componentSequence.map((name) => ({
|
|
10917
|
+
name,
|
|
10918
|
+
purpose: `Establish the ${name.toLowerCase()} pattern as a reusable system primitive.`,
|
|
10919
|
+
states: ["default", "hover", "focus", "disabled"],
|
|
10920
|
+
implementationNote: "Use semantic tokens first and keep copy/state logic outside the visual component."
|
|
10921
|
+
}));
|
|
10922
|
+
};
|
|
10923
|
+
var buildImplementationPlan = (brief, profile, references) => ({
|
|
10924
|
+
architectureRecommendation: "Implement the surface as token-first components using shared semantic CSS variables, then compose page sections from those primitives before adding any page-specific polish.",
|
|
10925
|
+
tokenStrategy: buildTokenStrategy(profile),
|
|
10926
|
+
componentBuildPlan: buildComponentBuildPlan(profile),
|
|
10927
|
+
pageAssemblyPlan: [
|
|
10928
|
+
"Start with the shell and primary navigation pattern.",
|
|
10929
|
+
"Compose the hero or primary decision section before supporting sections.",
|
|
10930
|
+
"Add proof, utility, and footer sections only after the top-level hierarchy is stable."
|
|
10931
|
+
],
|
|
10932
|
+
stateAndInteractionPlan: [
|
|
10933
|
+
"Keep hover, focus, loading, success, and error states visually distinct.",
|
|
10934
|
+
"Preserve layout during loading and keep transient confirmations out of the main flow.",
|
|
10935
|
+
"Use reduced-motion-safe transitions for reveals and CTA feedback."
|
|
10936
|
+
],
|
|
10937
|
+
accessibilityChecklist: [
|
|
10938
|
+
"Maintain 4.5:1 body text contrast across all surfaces.",
|
|
10939
|
+
"Preserve visible focus rings on every interactive element.",
|
|
10940
|
+
"Keep landmarks and heading levels explicit and sequential."
|
|
10941
|
+
],
|
|
10942
|
+
responsiveChecklist: [
|
|
10943
|
+
"Collapse multicolumn layouts before text measure becomes cramped.",
|
|
10944
|
+
"Keep the primary CTA visible without overlap on narrow screens.",
|
|
10945
|
+
"Avoid horizontal scrolling for primary content."
|
|
10946
|
+
],
|
|
10947
|
+
risksAndAmbiguities: [
|
|
10948
|
+
references.length === 0 ? "No live references were supplied, so visual cues are derived entirely from the written brief." : "Live references were reduced into reusable patterns; unique brand assets should still be recreated, not copied.",
|
|
10949
|
+
"Any missing interaction states must be validated during visual QA."
|
|
10950
|
+
],
|
|
10951
|
+
buildSequence: [
|
|
10952
|
+
"Define semantic tokens and typography.",
|
|
10953
|
+
"Build the shell, navigation, and primary CTA components.",
|
|
10954
|
+
"Implement section-level patterns and proof blocks.",
|
|
10955
|
+
"Add loading, empty, and error states.",
|
|
10956
|
+
"Run accessibility, responsive, and browser QA before final polish."
|
|
10957
|
+
]
|
|
10958
|
+
});
|
|
10959
|
+
var formatBulletList = (items) => items.map((item) => `- ${item}`).join("\n");
|
|
10960
|
+
var formatRecordList = (record) => {
|
|
10961
|
+
return Object.entries(record).map(([key, value]) => `- \`${key}\`: ${value}`).join("\n");
|
|
10962
|
+
};
|
|
10963
|
+
var referenceContribution = (reference) => {
|
|
10964
|
+
if (reference.captureStatus === "captured") return "Live hierarchy and component evidence captured from the page.";
|
|
10965
|
+
if (reference.fetchStatus === "captured") return "Content and structural cues inferred from fetched page data.";
|
|
10966
|
+
return "Only operator brief context was available for this reference.";
|
|
10967
|
+
};
|
|
10968
|
+
var referenceMotionNote = (reference) => {
|
|
10969
|
+
if (reference.capture?.snapshot?.warnings?.length) {
|
|
10970
|
+
return `Capture warnings: ${reference.capture.snapshot.warnings.join(", ")}`;
|
|
10971
|
+
}
|
|
10972
|
+
if (reference.captureStatus === "captured") return "Motion should remain subtle until validated against the live capture.";
|
|
10973
|
+
return "Motion is inferred from the brief rather than directly observed.";
|
|
10974
|
+
};
|
|
10975
|
+
var renderReferenceMarkdown = (reference, index) => {
|
|
10976
|
+
const excerpt = reference.excerpt ? clipText(reference.excerpt, 220) : "No fetched excerpt captured.";
|
|
10977
|
+
const title = reference.title ?? reference.url;
|
|
10978
|
+
return [
|
|
10979
|
+
`### Source ${index + 1}: ${title}`,
|
|
10980
|
+
`- what it contributes: ${referenceContribution(reference)}`,
|
|
10981
|
+
`- notable UI patterns: ${reference.capture?.snapshot ? "Primary hierarchy and actionables were captured from the live page." : "Patterns inferred from brief and fetched content."}`,
|
|
10982
|
+
`- typography observations: ${reference.title ? "Headline density and copy hierarchy were inferred from the fetched title and excerpt." : "Typography is inferred."}`,
|
|
10983
|
+
`- color and theme observations: ${reference.captureStatus === "captured" ? "Color posture should be validated against the captured page before cloning brand treatment." : "Color posture remains a synthesis decision."}`,
|
|
10984
|
+
`- layout and hierarchy observations: ${reference.capture?.snapshot ? clipText(reference.capture.snapshot.content, 180) : excerpt}`,
|
|
10985
|
+
`- component patterns: ${reference.capture?.clone ? "Buttons, cards, or layout wrappers can be inferred from the captured clone preview." : "Component families were inferred from available reference text."}`,
|
|
10986
|
+
`- motion/interaction observations: ${referenceMotionNote(reference)}`,
|
|
10987
|
+
`- accessibility/responsiveness notes: ${reference.captureStatus === "captured" ? "Validate focus order, CTA prominence, and stacked layouts during build QA." : "Accessibility and responsiveness are inferred from system defaults."}`,
|
|
10988
|
+
`- what should be adopted, adapted, or avoided: adopt layout hierarchy, adapt it to the new brand tokens, avoid copying proprietary copy or visual assets directly.`
|
|
10989
|
+
].join("\n");
|
|
10990
|
+
};
|
|
10991
|
+
var resolveProfileConfigFromGenerationPlan = (generationPlan) => {
|
|
10992
|
+
if (!generationPlan || typeof generationPlan !== "object" || !("visualDirection" in generationPlan)) {
|
|
10993
|
+
throw new Error("Inspiredesign design contract requires a generation plan.");
|
|
10994
|
+
}
|
|
10995
|
+
const visualDirection = generationPlan.visualDirection;
|
|
10996
|
+
if (!visualDirection || typeof visualDirection !== "object" || !("profile" in visualDirection)) {
|
|
10997
|
+
throw new Error("Inspiredesign design contract requires a visual direction profile.");
|
|
10998
|
+
}
|
|
10999
|
+
const profile = visualDirection.profile;
|
|
11000
|
+
if (typeof profile !== "string" || !(profile in PROFILE_CONFIG)) {
|
|
11001
|
+
throw new Error("Inspiredesign design contract profile is invalid.");
|
|
11002
|
+
}
|
|
11003
|
+
return PROFILE_CONFIG[profile];
|
|
11004
|
+
};
|
|
11005
|
+
var renderGovernanceMarkdown = (designContract, implementationPlan) => {
|
|
11006
|
+
const profileConfig = resolveProfileConfigFromGenerationPlan(designContract.generationPlan);
|
|
11007
|
+
return [
|
|
11008
|
+
"## 4.1 Design Intent",
|
|
11009
|
+
formatBulletList([
|
|
11010
|
+
`Purpose: ${designContract.intent.task || ""}`,
|
|
11011
|
+
"Capture the reusable visual logic from the references without cloning proprietary brand assets.",
|
|
11012
|
+
"Keep the resulting system executable for downstream build agents."
|
|
11013
|
+
]),
|
|
11014
|
+
"",
|
|
11015
|
+
"## 4.2 Core UX Principles",
|
|
11016
|
+
formatBulletList(profileConfig.hierarchyPrinciples),
|
|
11017
|
+
"",
|
|
11018
|
+
"## 4.3 Visual Identity",
|
|
11019
|
+
formatBulletList([
|
|
11020
|
+
`Aesthetic style: ${profileConfig.visualPersonality}`,
|
|
11021
|
+
`Brand tone: ${profileConfig.brandTone}`,
|
|
11022
|
+
`Quality posture: ${profileConfig.direction}`,
|
|
11023
|
+
"Direction: modern, system-led, and implementation-aware."
|
|
11024
|
+
]),
|
|
11025
|
+
"",
|
|
11026
|
+
"## 4.4 Color System",
|
|
11027
|
+
formatRecordList(implementationPlan.tokenStrategy.colors),
|
|
11028
|
+
"",
|
|
11029
|
+
"## 4.5 Typography System",
|
|
11030
|
+
formatRecordList(implementationPlan.tokenStrategy.typography),
|
|
11031
|
+
"",
|
|
11032
|
+
"## 4.6 Spacing and Layout System",
|
|
11033
|
+
formatRecordList(implementationPlan.tokenStrategy.spacing),
|
|
11034
|
+
"",
|
|
11035
|
+
"## 4.7 Shape, Border, and Elevation Rules",
|
|
11036
|
+
[
|
|
11037
|
+
formatRecordList(implementationPlan.tokenStrategy.radius),
|
|
11038
|
+
formatRecordList(implementationPlan.tokenStrategy.shadow)
|
|
11039
|
+
].join("\n"),
|
|
11040
|
+
"",
|
|
11041
|
+
"## 4.8 Motion and Interaction Rules",
|
|
11042
|
+
formatRecordList(implementationPlan.tokenStrategy.motion),
|
|
11043
|
+
"",
|
|
11044
|
+
"## 4.9 Component System",
|
|
11045
|
+
implementationPlan.componentBuildPlan.map((component) => [
|
|
11046
|
+
`### ${component.name}`,
|
|
11047
|
+
formatBulletList([
|
|
11048
|
+
`purpose: ${component.purpose}`,
|
|
11049
|
+
`structure: build from semantic tokens and keep state visuals explicit`,
|
|
11050
|
+
`visual style: ${profileConfig.direction}`,
|
|
11051
|
+
`states: ${component.states.join(", ")}`,
|
|
11052
|
+
"spacing: keep internal padding on the 8px rhythm",
|
|
11053
|
+
"accessibility notes: preserve focus visibility and keyboard parity",
|
|
11054
|
+
"responsive behavior: stack content before line length becomes cramped",
|
|
11055
|
+
`implementation notes: ${component.implementationNote}`
|
|
11056
|
+
])
|
|
11057
|
+
].join("\n")).join("\n\n"),
|
|
11058
|
+
"",
|
|
11059
|
+
"## 4.10 Page or Section Patterns",
|
|
11060
|
+
formatBulletList(profileConfig.pagePatterns),
|
|
11061
|
+
"",
|
|
11062
|
+
"## 4.11 Accessibility Requirements",
|
|
11063
|
+
formatBulletList(implementationPlan.accessibilityChecklist),
|
|
11064
|
+
"",
|
|
11065
|
+
"## 4.12 Responsiveness Requirements",
|
|
11066
|
+
formatBulletList(implementationPlan.responsiveChecklist),
|
|
11067
|
+
"",
|
|
11068
|
+
"## 4.13 Content and Microcopy Guidance",
|
|
11069
|
+
formatBulletList([
|
|
11070
|
+
"Use direct, confident labels and short CTA copy.",
|
|
11071
|
+
"Keep error and success messages specific to the affected region.",
|
|
11072
|
+
"Prefer descriptive button copy over generic verbs."
|
|
11073
|
+
]),
|
|
11074
|
+
"",
|
|
11075
|
+
"## 4.14 Do / Don't Rules",
|
|
11076
|
+
formatBulletList([
|
|
11077
|
+
"Do preserve one dominant message per section.",
|
|
11078
|
+
"Do encode repeated visual rules into semantic tokens.",
|
|
11079
|
+
"Don't copy proprietary logos, screenshots, or brand-only illustrations.",
|
|
11080
|
+
"Don't hide important actions inside ambiguous hover-only affordances."
|
|
11081
|
+
]),
|
|
11082
|
+
"",
|
|
11083
|
+
"## 4.15 Acceptance Criteria",
|
|
11084
|
+
formatBulletList([
|
|
11085
|
+
"Primary action is obvious within one viewport.",
|
|
11086
|
+
"Color, typography, spacing, and elevation all resolve through named tokens.",
|
|
11087
|
+
"Keyboard, focus, and reduced-motion behavior remain intact across breakpoints."
|
|
11088
|
+
])
|
|
11089
|
+
].join("\n");
|
|
11090
|
+
};
|
|
11091
|
+
var renderImplementationMarkdown = (implementationPlan) => {
|
|
11092
|
+
return [
|
|
11093
|
+
"# 5. Implementation Plan",
|
|
11094
|
+
"",
|
|
11095
|
+
"## 5.1 Architecture Recommendation",
|
|
11096
|
+
implementationPlan.architectureRecommendation,
|
|
11097
|
+
"",
|
|
11098
|
+
"## 5.2 Design Token Strategy",
|
|
11099
|
+
formatRecordList(implementationPlan.tokenStrategy.colors),
|
|
11100
|
+
"",
|
|
11101
|
+
formatRecordList(implementationPlan.tokenStrategy.typography),
|
|
11102
|
+
"",
|
|
11103
|
+
"## 5.3 Component Build Plan",
|
|
11104
|
+
implementationPlan.componentBuildPlan.map((component, index) => `${index + 1}. ${component.name}: ${component.purpose}`).join("\n"),
|
|
11105
|
+
"",
|
|
11106
|
+
"## 5.4 Page Assembly Plan",
|
|
11107
|
+
formatBulletList(implementationPlan.pageAssemblyPlan),
|
|
11108
|
+
"",
|
|
11109
|
+
"## 5.5 State and Interaction Plan",
|
|
11110
|
+
formatBulletList(implementationPlan.stateAndInteractionPlan),
|
|
11111
|
+
"",
|
|
11112
|
+
"## 5.6 Accessibility Implementation Checklist",
|
|
11113
|
+
formatBulletList(implementationPlan.accessibilityChecklist),
|
|
11114
|
+
"",
|
|
11115
|
+
"## 5.7 Responsive Implementation Checklist",
|
|
11116
|
+
formatBulletList(implementationPlan.responsiveChecklist),
|
|
11117
|
+
"",
|
|
11118
|
+
"## 5.8 Risks and Ambiguities",
|
|
11119
|
+
formatBulletList(implementationPlan.risksAndAmbiguities),
|
|
11120
|
+
"",
|
|
11121
|
+
"## 5.9 Recommended Build Sequence",
|
|
11122
|
+
implementationPlan.buildSequence.map((step, index) => `${index + 1}. ${step}`).join("\n")
|
|
11123
|
+
].join("\n");
|
|
11124
|
+
};
|
|
11125
|
+
var renderPrototypeGuidance = (profile) => {
|
|
11126
|
+
return [
|
|
11127
|
+
"# 6. Optional Prototype Plan",
|
|
11128
|
+
"",
|
|
11129
|
+
"- page structure: establish the shell, hero or primary action zone, proof sections, and footer in that order.",
|
|
11130
|
+
`- section order: ${PROFILE_CONFIG[profile].pagePatterns.join(" -> ")}`,
|
|
11131
|
+
"- component composition: reuse button, card, input, and navigation primitives before page-specific wrappers.",
|
|
11132
|
+
"- interaction expectations: provide visible focus, compact hover feedback, and reduced-motion-safe entry transitions.",
|
|
11133
|
+
"- HTML skeleton guidance: start with one main landmark, one primary CTA group, and semantic sections for proof or detail bands.",
|
|
11134
|
+
"- styling approach: define CSS variables first, then map components to semantic tokens rather than raw values.",
|
|
11135
|
+
"- first prototype should include vs omit: include shell, hero, CTA, one proof section, and one form or action cluster; omit analytics, heavy animation, and tertiary content until hierarchy is proven."
|
|
11136
|
+
].join("\n");
|
|
11137
|
+
};
|
|
11138
|
+
var renderDeliverablesSummary = (includePrototypeGuidance) => {
|
|
11139
|
+
const deliverables = [
|
|
11140
|
+
"Structured `designContract` JSON aligned to canvas governance",
|
|
11141
|
+
"Valid `generationPlan` JSON aligned to the canvas generation plan contract",
|
|
11142
|
+
"Ready-to-fill `canvasPlanRequest` JSON for `canvas.plan.set`",
|
|
11143
|
+
"Design-agent handoff JSON with contract scope, skill nudges, and richer implementation context",
|
|
11144
|
+
"Human-readable `design.md` design specification",
|
|
11145
|
+
"Engineering implementation plan in JSON and Markdown"
|
|
11146
|
+
];
|
|
11147
|
+
if (includePrototypeGuidance) {
|
|
11148
|
+
deliverables.push("Prototype guidance Markdown for the first HTML pass");
|
|
11149
|
+
}
|
|
11150
|
+
deliverables.push("Evidence digest describing brief, references, fetch outcomes, and capture outcomes");
|
|
11151
|
+
return formatBulletList(deliverables);
|
|
11152
|
+
};
|
|
11153
|
+
var buildEvidencePayload = (brief, urls, references) => ({
|
|
11154
|
+
brief,
|
|
11155
|
+
briefHash: referenceFingerprint(brief),
|
|
11156
|
+
urls,
|
|
11157
|
+
referenceCount: references.length,
|
|
11158
|
+
references: references.map((reference) => toReferenceEvidenceJson(reference))
|
|
11159
|
+
});
|
|
11160
|
+
var toCaptureEvidenceJson = (capture) => {
|
|
11161
|
+
if (!capture) return null;
|
|
11162
|
+
return {
|
|
11163
|
+
...capture.title ? { title: capture.title } : {},
|
|
11164
|
+
...capture.snapshot ? { snapshot: capture.snapshot } : {},
|
|
11165
|
+
...capture.dom ? { dom: capture.dom } : {},
|
|
11166
|
+
...capture.clone ? { clone: capture.clone } : {}
|
|
11167
|
+
};
|
|
11168
|
+
};
|
|
11169
|
+
var toReferenceEvidenceJson = (reference) => ({
|
|
11170
|
+
id: reference.id,
|
|
11171
|
+
url: reference.url,
|
|
11172
|
+
...reference.title ? { title: reference.title } : {},
|
|
11173
|
+
...reference.excerpt ? { excerpt: reference.excerpt } : {},
|
|
11174
|
+
fetchStatus: reference.fetchStatus,
|
|
11175
|
+
captureStatus: reference.captureStatus,
|
|
11176
|
+
...reference.fetchFailure ? { fetchFailure: reference.fetchFailure } : {},
|
|
11177
|
+
...reference.captureFailure ? { captureFailure: reference.captureFailure } : {},
|
|
11178
|
+
capture: toCaptureEvidenceJson(reference.capture)
|
|
11179
|
+
});
|
|
11180
|
+
var buildInspiredesignPacket = (input) => {
|
|
11181
|
+
const brief = trimText(input.brief);
|
|
11182
|
+
const urls = [...new Set(input.urls.map((url) => trimText(url)).filter(Boolean))];
|
|
11183
|
+
const references = input.references.map((reference) => ({
|
|
11184
|
+
...reference,
|
|
11185
|
+
title: reference.title ? trimText(reference.title) : void 0,
|
|
11186
|
+
excerpt: reference.excerpt ? trimText(reference.excerpt) : void 0
|
|
11187
|
+
}));
|
|
11188
|
+
const profile = classifyProfile(brief, references);
|
|
11189
|
+
const generationPlan = buildGenerationPlan(brief, profile, references);
|
|
11190
|
+
const canvasPlanRequest = buildCanvasPlanRequest(brief, generationPlan);
|
|
11191
|
+
const designContract = buildDesignContract(brief, urls, references, generationPlan);
|
|
11192
|
+
const followthrough = buildFollowthrough(generationPlan);
|
|
11193
|
+
const implementationPlan = buildImplementationPlan(brief, profile, references);
|
|
11194
|
+
const governanceMarkdown = renderGovernanceMarkdown(designContract, implementationPlan);
|
|
11195
|
+
const implementationPlanMarkdown = renderImplementationMarkdown(implementationPlan);
|
|
11196
|
+
const prototypeGuidanceMarkdown = input.includePrototypeGuidance ? renderPrototypeGuidance(profile) : null;
|
|
11197
|
+
const designMarkdown = [
|
|
11198
|
+
"# 1. Executive Summary",
|
|
9611
11199
|
"",
|
|
9612
|
-
|
|
11200
|
+
formatBulletList([
|
|
11201
|
+
`Analyzed brief plus ${references.length || 0} inspiration reference(s).`,
|
|
11202
|
+
`Chosen design direction: ${PROFILE_CONFIG[profile].direction}.`,
|
|
11203
|
+
"Final outcome: a reusable design contract, engineering plan, and optional prototype guidance.",
|
|
11204
|
+
`Scope mode: ${references.length > 1 ? "full-site synthesis" : "single-surface synthesis"}.`
|
|
11205
|
+
]),
|
|
9613
11206
|
"",
|
|
9614
|
-
"
|
|
9615
|
-
"
|
|
9616
|
-
|
|
9617
|
-
"
|
|
11207
|
+
"# 2. Inspiration Analysis",
|
|
11208
|
+
"",
|
|
11209
|
+
references.length > 0 ? references.map(renderReferenceMarkdown).join("\n\n") : "- No live inspiration source was provided. The system is derived entirely from the brief.",
|
|
11210
|
+
"",
|
|
11211
|
+
"# 3. Unified Design Direction",
|
|
11212
|
+
"",
|
|
11213
|
+
formatBulletList([
|
|
11214
|
+
`visual personality: ${PROFILE_CONFIG[profile].visualPersonality}`,
|
|
11215
|
+
`tone: ${PROFILE_CONFIG[profile].brandTone}`,
|
|
11216
|
+
`UX principles: ${PROFILE_CONFIG[profile].hierarchyPrinciples.join(" ")}`,
|
|
11217
|
+
`interaction philosophy: ${PROFILE_CONFIG[profile].interactionPhilosophy}`,
|
|
11218
|
+
"branding posture: preserve the intent of the references without cloning brand-only assets.",
|
|
11219
|
+
"system coherence rules: encode tokens first, keep one dominant idea per section, and keep states explicit."
|
|
11220
|
+
]),
|
|
11221
|
+
"",
|
|
11222
|
+
"# 4. Design Governance (`design.md`)",
|
|
11223
|
+
"",
|
|
11224
|
+
renderGovernanceMarkdown(designContract, implementationPlan),
|
|
11225
|
+
"",
|
|
11226
|
+
renderImplementationMarkdown(implementationPlan),
|
|
11227
|
+
"",
|
|
11228
|
+
prototypeGuidanceMarkdown ?? "# 6. Optional Prototype Plan\n\n- Prototype guidance omitted for this run.",
|
|
11229
|
+
"",
|
|
11230
|
+
"# 7. Deliverables Summary",
|
|
11231
|
+
"",
|
|
11232
|
+
renderDeliverablesSummary(Boolean(input.includePrototypeGuidance))
|
|
9618
11233
|
].join("\n");
|
|
9619
|
-
const comparisonCsv = toComparisonCsv(args.offers);
|
|
9620
|
-
const contextPayload = {
|
|
9621
|
-
query: args.query,
|
|
9622
|
-
highlights: lines,
|
|
9623
|
-
offers: args.offers,
|
|
9624
|
-
meta: args.meta
|
|
9625
|
-
};
|
|
9626
|
-
const files = [
|
|
9627
|
-
{ path: "deals.md", content: markdown },
|
|
9628
|
-
{ path: "offers.json", content: { offers: args.offers } },
|
|
9629
|
-
{ path: "comparison.csv", content: comparisonCsv },
|
|
9630
|
-
{ path: "meta.json", content: args.meta },
|
|
9631
|
-
{ path: "deals-context.json", content: contextPayload }
|
|
9632
|
-
];
|
|
9633
|
-
if (args.mode === "compact") {
|
|
9634
|
-
return {
|
|
9635
|
-
response: {
|
|
9636
|
-
mode: args.mode,
|
|
9637
|
-
summary: lines.join("\n"),
|
|
9638
|
-
meta: args.meta
|
|
9639
|
-
},
|
|
9640
|
-
files
|
|
9641
|
-
};
|
|
9642
|
-
}
|
|
9643
|
-
if (args.mode === "json") {
|
|
9644
|
-
return {
|
|
9645
|
-
response: {
|
|
9646
|
-
mode: args.mode,
|
|
9647
|
-
offers: args.offers,
|
|
9648
|
-
meta: args.meta
|
|
9649
|
-
},
|
|
9650
|
-
files
|
|
9651
|
-
};
|
|
9652
|
-
}
|
|
9653
|
-
if (args.mode === "md") {
|
|
9654
|
-
return {
|
|
9655
|
-
response: {
|
|
9656
|
-
mode: args.mode,
|
|
9657
|
-
markdown,
|
|
9658
|
-
meta: args.meta
|
|
9659
|
-
},
|
|
9660
|
-
files
|
|
9661
|
-
};
|
|
9662
|
-
}
|
|
9663
|
-
if (args.mode === "context") {
|
|
9664
|
-
return {
|
|
9665
|
-
response: {
|
|
9666
|
-
mode: args.mode,
|
|
9667
|
-
context: contextPayload,
|
|
9668
|
-
meta: args.meta
|
|
9669
|
-
},
|
|
9670
|
-
files
|
|
9671
|
-
};
|
|
9672
|
-
}
|
|
9673
11234
|
return {
|
|
9674
|
-
|
|
9675
|
-
|
|
9676
|
-
|
|
9677
|
-
|
|
9678
|
-
|
|
11235
|
+
designContract,
|
|
11236
|
+
generationPlan,
|
|
11237
|
+
canvasPlanRequest,
|
|
11238
|
+
followthrough,
|
|
11239
|
+
designMarkdown,
|
|
11240
|
+
implementationPlan,
|
|
11241
|
+
implementationPlanMarkdown,
|
|
11242
|
+
prototypeGuidanceMarkdown,
|
|
11243
|
+
evidence: buildEvidencePayload(brief, urls, references)
|
|
9679
11244
|
};
|
|
9680
11245
|
};
|
|
9681
11246
|
|
|
11247
|
+
// src/providers/workflow-handoff.ts
|
|
11248
|
+
var PRODUCT_VIDEO_BRIEF_HELPER_PATH = "./skills/opendevbrowser-product-presentation-asset/scripts/render-video-brief.sh";
|
|
11249
|
+
var PRODUCT_VIDEO_BRIEF_HELPER_COMMAND = `${PRODUCT_VIDEO_BRIEF_HELPER_PATH} <pack>/manifest.json`;
|
|
11250
|
+
var createSuccessHandoff = (followthroughSummary, suggestedNextAction, suggestedSteps) => ({
|
|
11251
|
+
followthroughSummary,
|
|
11252
|
+
suggestedNextAction,
|
|
11253
|
+
suggestedSteps
|
|
11254
|
+
});
|
|
11255
|
+
var buildResearchSuccessHandoff = () => {
|
|
11256
|
+
return createSuccessHandoff(
|
|
11257
|
+
"Review the ranked records and artifact bundle before turning the result into a publishable claim.",
|
|
11258
|
+
"Open the returned artifact path, inspect the supporting records, and rerun with explicit --sources or a tighter timebox if you need stronger evidence.",
|
|
11259
|
+
[
|
|
11260
|
+
{ reason: "Check which records actually support the final claim." },
|
|
11261
|
+
{ reason: "Rerun with explicit sources or a narrower timebox if the evidence set is still too broad." }
|
|
11262
|
+
]
|
|
11263
|
+
);
|
|
11264
|
+
};
|
|
11265
|
+
var buildShoppingSuccessHandoff = () => {
|
|
11266
|
+
return createSuccessHandoff(
|
|
11267
|
+
"Review the offer set and diagnostics before calling any result a strong deal.",
|
|
11268
|
+
"Inspect the offers and meta.offerFilterDiagnostics, then rerun with explicit providers or budget and region adjustments if you need a tighter comparison.",
|
|
11269
|
+
[
|
|
11270
|
+
{ reason: "Check which offers survived the workflow filters and why." },
|
|
11271
|
+
{ reason: "Rerun with explicit providers or updated budget and region inputs if the comparison is still noisy." }
|
|
11272
|
+
]
|
|
11273
|
+
);
|
|
11274
|
+
};
|
|
11275
|
+
var buildProductVideoSuccessHandoff = () => {
|
|
11276
|
+
return createSuccessHandoff(
|
|
11277
|
+
"Review the generated asset pack to confirm whether it is visual-ready or metadata-first before briefing production.",
|
|
11278
|
+
`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.`,
|
|
11279
|
+
[
|
|
11280
|
+
{ reason: "Confirm whether the pack already includes enough images or screenshots for production." },
|
|
11281
|
+
{
|
|
11282
|
+
reason: "Run the product-presentation-asset brief helper on manifest.json to generate the production brief files.",
|
|
11283
|
+
command: PRODUCT_VIDEO_BRIEF_HELPER_COMMAND
|
|
11284
|
+
},
|
|
11285
|
+
{ reason: "Source or capture visuals before final handoff if the pack is metadata-first." }
|
|
11286
|
+
]
|
|
11287
|
+
);
|
|
11288
|
+
};
|
|
11289
|
+
|
|
9682
11290
|
// src/providers/shopping-postprocess.ts
|
|
9683
|
-
import { createHash as
|
|
11291
|
+
import { createHash as createHash4 } from "crypto";
|
|
9684
11292
|
var LOOKS_LIKE_URL_RE = /^https?:\/\/\S+$/i;
|
|
9685
11293
|
var PRICE_TOKEN_RE = /((?:US\$|CA\$|C\$|USD|CAD|EUR|GBP|[$€£]))\s*([0-9]{1,4}(?:[.,][0-9]{3})*(?:[.,][0-9]{1,2})?)/gi;
|
|
9686
11294
|
var CONTEXTUAL_PRICE_TOKEN_RE = /(?:connect to any carrier later|starting at|starts at|starting from|from|buy now for|buy for)\s*((?:US\$|CA\$|C\$|USD|CAD|EUR|GBP|[$€£]))\s*([0-9]{1,4}(?:[.,][0-9]{3})*(?:[.,][0-9]{1,2})?)/gi;
|
|
@@ -9766,7 +11374,7 @@ var REGION_CURRENCY_BY_REGION = {
|
|
|
9766
11374
|
uk: "GBP",
|
|
9767
11375
|
eu: "EUR"
|
|
9768
11376
|
};
|
|
9769
|
-
var hash = (value) =>
|
|
11377
|
+
var hash = (value) => createHash4("sha1").update(value).digest("hex").slice(0, 16);
|
|
9770
11378
|
var normalizePlainText = (value) => {
|
|
9771
11379
|
if (!value) return "";
|
|
9772
11380
|
return extractText(value).replace(/[\u0000-\u001F\u007F-\u009F]+/g, " ").replace(/\s+/g, " ").trim();
|
|
@@ -10395,7 +12003,7 @@ var compileShoppingWorkflow = (input, options = {}) => {
|
|
|
10395
12003
|
};
|
|
10396
12004
|
|
|
10397
12005
|
// src/providers/shopping-compiler.ts
|
|
10398
|
-
import { createHash as
|
|
12006
|
+
import { createHash as createHash5 } from "crypto";
|
|
10399
12007
|
var DEFAULT_SHOPPING_SEARCH_LIMIT = 8;
|
|
10400
12008
|
var SHOPPING_FETCH_RECOVERY_LIMIT = 2;
|
|
10401
12009
|
var SEARCH_INDEX_RETRIEVAL_PATHS = /* @__PURE__ */ new Set(["shopping:search:index", "shopping:search:link"]);
|
|
@@ -10412,7 +12020,7 @@ var emptyCheckpointState = () => ({
|
|
|
10412
12020
|
step_results_by_id: {}
|
|
10413
12021
|
});
|
|
10414
12022
|
var createShoppingSearchStepId = (providerId) => `search:${providerId}`;
|
|
10415
|
-
var createShoppingFetchStepId = (providerId, url) => `fetch:${providerId}:${
|
|
12023
|
+
var createShoppingFetchStepId = (providerId, url) => `fetch:${providerId}:${createHash5("sha1").update(canonicalizeUrl(url)).digest("hex").slice(0, 16)}`;
|
|
10416
12024
|
var serializeShoppingCheckpointState = (state) => ({
|
|
10417
12025
|
completed_step_ids: [...state.completed_step_ids],
|
|
10418
12026
|
step_results_by_id: state.step_results_by_id
|
|
@@ -10898,7 +12506,7 @@ var compileProductVideoExecutionPlan = (args) => {
|
|
|
10898
12506
|
};
|
|
10899
12507
|
|
|
10900
12508
|
// src/providers/research-compiler.ts
|
|
10901
|
-
import { createHash as
|
|
12509
|
+
import { createHash as createHash6 } from "crypto";
|
|
10902
12510
|
var RESEARCH_AUTO_SOURCES = ["web", "community", "social"];
|
|
10903
12511
|
var RESEARCH_ALL_SOURCES = [...RESEARCH_AUTO_SOURCES];
|
|
10904
12512
|
var DEFAULT_RESEARCH_SEARCH_LIMIT = 10;
|
|
@@ -10923,7 +12531,7 @@ var toProviderSource = (providerId) => {
|
|
|
10923
12531
|
return null;
|
|
10924
12532
|
};
|
|
10925
12533
|
var createResearchSearchStepId = (source) => `search:${source}`;
|
|
10926
|
-
var createResearchFetchStepId = (url) => `fetch:web:${
|
|
12534
|
+
var createResearchFetchStepId = (url) => `fetch:web:${createHash6("sha1").update(canonicalizeUrl(url)).digest("hex").slice(0, 16)}`;
|
|
10927
12535
|
var serializeResearchCheckpointState = (state) => ({
|
|
10928
12536
|
completed_step_ids: [...state.completed_step_ids],
|
|
10929
12537
|
step_results_by_id: state.step_results_by_id
|
|
@@ -11266,6 +12874,10 @@ var SIGNAL_WINDOW = 50;
|
|
|
11266
12874
|
var RECOVERY_WINDOWS_REQUIRED = 2;
|
|
11267
12875
|
var providerSignalMap = /* @__PURE__ */ new Map();
|
|
11268
12876
|
var workflowLogger = createLogger("provider-workflows");
|
|
12877
|
+
var withFollowthroughMeta = (meta, handoff) => ({
|
|
12878
|
+
...meta,
|
|
12879
|
+
followthroughSummary: handoff.followthroughSummary
|
|
12880
|
+
});
|
|
11269
12881
|
var detectSignal = (error) => {
|
|
11270
12882
|
const reasonCode = error.reasonCode ?? normalizeProviderReasonCode({
|
|
11271
12883
|
code: error.code,
|
|
@@ -11509,24 +13121,54 @@ var withPrimaryConstraintMeta = (meta, failures) => {
|
|
|
11509
13121
|
const primaryIssue = summarizePrimaryProviderIssue(failures);
|
|
11510
13122
|
return primaryIssue ? {
|
|
11511
13123
|
...meta,
|
|
11512
|
-
primary_constraint: primaryIssue,
|
|
11513
13124
|
primaryConstraint: primaryIssue,
|
|
11514
13125
|
primaryConstraintSummary: primaryIssue.summary
|
|
11515
13126
|
} : meta;
|
|
11516
13127
|
};
|
|
11517
|
-
var
|
|
13128
|
+
var withCamelCasePrimaryConstraintMeta = withPrimaryConstraintMeta;
|
|
13129
|
+
var readPrimaryConstraintGuidance = (constraint) => {
|
|
13130
|
+
const guidance = constraint.guidance;
|
|
13131
|
+
return guidance && typeof guidance === "object" && !Array.isArray(guidance) ? guidance : void 0;
|
|
13132
|
+
};
|
|
13133
|
+
var withPrimaryConstraintSummaryOverride = (meta, summary, guidance) => {
|
|
11518
13134
|
const currentPrimaryConstraint = meta.primaryConstraint;
|
|
11519
|
-
const
|
|
11520
|
-
|
|
13135
|
+
const baseConstraint = currentPrimaryConstraint && typeof currentPrimaryConstraint === "object" && !Array.isArray(currentPrimaryConstraint) ? currentPrimaryConstraint : { reasonCode: "env_limited" };
|
|
13136
|
+
const existingGuidance = readPrimaryConstraintGuidance(baseConstraint);
|
|
13137
|
+
const { guidance: _existingGuidance, ...nextPrimaryConstraintBase } = baseConstraint;
|
|
13138
|
+
const nextGuidance = guidance ?? existingGuidance;
|
|
13139
|
+
const nextPrimaryConstraint = nextGuidance ? {
|
|
13140
|
+
...nextPrimaryConstraintBase,
|
|
13141
|
+
summary,
|
|
13142
|
+
guidance: nextGuidance
|
|
13143
|
+
} : {
|
|
13144
|
+
...nextPrimaryConstraintBase,
|
|
11521
13145
|
summary
|
|
11522
|
-
}
|
|
13146
|
+
};
|
|
11523
13147
|
return {
|
|
11524
13148
|
...meta,
|
|
11525
|
-
primary_constraint: nextPrimaryConstraint,
|
|
11526
13149
|
primaryConstraint: nextPrimaryConstraint,
|
|
11527
13150
|
primaryConstraintSummary: summary
|
|
11528
13151
|
};
|
|
11529
13152
|
};
|
|
13153
|
+
var withReasonCodeDistributionMeta = (meta, reasonCodeDistribution) => {
|
|
13154
|
+
const metrics = meta.metrics;
|
|
13155
|
+
const nextMetrics = metrics && typeof metrics === "object" && !Array.isArray(metrics) ? {
|
|
13156
|
+
...metrics,
|
|
13157
|
+
reasonCodeDistribution
|
|
13158
|
+
} : { reasonCodeDistribution };
|
|
13159
|
+
return {
|
|
13160
|
+
...meta,
|
|
13161
|
+
metrics: nextMetrics,
|
|
13162
|
+
reasonCodeDistribution
|
|
13163
|
+
};
|
|
13164
|
+
};
|
|
13165
|
+
var incrementReasonCodeDistribution = (reasonCodeDistribution, reasonCode, count) => {
|
|
13166
|
+
if (count <= 0) return reasonCodeDistribution;
|
|
13167
|
+
return Object.fromEntries(Object.entries({
|
|
13168
|
+
...reasonCodeDistribution,
|
|
13169
|
+
[reasonCode]: (reasonCodeDistribution[reasonCode] ?? 0) + count
|
|
13170
|
+
}).sort(([left], [right]) => left.localeCompare(right)));
|
|
13171
|
+
};
|
|
11530
13172
|
var summarizeShoppingOfferFilterConstraint = (args) => {
|
|
11531
13173
|
const primaryIssue = summarizePrimaryProviderIssue(args.failures);
|
|
11532
13174
|
if (primaryIssue && (primaryIssue.reasonCode !== "env_limited" || primaryIssue.constraint || primaryIssue.blockerType === "anti_bot_challenge")) {
|
|
@@ -11586,6 +13228,7 @@ var withBrowserModeOverride = (options, input) => {
|
|
|
11586
13228
|
var WORKFLOW_KIND_BY_SUSPENDED_INTENT_KIND = {
|
|
11587
13229
|
"workflow.research": "research",
|
|
11588
13230
|
"workflow.shopping": "shopping",
|
|
13231
|
+
"workflow.inspiredesign": "inspiredesign",
|
|
11589
13232
|
"workflow.product_video": "product_video"
|
|
11590
13233
|
};
|
|
11591
13234
|
var buildWorkflowResumePayload = (kind, input) => ({
|
|
@@ -11837,7 +13480,7 @@ var rankResearchRecords = (records) => {
|
|
|
11837
13480
|
return left.id.localeCompare(right.id);
|
|
11838
13481
|
});
|
|
11839
13482
|
};
|
|
11840
|
-
var hash2 = (value) =>
|
|
13483
|
+
var hash2 = (value) => createHash7("sha1").update(value).digest("hex").slice(0, 16);
|
|
11841
13484
|
var RESEARCH_ALWAYS_SANITIZED_PATHS = /* @__PURE__ */ new Set([
|
|
11842
13485
|
"community:search:index",
|
|
11843
13486
|
"social:search:index"
|
|
@@ -11956,6 +13599,235 @@ var createRemainingTimeoutResolver = (timeoutMs) => {
|
|
|
11956
13599
|
const startedAtMs = Date.now();
|
|
11957
13600
|
return () => Math.max(1, timeoutMs - Math.max(0, Date.now() - startedAtMs));
|
|
11958
13601
|
};
|
|
13602
|
+
var INSPIREDESIGN_RENDER_MODES = /* @__PURE__ */ new Set(["compact", "json", "md", "context", "path"]);
|
|
13603
|
+
var INSPIREDESIGN_CAPTURE_MODES = /* @__PURE__ */ new Set(["off", "deep"]);
|
|
13604
|
+
var INSPIREDESIGN_COOKIE_POLICIES = /* @__PURE__ */ new Set(["off", "auto", "required"]);
|
|
13605
|
+
var serializeInspiredesignRunInput = (input) => ({
|
|
13606
|
+
brief: input.brief,
|
|
13607
|
+
urls: input.urls,
|
|
13608
|
+
captureMode: input.captureMode,
|
|
13609
|
+
mode: input.mode,
|
|
13610
|
+
...input.includePrototypeGuidance !== void 0 ? { includePrototypeGuidance: input.includePrototypeGuidance } : {},
|
|
13611
|
+
...typeof input.timeoutMs === "number" ? { timeoutMs: input.timeoutMs } : {},
|
|
13612
|
+
...input.outputDir ? { outputDir: input.outputDir } : {},
|
|
13613
|
+
...typeof input.ttlHours === "number" ? { ttlHours: input.ttlHours } : {},
|
|
13614
|
+
...typeof input.useCookies === "boolean" ? { useCookies: input.useCookies } : {},
|
|
13615
|
+
...input.challengeAutomationMode ? { challengeAutomationMode: input.challengeAutomationMode } : {},
|
|
13616
|
+
...input.cookiePolicyOverride ? { cookiePolicyOverride: input.cookiePolicyOverride } : {}
|
|
13617
|
+
});
|
|
13618
|
+
var parseInspiredesignEnvelopeInput = (input) => ({
|
|
13619
|
+
brief: typeof input.brief === "string" ? input.brief : "",
|
|
13620
|
+
mode: typeof input.mode === "string" && INSPIREDESIGN_RENDER_MODES.has(input.mode) ? input.mode : "compact",
|
|
13621
|
+
...Array.isArray(input.urls) ? { urls: input.urls.filter((url) => typeof url === "string") } : {},
|
|
13622
|
+
...typeof input.captureMode === "string" && INSPIREDESIGN_CAPTURE_MODES.has(input.captureMode) ? { captureMode: input.captureMode } : {},
|
|
13623
|
+
...typeof input.includePrototypeGuidance === "boolean" ? { includePrototypeGuidance: input.includePrototypeGuidance } : {},
|
|
13624
|
+
...typeof input.timeoutMs === "number" ? { timeoutMs: input.timeoutMs } : {},
|
|
13625
|
+
...typeof input.outputDir === "string" && input.outputDir.length > 0 ? { outputDir: input.outputDir } : {},
|
|
13626
|
+
...typeof input.ttlHours === "number" ? { ttlHours: input.ttlHours } : {},
|
|
13627
|
+
...typeof input.useCookies === "boolean" ? { useCookies: input.useCookies } : {},
|
|
13628
|
+
...isChallengeAutomationMode(input.challengeAutomationMode) ? { challengeAutomationMode: input.challengeAutomationMode } : {},
|
|
13629
|
+
...typeof input.cookiePolicyOverride === "string" && INSPIREDESIGN_COOKIE_POLICIES.has(input.cookiePolicyOverride) ? { cookiePolicyOverride: input.cookiePolicyOverride } : {}
|
|
13630
|
+
});
|
|
13631
|
+
var normalizeInspiredesignUrls = (urls) => {
|
|
13632
|
+
if (!urls || urls.length === 0) return [];
|
|
13633
|
+
const normalized = urls.map((url) => url.trim()).filter(Boolean);
|
|
13634
|
+
const invalid = normalized.find((url) => !LOOKS_LIKE_URL_RE.test(url));
|
|
13635
|
+
if (invalid) {
|
|
13636
|
+
throw new Error(`Inspiredesign workflow received an invalid URL: ${invalid}`);
|
|
13637
|
+
}
|
|
13638
|
+
return [...new Set(normalized.map((url) => canonicalizeUrl(url)))];
|
|
13639
|
+
};
|
|
13640
|
+
var normalizeInspiredesignInput = (input) => {
|
|
13641
|
+
const brief = input.brief.trim();
|
|
13642
|
+
if (!brief) {
|
|
13643
|
+
throw new Error("Inspiredesign workflow requires a non-empty brief.");
|
|
13644
|
+
}
|
|
13645
|
+
return {
|
|
13646
|
+
...input,
|
|
13647
|
+
brief,
|
|
13648
|
+
urls: normalizeInspiredesignUrls(input.urls),
|
|
13649
|
+
captureMode: input.captureMode ?? "off",
|
|
13650
|
+
mode: input.mode ?? "compact"
|
|
13651
|
+
};
|
|
13652
|
+
};
|
|
13653
|
+
var isInspiredesignWorkflowEnvelopeInput = (input) => {
|
|
13654
|
+
return "kind" in input && "input" in input;
|
|
13655
|
+
};
|
|
13656
|
+
var buildInspiredesignEnvelope = (input) => {
|
|
13657
|
+
if (isInspiredesignWorkflowEnvelopeInput(input)) {
|
|
13658
|
+
if (!isWorkflowResumeEnvelope(input)) {
|
|
13659
|
+
throw new Error("Inspiredesign workflow envelope is invalid.");
|
|
13660
|
+
}
|
|
13661
|
+
if (input.kind !== "inspiredesign") {
|
|
13662
|
+
throw new Error(`Inspiredesign workflow envelope kind mismatch. Expected inspiredesign but received ${input.kind}.`);
|
|
13663
|
+
}
|
|
13664
|
+
return {
|
|
13665
|
+
envelope: input,
|
|
13666
|
+
workflowInput: normalizeInspiredesignInput(parseInspiredesignEnvelopeInput(input.input))
|
|
13667
|
+
};
|
|
13668
|
+
}
|
|
13669
|
+
const workflowInput = normalizeInspiredesignInput(input);
|
|
13670
|
+
return {
|
|
13671
|
+
envelope: buildWorkflowResumeEnvelope("inspiredesign", serializeInspiredesignRunInput(workflowInput)),
|
|
13672
|
+
workflowInput
|
|
13673
|
+
};
|
|
13674
|
+
};
|
|
13675
|
+
var appendWorkflowTrace = (trace, stage, event, details) => [
|
|
13676
|
+
...trace,
|
|
13677
|
+
{
|
|
13678
|
+
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
13679
|
+
stage,
|
|
13680
|
+
event,
|
|
13681
|
+
details
|
|
13682
|
+
}
|
|
13683
|
+
];
|
|
13684
|
+
var buildInspiredesignStepEnvelope = (workflowInput, trace, stepIndex, url) => buildWorkflowResumeEnvelope(
|
|
13685
|
+
"inspiredesign",
|
|
13686
|
+
serializeInspiredesignRunInput(workflowInput),
|
|
13687
|
+
{
|
|
13688
|
+
checkpoint: {
|
|
13689
|
+
stage: "execute",
|
|
13690
|
+
stepId: "fetch_reference",
|
|
13691
|
+
stepIndex,
|
|
13692
|
+
state: { url },
|
|
13693
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
13694
|
+
},
|
|
13695
|
+
trace
|
|
13696
|
+
}
|
|
13697
|
+
);
|
|
13698
|
+
var buildInspiredesignFetchOptions = (workflowInput, envelope, timeoutMs) => withWorkflowResumeEnvelopeIntent(
|
|
13699
|
+
withChallengeAutomationOverride(
|
|
13700
|
+
withCookieOverrides({
|
|
13701
|
+
...typeof timeoutMs === "number" ? { timeoutMs } : {}
|
|
13702
|
+
}, workflowInput),
|
|
13703
|
+
workflowInput
|
|
13704
|
+
),
|
|
13705
|
+
"workflow.inspiredesign",
|
|
13706
|
+
envelope
|
|
13707
|
+
);
|
|
13708
|
+
var hasInspiredesignCaptureEvidence = (capture) => {
|
|
13709
|
+
if (!capture) return false;
|
|
13710
|
+
return Boolean(capture.title || capture.snapshot || capture.dom || capture.clone);
|
|
13711
|
+
};
|
|
13712
|
+
var captureInspiredesignReference = async (url, captureMode, workflowInput, captureReference, timeoutMs) => {
|
|
13713
|
+
if (captureMode === "off") {
|
|
13714
|
+
return { captureStatus: "off" };
|
|
13715
|
+
}
|
|
13716
|
+
if (!captureReference) {
|
|
13717
|
+
return {
|
|
13718
|
+
captureStatus: "failed",
|
|
13719
|
+
captureFailure: "Deep capture requested, but no browser capture callback was available."
|
|
13720
|
+
};
|
|
13721
|
+
}
|
|
13722
|
+
try {
|
|
13723
|
+
const capture = await captureReference(url, {
|
|
13724
|
+
timeoutMs,
|
|
13725
|
+
useCookies: workflowInput.useCookies,
|
|
13726
|
+
challengeAutomationMode: workflowInput.challengeAutomationMode,
|
|
13727
|
+
cookiePolicyOverride: workflowInput.cookiePolicyOverride
|
|
13728
|
+
});
|
|
13729
|
+
if (!hasInspiredesignCaptureEvidence(capture)) {
|
|
13730
|
+
return {
|
|
13731
|
+
captureStatus: "failed",
|
|
13732
|
+
captureFailure: "Deep capture did not return usable snapshot, DOM, or clone evidence."
|
|
13733
|
+
};
|
|
13734
|
+
}
|
|
13735
|
+
return {
|
|
13736
|
+
captureStatus: "captured",
|
|
13737
|
+
capture
|
|
13738
|
+
};
|
|
13739
|
+
} catch (error) {
|
|
13740
|
+
return {
|
|
13741
|
+
captureStatus: "failed",
|
|
13742
|
+
captureFailure: error instanceof Error ? error.message : "Deep capture failed."
|
|
13743
|
+
};
|
|
13744
|
+
}
|
|
13745
|
+
};
|
|
13746
|
+
var getInspiredesignPrimaryRecord = (result, url) => {
|
|
13747
|
+
const canonicalUrl = canonicalizeUrl(url);
|
|
13748
|
+
return result.records.find((record) => record.url && canonicalizeUrl(record.url) === canonicalUrl) ?? result.records[0];
|
|
13749
|
+
};
|
|
13750
|
+
var summarizeInspiredesignFetchFailure = (result) => {
|
|
13751
|
+
return summarizePrimaryProviderIssue(result.failures)?.summary ?? result.error?.message;
|
|
13752
|
+
};
|
|
13753
|
+
var excerptFromInspiredesignRecord = (record) => {
|
|
13754
|
+
const content = normalizePlainText(record?.content);
|
|
13755
|
+
if (!content) return void 0;
|
|
13756
|
+
return toSnippet(content, 240);
|
|
13757
|
+
};
|
|
13758
|
+
var buildInspiredesignReference = (url, result, capture) => {
|
|
13759
|
+
const primary = getInspiredesignPrimaryRecord(result, url);
|
|
13760
|
+
const title = primary?.title ?? capture.capture?.title;
|
|
13761
|
+
const excerpt = excerptFromInspiredesignRecord(primary);
|
|
13762
|
+
const fetchStatus = result.records.length > 0 ? "captured" : "failed";
|
|
13763
|
+
return {
|
|
13764
|
+
id: createHash7("sha256").update(url).digest("hex").slice(0, 12),
|
|
13765
|
+
url,
|
|
13766
|
+
...title ? { title } : {},
|
|
13767
|
+
...excerpt ? { excerpt } : {},
|
|
13768
|
+
fetchStatus,
|
|
13769
|
+
captureStatus: capture.captureStatus,
|
|
13770
|
+
...fetchStatus === "failed" && summarizeInspiredesignFetchFailure(result) ? { fetchFailure: summarizeInspiredesignFetchFailure(result) } : {},
|
|
13771
|
+
...capture.captureFailure ? { captureFailure: capture.captureFailure } : {},
|
|
13772
|
+
...capture.capture ? { capture: capture.capture } : {}
|
|
13773
|
+
};
|
|
13774
|
+
};
|
|
13775
|
+
var summarizeInspiredesignCaptureConstraint = (references) => {
|
|
13776
|
+
const failedReferences = references.filter((reference) => reference.captureStatus === "failed");
|
|
13777
|
+
if (failedReferences.length === 0) {
|
|
13778
|
+
return void 0;
|
|
13779
|
+
}
|
|
13780
|
+
const summary = `Deep capture failed for ${failedReferences.length} ${failedReferences.length === 1 ? "reference" : "references"}.`;
|
|
13781
|
+
const retryUrls = failedReferences.slice(0, 2).map((reference) => `Retry deep capture for ${reference.url} after restoring the required browser session state.`);
|
|
13782
|
+
return {
|
|
13783
|
+
summary,
|
|
13784
|
+
guidance: {
|
|
13785
|
+
reason: summary,
|
|
13786
|
+
recommendedNextCommands: [
|
|
13787
|
+
"Rerun inspiredesign after configuring providers.cookieSource for the protected references you need to capture.",
|
|
13788
|
+
...retryUrls
|
|
13789
|
+
]
|
|
13790
|
+
}
|
|
13791
|
+
};
|
|
13792
|
+
};
|
|
13793
|
+
var buildInspiredesignMeta = (runtime, workflowInput, references, failures, followthrough) => {
|
|
13794
|
+
const failedCaptures = references.filter((reference) => reference.captureStatus === "failed");
|
|
13795
|
+
let reasonCodeDistribution = summarizeReasonCodeDistribution(failures);
|
|
13796
|
+
let meta = withCamelCasePrimaryConstraintMeta(withReasonCodeDistributionMeta({
|
|
13797
|
+
selection: {
|
|
13798
|
+
urls: workflowInput.urls,
|
|
13799
|
+
capture_mode: workflowInput.captureMode,
|
|
13800
|
+
include_prototype_guidance: Boolean(workflowInput.includePrototypeGuidance)
|
|
13801
|
+
},
|
|
13802
|
+
metrics: {
|
|
13803
|
+
reference_count: references.length,
|
|
13804
|
+
fetched_references: references.filter((reference) => reference.fetchStatus === "captured").length,
|
|
13805
|
+
captured_references: references.filter((reference) => reference.captureStatus === "captured").length,
|
|
13806
|
+
failed_fetches: references.filter((reference) => reference.fetchStatus === "failed").length,
|
|
13807
|
+
failed_captures: failedCaptures.length
|
|
13808
|
+
},
|
|
13809
|
+
alerts: buildWorkflowAlerts(runtime, failures)
|
|
13810
|
+
}, reasonCodeDistribution), failures);
|
|
13811
|
+
if (!meta.primaryConstraint) {
|
|
13812
|
+
const captureConstraint = summarizeInspiredesignCaptureConstraint(references);
|
|
13813
|
+
if (captureConstraint) {
|
|
13814
|
+
reasonCodeDistribution = incrementReasonCodeDistribution(
|
|
13815
|
+
reasonCodeDistribution,
|
|
13816
|
+
"env_limited",
|
|
13817
|
+
failedCaptures.length
|
|
13818
|
+
);
|
|
13819
|
+
meta = withReasonCodeDistributionMeta(meta, reasonCodeDistribution);
|
|
13820
|
+
meta = withPrimaryConstraintSummaryOverride(meta, captureConstraint.summary, captureConstraint.guidance);
|
|
13821
|
+
}
|
|
13822
|
+
}
|
|
13823
|
+
return {
|
|
13824
|
+
...meta,
|
|
13825
|
+
followthroughSummary: followthrough.summary,
|
|
13826
|
+
recommendedSkills: followthrough.recommendedSkills,
|
|
13827
|
+
deepCaptureRecommendation: followthrough.deepCaptureRecommendation,
|
|
13828
|
+
contractScope: followthrough.contractScope
|
|
13829
|
+
};
|
|
13830
|
+
};
|
|
11959
13831
|
var inferBrandFromContent = (content) => {
|
|
11960
13832
|
const normalized = normalizePlainText(content);
|
|
11961
13833
|
if (!normalized) return void 0;
|
|
@@ -12551,11 +14423,13 @@ var runResearchWorkflow = async (runtime, input) => {
|
|
|
12551
14423
|
failures: mergedFailures,
|
|
12552
14424
|
alerts: buildWorkflowAlerts(runtime, mergedFailures)
|
|
12553
14425
|
}, primaryConstraintFailures);
|
|
14426
|
+
const handoff = buildResearchSuccessHandoff();
|
|
14427
|
+
const responseMeta = withFollowthroughMeta(meta, handoff);
|
|
12554
14428
|
const rendered = renderResearch({
|
|
12555
14429
|
mode: workflowInput.mode,
|
|
12556
14430
|
topic: plan.compiled.topic,
|
|
12557
14431
|
records: ranked,
|
|
12558
|
-
meta
|
|
14432
|
+
meta: responseMeta
|
|
12559
14433
|
});
|
|
12560
14434
|
const bundle = await createArtifactBundle({
|
|
12561
14435
|
namespace: "research",
|
|
@@ -12566,20 +14440,22 @@ var runResearchWorkflow = async (runtime, input) => {
|
|
|
12566
14440
|
if (workflowInput.mode === "path") {
|
|
12567
14441
|
return {
|
|
12568
14442
|
...rendered.response,
|
|
14443
|
+
...handoff,
|
|
12569
14444
|
path: bundle.basePath,
|
|
12570
14445
|
records: ranked,
|
|
12571
14446
|
meta: {
|
|
12572
|
-
...
|
|
14447
|
+
...responseMeta,
|
|
12573
14448
|
artifact_manifest: bundle.manifest
|
|
12574
14449
|
}
|
|
12575
14450
|
};
|
|
12576
14451
|
}
|
|
12577
14452
|
return {
|
|
12578
14453
|
...rendered.response,
|
|
14454
|
+
...handoff,
|
|
12579
14455
|
artifact_path: bundle.basePath,
|
|
12580
14456
|
records: ranked,
|
|
12581
14457
|
meta: {
|
|
12582
|
-
...
|
|
14458
|
+
...responseMeta,
|
|
12583
14459
|
artifact_manifest: bundle.manifest
|
|
12584
14460
|
}
|
|
12585
14461
|
};
|
|
@@ -12726,11 +14602,13 @@ var runShoppingWorkflow = async (runtime, input) => {
|
|
|
12726
14602
|
if (typeof filterConstraintSummary === "string") {
|
|
12727
14603
|
meta = withPrimaryConstraintSummaryOverride(meta, filterConstraintSummary);
|
|
12728
14604
|
}
|
|
14605
|
+
const handoff = buildShoppingSuccessHandoff();
|
|
14606
|
+
const responseMeta = withFollowthroughMeta(meta, handoff);
|
|
12729
14607
|
const rendered = renderShopping({
|
|
12730
14608
|
mode: workflowInput.mode,
|
|
12731
14609
|
query: plan.compiled.query,
|
|
12732
14610
|
offers,
|
|
12733
|
-
meta
|
|
14611
|
+
meta: responseMeta
|
|
12734
14612
|
});
|
|
12735
14613
|
const bundle = await createArtifactBundle({
|
|
12736
14614
|
namespace: "shopping",
|
|
@@ -12741,18 +14619,112 @@ var runShoppingWorkflow = async (runtime, input) => {
|
|
|
12741
14619
|
if (workflowInput.mode === "path") {
|
|
12742
14620
|
return {
|
|
12743
14621
|
...rendered.response,
|
|
14622
|
+
...handoff,
|
|
12744
14623
|
path: bundle.basePath,
|
|
12745
14624
|
offers,
|
|
12746
14625
|
meta: {
|
|
12747
|
-
...
|
|
14626
|
+
...responseMeta,
|
|
12748
14627
|
artifact_manifest: bundle.manifest
|
|
12749
14628
|
}
|
|
12750
14629
|
};
|
|
12751
14630
|
}
|
|
12752
14631
|
return {
|
|
12753
14632
|
...rendered.response,
|
|
14633
|
+
...handoff,
|
|
12754
14634
|
offers,
|
|
12755
14635
|
artifact_path: bundle.basePath,
|
|
14636
|
+
meta: {
|
|
14637
|
+
...responseMeta,
|
|
14638
|
+
artifact_manifest: bundle.manifest
|
|
14639
|
+
}
|
|
14640
|
+
};
|
|
14641
|
+
};
|
|
14642
|
+
var runInspiredesignWorkflow = async (runtime, input, options = {}) => {
|
|
14643
|
+
const { envelope, workflowInput } = buildInspiredesignEnvelope(input);
|
|
14644
|
+
const remainingTimeoutMs = createRemainingTimeoutResolver(workflowInput.timeoutMs);
|
|
14645
|
+
let trace = appendWorkflowTrace(envelope.trace ?? [], "compile", "compile_started", {
|
|
14646
|
+
kind: "inspiredesign"
|
|
14647
|
+
});
|
|
14648
|
+
trace = appendWorkflowTrace(trace, "compile", "compile_completed", {
|
|
14649
|
+
kind: "inspiredesign",
|
|
14650
|
+
urlCount: workflowInput.urls.length,
|
|
14651
|
+
captureMode: workflowInput.captureMode
|
|
14652
|
+
});
|
|
14653
|
+
const references = [];
|
|
14654
|
+
const failures = [];
|
|
14655
|
+
for (const [index, url] of workflowInput.urls.entries()) {
|
|
14656
|
+
const stepTrace = appendWorkflowTrace(trace, "execute", "reference_started", {
|
|
14657
|
+
stepIndex: index,
|
|
14658
|
+
url
|
|
14659
|
+
});
|
|
14660
|
+
const fetchTimeoutMs = remainingTimeoutMs();
|
|
14661
|
+
const result = await runtime.fetch(
|
|
14662
|
+
{ url },
|
|
14663
|
+
buildInspiredesignFetchOptions(
|
|
14664
|
+
workflowInput,
|
|
14665
|
+
buildInspiredesignStepEnvelope(workflowInput, stepTrace, index, url),
|
|
14666
|
+
fetchTimeoutMs
|
|
14667
|
+
)
|
|
14668
|
+
);
|
|
14669
|
+
observeWorkflowSignals(runtime, result);
|
|
14670
|
+
failures.push(...result.failures);
|
|
14671
|
+
const captureTimeoutMs = remainingTimeoutMs();
|
|
14672
|
+
const capture = await captureInspiredesignReference(
|
|
14673
|
+
url,
|
|
14674
|
+
workflowInput.captureMode,
|
|
14675
|
+
workflowInput,
|
|
14676
|
+
options.captureReference,
|
|
14677
|
+
captureTimeoutMs
|
|
14678
|
+
);
|
|
14679
|
+
references.push(buildInspiredesignReference(url, result, capture));
|
|
14680
|
+
trace = appendWorkflowTrace(stepTrace, "execute", "reference_completed", {
|
|
14681
|
+
stepIndex: index,
|
|
14682
|
+
url,
|
|
14683
|
+
fetchStatus: result.records.length > 0 ? "captured" : "failed",
|
|
14684
|
+
captureStatus: capture.captureStatus
|
|
14685
|
+
});
|
|
14686
|
+
}
|
|
14687
|
+
const packet = buildInspiredesignPacket({
|
|
14688
|
+
brief: workflowInput.brief,
|
|
14689
|
+
urls: workflowInput.urls,
|
|
14690
|
+
references,
|
|
14691
|
+
includePrototypeGuidance: workflowInput.includePrototypeGuidance
|
|
14692
|
+
});
|
|
14693
|
+
const meta = buildInspiredesignMeta(runtime, workflowInput, references, failures, packet.followthrough);
|
|
14694
|
+
const rendered = renderInspiredesign({
|
|
14695
|
+
mode: workflowInput.mode,
|
|
14696
|
+
brief: workflowInput.brief,
|
|
14697
|
+
urls: workflowInput.urls,
|
|
14698
|
+
designContract: packet.designContract,
|
|
14699
|
+
canvasPlanRequest: packet.canvasPlanRequest,
|
|
14700
|
+
designAgentHandoff: packet.followthrough,
|
|
14701
|
+
generationPlan: packet.generationPlan,
|
|
14702
|
+
implementationPlan: packet.implementationPlan,
|
|
14703
|
+
designMarkdown: packet.designMarkdown,
|
|
14704
|
+
implementationPlanMarkdown: packet.implementationPlanMarkdown,
|
|
14705
|
+
prototypeGuidanceMarkdown: packet.prototypeGuidanceMarkdown,
|
|
14706
|
+
evidence: packet.evidence,
|
|
14707
|
+
meta
|
|
14708
|
+
});
|
|
14709
|
+
const bundle = await createArtifactBundle({
|
|
14710
|
+
namespace: "inspiredesign",
|
|
14711
|
+
outputDir: workflowInput.outputDir,
|
|
14712
|
+
ttlHours: workflowInput.ttlHours,
|
|
14713
|
+
files: rendered.files
|
|
14714
|
+
});
|
|
14715
|
+
if (workflowInput.mode === "path") {
|
|
14716
|
+
return {
|
|
14717
|
+
...rendered.response,
|
|
14718
|
+
path: bundle.basePath,
|
|
14719
|
+
meta: {
|
|
14720
|
+
...meta,
|
|
14721
|
+
artifact_manifest: bundle.manifest
|
|
14722
|
+
}
|
|
14723
|
+
};
|
|
14724
|
+
}
|
|
14725
|
+
return {
|
|
14726
|
+
...rendered.response,
|
|
14727
|
+
artifact_path: bundle.basePath,
|
|
12756
14728
|
meta: {
|
|
12757
14729
|
...meta,
|
|
12758
14730
|
artifact_manifest: bundle.manifest
|
|
@@ -13101,32 +15073,35 @@ var runProductVideoWorkflow = async (runtime, input, options = {}) => {
|
|
|
13101
15073
|
const cookieDiagnostics = summarizeCookieDiagnostics(details.failures, details.records);
|
|
13102
15074
|
const antiBotPressure = summarizeAntiBotPressure(details.failures);
|
|
13103
15075
|
const primaryIssue = summarizePrimaryProviderIssue(details.failures);
|
|
15076
|
+
const handoff = buildProductVideoSuccessHandoff();
|
|
15077
|
+
const meta = withFollowthroughMeta({
|
|
15078
|
+
alerts: buildWorkflowAlerts(runtime, details.failures),
|
|
15079
|
+
failures: details.failures,
|
|
15080
|
+
...primaryIssue ? { primaryConstraintSummary: primaryIssue.summary } : {},
|
|
15081
|
+
reasonCodeDistribution,
|
|
15082
|
+
transcript_strategy_failures: transcriptStrategyFailures,
|
|
15083
|
+
transcriptStrategyFailures,
|
|
15084
|
+
transcript_strategy_detail_failures: transcriptStrategyFailures,
|
|
15085
|
+
transcriptStrategyDetailFailures: transcriptStrategyFailures,
|
|
15086
|
+
transcript_strategy_detail_distribution: transcriptStrategyDetailDistribution,
|
|
15087
|
+
transcriptStrategyDetailDistribution,
|
|
15088
|
+
transcript_durability: transcriptDurability,
|
|
15089
|
+
transcriptDurability,
|
|
15090
|
+
cookie_diagnostics: cookieDiagnostics,
|
|
15091
|
+
cookieDiagnostics,
|
|
15092
|
+
anti_bot_pressure: antiBotPressure,
|
|
15093
|
+
antiBotPressure,
|
|
15094
|
+
artifact_manifest: bundle.manifest
|
|
15095
|
+
}, handoff);
|
|
13104
15096
|
return {
|
|
15097
|
+
...handoff,
|
|
13105
15098
|
path: bundle.basePath,
|
|
13106
15099
|
manifest: manifestPayload,
|
|
13107
15100
|
product: productPayload,
|
|
13108
15101
|
pricing,
|
|
13109
15102
|
screenshots: screenshotPaths,
|
|
13110
15103
|
images: imagePaths,
|
|
13111
|
-
meta
|
|
13112
|
-
alerts: buildWorkflowAlerts(runtime, details.failures),
|
|
13113
|
-
failures: details.failures,
|
|
13114
|
-
...primaryIssue ? { primaryConstraintSummary: primaryIssue.summary } : {},
|
|
13115
|
-
reasonCodeDistribution,
|
|
13116
|
-
transcript_strategy_failures: transcriptStrategyFailures,
|
|
13117
|
-
transcriptStrategyFailures,
|
|
13118
|
-
transcript_strategy_detail_failures: transcriptStrategyFailures,
|
|
13119
|
-
transcriptStrategyDetailFailures: transcriptStrategyFailures,
|
|
13120
|
-
transcript_strategy_detail_distribution: transcriptStrategyDetailDistribution,
|
|
13121
|
-
transcriptStrategyDetailDistribution,
|
|
13122
|
-
transcript_durability: transcriptDurability,
|
|
13123
|
-
transcriptDurability,
|
|
13124
|
-
cookie_diagnostics: cookieDiagnostics,
|
|
13125
|
-
cookieDiagnostics,
|
|
13126
|
-
anti_bot_pressure: antiBotPressure,
|
|
13127
|
-
antiBotPressure,
|
|
13128
|
-
artifact_manifest: bundle.manifest
|
|
13129
|
-
}
|
|
15104
|
+
meta
|
|
13130
15105
|
};
|
|
13131
15106
|
};
|
|
13132
15107
|
|
|
@@ -13140,6 +15115,7 @@ var DEFAULT_PROVIDER_SUSPENDED_INTENT_KIND = {
|
|
|
13140
15115
|
var WORKFLOW_KIND_BY_SUSPENDED_INTENT_KIND2 = {
|
|
13141
15116
|
"workflow.research": "research",
|
|
13142
15117
|
"workflow.shopping": "shopping",
|
|
15118
|
+
"workflow.inspiredesign": "inspiredesign",
|
|
13143
15119
|
"workflow.product_video": "product_video"
|
|
13144
15120
|
};
|
|
13145
15121
|
var EXTENSION_FIRST_SOCIAL_FALLBACK_PLATFORMS = /* @__PURE__ */ new Set(["x", "reddit", "bluesky", "linkedin"]);
|
|
@@ -14586,6 +16562,14 @@ var ProviderRuntime = class {
|
|
|
14586
16562
|
input
|
|
14587
16563
|
)
|
|
14588
16564
|
);
|
|
16565
|
+
case "workflow.inspiredesign":
|
|
16566
|
+
return runInspiredesignWorkflow(
|
|
16567
|
+
this,
|
|
16568
|
+
unwrapWorkflowResumeEnvelope(
|
|
16569
|
+
WORKFLOW_KIND_BY_SUSPENDED_INTENT_KIND2[intent.kind],
|
|
16570
|
+
input
|
|
16571
|
+
)
|
|
16572
|
+
);
|
|
14589
16573
|
case "workflow.product_video":
|
|
14590
16574
|
return runProductVideoWorkflow(
|
|
14591
16575
|
this,
|
|
@@ -14743,25 +16727,38 @@ var ProviderRuntime = class {
|
|
|
14743
16727
|
}
|
|
14744
16728
|
async withTimeout(timeoutMs, task) {
|
|
14745
16729
|
const controller = new AbortController();
|
|
14746
|
-
const
|
|
14747
|
-
|
|
14748
|
-
|
|
16730
|
+
const createTimeoutError = (cause) => {
|
|
16731
|
+
return new ProviderRuntimeError("timeout", `Provider request timed out after ${timeoutMs}ms`, {
|
|
16732
|
+
retryable: true,
|
|
16733
|
+
...cause !== void 0 ? { cause } : {}
|
|
16734
|
+
});
|
|
16735
|
+
};
|
|
16736
|
+
const taskPromise = Promise.resolve().then(() => task(controller.signal));
|
|
16737
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
16738
|
+
const timeoutId = setTimeout(() => {
|
|
16739
|
+
controller.abort("timeout");
|
|
16740
|
+
reject(createTimeoutError());
|
|
16741
|
+
}, timeoutMs);
|
|
16742
|
+
controller.signal.addEventListener("abort", () => clearTimeout(timeoutId), { once: true });
|
|
16743
|
+
});
|
|
14749
16744
|
try {
|
|
14750
|
-
|
|
14751
|
-
|
|
14752
|
-
|
|
14753
|
-
|
|
14754
|
-
|
|
16745
|
+
return await Promise.race([
|
|
16746
|
+
taskPromise.catch((error) => {
|
|
16747
|
+
if (controller.signal.aborted) {
|
|
16748
|
+
throw createTimeoutError(error);
|
|
16749
|
+
}
|
|
16750
|
+
throw error;
|
|
16751
|
+
}),
|
|
16752
|
+
timeoutPromise
|
|
16753
|
+
]);
|
|
14755
16754
|
} catch (error) {
|
|
16755
|
+
if (isProviderRuntimeError(error) && error.code === "timeout") {
|
|
16756
|
+
throw error;
|
|
16757
|
+
}
|
|
14756
16758
|
if (controller.signal.aborted) {
|
|
14757
|
-
throw
|
|
14758
|
-
retryable: true,
|
|
14759
|
-
cause: error
|
|
14760
|
-
});
|
|
16759
|
+
throw createTimeoutError(error);
|
|
14761
16760
|
}
|
|
14762
16761
|
throw error;
|
|
14763
|
-
} finally {
|
|
14764
|
-
clearTimeout(timeoutId);
|
|
14765
16762
|
}
|
|
14766
16763
|
}
|
|
14767
16764
|
};
|
|
@@ -15189,6 +17186,7 @@ var mergeBudgets = (base, partial) => {
|
|
|
15189
17186
|
};
|
|
15190
17187
|
|
|
15191
17188
|
export {
|
|
17189
|
+
redactSensitive,
|
|
15192
17190
|
createRequestId,
|
|
15193
17191
|
stderrSink,
|
|
15194
17192
|
setDefaultLogSink,
|
|
@@ -15204,6 +17202,7 @@ export {
|
|
|
15204
17202
|
CHALLENGE_AUTOMATION_MODES,
|
|
15205
17203
|
isChallengeAutomationMode,
|
|
15206
17204
|
resolveChallengeAutomationPolicy,
|
|
17205
|
+
inspectChallengePlanFromRuntime,
|
|
15207
17206
|
ChallengeOrchestrator,
|
|
15208
17207
|
summarizePrimaryProviderIssue,
|
|
15209
17208
|
createTraceContext,
|
|
@@ -15242,15 +17241,19 @@ export {
|
|
|
15242
17241
|
filterByTimebox,
|
|
15243
17242
|
toResearchRecord,
|
|
15244
17243
|
enrichResearchRecords,
|
|
17244
|
+
INSPIREDESIGN_HANDOFF_COMMANDS,
|
|
17245
|
+
INSPIREDESIGN_HANDOFF_GUIDANCE,
|
|
15245
17246
|
renderResearch,
|
|
15246
17247
|
renderShopping,
|
|
17248
|
+
renderInspiredesign,
|
|
15247
17249
|
workflowTestUtils,
|
|
15248
17250
|
runResearchWorkflow,
|
|
15249
17251
|
runShoppingWorkflow,
|
|
17252
|
+
runInspiredesignWorkflow,
|
|
15250
17253
|
runProductVideoWorkflow,
|
|
15251
17254
|
DEFAULT_PROVIDER_BUDGETS,
|
|
15252
17255
|
ProviderRuntime,
|
|
15253
17256
|
createProviderRuntime,
|
|
15254
17257
|
createDefaultRuntime
|
|
15255
17258
|
};
|
|
15256
|
-
//# sourceMappingURL=chunk-
|
|
17259
|
+
//# sourceMappingURL=chunk-ZE2E7ZGH.js.map
|