@crewx/app 0.1.0-rc.63 → 0.1.0-rc.64

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/SKILL.md CHANGED
@@ -28,6 +28,20 @@ metadata:
28
28
 
29
29
  `crewx app usage <appId>` prints the App's manual, then a table of every action: its inputs (`*` = required, real types, limits, allowed values), the agent access (`allowed`, `approval_required`, `denied`, the same words `crewx app state` prints) and the confirmation mode. Send exactly the keys listed. After a successful `crewx app run`, stderr suggests `→ Check: crewx app state <instanceId>`.
30
30
 
31
+ ## Open a captured image before describing marks
32
+
33
+ For the read-only `captureFeedback` action, send exactly `documentId`, `viewRef`, and `expectedAnnotationRevision`; use `--request-id` for the retry identity. A delivered image appears in `crewx app run` or `crewx app receipt` as a validated local PNG path, dimensions, byte count, and SHA-256. The image ref is replaced by that local path. The PNG is stored under `<cwd>/.crewx/app-captures/`; owned files older than 24 hours are pruned when another image is materialized. The cache holds at most 32 owned artifacts; a new artifact fails with `IMAGE_WRITE_FAILED` while 32 recent artifacts remain.
34
+
35
+ The capture folder's `.gitignore` must keep its generated contents (`*` followed by `!.gitignore`). If it is edited or replaced, image materialization fails with `IMAGE_WRITE_FAILED`; restore that file before retrying. The CLI never changes the workspace's `.gitignore` and never prunes unrelated files.
36
+
37
+ The pixels are not yet in model context. Open the exact printed path with the provider's image-reading tool before describing a marked target. If the provider has no image-reading tool, report that limitation; do not infer pixels from the path, counts, or note text, and do not claim an OCR fallback.
38
+
39
+ `crewx app state <instanceId>` may include a separate top-level `feedback` field for the task-bound Viewer. Its optional `summary` describes the loaded document and its `modelRevision`; it is not saved App state and it does not provide a replacement `viewRef`. Counts are last-known and updates may be coalesced for up to 750 ms. Do not decline a relevant user request solely because an older summary reports zero marks.
40
+
41
+ After a known `STALE` result, refresh with `crewx app state <instanceId>`, keep the same `viewRef` from the task prompt, and use `documentId` and `modelRevision` from the loaded `feedback.summary` rather than the saved document selection. Retry with a new `--request-id`. If the action outcome is unknown, recover the same receipt with `crewx app receipt <receiptId>`; do not rerun the capture. A receipt carrying the server-owned `viewCall: true` marker fails with exit 4 and an `IMAGE_*` code when its result expired or its top-level image descriptor is missing, while preserving the receipt and result text. Plain actions keep their existing behavior even if they share the name `captureFeedback`. If the output has no `image` field, no pixels were delivered; older servers may not expose the image result.
42
+
43
+ `IMAGE_EXPIRED` cannot be recovered from the same receipt; if the image is still needed, refresh state and send a new request ID for the same prompt-bound view using the loaded summary's `documentId` and `modelRevision`. If that view or its summary is unavailable, report that and do not substitute another view. The CLI never starts a new capture automatically.
44
+
31
45
  ## Build a `@Tool` App
32
46
 
33
47
  `crewx app build` needs nothing but the CrewX CLI: it ships the bundler and the SDK that `server.ts` imports as `@crewx/sdk/app`. Run it in the App folder (or pass the folder). The folder needs `server.ts` (default-exports a `CrewXApp` subclass) and a `package.json`; `manifest.json` is created when missing.
