@naturali/cli 0.120.2 → 0.120.4
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/dist/index.mjs +18 -15
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -14,7 +14,7 @@ var __exportAll = (all, no_symbols) => {
|
|
|
14
14
|
};
|
|
15
15
|
//#endregion
|
|
16
16
|
//#region package.json
|
|
17
|
-
var version = "0.120.
|
|
17
|
+
var version = "0.120.4";
|
|
18
18
|
//#endregion
|
|
19
19
|
//#region ../sdk/src/generated/core/bodySerializer.gen.ts
|
|
20
20
|
const serializeFormDataPair = (data, key, value) => {
|
|
@@ -3288,7 +3288,8 @@ var Orchestrations = class {
|
|
|
3288
3288
|
/**
|
|
3289
3289
|
* Get orchestration queue stats
|
|
3290
3290
|
*
|
|
3291
|
-
* Returns a point-in-time snapshot of the orchestration run queue: how many tasks are waiting to be claimed (`queue_depth`), how many are currently claimed with a valid lease (`claimed_tasks`), the age of the oldest waiting task, recent claim-latency percentiles over a rolling in-process window, and a per-project breakdown. Intended for admin/operator policies; guarded by `orchestrations:GetQueueStats`.
|
|
3291
|
+
* Returns a point-in-time snapshot of the orchestration run queue: how many tasks are waiting to be claimed (`queue_depth`), how many are currently claimed with a valid lease (`claimed_tasks`), the age of the oldest waiting task, recent claim-latency percentiles over a rolling in-process window, and a per-project breakdown. Intended for admin/operator policies; guarded by `orchestrations:GetQueueStats`.
|
|
3292
|
+
* Every figure is scoped to what the caller may see. A project-scoped caller gets `per_project` for their own projects only, `queue_depth` and `claimed_tasks` summed over those same projects, and `null` for `oldest_queued_age_seconds` and the `claim_latency_ms` percentiles — both describe the whole deployment and cannot be narrowed, so they are withheld rather than approximated. An unrestricted caller (the action granted on every project) gets the deployment-wide figures.
|
|
3292
3293
|
*
|
|
3293
3294
|
*/
|
|
3294
3295
|
static getQueueStats(options) {
|
|
@@ -4094,6 +4095,7 @@ var Tools = class {
|
|
|
4094
4095
|
* Directly invokes a tool and returns its output. Supported for `http`, `mcp`, and `pipeline` tools. `client` tools cannot be invoked server-side and will return 422. A `pipeline` tool runs its declared steps in order and returns the mapped `output` (or the last step's output); `action` is ignored and `input` is the pipeline input.
|
|
4095
4096
|
* For `mcp` tools the `action` field is required and identifies which tool name to invoke. For `http` tools `action` is ignored. When an `mcp` tool declares an `actions` allowlist, an action outside it is rejected with `400 VALIDATION_FAILED` ("not available on this tool") before any outbound request is made.
|
|
4096
4097
|
* `preset_parameters` stored on the tool are pinned over the caller-supplied `input` before execution: a key the tool presets keeps its preset value even when `input` sets it. Keys the presets do not name are taken from `input` as sent.
|
|
4098
|
+
* Guardrails attached to the tool or to its project adjudicate the call before dispatch, composing project + tool scope. A call this route cannot await a decision on — class C (human sign-off), class D, or a class-B tripwire — is refused with `422 TOOL_DISPATCH_FAILED`, whose `meta` carries the `tool_id` and the `outcome`. A `pipeline` tool is adjudicated before its first step runs, and every step is adjudicated as the call of that tool it is.
|
|
4097
4099
|
*
|
|
4098
4100
|
*/
|
|
4099
4101
|
static callTool(options) {
|
|
@@ -4211,7 +4213,8 @@ var Triggers = class {
|
|
|
4211
4213
|
/**
|
|
4212
4214
|
* Update a trigger
|
|
4213
4215
|
*
|
|
4214
|
-
* Updates an existing trigger's configuration. The type is immutable.
|
|
4216
|
+
* Updates an existing trigger's configuration. The type is immutable. Changing `target_type` or `target_id` re-checks the target-start action (`orchestrations:StartRun`, `agents:CreateAgentGeneration` or `tools:CallTool`) against the resulting target, because a firing runs with the trigger creator's authority rather than the updater's. A caller who could not start the new target is answered `403` and the trigger keeps the target it had.
|
|
4217
|
+
*
|
|
4215
4218
|
*/
|
|
4216
4219
|
static updateTrigger(options) {
|
|
4217
4220
|
return (options.client ?? client).patch({
|
|
@@ -7450,7 +7453,7 @@ const routes = {
|
|
|
7450
7453
|
},
|
|
7451
7454
|
{
|
|
7452
7455
|
"name": "arguments",
|
|
7453
|
-
"description": "Edited arguments to execute instead of the proposed ones",
|
|
7456
|
+
"description": "Edited arguments to execute instead of the proposed ones. Editing composes a new call, so it additionally requires permission to make that call: `tools:CallTool` on the tool, and for a `builtin` proposal the action's own IAM action.",
|
|
7454
7457
|
"required": false,
|
|
7455
7458
|
"type": "object",
|
|
7456
7459
|
"in": "body"
|
|
@@ -9518,7 +9521,7 @@ const routes = {
|
|
|
9518
9521
|
},
|
|
9519
9522
|
{
|
|
9520
9523
|
"name": "inputs",
|
|
9521
|
-
"description": "Batch of texts to embed.",
|
|
9524
|
+
"description": "Batch of texts to embed. At most 256 per request — each input is one call to the embedding model, so a larger batch is refused (`VALIDATION_FAILED`) rather than queued. Split it across requests.",
|
|
9522
9525
|
"required": false,
|
|
9523
9526
|
"type": "array",
|
|
9524
9527
|
"in": "body"
|
|
@@ -11679,7 +11682,7 @@ const routes = {
|
|
|
11679
11682
|
},
|
|
11680
11683
|
{
|
|
11681
11684
|
"name": "content_type_glob",
|
|
11682
|
-
"description": "MIME type glob matched against a file's content_type",
|
|
11685
|
+
"description": "MIME type glob matched against a file's content_type. At most 4 wildcards and 255 characters — a MIME glob needs one on each side of the slash at most.",
|
|
11683
11686
|
"required": true,
|
|
11684
11687
|
"type": "string",
|
|
11685
11688
|
"in": "body"
|
|
@@ -11803,7 +11806,7 @@ const routes = {
|
|
|
11803
11806
|
},
|
|
11804
11807
|
{
|
|
11805
11808
|
"name": "content_type_glob",
|
|
11806
|
-
"description": "",
|
|
11809
|
+
"description": "MIME type glob matched against a file's content_type. At most 4 wildcards and 255 characters.",
|
|
11807
11810
|
"required": false,
|
|
11808
11811
|
"type": "string",
|
|
11809
11812
|
"in": "body"
|
|
@@ -11934,7 +11937,7 @@ const routes = {
|
|
|
11934
11937
|
},
|
|
11935
11938
|
{
|
|
11936
11939
|
"name": "limit",
|
|
11937
|
-
"description": "Maximum number of results to return (default 10)",
|
|
11940
|
+
"description": "Maximum number of results to return (default 10). A value above 100 is clamped to 100 — the ceiling bounds the vector scan this one request performs, so a larger `limit` returns everything there is up to that many rows rather than being refused.",
|
|
11938
11941
|
"required": false,
|
|
11939
11942
|
"type": "integer",
|
|
11940
11943
|
"in": "body"
|
|
@@ -12740,7 +12743,7 @@ const routes = {
|
|
|
12740
12743
|
"get-queue-stats": {
|
|
12741
12744
|
serviceClass: "Orchestrations",
|
|
12742
12745
|
operationId: "getQueueStats",
|
|
12743
|
-
description: "Returns a point-in-time snapshot of the orchestration run queue: how many tasks are waiting to be claimed (`queue_depth`), how many are currently claimed with a valid lease (`claimed_tasks`), the age of the oldest waiting task, recent claim-latency percentiles over a rolling in-process window, and a per-project breakdown. Intended for admin/operator policies; guarded by `orchestrations:GetQueueStats`. A project-scoped caller
|
|
12746
|
+
description: "Returns a point-in-time snapshot of the orchestration run queue: how many tasks are waiting to be claimed (`queue_depth`), how many are currently claimed with a valid lease (`claimed_tasks`), the age of the oldest waiting task, recent claim-latency percentiles over a rolling in-process window, and a per-project breakdown. Intended for admin/operator policies; guarded by `orchestrations:GetQueueStats`. Every figure is scoped to what the caller may see. A project-scoped caller gets `per_project` for their own projects only, `queue_depth` and `claimed_tasks` summed over those same projects, and `null` for `oldest_queued_age_seconds` and the `claim_latency_ms` percentiles — both describe the whole deployment and cannot be narrowed, so they are withheld rather than approximated. An unrestricted caller (the action granted on every project) gets the deployment-wide figures.",
|
|
12744
12747
|
moduleDocsUrl: "https://docs.naturali.ai/docs/modules/orchestrations",
|
|
12745
12748
|
httpMethod: "get",
|
|
12746
12749
|
pathParams: ["project_id"],
|
|
@@ -14766,14 +14769,14 @@ const routes = {
|
|
|
14766
14769
|
},
|
|
14767
14770
|
{
|
|
14768
14771
|
"name": "execute",
|
|
14769
|
-
"description": "Execution config for http tools. Supported fields: `url` (required), `method` (default `POST`), `headers`, and `body_mode`. The `url` may contain `{paramName}` placeholders (e.g. `/users/{userId}`) that are replaced at call time with the corresponding tool argument value (URL-encoded). Arguments consumed as path parameters are excluded from the query string and request body. `body_mode` is `json` (default) or `multipart`. In `multipart` mode the merged tool arguments are sent as a `multipart/form-data` body: scalar fields become plain form fields and a field shaped like `{ content_type, filename, data_base64 }` is decoded from base64 and attached as a file part (the hardcoded `Content-Type: application/json` is dropped so `fetch` sets the multipart boundary itself).\n\n`auth` adds a computed request credential, for targets whose `Authorization` value cannot be expressed as a static header. Supported `auth.type` values:\n\n- `aws_sigv4` — signs the request with AWS Signature Version 4. Requires `region`, `service`, `access_key_id` and `secret_access_key`; `session_token` is optional (temporary credentials). Incompatible with `body_mode: multipart`, whose body bytes are not known at signing time.\n- `gcp_service_account` — mints a Google OAuth 2.0 access token from a signed service account assertion and sends it as a bearer token. Requires `credentials` (the service account key file JSON, as a string) and `scopes` (a non-empty array). Tokens are cached per service account and scope set until shortly before they expire.\n\nCredential fields accept `{{secret:...}}` references and should use them — a tool is readable by anyone who can `GET /tools`, and the stored reference is what is echoed back, never the resolved value.\n\n`headers` values additionally accept `{{context:<key>}}` references, resolved per call from the caller's `tool_context`, so a per-user credential can be placed in the real header the target expects (`Authorization: Bearer {{context:ocaToken}}`) instead of only in an `X-Naturali-Context-<key>` header. Valid **only** inside `headers` — a context value is caller-supplied, so it may not steer the `url` — and a key missing from the `tool_context` at call time fails the tool call with `MISSING_TOOL_CONTEXT_KEY` rather than sending an empty credential. See the Tool Context reference.\n",
|
|
14772
|
+
"description": "Execution config for http tools. Supported fields: `url` (required), `method` (default `POST`), `headers`, and `body_mode`. The `url` may contain `{paramName}` placeholders (e.g. `/users/{userId}`) that are replaced at call time with the corresponding tool argument value (URL-encoded). Arguments consumed as path parameters are excluded from the query string and request body. `body_mode` is `json` (default) or `multipart`. In `multipart` mode the merged tool arguments are sent as a `multipart/form-data` body: scalar fields become plain form fields and a field shaped like `{ content_type, filename, data_base64 }` is decoded from base64 and attached as a file part (the hardcoded `Content-Type: application/json` is dropped so `fetch` sets the multipart boundary itself).\n\n`auth` adds a computed request credential, for targets whose `Authorization` value cannot be expressed as a static header. Supported `auth.type` values:\n\n- `aws_sigv4` — signs the request with AWS Signature Version 4. Requires `region`, `service`, `access_key_id` and `secret_access_key`; `session_token` is optional (temporary credentials). Incompatible with `body_mode: multipart`, whose body bytes are not known at signing time.\n- `gcp_service_account` — mints a Google OAuth 2.0 access token from a signed service account assertion and sends it as a bearer token. Requires `credentials` (the service account key file JSON, as a string) and `scopes` (a non-empty array). Tokens are cached per service account and scope set until shortly before they expire.\n\nCredential fields accept `{{secret:...}}` references and should use them — a tool is readable by anyone who can `GET /tools`, and the stored reference is what is echoed back, never the resolved value.\n\nA credential written as a **literal** is stored and still sent on every call, but it is masked on every read: `secret_access_key`, `session_token` and `credentials` under `auth`, and any credential-named `headers` value (`Authorization`, `Cookie`, or a name containing `api-key`/`token`/`secret`/`password`), come back as `{\"no_echo\": true}`. The mask is an object rather than a string so a read-edit-write round trip fails the schema check instead of writing the placeholder in as the credential. A value carrying a `{{secret:...}}` reference is the wiring, not the credential, and stays readable.\n\n`headers` values additionally accept `{{context:<key>}}` references, resolved per call from the caller's `tool_context`, so a per-user credential can be placed in the real header the target expects (`Authorization: Bearer {{context:ocaToken}}`) instead of only in an `X-Naturali-Context-<key>` header. Valid **only** inside `headers` — a context value is caller-supplied, so it may not steer the `url` — and a key missing from the `tool_context` at call time fails the tool call with `MISSING_TOOL_CONTEXT_KEY` rather than sending an empty credential. See the Tool Context reference.\n",
|
|
14770
14773
|
"required": false,
|
|
14771
14774
|
"type": "object",
|
|
14772
14775
|
"in": "body"
|
|
14773
14776
|
},
|
|
14774
14777
|
{
|
|
14775
14778
|
"name": "mcp",
|
|
14776
|
-
"description": "MCP server config (`url`, `headers`). `headers` values accept `{{secret:...}}` and `{{context:<key>}}` references, resolved right before the outbound MCP request; `url` accepts `{{secret:...}}` only.",
|
|
14779
|
+
"description": "MCP server config (`url`, `headers`). `headers` values accept `{{secret:...}}` and `{{context:<key>}}` references, resolved right before the outbound MCP request; `url` accepts `{{secret:...}}` only. A literal credential in `headers` is masked on read, exactly as in `execute`.",
|
|
14777
14780
|
"required": false,
|
|
14778
14781
|
"type": "object",
|
|
14779
14782
|
"in": "body"
|
|
@@ -14904,14 +14907,14 @@ const routes = {
|
|
|
14904
14907
|
},
|
|
14905
14908
|
{
|
|
14906
14909
|
"name": "execute",
|
|
14907
|
-
"description": "Execution config for http tools. Supported fields: `url` (required), `method` (default `POST`), `headers`, and `body_mode`. The `url` may contain `{paramName}` placeholders (e.g. `/users/{userId}`) that are replaced at call time with the corresponding tool argument value (URL-encoded). Arguments consumed as path parameters are excluded from the query string and request body. `body_mode` is `json` (default) or `multipart`. In `multipart` mode the merged tool arguments are sent as a `multipart/form-data` body: scalar fields become plain form fields and a field shaped like `{ content_type, filename, data_base64 }` is decoded from base64 and attached as a file part (the hardcoded `Content-Type: application/json` is dropped so `fetch` sets the multipart boundary itself).\n\n`auth` adds a computed request credential, for targets whose `Authorization` value cannot be expressed as a static header. Supported `auth.type` values:\n\n- `aws_sigv4` — signs the request with AWS Signature Version 4. Requires `region`, `service`, `access_key_id` and `secret_access_key`; `session_token` is optional (temporary credentials). Incompatible with `body_mode: multipart`, whose body bytes are not known at signing time.\n- `gcp_service_account` — mints a Google OAuth 2.0 access token from a signed service account assertion and sends it as a bearer token. Requires `credentials` (the service account key file JSON, as a string) and `scopes` (a non-empty array). Tokens are cached per service account and scope set until shortly before they expire.\n\nCredential fields accept `{{secret:...}}` references and should use them — a tool is readable by anyone who can `GET /tools`, and the stored reference is what is echoed back, never the resolved value.\n\n`headers` values additionally accept `{{context:<key>}}` references, resolved per call from the caller's `tool_context`, so a per-user credential can be placed in the real header the target expects (`Authorization: Bearer {{context:ocaToken}}`) instead of only in an `X-Naturali-Context-<key>` header. Valid **only** inside `headers` — a context value is caller-supplied, so it may not steer the `url` — and a key missing from the `tool_context` at call time fails the tool call with `MISSING_TOOL_CONTEXT_KEY` rather than sending an empty credential. See the Tool Context reference.\n",
|
|
14910
|
+
"description": "Execution config for http tools. Supported fields: `url` (required), `method` (default `POST`), `headers`, and `body_mode`. The `url` may contain `{paramName}` placeholders (e.g. `/users/{userId}`) that are replaced at call time with the corresponding tool argument value (URL-encoded). Arguments consumed as path parameters are excluded from the query string and request body. `body_mode` is `json` (default) or `multipart`. In `multipart` mode the merged tool arguments are sent as a `multipart/form-data` body: scalar fields become plain form fields and a field shaped like `{ content_type, filename, data_base64 }` is decoded from base64 and attached as a file part (the hardcoded `Content-Type: application/json` is dropped so `fetch` sets the multipart boundary itself).\n\n`auth` adds a computed request credential, for targets whose `Authorization` value cannot be expressed as a static header. Supported `auth.type` values:\n\n- `aws_sigv4` — signs the request with AWS Signature Version 4. Requires `region`, `service`, `access_key_id` and `secret_access_key`; `session_token` is optional (temporary credentials). Incompatible with `body_mode: multipart`, whose body bytes are not known at signing time.\n- `gcp_service_account` — mints a Google OAuth 2.0 access token from a signed service account assertion and sends it as a bearer token. Requires `credentials` (the service account key file JSON, as a string) and `scopes` (a non-empty array). Tokens are cached per service account and scope set until shortly before they expire.\n\nCredential fields accept `{{secret:...}}` references and should use them — a tool is readable by anyone who can `GET /tools`, and the stored reference is what is echoed back, never the resolved value.\n\nA credential written as a **literal** is stored and still sent on every call, but it is masked on every read: `secret_access_key`, `session_token` and `credentials` under `auth`, and any credential-named `headers` value (`Authorization`, `Cookie`, or a name containing `api-key`/`token`/`secret`/`password`), come back as `{\"no_echo\": true}`. The mask is an object rather than a string so a read-edit-write round trip fails the schema check instead of writing the placeholder in as the credential. A value carrying a `{{secret:...}}` reference is the wiring, not the credential, and stays readable.\n\n`headers` values additionally accept `{{context:<key>}}` references, resolved per call from the caller's `tool_context`, so a per-user credential can be placed in the real header the target expects (`Authorization: Bearer {{context:ocaToken}}`) instead of only in an `X-Naturali-Context-<key>` header. Valid **only** inside `headers` — a context value is caller-supplied, so it may not steer the `url` — and a key missing from the `tool_context` at call time fails the tool call with `MISSING_TOOL_CONTEXT_KEY` rather than sending an empty credential. See the Tool Context reference.\n",
|
|
14908
14911
|
"required": false,
|
|
14909
14912
|
"type": "object",
|
|
14910
14913
|
"in": "body"
|
|
14911
14914
|
},
|
|
14912
14915
|
{
|
|
14913
14916
|
"name": "mcp",
|
|
14914
|
-
"description": "MCP server config (`url`, `headers`). `headers` values accept `{{secret:...}}` and `{{context:<key>}}` references, resolved right before the outbound MCP request; `url` accepts `{{secret:...}}` only.",
|
|
14917
|
+
"description": "MCP server config (`url`, `headers`). `headers` values accept `{{secret:...}}` and `{{context:<key>}}` references, resolved right before the outbound MCP request; `url` accepts `{{secret:...}}` only. A literal credential in `headers` is masked on read, exactly as in `execute`.",
|
|
14915
14918
|
"required": false,
|
|
14916
14919
|
"type": "object",
|
|
14917
14920
|
"in": "body"
|
|
@@ -14992,7 +14995,7 @@ const routes = {
|
|
|
14992
14995
|
"call-tool": {
|
|
14993
14996
|
serviceClass: "Tools",
|
|
14994
14997
|
operationId: "callTool",
|
|
14995
|
-
description: "Directly invokes a tool and returns its output. Supported for `http`, `mcp`, and `pipeline` tools. `client` tools cannot be invoked server-side and will return 422. A `pipeline` tool runs its declared steps in order and returns the mapped `output` (or the last step's output); `action` is ignored and `input` is the pipeline input. For `mcp` tools the `action` field is required and identifies which tool name to invoke. For `http` tools `action` is ignored. When an `mcp` tool declares an `actions` allowlist, an action outside it is rejected with `400 VALIDATION_FAILED` (\"not available on this tool\") before any outbound request is made. `preset_parameters` stored on the tool are pinned over the caller-supplied `input` before execution: a key the tool presets keeps its preset value even when `input` sets it. Keys the presets do not name are taken from `input` as sent.",
|
|
14998
|
+
description: "Directly invokes a tool and returns its output. Supported for `http`, `mcp`, and `pipeline` tools. `client` tools cannot be invoked server-side and will return 422. A `pipeline` tool runs its declared steps in order and returns the mapped `output` (or the last step's output); `action` is ignored and `input` is the pipeline input. For `mcp` tools the `action` field is required and identifies which tool name to invoke. For `http` tools `action` is ignored. When an `mcp` tool declares an `actions` allowlist, an action outside it is rejected with `400 VALIDATION_FAILED` (\"not available on this tool\") before any outbound request is made. `preset_parameters` stored on the tool are pinned over the caller-supplied `input` before execution: a key the tool presets keeps its preset value even when `input` sets it. Keys the presets do not name are taken from `input` as sent. Guardrails attached to the tool or to its project adjudicate the call before dispatch, composing project + tool scope. A call this route cannot await a decision on — class C (human sign-off), class D, or a class-B tripwire — is refused with `422 TOOL_DISPATCH_FAILED`, whose `meta` carries the `tool_id` and the `outcome`. A `pipeline` tool is adjudicated before its first step runs, and every step is adjudicated as the call of that tool it is.",
|
|
14996
14999
|
moduleDocsUrl: "https://docs.naturali.ai/docs/modules/tools",
|
|
14997
15000
|
httpMethod: "post",
|
|
14998
15001
|
pathParams: ["project_id", "tool_id"],
|
|
@@ -15314,7 +15317,7 @@ const routes = {
|
|
|
15314
15317
|
"update-trigger": {
|
|
15315
15318
|
serviceClass: "Triggers",
|
|
15316
15319
|
operationId: "updateTrigger",
|
|
15317
|
-
description: "Updates an existing trigger's configuration. The type is immutable.",
|
|
15320
|
+
description: "Updates an existing trigger's configuration. The type is immutable. Changing `target_type` or `target_id` re-checks the target-start action (`orchestrations:StartRun`, `agents:CreateAgentGeneration` or `tools:CallTool`) against the resulting target, because a firing runs with the trigger creator's authority rather than the updater's. A caller who could not start the new target is answered `403` and the trigger keeps the target it had.",
|
|
15318
15321
|
moduleDocsUrl: "https://docs.naturali.ai/docs/modules/triggers",
|
|
15319
15322
|
httpMethod: "patch",
|
|
15320
15323
|
pathParams: ["project_id", "trigger_id"],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@naturali/cli",
|
|
3
|
-
"version": "0.120.
|
|
3
|
+
"version": "0.120.4",
|
|
4
4
|
"description": "Command-line interface for the naturali.ai API, generated from its OpenAPI specs",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"tsx": "^4.23.1",
|
|
31
31
|
"typescript": "~6.0.3",
|
|
32
32
|
"vitest": "^4.1.10",
|
|
33
|
-
"@naturali/sdk": "0.120.
|
|
33
|
+
"@naturali/sdk": "0.120.4"
|
|
34
34
|
},
|
|
35
35
|
"scripts": {
|
|
36
36
|
"generate": "tsx scripts/generate.ts",
|