@hyperscale0/cli 1.0.0-beta.25 → 1.0.0-beta.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -9
- package/hyperscale.js +35 -42
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# @hyperscale0/cli
|
|
2
2
|
|
|
3
|
-
Hyperscale™ CLI: the founder command line. It logs a founder in,
|
|
4
|
-
|
|
3
|
+
Hyperscale™ CLI: the founder command line. It logs a founder in,
|
|
4
|
+
composes Products from HSX source, manages sandbox API keys, and runs one
|
|
5
5
|
Product's frozen public actions.
|
|
6
6
|
|
|
7
7
|
## Install
|
|
@@ -22,9 +22,6 @@ https://hyperscale0.ai/request-access.
|
|
|
22
22
|
export HYPERSCALE_TOKEN="<your founder PAT>"
|
|
23
23
|
bunx @hyperscale0/cli auth login --no-browser
|
|
24
24
|
bunx @hyperscale0/cli whoami
|
|
25
|
-
bunx @hyperscale0/cli start --blueprint vehicle-escrow-marketplace --json
|
|
26
|
-
bunx @hyperscale0/cli blueprint list
|
|
27
|
-
bunx @hyperscale0/cli product create --blueprint luxury-goods-consignment-escrow --name "Luxury Consignment"
|
|
28
25
|
bunx @hyperscale0/cli product create --source product.hsx --name "Custom Escrow"
|
|
29
26
|
bunx @hyperscale0/cli product select <Product id>
|
|
30
27
|
bunx @hyperscale0/cli key create --name "Founder laptop"
|
|
@@ -48,9 +45,8 @@ operation id such as `escrow_order.placeBuyerHold` to return its full input
|
|
|
48
45
|
schema, output schema, policies, build id, surface version, and operation-set
|
|
49
46
|
digest.
|
|
50
47
|
`product create` creates and selects a new Product with `--name <name>`
|
|
51
|
-
from
|
|
52
|
-
`
|
|
53
|
-
pass `--blueprint <slug>` to skip the prompt. `product select <Product id>`
|
|
48
|
+
from `--source <file.hsx>`.
|
|
49
|
+
`product select <Product id>`
|
|
54
50
|
stores the default Product used by compose, key, and Product commands when
|
|
55
51
|
`--product` is absent.
|
|
56
52
|
`compose check` compiles textual HSX and runs the independent composer check.
|
|
@@ -90,7 +86,7 @@ Run `bunx @hyperscale0/cli --help` for the full option list.
|
|
|
90
86
|
|
|
91
87
|
When passing `--json`, commands emit structured JSON to stdout on success.
|
|
92
88
|
Commands that create or switch active resources (`product create`, `product select`,
|
|
93
|
-
`product show`, `
|
|
89
|
+
`product show`, `key create`) include a
|
|
94
90
|
`nextCommands` string array in their success envelope with recommended follow-up
|
|
95
91
|
commands.
|
|
96
92
|
|
package/hyperscale.js
CHANGED
|
@@ -1,51 +1,44 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{spawn as
|
|
3
|
-
`)}function
|
|
4
|
-
`)}function
|
|
5
|
-
`)}function
|
|
2
|
+
import{spawn as Ge}from"node:child_process";import{createHash as Ot}from"node:crypto";import{createServer as jt}from"node:http";import{createInterface as Nt}from"node:readline/promises";import{chmod as he,mkdir as _t,readdir as Lt,readFile as q,rename as Ut,unlink as Ht,writeFile as Dt}from"node:fs/promises";import{homedir as Kt}from"node:os";import{basename as Jt,dirname as ke,join as se}from"node:path";var A={wordmark:"HYPERSCALE",columns:80,accent:{truecolour:[45,75,242],ansi16:34},strong:1,dim:2,reset:0,foregroundReset:39,weightReset:22,rule:"-",policy:{requireTTY:!0,honourNoColor:!0,json:"plain",nonTTY:"plain"}};var N="\x1B",Ue="\x07",Ct=new RegExp(`[${N}](?:\\[[0-?]*[ -/]*[@-~]|\\][^${Ue}${N}]*(?:${Ue}|${N}\\\\)|[PX^_][^${N}]*${N}\\\\|.)|[^\\P{Cc}\\t\\n\\r]`,"gu");function He(e){return String(e??"").replace(Ct,"")}function b(e,t,n){let o=!!e?.isTTY&&t?.NO_COLOR===void 0&&!n?.json,r=(u,l)=>f=>{let m=He(f);return o?`${u}${m}${l}`:m},s=u=>`${N}[${u}m`,i=t&&"COLORTERM"in t?t.COLORTERM:void 0,a=i==="truecolor"||i==="24bit"?`38;2;${A.accent.truecolour.join(";")}`:A.accent.ansi16,c=r(s(A.dim),s(A.weightReset));return{accent:r(s(a),s(A.foregroundReset)),strong:r(s(A.strong),s(A.weightReset)),dim:c,rule:u=>{let l=Number.isFinite(u)?Math.min(A.columns,Math.max(0,Math.floor(u))):A.columns;return c(A.rule.repeat(l))},text:He}}var x={wordmark:"HYPERSCALE",tagline:"For the company you have in mind.",viewBox:"0 0 32 32",strokeWidth:.32,paths:["M16 3.5L28.5 9.75V22.25L16 28.5L3.5 22.25V9.75Z","M3.5 9.75L16 16L28.5 9.75","M16 16V28.5","M16 5L24 9V17L16 21L8 17V9Z","M8 9L16 13L24 9","M16 13V21","M16 7L20 9V13L16 15L12 13V9Z","M12 9L16 11L20 9","M16 11V15"],wordmarkWeight:200,wordmarkTracking:"0.055em",strokeOffsetPx:1,wordmarkGapRatio:.25,construction:{slope:"1/2",halfWidths:[12.5,8,4],centres:[[16,16],[16,13],[16,11]],visibleVertexConnections:0,projection:"Three solid isometric cubes, each drawn as its silhouette and front edges, nesting toward the top corner. The outer cube is centred on the master; the middle and inner cubes sit higher so each rests inside the one before. No connecting edges."},sizeRule:{minimumPx:24,cubeCount:3,detailReduction:!1,description:"Keep all three cubes at every size of 24px or above."}};var eo=[x.paths[0],x.paths[1],x.paths[2],x.paths[3],x.paths[4],x.paths[5],x.paths[6],x.paths[7],x.paths[8]],to=x.strokeOffsetPx+x.strokeWidth;var pe=x.wordmark,no=`${pe}\u2122`,De="Hyperscale\u2122 is a trademark of Hyperscale LLC.";var Ke=x.tagline;function Je(e){return[e.strong(pe),"",Ke,"",e.accent("Run hyperscale auth login to sign in.")].join(`
|
|
3
|
+
`)}function Ye(e,t){let n=e.text(t.identity),o=[e.strong("Logged in"),"",` Identity: ${n}`];if(t.team){let r=e.text(t.team);o.push(` Team: ${r}`)}return o.join(`
|
|
4
|
+
`)}function fe(e){return[`${e.strong("Usage:")} hyperscale <command> [options]`,"","The founder command line.","",e.strong("Concepts:")," Blueprint -> Product A Blueprint is a public catalog template."," Composing one, or raw HSX, creates a Product."," Founder PAT vs API key A founder PAT manages the company: Blueprints,"," Products, composition, keys. A Product API key"," runs one Product's operations. Not interchangeable."," Actions vs operations product actions / product run execute a Product's"," frozen public contract. ops list / call invoke"," catalog operations from the machine document."," Public discovery blueprint list and blueprint show need no login.","",e.strong("Commands:")," start Create a Product and run its first published step"," help [command] Print help for hyperscale or a specific command"," auth login Sign in through the portal or save a founder PAT"," auth status Verify and show the active founder PAT"," auth logout [--revoke] Forget the local founder PAT, optionally revoke it"," blueprint list List public Blueprints without authentication"," blueprint show <id> Show one public Blueprint"," product create Create a Product from a Blueprint or HSX source"," product list List Products in the signed-in company"," product show [id] Show a Product (default: selected Product)"," product select <id> Select the default Product for later commands"," product actions [op-id] List frozen public actions or describe one exactly"," product run <op-id> Run one frozen public action"," compose check <file.hsx> Compile and check an HSX program"," compose plan <file.hsx> Diff an HSX program against the selected Product"," compose apply <file.hsx> Recompose the selected Product from checked HSX"," key create Create a sandbox Product API key"," key list List keys for the selected Product"," key revoke <id> Revoke a Product API key"," activity list List company activity"," whoami Show the user and company this founder PAT maps to"," ops list [filter] List callable operations (substring filter)"," call <operation> Call one operation by name or operation id","",e.strong("Options:")," --token <pat> Founder PAT (default: $HYPERSCALE_TOKEN)"," --api-key <key> Product API key (default: $HYPERSCALE_API_KEY)"," --base-url <url> API origin (default: $HYPERSCALE_BASE_URL)"," --environment <name> sandbox or live (default: $HYPERSCALE_ENVIRONMENT)"," --no-browser Skip browser login. Needs a PAT or it fails"," --revoke Revoke the founder PAT during auth logout"," --blueprint <slug> Blueprint for start or product create"," --source <file> HSX source for initial Product creation"," --name <name> Product or key name"," --product <id> Product id for key commands and actions"," --catalog-revision <id> Tenant catalog revision for HSX composition"," --json Print machine-readable JSON"," --help, -h Print this help"," --version, -v Print the CLI version","",De].join(`
|
|
5
|
+
`)}function me(e,t){if(!t)return[`${e.strong("Usage:")} hyperscale auth login [--no-browser] [--token <pat>]`,"","Sign in through the portal callback or save a founder PAT.","",e.strong("Options:")," --no-browser Skip browser login. Saves the PAT or fails without one."," --token <pat> Founder PAT. Defaults to HYPERSCALE_TOKEN."," --json Print the saved session summary as one JSON document.","",e.strong("Notes:")," Without a PAT, the CLI opens portal sign-in and accepts one callback."," With --no-browser and no token, the command fails with a login error."," Pass HYPERSCALE_TOKEN or --token to save a PAT.","",e.strong("Example:")," hyperscale auth login --no-browser"].join(`
|
|
6
6
|
`);if("subcommands"in t)return[`${e.strong("Usage:")} hyperscale ${t.prefix} <subcommand> [options]`,"",`Available ${t.prefix} subcommands:`,...t.subcommands.map(([o,r])=>` ${o.padEnd(20)} ${r}`),"",`Run "hyperscale help ${t.prefix} <subcommand>" for detailed options and examples.`].join(`
|
|
7
7
|
`);let n=[`${e.strong("Usage:")} hyperscale ${t.usage}`,"",t.summary,"",e.strong("Options:"),...(t.options??[]).map(o=>` ${o}`)];return t.notes&&t.notes.length>0&&n.push("",e.strong("Notes:"),...t.notes.map(o=>` ${o}`)),t.example&&n.push("",e.strong("Example:"),` ${t.example}`),n.join(`
|
|
8
|
-
`)}function
|
|
9
|
-
`);let o=t.columns.map(a=>e.text(a)),r=t.rows.map(a=>a.map(c=>e.text(c))),s=o.map((a,c)=>Math.max(a.length,...r.map(
|
|
10
|
-
`)}function
|
|
8
|
+
`)}function _(e,t){let n=[];if(t.title&&n.push(e.strong(e.text(t.title)),""),t.columns.length===0)return n.join(`
|
|
9
|
+
`);let o=t.columns.map(a=>e.text(a)),r=t.rows.map(a=>a.map(c=>e.text(c))),s=o.map((a,c)=>Math.max(a.length,...r.map(u=>(u[c]??"").length)));if(s.reduce((a,c)=>a+c,0)+2*(o.length-1)<=80){let a=o.map((c,u)=>u===o.length-1?c:c.padEnd(s[u])).join(" ");n.push(e.strong(a));for(let c of r){let u=o.map((l,f)=>{let m=c[f]??"";return f===o.length-1?m:m.padEnd(s[f])}).join(" ");n.push(u)}}else{let a=Math.max(...o.map(c=>c.length));for(let c=0;c<r.length;c++){let u=r[c];c>0&&n.push("");for(let l=0;l<o.length;l++){let f=o[l],m=u[l]??"";n.push(` ${f.padEnd(a)}: ${m}`)}}}return n.join(`
|
|
10
|
+
`)}function L(e,t){let n=[];if(t.title&&n.push(e.strong(e.text(t.title)),""),t.fields.length===0)return n.join(`
|
|
11
11
|
`);let o=t.fields.map(([s,i])=>[e.text(s),e.text(i)]),r=Math.max(...o.map(([s])=>s.length));for(let[s,i]of o){let a=` ${(s+":").padEnd(r+3)}`;if(i.includes(`
|
|
12
12
|
`)){let c=i.split(`
|
|
13
|
-
`);n.push(`${a}${c[0]}`);let
|
|
14
|
-
`)}function
|
|
15
|
-
`)}function
|
|
16
|
-
`)}var nt="https://hyperscale0.ai",ot="sandbox",Re="hyperscale-cli-session",Mt="/v1/personal-access-tokens/current",Pe=process.platform==="darwin"?"/usr/bin/security":null,qt="config.json",Ee="https://hyperscale0.ai/desk/security/tokens",rt="https://hyperscale0.ai/request-access",We=`Mint a founder PAT in Hyperscale Portal at ${Ee}. Open Security, then Personal access tokens.`,Ft=`Not logged in. Run "hyperscale auth login" to open Hyperscale Portal sign-in. In a headless environment, mint a founder PAT in Hyperscale Portal at ${Ee}. Open Security, then Personal access tokens. Then set HYPERSCALE_TOKEN or pass --token. Unapproved founders can request access at ${rt}.`,Wt=`Run "hyperscale auth login". For headless use, mint a founder PAT in Hyperscale Portal at ${Ee}. Open Security, then Personal access tokens. Unapproved founders can request access at ${rt}.`,$e=3e4,zt=2e3,Vt=120*1e3,Gt=/^prd_(sandbox|live)_[a-z0-9]{8,64}$/,we={start:{usage:"start [--blueprint <slug>] [--name <name>] [--json]",summary:"Choose a catalog company, create its Product, and run its first published runnable step.",options:["--blueprint <slug> Skip the prompt and choose this catalog Blueprint.","--name <name> Product name. Defaults to the selected Blueprint name.","--json Print one machine document, including the one-time API key under shown_once."],notes:["The command requires an active founder login.","Without --blueprint, start requires an interactive terminal and asks which company to build.","Scripts and agents must pass --blueprint <slug>.","Machine output returns the Product API key only under shown_once.","A Blueprint without a published runnable step stops after composition and names the next command."],example:"hyperscale start --blueprint vehicle-escrow-marketplace --json"},"auth login":{usage:"auth login [--no-browser] [--token <pat>]",summary:"Sign in through the portal callback or save a founder PAT.",options:["--no-browser Skip browser login. Saves the PAT or fails without one.","--token <pat> Founder PAT. Defaults to HYPERSCALE_TOKEN.","--json Print the saved session summary as one JSON document."],notes:["Without a PAT, the CLI opens portal sign-in and accepts one","localhost callback.","With --no-browser and no token, the command fails with a login","error and fix text. Pass HYPERSCALE_TOKEN or --token to save a PAT.","Set HYPERSCALE_CREDENTIAL_STORE=file to use the 0600 profile file","instead of macOS Keychain."],example:"hyperscale auth login --no-browser"},"auth status":{usage:"auth status [--json]",summary:"Verify and show the active founder PAT and selected Product.",options:["--json Print machine-readable JSON."],example:"hyperscale auth status --json"},"auth logout":{usage:"auth logout [--revoke] [--json]",summary:"Forget the local founder PAT. Optionally revoke it first.",options:["--revoke Revoke the PAT before deleting local state.","--json Print machine-readable JSON."],example:"hyperscale auth logout --revoke"},"blueprint list":{usage:"blueprint list [--json]",summary:"List public Blueprints without authentication.",options:["--json Print the complete collection as JSON."],example:"hyperscale blueprint list"},"blueprint show":{usage:"blueprint show <id> [--json]",summary:"Show one public Blueprint.",options:["--json Print the complete Blueprint as JSON."],example:"hyperscale blueprint show luxury-goods-consignment-escrow"},"product create":{usage:"product create (--blueprint <id> | --source <file>) --name <name> [--catalog-revision <id>] [--json]",summary:"Create and select a Product. The command refuses a duplicate name.",options:["--blueprint <id> Blueprint id to compose from.","--source <file> HSX source file for initial Product creation.","--name <name> Required Product name.","--catalog-revision <id> Tenant catalog revision for HSX composition.","--json Print the creation summary as JSON."],example:'hyperscale product create --blueprint luxury-goods-consignment-escrow --name "Luxury Consignment"'},"product list":{usage:"product list [--json]",summary:"List Products in the signed-in company.",options:["--json Print the complete collection as JSON."],example:"hyperscale product list"},"product show":{usage:"product show [id] [--json]",summary:"Show a Product summary, or the complete Product document as JSON.",options:["--json Print the complete Product document."],example:"hyperscale product show prd_sandbox_..."},"product select":{usage:"product select <id> [--json]",summary:"Verify a Product and save it as the default for later commands.",options:["--token <pat> Founder PAT. Defaults to HYPERSCALE_TOKEN or the stored login.","--base-url <url> API origin. Defaults to the active founder profile.","--environment <name> sandbox or live. Defaults to the active founder profile.","--json Print the selected Product id as JSON."],notes:["The CLI stores the selection in the active founder profile.","Product show, compose plan/apply, and key commands use it when --product is absent.","Product create and start select the Product they create."],example:"hyperscale product select prd_sandbox_..."},"product actions":{usage:"product actions [operation-id] [--product <id>] [--json]",summary:"List frozen public actions or show one action's full schemas.",options:["--product <id> Product to inspect. Defaults to the selected Product.","--api-key <key> Product API key. Defaults to HYPERSCALE_API_KEY.","--json Print machine-readable JSON."],notes:["Setup operation details include the public input schema used by hyperscale call.","When that schema has no required fields, omit --input or pass {}."],example:"hyperscale product actions escrow_order.placeBuyerHold --json"},"product run":{usage:"product run <operation-id> [--input <json> | --input-file <path>] [--idempotency-key <key>] [--json]",summary:"Run one frozen public action with a Product API key.",options:["--input <json> JSON input object. Stdin is used when piped.","--input-file <path> Read the JSON input object from a file.","--product <id> Product to call. Defaults to the selected Product.","--api-key <key> Product API key. Defaults to HYPERSCALE_API_KEY.","--idempotency-key <key> Send this exact Idempotency-Key header. The default is a generated UUID.","--json Print the key, receipt ids, and output as JSON."],notes:["Reuse an Idempotency-Key only with the same operation and input.",'If a bounded validation value appears as "[Truncated]", run "hyperscale product actions <operation-id>" for the full input schema.'],example:`hyperscale product run escrow_order.placeBuyerHold --input '{"escrowOrderId":"eord_sandbox_..."}' --idempotency-key hold-001`},"compose check":{usage:"compose check <file.hsx> [--catalog-revision <id>] [--json]",summary:"Ask the server to compile and check an HSX program.",options:["--catalog-revision <id> Compile against this immutable tenant catalog revision.","--json Print diagnostics and the verdict as JSON."],example:"hyperscale compose check product.hsx"},"compose plan":{usage:"compose plan <file.hsx> [--product <id>] [--catalog-revision <id>] [--json]",summary:"Diff an HSX program against a Product.",options:["--product <id> Product to compare. Defaults to the selected Product.","--catalog-revision <id> Compile against this immutable tenant catalog revision.","--json Print the plan as JSON."],example:"hyperscale compose plan product.hsx --json"},"compose apply":{usage:"compose apply <file.hsx> (--confirm [--pricing-identity <id> | --plan-file <path>] | --yes) [--product <id>] [--catalog-revision <id>] [--json]",summary:"Recompose the selected Product from checked HSX.",options:["--confirm Confirm the mutation for a person.","--yes Confirm the mutation without a prompt for an agent; accepts the candidate price current at apply time.","--pricing-identity <id> Candidate pricing identity from compose plan. Required with --confirm only when scheduled pricing exists.","--plan-file <path> Saved JSON plan file from compose plan --json. Used with --confirm to extract pricing identity when scheduled pricing exists.","--product <id> Product to recompose. Defaults to the selected Product.","--catalog-revision <id> Compile and persist against this immutable tenant catalog revision.","--json Print the result as JSON."],notes:["Apply --confirm requires a reviewed pricing identity or saved plan only when plan.pricing.scheduled exists; --yes selects the current candidate."],example:"hyperscale compose apply product.hsx --yes --pricing-identity <id>"},"key create":{usage:"key create [--name <name>] [--product <id>] [--json]",summary:"Create a sandbox Product API key.",options:["--name <name> Key name. Defaults to Founder CLI.","--product <id> Product for the key. Defaults to the selected Product.","--json Print the one-time secret and key metadata as JSON."],example:'hyperscale key create --name "Founder laptop"'},"key list":{usage:"key list [--product <id>] [--json]",summary:"List keys for one Product.",options:["--product <id> Product to inspect. Defaults to the selected Product.","--json Print the collection as JSON."],example:"hyperscale key list --json"},"key revoke":{usage:"key revoke <id> [--product <id>] [--json]",summary:"Revoke one Product API key.",options:["--product <id> Product that owns the key. Defaults to the selected Product.","--json Print the result as JSON."],example:"hyperscale key revoke key_sandbox_..."},"activity list":{usage:"activity list [--json]",summary:"List company activity with timestamps and resource targets.",options:["--json Print the complete collection as JSON."],example:"hyperscale activity list"},whoami:{usage:"whoami [--json]",summary:"Show the user and company the founder PAT resolves to.",options:["--json Print machine-readable JSON."],example:"hyperscale whoami --json"},"ops list":{usage:"ops list [filter] [--product <id>] [--json]",summary:"List callable operations from the Product machine document.",options:["filter Optional case-insensitive substring filter matching operation names and paths.","--product <id> Product to inspect. The Product API key must belong to it.","--api-key <key> Product API key. Defaults to HYPERSCALE_API_KEY.","--json Print matching operations as JSON."],notes:["The optional filter argument matches operation names and paths by case-insensitive substring."],example:"hyperscale ops list account"},call:{usage:"call <operation> [--input <json> | --input-file <path>] [--idempotency-key <key>] [--product <id>]",summary:"Call one operation from the Product machine document.",options:["--input <json> JSON input object. Stdin is used when piped.","--input-file <path> Read the JSON input object from a file.","--product <id> Product to call. The Product API key must belong to it.","--api-key <key> Product API key. Defaults to HYPERSCALE_API_KEY.","--idempotency-key <key> Send this exact Idempotency-Key header for a mutation. The default is a generated UUID."],notes:["Reuse an Idempotency-Key only with the same operation and input."],example:`hyperscale call account.create --input '{"currency":"SAR"}'`},help:{usage:"help [command]",summary:"Print help for hyperscale or a specific command.",options:[],notes:['Pass a command name to read its usage, options, and examples (e.g. "hyperscale help product create").'],example:"hyperscale help product create"}};function ze(e,t){let n=t??P(process.stdout,process.env,{json:!1}),o=Object.keys(we).sort((a,c)=>c.split(" ").length-a.split(" ").length),r=o.find(a=>a.split(" ").every((l,p)=>e[p]===l));if(r){let a=we[r];return ye(n,{usage:a.usage,summary:a.summary,options:a.options,notes:a.notes,example:a.example})}let s=e.join(" "),i=o.filter(a=>a.startsWith(`${s} `));if(i.length>0)return ye(n,{prefix:s,subcommands:i.map(a=>[a.slice(s.length+1),we[a].summary])});throw new d(`No help for ${e.join(" ")}. Run "hyperscale --help" to list commands.`,{fix:'Run "hyperscale --help" to list commands.'})}var d=class extends Error{constructor(t,n={}){super(t),typeof n.code=="string"&&(this.code=n.code),n.details!==void 0&&(this.details=n.details),Number.isInteger(n.exitCode)&&(this.exitCode=n.exitCode),typeof n.fix=="string"&&(this.fix=n.fix)}},O=class extends d{constructor(t,{requestId:n,status:o,code:r,details:s,operationId:i,receiptId:a,traceId:c,structuredError:l,fix:p}={}){super(t,{code:r,details:s,fix:p}),this.requestId=n,this.status=o,this.operationId=i??null,this.receiptId=a??null,this.traceId=c??null,this.structuredError=l}};function Y(){return new d(Ft,{fix:Wt})}function st(e){let t=e??"<id>";return new d(`This command needs a Product API key. Create one with "hyperscale key create --name 'Founder CLI' --product ${t}", then set HYPERSCALE_API_KEY or pass --api-key.`,{fix:`Run "hyperscale key create --name 'Founder CLI' --product ${t}", then set HYPERSCALE_API_KEY or pass --api-key.`})}var oe=class extends d{constructor(t,n){super(t),this.code="check_failed",this.details=n,this.exitCode=2}},Xt=new Set(["--api-key","--base-url","--blueprint","--catalog-revision","--environment","--idempotency-key","--input","--input-file","--name","--plan-file","--pricing-identity","--product","--source","--token"]);function Zt(e){let t=[],n={};for(let o=0;o<e.length;o+=1){let r=e[o];if(r==="-h")r="--help";else if(r==="-v")r="--version";else if(r.startsWith("-")&&!r.startsWith("--"))throw new d(`Unknown option: ${r}`);if(!r.startsWith("--")){t.push(r);continue}if(Xt.has(r)){let s=e[o+1];if(s===void 0)throw new d(`${r} needs a value`);n[r]=s,o+=1;continue}if(r==="--help"||r==="--version"||r==="--json"||r==="--confirm"||r==="--yes"||r==="--no-browser"||r==="--revoke"){n[r]=!0;continue}throw new d(`Unknown option: ${r}`)}return{flags:n,positional:t}}function Ve(e,t){let n=e["--api-key"]??t.HYPERSCALE_API_KEY;if(!n)throw st();let o=e["--environment"]??t.HYPERSCALE_ENVIRONMENT??ot;if(o!=="sandbox"&&o!=="live")throw new d(`Unknown environment: ${o}. Use sandbox or live.`);let r=(e["--base-url"]??t.HYPERSCALE_BASE_URL??nt).replace(/\/+$/,"");return{apiKey:n,baseUrl:r,environment:o}}function q(e,t,n={}){let o=e["--environment"]??t.HYPERSCALE_ENVIRONMENT??n.environment??ot;if(o!=="sandbox"&&o!=="live")throw new d(`Unknown environment: ${o}. Use sandbox or live.`);let r=(e["--base-url"]??t.HYPERSCALE_BASE_URL??n.baseUrl??nt).replace(/\/+$/,"");return je(r),{baseUrl:r,environment:o}}function it(e){return e.HYPERSCALE_CONFIG_DIR??ie(Bt(),".config","hyperscale")}function at(e){return ie(it(e),qt)}function E(e,t){return ie(it(t),`session-${z(e)}.json`)}function ae(e){let t=e.HYPERSCALE_CREDENTIAL_STORE??"auto";if(t==="auto"||t==="file")return t;throw new d(`Unknown HYPERSCALE_CREDENTIAL_STORE value: ${t}. Use auto or file.`)}async function Ce(e,t){let n=E(e,t),o=`${Yt(n)}.`,r;try{r=await Ht(be(n),{withFileTypes:!0})}catch(s){if(s&&s.code==="ENOENT")return;throw s}for(let s of r){if(!s.isFile()||!s.name.startsWith(o))continue;let i=s.name.slice(o.length);/^\d+\.[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\.tmp$/.test(i)&&await F(ie(be(n),s.name))}}async function Qt(e){try{return JSON.parse(await W(e,"utf8"))}catch(t){if(t&&t.code==="ENOENT")return null;throw t instanceof SyntaxError?new d(`The CLI profile at ${e} is corrupt: not valid JSON.`,{code:"corrupt_profile",fix:`Back up or remove ${e} before logging in again with "hyperscale auth login" (or "hyperscale auth login --no-browser").`}):t}}async function M(e,t){let n=en(e);await Ut(n,{mode:448,recursive:!0}),await ge(n,448);let o=`${e}.${process.pid}.${globalThis.crypto.randomUUID()}.tmp`;await Jt(o,t,{flag:"wx",mode:384}),await ge(o,384);try{await Dt(o,e),await ge(e,384)}catch(r){throw await F(o),r}}function en(e){return be(e)}async function F(e){try{await Kt(e)}catch(t){if(!t||t.code!=="ENOENT")throw t}}function tn(e,t){if(!e||typeof e!="object"||Array.isArray(e))throw new d(`The CLI profile at ${t} is corrupt: not a profile object.`,{code:"corrupt_profile",fix:`Back up or remove ${t} before logging in again with "hyperscale auth login" (or "hyperscale auth login --no-browser").`});let{baseUrl:n,email:o,environment:r,selectedProduct:s}=e;if(typeof n!="string"||typeof o!="string"||r!=="sandbox"&&r!=="live"||!(s===null||typeof s=="string"))throw new d(`The CLI profile at ${t} is corrupt: invalid profile fields.`,{code:"corrupt_profile",fix:`Back up or remove ${t} before logging in again with "hyperscale auth login" (or "hyperscale auth login --no-browser").`});return{baseUrl:n,email:o,environment:r,selectedProduct:s}}async function ce(e){let t=at(e),n=await Qt(t);return n===null?null:tn(n,t)}async function ue(e,t){let n={email:t.email,baseUrl:t.baseUrl,environment:t.environment,selectedProduct:t.selectedProduct??null};await M(at(e),`${JSON.stringify(n,null,2)}
|
|
17
|
-
`)}function
|
|
18
|
-
`)})}async function
|
|
19
|
-
`),"file"}async function
|
|
20
|
-
`),{keychainDeleted:!0};if(
|
|
21
|
-
`),{keychainDeleted:!1};let o=await
|
|
22
|
-
`),{keychainDeleted:!1}):(await
|
|
23
|
-
\r`.includes(t)?t:"")}function
|
|
13
|
+
`);n.push(`${a}${c[0]}`);let u=" ".repeat(a.length);for(let l=1;l<c.length;l++)n.push(`${u}${c[l]}`)}else n.push(`${a}${i}`)}return n.join(`
|
|
14
|
+
`)}function Me(e,t){let n=e.text(t.action),o=e.text(t.subject),r=typeof t.confirmation=="string"&&t.confirmation.trim()?e.text(t.confirmation):"Continue?";return[e.strong("Confirm mutation"),"",` Action: ${n}`,` Subject: ${o}`,"",` ${r} [y/N]`].join(`
|
|
15
|
+
`)}function qe(e,t){let n=e.text(String(t.code)),o=e.text(t.message),r=e.accent(t.nextStep);return[e.strong(`Error [${n}]`),o,"",`Next step: ${r}`].join(`
|
|
16
|
+
`)}var Xe="https://hyperscale0.ai",Ze="sandbox",Se="hyperscale-cli-session",Yt="/v1/personal-access-tokens/current",Ie=process.platform==="darwin"?"/usr/bin/security":null,Mt="config.json",Re="https://hyperscale0.ai/desk/security/tokens",Qe="https://hyperscale0.ai/request-access",Be=`Mint a founder PAT in Hyperscale Portal at ${Re}. Open Security, then Personal access tokens.`,qt=`Not logged in. Run "hyperscale auth login" to open Hyperscale Portal sign-in. In a headless environment, mint a founder PAT in Hyperscale Portal at ${Re}. Open Security, then Personal access tokens. Then set HYPERSCALE_TOKEN or pass --token. Unapproved founders can request access at ${Qe}.`,Bt=`Run "hyperscale auth login". For headless use, mint a founder PAT in Hyperscale Portal at ${Re}. Open Security, then Personal access tokens. Unapproved founders can request access at ${Qe}.`,Pe=3e4,Ft=2e3,Wt=120*1e3,ye={"auth login":{usage:"auth login [--no-browser] [--token <pat>]",summary:"Sign in through the portal callback or save a founder PAT.",options:["--no-browser Skip browser login. Saves the PAT or fails without one.","--token <pat> Founder PAT. Defaults to HYPERSCALE_TOKEN.","--json Print the saved session summary as one JSON document."],notes:["Without a PAT, the CLI opens portal sign-in and accepts one","localhost callback.","With --no-browser and no token, the command fails with a login","error and fix text. Pass HYPERSCALE_TOKEN or --token to save a PAT.","Set HYPERSCALE_CREDENTIAL_STORE=file to use the 0600 profile file","instead of macOS Keychain."],example:"hyperscale auth login --no-browser"},"auth status":{usage:"auth status [--json]",summary:"Verify and show the active founder PAT and selected Product.",options:["--json Print machine-readable JSON."],example:"hyperscale auth status --json"},"auth logout":{usage:"auth logout [--revoke] [--json]",summary:"Forget the local founder PAT. Optionally revoke it first.",options:["--revoke Revoke the PAT before deleting local state.","--json Print machine-readable JSON."],example:"hyperscale auth logout --revoke"},"product create":{usage:"product create --source <file> --name <name> [--catalog-revision <id>] [--json]",summary:"Create and select a Product. The command refuses a duplicate name.",options:["--source <file> HSX source file for initial Product creation.","--name <name> Required Product name.","--catalog-revision <id> Tenant catalog revision for HSX composition.","--json Print the creation summary as JSON."],example:'hyperscale product create --source product.hsx --name "Custom Product"'},"product list":{usage:"product list [--json]",summary:"List Products in the signed-in company.",options:["--json Print the complete collection as JSON."],example:"hyperscale product list"},"product show":{usage:"product show [id] [--json]",summary:"Show a Product summary, or the complete Product document as JSON.",options:["--json Print the complete Product document."],example:"hyperscale product show prd_sandbox_..."},"product select":{usage:"product select <id> [--json]",summary:"Verify a Product and save it as the default for later commands.",options:["--token <pat> Founder PAT. Defaults to HYPERSCALE_TOKEN or the stored login.","--base-url <url> API origin. Defaults to the active founder profile.","--environment <name> sandbox or live. Defaults to the active founder profile.","--json Print the selected Product id as JSON."],notes:["The CLI stores the selection in the active founder profile.","Product show, compose plan/apply, and key commands use it when --product is absent.","Product create selects the Product it creates."],example:"hyperscale product select prd_sandbox_..."},"product actions":{usage:"product actions [operation-id] [--product <id>] [--json]",summary:"List frozen public actions or show one action's full schemas.",options:["--product <id> Product to inspect. Defaults to the selected Product.","--api-key <key> Product API key. Defaults to HYPERSCALE_API_KEY.","--json Print machine-readable JSON."],notes:["Setup operation details include the public input schema used by hyperscale call.","When that schema has no required fields, omit --input or pass {}."],example:"hyperscale product actions escrow_order.placeBuyerHold --json"},"product run":{usage:"product run <operation-id> [--input <json> | --input-file <path>] [--idempotency-key <key>] [--json]",summary:"Run one frozen public action with a Product API key.",options:["--input <json> JSON input object. Stdin is used when piped.","--input-file <path> Read the JSON input object from a file.","--product <id> Product to call. Defaults to the selected Product.","--api-key <key> Product API key. Defaults to HYPERSCALE_API_KEY.","--idempotency-key <key> Send this exact Idempotency-Key header. The default is a generated UUID.","--json Print the key, receipt ids, and output as JSON."],notes:["Reuse an Idempotency-Key only with the same operation and input.",'If a bounded validation value appears as "[Truncated]", run "hyperscale product actions <operation-id>" for the full input schema.'],example:`hyperscale product run escrow_order.placeBuyerHold --input '{"escrowOrderId":"eord_sandbox_..."}' --idempotency-key hold-001`},"compose check":{usage:"compose check <file.hsx> [--catalog-revision <id>] [--json]",summary:"Ask the server to compile and check an HSX program.",options:["--catalog-revision <id> Compile against this immutable tenant catalog revision.","--json Print diagnostics and the verdict as JSON."],example:"hyperscale compose check product.hsx"},"compose plan":{usage:"compose plan <file.hsx> [--product <id>] [--catalog-revision <id>] [--json]",summary:"Diff an HSX program against a Product.",options:["--product <id> Product to compare. Defaults to the selected Product.","--catalog-revision <id> Compile against this immutable tenant catalog revision.","--json Print the plan as JSON."],example:"hyperscale compose plan product.hsx --json"},"compose apply":{usage:"compose apply <file.hsx> (--confirm [--pricing-identity <id> | --plan-file <path>] | --yes) [--product <id>] [--catalog-revision <id>] [--json]",summary:"Recompose the selected Product from checked HSX.",options:["--confirm Confirm the mutation for a person.","--yes Confirm the mutation without a prompt for an agent; accepts the candidate price current at apply time.","--pricing-identity <id> Candidate pricing identity from compose plan. Required with --confirm only when scheduled pricing exists.","--plan-file <path> Saved JSON plan file from compose plan --json. Used with --confirm to extract pricing identity when scheduled pricing exists.","--product <id> Product to recompose. Defaults to the selected Product.","--catalog-revision <id> Compile and persist against this immutable tenant catalog revision.","--json Print the result as JSON."],notes:["Apply --confirm requires a reviewed pricing identity or saved plan only when plan.pricing.scheduled exists; --yes selects the current candidate."],example:"hyperscale compose apply product.hsx --yes --pricing-identity <id>"},"key create":{usage:"key create [--name <name>] [--product <id>] [--json]",summary:"Create a sandbox Product API key.",options:["--name <name> Key name. Defaults to Founder CLI.","--product <id> Product for the key. Defaults to the selected Product.","--json Print the one-time secret and key metadata as JSON."],example:'hyperscale key create --name "Founder laptop"'},"key list":{usage:"key list [--product <id>] [--json]",summary:"List keys for one Product.",options:["--product <id> Product to inspect. Defaults to the selected Product.","--json Print the collection as JSON."],example:"hyperscale key list --json"},"key revoke":{usage:"key revoke <id> [--product <id>] [--json]",summary:"Revoke one Product API key.",options:["--product <id> Product that owns the key. Defaults to the selected Product.","--json Print the result as JSON."],example:"hyperscale key revoke key_sandbox_..."},"activity list":{usage:"activity list [--json]",summary:"List company activity with timestamps and resource targets.",options:["--json Print the complete collection as JSON."],example:"hyperscale activity list"},whoami:{usage:"whoami [--json]",summary:"Show the user and company the founder PAT resolves to.",options:["--json Print machine-readable JSON."],example:"hyperscale whoami --json"},"ops list":{usage:"ops list [filter] [--product <id>] [--json]",summary:"List callable operations from the Product machine document.",options:["filter Optional case-insensitive substring filter matching operation names and paths.","--product <id> Product to inspect. The Product API key must belong to it.","--api-key <key> Product API key. Defaults to HYPERSCALE_API_KEY.","--json Print matching operations as JSON."],notes:["The optional filter argument matches operation names and paths by case-insensitive substring."],example:"hyperscale ops list account"},call:{usage:"call <operation> [--input <json> | --input-file <path>] [--idempotency-key <key>] [--product <id>]",summary:"Call one operation from the Product machine document.",options:["--input <json> JSON input object. Stdin is used when piped.","--input-file <path> Read the JSON input object from a file.","--product <id> Product to call. The Product API key must belong to it.","--api-key <key> Product API key. Defaults to HYPERSCALE_API_KEY.","--idempotency-key <key> Send this exact Idempotency-Key header for a mutation. The default is a generated UUID."],notes:["Reuse an Idempotency-Key only with the same operation and input."],example:`hyperscale call account.create --input '{"currency":"SAR"}'`},help:{usage:"help [command]",summary:"Print help for hyperscale or a specific command.",options:[],notes:['Pass a command name to read its usage, options, and examples (e.g. "hyperscale help product create").'],example:"hyperscale help product create"}};function Fe(e,t){let n=t??b(process.stdout,process.env,{json:!1}),o=Object.keys(ye).sort((a,c)=>c.split(" ").length-a.split(" ").length),r=o.find(a=>a.split(" ").every((u,l)=>e[l]===u));if(r){let a=ye[r];return me(n,{usage:a.usage,summary:a.summary,options:a.options,notes:a.notes,example:a.example})}let s=e.join(" "),i=o.filter(a=>a.startsWith(`${s} `));if(i.length>0)return me(n,{prefix:s,subcommands:i.map(a=>[a.slice(s.length+1),ye[a].summary])});throw new d(`No help for ${e.join(" ")}. Run "hyperscale --help" to list commands.`,{fix:'Run "hyperscale --help" to list commands.'})}var d=class extends Error{constructor(t,n={}){super(t),typeof n.code=="string"&&(this.code=n.code),n.details!==void 0&&(this.details=n.details),Number.isInteger(n.exitCode)&&(this.exitCode=n.exitCode),typeof n.fix=="string"&&(this.fix=n.fix)}},O=class extends d{constructor(t,{requestId:n,status:o,code:r,details:s,operationId:i,receiptId:a,traceId:c,structuredError:u,fix:l}={}){super(t,{code:r,details:s,fix:l}),this.requestId=n,this.status=o,this.operationId=i??null,this.receiptId=a??null,this.traceId=c??null,this.structuredError=u}};function J(){return new d(qt,{fix:Bt})}function et(e){let t=e??"<id>";return new d(`This command needs a Product API key. Create one with "hyperscale key create --name 'Founder CLI' --product ${t}", then set HYPERSCALE_API_KEY or pass --api-key.`,{fix:`Run "hyperscale key create --name 'Founder CLI' --product ${t}", then set HYPERSCALE_API_KEY or pass --api-key.`})}var te=class extends d{constructor(t,n){super(t),this.code="check_failed",this.details=n,this.exitCode=2}},zt=new Set(["--api-key","--base-url","--catalog-revision","--environment","--idempotency-key","--input","--input-file","--name","--plan-file","--pricing-identity","--product","--source","--token"]);function Vt(e){let t=[],n={};for(let o=0;o<e.length;o+=1){let r=e[o];if(r==="-h")r="--help";else if(r==="-v")r="--version";else if(r.startsWith("-")&&!r.startsWith("--"))throw new d(`Unknown option: ${r}`);if(!r.startsWith("--")){t.push(r);continue}if(zt.has(r)){let s=e[o+1];if(s===void 0)throw new d(`${r} needs a value`);n[r]=s,o+=1;continue}if(r==="--help"||r==="--version"||r==="--json"||r==="--confirm"||r==="--yes"||r==="--no-browser"||r==="--revoke"){n[r]=!0;continue}throw new d(`Unknown option: ${r}`)}return{flags:n,positional:t}}function We(e,t){let n=e["--api-key"]??t.HYPERSCALE_API_KEY;if(!n)throw et();let o=e["--environment"]??t.HYPERSCALE_ENVIRONMENT??Ze;if(o!=="sandbox"&&o!=="live")throw new d(`Unknown environment: ${o}. Use sandbox or live.`);let r=(e["--base-url"]??t.HYPERSCALE_BASE_URL??Xe).replace(/\/+$/,"");return{apiKey:n,baseUrl:r,environment:o}}function ne(e,t,n={}){let o=e["--environment"]??t.HYPERSCALE_ENVIRONMENT??n.environment??Ze;if(o!=="sandbox"&&o!=="live")throw new d(`Unknown environment: ${o}. Use sandbox or live.`);let r=(e["--base-url"]??t.HYPERSCALE_BASE_URL??n.baseUrl??Xe).replace(/\/+$/,"");return ve(r),{baseUrl:r,environment:o}}function tt(e){return e.HYPERSCALE_CONFIG_DIR??se(Kt(),".config","hyperscale")}function nt(e){return se(tt(e),Mt)}function R(e,t){return se(tt(t),`session-${B(e)}.json`)}function ie(e){let t=e.HYPERSCALE_CREDENTIAL_STORE??"auto";if(t==="auto"||t==="file")return t;throw new d(`Unknown HYPERSCALE_CREDENTIAL_STORE value: ${t}. Use auto or file.`)}async function Ee(e,t){let n=R(e,t),o=`${Jt(n)}.`,r;try{r=await Lt(ke(n),{withFileTypes:!0})}catch(s){if(s&&s.code==="ENOENT")return;throw s}for(let s of r){if(!s.isFile()||!s.name.startsWith(o))continue;let i=s.name.slice(o.length);/^\d+\.[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\.tmp$/.test(i)&&await M(se(ke(n),s.name))}}async function Gt(e){try{return JSON.parse(await q(e,"utf8"))}catch(t){if(t&&t.code==="ENOENT")return null;throw t instanceof SyntaxError?new d(`The CLI profile at ${e} is corrupt: not valid JSON.`,{code:"corrupt_profile",fix:`Back up or remove ${e} before logging in again with "hyperscale auth login" (or "hyperscale auth login --no-browser").`}):t}}async function Y(e,t){let n=Xt(e);await _t(n,{mode:448,recursive:!0}),await he(n,448);let o=`${e}.${process.pid}.${globalThis.crypto.randomUUID()}.tmp`;await Dt(o,t,{flag:"wx",mode:384}),await he(o,384);try{await Ut(o,e),await he(e,384)}catch(r){throw await M(o),r}}function Xt(e){return ke(e)}async function M(e){try{await Ht(e)}catch(t){if(!t||t.code!=="ENOENT")throw t}}function Zt(e,t){if(!e||typeof e!="object"||Array.isArray(e))throw new d(`The CLI profile at ${t} is corrupt: not a profile object.`,{code:"corrupt_profile",fix:`Back up or remove ${t} before logging in again with "hyperscale auth login" (or "hyperscale auth login --no-browser").`});let{baseUrl:n,email:o,environment:r,selectedProduct:s}=e;if(typeof n!="string"||typeof o!="string"||r!=="sandbox"&&r!=="live"||!(s===null||typeof s=="string"))throw new d(`The CLI profile at ${t} is corrupt: invalid profile fields.`,{code:"corrupt_profile",fix:`Back up or remove ${t} before logging in again with "hyperscale auth login" (or "hyperscale auth login --no-browser").`});return{baseUrl:n,email:o,environment:r,selectedProduct:s}}async function ae(e){let t=nt(e),n=await Gt(t);return n===null?null:Zt(n,t)}async function Te(e,t){let n={email:t.email,baseUrl:t.baseUrl,environment:t.environment,selectedProduct:t.selectedProduct??null};await Y(nt(e),`${JSON.stringify(n,null,2)}
|
|
17
|
+
`)}function B(e){return Ot("sha256").update(`${e.baseUrl}\0${e.environment}\0${e.email}`).digest("hex")}async function ce(e,t){return Ie===null?{error:null,status:null,stdout:"",unavailable:!0}:await new Promise(n=>{let o={...process.env};delete o.HYPERSCALE_API_KEY,delete o.HYPERSCALE_TOKEN;let r=Ge(Ie,e,{env:o,stdio:["pipe","pipe","pipe"]}),s=[],i=!1,a=u=>{i||(i=!0,clearTimeout(c),n(u))},c=setTimeout(()=>{r.kill("SIGKILL"),a({error:null,status:null,stdout:"",unavailable:!0})},Ft);r.stdout.on("data",u=>s.push(u)),r.stderr.on("data",()=>{}),r.stdin.on("error",()=>{}),r.once("error",u=>a({error:u,status:null,stdout:"",unavailable:!0})),r.once("close",u=>a({error:null,status:u,stdout:Buffer.concat(s).toString("utf8"),unavailable:!1})),t===void 0?r.stdin.end():r.stdin.end(`${t}
|
|
18
|
+
`)})}async function Ce(){return(await ce(["show-keychain-info"])).status===0}function ot(e){try{let t=typeof e=="string"?JSON.parse(e):e;if(t&&typeof t=="object"&&!Array.isArray(t)&&typeof t.token=="string"&&typeof t.tenantId=="string"&&(t.personalAccessTokenId===void 0||typeof t.personalAccessTokenId=="string")&&(t.tokenName===void 0||typeof t.tokenName=="string"))return{token:t.token,tenantId:t.tenantId,...t.personalAccessTokenId?{personalAccessTokenId:t.personalAccessTokenId}:{},...t.tokenName?{tokenName:t.tokenName}:{}}}catch{}return null}async function Qt(e,t,n){await Ee(e,n);let o=B(e);if(ie(n)==="auto"&&await Ce()){let r=JSON.stringify(t),s=["add-generic-password","-a",o,"-s",Se,"-U","-X",Buffer.from(r,"utf8").toString("hex")].join(" ");if((await ce(["-i"],s)).status===0)return await M(R(e,n)),"keychain"}return await Y(R(e,n),`${JSON.stringify({account:o,activeStore:"file",credential:t})}
|
|
19
|
+
`),"file"}async function en(e,t){let n=B(e);try{let o=JSON.parse(await q(R(e,t),"utf8"));if(!o||typeof o!="object"||Array.isArray(o)||o.account!==n)return{state:"invalid"};if(o.revoked===!0)return{state:"revoked"};let r=ot(o.credential);return r?{activeStore:o.activeStore==="file"?"file":null,credential:r,state:"valid"}:{state:"invalid"}}catch(o){return o&&o.code==="ENOENT"?{state:"missing"}:{state:"invalid"}}}async function rt(e,t){await Ee(e,t);let n=ie(t),o=await en(e,t);if(o.state==="revoked")return null;if(o.state==="valid"&&(o.activeStore==="file"||n==="file"))return o.credential;if(n==="file")return null;let r=null;if(await Ce()){let s=await ce(["find-generic-password","-a",B(e),"-s",Se,"-w"]);s.status===0&&(r=ot(s.stdout.trim()))}return r||(o.state==="valid"?o.credential:null)}async function st(e,t){await Ee(e,t);let n=B(e);if(ie(t)==="file")return await Y(R(e,t),`${JSON.stringify({account:n,revoked:!0})}
|
|
20
|
+
`),{keychainDeleted:!0};if(Ie===null)return await M(R(e,t)),{keychainDeleted:!0};if(!await Ce())return await Y(R(e,t),`${JSON.stringify({account:n,revoked:!0})}
|
|
21
|
+
`),{keychainDeleted:!1};let o=await ce(["delete-generic-password","-a",n,"-s",Se]);return o.status!==0&&o.status!==44?(await Y(R(e,t),`${JSON.stringify({account:n,revoked:!0})}
|
|
22
|
+
`),{keychainDeleted:!1}):(await M(R(e,t)),{keychainDeleted:!0})}function it(e,t){return e["--token"]!==void 0?e["--token"]:t.HYPERSCALE_TOKEN||void 0}async function $(e,t,n=!1){let o=await ae(t),r=it(e,t);if(r!==void 0){if(!r)throw J();let a=ne(e,t,o??{}),c=await U(a,r),u=o?.baseUrl===a.baseUrl&&o.environment===a.environment&&o.email===c.email;return{...a,email:c.email,identity:c,personalAccessTokenId:c.personalAccessTokenId,selectedProduct:u?o.selectedProduct:null,tenantId:c.tenantId,token:r,tokenName:c.name}}if(!o){if(n)return null;throw J()}let s=ne(e,t,o);if(s.baseUrl!==o.baseUrl||s.environment!==o.environment)throw new d(`The active founder login belongs to ${o.baseUrl} (${o.environment}). Log in again to change it.`);let i=await rt(o,t);if(!i){if(n)return null;throw J()}return{...o,...i}}function w(e){return e.replace(new RegExp("\\p{Cc}","gu"),t=>`
|
|
23
|
+
\r`.includes(t)?t:"")}function at(e){try{return new URL(e).origin}catch{return null}}function ve(e){let t;try{t=new URL(e)}catch{t=null}if(!t||t.origin!==e)throw new d(`Invalid API origin: ${e}. Use a scheme, host, and optional port with nothing after them, such as https://hyperscale0.ai.`);let n=["localhost","127.0.0.1","[::1]","::1"].includes(t.hostname);if(t.protocol!=="https:"&&!(t.protocol==="http:"&&n))throw new d(`Refusing cleartext API origin ${e}: no credential was sent. Use https://${t.host} instead, or keep http:// only for a loopback API such as http://127.0.0.1:8787.`);return t.origin}var tn=/(?<![A-Za-z0-9_-])(?:hyperscale|arc)_[A-Za-z0-9_-]{32,}(?![A-Za-z0-9_-])/g,nn=/(?<![A-Za-z0-9_-])whsec_[A-Za-z0-9+/=]{32,}(?![A-Za-z0-9+/=])/g;function y(e,t=[]){let n=e;for(let o of t)typeof o=="string"&&o.length>0&&(n=n.replaceAll(o,"[redacted]"));return n.replaceAll(tn,"[redacted]").replaceAll(nn,"[redacted]")}function ct(e,t=[]){if(!e?.ok||!e?.headers)return;let n=e.headers.get("x-request-id"),o=e.headers.get("hyperscale-operation-id"),r=e.headers.get("hyperscale-receipt-id"),s=n?y(n,t):null,i=o?y(o,t):null,a=r?y(r,t):null;s&&process.stderr.write(`Request id: ${s}
|
|
24
24
|
`),i&&process.stderr.write(`Operation: ${i}
|
|
25
25
|
`),a&&process.stderr.write(`Receipt: ${a}
|
|
26
|
-
`)}async function
|
|
27
|
-
Request id: ${r.requestId}`:""}`,{code:o.code,details:o.details,fix:o.fix,operationId:r.operationId,receiptId:r.receiptId,requestId:r.requestId,status:e.status,structuredError:o.structuredError,traceId:r.traceId})}function
|
|
26
|
+
`)}async function Oe(e,t,n={},o){let r=`${e.baseUrl}${t}`,s=ve(e.baseUrl);if(at(r)!==s)throw new d(`The requested path ${t} leaves the ${s} origin; refusing the request.`);let i=[o].filter(Boolean);try{let a=await fetch(r,{...n,headers:{accept:"application/json",...o?{authorization:`Bearer ${o}`}:{},"x-hyperscale-environment":e.environment,...n.headers},signal:AbortSignal.timeout(Pe),redirect:"manual"});if(a.status>=300&&a.status<400){let c=w(y(r,i));throw new d(`${c} redirected, so no credential was sent on. Point --base-url at the origin the API answers on.`,{code:"unexpected_redirect",fix:"Point --base-url at the origin the API answers on."})}return ct(a,i),{response:a,text:w(await a.text())}}catch(a){if(a instanceof d)throw a;let c=w(y(r,i)),u=n.headers?.["idempotency-key"]??n.headers?.["Idempotency-Key"],l=u?w(y(u,i)):void 0,f=w(y(a?.message??"network failure",i)),m=l?`Retry the request with the same idempotency key: ${l}.`:`Check that --base-url names the Hyperscale API origin and connectivity to ${c}.`;throw new d(`Could not reach ${c}: ${f}`,{code:"transport_error",details:{...l?{idempotencyKey:l}:{},path:t,url:c},fix:m})}}async function E(e,t,n={},o,r=[]){let{response:s,text:i}=await Oe(e,t,n,o);if(!s.ok)throw de(s,i,r);try{return JSON.parse(i)}catch{throw new d(`HTTP ${s.status} returned invalid JSON`)}}function C(e,t=globalThis.crypto.randomUUID()){return{body:JSON.stringify(e),headers:{"content-type":"application/json","idempotency-key":t},method:"POST"}}async function on(){let e=[];for await(let t of process.stdin)e.push(Buffer.from(t));return Buffer.concat(e).toString("utf8")}async function ue(e,t,n={},o){let r=`${e.baseUrl}${t}`,s=ve(e.baseUrl);if(at(r)!==s)throw new d(`The product document puts ${t} on another origin than the ${s} you configured; refusing to send the key there.`);let i=[e.apiKey].filter(Boolean);try{let a=await fetch(r,{...n,headers:{accept:"application/json",authorization:`Bearer ${e.apiKey}`,"x-hyperscale-environment":e.environment,...n.headers},signal:AbortSignal.timeout(Pe),redirect:"manual"});if(a.status>=300&&a.status<400){let c=w(y(r,i));throw new d(`${c} redirected, so the key was not sent on. Point --base-url at the origin the API answers on; the usual cause is http:// where it serves https://.`,{code:"unexpected_redirect",fix:"Point --base-url at the origin the API answers on; the usual cause is http:// where it serves https://."})}return ct(a,i),{response:a,text:w(await a.text())}}catch(a){if(a instanceof d)throw a;if(o&&(a?.name==="TimeoutError"||a?.name==="AbortError"))throw new d(`product run ${o} timed out after ${Pe/1e3} seconds.`);let c=w(y(r,i)),u=n.headers?.["idempotency-key"]??n.headers?.["Idempotency-Key"],l=u?w(y(u,i)):void 0,f=w(y(a?.message??"network failure",i)),m=l?`Retry the request with the same idempotency key: ${l}.`:`Check that --base-url names the Hyperscale API origin and connectivity to ${c}.`;throw new d(`Could not reach ${c}: ${f}`,{code:"transport_error",details:{...l?{idempotencyKey:l}:{},path:t,url:c},fix:m})}}async function ut(e){let{response:t,text:n}=await ue(e,"/v1/product.json");if(!t.ok)throw de(t,n,[e.apiKey]);let o=rn(n);if(!o)throw new d("The product document is not in the expected format.",{fix:'Run the latest unpinned CLI (e.g. "bunx @hyperscale0/cli@latest <command>"), or report the issue without including credentials.'});if(e.productId&&o.productId===void 0)throw new d(`The server's product document names no Product, so "--product ${e.productId}" cannot be checked against the API key. The platform predates Product identity in the descriptor: redeploy it, or drop --product.`);if(e.productId&&o.productId&&e.productId!==o.productId)throw new d(`Selected Product ${e.productId} does not match API key Product ${o.productId}. Run "hyperscale product select ${o.productId}" or pass "--product ${o.productId}". Or set HYPERSCALE_API_KEY to a key for ${e.productId}, or pass that key with --api-key.`);let r=o.operations.map(s=>{if(typeof s.summary!="string"||typeof s.description!="string")throw new d(`The product document carries no prose for ${s.operationId}. The server descriptor predates operation prose. Redeploy the platform, then recompose the Product.`);return{description:s.description,idempotency:s.idempotency,method:s.method,name:s.name,operationId:s.operationId,path:s.path,summary:s.summary}});return{compositionId:o.composition.id,operations:r,packageName:o.sdk?o.sdk.packageName.trim():null,title:o.title.trim()}}function rn(e){let t;try{t=JSON.parse(e)}catch{return null}let n=be(t),o=r=>typeof r=="string";if(!K(n)||n.schemaVersion!==1||!(n.productId===void 0||o(n.productId))||!o(n.title)||!K(n.composition)||!o(n.composition.id)||!Array.isArray(n.operations))return null;for(let r of n.operations)if(!K(r)||!o(r.method)||!o(r.path)||!o(r.name)||!o(r.operationId)||!o(r.idempotency))return null;return n.sdk!==void 0&&(!K(n.sdk)||!o(n.sdk.packageName))?null:n}function K(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function be(e){return typeof e=="string"?w(e):Array.isArray(e)?e.map(be):K(e)?Object.fromEntries(Object.entries(e).map(([t,n])=>[w(t),be(n)])):e}function dt(e){let t=e.get("x-trace-id");if(t&&t.trim()!=="")return t.trim();let n=e.get("traceparent");if(n){let o=/^00-([0-9a-fA-F]{32})-[0-9a-fA-F]{16}-[0-9a-fA-F]{2}$/.exec(n.trim());if(o)return o[1]}return null}function sn(e){if(!e||e.trim()==="")return null;try{return JSON.parse(e)}catch{return e}}function lt(e,t,n=[]){let o=e?.get?.("x-request-id")??t??null,r=e?.get?.("hyperscale-operation-id")??null,s=e?.get?.("hyperscale-receipt-id")??null,i=e?dt(e):null;return{requestId:o?w(y(o,n)):null,operationId:r?w(y(r,n)):null,receiptId:s?w(y(s,n)):null,traceId:i?w(y(i,n)):null}}function oe(e,t=[]){if(typeof e=="string")return w(y(e,t));if(Array.isArray(e))return e.map(n=>oe(n,t));if(e&&typeof e=="object"){let n=[];for(let[o,r]of Object.entries(e)){let s=w(y(o,t));n.push([s,oe(r,t)])}return Object.fromEntries(n)}return e}function pt(e,t=[],n){let o;try{o=JSON.parse(e)}catch{o=null}let r=o&&typeof o=="object"&&o.error&&typeof o.error=="object"?o.error:null;if(r){let a=typeof r.code=="string"?r.code:void 0,c=typeof r.fix=="string"?r.fix:void 0,u=c?w(y(c,t)):void 0,l=typeof r.message=="string"?r.message:n?`HTTP ${n}`:"HTTP error",f=w(y(l,t)),m=f.length>1024?f.slice(0,1024):f,k=a&&typeof r.message=="string"?`${a}: ${m}`:m,g=r.details!==void 0?oe(r.details,t):void 0,h=o&&typeof o=="object"&&typeof o.requestId=="string"?w(y(o.requestId,t)):void 0;return{code:a,details:g,fix:u,humanMessage:k,redactedMessage:m,requestId:h,structuredError:{code:a??"http_error",message:m,...g!==void 0?{details:g}:{},...u!==void 0?{fix:u}:{}}}}let s=n?`HTTP ${n}`:"HTTP error",i="Check that --base-url names the Hyperscale API origin, or report the issue without including credentials.";return{code:"http_error",details:void 0,fix:i,humanMessage:s,redactedMessage:s,requestId:void 0,structuredError:{code:"http_error",message:s,fix:i}}}function de(e,t,n=[]){let o=pt(t,n,e.status),r=lt(e.headers,o.requestId,n),s=o.humanMessage;return new O(`HTTP ${e.status}${s?` \xB7 ${s}`:""}${r.requestId?`
|
|
27
|
+
Request id: ${r.requestId}`:""}`,{code:o.code,details:o.details,fix:o.fix,operationId:r.operationId,receiptId:r.receiptId,requestId:r.requestId,status:e.status,structuredError:o.structuredError,traceId:r.traceId})}function je(e,t){return{authenticated:!0,baseUrl:e.baseUrl,email:t.email,environment:e.environment,expiresAt:t.expiresAt,personalAccessTokenId:t.personalAccessTokenId,role:t.role,scopes:t.scopes,selectedProduct:e.selectedProduct,teamId:t.teamId,tenantId:t.tenantId,tokenName:t.name,userId:t.userId}}function an(e){if(!e||typeof e!="object"||typeof e.userId!="string"||typeof e.email!="string"||typeof e.tenantId!="string"||typeof e.teamId!="string"||typeof e.role!="string"||typeof e.personalAccessTokenId!="string"||typeof e.name!="string"||!Array.isArray(e.scopes)||e.scopes.some(t=>typeof t!="string")||typeof e.expiresAt!="string"||e.status!=="active")throw new d("personal_access_token.current returned invalid data");return e}async function U(e,t){try{return an(await E(e,Yt,{},t,[t]))}catch(n){throw!(n instanceof O)||n.status!==401?n:new d(`That founder PAT was not accepted (HTTP 401). ${Be}${n.requestId?` Request id: ${n.requestId}.`:""}`,{code:"founder_pat_rejected",fix:Be})}}function cn(e,t){return e.HYPERSCALE_CLI_BROWSER?{command:e.HYPERSCALE_CLI_BROWSER,args:[t]}:e.HYPERSCALE_NO_BROWSER==="1"||e.CI==="1"||e.CI==="true"||process.platform==="linux"&&!e.DISPLAY&&!e.WAYLAND_DISPLAY?null:process.platform==="darwin"?{command:"/usr/bin/open",args:[t]}:process.platform==="win32"?{command:"rundll32.exe",args:["url.dll,FileProtocolHandler",t]}:{command:"xdg-open",args:[t]}}async function un(e,t){let n=cn(e,t);return n?new Promise(o=>{let r=Ge(n.command,n.args,{detached:!0,stdio:"ignore"});r.once("error",()=>o(!1)),r.once("spawn",()=>{r.unref(),o(!0)})}):!1}function ge(e){return new Promise(t=>{if(!e.listening){t();return}e.close(()=>t())})}async function dn(e,t){let n=globalThis.crypto.randomUUID(),o=!1,r,s=new Promise((g,h)=>{r={reject:h,resolve:g}}),i=jt((g,h)=>{let I=new URL(g.url??"/","http://127.0.0.1");if(g.method!=="GET"||I.pathname!=="/callback"){h.writeHead(404,{"content-type":"text/plain; charset=utf-8"}),h.end(`Not found.
|
|
28
28
|
`);return}if(o){h.writeHead(409,{"content-type":"text/plain; charset=utf-8"}),h.end(`Login callback was already received.
|
|
29
|
-
`);return}if(
|
|
30
|
-
`);return}if(
|
|
31
|
-
`),r.reject(new d("Portal login was declined. Run hyperscale auth login to start again.",{code:"auth_callback_denied"}));return}let
|
|
29
|
+
`);return}if(I.searchParams.get("state")!==n){h.writeHead(400,{"content-type":"text/plain; charset=utf-8"}),h.end(`Login state did not match. Return to the terminal.
|
|
30
|
+
`);return}if(I.searchParams.get("error")!==null){o=!0,h.writeHead(200,{"content-type":"text/plain; charset=utf-8"}),h.end(`Login declined. Return to the terminal.
|
|
31
|
+
`),r.reject(new d("Portal login was declined. Run hyperscale auth login to start again.",{code:"auth_callback_denied"}));return}let T=I.searchParams.get("grant"),v=I.searchParams.get("tenantId");if(!T||!v){h.writeHead(400,{"content-type":"text/plain; charset=utf-8"}),h.end(`Login callback is missing its grant or tenant.
|
|
32
32
|
`);return}o=!0,h.writeHead(200,{"content-type":"text/plain; charset=utf-8"}),h.end(`Login received. Return to the terminal.
|
|
33
|
-
`),r.resolve({grant:
|
|
34
|
-
`);let
|
|
35
|
-
`)}let c=
|
|
36
|
-
`)}function
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
`).map(n=>`${t}${n}`).join(`
|
|
40
|
-
`)}function
|
|
41
|
-
`)
|
|
42
|
-
|
|
43
|
-
`)}let
|
|
44
|
-
`),{
|
|
45
|
-
`),{actions:s,file:t,...r,...e.productId?{productId:e.productId}:{}});return{...o,...r}}async function Hn(e,t,n){let o=await Le(e,t,n,"optional","compose plan"),r=await bt(o,n);if(e["--json"]){b({command:"composer.plan",file:n,check:{...o.check,...o.receipt},plan:r,...o.productId?{productId:o.productId}:{}});return}u(r.summary);for(let i of r.actions)u(`${i.kind} ${i.target} ${It(i.detail)}`);let s=r.pricing?.currency??"SAR";if(r.pricing?.scheduled){let i=r.pricing.current?.monthly,a=r.pricing.scheduled?.monthly;u(`Current billing price: ${s} ${i}/mo`),u(`Candidate price from ${r.pricing.scheduled.effectiveAt}: ${s} ${a}/mo`),u(`Pricing identity: ${r.pricing.scheduled.pricingIdentity}`)}else if(r.pricing){let i=r.pricing.monthly,a=r.pricing.activation;i!==void 0&&u(`Monthly: ${s} ${i}`),a!==void 0&&u(`Activation: ${s} ${a}`)}}async function Dn(e,t,n){if(!e["--confirm"]&&!e["--yes"])if(process.stdin.isTTY&&process.stderr.isTTY){let c=P(process.stderr,process.env,{json:!1});process.stderr.write(`${qe(c,{action:"recompose",subject:n,confirmation:"Recompose selected Product?"})}
|
|
46
|
-
`);let l=tt({input:process.stdin,output:process.stderr,terminal:!0});try{let p=await l.question("");if(p.trim().toLowerCase()!=="y"&&p.trim().toLowerCase()!=="yes")throw new d("Mutation cancelled.",{code:"cancelled"})}finally{l.close()}}else throw new d("compose apply changes the selected Product. Pass --confirm, or --yes for an agent.");let o=e["--pricing-identity"];if(!o&&e["--plan-file"]){let c=e["--plan-file"];try{let l=await W(c,"utf8"),p=JSON.parse(l);o=p.plan?.pricing?.scheduled?.pricingIdentity??p.pricing?.scheduled?.pricingIdentity??p.pricingIdentity}catch(l){throw new d(`Failed to read saved plan file ${c}: ${l.message}`)}}let r=await Le(e,t,n,"required","compose apply"),s=await bt(r,n);if(s.pricing?.scheduled&&!o){if(!e["--yes"])throw new d(`compose apply --confirm requires --pricing-identity (or --plan-file). Run "hyperscale compose plan ${n}" to review candidate pricing and copy the pricing identity, or pass --yes to accept the current candidate.`);o=s.pricing.scheduled.pricingIdentity}let i=e["--idempotency-key"]??globalThis.crypto.randomUUID(),a;try{a=await T(r.context,"/v1/products/recompose",C({program:{source:r.program.source},...r.catalogRevisionId?{catalogRevisionId:r.catalogRevisionId}:{},...o?{pricingIdentity:o}:{},tenantId:r.context.tenantId,productId:r.productId},i),r.context.token,[r.context.token])}catch(c){throw c instanceof O&&c.code==="product_instrument_not_drained"&&(c.fix=`Drain live instrument instances, or create a new Product directly from source: hyperscale product create --source ${n} --name <name>`),c}if(!a||typeof a.productBuildId!="string")throw new d("product.recompose returned no new build identity");if(e["--json"]){b({command:"product.recompose",file:n,output:a});return}if(u(`Product: ${a.productId??r.productId}`),u(`Build: ${a.productBuildId}`),a.buildDigest&&u(`Digest: ${a.buildDigest}`),a.pricing?.scheduled){let c=a.pricing.currency??"SAR",l=a.pricing.current?.monthly,p=a.pricing.scheduled?.monthly;u(`Current billing price: ${c} ${l}/mo`),u(`Accepted price from ${a.pricing.scheduled.effectiveAt}: ${c} ${p}/mo`)}}function Pt(e,t){let n=t["--product"]??e.selectedProduct;return typeof n=="string"&&n.length>0?n:void 0}function V(e,t){let n=Pt(e,t);if(!n)throw new d("No Product selected. Pass --product <id> or create a Product first.",{fix:'Run "hyperscale product list" to see existing Products, or "hyperscale product create" to create one.'});return n}async function se(e,t){let n=await ce(t),o=V(n??{},e),r=q(e,t,n??{});if(n&&(r.baseUrl!==n.baseUrl||r.environment!==n.environment))throw new d(`The selected Product belongs to ${n.baseUrl} (${n.environment}). Select a Product at the configured API origin first.`);let s=e["--api-key"]??t.HYPERSCALE_API_KEY;if(!s)throw st(o);return{...r,apiKey:s,productId:o}}async function $t(e,t){let n=`/v1/products/${encodeURIComponent(e.productId)}/operation-set`,{response:o,text:r}=await pe(e,n,{},t);if(!o.ok)throw St(o,r,[e.apiKey],{productId:e.productId});return Bn(r,o.status)}async function Kn(e,t,n){let o=await se(e,t),r=await $t(o);if(n){Jn(r,n,e);return}if(e["--json"]){b(r);return}if(r.publicActions.length===0)u("No public actions");else{let s=P(process.stdout,t,{json:!1});u(j(s,{columns:["Operation ID","Input","Kind"],rows:r.publicActions.map(i=>{let a=i.idempotencyPolicy?.mode==="not_required"?"read-only":"mutation";return[`${i.instrument}.${i.name}`,qn(i.inputSchema),a]})}))}if(r.setupOperations.length>0){u("Setup operations (run with hyperscale call)");for(let s of r.setupOperations)u(s.operationName)}if(r.readOperationIds.length>0){u("Reads (run with hyperscale call)");for(let s of r.readOperationIds)u(Mn(s))}u(`Digest: ${r.tenantOperationSetDigest}`),u(`Setup digest: ${r.tenantSetupOperationSetDigest}`),u(`Read digest: ${r.tenantReadOperationSetDigest}`),u(`Build: ${r.productBuildId}`),u(`Surface version: ${r.tenantSurfaceVersion}`)}function Jn(e,t,n){let o=e.publicActions.find(c=>c&&`${c.instrument}.${c.name}`===t),r=Yn(t),s=e.setupOperations.find(c=>c&&(c.operationId===t||c.operationId===r||c.operationName===t));if(s){let{inputSchema:c,operationId:l,operationName:p}=s,f={status:e.status,productBuildId:e.productBuildId,tenantSurfaceVersion:e.tenantSurfaceVersion,tenantSetupOperationSetDigest:e.tenantSetupOperationSetDigest,setupOperationId:l,operationName:p,command:`hyperscale call ${p}`,inputSchema:c};if(n["--json"]){b(f);return}let m=P(process.stdout,n?process.env:{},{json:!1}),g=[["Operation ID",l],["Operation name",p],["Run",`hyperscale call ${p}`],["Input schema",JSON.stringify(c,null,2)]];(!Array.isArray(c.required)||c.required.length===0)&&g.push(["Input","omit --input or pass {}."]),g.push(["Setup digest",e.tenantSetupOperationSetDigest],["Build",e.productBuildId],["Surface version",e.tenantSurfaceVersion]),u(H(m,{fields:g}));return}if(!o)throw new d(`Unknown frozen public action: ${t}. Run "hyperscale product actions" to list exact names.`);let i={status:e.status,productBuildId:e.productBuildId,tenantSurfaceVersion:e.tenantSurfaceVersion,tenantOperationSetDigest:e.tenantOperationSetDigest,qualifiedName:`${o.instrument}.${o.name}`,publicAction:o};if(n["--json"]){b(i);return}let a=P(process.stdout,n?process.env:{},{json:!1});u(H(a,{fields:[["Operation ID",`${o.instrument}.${o.name}`],["Instrument",o.instrument],["Input schema",JSON.stringify(o.inputSchema,null,2)],["Output schema",JSON.stringify(o.outputSchema,null,2)],["Actor policy",JSON.stringify(o.actorPolicy,null,2)],["Port policy",JSON.stringify(o.portPolicy,null,2)],["Idempotency policy",JSON.stringify(o.idempotencyPolicy,null,2)],["Receipt policy",JSON.stringify(o.receiptPolicy,null,2)],["Receipt evidence",JSON.stringify(o.receiptEvidence,null,2)],["Digest",e.tenantOperationSetDigest],["Build",e.productBuildId],["Surface version",e.tenantSurfaceVersion]]}))}function Bn(e,t){let n;try{n=JSON.parse(e)}catch{throw new d(`HTTP ${t} returned invalid JSON`)}if(!n||typeof n!="object"||n.status!=="frozen"||typeof n.productBuildId!="string"||typeof n.tenantSurfaceVersion!="number"||typeof n.tenantOperationSetDigest!="string"||typeof n.tenantReadOperationSetDigest!="string"||typeof n.tenantSetupOperationSetDigest!="string"||!Array.isArray(n.publicActions)||!Array.isArray(n.readOperationIds)||!Array.isArray(n.setupOperationIds)||!Array.isArray(n.setupOperations))throw new d("The Product operation set is not in the expected format.",{fix:'Run the latest unpinned CLI (e.g. "bunx @hyperscale0/cli@latest <command>"), or report the issue without including credentials.'});return n.publicActions=n.publicActions.map(o=>{if(!o||typeof o!="object"||typeof o.instrument!="string"||o.instrument.length===0||typeof o.name!="string"||o.name.length===0)throw new d("The server's public action names no instrument or action name. The platform predates Product identity in public actions: redeploy it.");return{...o,qualifiedName:`${o.instrument}.${o.name}`}}),n}function Yn(e){return e.replaceAll(".","_")}function Mn(e){for(let t of["create","list","retrieve"]){let n=`_${t}`;if(e.endsWith(n))return`${e.slice(0,-n.length)}.${t}`}return e}function qn(e){if(!e||typeof e!="object")return"input schema unavailable";let t=e.properties&&typeof e.properties=="object"&&!Array.isArray(e.properties)?e.properties:{},n=new Set(Array.isArray(e.required)?e.required.filter(r=>typeof r=="string"):[]),o=Object.entries(t).map(([r,s])=>`${r}${n.has(r)?"":"?"}: ${xt(s)}`);return o.length===0?"no input":o.join(", ")}function xt(e){return!e||typeof e!="object"?"value":Array.isArray(e.enum)&&e.enum.length>0?e.enum.map(t=>String(t)).join(" | "):e.type==="array"?`${xt(e.items)}[]`:typeof e.type=="string"?typeof e.format=="string"?`${e.type} (${e.format})`:e.type:"value"}async function Fn(e,t,n){if(!n)throw new d("product run needs a public action");let o=await se(e,t),r=await $t(o,n);Wn(r,n);let s=await At(e),i=e["--idempotency-key"]??globalThis.crypto.randomUUID(),{response:a,text:c}=await pe(o,`/v1/operations/${encodeURIComponent(n)}`,{body:JSON.stringify(s),headers:{"content-type":"application/json","idempotency-key":i},method:"POST"},n);if(!a.ok)throw St(a,c,[o.apiKey],{action:n,productId:o.productId});let l=a.headers.get("hyperscale-operation-id"),p=a.headers.get("hyperscale-receipt-id"),f=a.headers.get("x-request-id"),m=l?y(l,[o.apiKey]):null,g=p?y(p,[o.apiKey]):null,I=f?y(f,[o.apiKey]):null;if(e["--json"]){b({idempotencyKey:i,...I?{requestId:I}:{},operationId:m,receiptId:g,output:zn(c)});return}m&&u(`Operation: ${m}`),g&&u(`Receipt: ${g}`),u(`Idempotency key: ${i}`);let h=Tt(c);h&&u(h)}function Wn(e,t){let n=e.publicActions.find(r=>r&&`${r.instrument}.${r.name}`===t);if(n)return n;let o=e.publicActions.map(r=>`${r.instrument}.${r.name}`).map(r=>({candidate:r,distance:Te(t,r)})).sort((r,s)=>r.distance-s.distance||r.candidate.localeCompare(s.candidate)).slice(0,3).map(({candidate:r})=>r);throw new d(`Unknown frozen public action: ${t}. Closest valid names: ${o.join(", ")}. Run "hyperscale product actions" to list exact names.`)}function zn(e){if(e.trim()==="")return null;try{return JSON.parse(e)}catch{return e}}function St(e,t,n=[],o={}){let r=gt(t,n,e.status),s=yt(e.headers,r.requestId,n),i=r.code??"user_error",a=r.redactedMessage;if(typeof a=="string"&&a.includes("does not match API key Product")){let m=o.productId??a.match(/^Selected Product (\S+) does not match/)?.[1];m&&(a=`${a} Or set HYPERSCALE_API_KEY to a key for ${m}, or pass that key with --api-key.`)}let c=i==="user_error"?"":`${i}: `,l=`HTTP ${e.status} \xB7 ${c}${a}`,p=Vn(r.details,n),f=r.fix;return i==="idempotency_conflict"?f="Reuse the same key only with the same operation and input. Use a new unique key for a different request.":e.status===409&&typeof a=="string"&&a.includes("capability-derived")?f='This Product has no frozen public actions. List its operations with "hyperscale ops list" and run them with "hyperscale call".':[a,...p].some(m=>typeof m=="string"&&m.includes("[Truncated]"))&&o.action&&(f=`Run "hyperscale product actions ${o.action}" to read the full input schema and allowed values.`),new O([l,...p].join(`
|
|
47
|
-
`),{code:i,details:r.details,fix:f,operationId:s.operationId,receiptId:s.receiptId,requestId:s.requestId,status:e.status,traceId:s.traceId})}function Vn(e,t){if(!e||typeof e!="object")return[];if(Array.isArray(e.issues))return e.issues.flatMap(o=>{if(!o||typeof o!="object")return[];let s=(Array.isArray(o.path)?o.path.join("."):"input")||"input";return typeof o.message=="string"?[`${s}: ${y(o.message,t)}`]:[]});let n=[];return Ae(e,"",n,t),n}function Ae(e,t,n,o){if(Array.isArray(e)){if(e.every(r=>r===null||typeof r!="object")){n.push(`${Qe(t)}: ${y(e.join(", "),o)}`);return}e.forEach((r,s)=>Ae(r,`${t}[${s}]`,n,o));return}if(e&&typeof e=="object"){for(let[r,s]of Object.entries(e))Ae(s,t?`${t}.${r}`:r,n,o);return}t&&n.push(`${Qe(t)}: ${y(String(e),o)}`)}function Qe(e){let t=e.replace(/([a-z0-9])([A-Z])/g,"$1 $2").replaceAll("."," ");return t.charAt(0).toUpperCase()+t.slice(1)}async function Gn(e,t){let n=await x(e,t),o=V(n,e),r=await T(n,"/v1/sandbox-api-keys",C({name:e["--name"]??"Founder CLI",tenantId:n.tenantId,productId:o}),n.token,[n.token]),s=["export HYPERSCALE_API_KEY=<paste the shown_once value>",`hyperscale product actions --product ${o}`];if(e["--json"]){let{secret:i,...a}=r;b({...a,...typeof i=="string"?{shown_once:i}:{},nextCommands:s});return}u(`Key: ${r.apiKeyId??"unknown"}`),u(`Product: ${r.productId??o}`),u(`Status: ${r.status??"unknown"}`),r.secret?(u(`Secret: ${r.secret}`),u("Store it now. Hyperscale will not return it again."),u("Next:"),u(" export HYPERSCALE_API_KEY=<paste the secret above>"),u(` hyperscale product actions --product ${o}`)):u("The key already existed, so the one-time secret is unavailable.")}async function Xn(e,t){let n=await x(e,t),o=V(n,e),r=await D(n,"/v1/api-keys",{productId:o,tenantId:n.tenantId},"api_key.list",n.token,[n.token]),s=_(r,"api_key.list");if(e["--json"]){b(r);return}let i=P(process.stdout,t,{json:!1});u(j(i,{columns:["ID","Name","Status"],rows:s.map(a=>[a.apiKeyId,a.name??"unnamed",a.status??"unknown"])}))}async function Zn(e,t,n){if(!n)throw new d("key revoke needs an API key id",{fix:'Run "hyperscale key list" to list keys, then pass one ID.'});let o=await x(e,t),r=V(o,e),s=await T(o,`/v1/api-keys/${encodeURIComponent(n)}/revoke`,C({tenantId:o.tenantId,productId:r}),o.token,[o.token]);e["--json"]?b(s):u(`Key ${s.apiKeyId??n}: ${s.status??"revoked"}`)}async function Qn(e,t){let n=await x(e,t),o=n.identity??await N(n,n.token),r=Oe(n,o);if(e["--json"]){b(r);return}let s=P(process.stdout,t,{json:!1});u(H(s,{fields:[["User",o.email],["Tenant",o.tenantId],["Role",o.role],["Token",o.name],["Expires",o.expiresAt]]}))}async function eo(e,t,n){let o=await ft(e),r=n?n.toLowerCase():null,s=r?o.operations.filter(a=>a.name.toLowerCase().includes(r)||a.path.toLowerCase().includes(r)):o.operations;if(t["--json"]){u(JSON.stringify(s,null,2));return}if(s.length===0){u(n?`No operation matches ${n}`:"No operations");return}let i=P(process.stdout,process.env,{json:!1});u(j(i,{columns:["Operation","Method","Path"],rows:s.map(a=>[a.name,a.method,a.path])}))}async function to(e,t){let n=await x(e,t),o=await D(n,"/v1/activity",{tenantId:n.tenantId},"activity.list",n.token,[n.token]),r=_(o,"activity.list");if(e["--json"]){b(o);return}let s=P(process.stdout,t,{json:!1});u(j(s,{columns:["Time","Activity","Target","Status"],rows:r.map(i=>{let a=i.operation??i.auditEvent??"activity",c=i.resourceKind&&i.resourceId?`${i.resourceKind}:${i.resourceId}`:i.resourceKind??i.resourceId??"-";return[i.occurredAt??"unknown",a,c,i.status??"recorded"]})}))}function no(e,t){let n={...t},o=[],r=e.path.replace(/\{([^}]+)\}/g,(s,i)=>{let a=n[i];return a==null?(o.push(i),""):(delete n[i],encodeURIComponent(String(a)))});if(o.length>0)throw new d(`${e.name} needs ${o.join(", ")} in --input`);return{path:r,remaining:n}}function oo(e){let t=new URLSearchParams;for(let[o,r]of Object.entries(e))r!=null&&t.set(o,typeof r=="string"?r:JSON.stringify(r));let n=t.toString();return n?`?${n}`:""}function Te(e,t){let n=Array.from({length:t.length+1},(o,r)=>r);for(let o=1;o<=e.length;o+=1){let r=[o];for(let s=1;s<=t.length;s+=1)r[s]=Math.min(r[s-1]+1,n[s]+1,n[s-1]+(e[o-1]===t[s-1]?0:1));n.splice(0,n.length,...r)}return n[t.length]}function ro(e,t){let n=e.find(s=>s.name===t);if(n)return n;let o=e.filter(s=>s.operationId===t);if(o.length===1)return o[0];if(o.length>1)throw new d(`${t} matches more than one operation. Use one of: ${o.map(s=>s.name).join(", ")}.`);let r=e.map(s=>({candidate:s,distance:Math.min(Te(t,s.name),Te(t,s.operationId))})).sort((s,i)=>s.distance-i.distance||s.candidate.name.localeCompare(i.candidate.name)).slice(0,3).flatMap(({candidate:s})=>[s.name,s.operationId]);throw new d(`${t} is not an operation in the selected Product's machine document. Closest valid names: ${r.join(", ")}.`)}async function so(e,t,n){if(!n)throw new d("call needs an operation name",{fix:'Run "hyperscale ops list" to list operations.'});let o=await ft(e),r=ro(o.operations,n),s=await At(t),{path:i,remaining:a}=no(r,s),c={method:r.method},l=i;r.method==="GET"?l+=oo(a):(c.body=JSON.stringify(a),c.headers={"content-type":"application/json",...r.idempotency==="not_required"?{}:{"idempotency-key":t["--idempotency-key"]??globalThis.crypto.randomUUID()}});let{response:p,text:f}=await pe(e,l,c);if(p.ok){if(t["--json"]){let m=un(f),g=p.headers.get("x-request-id")??(m&&typeof m=="object"&&typeof m.requestId=="string"?m.requestId:null),I=p.headers.get("hyperscale-operation-id")??null,h=p.headers.get("hyperscale-receipt-id")??null,w=ht(p.headers),S=g?y(g,[e.apiKey]):null,v=I?y(I,[e.apiKey]):null,G=h?y(h,[e.apiKey]):null,L=w?y(w,[e.apiKey]):null;b({status:p.status,data:m,requestId:S,operationId:v,receiptId:G,traceId:L});return}u(Tt(f));return}throw me(p,f,[e.apiKey])}async function At(e){if(e["--input"]!==void 0&&e["--input-file"]!==void 0)throw new d("Use only one of --input and --input-file");if(e["--input"]!==void 0)return ke(e["--input"],"--input");if(e["--input-file"]!==void 0){let t;try{t=await W(e["--input-file"],"utf8")}catch(n){throw new d(`Could not read ${e["--input-file"]}: ${n.message}`)}return ke(t,"--input-file")}if(!process.stdin.isTTY){let t=await an();if(t.trim()!=="")return ke(t,"stdin")}return{}}function ke(e,t="--input"){if(e===void 0)return{};let n;try{n=JSON.parse(e)}catch(o){throw new d(`${t} is not valid JSON: ${o.message}`)}if(n===null||typeof n!="object"||Array.isArray(n))throw new d(`${t} must be a JSON object`);return n}function Tt(e){if(e.trim()==="")return"";try{return JSON.stringify(JSON.parse(e),null,2)}catch{return e}}function u(e){process.stdout.write(`${e}
|
|
48
|
-
`)}function b(e){u(JSON.stringify(e,null,2))}function io(e,t){let n=t.includes("--json"),o=[process.env.HYPERSCALE_API_KEY,process.env.HYPERSCALE_TOKEN].filter(Boolean),r=e instanceof d,s=r?e.message:"The command failed unexpectedly.",i=k(y(String(s),o)),a=i.length>1024?i.slice(0,1024):i,c=r?e.fix??'Follow the message, or run "hyperscale --help" for command usage.':"Report the failure without including credentials.",l=k(y(String(c),o)),p=r&&typeof e.shownOnce=="string"?k(y(e.shownOnce,o)):void 0;if(!n){let R=P(process.stderr,process.env,{json:!1}),Rt=(typeof e?.structuredError?.code=="string"?e.structuredError.code:void 0)??(r&&typeof e.code=="string"?e.code:r?"user_error":"internal_error"),Et=r?a:i,Ct=p?`
|
|
49
|
-
Shown once Product API key: ${p}`:"",vt=Fe(R,{code:Rt,message:Et,nextStep:l});process.stderr.write(`${vt}${Ct}
|
|
50
|
-
`);return}let f=(typeof e?.structuredError?.code=="string"?e.structuredError.code:void 0)??(r&&typeof e.code=="string"?e.code:r?"user_error":"internal_error"),m=(typeof e?.structuredError?.message=="string"?e.structuredError.message:void 0)??(r?e.message:"The command failed unexpectedly."),g=k(y(String(m),o)),I=g.length>1024?g.slice(0,1024):g,h=(typeof e?.structuredError?.fix=="string"?e.structuredError.fix:void 0)??(r?e.fix??'Follow the message, or run "hyperscale --help" for command usage.':"Report the failure without including credentials."),w=k(y(String(h),o)),S=w.length>1024?w.slice(0,1024):w,v=e?.structuredError?.details!==void 0?e.structuredError.details:r&&e.details!==void 0?e.details:void 0,G=v!==void 0?re(v,o):void 0,L=r&&typeof e.status=="number"?e.status:void 0,X=R=>typeof R!="string"||R.trim().length===0?null:k(y(R.trim(),o)),Z=r&&(e.requestId!==void 0||e.operationId!==void 0||e.receiptId!==void 0||e.traceId!==void 0),Q=Z?X(e.requestId):void 0,ee=Z?X(e.operationId):void 0,te=Z?X(e.receiptId):void 0,ne=Z?X(e.traceId):void 0,Ue=R=>({...L!==void 0?{status:L}:{},error:{code:f,message:I,...R!==void 0?{details:R}:{},fix:S},...Q!==void 0?{requestId:Q}:{},...ee!==void 0?{operationId:ee}:{},...te!==void 0?{receiptId:te}:{},...ne!==void 0?{traceId:ne}:{},...p?{shown_once:p}:{}}),He=R=>Buffer.byteLength(R,"utf8")>8192,K=Ue(G),J=JSON.stringify(K);He(J)&&G!==void 0&&(K=Ue("[Truncated]"),J=JSON.stringify(K)),He(J)&&(K={...L!==void 0?{status:L}:{},error:{code:f,message:I,fix:"[Truncated]"},...Q!==void 0?{requestId:Q}:{},...ee!==void 0?{operationId:ee}:{},...te!==void 0?{receiptId:te}:{},...ne!==void 0?{traceId:ne}:{}},J=JSON.stringify(K)),process.stderr.write(`${J}
|
|
51
|
-
`)}async function ao(){let{readFileSync:e}=await import("node:fs");return JSON.parse(e(new URL("./package.json",import.meta.url),"utf8")).version}async function co(e,t){let{flags:n,positional:o}=Zt(e);if(n["--version"])return u(await ao()),0;if(n["--help"]&&o.length>0){let i=P(process.stdout,t,{json:!1});return u(ze(o,i)),0}if(o[0]==="help"){let i=o.slice(1),a=P(process.stdout,t,{json:!1});return i.length===0?u(he(a)):u(ze(i,a)),0}if(o.length===0&&!n["--help"]){if(n["--json"])throw new d('No command. Run "hyperscale --help" to list commands.');if(!await x(n,t,!0)){let a=P(process.stdout,t,{json:!1});return u(Ye(a)),0}return process.stdin.isTTY&&process.stderr.isTTY?(await Ze(n,t),0):(u('Build your first Product with "hyperscale start".'),u('Run "hyperscale --help" for every command.'),0)}if(n["--help"]){let i=P(process.stdout,t,{json:!1});return u(he(i)),0}let[r,...s]=o;if(r==="start")return await Ze(n,t),0;if(r==="auth"){if(s[0]==="login")await fn(n,t);else if(s[0]==="status")await hn(n,t);else if(s[0]==="logout")await yn(n,t);else throw new d('Auth subcommands are "login", "status", and "logout"',{fix:'Run "hyperscale help auth" to see valid subcommands.'});return 0}if(r==="blueprint"){let i=q(n,t);if(s[0]==="list")await wn(i,n);else if(s[0]==="show")await In(i,n,s[1]);else throw new d('Blueprint subcommands are "list" and "show"',{fix:'Run "hyperscale help blueprint" to see valid subcommands.'});return 0}if(r==="product"){if(s[0]==="create")await En(n,t);else if(s[0]==="list")await Cn(n,t);else if(s[0]==="show")await vn(n,t,s[1]);else if(s[0]==="select")await On(n,t,s[1]);else if(s[0]==="actions")await Kn(n,t,s[1]);else if(s[0]==="run")await Fn(n,t,s[1]);else throw new d('Product subcommands are "create", "list", "show", "select", "actions", and "run"',{fix:'Run "hyperscale help product" to see valid subcommands.'});return 0}if(r==="compose"){if(s[0]==="check")await Un(n,t,s[1]);else if(s[0]==="plan")await Hn(n,t,s[1]);else if(s[0]==="apply")await Dn(n,t,s[1]);else throw new d('Compose subcommands are "check", "plan", and "apply"',{fix:'Run "hyperscale help compose" to see valid subcommands.'});return 0}if(r==="key"){if(s[0]==="create")await Gn(n,t);else if(s[0]==="list")await Xn(n,t);else if(s[0]==="revoke")await Zn(n,t,s[1]);else throw new d('Key subcommands are "create", "list", and "revoke"',{fix:'Run "hyperscale help key" to see valid subcommands.'});return 0}if(r==="whoami")return await Qn(n,t),0;if(r==="activity"){if(s[0]!=="list")throw new d('The only activity subcommand is "list"',{fix:'Run "hyperscale help activity" to see usage.'});return await to(n,t),0}if(r==="ops"){if(s[0]!=="list")throw new d('The only ops subcommand is "list"',{fix:'Run "hyperscale help ops" to see usage.'});let i=n["--product"]?await se(n,t):Ve(n,t);return await eo(i,n,s[1]),0}if(r==="call"){let i=n["--product"]?await se(n,t):Ve(n,t);return await so(i,n,s[0]),0}throw new d(`Unknown command: ${r}`,{fix:'Run "hyperscale --help" to list commands.'})}co(process.argv.slice(2),process.env).then(e=>{process.exitCode=e},e=>{io(e,process.argv.slice(2)),process.exitCode=e instanceof d&&Number.isInteger(e.exitCode)?e.exitCode:1});
|
|
33
|
+
`),r.resolve({grant:T,tenantId:v})});await new Promise((g,h)=>{let I=T=>h(T);i.once("error",I),i.listen(0,"127.0.0.1",()=>{i.off("error",I),g()})}),i.once("error",g=>r.reject(g));let a=i.address();if(!a||typeof a=="string")throw await ge(i),new d("Could not bind the localhost login callback");let c=`http://127.0.0.1:${a.port}/callback`,u=new URL("/auth/cli",e.baseUrl);u.searchParams.set("callback",c),u.searchParams.set("state",n);let l=new URL("/signin",e.baseUrl);l.searchParams.set("returnTo",`${u.pathname}${u.search}`);let f=l.toString();if(!await un(t,f))return await ge(i),null;process.stderr.write(`Opening portal sign-in: ${f}
|
|
34
|
+
`);let k=setTimeout(()=>{r.reject(new d("Portal login timed out. Run hyperscale auth login to start a new callback.",{code:"auth_callback_timeout"}))},Wt);try{return await s}finally{clearTimeout(k),await ge(i)}}async function ze(e,t,n,o,r){let s=await ae(r),i={email:t.email,...e,selectedProduct:s&&s.email===t.email&&s.baseUrl===e.baseUrl&&s.environment===e.environment?s.selectedProduct:null},a=await Qt(i,{personalAccessTokenId:t.personalAccessTokenId,token:n,tokenName:t.name,tenantId:t.tenantId},r);try{await Te(r,i)}catch(u){throw await st(i,r),u}if(a==="file"){let u=ie(r)==="file"?"Founder PAT file storage is active.":"macOS Keychain is unavailable.";process.stderr.write(`${u} The founder PAT is in ${R(i,r)} with mode 0600.
|
|
35
|
+
`)}let c=je(i,t);if(o["--json"])P(c);else{let u=b(process.stdout,r,{json:!1});p(Ye(u,{identity:t.email,team:t.teamId}))}}async function ln(e,t){let n=ne(e,t),o=it(e,t);if(o){if(!o.startsWith("hyperscale_pat_"))throw new d("Founder PATs start with hyperscale_pat_. Product API keys belong in HYPERSCALE_API_KEY.");let c=await U(n,o);await ze(n,c,o,e,t);return}if(e["--no-browser"])throw J();let r=await dn(n,t);if(!r)throw J();let s=await E(n,"/v1/personal-access-token-login-grants/exchange",C({tenantId:r.tenantId,grant:r.grant}),void 0,[r.grant]),i=s?.secret;if(typeof i!="string"||!i.startsWith("hyperscale_pat_")||s?.tenantId!==r.tenantId)throw new d("CLI login grant exchange returned an invalid PAT");let a=await U(n,i);await ze(n,a,i,e,t)}async function pn(e,t){let n=await $(e,t),o=n.identity??await U(n,n.token),r=je(n,o);if(e["--json"]){P(r);return}let s=b(process.stdout,t,{json:!1});p(L(s,{fields:[["User",o.email],["Tenant",o.tenantId],["Role",o.role],["Token",o.name],["Scopes",o.scopes.join(", ")],["Expires",o.expiresAt],["API",n.baseUrl],["Environment",n.environment],["Product",n.selectedProduct??"not selected"]]}))}async function fn(e,t){let n=await ae(t);if(!n){e["--json"]?P({status:"signed_out"}):p("Already logged out.");return}let o=await rt(n,t);if(e["--revoke"]&&!o)throw new d("The local founder PAT is missing, so the CLI cannot revoke it.");let r=o?.personalAccessTokenId,s=o?.tokenName;if(e["--revoke"]&&o){if(!r||!s){let c=await U(n,o.token);r=c.personalAccessTokenId,s=c.name}await E(n,`/v1/personal-access-tokens/${encodeURIComponent(r)}/revoke`,C({tenantId:o.tenantId,personalAccessTokenId:r}),o.token,[o.token])}let i=await st(n,t),a=e["--revoke"]===!0;mn(e,{cleanup:i,personalAccessTokenId:r,revoked:a,status:"signed_out",tokenName:s})}function mn(e,t){let n=t.cleanup.keychainDeleted?"complete":"tombstoned";if(e["--json"])P({credentialCleanup:n,...t.personalAccessTokenId?{personalAccessTokenId:t.personalAccessTokenId}:{},...t.revoked===void 0?{}:{revoked:t.revoked},status:t.status,...t.tokenName?{tokenName:t.tokenName}:{},...t.revoked===!1?{tokenStillValid:!0}:{}});else{let o=t.tokenName&&t.personalAccessTokenId?`${t.tokenName} (${t.personalAccessTokenId})`:"with unavailable local metadata";t.revoked?p(`Revoked founder PAT ${o} and forgot local state.`):(p(`Forgot local founder PAT ${o}.`),p("The PAT stays valid until expiry; revoke at /desk/security/tokens."))}t.cleanup.keychainDeleted||process.stderr.write(`Keychain cleanup failed. A 0600 profile tombstone blocks the stale founder PAT.
|
|
36
|
+
`)}function F(e,t){if(!e||typeof e!="object"||!Array.isArray(e.items))throw new d(`${t} returned an invalid collection`);return e.items}async function le(e,t,n,o,r,s=[]){let i=[],a=new Set,c,u;for(;;){let k=new URLSearchParams(n);c&&k.set("cursor",c);let g=k.size>0?`?${k}`:"",h=await E(e,`${t}${g}`,{},r,s);u===void 0&&(u=h),i.push(...F(h,o));let I=h.nextCursor;if(typeof I!="string"||I.length===0)break;if(a.has(I))throw new d(`${o} repeated cursor ${I}`);a.add(I),c=I}let{items:l,nextCursor:f,...m}=u;return{...m,items:i}}function ft(e,t=[]){let n=e.headers.get("hyperscale-operation-id"),o=e.headers.get("hyperscale-receipt-id"),r=n?y(n,t):void 0,s=o?y(o,t):void 0;return{...r?{operationId:r}:{},...s?{receiptId:s}:{}}}function mt(e,t,n=[]){if(!e.ok)throw de(e,t,n);try{return JSON.parse(t)}catch{throw new d(`HTTP ${e.status} returned invalid JSON`)}}async function hn(e,t){let n=e["--source"],o=e["--name"];if(!n)throw new d("product create needs --source <file>",{fix:'Run "hyperscale product create --source <file.hsx> --name <name>".'});if(!o)throw new d("product create needs --name <name>");let r=await gt(n,"product create"),s=await $(e,t),i;try{i=await le(s,"/v1/products",{tenantId:s.tenantId},"product.list",s.token,[s.token])}catch(h){if(!(h instanceof O)||h.status!==403)throw h}let a=o.trim().toLocaleLowerCase("en-US"),c=(i?F(i,"product.list"):[]).find(h=>{let I=h?.displayName??h?.name;return typeof I=="string"&&I.trim().toLocaleLowerCase("en-US")===a});if(c){let h=c.productId??c.id??"<id>";throw new d(`A Product named ${JSON.stringify(o.trim())} already exists as ${h}.`,{code:"duplicate_product_name",fix:`Use "hyperscale product select ${h}" or choose another --name.`})}let u="/v1/products/instruments-compose",l={name:o,program:{source:r.source},tenantId:s.tenantId,...e["--catalog-revision"]?{catalogRevisionId:e["--catalog-revision"]}:{}},f=await E(s,u,C(l),s.token,[s.token]);if(typeof f?.productId!="string"||typeof f?.productBuildId!="string")throw new d("product.instruments.compose returned an invalid Product");await Te(t,{...s,selectedProduct:f.productId});let m=typeof f?.shown_once=="string"&&f.shown_once.length>0?f.shown_once:void 0,k=[`hyperscale product show ${f.productId}`,...m?[]:[`hyperscale key create --name "Founder CLI" --product ${f.productId}`]],g={nextCommands:k,nextSteps:k,productBuildId:f.productBuildId,productId:f.productId,selectedProduct:f.productId,...typeof f.startKeyId=="string"?{startKeyId:f.startKeyId}:{},...m?{shown_once:m}:{}};if(e["--json"]){P(g);return}p(`Product: ${g.productId}`),p(`Build: ${g.productBuildId}`),p(`Selected: ${g.selectedProduct}`),g.shown_once&&p(`Shown once Product API key: ${g.shown_once}`),p("Next:");for(let h of g.nextSteps)p(` ${h}`)}function ht(e){return new URLSearchParams({tenantId:e}).toString()}async function yn(e,t){let n=await $(e,t),o=await le(n,"/v1/products",{tenantId:n.tenantId},"product.list",n.token,[n.token]),r=F(o,"product.list");if(e["--json"]){P(o);return}if(r.length===0){p('No Products yet. Run "hyperscale product create --source <file.hsx> --name <name>".');return}let s=b(process.stdout,t,{json:!1});p(_(s,{columns:["ID","Name","Status"],rows:r.map(i=>[i.productId??i.id??"unknown",i.displayName??i.name??"unnamed",i.status??""])}))}async function gn(e,t,n){let o=await $(e,t),r=n??o.selectedProduct;if(!r)throw new d("product show needs an id because no Product is selected. Create a Product first.",{fix:'Run "hyperscale product list" to see existing Products, or "hyperscale product create" to create one.'});let s=await E(o,`/v1/products/${encodeURIComponent(r)}?${ht(o.tenantId)}`,{},o.token,[o.token]);if(e["--json"]){P({...s,nextCommands:[`hyperscale product actions --product ${r}`,`hyperscale key list --product ${r}`]});return}wn(s,r)}function wn(e,t){let n=e?.displayName??e?.name??"unnamed",o=e?.status??"unknown",r=e?.pricing?.currency??e?.cost?.currency??"SAR",s=e?.pricing?.current?.monthly??e?.cost?.platformMonthly,i=e?.pricing?.current?.setup??e?.cost?.platformSetup,a=[...Array.isArray(e?.readiness?.outstandingLiveRequirements)?e.readiness.outstandingLiveRequirements.map(l=>typeof l=="string"?l:l?.owner?`${l.key} (${l.owner})`:l?.key):[],...Array.isArray(e?.readiness?.liveUnavailableCapabilities)?e.readiness.liveUnavailableCapabilities.map(l=>`unavailable:${l}`):[],...Array.isArray(e?.cost?.blockers)?e.cost.blockers.map(l=>l?.code??"pricing"):[]],c=b(process.stdout,process.env,{json:!1}),u=[["Name",n],["Product",e?.productId??t],["Status",o]];if(e?.pricing?.scheduled){let l=e.pricing.current?.monthly,f=e.pricing.scheduled?.monthly;u.push(["Current billing price",`${r} ${l}/mo`],[`Accepted price from ${e.pricing.scheduled.effectiveAt}`,`${r} ${f}/mo`])}else u.push(["Monthly",s==null?"not returned":`${r} ${s}`]);u.push(["Setup",i==null?"not returned":`${r} ${i}`]),u.push(["Live",e?.readiness?.live===!0?"active":"not active"]),u.push(["Live blockers",a.length>0?a.join(", "):"none"]);for(let[l,f]of[["openapi","OpenAPI"],["mcp","MCP"],["sdk","SDK"],["graphql","GraphQL"]]){let m=e?.surfaces?.[l];m?.url&&u.push([f,m.url])}p(L(c,{fields:u})),p(""),p("Next:"),p(` hyperscale key create --name "Founder CLI" --product ${e?.productId??t}`)}async function kn(e,t,n){if(!n)throw new d("product select needs a Product id",{fix:'Run "hyperscale product list" to list Products, then pass one ID.'});let o=await $(e,t),r=await E(o,`/v1/products/${encodeURIComponent(n)}?${ht(o.tenantId)}`,{},o.token,[o.token]);if(r?.productId!==n)throw new d("product.retrieve returned the wrong Product");await Te(t,{...o,selectedProduct:n});let i={nextCommands:[`hyperscale product show ${n}`,`hyperscale key list --product ${n}`],productId:n,selected:!0};e["--json"]?P(i):p(`Selected Product: ${r.displayName??n} (${n})`)}function In(e){return e.map(t=>`${t.path}: error [composer] ${t.code}: ${t.message}`)}function Pn(e){return JSON.stringify(xe(e))}function xe(e){if(e===null||typeof e!="object")return e;if(Array.isArray(e))return e.map(xe);let t={};for(let n of Object.keys(e).sort())t[n]=xe(e[n]);return t}function yt(e,t=""){if(e==null)return t;if(typeof e=="string")return e;if(typeof e=="object")try{return Pn(e)}catch{return t}return String(e)}async function gt(e,t="compose"){if(!e)throw new d(`${t} needs a .hsx file`,{fix:`Run "hyperscale ${t} <file.hsx>" with an existing .hsx file.`});if(!e.endsWith(".hsx"))throw new d(`${t} reads a .hsx file, got ${e}`,{fix:`Point ${t} at a file ending in .hsx.`});let n;try{n=await q(e,"utf8")}catch(o){throw new d(`Could not read ${e}: ${o.message}`)}return{file:e,source:n}}function bn(e){if(!e||typeof e!="object"||typeof e.ok!="boolean"||!Array.isArray(e.issues))throw new d("composer.check returned an invalid result",{fix:'Run the latest unpinned CLI (e.g. "bunx @hyperscale0/cli@latest <command>"), or report the issue without including credentials.'});return{issues:e.issues.map(n=>{if(!n||typeof n!="object"||typeof n.code!="string"||typeof n.message!="string"||typeof n.path!="string")throw new d("composer.check returned an invalid issue",{fix:'Run the latest unpinned CLI (e.g. "bunx @hyperscale0/cli@latest <command>"), or report the issue without including credentials.'});return{code:n.code,message:n.message,path:n.path}}),ok:e.ok}}async function Ne(e,t,n,o="none",r="compose"){let s=await gt(n,r),i=await $(e,t),a=o==="required"?W(i,e):o==="optional"?kt(i,e):void 0,c=await Oe(i,"/v1/composer/check",C({tenantId:i.tenantId,document:s.source,...e["--catalog-revision"]?{catalogRevisionId:e["--catalog-revision"]}:{}}),i.token),u=ft(c.response,[i.token]),l=bn(mt(c.response,c.text,[i.token]));if(!l.ok)throw new te(["composer.check refused the program.",...In(l.issues)].join(`
|
|
37
|
+
`),{file:n,issues:l.issues,...u});return{check:l,receipt:u,context:i,productId:a,program:s,catalogRevisionId:e["--catalog-revision"]}}async function xn(e,t,n){let o=await Ne(e,t,n,"none","compose check");if(e["--json"]){P({command:"composer.check",file:n,issues:o.check.issues,ok:!0,...o.receipt});return}p(`Check passed: ${n}`)}async function wt(e,t){let n=await Oe(e.context,"/v1/composer/plan",C({document:e.program.source,tenantId:e.context.tenantId,...e.productId?{productId:e.productId}:{},...e.catalogRevisionId?{catalogRevisionId:e.catalogRevisionId}:{}}),e.context.token),o=mt(n.response,n.text,[e.context.token]),r=ft(n.response,[e.context.token]);if(!o||typeof o!="object"||typeof o.summary!="string"||!Array.isArray(o.actions)||!o.pricing||typeof o.pricing!="object")throw new d("composer.plan returned an invalid result");let s=o.actions.filter(i=>!i||typeof i!="object"||i.kind!=="configure_product");if(s.length>0)throw new te([o.summary,...s.map(i=>i&&typeof i=="object"?`${i.kind??"unknown"} ${i.target??"unknown"} ${yt(i.detail,"Composer refused this action.")}`:"unknown unknown Composer returned an invalid refusal action.")].join(`
|
|
38
|
+
`),{actions:s,file:t,...r,...e.productId?{productId:e.productId}:{}});return{...o,...r}}async function $n(e,t,n){let o=await Ne(e,t,n,"optional","compose plan"),r=await wt(o,n);if(e["--json"]){P({command:"composer.plan",file:n,check:{...o.check,...o.receipt},plan:r,...o.productId?{productId:o.productId}:{}});return}p(r.summary);for(let i of r.actions)p(`${i.kind} ${i.target} ${yt(i.detail)}`);let s=r.pricing?.currency??"SAR";if(r.pricing?.scheduled){let i=r.pricing.current?.monthly,a=r.pricing.scheduled?.monthly;p(`Current billing price: ${s} ${i}/mo`),p(`Candidate price from ${r.pricing.scheduled.effectiveAt}: ${s} ${a}/mo`),p(`Pricing identity: ${r.pricing.scheduled.pricingIdentity}`)}else if(r.pricing){let i=r.pricing.monthly,a=r.pricing.activation;i!==void 0&&p(`Monthly: ${s} ${i}`),a!==void 0&&p(`Activation: ${s} ${a}`)}}async function An(e,t,n){if(!e["--confirm"]&&!e["--yes"])if(process.stdin.isTTY&&process.stderr.isTTY){let c=b(process.stderr,process.env,{json:!1});process.stderr.write(`${Me(c,{action:"recompose",subject:n,confirmation:"Recompose selected Product?"})}
|
|
39
|
+
`);let u=Nt({input:process.stdin,output:process.stderr,terminal:!0});try{let l=await u.question("");if(l.trim().toLowerCase()!=="y"&&l.trim().toLowerCase()!=="yes")throw new d("Mutation cancelled.",{code:"cancelled"})}finally{u.close()}}else throw new d("compose apply changes the selected Product. Pass --confirm, or --yes for an agent.");let o=e["--pricing-identity"];if(!o&&e["--plan-file"]){let c=e["--plan-file"];try{let u=await q(c,"utf8"),l=JSON.parse(u);o=l.plan?.pricing?.scheduled?.pricingIdentity??l.pricing?.scheduled?.pricingIdentity??l.pricingIdentity}catch(u){throw new d(`Failed to read saved plan file ${c}: ${u.message}`)}}let r=await Ne(e,t,n,"required","compose apply"),s=await wt(r,n);if(s.pricing?.scheduled&&!o){if(!e["--yes"])throw new d(`compose apply --confirm requires --pricing-identity (or --plan-file). Run "hyperscale compose plan ${n}" to review candidate pricing and copy the pricing identity, or pass --yes to accept the current candidate.`);o=s.pricing.scheduled.pricingIdentity}let i=e["--idempotency-key"]??globalThis.crypto.randomUUID(),a;try{a=await E(r.context,"/v1/products/recompose",C({program:{source:r.program.source},...r.catalogRevisionId?{catalogRevisionId:r.catalogRevisionId}:{},...o?{pricingIdentity:o}:{},tenantId:r.context.tenantId,productId:r.productId},i),r.context.token,[r.context.token])}catch(c){throw c instanceof O&&c.code==="product_instrument_not_drained"&&(c.fix=`Drain live instrument instances, or create a new Product directly from source: hyperscale product create --source ${n} --name <name>`),c}if(!a||typeof a.productBuildId!="string")throw new d("product.recompose returned no new build identity");if(e["--json"]){P({command:"product.recompose",file:n,output:a});return}if(p(`Product: ${a.productId??r.productId}`),p(`Build: ${a.productBuildId}`),a.buildDigest&&p(`Digest: ${a.buildDigest}`),a.pricing?.scheduled){let c=a.pricing.currency??"SAR",u=a.pricing.current?.monthly,l=a.pricing.scheduled?.monthly;p(`Current billing price: ${c} ${u}/mo`),p(`Accepted price from ${a.pricing.scheduled.effectiveAt}: ${c} ${l}/mo`)}}function kt(e,t){let n=t["--product"]??e.selectedProduct;return typeof n=="string"&&n.length>0?n:void 0}function W(e,t){let n=kt(e,t);if(!n)throw new d("No Product selected. Pass --product <id> or create a Product first.",{fix:'Run "hyperscale product list" to see existing Products, or "hyperscale product create" to create one.'});return n}async function re(e,t){let n=await ae(t),o=W(n??{},e),r=ne(e,t,n??{});if(n&&(r.baseUrl!==n.baseUrl||r.environment!==n.environment))throw new d(`The selected Product belongs to ${n.baseUrl} (${n.environment}). Select a Product at the configured API origin first.`);let s=e["--api-key"]??t.HYPERSCALE_API_KEY;if(!s)throw et(o);return{...r,apiKey:s,productId:o}}async function It(e,t){let n=`/v1/products/${encodeURIComponent(e.productId)}/operation-set`,{response:o,text:r}=await ue(e,n,{},t);if(!o.ok)throw bt(o,r,[e.apiKey],{productId:e.productId});return En(r,o.status)}async function Sn(e,t,n){let o=await re(e,t),r=await It(o);if(n){Rn(r,n,e);return}if(e["--json"]){P(r);return}if(r.publicActions.length===0)p("No public actions");else{let s=b(process.stdout,t,{json:!1});p(_(s,{columns:["Operation ID","Input","Kind"],rows:r.publicActions.map(i=>{let a=i.idempotencyPolicy?.mode==="not_required"?"read-only":"mutation";return[`${i.instrument}.${i.name}`,vn(i.inputSchema),a]})}))}if(r.setupOperations.length>0){p("Setup operations (run with hyperscale call)");for(let s of r.setupOperations)p(s.operationName)}if(r.readOperationIds.length>0){p("Reads (run with hyperscale call)");for(let s of r.readOperationIds)p(Cn(s))}p(`Digest: ${r.tenantOperationSetDigest}`),p(`Setup digest: ${r.tenantSetupOperationSetDigest}`),p(`Read digest: ${r.tenantReadOperationSetDigest}`),p(`Build: ${r.productBuildId}`),p(`Surface version: ${r.tenantSurfaceVersion}`)}function Rn(e,t,n){let o=e.publicActions.find(c=>c&&`${c.instrument}.${c.name}`===t),r=Tn(t),s=e.setupOperations.find(c=>c&&(c.operationId===t||c.operationId===r||c.operationName===t));if(s){let{inputSchema:c,operationId:u,operationName:l}=s,f={status:e.status,productBuildId:e.productBuildId,tenantSurfaceVersion:e.tenantSurfaceVersion,tenantSetupOperationSetDigest:e.tenantSetupOperationSetDigest,setupOperationId:u,operationName:l,command:`hyperscale call ${l}`,inputSchema:c};if(n["--json"]){P(f);return}let m=b(process.stdout,n?process.env:{},{json:!1}),k=[["Operation ID",u],["Operation name",l],["Run",`hyperscale call ${l}`],["Input schema",JSON.stringify(c,null,2)]];(!Array.isArray(c.required)||c.required.length===0)&&k.push(["Input","omit --input or pass {}."]),k.push(["Setup digest",e.tenantSetupOperationSetDigest],["Build",e.productBuildId],["Surface version",e.tenantSurfaceVersion]),p(L(m,{fields:k}));return}if(!o)throw new d(`Unknown frozen public action: ${t}. Run "hyperscale product actions" to list exact names.`);let i={status:e.status,productBuildId:e.productBuildId,tenantSurfaceVersion:e.tenantSurfaceVersion,tenantOperationSetDigest:e.tenantOperationSetDigest,qualifiedName:`${o.instrument}.${o.name}`,publicAction:o};if(n["--json"]){P(i);return}let a=b(process.stdout,n?process.env:{},{json:!1});p(L(a,{fields:[["Operation ID",`${o.instrument}.${o.name}`],["Instrument",o.instrument],["Input schema",JSON.stringify(o.inputSchema,null,2)],["Output schema",JSON.stringify(o.outputSchema,null,2)],["Actor policy",JSON.stringify(o.actorPolicy,null,2)],["Port policy",JSON.stringify(o.portPolicy,null,2)],["Idempotency policy",JSON.stringify(o.idempotencyPolicy,null,2)],["Receipt policy",JSON.stringify(o.receiptPolicy,null,2)],["Receipt evidence",JSON.stringify(o.receiptEvidence,null,2)],["Digest",e.tenantOperationSetDigest],["Build",e.productBuildId],["Surface version",e.tenantSurfaceVersion]]}))}function En(e,t){let n;try{n=JSON.parse(e)}catch{throw new d(`HTTP ${t} returned invalid JSON`)}if(!n||typeof n!="object"||n.status!=="frozen"||typeof n.productBuildId!="string"||typeof n.tenantSurfaceVersion!="number"||typeof n.tenantOperationSetDigest!="string"||typeof n.tenantReadOperationSetDigest!="string"||typeof n.tenantSetupOperationSetDigest!="string"||!Array.isArray(n.publicActions)||!Array.isArray(n.readOperationIds)||!Array.isArray(n.setupOperationIds)||!Array.isArray(n.setupOperations))throw new d("The Product operation set is not in the expected format.",{fix:'Run the latest unpinned CLI (e.g. "bunx @hyperscale0/cli@latest <command>"), or report the issue without including credentials.'});return n.publicActions=n.publicActions.map(o=>{if(!o||typeof o!="object"||typeof o.instrument!="string"||o.instrument.length===0||typeof o.name!="string"||o.name.length===0)throw new d("The server's public action names no instrument or action name. The platform predates Product identity in public actions: redeploy it.");return{...o,qualifiedName:`${o.instrument}.${o.name}`}}),n}function Tn(e){return e.replaceAll(".","_")}function Cn(e){for(let t of["create","list","retrieve"]){let n=`_${t}`;if(e.endsWith(n))return`${e.slice(0,-n.length)}.${t}`}return e}function vn(e){if(!e||typeof e!="object")return"input schema unavailable";let t=e.properties&&typeof e.properties=="object"&&!Array.isArray(e.properties)?e.properties:{},n=new Set(Array.isArray(e.required)?e.required.filter(r=>typeof r=="string"):[]),o=Object.entries(t).map(([r,s])=>`${r}${n.has(r)?"":"?"}: ${Pt(s)}`);return o.length===0?"no input":o.join(", ")}function Pt(e){return!e||typeof e!="object"?"value":Array.isArray(e.enum)&&e.enum.length>0?e.enum.map(t=>String(t)).join(" | "):e.type==="array"?`${Pt(e.items)}[]`:typeof e.type=="string"?typeof e.format=="string"?`${e.type} (${e.format})`:e.type:"value"}async function On(e,t,n){if(!n)throw new d("product run needs a public action");let o=await re(e,t),r=await It(o,n);jn(r,n);let s=await xt(e),i=e["--idempotency-key"]??globalThis.crypto.randomUUID(),{response:a,text:c}=await ue(o,`/v1/operations/${encodeURIComponent(n)}`,{body:JSON.stringify(s),headers:{"content-type":"application/json","idempotency-key":i},method:"POST"},n);if(!a.ok)throw bt(a,c,[o.apiKey],{action:n,productId:o.productId});let u=a.headers.get("hyperscale-operation-id"),l=a.headers.get("hyperscale-receipt-id"),f=a.headers.get("x-request-id"),m=u?y(u,[o.apiKey]):null,k=l?y(l,[o.apiKey]):null,g=f?y(f,[o.apiKey]):null;if(e["--json"]){P({idempotencyKey:i,...g?{requestId:g}:{},operationId:m,receiptId:k,output:Nn(c)});return}m&&p(`Operation: ${m}`),k&&p(`Receipt: ${k}`),p(`Idempotency key: ${i}`);let h=$t(c);h&&p(h)}function jn(e,t){let n=e.publicActions.find(r=>r&&`${r.instrument}.${r.name}`===t);if(n)return n;let o=e.publicActions.map(r=>`${r.instrument}.${r.name}`).map(r=>({candidate:r,distance:Ae(t,r)})).sort((r,s)=>r.distance-s.distance||r.candidate.localeCompare(s.candidate)).slice(0,3).map(({candidate:r})=>r);throw new d(`Unknown frozen public action: ${t}. Closest valid names: ${o.join(", ")}. Run "hyperscale product actions" to list exact names.`)}function Nn(e){if(e.trim()==="")return null;try{return JSON.parse(e)}catch{return e}}function bt(e,t,n=[],o={}){let r=pt(t,n,e.status),s=lt(e.headers,r.requestId,n),i=r.code??"user_error",a=r.redactedMessage;if(typeof a=="string"&&a.includes("does not match API key Product")){let m=o.productId??a.match(/^Selected Product (\S+) does not match/)?.[1];m&&(a=`${a} Or set HYPERSCALE_API_KEY to a key for ${m}, or pass that key with --api-key.`)}let c=i==="user_error"?"":`${i}: `,u=`HTTP ${e.status} \xB7 ${c}${a}`,l=_n(r.details,n),f=r.fix;return i==="idempotency_conflict"?f="Reuse the same key only with the same operation and input. Use a new unique key for a different request.":e.status===409&&typeof a=="string"&&a.includes("capability-derived")?f='This Product has no frozen public actions. List its operations with "hyperscale ops list" and run them with "hyperscale call".':[a,...l].some(m=>typeof m=="string"&&m.includes("[Truncated]"))&&o.action&&(f=`Run "hyperscale product actions ${o.action}" to read the full input schema and allowed values.`),new O([u,...l].join(`
|
|
40
|
+
`),{code:i,details:r.details,fix:f,operationId:s.operationId,receiptId:s.receiptId,requestId:s.requestId,status:e.status,traceId:s.traceId})}function _n(e,t){if(!e||typeof e!="object")return[];if(Array.isArray(e.issues))return e.issues.flatMap(o=>{if(!o||typeof o!="object")return[];let s=(Array.isArray(o.path)?o.path.join("."):"input")||"input";return typeof o.message=="string"?[`${s}: ${y(o.message,t)}`]:[]});let n=[];return $e(e,"",n,t),n}function $e(e,t,n,o){if(Array.isArray(e)){if(e.every(r=>r===null||typeof r!="object")){n.push(`${Ve(t)}: ${y(e.join(", "),o)}`);return}e.forEach((r,s)=>$e(r,`${t}[${s}]`,n,o));return}if(e&&typeof e=="object"){for(let[r,s]of Object.entries(e))$e(s,t?`${t}.${r}`:r,n,o);return}t&&n.push(`${Ve(t)}: ${y(String(e),o)}`)}function Ve(e){let t=e.replace(/([a-z0-9])([A-Z])/g,"$1 $2").replaceAll("."," ");return t.charAt(0).toUpperCase()+t.slice(1)}async function Ln(e,t){let n=await $(e,t),o=W(n,e),r=await E(n,"/v1/sandbox-api-keys",C({name:e["--name"]??"Founder CLI",tenantId:n.tenantId,productId:o}),n.token,[n.token]),s=["export HYPERSCALE_API_KEY=<paste the shown_once value>",`hyperscale product actions --product ${o}`];if(e["--json"]){let{secret:i,...a}=r;P({...a,...typeof i=="string"?{shown_once:i}:{},nextCommands:s});return}p(`Key: ${r.apiKeyId??"unknown"}`),p(`Product: ${r.productId??o}`),p(`Status: ${r.status??"unknown"}`),r.secret?(p(`Secret: ${r.secret}`),p("Store it now. Hyperscale will not return it again."),p("Next:"),p(" export HYPERSCALE_API_KEY=<paste the secret above>"),p(` hyperscale product actions --product ${o}`)):p("The key already existed, so the one-time secret is unavailable.")}async function Un(e,t){let n=await $(e,t),o=W(n,e),r=await le(n,"/v1/api-keys",{productId:o,tenantId:n.tenantId},"api_key.list",n.token,[n.token]),s=F(r,"api_key.list");if(e["--json"]){P(r);return}let i=b(process.stdout,t,{json:!1});p(_(i,{columns:["ID","Name","Status"],rows:s.map(a=>[a.apiKeyId,a.name??"unnamed",a.status??"unknown"])}))}async function Hn(e,t,n){if(!n)throw new d("key revoke needs an API key id",{fix:'Run "hyperscale key list" to list keys, then pass one ID.'});let o=await $(e,t),r=W(o,e),s=await E(o,`/v1/api-keys/${encodeURIComponent(n)}/revoke`,C({tenantId:o.tenantId,productId:r}),o.token,[o.token]);e["--json"]?P(s):p(`Key ${s.apiKeyId??n}: ${s.status??"revoked"}`)}async function Dn(e,t){let n=await $(e,t),o=n.identity??await U(n,n.token),r=je(n,o);if(e["--json"]){P(r);return}let s=b(process.stdout,t,{json:!1});p(L(s,{fields:[["User",o.email],["Tenant",o.tenantId],["Role",o.role],["Token",o.name],["Expires",o.expiresAt]]}))}async function Kn(e,t,n){let o=await ut(e),r=n?n.toLowerCase():null,s=r?o.operations.filter(a=>a.name.toLowerCase().includes(r)||a.path.toLowerCase().includes(r)):o.operations;if(t["--json"]){p(JSON.stringify(s,null,2));return}if(s.length===0){p(n?`No operation matches ${n}`:"No operations");return}let i=b(process.stdout,process.env,{json:!1});p(_(i,{columns:["Operation","Method","Path"],rows:s.map(a=>[a.name,a.method,a.path])}))}async function Jn(e,t){let n=await $(e,t),o=await le(n,"/v1/activity",{tenantId:n.tenantId},"activity.list",n.token,[n.token]),r=F(o,"activity.list");if(e["--json"]){P(o);return}let s=b(process.stdout,t,{json:!1});p(_(s,{columns:["Time","Activity","Target","Status"],rows:r.map(i=>{let a=i.operation??i.auditEvent??"activity",c=i.resourceKind&&i.resourceId?`${i.resourceKind}:${i.resourceId}`:i.resourceKind??i.resourceId??"-";return[i.occurredAt??"unknown",a,c,i.status??"recorded"]})}))}function Yn(e,t){let n={...t},o=[],r=e.path.replace(/\{([^}]+)\}/g,(s,i)=>{let a=n[i];return a==null?(o.push(i),""):(delete n[i],encodeURIComponent(String(a)))});if(o.length>0)throw new d(`${e.name} needs ${o.join(", ")} in --input`);return{path:r,remaining:n}}function Mn(e){let t=new URLSearchParams;for(let[o,r]of Object.entries(e))r!=null&&t.set(o,typeof r=="string"?r:JSON.stringify(r));let n=t.toString();return n?`?${n}`:""}function Ae(e,t){let n=Array.from({length:t.length+1},(o,r)=>r);for(let o=1;o<=e.length;o+=1){let r=[o];for(let s=1;s<=t.length;s+=1)r[s]=Math.min(r[s-1]+1,n[s]+1,n[s-1]+(e[o-1]===t[s-1]?0:1));n.splice(0,n.length,...r)}return n[t.length]}function qn(e,t){let n=e.find(s=>s.name===t);if(n)return n;let o=e.filter(s=>s.operationId===t);if(o.length===1)return o[0];if(o.length>1)throw new d(`${t} matches more than one operation. Use one of: ${o.map(s=>s.name).join(", ")}.`);let r=e.map(s=>({candidate:s,distance:Math.min(Ae(t,s.name),Ae(t,s.operationId))})).sort((s,i)=>s.distance-i.distance||s.candidate.name.localeCompare(i.candidate.name)).slice(0,3).flatMap(({candidate:s})=>[s.name,s.operationId]);throw new d(`${t} is not an operation in the selected Product's machine document. Closest valid names: ${r.join(", ")}.`)}async function Bn(e,t,n){if(!n)throw new d("call needs an operation name",{fix:'Run "hyperscale ops list" to list operations.'});let o=await ut(e),r=qn(o.operations,n),s=await xt(t),{path:i,remaining:a}=Yn(r,s),c={method:r.method},u=i;r.method==="GET"?u+=Mn(a):(c.body=JSON.stringify(a),c.headers={"content-type":"application/json",...r.idempotency==="not_required"?{}:{"idempotency-key":t["--idempotency-key"]??globalThis.crypto.randomUUID()}});let{response:l,text:f}=await ue(e,u,c);if(l.ok){if(t["--json"]){let m=sn(f),k=l.headers.get("x-request-id")??(m&&typeof m=="object"&&typeof m.requestId=="string"?m.requestId:null),g=l.headers.get("hyperscale-operation-id")??null,h=l.headers.get("hyperscale-receipt-id")??null,I=dt(l.headers),T=k?y(k,[e.apiKey]):null,v=g?y(g,[e.apiKey]):null,z=h?y(h,[e.apiKey]):null,j=I?y(I,[e.apiKey]):null;P({status:l.status,data:m,requestId:T,operationId:v,receiptId:z,traceId:j});return}p($t(f));return}throw de(l,f,[e.apiKey])}async function xt(e){if(e["--input"]!==void 0&&e["--input-file"]!==void 0)throw new d("Use only one of --input and --input-file");if(e["--input"]!==void 0)return we(e["--input"],"--input");if(e["--input-file"]!==void 0){let t;try{t=await q(e["--input-file"],"utf8")}catch(n){throw new d(`Could not read ${e["--input-file"]}: ${n.message}`)}return we(t,"--input-file")}if(!process.stdin.isTTY){let t=await on();if(t.trim()!=="")return we(t,"stdin")}return{}}function we(e,t="--input"){if(e===void 0)return{};let n;try{n=JSON.parse(e)}catch(o){throw new d(`${t} is not valid JSON: ${o.message}`)}if(n===null||typeof n!="object"||Array.isArray(n))throw new d(`${t} must be a JSON object`);return n}function $t(e){if(e.trim()==="")return"";try{return JSON.stringify(JSON.parse(e),null,2)}catch{return e}}function p(e){process.stdout.write(`${e}
|
|
41
|
+
`)}function P(e){p(JSON.stringify(e,null,2))}function Fn(e,t){let n=t.includes("--json"),o=[process.env.HYPERSCALE_API_KEY,process.env.HYPERSCALE_TOKEN].filter(Boolean),r=e instanceof d,s=r?e.message:"The command failed unexpectedly.",i=w(y(String(s),o)),a=i.length>1024?i.slice(0,1024):i,c=r?e.fix??'Follow the message, or run "hyperscale --help" for command usage.':"Report the failure without including credentials.",u=w(y(String(c),o)),l=r&&typeof e.shownOnce=="string"?w(y(e.shownOnce,o)):void 0;if(!n){let S=b(process.stderr,process.env,{json:!1}),At=(typeof e?.structuredError?.code=="string"?e.structuredError.code:void 0)??(r&&typeof e.code=="string"?e.code:r?"user_error":"internal_error"),St=r?a:i,Rt=l?`
|
|
42
|
+
Shown once Product API key: ${l}`:"",Et=qe(S,{code:At,message:St,nextStep:u});process.stderr.write(`${Et}${Rt}
|
|
43
|
+
`);return}let f=(typeof e?.structuredError?.code=="string"?e.structuredError.code:void 0)??(r&&typeof e.code=="string"?e.code:r?"user_error":"internal_error"),m=(typeof e?.structuredError?.message=="string"?e.structuredError.message:void 0)??(r?e.message:"The command failed unexpectedly."),k=w(y(String(m),o)),g=k.length>1024?k.slice(0,1024):k,h=(typeof e?.structuredError?.fix=="string"?e.structuredError.fix:void 0)??(r?e.fix??'Follow the message, or run "hyperscale --help" for command usage.':"Report the failure without including credentials."),I=w(y(String(h),o)),T=I.length>1024?I.slice(0,1024):I,v=e?.structuredError?.details!==void 0?e.structuredError.details:r&&e.details!==void 0?e.details:void 0,z=v!==void 0?oe(v,o):void 0,j=r&&typeof e.status=="number"?e.status:void 0,V=S=>typeof S!="string"||S.trim().length===0?null:w(y(S.trim(),o)),G=r&&(e.requestId!==void 0||e.operationId!==void 0||e.receiptId!==void 0||e.traceId!==void 0),X=G?V(e.requestId):void 0,Z=G?V(e.operationId):void 0,Q=G?V(e.receiptId):void 0,ee=G?V(e.traceId):void 0,_e=S=>({...j!==void 0?{status:j}:{},error:{code:f,message:g,...S!==void 0?{details:S}:{},fix:T},...X!==void 0?{requestId:X}:{},...Z!==void 0?{operationId:Z}:{},...Q!==void 0?{receiptId:Q}:{},...ee!==void 0?{traceId:ee}:{},...l?{shown_once:l}:{}}),Le=S=>Buffer.byteLength(S,"utf8")>8192,H=_e(z),D=JSON.stringify(H);Le(D)&&z!==void 0&&(H=_e("[Truncated]"),D=JSON.stringify(H)),Le(D)&&(H={...j!==void 0?{status:j}:{},error:{code:f,message:g,fix:"[Truncated]"},...X!==void 0?{requestId:X}:{},...Z!==void 0?{operationId:Z}:{},...Q!==void 0?{receiptId:Q}:{},...ee!==void 0?{traceId:ee}:{}},D=JSON.stringify(H)),process.stderr.write(`${D}
|
|
44
|
+
`)}async function Wn(){let{readFileSync:e}=await import("node:fs");return JSON.parse(e(new URL("./package.json",import.meta.url),"utf8")).version}async function zn(e,t){let{flags:n,positional:o}=Vt(e);if(n["--version"])return p(await Wn()),0;if(n["--help"]&&o.length>0){let i=b(process.stdout,t,{json:!1});return p(Fe(o,i)),0}if(o[0]==="help"){let i=o.slice(1),a=b(process.stdout,t,{json:!1});return i.length===0?p(fe(a)):p(Fe(i,a)),0}if(o.length===0&&!n["--help"]){if(n["--json"])throw new d('No command. Run "hyperscale --help" to list commands.');if(!await $(n,t,!0)){let a=b(process.stdout,t,{json:!1});return p(Je(a)),0}return p('Build your first Product with "hyperscale product create --source <file.hsx> --name <name>".'),p('Run "hyperscale --help" for every command.'),0}if(n["--help"]){let i=b(process.stdout,t,{json:!1});return p(fe(i)),0}let[r,...s]=o;if(r==="auth"){if(s[0]==="login")await ln(n,t);else if(s[0]==="status")await pn(n,t);else if(s[0]==="logout")await fn(n,t);else throw new d('Auth subcommands are "login", "status", and "logout"',{fix:'Run "hyperscale help auth" to see valid subcommands.'});return 0}if(r==="product"){if(s[0]==="create")await hn(n,t);else if(s[0]==="list")await yn(n,t);else if(s[0]==="show")await gn(n,t,s[1]);else if(s[0]==="select")await kn(n,t,s[1]);else if(s[0]==="actions")await Sn(n,t,s[1]);else if(s[0]==="run")await On(n,t,s[1]);else throw new d('Product subcommands are "create", "list", "show", "select", "actions", and "run"',{fix:'Run "hyperscale help product" to see valid subcommands.'});return 0}if(r==="compose"){if(s[0]==="check")await xn(n,t,s[1]);else if(s[0]==="plan")await $n(n,t,s[1]);else if(s[0]==="apply")await An(n,t,s[1]);else throw new d('Compose subcommands are "check", "plan", and "apply"',{fix:'Run "hyperscale help compose" to see valid subcommands.'});return 0}if(r==="key"){if(s[0]==="create")await Ln(n,t);else if(s[0]==="list")await Un(n,t);else if(s[0]==="revoke")await Hn(n,t,s[1]);else throw new d('Key subcommands are "create", "list", and "revoke"',{fix:'Run "hyperscale help key" to see valid subcommands.'});return 0}if(r==="whoami")return await Dn(n,t),0;if(r==="activity"){if(s[0]!=="list")throw new d('The only activity subcommand is "list"',{fix:'Run "hyperscale help activity" to see usage.'});return await Jn(n,t),0}if(r==="ops"){if(s[0]!=="list")throw new d('The only ops subcommand is "list"',{fix:'Run "hyperscale help ops" to see usage.'});let i=n["--product"]?await re(n,t):We(n,t);return await Kn(i,n,s[1]),0}if(r==="call"){let i=n["--product"]?await re(n,t):We(n,t);return await Bn(i,n,s[0]),0}throw new d(`Unknown command: ${r}`,{fix:'Run "hyperscale --help" to list commands.'})}zn(process.argv.slice(2),process.env).then(e=>{process.exitCode=e},e=>{Fn(e,process.argv.slice(2)),process.exitCode=e instanceof d&&Number.isInteger(e.exitCode)?e.exitCode:1});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyperscale0/cli",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.26",
|
|
4
4
|
"description": "Hyperscale CLI: compose Products, manage keys, and call Product operations.",
|
|
5
5
|
"license": "LicenseRef-Hyperscale-Proprietary",
|
|
6
6
|
"author": "Hyperscale LLC",
|
|
@@ -20,5 +20,5 @@
|
|
|
20
20
|
"publishConfig": {
|
|
21
21
|
"access": "public"
|
|
22
22
|
},
|
|
23
|
-
"gitHead": "
|
|
23
|
+
"gitHead": "ed8866f5e5201aad938ad0219da06e430a513467"
|
|
24
24
|
}
|