@naturali/cli 0.28.0 → 0.28.2

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.
Files changed (3) hide show
  1. package/README.md +13 -0
  2. package/dist/index.mjs +87 -72
  3. package/package.json +5 -3
package/README.md CHANGED
@@ -88,6 +88,19 @@ pipeline.
88
88
  Hand-written source is limited to dispatch, flag parsing, credentials and help;
89
89
  there is no per-endpoint code.
90
90
 
91
+ ## Testing
92
+
93
+ `pnpm test` runs the unit suite against a mocked `fetch` — flag parsing,
94
+ dispatch, and help output, on every pull request.
95
+
96
+ `pnpm e2e` (`tests/e2e/smoke.ts`) is different: it drives the *built* CLI
97
+ binary (`bin/naturali`) as real subprocesses against the real, deployed API,
98
+ using a `NATURALI_E2E_API_KEY` account-scoped key. It proves the one thing the
99
+ mocked suite can't — that the CLI, the `@naturali/sdk` it bundles, and the live
100
+ API actually agree — and it provisions and archives its own throwaway project.
101
+ It costs real model-provider money, so it only runs as part of the `e2e` job in
102
+ [`main.yml`](../../.github/workflows/main.yml), never on pull requests.
103
+
91
104
  ## Versioning
92
105
 
93
106
  Releases are automatic, and the version is **shared with the API and with
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.28.0";
17
+ var version = "0.28.2";
18
18
  //#endregion
19
19
  //#region ../sdk/src/generated/core/bodySerializer.gen.ts
20
20
  const jsonBodySerializer = { bodySerializer: (body) => JSON.stringify(body, (_key, value) => typeof value === "bigint" ? value.toString() : value) };
