← Files ShopifyARCHIVED FILE

skills/shopify-dev/scripts/log_feedback.mjs

10.1 KB · Sep 30, 2026 · 23:18 UTC

↓ Download file

#!/usr/bin/env node
var ce=Object.defineProperty;var n=(e,t)=>ce(e,"name",{value:t,configurable:!0});import{createHash as ve}from"crypto";import{chmodSync as ye,closeSync as Te,lstatSync as Ne,mkdirSync as Re,openSync as be,readdirSync as De,rmSync as Ce,statSync as Ae}from"fs";import{tmpdir as xe}from"os";import{join as D}from"path";import{parseArgs as Le}from"util";var T="assistant-first-turn-complete",N=["up","down","mixed"],p=["worked","partial","failed","not_used"];function g(e){return typeof e=="string"&&e.length>0?e:void 0}n(g,"nonEmpty");function _(){let e=[process.env.CLAUDE_SESSION_ID,process.env.CLAUDE_CODE_SESSION_ID,process.env.CURSOR_SESSION_ID,process.env.COPILOT_SESSION_ID];for(let t of e)if(typeof t=="string"&&t.length>0)return t}n(_,"readHostSessionId");function L(e){let t=n(a=>`${a}:${e.trigger}:1`,"key"),r=g(e.sessionId);if(r)return{feedbackId:t(r),feedbackIdSource:"session"};let s=g(e.conversationId);if(s)return{feedbackId:t(s),feedbackIdSource:"conversation"};let o=g(e.toolUseId);if(o)return{feedbackId:t(o),feedbackIdSource:"tool-use"};let i=g(e.fallbackId);if(i)return{feedbackId:t(i),feedbackIdSource:"random"}}n(L,"deriveFeedbackId");import{readFileSync as de,statSync as pe}from"node:fs";import{homedir as ue}from"node:os";import{join as f}from"node:path";var E="shopify-ai-toolkit",h="opt-out",fe="SHOPIFY_AI_TOOLKIT_OPT_OUT_FILE",le=new Set(["false","0","no","off"]);function P(e){return{env:e?.env??process.env,platform:e?.platform??process.platform,homeDir:e&&"homeDir"in e?e.homeDir:me(e?.env??process.env)}}n(P,"resolveContext");function me(e){let t=e.HOME?.trim()||e.USERPROFILE?.trim();if(t)return t;try{return ue()||void 0}catch{return}}n(me,"resolveHomeDir");function ge(e){let{env:t,platform:r,homeDir:s}=P(e),o=[],i=t[fe]?.trim();i&&o.push(i);let a=t.XDG_CONFIG_HOME?.trim();if(a&&o.push(f(a,E,h)),s&&(o.push(f(s,".config",E,h)),r==="darwin"&&o.push(f(s,"Library","Application Support",E,h))),r==="win32"){let d=t.APPDATA?.trim()||(s?f(s,"AppData","Roaming"):void 0);d&&o.push(f(d,E,h))}return[...new Set(o.filter(d=>!!d))]}n(ge,"telemetryOptOutFileCandidates");function _e(e){if(e.OPT_OUT_INSTRUMENTATION?.trim().toLowerCase()==="true")return!0;let t=e.DO_NOT_TRACK?.trim().toLowerCase();return t==="1"||t==="true"}n(_e,"envSaysOptOut");function Ee(e){try{if(!pe(e).isFile())return!1}catch{return!1}try{let t=de(e,"utf8").trim().toLowerCase();return!le.has(t)}catch{return!0}}n(Ee,"fileSaysOptOut");function I(e){try{let t=P(e);return _e(t.env)?!0:ge(t).some(Ee)}catch{return!1}}n(I,"isTelemetryOptedOut");function k(e){return Object.fromEntries(Object.entries(e).map(([t,r])=>{let{description:s,valueName:o,choices:i,...a}=r;return[t,a]}))}n(k,"toParseArgsOptions");var R={model:{type:"string",valueName:"name",description:"Agent model name"},"client-name":{type:"string",valueName:"name",description:"Agent client name"},"client-version":{type:"string",valueName:"version",description:"Agent client version"}},S={"user-prompt-base64":{type:"string",valueName:"base64",description:"Base64-encoded triggering prompt"},"session-id":{type:"string",valueName:"id",description:"Agent session identifier"},"tool-use-id":{type:"string",valueName:"id",description:"Agent tool-use identifier"}},Je={"artifact-id":{type:"string",valueName:"id",description:"Stable artifact identifier"},revision:{type:"string",valueName:"number",description:"Positive artifact revision"},...R,...S,json:{type:"boolean",description:"Emit machine-readable JSON"}},U={help:{type:"boolean",short:"h",description:"Show this help"}};function V(e,t){let r=Object.entries(t).map(([o,i])=>{let a=i.type==="string"?i.valueName||i.choices?.join("|")||"value":void 0,d=`--${o}${a?` <${a}>`:""}`;return[i.short?`-${i.short}, ${d}`:d,i.description]}),s=Math.max(...r.map(([o])=>o.length));return["Usage:",...e.map(o=>`  ${o}`),"","Options:",...r.map(([o,i])=>`  ${o.padEnd(s)}  ${i}`)].join(`
`)}n(V,"formatCliHelp");var he="https://shopify.dev/",Ie="https://shopify-dev.shop.dev/";function F(e){return`https://shopify-dev-staging${e}.shopifycloud.com/`}n(F,"stagingHost");function b(e){let t=e?.env??process.env,r=t.SHOPIFY_DEV_STAGING_SERVER_NUMBER?.trim();if(r){if(!/^\d+$/.test(r))throw new Error(`SHOPIFY_DEV_STAGING_SERVER_NUMBER must be a positive integer; got: "${r}"`);let o=Number(r);if(!Number.isSafeInteger(o)||o<=0)throw new Error(`SHOPIFY_DEV_STAGING_SERVER_NUMBER must be a positive integer; got: "${r}"`);let i=t.MINERVA_TOKEN;if(!i){let a=F(o).replace(/\/$/,"");throw new Error(`SHOPIFY_DEV_STAGING_SERVER_NUMBER=${o} is set but no Minerva token is available. Staging servers are behind Minerva. Get a token via:
  export MINERVA_TOKEN=$(devx minerva-auth --client-id 0oa1bphetnkOusboI0x8 --audience ${a})`)}return{url:F(o),headers:{Cookie:`MINERVA_TOKEN=${i}`}}}let s=t.SHOPIFY_DEV_INSTRUMENTATION_URL?.trim();return s&&e?.uri?.startsWith("/mcp/usage")?{url:s,headers:{}}:t.DEV&&t.DEV!=="false"?{url:Ie,headers:{}}:{url:he,headers:{}}}n(b,"resolveShopifyDevBaseUrl");async function M(e,t){let r,s={};if(e.startsWith("http://")||e.startsWith("https://"))r=new URL(e);else{let i=b({uri:e});r=new URL(e,i.url),s=i.headers}t?.parameters&&Object.entries(t.parameters).forEach(([i,a])=>{r.searchParams.append(i,a)});let o=await fetch(r.toString(),{method:t?.method||"GET",headers:{Accept:"application/json","Cache-Control":"no-cache","X-Shopify-Surface":"mcp","X-Shopify-MCP-Version":t?.instrumentation?.packageVersion||"","X-Shopify-Timestamp":t?.instrumentation?.timestamp||"",...s,...t?.headers},...t?.body&&{body:t.body}});if(!o.ok){let i;try{i=await o.text()}catch{}throw new Error(i?`HTTP ${o.status}: ${i}`:`HTTP error! status: ${o.status}`)}return await o.text()}n(M,"shopifyDevFetch");function w(e){return{...e?.api&&{api:e.api},...e?.api_version&&{api_version:e.api_version},...e?.resolve_api_version&&{resolve_api_version:e.resolve_api_version}}}n(w,"nonEmptyUsageMetadata");function Se(){return I()}n(Se,"isInstrumentationDisabled");function $(e){if(!(typeof e!="string"||e.length===0))try{let t=Buffer.from(e,"base64").toString("utf8");return t.length>0?t:void 0}catch{return}}n($,"decodeUserPrompt");async function H(e,t,r,s){if(Se())return;let{model:o,clientName:i,clientVersion:a,user_prompt:d,sessionId:m,toolUseId:y,...ne}=r??{},C=typeof m=="string"&&m.length>0?m:_(),A=typeof d=="string"&&d.length>0?d.slice(0,2e3):void 0;try{let u={"Content-Type":"application/json","X-Shopify-Surface":"skills"};i&&(u["X-Shopify-Client-Name"]=String(i)),a&&(u["X-Shopify-Client-Version"]=String(a)),o&&(u["X-Shopify-Client-Model"]=String(o));let x=JSON.stringify({tool:e,parameters:{skill:"shopify-dev",skillVersion:"1.14.1",...A!==void 0&&{user_prompt:A},...C!==void 0&&{sessionId:C},...typeof y=="string"&&y.length>0&&{toolUseId:y},...ne},result:t,...w(s)});if(process.env.SKILL_TELEMETRY_TEST_MODE==="1"){let{url:oe}=b({uri:"/mcp/usage"}),ie=new URL("/mcp/usage",oe).toString();process.stderr.write([`[TEST_TELEMETRY_ENDPOINT] ${ie}`,...Object.entries(u).map(([se,ae])=>`[TEST_TELEMETRY_HEADER] ${se}: ${ae}`),`[TEST_TELEMETRY_BODY] ${x}`,""].join(`
`));return}await M("/mcp/usage",{method:"POST",headers:u,body:x,instrumentation:{packageVersion:"1.14.1",timestamp:new Date().toISOString()}})}catch{}}n(H,"reportValidation");var G=".feedback",Pe=1440*60*1e3;function ke(){let e=process.getuid?.()??0;return D(xe(),`shopify-ai-toolkit-telemetry-${e}`)}n(ke,"markerDir");function Ue(e,t){let r=ve("sha256").update(t).digest("hex").slice(0,32);return D(e,`${r}${G}`)}n(Ue,"markerPath");function Ve(e){try{let t=Date.now()-Pe;for(let r of De(e)){if(!r.endsWith(G))continue;let s=D(e,r);try{Ae(s).mtimeMs<t&&Ce(s,{force:!0})}catch{}}}catch{}}n(Ve,"pruneStaleMarkers");function Fe(e){let t;try{t=ke(),Re(t,{recursive:!0,mode:448});let r=Ne(t),s=process.getuid?.();if(r.isSymbolicLink()||!r.isDirectory()||s!==void 0&&r.uid!==s)return!0;try{ye(t,448)}catch{return!0}Ve(t)}catch{return!0}try{return Te(be(Ue(t,e),"wx",384)),!0}catch(r){return r?.code!=="EEXIST"}}n(Fe,"claimOnceMarker");function l(e,t){return e.includes(t)?t:void 0}n(l,"parseEnum");function j(e){return typeof e=="string"&&e.length>0?e:void 0}n(j,"nonEmptyFlag");function O(e){return{type:"string",choices:p,description:e}}n(O,"verdictOption");var Y={overall:{type:"string",choices:N,description:"Overall toolkit verdict for this turn"},"docs-context":O("Verdict for docs/search context"),"schema-validation":O("Verdict for schema/code validation"),"api-version":O("Verdict for API version targeting"),codegen:O("Verdict for generated code"),"comment-base64":{type:"string",valueName:"base64",description:`Base64-encoded rationale, decoded and truncated to ${500} chars (base64 keeps arbitrary text inert in the shell)`},"session-id":S["session-id"],"tool-use-id":S["tool-use-id"],...R,...U},Me=[V(["scripts/log_feedback.mjs --overall <up|down|mixed> --docs-context <verdict>","  --schema-validation <verdict> --api-version <verdict> --codegen <verdict>","  --comment-base64 <base64> [--session-id <id>] [--tool-use-id <id>]","  [--model <name>] [--client-name <name>] [--client-version <version>]"],Y),"","Each <verdict> is one of: worked | partial | failed | not_used.","Run once per turn. Without a session id or tool-use id there is no dedupe","key, so nothing is sent."].join(`
`);function X(){console.error("Usage: scripts/log_feedback.mjs --overall <up|down|mixed> --docs-context <verdict> --schema-validation <verdict> --api-version <verdict> --codegen <verdict> --comment-base64 <base64> [options] (run with --help for details)"),process.exit(1)}n(X,"exitWithUsageHint");var J=(()=>{try{return Le({options:k(Y),allowPositionals:!0})}catch{return}})();J||X();var{values:c}=J;c.help&&(console.log(Me),process.exit(0));I()&&process.exit(0);var W=l(N,c.overall),z=l(p,c["docs-context"]),q=l(p,c["schema-validation"]),Q=l(p,c["api-version"]),Z=l(p,c.codegen),B=c["comment-base64"],we=B===""?"":$(B),ee=we?.slice(0,500);(!W||!z||!q||!Q||!Z||ee===void 0)&&X();var te=j(c["session-id"])??_(),re=j(c["tool-use-id"]),v=L({trigger:T,sessionId:te,toolUseId:re});v&&Fe(v.feedbackId)&&await H("feedback","ok",{model:c.model,clientName:c["client-name"],clientVersion:c["client-version"],sessionId:te,toolUseId:re,feedbackVersion:1,feedbackId:v.feedbackId,feedbackIdSource:v.feedbackIdSource,trigger:T,overall:W,docsContext:z,schemaValidation:q,apiVersion:Q,codegen:Z,comment:ee});process.exit(0);

SHA-256: 93364b82c70fc1daf385ecd077ab38ae1ef22bc0383f53126e5f2b9149737344