@constal/cli 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,30 @@
1
+ # `@constal/cli`
2
+
3
+ The command-line client for the public Constal Platform API.
4
+
5
+ ```sh
6
+ npm install --global @constal/cli
7
+ constal --help
8
+ ```
9
+
10
+ Authenticate and select a namespace:
11
+
12
+ ```sh
13
+ printf '%s' "$CONSTAL_API_KEY" | constal auth login --token-stdin
14
+ constal context use --namespace default
15
+ constal auth status
16
+ ```
17
+
18
+ The CLI covers deployments, Agents and Runs, Resources and bindings, Credentials, Channels, Policies, analytics, Evals and training, Memory, customers, artifacts, stages, and tables. Run `constal help <command>` for exact arguments and examples.
19
+
20
+ Configuration is read in this order:
21
+
22
+ 1. command-line options
23
+ 2. `CONSTAL_PLATFORM_URL`, `CONSTAL_NAMESPACE`, and `CONSTAL_TENANT`
24
+ 3. the saved context file
25
+
26
+ `CONSTAL_API_KEY` overrides the saved credential. Local files live under `$XDG_CONFIG_HOME/constal`, or `~/.config/constal` when `XDG_CONFIG_HOME` is unset. Set `CONSTAL_CONFIG_DIR` to use another directory.
27
+
28
+ JSON values accept inline JSON, `@FILE`, or `@-` for stdin where the command help allows them. Credential material is accepted only through the dedicated file or stdin options and is redacted from CLI output.
29
+
30
+ See the [Constal CLI documentation](https://constal.ai/docs/cli) for complete workflows.
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@constal/cli",
3
+ "version": "1.0.0",
4
+ "description": "Task-oriented command line client for the Constal Platform API",
5
+ "keywords": [
6
+ "constal",
7
+ "agents",
8
+ "cli"
9
+ ],
10
+ "license": "UNLICENSED",
11
+ "homepage": "https://constal.ai",
12
+ "preferGlobal": true,
13
+ "engines": {
14
+ "node": ">=20"
15
+ },
16
+ "type": "module",
17
+ "bin": {
18
+ "constal": "publish/cli.mjs"
19
+ },
20
+ "files": [
21
+ "publish"
22
+ ],
23
+ "publishConfig": {
24
+ "access": "public"
25
+ },
26
+ "scripts": {
27
+ "build": "node ../../scripts/build-cli-package.mjs",
28
+ "test": "vitest run test",
29
+ "prepack": "npm test && npm run build"
30
+ },
31
+ "devDependencies": {
32
+ "esbuild": "^0.28.2"
33
+ }
34
+ }
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env node
2
+ import{createHash as we,randomUUID as Te}from"node:crypto";import{readFile as Ee,writeFile as Se}from"node:fs/promises";import{stdin as Re,stdout as Oe,stderr as Ce}from"node:process";var l=(e,a,n,s={})=>({name:e,value:a,description:n,...s}),t=(e,a,n={})=>({name:e,description:a,...n}),K=Object.freeze([l("help",null,"Show command help."),l("version",null,"Show the CLI version."),l("origin","URL","Override the configured Platform API origin."),l("namespace","NAME","Override the configured namespace."),l("tenant","NAME","Restrict authentication to this tenant."),l("output","FORMAT","Render table, json, or jsonl output.",{choices:["table","json","jsonl"]})]),u=l("body","JSON|@FILE|@-","Read the JSON request body inline, from a file, or from stdin."),ie=l("body","SOURCE","Read protected setup JSON from @FILE or @-."),F=l("idempotency-key","KEY","Use a caller-stable idempotency key."),g=l("event-id","ID","Use a caller-stable idempotency event identifier."),L=l("reason","TEXT","Record an optional operator reason."),v=l("after","CURSOR","Continue after a returned cursor."),f=l("limit","COUNT","Bound the number of returned records."),R=l("out","FILE","Write the binary response to a file instead of stdout."),O=l("quiet",null,"Suppress the file-write status message."),T=(e,a,n={})=>Object.freeze({path:e.split(" "),summary:a,...n}),o=(e,a,n,s,c={})=>T(e,a,{method:n,route:s,...c}),A=Object.freeze([T("auth login","Save a Constal API key using a hidden prompt, stdin, or a file.",{local:"auth.login",options:[l("token-stdin",null,"Read the API key from stdin."),l("token-file","FILE","Read the API key from a file.")],examples:[`printf '%s' "$CONSTAL_API_KEY" | constal auth login --token-stdin`]}),T("auth logout","Remove the locally stored Constal API key.",{local:"auth.logout"}),T("auth status","Check whether the current credentials can read the selected namespace.",{local:"auth.status"}),T("context show","Show the effective origin, tenant restriction, namespace, and credential source.",{local:"context.show"}),T("context use","Persist the default origin, tenant restriction, or namespace.",{local:"context.use",options:[l("origin","URL","Set the Platform API origin."),l("namespace","NAME","Set the default namespace."),l("tenant","NAME","Set the tenant restriction."),l("clear-tenant",null,"Remove the tenant restriction.")],examples:["constal context use --namespace production","constal context use --tenant acme"]}),o("deployments create","Upload an immutable executable ZIP or tar.gz package.","POST","/v1/deployments",{positionals:[t("archive","Path to the ZIP or tar.gz package.")],bodyKind:"archive",query:[["rollout","rollout"],["fraction","fraction"],["tags","tags"]],options:[l("idempotency-key","KEY","Override the content-derived deployment key."),l("rollout","STRATEGY","Activate immediately or begin a canary.",{choices:["immediate","canary"]}),l("fraction","RATE","Fraction of eligible new Sessions assigned to the candidate."),l("tags","JSON","Optional exact-match tag selector for canary eligibility.")],examples:["constal deployments create support-agent.zip"]}),o("deployments get","Read deployment build and publication state.","GET","/v1/deployments/{deployment}",{positionals:[t("deployment","Deployment UUID.")]}),o("agents list","List deployed Agents in the namespace.","GET","/v1/namespaces/{namespace}/agents"),o("agents get","Read one deployed Agent.","GET","/v1/namespaces/{namespace}/agents/{agent}",{positionals:[t("agent","Agent id.")]}),o("agents rollout get","Read the active or most recent canary rollout.","GET","/v1/namespaces/{namespace}/agents/{agent}/rollout",{positionals:[t("agent","Agent id.")]}),...["promote","rollback"].map(e=>o(`agents rollout ${e}`,`${e==="promote"?"Promote":"Roll back"} one exact canary deployment.`,"POST",`/v1/namespaces/{namespace}/agents/{agent}/rollout/${e}`,{positionals:[t("agent","Agent id.")],bodyKind:"rollout-control",eventId:!0,options:[l("deployment","REVISION","Exact canary deployment revision.",{required:!0}),l("reason","TEXT","Record why this rollout decision was made.",{required:!0}),g]})),o("runs start","Start an Agent Run in a stable session.","POST","/v1/namespaces/{namespace}/agents/{agent}/sessions/{session}/events",{positionals:[t("agent","Agent id."),t("session","Stable session id.")],bodyKind:"run-start",eventId:!0,options:[l("data","JSON|@FILE|@-","Agent input JSON."),l("deliver","MODE","Queue work or drive it live.",{choices:["queue","live"]}),l("tags","JSON|@FILE|@-","Attach bounded tags used by policy-governed live sampling."),g],examples:["constal runs start support customer-42 --data @request.json --deliver live"]}),o("runs session","Read bounded authoritative session state.","GET","/v1/namespaces/{namespace}/agents/{agent}/sessions/{session}",{positionals:[t("agent","Agent id."),t("session","Session id.")],query:[["limit","limit"]],options:[f]}),o("runs events","Page accepted session events and ledger history.","GET","/v1/namespaces/{namespace}/agents/{agent}/sessions/{session}/events",{positionals:[t("agent","Agent id."),t("session","Session id.")],query:[["after","after"],["limit","limit"]],options:[v,f]}),o("runs workflow","Read the authoritative current workflow view.","GET","/v1/namespaces/{namespace}/agents/{agent}/sessions/{session}/workflow",{positionals:[t("agent","Agent id."),t("session","Session id.")]}),o("runs get","Read one authoritative Run.","GET","/v1/namespaces/{namespace}/agents/{agent}/sessions/{session}/runs/{run}",{positionals:[t("agent","Agent id."),t("session","Session id."),t("run","Run id.")]}),o("runs detail","Read bounded Run, fact, wait, steer, and journal detail.","GET","/v1/namespaces/{namespace}/agents/{agent}/sessions/{session}/runs/{run}/detail",{positionals:[t("agent","Agent id."),t("session","Session id."),t("run","Run id.")],query:[["limit","journalLimit"]],options:[f]}),o("runs journal","Read the cryptographically rooted Run journal.","GET","/v1/namespaces/{namespace}/agents/{agent}/sessions/{session}/runs/{run}/journal",{positionals:[t("agent","Agent id."),t("session","Session id."),t("run","Run id.")],query:[["after","after"],["limit","limit"]],options:[v,f]}),o("runs journal-window","Page an operator-oriented Run journal window.","GET","/v1/namespaces/{namespace}/agents/{agent}/sessions/{session}/runs/{run}/journal-window",{positionals:[t("agent","Agent id."),t("session","Session id."),t("run","Run id.")],query:[["after","after"],["before","before"],["limit","limit"]],options:[v,l("before","CURSOR","Read before a returned cursor."),f]}),o("runs waits","List open durable waits for a session.","GET","/v1/namespaces/{namespace}/agents/{agent}/sessions/{session}/waits",{positionals:[t("agent","Agent id."),t("session","Session id.")]}),o("runs resolve","Resolve one durable wait with a schema-checked value.","POST","/v1/namespaces/{namespace}/agents/{agent}/sessions/{session}/waits/{promise}/resolve",{positionals:[t("agent","Agent id."),t("session","Session id."),t("promise","Wait promise id.")],bodyKind:"wait-resolve",eventId:!0,options:[l("value","JSON|@FILE|@-","Resolution value."),g]}),o("runs steer","Append authenticated guidance to a session.","POST","/v1/namespaces/{namespace}/agents/{agent}/sessions/{session}/steers",{positionals:[t("agent","Agent id."),t("session","Session id.")],bodyKind:"steer",eventId:!0,options:[l("text","TEXT","Guidance text.",{required:!0}),l("data","JSON|@FILE|@-","Optional structured guidance."),g]}),o("runs stream","Stream committed Run frames over Server-Sent Events.","GET","/v1/namespaces/{namespace}/agents/{agent}/sessions/{session}/stream",{positionals:[t("agent","Agent id."),t("session","Session id.")],query:[["run","runId"]],options:[l("run","RUN","Run id to stream.",{required:!0})],stream:!0}),o("runs delete-session","Delete a session asynchronously and preserve a bounded tombstone.","DELETE","/v1/namespaces/{namespace}/agents/{agent}/sessions/{session}",{positionals:[t("agent","Agent id."),t("session","Session id.")],bodyKind:"json",eventId:!0,options:[g]}),o("runs deletion","Read asynchronous session-deletion progress.","GET","/v1/namespaces/{namespace}/agents/{agent}/sessions/{session}/deletion",{positionals:[t("agent","Agent id."),t("session","Session id.")]}),...["pause","resume","cancel"].map(e=>o(`runs ${e}`,`${e[0].toUpperCase()}${e.slice(1)} one exact Run.`,"POST",`/v1/namespaces/{namespace}/agents/{agent}/sessions/{session}/runs/{run}/${e}`,{positionals:[t("agent","Agent id."),t("session","Session id."),t("run","Run id.")],bodyKind:"json",eventId:!0,options:[u,g]})),o("runs interrupt","Interrupt a Run at a safe point or abort active work.","POST","/v1/namespaces/{namespace}/agents/{agent}/sessions/{session}/runs/{run}/interrupt",{positionals:[t("agent","Agent id."),t("session","Session id."),t("run","Run id.")],bodyKind:"interrupt",eventId:!0,options:[l("mode","MODE","Use safe-point or abort.",{required:!0,choices:["safe-point","abort"]}),u,g]}),...["policy","rebind","truncate","branch"].map(e=>o(`runs ${e}`,`Apply an idempotent ${e} control to one Run.`,"POST",`/v1/namespaces/{namespace}/agents/{agent}/sessions/{session}/runs/{run}/${e}`,{positionals:[t("agent","Agent id."),t("session","Session id."),t("run","Run id.")],bodyKind:"json",eventId:!0,options:[u,g]})),o("resources list","List configured Resources, optionally by kind.","GET","/v1/namespaces/{namespace}/resources",{query:[["kind","kind"]],options:[l("kind","KIND","Filter by Resource kind.")]}),o("resources create","Create a configured Resource from a JSON definition.","POST","/v1/namespaces/{namespace}/resources",{bodyKind:"required-json",options:[u]}),...["get","delete"].map(e=>o(`resources ${e}`,`${e==="get"?"Read":"Delete"} one tenant-managed Resource.`,e==="get"?"GET":"DELETE","/v1/namespaces/{namespace}/resources/{kind}/{id}",{positionals:[t("kind","Resource kind."),t("id","Resource id.")]})),o("resources control","Read one Resource control head.","GET","/v1/namespaces/{namespace}/resources/{kind}/{id}/control",{positionals:[t("kind","Resource kind."),t("id","Resource id.")]}),...["enable","disable"].map(e=>o(`resources ${e}`,`${e[0].toUpperCase()}${e.slice(1)} a tenant-managed Resource.`,"POST",`/v1/namespaces/{namespace}/resources/{kind}/{id}/${e}`,{positionals:[t("kind","Resource kind."),t("id","Resource id.")],bodyKind:"reason",eventId:!0,options:[g,L]})),o("bindings list","List scoped Resource and Credential assignments.","GET","/v1/namespaces/{namespace}/bindings"),o("bindings create","Create a scoped assignment from a JSON definition.","POST","/v1/namespaces/{namespace}/bindings",{bodyKind:"required-json",eventId:!0,options:[u,g]}),o("bindings get","Read one scoped assignment.","GET","/v1/namespaces/{namespace}/bindings/{binding}",{positionals:[t("binding","Binding id.")]}),o("bindings delete","Delete one scoped assignment idempotently.","DELETE","/v1/namespaces/{namespace}/bindings/{binding}",{positionals:[t("binding","Binding id.")],bodyKind:"json",eventId:!0,options:[g]}),o("bindings promote","Promote a binding when its current revision still matches.","POST","/v1/namespaces/{namespace}/bindings/{binding}/promote",{positionals:[t("binding","Binding id.")],bodyKind:"required-json",eventId:!0,options:[u,g]}),...["enable","disable","revoke"].map(e=>o(`bindings ${e}`,`${e[0].toUpperCase()}${e.slice(1)} one scoped assignment.`,"POST",`/v1/namespaces/{namespace}/bindings/{binding}/${e}`,{positionals:[t("binding","Binding id.")],bodyKind:"reason",eventId:!0,options:[g,L]})),o("credentials providers catalog","List Credential Provider packages visible to the tenant.","GET","/v1/namespaces/{namespace}/credential-provider-catalog"),o("credentials providers list","List installed Credential Providers.","GET","/v1/namespaces/{namespace}/credential-providers"),o("credentials providers get","Read one installed Credential Provider.","GET","/v1/namespaces/{namespace}/credential-providers/{provider}",{positionals:[t("provider","Provider id.")]}),o("credentials providers install","Install a catalog Credential Provider package.","POST","/v1/namespaces/{namespace}/credential-providers/install",{bodyKind:"protected-json",options:[ie],examples:["constal credentials providers install --body @provider-setup.json"]}),o("credentials list","List Credentials without returning material.","GET","/v1/namespaces/{namespace}/credentials"),o("credentials get","Read authoritative Credential metadata.","GET","/v1/namespaces/{namespace}/credentials/{credential}",{positionals:[t("credential","Credential id.")]}),o("credentials create","Create, mint, or begin authorization for a Credential.","POST","/v1/namespaces/{namespace}/credentials",{positionals:[t("credential","New Credential id.")],bodyKind:"credential-create",options:[l("provider","CRN","Installed Credential Provider CRN.",{required:!0}),l("configuration","JSON|@FILE","Provider-defined non-secret configuration."),l("material-file","FILE","Read imported secret material from a file."),l("material-stdin",null,"Read imported secret material from stdin."),l("policies","JSON|@FILE","Optional Policy CRN array.")]}),o("credentials version","Add imported material as a scheduled Credential version.","POST","/v1/namespaces/{namespace}/credentials/{credential}/versions",{positionals:[t("credential","Credential id.")],bodyKind:"credential-version",options:[l("material-file","FILE","Read secret material from a file."),l("material-stdin",null,"Read secret material from stdin.")]}),...["activate","rotate","authorize","revoke"].map(e=>o(`credentials ${e}`,`${e[0].toUpperCase()}${e.slice(1)} a Credential lifecycle operation.`,"POST",`/v1/namespaces/{namespace}/credentials/{credential}/${e}`,{positionals:[t("credential","Credential id.")],bodyKind:"json",options:[u]})),...["consumers","uses","events"].map(e=>o(`credentials ${e}`,`List bounded Credential ${e}.`,"GET",`/v1/namespaces/{namespace}/credentials/{credential}/${e}`,{positionals:[t("credential","Credential id.")],query:e==="consumers"?[]:[["after","after"]],options:e==="consumers"?[]:[v]})),o("channels list","List deployed Channels.","GET","/v1/namespaces/{namespace}/channels"),o("channels get","Read one deployed Channel.","GET","/v1/namespaces/{namespace}/channels/{channel}",{positionals:[t("channel","Channel id.")]}),o("channels send","Send one outbound Channel message.","POST","/v1/namespaces/{namespace}/channels/{channel}/messages",{positionals:[t("channel","Channel id.")],bodyKind:"required-json",options:[u]}),o("channels message","Read one outbound delivery receipt.","GET","/v1/namespaces/{namespace}/channels/{channel}/messages/{message}",{positionals:[t("channel","Channel id."),t("message","Message id.")]}),o("channels events","Read bounded Channel events.","GET","/v1/namespaces/{namespace}/channels/{channel}/events",{positionals:[t("channel","Channel id.")],query:[["after","after"],["limit","limit"]],options:[v,f]}),o("channels alarm","Schedule a Channel alarm.","POST","/v1/namespaces/{namespace}/channels/{channel}/alarms",{positionals:[t("channel","Channel id.")],bodyKind:"required-json",options:[u]}),o("channels alarm-get","Read one Channel alarm.","GET","/v1/namespaces/{namespace}/channels/{channel}/alarms/{alarm}",{positionals:[t("channel","Channel id."),t("alarm","Alarm id.")]}),o("channels alarm-cancel","Cancel one Channel alarm.","DELETE","/v1/namespaces/{namespace}/channels/{channel}/alarms/{alarm}",{positionals:[t("channel","Channel id."),t("alarm","Alarm id.")]}),o("policies evaluate","Evaluate a deployed Policy against a normalized test input.","POST","/v1/namespaces/{namespace}/policies/{policy}/evaluate",{positionals:[t("policy","Policy id.")],bodyKind:"required-json",options:[u]}),o("analytics summary","Read a bounded recent analytics summary.","GET","/v1/namespaces/{namespace}/analytics/summary"),...["live","dashboard","query","export"].map(e=>o(`analytics ${e}`,`${e==="export"?"Create":"Query"} ${e} analytics data.`,"POST",`/v1/namespaces/{namespace}/analytics/${e==="export"?"exports":e}`,{bodyKind:"required-json",options:[u]})),o("analytics export-get","Download one namespace-owned analytics export.","GET","/v1/namespaces/{namespace}/analytics/exports/{ref}",{positionals:[t("ref","Export artifact hash.")],binary:!0,options:[R,O]}),o("evals datasets list","List immutable Dataset Resources.","GET","/v1/namespaces/{namespace}/resources",{queryValues:{kind:"dataset"}}),o("evals datasets create","Create or idempotently initialize a Dataset draft.","POST","/v1/namespaces/{namespace}/evals/datasets/{dataset}/draft",{positionals:[t("dataset","Dataset id.")],bodyKind:"required-json",options:[u]}),o("evals datasets draft","Read a Dataset draft head.","GET","/v1/namespaces/{namespace}/evals/datasets/{dataset}/draft",{positionals:[t("dataset","Dataset id.")]}),o("evals datasets cases","Page cases in a Dataset draft.","GET","/v1/namespaces/{namespace}/evals/datasets/{dataset}/cases",{positionals:[t("dataset","Dataset id.")],query:[["after","after"],["limit","limit"]],options:[v,f]}),o("evals datasets add-case","Create or replace one caller-identified Dataset case.","POST","/v1/namespaces/{namespace}/evals/datasets/{dataset}/cases",{positionals:[t("dataset","Dataset id.")],bodyKind:"required-json",options:[u]}),o("evals datasets delete-case","Delete one case from a Dataset draft.","DELETE","/v1/namespaces/{namespace}/evals/datasets/{dataset}/cases/{case}",{positionals:[t("dataset","Dataset id."),t("case","Case id.")]}),o("evals datasets capture","Capture a recorded Agent interaction into a Dataset draft.","POST","/v1/namespaces/{namespace}/evals/datasets/{dataset}/capture",{positionals:[t("dataset","Dataset id.")],bodyKind:"required-json",options:[u]}),o("evals datasets publish","Publish the current Dataset draft as an immutable version.","POST","/v1/namespaces/{namespace}/evals/datasets/{dataset}/publish",{positionals:[t("dataset","Dataset id.")],bodyKind:"required-json",options:[u]}),o("evals scores start","Score a pinned Subject asynchronously and append its verdict to the judged Session.","POST","/v1/namespaces/{namespace}/evals/scores",{bodyKind:"required-json",options:[u,F]}),o("evals scores get","Read one durable scoring job.","GET","/v1/namespaces/{namespace}/evals/scores/{score}",{positionals:[t("score","Score job id.")]}),o("evals scores cancel","Cancel one durable scoring job.","POST","/v1/namespaces/{namespace}/evals/scores/{score}/cancel",{positionals:[t("score","Score job id.")],bodyKind:"optional-json",options:[u]}),o("evals labels request","Open a durable, schema-checked human labeling wait.","POST","/v1/namespaces/{namespace}/evals/labels",{bodyKind:"required-json",options:[u,F]}),o("evals scorers list","List versioned Scorer Resources.","GET","/v1/namespaces/{namespace}/resources",{queryValues:{kind:"scorer"}}),o("evals scorers create","Create a versioned code, Judge Agent, or human-review Scorer.","POST","/v1/namespaces/{namespace}/evals/scorers",{bodyKind:"required-json",options:[u]}),o("evals scorers get","Read one Scorer Resource.","GET","/v1/namespaces/{namespace}/resources/scorer/{scorer}",{positionals:[t("scorer","Scorer id.")]}),o("evals suites list","Page evaluation suites by most recent activity.","GET","/v1/namespaces/{namespace}/evals/suites",{query:[["after","after"],["limit","limit"]],options:[v,f]}),o("evals suites start","Run a fresh suite over an immutable Dataset.","POST","/v1/namespaces/{namespace}/evals/suites",{bodyKind:"required-json",options:[u]}),o("evals suites get","Read authoritative suite progress and results.","GET","/v1/namespaces/{namespace}/evals/suites/{suite}",{positionals:[t("suite","Suite id.")]}),o("evals suites cancel","Cancel a running evaluation suite.","POST","/v1/namespaces/{namespace}/evals/suites/{suite}/cancel",{positionals:[t("suite","Suite id.")],bodyKind:"json",options:[u]}),o("evals compare","Compare paired suite and baseline verdicts.","POST","/v1/namespaces/{namespace}/evals/compare",{bodyKind:"required-json",options:[u]}),o("evals baseline","Set an Agent's evaluation baseline.","POST","/v1/namespaces/{namespace}/evals/baseline",{bodyKind:"required-json",options:[u]}),o("evals policy get","Read the namespace eval door policy pinned at Run admission.","GET","/v1/namespaces/{namespace}/evals/policy"),o("evals policy set","Atomically set sampling rates, Scorers, and eval budget ceilings.","PUT","/v1/namespaces/{namespace}/evals/policy",{bodyKind:"required-json",options:[u]}),o("evals samples list","Page asynchronous live-traffic scoring dispatches.","GET","/v1/namespaces/{namespace}/evals/samples",{query:[["before","before"],["limit","limit"]],options:[l("before","TIMESTAMP","Read samples created before this millisecond timestamp."),f]}),o("evals schedules list","List continuous evaluation schedules.","GET","/v1/namespaces/{namespace}/evals/schedules"),o("evals schedules get","Read one continuous evaluation schedule.","GET","/v1/namespaces/{namespace}/evals/schedules/{schedule}",{positionals:[t("schedule","Schedule id.")]}),o("evals schedules apply","Create or atomically update a continuous evaluation schedule.","PUT","/v1/namespaces/{namespace}/evals/schedules/{schedule}",{positionals:[t("schedule","Schedule id.")],bodyKind:"required-json",options:[u]}),o("evals schedules delete","Delete one exact continuous evaluation schedule revision.","DELETE","/v1/namespaces/{namespace}/evals/schedules/{schedule}",{positionals:[t("schedule","Schedule id.")],bodyKind:"schedule-delete",options:[l("expected-hash","HASH","Current schedule hash.",{required:!0})]}),o("evals schedules run","Run a scheduled Suite now without changing its cadence.","POST","/v1/namespaces/{namespace}/evals/schedules/{schedule}/run",{positionals:[t("schedule","Schedule id.")],bodyKind:"json",eventId:!0,options:[g]}),o("evals training providers","List installed Training Providers and checkpoint capabilities.","GET","/v1/namespaces/{namespace}/evals/training-providers"),o("evals training models","List models and pinned prices advertised by one Training Provider.","GET","/v1/namespaces/{namespace}/evals/training-models",{query:[["provider","provider"],["hash","hash"]],options:[l("provider","CRN","Training Provider Resource CRN."),l("hash","HASH","Exact Training Provider Resource hash.")]}),o("evals training list","Page fine-tuning and reinforcement-learning jobs.","GET","/v1/namespaces/{namespace}/evals/training-jobs",{query:[["after","after"],["limit","limit"]],options:[v,f]}),o("evals training start","Start a durable metered SFT or RL job.","POST","/v1/namespaces/{namespace}/evals/training-jobs",{bodyKind:"required-json",options:[u]}),o("evals training get","Read authoritative training progress, usage, and results.","GET","/v1/namespaces/{namespace}/evals/training-jobs/{job}",{positionals:[t("job","Training job id.")]}),o("evals training cancel","Cancel a running training job.","POST","/v1/namespaces/{namespace}/evals/training-jobs/{job}/cancel",{positionals:[t("job","Training job id.")],bodyKind:"json",options:[u]}),o("evals training checkpoint-gateways","List exact Gateway revisions compatible with one durable checkpoint.","GET","/v1/namespaces/{namespace}/evals/training-jobs/{job}/checkpoint-gateways",{positionals:[t("job","Succeeded Training Job id.")],query:[["step","step"],["ref","ref"]],options:[l("step","COUNT","Exact checkpoint step."),l("ref","HASH","Exact checkpoint Artifact hash.")]}),o("evals training create-model","Import a checkpoint through a compatible Gateway and create a Model.","POST","/v1/namespaces/{namespace}/evals/training-jobs/{job}/models",{positionals:[t("job","Succeeded Training Job id.")],bodyKind:"required-json",options:[u]}),o("memory stores list","List configured Memory Stores.","GET","/v1/namespaces/{namespace}/resources",{queryValues:{kind:"memory-store"}}),o("memory stores create","Create a Memory Store Resource.","POST","/v1/namespaces/{namespace}/resources",{bodyKind:"resource-kind",resourceKind:"memory-store",options:[u]}),...["get","delete"].map(e=>o(`memory stores ${e}`,`${e==="get"?"Read":"Delete"} one Memory Store.`,e==="get"?"GET":"DELETE","/v1/namespaces/{namespace}/resources/memory-store/{id}",{positionals:[t("id","Memory Store id.")]})),o("memory list","List configured Memory Resources.","GET","/v1/namespaces/{namespace}/resources",{queryValues:{kind:"memory"}}),o("memory create","Create a Memory Resource.","POST","/v1/namespaces/{namespace}/resources",{bodyKind:"resource-kind",resourceKind:"memory",options:[u]}),...["get","delete"].map(e=>o(`memory ${e}`,`${e==="get"?"Read":"Delete"} one Memory Resource.`,e==="get"?"GET":"DELETE","/v1/namespaces/{namespace}/resources/memory/{id}",{positionals:[t("id","Memory id.")]})),o("customers list","List downstream customers.","GET","/v1/customers"),o("customers get","Read one downstream customer.","GET","/v1/customers/{customer}",{positionals:[t("customer","Customer id.")]}),o("customers put","Create or update a downstream customer.","PUT","/v1/customers/{customer}",{positionals:[t("customer","Customer id.")],bodyKind:"required-json",eventId:!0,options:[u,g]}),...["enable","disable"].map(e=>o(`customers ${e}`,`${e[0].toUpperCase()}${e.slice(1)} a downstream customer.`,"POST",`/v1/customers/{customer}/${e}`,{positionals:[t("customer","Customer id.")],bodyKind:"reason",eventId:!0,options:[g,L]})),...[["map","Map an external identity to a downstream customer.","PUT","identity-mappings"],["unmap","Remove an external identity mapping from a downstream customer.","DELETE","identity-mappings"],["bind-policy","Bind a Policy to a downstream customer.","PUT","policy-bindings"],["unbind-policy","Remove a Policy binding from a downstream customer.","DELETE","policy-bindings"]].map(([e,a,n,s])=>o(`customers ${e}`,a,n,`/v1/customers/{customer}/${s}/{binding}`,{positionals:[t("customer","Customer id."),t("binding","Mapping or binding id.")],bodyKind:"required-json",eventId:!0,options:[u,g]})),o("artifacts get","Download an authorized content-addressed artifact.","GET","/v1/artifacts/{ref}",{positionals:[t("ref","Artifact hash.")],binary:!0,options:[R,O]}),o("exports get","Download a redacted durable export.","GET","/v1/exports/{ref}",{positionals:[t("ref","Export hash.")],binary:!0,options:[R,O]}),o("anchors get","Download an authorized customer audit anchor.","GET","/v1/anchors/{ref}",{positionals:[t("ref","Anchor hash.")],binary:!0,options:[R,O]}),o("stages get","Inspect one map/reduce stage.","GET","/v1/stages/{stage}",{positionals:[t("stage","Stage hash.")]}),o("stages recover","Request authorized stage recovery.","POST","/v1/stages/{stage}/recover",{positionals:[t("stage","Stage hash.")],bodyKind:"json",options:[u]}),o("tables get","Read a table branch head and state.","GET","/v1/namespaces/{namespace}/tables/{table}",{positionals:[t("table","Table id.")],query:[["branch","branch"]],options:[l("branch","NAME","Table branch; defaults to main.")]}),o("tables export-get","Read an exact table catalog commit, export, or intent.","GET","/v1/namespaces/{namespace}/table-exports/{table}/{branch}/{sequence}/{hash}",{positionals:[t("table","Table id."),t("branch","Branch name."),t("sequence","Commit sequence."),t("hash","Commit hash.")],binary:!0,options:[R,O]})]);function C(e){return e.path.join(" ")}function re(e=A){let a=new Set;for(let n of e){let s=C(n);if(a.has(s))throw new TypeError(`duplicate CLI command ${s}`);if(a.add(s),!n.summary||!n.local&&(!n.method||!n.route))throw new TypeError(`invalid CLI command ${s}`);let c=n.positionals??[];if(new Set(c.map(d=>d.name)).size!==c.length)throw new TypeError(`duplicate positional in ${s}`);let i=n.options??[];if(new Set(i.map(d=>d.name)).size!==i.length)throw new TypeError(`duplicate option in ${s}`);for(let d of n.route?.matchAll(/\{([^}]+)\}/gu)??[])if(d[1]!=="namespace"&&!c.some(r=>r.name===d[1]))throw new TypeError(`unknown route placeholder ${d[1]} in ${s}`)}return e}re();import{randomUUID as ce}from"node:crypto";import{chmod as J,mkdir as de,readFile as le,rename as pe,unlink as ue,writeFile as me}from"node:fs/promises";import{homedir as ge}from"node:os";import{dirname as he,join as P}from"node:path";var q="https://platform.constal.ai",fe=/^[a-z0-9][a-z0-9._-]{0,127}$/u;function ye(e=process.env){return e.CONSTAL_CONFIG_DIR||P(e.XDG_CONFIG_HOME||P(ge(),".config"),"constal")}function I(e=process.env){let a=ye(e);return{root:a,context:P(a,"config.json"),credentials:P(a,"credentials.json")}}async function D(e){try{let a=JSON.parse(await le(e,"utf8"));return a&&typeof a=="object"&&!Array.isArray(a)?a:{}}catch(a){if(a?.code==="ENOENT")return{};throw new TypeError(`Cannot read Constal configuration at ${e}: ${a instanceof Error?a.message:String(a)}`)}}async function z(e,a,n){await de(he(e),{recursive:!0,mode:448});let s=`${e}.${process.pid}.${ce()}.tmp`;await me(s,`${JSON.stringify(a,null,2)}
3
+ `,{mode:n}),await J(s,n),await pe(s,e),await J(e,n)}function _(e){let a;try{a=new URL(String(e||q))}catch{throw new TypeError("Platform origin must be an absolute HTTPS URL")}if(a.protocol!=="https:"||a.username||a.password||a.search||a.hash)throw new TypeError("Platform origin must be an absolute HTTPS URL");return a.origin+a.pathname.replace(/\/+$/u,"")}function k(e,a){if(e==null||e==="")return null;if(!fe.test(String(e)))throw new TypeError(`${a} is invalid`);return String(e)}async function B({environment:e=process.env,overrides:a={}}={}){let n=I(e),[s,c]=await Promise.all([D(n.context),D(n.credentials)]),i=k(a.namespace??e.CONSTAL_NAMESPACE??s.namespace??"default","namespace"),d=k(a.tenant??e.CONSTAL_TENANT??s.tenant??null,"tenant"),r=typeof e.CONSTAL_API_KEY=="string"&&e.CONSTAL_API_KEY.trim()?e.CONSTAL_API_KEY.trim():null,p=typeof c.apiKey=="string"&&c.apiKey.trim()?c.apiKey.trim():null;return{origin:_(a.origin??e.CONSTAL_PLATFORM_URL??s.origin??q),namespace:i,tenant:d,apiKey:r??p,credentialSource:r?"environment":p?"credentials-file":"none",paths:n}}async function V(e,{environment:a=process.env}={}){let n=I(a),s=await D(n.context),c=e.clearTenant?null:k(e.tenant??s.tenant??null,"tenant"),i={origin:_(e.origin??s.origin??q),namespace:k(e.namespace??s.namespace??"default","namespace"),...c?{tenant:c}:{}};return await z(n.context,i,384),i}async function H(e,{environment:a=process.env}={}){let n=String(e??"").trim();if(!n||n.length>16384||/[\r\n]/u.test(n))throw new TypeError("Constal API key is invalid");let s=I(a);return await z(s.credentials,{apiKey:n},384),s.credentials}async function Y({environment:e=process.env}={}){let a=I(e).credentials;try{return await ue(a),!0}catch(n){if(n?.code==="ENOENT")return!1;throw n}}var Fe=Object.freeze({origin:q,namespace:"default"});function W(e){return e==null?"\u2014":typeof e=="object"?JSON.stringify(e):String(e)}function ve(e){return Array.isArray(e)?e:e&&typeof e=="object"&&Array.isArray(e.data)?e.data:e&&typeof e=="object"?Object.entries(e).map(([a,n])=>({field:a,value:n})):[{value:e}]}function be(e){let a=ve(e);if(!a.length)return`No results
4
+ `;let n=a.map(d=>d&&typeof d=="object"&&!Array.isArray(d)?d:{value:d}),s=[...new Set(n.flatMap(d=>Object.keys(d)))].slice(0,8),c=s.map(d=>Math.min(48,Math.max(d.length,...n.map(r=>W(r[d]).length)))),i=d=>s.map((r,p)=>{let h=W(d[r]),E=c[p];return(h.length>E?`${h.slice(0,Math.max(1,E-1))}\u2026`:h).padEnd(E)}).join(" ").trimEnd();return`${i(Object.fromEntries(s.map(d=>[d,d.toUpperCase()])))}
5
+ ${n.map(i).join(`
6
+ `)}
7
+ `}function X(e,a="table"){return a==="json"?`${JSON.stringify(e,null,2)}
8
+ `:a==="jsonl"?`${(Array.isArray(e)?e:e&&typeof e=="object"&&Array.isArray(e.data)?e.data:[e]).map(s=>JSON.stringify(s)).join(`
9
+ `)}
10
+ `:be(e)}var ae="1.0.0",m=class extends Error{constructor(a){super(a),this.name="CliUsageError",this.exitCode=2}},x=class extends Error{constructor(a,n,s=null){super(`Platform API returned ${a}${n?`: ${n}`:""}${s?` (request ${s})`:""}`),this.name="CliApiError",this.exitCode=1,this.status=a,this.requestId=s}},je={stdin:Re,stdout:Oe,stderr:Ce,environment:process.env,fetch:globalThis.fetch,readFile:Ee,writeFile:Se,randomUUID:Te};function y(e,a){e.write(String(a))}async function N(e){let a=[];for await(let n of e)a.push(typeof n=="string"?Buffer.from(n):n);return Buffer.concat(a).toString("utf8")}async function $e(e,a){return!e.stdin.isTTY||typeof e.stdin.setRawMode!="function"?(await N(e.stdin)).trim():(y(e.stderr,a),e.stdin.setRawMode(!0),e.stdin.resume(),new Promise((n,s)=>{let c="",i=()=>{e.stdin.off("data",d),e.stdin.setRawMode(!1),e.stdin.pause(),y(e.stderr,`
11
+ `)},d=r=>{for(let p of Buffer.from(r)){if(p===3){i(),s(new m("Authentication cancelled"));return}if(p===13||p===10){i(),n(c.trim());return}if(p===127||p===8){c=c.slice(0,-1);continue}p>=32&&(c+=String.fromCharCode(p))}};e.stdin.on("data",d)}))}function U(e){let a=new Map;for(let n of[...K,...e?.options??[]])a.set(n.name,n);return[...a.values()]}function Q(e){let a=`--${e.name}${e.value?` <${e.value}>`:""}`,n=e.required?" Required.":e.choices?` Values: ${e.choices.join(", ")}.`:"";return` ${a.padEnd(28)} ${e.description}${n}`}function Z(e=null){if(!e){let s=new Map;for(let c of A){let i=c.path[0],d=s.get(i)??[];d.push(c),s.set(i,d)}return`Constal CLI ${ae}
12
+
13
+ Usage:
14
+ constal <command> [arguments] [options]
15
+
16
+ Commands:
17
+ ${[...s].map(([c,i])=>`
18
+ ${c.toUpperCase()}
19
+ ${i.map(d=>` ${C(d).padEnd(34)} ${d.summary}`).join(`
20
+ `)}`).join(`
21
+ `)}
22
+
23
+ Global options:
24
+ ${K.map(Q).join(`
25
+ `)}
26
+
27
+ Run constal help <command> for command-specific help.
28
+ `}let a=e.positionals??[],n=`constal ${C(e)}${a.map(s=>` <${s.name}>`).join("")}${U(e).length?" [options]":""}`;return`${e.summary}
29
+
30
+ Usage:
31
+ ${n}
32
+ ${a.length?`
33
+ Arguments:
34
+ ${a.map(s=>` ${s.name.padEnd(26)} ${s.description}`).join(`
35
+ `)}
36
+ `:""}
37
+ Options:
38
+ ${U(e).map(Q).join(`
39
+ `)}${e.examples?.length?`
40
+
41
+ Examples:
42
+ ${e.examples.map(s=>` ${s}`).join(`
43
+ `)}`:""}
44
+ `}function Ae(e){return[...A].sort((a,n)=>n.path.length-a.path.length).find(a=>a.path.every((n,s)=>e[s]===n))}function Pe(e,a){let n={},s=[],c=new Map(U(e).map(r=>[r.name,r]));for(let r=0;r<a.length;r++){let p=a[r];if(p==="--"){s.push(...a.slice(r+1));break}if(!p.startsWith("--")){s.push(p);continue}let[h,E]=p.slice(2).split(/=(.*)/su,2),G=h.startsWith("no-"),w=G?h.slice(3):h,S=c.get(w);if(!S)throw new m(`Unknown option --${h} for ${C(e)}`);if(S.value){if(G)throw new m(`--no-${w} is not valid`);let $=E??a[++r];if($===void 0||$.startsWith("--"))throw new m(`--${w} requires a value`);if(S.choices&&!S.choices.includes($))throw new m(`--${w} must be one of ${S.choices.join(", ")}`);n[w]=$}else n[w]=!G}let i=e.positionals??[];if(s.length<i.filter(r=>!r.optional).length||s.length>i.length)throw new m(`Expected ${i.map(r=>`<${r.name}>`).join(" ")||"no arguments"}`);let d=Object.fromEntries(i.map((r,p)=>[r.name,s[p]]));for(let r of e.options??[])if(r.required&&n[r.name]===void 0)throw new m(`--${r.name} is required`);return{options:n,values:d}}async function ke(e,a,n){if(e!==void 0)return e==="@-"?(await N(a.stdin)).trim():e.startsWith("@")?(await a.readFile(e.slice(1),"utf8")).trim():e}async function j(e,a,n,s){let c=await ke(e,a,n);if(c===void 0)return s;try{return JSON.parse(c)}catch{throw new m(`${n} must be valid JSON, @FILE, or @-`)}}async function b(e,a,n,s){let c=await j(e,a,n,s);if(!c||typeof c!="object"||Array.isArray(c))throw new m(`${n} must be a JSON object`);return c}async function ee(e,a){if(e["material-file"]&&e["material-stdin"])throw new m("Choose only one material source");if(e["material-file"])return(await a.readFile(e["material-file"],"utf8")).replace(/[\r\n]+$/u,"");if(e["material-stdin"])return(await N(a.stdin)).replace(/[\r\n]+$/u,"")}function M(e,a=[]){if(typeof e=="string")a.push(e);else if(Array.isArray(e))for(let n of e)M(n,a);else if(e&&typeof e=="object")for(let n of Object.values(e))M(n,a);return a}async function qe(e,a,n){let{options:s,values:c}=a,i,d=[];switch(e.bodyKind){case void 0:return{body:void 0,headers:{},sensitiveValues:d};case"archive":{let r=await n.readFile(c.archive),p=/\.(?:tar\.gz|tgz)$/iu.test(c.archive);if(!p&&!/\.zip$/iu.test(c.archive))throw new m("Deployment archive must end in .zip, .tar.gz, or .tgz");let h=s["idempotency-key"]??`sha256-${we("sha256").update(r).digest("hex")}`;return{body:r,headers:{"content-type":p?"application/gzip":"application/zip","idempotency-key":h},sensitiveValues:d}}case"required-json":if(s.body===void 0)throw new m("--body is required");i=await b(s.body,n,"body");break;case"optional-json":i=await b(s.body,n,"body",{});break;case"protected-json":if(s.body===void 0)throw new m("--body is required");if(!s.body.startsWith("@"))throw new m("This setup document must be read from @FILE or @-");i=await b(s.body,n,"body"),d.push(...M(i));break;case"resource-kind":if(s.body===void 0)throw new m("--body is required");i={...await b(s.body,n,"body"),kind:e.resourceKind};break;case"json":i=await b(s.body,n,"body",{});break;case"reason":i={...s.reason?{reason:s.reason}:{}};break;case"run-start":{i={body:await j(s.data,n,"data",{}),deliver:s.deliver??"queue",...s.tags===void 0?{}:{tags:await b(s.tags,n,"tags",{})}};break}case"wait-resolve":if(s.value===void 0)throw new m("--value is required");i={value:await j(s.value,n,"value")};break;case"steer":i={text:s.text,...s.data===void 0?{}:{data:await j(s.data,n,"data")}};break;case"interrupt":i={...await b(s.body,n,"body",{}),mode:s.mode};break;case"rollout-control":i={deploymentRevision:s.deployment,reason:s.reason};break;case"schedule-delete":i={expectedHash:s["expected-hash"]};break;case"credential-create":{let r=await ee(s,n);i={id:c.credential,provider:s.provider,configuration:await b(s.configuration,n,"configuration",{}),...s.policies===void 0?{}:{policies:await j(s.policies,n,"policies")},...r===void 0?{}:{material:r}},r!==void 0&&d.push(r);break}case"credential-version":{let r=await ee(s,n);if(r===void 0)throw new m("--material-file or --material-stdin is required");d.push(r),i={material:r};break}default:throw new m(`Unsupported request body kind ${e.bodyKind}`)}if(!i||typeof i!="object"||Array.isArray(i))throw new m("Request body must be a JSON object");return e.eventId&&i.eventId===void 0&&(i.eventId=s["event-id"]??n.randomUUID()),{body:JSON.stringify(i),headers:{"content-type":"application/json"},sensitiveValues:d}}function Ie(e,a,n){let s={...a.values,namespace:n.namespace},c=e.route.replace(/\{([^}]+)\}/gu,(d,r)=>encodeURIComponent(s[r])),i=new URL(`${n.origin}${c}`);for(let[d,r]of e.query??[])a.options[d]!==void 0&&i.searchParams.set(r,a.options[d]);for(let[d,r]of Object.entries(e.queryValues??{}))i.searchParams.set(d,r);return i}async function ne(e){return(e.headers.get("content-type")??"").includes("json")?e.json().catch(()=>null):e.text()}function xe(e){return typeof e=="string"?e:typeof e?.error=="string"?e.error:typeof e?.error?.message=="string"?e.error.message:typeof e?.message=="string"?e.message:e==null?"request failed":JSON.stringify(e)}function se(e,a){let n=String(e??"");for(let s of a)s&&(n=n.replaceAll(String(s),"[REDACTED]"));return n}async function te(e,a,n,s){if(!n.apiKey)throw new m("No API key is configured. Set CONSTAL_API_KEY or run constal auth login");let c=Ie(e,a,n),i=await qe(e,a,s),d=new Headers({authorization:`Bearer ${n.apiKey}`,accept:e.stream?"text/event-stream":"application/json",...i.headers});n.tenant&&d.set("x-constal-tenant",n.tenant);let r;try{r=await s.fetch(c,{method:e.method,headers:d,...i.body===void 0?{}:{body:i.body}})}catch(p){let h=p instanceof Error?p.message:"network request failed";throw new x(0,se(h,[n.apiKey,...i.sensitiveValues]))}if(!r.ok){let p=await ne(r),h=se(xe(p),[n.apiKey,...i.sensitiveValues]);throw new x(r.status,h,r.headers.get("x-request-id"))}if(e.stream){if(!r.body)return null;for await(let p of r.body)s.stdout.write(p);return null}if(e.binary){let p=new Uint8Array(await r.arrayBuffer());return a.options.out?(await s.writeFile(a.options.out,p,{mode:384}),a.options.quiet||y(s.stderr,`Wrote ${p.byteLength} bytes to ${a.options.out}
45
+ `)):s.stdout.write(p),null}return ne(r)}async function Ne(e,a,n,s){let{options:c}=a;if(e.local==="auth.login"){if(c["token-file"]&&c["token-stdin"])throw new m("Choose only one token source");let i=c["token-file"]?await s.readFile(c["token-file"],"utf8"):c["token-stdin"]?await N(s.stdin):await $e(s,"Constal API key: ");return{authenticated:!0,storedAt:await H(i,{environment:s.environment})}}if(e.local==="auth.logout")return{authenticated:!1,removed:await Y({environment:s.environment})};if(e.local==="auth.status")return n.apiKey?(await te({method:"GET",route:"/v1/namespaces/{namespace}/agents",bodyKind:void 0},{options:c,values:{}},n,s),{authenticated:!0,credentialSource:n.credentialSource,origin:n.origin,tenant:n.tenant,namespace:n.namespace}):{authenticated:!1,credentialSource:"none",namespace:n.namespace};if(e.local==="context.show")return{origin:n.origin,tenant:n.tenant,namespace:n.namespace,credentialSource:n.credentialSource};if(e.local==="context.use"){if(!["origin","namespace","tenant","clear-tenant"].some(i=>c[i]!==void 0))throw new m("Specify --origin, --namespace, --tenant, or --clear-tenant");return V({origin:c.origin,namespace:c.namespace,tenant:c.tenant,clearTenant:c["clear-tenant"]},{environment:s.environment})}throw new m(`Unsupported local command ${e.local}`)}function Ge(e={}){return{...je,...e}}async function oe(e,a={}){let n=Ge(a);try{if(!Array.isArray(e))throw new m("argv must be an array");if(e.includes("--version")||e[0]==="version")return y(n.stdout,`${ae}
46
+ `),0;if(!e.length||e[0]==="--help")return y(n.stdout,Z()),0;let s=e[0]==="help",c=s?e.slice(1):e,i=Ae(c);if(!i)throw new m(`Unknown command ${c.join(" ")||"(none)"}`);if(s||c.includes("--help"))return y(n.stdout,Z(i)),0;let d=Pe(i,c.slice(i.path.length)),r=await B({environment:n.environment,overrides:d.options}),p=i.local?await Ne(i,d,r,n):await te(i,d,r,n);return p!=null&&y(n.stdout,X(p,d.options.output??"table")),0}catch(s){return y(n.stderr,`Error: ${s instanceof Error?s.message:String(s)}
47
+ `),s instanceof m&&y(n.stderr,`Run constal --help for usage.
48
+ `),Number(s?.exitCode??1)}}process.exitCode=await oe(process.argv.slice(2));