@@ -1299,7 +1299,7 @@ var Knowledge = class {
1299
1299
  */
1300
1300
  static queryKnowledgeCollection(options) {
1301
1301
  return (options.client ?? client).post({
1302
- url: "/v1/projects/{project_id}/knowledge/collections/{collection_id}",
1302
+ url: "/v1/projects/{project_id}/knowledge/collections/{collection_id}:query",
1303
1303
  ...options,
1304
1304
  headers: {
1305
1305
  "Content-Type": "application/json",
@@ -1362,7 +1362,7 @@ var Knowledge = class {
1362
1362
  */
1363
1363
  static reingestKnowledgeDocument(options) {
1364
1364
  return (options.client ?? client).post({
1365
- url: "/v1/projects/{project_id}/knowledge/collections/{collection_id}/documents/{document_id}",
1365
+ url: "/v1/projects/{project_id}/knowledge/collections/{collection_id}/documents/{document_id}:reingest",
1366
1366
  ...options
1367
1367
  });
1368
1368
  }
@@ -2107,6 +2107,32 @@ const formatError = (args) => {
2107
2107
  }, null, 2);
2108
2108
  };
2109
2109
  /**
2110
+ * Resolves the generated SDK method for a route, exiting with an error
2111
+ * envelope if the service class or the method itself cannot be found.
2112
+ */
2113
+ const resolveServiceMethod = (route) => {
2114
+ const serviceClass = resolveServiceClass(route.serviceClass);
2115
+ if (!serviceClass) {
2116
+ console.error(`SDK class "${route.serviceClass}" not found.`);
2117
+ process.exit(1);
2118
+ }
2119
+ const method = serviceClass[route.operationId];
2120
+ if (typeof method !== "function") {
2121
+ console.error(`Method "${route.operationId}" not found on ${route.serviceClass}.`);
2122
+ process.exit(1);
2123
+ }
2124
+ return method;
2125
+ };
2126
+ /** Builds the SDK call options from a resolved route call, omitting empty parts. */
2127
+ const buildCallOptions = (args) => {
2128
+ const { client, call } = args;
2129
+ const callOptions = { client };
2130
+ if (Object.keys(call.path).length) callOptions["path"] = call.path;
2131
+ if (Object.keys(call.query).length) callOptions["query"] = call.query;
2132
+ if (Object.keys(call.body).length) callOptions["body"] = call.body;
2133
+ return callOptions;
2134
+ };
2135
+ /**
2110
2136
  * Runs one generated command: parses its flags, resolves credentials, calls the
2111
2137
  * matching SDK method, and prints the result.
2112
2138
  *
@@ -2135,21 +2161,10 @@ const dispatchCommand = async (args) => {
2135
2161
  console.error(`Missing required path parameter(s): ${built.missingPathParams.join(", ")}.\nProvide with ${flagsHint}.`);
2136
2162
  process.exit(1);
2137
2163
  }
2138
- const serviceClass = resolveServiceClass(route.serviceClass);
2139
- if (!serviceClass) {
2140
- console.error(`SDK class "${route.serviceClass}" not found.`);
2141
- process.exit(1);
2142
- }
2143
- const method = serviceClass[route.operationId];
2144
- if (typeof method !== "function") {
2145
- console.error(`Method "${route.operationId}" not found on ${route.serviceClass}.`);
2146
- process.exit(1);
2147
- }
2148
- const callOptions = { client: context.client };
2149
- if (Object.keys(built.call.path).length) callOptions["path"] = built.call.path;
2150
- if (Object.keys(built.call.query).length) callOptions["query"] = built.call.query;
2151
- if (Object.keys(built.call.body).length) callOptions["body"] = built.call.body;
2152
- const result = await method(callOptions) ?? {};
2164
+ const result = await resolveServiceMethod(route)(buildCallOptions({
2165
+ client: context.client,
2166
+ call: built.call
2167
+ })) ?? {};
2153
2168
  if (result.error) {
2154
2169
  console.error(formatError({
2155
2170
  error: result.error,
@@ -3779,52 +3794,6 @@ const routes = {
3779
3794
  "in": "path"
3780
3795
  }]
3781
3796
  },
3782
- "query-knowledge-collection": {
3783
- serviceClass: "Knowledge",
3784
- operationId: "queryKnowledgeCollection",
3785
- description: "Retrieval preview (API.md §4, K5): returns the chunks the collection would surface for a question — debuggable standalone, before any agent is bound to it. This is the `…:query` action; the path segment is `{collection_id}:query`.",
3786
- moduleDocsUrl: "https://docs.naturali.ai/docs/modules/knowledge",
3787
- httpMethod: "post",
3788
- pathParams: ["project_id", "collection_id"],
3789
- queryParams: [],
3790
- flags: [
3791
- {
3792
- "name": "project_id",
3793
- "description": "Project public ID (proj_ prefix).",
3794
- "required": true,
3795
- "type": "string",
3796
- "in": "path"
3797
- },
3798
- {
3799
- "name": "collection_id",
3800
- "description": "Knowledge collection public ID (kcol_ prefix).",
3801
- "required": true,
3802
- "type": "string",
3803
- "in": "path"
3804
- },
3805
- {
3806
- "name": "query",
3807
- "description": "The question to preview retrieval for.",
3808
- "required": true,
3809
- "type": "string",
3810
- "in": "body"
3811
- },
3812
- {
3813
- "name": "top_k",
3814
- "description": "Maximum chunks to return.",
3815
- "required": false,
3816
- "type": "integer",
3817
- "in": "body"
3818
- },
3819
- {
3820
- "name": "min_score",
3821
- "description": "Drop chunks below this similarity score.",
3822
- "required": false,
3823
- "type": "number",
3824
- "in": "body"
3825
- }
3826
- ]
3827
- },
3828
3797
  "update-knowledge-collection": {
3829
3798
  serviceClass: "Knowledge",
3830
3799
  operationId: "updateKnowledgeCollection",
@@ -3886,6 +3855,52 @@ const routes = {
3886
3855
  "in": "path"
3887
3856
  }]
3888
3857
  },
3858
+ "query-knowledge-collection": {
3859
+ serviceClass: "Knowledge",
3860
+ operationId: "queryKnowledgeCollection",
3861
+ description: "Retrieval preview (API.md §4, K5): returns the chunks the collection would surface for a question — debuggable standalone, before any agent is bound to it. This is the `…:query` action; the path segment is `{collection_id}:query`.",
3862
+ moduleDocsUrl: "https://docs.naturali.ai/docs/modules/knowledge",
3863
+ httpMethod: "post",
3864
+ pathParams: ["project_id", "collection_id"],
3865
+ queryParams: [],
3866
+ flags: [
3867
+ {
3868
+ "name": "project_id",
3869
+ "description": "Project public ID (proj_ prefix).",
3870
+ "required": true,
3871
+ "type": "string",
3872
+ "in": "path"
3873
+ },
3874
+ {
3875
+ "name": "collection_id",
3876
+ "description": "Knowledge collection public ID (kcol_ prefix).",
3877
+ "required": true,
3878
+ "type": "string",
3879
+ "in": "path"
3880
+ },
3881
+ {
3882
+ "name": "query",
3883
+ "description": "The question to preview retrieval for.",
3884
+ "required": true,
3885
+ "type": "string",
3886
+ "in": "body"
3887
+ },
3888
+ {
3889
+ "name": "top_k",
3890
+ "description": "Maximum chunks to return.",
3891
+ "required": false,
3892
+ "type": "integer",
3893
+ "in": "body"
3894
+ },
3895
+ {
3896
+ "name": "min_score",
3897
+ "description": "Drop chunks below this similarity score.",
3898
+ "required": false,
3899
+ "type": "number",
3900
+ "in": "body"
3901
+ }
3902
+ ]
3903
+ },
3889
3904
  "list-knowledge-documents": {
3890
3905
  serviceClass: "Knowledge",
3891
3906
  operationId: "listKnowledgeDocuments",
@@ -4007,12 +4022,12 @@ const routes = {
4007
4022
  }
4008
4023
  ]
4009
4024
  },
4010
- "reingest-knowledge-document": {
4025
+ "delete-knowledge-document": {
4011
4026
  serviceClass: "Knowledge",
4012
- operationId: "reingestKnowledgeDocument",
4013
- description: "Re-run ingestion for a document against its stored source, resetting it to `pending` before re-processing — the recovery path for a `failed` ingest (API.md §4, K1). This is the `…:reingest` action; the path segment is `{document_id}:reingest`.",
4027
+ operationId: "deleteKnowledgeDocument",
4028
+ description: "Delete a document",
4014
4029
  moduleDocsUrl: "https://docs.naturali.ai/docs/modules/knowledge",
4015
- httpMethod: "post",
4030
+ httpMethod: "delete",
4016
4031
  pathParams: [
4017
4032
  "project_id",
4018
4033
  "collection_id",
@@ -4043,12 +4058,12 @@ const routes = {
4043
4058
  }
4044
4059
  ]
4045
4060
  },
4046
- "delete-knowledge-document": {
4061
+ "reingest-knowledge-document": {
4047
4062
  serviceClass: "Knowledge",
4048
- operationId: "deleteKnowledgeDocument",
4049
- description: "Delete a document",
4063
+ operationId: "reingestKnowledgeDocument",
4064
+ description: "Re-run ingestion for a document against its stored source, resetting it to `pending` before re-processing — the recovery path for a `failed` ingest (API.md §4, K1). This is the `…:reingest` action; the path segment is `{document_id}:reingest`.",
4050
4065
  moduleDocsUrl: "https://docs.naturali.ai/docs/modules/knowledge",
4051
- httpMethod: "delete",
4066
+ httpMethod: "post",
4052
4067
  pathParams: [
4053
4068
  "project_id",
4054
4069
  "collection_id",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naturali/cli",
3
- "version": "0.28.0",
3
+ "version": "0.28.2",
4
4
  "description": "Command-line interface for the naturali.ai API, generated from its OpenAPI specs",
5
5
  "type": "module",
6
6
  "bin": {
@@ -30,12 +30,14 @@
30
30
  "tsx": "^4.23.1",
31
31
  "typescript": "~6.0.3",
32
32
  "vitest": "^4.1.10",
33
- "@naturali/sdk": "0.28.0"
33
+ "@naturali/sdk": "0.28.2"
34
34
  },
35
35
  "scripts": {
36
36
  "generate": "tsx scripts/generate.ts",
37
37
  "typecheck": "tsc --noEmit",
38
+ "lint": "eslint src tests",
38
39
  "test": "vitest run",
39
- "build": "tsdown"
40
+ "build": "tsdown",
41
+ "e2e": "tsx tests/e2e/smoke.ts"
40
42
  }
41
43
  }