shotops-mcp 0.9.5 → 0.9.6
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/dist/local.js
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
}
|
|
25
25
|
await visit('')
|
|
26
26
|
return hash.digest('hex')
|
|
27
|
-
})(sourceDirectory) !== "
|
|
27
|
+
})(sourceDirectory) !== "5df467e22a054acf0779df03013843f6f55d0a3e8cb9f87ecca7dca8eef02f46") {
|
|
28
28
|
console.error('shotops-mcp: dist/local.js is stale; run npm run build in shotops-mcp.');
|
|
29
29
|
}
|
|
30
30
|
} catch { /* An unreadable checkout must not break an otherwise working CLI. */ }
|
|
@@ -1892,6 +1892,12 @@ var init_fonts = __esm({
|
|
|
1892
1892
|
});
|
|
1893
1893
|
|
|
1894
1894
|
// ../mockup-engine/appstore/refineIntent.ts
|
|
1895
|
+
function requestsBroaderDeviceScope(instruction) {
|
|
1896
|
+
return BROADER_DEVICE_SCOPE.test(instruction) || NUMBERED_SIBLING_SCOPE.test(instruction);
|
|
1897
|
+
}
|
|
1898
|
+
function canRepairLayoutForFocus(focus, instruction) {
|
|
1899
|
+
return focus?.kind !== "device" || requestsBroaderDeviceScope(instruction);
|
|
1900
|
+
}
|
|
1895
1901
|
function structuralOperationTargets(operation) {
|
|
1896
1902
|
switch (operation.op) {
|
|
1897
1903
|
case "frame.add":
|
|
@@ -1931,7 +1937,7 @@ function resolveAiNumber(input, current, range) {
|
|
|
1931
1937
|
if (raw === void 0 || !Number.isFinite(raw)) return void 0;
|
|
1932
1938
|
return Math.min(Math.max(raw, range.min), range.max);
|
|
1933
1939
|
}
|
|
1934
|
-
var MAX_REFINE_PROMPT_LENGTH, AI_COLORWAY_IDS, AI_CLAY_TONES, AI_SHOT_RANGES, AI_SCALE_RANGE, AI_CAPTION_FONT_IDS, AI_CAPTION_RANGES, AI_GRADIENT_STOPS;
|
|
1940
|
+
var MAX_REFINE_PROMPT_LENGTH, AI_COLORWAY_IDS, AI_CLAY_TONES, AI_SHOT_RANGES, AI_SCALE_RANGE, AI_CAPTION_FONT_IDS, AI_CAPTION_RANGES, AI_GRADIENT_STOPS, BROADER_DEVICE_SCOPE, NUMBERED_SIBLING_SCOPE;
|
|
1935
1941
|
var init_refineIntent = __esm({
|
|
1936
1942
|
"../mockup-engine/appstore/refineIntent.ts"() {
|
|
1937
1943
|
"use strict";
|
|
@@ -1949,6 +1955,8 @@ var init_refineIntent = __esm({
|
|
|
1949
1955
|
AI_CAPTION_FONT_IDS = CAPTION_FONT_IDS;
|
|
1950
1956
|
AI_CAPTION_RANGES = CAPTION_STYLE_BOUNDS;
|
|
1951
1957
|
AI_GRADIENT_STOPS = { min: 1, max: 6 };
|
|
1958
|
+
BROADER_DEVICE_SCOPE = /\b(?:all|every|each|both|entire|whole|across|throughout|other|others|rest|remaining|project|strip|frames|screenshots|screens|devices|phones|captions)\b/i;
|
|
1959
|
+
NUMBERED_SIBLING_SCOPE = /\b(?:frame|device|phone)\s+\d+\b/i;
|
|
1952
1960
|
}
|
|
1953
1961
|
});
|
|
1954
1962
|
|
|
@@ -3259,7 +3267,7 @@ function presetCaptionStyle(preset) {
|
|
|
3259
3267
|
return { ...preset.caption };
|
|
3260
3268
|
}
|
|
3261
3269
|
function presetShotLook(preset) {
|
|
3262
|
-
return { ...preset.shotLook };
|
|
3270
|
+
return { ...preset.shotLook, ...preset.shotLook.angle !== void 0 ? { cameraPos: null } : {} };
|
|
3263
3271
|
}
|
|
3264
3272
|
function expandLookChoice(designPreset, layout) {
|
|
3265
3273
|
const preset = designPreset === void 0 ? void 0 : designPresetById(designPreset);
|
|
@@ -7117,8 +7125,8 @@ var init_agentCapabilities = __esm({
|
|
|
7117
7125
|
studioCommands: ["addPanel"],
|
|
7118
7126
|
wire: "structuralOperations: frame.add",
|
|
7119
7127
|
targets: ["project"],
|
|
7120
|
-
requiredInputs: ["afterFrameId (optional)"],
|
|
7121
|
-
limits: ["
|
|
7128
|
+
requiredInputs: ["afterFrameId (optional)", "frameRef (optional, patch-local alias)"],
|
|
7129
|
+
limits: ["Declare frameRef to address the new frame in later ordered operations of the same patch. Without frameRef, wait until the next cycle reports its id."],
|
|
7122
7130
|
evaluationCases: ["structure-add-closing-frame"]
|
|
7123
7131
|
},
|
|
7124
7132
|
{
|
|
@@ -7566,8 +7574,8 @@ function validateAgentOutcome(outcome) {
|
|
|
7566
7574
|
if (outcome.status === "applied_with_remaining" && !outcome.remaining) {
|
|
7567
7575
|
problems.push("applied_with_remaining must name what is still outstanding.");
|
|
7568
7576
|
}
|
|
7569
|
-
if (outcome.question !== void 0 && outcome.status !== "needs_clarification") {
|
|
7570
|
-
problems.push(`Only needs_clarification
|
|
7577
|
+
if (outcome.question !== void 0 && outcome.status !== "needs_clarification" && outcome.status !== "needs_asset") {
|
|
7578
|
+
problems.push(`Only needs_clarification and needs_asset carry a question, not ${outcome.status}.`);
|
|
7571
7579
|
}
|
|
7572
7580
|
if (outcome.status === "needs_clarification" && !outcome.question) {
|
|
7573
7581
|
problems.push("needs_clarification must ask exactly one focused question.");
|
|
@@ -7575,6 +7583,16 @@ function validateAgentOutcome(outcome) {
|
|
|
7575
7583
|
if (outcome.capabilityId !== void 0 && !capabilityById(outcome.capabilityId)) {
|
|
7576
7584
|
problems.push(`Outcome names capability ${JSON.stringify(outcome.capabilityId)}, which the catalog does not list.`);
|
|
7577
7585
|
}
|
|
7586
|
+
if (outcome.capabilityIds !== void 0) {
|
|
7587
|
+
if (!Array.isArray(outcome.capabilityIds) || outcome.capabilityIds.length > MAX_OUTCOME_CAPABILITY_IDS) {
|
|
7588
|
+
problems.push(`capabilityIds must be a list of at most ${MAX_OUTCOME_CAPABILITY_IDS} catalog ids.`);
|
|
7589
|
+
} else {
|
|
7590
|
+
for (const id of outcome.capabilityIds) {
|
|
7591
|
+
if (typeof id !== "string" || !capabilityById(id)) problems.push(`Outcome lists capability ${JSON.stringify(id)}, which the catalog does not list.`);
|
|
7592
|
+
}
|
|
7593
|
+
if (new Set(outcome.capabilityIds).size !== outcome.capabilityIds.length) problems.push("capabilityIds repeats an id.");
|
|
7594
|
+
}
|
|
7595
|
+
}
|
|
7578
7596
|
problems.push(...boundProblems("headline", outcome.headline, AGENT_OUTCOME_BOUNDS.headline, true));
|
|
7579
7597
|
problems.push(...boundProblems("detail", outcome.detail, AGENT_OUTCOME_BOUNDS.detail, false));
|
|
7580
7598
|
problems.push(...boundProblems("remaining", outcome.remaining, AGENT_OUTCOME_BOUNDS.remaining, false));
|
|
@@ -7591,6 +7609,77 @@ function boundProblems(field, value, maximum, required) {
|
|
|
7591
7609
|
if (value.length > maximum) return [`${field} is ${value.length} characters, over its ${maximum} bound.`];
|
|
7592
7610
|
return [];
|
|
7593
7611
|
}
|
|
7612
|
+
function capabilitiesForPatch(patch) {
|
|
7613
|
+
const ids = [];
|
|
7614
|
+
if (!patch) return ids;
|
|
7615
|
+
const add = (id) => {
|
|
7616
|
+
if (ids.indexOf(id) < 0) ids.push(id);
|
|
7617
|
+
};
|
|
7618
|
+
if (patch.captions) add("caption.text");
|
|
7619
|
+
if (patch.screenOrder) add("frame.reorder");
|
|
7620
|
+
if (patch.designPreset) add("look.design-preset");
|
|
7621
|
+
if (patch.layout) add("look.layout-template");
|
|
7622
|
+
if (patch.outputs) add("output.membership");
|
|
7623
|
+
if (patch.locales) add("locale.membership");
|
|
7624
|
+
if (patch.shots?.some((shot) => Object.keys(shot).length > 0)) add("device.look");
|
|
7625
|
+
if (patch.devices?.some((device) => Object.keys(device.patch).length > 0)) add("device.look");
|
|
7626
|
+
if (patch.captionStyle && Object.keys(patch.captionStyle).length > 0) add("caption.style");
|
|
7627
|
+
if (patch.background && Object.keys(patch.background).length > 0) add("strip.background");
|
|
7628
|
+
patch.frames?.forEach((frame) => {
|
|
7629
|
+
if (frame.captionStyle && Object.keys(frame.captionStyle).length > 0) add("caption.style");
|
|
7630
|
+
if (frame.background && Object.keys(frame.background).length > 0) add("frame.background");
|
|
7631
|
+
});
|
|
7632
|
+
patch.captionOperations?.forEach((operation) => {
|
|
7633
|
+
if (operation.operation === "add") add("caption.add");
|
|
7634
|
+
else if (operation.operation === "remove") add("caption.remove");
|
|
7635
|
+
else add(operation.frameId === operation.toFrameId ? "caption.reorder" : "caption.move-to-frame");
|
|
7636
|
+
});
|
|
7637
|
+
patch.frameOperations?.forEach((operation) => {
|
|
7638
|
+
if (operation.operation === "add") add("frame.add");
|
|
7639
|
+
else if (operation.operation === "remove") add("frame.remove");
|
|
7640
|
+
else if (operation.operation === "move") add("frame.reorder");
|
|
7641
|
+
else add("frame.split");
|
|
7642
|
+
});
|
|
7643
|
+
patch.structuralOperations?.forEach((operation) => add(capabilityForStructuralOperation(operation)));
|
|
7644
|
+
return ids;
|
|
7645
|
+
}
|
|
7646
|
+
function capabilityForStructuralOperation(operation) {
|
|
7647
|
+
switch (operation.op) {
|
|
7648
|
+
case "frame.add":
|
|
7649
|
+
return "frame.add";
|
|
7650
|
+
case "frame.remove":
|
|
7651
|
+
return "frame.remove";
|
|
7652
|
+
case "frame.move":
|
|
7653
|
+
return "frame.reorder";
|
|
7654
|
+
case "frame.split":
|
|
7655
|
+
return "frame.split";
|
|
7656
|
+
case "frame.combine":
|
|
7657
|
+
return "frame.combine";
|
|
7658
|
+
case "frame.template-reset":
|
|
7659
|
+
return "look.layout-template";
|
|
7660
|
+
case "caption.add":
|
|
7661
|
+
return "caption.add";
|
|
7662
|
+
case "caption.remove":
|
|
7663
|
+
return "caption.remove";
|
|
7664
|
+
// One `caption.move` covers both Studio controls: staying inside a frame is a reorder, crossing
|
|
7665
|
+
// to another is a move. The catalog names them separately because the user experiences them
|
|
7666
|
+
// separately.
|
|
7667
|
+
case "caption.move":
|
|
7668
|
+
return operation.frameId === operation.toFrameId ? "caption.reorder" : "caption.move-to-frame";
|
|
7669
|
+
case "device.move":
|
|
7670
|
+
return "device.move-to-frame";
|
|
7671
|
+
case "device.reorder":
|
|
7672
|
+
return "device.reorder";
|
|
7673
|
+
case "device.remove":
|
|
7674
|
+
return "device.remove";
|
|
7675
|
+
case "device.add":
|
|
7676
|
+
return "device.add";
|
|
7677
|
+
// The catalog names this one for what the user experiences — the pixels change, the device does
|
|
7678
|
+
// not — so the id deliberately does not match the wire's `device.replace`.
|
|
7679
|
+
case "device.replace":
|
|
7680
|
+
return "device.replace-pixels";
|
|
7681
|
+
}
|
|
7682
|
+
}
|
|
7594
7683
|
function applicationOutcome(facts) {
|
|
7595
7684
|
if (facts.conflicted) {
|
|
7596
7685
|
return {
|
|
@@ -7654,7 +7743,14 @@ function cancelledOutcome() {
|
|
|
7654
7743
|
changed: []
|
|
7655
7744
|
};
|
|
7656
7745
|
}
|
|
7657
|
-
|
|
7746
|
+
function withTouchedCapabilities(outcome, touched) {
|
|
7747
|
+
const ids = [];
|
|
7748
|
+
for (const id of touched) if (capabilityById(id) && ids.indexOf(id) < 0) ids.push(id);
|
|
7749
|
+
if (outcome.capabilityId && capabilityById(outcome.capabilityId) && ids.indexOf(outcome.capabilityId) < 0) ids.push(outcome.capabilityId);
|
|
7750
|
+
if (ids.length === 0) return outcome;
|
|
7751
|
+
return { ...outcome, capabilityIds: ids.slice(0, MAX_OUTCOME_CAPABILITY_IDS) };
|
|
7752
|
+
}
|
|
7753
|
+
var AGENT_OUTCOME_STATUSES, AGENT_MUTATING_STATUSES, AGENT_OUTCOME_REASONS, AGENT_OUTCOME_BOUNDS, MAX_OUTCOME_CAPABILITY_IDS;
|
|
7658
7754
|
var init_agentOutcome = __esm({
|
|
7659
7755
|
"../mockup-engine/appstore/agentOutcome.ts"() {
|
|
7660
7756
|
"use strict";
|
|
@@ -7693,9 +7789,39 @@ var init_agentOutcome = __esm({
|
|
|
7693
7789
|
remaining: 300,
|
|
7694
7790
|
/** The label on the single next step. */
|
|
7695
7791
|
nextStep: 120,
|
|
7696
|
-
/**
|
|
7697
|
-
question:
|
|
7792
|
+
/** Transport ceiling for a complete assistant question or screenshot request; never clip it. */
|
|
7793
|
+
question: 32e3
|
|
7698
7794
|
};
|
|
7795
|
+
MAX_OUTCOME_CAPABILITY_IDS = 16;
|
|
7796
|
+
}
|
|
7797
|
+
});
|
|
7798
|
+
|
|
7799
|
+
// ../mockup-engine/appstore/agentUnmetActions.ts
|
|
7800
|
+
function normalizeIds(ids) {
|
|
7801
|
+
return Array.from(new Set(ids)).sort().slice(0, MAX_UNMET_ACTIONS_PER_TURN);
|
|
7802
|
+
}
|
|
7803
|
+
function classifiedDemand(ids) {
|
|
7804
|
+
return { classification: "classified", actionIds: normalizeIds(ids) };
|
|
7805
|
+
}
|
|
7806
|
+
var AGENT_UNMET_ACTION_UNKNOWN, MAX_UNMET_ACTIONS_PER_TURN, AGENT_UNMET_ACTIONS, CAPABILITY_IDS, AGENT_UNMET_ACTION_VOCABULARY, NOT_MEASURED_DEMAND;
|
|
7807
|
+
var init_agentUnmetActions = __esm({
|
|
7808
|
+
"../mockup-engine/appstore/agentUnmetActions.ts"() {
|
|
7809
|
+
"use strict";
|
|
7810
|
+
init_agentCapabilities();
|
|
7811
|
+
AGENT_UNMET_ACTION_UNKNOWN = "unknown";
|
|
7812
|
+
MAX_UNMET_ACTIONS_PER_TURN = 8;
|
|
7813
|
+
AGENT_UNMET_ACTIONS = [
|
|
7814
|
+
{ id: "image.generate", summary: "Generate or paint new imagery rather than arranging supplied screenshots." },
|
|
7815
|
+
{ id: "animation.create", summary: "Animate a screen, produce a video, or export motion instead of stills." },
|
|
7816
|
+
{ id: "device.unsupported-model", summary: "Use a device model ShotOps does not offer." }
|
|
7817
|
+
];
|
|
7818
|
+
CAPABILITY_IDS = AGENT_CAPABILITIES.map((capability) => capability.id);
|
|
7819
|
+
AGENT_UNMET_ACTION_VOCABULARY = [
|
|
7820
|
+
...CAPABILITY_IDS,
|
|
7821
|
+
...AGENT_UNMET_ACTIONS.map((action) => action.id),
|
|
7822
|
+
AGENT_UNMET_ACTION_UNKNOWN
|
|
7823
|
+
];
|
|
7824
|
+
NOT_MEASURED_DEMAND = { classification: "not_measured", actionIds: [] };
|
|
7699
7825
|
}
|
|
7700
7826
|
});
|
|
7701
7827
|
|
|
@@ -8164,7 +8290,7 @@ function applyFrameOperation(state, operation) {
|
|
|
8164
8290
|
if (operation.operation === "add") {
|
|
8165
8291
|
if (operation.afterFrameId !== void 0 && panelIndex(state, operation.afterFrameId) < 0) return null;
|
|
8166
8292
|
const frameId = nextAgentPanelId(state);
|
|
8167
|
-
const added = addPanel(state, frameId);
|
|
8293
|
+
const added = inheritFrameTemplate(addPanel(state, frameId), frameId, operation.afterFrameId ?? state.panels[state.panels.length - 1]?.id);
|
|
8168
8294
|
return operation.afterFrameId === void 0 ? added : movePanelAfter(added, frameId, operation.afterFrameId);
|
|
8169
8295
|
}
|
|
8170
8296
|
if (operation.operation === "remove") {
|
|
@@ -8187,7 +8313,17 @@ function applyFrameOperation(state, operation) {
|
|
|
8187
8313
|
if (!moved) return null;
|
|
8188
8314
|
next = moved;
|
|
8189
8315
|
}
|
|
8190
|
-
return next;
|
|
8316
|
+
return inheritFrameTemplate(next, newFrameId, operation.frameId);
|
|
8317
|
+
}
|
|
8318
|
+
function inheritFrameTemplate(state, panelId, fromPanelId) {
|
|
8319
|
+
const source = fromPanelId === void 0 ? void 0 : state.frameTemplates?.[fromPanelId];
|
|
8320
|
+
if (!source) return state;
|
|
8321
|
+
const baseline = captureFrameTemplateBaseline(
|
|
8322
|
+
{ shots: state.shots, captionText: state.captionText, captionSlotIds: captionSlotIds(state), baseLocale: state.baseLocale },
|
|
8323
|
+
panelId,
|
|
8324
|
+
source.templateId
|
|
8325
|
+
);
|
|
8326
|
+
return { ...state, frameTemplates: { ...state.frameTemplates ?? {}, [panelId]: baseline } };
|
|
8191
8327
|
}
|
|
8192
8328
|
function addCaptionLayer(state, panelId, text3, style2) {
|
|
8193
8329
|
const source = state.captionText[state.baseLocale] ?? {};
|
|
@@ -8496,16 +8632,39 @@ function applyStructuralOperation(state, operation, assets = [], bindings) {
|
|
|
8496
8632
|
function applyStructuralOperations(state, patch, assets = []) {
|
|
8497
8633
|
let next = state;
|
|
8498
8634
|
const assetBindings = [];
|
|
8499
|
-
|
|
8635
|
+
const frameRefs = /* @__PURE__ */ new Map();
|
|
8636
|
+
const retiredRefs = /* @__PURE__ */ new Set();
|
|
8637
|
+
for (const raw of normalizeStructuralOperations(patch)) {
|
|
8638
|
+
const ref = raw.op === "frame.add" ? raw.frameRef : void 0;
|
|
8639
|
+
if (ref !== void 0 && (!/^[A-Za-z][A-Za-z0-9_-]{0,63}$/.test(ref) || frameRefs.has(ref) || state.panels.some((panel) => panel.id === ref) || state.shots.some((shot) => shot.id === ref))) return null;
|
|
8640
|
+
if (structuralOperationTargets(raw).frameIds.some((id) => retiredRefs.has(id))) return null;
|
|
8641
|
+
const resolve14 = (id) => frameRefs.get(id) ?? id;
|
|
8642
|
+
const operation = {
|
|
8643
|
+
...raw,
|
|
8644
|
+
..."frameId" in raw ? { frameId: resolve14(raw.frameId) } : {},
|
|
8645
|
+
..."toFrameId" in raw ? { toFrameId: resolve14(raw.toFrameId) } : {},
|
|
8646
|
+
..."fromFrameId" in raw ? { fromFrameId: resolve14(raw.fromFrameId) } : {},
|
|
8647
|
+
..."afterFrameId" in raw && raw.afterFrameId !== void 0 ? { afterFrameId: resolve14(raw.afterFrameId) } : {}
|
|
8648
|
+
};
|
|
8500
8649
|
const applied = applyStructuralOperation(next, operation, assets, assetBindings);
|
|
8501
8650
|
if (!applied) return null;
|
|
8651
|
+
if (ref !== void 0) {
|
|
8652
|
+
const created = applied.panels.find((panel) => !next.panels.some((previous) => previous.id === panel.id));
|
|
8653
|
+
if (!created) return null;
|
|
8654
|
+
frameRefs.set(ref, created.id);
|
|
8655
|
+
}
|
|
8656
|
+
frameRefs.forEach((id, alias) => {
|
|
8657
|
+
if (!applied.panels.some((panel) => panel.id === id)) retiredRefs.add(alias);
|
|
8658
|
+
});
|
|
8502
8659
|
next = applied;
|
|
8503
8660
|
}
|
|
8504
|
-
|
|
8661
|
+
const survivingRefs = Array.from(frameRefs.entries()).filter(([alias]) => !retiredRefs.has(alias));
|
|
8662
|
+
return { state: next, assetBindings, ...survivingRefs.length > 0 ? { frameRefs: Object.fromEntries(survivingRefs) } : {} };
|
|
8505
8663
|
}
|
|
8506
8664
|
var init_refinementStructure = __esm({
|
|
8507
8665
|
"../mockup-engine/appstore/refinementStructure.ts"() {
|
|
8508
8666
|
"use strict";
|
|
8667
|
+
init_refineIntent();
|
|
8509
8668
|
init_defaults();
|
|
8510
8669
|
init_recordTransforms();
|
|
8511
8670
|
init_shot();
|
|
@@ -8877,7 +9036,7 @@ function applyProjectRefinementWithAssets(state, patch, panelIds, assets = []) {
|
|
|
8877
9036
|
next = { ...next, panels, shots: shotsInPanelOrder(next.shots, panels) };
|
|
8878
9037
|
}
|
|
8879
9038
|
}
|
|
8880
|
-
return { state: next, assetBindings: structured.assetBindings };
|
|
9039
|
+
return { state: next, assetBindings: structured.assetBindings, ...structured.frameRefs ? { frameRefs: structured.frameRefs } : {} };
|
|
8881
9040
|
}
|
|
8882
9041
|
var init_refinement = __esm({
|
|
8883
9042
|
"../mockup-engine/appstore/refinement.ts"() {
|
|
@@ -8964,6 +9123,67 @@ var init_appStoreLocales = __esm({
|
|
|
8964
9123
|
}
|
|
8965
9124
|
});
|
|
8966
9125
|
|
|
9126
|
+
// ../mockup-engine/appstore/agentTurnRepetition.ts
|
|
9127
|
+
function creationOf(operation) {
|
|
9128
|
+
if (!CREATING_OPS.has(operation.op)) return null;
|
|
9129
|
+
const target = "frameId" in operation ? operation.frameId : "toFrameId" in operation ? operation.toFrameId : "afterFrameId" in operation && operation.afterFrameId ? `after:${operation.afterFrameId}` : "strip";
|
|
9130
|
+
return { op: operation.op, target };
|
|
9131
|
+
}
|
|
9132
|
+
function contextualCreations(operations, resolved = {}) {
|
|
9133
|
+
const refs = /* @__PURE__ */ new Map();
|
|
9134
|
+
return operations.map((operation) => {
|
|
9135
|
+
const creation = creationOf(operation);
|
|
9136
|
+
const target = creation?.target;
|
|
9137
|
+
const normalized = creation && target !== void 0 ? {
|
|
9138
|
+
...creation,
|
|
9139
|
+
target: target.startsWith("after:") ? `after:${refs.get(target.slice(6)) ?? target.slice(6)}` : refs.get(target) ?? target
|
|
9140
|
+
} : null;
|
|
9141
|
+
if (operation.op === "frame.add" && operation.frameRef && normalized) {
|
|
9142
|
+
refs.set(operation.frameRef, Object.prototype.hasOwnProperty.call(resolved, operation.frameRef) ? resolved[operation.frameRef] : `created-frame:${normalized.target}`);
|
|
9143
|
+
}
|
|
9144
|
+
return normalized;
|
|
9145
|
+
});
|
|
9146
|
+
}
|
|
9147
|
+
function creationsIn(patch, frameRefs) {
|
|
9148
|
+
const operations = patch.structuralOperations ?? [];
|
|
9149
|
+
const symbolic = contextualCreations(operations).flatMap((creation) => creation ? [creation] : []);
|
|
9150
|
+
const durable = frameRefs ? contextualCreations(operations, frameRefs).flatMap((creation) => creation ? [creation] : []) : [];
|
|
9151
|
+
return symbolic.concat(durable.filter((creation) => !symbolic.some((entry) => entry.op === creation.op && entry.target === creation.target)));
|
|
9152
|
+
}
|
|
9153
|
+
function dropRepeatedCreations(patch, already) {
|
|
9154
|
+
const operations = patch.structuralOperations;
|
|
9155
|
+
if (!operations || operations.length === 0 || already.length === 0) return { patch, dropped: [] };
|
|
9156
|
+
const seen = new Set(already.map((creation) => `${creation.op} ${creation.target}`));
|
|
9157
|
+
const dropped = [];
|
|
9158
|
+
const creations = contextualCreations(operations);
|
|
9159
|
+
const unavailableRefs = /* @__PURE__ */ new Set();
|
|
9160
|
+
const kept = operations.filter((operation, index) => {
|
|
9161
|
+
const creation = creations[index];
|
|
9162
|
+
const dependent = structuralOperationTargets(operation).frameIds.some((id) => unavailableRefs.has(id));
|
|
9163
|
+
if (!dependent && (!creation || !seen.has(`${creation.op} ${creation.target}`))) return true;
|
|
9164
|
+
if (operation.op === "frame.add" && operation.frameRef) unavailableRefs.add(operation.frameRef);
|
|
9165
|
+
if (creation) dropped.push(creation);
|
|
9166
|
+
return false;
|
|
9167
|
+
});
|
|
9168
|
+
if (dropped.length === 0) return { patch, dropped };
|
|
9169
|
+
const { structuralOperations: _dropped, ...rest } = patch;
|
|
9170
|
+
void _dropped;
|
|
9171
|
+
return { patch: kept.length > 0 ? { ...rest, structuralOperations: kept } : rest, dropped };
|
|
9172
|
+
}
|
|
9173
|
+
var CREATING_OPS;
|
|
9174
|
+
var init_agentTurnRepetition = __esm({
|
|
9175
|
+
"../mockup-engine/appstore/agentTurnRepetition.ts"() {
|
|
9176
|
+
"use strict";
|
|
9177
|
+
init_refineIntent();
|
|
9178
|
+
CREATING_OPS = /* @__PURE__ */ new Set([
|
|
9179
|
+
"frame.add",
|
|
9180
|
+
"frame.split",
|
|
9181
|
+
"caption.add",
|
|
9182
|
+
"device.add"
|
|
9183
|
+
]);
|
|
9184
|
+
}
|
|
9185
|
+
});
|
|
9186
|
+
|
|
8967
9187
|
// ../mockup-engine/appstore/agentTurnCoordinator.ts
|
|
8968
9188
|
function phaseFor(cycle) {
|
|
8969
9189
|
return cycle === 1 ? "applying" : cycle === 2 ? "inspecting" : "adjusting";
|
|
@@ -9008,6 +9228,7 @@ async function runAgentTurn(input, ports) {
|
|
|
9008
9228
|
if (!turnId) throw new Error("Agent turn id must not be empty");
|
|
9009
9229
|
const emit = (event) => ports.emit({ ...event, turnId });
|
|
9010
9230
|
const now = input.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
|
|
9231
|
+
const layoutRepairable = canRepairLayoutForFocus(input.focus, instruction);
|
|
9011
9232
|
const loaded = await ports.loadProject();
|
|
9012
9233
|
const before = loaded.state;
|
|
9013
9234
|
let working = before;
|
|
@@ -9018,9 +9239,13 @@ async function runAgentTurn(input, ports) {
|
|
|
9018
9239
|
let best = null;
|
|
9019
9240
|
let selected = null;
|
|
9020
9241
|
let workingAssetBindings = [];
|
|
9242
|
+
const unmetActions = /* @__PURE__ */ new Set();
|
|
9243
|
+
let demandClassified = false;
|
|
9021
9244
|
let interpretation = "";
|
|
9022
9245
|
let inspection = "";
|
|
9023
9246
|
let remainingMismatch = null;
|
|
9247
|
+
const appliedCreations = [];
|
|
9248
|
+
const touchedCapabilities = /* @__PURE__ */ new Set();
|
|
9024
9249
|
let terminalOutcome = null;
|
|
9025
9250
|
let invalid2 = false;
|
|
9026
9251
|
let cancelled = false;
|
|
@@ -9049,7 +9274,14 @@ async function runAgentTurn(input, ports) {
|
|
|
9049
9274
|
focus: input.focus,
|
|
9050
9275
|
state: working,
|
|
9051
9276
|
rendered,
|
|
9052
|
-
...cycle > 1 ? {
|
|
9277
|
+
...cycle > 1 ? {
|
|
9278
|
+
previous: {
|
|
9279
|
+
actualDiff: selected?.changed ?? [],
|
|
9280
|
+
inspection,
|
|
9281
|
+
cycle: cycle - 1,
|
|
9282
|
+
appliedOperations: [...appliedCreations]
|
|
9283
|
+
}
|
|
9284
|
+
} : {}
|
|
9053
9285
|
});
|
|
9054
9286
|
} catch {
|
|
9055
9287
|
terminalOutcome = failureOutcome(
|
|
@@ -9058,6 +9290,10 @@ async function runAgentTurn(input, ports) {
|
|
|
9058
9290
|
);
|
|
9059
9291
|
break;
|
|
9060
9292
|
}
|
|
9293
|
+
if (authorization.demand?.classification === "classified") {
|
|
9294
|
+
demandClassified = true;
|
|
9295
|
+
for (const actionId of authorization.demand.actionIds) unmetActions.add(actionId);
|
|
9296
|
+
}
|
|
9061
9297
|
interpretation ||= authorization.interpretation?.trim() || instruction;
|
|
9062
9298
|
inspection = authorization.inspection?.trim() || "Inspected the current composed result.";
|
|
9063
9299
|
const pass = {
|
|
@@ -9085,7 +9321,12 @@ async function runAgentTurn(input, ports) {
|
|
|
9085
9321
|
}
|
|
9086
9322
|
remainingMismatch = authorization.remainingMismatch?.trim() || authorization.followUp?.trim() || null;
|
|
9087
9323
|
for (const change of authorization.broaderChanges ?? []) broaderChanges.add(change);
|
|
9324
|
+
if (authorization.patch && cycle > 1) {
|
|
9325
|
+
const guarded = dropRepeatedCreations(authorization.patch, appliedCreations);
|
|
9326
|
+
if (guarded.dropped.length > 0) authorization = { ...authorization, patch: guarded.patch };
|
|
9327
|
+
}
|
|
9088
9328
|
if (authorization.patch) {
|
|
9329
|
+
for (const id of capabilitiesForPatch(authorization.patch)) touchedCapabilities.add(id);
|
|
9089
9330
|
const application = applyProjectRefinementWithAssets(
|
|
9090
9331
|
working,
|
|
9091
9332
|
authorization.patch,
|
|
@@ -9097,6 +9338,7 @@ async function runAgentTurn(input, ports) {
|
|
|
9097
9338
|
break;
|
|
9098
9339
|
}
|
|
9099
9340
|
working = application.state;
|
|
9341
|
+
appliedCreations.push(...creationsIn(authorization.patch, application.frameRefs));
|
|
9100
9342
|
workingAssetBindings = [...workingAssetBindings, ...application.assetBindings];
|
|
9101
9343
|
checkpointId += 1;
|
|
9102
9344
|
const checkpoint = {
|
|
@@ -9123,12 +9365,14 @@ async function runAgentTurn(input, ports) {
|
|
|
9123
9365
|
});
|
|
9124
9366
|
}
|
|
9125
9367
|
const requiresRenderedInspection = cycle === 1 && authorization.patch != null;
|
|
9126
|
-
|
|
9368
|
+
const unresolvedLayout = layoutRepairable && authorization.complete === true && !requiresRenderedInspection && authorization.patch == null ? ports.unresolvedLayout?.(rendered)?.trim() || null : null;
|
|
9369
|
+
if (authorization.complete === true && !requiresRenderedInspection && !(unresolvedLayout && cycle < AGENT_TURN_PASS_CAP)) {
|
|
9127
9370
|
if (selected?.changed.length) best = selected;
|
|
9128
|
-
remainingMismatch =
|
|
9371
|
+
remainingMismatch = unresolvedLayout;
|
|
9129
9372
|
break;
|
|
9130
9373
|
}
|
|
9131
|
-
if (
|
|
9374
|
+
if (unresolvedLayout) remainingMismatch = unresolvedLayout;
|
|
9375
|
+
else if (authorization.followUp && !authorization.patch) break;
|
|
9132
9376
|
if (cycle < AGENT_TURN_PASS_CAP) {
|
|
9133
9377
|
try {
|
|
9134
9378
|
rendered = await ports.renderComposed(working, cycle);
|
|
@@ -9145,11 +9389,14 @@ async function runAgentTurn(input, ports) {
|
|
|
9145
9389
|
selected = best;
|
|
9146
9390
|
const selectedState = selected?.state ?? before;
|
|
9147
9391
|
await emit({ type: "draft_selected", checkpointId: selected?.id ?? 0, state: selectedState });
|
|
9148
|
-
let outcome =
|
|
9149
|
-
|
|
9150
|
-
|
|
9151
|
-
|
|
9152
|
-
|
|
9392
|
+
let outcome = withTouchedCapabilities(
|
|
9393
|
+
terminalOutcome ?? applicationOutcome({
|
|
9394
|
+
changed: selected?.changed ?? [],
|
|
9395
|
+
invalid: invalid2,
|
|
9396
|
+
gaps: selected?.gaps ?? []
|
|
9397
|
+
}),
|
|
9398
|
+
Array.from(touchedCapabilities)
|
|
9399
|
+
);
|
|
9153
9400
|
let committed = false;
|
|
9154
9401
|
let commitData;
|
|
9155
9402
|
if (outcome.status === "applied" || outcome.status === "applied_with_remaining") {
|
|
@@ -9166,7 +9413,10 @@ async function runAgentTurn(input, ports) {
|
|
|
9166
9413
|
commitData = commit.data;
|
|
9167
9414
|
await emit({ type: "commit_succeeded", data: commit.data, outcome });
|
|
9168
9415
|
} else {
|
|
9169
|
-
outcome =
|
|
9416
|
+
outcome = withTouchedCapabilities(
|
|
9417
|
+
commit.reason === "stale_version" ? applicationOutcome({ changed: [], conflicted: true }) : failureOutcome("service_unavailable", "The Agent could not save this change. Nothing changed."),
|
|
9418
|
+
Array.from(touchedCapabilities)
|
|
9419
|
+
);
|
|
9170
9420
|
await emit({ type: "draft_rolled_back", outcome });
|
|
9171
9421
|
}
|
|
9172
9422
|
} else {
|
|
@@ -9200,7 +9450,8 @@ async function runAgentTurn(input, ports) {
|
|
|
9200
9450
|
state: committed ? selectedState : before,
|
|
9201
9451
|
expectedVersion: loaded.expectedVersion,
|
|
9202
9452
|
committed,
|
|
9203
|
-
...commitData === void 0 ? {} : { commitData }
|
|
9453
|
+
...commitData === void 0 ? {} : { commitData },
|
|
9454
|
+
demand: demandClassified ? classifiedDemand(unmetActions) : NOT_MEASURED_DEMAND
|
|
9204
9455
|
};
|
|
9205
9456
|
assertOutcome(outcome);
|
|
9206
9457
|
await emit({ type: "turn_completed", result });
|
|
@@ -9212,10 +9463,13 @@ var init_agentTurnCoordinator = __esm({
|
|
|
9212
9463
|
"../mockup-engine/appstore/agentTurnCoordinator.ts"() {
|
|
9213
9464
|
"use strict";
|
|
9214
9465
|
init_agentOutcome();
|
|
9466
|
+
init_refineIntent();
|
|
9215
9467
|
init_refinement();
|
|
9468
|
+
init_agentUnmetActions();
|
|
9216
9469
|
init_recordTransforms();
|
|
9217
9470
|
init_appStoreLocales();
|
|
9218
9471
|
init_agentAssetCustody();
|
|
9472
|
+
init_agentTurnRepetition();
|
|
9219
9473
|
AGENT_TURN_PASS_CAP = 3;
|
|
9220
9474
|
EMPTY_USAGE = {
|
|
9221
9475
|
inputTokens: 0,
|
|
@@ -9263,7 +9517,9 @@ var init_agentTurnConformance = __esm({
|
|
|
9263
9517
|
panelId: "p1",
|
|
9264
9518
|
frameNodeId: "frame-1",
|
|
9265
9519
|
frameName: "home.png",
|
|
9266
|
-
|
|
9520
|
+
// Real pixels, because a surface derives its vision list from THIS state: a shot with no
|
|
9521
|
+
// bytes is a blank frame, which every door drops from the turn (#829).
|
|
9522
|
+
bytes: new Uint8Array([1, 2, 3]),
|
|
9267
9523
|
look: { ...DEFAULT_LOOK },
|
|
9268
9524
|
thumb: null,
|
|
9269
9525
|
thumbStale: false
|
|
@@ -9331,6 +9587,8 @@ var init_agentTurnConformance = __esm({
|
|
|
9331
9587
|
outcome: {
|
|
9332
9588
|
status: "applied",
|
|
9333
9589
|
headline: "Restyled 1 device",
|
|
9590
|
+
// #840 — every capability the drafts touched, derived from the patch, travels on the outcome.
|
|
9591
|
+
capabilityIds: ["device.look"],
|
|
9334
9592
|
changed: ["Restyled 1 device"]
|
|
9335
9593
|
},
|
|
9336
9594
|
stateDiff: {
|
|
@@ -9399,6 +9657,7 @@ var init_agentTurnConformance = __esm({
|
|
|
9399
9657
|
outcome: {
|
|
9400
9658
|
status: "applied",
|
|
9401
9659
|
headline: "Replaced the screenshot on 1 device",
|
|
9660
|
+
capabilityIds: ["device.replace-pixels"],
|
|
9402
9661
|
changed: ["Replaced the screenshot on 1 device"]
|
|
9403
9662
|
},
|
|
9404
9663
|
stateDiff: {
|
|
@@ -9461,6 +9720,7 @@ var init_appstore = __esm({
|
|
|
9461
9720
|
init_agentAssetCustody();
|
|
9462
9721
|
init_agentCapabilities();
|
|
9463
9722
|
init_agentOutcome();
|
|
9723
|
+
init_agentUnmetActions();
|
|
9464
9724
|
init_agentTurnCoordinator();
|
|
9465
9725
|
init_agentTurnConformance();
|
|
9466
9726
|
init_refinement();
|
|
@@ -11136,6 +11396,33 @@ var init_production = __esm({
|
|
|
11136
11396
|
}
|
|
11137
11397
|
});
|
|
11138
11398
|
|
|
11399
|
+
// ../product/accountRights.ts
|
|
11400
|
+
var ACCOUNT_TRAFFIC_CLASSES, RECORDED_TRAFFIC_CLASSES;
|
|
11401
|
+
var init_accountRights = __esm({
|
|
11402
|
+
"../product/accountRights.ts"() {
|
|
11403
|
+
"use strict";
|
|
11404
|
+
ACCOUNT_TRAFFIC_CLASSES = ["customer", "owner", "benchmark"];
|
|
11405
|
+
RECORDED_TRAFFIC_CLASSES = [...ACCOUNT_TRAFFIC_CLASSES, "unclassified"];
|
|
11406
|
+
}
|
|
11407
|
+
});
|
|
11408
|
+
|
|
11409
|
+
// ../api/_lib/authorization/accountAccess.ts
|
|
11410
|
+
var init_accountAccess = __esm({
|
|
11411
|
+
"../api/_lib/authorization/accountAccess.ts"() {
|
|
11412
|
+
"use strict";
|
|
11413
|
+
init_accountRights();
|
|
11414
|
+
init_supabaseRest();
|
|
11415
|
+
}
|
|
11416
|
+
});
|
|
11417
|
+
|
|
11418
|
+
// ../api/_lib/authorization/operatorAudit.ts
|
|
11419
|
+
var init_operatorAudit = __esm({
|
|
11420
|
+
"../api/_lib/authorization/operatorAudit.ts"() {
|
|
11421
|
+
"use strict";
|
|
11422
|
+
init_supabaseRest();
|
|
11423
|
+
}
|
|
11424
|
+
});
|
|
11425
|
+
|
|
11139
11426
|
// ../api/_lib/log.ts
|
|
11140
11427
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
11141
11428
|
function currentRequestId() {
|
|
@@ -11168,6 +11455,7 @@ var JWKS_TTL_MS;
|
|
|
11168
11455
|
var init_supabaseAuth = __esm({
|
|
11169
11456
|
"../api/_lib/supabaseAuth.ts"() {
|
|
11170
11457
|
"use strict";
|
|
11458
|
+
init_accountAccess();
|
|
11171
11459
|
JWKS_TTL_MS = 10 * 60 * 1e3;
|
|
11172
11460
|
}
|
|
11173
11461
|
});
|
|
@@ -11214,6 +11502,8 @@ var init_polarWebhook = __esm({
|
|
|
11214
11502
|
var init_billingReconcile = __esm({
|
|
11215
11503
|
"../api/_lib/billingReconcile.ts"() {
|
|
11216
11504
|
"use strict";
|
|
11505
|
+
init_accountAccess();
|
|
11506
|
+
init_operatorAudit();
|
|
11217
11507
|
init_log();
|
|
11218
11508
|
init_supabaseAuth();
|
|
11219
11509
|
init_entitlement();
|
|
@@ -11224,10 +11514,62 @@ var init_billingReconcile = __esm({
|
|
|
11224
11514
|
}
|
|
11225
11515
|
});
|
|
11226
11516
|
|
|
11517
|
+
// ../api/_lib/providerUsage.ts
|
|
11518
|
+
var init_providerUsage = __esm({
|
|
11519
|
+
"../api/_lib/providerUsage.ts"() {
|
|
11520
|
+
"use strict";
|
|
11521
|
+
}
|
|
11522
|
+
});
|
|
11523
|
+
|
|
11524
|
+
// ../api/_lib/providerCost.ts
|
|
11525
|
+
var init_providerCost = __esm({
|
|
11526
|
+
"../api/_lib/providerCost.ts"() {
|
|
11527
|
+
"use strict";
|
|
11528
|
+
}
|
|
11529
|
+
});
|
|
11530
|
+
|
|
11531
|
+
// ../api/_lib/providerSpendStore.ts
|
|
11532
|
+
import { z as z8 } from "zod";
|
|
11533
|
+
var nullableCount, decimalMoney, evidenceSchema;
|
|
11534
|
+
var init_providerSpendStore = __esm({
|
|
11535
|
+
"../api/_lib/providerSpendStore.ts"() {
|
|
11536
|
+
"use strict";
|
|
11537
|
+
init_providerCost();
|
|
11538
|
+
init_providerUsage();
|
|
11539
|
+
init_supabaseRest();
|
|
11540
|
+
nullableCount = z8.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER).nullable();
|
|
11541
|
+
decimalMoney = z8.string().regex(/^\d{1,19}$/).refine((n) => BigInt(n) <= 9223372036854775807n);
|
|
11542
|
+
evidenceSchema = z8.object({
|
|
11543
|
+
state: z8.enum(["estimated", "partial", "unknown", "not_incurred"]),
|
|
11544
|
+
amountNanoUsd: decimalMoney.nullable(),
|
|
11545
|
+
missing: z8.array(z8.enum(["rate", "usage", "input", "input_breakdown", "inconsistent_input", "cache_read", "cache_write", "cache_write_ttl", "output", "multiple_provider_attempts", "provider_attempts_unknown", "amount_overflow"])),
|
|
11546
|
+
usage: z8.object({ inputTokens: nullableCount, cacheReadTokens: nullableCount, cacheWriteTokens: nullableCount, outputTokens: nullableCount, cacheWriteTtl: z8.enum(["5m", "1h"]).nullable() }).strict().nullable(),
|
|
11547
|
+
rate: z8.object({
|
|
11548
|
+
version: z8.string().regex(/^[a-zA-Z0-9._-]{1,100}$/),
|
|
11549
|
+
effectiveAt: z8.string().datetime(),
|
|
11550
|
+
currency: z8.literal("USD"),
|
|
11551
|
+
model: z8.literal("anthropic/claude-sonnet-4.6"),
|
|
11552
|
+
basis: z8.literal("gateway-list-standard"),
|
|
11553
|
+
region: z8.enum(["global", "us", "eu"]),
|
|
11554
|
+
nanoUsdPerMillion: z8.object({ input: decimalMoney, output: decimalMoney, cacheRead: decimalMoney, cacheWrite5m: decimalMoney, cacheWrite1h: decimalMoney }).strict(),
|
|
11555
|
+
sources: z8.array(z8.enum(["https://platform.claude.com/docs/en/about-claude/pricing", "https://ai-gateway.vercel.sh/v1/models"]))
|
|
11556
|
+
}).strict().nullable(),
|
|
11557
|
+
gateway: z8.object({ generationId: z8.string().regex(/^gen_[a-zA-Z0-9_-]{1,100}$/).nullable(), costUsd: z8.string().regex(/^\d{1,12}(\.\d{1,18})?$/).nullable(), marketCostUsd: z8.string().regex(/^\d{1,12}(\.\d{1,18})?$/).nullable(), attempts: nullableCount, route: z8.string().regex(/^[a-zA-Z0-9_-]{1,40}$/).nullable() }).strict().nullable(),
|
|
11558
|
+
noAttempt: z8.literal(true).optional()
|
|
11559
|
+
}).strict().superRefine((e, context) => {
|
|
11560
|
+
if ((e.state === "estimated" || e.state === "partial") && e.amountNanoUsd === null || e.state === "unknown" && e.amountNanoUsd !== null || e.state === "not_incurred" && (e.amountNanoUsd !== "0" || e.noAttempt !== true)) {
|
|
11561
|
+
context.addIssue({ code: "custom", message: "inconsistent spend state" });
|
|
11562
|
+
}
|
|
11563
|
+
});
|
|
11564
|
+
}
|
|
11565
|
+
});
|
|
11566
|
+
|
|
11227
11567
|
// ../api/_lib/aiGenerationStore.ts
|
|
11228
11568
|
var init_aiGenerationStore = __esm({
|
|
11229
11569
|
"../api/_lib/aiGenerationStore.ts"() {
|
|
11230
11570
|
"use strict";
|
|
11571
|
+
init_providerUsage();
|
|
11572
|
+
init_providerSpendStore();
|
|
11231
11573
|
init_supabaseRest();
|
|
11232
11574
|
}
|
|
11233
11575
|
});
|
|
@@ -11716,7 +12058,7 @@ var init_package = __esm({
|
|
|
11716
12058
|
"package.json"() {
|
|
11717
12059
|
package_default = {
|
|
11718
12060
|
name: "shotops-mcp",
|
|
11719
|
-
version: "0.9.
|
|
12061
|
+
version: "0.9.6",
|
|
11720
12062
|
private: false,
|
|
11721
12063
|
type: "module",
|
|
11722
12064
|
description: "The bundle-emitting MCP server over the @engine/@sync spine. Exposes ShotOps tools to ChatGPT, Claude Code, Cursor, and CI over Streamable HTTP with OAuth or personal API tokens. Hosted and MCP tool paths never accept, store, or forward a store-signing credential; the explicit local release CLI validates the user's existing key directly with Apple and records only its path. Renders via headless Playwright Chromium, the engine's native non-browser habitat (same path as mockup-mcp). Also ships as a free LOCAL stdio server (`npx shotops-mcp`) \u2014 same render, on your own machine, no account needed.",
|
|
@@ -13926,14 +14268,21 @@ function connectHostedBridge(token2) {
|
|
|
13926
14268
|
async refineProject(input) {
|
|
13927
14269
|
return callOp(token2, "refine_project", input);
|
|
13928
14270
|
},
|
|
13929
|
-
async refinePass(projectId, pass, turnKey) {
|
|
13930
|
-
const
|
|
14271
|
+
async refinePass(projectId, pass, turnKey, benchmark, attachments) {
|
|
14272
|
+
const args = {
|
|
14273
|
+
project: projectId,
|
|
14274
|
+
turnKey,
|
|
14275
|
+
pass,
|
|
14276
|
+
...benchmark === void 0 ? {} : { benchmark },
|
|
14277
|
+
...attachments === void 0 ? {} : { attachments }
|
|
14278
|
+
};
|
|
14279
|
+
const body = JSON.stringify({ op: "refine_pass", ...args });
|
|
13931
14280
|
if (body.length > MAX_PASS_BODY_BYTES) {
|
|
13932
14281
|
throw new Error(
|
|
13933
14282
|
"This project has too many screenshots for one Agent pass. Refine a smaller selection, or run the Agent from ShotOps in the browser."
|
|
13934
14283
|
);
|
|
13935
14284
|
}
|
|
13936
|
-
return callOp(token2, "refine_pass",
|
|
14285
|
+
return callOp(token2, "refine_pass", args);
|
|
13937
14286
|
},
|
|
13938
14287
|
async settleRefineTurn(projectId, settlement) {
|
|
13939
14288
|
const res = await callOp(token2, "refine_finalize", {
|
|
@@ -14004,6 +14353,23 @@ var init_hostedBridge = __esm({
|
|
|
14004
14353
|
}
|
|
14005
14354
|
});
|
|
14006
14355
|
|
|
14356
|
+
// ../mockup-engine/layoutFindings.ts
|
|
14357
|
+
function describeUnresolvedLayout(findings) {
|
|
14358
|
+
if (!findings || findings.length === 0) return null;
|
|
14359
|
+
const frames = Array.from(new Set(findings.flatMap((finding) => finding.frames))).sort((left, right) => left - right).map((index) => `Frame ${index + 1}`);
|
|
14360
|
+
const where = frames.length === 0 ? "" : frames.length === 1 ? ` in ${frames[0]}` : ` in ${frames.slice(0, -1).join(", ")} and ${frames[frames.length - 1]}`;
|
|
14361
|
+
if (findings.length === 1) {
|
|
14362
|
+
const what = findings[0].kind === "caption-device" ? "A caption still overlaps a device" : findings[0].kind === "caption-caption" ? "Two captions still overlap" : "Two devices still collide";
|
|
14363
|
+
return `${what}${where}.`;
|
|
14364
|
+
}
|
|
14365
|
+
return `${findings.length} layout overlaps still remain${where}.`;
|
|
14366
|
+
}
|
|
14367
|
+
var init_layoutFindings = __esm({
|
|
14368
|
+
"../mockup-engine/layoutFindings.ts"() {
|
|
14369
|
+
"use strict";
|
|
14370
|
+
}
|
|
14371
|
+
});
|
|
14372
|
+
|
|
14007
14373
|
// ../api/_lib/invalidRequest.ts
|
|
14008
14374
|
function safeFailureDiagnostic(error) {
|
|
14009
14375
|
const errorTypes = [];
|
|
@@ -14038,57 +14404,57 @@ var init_invalidRequest = __esm({
|
|
|
14038
14404
|
});
|
|
14039
14405
|
|
|
14040
14406
|
// ../api/_lib/aiShotProjection.ts
|
|
14041
|
-
import { z as
|
|
14407
|
+
import { z as z9 } from "zod";
|
|
14042
14408
|
var deviceHexSchema, API_AI_SHOT_PROJECTION, API_AI_SHOT_INCLUDED_ENTRIES, API_AI_SHOT_PATCH_SHAPE, apiAiShotPatchSchema, API_AI_SHOT_PROMPT_INVENTORY;
|
|
14043
14409
|
var init_aiShotProjection = __esm({
|
|
14044
14410
|
"../api/_lib/aiShotProjection.ts"() {
|
|
14045
14411
|
"use strict";
|
|
14046
14412
|
init_refineIntent();
|
|
14047
|
-
deviceHexSchema =
|
|
14413
|
+
deviceHexSchema = z9.string().trim().regex(/^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/);
|
|
14048
14414
|
API_AI_SHOT_PROJECTION = {
|
|
14049
14415
|
orbit: {
|
|
14050
14416
|
exposure: "included",
|
|
14051
|
-
schema:
|
|
14417
|
+
schema: z9.number().min(AI_SHOT_RANGES.orbit.min).max(AI_SHOT_RANGES.orbit.max).optional(),
|
|
14052
14418
|
prompt: `orbit: camera azimuth in degrees, ${AI_SHOT_RANGES.orbit.min} to ${AI_SHOT_RANGES.orbit.max}. 0 is straight on, negative swings the device left, positive right. Subtle is \xB15\u201320.`
|
|
14053
14419
|
},
|
|
14054
14420
|
roll: {
|
|
14055
14421
|
exposure: "included",
|
|
14056
|
-
schema:
|
|
14422
|
+
schema: z9.number().min(AI_SHOT_RANGES.roll.min).max(AI_SHOT_RANGES.roll.max).optional(),
|
|
14057
14423
|
prompt: `roll: clock-hand tilt, ${AI_SHOT_RANGES.roll.min} to ${AI_SHOT_RANGES.roll.max} degrees. 0 is upright. Subtle is \xB12\u20138.`
|
|
14058
14424
|
},
|
|
14059
14425
|
angle: {
|
|
14060
14426
|
exposure: "included",
|
|
14061
|
-
schema:
|
|
14427
|
+
schema: z9.enum(["front", "left", "right"]).optional(),
|
|
14062
14428
|
prompt: "angle: front | left | right \u2014 a camera PRESET. Setting it discards any orbit value on that frame, so send orbit OR angle, never both."
|
|
14063
14429
|
},
|
|
14064
14430
|
phoneHeight: {
|
|
14065
14431
|
exposure: "included",
|
|
14066
|
-
schema:
|
|
14432
|
+
schema: z9.number().min(AI_SHOT_RANGES.phoneHeight.min).max(AI_SHOT_RANGES.phoneHeight.max).optional(),
|
|
14067
14433
|
prompt: `phoneHeight: ${AI_SHOT_RANGES.phoneHeight.min}\u2013${AI_SHOT_RANGES.phoneHeight.max} (% of panel height; over 100 bleeds off an edge)`
|
|
14068
14434
|
},
|
|
14069
14435
|
hOffset: {
|
|
14070
14436
|
exposure: "included",
|
|
14071
|
-
schema:
|
|
14437
|
+
schema: z9.number().min(AI_SHOT_RANGES.hOffset.min).max(AI_SHOT_RANGES.hOffset.max).optional(),
|
|
14072
14438
|
prompt: `hOffset: ${AI_SHOT_RANGES.hOffset.min}\u2013${AI_SHOT_RANGES.hOffset.max} horizontal position, 0 is centred`
|
|
14073
14439
|
},
|
|
14074
14440
|
vOffset: {
|
|
14075
14441
|
exposure: "included",
|
|
14076
|
-
schema:
|
|
14442
|
+
schema: z9.number().min(AI_SHOT_RANGES.vOffset.min).max(AI_SHOT_RANGES.vOffset.max).optional(),
|
|
14077
14443
|
prompt: `vOffset: ${AI_SHOT_RANGES.vOffset.min}\u2013${AI_SHOT_RANGES.vOffset.max} vertical position, 0 is centred`
|
|
14078
14444
|
},
|
|
14079
14445
|
material: {
|
|
14080
14446
|
exposure: "included",
|
|
14081
|
-
schema:
|
|
14447
|
+
schema: z9.enum(["real", "clay"]).optional(),
|
|
14082
14448
|
prompt: `material: real | clay. colorway (real only): ${AI_COLORWAY_IDS.join(" | ")}. clayTone (clay only): ${AI_CLAY_TONES.join(" | ")}.`
|
|
14083
14449
|
},
|
|
14084
14450
|
colorway: {
|
|
14085
14451
|
exposure: "included",
|
|
14086
|
-
schema:
|
|
14452
|
+
schema: z9.enum(AI_COLORWAY_IDS).optional(),
|
|
14087
14453
|
prompt: `material: real | clay. colorway (real only): ${AI_COLORWAY_IDS.join(" | ")}. clayTone (clay only): ${AI_CLAY_TONES.join(" | ")}.`
|
|
14088
14454
|
},
|
|
14089
14455
|
clayTone: {
|
|
14090
14456
|
exposure: "included",
|
|
14091
|
-
schema:
|
|
14457
|
+
schema: z9.enum(AI_CLAY_TONES).optional(),
|
|
14092
14458
|
prompt: `material: real | clay. colorway (real only): ${AI_COLORWAY_IDS.join(" | ")}. clayTone (clay only): ${AI_CLAY_TONES.join(" | ")}.`
|
|
14093
14459
|
},
|
|
14094
14460
|
customColor: {
|
|
@@ -14103,37 +14469,37 @@ var init_aiShotProjection = __esm({
|
|
|
14103
14469
|
},
|
|
14104
14470
|
finish: {
|
|
14105
14471
|
exposure: "included",
|
|
14106
|
-
schema:
|
|
14472
|
+
schema: z9.number().min(AI_SHOT_RANGES.finish.min).max(AI_SHOT_RANGES.finish.max).optional(),
|
|
14107
14473
|
prompt: `finish: ${AI_SHOT_RANGES.finish.min}\u2013${AI_SHOT_RANGES.finish.max} (0 matte, 1 glossy). clearcoat: ${AI_SHOT_RANGES.clearcoat.min}\u2013${AI_SHOT_RANGES.clearcoat.max} lacquer sheen on top.`
|
|
14108
14474
|
},
|
|
14109
14475
|
clearcoat: {
|
|
14110
14476
|
exposure: "included",
|
|
14111
|
-
schema:
|
|
14477
|
+
schema: z9.number().min(AI_SHOT_RANGES.clearcoat.min).max(AI_SHOT_RANGES.clearcoat.max).optional(),
|
|
14112
14478
|
prompt: `finish: ${AI_SHOT_RANGES.finish.min}\u2013${AI_SHOT_RANGES.finish.max} (0 matte, 1 glossy). clearcoat: ${AI_SHOT_RANGES.clearcoat.min}\u2013${AI_SHOT_RANGES.clearcoat.max} lacquer sheen on top.`
|
|
14113
14479
|
},
|
|
14114
14480
|
flatScreen: {
|
|
14115
14481
|
exposure: "included",
|
|
14116
|
-
schema:
|
|
14482
|
+
schema: z9.boolean().optional(),
|
|
14117
14483
|
prompt: "flatScreen, glare, lighting, reflections, clipToFrame: true | false."
|
|
14118
14484
|
},
|
|
14119
14485
|
glare: {
|
|
14120
14486
|
exposure: "included",
|
|
14121
|
-
schema:
|
|
14487
|
+
schema: z9.boolean().optional(),
|
|
14122
14488
|
prompt: "flatScreen, glare, lighting, reflections, clipToFrame: true | false."
|
|
14123
14489
|
},
|
|
14124
14490
|
lighting: {
|
|
14125
14491
|
exposure: "included",
|
|
14126
|
-
schema:
|
|
14492
|
+
schema: z9.boolean().optional(),
|
|
14127
14493
|
prompt: "flatScreen, glare, lighting, reflections, clipToFrame: true | false."
|
|
14128
14494
|
},
|
|
14129
14495
|
reflections: {
|
|
14130
14496
|
exposure: "included",
|
|
14131
|
-
schema:
|
|
14497
|
+
schema: z9.boolean().optional(),
|
|
14132
14498
|
prompt: "flatScreen, glare, lighting, reflections, clipToFrame: true | false."
|
|
14133
14499
|
},
|
|
14134
14500
|
clipToFrame: {
|
|
14135
14501
|
exposure: "included",
|
|
14136
|
-
schema:
|
|
14502
|
+
schema: z9.boolean().optional(),
|
|
14137
14503
|
prompt: "flatScreen, glare, lighting, reflections, clipToFrame: true | false."
|
|
14138
14504
|
}
|
|
14139
14505
|
};
|
|
@@ -14141,7 +14507,7 @@ var init_aiShotProjection = __esm({
|
|
|
14141
14507
|
API_AI_SHOT_PATCH_SHAPE = Object.fromEntries(
|
|
14142
14508
|
API_AI_SHOT_INCLUDED_ENTRIES.map(([field, projection]) => [field, projection.schema])
|
|
14143
14509
|
);
|
|
14144
|
-
apiAiShotPatchSchema =
|
|
14510
|
+
apiAiShotPatchSchema = z9.object(API_AI_SHOT_PATCH_SHAPE);
|
|
14145
14511
|
API_AI_SHOT_PROMPT_INVENTORY = [
|
|
14146
14512
|
...new Set(API_AI_SHOT_INCLUDED_ENTRIES.map(([, projection]) => projection.prompt))
|
|
14147
14513
|
];
|
|
@@ -14171,8 +14537,8 @@ var init_visionGeneration = __esm({
|
|
|
14171
14537
|
});
|
|
14172
14538
|
|
|
14173
14539
|
// ../api/_lib/refineProjectContracts.ts
|
|
14174
|
-
import { z as
|
|
14175
|
-
var localeIds, MAX_DURABLE_MODEL_PROSE, hexSchema, currentColorSchema, shotPatchSchema, aiNumberSchema, captionStylePatchSchema, MAX_WIRE_GRADIENT_STOPS, gradientStopSchema, backgroundPatchSchema, stripBackgroundPatchSchema, framePatchSchema, currentCaptionStyleSchema, currentGradientStopSchema, currentStops, currentBackgroundSchema, currentStripBackgroundSchema, currentShotSchema, currentFramePatchSchema, localeCodeSchema, focusSchema, currentFrameSchema, captionOperationSchema, frameOperationSchema, frameIdSchema, assetIdSchema, structuralOperationSchema, attachmentSchema, visionScreenshotSchema, requestSchema, legacyFinalizeSchema, durableUsageSchema, durablePassSchema, durableStateDiffSchema, agentOutcomeSchema, durableFinalizeSchema, revertSchema, finalizeSchema, createSessionSchema, historySchema, REFINE_FIELD_LABELS;
|
|
14540
|
+
import { z as z10 } from "zod";
|
|
14541
|
+
var localeIds, MAX_DURABLE_MODEL_PROSE, hexSchema, currentColorSchema, shotPatchSchema, aiNumberSchema, captionStylePatchSchema, MAX_WIRE_GRADIENT_STOPS, gradientStopSchema, backgroundPatchSchema, stripBackgroundPatchSchema, framePatchSchema, currentCaptionStyleSchema, currentGradientStopSchema, currentStops, currentBackgroundSchema, currentStripBackgroundSchema, currentShotSchema, currentFramePatchSchema, localeCodeSchema, focusSchema, currentFrameSchema, captionOperationSchema, frameOperationSchema, frameIdSchema, assetIdSchema, structuralOperationSchema, attachmentSchema, refinementAttachmentsSchema, visionScreenshotSchema, requestSchema, legacyFinalizeSchema, durableUsageSchema, durablePassSchema, durableStateDiffSchema, agentOutcomeSchema, durableFinalizeSchema, revertSchema, finalizeSchema, createSessionSchema, historySchema, REFINE_FIELD_LABELS;
|
|
14176
14542
|
var init_refineProjectContracts = __esm({
|
|
14177
14543
|
"../api/_lib/refineProjectContracts.ts"() {
|
|
14178
14544
|
"use strict";
|
|
@@ -14184,229 +14550,237 @@ var init_refineProjectContracts = __esm({
|
|
|
14184
14550
|
init_aiShotProjection();
|
|
14185
14551
|
localeIds = APP_STORE_LOCALES;
|
|
14186
14552
|
MAX_DURABLE_MODEL_PROSE = 32e3;
|
|
14187
|
-
hexSchema =
|
|
14188
|
-
currentColorSchema =
|
|
14553
|
+
hexSchema = z10.string().trim().regex(/^#?([0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/);
|
|
14554
|
+
currentColorSchema = z10.string().trim().max(64);
|
|
14189
14555
|
shotPatchSchema = apiAiShotPatchSchema;
|
|
14190
|
-
aiNumberSchema =
|
|
14191
|
-
captionStylePatchSchema =
|
|
14192
|
-
fontId:
|
|
14556
|
+
aiNumberSchema = z10.union([z10.number().finite(), z10.object({ scale: z10.number().finite() })]);
|
|
14557
|
+
captionStylePatchSchema = z10.object({
|
|
14558
|
+
fontId: z10.enum(AI_CAPTION_FONT_IDS).optional(),
|
|
14193
14559
|
sizePt: aiNumberSchema.optional(),
|
|
14194
14560
|
color: hexSchema.optional(),
|
|
14195
|
-
align:
|
|
14561
|
+
align: z10.enum(["left", "center", "right"]).optional(),
|
|
14196
14562
|
maxWidth: aiNumberSchema.optional(),
|
|
14197
14563
|
lineHeight: aiNumberSchema.optional(),
|
|
14198
|
-
band:
|
|
14564
|
+
band: z10.enum(["top", "bottom"]).optional(),
|
|
14199
14565
|
bandInset: aiNumberSchema.optional(),
|
|
14200
14566
|
bandCenter: aiNumberSchema.optional(),
|
|
14201
14567
|
reserveLines: aiNumberSchema.optional()
|
|
14202
14568
|
});
|
|
14203
14569
|
MAX_WIRE_GRADIENT_STOPS = 32;
|
|
14204
|
-
gradientStopSchema =
|
|
14205
|
-
backgroundPatchSchema =
|
|
14206
|
-
stops:
|
|
14207
|
-
angle:
|
|
14570
|
+
gradientStopSchema = z10.object({ color: hexSchema, at: z10.number().finite() });
|
|
14571
|
+
backgroundPatchSchema = z10.object({
|
|
14572
|
+
stops: z10.array(gradientStopSchema).max(MAX_WIRE_GRADIENT_STOPS).optional(),
|
|
14573
|
+
angle: z10.number().finite().optional()
|
|
14208
14574
|
});
|
|
14209
14575
|
stripBackgroundPatchSchema = backgroundPatchSchema.extend({
|
|
14210
|
-
shadow:
|
|
14211
|
-
floorReflection:
|
|
14576
|
+
shadow: z10.boolean().optional(),
|
|
14577
|
+
floorReflection: z10.boolean().optional()
|
|
14212
14578
|
});
|
|
14213
|
-
framePatchSchema =
|
|
14579
|
+
framePatchSchema = z10.object({
|
|
14214
14580
|
captionStyle: captionStylePatchSchema.optional(),
|
|
14215
14581
|
background: backgroundPatchSchema.optional()
|
|
14216
14582
|
});
|
|
14217
14583
|
currentCaptionStyleSchema = captionStylePatchSchema.extend({
|
|
14218
14584
|
color: currentColorSchema.optional()
|
|
14219
14585
|
});
|
|
14220
|
-
currentGradientStopSchema =
|
|
14221
|
-
currentStops =
|
|
14586
|
+
currentGradientStopSchema = z10.object({ color: currentColorSchema, at: z10.number().finite() });
|
|
14587
|
+
currentStops = z10.array(currentGradientStopSchema).max(MAX_WIRE_GRADIENT_STOPS).optional();
|
|
14222
14588
|
currentBackgroundSchema = backgroundPatchSchema.extend({ stops: currentStops });
|
|
14223
14589
|
currentStripBackgroundSchema = stripBackgroundPatchSchema.extend({ stops: currentStops });
|
|
14224
14590
|
currentShotSchema = shotPatchSchema.extend({
|
|
14225
14591
|
customColor: currentColorSchema.optional(),
|
|
14226
14592
|
clayCustom: currentColorSchema.optional()
|
|
14227
14593
|
});
|
|
14228
|
-
currentFramePatchSchema =
|
|
14594
|
+
currentFramePatchSchema = z10.object({
|
|
14229
14595
|
captionStyle: currentCaptionStyleSchema.optional(),
|
|
14230
14596
|
background: currentBackgroundSchema.optional()
|
|
14231
14597
|
});
|
|
14232
|
-
localeCodeSchema =
|
|
14233
|
-
focusSchema =
|
|
14234
|
-
|
|
14235
|
-
|
|
14236
|
-
kind:
|
|
14237
|
-
frameId:
|
|
14238
|
-
label:
|
|
14598
|
+
localeCodeSchema = z10.string().trim().regex(/^[A-Za-z]{2,3}(-[A-Za-z0-9]{2,8})*$/);
|
|
14599
|
+
focusSchema = z10.discriminatedUnion("kind", [
|
|
14600
|
+
z10.object({ kind: z10.literal("project"), label: z10.string().trim().min(1).max(180) }),
|
|
14601
|
+
z10.object({
|
|
14602
|
+
kind: z10.literal("frame"),
|
|
14603
|
+
frameId: z10.string().trim().min(1).max(180),
|
|
14604
|
+
label: z10.string().trim().min(1).max(180)
|
|
14239
14605
|
}),
|
|
14240
|
-
|
|
14241
|
-
kind:
|
|
14242
|
-
frameId:
|
|
14243
|
-
deviceId:
|
|
14244
|
-
label:
|
|
14606
|
+
z10.object({
|
|
14607
|
+
kind: z10.literal("device"),
|
|
14608
|
+
frameId: z10.string().trim().min(1).max(180),
|
|
14609
|
+
deviceId: z10.string().trim().min(1).max(180),
|
|
14610
|
+
label: z10.string().trim().min(1).max(180)
|
|
14245
14611
|
}),
|
|
14246
|
-
|
|
14247
|
-
kind:
|
|
14248
|
-
frameId:
|
|
14249
|
-
captionIndex:
|
|
14250
|
-
label:
|
|
14612
|
+
z10.object({
|
|
14613
|
+
kind: z10.literal("caption"),
|
|
14614
|
+
frameId: z10.string().trim().min(1).max(180),
|
|
14615
|
+
captionIndex: z10.number().int().min(0).max(32),
|
|
14616
|
+
label: z10.string().trim().min(1).max(240)
|
|
14251
14617
|
})
|
|
14252
14618
|
]);
|
|
14253
|
-
currentFrameSchema =
|
|
14254
|
-
id:
|
|
14255
|
-
label:
|
|
14256
|
-
sourceName:
|
|
14257
|
-
devices:
|
|
14258
|
-
id:
|
|
14259
|
-
label:
|
|
14619
|
+
currentFrameSchema = z10.object({
|
|
14620
|
+
id: z10.string().trim().min(1).max(180),
|
|
14621
|
+
label: z10.string().trim().min(1).max(180),
|
|
14622
|
+
sourceName: z10.string().trim().min(1).max(180).nullable(),
|
|
14623
|
+
devices: z10.array(z10.object({
|
|
14624
|
+
id: z10.string().trim().min(1).max(180),
|
|
14625
|
+
label: z10.string().trim().min(1).max(180),
|
|
14260
14626
|
look: currentShotSchema
|
|
14261
14627
|
})).max(20),
|
|
14262
|
-
captions:
|
|
14263
|
-
index:
|
|
14264
|
-
label:
|
|
14265
|
-
text:
|
|
14628
|
+
captions: z10.array(z10.object({
|
|
14629
|
+
index: z10.number().int().min(0).max(32),
|
|
14630
|
+
label: z10.string().trim().min(1).max(180),
|
|
14631
|
+
text: z10.string().max(240),
|
|
14266
14632
|
style: currentCaptionStyleSchema
|
|
14267
14633
|
})).max(32),
|
|
14268
|
-
background: currentBackgroundSchema.nullable()
|
|
14634
|
+
background: currentBackgroundSchema.nullable(),
|
|
14635
|
+
// The per-screenshot slot this frame's pixels occupy, or null for a frame with no screenshot yet.
|
|
14636
|
+
// Optional so a client that predates it still parses; the prompt then numbers by position.
|
|
14637
|
+
screenshotIndex: z10.number().int().min(0).max(31).nullable().optional()
|
|
14269
14638
|
});
|
|
14270
|
-
captionOperationSchema =
|
|
14271
|
-
|
|
14272
|
-
operation:
|
|
14273
|
-
frameId:
|
|
14274
|
-
afterIndex:
|
|
14275
|
-
text:
|
|
14639
|
+
captionOperationSchema = z10.discriminatedUnion("operation", [
|
|
14640
|
+
z10.object({
|
|
14641
|
+
operation: z10.literal("add"),
|
|
14642
|
+
frameId: z10.string().trim().min(1).max(180),
|
|
14643
|
+
afterIndex: z10.number().int().min(-1).max(32).optional(),
|
|
14644
|
+
text: z10.string().trim().max(240),
|
|
14276
14645
|
style: captionStylePatchSchema.optional()
|
|
14277
14646
|
}),
|
|
14278
|
-
|
|
14279
|
-
operation:
|
|
14280
|
-
frameId:
|
|
14281
|
-
index:
|
|
14647
|
+
z10.object({
|
|
14648
|
+
operation: z10.literal("remove"),
|
|
14649
|
+
frameId: z10.string().trim().min(1).max(180),
|
|
14650
|
+
index: z10.number().int().min(0).max(32)
|
|
14282
14651
|
}),
|
|
14283
|
-
|
|
14284
|
-
operation:
|
|
14285
|
-
frameId:
|
|
14286
|
-
index:
|
|
14287
|
-
toFrameId:
|
|
14288
|
-
toIndex:
|
|
14652
|
+
z10.object({
|
|
14653
|
+
operation: z10.literal("move"),
|
|
14654
|
+
frameId: z10.string().trim().min(1).max(180),
|
|
14655
|
+
index: z10.number().int().min(0).max(32),
|
|
14656
|
+
toFrameId: z10.string().trim().min(1).max(180),
|
|
14657
|
+
toIndex: z10.number().int().min(0).max(32).optional()
|
|
14289
14658
|
})
|
|
14290
14659
|
]);
|
|
14291
|
-
frameOperationSchema =
|
|
14292
|
-
|
|
14293
|
-
operation:
|
|
14294
|
-
afterFrameId:
|
|
14660
|
+
frameOperationSchema = z10.discriminatedUnion("operation", [
|
|
14661
|
+
z10.object({
|
|
14662
|
+
operation: z10.literal("add"),
|
|
14663
|
+
afterFrameId: z10.string().trim().min(1).max(180).optional()
|
|
14295
14664
|
}),
|
|
14296
|
-
|
|
14297
|
-
operation:
|
|
14298
|
-
frameId:
|
|
14665
|
+
z10.object({
|
|
14666
|
+
operation: z10.literal("remove"),
|
|
14667
|
+
frameId: z10.string().trim().min(1).max(180)
|
|
14299
14668
|
}),
|
|
14300
|
-
|
|
14301
|
-
operation:
|
|
14302
|
-
frameId:
|
|
14303
|
-
afterFrameId:
|
|
14669
|
+
z10.object({
|
|
14670
|
+
operation: z10.literal("move"),
|
|
14671
|
+
frameId: z10.string().trim().min(1).max(180),
|
|
14672
|
+
afterFrameId: z10.string().trim().min(1).max(180).optional()
|
|
14304
14673
|
}),
|
|
14305
|
-
|
|
14306
|
-
operation:
|
|
14307
|
-
frameId:
|
|
14308
|
-
deviceIds:
|
|
14674
|
+
z10.object({
|
|
14675
|
+
operation: z10.literal("split"),
|
|
14676
|
+
frameId: z10.string().trim().min(1).max(180),
|
|
14677
|
+
deviceIds: z10.array(z10.string().trim().min(1).max(180)).min(1).max(20)
|
|
14309
14678
|
})
|
|
14310
14679
|
]);
|
|
14311
|
-
frameIdSchema =
|
|
14312
|
-
assetIdSchema =
|
|
14313
|
-
structuralOperationSchema =
|
|
14314
|
-
|
|
14315
|
-
|
|
14316
|
-
|
|
14317
|
-
|
|
14318
|
-
|
|
14680
|
+
frameIdSchema = z10.string().trim().min(1).max(180);
|
|
14681
|
+
assetIdSchema = z10.string().trim().min(1).max(64).regex(/^[A-Za-z0-9][A-Za-z0-9_-]*$/);
|
|
14682
|
+
structuralOperationSchema = z10.discriminatedUnion("op", [
|
|
14683
|
+
z10.object({
|
|
14684
|
+
op: z10.literal("frame.add"),
|
|
14685
|
+
afterFrameId: frameIdSchema.optional(),
|
|
14686
|
+
frameRef: z10.string().min(1).max(64).regex(/^[A-Za-z][A-Za-z0-9_-]*$/).describe("Patch-local frame alias, unique and different from every existing frame/device id. Later ordered operations may use it as a frame target. Never persisted.").optional()
|
|
14687
|
+
}),
|
|
14688
|
+
z10.object({ op: z10.literal("frame.remove"), frameId: frameIdSchema }),
|
|
14689
|
+
z10.object({ op: z10.literal("frame.move"), frameId: frameIdSchema, afterFrameId: frameIdSchema.optional() }),
|
|
14690
|
+
z10.object({
|
|
14691
|
+
op: z10.literal("frame.split"),
|
|
14319
14692
|
frameId: frameIdSchema,
|
|
14320
|
-
deviceIds:
|
|
14693
|
+
deviceIds: z10.array(frameIdSchema).min(1).max(20)
|
|
14321
14694
|
}),
|
|
14322
|
-
|
|
14323
|
-
|
|
14324
|
-
|
|
14325
|
-
op:
|
|
14695
|
+
z10.object({ op: z10.literal("frame.combine"), frameId: frameIdSchema, fromFrameId: frameIdSchema }),
|
|
14696
|
+
z10.object({ op: z10.literal("frame.template-reset"), frameId: frameIdSchema }),
|
|
14697
|
+
z10.object({
|
|
14698
|
+
op: z10.literal("caption.add"),
|
|
14326
14699
|
frameId: frameIdSchema,
|
|
14327
|
-
afterIndex:
|
|
14328
|
-
text:
|
|
14700
|
+
afterIndex: z10.number().int().min(-1).max(32).optional(),
|
|
14701
|
+
text: z10.string().trim().max(240),
|
|
14329
14702
|
style: captionStylePatchSchema.optional()
|
|
14330
14703
|
}),
|
|
14331
|
-
|
|
14332
|
-
|
|
14333
|
-
op:
|
|
14704
|
+
z10.object({ op: z10.literal("caption.remove"), frameId: frameIdSchema, index: z10.number().int().min(0).max(32) }),
|
|
14705
|
+
z10.object({
|
|
14706
|
+
op: z10.literal("caption.move"),
|
|
14334
14707
|
frameId: frameIdSchema,
|
|
14335
|
-
index:
|
|
14708
|
+
index: z10.number().int().min(0).max(32),
|
|
14336
14709
|
toFrameId: frameIdSchema,
|
|
14337
|
-
toIndex:
|
|
14710
|
+
toIndex: z10.number().int().min(0).max(32).optional()
|
|
14338
14711
|
}),
|
|
14339
|
-
|
|
14340
|
-
op:
|
|
14712
|
+
z10.object({
|
|
14713
|
+
op: z10.literal("device.move"),
|
|
14341
14714
|
deviceId: frameIdSchema,
|
|
14342
14715
|
toFrameId: frameIdSchema,
|
|
14343
|
-
toIndex:
|
|
14716
|
+
toIndex: z10.number().int().min(0).max(20).optional()
|
|
14344
14717
|
}),
|
|
14345
|
-
|
|
14346
|
-
|
|
14718
|
+
z10.object({ op: z10.literal("device.reorder"), deviceId: frameIdSchema, toIndex: z10.number().int().min(0).max(20) }),
|
|
14719
|
+
z10.object({ op: z10.literal("device.remove"), deviceId: frameIdSchema }),
|
|
14347
14720
|
// The two asset operations (#573). `assetId` is an OPAQUE per-turn handle, so the wire bounds its
|
|
14348
14721
|
// shape and nothing more: a path, a URL or an account id is never a legal value here because the
|
|
14349
14722
|
// handle table is the only thing that resolves one, and it holds only handles this turn minted.
|
|
14350
|
-
|
|
14351
|
-
op:
|
|
14723
|
+
z10.object({
|
|
14724
|
+
op: z10.literal("device.add"),
|
|
14352
14725
|
toFrameId: frameIdSchema,
|
|
14353
14726
|
assetId: assetIdSchema,
|
|
14354
|
-
toIndex:
|
|
14727
|
+
toIndex: z10.number().int().min(0).max(20).optional()
|
|
14355
14728
|
}),
|
|
14356
|
-
|
|
14729
|
+
z10.object({ op: z10.literal("device.replace"), deviceId: frameIdSchema, assetId: assetIdSchema })
|
|
14357
14730
|
]);
|
|
14358
|
-
attachmentSchema =
|
|
14359
|
-
ref:
|
|
14360
|
-
label:
|
|
14361
|
-
width:
|
|
14362
|
-
height:
|
|
14731
|
+
attachmentSchema = z10.object({
|
|
14732
|
+
ref: z10.string().trim().min(1).max(512),
|
|
14733
|
+
label: z10.string().trim().min(1).max(180),
|
|
14734
|
+
width: z10.number().int().min(1).max(2e4).optional(),
|
|
14735
|
+
height: z10.number().int().min(1).max(2e4).optional()
|
|
14363
14736
|
});
|
|
14364
|
-
|
|
14365
|
-
|
|
14366
|
-
|
|
14367
|
-
|
|
14737
|
+
refinementAttachmentsSchema = z10.array(attachmentSchema).max(MAX_START_SCREENSHOTS);
|
|
14738
|
+
visionScreenshotSchema = z10.object({
|
|
14739
|
+
name: z10.string().trim().min(1).max(180),
|
|
14740
|
+
mediaType: z10.enum(["image/png", "image/jpeg", "image/webp"]),
|
|
14741
|
+
data: z10.string().min(16).max(MAX_VISION_IMAGE_BASE64).regex(/^[A-Za-z0-9+/]+=*$/)
|
|
14368
14742
|
});
|
|
14369
|
-
requestSchema =
|
|
14370
|
-
projectId:
|
|
14371
|
-
sessionId:
|
|
14372
|
-
turnId:
|
|
14373
|
-
cycle:
|
|
14374
|
-
instruction:
|
|
14743
|
+
requestSchema = z10.object({
|
|
14744
|
+
projectId: z10.string().uuid(),
|
|
14745
|
+
sessionId: z10.string().uuid().optional(),
|
|
14746
|
+
turnId: z10.string().uuid().optional(),
|
|
14747
|
+
cycle: z10.number().int().min(1).max(3).optional(),
|
|
14748
|
+
instruction: z10.string().trim().min(1).max(MAX_REFINE_PROMPT_LENGTH),
|
|
14375
14749
|
focus: focusSchema.optional(),
|
|
14376
14750
|
baseLocale: localeCodeSchema,
|
|
14377
|
-
current:
|
|
14378
|
-
captions:
|
|
14379
|
-
outputs:
|
|
14751
|
+
current: z10.object({
|
|
14752
|
+
captions: z10.array(z10.string().max(240)).min(1).max(MAX_START_SCREENSHOTS),
|
|
14753
|
+
outputs: z10.array(z10.enum(START_OUTPUT_IDS)).min(1).max(START_OUTPUT_IDS.length),
|
|
14380
14754
|
// Bounded by the CATALOG, not by six. Studio's Add-language dialog offers every catalog entry
|
|
14381
14755
|
// with no ceiling and the reducer just appends, so a seventh language used to 400 every Agent
|
|
14382
14756
|
// turn on that project forever. A count ceiling below what the product lets a user build is a
|
|
14383
14757
|
// lockout; this one is only here to bound the prompt.
|
|
14384
|
-
locales:
|
|
14385
|
-
designPreset:
|
|
14386
|
-
layout:
|
|
14387
|
-
frames:
|
|
14758
|
+
locales: z10.array(localeCodeSchema).min(1).max(localeIds.length),
|
|
14759
|
+
designPreset: z10.enum(START_DESIGN_PRESET_IDS).nullable(),
|
|
14760
|
+
layout: z10.enum(START_LAYOUT_IDS).nullable(),
|
|
14761
|
+
frames: z10.array(currentShotSchema).min(1).max(MAX_START_SCREENSHOTS),
|
|
14388
14762
|
background: currentStripBackgroundSchema.optional(),
|
|
14389
|
-
frameStyles:
|
|
14763
|
+
frameStyles: z10.array(currentFramePatchSchema).min(1).max(MAX_START_SCREENSHOTS).optional(),
|
|
14390
14764
|
// Structural editing can add blank frames without adding source screenshots. Keep the vision
|
|
14391
14765
|
// attachment ceiling at ten while allowing those real project frames back into correction
|
|
14392
14766
|
// cycles instead of rejecting the first successful `add` operation on a full strip.
|
|
14393
|
-
structure:
|
|
14767
|
+
structure: z10.array(currentFrameSchema).min(1).max(20).optional()
|
|
14394
14768
|
}),
|
|
14395
|
-
screenshots:
|
|
14769
|
+
screenshots: z10.array(visionScreenshotSchema).min(1).max(MAX_START_SCREENSHOTS),
|
|
14396
14770
|
// Private refs from Studio. Opaque asset handles are derived server-side, so a client cannot
|
|
14397
14771
|
// plant its own handle table or smuggle a ref into model-visible data.
|
|
14398
|
-
attachments:
|
|
14772
|
+
attachments: refinementAttachmentsSchema.optional(),
|
|
14399
14773
|
// Opaque per-turn handles, on the wire because the MCP doors mint the table where the refs are
|
|
14400
14774
|
// (the adapter) and buy the pass somewhere else — hosted in-process, local over the control
|
|
14401
14775
|
// plane. Carrying a descriptor is not carrying authority: `{ id, label }` names nothing outside
|
|
14402
14776
|
// the turn that minted it, binds nothing, and the Studio door overwrites this field with its own
|
|
14403
14777
|
// table's descriptors regardless of what a client sent. The gate that matters is the
|
|
14404
14778
|
// authoritative write, which re-checks every ref a record introduces.
|
|
14405
|
-
assets:
|
|
14406
|
-
id:
|
|
14407
|
-
label:
|
|
14408
|
-
width:
|
|
14409
|
-
height:
|
|
14779
|
+
assets: z10.array(z10.object({
|
|
14780
|
+
id: z10.string().trim().min(1).max(64),
|
|
14781
|
+
label: z10.string().trim().min(1).max(180),
|
|
14782
|
+
width: z10.number().int().min(1).max(2e4).optional(),
|
|
14783
|
+
height: z10.number().int().min(1).max(2e4).optional()
|
|
14410
14784
|
})).max(MAX_START_SCREENSHOTS).optional(),
|
|
14411
14785
|
composedPreview: visionScreenshotSchema.optional(),
|
|
14412
14786
|
// MEASURED, never authored (#550): the client derives these from the engine's own collision
|
|
@@ -14414,17 +14788,24 @@ var init_refineProjectContracts = __esm({
|
|
|
14414
14788
|
// prompt renders into prose, never a value that reaches the reducer, and a strip with an unusual
|
|
14415
14789
|
// number of overlaps must not 400 a turn that was not about layout. The client's own ceiling is
|
|
14416
14790
|
// `MAX_REPORTED_FINDINGS` (mockup-engine/layoutFindings.ts), well inside this.
|
|
14417
|
-
layoutFindings:
|
|
14418
|
-
kind:
|
|
14419
|
-
frames:
|
|
14420
|
-
depthPct:
|
|
14421
|
-
anchored:
|
|
14422
|
-
clearAtScale:
|
|
14791
|
+
layoutFindings: z10.array(z10.object({
|
|
14792
|
+
kind: z10.enum(["caption-caption", "caption-device", "device-device"]),
|
|
14793
|
+
frames: z10.array(z10.number().int().min(0).max(31)).min(1).max(2),
|
|
14794
|
+
depthPct: z10.number().int().min(0).max(100),
|
|
14795
|
+
anchored: z10.boolean(),
|
|
14796
|
+
clearAtScale: z10.number().min(0.05).max(1).optional()
|
|
14423
14797
|
})).max(24).optional(),
|
|
14424
|
-
previous:
|
|
14425
|
-
actualDiff:
|
|
14426
|
-
inspection:
|
|
14427
|
-
cycle:
|
|
14798
|
+
previous: z10.object({
|
|
14799
|
+
actualDiff: z10.array(z10.string().trim().min(1).max(300)).max(24),
|
|
14800
|
+
inspection: z10.string().trim().min(1).max(MAX_DURABLE_MODEL_PROSE),
|
|
14801
|
+
cycle: z10.number().int().min(1).max(2),
|
|
14802
|
+
// The creating structural operations earlier cycles of this turn already performed, so the
|
|
14803
|
+
// prompt can list them and the model stops re-adding what it added. Optional: an older client
|
|
14804
|
+
// sends none, and the coordinator drops a repeat regardless.
|
|
14805
|
+
appliedOperations: z10.array(z10.object({
|
|
14806
|
+
op: z10.string().trim().min(1).max(40),
|
|
14807
|
+
target: z10.string().trim().min(1).max(180)
|
|
14808
|
+
})).max(32).optional()
|
|
14428
14809
|
}).optional()
|
|
14429
14810
|
}).superRefine((value, context) => {
|
|
14430
14811
|
if (value.sessionId == null !== (value.turnId == null)) {
|
|
@@ -14454,13 +14835,13 @@ var init_refineProjectContracts = __esm({
|
|
|
14454
14835
|
});
|
|
14455
14836
|
}
|
|
14456
14837
|
});
|
|
14457
|
-
legacyFinalizeSchema =
|
|
14458
|
-
generationId:
|
|
14459
|
-
outcome:
|
|
14460
|
-
projectId:
|
|
14461
|
-
instruction:
|
|
14462
|
-
effectSummary:
|
|
14463
|
-
turnStatus:
|
|
14838
|
+
legacyFinalizeSchema = z10.object({
|
|
14839
|
+
generationId: z10.string().uuid(),
|
|
14840
|
+
outcome: z10.enum(["completed", "cancelled", "failed"]),
|
|
14841
|
+
projectId: z10.string().uuid(),
|
|
14842
|
+
instruction: z10.string().trim().min(1).max(MAX_REFINE_PROMPT_LENGTH).optional(),
|
|
14843
|
+
effectSummary: z10.string().trim().min(1).max(2e3).optional(),
|
|
14844
|
+
turnStatus: z10.enum(["applied", "no_change", "failed", "cancelled"]).optional()
|
|
14464
14845
|
}).superRefine((value, context) => {
|
|
14465
14846
|
const durableFields = [value.instruction, value.effectSummary, value.turnStatus];
|
|
14466
14847
|
const present = durableFields.filter((field) => field !== void 0).length;
|
|
@@ -14472,52 +14853,57 @@ var init_refineProjectContracts = __esm({
|
|
|
14472
14853
|
});
|
|
14473
14854
|
}
|
|
14474
14855
|
});
|
|
14475
|
-
durableUsageSchema =
|
|
14476
|
-
inputTokens:
|
|
14477
|
-
cacheReadTokens:
|
|
14478
|
-
imageTokens:
|
|
14479
|
-
outputTokens:
|
|
14480
|
-
totalTokens:
|
|
14856
|
+
durableUsageSchema = z10.object({
|
|
14857
|
+
inputTokens: z10.number().int().min(0),
|
|
14858
|
+
cacheReadTokens: z10.number().int().min(0).default(0),
|
|
14859
|
+
imageTokens: z10.number().int().min(0).nullable(),
|
|
14860
|
+
outputTokens: z10.number().int().min(0),
|
|
14861
|
+
totalTokens: z10.number().int().min(0)
|
|
14481
14862
|
});
|
|
14482
|
-
durablePassSchema =
|
|
14483
|
-
phase:
|
|
14484
|
-
generationId:
|
|
14485
|
-
summary:
|
|
14863
|
+
durablePassSchema = z10.object({
|
|
14864
|
+
phase: z10.enum(["applying", "inspecting", "adjusting"]),
|
|
14865
|
+
generationId: z10.string().uuid(),
|
|
14866
|
+
summary: z10.string().trim().min(1).max(MAX_DURABLE_MODEL_PROSE),
|
|
14486
14867
|
usage: durableUsageSchema,
|
|
14487
|
-
createdAt:
|
|
14868
|
+
createdAt: z10.string().datetime()
|
|
14488
14869
|
});
|
|
14489
|
-
durableStateDiffSchema =
|
|
14490
|
-
summary:
|
|
14491
|
-
broaderChanges:
|
|
14492
|
-
remainingMismatch:
|
|
14870
|
+
durableStateDiffSchema = z10.object({
|
|
14871
|
+
summary: z10.string().trim().min(1).max(2e3),
|
|
14872
|
+
broaderChanges: z10.array(z10.string().trim().min(1).max(500)).max(24),
|
|
14873
|
+
remainingMismatch: z10.string().trim().min(1).max(MAX_DURABLE_MODEL_PROSE).nullable()
|
|
14493
14874
|
});
|
|
14494
|
-
agentOutcomeSchema =
|
|
14875
|
+
agentOutcomeSchema = z10.custom((value) => {
|
|
14495
14876
|
try {
|
|
14496
14877
|
return !!value && typeof value === "object" && validateAgentOutcome(value).length === 0;
|
|
14497
14878
|
} catch {
|
|
14498
14879
|
return false;
|
|
14499
14880
|
}
|
|
14500
14881
|
}, { message: "The Agent outcome is invalid." });
|
|
14501
|
-
durableFinalizeSchema =
|
|
14502
|
-
projectId:
|
|
14503
|
-
sessionId:
|
|
14504
|
-
turnId:
|
|
14882
|
+
durableFinalizeSchema = z10.object({
|
|
14883
|
+
projectId: z10.string().uuid(),
|
|
14884
|
+
sessionId: z10.string().uuid(),
|
|
14885
|
+
turnId: z10.string().uuid(),
|
|
14505
14886
|
// #580 — the retry / clarification chain, and the ONLY receipt fact this door takes from the
|
|
14506
14887
|
// browser. Every other figure on the receipt is re-read server-side from the ledger or derived
|
|
14507
14888
|
// from the validated outcome; a parent id is a correlation the client alone knows.
|
|
14508
|
-
parentTurnId:
|
|
14509
|
-
generationIds:
|
|
14510
|
-
outcome:
|
|
14511
|
-
committed:
|
|
14512
|
-
instruction:
|
|
14889
|
+
parentTurnId: z10.string().uuid().optional(),
|
|
14890
|
+
generationIds: z10.array(z10.string().uuid()).min(1).max(3),
|
|
14891
|
+
outcome: z10.enum(["completed", "cancelled", "failed"]),
|
|
14892
|
+
committed: z10.boolean(),
|
|
14893
|
+
instruction: z10.string().trim().min(1).max(MAX_REFINE_PROMPT_LENGTH),
|
|
14513
14894
|
focus: focusSchema,
|
|
14514
|
-
interpretation:
|
|
14515
|
-
passes:
|
|
14895
|
+
interpretation: z10.string().trim().min(1).max(MAX_DURABLE_MODEL_PROSE),
|
|
14896
|
+
passes: z10.array(durablePassSchema).min(1).max(3),
|
|
14516
14897
|
finalStateDiff: durableStateDiffSchema,
|
|
14517
14898
|
agentOutcome: agentOutcomeSchema,
|
|
14518
|
-
|
|
14519
|
-
|
|
14520
|
-
|
|
14899
|
+
// #781 — the coordinator's unmet-demand classification for the whole turn. Optional and
|
|
14900
|
+
// deliberately loose here: it is analytics, so a malformed value must never fail a finalize that
|
|
14901
|
+
// settles real money. `parseAgentTurnDemand` closes it against the vocabulary downstream, and
|
|
14902
|
+
// anything it rejects becomes `not_measured` rather than a 400.
|
|
14903
|
+
agentDemand: z10.unknown().optional(),
|
|
14904
|
+
turnStatus: z10.enum(["applied", "no_change", "capped", "needs_input", "failed", "cancelled"]),
|
|
14905
|
+
startedAt: z10.string().datetime(),
|
|
14906
|
+
completedAt: z10.string().datetime()
|
|
14521
14907
|
}).superRefine((value, context) => {
|
|
14522
14908
|
const passGenerationIds = value.passes.map((pass) => pass.generationId);
|
|
14523
14909
|
if (new Set(value.generationIds).size !== value.generationIds.length) {
|
|
@@ -14550,23 +14936,23 @@ var init_refineProjectContracts = __esm({
|
|
|
14550
14936
|
});
|
|
14551
14937
|
}
|
|
14552
14938
|
});
|
|
14553
|
-
revertSchema =
|
|
14554
|
-
intent:
|
|
14555
|
-
projectId:
|
|
14939
|
+
revertSchema = z10.object({
|
|
14940
|
+
intent: z10.literal("revert"),
|
|
14941
|
+
projectId: z10.string().uuid(),
|
|
14556
14942
|
/** The committed turn being undone. Becomes the new receipt's `parent_turn_id`. */
|
|
14557
|
-
turnId:
|
|
14943
|
+
turnId: z10.string().uuid(),
|
|
14558
14944
|
/** The revert's own turn id, minted by the browser exactly as a turn id is. */
|
|
14559
|
-
revertTurnId:
|
|
14945
|
+
revertTurnId: z10.string().uuid()
|
|
14560
14946
|
});
|
|
14561
|
-
finalizeSchema =
|
|
14562
|
-
createSessionSchema =
|
|
14563
|
-
projectId:
|
|
14564
|
-
sessionId:
|
|
14565
|
-
firstInstruction:
|
|
14947
|
+
finalizeSchema = z10.union([revertSchema, durableFinalizeSchema, legacyFinalizeSchema]);
|
|
14948
|
+
createSessionSchema = z10.object({
|
|
14949
|
+
projectId: z10.string().uuid(),
|
|
14950
|
+
sessionId: z10.string().uuid(),
|
|
14951
|
+
firstInstruction: z10.string().trim().min(1).max(MAX_REFINE_PROMPT_LENGTH).optional()
|
|
14566
14952
|
});
|
|
14567
|
-
historySchema =
|
|
14568
|
-
projectId:
|
|
14569
|
-
sessionId:
|
|
14953
|
+
historySchema = z10.object({
|
|
14954
|
+
projectId: z10.string().uuid(),
|
|
14955
|
+
sessionId: z10.string().uuid().optional()
|
|
14570
14956
|
});
|
|
14571
14957
|
REFINE_FIELD_LABELS = {
|
|
14572
14958
|
projectId: "the project id",
|
|
@@ -14728,47 +15114,55 @@ async function renderedTurn(deps, state, screens) {
|
|
|
14728
15114
|
if (!rendered.ok) throw new Error("The project could not be rendered for Agent inspection.");
|
|
14729
15115
|
const bytesByShotId = new Map(screens.screenManifest.map((entry) => [entry.shotId, entry.bytes]));
|
|
14730
15116
|
const baseCaptions = resolveCaptionText(state.captionText, state.baseLocale, state.baseLocale);
|
|
14731
|
-
const
|
|
15117
|
+
const hasPixels = (shot) => bytesByShotId.has(shot.id);
|
|
15118
|
+
const visionScreens = await Promise.all(state.panels.flatMap((panel) => {
|
|
14732
15119
|
const devices = state.shots.filter((shot) => shot.panelId === panel.id);
|
|
14733
|
-
const representative = devices.find(
|
|
15120
|
+
const representative = devices.find(hasPixels);
|
|
14734
15121
|
if (!representative) return [];
|
|
14735
15122
|
const bytes = bytesByShotId.get(representative.id);
|
|
14736
15123
|
const captions = baseCaptions[panel.id] ?? [];
|
|
14737
15124
|
const background2 = aiBackgroundFromPanel(state.panelBackgrounds[panel.id]);
|
|
14738
15125
|
return [compactVisionImage(bytes, representative.frameName).then((vision) => ({
|
|
14739
|
-
|
|
14740
|
-
|
|
14741
|
-
|
|
14742
|
-
|
|
14743
|
-
|
|
14744
|
-
|
|
14745
|
-
background: background2
|
|
14746
|
-
},
|
|
14747
|
-
structure: {
|
|
14748
|
-
id: panel.id,
|
|
14749
|
-
label: `Frame ${frameIndex + 1}`,
|
|
14750
|
-
sourceName: devices[0]?.frameName ?? null,
|
|
14751
|
-
devices: devices.map((shot, deviceIndex) => ({
|
|
14752
|
-
id: shot.id,
|
|
14753
|
-
label: devices.length === 1 ? shot.frameName : `${shot.frameName} \xB7 Device ${deviceIndex + 1}`,
|
|
14754
|
-
look: aiShotPatchFromLook(shot.look)
|
|
14755
|
-
})),
|
|
14756
|
-
captions: captions.map((caption, index) => ({
|
|
14757
|
-
index,
|
|
14758
|
-
label: caption.text.trim() || `Caption ${index + 1}`,
|
|
14759
|
-
text: caption.text,
|
|
14760
|
-
style: aiCaptionStyleFromLayer(caption)
|
|
14761
|
-
})),
|
|
14762
|
-
background: background2
|
|
14763
|
-
}
|
|
15126
|
+
...vision,
|
|
15127
|
+
panelId: panel.id,
|
|
15128
|
+
caption: captions[0]?.text ?? "",
|
|
15129
|
+
frame: aiShotPatchFromLook(representative.look),
|
|
15130
|
+
captionStyle: aiCaptionStyleFromLayer(captions[0]),
|
|
15131
|
+
background: background2
|
|
14764
15132
|
}))];
|
|
14765
15133
|
}));
|
|
14766
|
-
|
|
15134
|
+
let nextScreenshot = 0;
|
|
15135
|
+
const structure = state.panels.map((panel, frameIndex) => {
|
|
15136
|
+
const devices = state.shots.filter((shot) => shot.panelId === panel.id);
|
|
15137
|
+
const captions = baseCaptions[panel.id] ?? [];
|
|
15138
|
+
const background2 = aiBackgroundFromPanel(state.panelBackgrounds[panel.id]);
|
|
15139
|
+
const screenshotIndex = devices.some(hasPixels) ? nextScreenshot++ : null;
|
|
15140
|
+
return {
|
|
15141
|
+
id: panel.id,
|
|
15142
|
+
label: `Frame ${frameIndex + 1}`,
|
|
15143
|
+
sourceName: devices[0]?.frameName ?? null,
|
|
15144
|
+
devices: devices.map((shot, deviceIndex) => ({
|
|
15145
|
+
id: shot.id,
|
|
15146
|
+
label: devices.length === 1 ? shot.frameName : `${shot.frameName} \xB7 Device ${deviceIndex + 1}`,
|
|
15147
|
+
look: aiShotPatchFromLook(shot.look)
|
|
15148
|
+
})),
|
|
15149
|
+
captions: captions.map((caption, index) => ({
|
|
15150
|
+
index,
|
|
15151
|
+
label: caption.text.trim() || `Caption ${index + 1}`,
|
|
15152
|
+
text: caption.text,
|
|
15153
|
+
style: aiCaptionStyleFromLayer(caption)
|
|
15154
|
+
})),
|
|
15155
|
+
background: background2,
|
|
15156
|
+
screenshotIndex
|
|
15157
|
+
};
|
|
15158
|
+
});
|
|
15159
|
+
if (visionScreens.length === 0) throw new Error("The project has no readable screenshots for Agent inspection.");
|
|
15160
|
+
const layoutFindings = rendered.layout?.findings ?? (rendered.layoutMeasured ? [] : void 0);
|
|
14767
15161
|
return {
|
|
14768
|
-
screens:
|
|
14769
|
-
structure
|
|
15162
|
+
screens: visionScreens,
|
|
15163
|
+
structure,
|
|
14770
15164
|
...rendered.stripBase64 ? { composedPreview: await compactVisionImage(rendered.stripBase64, "shotops-composed-preview.png") } : {},
|
|
14771
|
-
...
|
|
15165
|
+
...layoutFindings !== void 0 ? { layoutFindings } : {}
|
|
14772
15166
|
};
|
|
14773
15167
|
}
|
|
14774
15168
|
function outsideFocus(patch, focus, rendered) {
|
|
@@ -14841,11 +15235,14 @@ function requestForPass(context, input) {
|
|
|
14841
15235
|
// planner pass carries about a supplied screenshot has to be meaningless outside this turn.
|
|
14842
15236
|
...context.assets.length > 0 ? { assets: context.assets.map((asset) => ({ ...asset })) } : {},
|
|
14843
15237
|
...input.rendered.composedPreview ? { composedPreview: input.rendered.composedPreview } : {},
|
|
14844
|
-
|
|
15238
|
+
// #827 — `!== undefined`, not truthiness: a measured-clean render's `layoutFindings` is `[]`,
|
|
15239
|
+
// which must still reach the planner (it is what says "measured, nothing wrong").
|
|
15240
|
+
...input.rendered.layoutFindings !== void 0 ? { layoutFindings: input.rendered.layoutFindings } : {},
|
|
14845
15241
|
...input.previous ? {
|
|
14846
15242
|
previous: {
|
|
14847
15243
|
...input.previous,
|
|
14848
|
-
actualDiff: [...input.previous.actualDiff]
|
|
15244
|
+
actualDiff: [...input.previous.actualDiff],
|
|
15245
|
+
...input.previous.appliedOperations ? { appliedOperations: [...input.previous.appliedOperations] } : {}
|
|
14849
15246
|
}
|
|
14850
15247
|
} : {}
|
|
14851
15248
|
});
|
|
@@ -14866,7 +15263,9 @@ function generatedAuthorization(request, generated, generationId, panelIds, rend
|
|
|
14866
15263
|
...generated.followUp ? { followUp: generated.followUp } : {},
|
|
14867
15264
|
...patch ? { patch, broaderChanges: outsideFocus(patch, request.focus ?? contextFocus(), rendered) } : {},
|
|
14868
15265
|
...generated.outcome ? { terminalOutcome: generated.outcome } : {},
|
|
14869
|
-
...generated.gaps ? { gaps: generated.gaps } : {}
|
|
15266
|
+
...generated.gaps ? { gaps: generated.gaps } : {},
|
|
15267
|
+
// #781 — the same intent that decided the outcome, reported as this pass's unmet demand.
|
|
15268
|
+
...generated.demand ? { demand: generated.demand } : {}
|
|
14870
15269
|
};
|
|
14871
15270
|
}
|
|
14872
15271
|
function contextFocus() {
|
|
@@ -14877,7 +15276,7 @@ function applyAllowance(allowance, pass) {
|
|
|
14877
15276
|
}
|
|
14878
15277
|
async function authorizePass(context, request, panelIds, rendered) {
|
|
14879
15278
|
context.screenshotCount = request.screenshots.length + (request.composedPreview ? 1 : 0);
|
|
14880
|
-
const result = await context.runtime.plannerPass(context.userId, request, context.turnKey);
|
|
15279
|
+
const result = await context.runtime.plannerPass(context.userId, request, context.turnKey, context.assetTable);
|
|
14881
15280
|
applyAllowance(context.allowance, result.allowance);
|
|
14882
15281
|
if (result.ok) {
|
|
14883
15282
|
return generatedAuthorization(request, result.plan, result.generationId, panelIds, rendered);
|
|
@@ -14934,7 +15333,8 @@ async function runMcpProjectAgentTurn(deps, input, runtime) {
|
|
|
14934
15333
|
focus: input.focus,
|
|
14935
15334
|
allowance,
|
|
14936
15335
|
runtime,
|
|
14937
|
-
assets: assetTable.descriptors
|
|
15336
|
+
assets: assetTable.descriptors,
|
|
15337
|
+
assetTable
|
|
14938
15338
|
};
|
|
14939
15339
|
const result = await runAgentTurn({
|
|
14940
15340
|
turnId,
|
|
@@ -14971,6 +15371,7 @@ async function runMcpProjectAgentTurn(deps, input, runtime) {
|
|
|
14971
15371
|
}
|
|
14972
15372
|
return renderedTurn(deps, state, resolved);
|
|
14973
15373
|
},
|
|
15374
|
+
unresolvedLayout: (rendered) => describeUnresolvedLayout(rendered.layoutFindings),
|
|
14974
15375
|
authorize: async ({ cycle, state, rendered, previous }) => {
|
|
14975
15376
|
const request = requestForPass(context, { cycle, state, rendered, previous });
|
|
14976
15377
|
const authorization = await authorizePass(
|
|
@@ -15023,7 +15424,8 @@ async function runMcpProjectAgentTurn(deps, input, runtime) {
|
|
|
15023
15424
|
startedAt,
|
|
15024
15425
|
completedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
15025
15426
|
screenshotCount: context.screenshotCount,
|
|
15026
|
-
instructionLength: input.instruction.length
|
|
15427
|
+
instructionLength: input.instruction.length,
|
|
15428
|
+
demand: event.result.demand
|
|
15027
15429
|
}
|
|
15028
15430
|
});
|
|
15029
15431
|
allowance.remaining = settlement.balanceCredits;
|
|
@@ -15051,7 +15453,8 @@ async function runMcpProjectAgentTurn(deps, input, runtime) {
|
|
|
15051
15453
|
startedAt,
|
|
15052
15454
|
completedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
15053
15455
|
screenshotCount: context.screenshotCount,
|
|
15054
|
-
instructionLength: input.instruction.length
|
|
15456
|
+
instructionLength: input.instruction.length,
|
|
15457
|
+
demand: event.result.demand
|
|
15055
15458
|
});
|
|
15056
15459
|
} catch (error) {
|
|
15057
15460
|
runtime.log("mcp_agent_turn_receipt_failed", { turnKey, ...safeFailureDiagnostic(error) });
|
|
@@ -15070,6 +15473,7 @@ var init_agentTurnAdapter = __esm({
|
|
|
15070
15473
|
init_agentOutcome();
|
|
15071
15474
|
init_projectRecord();
|
|
15072
15475
|
init_gradient();
|
|
15476
|
+
init_layoutFindings();
|
|
15073
15477
|
init_capabilities();
|
|
15074
15478
|
init_invalidRequest();
|
|
15075
15479
|
init_refineProjectContracts();
|
|
@@ -15102,7 +15506,16 @@ function writeErrorFrom(error) {
|
|
|
15102
15506
|
}
|
|
15103
15507
|
function localAgentTurnRuntime(bridge) {
|
|
15104
15508
|
return {
|
|
15105
|
-
plannerPass: (_userId, request, turnKey) => bridge.refinePass(
|
|
15509
|
+
plannerPass: (_userId, request, turnKey, assetTable) => bridge.refinePass(
|
|
15510
|
+
request.projectId,
|
|
15511
|
+
request,
|
|
15512
|
+
turnKey,
|
|
15513
|
+
void 0,
|
|
15514
|
+
assetTable.descriptors.map(({ id }) => {
|
|
15515
|
+
const { ref, label, width, height } = assetTable.sources[id];
|
|
15516
|
+
return { ref, label, ...width ? { width } : {}, ...height ? { height } : {} };
|
|
15517
|
+
})
|
|
15518
|
+
),
|
|
15106
15519
|
// The receipt facts travel WITH settlement (#580): the server writes the one receipt for this
|
|
15107
15520
|
// turn, keyed by the id the local coordinator ran under, and this machine — which holds no
|
|
15108
15521
|
// Supabase credential — writes nothing durable at all.
|
|
@@ -15122,7 +15535,8 @@ function localAgentTurnRuntime(bridge) {
|
|
|
15122
15535
|
startedAt: input.startedAt,
|
|
15123
15536
|
completedAt: input.completedAt,
|
|
15124
15537
|
screenshotCount: input.screenshotCount ?? 0,
|
|
15125
|
-
instructionLength: input.instructionLength ?? 0
|
|
15538
|
+
instructionLength: input.instructionLength ?? 0,
|
|
15539
|
+
demand: input.demand ?? NOT_MEASURED_DEMAND
|
|
15126
15540
|
}
|
|
15127
15541
|
});
|
|
15128
15542
|
},
|
|
@@ -15138,7 +15552,7 @@ function localAgentTurnRuntime(bridge) {
|
|
|
15138
15552
|
log: (event, fields2) => logEvent("error", event, fields2)
|
|
15139
15553
|
};
|
|
15140
15554
|
}
|
|
15141
|
-
async function runLocalRefineTurn(deps, bridge, input) {
|
|
15555
|
+
async function runLocalRefineTurn(deps, bridge, input, runtimeOverrides) {
|
|
15142
15556
|
try {
|
|
15143
15557
|
const turn = await runMcpProjectAgentTurn(
|
|
15144
15558
|
deps,
|
|
@@ -15148,7 +15562,7 @@ async function runLocalRefineTurn(deps, bridge, input) {
|
|
|
15148
15562
|
...input.project ? { project: input.project } : {},
|
|
15149
15563
|
...input.attachments?.length ? { attachments: input.attachments } : {}
|
|
15150
15564
|
},
|
|
15151
|
-
localAgentTurnRuntime(bridge)
|
|
15565
|
+
runtimeOverrides ? { ...localAgentTurnRuntime(bridge), ...runtimeOverrides } : localAgentTurnRuntime(bridge)
|
|
15152
15566
|
);
|
|
15153
15567
|
return refineProjectResult(turn);
|
|
15154
15568
|
} catch {
|
|
@@ -15159,6 +15573,7 @@ var init_localRefineTurn = __esm({
|
|
|
15159
15573
|
"src/project/localRefineTurn.ts"() {
|
|
15160
15574
|
"use strict";
|
|
15161
15575
|
init_log();
|
|
15576
|
+
init_agentUnmetActions();
|
|
15162
15577
|
init_agentTurnAdapter();
|
|
15163
15578
|
init_hostedBridge();
|
|
15164
15579
|
init_refineProjectReceipt();
|
|
@@ -15307,7 +15722,7 @@ var init_projectClaimClient = __esm({
|
|
|
15307
15722
|
|
|
15308
15723
|
// src/runtime/localDeps.ts
|
|
15309
15724
|
import { readFile as readFile4 } from "node:fs/promises";
|
|
15310
|
-
function localToolDeps(token2) {
|
|
15725
|
+
function localToolDeps(token2, options = {}) {
|
|
15311
15726
|
const base = {
|
|
15312
15727
|
renderer: new StripRenderer({ serve: "static" }),
|
|
15313
15728
|
// Token-backed cloud writes cross the same authority in the control plane. This local handler
|
|
@@ -15372,7 +15787,7 @@ function localToolDeps(token2) {
|
|
|
15372
15787
|
}
|
|
15373
15788
|
};
|
|
15374
15789
|
}
|
|
15375
|
-
const bridge = connectHostedBridge(token2);
|
|
15790
|
+
const bridge = options.decorateBridge ? options.decorateBridge(connectHostedBridge(token2)) : connectHostedBridge(token2);
|
|
15376
15791
|
const bridged = {
|
|
15377
15792
|
...base,
|
|
15378
15793
|
resolveProject: (userId, projectId) => bridge.resolveProject(userId, projectId),
|
|
@@ -15413,7 +15828,7 @@ function localToolDeps(token2) {
|
|
|
15413
15828
|
await bridge.close();
|
|
15414
15829
|
}
|
|
15415
15830
|
};
|
|
15416
|
-
bridged.refineProject = (userId, input) => runLocalRefineTurn({ ...bridged, userId }, bridge, input);
|
|
15831
|
+
bridged.refineProject = (userId, input) => runLocalRefineTurn({ ...bridged, userId }, bridge, input, options.emit ? { emit: options.emit } : void 0);
|
|
15417
15832
|
return bridged;
|
|
15418
15833
|
}
|
|
15419
15834
|
async function pushScreens(bridge, projectId, record8, recordVersion, screenshots2) {
|