shotops-mcp 0.7.0 → 0.9.0
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 +242 -88
- package/THIRD_PARTY_NOTICES +1 -0
- package/dist/local.js +21022 -5365
- package/harness-dist/assets/index-Wb7M1qGz.js +1 -0
- package/harness-dist/assets/three-addons-CvX38LO6.js +1 -0
- package/harness-dist/assets/three-webgl-DCw804Ic.js +6491 -0
- package/harness-dist/index.html +3 -1
- package/package.json +10 -4
- package/widget-dist/bundle.js +4 -4
- package/widget-dist/panels.js +3 -3
- package/harness-dist/assets/index-DvvjdOuK.js +0 -3802
package/harness-dist/index.html
CHANGED
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="utf-8" />
|
|
5
5
|
<title>shotops-mcp headless render harness</title>
|
|
6
|
-
<script type="module" crossorigin src="./assets/index-
|
|
6
|
+
<script type="module" crossorigin src="./assets/index-Wb7M1qGz.js"></script>
|
|
7
|
+
<link rel="modulepreload" crossorigin href="./assets/three-webgl-DCw804Ic.js">
|
|
8
|
+
<link rel="modulepreload" crossorigin href="./assets/three-addons-CvX38LO6.js">
|
|
7
9
|
</head>
|
|
8
10
|
<body>
|
|
9
11
|
</body>
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shotops-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
|
-
"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.
|
|
6
|
+
"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`) — same render, on your own machine, no account needed.",
|
|
7
7
|
"license": "SEE LICENSE IN LICENSE",
|
|
8
8
|
"homepage": "https://shotops.dev",
|
|
9
9
|
"repository": {
|
|
@@ -32,27 +32,33 @@
|
|
|
32
32
|
"start": "tsx src/server.ts",
|
|
33
33
|
"build:harness": "vite build --config vite.harness.config.mjs",
|
|
34
34
|
"build:node": "node build.mjs",
|
|
35
|
-
"build:server": "
|
|
35
|
+
"build:server": "nitro build",
|
|
36
36
|
"build": "npm run build:harness && npm run build:widget && npm run build:node",
|
|
37
|
+
"prepack": "node ../scripts/third-party-notices.mjs --check",
|
|
37
38
|
"prepublishOnly": "npm run build",
|
|
38
39
|
"typecheck": "tsc --noEmit",
|
|
39
40
|
"build:widget": "node build.widget.mjs"
|
|
40
41
|
},
|
|
41
42
|
"dependencies": {
|
|
42
43
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
44
|
+
"@opentelemetry/api": "1.9.0",
|
|
43
45
|
"express": "^5.2.1",
|
|
44
46
|
"fflate": "^0.8.3",
|
|
45
47
|
"playwright": "1.61.1",
|
|
46
48
|
"sharp": "^0.35.3",
|
|
47
49
|
"tsx": "^4.23.0",
|
|
50
|
+
"workflow": "4.8.4",
|
|
48
51
|
"zod": "^3.25.76"
|
|
49
52
|
},
|
|
50
53
|
"devDependencies": {
|
|
51
54
|
"@types/express": "^5.0.6",
|
|
55
|
+
"ai": "^7.0.48",
|
|
52
56
|
"esbuild": "^0.28.1",
|
|
57
|
+
"nitro": "3.0.260610-beta",
|
|
53
58
|
"pixelmatch": "^7.2.0",
|
|
54
59
|
"pngjs": "^7.0.0",
|
|
60
|
+
"rollup": "^4.62.5",
|
|
55
61
|
"typescript": "^5.6.0",
|
|
56
|
-
"vite": "^
|
|
62
|
+
"vite": "^7.3.6"
|
|
57
63
|
}
|
|
58
64
|
}
|
package/widget-dist/bundle.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";(()=>{var z=`
|
|
1
|
+
"use strict";(()=>{var z="shotops/widgetPayload";var P=`
|
|
2
2
|
:root {
|
|
3
3
|
color-scheme: light dark;
|
|
4
4
|
--sf-ink: #15151a;
|
|
@@ -124,8 +124,8 @@ button, a { font: inherit; }
|
|
|
124
124
|
@media (prefers-reduced-motion: reduce) {
|
|
125
125
|
.sf-download, .sf-open { transition: none; }
|
|
126
126
|
}
|
|
127
|
-
`;function
|
|
128
|
-
`)}var
|
|
127
|
+
`;function r(e,n,o){let t=document.createElement(e);return n&&(t.className=n),o!==void 0&&(t.textContent=o),t}function g(e,n,o){let t=r("div","sf-stat");t.append(r("div","sf-k",n),r("div","sf-v",o)),e.append(t)}async function L(e){if(window.openai?.openExternal){await window.openai.openExternal({href:e});return}window.open(e,"_blank","noopener,noreferrer")}function R(e,n,o,t){let i=n;try{let p=new URL(n);/\/storage\/v1\/object\/sign\//.test(p.pathname)&&(p.searchParams.set("download",o),i=p.toString())}catch{}let s=r("a",t,e);return s.href=i,s.download=o,s.rel="noopener noreferrer",/^https?:/i.test(n)&&(s.target="_blank",s.addEventListener("click",p=>{window.openai?.openExternal&&(p.preventDefault(),L(i))})),s}function M(e,n,o){let t=r("button",o,e);return t.type="button",t.addEventListener("click",()=>{L(n)}),t}function d(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:null}function D(e){if(!Array.isArray(e.content))return null;let n=[];for(let o of e.content){let t=d(o);if(!t)continue;if(t.type==="image"&&typeof t.data=="string"&&t.mimeType==="image/png"){n.push(t.data);continue}if(t.type==="resource_link"&&typeof t.uri=="string"&&t.mimeType==="image/png"){n.push({url:t.uri});continue}let i=d(t.resource);t.type==="resource"&&i&&typeof i.uri=="string"&&i.mimeType==="image/png"&&n.push({url:i.uri})}if(n.length>0)return{ok:!0,count:n.length,output:typeof n[0]=="string"?"inline":"urls",panels:n};if(e.isError===!0){let o=e.content.map(t=>d(t)).find(t=>t?.type==="text"&&typeof t.text=="string")?.text;return{ok:!1,...typeof o=="string"?{note:o}:{}}}return null}function C(e,n=0){let o=d(e);if(!o||n>6)return null;let t=d(o[z]);if(t)return t;let i=d(o._meta),s=d(i?.[z]);if(s)return s;for(let p of["mcp_tool_result","call_tool_result","tool_result","result"]){let c=C(o[p],n+1);if(c)return c}return null}function _(e,n=!0,o=0){let t=d(e);if(!t||o>6)return n?e:null;for(let s of["structuredContent","structured_content"]){let p=d(t[s]);if(p)return p}for(let s of["mcp_tool_result","call_tool_result","tool_result","result"]){if(t[s]===void 0)continue;let p=_(t[s],!1,o+1);if(p)return p}let i=D(t);return i||(n?e:null)}function B(e,n=0){let o=d(e);if(!o||n>6)return null;let t=typeof o.status=="string"?o.status.toLowerCase():"";if(["failed","failure","error","cancelled","canceled"].includes(t))return"failure";if(["complete","completed","success","succeeded"].includes(t))return"success";for(let i of["mcp_tool_result","call_tool_result","tool_result","result"]){let s=B(o[i],n+1);if(s)return s}return null}function j(e){let n=d(e.detail);return d(n?.globals)}function F(e){return C(e)??_(e,!1)}function U(e){if(!e||typeof e!="object")return e;let n=e;return n.structuredContent&&typeof n.structuredContent=="object"?n.structuredContent:_(e)}function I(e){let n=document.createElement("style");n.textContent=e.css;let o=r("div","sf-root");o.id=e.rootId,o.append(r("div","sf-empty",e.loading)),document.body.append(n,o);let t=!1,i=l=>{let a=U(l);!a||typeof a!="object"||e.accept&&!e.accept(a)||(t=!0,e.render(o,a))},s=l=>i(F(l));window.addEventListener("message",l=>{if(l.source!==window.parent)return;let a=l.data;!a||a.jsonrpc!=="2.0"||a.method!=="ui/notifications/tool-result"||(i(a.params?.structuredContent),t||s(a.params))},{passive:!0}),window.addEventListener("openai:set_globals",l=>{let a=j(l);a&&(i(a.toolOutput),t||s(a.toolResponseMetadata))},{passive:!0});let p=100,c=500,v=2e3,k=5*6e4,x=2e3,u=0,m=null,h=!1,w=()=>{if(i(window.openai?.toolOutput),t||s(window.openai?.toolResponseMetadata),t)return;let l=B(window.openai?.toolResponseMetadata);if(l&&m===null&&(m=u),l&&!h&&(l==="failure"||u-(m??u)>=x)&&(h=!0,o.replaceChildren(r("div","sf-empty",e.terminal??e.empty))),u>=k){h||o.replaceChildren(r("div","sf-empty",e.terminal??e.empty));return}let a=u<v?p:c;u+=a,setTimeout(w,a)};w()}function W(e){return e<1024?`${e} B`:e<1024*1024?`${Math.round(e/1024)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`}function S(e){if(typeof e.zipBase64=="string"&&e.zipBase64.length>0){let n=e.zipBase64.endsWith("==")?2:e.zipBase64.endsWith("=")?1:0;return{href:`data:application/zip;base64,${e.zipBase64}`,size:W(Math.max(0,e.zipBase64.length*3/4-n))}}return typeof e.zipUrl=="string"&&e.zipUrl.length>0?{href:e.zipUrl,size:null}:null}function $(e){if(!e)return"Anyone with the link can download it. Links last 14 days.";let n=new Date(e);if(Number.isNaN(n.getTime()))return"Anyone with the link can download it. Links last 14 days.";let o=n.toLocaleDateString(void 0,{day:"numeric",month:"short",year:"numeric"}),t=Math.ceil((n.getTime()-Date.now())/864e5);return t<=0?`This link has expired (${o}). Emit the bundle again for a fresh one.`:`Anyone with the link can download it. Expires ${o} \u2014 ${t} day${t===1?"":"s"} from now.`}function N(e){let n=e.length>0?e:["en-US"],o=["fastlane/"],t=n.slice(0,3);return t.forEach(i=>{o.push(` screenshots/${i}/ the PNGs, named in strip order`)}),n.length>t.length&&o.push(` screenshots/\u2026 +${n.length-t.length} more locale folder(s)`),o.push(" Deliverfile pre-filled, ready to run"),o.push("README.md how to upload with your own key"),o.join(`
|
|
128
|
+
`)}function T(e){if(!e.operationId||!e.status)return null;let n=Math.max(0,Number(e.progress?.completed??0)),o=Math.max(n,Number(e.progress?.total??0)),t={accepted:["Production accepted","ShotOps is preparing the durable render.","Accepted",!1],queued:["Production queued","The render is safely queued and can outlive this conversation.","Queued",!1],running:["Production rendering","ShotOps is rendering and checkpointing the final assets.","Running",!1],cancel_requested:["Cancellation requested","Work already in flight will stop at the next safe checkpoint.","Cancelling",!1],failed:["Production could not finish","The operation stopped without returning a partial asset set.","Failed",!0],cancelled:["Production cancelled","Unfinished work stopped and the remaining reservation was released.","Cancelled",!0],succeeded:["Production finished","The durable operation succeeded; request its result for fresh download links.","Succeeded",!0]},[i,s,p,c]=t[e.status];return{title:i,detail:s,badge:p,terminal:c,completed:n,total:o}}var H=`${P}
|
|
129
129
|
.sf-body { padding: 15px 16px 4px; }
|
|
130
130
|
.sf-zip {
|
|
131
131
|
display: flex;
|
|
@@ -218,4 +218,4 @@ button, a { font: inherit; }
|
|
|
218
218
|
@media (prefers-reduced-motion: reduce) {
|
|
219
219
|
.sf-get { transition: none; }
|
|
220
220
|
}
|
|
221
|
-
|
|
221
|
+
`,Y="You upload this yourself. ShotOps never holds your Apple credentials, never creates an App Store version, and never submits anything for review.";function q(e,n){return R("Download .zip",e.href,n,"sf-get")}function G(e,n){e.replaceChildren();let o=T(n);if(o&&!S(n)){let f=r("section","sf-shell"),b=r("header","sf-head"),O=r("div");O.append(r("p","sf-eyebrow","ShotOps / durable production"),r("h2","sf-title",o.title),r("p","sf-sub",o.detail));let A=r("span","sf-badge");A.append(r("span","sf-dot"),document.createTextNode(o.badge)),b.append(O,A),f.append(b);let y=r("footer","sf-meta");g(y,"Progress",o.total>0?`${o.completed}/${o.total}`:"Waiting"),typeof n.progress?.attempt=="number"&&g(y,"Attempt",String(n.progress.attempt)),typeof n.contract?.cost?.reserved=="number"&&g(y,"Reserved",String(n.contract.cost.reserved)),typeof n.contract?.cost?.released=="number"&&g(y,"Released",String(n.contract.cost.released)),f.append(y,r("p","sf-note",`Operation ${n.operationId}. Reconnect with production_operation.`)),e.append(f),window.openai?.notifyIntrinsicHeight?.();return}let t=Array.isArray(n.locales)&&n.locales.length>0?n.locales:n.locale?[n.locale]:[],i=typeof n.panelCount=="number"?n.panelCount:0,s=typeof n.totalPanelCount=="number"?n.totalPanelCount:i*Math.max(1,t.length),p=r("section","sf-shell"),c=r("header","sf-head"),v=r("div");v.append(r("p","sf-eyebrow","ShotOps / fastlane"),r("h2","sf-title","Your fastlane bundle is ready"),r("p","sf-sub",t.length>1?`${s} screenshots across ${t.length} locales, laid out the way fastlane deliver expects.`:"Laid out the way fastlane deliver expects \u2014 download it and upload with your own key."));let k=r("span","sf-badge");k.append(r("span","sf-dot"),document.createTextNode(n.output==="urls"?"Download link":"Inline zip")),c.append(v,k),p.append(c);let x=r("div","sf-body"),u=S(n),m=r("div","sf-zip");m.append(r("div","sf-zip-icon","ZIP"));let h=r("div","sf-zip-text");h.append(r("div","sf-zip-name",n.filename??"fastlane-bundle.zip"));let w=u?.size?` \xB7 ${u.size}`:"";h.append(r("div","sf-zip-sub",s>0?`${s} screenshot${s===1?"":"s"}${w}`:`Bundle${w}`)),m.append(h),u&&m.append(q(u,n.filename??"fastlane-bundle.zip")),x.append(m);let l=r("div","sf-inside");if(l.append(r("p","sf-inside-k","What's inside")),l.append(r("pre","sf-tree",N(t))),x.append(l),n.shareLink?.url){let f=r("div","sf-share"),b=r("div","sf-share-text");b.append(document.createTextNode("Share link")),b.append(r("div","sf-share-sub",$(n.shareLink.expiresAt))),f.append(b,M("Open \u2197",n.shareLink.url,"sf-open")),x.append(f)}p.append(x);let a=r("footer","sf-meta");if(n.bundleId&&g(a,"Bundle ID",n.bundleId),t.length>0&&g(a,t.length===1?"Locale":"Locales",t.join(", ")),Array.isArray(n.outputs)&&n.outputs.length>0&&g(a,"Devices",n.outputs.join(", ")),i>0&&t.length>1&&g(a,"Per locale",String(i)),n.openUrl){let f=r("div","sf-actions");f.append(M("Open in ShotOps \u2197",n.openUrl,"sf-open")),a.append(f)}a.childElementCount>0&&p.append(a);let E=[n.note,n.projectNote].filter(Boolean).join(" ");E&&p.append(r("p","sf-note",E)),p.append(r("p","sf-custody",Y)),e.append(p),window.openai?.notifyIntrinsicHeight?.()}I({css:H,rootId:"shotops-bundle",loading:"Preparing your fastlane bundle\u2026",empty:"No ShotOps bundle result is available.",terminal:"The bundle finished, but ChatGPT did not deliver its result. Refresh ShotOps and try again.",accept:e=>!!(T(e)||S(e)),render:G});})();
|
package/widget-dist/panels.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";(()=>{var
|
|
1
|
+
"use strict";(()=>{var k="shotops/widgetPayload";var _=`
|
|
2
2
|
:root {
|
|
3
3
|
color-scheme: light dark;
|
|
4
4
|
--sf-ink: #15151a;
|
|
@@ -124,7 +124,7 @@ button, a { font: inherit; }
|
|
|
124
124
|
@media (prefers-reduced-motion: reduce) {
|
|
125
125
|
.sf-download, .sf-open { transition: none; }
|
|
126
126
|
}
|
|
127
|
-
`;function
|
|
127
|
+
`;function o(t,e,r){let n=document.createElement(t);return e&&(n.className=e),r!==void 0&&(n.textContent=r),n}function h(t,e,r){let n=o("div","sf-stat");n.append(o("div","sf-k",e),o("div","sf-v",r)),t.append(n)}async function M(t){if(window.openai?.openExternal){await window.openai.openExternal({href:t});return}window.open(t,"_blank","noopener,noreferrer")}function O(t,e,r,n){let i=e;try{let p=new URL(e);/\/storage\/v1\/object\/sign\//.test(p.pathname)&&(p.searchParams.set("download",r),i=p.toString())}catch{}let s=o("a",n,t);return s.href=i,s.download=r,s.rel="noopener noreferrer",/^https?:/i.test(e)&&(s.target="_blank",s.addEventListener("click",p=>{window.openai?.openExternal&&(p.preventDefault(),M(i))})),s}function P(t,e,r){let n=o("button",r,t);return n.type="button",n.addEventListener("click",()=>{M(e)}),n}function u(t){return t&&typeof t=="object"&&!Array.isArray(t)?t:null}function C(t){if(!Array.isArray(t.content))return null;let e=[];for(let r of t.content){let n=u(r);if(!n)continue;if(n.type==="image"&&typeof n.data=="string"&&n.mimeType==="image/png"){e.push(n.data);continue}if(n.type==="resource_link"&&typeof n.uri=="string"&&n.mimeType==="image/png"){e.push({url:n.uri});continue}let i=u(n.resource);n.type==="resource"&&i&&typeof i.uri=="string"&&i.mimeType==="image/png"&&e.push({url:i.uri})}if(e.length>0)return{ok:!0,count:e.length,output:typeof e[0]=="string"?"inline":"urls",panels:e};if(t.isError===!0){let r=t.content.map(n=>u(n)).find(n=>n?.type==="text"&&typeof n.text=="string")?.text;return{ok:!1,...typeof r=="string"?{note:r}:{}}}return null}function E(t,e=0){let r=u(t);if(!r||e>6)return null;let n=u(r[k]);if(n)return n;let i=u(r._meta),s=u(i?.[k]);if(s)return s;for(let p of["mcp_tool_result","call_tool_result","tool_result","result"]){let g=E(r[p],e+1);if(g)return g}return null}function S(t,e=!0,r=0){let n=u(t);if(!n||r>6)return e?t:null;for(let s of["structuredContent","structured_content"]){let p=u(n[s]);if(p)return p}for(let s of["mcp_tool_result","call_tool_result","tool_result","result"]){if(n[s]===void 0)continue;let p=S(n[s],!1,r+1);if(p)return p}let i=C(n);return i||(e?t:null)}function T(t,e=0){let r=u(t);if(!r||e>6)return null;let n=typeof r.status=="string"?r.status.toLowerCase():"";if(["failed","failure","error","cancelled","canceled"].includes(n))return"failure";if(["complete","completed","success","succeeded"].includes(n))return"success";for(let i of["mcp_tool_result","call_tool_result","tool_result","result"]){let s=T(r[i],e+1);if(s)return s}return null}function I(t){let e=u(t.detail);return u(e?.globals)}function H(t){return E(t)??S(t,!1)}function W(t){if(!t||typeof t!="object")return t;let e=t;return e.structuredContent&&typeof e.structuredContent=="object"?e.structuredContent:S(t)}function A(t){let e=document.createElement("style");e.textContent=t.css;let r=o("div","sf-root");r.id=t.rootId,r.append(o("div","sf-empty",t.loading)),document.body.append(e,r);let n=!1,i=l=>{let a=W(l);!a||typeof a!="object"||t.accept&&!t.accept(a)||(n=!0,t.render(r,a))},s=l=>i(H(l));window.addEventListener("message",l=>{if(l.source!==window.parent)return;let a=l.data;!a||a.jsonrpc!=="2.0"||a.method!=="ui/notifications/tool-result"||(i(a.params?.structuredContent),n||s(a.params))},{passive:!0}),window.addEventListener("openai:set_globals",l=>{let a=I(l);a&&(i(a.toolOutput),n||s(a.toolResponseMetadata))},{passive:!0});let p=100,g=500,w=2e3,m=5*6e4,y=2e3,d=0,x=null,c=!1,f=()=>{if(i(window.openai?.toolOutput),n||s(window.openai?.toolResponseMetadata),n)return;let l=T(window.openai?.toolResponseMetadata);if(l&&x===null&&(x=d),l&&!c&&(l==="failure"||d-(x??d)>=y)&&(c=!0,r.replaceChildren(o("div","sf-empty",t.terminal??t.empty))),d>=m){c||r.replaceChildren(o("div","sf-empty",t.terminal??t.empty));return}let a=d<w?p:g;d+=a,setTimeout(f,a)};f()}function R(t){if(!t.operationId||!t.status)return null;let e=Math.max(0,Number(t.progress?.completed??0)),r=Math.max(e,Number(t.progress?.total??0)),n={accepted:["Production accepted","ShotOps is preparing the durable render.","Accepted",!1],queued:["Production queued","The render is safely queued and can outlive this conversation.","Queued",!1],running:["Production rendering","ShotOps is rendering and checkpointing the final assets.","Running",!1],cancel_requested:["Cancellation requested","Work already in flight will stop at the next safe checkpoint.","Cancelling",!1],failed:["Production could not finish","The operation stopped without returning a partial asset set.","Failed",!0],cancelled:["Production cancelled","Unfinished work stopped and the remaining reservation was released.","Cancelled",!0],succeeded:["Production finished","The durable operation succeeded; request its result for fresh download links.","Succeeded",!0]},[i,s,p,g]=n[t.status];return{title:i,detail:s,badge:p,terminal:g,completed:e,total:r}}var j=`${_}
|
|
128
128
|
.sf-rail {
|
|
129
129
|
display: grid;
|
|
130
130
|
grid-auto-flow: column;
|
|
@@ -185,4 +185,4 @@ button, a { font: inherit; }
|
|
|
185
185
|
@media (max-width: 440px) {
|
|
186
186
|
.sf-rail { padding-inline: 14px; grid-auto-columns: min(64vw, 190px); }
|
|
187
187
|
}
|
|
188
|
-
`;function
|
|
188
|
+
`;function L(t){if(typeof t=="string"){let e=t.startsWith("data:")?t:`data:image/png;base64,${t}`;return{src:e,href:e}}return typeof t?.url=="string"&&t.url.length>0?{src:t.url,href:t.url}:null}function N(t,e){return O("Download PNG",t,`shotops-panel-${String(e+1).padStart(2,"0")}.png`,"sf-download")}function $(t,e){t.replaceChildren();let r=R(e);if(r&&(!Array.isArray(e.panels)||e.panels.length===0)){let d=o("section","sf-shell"),x=o("header","sf-head"),c=o("div");c.append(o("p","sf-eyebrow","ShotOps / durable production"),o("h2","sf-title",r.title),o("p","sf-sub",r.detail));let f=o("span","sf-badge");f.append(o("span","sf-dot"),document.createTextNode(r.badge)),x.append(c,f),d.append(x);let l=o("footer","sf-meta");h(l,"Progress",r.total>0?`${r.completed}/${r.total}`:"Waiting"),typeof e.progress?.attempt=="number"&&h(l,"Attempt",String(e.progress.attempt)),typeof e.contract?.cost?.reserved=="number"&&h(l,"Reserved",String(e.contract.cost.reserved)),typeof e.contract?.cost?.released=="number"&&h(l,"Released",String(e.contract.cost.released)),d.append(l,o("p","sf-note",`Operation ${e.operationId}. Reconnect with production_operation.`)),t.append(d),window.openai?.notifyIntrinsicHeight?.();return}let n=o("section","sf-shell"),i=o("header","sf-head"),s=o("div"),p=Array.isArray(e.panels)?e.panels:[],g=typeof e.count=="number"?e.count:p.length;s.append(o("p","sf-eyebrow","ShotOps / App Store"),o("h2","sf-title",g===1?"Your panel is ready":`Your ${g}-panel strip is ready`),o("p","sf-sub","Swipe through the final panels, then open or download each PNG."));let w=o("span","sf-badge");if(w.append(o("span","sf-dot"),document.createTextNode(e.output==="urls"?"Full-size links":"Inline result")),i.append(s,w),n.append(i),p.length>0){let d=o("div","sf-rail");e.panelWidth&&e.panelHeight&&d.style.setProperty("--sf-ratio",`${e.panelWidth} / ${e.panelHeight}`),p.forEach((x,c)=>{let f=L(x),l=o("article","sf-panel"),a=o("div","sf-frame");if(a.append(o("span","sf-index",String(c+1).padStart(2,"0"))),f){let b=o("img");b.src=f.src,b.alt=`Rendered App Store panel ${c+1} of ${p.length}`,b.loading=c===0?"eager":"lazy",b.addEventListener("error",()=>a.classList.add("is-error")),a.append(b)}else a.classList.add("is-error");a.append(o("div","sf-expired","Preview unavailable. Ask ShotOps to render this panel again."));let v=o("div","sf-panel-foot");v.append(o("span","sf-panel-name",`Panel ${String(c+1).padStart(2,"0")}`)),f&&v.append(N(f.href,c)),l.append(a,v),d.append(l)}),n.append(d)}else n.append(o("div","sf-empty","The render completed, but no panel previews were returned."));let m=o("footer","sf-meta");if(e.panelWidth&&e.panelHeight&&h(m,"Canvas",`${e.panelWidth}\xD7${e.panelHeight}`),e.panelPresetId&&h(m,"Preset",e.panelPresetId),e.locale&&h(m,"Locale",e.locale),typeof e.renderMs=="number"&&h(m,"Render",`${(e.renderMs/1e3).toFixed(1)}s`),e.openUrl){let d=o("div","sf-actions");d.append(P("Open in ShotOps \u2197",e.openUrl,"sf-open")),m.append(d)}m.childElementCount>0&&n.append(m);let y=[e.note,e.projectNote].filter(Boolean).join(" ");y&&n.append(o("p","sf-note",y)),t.append(n),window.openai?.notifyIntrinsicHeight?.()}function F(t){if(typeof t.operationId=="string"&&typeof t.status=="string"||t.ok===!1)return!0;if(t.ok!==!0)return!1;let e=Array.isArray(t.panels)?t.panels:[];return(typeof t.count=="number"?t.count:e.length)===0||e.length>0&&e.every(n=>L(n)!==null)}A({css:j,rootId:"shotops-result",loading:"Loading ShotOps panels\u2026",empty:"No ShotOps render result is available.",terminal:"The render finished, but ChatGPT did not deliver its panel data. Refresh ShotOps and try again.",accept:F,render:$});})();
|