@@ -1,7 +1,8 @@
1
- "use strict";var xe=exports&&exports.__createBinding||(Object.create?(function(e,t,n,r){if(r===void 0)r=n;var o=Object.getOwnPropertyDescriptor(t,n);if(!o||("get"in o?!t.__esModule:o.writable||o.configurable)){o={enumerable:true,get:function(){return t[n]}}}Object.defineProperty(e,r,o)}):(function(e,t,n,r){if(r===void 0)r=n;e[r]=t[n]}));var Ne=exports&&exports.__setModuleDefault||(Object.create?(function(e,t){Object.defineProperty(e,"default",{enumerable:true,value:t})}):function(e,t){e["default"]=t});var j=exports&&exports.__importStar||(function(){var e=function(t){e=Object.getOwnPropertyNames||function(n){var r=[];for(var o in n)if(Object.prototype.hasOwnProperty.call(n,o))r[r.length]=o;return r};return e(t)};return function(t){if(t&&t.__esModule)return t;var n={};if(t!=null){for(var r=e(t),o=0;o<r.length;o++)if(r[o]!=="default")xe(n,t,r[o])}Ne(n,t);return n}})();Object.defineProperty(exports,"__esModule",{value:true});exports.executeAppCommand=bt;const ie=require("node:crypto");const ae=require("node:child_process");const v=j(require("node:fs"));const je=j(require("node:http"));const $e=j(require("node:https"));const h=j(require("node:path"));const ue=require("node:url");const z=require("@crewx/shared/crewx-api-credential");const b=require("./receipt-wait.js");const C=require("./usage.js");const x=15e3;const Q=3e4;const Le=6e4;const ce=64*1024;const le="uic_";const Ue="/api/v1";const qe="/api/v1/app-dev/capabilities";const Me="/api/v1/app-dev/sessions";const Be=12;const Fe=13;const We=/^[A-Za-z0-9_-]{8,128}$/;const Ge=new Set(["127.0.0.1","[::1]","localhost"]);const Ve="http://localhost:8150";const Je="Do not work around this by clicking the screen or using another browser. Report that you could not use the App route.";const He="Do not retry. Report the failure.";const Xe="The server did not answer in time. Retry once; if it happens again, report it.";function l(e){return e!==null&&typeof e==="object"&&!Array.isArray(e)}function p(e,t,n,r){let o=r;if(!o&&(e===3||e===9||e===10||e===11)){o=Je}else if(!o&&e===4){o=He}return{exitCode:e,payload:{ok:false,exit:e,error:{code:t,status:n}},...o?{stderr:o}:{}}}function P(e){return{exitCode:0,payload:e}}function $(){return p(2,"USAGE",null)}function pe(e){const t=e[0];if(t!=="list"&&t!=="open"&&t!=="state"&&t!=="run"&&t!=="receipt"){return null}const n=[];const r=new Map;for(let a=1;a<e.length;a+=1){const u=e[a];if(!u.startsWith("--")){n.push(u);continue}const c=u.indexOf("=");const d=c>=0?u.slice(2,c):u.slice(2);const f=c>=0?u.slice(c+1):void 0;if(d!=="input"&&d!=="request-id"&&d!=="wait"||r.has(d))return null;const y=f??e[a+1];if(y===void 0)return null;if(f===void 0)a+=1;r.set(d,y)}if(t==="list"&&n.length!==0||t==="open"&&n.length!==1||t==="state"&&(n.length!==1||!n[0].startsWith(le))||t==="run"&&n.length!==2||t==="receipt"&&n.length!==1){return null}if(t!=="run"&&(r.has("input")||r.has("request-id")))return null;if(t!=="receipt"&&r.has("wait"))return null;let o={};if(r.has("input")){const a=r.get("input");try{const u=JSON.parse(a==="-"?v.readFileSync(0,"utf8"):a);if(!l(u))return null;o=u}catch{return null}}const i=r.get("request-id");if(i!==void 0&&!We.test(i))return null;const s=r.has("wait")?(0,b.parseWaitSeconds)(r.get("wait")):void 0;if(s===null)return null;return{command:t,positional:n,input:o,...i!==void 0?{requestId:i}:{},...s!==void 0?{waitSeconds:s}:{}}}function Y(e){if(!e)return null;let t;try{t=new ue.URL(e)}catch{return null}if(!Ge.has(t.hostname)||t.protocol!=="http:"&&t.protocol!=="https:"||t.username!==""||t.password!==""||t.search!==""||t.hash!==""||t.pathname!==""&&t.pathname!=="/"){return null}return t}function F(e){return encodeURIComponent(e)}function Ke(e,t){return["api","v1","ws",F(e),"threads",F(t)].join("/")}function L(e,...t){return`/${e.basePath}/${t.map(F).join("/")}`}function k(e,t){if(!l(e)||!l(e["error"]))return t;const n=e["error"]["code"];return typeof n==="string"&&n.length>0?n:t}function W(e){const{status:t,data:n}=e;if(t>=300&&t<400)return p(9,"ENDPOINT_REJECTED",t);if(t===401)return p(4,k(n,"UNAUTHORIZED"),t);if(t===403)return p(5,k(n,"FORBIDDEN"),t);if(t===404)return p(6,k(n,"NOT_FOUND"),t);if(t===409){const r=k(n,"CONFLICT");if(r==="APPROVAL_ALREADY_PENDING"){const o=l(n)&&l(n["error"])?n["error"]:void 0;const i=o&&l(o["details"])?o["details"]:void 0;const s=o?.["receiptId"]??i?.["receiptId"]??(l(n)?n["receiptId"]:void 0);return{exitCode:8,payload:{ok:false,exit:8,error:{code:r,status:t},...typeof s==="string"?{receiptId:s}:{}}}}return p(7,r,t)}return p(1,k(n,"ERROR"),t)}function U(e,t=true){const n=l(e)&&typeof e["code"]==="string"?e["code"]:"";const r=process.env["CODEX_SANDBOX_NETWORK_DISABLED"]==="1";const o=!r&&(n==="EPERM"||n==="EACCES");if(r||o)return p(11,"SANDBOX_BLOCKED",null);if(t&&n==="ETIMEDOUT"&&l(e)&&e["connectionEstablished"]===true){return p(14,"TIMED_OUT",null,Xe)}return p(10,"SERVER_UNREACHABLE",null)}function Z(e,t){if(e.exitCode!==14)return e;return{...e,payload:{...e.payload,requestId:t},stderr:["The request timed out and its outcome is unknown.",`Retry the same command once with --request-id ${t}; the server will return the same request's receipt without running the action twice.`,`If it times out again, report "server response delayed, outcome unknown" with requestId ${t}.`,"Do not report success or failure, click the screen, or use another route."].join("\n")}}function q(e,t,n,r,o,i=x){const s=e.protocol==="https:"?$e.request:je.request;const a=e.hostname==="[::1]"?"::1":e.hostname;const u=e.port?Number(e.port):void 0;const c=o===void 0?void 0:JSON.stringify(o);const d=s({protocol:e.protocol,hostname:a,...u!==void 0?{port:u}:{},method:n,path:r,headers:{Authorization:`Bearer ${t}`,Accept:"application/json",...c!==void 0?{"Content-Type":"application/json"}:{}}},m=>{const w=m.statusCode??0;if(w>=300&&w<400){m.destroy();clearTimeout(N);_({status:w,data:void 0,invalidJson:false,rawText:""});return}const A=[];m.setEncoding("utf8");m.on("data",O=>A.push(O));m.once("error",O=>I(O));m.once("end",()=>{clearTimeout(N);const O=A.join("");try{_({status:w,data:JSON.parse(O),invalidJson:false,rawText:O})}catch{_({status:w,data:void 0,invalidJson:true,rawText:O})}})});let f;let y=false;let _;let I;const S=new Promise((m,w)=>{_=m;I=w});const N=setTimeout(()=>{const m=new Error("Request timed out");m.code="ETIMEDOUT";m.connectionEstablished=y;d.destroy(m)},i);d.on("socket",m=>{const w=()=>{y=true};if(e.protocol==="https:"){const A=m;if(A.authorized)w();else A.once("secureConnect",w)}else{if(m.connecting)m.once("connect",w);else w()}m.once("error",A=>{f=A})});d.once("error",m=>{clearTimeout(N);I(f??m)});if(c!==void 0)d.write(c);d.end();return S}async function M(e,t,n,r,o=x){try{const i=await q(e.endpoint,e.ticket,t,n,r,o);if(i.status<200||i.status>=300){return{ok:false,outcome:W(i)}}if(i.invalidJson||!l(i.data)||i.data["success"]!==true){return{ok:false,outcome:p(1,k(i.data,"ERROR"),i.status)}}const s=i.data["data"];if(!l(s)){return{ok:false,outcome:p(1,"ERROR",i.status)}}return{ok:true,value:s,status:i.status}}catch(i){return{ok:false,outcome:U(i)}}}function de(e){return p(Be,"SERVER_TOO_OLD",e,"The running CrewX does not support App dev mode.")}function fe(e){if(e instanceof z.CrewxCredentialError){return p(e.exitCode,e.code,null,e.message)}return p(1,"ERROR",null)}function ze(){const e=process.env["CREWX_ENDPOINT"]?.trim()||Ve;return Y(e)}function G(e){try{return v.statSync(e).isDirectory()}catch{return false}}function ee(e){try{return v.statSync(e).isFile()}catch{return false}}function he(e=process.cwd()){let t=h.resolve(e);while(true){if(G(h.join(t,"apps"))||ee(h.join(t,"crewx.yaml"))){try{return v.realpathSync(t)}catch{return void 0}}const n=h.dirname(t);if(n===t)return void 0;t=n}}const ye="manifest.json";const me="ui-plugin.json";const Qe="dev.crewx";function we(e){try{const t=JSON.parse(v.readFileSync(e,"utf8"));return l(t)?t:void 0}catch{return void 0}}function te(e){const t=we(h.join(e,me));const n=h.join(e,ye);if(!ee(n))return t;const r=we(n);if(!r)return void 0;const o=r["_meta"];const i=l(o)?o[Qe]:void 0;const s={pluginId:r["name"],entry:l(i)?i["entry"]:void 0};if(t&&t["pluginId"]!==s["pluginId"])return void 0;return s}function Ee(e,t){const n=h.relative(e,t);return n!==""&&n!==".."&&!n.startsWith(`..${h.sep}`)&&!h.isAbsolute(n)}function Ye(e,t){if(!t||t==="."||t===".."||/[\\/]/.test(t)){return p(2,"USAGE",null,"App must be a folder name or pluginId.")}const n=h.join(e,"apps");const r=h.join(n,t);let o=G(r)?r:void 0;if(!o&&G(n)){try{for(const s of v.readdirSync(n,{withFileTypes:true})){if(!s.isDirectory())continue;const a=h.join(n,s.name);const u=te(a);if(u?.["pluginId"]===t){o=a;break}}}catch{}}let i=t;if(o){try{o=v.realpathSync(o)}catch{return p(6,"APP_INVALID",null)}if(!Ee(v.realpathSync(n),o)){return p(2,"USAGE",null,"App folder must be inside the workspace apps directory.")}const s=te(o);if(typeof s?.["pluginId"]==="string"&&s["pluginId"].length>0){i=s["pluginId"]}}else{o=r}return{appId:i,appDirectory:o}}function ve(e){if(e.status<200||e.status>=300){return{ok:false,outcome:W(e)}}if(e.invalidJson||!l(e.data)||e.data["success"]!==true||!l(e.data["data"])){return{ok:false,outcome:p(1,k(e.data,"ERROR"),e.status)}}return{ok:true,value:e.data,status:e.status,rawText:e.rawText}}async function Ze(e,t){try{const n=await q(e,t,"GET",qe);if(n.status===404||n.status>=300&&n.status<400||n.invalidJson){return{ok:false,outcome:de(n.status)}}if(n.status<200||n.status>=300){return{ok:false,outcome:W(n)}}if(!l(n.data)||n.data["success"]!==true||!l(n.data["data"])||n.data["data"]["appDev"]!==1){return{ok:false,outcome:de(n.status)}}return{ok:true,value:n.data,status:n.status,rawText:n.rawText}}catch(n){return{ok:false,outcome:U(n,false)}}}async function ne(e){const t=ze();if(!t)return{ok:false,outcome:p(9,"ENDPOINT_REJECTED",null)};let n;try{n=(0,z.resolveCrewxApiCredential)("app-dev").token}catch(c){return{ok:false,outcome:fe(c)}}const r=await Ze(t,n);if(!r.ok)return{ok:false,outcome:r.outcome};const o=he();if(!o){return{ok:false,outcome:p(2,"WORKSPACE_NOT_FOUND",null,"No workspace root with apps/ or crewx.yaml was found.")}}const i=Ye(o,e);if("exitCode"in i)return{ok:false,outcome:i};let s;try{s=await q(t,n,"POST",Me,{workspacePath:o,appId:i.appId})}catch(c){return{ok:false,outcome:U(c,false)}}const a=ve(s);if(!a.ok)return{ok:false,outcome:a.outcome};const u=a.value["data"];if(!l(u)||typeof u["workspaceSlug"]!=="string"||typeof u["appId"]!=="string"||typeof u["devPath"]!=="string"||!u["devPath"].startsWith("/ws/")){return{ok:false,outcome:p(1,"ERROR",s.status)}}if(!G(i.appDirectory)){return{ok:false,outcome:p(6,"APP_INVALID",s.status)}}return{ok:true,context:{endpoint:t,token:n,workspacePath:o,appId:u["appId"],appDirectory:i.appDirectory,devPath:u["devPath"]}}}function V(e,...t){return`${Ue}${e.devPath}${t.length>0?`/${t.map(F).join("/")}`:""}`}async function J(e,t,n,r,o=x){try{const i=await q(e.endpoint,e.token,t,n,r,o);return ve(i)}catch(i){return{ok:false,outcome:U(i,false)}}}function et(e){const t=e["appId"]??e["id"];if(typeof t==="string"&&t.length>0)return t;const n=e["definition"];if(l(n)&&typeof n["id"]==="string")return n["id"];return void 0}function tt(e){const t=e["definitionHash"];if(typeof t==="string"&&t.length>0)return t;const n=e["definition"];if(l(n)&&typeof n["hash"]==="string"){return n["hash"]}return void 0}function nt(e){if(!l(e))return void 0;const t=et(e);const n=tt(e);if(!t||!n)return void 0;const r=e["agentActions"];const o=ot(e["agentAccess"]);return{appId:t,name:typeof e["name"]==="string"?e["name"]:"",description:typeof e["description"]==="string"?e["description"]:"",definitionHash:n,agentActions:Array.isArray(r)?r:[],...o===void 0?{}:{agentAccess:o}}}const rt=new Set(["allowed","approval_required","denied"]);function ot(e){if(!l(e))return void 0;const t=new Map;for(const[n,r]of Object.entries(e)){if(rt.has(r))t.set(n,r)}return t.size>0?t:void 0}async function H(e,t=x){const n=await M(e,"GET",L(e,"ui-instances","apps"),void 0,t);if(!n.ok)return n;const r=n.value["apps"];if(!Array.isArray(r)){return{ok:false,outcome:p(1,"ERROR",n.status)}}const o=r.map(nt);if(o.some(i=>i===void 0)){return{ok:false,outcome:p(1,"ERROR",n.status)}}return{ok:true,value:o,status:n.status}}function re(e,t){return e.find(n=>n.appId===t)}async function ge(e,t,n=x){const r=await M(e,"POST",L(e,"ui-instances","open"),{appId:t.appId,expectedDefinitionHash:t.definitionHash},n);if(!r.ok)return r;const o=l(r.value["instance"])?r.value["instance"]:r.value;if(!l(o)){return{ok:false,outcome:p(1,"ERROR",r.status)}}const i=o["instanceId"]??o["id"];const s=o["revision"];if(typeof i!=="string"||typeof s!=="number"){return{ok:false,outcome:p(1,"ERROR",r.status)}}const a=l(r.value["ai"])?r.value["ai"]:l(o["ai"])?o["ai"]:void 0;return{ok:true,status:r.status,value:{appId:t.appId,definitionHash:t.definitionHash,instanceId:i,revision:s,state:a&&Object.prototype.hasOwnProperty.call(a,"state")?a["state"]:null}}}async function st(e,t){const n=await M(e,"GET",L(e,"ui-instances",t));if(!n.ok)return n;const r=n.value;const o=r["instanceId"];const i=r["revision"];if(typeof o!=="string"||typeof i!=="number"){return{ok:false,outcome:p(1,"ERROR",n.status)}}const s=l(r["ai"])?r["ai"]:void 0;const a=u=>{if(Object.prototype.hasOwnProperty.call(r,u))return{[u]:r[u]};if(s&&Object.prototype.hasOwnProperty.call(s,u))return{[u]:s[u]};return{}};return{ok:true,status:n.status,value:{instanceId:o,revision:i,state:s&&Object.prototype.hasOwnProperty.call(s,"state")?s["state"]:null,buttons:s&&Object.prototype.hasOwnProperty.call(s,"buttons")?s["buttons"]:null,...a("agentAccess"),...a("modelContext"),...a("pendingApproval")}}}async function it(e,t,n,r,o,i=x){const s=await M(e,"POST",L(e,"ui-instances",t,"actions"),{actionId:n,requestId:r,input:o},i);if(!s.ok)return s;const a=s.value["receipt"];if(!l(a)){return{ok:false,outcome:p(1,"ERROR",s.status)}}const u=a["receiptId"]??a["id"];const c=s.value["approval"];if(s.status===202&&l(c)){const _=c["approvalId"];const I=c["expiresAt"];const S=typeof a["requestId"]==="string"?a["requestId"]:typeof c["requestId"]==="string"?c["requestId"]:r;if(typeof u!=="string"||typeof _!=="string"||typeof I!=="string"&&typeof I!=="number"){return{ok:false,outcome:p(1,"ERROR",s.status)}}return{ok:false,outcome:{exitCode:8,payload:{ok:false,exit:8,error:{code:"APPROVAL_PENDING",status:202},receiptId:u,requestId:S,approvalId:_,expiresAt:I}}}}const d=a["status"]??(s.status===202?"requested":"settled");const f=s.value["resolve"];const y=l(f)&&l(f["ai"])?f["ai"]:void 0;return{ok:true,status:s.status,value:{receiptId:typeof u==="string"?u:"",requestId:typeof a["requestId"]==="string"?a["requestId"]:r,instanceId:t,actionId:typeof a["actionId"]==="string"?a["actionId"]:n,status:d,outcome:Object.prototype.hasOwnProperty.call(a,"outcome")?a["outcome"]:null,...typeof a["errorCode"]==="string"?{errorCode:a["errorCode"]}:{},state:y&&Object.prototype.hasOwnProperty.call(y,"state")?y["state"]:null,...Object.prototype.hasOwnProperty.call(s.value,"result")?{result:s.value["result"]}:{},...Object.prototype.hasOwnProperty.call(s.value,"resultExpired")?{resultExpired:s.value["resultExpired"]}:{}}}}function at(e){const t=e.payload["error"];return e.exitCode===14||l(t)&&t["status"]===429}async function Ae(e,t){const n=await M(e,"GET",L(e,"ui-action-receipts",t));if(!n.ok){return{state:"failed",retryable:at(n.outcome),value:n.outcome}}const r=n.value["receipt"];if(!l(r))return{state:"failed",retryable:false,value:p(1,"ERROR",n.status)};return{state:r["status"]==="requested"?"pending":"settled",value:P({ok:true,receipt:r,outcome:Object.prototype.hasOwnProperty.call(r,"outcome")?r["outcome"]:null,...typeof r["errorCode"]==="string"?{errorCode:r["errorCode"]}:{},...Object.prototype.hasOwnProperty.call(n.value,"result")?{result:n.value["result"]}:{},...Object.prototype.hasOwnProperty.call(n.value,"resultExpired")?{resultExpired:n.value["resultExpired"]}:{}})}}function ut(e,t){return{exitCode:124,payload:{ok:false,exit:124,error:{code:"WAIT_TIMEOUT",status:null},receiptId:e},suppressOutput:true,stderr:`\u2192 Receipt ${e} is still pending after ${t}s. Do not end your turn: run crewx app receipt ${e} --wait=${(0,b.nextWaitSeconds)(t)} again.`}}function Ie(){const e=process.env["CREWX_TASK_TICKET"]??"";const t=process.env["CREWX_WORKSPACE_SLUG"]??"";const n=process.env["CREWX_THREAD_ID"]??"";if(!e.startsWith("crewxtk_")||!t||!n){return p(3,"NO_TICKET",null)}const r=Y(process.env["CREWX_ENDPOINT"]);if(!r)return p(9,"ENDPOINT_REJECTED",null);return{ticket:e,workspaceSlug:t,threadId:n,endpoint:r,basePath:Ke(t,n)}}function _e(e){return"exitCode"in e}function Oe(e){return String(e).padStart(2,"0")}function ct(e){const t=typeof e==="number"?new Date(e):typeof e==="string"?new Date(/^\d+$/.test(e)?Number(e):e):void 0;if(!t||Number.isNaN(t.getTime()))return void 0;return`${Oe(t.getHours())}:${Oe(t.getMinutes())}`}function lt(e){if(e.exitCode!==8)return e;const t=ct(e.payload["expiresAt"]);const n=e.payload["receiptId"];const r=[`\u2192 Waiting for the user's approval in the App window${t?` (expires ${t})`:""}. Do not end your turn: ending it cancels the request.`,...typeof n==="string"&&n.length>0?[`\u2192 Wait: crewx app receipt ${n} --wait=${b.RECEIPT_WAIT_DEFAULT_SECONDS} (repeat on exit 124 until it settles)`]:[],"\u2192 Report success only if it settles as succeeded."];return{...e,stderr:[e.stderr,...r].filter(Boolean).join("\n")}}const pt=256*1024;function dt(e){try{const t=v.realpathSync(e);const n=v.realpathSync(h.join(t,"SKILL.md"));if(!Ee(t,n)||!ee(n))return void 0;const r=v.openSync(n,"r");try{const o=new Uint8Array(pt);const i=v.readSync(r,o,0,o.length,0);return(0,C.manualBody)(Buffer.from(o.buffer,0,i).toString("utf8"))}finally{v.closeSync(r)}}catch{return void 0}}async function ft(e){const t=he();if(!t)return void 0;try{const n=await Promise.resolve().then(()=>j(require("@crewx/sdk")));const r=await n.discoverWorkspaceApps(t);const o=r.apps.find(i=>i.appId===e)??r.apps.find(i=>i.pluginId===e);if(!o)return void 0;return{candidate:o,directory:h.join(t,o.relativePath),resolveAccess:n.resolveAgentAccess}}catch{return void 0}}async function ht(e){if(e.length!==2||e[1].startsWith("--"))return $();const t=e[1];const n=Ie();if(_e(n))return n;const r=await H(n);if(!r.ok)return r.outcome;const o=re(r.value,t);if(!o)return p(6,"MCP_APP_NOT_FOUND",null);const i=o.agentActions.filter(u=>typeof u==="string");const s=await ft(t);const a=s?(0,C.renderUsage)(dt(s.directory),(0,C.renderActionsSection)(t,s.candidate,(0,C.buildActionRows)(s.candidate,new Set(i),u=>s.resolveAccess(u),o.agentAccess)),s.candidate.manifest.csp?.connectDomains):(0,C.renderUsage)(void 0,(0,C.renderServerOnlyActions)(t,i));return{exitCode:0,payload:{ok:true},stdout:a}}function Re(e,t){if(e[0]!==t)return null;const n=[];let r=false;for(const o of e.slice(1)){if(o===(t==="dev"?"--no-open":"--json")){if(r)return null;r=true}else if(o.startsWith("--")){return null}else{n.push(o)}}if(n.length!==1)return null;return{appSelector:n[0],flag:r}}function Se(e){return`${JSON.stringify(e.payload)}
2
- `}function yt(e){const t=e["detail"];if(e["rule"]!=="manifest"||!l(t))return"";const n=typeof t["path"]==="string"?t["path"]:"";const r=typeof t["rule"]==="string"?t["rule"]:"";if(!r)return"";return` ${n?`${n} `:""}(${r})`}async function mt(e){const t=Re(e,"check");if(!t)return $();const n=await ne(t.appSelector);if(!n.ok)return n.outcome;const r=await J(n.context,"GET",V(n.context,"check"));if(!r.ok)return r.outcome;const o=r.value["data"];if(!l(o))return p(1,"ERROR",r.status);const i=l(o["summary"])?o["summary"]:{};const s=Array.isArray(o["items"])?o["items"]:[];const a=typeof i["errors"]==="number"?i["errors"]:s.filter(f=>l(f)&&f["severity"]==="error").length;const u=typeof i["warnings"]==="number"?i["warnings"]:s.filter(f=>l(f)&&f["severity"]==="warning").length;const c=a===0?0:Fe;if(t.flag){return{exitCode:c,payload:r.value,stdout:`${r.rawText??Se({exitCode:c,payload:r.value})}`+(r.rawText?.endsWith("\n")?"":"\n"),suppressOutput:true}}const d=s.flatMap(f=>{if(!l(f))return[];const y=f["severity"];const _=y==="error"?"\u2715":y==="ok"?"\u2713":"!";const I=typeof f["where"]==="string"?f["where"]:"";const S=typeof f["code"]==="string"?f["code"]:"";return[`${_} ${I} ${S}${yt(f)}`]});d.push(`Summary: ${a} errors, ${u} warnings`);return{exitCode:c,payload:{},stdout:`${d.join("\n")}
3
- `,suppressOutput:true}}async function wt(e){let t;try{t=(0,z.resolveCrewxApiCredential)("pairing").token}catch(r){return fe(r)}let n;try{n=await q(e.endpoint,t,"POST","/api/v1/auth/local/code")}catch(r){return U(r,false)}if(n.status<200||n.status>=300){return W(n)}if(n.invalidJson||!l(n.data)||typeof n.data["url"]!=="string"){return p(1,"PAIRING_CODE_INVALID",n.status)}try{const r=new ue.URL(n.data["url"]);const o=Y(r.origin);const i=r.hash.match(/^#pair=(.+)$/);if(!o||!i)return p(1,"PAIRING_CODE_INVALID",n.status);return`${o.origin}${e.devPath}#pair=${encodeURIComponent(i[1])}`}catch{return p(1,"PAIRING_CODE_INVALID",n.status)}}async function Et(e){const t=process.platform==="darwin"?"open":process.platform==="win32"?"explorer.exe":"xdg-open";const n=(0,ae.spawn)(t,[e],{detached:true,stdio:"ignore"});await new Promise((r,o)=>{n.once("error",o);n.once("spawn",()=>{n.unref();r()})})}async function vt(e){const t=pe(["run",...e.slice(2)]);if(!t||t.command!=="run")return $();const[n,r]=t.positional;const o=await ne(n);if(!o.ok)return o.outcome;const i=await J(o.context,"GET",V(o.context,"state"));if(!i.ok)return i.outcome;const s=i.value["data"];if(!l(s)||typeof s["revision"]!=="number"){return p(1,"APP_DEV_RESPONSE_INVALID",i.status)}const a=t.requestId??`cxa_${(0,ie.randomBytes)(16).toString("base64url")}`;const u=await J(o.context,"POST",V(o.context,"actions"),{actionId:r,requestId:a,input:t.input,expectedRevision:s["revision"]},Le);if(!u.ok)return u.outcome;const c=u.value["data"];const d=l(c)&&l(c["receipt"])?c["receipt"]:void 0;return{exitCode:d?.["outcome"]==="succeeded"?0:1,payload:u.value,stdout:`${u.rawText??Se({exitCode:0,payload:u.value})}`+(u.rawText?.endsWith("\n")?"":"\n"),suppressOutput:true}}function gt(e){try{const t=JSON.parse(v.readFileSync(h.join(e,"package.json"),"utf8"));if(!l(t)||!l(t["scripts"]))return false;const n=t["scripts"]["build"];return typeof n==="string"&&n.trim().length>0}catch{return false}}function De(e){const t=new Set([h.normalize(ye),h.normalize(me)]);const n=te(e);const r=n?.["entry"];if(typeof r==="string"&&r.length>0&&!h.isAbsolute(r)){const o=h.normalize(r);if(o!==".."&&!o.startsWith(`..${h.sep}`))t.add(o)}return t}function At(e,t){try{const n=v.statSync(h.join(e,t));return`${n.size}:${n.mtimeMs}:${n.ino}`}catch{return null}}function Te(e,t){return new Map([...t].map(n=>[n,At(e,n)]))}function It(e,t){const n=Date.now();let r="";let o=false;const i=s=>{const a=Buffer.from(r+(Buffer.isBuffer(s)?s.toString("utf8"):s),"utf8");r=a.length>ce?a.subarray(a.length-ce).toString("utf8"):a.toString("utf8")};return new Promise(s=>{const a=(0,ae.spawn)("npm",["run","build"],{cwd:e,env:process.env,stdio:["ignore","pipe","pipe"]});t(a);a.stdout?.on("data",i);a.stderr?.on("data",i);const u=c=>{if(o)return;o=true;t(void 0);s({ok:c,ms:Math.max(0,Date.now()-n),output:r})};a.once("error",c=>{i(`${c.message}
4
- `);u(false)});a.once("close",c=>u(c===0))})}function _t(e){const t=e.payload["error"];return l(t)&&typeof t["code"]==="string"?t["code"]:"ERROR"}async function Ot(e,t){const n=await J(e,"POST",V(e,"reload"),t);if(!n.ok)return{errorCode:_t(n.outcome)};const r=n.value["data"];return l(r)&&typeof r["generation"]==="number"?{generation:r["generation"]}:{errorCode:"APP_DEV_RESPONSE_INVALID"}}async function Rt(e,t){const n=process.ppid;let r;try{r=v.watch(e.appDirectory,{recursive:true},(E,g)=>{O(g)})}catch(E){return p(1,"WATCH_FAILED",null,E instanceof Error?E.message:"Unable to watch the App folder.")}let o=false;let i=false;let s=false;let a=false;let u="";let c="";let d;let f;let y;let _={exitCode:0,payload:{},suppressOutput:true};const I=new Map;let S;const N=new Promise(E=>{S=E});const m=E=>{process.stdout.write(`${E}
5
- `)};const w=()=>{if(o)return;o=true;if(d)clearTimeout(d);if(f)clearInterval(f);process.removeListener("SIGINT",A);process.removeListener("SIGTERM",A);S(_)};const A=()=>{if(i)return;i=true;r.close();if(d)clearTimeout(d);if(y&&y.exitCode===null)y.kill("SIGTERM");if(!s)w()};const O=E=>{if(i||o)return;const g=E===null?"":h.normalize(E.toString());const D=g.split(h.sep);if(D.some(T=>T==="node_modules"||T===".crewx"||T==="dist"))return;const K=t?De(e.appDirectory):new Set;if(y&&K.has(g))return;const R=I.get(g);if(R!==void 0){if(Date.now()<=R)return;I.delete(g)}if(s){a=true;u=g||"App files";return}c=g||"App files";if(d)clearTimeout(d);d=setTimeout(()=>{d=void 0;const T=c||"App files";c="";void X(T,false)},200)};const se=async E=>{const g=await Ot(e,E);return g.generation===void 0?`failed ${g.errorCode??"ERROR"}`:String(g.generation)};const X=async(E,g)=>{if(i||o)return;s=true;if(t){const D=De(e.appDirectory);const K=Te(e.appDirectory,D);const R=await It(e.appDirectory,B=>{y=B});const T=Te(e.appDirectory,D);for(const[B,Ce]of T){if(K.get(B)!==Ce){I.set(B,Date.now()+1e3)}}if(i){s=false;w();return}const ke={reason:"build",build:{ok:R.ok,ms:R.ms,...!R.ok?{output:R.output}:{}}};const be=await se(ke);m(`${g?"initial":E} -> build ${R.ok?"ok":"failed"} ${R.ms}ms -> reload ${be}`)}else if(!g){const D=await se({reason:"manual"});m(`${E} -> reload ${D}`)}s=false;if(i){w();return}if(a){const D=u||"App files";a=false;u="";void X(D,false);return}if(i)w()};r.once("error",E=>{_=p(1,"WATCH_FAILED",null,E.message);A()});process.once("SIGINT",A);process.once("SIGTERM",A);f=setInterval(()=>{if(process.ppid!==n)A()},1e3);f.unref();if(t)void X("initial",true);return N}async function St(e){const t=Re(e,"dev");if(!t)return $();const n=await ne(t.appSelector);if(!n.ok)return n.outcome;const r=`${n.context.endpoint.origin}${n.context.devPath}`;process.stdout.write(`${r}
6
- `);if(!t.flag){const o=await wt(n.context);if(typeof o!=="string")return o;try{await Et(o)}catch(i){return p(1,"BROWSER_OPEN_FAILED",null,i instanceof Error?i.message:"Could not open the App dev tab.")}}return Rt(n.context,gt(n.context.appDirectory))}const Pe="usage: crewx app build [<appDir>] [--check | --watch]";const Dt=["crewx app <command>",""," list List Apps available to this task"," open <appId> Open an App in this conversation"," state <instanceId> Read AI-visible state, buttons, and agent access"," run <instanceId|appId> <actionId> [--input <JSON>|-] [--request-id <id>] Run one available action"," receipt <receiptId> [--wait=<seconds>] Read a safe action receipt"," build [<appDir>] [--check | --watch] Build a @Tool App: server.ts -> dist/ and the actions (manifest.json, or dist/tools.json)"," dev <app> [--no-open] Start a foreground App dev session"," check <app> [--json] Run the App dev checks"," run --dev <app> <actionId> [--input <JSON>|-] Run an App action through the dev checks"," usage [<appId>] Show the guide, or one App's manual and action table",""].join("\n");const Tt=[Pe,""," Builds <appDir> (default: the current directory) from its server.ts: dist/server.mjs, dist/entry.mjs,",' and the actions of manifest.json. With no "bin" and no crewx.app.command in package.json the App is'," server.ts only (tool mode): dist/server.mjs, dist/main.mjs and dist/tools.json, and manifest.json"," carries no actions. --check writes nothing and exits 1 when a generated file is stale."," --watch rebuilds on every change until Ctrl-C.",""].join("\n");function Pt(){const e=[h.join(__dirname,"..","..","build-app","load.cjs"),h.join(__dirname,"..","build-app","load.cjs")];const t=e.find(n=>v.existsSync(n));if(!t)return Promise.reject(new Error("the App build is not part of this install"));return require(t).loadAppBuilder()}function oe(e){return e instanceof Error?e.message:String(e)}async function kt(e){if(e.slice(1).some(s=>s==="--help"||s==="-h")){return{exitCode:0,payload:{ok:true},stdout:Tt}}let t;try{t=await Pt()}catch(s){return p(1,"BUILD_UNAVAILABLE",null,oe(s))}let n;try{n=t.parseArguments(e.slice(1))}catch(s){return p(2,"USAGE",null,`${oe(s)} \u2192 ${Pe}`)}const{appDirectory:r}=n;const o=h.relative(process.cwd(),r);const i=o===""?"crewx app build":`crewx app build ${o}`;if(n.watch){const s=new AbortController;const a=()=>s.abort();process.once("SIGINT",a);process.once("SIGTERM",a);try{await t.watchApp(r,u=>process.stdout.write(`${u}
7
- `),{signal:s.signal})}finally{process.removeListener("SIGINT",a);process.removeListener("SIGTERM",a)}return{exitCode:0,payload:{},suppressOutput:true}}try{const s=await t.buildApp({appDirectory:r,check:n.check});if(n.check&&s.staleFiles.length>0){return{...p(1,"BUILD_STALE",null,`Stale generated files: ${s.staleFiles.join(", ")} \u2192 Fix: ${i}`),payload:{ok:false,exit:1,error:{code:"BUILD_STALE",status:null},appDir:r,stale:s.staleFiles}}}if(n.check){return P({ok:true,appDir:r,check:true,inSync:true,files:s.files,actions:s.actions})}const a=h.basename(r);const u=h.basename(h.dirname(r))==="apps";return{...P({ok:true,appDir:r,files:s.files,actions:s.actions}),stderr:u?`\u2192 Next: crewx app check ${a}`:`\u2192 Next: put ${a} in the workspace apps/ folder, then crewx app check ${a}`}}catch(s){return p(1,"BUILD_FAILED",null,oe(s))}}async function bt(e,{clock:t=b.realClock}={}){if(e.length===1&&(e[0]==="--help"||e[0]==="-h")){return{exitCode:0,payload:{ok:true},stdout:Dt}}if(e[0]==="build")return kt(e);if(e[0]==="dev")return St(e);if(e[0]==="check")return mt(e);if(e[0]==="run"&&e[1]==="--dev")return vt(e);if(e[0]==="usage")return ht(e);const n=pe(e);if(!n)return $();const r=Ie();if(_e(r))return r;if(n.command==="list"){const c=await H(r);if(!c.ok)return c.outcome;return P({ok:true,apps:c.value})}if(n.command==="receipt"){const c=n.positional[0];const d=(0,b.clampWaitSeconds)(n.waitSeconds??0);if(d===0)return(await Ae(r,c)).value;const f=await(0,b.pollUntilSettled)(()=>Ae(r,c),d,t);if(f.state!=="pending")return f.value;return ut(c,d)}if(n.command==="state"){const c=await st(r,n.positional[0]);if(!c.ok)return c.outcome;return P({ok:true,...c.value})}if(n.command==="open"){const c=n.positional[0];const d=await H(r);if(!d.ok)return d.outcome;const f=re(d.value,c);if(!f)return p(6,"MCP_APP_NOT_FOUND",null);const y=await ge(r,f);if(!y.ok)return y.outcome;return P({ok:true,...y.value})}const[o,i]=n.positional;const s=n.requestId??`cxa_${(0,ie.randomBytes)(16).toString("base64url")}`;let a=o;if(!o.startsWith(le)){const c=await H(r,Q);if(!c.ok)return Z(c.outcome,s);const d=re(c.value,o);if(!d)return p(6,"MCP_APP_NOT_FOUND",null);const f=await ge(r,d,Q);if(!f.ok)return Z(f.outcome,s);a=f.value.instanceId}const u=await it(r,a,i,s,n.input,Q);if(!u.ok)return lt(Z(u.outcome,s));return{...P({ok:true,...u.value}),stderr:`\u2192 Check: crewx app state ${u.value.instanceId}`}}
1
+ "use strict";var We=exports&&exports.__createBinding||(Object.create?(function(e,n,t,r){if(r===void 0)r=t;var o=Object.getOwnPropertyDescriptor(n,t);if(!o||("get"in o?!n.__esModule:o.writable||o.configurable)){o={enumerable:true,get:function(){return n[t]}}}Object.defineProperty(e,r,o)}):(function(e,n,t,r){if(r===void 0)r=t;e[r]=n[t]}));var Ve=exports&&exports.__setModuleDefault||(Object.create?(function(e,n){Object.defineProperty(e,"default",{enumerable:true,value:n})}):function(e,n){e["default"]=n});var U=exports&&exports.__importStar||(function(){var e=function(n){e=Object.getOwnPropertyNames||function(t){var r=[];for(var o in t)if(Object.prototype.hasOwnProperty.call(t,o))r[r.length]=o;return r};return e(n)};return function(n){if(n&&n.__esModule)return n;var t={};if(n!=null){for(var r=e(n),o=0;o<r.length;o++)if(r[o]!=="default")We(t,n,r[o])}Ve(t,n);return t}})();Object.defineProperty(exports,"__esModule",{value:true});exports.executeAppCommand=zt;const pe=require("node:crypto");const de=require("node:child_process");const v=U(require("node:fs"));const le=U(require("node:http"));const fe=U(require("node:https"));const E=U(require("node:path"));const he=require("node:url");const te=require("@crewx/shared/crewx-api-credential");const D=require("./image-artifact.js");const j=require("./receipt-wait.js");const L=require("./usage.js");const N=15e3;const ne=3e4;const Je=6e4;const me=64*1024;const ye="uic_";const Ke="/api/v1";const He="/api/v1/app-dev/capabilities";const Xe="/api/v1/app-dev/sessions";const ze=12;const Ye=13;const Ze=/^[A-Za-z0-9_-]{8,128}$/;const Qe=new Set(["127.0.0.1","[::1]","localhost"]);const et="http://localhost:8150";const tt="Do not work around this by clicking the screen or using another browser. Report that you could not use the App route.";const nt="Do not retry. Report the failure.";const rt="The server did not answer in time. Retry once; if it happens again, report it.";function u(e){return e!==null&&typeof e==="object"&&!Array.isArray(e)}function d(e,n,t,r){let o=r;if(!o&&(e===3||e===9||e===10||e===11)){o=tt}else if(!o&&e===4){o=nt}return{exitCode:e,payload:{ok:false,exit:e,error:{code:n,status:t}},...o?{stderr:o}:{}}}function P(e){return{exitCode:0,payload:e}}function B(){return d(2,"USAGE",null)}function ge(e){const n=e[0];if(n!=="list"&&n!=="open"&&n!=="state"&&n!=="run"&&n!=="receipt"){return null}const t=[];const r=new Map;for(let a=1;a<e.length;a+=1){const c=e[a];if(!c.startsWith("--")){t.push(c);continue}const p=c.indexOf("=");const l=p>=0?c.slice(2,p):c.slice(2);const f=p>=0?c.slice(p+1):void 0;if(l!=="input"&&l!=="request-id"&&l!=="wait"||r.has(l))return null;const y=f??e[a+1];if(y===void 0)return null;if(f===void 0)a+=1;r.set(l,y)}if(n==="list"&&t.length!==0||n==="open"&&t.length!==1||n==="state"&&(t.length!==1||!t[0].startsWith(ye))||n==="run"&&t.length!==2||n==="receipt"&&t.length!==1){return null}if(n!=="run"&&(r.has("input")||r.has("request-id")))return null;if(n!=="receipt"&&r.has("wait"))return null;let o={};if(r.has("input")){const a=r.get("input");try{const c=JSON.parse(a==="-"?v.readFileSync(0,"utf8"):a);if(!u(c))return null;o=c}catch{return null}}const i=r.get("request-id");if(i!==void 0&&!Ze.test(i))return null;const s=r.has("wait")?(0,j.parseWaitSeconds)(r.get("wait")):void 0;if(s===null)return null;return{command:n,positional:t,input:o,...i!==void 0?{requestId:i}:{},...s!==void 0?{waitSeconds:s}:{}}}function re(e){if(!e)return null;let n;try{n=new he.URL(e)}catch{return null}if(!Qe.has(n.hostname)||n.protocol!=="http:"&&n.protocol!=="https:"||n.username!==""||n.password!==""||n.search!==""||n.hash!==""||n.pathname!==""&&n.pathname!=="/"){return null}return n}function J(e){return encodeURIComponent(e)}function ot(e,n){return["api","v1","ws",J(e),"threads",J(n)].join("/")}function $(e,...n){return`/${e.basePath}/${n.map(J).join("/")}`}function x(e,n){if(!u(e)||!u(e["error"]))return n;const t=e["error"]["code"];return typeof t==="string"&&t.length>0?t:n}function K(e){const{status:n,data:t}=e;if(n>=300&&n<400)return d(9,"ENDPOINT_REJECTED",n);if(n===401)return d(4,x(t,"UNAUTHORIZED"),n);if(n===403)return d(5,x(t,"FORBIDDEN"),n);if(n===404)return d(6,x(t,"NOT_FOUND"),n);if(n===409){const r=x(t,"CONFLICT");if(r==="APPROVAL_ALREADY_PENDING"){const o=u(t)&&u(t["error"])?t["error"]:void 0;const i=o&&u(o["details"])?o["details"]:void 0;const s=o?.["receiptId"]??i?.["receiptId"]??(u(t)?t["receiptId"]:void 0);return{exitCode:8,payload:{ok:false,exit:8,error:{code:r,status:n},...typeof s==="string"?{receiptId:s}:{}}}}return d(7,r,n)}return d(1,x(t,"ERROR"),n)}function F(e,n=true){const t=u(e)&&typeof e["code"]==="string"?e["code"]:"";const r=process.env["CODEX_SANDBOX_NETWORK_DISABLED"]==="1";const o=!r&&(t==="EPERM"||t==="EACCES");if(r||o)return d(11,"SANDBOX_BLOCKED",null);if(n&&t==="ETIMEDOUT"&&u(e)&&e["connectionEstablished"]===true){return d(14,"TIMED_OUT",null,rt)}return d(10,"SERVER_UNREACHABLE",null)}function oe(e,n){if(e.exitCode!==14)return e;return{...e,payload:{...e.payload,requestId:n},stderr:["The request timed out and its outcome is unknown.",`Retry the same command once with --request-id ${n}; the server will return the same request's receipt without running the action twice.`,`If it times out again, report "server response delayed, outcome unknown" with requestId ${n}.`,"Do not report success or failure, click the screen, or use another route."].join("\n")}}function q(e,n,t,r,o,i=N){const s=e.protocol==="https:"?fe.request:le.request;const a=e.hostname==="[::1]"?"::1":e.hostname;const c=e.port?Number(e.port):void 0;const p=o===void 0?void 0:JSON.stringify(o);const l=s({protocol:e.protocol,hostname:a,...c!==void 0?{port:c}:{},method:t,path:r,headers:{Authorization:`Bearer ${n}`,Accept:"application/json",...p!==void 0?{"Content-Type":"application/json"}:{}}},m=>{const _=m.statusCode??0;if(_>=300&&_<400){m.destroy();clearTimeout(g);h({status:_,data:void 0,invalidJson:false,rawText:""});return}const b=[];m.setEncoding("utf8");m.on("data",R=>b.push(R));m.once("error",R=>w(R));m.once("end",()=>{clearTimeout(g);const R=b.join("");try{h({status:_,data:JSON.parse(R),invalidJson:false,rawText:R})}catch{h({status:_,data:void 0,invalidJson:true,rawText:R})}})});let f;let y=false;let h;let w;const A=new Promise((m,_)=>{h=m;w=_});const g=setTimeout(()=>{const m=new Error("Request timed out");m.code="ETIMEDOUT";m.connectionEstablished=y;l.destroy(m)},i);l.on("socket",m=>{const _=()=>{y=true};if(e.protocol==="https:"){const b=m;if(b.authorized)_();else b.once("secureConnect",_)}else{if(m.connecting)m.once("connect",_);else _()}m.once("error",b=>{f=b})});l.once("error",m=>{clearTimeout(g);w(f??m)});if(p!==void 0)l.write(p);l.end();return A}function st(e,n,t,r,o=N){const i=e.protocol==="https:"?fe.request:le.request;const s=e.hostname==="[::1]"?"::1":e.hostname;const a=e.port?Number(e.port):void 0;let c;let p;let l=false;let f;const y=new Promise((g,m)=>{c=g;p=m});const h=g=>{if(l)return;l=true;clearTimeout(f);c(g)};const w=g=>{if(l)return;l=true;clearTimeout(f);p(g)};const A=i({protocol:e.protocol,hostname:s,...a!==void 0?{port:a}:{},method:"GET",path:t,headers:{Authorization:`Bearer ${n}`,Accept:"image/png"}},g=>{const m=g.statusCode??0;const _=typeof g.headers["content-type"]==="string"?g.headers["content-type"]:void 0;if(m>=300&&m<400){g.destroy();h({status:m,contentType:_,bytes:new Uint8Array(0),rawText:""});return}if(m>=200&&m<300&&_?.split(";",1)[0]?.trim().toLowerCase()!=="image/png"){g.destroy();h({status:m,contentType:_,bytes:new Uint8Array(0),rawText:""});return}const b=[];let R=0;const W=m>=200&&m<300?r:64*1024;g.on("data",T=>{if(l)return;const I=typeof T==="string"?Buffer.from(T):T;const O=new Uint8Array(I.byteLength);O.set(I);R+=O.byteLength;if(R>W){g.destroy();w(new D.AppCaptureImageError(m>=200&&m<300?"IMAGE_BYTE_COUNT_MISMATCH":"IMAGE_DOWNLOAD_FAILED",m));return}b.push(O)});g.once("aborted",()=>w(new Error("Image response was interrupted")));g.once("error",T=>w(T));g.once("end",()=>{const T=new Uint8Array(R);let I=0;for(const O of b){T.set(O,I);I+=O.byteLength}h({status:m,contentType:_,bytes:T,rawText:m>=200&&m<300?"":Buffer.from(T).toString("utf8")})})});f=setTimeout(()=>{const g=new Error("Image request timed out");g.code="ETIMEDOUT";A.destroy(g)},o);A.once("error",g=>w(g));A.end();return y}function it(e){try{const n=JSON.parse(e);if(!u(n))return void 0;const t=u(n["error"])?n["error"]:void 0;return t&&typeof t["code"]==="string"?t["code"]:void 0}catch{return void 0}}async function at(e,n,t){let r;try{r=await st(e.endpoint,e.ticket,$(e,"ui-action-receipts",n,"image"),t)}catch(o){if(o instanceof D.AppCaptureImageError)throw o;throw new D.AppCaptureImageError("IMAGE_DOWNLOAD_FAILED")}if(r.status<200||r.status>=300){throw new D.AppCaptureImageError(it(r.rawText)==="IMAGE_EXPIRED"?"IMAGE_EXPIRED":"IMAGE_DOWNLOAD_FAILED",r.status)}if(r.contentType?.split(";",1)[0]?.trim().toLowerCase()!=="image/png"){throw new D.AppCaptureImageError("IMAGE_INVALID_MIME",r.status)}if(r.bytes.byteLength!==t){throw new D.AppCaptureImageError("IMAGE_BYTE_COUNT_MISMATCH",r.status)}return r.bytes}async function G(e,n,t,r,o=N){try{const i=await q(e.endpoint,e.ticket,n,t,r,o);if(i.status<200||i.status>=300){return{ok:false,outcome:K(i)}}if(i.invalidJson||!u(i.data)||i.data["success"]!==true){return{ok:false,outcome:d(1,x(i.data,"ERROR"),i.status)}}const s=i.data["data"];if(!u(s)){return{ok:false,outcome:d(1,"ERROR",i.status)}}return{ok:true,value:s,status:i.status}}catch(i){return{ok:false,outcome:F(i)}}}function we(e){return d(ze,"SERVER_TOO_OLD",e,"The running CrewX does not support App dev mode.")}function Ee(e){if(e instanceof te.CrewxCredentialError){return d(e.exitCode,e.code,null,e.message)}return d(1,"ERROR",null)}function ct(){const e=process.env["CREWX_ENDPOINT"]?.trim()||et;return re(e)}function H(e){try{return v.statSync(e).isDirectory()}catch{return false}}function se(e){try{return v.statSync(e).isFile()}catch{return false}}function Ie(e=process.cwd()){let n=E.resolve(e);while(true){if(H(E.join(n,"apps"))||se(E.join(n,"crewx.yaml"))){try{return v.realpathSync(n)}catch{return void 0}}const t=E.dirname(n);if(t===n)return void 0;n=t}}const Ae="manifest.json";const _e="ui-plugin.json";const ut="dev.crewx";function Oe(e){try{const n=JSON.parse(v.readFileSync(e,"utf8"));return u(n)?n:void 0}catch{return void 0}}function ie(e){const n=Oe(E.join(e,_e));const t=E.join(e,Ae);if(!se(t))return n;const r=Oe(t);if(!r)return void 0;const o=r["_meta"];const i=u(o)?o[ut]:void 0;const s={pluginId:r["name"],entry:u(i)?i["entry"]:void 0};if(n&&n["pluginId"]!==s["pluginId"])return void 0;return s}function be(e,n){const t=E.relative(e,n);return t!==""&&t!==".."&&!t.startsWith(`..${E.sep}`)&&!E.isAbsolute(t)}function pt(e,n){if(!n||n==="."||n===".."||/[\\/]/.test(n)){return d(2,"USAGE",null,"App must be a folder name or pluginId.")}const t=E.join(e,"apps");const r=E.join(t,n);let o=H(r)?r:void 0;if(!o&&H(t)){try{for(const s of v.readdirSync(t,{withFileTypes:true})){if(!s.isDirectory())continue;const a=E.join(t,s.name);const c=ie(a);if(c?.["pluginId"]===n){o=a;break}}}catch{}}let i=n;if(o){try{o=v.realpathSync(o)}catch{return d(6,"APP_INVALID",null)}if(!be(v.realpathSync(t),o)){return d(2,"USAGE",null,"App folder must be inside the workspace apps directory.")}const s=ie(o);if(typeof s?.["pluginId"]==="string"&&s["pluginId"].length>0){i=s["pluginId"]}}else{o=r}return{appId:i,appDirectory:o}}function ve(e){if(e.status<200||e.status>=300){return{ok:false,outcome:K(e)}}if(e.invalidJson||!u(e.data)||e.data["success"]!==true||!u(e.data["data"])){return{ok:false,outcome:d(1,x(e.data,"ERROR"),e.status)}}return{ok:true,value:e.data,status:e.status,rawText:e.rawText}}async function dt(e,n){try{const t=await q(e,n,"GET",He);if(t.status===404||t.status>=300&&t.status<400||t.invalidJson){return{ok:false,outcome:we(t.status)}}if(t.status<200||t.status>=300){return{ok:false,outcome:K(t)}}if(!u(t.data)||t.data["success"]!==true||!u(t.data["data"])||t.data["data"]["appDev"]!==1){return{ok:false,outcome:we(t.status)}}return{ok:true,value:t.data,status:t.status,rawText:t.rawText}}catch(t){return{ok:false,outcome:F(t,false)}}}async function ae(e){const n=ct();if(!n)return{ok:false,outcome:d(9,"ENDPOINT_REJECTED",null)};let t;try{t=(0,te.resolveCrewxApiCredential)("app-dev").token}catch(p){return{ok:false,outcome:Ee(p)}}const r=await dt(n,t);if(!r.ok)return{ok:false,outcome:r.outcome};const o=Ie();if(!o){return{ok:false,outcome:d(2,"WORKSPACE_NOT_FOUND",null,"No workspace root with apps/ or crewx.yaml was found.")}}const i=pt(o,e);if("exitCode"in i)return{ok:false,outcome:i};let s;try{s=await q(n,t,"POST",Xe,{workspacePath:o,appId:i.appId})}catch(p){return{ok:false,outcome:F(p,false)}}const a=ve(s);if(!a.ok)return{ok:false,outcome:a.outcome};const c=a.value["data"];if(!u(c)||typeof c["workspaceSlug"]!=="string"||typeof c["appId"]!=="string"||typeof c["devPath"]!=="string"||!c["devPath"].startsWith("/ws/")){return{ok:false,outcome:d(1,"ERROR",s.status)}}if(!H(i.appDirectory)){return{ok:false,outcome:d(6,"APP_INVALID",s.status)}}return{ok:true,context:{endpoint:n,token:t,workspacePath:o,appId:c["appId"],appDirectory:i.appDirectory,devPath:c["devPath"]}}}function X(e,...n){return`${Ke}${e.devPath}${n.length>0?`/${n.map(J).join("/")}`:""}`}async function z(e,n,t,r,o=N){try{const i=await q(e.endpoint,e.token,n,t,r,o);return ve(i)}catch(i){return{ok:false,outcome:F(i,false)}}}function lt(e){const n=e["appId"]??e["id"];if(typeof n==="string"&&n.length>0)return n;const t=e["definition"];if(u(t)&&typeof t["id"]==="string")return t["id"];return void 0}function ft(e){const n=e["definitionHash"];if(typeof n==="string"&&n.length>0)return n;const t=e["definition"];if(u(t)&&typeof t["hash"]==="string"){return t["hash"]}return void 0}function ht(e){if(!u(e))return void 0;const n=lt(e);const t=ft(e);if(!n||!t)return void 0;const r=e["agentActions"];const o=yt(e["agentAccess"]);return{appId:n,name:typeof e["name"]==="string"?e["name"]:"",description:typeof e["description"]==="string"?e["description"]:"",definitionHash:t,agentActions:Array.isArray(r)?r:[],...o===void 0?{}:{agentAccess:o}}}const mt=new Set(["allowed","approval_required","denied"]);function yt(e){if(!u(e))return void 0;const n=new Map;for(const[t,r]of Object.entries(e)){if(mt.has(r))n.set(t,r)}return n.size>0?n:void 0}async function Y(e,n=N){const t=await G(e,"GET",$(e,"ui-instances","apps"),void 0,n);if(!t.ok)return t;const r=t.value["apps"];if(!Array.isArray(r)){return{ok:false,outcome:d(1,"ERROR",t.status)}}const o=r.map(ht);if(o.some(i=>i===void 0)){return{ok:false,outcome:d(1,"ERROR",t.status)}}return{ok:true,value:o,status:t.status}}function ce(e,n){return e.find(t=>t.appId===n)}async function Re(e,n,t=N){const r=await G(e,"POST",$(e,"ui-instances","open"),{appId:n.appId,expectedDefinitionHash:n.definitionHash},t);if(!r.ok)return r;const o=u(r.value["instance"])?r.value["instance"]:r.value;if(!u(o)){return{ok:false,outcome:d(1,"ERROR",r.status)}}const i=o["instanceId"]??o["id"];const s=o["revision"];if(typeof i!=="string"||typeof s!=="number"){return{ok:false,outcome:d(1,"ERROR",r.status)}}const a=u(r.value["ai"])?r.value["ai"]:u(o["ai"])?o["ai"]:void 0;return{ok:true,status:r.status,value:{appId:n.appId,definitionHash:n.definitionHash,instanceId:i,revision:s,state:a&&Object.prototype.hasOwnProperty.call(a,"state")?a["state"]:null}}}const gt=new Set(["ready","unknown","hidden","expired","stale","ambiguous","unsupported"]);const wt=new Set(["native","activation-required","unsupported"]);const Et=new Set(["top-left","top-center","top-right","middle-left","middle-center","middle-right","bottom-left","bottom-center","bottom-right"]);const It=2*1024;const At=3*1024;function M(e,n,t=[]){const r=new Set([...n,...t]);return n.every(o=>Object.prototype.hasOwnProperty.call(e,o))&&Object.keys(e).every(o=>r.has(o))}function Te(e){return Number.isSafeInteger(e)&&e>=0}function Z(e){return Te(e)&&e<=1e5}function _t(e){const n=["schema","documentId","documentName","truncated","modelRevision","asOf","open","measured","counts","placement","regions"];if(!u(e)||!M(e,n,["unfinishedInput"]))return void 0;if(e["schema"]!=="html-viewer-feedback/v1"||typeof e["documentId"]!=="string"||!/^[A-Za-z0-9_-]{1,64}$/.test(e["documentId"])||e["documentName"]!==null&&(typeof e["documentName"]!=="string"||e["documentName"].length>256||/[\\/\u0000-\u001f\u007f]/.test(e["documentName"]))||typeof e["truncated"]!=="boolean"||typeof e["modelRevision"]!=="string"||!/^[A-Za-z0-9_-]{1,64}$/.test(e["modelRevision"])||typeof e["asOf"]!=="string"||e["asOf"].length>40||!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,9})?(?:Z|[+-]\d{2}:\d{2})$/.test(e["asOf"])||!Number.isFinite(Date.parse(e["asOf"]))||typeof e["open"]!=="boolean"||typeof e["measured"]!=="boolean"||Object.prototype.hasOwnProperty.call(e,"unfinishedInput")&&typeof e["unfinishedInput"]!=="boolean"){return void 0}const t=e["counts"];const r=e["placement"];if(!u(t)||!M(t,["drawings","notes","byKind","descriptionPresent"])||!u(t["byKind"])||!M(t["byKind"],["pen","highlighter","arrow","rectangle"])||!u(r)||!M(r,["visible","partial","offscreen","uncertain","total"])||!Array.isArray(e["regions"])||e["regions"].length>9){return void 0}const o=t["byKind"];const i=[t["drawings"],t["notes"],o["pen"],o["highlighter"],o["arrow"],o["rectangle"]];const s=[r["visible"],r["partial"],r["offscreen"],r["uncertain"],r["total"]];if(!i.every(Z)||typeof t["descriptionPresent"]!=="boolean"||!s.every(Z)){return void 0}const a=o["pen"]+o["highlighter"]+o["arrow"]+o["rectangle"];const c=r["visible"]+r["partial"]+r["offscreen"]+r["uncertain"];if(!Number.isSafeInteger(a)||t["drawings"]!==a||!Number.isSafeInteger(c)||r["total"]!==c||r["total"]!==t["drawings"]+t["notes"]){return void 0}const p=[];const l=new Set;for(const y of e["regions"]){if(!u(y)||!M(y,["region","drawings","notes"])||!Et.has(y["region"])||l.has(y["region"])||!Z(y["drawings"])||!Z(y["notes"])){return void 0}l.add(y["region"]);p.push({region:y["region"],drawings:y["drawings"],notes:y["notes"]})}const f={schema:"html-viewer-feedback/v1",documentId:e["documentId"],documentName:e["documentName"],truncated:e["truncated"],modelRevision:e["modelRevision"],asOf:e["asOf"],open:e["open"],measured:e["measured"],counts:{drawings:t["drawings"],notes:t["notes"],byKind:{pen:o["pen"],highlighter:o["highlighter"],arrow:o["arrow"],rectangle:o["rectangle"]},descriptionPresent:t["descriptionPresent"]},placement:{visible:r["visible"],partial:r["partial"],offscreen:r["offscreen"],uncertain:r["uncertain"],total:r["total"]},regions:p,...Object.prototype.hasOwnProperty.call(e,"unfinishedInput")?{unfinishedInput:e["unfinishedInput"]}:{}};return Buffer.byteLength(JSON.stringify(f),"utf8")<=It?f:void 0}function Ot(e){if(!u(e)||!M(e,["status"],["receivedAt","summary","capability"])||!gt.has(e["status"])||Object.prototype.hasOwnProperty.call(e,"receivedAt")&&!Te(e["receivedAt"])||Object.prototype.hasOwnProperty.call(e,"capability")&&!wt.has(e["capability"])){return void 0}const n=Object.prototype.hasOwnProperty.call(e,"summary")?_t(e["summary"]):void 0;if(Object.prototype.hasOwnProperty.call(e,"summary")&&n===void 0)return void 0;const t={status:e["status"],...Object.prototype.hasOwnProperty.call(e,"receivedAt")?{receivedAt:e["receivedAt"]}:{},...n===void 0?{}:{summary:n},...Object.prototype.hasOwnProperty.call(e,"capability")?{capability:e["capability"]}:{}};return Buffer.byteLength(JSON.stringify(t),"utf8")<=At?t:void 0}async function bt(e,n){const t=await G(e,"GET",$(e,"ui-instances",n));if(!t.ok)return t;const r=t.value;const o=r["instanceId"];const i=r["revision"];if(typeof o!=="string"||typeof i!=="number"){return{ok:false,outcome:d(1,"ERROR",t.status)}}const s=u(r["ai"])?r["ai"]:void 0;const a=p=>{if(Object.prototype.hasOwnProperty.call(r,p))return{[p]:r[p]};if(s&&Object.prototype.hasOwnProperty.call(s,p))return{[p]:s[p]};return{}};const c=Ot(r["feedback"]);return{ok:true,status:t.status,value:{instanceId:o,revision:i,state:s&&Object.prototype.hasOwnProperty.call(s,"state")?s["state"]:null,buttons:s&&Object.prototype.hasOwnProperty.call(s,"buttons")?s["buttons"]:null,...a("agentAccess"),...a("modelContext"),...a("pendingApproval"),...c===void 0?{}:{feedback:c}}}}const De="the pixels are not yet in model context; open this exact PNG with the provider's image-reading tool before describing a marked target.";async function Se(e,n,t,r){if(!Pe(n))return void 0;const o=u(t)?t:void 0;if(!o||!Object.prototype.hasOwnProperty.call(o,"crewxImage")){if(n["viewCall"]===true)throw new D.AppCaptureImageError("IMAGE_INVALID_DESCRIPTOR");return void 0}if(r.length===0){throw new D.AppCaptureImageError("IMAGE_INVALID_DESCRIPTOR")}const i=await(0,D.materializeAppCaptureImage)({cwd:process.cwd(),receiptId:r,descriptor:o["crewxImage"],download:s=>at(e,r,s)});return{result:{...o,crewxImage:i},image:i}}function Pe(e){return e["status"]==="settled"&&e["outcome"]==="succeeded"}function Ce(e){return Pe(e)&&e["viewCall"]===true}function Q(e,n,t,r){const o=t instanceof D.AppCaptureImageError?t:new D.AppCaptureImageError("IMAGE_WRITE_FAILED");const i=o.code==="IMAGE_EXPIRED"?["The App action receipt is preserved, but its image has expired on the server (IMAGE_EXPIRED).",`Reading this receipt again will not return the pixels. If you still need the image, refresh with crewx app state ${r??"<instanceId>"} and request a new capture with a NEW --request-id: keep the same viewRef from the task prompt and use documentId/modelRevision from feedback.summary.`,"If that bound view or a ready summary is unavailable, report that a new capture cannot currently be made; do not substitute another view.","The pixels are not in model context; do not describe them from metadata or text."].join("\n"):[`The App action receipt is preserved, but its image was not delivered (${o.code}).`,`Recover the same result with crewx app receipt ${n}; do not rerun the action.`,"The pixels are not in model context. Do not describe them from metadata or text. If the image is still retrievable, open the returned local PNG with the provider's image-reading tool before describing a marked target."].join("\n");return{exitCode:4,payload:{...e,ok:false,exit:4,error:{code:o.code,status:o.status},receiptId:n},stderr:i}}async function vt(e,n,t,r,o,i=N){const s=await G(e,"POST",$(e,"ui-instances",n,"actions"),{actionId:t,requestId:r,input:o},i);if(!s.ok)return s;const a=s.value["receipt"];if(!u(a)){return{ok:false,outcome:d(1,"ERROR",s.status)}}const c=a["receiptId"]??a["id"];const p=s.value["approval"];if(s.status===202&&u(p)){const h=p["approvalId"];const w=p["expiresAt"];const A=typeof a["requestId"]==="string"?a["requestId"]:typeof p["requestId"]==="string"?p["requestId"]:r;if(typeof c!=="string"||typeof h!=="string"||typeof w!=="string"&&typeof w!=="number"){return{ok:false,outcome:d(1,"ERROR",s.status)}}return{ok:false,outcome:{exitCode:8,payload:{ok:false,exit:8,error:{code:"APPROVAL_PENDING",status:202},receiptId:c,requestId:A,approvalId:h,expiresAt:w}}}}const l=a["status"]??(s.status===202?"requested":"settled");const f=s.value["resolve"];const y=u(f)&&u(f["ai"])?f["ai"]:void 0;return{ok:true,status:s.status,value:{receiptId:typeof c==="string"?c:"",requestId:typeof a["requestId"]==="string"?a["requestId"]:r,instanceId:n,actionId:typeof a["actionId"]==="string"?a["actionId"]:t,status:l,outcome:Object.prototype.hasOwnProperty.call(a,"outcome")?a["outcome"]:null,...typeof a["errorCode"]==="string"?{errorCode:a["errorCode"]}:{},state:y&&Object.prototype.hasOwnProperty.call(y,"state")?y["state"]:null,...Object.prototype.hasOwnProperty.call(s.value,"result")?{result:s.value["result"]}:{},...Object.prototype.hasOwnProperty.call(s.value,"resultExpired")?{resultExpired:s.value["resultExpired"]}:{},receipt:a}}}function Rt(e){const n=e.payload["error"];return e.exitCode===14||u(n)&&n["status"]===429}async function ke(e,n){const t=await G(e,"GET",$(e,"ui-action-receipts",n));if(!t.ok){return{state:"failed",retryable:Rt(t.outcome),value:t.outcome}}const r=t.value["receipt"];if(!u(r))return{state:"failed",retryable:false,value:d(1,"ERROR",t.status)};const o={ok:true,receipt:r,outcome:Object.prototype.hasOwnProperty.call(r,"outcome")?r["outcome"]:null,...typeof r["errorCode"]==="string"?{errorCode:r["errorCode"]}:{},...Object.prototype.hasOwnProperty.call(t.value,"result")?{result:t.value["result"]}:{},...Object.prototype.hasOwnProperty.call(t.value,"resultExpired")?{resultExpired:t.value["resultExpired"]}:{}};if(t.value["resultExpired"]===true&&Ce(r)){return{state:"failed",retryable:false,value:Q(o,n,new D.AppCaptureImageError("IMAGE_EXPIRED"))}}if(t.value["resultExpired"]!==true){try{const i=await Se(e,r,t.value["result"],n);if(i){return{state:"settled",value:{...P({...o,result:i.result,image:i.image}),stderr:De}}}}catch(i){return{state:"failed",retryable:false,value:Q(o,n,i)}}}return{state:r["status"]==="requested"?"pending":"settled",value:P(o)}}function Tt(e,n){return{exitCode:124,payload:{ok:false,exit:124,error:{code:"WAIT_TIMEOUT",status:null},receiptId:e},suppressOutput:true,stderr:`\u2192 Receipt ${e} is still pending after ${n}s. Do not end your turn: run crewx app receipt ${e} --wait=${(0,j.nextWaitSeconds)(n)} again.`}}function Ne(){const e=process.env["CREWX_TASK_TICKET"]??"";const n=process.env["CREWX_WORKSPACE_SLUG"]??"";const t=process.env["CREWX_THREAD_ID"]??"";if(!e.startsWith("crewxtk_")||!n||!t){return d(3,"NO_TICKET",null)}const r=re(process.env["CREWX_ENDPOINT"]);if(!r)return d(9,"ENDPOINT_REJECTED",null);return{ticket:e,workspaceSlug:n,threadId:t,endpoint:r,basePath:ot(n,t)}}function xe(e){return"exitCode"in e}function je(e){return String(e).padStart(2,"0")}function Dt(e){const n=typeof e==="number"?new Date(e):typeof e==="string"?new Date(/^\d+$/.test(e)?Number(e):e):void 0;if(!n||Number.isNaN(n.getTime()))return void 0;return`${je(n.getHours())}:${je(n.getMinutes())}`}function St(e){if(e.exitCode!==8)return e;const n=Dt(e.payload["expiresAt"]);const t=e.payload["receiptId"];const r=[`\u2192 Waiting for the user's approval in the App window${n?` (expires ${n})`:""}. Do not end your turn: ending it cancels the request.`,...typeof t==="string"&&t.length>0?[`\u2192 Wait: crewx app receipt ${t} --wait=${j.RECEIPT_WAIT_DEFAULT_SECONDS} (repeat on exit 124 until it settles)`]:[],"\u2192 Report success only if it settles as succeeded."];return{...e,stderr:[e.stderr,...r].filter(Boolean).join("\n")}}const Pt=256*1024;function Ct(e){try{const n=v.realpathSync(e);const t=v.realpathSync(E.join(n,"SKILL.md"));if(!be(n,t)||!se(t))return void 0;const r=v.openSync(t,"r");try{const o=new Uint8Array(Pt);const i=v.readSync(r,o,0,o.length,0);return(0,L.manualBody)(Buffer.from(o.buffer,0,i).toString("utf8"))}finally{v.closeSync(r)}}catch{return void 0}}async function kt(e){const n=Ie();if(!n)return void 0;try{const t=await Promise.resolve().then(()=>U(require("@crewx/sdk")));const r=await t.discoverWorkspaceApps(n);const o=r.apps.find(i=>i.appId===e)??r.apps.find(i=>i.pluginId===e);if(!o)return void 0;return{candidate:o,directory:E.join(n,o.relativePath),resolveAccess:t.resolveAgentAccess}}catch{return void 0}}async function Nt(e){if(e.length!==2||e[1].startsWith("--"))return B();const n=e[1];const t=Ne();if(xe(t))return t;const r=await Y(t);if(!r.ok)return r.outcome;const o=ce(r.value,n);if(!o)return d(6,"MCP_APP_NOT_FOUND",null);const i=o.agentActions.filter(c=>typeof c==="string");const s=await kt(n);const a=s?(0,L.renderUsage)(Ct(s.directory),(0,L.renderActionsSection)(n,s.candidate,(0,L.buildActionRows)(s.candidate,new Set(i),c=>s.resolveAccess(c),o.agentAccess)),s.candidate.manifest.csp?.connectDomains):(0,L.renderUsage)(void 0,(0,L.renderServerOnlyActions)(n,i));return{exitCode:0,payload:{ok:true},stdout:a}}function Le(e,n){if(e[0]!==n)return null;const t=[];let r=false;for(const o of e.slice(1)){if(o===(n==="dev"?"--no-open":"--json")){if(r)return null;r=true}else if(o.startsWith("--")){return null}else{t.push(o)}}if(t.length!==1)return null;return{appSelector:t[0],flag:r}}function $e(e){return`${JSON.stringify(e.payload)}
2
+ `}function xt(e){const n=e["detail"];if(e["rule"]!=="manifest"||!u(n))return"";const t=typeof n["path"]==="string"?n["path"]:"";const r=typeof n["rule"]==="string"?n["rule"]:"";if(!r)return"";return` ${t?`${t} `:""}(${r})`}async function jt(e){const n=Le(e,"check");if(!n)return B();const t=await ae(n.appSelector);if(!t.ok)return t.outcome;const r=await z(t.context,"GET",X(t.context,"check"));if(!r.ok)return r.outcome;const o=r.value["data"];if(!u(o))return d(1,"ERROR",r.status);const i=u(o["summary"])?o["summary"]:{};const s=Array.isArray(o["items"])?o["items"]:[];const a=typeof i["errors"]==="number"?i["errors"]:s.filter(f=>u(f)&&f["severity"]==="error").length;const c=typeof i["warnings"]==="number"?i["warnings"]:s.filter(f=>u(f)&&f["severity"]==="warning").length;const p=a===0?0:Ye;if(n.flag){return{exitCode:p,payload:r.value,stdout:`${r.rawText??$e({exitCode:p,payload:r.value})}`+(r.rawText?.endsWith("\n")?"":"\n"),suppressOutput:true}}const l=s.flatMap(f=>{if(!u(f))return[];const y=f["severity"];const h=y==="error"?"\u2715":y==="ok"?"\u2713":"!";const w=typeof f["where"]==="string"?f["where"]:"";const A=typeof f["code"]==="string"?f["code"]:"";return[`${h} ${w} ${A}${xt(f)}`]});l.push(`Summary: ${a} errors, ${c} warnings`);return{exitCode:p,payload:{},stdout:`${l.join("\n")}
3
+ `,suppressOutput:true}}async function Lt(e){let n;try{n=(0,te.resolveCrewxApiCredential)("pairing").token}catch(r){return Ee(r)}let t;try{t=await q(e.endpoint,n,"POST","/api/v1/auth/local/code")}catch(r){return F(r,false)}if(t.status<200||t.status>=300){return K(t)}if(t.invalidJson||!u(t.data)||typeof t.data["url"]!=="string"){return d(1,"PAIRING_CODE_INVALID",t.status)}try{const r=new he.URL(t.data["url"]);const o=re(r.origin);const i=r.hash.match(/^#pair=(.+)$/);if(!o||!i)return d(1,"PAIRING_CODE_INVALID",t.status);return`${o.origin}${e.devPath}#pair=${encodeURIComponent(i[1])}`}catch{return d(1,"PAIRING_CODE_INVALID",t.status)}}async function $t(e){const n=process.platform==="darwin"?"open":process.platform==="win32"?"explorer.exe":"xdg-open";const t=(0,de.spawn)(n,[e],{detached:true,stdio:"ignore"});await new Promise((r,o)=>{t.once("error",o);t.once("spawn",()=>{t.unref();r()})})}async function Mt(e){const n=ge(["run",...e.slice(2)]);if(!n||n.command!=="run")return B();const[t,r]=n.positional;const o=await ae(t);if(!o.ok)return o.outcome;const i=await z(o.context,"GET",X(o.context,"state"));if(!i.ok)return i.outcome;const s=i.value["data"];if(!u(s)||typeof s["revision"]!=="number"){return d(1,"APP_DEV_RESPONSE_INVALID",i.status)}const a=n.requestId??`cxa_${(0,pe.randomBytes)(16).toString("base64url")}`;const c=await z(o.context,"POST",X(o.context,"actions"),{actionId:r,requestId:a,input:n.input,expectedRevision:s["revision"]},Je);if(!c.ok)return c.outcome;const p=c.value["data"];const l=u(p)&&u(p["receipt"])?p["receipt"]:void 0;return{exitCode:l?.["outcome"]==="succeeded"?0:1,payload:c.value,stdout:`${c.rawText??$e({exitCode:0,payload:c.value})}`+(c.rawText?.endsWith("\n")?"":"\n"),suppressOutput:true}}function Ut(e){try{const n=JSON.parse(v.readFileSync(E.join(e,"package.json"),"utf8"));if(!u(n)||!u(n["scripts"]))return false;const t=n["scripts"]["build"];return typeof t==="string"&&t.trim().length>0}catch{return false}}function Me(e){const n=new Set([E.normalize(Ae),E.normalize(_e)]);const t=ie(e);const r=t?.["entry"];if(typeof r==="string"&&r.length>0&&!E.isAbsolute(r)){const o=E.normalize(r);if(o!==".."&&!o.startsWith(`..${E.sep}`))n.add(o)}return n}function Bt(e,n){try{const t=v.statSync(E.join(e,n));return`${t.size}:${t.mtimeMs}:${t.ino}`}catch{return null}}function Ue(e,n){return new Map([...n].map(t=>[t,Bt(e,t)]))}function Ft(e,n){const t=Date.now();let r="";let o=false;const i=s=>{const a=Buffer.from(r+(Buffer.isBuffer(s)?s.toString("utf8"):s),"utf8");r=a.length>me?a.subarray(a.length-me).toString("utf8"):a.toString("utf8")};return new Promise(s=>{const a=(0,de.spawn)("npm",["run","build"],{cwd:e,env:process.env,stdio:["ignore","pipe","pipe"]});n(a);a.stdout?.on("data",i);a.stderr?.on("data",i);const c=p=>{if(o)return;o=true;n(void 0);s({ok:p,ms:Math.max(0,Date.now()-t),output:r})};a.once("error",p=>{i(`${p.message}
4
+ `);c(false)});a.once("close",p=>c(p===0))})}function qt(e){const n=e.payload["error"];return u(n)&&typeof n["code"]==="string"?n["code"]:"ERROR"}async function Gt(e,n){const t=await z(e,"POST",X(e,"reload"),n);if(!t.ok)return{errorCode:qt(t.outcome)};const r=t.value["data"];return u(r)&&typeof r["generation"]==="number"?{generation:r["generation"]}:{errorCode:"APP_DEV_RESPONSE_INVALID"}}async function Wt(e,n){const t=process.ppid;let r;try{r=v.watch(e.appDirectory,{recursive:true},(I,O)=>{R(O)})}catch(I){return d(1,"WATCH_FAILED",null,I instanceof Error?I.message:"Unable to watch the App folder.")}let o=false;let i=false;let s=false;let a=false;let c="";let p="";let l;let f;let y;let h={exitCode:0,payload:{},suppressOutput:true};const w=new Map;let A;const g=new Promise(I=>{A=I});const m=I=>{process.stdout.write(`${I}
5
+ `)};const _=()=>{if(o)return;o=true;if(l)clearTimeout(l);if(f)clearInterval(f);process.removeListener("SIGINT",b);process.removeListener("SIGTERM",b);A(h)};const b=()=>{if(i)return;i=true;r.close();if(l)clearTimeout(l);if(y&&y.exitCode===null)y.kill("SIGTERM");if(!s)_()};const R=I=>{if(i||o)return;const O=I===null?"":E.normalize(I.toString());const C=O.split(E.sep);if(C.some(k=>k==="node_modules"||k===".crewx"||k==="dist"))return;const ee=n?Me(e.appDirectory):new Set;if(y&&ee.has(O))return;const S=w.get(O);if(S!==void 0){if(Date.now()<=S)return;w.delete(O)}if(s){a=true;c=O||"App files";return}p=O||"App files";if(l)clearTimeout(l);l=setTimeout(()=>{l=void 0;const k=p||"App files";p="";void T(k,false)},200)};const W=async I=>{const O=await Gt(e,I);return O.generation===void 0?`failed ${O.errorCode??"ERROR"}`:String(O.generation)};const T=async(I,O)=>{if(i||o)return;s=true;if(n){const C=Me(e.appDirectory);const ee=Ue(e.appDirectory,C);const S=await Ft(e.appDirectory,V=>{y=V});const k=Ue(e.appDirectory,C);for(const[V,Ge]of k){if(ee.get(V)!==Ge){w.set(V,Date.now()+1e3)}}if(i){s=false;_();return}const Fe={reason:"build",build:{ok:S.ok,ms:S.ms,...!S.ok?{output:S.output}:{}}};const qe=await W(Fe);m(`${O?"initial":I} -> build ${S.ok?"ok":"failed"} ${S.ms}ms -> reload ${qe}`)}else if(!O){const C=await W({reason:"manual"});m(`${I} -> reload ${C}`)}s=false;if(i){_();return}if(a){const C=c||"App files";a=false;c="";void T(C,false);return}if(i)_()};r.once("error",I=>{h=d(1,"WATCH_FAILED",null,I.message);b()});process.once("SIGINT",b);process.once("SIGTERM",b);f=setInterval(()=>{if(process.ppid!==t)b()},1e3);f.unref();if(n)void T("initial",true);return g}async function Vt(e){const n=Le(e,"dev");if(!n)return B();const t=await ae(n.appSelector);if(!t.ok)return t.outcome;const r=`${t.context.endpoint.origin}${t.context.devPath}`;process.stdout.write(`${r}
6
+ `);if(!n.flag){const o=await Lt(t.context);if(typeof o!=="string")return o;try{await $t(o)}catch(i){return d(1,"BROWSER_OPEN_FAILED",null,i instanceof Error?i.message:"Could not open the App dev tab.")}}return Wt(t.context,Ut(t.context.appDirectory))}const Be="usage: crewx app build [<appDir>] [--check | --watch]";const Jt=["crewx app <command>",""," list List Apps available to this task"," open <appId> Open an App in this conversation"," state <instanceId> Read AI-visible state, buttons, and agent access"," run <instanceId|appId> <actionId> [--input <JSON>|-] [--request-id <id>] Run one available action"," receipt <receiptId> [--wait=<seconds>] Read a safe action receipt"," build [<appDir>] [--check | --watch] Build a @Tool App: server.ts -> dist/ and the actions (manifest.json, or dist/tools.json)"," dev <app> [--no-open] Start a foreground App dev session"," check <app> [--json] Run the App dev checks"," run --dev <app> <actionId> [--input <JSON>|-] Run an App action through the dev checks"," usage [<appId>] Show the guide, or one App's manual and action table",""].join("\n");const Kt=[Be,""," Builds <appDir> (default: the current directory) from its server.ts: dist/server.mjs, dist/entry.mjs,",' and the actions of manifest.json. With no "bin" and no crewx.app.command in package.json the App is'," server.ts only (tool mode): dist/server.mjs, dist/main.mjs and dist/tools.json, and manifest.json"," carries no actions. --check writes nothing and exits 1 when a generated file is stale."," --watch rebuilds on every change until Ctrl-C.",""].join("\n");function Ht(){const e=[E.join(__dirname,"..","..","build-app","load.cjs"),E.join(__dirname,"..","build-app","load.cjs")];const n=e.find(t=>v.existsSync(t));if(!n)return Promise.reject(new Error("the App build is not part of this install"));return require(n).loadAppBuilder()}function ue(e){return e instanceof Error?e.message:String(e)}async function Xt(e){if(e.slice(1).some(s=>s==="--help"||s==="-h")){return{exitCode:0,payload:{ok:true},stdout:Kt}}let n;try{n=await Ht()}catch(s){return d(1,"BUILD_UNAVAILABLE",null,ue(s))}let t;try{t=n.parseArguments(e.slice(1))}catch(s){return d(2,"USAGE",null,`${ue(s)} \u2192 ${Be}`)}const{appDirectory:r}=t;const o=E.relative(process.cwd(),r);const i=o===""?"crewx app build":`crewx app build ${o}`;if(t.watch){const s=new AbortController;const a=()=>s.abort();process.once("SIGINT",a);process.once("SIGTERM",a);try{await n.watchApp(r,c=>process.stdout.write(`${c}
7
+ `),{signal:s.signal})}finally{process.removeListener("SIGINT",a);process.removeListener("SIGTERM",a)}return{exitCode:0,payload:{},suppressOutput:true}}try{const s=await n.buildApp({appDirectory:r,check:t.check});if(t.check&&s.staleFiles.length>0){return{...d(1,"BUILD_STALE",null,`Stale generated files: ${s.staleFiles.join(", ")} \u2192 Fix: ${i}`),payload:{ok:false,exit:1,error:{code:"BUILD_STALE",status:null},appDir:r,stale:s.staleFiles}}}if(t.check){return P({ok:true,appDir:r,check:true,inSync:true,files:s.files,actions:s.actions})}const a=E.basename(r);const c=E.basename(E.dirname(r))==="apps";return{...P({ok:true,appDir:r,files:s.files,actions:s.actions}),stderr:c?`\u2192 Next: crewx app check ${a}`:`\u2192 Next: put ${a} in the workspace apps/ folder, then crewx app check ${a}`}}catch(s){return d(1,"BUILD_FAILED",null,ue(s))}}async function zt(e,{clock:n=j.realClock}={}){if(e.length===1&&(e[0]==="--help"||e[0]==="-h")){return{exitCode:0,payload:{ok:true},stdout:Jt}}if(e[0]==="build")return Xt(e);if(e[0]==="dev")return Vt(e);if(e[0]==="check")return jt(e);if(e[0]==="run"&&e[1]==="--dev")return Mt(e);if(e[0]==="usage")return Nt(e);const t=ge(e);if(!t)return B();const r=Ne();if(xe(r))return r;if(t.command==="list"){const h=await Y(r);if(!h.ok)return h.outcome;return P({ok:true,apps:h.value})}if(t.command==="receipt"){const h=t.positional[0];const w=(0,j.clampWaitSeconds)(t.waitSeconds??0);if(w===0)return(await ke(r,h)).value;const A=await(0,j.pollUntilSettled)(()=>ke(r,h),w,n);if(A.state!=="pending")return A.value;return Tt(h,w)}if(t.command==="state"){const h=await bt(r,t.positional[0]);if(!h.ok)return h.outcome;return P({ok:true,...h.value})}if(t.command==="open"){const h=t.positional[0];const w=await Y(r);if(!w.ok)return w.outcome;const A=ce(w.value,h);if(!A)return d(6,"MCP_APP_NOT_FOUND",null);const g=await Re(r,A);if(!g.ok)return g.outcome;return P({ok:true,...g.value})}const[o,i]=t.positional;const s=t.requestId??`cxa_${(0,pe.randomBytes)(16).toString("base64url")}`;let a=o;if(!o.startsWith(ye)){const h=await Y(r,ne);if(!h.ok)return oe(h.outcome,s);const w=ce(h.value,o);if(!w)return d(6,"MCP_APP_NOT_FOUND",null);const A=await Re(r,w,ne);if(!A.ok)return oe(A.outcome,s);a=A.value.instanceId}const c=await vt(r,a,i,s,t.input,ne);if(!c.ok)return St(oe(c.outcome,s));const{receipt:p,...l}=c.value;const f={ok:true,...l};const y=typeof l["receiptId"]==="string"?l["receiptId"]:"";if(l["resultExpired"]===true&&u(p)&&Ce(p)){return Q({...f,receipt:p},y,new D.AppCaptureImageError("IMAGE_EXPIRED"),a)}if(u(p)&&l["resultExpired"]!==true){try{const h=await Se(r,p,l["result"],y);if(h){return{...P({...f,receipt:p,result:h.result,image:h.image}),stderr:`\u2192 Check: crewx app state ${c.value.instanceId}
8
+ ${De}`}}}catch(h){return Q({...f,receipt:p},y,h,a)}}return{...P(f),stderr:`\u2192 Check: crewx app state ${c.value.instanceId}`}}
@@ -0,0 +1,24 @@
1
+ export type AppCaptureImageErrorCode = 'IMAGE_INVALID_DESCRIPTOR' | 'IMAGE_INVALID_MIME' | 'IMAGE_TOO_LARGE' | 'IMAGE_BYTE_COUNT_MISMATCH' | 'IMAGE_DIMENSIONS_MISMATCH' | 'IMAGE_DIGEST_MISMATCH' | 'IMAGE_INVALID_PNG' | 'IMAGE_VALIDATION_FAILED' | 'IMAGE_DOWNLOAD_FAILED' | 'IMAGE_EXPIRED' | 'IMAGE_WRITE_FAILED';
2
+ export declare class AppCaptureImageError extends Error {
3
+ readonly code: AppCaptureImageErrorCode;
4
+ readonly status: number | null;
5
+ constructor(code: AppCaptureImageErrorCode, status?: number | null);
6
+ }
7
+ export interface LocalAppCaptureImage {
8
+ readonly path: string;
9
+ readonly mediaType: 'image/png';
10
+ readonly width: number;
11
+ readonly height: number;
12
+ readonly bytes: number;
13
+ readonly sha256: string;
14
+ }
15
+ interface MaterializeAppCaptureImageOptions {
16
+ readonly cwd: string;
17
+ readonly receiptId: string;
18
+ readonly descriptor: unknown;
19
+ readonly download: (maxBytes: number) => Promise<Uint8Array>;
20
+ readonly now?: number;
21
+ }
22
+ export declare function materializeAppCaptureImage(options: MaterializeAppCaptureImageOptions): Promise<LocalAppCaptureImage>;
23
+ export {};
24
+
@@ -0,0 +1 @@
1
+ "use strict";var N=exports&&exports.__createBinding||(Object.create?(function(t,e,n,i){if(i===void 0)i=n;var o=Object.getOwnPropertyDescriptor(e,n);if(!o||("get"in o?!e.__esModule:o.writable||o.configurable)){o={enumerable:true,get:function(){return e[n]}}}Object.defineProperty(t,i,o)}):(function(t,e,n,i){if(i===void 0)i=n;t[i]=e[n]}));var C=exports&&exports.__setModuleDefault||(Object.create?(function(t,e){Object.defineProperty(t,"default",{enumerable:true,value:e})}):function(t,e){t["default"]=e});var A=exports&&exports.__importStar||(function(){var t=function(e){t=Object.getOwnPropertyNames||function(n){var i=[];for(var o in n)if(Object.prototype.hasOwnProperty.call(n,o))i[i.length]=o;return i};return t(e)};return function(e){if(e&&e.__esModule)return e;var n={};if(e!=null){for(var i=t(e),o=0;o<i.length;o++)if(i[o]!=="default")N(n,e,i[o])}C(n,e);return n}})();Object.defineProperty(exports,"__esModule",{value:true});exports.AppCaptureImageError=void 0;exports.materializeAppCaptureImage=V;const w=require("node:crypto");const r=A(require("node:fs"));const E=A(require("node:path"));const f=require("@crewx/sdk");const T=E.join(".crewx","app-captures");const p="*\n!.gitignore\n";const D=24*60*60*1e3;const g=32;const b=g*f.UI_VIEW_CALL_IMAGE_MAX_BYTES;const F=/^capture-[a-f0-9]{24}-[a-f0-9]{64}\.png$/;const G=/^capture-tmp-[a-f0-9]{32}\.part$/;class l extends Error{constructor(e,n=null){super(e);this.name="AppCaptureImageError";this.code=e;this.status=n}}exports.AppCaptureImageError=l;function R(t){if(t===null||typeof t!=="object"||Array.isArray(t))return false;const e=t;const n=e["width"];const i=e["height"];const o=e["bytes"];if(Number.isSafeInteger(o)&&o>f.UI_VIEW_CALL_IMAGE_MAX_BYTES)return true;if(Number.isSafeInteger(n)&&n>f.UI_VIEW_CALL_IMAGE_MAX_DIMENSION)return true;if(Number.isSafeInteger(i)&&i>f.UI_VIEW_CALL_IMAGE_MAX_DIMENSION)return true;return Number.isSafeInteger(n)&&Number.isSafeInteger(i)&&n*i>f.UI_VIEW_CALL_IMAGE_MAX_PIXELS}function W(t,e){return t instanceof l?t:new l(e)}function P(t){const e=t instanceof Error?t.message.toLowerCase():"";if(e.includes("digest"))return"IMAGE_DIGEST_MISMATCH";if(e.includes("byte count"))return"IMAGE_BYTE_COUNT_MISMATCH";if(e.includes("dimensions"))return"IMAGE_DIMENSIONS_MISMATCH";if(e.includes("size"))return"IMAGE_INVALID_PNG";if(e.includes("sha-256 validation is unavailable"))return"IMAGE_VALIDATION_FAILED";return"IMAGE_INVALID_PNG"}function d(t){try{return r.lstatSync(t)}catch(e){if(e.code==="ENOENT")return void 0;throw e}}function S(t,e,n){try{r.mkdirSync(t,{mode:e})}catch(o){if(o.code!=="EEXIST")throw o}const i=r.lstatSync(t);if(i.isSymbolicLink()||!i.isDirectory())throw new Error("Capture directory is not a real directory");if(n)r.chmodSync(t,e)}function O(t,e,n){const i=r.constants.O_NOFOLLOW??0;const o=r.openSync(t,r.constants.O_RDONLY|i);try{const c=r.fstatSync(o);if(!c.isFile()||c.size>e)throw new Error("Capture file is not a bounded regular file");if(n!==void 0)r.fchmodSync(o,n);return r.readFileSync(o)}finally{r.closeSync(o)}}function v(t){const e=E.join(t,".gitignore");let n=d(e);if(n===void 0){const o=r.constants.O_NOFOLLOW??0;let c;try{c=r.openSync(e,r.constants.O_WRONLY|r.constants.O_CREAT|r.constants.O_EXCL|o,384)}catch(a){if(a.code!=="EEXIST")throw a}if(c!==void 0){try{r.writeFileSync(c,p,"utf8");r.fsyncSync(c)}finally{r.closeSync(c)}}n=d(e)}if(!n||n.isSymbolicLink()||!n.isFile())throw new Error("Capture ignore file is not a regular file");const i=O(e,1024,384).toString("utf8");if(i!==p)throw new Error("Capture ignore file has unexpected contents")}function j(t){const e=r.realpathSync(E.resolve(t));const n=E.join(e,".crewx");const i=E.join(e,T);S(n,448,false);S(i,448,true);v(i);return i}function U(t,e){let n=0;let i=0;for(const o of r.readdirSync(t)){const c=F.test(o);if(!c&&!G.test(o))continue;const a=E.join(t,o);const s=d(a);if(!s||s.isSymbolicLink()||!s.isFile())continue;if(e-s.mtimeMs>D){r.unlinkSync(a);continue}n+=1;i+=s.size}return{count:n,bytes:i}}function X(t,e,n){const i=d(e);if(i&&(i.isSymbolicLink()||!i.isFile())){throw new Error("Capture target is not a regular file")}const o=E.join(t,`capture-tmp-${(0,w.randomBytes)(16).toString("hex")}.part`);const c=r.constants.O_NOFOLLOW??0;let a;try{a=r.openSync(o,r.constants.O_WRONLY|r.constants.O_CREAT|r.constants.O_EXCL|c,384);let s=0;while(s<n.byteLength){const I=r.writeSync(a,n,s,n.byteLength-s);if(I<=0)throw new Error("Capture write made no progress");s+=I}r.fsyncSync(a);r.closeSync(a);a=void 0;r.renameSync(o,e);const _=r.openSync(e,r.constants.O_RDONLY|c);try{const I=r.fstatSync(_);if(!I.isFile())throw new Error("Capture target is not a regular file");r.fchmodSync(_,384);r.fsyncSync(_)}finally{r.closeSync(_)}const y=r.openSync(t,r.constants.O_RDONLY);try{r.fsyncSync(y)}finally{r.closeSync(y)}}finally{if(a!==void 0)r.closeSync(a);try{r.unlinkSync(o)}catch(s){if(s.code!=="ENOENT")throw s}}}function L(t,e){return{path:E.resolve(t),mediaType:e.mediaType,width:e.width,height:e.height,bytes:e.bytes,sha256:e.sha256}}async function V(t){let e;try{e=(0,f.validateUiActionImageDescriptor)(t.descriptor)}catch{throw new l(R(t.descriptor)?"IMAGE_TOO_LARGE":"IMAGE_INVALID_DESCRIPTOR")}if(typeof t.receiptId!=="string"||t.receiptId.length===0){throw new l("IMAGE_INVALID_DESCRIPTOR")}let n;try{n=j(t.cwd)}catch{throw new l("IMAGE_WRITE_FAILED")}const i=(0,w.createHash)("sha256").update(t.receiptId).digest("hex").slice(0,24);const o=`capture-${i}-${e.sha256}.png`;const c=E.join(n,o);const a=t.now??Date.now();let s;try{s=U(n,a)}catch{throw new l("IMAGE_WRITE_FAILED")}let _=false;let y=0;try{const u=d(c);if(u!==void 0){if(u.isSymbolicLink()||!u.isFile())throw new Error("Capture target is not a regular file");y=u.size;if(u.size>f.UI_VIEW_CALL_IMAGE_MAX_BYTES){_=true}else{const m=O(c,f.UI_VIEW_CALL_IMAGE_MAX_BYTES,384);try{await(0,f.validateUiActionImagePng)(new Uint8Array(m),e);return L(c,e)}catch{_=true}}}}catch(u){if(u instanceof l)throw u;throw new l("IMAGE_WRITE_FAILED")}const I=s.count-(_?1:0);const M=s.bytes-(_?y:0);if(I>=g||M+e.bytes>b){throw new l("IMAGE_WRITE_FAILED")}let h;try{h=await t.download(e.bytes)}catch(u){throw W(u,"IMAGE_DOWNLOAD_FAILED")}try{await(0,f.validateUiActionImagePng)(h,e)}catch(u){throw new l(P(u))}try{X(n,c,h);return L(c,e)}catch{throw new l("IMAGE_WRITE_FAILED")}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crewx/app",
3
- "version": "0.1.0-rc.63",
3
+ "version": "0.1.0-rc.64",
4
4
  "description": "Task-scoped CLI access to CrewX Apps",
5
5
  "type": "commonjs",
6
6
  "main": "dist/src/engine.js",
@@ -28,7 +28,7 @@
28
28
  ],
29
29
  "dependencies": {
30
30
  "esbuild": "0.27.7",
31
- "@crewx/sdk": "0.9.0-rc.182"
31
+ "@crewx/sdk": "0.9.0-rc.183"
32
32
  },
33
33
  "keywords": [
34
34
  "crewx",