diff --git a/.fern/metadata.json b/.fern/metadata.json index 9ddb2e8..57faac3 100644 --- a/.fern/metadata.json +++ b/.fern/metadata.json @@ -18,6 +18,6 @@ "testImplementation org.mockito:mockito-inline:4.11.0" ] }, - "originGitCommit": "a155514591918efab974910cfee4187442fa8f75", - "sdkVersion": "1.16.0" + "originGitCommit": "094c36681badc82afeb39a2c91a716461a5a0bd2", + "sdkVersion": "1.17.0" } \ No newline at end of file diff --git a/.fern/replay.lock b/.fern/replay.lock index 62071c5..59c0dae 100644 --- a/.fern/replay.lock +++ b/.fern/replay.lock @@ -6,5 +6,11 @@ generations: timestamp: 2026-05-22T18:11:45.172Z cli_version: unknown generator_versions: {} -current_generation: 710d88bcb4d50d2e360b61cc28953fa1c2ade039 + - commit_sha: 4bfa1695c5fdc3aaa796c53d117df0c43484a3a8 + tree_hash: c388b88a5b989c6000e0199608162c75f2ef838d + timestamp: 2026-07-15T17:03:23.896Z + cli_version: unknown + generator_versions: + fernapi/fern-java-sdk: 3.34.8 +current_generation: 4bfa1695c5fdc3aaa796c53d117df0c43484a3a8 patches: [] diff --git a/build.gradle b/build.gradle index 5515273..78077a1 100644 --- a/build.gradle +++ b/build.gradle @@ -50,7 +50,7 @@ java { group = 'ai.extend' -version = '1.16.0' +version = '1.17.0' jar { dependsOn(":generatePomFileForMavenPublication") @@ -81,7 +81,7 @@ publishing { maven(MavenPublication) { groupId = 'ai.extend' artifactId = 'extend-java-sdk' - version = '1.16.0' + version = '1.17.0' from components.java pom { name = 'Extend.ai' diff --git a/reference.md b/reference.md index 9eb8f65..b1b9fff 100644 --- a/reference.md +++ b/reference.md @@ -98,6 +98,14 @@ Controls the format of the response chunks. Defaults to `json` if not specified. **metadata:** `Optional>` + + + +
+
+ +**dataRetention:** `Optional` +
@@ -126,7 +134,7 @@ Edit a file synchronously, waiting for the result before returning. This endpoin The Edit endpoint allows you to detect and fill form fields in PDF documents. -For more details, see the [Edit File guide](https://docs.extend.ai/2026-02-09/editing/edit). +For more details, see the [Edit File guide](https://docs.extend.ai/2026-02-09/editing/overview). See [Editing Error Handling](https://docs.extend.ai/2026-02-09/editing/error-handling) for HTTP errors and run failure reasons. @@ -196,6 +204,94 @@ client.edit( + + + + +
client.detectForm(request) -> FormDetectionRun +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Detect fields in a PDF form and wait for the generated edit schema before returning. This endpoint has a 5-minute timeout. + +For production workloads, use `POST /form_detection_runs` and poll `GET /form_detection_runs/{id}` instead. The response is a completed `form_detection_run`; its `output.schema` can be passed directly to `POST /edit` or `POST /edit_runs`. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```java +client.detectForm( + DetectFormRequest + .builder() + .file( + DetectFormRequestFile.of( + FileFromUrl + .builder() + .url("https://example.com/form.pdf") + .build() + ) + ) + .config( + EditSchemaGenerationConfig + .builder() + .instructions("Detect the form fields and use human-readable field names.") + .advancedOptions( + EditSchemaGenerationConfigAdvancedOptions + .builder() + .radioEnumsEnabled(true) + .build() + ) + .build() + ) + .build() +); +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**file:** `DetectFormRequestFile` — The PDF form to analyze. Files can be provided as a URL or an Extend file ID. + +
+
+ +
+
+ +**config:** `Optional` + +
+
+
+
+ +
@@ -366,7 +462,7 @@ Classify a document synchronously, waiting for the result before returning. This The Classify endpoint allows you to classify documents using an existing classifier or an inline configuration. -For more details, see the [Classify File guide](https://docs.extend.ai/2026-02-09/classification/configuring-a-classifier). +For more details, see the [Classify File guide](https://docs.extend.ai/2026-02-09/classification/configuration). @@ -489,7 +585,7 @@ Split a document synchronously, waiting for the result before returning. This en The Split endpoint allows you to split documents into multiple parts using an existing splitter or an inline configuration. -For more details, see the [Split File guide](https://docs.extend.ai/2026-02-09/splitting/configuring-a-splitter). +For more details, see the [Split File guide](https://docs.extend.ai/2026-02-09/splitting/configuration). @@ -753,7 +849,7 @@ Example: `"file_Xj8mK2pL9nR4vT7qY5wZ"` **rawText:** `Optional` -**Deprecated:** Use `POST /parse_runs` instead to parse file contents. +**Deprecated:** Use `POST /parse_runs` instead to parse file contents and get contents or `GET /parse_runs/{id}` to retrieve the results async if file is already parsed. Files parsed with versions >2.x will not support this parameter. If set to true, the raw text content of the file will be included in the response. @@ -765,7 +861,7 @@ If set to true, the raw text content of the file will be included in the respons **markdown:** `Optional` -**Deprecated:** Use `POST /parse_runs` instead to parse file contents. +**Deprecated:** Use `POST /parse_runs` instead to parse file contents and get contents or `GET /parse_runs/{id}` to retrieve the results async if file is already parsed. Files parsed with versions >2.x will not support this parameter. If set to true, the markdown content of the file will be included in the response. @@ -779,7 +875,7 @@ Only available for files with a type of PDF, IMG, or DOCX files that were auto-c **html:** `Optional` -**Deprecated:** Use `POST /parse_runs` instead to parse file contents. +**Deprecated:** Use `POST /parse_runs` instead to parse file contents and get contents or `GET /parse_runs/{id}` to retrieve the results async if file is already parsed. Files parsed with versions >2.x will not support this parameter. If set to true, the html content of the file will be included in the response. @@ -1157,6 +1253,14 @@ client.parseRuns().create( **metadata:** `Optional>` + + + +
+
+ +**dataRetention:** `Optional` +
@@ -1785,7 +1889,7 @@ Example: `"edr_xK9mLPqRtN3vS8wF5hB2cQ"` Retrieve a saved edit template by ID. -Use this endpoint to inspect the source file, default edit configuration, and optional schema generation configuration saved on an edit template. You can reuse the returned `config` with `POST /edit` or `POST /edit_runs`, and reuse `schemaConfig` with `POST /edit_schemas/generate`. +Use this endpoint to inspect the source file, default edit configuration, and optional schema generation configuration saved on an edit template. You can reuse the returned `config` with `POST /edit` or `POST /edit_runs`, and reuse `schemaConfig` with `POST /detect_form` or `POST /form_detection_runs`. @@ -1857,13 +1961,15 @@ Example: `"edt_xK9mLPqRtN3vS8wF5hB2cQ"`
+**Deprecated:** Use `POST /detect_form` for synchronous form detection or `POST /form_detection_runs` for asynchronous processing. + Detect fields in a PDF form and synchronously return an edit schema payload. Use this endpoint when you want Extend to bootstrap an `EditRootJSON` schema from an existing form, optionally mapping an existing schema onto the detected fields. This endpoint returns the generated schema directly. There are no schema generation run resources to poll or delete. -For more details, see the [Generate Edit Schema guide](https://docs.extend.ai/2026-02-09/editing/generate-edit-schema) and the [Edit File guide](https://docs.extend.ai/2026-02-09/editing/edit). +For more details, see the [Detect Form guide](https://docs.extend.ai/2026-02-09/editing/detect-form) and the [Edit File guide](https://docs.extend.ai/2026-02-09/editing/overview).
@@ -1933,6 +2039,168 @@ client.editSchemas().generate( + + + + +## FormDetectionRuns +
client.formDetectionRuns.create(request) -> FormDetectionRun +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Start detecting fields in a PDF form and return immediately with a `form_detection_run` resource, typically in the `PROCESSING` state. + +Poll `GET /form_detection_runs/{id}` until the status is `PROCESSED` or `FAILED`. When processing succeeds, `output.schema` contains an edit schema you can pass directly to `POST /edit` or `POST /edit_runs`. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```java +client.formDetectionRuns().create( + FormDetectionRunsCreateRequest + .builder() + .file( + FormDetectionRunsCreateRequestFile.of( + FileFromUrl + .builder() + .url("https://example.com/form.pdf") + .build() + ) + ) + .config( + EditSchemaGenerationConfig + .builder() + .instructions("Detect the form fields and use human-readable field names.") + .advancedOptions( + EditSchemaGenerationConfigAdvancedOptions + .builder() + .radioEnumsEnabled(true) + .build() + ) + .build() + ) + .build() +); +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**file:** `FormDetectionRunsCreateRequestFile` — The PDF form to analyze. Files can be provided as a URL or an Extend file ID. + +
+
+ +
+
+ +**config:** `Optional` + +
+
+
+
+ + +
+
+
+ +
client.formDetectionRuns.retrieve(id) -> FormDetectionRun +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Retrieve the status and results of a form detection run. + +Use this endpoint to poll a run created with `POST /form_detection_runs`. When `status` is `PROCESSED`, `output.schema` contains the generated edit schema. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```java +client.formDetectionRuns().retrieve( + "sgr_xK9mLPqRtN3vS8wF5hB2cQ", + FormDetectionRunsRetrieveRequest + .builder() + .build() +); +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**id:** `String` + +The unique identifier for the form detection run. + +Example: `"sgr_xK9mLPqRtN3vS8wF5hB2cQ"` + +
+
+ +
+
+ +**extendWorkspaceId:** `Optional` — The workspace ID to target. **Required** when using an organization-scoped API key; optional for workspace-scoped keys (the key is already tied to a workspace). See [Authentication](https://docs.extend.ai/2026-02-09/api-reference/authentication) for details on API key scopes. + +
+
+
+
+ +
diff --git a/src/main/java/ai/extend/AsyncExtendClientBase.java b/src/main/java/ai/extend/AsyncExtendClientBase.java index 73dd7ae..1fc1f54 100644 --- a/src/main/java/ai/extend/AsyncExtendClientBase.java +++ b/src/main/java/ai/extend/AsyncExtendClientBase.java @@ -7,6 +7,7 @@ import ai.extend.core.RequestOptions; import ai.extend.core.Suppliers; import ai.extend.requests.ClassifyRequest; +import ai.extend.requests.DetectFormRequest; import ai.extend.requests.EditRequest; import ai.extend.requests.ExtractRequest; import ai.extend.requests.ParseRequest; @@ -26,6 +27,7 @@ import ai.extend.resources.extractorversions.AsyncExtractorVersionsClient; import ai.extend.resources.extractruns.AsyncExtractRunsClient; import ai.extend.resources.files.AsyncFilesClient; +import ai.extend.resources.formdetectionruns.AsyncFormDetectionRunsClient; import ai.extend.resources.parseruns.AsyncParseRunsClient; import ai.extend.resources.processor.AsyncProcessorClient; import ai.extend.resources.processorrun.AsyncProcessorRunClient; @@ -41,6 +43,7 @@ import ai.extend.types.ClassifyRun; import ai.extend.types.EditRun; import ai.extend.types.ExtractRun; +import ai.extend.types.FormDetectionRun; import ai.extend.types.ParseRun; import ai.extend.types.SplitRun; import java.util.concurrent.CompletableFuture; @@ -61,6 +64,8 @@ public class AsyncExtendClientBase { protected final Supplier editSchemasClient; + protected final Supplier formDetectionRunsClient; + protected final Supplier extractRunsClient; protected final Supplier extractorsClient; @@ -113,6 +118,7 @@ public AsyncExtendClientBase(ClientOptions clientOptions) { this.editRunsClient = Suppliers.memoize(() -> new AsyncEditRunsClient(clientOptions)); this.editTemplatesClient = Suppliers.memoize(() -> new AsyncEditTemplatesClient(clientOptions)); this.editSchemasClient = Suppliers.memoize(() -> new AsyncEditSchemasClient(clientOptions)); + this.formDetectionRunsClient = Suppliers.memoize(() -> new AsyncFormDetectionRunsClient(clientOptions)); this.extractRunsClient = Suppliers.memoize(() -> new AsyncExtractRunsClient(clientOptions)); this.extractorsClient = Suppliers.memoize(() -> new AsyncExtractorsClient(clientOptions)); this.extractorVersionsClient = Suppliers.memoize(() -> new AsyncExtractorVersionsClient(clientOptions)); @@ -168,7 +174,7 @@ public CompletableFuture parse(ParseRequest request, RequestOptions re * Edit a file synchronously, waiting for the result before returning. This endpoint has a 5-minute timeout — if processing takes longer, the request will fail. *

Note: This endpoint is intended for onboarding and testing only. For production workloads, use POST /edit_runs with polling or webhooks instead, as it provides better reliability for large files and avoids timeout issues.

*

The Edit endpoint allows you to detect and fill form fields in PDF documents.

- *

For more details, see the Edit File guide.

+ *

For more details, see the Edit File guide. See Editing Error Handling for HTTP errors and run failure reasons.

*/ public CompletableFuture edit(EditRequest request) { return this.rawClient.edit(request).thenApply(response -> response.body()); @@ -178,12 +184,28 @@ public CompletableFuture edit(EditRequest request) { * Edit a file synchronously, waiting for the result before returning. This endpoint has a 5-minute timeout — if processing takes longer, the request will fail. *

Note: This endpoint is intended for onboarding and testing only. For production workloads, use POST /edit_runs with polling or webhooks instead, as it provides better reliability for large files and avoids timeout issues.

*

The Edit endpoint allows you to detect and fill form fields in PDF documents.

- *

For more details, see the Edit File guide.

+ *

For more details, see the Edit File guide. See Editing Error Handling for HTTP errors and run failure reasons.

*/ public CompletableFuture edit(EditRequest request, RequestOptions requestOptions) { return this.rawClient.edit(request, requestOptions).thenApply(response -> response.body()); } + /** + * Detect fields in a PDF form and wait for the generated edit schema before returning. This endpoint has a 5-minute timeout. + *

For production workloads, use POST /form_detection_runs and poll GET /form_detection_runs/{id} instead. The response is a completed form_detection_run; its output.schema can be passed directly to POST /edit or POST /edit_runs.

+ */ + public CompletableFuture detectForm(DetectFormRequest request) { + return this.rawClient.detectForm(request).thenApply(response -> response.body()); + } + + /** + * Detect fields in a PDF form and wait for the generated edit schema before returning. This endpoint has a 5-minute timeout. + *

For production workloads, use POST /form_detection_runs and poll GET /form_detection_runs/{id} instead. The response is a completed form_detection_run; its output.schema can be passed directly to POST /edit or POST /edit_runs.

+ */ + public CompletableFuture detectForm(DetectFormRequest request, RequestOptions requestOptions) { + return this.rawClient.detectForm(request, requestOptions).thenApply(response -> response.body()); + } + /** * Extract structured data from a file synchronously, waiting for the result before returning. This endpoint has a 5-minute timeout — if processing takes longer, the request will fail. *

Note: This endpoint is intended for onboarding and testing only. For production workloads, use POST /extract_runs with polling or webhooks instead, as it provides better reliability for large files and avoids timeout issues.

@@ -232,7 +254,7 @@ public CompletableFuture extract(ExtractRequest request, RequestOpti * Classify a document synchronously, waiting for the result before returning. This endpoint has a 5-minute timeout — if processing takes longer, the request will fail. *

Note: This endpoint is intended for onboarding and testing only. For production workloads, use POST /classify_runs with polling or webhooks instead, as it provides better reliability for large files and avoids timeout issues.

*

The Classify endpoint allows you to classify documents using an existing classifier or an inline configuration.

- *

For more details, see the Classify File guide.

+ *

For more details, see the Classify File guide.

*/ public CompletableFuture classify(ClassifyRequest request) { return this.rawClient.classify(request).thenApply(response -> response.body()); @@ -242,7 +264,7 @@ public CompletableFuture classify(ClassifyRequest request) { * Classify a document synchronously, waiting for the result before returning. This endpoint has a 5-minute timeout — if processing takes longer, the request will fail. *

Note: This endpoint is intended for onboarding and testing only. For production workloads, use POST /classify_runs with polling or webhooks instead, as it provides better reliability for large files and avoids timeout issues.

*

The Classify endpoint allows you to classify documents using an existing classifier or an inline configuration.

- *

For more details, see the Classify File guide.

+ *

For more details, see the Classify File guide.

*/ public CompletableFuture classify(ClassifyRequest request, RequestOptions requestOptions) { return this.rawClient.classify(request, requestOptions).thenApply(response -> response.body()); @@ -252,7 +274,7 @@ public CompletableFuture classify(ClassifyRequest request, RequestO * Split a document synchronously, waiting for the result before returning. This endpoint has a 5-minute timeout — if processing takes longer, the request will fail. *

Note: This endpoint is intended for onboarding and testing only. For production workloads, use POST /split_runs with polling or webhooks instead, as it provides better reliability for large files and avoids timeout issues.

*

The Split endpoint allows you to split documents into multiple parts using an existing splitter or an inline configuration.

- *

For more details, see the Split File guide.

+ *

For more details, see the Split File guide.

*/ public CompletableFuture split(SplitRequest request) { return this.rawClient.split(request).thenApply(response -> response.body()); @@ -262,7 +284,7 @@ public CompletableFuture split(SplitRequest request) { * Split a document synchronously, waiting for the result before returning. This endpoint has a 5-minute timeout — if processing takes longer, the request will fail. *

Note: This endpoint is intended for onboarding and testing only. For production workloads, use POST /split_runs with polling or webhooks instead, as it provides better reliability for large files and avoids timeout issues.

*

The Split endpoint allows you to split documents into multiple parts using an existing splitter or an inline configuration.

- *

For more details, see the Split File guide.

+ *

For more details, see the Split File guide.

*/ public CompletableFuture split(SplitRequest request, RequestOptions requestOptions) { return this.rawClient.split(request, requestOptions).thenApply(response -> response.body()); @@ -288,6 +310,10 @@ public AsyncEditSchemasClient editSchemas() { return this.editSchemasClient.get(); } + public AsyncFormDetectionRunsClient formDetectionRuns() { + return this.formDetectionRunsClient.get(); + } + public AsyncExtractRunsClient extractRuns() { return this.extractRunsClient.get(); } diff --git a/src/main/java/ai/extend/AsyncRawExtendClientBase.java b/src/main/java/ai/extend/AsyncRawExtendClientBase.java index 3eb533c..67c737b 100644 --- a/src/main/java/ai/extend/AsyncRawExtendClientBase.java +++ b/src/main/java/ai/extend/AsyncRawExtendClientBase.java @@ -20,6 +20,7 @@ import ai.extend.errors.UnauthorizedError; import ai.extend.errors.UnprocessableEntityError; import ai.extend.requests.ClassifyRequest; +import ai.extend.requests.DetectFormRequest; import ai.extend.requests.EditRequest; import ai.extend.requests.ExtractRequest; import ai.extend.requests.ParseRequest; @@ -28,6 +29,7 @@ import ai.extend.types.ClassifyRun; import ai.extend.types.EditRun; import ai.extend.types.ExtractRun; +import ai.extend.types.FormDetectionRun; import ai.extend.types.ParseRun; import ai.extend.types.SplitRun; import com.fasterxml.jackson.core.JsonProcessingException; @@ -181,7 +183,7 @@ public void onFailure(@NotNull Call call, @NotNull IOException e) { * Edit a file synchronously, waiting for the result before returning. This endpoint has a 5-minute timeout — if processing takes longer, the request will fail. *

Note: This endpoint is intended for onboarding and testing only. For production workloads, use POST /edit_runs with polling or webhooks instead, as it provides better reliability for large files and avoids timeout issues.

*

The Edit endpoint allows you to detect and fill form fields in PDF documents.

- *

For more details, see the Edit File guide.

+ *

For more details, see the Edit File guide. See Editing Error Handling for HTTP errors and run failure reasons.

*/ public CompletableFuture> edit(EditRequest request) { return edit(request, null); @@ -191,7 +193,7 @@ public CompletableFuture> edit(EditRequest * Edit a file synchronously, waiting for the result before returning. This endpoint has a 5-minute timeout — if processing takes longer, the request will fail. *

Note: This endpoint is intended for onboarding and testing only. For production workloads, use POST /edit_runs with polling or webhooks instead, as it provides better reliability for large files and avoids timeout issues.

*

The Edit endpoint allows you to detect and fill form fields in PDF documents.

- *

For more details, see the Edit File guide.

+ *

For more details, see the Edit File guide. See Editing Error Handling for HTTP errors and run failure reasons.

*/ public CompletableFuture> edit( EditRequest request, RequestOptions requestOptions) { @@ -295,6 +297,121 @@ public void onFailure(@NotNull Call call, @NotNull IOException e) { return future; } + /** + * Detect fields in a PDF form and wait for the generated edit schema before returning. This endpoint has a 5-minute timeout. + *

For production workloads, use POST /form_detection_runs and poll GET /form_detection_runs/{id} instead. The response is a completed form_detection_run; its output.schema can be passed directly to POST /edit or POST /edit_runs.

+ */ + public CompletableFuture> detectForm(DetectFormRequest request) { + return detectForm(request, null); + } + + /** + * Detect fields in a PDF form and wait for the generated edit schema before returning. This endpoint has a 5-minute timeout. + *

For production workloads, use POST /form_detection_runs and poll GET /form_detection_runs/{id} instead. The response is a completed form_detection_run; its output.schema can be passed directly to POST /edit or POST /edit_runs.

+ */ + public CompletableFuture> detectForm( + DetectFormRequest request, RequestOptions requestOptions) { + HttpUrl.Builder httpUrl = HttpUrl.parse(this.clientOptions.environment().getUrl()) + .newBuilder() + .addPathSegments("detect_form"); + if (requestOptions != null) { + requestOptions.getQueryParameters().forEach((_key, _value) -> { + httpUrl.addQueryParameter(_key, _value); + }); + } + RequestBody body; + try { + body = RequestBody.create( + ObjectMappers.JSON_MAPPER.writeValueAsBytes(request), MediaTypes.APPLICATION_JSON); + } catch (JsonProcessingException e) { + throw new ExtendClientException("Failed to serialize request", e); + } + Request okhttpRequest = new Request.Builder() + .url(httpUrl.build()) + .method("POST", body) + .headers(Headers.of(clientOptions.headers(requestOptions))) + .addHeader("Content-Type", "application/json") + .addHeader("Accept", "application/json") + .build(); + OkHttpClient client = clientOptions.httpClient(); + if (requestOptions != null && requestOptions.getTimeout().isPresent()) { + client = clientOptions.httpClientWithTimeout(requestOptions); + } + CompletableFuture> future = new CompletableFuture<>(); + client.newCall(okhttpRequest).enqueue(new Callback() { + @Override + public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException { + try (ResponseBody responseBody = response.body()) { + String responseBodyString = responseBody != null ? responseBody.string() : "{}"; + if (response.isSuccessful()) { + future.complete(new ExtendClientBaseHttpResponse<>( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, FormDetectionRun.class), + response)); + return; + } + try { + switch (response.code()) { + case 400: + future.completeExceptionally(new BadRequestError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, Object.class), + response)); + return; + case 401: + future.completeExceptionally(new UnauthorizedError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, Object.class), + response)); + return; + case 402: + future.completeExceptionally(new PaymentRequiredError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, ApiError.class), + response)); + return; + case 403: + future.completeExceptionally(new ForbiddenError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, ApiError.class), + response)); + return; + case 404: + future.completeExceptionally(new NotFoundError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, Object.class), + response)); + return; + case 422: + future.completeExceptionally(new UnprocessableEntityError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, ApiError.class), + response)); + return; + case 429: + future.completeExceptionally(new TooManyRequestsError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, Object.class), + response)); + return; + case 500: + future.completeExceptionally(new InternalServerError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, Object.class), + response)); + return; + } + } catch (JsonProcessingException ignored) { + // unable to map error response, throwing generic error + } + Object errorBody = ObjectMappers.parseErrorBody(responseBodyString); + future.completeExceptionally(new ExtendClientApiException( + "Error with status code " + response.code(), response.code(), errorBody, response)); + return; + } catch (IOException e) { + future.completeExceptionally(new ExtendClientException("Network error executing HTTP request", e)); + } + } + + @Override + public void onFailure(@NotNull Call call, @NotNull IOException e) { + future.completeExceptionally(new ExtendClientException("Network error executing HTTP request", e)); + } + }); + return future; + } + /** * Extract structured data from a file synchronously, waiting for the result before returning. This endpoint has a 5-minute timeout — if processing takes longer, the request will fail. *

Note: This endpoint is intended for onboarding and testing only. For production workloads, use POST /extract_runs with polling or webhooks instead, as it provides better reliability for large files and avoids timeout issues.

@@ -441,7 +558,7 @@ public void onFailure(@NotNull Call call, @NotNull IOException e) { * Classify a document synchronously, waiting for the result before returning. This endpoint has a 5-minute timeout — if processing takes longer, the request will fail. *

Note: This endpoint is intended for onboarding and testing only. For production workloads, use POST /classify_runs with polling or webhooks instead, as it provides better reliability for large files and avoids timeout issues.

*

The Classify endpoint allows you to classify documents using an existing classifier or an inline configuration.

- *

For more details, see the Classify File guide.

+ *

For more details, see the Classify File guide.

*/ public CompletableFuture> classify(ClassifyRequest request) { return classify(request, null); @@ -451,7 +568,7 @@ public CompletableFuture> classify(Cla * Classify a document synchronously, waiting for the result before returning. This endpoint has a 5-minute timeout — if processing takes longer, the request will fail. *

Note: This endpoint is intended for onboarding and testing only. For production workloads, use POST /classify_runs with polling or webhooks instead, as it provides better reliability for large files and avoids timeout issues.

*

The Classify endpoint allows you to classify documents using an existing classifier or an inline configuration.

- *

For more details, see the Classify File guide.

+ *

For more details, see the Classify File guide.

*/ public CompletableFuture> classify( ClassifyRequest request, RequestOptions requestOptions) { @@ -559,7 +676,7 @@ public void onFailure(@NotNull Call call, @NotNull IOException e) { * Split a document synchronously, waiting for the result before returning. This endpoint has a 5-minute timeout — if processing takes longer, the request will fail. *

Note: This endpoint is intended for onboarding and testing only. For production workloads, use POST /split_runs with polling or webhooks instead, as it provides better reliability for large files and avoids timeout issues.

*

The Split endpoint allows you to split documents into multiple parts using an existing splitter or an inline configuration.

- *

For more details, see the Split File guide.

+ *

For more details, see the Split File guide.

*/ public CompletableFuture> split(SplitRequest request) { return split(request, null); @@ -569,7 +686,7 @@ public CompletableFuture> split(SplitRequ * Split a document synchronously, waiting for the result before returning. This endpoint has a 5-minute timeout — if processing takes longer, the request will fail. *

Note: This endpoint is intended for onboarding and testing only. For production workloads, use POST /split_runs with polling or webhooks instead, as it provides better reliability for large files and avoids timeout issues.

*

The Split endpoint allows you to split documents into multiple parts using an existing splitter or an inline configuration.

- *

For more details, see the Split File guide.

+ *

For more details, see the Split File guide.

*/ public CompletableFuture> split( SplitRequest request, RequestOptions requestOptions) { diff --git a/src/main/java/ai/extend/ExtendClientBase.java b/src/main/java/ai/extend/ExtendClientBase.java index 1d17dc7..a037a99 100644 --- a/src/main/java/ai/extend/ExtendClientBase.java +++ b/src/main/java/ai/extend/ExtendClientBase.java @@ -7,6 +7,7 @@ import ai.extend.core.RequestOptions; import ai.extend.core.Suppliers; import ai.extend.requests.ClassifyRequest; +import ai.extend.requests.DetectFormRequest; import ai.extend.requests.EditRequest; import ai.extend.requests.ExtractRequest; import ai.extend.requests.ParseRequest; @@ -26,6 +27,7 @@ import ai.extend.resources.extractorversions.ExtractorVersionsClient; import ai.extend.resources.extractruns.ExtractRunsClient; import ai.extend.resources.files.FilesClient; +import ai.extend.resources.formdetectionruns.FormDetectionRunsClient; import ai.extend.resources.parseruns.ParseRunsClient; import ai.extend.resources.processor.ProcessorClient; import ai.extend.resources.processorrun.ProcessorRunClient; @@ -41,6 +43,7 @@ import ai.extend.types.ClassifyRun; import ai.extend.types.EditRun; import ai.extend.types.ExtractRun; +import ai.extend.types.FormDetectionRun; import ai.extend.types.ParseRun; import ai.extend.types.SplitRun; import java.util.function.Supplier; @@ -60,6 +63,8 @@ public class ExtendClientBase { protected final Supplier editSchemasClient; + protected final Supplier formDetectionRunsClient; + protected final Supplier extractRunsClient; protected final Supplier extractorsClient; @@ -112,6 +117,7 @@ public ExtendClientBase(ClientOptions clientOptions) { this.editRunsClient = Suppliers.memoize(() -> new EditRunsClient(clientOptions)); this.editTemplatesClient = Suppliers.memoize(() -> new EditTemplatesClient(clientOptions)); this.editSchemasClient = Suppliers.memoize(() -> new EditSchemasClient(clientOptions)); + this.formDetectionRunsClient = Suppliers.memoize(() -> new FormDetectionRunsClient(clientOptions)); this.extractRunsClient = Suppliers.memoize(() -> new ExtractRunsClient(clientOptions)); this.extractorsClient = Suppliers.memoize(() -> new ExtractorsClient(clientOptions)); this.extractorVersionsClient = Suppliers.memoize(() -> new ExtractorVersionsClient(clientOptions)); @@ -167,7 +173,7 @@ public ParseRun parse(ParseRequest request, RequestOptions requestOptions) { * Edit a file synchronously, waiting for the result before returning. This endpoint has a 5-minute timeout — if processing takes longer, the request will fail. *

Note: This endpoint is intended for onboarding and testing only. For production workloads, use POST /edit_runs with polling or webhooks instead, as it provides better reliability for large files and avoids timeout issues.

*

The Edit endpoint allows you to detect and fill form fields in PDF documents.

- *

For more details, see the Edit File guide.

+ *

For more details, see the Edit File guide. See Editing Error Handling for HTTP errors and run failure reasons.

*/ public EditRun edit(EditRequest request) { return this.rawClient.edit(request).body(); @@ -177,12 +183,28 @@ public EditRun edit(EditRequest request) { * Edit a file synchronously, waiting for the result before returning. This endpoint has a 5-minute timeout — if processing takes longer, the request will fail. *

Note: This endpoint is intended for onboarding and testing only. For production workloads, use POST /edit_runs with polling or webhooks instead, as it provides better reliability for large files and avoids timeout issues.

*

The Edit endpoint allows you to detect and fill form fields in PDF documents.

- *

For more details, see the Edit File guide.

+ *

For more details, see the Edit File guide. See Editing Error Handling for HTTP errors and run failure reasons.

*/ public EditRun edit(EditRequest request, RequestOptions requestOptions) { return this.rawClient.edit(request, requestOptions).body(); } + /** + * Detect fields in a PDF form and wait for the generated edit schema before returning. This endpoint has a 5-minute timeout. + *

For production workloads, use POST /form_detection_runs and poll GET /form_detection_runs/{id} instead. The response is a completed form_detection_run; its output.schema can be passed directly to POST /edit or POST /edit_runs.

+ */ + public FormDetectionRun detectForm(DetectFormRequest request) { + return this.rawClient.detectForm(request).body(); + } + + /** + * Detect fields in a PDF form and wait for the generated edit schema before returning. This endpoint has a 5-minute timeout. + *

For production workloads, use POST /form_detection_runs and poll GET /form_detection_runs/{id} instead. The response is a completed form_detection_run; its output.schema can be passed directly to POST /edit or POST /edit_runs.

+ */ + public FormDetectionRun detectForm(DetectFormRequest request, RequestOptions requestOptions) { + return this.rawClient.detectForm(request, requestOptions).body(); + } + /** * Extract structured data from a file synchronously, waiting for the result before returning. This endpoint has a 5-minute timeout — if processing takes longer, the request will fail. *

Note: This endpoint is intended for onboarding and testing only. For production workloads, use POST /extract_runs with polling or webhooks instead, as it provides better reliability for large files and avoids timeout issues.

@@ -231,7 +253,7 @@ public ExtractRun extract(ExtractRequest request, RequestOptions requestOptions) * Classify a document synchronously, waiting for the result before returning. This endpoint has a 5-minute timeout — if processing takes longer, the request will fail. *

Note: This endpoint is intended for onboarding and testing only. For production workloads, use POST /classify_runs with polling or webhooks instead, as it provides better reliability for large files and avoids timeout issues.

*

The Classify endpoint allows you to classify documents using an existing classifier or an inline configuration.

- *

For more details, see the Classify File guide.

+ *

For more details, see the Classify File guide.

*/ public ClassifyRun classify(ClassifyRequest request) { return this.rawClient.classify(request).body(); @@ -241,7 +263,7 @@ public ClassifyRun classify(ClassifyRequest request) { * Classify a document synchronously, waiting for the result before returning. This endpoint has a 5-minute timeout — if processing takes longer, the request will fail. *

Note: This endpoint is intended for onboarding and testing only. For production workloads, use POST /classify_runs with polling or webhooks instead, as it provides better reliability for large files and avoids timeout issues.

*

The Classify endpoint allows you to classify documents using an existing classifier or an inline configuration.

- *

For more details, see the Classify File guide.

+ *

For more details, see the Classify File guide.

*/ public ClassifyRun classify(ClassifyRequest request, RequestOptions requestOptions) { return this.rawClient.classify(request, requestOptions).body(); @@ -251,7 +273,7 @@ public ClassifyRun classify(ClassifyRequest request, RequestOptions requestOptio * Split a document synchronously, waiting for the result before returning. This endpoint has a 5-minute timeout — if processing takes longer, the request will fail. *

Note: This endpoint is intended for onboarding and testing only. For production workloads, use POST /split_runs with polling or webhooks instead, as it provides better reliability for large files and avoids timeout issues.

*

The Split endpoint allows you to split documents into multiple parts using an existing splitter or an inline configuration.

- *

For more details, see the Split File guide.

+ *

For more details, see the Split File guide.

*/ public SplitRun split(SplitRequest request) { return this.rawClient.split(request).body(); @@ -261,7 +283,7 @@ public SplitRun split(SplitRequest request) { * Split a document synchronously, waiting for the result before returning. This endpoint has a 5-minute timeout — if processing takes longer, the request will fail. *

Note: This endpoint is intended for onboarding and testing only. For production workloads, use POST /split_runs with polling or webhooks instead, as it provides better reliability for large files and avoids timeout issues.

*

The Split endpoint allows you to split documents into multiple parts using an existing splitter or an inline configuration.

- *

For more details, see the Split File guide.

+ *

For more details, see the Split File guide.

*/ public SplitRun split(SplitRequest request, RequestOptions requestOptions) { return this.rawClient.split(request, requestOptions).body(); @@ -287,6 +309,10 @@ public EditSchemasClient editSchemas() { return this.editSchemasClient.get(); } + public FormDetectionRunsClient formDetectionRuns() { + return this.formDetectionRunsClient.get(); + } + public ExtractRunsClient extractRuns() { return this.extractRunsClient.get(); } diff --git a/src/main/java/ai/extend/RawExtendClientBase.java b/src/main/java/ai/extend/RawExtendClientBase.java index 5f7909e..c506aba 100644 --- a/src/main/java/ai/extend/RawExtendClientBase.java +++ b/src/main/java/ai/extend/RawExtendClientBase.java @@ -20,6 +20,7 @@ import ai.extend.errors.UnauthorizedError; import ai.extend.errors.UnprocessableEntityError; import ai.extend.requests.ClassifyRequest; +import ai.extend.requests.DetectFormRequest; import ai.extend.requests.EditRequest; import ai.extend.requests.ExtractRequest; import ai.extend.requests.ParseRequest; @@ -28,6 +29,7 @@ import ai.extend.types.ClassifyRun; import ai.extend.types.EditRun; import ai.extend.types.ExtractRun; +import ai.extend.types.FormDetectionRun; import ai.extend.types.ParseRun; import ai.extend.types.SplitRun; import com.fasterxml.jackson.core.JsonProcessingException; @@ -147,7 +149,7 @@ public ExtendClientBaseHttpResponse parse(ParseRequest request, Reques * Edit a file synchronously, waiting for the result before returning. This endpoint has a 5-minute timeout — if processing takes longer, the request will fail. *

Note: This endpoint is intended for onboarding and testing only. For production workloads, use POST /edit_runs with polling or webhooks instead, as it provides better reliability for large files and avoids timeout issues.

*

The Edit endpoint allows you to detect and fill form fields in PDF documents.

- *

For more details, see the Edit File guide.

+ *

For more details, see the Edit File guide. See Editing Error Handling for HTTP errors and run failure reasons.

*/ public ExtendClientBaseHttpResponse edit(EditRequest request) { return edit(request, null); @@ -157,7 +159,7 @@ public ExtendClientBaseHttpResponse edit(EditRequest request) { * Edit a file synchronously, waiting for the result before returning. This endpoint has a 5-minute timeout — if processing takes longer, the request will fail. *

Note: This endpoint is intended for onboarding and testing only. For production workloads, use POST /edit_runs with polling or webhooks instead, as it provides better reliability for large files and avoids timeout issues.

*

The Edit endpoint allows you to detect and fill form fields in PDF documents.

- *

For more details, see the Edit File guide.

+ *

For more details, see the Edit File guide. See Editing Error Handling for HTTP errors and run failure reasons.

*/ public ExtendClientBaseHttpResponse edit(EditRequest request, RequestOptions requestOptions) { HttpUrl.Builder httpUrl = HttpUrl.parse(this.clientOptions.environment().getUrl()) @@ -231,6 +233,91 @@ public ExtendClientBaseHttpResponse edit(EditRequest request, RequestOp } } + /** + * Detect fields in a PDF form and wait for the generated edit schema before returning. This endpoint has a 5-minute timeout. + *

For production workloads, use POST /form_detection_runs and poll GET /form_detection_runs/{id} instead. The response is a completed form_detection_run; its output.schema can be passed directly to POST /edit or POST /edit_runs.

+ */ + public ExtendClientBaseHttpResponse detectForm(DetectFormRequest request) { + return detectForm(request, null); + } + + /** + * Detect fields in a PDF form and wait for the generated edit schema before returning. This endpoint has a 5-minute timeout. + *

For production workloads, use POST /form_detection_runs and poll GET /form_detection_runs/{id} instead. The response is a completed form_detection_run; its output.schema can be passed directly to POST /edit or POST /edit_runs.

+ */ + public ExtendClientBaseHttpResponse detectForm( + DetectFormRequest request, RequestOptions requestOptions) { + HttpUrl.Builder httpUrl = HttpUrl.parse(this.clientOptions.environment().getUrl()) + .newBuilder() + .addPathSegments("detect_form"); + if (requestOptions != null) { + requestOptions.getQueryParameters().forEach((_key, _value) -> { + httpUrl.addQueryParameter(_key, _value); + }); + } + RequestBody body; + try { + body = RequestBody.create( + ObjectMappers.JSON_MAPPER.writeValueAsBytes(request), MediaTypes.APPLICATION_JSON); + } catch (JsonProcessingException e) { + throw new ExtendClientException("Failed to serialize request", e); + } + Request okhttpRequest = new Request.Builder() + .url(httpUrl.build()) + .method("POST", body) + .headers(Headers.of(clientOptions.headers(requestOptions))) + .addHeader("Content-Type", "application/json") + .addHeader("Accept", "application/json") + .build(); + OkHttpClient client = clientOptions.httpClient(); + if (requestOptions != null && requestOptions.getTimeout().isPresent()) { + client = clientOptions.httpClientWithTimeout(requestOptions); + } + try (Response response = client.newCall(okhttpRequest).execute()) { + ResponseBody responseBody = response.body(); + String responseBodyString = responseBody != null ? responseBody.string() : "{}"; + if (response.isSuccessful()) { + return new ExtendClientBaseHttpResponse<>( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, FormDetectionRun.class), response); + } + try { + switch (response.code()) { + case 400: + throw new BadRequestError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, Object.class), response); + case 401: + throw new UnauthorizedError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, Object.class), response); + case 402: + throw new PaymentRequiredError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, ApiError.class), response); + case 403: + throw new ForbiddenError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, ApiError.class), response); + case 404: + throw new NotFoundError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, Object.class), response); + case 422: + throw new UnprocessableEntityError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, ApiError.class), response); + case 429: + throw new TooManyRequestsError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, Object.class), response); + case 500: + throw new InternalServerError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, Object.class), response); + } + } catch (JsonProcessingException ignored) { + // unable to map error response, throwing generic error + } + Object errorBody = ObjectMappers.parseErrorBody(responseBodyString); + throw new ExtendClientApiException( + "Error with status code " + response.code(), response.code(), errorBody, response); + } catch (IOException e) { + throw new ExtendClientException("Network error executing HTTP request", e); + } + } + /** * Extract structured data from a file synchronously, waiting for the result before returning. This endpoint has a 5-minute timeout — if processing takes longer, the request will fail. *

Note: This endpoint is intended for onboarding and testing only. For production workloads, use POST /extract_runs with polling or webhooks instead, as it provides better reliability for large files and avoids timeout issues.

@@ -347,7 +434,7 @@ public ExtendClientBaseHttpResponse extract(ExtractRequest request, * Classify a document synchronously, waiting for the result before returning. This endpoint has a 5-minute timeout — if processing takes longer, the request will fail. *

Note: This endpoint is intended for onboarding and testing only. For production workloads, use POST /classify_runs with polling or webhooks instead, as it provides better reliability for large files and avoids timeout issues.

*

The Classify endpoint allows you to classify documents using an existing classifier or an inline configuration.

- *

For more details, see the Classify File guide.

+ *

For more details, see the Classify File guide.

*/ public ExtendClientBaseHttpResponse classify(ClassifyRequest request) { return classify(request, null); @@ -357,7 +444,7 @@ public ExtendClientBaseHttpResponse classify(ClassifyRequest reques * Classify a document synchronously, waiting for the result before returning. This endpoint has a 5-minute timeout — if processing takes longer, the request will fail. *

Note: This endpoint is intended for onboarding and testing only. For production workloads, use POST /classify_runs with polling or webhooks instead, as it provides better reliability for large files and avoids timeout issues.

*

The Classify endpoint allows you to classify documents using an existing classifier or an inline configuration.

- *

For more details, see the Classify File guide.

+ *

For more details, see the Classify File guide.

*/ public ExtendClientBaseHttpResponse classify(ClassifyRequest request, RequestOptions requestOptions) { HttpUrl.Builder httpUrl = HttpUrl.parse(this.clientOptions.environment().getUrl()) @@ -435,7 +522,7 @@ public ExtendClientBaseHttpResponse classify(ClassifyRequest reques * Split a document synchronously, waiting for the result before returning. This endpoint has a 5-minute timeout — if processing takes longer, the request will fail. *

Note: This endpoint is intended for onboarding and testing only. For production workloads, use POST /split_runs with polling or webhooks instead, as it provides better reliability for large files and avoids timeout issues.

*

The Split endpoint allows you to split documents into multiple parts using an existing splitter or an inline configuration.

- *

For more details, see the Split File guide.

+ *

For more details, see the Split File guide.

*/ public ExtendClientBaseHttpResponse split(SplitRequest request) { return split(request, null); @@ -445,7 +532,7 @@ public ExtendClientBaseHttpResponse split(SplitRequest request) { * Split a document synchronously, waiting for the result before returning. This endpoint has a 5-minute timeout — if processing takes longer, the request will fail. *

Note: This endpoint is intended for onboarding and testing only. For production workloads, use POST /split_runs with polling or webhooks instead, as it provides better reliability for large files and avoids timeout issues.

*

The Split endpoint allows you to split documents into multiple parts using an existing splitter or an inline configuration.

- *

For more details, see the Split File guide.

+ *

For more details, see the Split File guide.

*/ public ExtendClientBaseHttpResponse split(SplitRequest request, RequestOptions requestOptions) { HttpUrl.Builder httpUrl = HttpUrl.parse(this.clientOptions.environment().getUrl()) diff --git a/src/main/java/ai/extend/core/ClientOptions.java b/src/main/java/ai/extend/core/ClientOptions.java index 4ed2c6a..43e09a5 100644 --- a/src/main/java/ai/extend/core/ClientOptions.java +++ b/src/main/java/ai/extend/core/ClientOptions.java @@ -35,10 +35,10 @@ private ClientOptions( this.headers.putAll(headers); this.headers.putAll(new HashMap() { { - put("User-Agent", "ai.extend:extend-java-sdk/1.16.0"); + put("User-Agent", "ai.extend:extend-java-sdk/1.17.0"); put("X-Fern-Language", "JAVA"); put("X-Fern-SDK-Name", "com.extendconfig.fern:api-sdk"); - put("X-Fern-SDK-Version", "1.16.0"); + put("X-Fern-SDK-Version", "1.17.0"); } }); this.headerSuppliers = headerSuppliers; diff --git a/src/main/java/ai/extend/requests/DetectFormRequest.java b/src/main/java/ai/extend/requests/DetectFormRequest.java new file mode 100644 index 0000000..787cf05 --- /dev/null +++ b/src/main/java/ai/extend/requests/DetectFormRequest.java @@ -0,0 +1,148 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package ai.extend.requests; + +import ai.extend.core.ObjectMappers; +import ai.extend.types.DetectFormRequestFile; +import ai.extend.types.EditSchemaGenerationConfig; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.annotation.Nulls; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import org.jetbrains.annotations.NotNull; + +@JsonInclude(JsonInclude.Include.NON_ABSENT) +@JsonDeserialize(builder = DetectFormRequest.Builder.class) +public final class DetectFormRequest { + private final DetectFormRequestFile file; + + private final Optional config; + + private final Map additionalProperties; + + private DetectFormRequest( + DetectFormRequestFile file, + Optional config, + Map additionalProperties) { + this.file = file; + this.config = config; + this.additionalProperties = additionalProperties; + } + + /** + * @return The PDF form to analyze. Files can be provided as a URL or an Extend file ID. + */ + @JsonProperty("file") + public DetectFormRequestFile getFile() { + return file; + } + + @JsonProperty("config") + public Optional getConfig() { + return config; + } + + @java.lang.Override + public boolean equals(Object other) { + if (this == other) return true; + return other instanceof DetectFormRequest && equalTo((DetectFormRequest) other); + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + private boolean equalTo(DetectFormRequest other) { + return file.equals(other.file) && config.equals(other.config); + } + + @java.lang.Override + public int hashCode() { + return Objects.hash(this.file, this.config); + } + + @java.lang.Override + public String toString() { + return ObjectMappers.stringify(this); + } + + public static FileStage builder() { + return new Builder(); + } + + public interface FileStage { + /** + *

The PDF form to analyze. Files can be provided as a URL or an Extend file ID.

+ */ + _FinalStage file(@NotNull DetectFormRequestFile file); + + Builder from(DetectFormRequest other); + } + + public interface _FinalStage { + DetectFormRequest build(); + + _FinalStage config(Optional config); + + _FinalStage config(EditSchemaGenerationConfig config); + } + + @JsonIgnoreProperties(ignoreUnknown = true) + public static final class Builder implements FileStage, _FinalStage { + private DetectFormRequestFile file; + + private Optional config = Optional.empty(); + + @JsonAnySetter + private Map additionalProperties = new HashMap<>(); + + private Builder() {} + + @java.lang.Override + public Builder from(DetectFormRequest other) { + file(other.getFile()); + config(other.getConfig()); + return this; + } + + /** + *

The PDF form to analyze. Files can be provided as a URL or an Extend file ID.

+ *

The PDF form to analyze. Files can be provided as a URL or an Extend file ID.

+ * @return Reference to {@code this} so that method calls can be chained together. + */ + @java.lang.Override + @JsonSetter("file") + public _FinalStage file(@NotNull DetectFormRequestFile file) { + this.file = Objects.requireNonNull(file, "file must not be null"); + return this; + } + + @java.lang.Override + public _FinalStage config(EditSchemaGenerationConfig config) { + this.config = Optional.ofNullable(config); + return this; + } + + @java.lang.Override + @JsonSetter(value = "config", nulls = Nulls.SKIP) + public _FinalStage config(Optional config) { + this.config = config; + return this; + } + + @java.lang.Override + public DetectFormRequest build() { + return new DetectFormRequest(file, config, additionalProperties); + } + } +} diff --git a/src/main/java/ai/extend/requests/ParseRequest.java b/src/main/java/ai/extend/requests/ParseRequest.java index f474009..0ae7cb4 100644 --- a/src/main/java/ai/extend/requests/ParseRequest.java +++ b/src/main/java/ai/extend/requests/ParseRequest.java @@ -4,6 +4,7 @@ package ai.extend.requests; import ai.extend.core.ObjectMappers; +import ai.extend.types.DataRetention; import ai.extend.types.ParseConfig; import ai.extend.types.ParseRequestFile; import ai.extend.types.ParseRequestResponseType; @@ -35,6 +36,8 @@ public final class ParseRequest { private final Optional> metadata; + private final Optional dataRetention; + private final Map additionalProperties; private ParseRequest( @@ -43,12 +46,14 @@ private ParseRequest( ParseRequestFile file, Optional config, Optional> metadata, + Optional dataRetention, Map additionalProperties) { this.extendWorkspaceId = extendWorkspaceId; this.responseType = responseType; this.file = file; this.config = config; this.metadata = metadata; + this.dataRetention = dataRetention; this.additionalProperties = additionalProperties; } @@ -90,6 +95,11 @@ public Optional> getMetadata() { return metadata; } + @JsonProperty("dataRetention") + public Optional getDataRetention() { + return dataRetention; + } + @java.lang.Override public boolean equals(Object other) { if (this == other) return true; @@ -106,12 +116,14 @@ private boolean equalTo(ParseRequest other) { && responseType.equals(other.responseType) && file.equals(other.file) && config.equals(other.config) - && metadata.equals(other.metadata); + && metadata.equals(other.metadata) + && dataRetention.equals(other.dataRetention); } @java.lang.Override public int hashCode() { - return Objects.hash(this.extendWorkspaceId, this.responseType, this.file, this.config, this.metadata); + return Objects.hash( + this.extendWorkspaceId, this.responseType, this.file, this.config, this.metadata, this.dataRetention); } @java.lang.Override @@ -160,12 +172,18 @@ public interface _FinalStage { _FinalStage metadata(Optional> metadata); _FinalStage metadata(Map metadata); + + _FinalStage dataRetention(Optional dataRetention); + + _FinalStage dataRetention(DataRetention dataRetention); } @JsonIgnoreProperties(ignoreUnknown = true) public static final class Builder implements FileStage, _FinalStage { private ParseRequestFile file; + private Optional dataRetention = Optional.empty(); + private Optional> metadata = Optional.empty(); private Optional config = Optional.empty(); @@ -186,6 +204,7 @@ public Builder from(ParseRequest other) { file(other.getFile()); config(other.getConfig()); metadata(other.getMetadata()); + dataRetention(other.getDataRetention()); return this; } @@ -201,6 +220,19 @@ public _FinalStage file(@NotNull ParseRequestFile file) { return this; } + @java.lang.Override + public _FinalStage dataRetention(DataRetention dataRetention) { + this.dataRetention = Optional.ofNullable(dataRetention); + return this; + } + + @java.lang.Override + @JsonSetter(value = "dataRetention", nulls = Nulls.SKIP) + public _FinalStage dataRetention(Optional dataRetention) { + this.dataRetention = dataRetention; + return this; + } + @java.lang.Override public _FinalStage metadata(Map metadata) { this.metadata = Optional.ofNullable(metadata); @@ -276,7 +308,8 @@ public _FinalStage extendWorkspaceId(Optional extendWorkspaceId) { @java.lang.Override public ParseRequest build() { - return new ParseRequest(extendWorkspaceId, responseType, file, config, metadata, additionalProperties); + return new ParseRequest( + extendWorkspaceId, responseType, file, config, metadata, dataRetention, additionalProperties); } } } diff --git a/src/main/java/ai/extend/resources/editschemas/AsyncEditSchemasClient.java b/src/main/java/ai/extend/resources/editschemas/AsyncEditSchemasClient.java index 330ce6a..27cf4de 100644 --- a/src/main/java/ai/extend/resources/editschemas/AsyncEditSchemasClient.java +++ b/src/main/java/ai/extend/resources/editschemas/AsyncEditSchemasClient.java @@ -27,20 +27,22 @@ public AsyncRawEditSchemasClient withRawResponse() { } /** - * Detect fields in a PDF form and synchronously return an edit schema payload. + * Deprecated: Use POST /detect_form for synchronous form detection or POST /form_detection_runs for asynchronous processing. + *

Detect fields in a PDF form and synchronously return an edit schema payload.

*

Use this endpoint when you want Extend to bootstrap an EditRootJSON schema from an existing form, optionally mapping an existing schema onto the detected fields.

*

This endpoint returns the generated schema directly. There are no schema generation run resources to poll or delete.

- *

For more details, see the Generate Edit Schema guide and the Edit File guide.

+ *

For more details, see the Detect Form guide and the Edit File guide.

*/ public CompletableFuture generate(EditSchemasGenerateRequest request) { return this.rawClient.generate(request).thenApply(response -> response.body()); } /** - * Detect fields in a PDF form and synchronously return an edit schema payload. + * Deprecated: Use POST /detect_form for synchronous form detection or POST /form_detection_runs for asynchronous processing. + *

Detect fields in a PDF form and synchronously return an edit schema payload.

*

Use this endpoint when you want Extend to bootstrap an EditRootJSON schema from an existing form, optionally mapping an existing schema onto the detected fields.

*

This endpoint returns the generated schema directly. There are no schema generation run resources to poll or delete.

- *

For more details, see the Generate Edit Schema guide and the Edit File guide.

+ *

For more details, see the Detect Form guide and the Edit File guide.

*/ public CompletableFuture generate( EditSchemasGenerateRequest request, RequestOptions requestOptions) { diff --git a/src/main/java/ai/extend/resources/editschemas/AsyncRawEditSchemasClient.java b/src/main/java/ai/extend/resources/editschemas/AsyncRawEditSchemasClient.java index 04fd355..9f99d1f 100644 --- a/src/main/java/ai/extend/resources/editschemas/AsyncRawEditSchemasClient.java +++ b/src/main/java/ai/extend/resources/editschemas/AsyncRawEditSchemasClient.java @@ -43,10 +43,11 @@ public AsyncRawEditSchemasClient(ClientOptions clientOptions) { } /** - * Detect fields in a PDF form and synchronously return an edit schema payload. + * Deprecated: Use POST /detect_form for synchronous form detection or POST /form_detection_runs for asynchronous processing. + *

Detect fields in a PDF form and synchronously return an edit schema payload.

*

Use this endpoint when you want Extend to bootstrap an EditRootJSON schema from an existing form, optionally mapping an existing schema onto the detected fields.

*

This endpoint returns the generated schema directly. There are no schema generation run resources to poll or delete.

- *

For more details, see the Generate Edit Schema guide and the Edit File guide.

+ *

For more details, see the Detect Form guide and the Edit File guide.

*/ public CompletableFuture> generate( EditSchemasGenerateRequest request) { @@ -54,10 +55,11 @@ public CompletableFutureDeprecated: Use POST /detect_form for synchronous form detection or POST /form_detection_runs for asynchronous processing. + *

Detect fields in a PDF form and synchronously return an edit schema payload.

*

Use this endpoint when you want Extend to bootstrap an EditRootJSON schema from an existing form, optionally mapping an existing schema onto the detected fields.

*

This endpoint returns the generated schema directly. There are no schema generation run resources to poll or delete.

- *

For more details, see the Generate Edit Schema guide and the Edit File guide.

+ *

For more details, see the Detect Form guide and the Edit File guide.

*/ public CompletableFuture> generate( EditSchemasGenerateRequest request, RequestOptions requestOptions) { diff --git a/src/main/java/ai/extend/resources/editschemas/EditSchemasClient.java b/src/main/java/ai/extend/resources/editschemas/EditSchemasClient.java index 5eeaecc..9dc26ff 100644 --- a/src/main/java/ai/extend/resources/editschemas/EditSchemasClient.java +++ b/src/main/java/ai/extend/resources/editschemas/EditSchemasClient.java @@ -26,20 +26,22 @@ public RawEditSchemasClient withRawResponse() { } /** - * Detect fields in a PDF form and synchronously return an edit schema payload. + * Deprecated: Use POST /detect_form for synchronous form detection or POST /form_detection_runs for asynchronous processing. + *

Detect fields in a PDF form and synchronously return an edit schema payload.

*

Use this endpoint when you want Extend to bootstrap an EditRootJSON schema from an existing form, optionally mapping an existing schema onto the detected fields.

*

This endpoint returns the generated schema directly. There are no schema generation run resources to poll or delete.

- *

For more details, see the Generate Edit Schema guide and the Edit File guide.

+ *

For more details, see the Detect Form guide and the Edit File guide.

*/ public EditSchemaGenerationResponse generate(EditSchemasGenerateRequest request) { return this.rawClient.generate(request).body(); } /** - * Detect fields in a PDF form and synchronously return an edit schema payload. + * Deprecated: Use POST /detect_form for synchronous form detection or POST /form_detection_runs for asynchronous processing. + *

Detect fields in a PDF form and synchronously return an edit schema payload.

*

Use this endpoint when you want Extend to bootstrap an EditRootJSON schema from an existing form, optionally mapping an existing schema onto the detected fields.

*

This endpoint returns the generated schema directly. There are no schema generation run resources to poll or delete.

- *

For more details, see the Generate Edit Schema guide and the Edit File guide.

+ *

For more details, see the Detect Form guide and the Edit File guide.

*/ public EditSchemaGenerationResponse generate(EditSchemasGenerateRequest request, RequestOptions requestOptions) { return this.rawClient.generate(request, requestOptions).body(); diff --git a/src/main/java/ai/extend/resources/editschemas/RawEditSchemasClient.java b/src/main/java/ai/extend/resources/editschemas/RawEditSchemasClient.java index 1f5bbab..1630761 100644 --- a/src/main/java/ai/extend/resources/editschemas/RawEditSchemasClient.java +++ b/src/main/java/ai/extend/resources/editschemas/RawEditSchemasClient.java @@ -39,20 +39,22 @@ public RawEditSchemasClient(ClientOptions clientOptions) { } /** - * Detect fields in a PDF form and synchronously return an edit schema payload. + * Deprecated: Use POST /detect_form for synchronous form detection or POST /form_detection_runs for asynchronous processing. + *

Detect fields in a PDF form and synchronously return an edit schema payload.

*

Use this endpoint when you want Extend to bootstrap an EditRootJSON schema from an existing form, optionally mapping an existing schema onto the detected fields.

*

This endpoint returns the generated schema directly. There are no schema generation run resources to poll or delete.

- *

For more details, see the Generate Edit Schema guide and the Edit File guide.

+ *

For more details, see the Detect Form guide and the Edit File guide.

*/ public ExtendClientBaseHttpResponse generate(EditSchemasGenerateRequest request) { return generate(request, null); } /** - * Detect fields in a PDF form and synchronously return an edit schema payload. + * Deprecated: Use POST /detect_form for synchronous form detection or POST /form_detection_runs for asynchronous processing. + *

Detect fields in a PDF form and synchronously return an edit schema payload.

*

Use this endpoint when you want Extend to bootstrap an EditRootJSON schema from an existing form, optionally mapping an existing schema onto the detected fields.

*

This endpoint returns the generated schema directly. There are no schema generation run resources to poll or delete.

- *

For more details, see the Generate Edit Schema guide and the Edit File guide.

+ *

For more details, see the Detect Form guide and the Edit File guide.

*/ public ExtendClientBaseHttpResponse generate( EditSchemasGenerateRequest request, RequestOptions requestOptions) { diff --git a/src/main/java/ai/extend/resources/edittemplates/AsyncEditTemplatesClient.java b/src/main/java/ai/extend/resources/edittemplates/AsyncEditTemplatesClient.java index 206afb6..443070c 100644 --- a/src/main/java/ai/extend/resources/edittemplates/AsyncEditTemplatesClient.java +++ b/src/main/java/ai/extend/resources/edittemplates/AsyncEditTemplatesClient.java @@ -28,7 +28,7 @@ public AsyncRawEditTemplatesClient withRawResponse() { /** * Retrieve a saved edit template by ID. - *

Use this endpoint to inspect the source file, default edit configuration, and optional schema generation configuration saved on an edit template. You can reuse the returned config with POST /edit or POST /edit_runs, and reuse schemaConfig with POST /edit_schemas/generate.

+ *

Use this endpoint to inspect the source file, default edit configuration, and optional schema generation configuration saved on an edit template. You can reuse the returned config with POST /edit or POST /edit_runs, and reuse schemaConfig with POST /detect_form or POST /form_detection_runs.

*/ public CompletableFuture retrieve(String id) { return this.rawClient.retrieve(id).thenApply(response -> response.body()); @@ -36,7 +36,7 @@ public CompletableFuture retrieve(String id) { /** * Retrieve a saved edit template by ID. - *

Use this endpoint to inspect the source file, default edit configuration, and optional schema generation configuration saved on an edit template. You can reuse the returned config with POST /edit or POST /edit_runs, and reuse schemaConfig with POST /edit_schemas/generate.

+ *

Use this endpoint to inspect the source file, default edit configuration, and optional schema generation configuration saved on an edit template. You can reuse the returned config with POST /edit or POST /edit_runs, and reuse schemaConfig with POST /detect_form or POST /form_detection_runs.

*/ public CompletableFuture retrieve(String id, RequestOptions requestOptions) { return this.rawClient.retrieve(id, requestOptions).thenApply(response -> response.body()); @@ -44,7 +44,7 @@ public CompletableFuture retrieve(String id, RequestOptions reques /** * Retrieve a saved edit template by ID. - *

Use this endpoint to inspect the source file, default edit configuration, and optional schema generation configuration saved on an edit template. You can reuse the returned config with POST /edit or POST /edit_runs, and reuse schemaConfig with POST /edit_schemas/generate.

+ *

Use this endpoint to inspect the source file, default edit configuration, and optional schema generation configuration saved on an edit template. You can reuse the returned config with POST /edit or POST /edit_runs, and reuse schemaConfig with POST /detect_form or POST /form_detection_runs.

*/ public CompletableFuture retrieve(String id, EditTemplatesRetrieveRequest request) { return this.rawClient.retrieve(id, request).thenApply(response -> response.body()); @@ -52,7 +52,7 @@ public CompletableFuture retrieve(String id, EditTemplatesRetrieve /** * Retrieve a saved edit template by ID. - *

Use this endpoint to inspect the source file, default edit configuration, and optional schema generation configuration saved on an edit template. You can reuse the returned config with POST /edit or POST /edit_runs, and reuse schemaConfig with POST /edit_schemas/generate.

+ *

Use this endpoint to inspect the source file, default edit configuration, and optional schema generation configuration saved on an edit template. You can reuse the returned config with POST /edit or POST /edit_runs, and reuse schemaConfig with POST /detect_form or POST /form_detection_runs.

*/ public CompletableFuture retrieve( String id, EditTemplatesRetrieveRequest request, RequestOptions requestOptions) { diff --git a/src/main/java/ai/extend/resources/edittemplates/AsyncRawEditTemplatesClient.java b/src/main/java/ai/extend/resources/edittemplates/AsyncRawEditTemplatesClient.java index a65fe86..ae6ba40 100644 --- a/src/main/java/ai/extend/resources/edittemplates/AsyncRawEditTemplatesClient.java +++ b/src/main/java/ai/extend/resources/edittemplates/AsyncRawEditTemplatesClient.java @@ -42,7 +42,7 @@ public AsyncRawEditTemplatesClient(ClientOptions clientOptions) { /** * Retrieve a saved edit template by ID. - *

Use this endpoint to inspect the source file, default edit configuration, and optional schema generation configuration saved on an edit template. You can reuse the returned config with POST /edit or POST /edit_runs, and reuse schemaConfig with POST /edit_schemas/generate.

+ *

Use this endpoint to inspect the source file, default edit configuration, and optional schema generation configuration saved on an edit template. You can reuse the returned config with POST /edit or POST /edit_runs, and reuse schemaConfig with POST /detect_form or POST /form_detection_runs.

*/ public CompletableFuture> retrieve(String id) { return retrieve(id, EditTemplatesRetrieveRequest.builder().build()); @@ -50,7 +50,7 @@ public CompletableFuture> retrieve(St /** * Retrieve a saved edit template by ID. - *

Use this endpoint to inspect the source file, default edit configuration, and optional schema generation configuration saved on an edit template. You can reuse the returned config with POST /edit or POST /edit_runs, and reuse schemaConfig with POST /edit_schemas/generate.

+ *

Use this endpoint to inspect the source file, default edit configuration, and optional schema generation configuration saved on an edit template. You can reuse the returned config with POST /edit or POST /edit_runs, and reuse schemaConfig with POST /detect_form or POST /form_detection_runs.

*/ public CompletableFuture> retrieve( String id, RequestOptions requestOptions) { @@ -59,7 +59,7 @@ public CompletableFuture> retrieve( /** * Retrieve a saved edit template by ID. - *

Use this endpoint to inspect the source file, default edit configuration, and optional schema generation configuration saved on an edit template. You can reuse the returned config with POST /edit or POST /edit_runs, and reuse schemaConfig with POST /edit_schemas/generate.

+ *

Use this endpoint to inspect the source file, default edit configuration, and optional schema generation configuration saved on an edit template. You can reuse the returned config with POST /edit or POST /edit_runs, and reuse schemaConfig with POST /detect_form or POST /form_detection_runs.

*/ public CompletableFuture> retrieve( String id, EditTemplatesRetrieveRequest request) { @@ -68,7 +68,7 @@ public CompletableFuture> retrieve( /** * Retrieve a saved edit template by ID. - *

Use this endpoint to inspect the source file, default edit configuration, and optional schema generation configuration saved on an edit template. You can reuse the returned config with POST /edit or POST /edit_runs, and reuse schemaConfig with POST /edit_schemas/generate.

+ *

Use this endpoint to inspect the source file, default edit configuration, and optional schema generation configuration saved on an edit template. You can reuse the returned config with POST /edit or POST /edit_runs, and reuse schemaConfig with POST /detect_form or POST /form_detection_runs.

*/ public CompletableFuture> retrieve( String id, EditTemplatesRetrieveRequest request, RequestOptions requestOptions) { diff --git a/src/main/java/ai/extend/resources/edittemplates/EditTemplatesClient.java b/src/main/java/ai/extend/resources/edittemplates/EditTemplatesClient.java index 6f7a2f0..46dd32d 100644 --- a/src/main/java/ai/extend/resources/edittemplates/EditTemplatesClient.java +++ b/src/main/java/ai/extend/resources/edittemplates/EditTemplatesClient.java @@ -27,7 +27,7 @@ public RawEditTemplatesClient withRawResponse() { /** * Retrieve a saved edit template by ID. - *

Use this endpoint to inspect the source file, default edit configuration, and optional schema generation configuration saved on an edit template. You can reuse the returned config with POST /edit or POST /edit_runs, and reuse schemaConfig with POST /edit_schemas/generate.

+ *

Use this endpoint to inspect the source file, default edit configuration, and optional schema generation configuration saved on an edit template. You can reuse the returned config with POST /edit or POST /edit_runs, and reuse schemaConfig with POST /detect_form or POST /form_detection_runs.

*/ public EditTemplate retrieve(String id) { return this.rawClient.retrieve(id).body(); @@ -35,7 +35,7 @@ public EditTemplate retrieve(String id) { /** * Retrieve a saved edit template by ID. - *

Use this endpoint to inspect the source file, default edit configuration, and optional schema generation configuration saved on an edit template. You can reuse the returned config with POST /edit or POST /edit_runs, and reuse schemaConfig with POST /edit_schemas/generate.

+ *

Use this endpoint to inspect the source file, default edit configuration, and optional schema generation configuration saved on an edit template. You can reuse the returned config with POST /edit or POST /edit_runs, and reuse schemaConfig with POST /detect_form or POST /form_detection_runs.

*/ public EditTemplate retrieve(String id, RequestOptions requestOptions) { return this.rawClient.retrieve(id, requestOptions).body(); @@ -43,7 +43,7 @@ public EditTemplate retrieve(String id, RequestOptions requestOptions) { /** * Retrieve a saved edit template by ID. - *

Use this endpoint to inspect the source file, default edit configuration, and optional schema generation configuration saved on an edit template. You can reuse the returned config with POST /edit or POST /edit_runs, and reuse schemaConfig with POST /edit_schemas/generate.

+ *

Use this endpoint to inspect the source file, default edit configuration, and optional schema generation configuration saved on an edit template. You can reuse the returned config with POST /edit or POST /edit_runs, and reuse schemaConfig with POST /detect_form or POST /form_detection_runs.

*/ public EditTemplate retrieve(String id, EditTemplatesRetrieveRequest request) { return this.rawClient.retrieve(id, request).body(); @@ -51,7 +51,7 @@ public EditTemplate retrieve(String id, EditTemplatesRetrieveRequest request) { /** * Retrieve a saved edit template by ID. - *

Use this endpoint to inspect the source file, default edit configuration, and optional schema generation configuration saved on an edit template. You can reuse the returned config with POST /edit or POST /edit_runs, and reuse schemaConfig with POST /edit_schemas/generate.

+ *

Use this endpoint to inspect the source file, default edit configuration, and optional schema generation configuration saved on an edit template. You can reuse the returned config with POST /edit or POST /edit_runs, and reuse schemaConfig with POST /detect_form or POST /form_detection_runs.

*/ public EditTemplate retrieve(String id, EditTemplatesRetrieveRequest request, RequestOptions requestOptions) { return this.rawClient.retrieve(id, request, requestOptions).body(); diff --git a/src/main/java/ai/extend/resources/edittemplates/RawEditTemplatesClient.java b/src/main/java/ai/extend/resources/edittemplates/RawEditTemplatesClient.java index f5fe64c..b7d48e1 100644 --- a/src/main/java/ai/extend/resources/edittemplates/RawEditTemplatesClient.java +++ b/src/main/java/ai/extend/resources/edittemplates/RawEditTemplatesClient.java @@ -38,7 +38,7 @@ public RawEditTemplatesClient(ClientOptions clientOptions) { /** * Retrieve a saved edit template by ID. - *

Use this endpoint to inspect the source file, default edit configuration, and optional schema generation configuration saved on an edit template. You can reuse the returned config with POST /edit or POST /edit_runs, and reuse schemaConfig with POST /edit_schemas/generate.

+ *

Use this endpoint to inspect the source file, default edit configuration, and optional schema generation configuration saved on an edit template. You can reuse the returned config with POST /edit or POST /edit_runs, and reuse schemaConfig with POST /detect_form or POST /form_detection_runs.

*/ public ExtendClientBaseHttpResponse retrieve(String id) { return retrieve(id, EditTemplatesRetrieveRequest.builder().build()); @@ -46,7 +46,7 @@ public ExtendClientBaseHttpResponse retrieve(String id) { /** * Retrieve a saved edit template by ID. - *

Use this endpoint to inspect the source file, default edit configuration, and optional schema generation configuration saved on an edit template. You can reuse the returned config with POST /edit or POST /edit_runs, and reuse schemaConfig with POST /edit_schemas/generate.

+ *

Use this endpoint to inspect the source file, default edit configuration, and optional schema generation configuration saved on an edit template. You can reuse the returned config with POST /edit or POST /edit_runs, and reuse schemaConfig with POST /detect_form or POST /form_detection_runs.

*/ public ExtendClientBaseHttpResponse retrieve(String id, RequestOptions requestOptions) { return retrieve(id, EditTemplatesRetrieveRequest.builder().build(), requestOptions); @@ -54,7 +54,7 @@ public ExtendClientBaseHttpResponse retrieve(String id, RequestOpt /** * Retrieve a saved edit template by ID. - *

Use this endpoint to inspect the source file, default edit configuration, and optional schema generation configuration saved on an edit template. You can reuse the returned config with POST /edit or POST /edit_runs, and reuse schemaConfig with POST /edit_schemas/generate.

+ *

Use this endpoint to inspect the source file, default edit configuration, and optional schema generation configuration saved on an edit template. You can reuse the returned config with POST /edit or POST /edit_runs, and reuse schemaConfig with POST /detect_form or POST /form_detection_runs.

*/ public ExtendClientBaseHttpResponse retrieve(String id, EditTemplatesRetrieveRequest request) { return retrieve(id, request, null); @@ -62,7 +62,7 @@ public ExtendClientBaseHttpResponse retrieve(String id, EditTempla /** * Retrieve a saved edit template by ID. - *

Use this endpoint to inspect the source file, default edit configuration, and optional schema generation configuration saved on an edit template. You can reuse the returned config with POST /edit or POST /edit_runs, and reuse schemaConfig with POST /edit_schemas/generate.

+ *

Use this endpoint to inspect the source file, default edit configuration, and optional schema generation configuration saved on an edit template. You can reuse the returned config with POST /edit or POST /edit_runs, and reuse schemaConfig with POST /detect_form or POST /form_detection_runs.

*/ public ExtendClientBaseHttpResponse retrieve( String id, EditTemplatesRetrieveRequest request, RequestOptions requestOptions) { diff --git a/src/main/java/ai/extend/resources/files/requests/FilesRetrieveRequest.java b/src/main/java/ai/extend/resources/files/requests/FilesRetrieveRequest.java index 56d0b11..300936a 100644 --- a/src/main/java/ai/extend/resources/files/requests/FilesRetrieveRequest.java +++ b/src/main/java/ai/extend/resources/files/requests/FilesRetrieveRequest.java @@ -53,7 +53,7 @@ public Optional getExtendWorkspaceId() { } /** - * @return Deprecated: Use POST /parse_runs instead to parse file contents. + * @return Deprecated: Use POST /parse_runs instead to parse file contents and get contents or GET /parse_runs/{id} to retrieve the results async if file is already parsed. Files parsed with versions >2.x will not support this parameter. *

If set to true, the raw text content of the file will be included in the response.

*/ @JsonProperty("rawText") @@ -62,7 +62,7 @@ public Optional getRawText() { } /** - * @return Deprecated: Use POST /parse_runs instead to parse file contents. + * @return Deprecated: Use POST /parse_runs instead to parse file contents and get contents or GET /parse_runs/{id} to retrieve the results async if file is already parsed. Files parsed with versions >2.x will not support this parameter. *

If set to true, the markdown content of the file will be included in the response.

*

Only available for files with a type of PDF, IMG, or DOCX files that were auto-converted to PDFs.

*/ @@ -72,7 +72,7 @@ public Optional getMarkdown() { } /** - * @return Deprecated: Use POST /parse_runs instead to parse file contents. + * @return Deprecated: Use POST /parse_runs instead to parse file contents and get contents or GET /parse_runs/{id} to retrieve the results async if file is already parsed. Files parsed with versions >2.x will not support this parameter. *

If set to true, the html content of the file will be included in the response.

*

Only available for files with a type of DOCX.

*/ @@ -150,7 +150,7 @@ public Builder extendWorkspaceId(String extendWorkspaceId) { } /** - *

Deprecated: Use POST /parse_runs instead to parse file contents.

+ *

Deprecated: Use POST /parse_runs instead to parse file contents and get contents or GET /parse_runs/{id} to retrieve the results async if file is already parsed. Files parsed with versions >2.x will not support this parameter.

*

If set to true, the raw text content of the file will be included in the response.

*/ @JsonSetter(value = "rawText", nulls = Nulls.SKIP) @@ -165,7 +165,7 @@ public Builder rawText(Boolean rawText) { } /** - *

Deprecated: Use POST /parse_runs instead to parse file contents.

+ *

Deprecated: Use POST /parse_runs instead to parse file contents and get contents or GET /parse_runs/{id} to retrieve the results async if file is already parsed. Files parsed with versions >2.x will not support this parameter.

*

If set to true, the markdown content of the file will be included in the response.

*

Only available for files with a type of PDF, IMG, or DOCX files that were auto-converted to PDFs.

*/ @@ -181,7 +181,7 @@ public Builder markdown(Boolean markdown) { } /** - *

Deprecated: Use POST /parse_runs instead to parse file contents.

+ *

Deprecated: Use POST /parse_runs instead to parse file contents and get contents or GET /parse_runs/{id} to retrieve the results async if file is already parsed. Files parsed with versions >2.x will not support this parameter.

*

If set to true, the html content of the file will be included in the response.

*

Only available for files with a type of DOCX.

*/ diff --git a/src/main/java/ai/extend/resources/formdetectionruns/AsyncFormDetectionRunsClient.java b/src/main/java/ai/extend/resources/formdetectionruns/AsyncFormDetectionRunsClient.java new file mode 100644 index 0000000..455dcd6 --- /dev/null +++ b/src/main/java/ai/extend/resources/formdetectionruns/AsyncFormDetectionRunsClient.java @@ -0,0 +1,79 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package ai.extend.resources.formdetectionruns; + +import ai.extend.core.ClientOptions; +import ai.extend.core.RequestOptions; +import ai.extend.resources.formdetectionruns.requests.FormDetectionRunsCreateRequest; +import ai.extend.resources.formdetectionruns.requests.FormDetectionRunsRetrieveRequest; +import ai.extend.types.FormDetectionRun; +import java.util.concurrent.CompletableFuture; + +public class AsyncFormDetectionRunsClient { + protected final ClientOptions clientOptions; + + private final AsyncRawFormDetectionRunsClient rawClient; + + public AsyncFormDetectionRunsClient(ClientOptions clientOptions) { + this.clientOptions = clientOptions; + this.rawClient = new AsyncRawFormDetectionRunsClient(clientOptions); + } + + /** + * Get responses with HTTP metadata like headers + */ + public AsyncRawFormDetectionRunsClient withRawResponse() { + return this.rawClient; + } + + /** + * Start detecting fields in a PDF form and return immediately with a form_detection_run resource, typically in the PROCESSING state. + *

Poll GET /form_detection_runs/{id} until the status is PROCESSED or FAILED. When processing succeeds, output.schema contains an edit schema you can pass directly to POST /edit or POST /edit_runs.

+ */ + public CompletableFuture create(FormDetectionRunsCreateRequest request) { + return this.rawClient.create(request).thenApply(response -> response.body()); + } + + /** + * Start detecting fields in a PDF form and return immediately with a form_detection_run resource, typically in the PROCESSING state. + *

Poll GET /form_detection_runs/{id} until the status is PROCESSED or FAILED. When processing succeeds, output.schema contains an edit schema you can pass directly to POST /edit or POST /edit_runs.

+ */ + public CompletableFuture create( + FormDetectionRunsCreateRequest request, RequestOptions requestOptions) { + return this.rawClient.create(request, requestOptions).thenApply(response -> response.body()); + } + + /** + * Retrieve the status and results of a form detection run. + *

Use this endpoint to poll a run created with POST /form_detection_runs. When status is PROCESSED, output.schema contains the generated edit schema.

+ */ + public CompletableFuture retrieve(String id) { + return this.rawClient.retrieve(id).thenApply(response -> response.body()); + } + + /** + * Retrieve the status and results of a form detection run. + *

Use this endpoint to poll a run created with POST /form_detection_runs. When status is PROCESSED, output.schema contains the generated edit schema.

+ */ + public CompletableFuture retrieve(String id, RequestOptions requestOptions) { + return this.rawClient.retrieve(id, requestOptions).thenApply(response -> response.body()); + } + + /** + * Retrieve the status and results of a form detection run. + *

Use this endpoint to poll a run created with POST /form_detection_runs. When status is PROCESSED, output.schema contains the generated edit schema.

+ */ + public CompletableFuture retrieve(String id, FormDetectionRunsRetrieveRequest request) { + return this.rawClient.retrieve(id, request).thenApply(response -> response.body()); + } + + /** + * Retrieve the status and results of a form detection run. + *

Use this endpoint to poll a run created with POST /form_detection_runs. When status is PROCESSED, output.schema contains the generated edit schema.

+ */ + public CompletableFuture retrieve( + String id, FormDetectionRunsRetrieveRequest request, RequestOptions requestOptions) { + return this.rawClient.retrieve(id, request, requestOptions).thenApply(response -> response.body()); + } +} diff --git a/src/main/java/ai/extend/resources/formdetectionruns/AsyncRawFormDetectionRunsClient.java b/src/main/java/ai/extend/resources/formdetectionruns/AsyncRawFormDetectionRunsClient.java new file mode 100644 index 0000000..acddace --- /dev/null +++ b/src/main/java/ai/extend/resources/formdetectionruns/AsyncRawFormDetectionRunsClient.java @@ -0,0 +1,291 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package ai.extend.resources.formdetectionruns; + +import ai.extend.core.ClientOptions; +import ai.extend.core.ExtendClientApiException; +import ai.extend.core.ExtendClientBaseHttpResponse; +import ai.extend.core.ExtendClientException; +import ai.extend.core.MediaTypes; +import ai.extend.core.ObjectMappers; +import ai.extend.core.RequestOptions; +import ai.extend.errors.BadRequestError; +import ai.extend.errors.ForbiddenError; +import ai.extend.errors.InternalServerError; +import ai.extend.errors.NotFoundError; +import ai.extend.errors.PaymentRequiredError; +import ai.extend.errors.TooManyRequestsError; +import ai.extend.errors.UnauthorizedError; +import ai.extend.errors.UnprocessableEntityError; +import ai.extend.resources.formdetectionruns.requests.FormDetectionRunsCreateRequest; +import ai.extend.resources.formdetectionruns.requests.FormDetectionRunsRetrieveRequest; +import ai.extend.types.ApiError; +import ai.extend.types.FormDetectionRun; +import com.fasterxml.jackson.core.JsonProcessingException; +import java.io.IOException; +import java.util.concurrent.CompletableFuture; +import okhttp3.Call; +import okhttp3.Callback; +import okhttp3.Headers; +import okhttp3.HttpUrl; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; +import okhttp3.ResponseBody; +import org.jetbrains.annotations.NotNull; + +public class AsyncRawFormDetectionRunsClient { + protected final ClientOptions clientOptions; + + public AsyncRawFormDetectionRunsClient(ClientOptions clientOptions) { + this.clientOptions = clientOptions; + } + + /** + * Start detecting fields in a PDF form and return immediately with a form_detection_run resource, typically in the PROCESSING state. + *

Poll GET /form_detection_runs/{id} until the status is PROCESSED or FAILED. When processing succeeds, output.schema contains an edit schema you can pass directly to POST /edit or POST /edit_runs.

+ */ + public CompletableFuture> create( + FormDetectionRunsCreateRequest request) { + return create(request, null); + } + + /** + * Start detecting fields in a PDF form and return immediately with a form_detection_run resource, typically in the PROCESSING state. + *

Poll GET /form_detection_runs/{id} until the status is PROCESSED or FAILED. When processing succeeds, output.schema contains an edit schema you can pass directly to POST /edit or POST /edit_runs.

+ */ + public CompletableFuture> create( + FormDetectionRunsCreateRequest request, RequestOptions requestOptions) { + HttpUrl.Builder httpUrl = HttpUrl.parse(this.clientOptions.environment().getUrl()) + .newBuilder() + .addPathSegments("form_detection_runs"); + if (requestOptions != null) { + requestOptions.getQueryParameters().forEach((_key, _value) -> { + httpUrl.addQueryParameter(_key, _value); + }); + } + RequestBody body; + try { + body = RequestBody.create( + ObjectMappers.JSON_MAPPER.writeValueAsBytes(request), MediaTypes.APPLICATION_JSON); + } catch (JsonProcessingException e) { + throw new ExtendClientException("Failed to serialize request", e); + } + Request okhttpRequest = new Request.Builder() + .url(httpUrl.build()) + .method("POST", body) + .headers(Headers.of(clientOptions.headers(requestOptions))) + .addHeader("Content-Type", "application/json") + .addHeader("Accept", "application/json") + .build(); + OkHttpClient client = clientOptions.httpClient(); + if (requestOptions != null && requestOptions.getTimeout().isPresent()) { + client = clientOptions.httpClientWithTimeout(requestOptions); + } + CompletableFuture> future = new CompletableFuture<>(); + client.newCall(okhttpRequest).enqueue(new Callback() { + @Override + public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException { + try (ResponseBody responseBody = response.body()) { + String responseBodyString = responseBody != null ? responseBody.string() : "{}"; + if (response.isSuccessful()) { + future.complete(new ExtendClientBaseHttpResponse<>( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, FormDetectionRun.class), + response)); + return; + } + try { + switch (response.code()) { + case 400: + future.completeExceptionally(new BadRequestError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, Object.class), + response)); + return; + case 401: + future.completeExceptionally(new UnauthorizedError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, Object.class), + response)); + return; + case 402: + future.completeExceptionally(new PaymentRequiredError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, ApiError.class), + response)); + return; + case 403: + future.completeExceptionally(new ForbiddenError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, ApiError.class), + response)); + return; + case 404: + future.completeExceptionally(new NotFoundError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, Object.class), + response)); + return; + case 422: + future.completeExceptionally(new UnprocessableEntityError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, ApiError.class), + response)); + return; + case 429: + future.completeExceptionally(new TooManyRequestsError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, Object.class), + response)); + return; + case 500: + future.completeExceptionally(new InternalServerError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, Object.class), + response)); + return; + } + } catch (JsonProcessingException ignored) { + // unable to map error response, throwing generic error + } + Object errorBody = ObjectMappers.parseErrorBody(responseBodyString); + future.completeExceptionally(new ExtendClientApiException( + "Error with status code " + response.code(), response.code(), errorBody, response)); + return; + } catch (IOException e) { + future.completeExceptionally(new ExtendClientException("Network error executing HTTP request", e)); + } + } + + @Override + public void onFailure(@NotNull Call call, @NotNull IOException e) { + future.completeExceptionally(new ExtendClientException("Network error executing HTTP request", e)); + } + }); + return future; + } + + /** + * Retrieve the status and results of a form detection run. + *

Use this endpoint to poll a run created with POST /form_detection_runs. When status is PROCESSED, output.schema contains the generated edit schema.

+ */ + public CompletableFuture> retrieve(String id) { + return retrieve(id, FormDetectionRunsRetrieveRequest.builder().build()); + } + + /** + * Retrieve the status and results of a form detection run. + *

Use this endpoint to poll a run created with POST /form_detection_runs. When status is PROCESSED, output.schema contains the generated edit schema.

+ */ + public CompletableFuture> retrieve( + String id, RequestOptions requestOptions) { + return retrieve(id, FormDetectionRunsRetrieveRequest.builder().build(), requestOptions); + } + + /** + * Retrieve the status and results of a form detection run. + *

Use this endpoint to poll a run created with POST /form_detection_runs. When status is PROCESSED, output.schema contains the generated edit schema.

+ */ + public CompletableFuture> retrieve( + String id, FormDetectionRunsRetrieveRequest request) { + return retrieve(id, request, null); + } + + /** + * Retrieve the status and results of a form detection run. + *

Use this endpoint to poll a run created with POST /form_detection_runs. When status is PROCESSED, output.schema contains the generated edit schema.

+ */ + public CompletableFuture> retrieve( + String id, FormDetectionRunsRetrieveRequest request, RequestOptions requestOptions) { + HttpUrl.Builder httpUrl = HttpUrl.parse(this.clientOptions.environment().getUrl()) + .newBuilder() + .addPathSegments("form_detection_runs") + .addPathSegment(id); + if (requestOptions != null) { + requestOptions.getQueryParameters().forEach((_key, _value) -> { + httpUrl.addQueryParameter(_key, _value); + }); + } + Request.Builder _requestBuilder = new Request.Builder() + .url(httpUrl.build()) + .method("GET", null) + .headers(Headers.of(clientOptions.headers(requestOptions))) + .addHeader("Accept", "application/json"); + if (request.getExtendWorkspaceId().isPresent()) { + _requestBuilder.addHeader( + "x-extend-workspace-id", request.getExtendWorkspaceId().get()); + } + Request okhttpRequest = _requestBuilder.build(); + OkHttpClient client = clientOptions.httpClient(); + if (requestOptions != null && requestOptions.getTimeout().isPresent()) { + client = clientOptions.httpClientWithTimeout(requestOptions); + } + CompletableFuture> future = new CompletableFuture<>(); + client.newCall(okhttpRequest).enqueue(new Callback() { + @Override + public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException { + try (ResponseBody responseBody = response.body()) { + String responseBodyString = responseBody != null ? responseBody.string() : "{}"; + if (response.isSuccessful()) { + future.complete(new ExtendClientBaseHttpResponse<>( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, FormDetectionRun.class), + response)); + return; + } + try { + switch (response.code()) { + case 400: + future.completeExceptionally(new BadRequestError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, Object.class), + response)); + return; + case 401: + future.completeExceptionally(new UnauthorizedError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, Object.class), + response)); + return; + case 402: + future.completeExceptionally(new PaymentRequiredError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, ApiError.class), + response)); + return; + case 403: + future.completeExceptionally(new ForbiddenError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, ApiError.class), + response)); + return; + case 404: + future.completeExceptionally(new NotFoundError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, Object.class), + response)); + return; + case 422: + future.completeExceptionally(new UnprocessableEntityError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, ApiError.class), + response)); + return; + case 429: + future.completeExceptionally(new TooManyRequestsError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, Object.class), + response)); + return; + case 500: + future.completeExceptionally(new InternalServerError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, Object.class), + response)); + return; + } + } catch (JsonProcessingException ignored) { + // unable to map error response, throwing generic error + } + Object errorBody = ObjectMappers.parseErrorBody(responseBodyString); + future.completeExceptionally(new ExtendClientApiException( + "Error with status code " + response.code(), response.code(), errorBody, response)); + return; + } catch (IOException e) { + future.completeExceptionally(new ExtendClientException("Network error executing HTTP request", e)); + } + } + + @Override + public void onFailure(@NotNull Call call, @NotNull IOException e) { + future.completeExceptionally(new ExtendClientException("Network error executing HTTP request", e)); + } + }); + return future; + } +} diff --git a/src/main/java/ai/extend/resources/formdetectionruns/FormDetectionRunsClient.java b/src/main/java/ai/extend/resources/formdetectionruns/FormDetectionRunsClient.java new file mode 100644 index 0000000..2095f3e --- /dev/null +++ b/src/main/java/ai/extend/resources/formdetectionruns/FormDetectionRunsClient.java @@ -0,0 +1,77 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package ai.extend.resources.formdetectionruns; + +import ai.extend.core.ClientOptions; +import ai.extend.core.RequestOptions; +import ai.extend.resources.formdetectionruns.requests.FormDetectionRunsCreateRequest; +import ai.extend.resources.formdetectionruns.requests.FormDetectionRunsRetrieveRequest; +import ai.extend.types.FormDetectionRun; + +public class FormDetectionRunsClient { + protected final ClientOptions clientOptions; + + private final RawFormDetectionRunsClient rawClient; + + public FormDetectionRunsClient(ClientOptions clientOptions) { + this.clientOptions = clientOptions; + this.rawClient = new RawFormDetectionRunsClient(clientOptions); + } + + /** + * Get responses with HTTP metadata like headers + */ + public RawFormDetectionRunsClient withRawResponse() { + return this.rawClient; + } + + /** + * Start detecting fields in a PDF form and return immediately with a form_detection_run resource, typically in the PROCESSING state. + *

Poll GET /form_detection_runs/{id} until the status is PROCESSED or FAILED. When processing succeeds, output.schema contains an edit schema you can pass directly to POST /edit or POST /edit_runs.

+ */ + public FormDetectionRun create(FormDetectionRunsCreateRequest request) { + return this.rawClient.create(request).body(); + } + + /** + * Start detecting fields in a PDF form and return immediately with a form_detection_run resource, typically in the PROCESSING state. + *

Poll GET /form_detection_runs/{id} until the status is PROCESSED or FAILED. When processing succeeds, output.schema contains an edit schema you can pass directly to POST /edit or POST /edit_runs.

+ */ + public FormDetectionRun create(FormDetectionRunsCreateRequest request, RequestOptions requestOptions) { + return this.rawClient.create(request, requestOptions).body(); + } + + /** + * Retrieve the status and results of a form detection run. + *

Use this endpoint to poll a run created with POST /form_detection_runs. When status is PROCESSED, output.schema contains the generated edit schema.

+ */ + public FormDetectionRun retrieve(String id) { + return this.rawClient.retrieve(id).body(); + } + + /** + * Retrieve the status and results of a form detection run. + *

Use this endpoint to poll a run created with POST /form_detection_runs. When status is PROCESSED, output.schema contains the generated edit schema.

+ */ + public FormDetectionRun retrieve(String id, RequestOptions requestOptions) { + return this.rawClient.retrieve(id, requestOptions).body(); + } + + /** + * Retrieve the status and results of a form detection run. + *

Use this endpoint to poll a run created with POST /form_detection_runs. When status is PROCESSED, output.schema contains the generated edit schema.

+ */ + public FormDetectionRun retrieve(String id, FormDetectionRunsRetrieveRequest request) { + return this.rawClient.retrieve(id, request).body(); + } + + /** + * Retrieve the status and results of a form detection run. + *

Use this endpoint to poll a run created with POST /form_detection_runs. When status is PROCESSED, output.schema contains the generated edit schema.

+ */ + public FormDetectionRun retrieve( + String id, FormDetectionRunsRetrieveRequest request, RequestOptions requestOptions) { + return this.rawClient.retrieve(id, request, requestOptions).body(); + } +} diff --git a/src/main/java/ai/extend/resources/formdetectionruns/RawFormDetectionRunsClient.java b/src/main/java/ai/extend/resources/formdetectionruns/RawFormDetectionRunsClient.java new file mode 100644 index 0000000..160db0f --- /dev/null +++ b/src/main/java/ai/extend/resources/formdetectionruns/RawFormDetectionRunsClient.java @@ -0,0 +1,225 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package ai.extend.resources.formdetectionruns; + +import ai.extend.core.ClientOptions; +import ai.extend.core.ExtendClientApiException; +import ai.extend.core.ExtendClientBaseHttpResponse; +import ai.extend.core.ExtendClientException; +import ai.extend.core.MediaTypes; +import ai.extend.core.ObjectMappers; +import ai.extend.core.RequestOptions; +import ai.extend.errors.BadRequestError; +import ai.extend.errors.ForbiddenError; +import ai.extend.errors.InternalServerError; +import ai.extend.errors.NotFoundError; +import ai.extend.errors.PaymentRequiredError; +import ai.extend.errors.TooManyRequestsError; +import ai.extend.errors.UnauthorizedError; +import ai.extend.errors.UnprocessableEntityError; +import ai.extend.resources.formdetectionruns.requests.FormDetectionRunsCreateRequest; +import ai.extend.resources.formdetectionruns.requests.FormDetectionRunsRetrieveRequest; +import ai.extend.types.ApiError; +import ai.extend.types.FormDetectionRun; +import com.fasterxml.jackson.core.JsonProcessingException; +import java.io.IOException; +import okhttp3.Headers; +import okhttp3.HttpUrl; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; +import okhttp3.ResponseBody; + +public class RawFormDetectionRunsClient { + protected final ClientOptions clientOptions; + + public RawFormDetectionRunsClient(ClientOptions clientOptions) { + this.clientOptions = clientOptions; + } + + /** + * Start detecting fields in a PDF form and return immediately with a form_detection_run resource, typically in the PROCESSING state. + *

Poll GET /form_detection_runs/{id} until the status is PROCESSED or FAILED. When processing succeeds, output.schema contains an edit schema you can pass directly to POST /edit or POST /edit_runs.

+ */ + public ExtendClientBaseHttpResponse create(FormDetectionRunsCreateRequest request) { + return create(request, null); + } + + /** + * Start detecting fields in a PDF form and return immediately with a form_detection_run resource, typically in the PROCESSING state. + *

Poll GET /form_detection_runs/{id} until the status is PROCESSED or FAILED. When processing succeeds, output.schema contains an edit schema you can pass directly to POST /edit or POST /edit_runs.

+ */ + public ExtendClientBaseHttpResponse create( + FormDetectionRunsCreateRequest request, RequestOptions requestOptions) { + HttpUrl.Builder httpUrl = HttpUrl.parse(this.clientOptions.environment().getUrl()) + .newBuilder() + .addPathSegments("form_detection_runs"); + if (requestOptions != null) { + requestOptions.getQueryParameters().forEach((_key, _value) -> { + httpUrl.addQueryParameter(_key, _value); + }); + } + RequestBody body; + try { + body = RequestBody.create( + ObjectMappers.JSON_MAPPER.writeValueAsBytes(request), MediaTypes.APPLICATION_JSON); + } catch (JsonProcessingException e) { + throw new ExtendClientException("Failed to serialize request", e); + } + Request okhttpRequest = new Request.Builder() + .url(httpUrl.build()) + .method("POST", body) + .headers(Headers.of(clientOptions.headers(requestOptions))) + .addHeader("Content-Type", "application/json") + .addHeader("Accept", "application/json") + .build(); + OkHttpClient client = clientOptions.httpClient(); + if (requestOptions != null && requestOptions.getTimeout().isPresent()) { + client = clientOptions.httpClientWithTimeout(requestOptions); + } + try (Response response = client.newCall(okhttpRequest).execute()) { + ResponseBody responseBody = response.body(); + String responseBodyString = responseBody != null ? responseBody.string() : "{}"; + if (response.isSuccessful()) { + return new ExtendClientBaseHttpResponse<>( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, FormDetectionRun.class), response); + } + try { + switch (response.code()) { + case 400: + throw new BadRequestError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, Object.class), response); + case 401: + throw new UnauthorizedError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, Object.class), response); + case 402: + throw new PaymentRequiredError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, ApiError.class), response); + case 403: + throw new ForbiddenError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, ApiError.class), response); + case 404: + throw new NotFoundError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, Object.class), response); + case 422: + throw new UnprocessableEntityError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, ApiError.class), response); + case 429: + throw new TooManyRequestsError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, Object.class), response); + case 500: + throw new InternalServerError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, Object.class), response); + } + } catch (JsonProcessingException ignored) { + // unable to map error response, throwing generic error + } + Object errorBody = ObjectMappers.parseErrorBody(responseBodyString); + throw new ExtendClientApiException( + "Error with status code " + response.code(), response.code(), errorBody, response); + } catch (IOException e) { + throw new ExtendClientException("Network error executing HTTP request", e); + } + } + + /** + * Retrieve the status and results of a form detection run. + *

Use this endpoint to poll a run created with POST /form_detection_runs. When status is PROCESSED, output.schema contains the generated edit schema.

+ */ + public ExtendClientBaseHttpResponse retrieve(String id) { + return retrieve(id, FormDetectionRunsRetrieveRequest.builder().build()); + } + + /** + * Retrieve the status and results of a form detection run. + *

Use this endpoint to poll a run created with POST /form_detection_runs. When status is PROCESSED, output.schema contains the generated edit schema.

+ */ + public ExtendClientBaseHttpResponse retrieve(String id, RequestOptions requestOptions) { + return retrieve(id, FormDetectionRunsRetrieveRequest.builder().build(), requestOptions); + } + + /** + * Retrieve the status and results of a form detection run. + *

Use this endpoint to poll a run created with POST /form_detection_runs. When status is PROCESSED, output.schema contains the generated edit schema.

+ */ + public ExtendClientBaseHttpResponse retrieve( + String id, FormDetectionRunsRetrieveRequest request) { + return retrieve(id, request, null); + } + + /** + * Retrieve the status and results of a form detection run. + *

Use this endpoint to poll a run created with POST /form_detection_runs. When status is PROCESSED, output.schema contains the generated edit schema.

+ */ + public ExtendClientBaseHttpResponse retrieve( + String id, FormDetectionRunsRetrieveRequest request, RequestOptions requestOptions) { + HttpUrl.Builder httpUrl = HttpUrl.parse(this.clientOptions.environment().getUrl()) + .newBuilder() + .addPathSegments("form_detection_runs") + .addPathSegment(id); + if (requestOptions != null) { + requestOptions.getQueryParameters().forEach((_key, _value) -> { + httpUrl.addQueryParameter(_key, _value); + }); + } + Request.Builder _requestBuilder = new Request.Builder() + .url(httpUrl.build()) + .method("GET", null) + .headers(Headers.of(clientOptions.headers(requestOptions))) + .addHeader("Accept", "application/json"); + if (request.getExtendWorkspaceId().isPresent()) { + _requestBuilder.addHeader( + "x-extend-workspace-id", request.getExtendWorkspaceId().get()); + } + Request okhttpRequest = _requestBuilder.build(); + OkHttpClient client = clientOptions.httpClient(); + if (requestOptions != null && requestOptions.getTimeout().isPresent()) { + client = clientOptions.httpClientWithTimeout(requestOptions); + } + try (Response response = client.newCall(okhttpRequest).execute()) { + ResponseBody responseBody = response.body(); + String responseBodyString = responseBody != null ? responseBody.string() : "{}"; + if (response.isSuccessful()) { + return new ExtendClientBaseHttpResponse<>( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, FormDetectionRun.class), response); + } + try { + switch (response.code()) { + case 400: + throw new BadRequestError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, Object.class), response); + case 401: + throw new UnauthorizedError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, Object.class), response); + case 402: + throw new PaymentRequiredError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, ApiError.class), response); + case 403: + throw new ForbiddenError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, ApiError.class), response); + case 404: + throw new NotFoundError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, Object.class), response); + case 422: + throw new UnprocessableEntityError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, ApiError.class), response); + case 429: + throw new TooManyRequestsError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, Object.class), response); + case 500: + throw new InternalServerError( + ObjectMappers.JSON_MAPPER.readValue(responseBodyString, Object.class), response); + } + } catch (JsonProcessingException ignored) { + // unable to map error response, throwing generic error + } + Object errorBody = ObjectMappers.parseErrorBody(responseBodyString); + throw new ExtendClientApiException( + "Error with status code " + response.code(), response.code(), errorBody, response); + } catch (IOException e) { + throw new ExtendClientException("Network error executing HTTP request", e); + } + } +} diff --git a/src/main/java/ai/extend/resources/formdetectionruns/requests/FormDetectionRunsCreateRequest.java b/src/main/java/ai/extend/resources/formdetectionruns/requests/FormDetectionRunsCreateRequest.java new file mode 100644 index 0000000..ad9a1bf --- /dev/null +++ b/src/main/java/ai/extend/resources/formdetectionruns/requests/FormDetectionRunsCreateRequest.java @@ -0,0 +1,148 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package ai.extend.resources.formdetectionruns.requests; + +import ai.extend.core.ObjectMappers; +import ai.extend.resources.formdetectionruns.types.FormDetectionRunsCreateRequestFile; +import ai.extend.types.EditSchemaGenerationConfig; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.annotation.Nulls; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import org.jetbrains.annotations.NotNull; + +@JsonInclude(JsonInclude.Include.NON_ABSENT) +@JsonDeserialize(builder = FormDetectionRunsCreateRequest.Builder.class) +public final class FormDetectionRunsCreateRequest { + private final FormDetectionRunsCreateRequestFile file; + + private final Optional config; + + private final Map additionalProperties; + + private FormDetectionRunsCreateRequest( + FormDetectionRunsCreateRequestFile file, + Optional config, + Map additionalProperties) { + this.file = file; + this.config = config; + this.additionalProperties = additionalProperties; + } + + /** + * @return The PDF form to analyze. Files can be provided as a URL or an Extend file ID. + */ + @JsonProperty("file") + public FormDetectionRunsCreateRequestFile getFile() { + return file; + } + + @JsonProperty("config") + public Optional getConfig() { + return config; + } + + @java.lang.Override + public boolean equals(Object other) { + if (this == other) return true; + return other instanceof FormDetectionRunsCreateRequest && equalTo((FormDetectionRunsCreateRequest) other); + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + private boolean equalTo(FormDetectionRunsCreateRequest other) { + return file.equals(other.file) && config.equals(other.config); + } + + @java.lang.Override + public int hashCode() { + return Objects.hash(this.file, this.config); + } + + @java.lang.Override + public String toString() { + return ObjectMappers.stringify(this); + } + + public static FileStage builder() { + return new Builder(); + } + + public interface FileStage { + /** + *

The PDF form to analyze. Files can be provided as a URL or an Extend file ID.

+ */ + _FinalStage file(@NotNull FormDetectionRunsCreateRequestFile file); + + Builder from(FormDetectionRunsCreateRequest other); + } + + public interface _FinalStage { + FormDetectionRunsCreateRequest build(); + + _FinalStage config(Optional config); + + _FinalStage config(EditSchemaGenerationConfig config); + } + + @JsonIgnoreProperties(ignoreUnknown = true) + public static final class Builder implements FileStage, _FinalStage { + private FormDetectionRunsCreateRequestFile file; + + private Optional config = Optional.empty(); + + @JsonAnySetter + private Map additionalProperties = new HashMap<>(); + + private Builder() {} + + @java.lang.Override + public Builder from(FormDetectionRunsCreateRequest other) { + file(other.getFile()); + config(other.getConfig()); + return this; + } + + /** + *

The PDF form to analyze. Files can be provided as a URL or an Extend file ID.

+ *

The PDF form to analyze. Files can be provided as a URL or an Extend file ID.

+ * @return Reference to {@code this} so that method calls can be chained together. + */ + @java.lang.Override + @JsonSetter("file") + public _FinalStage file(@NotNull FormDetectionRunsCreateRequestFile file) { + this.file = Objects.requireNonNull(file, "file must not be null"); + return this; + } + + @java.lang.Override + public _FinalStage config(EditSchemaGenerationConfig config) { + this.config = Optional.ofNullable(config); + return this; + } + + @java.lang.Override + @JsonSetter(value = "config", nulls = Nulls.SKIP) + public _FinalStage config(Optional config) { + this.config = config; + return this; + } + + @java.lang.Override + public FormDetectionRunsCreateRequest build() { + return new FormDetectionRunsCreateRequest(file, config, additionalProperties); + } + } +} diff --git a/src/main/java/ai/extend/resources/formdetectionruns/requests/FormDetectionRunsRetrieveRequest.java b/src/main/java/ai/extend/resources/formdetectionruns/requests/FormDetectionRunsRetrieveRequest.java new file mode 100644 index 0000000..1565e29 --- /dev/null +++ b/src/main/java/ai/extend/resources/formdetectionruns/requests/FormDetectionRunsRetrieveRequest.java @@ -0,0 +1,99 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package ai.extend.resources.formdetectionruns.requests; + +import ai.extend.core.ObjectMappers; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; + +@JsonInclude(JsonInclude.Include.NON_ABSENT) +@JsonDeserialize(builder = FormDetectionRunsRetrieveRequest.Builder.class) +public final class FormDetectionRunsRetrieveRequest { + private final Optional extendWorkspaceId; + + private final Map additionalProperties; + + private FormDetectionRunsRetrieveRequest( + Optional extendWorkspaceId, Map additionalProperties) { + this.extendWorkspaceId = extendWorkspaceId; + this.additionalProperties = additionalProperties; + } + + /** + * @return The workspace ID to target. Required when using an organization-scoped API key; optional for workspace-scoped keys (the key is already tied to a workspace). See Authentication for details on API key scopes. + */ + @JsonIgnore + public Optional getExtendWorkspaceId() { + return extendWorkspaceId; + } + + @java.lang.Override + public boolean equals(Object other) { + if (this == other) return true; + return other instanceof FormDetectionRunsRetrieveRequest && equalTo((FormDetectionRunsRetrieveRequest) other); + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + private boolean equalTo(FormDetectionRunsRetrieveRequest other) { + return extendWorkspaceId.equals(other.extendWorkspaceId); + } + + @java.lang.Override + public int hashCode() { + return Objects.hash(this.extendWorkspaceId); + } + + @java.lang.Override + public String toString() { + return ObjectMappers.stringify(this); + } + + public static Builder builder() { + return new Builder(); + } + + @JsonIgnoreProperties(ignoreUnknown = true) + public static final class Builder { + private Optional extendWorkspaceId = Optional.empty(); + + @JsonAnySetter + private Map additionalProperties = new HashMap<>(); + + private Builder() {} + + public Builder from(FormDetectionRunsRetrieveRequest other) { + extendWorkspaceId(other.getExtendWorkspaceId()); + return this; + } + + /** + *

The workspace ID to target. Required when using an organization-scoped API key; optional for workspace-scoped keys (the key is already tied to a workspace). See Authentication for details on API key scopes.

+ */ + public Builder extendWorkspaceId(Optional extendWorkspaceId) { + this.extendWorkspaceId = extendWorkspaceId; + return this; + } + + public Builder extendWorkspaceId(String extendWorkspaceId) { + this.extendWorkspaceId = Optional.ofNullable(extendWorkspaceId); + return this; + } + + public FormDetectionRunsRetrieveRequest build() { + return new FormDetectionRunsRetrieveRequest(extendWorkspaceId, additionalProperties); + } + } +} diff --git a/src/main/java/ai/extend/resources/formdetectionruns/types/FormDetectionRunsCreateRequestFile.java b/src/main/java/ai/extend/resources/formdetectionruns/types/FormDetectionRunsCreateRequestFile.java new file mode 100644 index 0000000..1011aac --- /dev/null +++ b/src/main/java/ai/extend/resources/formdetectionruns/types/FormDetectionRunsCreateRequestFile.java @@ -0,0 +1,99 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package ai.extend.resources.formdetectionruns.types; + +import ai.extend.core.ObjectMappers; +import ai.extend.types.FileFromId; +import ai.extend.types.FileFromUrl; +import com.fasterxml.jackson.annotation.JsonValue; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import java.io.IOException; +import java.util.Objects; + +@JsonDeserialize(using = FormDetectionRunsCreateRequestFile.Deserializer.class) +public final class FormDetectionRunsCreateRequestFile { + private final Object value; + + private final int type; + + private FormDetectionRunsCreateRequestFile(Object value, int type) { + this.value = value; + this.type = type; + } + + @JsonValue + public Object get() { + return this.value; + } + + @SuppressWarnings("unchecked") + public T visit(Visitor visitor) { + if (this.type == 0) { + return visitor.visit((FileFromUrl) this.value); + } else if (this.type == 1) { + return visitor.visit((FileFromId) this.value); + } + throw new IllegalStateException("Failed to visit value. This should never happen."); + } + + @java.lang.Override + public boolean equals(Object other) { + if (this == other) return true; + return other instanceof FormDetectionRunsCreateRequestFile + && equalTo((FormDetectionRunsCreateRequestFile) other); + } + + private boolean equalTo(FormDetectionRunsCreateRequestFile other) { + return value.equals(other.value); + } + + @java.lang.Override + public int hashCode() { + return Objects.hash(this.value); + } + + @java.lang.Override + public String toString() { + return this.value.toString(); + } + + public static FormDetectionRunsCreateRequestFile of(FileFromUrl value) { + return new FormDetectionRunsCreateRequestFile(value, 0); + } + + public static FormDetectionRunsCreateRequestFile of(FileFromId value) { + return new FormDetectionRunsCreateRequestFile(value, 1); + } + + public interface Visitor { + T visit(FileFromUrl value); + + T visit(FileFromId value); + } + + static final class Deserializer extends StdDeserializer { + Deserializer() { + super(FormDetectionRunsCreateRequestFile.class); + } + + @java.lang.Override + public FormDetectionRunsCreateRequestFile deserialize(JsonParser p, DeserializationContext context) + throws IOException { + Object value = p.readValueAs(Object.class); + try { + return of(ObjectMappers.JSON_MAPPER.convertValue(value, FileFromUrl.class)); + } catch (RuntimeException e) { + } + try { + return of(ObjectMappers.JSON_MAPPER.convertValue(value, FileFromId.class)); + } catch (RuntimeException e) { + } + throw new JsonParseException(p, "Failed to deserialize"); + } + } +} diff --git a/src/main/java/ai/extend/resources/parseruns/requests/ParseRunsCreateRequest.java b/src/main/java/ai/extend/resources/parseruns/requests/ParseRunsCreateRequest.java index abb5e07..3b18916 100644 --- a/src/main/java/ai/extend/resources/parseruns/requests/ParseRunsCreateRequest.java +++ b/src/main/java/ai/extend/resources/parseruns/requests/ParseRunsCreateRequest.java @@ -5,6 +5,7 @@ import ai.extend.core.ObjectMappers; import ai.extend.resources.parseruns.types.ParseRunsCreateRequestFile; +import ai.extend.types.DataRetention; import ai.extend.types.ParseConfig; import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.fasterxml.jackson.annotation.JsonAnySetter; @@ -29,16 +30,20 @@ public final class ParseRunsCreateRequest { private final Optional> metadata; + private final Optional dataRetention; + private final Map additionalProperties; private ParseRunsCreateRequest( ParseRunsCreateRequestFile file, Optional config, Optional> metadata, + Optional dataRetention, Map additionalProperties) { this.file = file; this.config = config; this.metadata = metadata; + this.dataRetention = dataRetention; this.additionalProperties = additionalProperties; } @@ -60,6 +65,11 @@ public Optional> getMetadata() { return metadata; } + @JsonProperty("dataRetention") + public Optional getDataRetention() { + return dataRetention; + } + @java.lang.Override public boolean equals(Object other) { if (this == other) return true; @@ -72,12 +82,15 @@ public Map getAdditionalProperties() { } private boolean equalTo(ParseRunsCreateRequest other) { - return file.equals(other.file) && config.equals(other.config) && metadata.equals(other.metadata); + return file.equals(other.file) + && config.equals(other.config) + && metadata.equals(other.metadata) + && dataRetention.equals(other.dataRetention); } @java.lang.Override public int hashCode() { - return Objects.hash(this.file, this.config, this.metadata); + return Objects.hash(this.file, this.config, this.metadata, this.dataRetention); } @java.lang.Override @@ -108,12 +121,18 @@ public interface _FinalStage { _FinalStage metadata(Optional> metadata); _FinalStage metadata(Map metadata); + + _FinalStage dataRetention(Optional dataRetention); + + _FinalStage dataRetention(DataRetention dataRetention); } @JsonIgnoreProperties(ignoreUnknown = true) public static final class Builder implements FileStage, _FinalStage { private ParseRunsCreateRequestFile file; + private Optional dataRetention = Optional.empty(); + private Optional> metadata = Optional.empty(); private Optional config = Optional.empty(); @@ -128,6 +147,7 @@ public Builder from(ParseRunsCreateRequest other) { file(other.getFile()); config(other.getConfig()); metadata(other.getMetadata()); + dataRetention(other.getDataRetention()); return this; } @@ -143,6 +163,19 @@ public _FinalStage file(@NotNull ParseRunsCreateRequestFile file) { return this; } + @java.lang.Override + public _FinalStage dataRetention(DataRetention dataRetention) { + this.dataRetention = Optional.ofNullable(dataRetention); + return this; + } + + @java.lang.Override + @JsonSetter(value = "dataRetention", nulls = Nulls.SKIP) + public _FinalStage dataRetention(Optional dataRetention) { + this.dataRetention = dataRetention; + return this; + } + @java.lang.Override public _FinalStage metadata(Map metadata) { this.metadata = Optional.ofNullable(metadata); @@ -171,7 +204,7 @@ public _FinalStage config(Optional config) { @java.lang.Override public ParseRunsCreateRequest build() { - return new ParseRunsCreateRequest(file, config, metadata, additionalProperties); + return new ParseRunsCreateRequest(file, config, metadata, dataRetention, additionalProperties); } } } diff --git a/src/main/java/ai/extend/types/ApiError.java b/src/main/java/ai/extend/types/ApiError.java index e81acb0..aca86dc 100644 --- a/src/main/java/ai/extend/types/ApiError.java +++ b/src/main/java/ai/extend/types/ApiError.java @@ -29,6 +29,8 @@ public final class ApiError { private final Optional requestId; + private final Optional docUrl; + private final Map additionalProperties; private ApiError( @@ -36,11 +38,13 @@ private ApiError( String message, boolean retryable, Optional requestId, + Optional docUrl, Map additionalProperties) { this.code = code; this.message = message; this.retryable = retryable; this.requestId = requestId; + this.docUrl = docUrl; this.additionalProperties = additionalProperties; } @@ -79,6 +83,14 @@ public Optional getRequestId() { return requestId; } + /** + * @return Link to relevant documentation when one is available. + */ + @JsonProperty("docUrl") + public Optional getDocUrl() { + return docUrl; + } + @java.lang.Override public boolean equals(Object other) { if (this == other) return true; @@ -94,12 +106,13 @@ private boolean equalTo(ApiError other) { return code.equals(other.code) && message.equals(other.message) && retryable == other.retryable - && requestId.equals(other.requestId); + && requestId.equals(other.requestId) + && docUrl.equals(other.docUrl); } @java.lang.Override public int hashCode() { - return Objects.hash(this.code, this.message, this.retryable, this.requestId); + return Objects.hash(this.code, this.message, this.retryable, this.requestId, this.docUrl); } @java.lang.Override @@ -146,6 +159,13 @@ public interface _FinalStage { _FinalStage requestId(Optional requestId); _FinalStage requestId(String requestId); + + /** + *

Link to relevant documentation when one is available.

+ */ + _FinalStage docUrl(Optional docUrl); + + _FinalStage docUrl(String docUrl); } @JsonIgnoreProperties(ignoreUnknown = true) @@ -156,6 +176,8 @@ public static final class Builder implements CodeStage, MessageStage, RetryableS private boolean retryable; + private Optional docUrl = Optional.empty(); + private Optional requestId = Optional.empty(); @JsonAnySetter @@ -169,6 +191,7 @@ public Builder from(ApiError other) { message(other.getMessage()); retryable(other.getRetryable()); requestId(other.getRequestId()); + docUrl(other.getDocUrl()); return this; } @@ -212,6 +235,26 @@ public _FinalStage retryable(boolean retryable) { return this; } + /** + *

Link to relevant documentation when one is available.

+ * @return Reference to {@code this} so that method calls can be chained together. + */ + @java.lang.Override + public _FinalStage docUrl(String docUrl) { + this.docUrl = Optional.ofNullable(docUrl); + return this; + } + + /** + *

Link to relevant documentation when one is available.

+ */ + @java.lang.Override + @JsonSetter(value = "docUrl", nulls = Nulls.SKIP) + public _FinalStage docUrl(Optional docUrl) { + this.docUrl = docUrl; + return this; + } + /** *

Unique request identifier for support purposes. Always include this * when contacting Extend support about an error.

@@ -236,7 +279,7 @@ public _FinalStage requestId(Optional requestId) { @java.lang.Override public ApiError build() { - return new ApiError(code, message, retryable, requestId, additionalProperties); + return new ApiError(code, message, retryable, requestId, docUrl, additionalProperties); } } } diff --git a/src/main/java/ai/extend/types/ArrayStrategy.java b/src/main/java/ai/extend/types/ArrayStrategy.java index 60f04da..5d9c543 100644 --- a/src/main/java/ai/extend/types/ArrayStrategy.java +++ b/src/main/java/ai/extend/types/ArrayStrategy.java @@ -37,7 +37,7 @@ private ArrayStrategy(ArrayStrategyType type, Map additionalProp * *
  • *

    large_array_max_context: Optimizes for accuracy over latency in documents with very large arrays.

    - *

    This strategy will do multiple passes through the entire document to ensure there is no context loss across any chunks/pages, maximizing accuracy for complex array extraction, but adding material latency.

    + *

    This strategy will do multiple passes through the entire document to ensure there is no context loss across any chunks/pages, maximizing accuracy for complex array extraction, but adding material latency. This strategy incurs additional extraction credits when enabled.

    *
  • *
  • *

    large_array_overlap_context: Balances accuracy and latency in documents with very large arrays.

    @@ -89,7 +89,7 @@ public interface TypeStage { *
  • *
  • *

    large_array_max_context: Optimizes for accuracy over latency in documents with very large arrays.

    - *

    This strategy will do multiple passes through the entire document to ensure there is no context loss across any chunks/pages, maximizing accuracy for complex array extraction, but adding material latency.

    + *

    This strategy will do multiple passes through the entire document to ensure there is no context loss across any chunks/pages, maximizing accuracy for complex array extraction, but adding material latency. This strategy incurs additional extraction credits when enabled.

    *
  • *
  • *

    large_array_overlap_context: Balances accuracy and latency in documents with very large arrays.

    @@ -130,7 +130,7 @@ public Builder from(ArrayStrategy other) { *
  • *
  • *

    large_array_max_context: Optimizes for accuracy over latency in documents with very large arrays.

    - *

    This strategy will do multiple passes through the entire document to ensure there is no context loss across any chunks/pages, maximizing accuracy for complex array extraction, but adding material latency.

    + *

    This strategy will do multiple passes through the entire document to ensure there is no context loss across any chunks/pages, maximizing accuracy for complex array extraction, but adding material latency. This strategy incurs additional extraction credits when enabled.

    *
  • *
  • *

    large_array_overlap_context: Balances accuracy and latency in documents with very large arrays.

    @@ -145,7 +145,7 @@ public Builder from(ArrayStrategy other) { *
  • *
  • *

    large_array_max_context: Optimizes for accuracy over latency in documents with very large arrays.

    - *

    This strategy will do multiple passes through the entire document to ensure there is no context loss across any chunks/pages, maximizing accuracy for complex array extraction, but adding material latency.

    + *

    This strategy will do multiple passes through the entire document to ensure there is no context loss across any chunks/pages, maximizing accuracy for complex array extraction, but adding material latency. This strategy incurs additional extraction credits when enabled.

    *
  • *
  • *

    large_array_overlap_context: Balances accuracy and latency in documents with very large arrays.

    diff --git a/src/main/java/ai/extend/types/BlockDetails.java b/src/main/java/ai/extend/types/BlockDetails.java index 3f4d067..01a3b78 100644 --- a/src/main/java/ai/extend/types/BlockDetails.java +++ b/src/main/java/ai/extend/types/BlockDetails.java @@ -34,18 +34,20 @@ public Object get() { @SuppressWarnings("unchecked") public T visit(Visitor visitor) { if (this.type == 0) { - return visitor.visit((TableDetails) this.value); + return visitor.visit((TextDetails) this.value); } else if (this.type == 1) { - return visitor.visit((TableCellDetails) this.value); + return visitor.visit((TableDetails) this.value); } else if (this.type == 2) { - return visitor.visit((FigureDetails) this.value); + return visitor.visit((TableCellDetails) this.value); } else if (this.type == 3) { - return visitor.visit((BarcodeDetails) this.value); + return visitor.visit((FigureDetails) this.value); } else if (this.type == 4) { - return visitor.visit((FormulaDetails) this.value); + return visitor.visit((BarcodeDetails) this.value); } else if (this.type == 5) { - return visitor.visit((KeyValueDetails) this.value); + return visitor.visit((FormulaDetails) this.value); } else if (this.type == 6) { + return visitor.visit((KeyValueDetails) this.value); + } else if (this.type == 7) { return visitor.visit((Map) this.value); } throw new IllegalStateException("Failed to visit value. This should never happen."); @@ -71,35 +73,41 @@ public String toString() { return this.value.toString(); } - public static BlockDetails of(TableDetails value) { + public static BlockDetails of(TextDetails value) { return new BlockDetails(value, 0); } - public static BlockDetails of(TableCellDetails value) { + public static BlockDetails of(TableDetails value) { return new BlockDetails(value, 1); } - public static BlockDetails of(FigureDetails value) { + public static BlockDetails of(TableCellDetails value) { return new BlockDetails(value, 2); } - public static BlockDetails of(BarcodeDetails value) { + public static BlockDetails of(FigureDetails value) { return new BlockDetails(value, 3); } - public static BlockDetails of(FormulaDetails value) { + public static BlockDetails of(BarcodeDetails value) { return new BlockDetails(value, 4); } - public static BlockDetails of(KeyValueDetails value) { + public static BlockDetails of(FormulaDetails value) { return new BlockDetails(value, 5); } - public static BlockDetails of(Map value) { + public static BlockDetails of(KeyValueDetails value) { return new BlockDetails(value, 6); } + public static BlockDetails of(Map value) { + return new BlockDetails(value, 7); + } + public interface Visitor { + T visit(TextDetails value); + T visit(TableDetails value); T visit(TableCellDetails value); @@ -123,6 +131,10 @@ static final class Deserializer extends StdDeserializer { @java.lang.Override public BlockDetails deserialize(JsonParser p, DeserializationContext context) throws IOException { Object value = p.readValueAs(Object.class); + try { + return of(ObjectMappers.JSON_MAPPER.convertValue(value, TextDetails.class)); + } catch (RuntimeException e) { + } try { return of(ObjectMappers.JSON_MAPPER.convertValue(value, TableDetails.class)); } catch (RuntimeException e) { diff --git a/src/main/java/ai/extend/types/CellFormatting.java b/src/main/java/ai/extend/types/CellFormatting.java new file mode 100644 index 0000000..e494264 --- /dev/null +++ b/src/main/java/ai/extend/types/CellFormatting.java @@ -0,0 +1,193 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package ai.extend.types; + +import ai.extend.core.ObjectMappers; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.annotation.Nulls; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; + +@JsonInclude(JsonInclude.Include.NON_ABSENT) +@JsonDeserialize(builder = CellFormatting.Builder.class) +public final class CellFormatting { + private final Optional bold; + + private final Optional italic; + + private final Optional fontColor; + + private final Optional backgroundColor; + + private final Map additionalProperties; + + private CellFormatting( + Optional bold, + Optional italic, + Optional fontColor, + Optional backgroundColor, + Map additionalProperties) { + this.bold = bold; + this.italic = italic; + this.fontColor = fontColor; + this.backgroundColor = backgroundColor; + this.additionalProperties = additionalProperties; + } + + /** + * @return Whether the cell text is bold. + */ + @JsonProperty("bold") + public Optional getBold() { + return bold; + } + + /** + * @return Whether the cell text is italic. + */ + @JsonProperty("italic") + public Optional getItalic() { + return italic; + } + + /** + * @return Cell font color as a hex string. + */ + @JsonProperty("fontColor") + public Optional getFontColor() { + return fontColor; + } + + /** + * @return Cell background color as a hex string. + */ + @JsonProperty("backgroundColor") + public Optional getBackgroundColor() { + return backgroundColor; + } + + @java.lang.Override + public boolean equals(Object other) { + if (this == other) return true; + return other instanceof CellFormatting && equalTo((CellFormatting) other); + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + private boolean equalTo(CellFormatting other) { + return bold.equals(other.bold) + && italic.equals(other.italic) + && fontColor.equals(other.fontColor) + && backgroundColor.equals(other.backgroundColor); + } + + @java.lang.Override + public int hashCode() { + return Objects.hash(this.bold, this.italic, this.fontColor, this.backgroundColor); + } + + @java.lang.Override + public String toString() { + return ObjectMappers.stringify(this); + } + + public static Builder builder() { + return new Builder(); + } + + @JsonIgnoreProperties(ignoreUnknown = true) + public static final class Builder { + private Optional bold = Optional.empty(); + + private Optional italic = Optional.empty(); + + private Optional fontColor = Optional.empty(); + + private Optional backgroundColor = Optional.empty(); + + @JsonAnySetter + private Map additionalProperties = new HashMap<>(); + + private Builder() {} + + public Builder from(CellFormatting other) { + bold(other.getBold()); + italic(other.getItalic()); + fontColor(other.getFontColor()); + backgroundColor(other.getBackgroundColor()); + return this; + } + + /** + *

    Whether the cell text is bold.

    + */ + @JsonSetter(value = "bold", nulls = Nulls.SKIP) + public Builder bold(Optional bold) { + this.bold = bold; + return this; + } + + public Builder bold(Boolean bold) { + this.bold = Optional.ofNullable(bold); + return this; + } + + /** + *

    Whether the cell text is italic.

    + */ + @JsonSetter(value = "italic", nulls = Nulls.SKIP) + public Builder italic(Optional italic) { + this.italic = italic; + return this; + } + + public Builder italic(Boolean italic) { + this.italic = Optional.ofNullable(italic); + return this; + } + + /** + *

    Cell font color as a hex string.

    + */ + @JsonSetter(value = "fontColor", nulls = Nulls.SKIP) + public Builder fontColor(Optional fontColor) { + this.fontColor = fontColor; + return this; + } + + public Builder fontColor(String fontColor) { + this.fontColor = Optional.ofNullable(fontColor); + return this; + } + + /** + *

    Cell background color as a hex string.

    + */ + @JsonSetter(value = "backgroundColor", nulls = Nulls.SKIP) + public Builder backgroundColor(Optional backgroundColor) { + this.backgroundColor = backgroundColor; + return this; + } + + public Builder backgroundColor(String backgroundColor) { + this.backgroundColor = Optional.ofNullable(backgroundColor); + return this; + } + + public CellFormatting build() { + return new CellFormatting(bold, italic, fontColor, backgroundColor, additionalProperties); + } + } +} diff --git a/src/main/java/ai/extend/types/Citation.java b/src/main/java/ai/extend/types/Citation.java index f021a27..79d15c8 100644 --- a/src/main/java/ai/extend/types/Citation.java +++ b/src/main/java/ai/extend/types/Citation.java @@ -24,6 +24,8 @@ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonDeserialize(builder = Citation.Builder.class) public final class Citation { + private final Optional fileId; + private final Optional page; private final Optional referenceText; @@ -33,16 +35,26 @@ public final class Citation { private final Map additionalProperties; private Citation( + Optional fileId, Optional page, Optional referenceText, Optional> polygon, Map additionalProperties) { + this.fileId = fileId; this.page = page; this.referenceText = referenceText; this.polygon = polygon; this.additionalProperties = additionalProperties; } + /** + * @return ID of the file the cited content was found in. On multifile runs, join this against the run's files array to determine which input file the citation refers to; on single-file runs it equals the run's file.id. + */ + @JsonProperty("fileId") + public Optional getFileId() { + return fileId; + } + @JsonProperty("page") public Optional getPage() { return page; @@ -85,12 +97,15 @@ public Map getAdditionalProperties() { } private boolean equalTo(Citation other) { - return page.equals(other.page) && referenceText.equals(other.referenceText) && polygon.equals(other.polygon); + return fileId.equals(other.fileId) + && page.equals(other.page) + && referenceText.equals(other.referenceText) + && polygon.equals(other.polygon); } @java.lang.Override public int hashCode() { - return Objects.hash(this.page, this.referenceText, this.polygon); + return Objects.hash(this.fileId, this.page, this.referenceText, this.polygon); } @java.lang.Override @@ -104,6 +119,8 @@ public static Builder builder() { @JsonIgnoreProperties(ignoreUnknown = true) public static final class Builder { + private Optional fileId = Optional.empty(); + private Optional page = Optional.empty(); private Optional referenceText = Optional.empty(); @@ -116,12 +133,27 @@ public static final class Builder { private Builder() {} public Builder from(Citation other) { + fileId(other.getFileId()); page(other.getPage()); referenceText(other.getReferenceText()); polygon(other.getPolygon()); return this; } + /** + *

    ID of the file the cited content was found in. On multifile runs, join this against the run's files array to determine which input file the citation refers to; on single-file runs it equals the run's file.id.

    + */ + @JsonSetter(value = "fileId", nulls = Nulls.SKIP) + public Builder fileId(Optional fileId) { + this.fileId = fileId; + return this; + } + + public Builder fileId(String fileId) { + this.fileId = Optional.ofNullable(fileId); + return this; + } + @JsonSetter(value = "page", nulls = Nulls.SKIP) public Builder page(Optional page) { this.page = page; @@ -173,7 +205,7 @@ public Builder polygon(List polygon) { } public Citation build() { - return new Citation(page, referenceText, polygon, additionalProperties); + return new Citation(fileId, page, referenceText, polygon, additionalProperties); } } } diff --git a/src/main/java/ai/extend/types/ClassifyStepDefinition.java b/src/main/java/ai/extend/types/ClassifyStepDefinition.java index e7dde82..3089655 100644 --- a/src/main/java/ai/extend/types/ClassifyStepDefinition.java +++ b/src/main/java/ai/extend/types/ClassifyStepDefinition.java @@ -48,8 +48,8 @@ public String getName() { /** * @return Optional on create/update. Required before the workflow can be deployed. Omitted in responses when the step is not yet configured. - *

    Reference to the classifier used by this step. The next[].classificationId values must match classification id values (not type strings) from the referenced classifier's configuration. For example, if the classifier defines { "id": "cls_invoice", "type": "invoice" }, use "cls_invoice" as the classificationId.

    - *

    The classifier version is required and must be a pinned version (semver like "0.1" or "draft"). "latest" is not allowed.

    + *

    When present, must contain exactly one of classifier (saved processor reference) or classifierConfig (inline configuration) — not both.

    + *

    The next[].classificationId values must match classification id values (not type strings) from the classifier's configuration — the referenced version's config for a saved reference, or the inline classifications array for an inline config. For example, if the classifier defines { "id": "cls_invoice", "type": "invoice" }, use "cls_invoice" as the classificationId.

    *

    See the Classify step docs.

    */ @JsonProperty("config") @@ -58,7 +58,7 @@ public Optional getConfig() { } /** - * @return Can only be set when config is present. Each entry must include a classificationId matching a classification id from the referenced classifier's configuration. Use the classification's stable id (e.g. "cls_invoice"), not the type string. + * @return Can only be set when config is present. Each entry must include a classificationId matching a classification id from the classifier's configuration (saved or inline). Use the classification's stable id (e.g. "cls_invoice"), not the type string. *

    See the Classify step docs.

    */ @JsonProperty("next") @@ -106,8 +106,8 @@ public interface _FinalStage { /** *

    Optional on create/update. Required before the workflow can be deployed. Omitted in responses when the step is not yet configured.

    - *

    Reference to the classifier used by this step. The next[].classificationId values must match classification id values (not type strings) from the referenced classifier's configuration. For example, if the classifier defines { "id": "cls_invoice", "type": "invoice" }, use "cls_invoice" as the classificationId.

    - *

    The classifier version is required and must be a pinned version (semver like "0.1" or "draft"). "latest" is not allowed.

    + *

    When present, must contain exactly one of classifier (saved processor reference) or classifierConfig (inline configuration) — not both.

    + *

    The next[].classificationId values must match classification id values (not type strings) from the classifier's configuration — the referenced version's config for a saved reference, or the inline classifications array for an inline config. For example, if the classifier defines { "id": "cls_invoice", "type": "invoice" }, use "cls_invoice" as the classificationId.

    *

    See the Classify step docs.

    */ _FinalStage config(Optional config); @@ -115,7 +115,7 @@ public interface _FinalStage { _FinalStage config(ClassifyStepDefinitionConfig config); /** - *

    Can only be set when config is present. Each entry must include a classificationId matching a classification id from the referenced classifier's configuration. Use the classification's stable id (e.g. "cls_invoice"), not the type string.

    + *

    Can only be set when config is present. Each entry must include a classificationId matching a classification id from the classifier's configuration (saved or inline). Use the classification's stable id (e.g. "cls_invoice"), not the type string.

    *

    See the Classify step docs.

    */ _FinalStage next(Optional> next); @@ -152,7 +152,7 @@ public _FinalStage name(@NotNull String name) { } /** - *

    Can only be set when config is present. Each entry must include a classificationId matching a classification id from the referenced classifier's configuration. Use the classification's stable id (e.g. "cls_invoice"), not the type string.

    + *

    Can only be set when config is present. Each entry must include a classificationId matching a classification id from the classifier's configuration (saved or inline). Use the classification's stable id (e.g. "cls_invoice"), not the type string.

    *

    See the Classify step docs.

    * @return Reference to {@code this} so that method calls can be chained together. */ @@ -163,7 +163,7 @@ public _FinalStage next(List next) { } /** - *

    Can only be set when config is present. Each entry must include a classificationId matching a classification id from the referenced classifier's configuration. Use the classification's stable id (e.g. "cls_invoice"), not the type string.

    + *

    Can only be set when config is present. Each entry must include a classificationId matching a classification id from the classifier's configuration (saved or inline). Use the classification's stable id (e.g. "cls_invoice"), not the type string.

    *

    See the Classify step docs.

    */ @java.lang.Override @@ -175,8 +175,8 @@ public _FinalStage next(Optional> next) { /** *

    Optional on create/update. Required before the workflow can be deployed. Omitted in responses when the step is not yet configured.

    - *

    Reference to the classifier used by this step. The next[].classificationId values must match classification id values (not type strings) from the referenced classifier's configuration. For example, if the classifier defines { "id": "cls_invoice", "type": "invoice" }, use "cls_invoice" as the classificationId.

    - *

    The classifier version is required and must be a pinned version (semver like "0.1" or "draft"). "latest" is not allowed.

    + *

    When present, must contain exactly one of classifier (saved processor reference) or classifierConfig (inline configuration) — not both.

    + *

    The next[].classificationId values must match classification id values (not type strings) from the classifier's configuration — the referenced version's config for a saved reference, or the inline classifications array for an inline config. For example, if the classifier defines { "id": "cls_invoice", "type": "invoice" }, use "cls_invoice" as the classificationId.

    *

    See the Classify step docs.

    * @return Reference to {@code this} so that method calls can be chained together. */ @@ -188,8 +188,8 @@ public _FinalStage config(ClassifyStepDefinitionConfig config) { /** *

    Optional on create/update. Required before the workflow can be deployed. Omitted in responses when the step is not yet configured.

    - *

    Reference to the classifier used by this step. The next[].classificationId values must match classification id values (not type strings) from the referenced classifier's configuration. For example, if the classifier defines { "id": "cls_invoice", "type": "invoice" }, use "cls_invoice" as the classificationId.

    - *

    The classifier version is required and must be a pinned version (semver like "0.1" or "draft"). "latest" is not allowed.

    + *

    When present, must contain exactly one of classifier (saved processor reference) or classifierConfig (inline configuration) — not both.

    + *

    The next[].classificationId values must match classification id values (not type strings) from the classifier's configuration — the referenced version's config for a saved reference, or the inline classifications array for an inline config. For example, if the classifier defines { "id": "cls_invoice", "type": "invoice" }, use "cls_invoice" as the classificationId.

    *

    See the Classify step docs.

    */ @java.lang.Override diff --git a/src/main/java/ai/extend/types/ClassifyStepDefinitionConfig.java b/src/main/java/ai/extend/types/ClassifyStepDefinitionConfig.java index f10ca54..fca7d2c 100644 --- a/src/main/java/ai/extend/types/ClassifyStepDefinitionConfig.java +++ b/src/main/java/ai/extend/types/ClassifyStepDefinitionConfig.java @@ -10,29 +10,49 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.annotation.Nulls; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import java.util.HashMap; import java.util.Map; import java.util.Objects; -import org.jetbrains.annotations.NotNull; +import java.util.Optional; @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonDeserialize(builder = ClassifyStepDefinitionConfig.Builder.class) public final class ClassifyStepDefinitionConfig { - private final ClassifierRef classifier; + private final Optional classifier; + + private final Optional classifierConfig; private final Map additionalProperties; - private ClassifyStepDefinitionConfig(ClassifierRef classifier, Map additionalProperties) { + private ClassifyStepDefinitionConfig( + Optional classifier, + Optional classifierConfig, + Map additionalProperties) { this.classifier = classifier; + this.classifierConfig = classifierConfig; this.additionalProperties = additionalProperties; } + /** + * @return Reference to a saved classifier. Provide either this or classifierConfig, not both. + *

    The version is required and must be a pinned version (semver like "0.1" or "draft"). "latest" is not allowed.

    + */ @JsonProperty("classifier") - public ClassifierRef getClassifier() { + public Optional getClassifier() { return classifier; } + /** + * @return Inline classifier configuration. Provide either this or classifier, not both. Same shape as the config accepted by Create Classify Run. + *

    Inline configs are returned verbatim in responses (there is no saved processor, so no version is involved).

    + */ + @JsonProperty("classifierConfig") + public Optional getClassifierConfig() { + return classifierConfig; + } + @java.lang.Override public boolean equals(Object other) { if (this == other) return true; @@ -45,12 +65,12 @@ public Map getAdditionalProperties() { } private boolean equalTo(ClassifyStepDefinitionConfig other) { - return classifier.equals(other.classifier); + return classifier.equals(other.classifier) && classifierConfig.equals(other.classifierConfig); } @java.lang.Override public int hashCode() { - return Objects.hash(this.classifier); + return Objects.hash(this.classifier, this.classifierConfig); } @java.lang.Override @@ -58,45 +78,59 @@ public String toString() { return ObjectMappers.stringify(this); } - public static ClassifierStage builder() { + public static Builder builder() { return new Builder(); } - public interface ClassifierStage { - _FinalStage classifier(@NotNull ClassifierRef classifier); - - Builder from(ClassifyStepDefinitionConfig other); - } - - public interface _FinalStage { - ClassifyStepDefinitionConfig build(); - } - @JsonIgnoreProperties(ignoreUnknown = true) - public static final class Builder implements ClassifierStage, _FinalStage { - private ClassifierRef classifier; + public static final class Builder { + private Optional classifier = Optional.empty(); + + private Optional classifierConfig = Optional.empty(); @JsonAnySetter private Map additionalProperties = new HashMap<>(); private Builder() {} - @java.lang.Override public Builder from(ClassifyStepDefinitionConfig other) { classifier(other.getClassifier()); + classifierConfig(other.getClassifierConfig()); + return this; + } + + /** + *

    Reference to a saved classifier. Provide either this or classifierConfig, not both.

    + *

    The version is required and must be a pinned version (semver like "0.1" or "draft"). "latest" is not allowed.

    + */ + @JsonSetter(value = "classifier", nulls = Nulls.SKIP) + public Builder classifier(Optional classifier) { + this.classifier = classifier; + return this; + } + + public Builder classifier(ClassifierRef classifier) { + this.classifier = Optional.ofNullable(classifier); + return this; + } + + /** + *

    Inline classifier configuration. Provide either this or classifier, not both. Same shape as the config accepted by Create Classify Run.

    + *

    Inline configs are returned verbatim in responses (there is no saved processor, so no version is involved).

    + */ + @JsonSetter(value = "classifierConfig", nulls = Nulls.SKIP) + public Builder classifierConfig(Optional classifierConfig) { + this.classifierConfig = classifierConfig; return this; } - @java.lang.Override - @JsonSetter("classifier") - public _FinalStage classifier(@NotNull ClassifierRef classifier) { - this.classifier = Objects.requireNonNull(classifier, "classifier must not be null"); + public Builder classifierConfig(ClassifyConfig classifierConfig) { + this.classifierConfig = Optional.ofNullable(classifierConfig); return this; } - @java.lang.Override public ClassifyStepDefinitionConfig build() { - return new ClassifyStepDefinitionConfig(classifier, additionalProperties); + return new ClassifyStepDefinitionConfig(classifier, classifierConfig, additionalProperties); } } } diff --git a/src/main/java/ai/extend/types/DataRetention.java b/src/main/java/ai/extend/types/DataRetention.java new file mode 100644 index 0000000..d8d0d42 --- /dev/null +++ b/src/main/java/ai/extend/types/DataRetention.java @@ -0,0 +1,109 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package ai.extend.types; + +import ai.extend.core.ObjectMappers; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.annotation.Nulls; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; + +@JsonInclude(JsonInclude.Include.NON_ABSENT) +@JsonDeserialize(builder = DataRetention.Builder.class) +public final class DataRetention { + private final Optional mode; + + private final Map additionalProperties; + + private DataRetention(Optional mode, Map additionalProperties) { + this.mode = mode; + this.additionalProperties = additionalProperties; + } + + /** + * @return The retention mode for this run: + *
      + *
    • workspace_default - Use the workspace's configured retention policy.
    • + *
    • zero - Do not retain supported run data after processing.
    • + *
    + */ + @JsonProperty("mode") + public Optional getMode() { + return mode; + } + + @java.lang.Override + public boolean equals(Object other) { + if (this == other) return true; + return other instanceof DataRetention && equalTo((DataRetention) other); + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + private boolean equalTo(DataRetention other) { + return mode.equals(other.mode); + } + + @java.lang.Override + public int hashCode() { + return Objects.hash(this.mode); + } + + @java.lang.Override + public String toString() { + return ObjectMappers.stringify(this); + } + + public static Builder builder() { + return new Builder(); + } + + @JsonIgnoreProperties(ignoreUnknown = true) + public static final class Builder { + private Optional mode = Optional.empty(); + + @JsonAnySetter + private Map additionalProperties = new HashMap<>(); + + private Builder() {} + + public Builder from(DataRetention other) { + mode(other.getMode()); + return this; + } + + /** + *

    The retention mode for this run:

    + *
      + *
    • workspace_default - Use the workspace's configured retention policy.
    • + *
    • zero - Do not retain supported run data after processing.
    • + *
    + */ + @JsonSetter(value = "mode", nulls = Nulls.SKIP) + public Builder mode(Optional mode) { + this.mode = mode; + return this; + } + + public Builder mode(DataRetentionMode mode) { + this.mode = Optional.ofNullable(mode); + return this; + } + + public DataRetention build() { + return new DataRetention(mode, additionalProperties); + } + } +} diff --git a/src/main/java/ai/extend/types/DataRetentionMode.java b/src/main/java/ai/extend/types/DataRetentionMode.java new file mode 100644 index 0000000..658c6d0 --- /dev/null +++ b/src/main/java/ai/extend/types/DataRetentionMode.java @@ -0,0 +1,84 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package ai.extend.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +public final class DataRetentionMode { + public static final DataRetentionMode WORKSPACE_DEFAULT = + new DataRetentionMode(Value.WORKSPACE_DEFAULT, "workspace_default"); + + public static final DataRetentionMode ZERO = new DataRetentionMode(Value.ZERO, "zero"); + + private final Value value; + + private final String string; + + DataRetentionMode(Value value, String string) { + this.value = value; + this.string = string; + } + + public Value getEnumValue() { + return value; + } + + @java.lang.Override + @JsonValue + public String toString() { + return this.string; + } + + @java.lang.Override + public boolean equals(Object other) { + return (this == other) + || (other instanceof DataRetentionMode && this.string.equals(((DataRetentionMode) other).string)); + } + + @java.lang.Override + public int hashCode() { + return this.string.hashCode(); + } + + public T visit(Visitor visitor) { + switch (value) { + case WORKSPACE_DEFAULT: + return visitor.visitWorkspaceDefault(); + case ZERO: + return visitor.visitZero(); + case UNKNOWN: + default: + return visitor.visitUnknown(string); + } + } + + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static DataRetentionMode valueOf(String value) { + switch (value) { + case "workspace_default": + return WORKSPACE_DEFAULT; + case "zero": + return ZERO; + default: + return new DataRetentionMode(Value.UNKNOWN, value); + } + } + + public enum Value { + WORKSPACE_DEFAULT, + + ZERO, + + UNKNOWN + } + + public interface Visitor { + T visitWorkspaceDefault(); + + T visitZero(); + + T visitUnknown(String unknownType); + } +} diff --git a/src/main/java/ai/extend/types/DetectFormRequestFile.java b/src/main/java/ai/extend/types/DetectFormRequestFile.java new file mode 100644 index 0000000..a28a09e --- /dev/null +++ b/src/main/java/ai/extend/types/DetectFormRequestFile.java @@ -0,0 +1,95 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package ai.extend.types; + +import ai.extend.core.ObjectMappers; +import com.fasterxml.jackson.annotation.JsonValue; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import java.io.IOException; +import java.util.Objects; + +@JsonDeserialize(using = DetectFormRequestFile.Deserializer.class) +public final class DetectFormRequestFile { + private final Object value; + + private final int type; + + private DetectFormRequestFile(Object value, int type) { + this.value = value; + this.type = type; + } + + @JsonValue + public Object get() { + return this.value; + } + + @SuppressWarnings("unchecked") + public T visit(Visitor visitor) { + if (this.type == 0) { + return visitor.visit((FileFromUrl) this.value); + } else if (this.type == 1) { + return visitor.visit((FileFromId) this.value); + } + throw new IllegalStateException("Failed to visit value. This should never happen."); + } + + @java.lang.Override + public boolean equals(Object other) { + if (this == other) return true; + return other instanceof DetectFormRequestFile && equalTo((DetectFormRequestFile) other); + } + + private boolean equalTo(DetectFormRequestFile other) { + return value.equals(other.value); + } + + @java.lang.Override + public int hashCode() { + return Objects.hash(this.value); + } + + @java.lang.Override + public String toString() { + return this.value.toString(); + } + + public static DetectFormRequestFile of(FileFromUrl value) { + return new DetectFormRequestFile(value, 0); + } + + public static DetectFormRequestFile of(FileFromId value) { + return new DetectFormRequestFile(value, 1); + } + + public interface Visitor { + T visit(FileFromUrl value); + + T visit(FileFromId value); + } + + static final class Deserializer extends StdDeserializer { + Deserializer() { + super(DetectFormRequestFile.class); + } + + @java.lang.Override + public DetectFormRequestFile deserialize(JsonParser p, DeserializationContext context) throws IOException { + Object value = p.readValueAs(Object.class); + try { + return of(ObjectMappers.JSON_MAPPER.convertValue(value, FileFromUrl.class)); + } catch (RuntimeException e) { + } + try { + return of(ObjectMappers.JSON_MAPPER.convertValue(value, FileFromId.class)); + } catch (RuntimeException e) { + } + throw new JsonParseException(p, "Failed to deserialize"); + } + } +} diff --git a/src/main/java/ai/extend/types/EditConfigAdvancedOptions.java b/src/main/java/ai/extend/types/EditConfigAdvancedOptions.java index 31288a6..757e353 100644 --- a/src/main/java/ai/extend/types/EditConfigAdvancedOptions.java +++ b/src/main/java/ai/extend/types/EditConfigAdvancedOptions.java @@ -28,6 +28,8 @@ public final class EditConfigAdvancedOptions { private final Optional nativeFieldsOnly; + private final Optional conditionalGenerationEnabled; + private final Map additionalProperties; private EditConfigAdvancedOptions( @@ -35,11 +37,13 @@ private EditConfigAdvancedOptions( Optional flattenPdf, Optional radioEnumsEnabled, Optional nativeFieldsOnly, + Optional conditionalGenerationEnabled, Map additionalProperties) { this.tableParsingEnabled = tableParsingEnabled; this.flattenPdf = flattenPdf; this.radioEnumsEnabled = radioEnumsEnabled; this.nativeFieldsOnly = nativeFieldsOnly; + this.conditionalGenerationEnabled = conditionalGenerationEnabled; this.additionalProperties = additionalProperties; } @@ -75,6 +79,14 @@ public Optional getNativeFieldsOnly() { return nativeFieldsOnly; } + /** + * @return When enabled and no config.schema is supplied, reads requirements explicitly stated in the form and adds supported root-level JSON Schema conditional validation rules to the generated schema. If generated edit values do not satisfy the rules, the Edit run fails with SCHEMA_VALIDATION_ERROR. Has no effect when a schema is supplied. Defaults to false. + */ + @JsonProperty("conditionalGenerationEnabled") + public Optional getConditionalGenerationEnabled() { + return conditionalGenerationEnabled; + } + @java.lang.Override public boolean equals(Object other) { if (this == other) return true; @@ -90,12 +102,18 @@ private boolean equalTo(EditConfigAdvancedOptions other) { return tableParsingEnabled.equals(other.tableParsingEnabled) && flattenPdf.equals(other.flattenPdf) && radioEnumsEnabled.equals(other.radioEnumsEnabled) - && nativeFieldsOnly.equals(other.nativeFieldsOnly); + && nativeFieldsOnly.equals(other.nativeFieldsOnly) + && conditionalGenerationEnabled.equals(other.conditionalGenerationEnabled); } @java.lang.Override public int hashCode() { - return Objects.hash(this.tableParsingEnabled, this.flattenPdf, this.radioEnumsEnabled, this.nativeFieldsOnly); + return Objects.hash( + this.tableParsingEnabled, + this.flattenPdf, + this.radioEnumsEnabled, + this.nativeFieldsOnly, + this.conditionalGenerationEnabled); } @java.lang.Override @@ -117,6 +135,8 @@ public static final class Builder { private Optional nativeFieldsOnly = Optional.empty(); + private Optional conditionalGenerationEnabled = Optional.empty(); + @JsonAnySetter private Map additionalProperties = new HashMap<>(); @@ -127,6 +147,7 @@ public Builder from(EditConfigAdvancedOptions other) { flattenPdf(other.getFlattenPdf()); radioEnumsEnabled(other.getRadioEnumsEnabled()); nativeFieldsOnly(other.getNativeFieldsOnly()); + conditionalGenerationEnabled(other.getConditionalGenerationEnabled()); return this; } @@ -186,9 +207,28 @@ public Builder nativeFieldsOnly(Boolean nativeFieldsOnly) { return this; } + /** + *

    When enabled and no config.schema is supplied, reads requirements explicitly stated in the form and adds supported root-level JSON Schema conditional validation rules to the generated schema. If generated edit values do not satisfy the rules, the Edit run fails with SCHEMA_VALIDATION_ERROR. Has no effect when a schema is supplied. Defaults to false.

    + */ + @JsonSetter(value = "conditionalGenerationEnabled", nulls = Nulls.SKIP) + public Builder conditionalGenerationEnabled(Optional conditionalGenerationEnabled) { + this.conditionalGenerationEnabled = conditionalGenerationEnabled; + return this; + } + + public Builder conditionalGenerationEnabled(Boolean conditionalGenerationEnabled) { + this.conditionalGenerationEnabled = Optional.ofNullable(conditionalGenerationEnabled); + return this; + } + public EditConfigAdvancedOptions build() { return new EditConfigAdvancedOptions( - tableParsingEnabled, flattenPdf, radioEnumsEnabled, nativeFieldsOnly, additionalProperties); + tableParsingEnabled, + flattenPdf, + radioEnumsEnabled, + nativeFieldsOnly, + conditionalGenerationEnabled, + additionalProperties); } } } diff --git a/src/main/java/ai/extend/types/EditRun.java b/src/main/java/ai/extend/types/EditRun.java index ac52df7..1df6920 100644 --- a/src/main/java/ai/extend/types/EditRun.java +++ b/src/main/java/ai/extend/types/EditRun.java @@ -121,6 +121,7 @@ public EditRunStatus getStatus() { *
  • INVALID_OPTIONS - The provided configuration options are invalid
  • *
  • EMPTY_SCHEMA - No schema was provided and no fields could be detected
  • *
  • OUT_OF_CREDITS - Insufficient credits to process the file
  • + *
  • SCHEMA_VALIDATION_ERROR - The generated output value failed validation against the edit schema
  • * *

    Note: Additional failure reasons may be added in the future. Your integration should handle unknown values gracefully.

    */ @@ -319,6 +320,7 @@ public interface _FinalStage { *
  • INVALID_OPTIONS - The provided configuration options are invalid
  • *
  • EMPTY_SCHEMA - No schema was provided and no fields could be detected
  • *
  • OUT_OF_CREDITS - Insufficient credits to process the file
  • + *
  • SCHEMA_VALIDATION_ERROR - The generated output value failed validation against the edit schema
  • * *

    Note: Additional failure reasons may be added in the future. Your integration should handle unknown values gracefully.

    */ @@ -640,6 +642,7 @@ public _FinalStage failureMessage(Optional failureMessage) { *
  • INVALID_OPTIONS - The provided configuration options are invalid
  • *
  • EMPTY_SCHEMA - No schema was provided and no fields could be detected
  • *
  • OUT_OF_CREDITS - Insufficient credits to process the file
  • + *
  • SCHEMA_VALIDATION_ERROR - The generated output value failed validation against the edit schema
  • * *

    Note: Additional failure reasons may be added in the future. Your integration should handle unknown values gracefully.

    * @return Reference to {@code this} so that method calls can be chained together. @@ -672,6 +675,7 @@ public _FinalStage failureReason(Nullable failureReason) { *
  • INVALID_OPTIONS - The provided configuration options are invalid
  • *
  • EMPTY_SCHEMA - No schema was provided and no fields could be detected
  • *
  • OUT_OF_CREDITS - Insufficient credits to process the file
  • + *
  • SCHEMA_VALIDATION_ERROR - The generated output value failed validation against the edit schema
  • * *

    Note: Additional failure reasons may be added in the future. Your integration should handle unknown values gracefully.

    * @return Reference to {@code this} so that method calls can be chained together. @@ -698,6 +702,7 @@ public _FinalStage failureReason(String failureReason) { *
  • INVALID_OPTIONS - The provided configuration options are invalid
  • *
  • EMPTY_SCHEMA - No schema was provided and no fields could be detected
  • *
  • OUT_OF_CREDITS - Insufficient credits to process the file
  • + *
  • SCHEMA_VALIDATION_ERROR - The generated output value failed validation against the edit schema
  • * *

    Note: Additional failure reasons may be added in the future. Your integration should handle unknown values gracefully.

    */ diff --git a/src/main/java/ai/extend/types/EditSchemaGenerationConfigAdvancedOptions.java b/src/main/java/ai/extend/types/EditSchemaGenerationConfigAdvancedOptions.java index 8edbf3e..5d1e42f 100644 --- a/src/main/java/ai/extend/types/EditSchemaGenerationConfigAdvancedOptions.java +++ b/src/main/java/ai/extend/types/EditSchemaGenerationConfigAdvancedOptions.java @@ -26,16 +26,20 @@ public final class EditSchemaGenerationConfigAdvancedOptions { private final Optional nativeFieldsOnly; + private final Optional conditionalGenerationEnabled; + private final Map additionalProperties; private EditSchemaGenerationConfigAdvancedOptions( Optional tableParsingEnabled, Optional radioEnumsEnabled, Optional nativeFieldsOnly, + Optional conditionalGenerationEnabled, Map additionalProperties) { this.tableParsingEnabled = tableParsingEnabled; this.radioEnumsEnabled = radioEnumsEnabled; this.nativeFieldsOnly = nativeFieldsOnly; + this.conditionalGenerationEnabled = conditionalGenerationEnabled; this.additionalProperties = additionalProperties; } @@ -63,6 +67,14 @@ public Optional getNativeFieldsOnly() { return nativeFieldsOnly; } + /** + * @return When enabled, reads requirements explicitly stated in the form and adds supported root-level JSON Schema conditional validation rules to the generated schema. These rules validate form data when the schema is used for an edit; they do not add interactive UI behavior. If generated edit values do not satisfy the rules, the Edit run fails with SCHEMA_VALIDATION_ERROR. Defaults to false. + */ + @JsonProperty("conditionalGenerationEnabled") + public Optional getConditionalGenerationEnabled() { + return conditionalGenerationEnabled; + } + @java.lang.Override public boolean equals(Object other) { if (this == other) return true; @@ -78,12 +90,17 @@ public Map getAdditionalProperties() { private boolean equalTo(EditSchemaGenerationConfigAdvancedOptions other) { return tableParsingEnabled.equals(other.tableParsingEnabled) && radioEnumsEnabled.equals(other.radioEnumsEnabled) - && nativeFieldsOnly.equals(other.nativeFieldsOnly); + && nativeFieldsOnly.equals(other.nativeFieldsOnly) + && conditionalGenerationEnabled.equals(other.conditionalGenerationEnabled); } @java.lang.Override public int hashCode() { - return Objects.hash(this.tableParsingEnabled, this.radioEnumsEnabled, this.nativeFieldsOnly); + return Objects.hash( + this.tableParsingEnabled, + this.radioEnumsEnabled, + this.nativeFieldsOnly, + this.conditionalGenerationEnabled); } @java.lang.Override @@ -103,6 +120,8 @@ public static final class Builder { private Optional nativeFieldsOnly = Optional.empty(); + private Optional conditionalGenerationEnabled = Optional.empty(); + @JsonAnySetter private Map additionalProperties = new HashMap<>(); @@ -112,6 +131,7 @@ public Builder from(EditSchemaGenerationConfigAdvancedOptions other) { tableParsingEnabled(other.getTableParsingEnabled()); radioEnumsEnabled(other.getRadioEnumsEnabled()); nativeFieldsOnly(other.getNativeFieldsOnly()); + conditionalGenerationEnabled(other.getConditionalGenerationEnabled()); return this; } @@ -157,9 +177,27 @@ public Builder nativeFieldsOnly(Boolean nativeFieldsOnly) { return this; } + /** + *

    When enabled, reads requirements explicitly stated in the form and adds supported root-level JSON Schema conditional validation rules to the generated schema. These rules validate form data when the schema is used for an edit; they do not add interactive UI behavior. If generated edit values do not satisfy the rules, the Edit run fails with SCHEMA_VALIDATION_ERROR. Defaults to false.

    + */ + @JsonSetter(value = "conditionalGenerationEnabled", nulls = Nulls.SKIP) + public Builder conditionalGenerationEnabled(Optional conditionalGenerationEnabled) { + this.conditionalGenerationEnabled = conditionalGenerationEnabled; + return this; + } + + public Builder conditionalGenerationEnabled(Boolean conditionalGenerationEnabled) { + this.conditionalGenerationEnabled = Optional.ofNullable(conditionalGenerationEnabled); + return this; + } + public EditSchemaGenerationConfigAdvancedOptions build() { return new EditSchemaGenerationConfigAdvancedOptions( - tableParsingEnabled, radioEnumsEnabled, nativeFieldsOnly, additionalProperties); + tableParsingEnabled, + radioEnumsEnabled, + nativeFieldsOnly, + conditionalGenerationEnabled, + additionalProperties); } } } diff --git a/src/main/java/ai/extend/types/EditTextOptions.java b/src/main/java/ai/extend/types/EditTextOptions.java index 28aef72..02f928f 100644 --- a/src/main/java/ai/extend/types/EditTextOptions.java +++ b/src/main/java/ai/extend/types/EditTextOptions.java @@ -31,6 +31,8 @@ public final class EditTextOptions { private final Optional maxLength; + private final Optional multiLine; + private final Map additionalProperties; private EditTextOptions( @@ -39,12 +41,14 @@ private EditTextOptions( Optional font, Optional combing, Optional maxLength, + Optional multiLine, Map additionalProperties) { this.fontSize = fontSize; this.fontColor = fontColor; this.font = font; this.combing = combing; this.maxLength = maxLength; + this.multiLine = multiLine; this.additionalProperties = additionalProperties; } @@ -88,6 +92,14 @@ public Optional getMaxLength() { return maxLength; } + /** + * @return Whether text can wrap across multiple lines + */ + @JsonProperty("multiLine") + public Optional getMultiLine() { + return multiLine; + } + @java.lang.Override public boolean equals(Object other) { if (this == other) return true; @@ -104,12 +116,13 @@ private boolean equalTo(EditTextOptions other) { && fontColor.equals(other.fontColor) && font.equals(other.font) && combing.equals(other.combing) - && maxLength.equals(other.maxLength); + && maxLength.equals(other.maxLength) + && multiLine.equals(other.multiLine); } @java.lang.Override public int hashCode() { - return Objects.hash(this.fontSize, this.fontColor, this.font, this.combing, this.maxLength); + return Objects.hash(this.fontSize, this.fontColor, this.font, this.combing, this.maxLength, this.multiLine); } @java.lang.Override @@ -133,6 +146,8 @@ public static final class Builder { private Optional maxLength = Optional.empty(); + private Optional multiLine = Optional.empty(); + @JsonAnySetter private Map additionalProperties = new HashMap<>(); @@ -144,6 +159,7 @@ public Builder from(EditTextOptions other) { font(other.getFont()); combing(other.getCombing()); maxLength(other.getMaxLength()); + multiLine(other.getMultiLine()); return this; } @@ -217,8 +233,22 @@ public Builder maxLength(Integer maxLength) { return this; } + /** + *

    Whether text can wrap across multiple lines

    + */ + @JsonSetter(value = "multiLine", nulls = Nulls.SKIP) + public Builder multiLine(Optional multiLine) { + this.multiLine = multiLine; + return this; + } + + public Builder multiLine(Boolean multiLine) { + this.multiLine = Optional.ofNullable(multiLine); + return this; + } + public EditTextOptions build() { - return new EditTextOptions(fontSize, fontColor, font, combing, maxLength, additionalProperties); + return new EditTextOptions(fontSize, fontColor, font, combing, maxLength, multiLine, additionalProperties); } } } diff --git a/src/main/java/ai/extend/types/ExtractAdvancedOptions.java b/src/main/java/ai/extend/types/ExtractAdvancedOptions.java index 00b8971..95d15e9 100644 --- a/src/main/java/ai/extend/types/ExtractAdvancedOptions.java +++ b/src/main/java/ai/extend/types/ExtractAdvancedOptions.java @@ -114,7 +114,11 @@ public Optional getCitationMode() { } /** - * @return Granularity for array citations. This requires citationsEnabled=true and a base processor version that supports property-level array citations (extraction_performance ≥ 4.4.0). + * @return Granularity for array citations. Requires turning on citations: citationsEnabled=true. + *
      + *
    • item: Creates item-level citations for array fields. This will return a single bbox citation for each "item" in the array e.g. line_items[0], line_items[1], etc.
    • + *
    • property: Creates property-level citations (cell-level citations) for array fields. This will return a citation for each property/cell for every item/row in the array, e.g. line_items[0].description, line_items[1].price, etc.
    • + *
    */ @JsonProperty("arrayCitationStrategy") public Optional getArrayCitationStrategy() { @@ -160,6 +164,7 @@ public Optional> getPageRanges() { * When enabled, each field in the output metadata will include a reviewAgentScore (1-5) * and may include additional insights of type issue or review_summary to help identify * fields that may need manual review. + *

    Enabling the review agent incurs additional credits.

    *

    To learn more, view the Review Agent Documentation

    */ @JsonProperty("reviewAgent") @@ -337,7 +342,11 @@ public Builder citationMode(ExtractAdvancedOptionsCitationMode citationMode) { } /** - *

    Granularity for array citations. This requires citationsEnabled=true and a base processor version that supports property-level array citations (extraction_performance ≥ 4.4.0).

    + *

    Granularity for array citations. Requires turning on citations: citationsEnabled=true.

    + *
      + *
    • item: Creates item-level citations for array fields. This will return a single bbox citation for each "item" in the array e.g. line_items[0], line_items[1], etc.
    • + *
    • property: Creates property-level citations (cell-level citations) for array fields. This will return a citation for each property/cell for every item/row in the array, e.g. line_items[0].description, line_items[1].price, etc.
    • + *
    */ @JsonSetter(value = "arrayCitationStrategy", nulls = Nulls.SKIP) public Builder arrayCitationStrategy( @@ -422,6 +431,7 @@ public Builder pageRanges(List pageRanges) { * When enabled, each field in the output metadata will include a reviewAgentScore (1-5) * and may include additional insights of type issue or review_summary to help identify * fields that may need manual review.

    + *

    Enabling the review agent incurs additional credits.

    *

    To learn more, view the Review Agent Documentation

    */ @JsonSetter(value = "reviewAgent", nulls = Nulls.SKIP) diff --git a/src/main/java/ai/extend/types/ExtractStepDefinition.java b/src/main/java/ai/extend/types/ExtractStepDefinition.java index eb9e962..9cb2443 100644 --- a/src/main/java/ai/extend/types/ExtractStepDefinition.java +++ b/src/main/java/ai/extend/types/ExtractStepDefinition.java @@ -48,6 +48,7 @@ public String getName() { /** * @return Optional on create/update. Required before the workflow can be deployed. Omitted in responses when the step is not yet configured. + *

    When present, must contain exactly one of extractor (saved processor reference) or extractorConfig (inline configuration) — not both.

    */ @JsonProperty("config") public Optional getConfig() { @@ -102,6 +103,7 @@ public interface _FinalStage { /** *

    Optional on create/update. Required before the workflow can be deployed. Omitted in responses when the step is not yet configured.

    + *

    When present, must contain exactly one of extractor (saved processor reference) or extractorConfig (inline configuration) — not both.

    */ _FinalStage config(Optional config); @@ -165,6 +167,7 @@ public _FinalStage next(Optional> next) { /** *

    Optional on create/update. Required before the workflow can be deployed. Omitted in responses when the step is not yet configured.

    + *

    When present, must contain exactly one of extractor (saved processor reference) or extractorConfig (inline configuration) — not both.

    * @return Reference to {@code this} so that method calls can be chained together. */ @java.lang.Override @@ -175,6 +178,7 @@ public _FinalStage config(ExtractStepDefinitionConfig config) { /** *

    Optional on create/update. Required before the workflow can be deployed. Omitted in responses when the step is not yet configured.

    + *

    When present, must contain exactly one of extractor (saved processor reference) or extractorConfig (inline configuration) — not both.

    */ @java.lang.Override @JsonSetter(value = "config", nulls = Nulls.SKIP) diff --git a/src/main/java/ai/extend/types/ExtractStepDefinitionConfig.java b/src/main/java/ai/extend/types/ExtractStepDefinitionConfig.java index b714baf..5f26045 100644 --- a/src/main/java/ai/extend/types/ExtractStepDefinitionConfig.java +++ b/src/main/java/ai/extend/types/ExtractStepDefinitionConfig.java @@ -10,29 +10,48 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.annotation.Nulls; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import java.util.HashMap; import java.util.Map; import java.util.Objects; -import org.jetbrains.annotations.NotNull; +import java.util.Optional; @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonDeserialize(builder = ExtractStepDefinitionConfig.Builder.class) public final class ExtractStepDefinitionConfig { - private final ExtractorRef extractor; + private final Optional extractor; + + private final Optional extractorConfig; private final Map additionalProperties; - private ExtractStepDefinitionConfig(ExtractorRef extractor, Map additionalProperties) { + private ExtractStepDefinitionConfig( + Optional extractor, + Optional extractorConfig, + Map additionalProperties) { this.extractor = extractor; + this.extractorConfig = extractorConfig; this.additionalProperties = additionalProperties; } + /** + * @return Reference to a saved extractor. Provide either this or extractorConfig, not both. + */ @JsonProperty("extractor") - public ExtractorRef getExtractor() { + public Optional getExtractor() { return extractor; } + /** + * @return Inline extractor configuration. Provide either this or extractor, not both. Unlike the run endpoints, schema is required — schema-less extraction is not supported in workflows. + *

    Inline configs are returned verbatim in responses (there is no saved processor, so no version is involved).

    + */ + @JsonProperty("extractorConfig") + public Optional getExtractorConfig() { + return extractorConfig; + } + @java.lang.Override public boolean equals(Object other) { if (this == other) return true; @@ -45,12 +64,12 @@ public Map getAdditionalProperties() { } private boolean equalTo(ExtractStepDefinitionConfig other) { - return extractor.equals(other.extractor); + return extractor.equals(other.extractor) && extractorConfig.equals(other.extractorConfig); } @java.lang.Override public int hashCode() { - return Objects.hash(this.extractor); + return Objects.hash(this.extractor, this.extractorConfig); } @java.lang.Override @@ -58,45 +77,58 @@ public String toString() { return ObjectMappers.stringify(this); } - public static ExtractorStage builder() { + public static Builder builder() { return new Builder(); } - public interface ExtractorStage { - _FinalStage extractor(@NotNull ExtractorRef extractor); - - Builder from(ExtractStepDefinitionConfig other); - } - - public interface _FinalStage { - ExtractStepDefinitionConfig build(); - } - @JsonIgnoreProperties(ignoreUnknown = true) - public static final class Builder implements ExtractorStage, _FinalStage { - private ExtractorRef extractor; + public static final class Builder { + private Optional extractor = Optional.empty(); + + private Optional extractorConfig = Optional.empty(); @JsonAnySetter private Map additionalProperties = new HashMap<>(); private Builder() {} - @java.lang.Override public Builder from(ExtractStepDefinitionConfig other) { extractor(other.getExtractor()); + extractorConfig(other.getExtractorConfig()); + return this; + } + + /** + *

    Reference to a saved extractor. Provide either this or extractorConfig, not both.

    + */ + @JsonSetter(value = "extractor", nulls = Nulls.SKIP) + public Builder extractor(Optional extractor) { + this.extractor = extractor; + return this; + } + + public Builder extractor(ExtractorRef extractor) { + this.extractor = Optional.ofNullable(extractor); + return this; + } + + /** + *

    Inline extractor configuration. Provide either this or extractor, not both. Unlike the run endpoints, schema is required — schema-less extraction is not supported in workflows.

    + *

    Inline configs are returned verbatim in responses (there is no saved processor, so no version is involved).

    + */ + @JsonSetter(value = "extractorConfig", nulls = Nulls.SKIP) + public Builder extractorConfig(Optional extractorConfig) { + this.extractorConfig = extractorConfig; return this; } - @java.lang.Override - @JsonSetter("extractor") - public _FinalStage extractor(@NotNull ExtractorRef extractor) { - this.extractor = Objects.requireNonNull(extractor, "extractor must not be null"); + public Builder extractorConfig(WorkflowInlineExtractConfig extractorConfig) { + this.extractorConfig = Optional.ofNullable(extractorConfig); return this; } - @java.lang.Override public ExtractStepDefinitionConfig build() { - return new ExtractStepDefinitionConfig(extractor, additionalProperties); + return new ExtractStepDefinitionConfig(extractor, extractorConfig, additionalProperties); } } } diff --git a/src/main/java/ai/extend/types/FormDetectionRun.java b/src/main/java/ai/extend/types/FormDetectionRun.java new file mode 100644 index 0000000..d55603b --- /dev/null +++ b/src/main/java/ai/extend/types/FormDetectionRun.java @@ -0,0 +1,721 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package ai.extend.types; + +import ai.extend.core.Nullable; +import ai.extend.core.NullableNonemptyFilter; +import ai.extend.core.ObjectMappers; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.annotation.Nulls; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import org.jetbrains.annotations.NotNull; + +@JsonInclude(JsonInclude.Include.NON_ABSENT) +@JsonDeserialize(builder = FormDetectionRun.Builder.class) +public final class FormDetectionRun { + private final String id; + + private final FileSummary file; + + private final FormDetectionRunStatus status; + + private final Optional failureReason; + + private final Optional failureMessage; + + private final EditSchemaGenerationConfig config; + + private final Optional output; + + private final Optional metrics; + + private final Optional usage; + + private final Map additionalProperties; + + private FormDetectionRun( + String id, + FileSummary file, + FormDetectionRunStatus status, + Optional failureReason, + Optional failureMessage, + EditSchemaGenerationConfig config, + Optional output, + Optional metrics, + Optional usage, + Map additionalProperties) { + this.id = id; + this.file = file; + this.status = status; + this.failureReason = failureReason; + this.failureMessage = failureMessage; + this.config = config; + this.output = output; + this.metrics = metrics; + this.usage = usage; + this.additionalProperties = additionalProperties; + } + + /** + * @return The type of object. Will always be "form_detection_run". + */ + @JsonProperty("object") + public String getObject() { + return "form_detection_run"; + } + + /** + * @return A unique identifier for the form detection run. + *

    Example: "sgr_xK9mLPqRtN3vS8wF5hB2cQ"

    + */ + @JsonProperty("id") + public String getId() { + return id; + } + + /** + * @return The input PDF submitted for form detection. + */ + @JsonProperty("file") + public FileSummary getFile() { + return file; + } + + /** + * @return The status of the form detection run: + *
      + *
    • "PROCESSING" - The form is still being analyzed
    • + *
    • "PROCESSED" - Form detection completed successfully
    • + *
    • "FAILED" - Form detection failed (see failureReason for details)
    • + *
    + */ + @JsonProperty("status") + public FormDetectionRunStatus getStatus() { + return status; + } + + /** + * @return The reason for failure. + *

    Availability: Present when status is "FAILED".

    + *

    Possible values include:

    + *
      + *
    • UNABLE_TO_DOWNLOAD_FILE
    • + *
    • FILE_TYPE_NOT_SUPPORTED
    • + *
    • FILE_SIZE_TOO_LARGE
    • + *
    • CORRUPT_FILE
    • + *
    • FIELD_DETECTION_ERROR
    • + *
    • PASSWORD_PROTECTED_FILE
    • + *
    • FAILED_TO_CONVERT_TO_PDF
    • + *
    • EMPTY_SCHEMA
    • + *
    • INTERNAL_ERROR
    • + *
    • INVALID_OPTIONS
    • + *
    • OUT_OF_CREDITS
    • + *
    + *

    Note: Additional failure reasons may be added in the future. Your integration should handle unknown values gracefully.

    + */ + @JsonIgnore + public Optional getFailureReason() { + if (failureReason == null) { + return Optional.empty(); + } + return failureReason; + } + + /** + * @return A human-readable description of the failure. + *

    Availability: Present when status is "FAILED".

    + */ + @JsonIgnore + public Optional getFailureMessage() { + if (failureMessage == null) { + return Optional.empty(); + } + return failureMessage; + } + + /** + * @return The configuration used for this form detection run, including any default values that were applied. + */ + @JsonProperty("config") + public EditSchemaGenerationConfig getConfig() { + return config; + } + + /** + * @return The detected schema and optional mapping metadata. + *

    Availability: Present when status is "PROCESSED".

    + */ + @JsonIgnore + public Optional getOutput() { + if (output == null) { + return Optional.empty(); + } + return output; + } + + /** + * @return Metrics about the form detection process. + *

    Availability: Present when status is "PROCESSED".

    + */ + @JsonIgnore + public Optional getMetrics() { + if (metrics == null) { + return Optional.empty(); + } + return metrics; + } + + /** + * @return Usage credits consumed by this form detection run. + */ + @JsonIgnore + public Optional getUsage() { + if (usage == null) { + return Optional.empty(); + } + return usage; + } + + @JsonInclude(value = JsonInclude.Include.CUSTOM, valueFilter = NullableNonemptyFilter.class) + @JsonProperty("failureReason") + private Optional _getFailureReason() { + return failureReason; + } + + @JsonInclude(value = JsonInclude.Include.CUSTOM, valueFilter = NullableNonemptyFilter.class) + @JsonProperty("failureMessage") + private Optional _getFailureMessage() { + return failureMessage; + } + + @JsonInclude(value = JsonInclude.Include.CUSTOM, valueFilter = NullableNonemptyFilter.class) + @JsonProperty("output") + private Optional _getOutput() { + return output; + } + + @JsonInclude(value = JsonInclude.Include.CUSTOM, valueFilter = NullableNonemptyFilter.class) + @JsonProperty("metrics") + private Optional _getMetrics() { + return metrics; + } + + @JsonInclude(value = JsonInclude.Include.CUSTOM, valueFilter = NullableNonemptyFilter.class) + @JsonProperty("usage") + private Optional _getUsage() { + return usage; + } + + @java.lang.Override + public boolean equals(Object other) { + if (this == other) return true; + return other instanceof FormDetectionRun && equalTo((FormDetectionRun) other); + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + private boolean equalTo(FormDetectionRun other) { + return id.equals(other.id) + && file.equals(other.file) + && status.equals(other.status) + && failureReason.equals(other.failureReason) + && failureMessage.equals(other.failureMessage) + && config.equals(other.config) + && output.equals(other.output) + && metrics.equals(other.metrics) + && usage.equals(other.usage); + } + + @java.lang.Override + public int hashCode() { + return Objects.hash( + this.id, + this.file, + this.status, + this.failureReason, + this.failureMessage, + this.config, + this.output, + this.metrics, + this.usage); + } + + @java.lang.Override + public String toString() { + return ObjectMappers.stringify(this); + } + + public static IdStage builder() { + return new Builder(); + } + + public interface IdStage { + /** + *

    A unique identifier for the form detection run.

    + *

    Example: "sgr_xK9mLPqRtN3vS8wF5hB2cQ"

    + */ + FileStage id(@NotNull String id); + + Builder from(FormDetectionRun other); + } + + public interface FileStage { + /** + *

    The input PDF submitted for form detection.

    + */ + StatusStage file(@NotNull FileSummary file); + } + + public interface StatusStage { + /** + *

    The status of the form detection run:

    + *
      + *
    • "PROCESSING" - The form is still being analyzed
    • + *
    • "PROCESSED" - Form detection completed successfully
    • + *
    • "FAILED" - Form detection failed (see failureReason for details)
    • + *
    + */ + ConfigStage status(@NotNull FormDetectionRunStatus status); + } + + public interface ConfigStage { + /** + *

    The configuration used for this form detection run, including any default values that were applied.

    + */ + _FinalStage config(@NotNull EditSchemaGenerationConfig config); + } + + public interface _FinalStage { + FormDetectionRun build(); + + /** + *

    The reason for failure.

    + *

    Availability: Present when status is "FAILED".

    + *

    Possible values include:

    + *
      + *
    • UNABLE_TO_DOWNLOAD_FILE
    • + *
    • FILE_TYPE_NOT_SUPPORTED
    • + *
    • FILE_SIZE_TOO_LARGE
    • + *
    • CORRUPT_FILE
    • + *
    • FIELD_DETECTION_ERROR
    • + *
    • PASSWORD_PROTECTED_FILE
    • + *
    • FAILED_TO_CONVERT_TO_PDF
    • + *
    • EMPTY_SCHEMA
    • + *
    • INTERNAL_ERROR
    • + *
    • INVALID_OPTIONS
    • + *
    • OUT_OF_CREDITS
    • + *
    + *

    Note: Additional failure reasons may be added in the future. Your integration should handle unknown values gracefully.

    + */ + _FinalStage failureReason(Optional failureReason); + + _FinalStage failureReason(String failureReason); + + _FinalStage failureReason(Nullable failureReason); + + /** + *

    A human-readable description of the failure.

    + *

    Availability: Present when status is "FAILED".

    + */ + _FinalStage failureMessage(Optional failureMessage); + + _FinalStage failureMessage(String failureMessage); + + _FinalStage failureMessage(Nullable failureMessage); + + /** + *

    The detected schema and optional mapping metadata.

    + *

    Availability: Present when status is "PROCESSED".

    + */ + _FinalStage output(Optional output); + + _FinalStage output(EditSchemaGenerationResponse output); + + _FinalStage output(Nullable output); + + /** + *

    Metrics about the form detection process.

    + *

    Availability: Present when status is "PROCESSED".

    + */ + _FinalStage metrics(Optional metrics); + + _FinalStage metrics(FormDetectionRunMetrics metrics); + + _FinalStage metrics(Nullable metrics); + + /** + *

    Usage credits consumed by this form detection run.

    + */ + _FinalStage usage(Optional usage); + + _FinalStage usage(RunUsage usage); + + _FinalStage usage(Nullable usage); + } + + @JsonIgnoreProperties(ignoreUnknown = true) + public static final class Builder implements IdStage, FileStage, StatusStage, ConfigStage, _FinalStage { + private String id; + + private FileSummary file; + + private FormDetectionRunStatus status; + + private EditSchemaGenerationConfig config; + + private Optional usage = Optional.empty(); + + private Optional metrics = Optional.empty(); + + private Optional output = Optional.empty(); + + private Optional failureMessage = Optional.empty(); + + private Optional failureReason = Optional.empty(); + + @JsonAnySetter + private Map additionalProperties = new HashMap<>(); + + private Builder() {} + + @java.lang.Override + public Builder from(FormDetectionRun other) { + id(other.getId()); + file(other.getFile()); + status(other.getStatus()); + failureReason(other.getFailureReason()); + failureMessage(other.getFailureMessage()); + config(other.getConfig()); + output(other.getOutput()); + metrics(other.getMetrics()); + usage(other.getUsage()); + return this; + } + + /** + *

    A unique identifier for the form detection run.

    + *

    Example: "sgr_xK9mLPqRtN3vS8wF5hB2cQ"

    + *

    A unique identifier for the form detection run.

    + *

    Example: "sgr_xK9mLPqRtN3vS8wF5hB2cQ"

    + * @return Reference to {@code this} so that method calls can be chained together. + */ + @java.lang.Override + @JsonSetter("id") + public FileStage id(@NotNull String id) { + this.id = Objects.requireNonNull(id, "id must not be null"); + return this; + } + + /** + *

    The input PDF submitted for form detection.

    + *

    The input PDF submitted for form detection.

    + * @return Reference to {@code this} so that method calls can be chained together. + */ + @java.lang.Override + @JsonSetter("file") + public StatusStage file(@NotNull FileSummary file) { + this.file = Objects.requireNonNull(file, "file must not be null"); + return this; + } + + /** + *

    The status of the form detection run:

    + *
      + *
    • "PROCESSING" - The form is still being analyzed
    • + *
    • "PROCESSED" - Form detection completed successfully
    • + *
    • "FAILED" - Form detection failed (see failureReason for details)
    • + *
    + *

    The status of the form detection run:

    + *
      + *
    • "PROCESSING" - The form is still being analyzed
    • + *
    • "PROCESSED" - Form detection completed successfully
    • + *
    • "FAILED" - Form detection failed (see failureReason for details)
    • + *
    + * @return Reference to {@code this} so that method calls can be chained together. + */ + @java.lang.Override + @JsonSetter("status") + public ConfigStage status(@NotNull FormDetectionRunStatus status) { + this.status = Objects.requireNonNull(status, "status must not be null"); + return this; + } + + /** + *

    The configuration used for this form detection run, including any default values that were applied.

    + *

    The configuration used for this form detection run, including any default values that were applied.

    + * @return Reference to {@code this} so that method calls can be chained together. + */ + @java.lang.Override + @JsonSetter("config") + public _FinalStage config(@NotNull EditSchemaGenerationConfig config) { + this.config = Objects.requireNonNull(config, "config must not be null"); + return this; + } + + /** + *

    Usage credits consumed by this form detection run.

    + * @return Reference to {@code this} so that method calls can be chained together. + */ + @java.lang.Override + public _FinalStage usage(Nullable usage) { + if (usage.isNull()) { + this.usage = null; + } else if (usage.isEmpty()) { + this.usage = Optional.empty(); + } else { + this.usage = Optional.of(usage.get()); + } + return this; + } + + /** + *

    Usage credits consumed by this form detection run.

    + * @return Reference to {@code this} so that method calls can be chained together. + */ + @java.lang.Override + public _FinalStage usage(RunUsage usage) { + this.usage = Optional.ofNullable(usage); + return this; + } + + /** + *

    Usage credits consumed by this form detection run.

    + */ + @java.lang.Override + @JsonSetter(value = "usage", nulls = Nulls.SKIP) + public _FinalStage usage(Optional usage) { + this.usage = usage; + return this; + } + + /** + *

    Metrics about the form detection process.

    + *

    Availability: Present when status is "PROCESSED".

    + * @return Reference to {@code this} so that method calls can be chained together. + */ + @java.lang.Override + public _FinalStage metrics(Nullable metrics) { + if (metrics.isNull()) { + this.metrics = null; + } else if (metrics.isEmpty()) { + this.metrics = Optional.empty(); + } else { + this.metrics = Optional.of(metrics.get()); + } + return this; + } + + /** + *

    Metrics about the form detection process.

    + *

    Availability: Present when status is "PROCESSED".

    + * @return Reference to {@code this} so that method calls can be chained together. + */ + @java.lang.Override + public _FinalStage metrics(FormDetectionRunMetrics metrics) { + this.metrics = Optional.ofNullable(metrics); + return this; + } + + /** + *

    Metrics about the form detection process.

    + *

    Availability: Present when status is "PROCESSED".

    + */ + @java.lang.Override + @JsonSetter(value = "metrics", nulls = Nulls.SKIP) + public _FinalStage metrics(Optional metrics) { + this.metrics = metrics; + return this; + } + + /** + *

    The detected schema and optional mapping metadata.

    + *

    Availability: Present when status is "PROCESSED".

    + * @return Reference to {@code this} so that method calls can be chained together. + */ + @java.lang.Override + public _FinalStage output(Nullable output) { + if (output.isNull()) { + this.output = null; + } else if (output.isEmpty()) { + this.output = Optional.empty(); + } else { + this.output = Optional.of(output.get()); + } + return this; + } + + /** + *

    The detected schema and optional mapping metadata.

    + *

    Availability: Present when status is "PROCESSED".

    + * @return Reference to {@code this} so that method calls can be chained together. + */ + @java.lang.Override + public _FinalStage output(EditSchemaGenerationResponse output) { + this.output = Optional.ofNullable(output); + return this; + } + + /** + *

    The detected schema and optional mapping metadata.

    + *

    Availability: Present when status is "PROCESSED".

    + */ + @java.lang.Override + @JsonSetter(value = "output", nulls = Nulls.SKIP) + public _FinalStage output(Optional output) { + this.output = output; + return this; + } + + /** + *

    A human-readable description of the failure.

    + *

    Availability: Present when status is "FAILED".

    + * @return Reference to {@code this} so that method calls can be chained together. + */ + @java.lang.Override + public _FinalStage failureMessage(Nullable failureMessage) { + if (failureMessage.isNull()) { + this.failureMessage = null; + } else if (failureMessage.isEmpty()) { + this.failureMessage = Optional.empty(); + } else { + this.failureMessage = Optional.of(failureMessage.get()); + } + return this; + } + + /** + *

    A human-readable description of the failure.

    + *

    Availability: Present when status is "FAILED".

    + * @return Reference to {@code this} so that method calls can be chained together. + */ + @java.lang.Override + public _FinalStage failureMessage(String failureMessage) { + this.failureMessage = Optional.ofNullable(failureMessage); + return this; + } + + /** + *

    A human-readable description of the failure.

    + *

    Availability: Present when status is "FAILED".

    + */ + @java.lang.Override + @JsonSetter(value = "failureMessage", nulls = Nulls.SKIP) + public _FinalStage failureMessage(Optional failureMessage) { + this.failureMessage = failureMessage; + return this; + } + + /** + *

    The reason for failure.

    + *

    Availability: Present when status is "FAILED".

    + *

    Possible values include:

    + *
      + *
    • UNABLE_TO_DOWNLOAD_FILE
    • + *
    • FILE_TYPE_NOT_SUPPORTED
    • + *
    • FILE_SIZE_TOO_LARGE
    • + *
    • CORRUPT_FILE
    • + *
    • FIELD_DETECTION_ERROR
    • + *
    • PASSWORD_PROTECTED_FILE
    • + *
    • FAILED_TO_CONVERT_TO_PDF
    • + *
    • EMPTY_SCHEMA
    • + *
    • INTERNAL_ERROR
    • + *
    • INVALID_OPTIONS
    • + *
    • OUT_OF_CREDITS
    • + *
    + *

    Note: Additional failure reasons may be added in the future. Your integration should handle unknown values gracefully.

    + * @return Reference to {@code this} so that method calls can be chained together. + */ + @java.lang.Override + public _FinalStage failureReason(Nullable failureReason) { + if (failureReason.isNull()) { + this.failureReason = null; + } else if (failureReason.isEmpty()) { + this.failureReason = Optional.empty(); + } else { + this.failureReason = Optional.of(failureReason.get()); + } + return this; + } + + /** + *

    The reason for failure.

    + *

    Availability: Present when status is "FAILED".

    + *

    Possible values include:

    + *
      + *
    • UNABLE_TO_DOWNLOAD_FILE
    • + *
    • FILE_TYPE_NOT_SUPPORTED
    • + *
    • FILE_SIZE_TOO_LARGE
    • + *
    • CORRUPT_FILE
    • + *
    • FIELD_DETECTION_ERROR
    • + *
    • PASSWORD_PROTECTED_FILE
    • + *
    • FAILED_TO_CONVERT_TO_PDF
    • + *
    • EMPTY_SCHEMA
    • + *
    • INTERNAL_ERROR
    • + *
    • INVALID_OPTIONS
    • + *
    • OUT_OF_CREDITS
    • + *
    + *

    Note: Additional failure reasons may be added in the future. Your integration should handle unknown values gracefully.

    + * @return Reference to {@code this} so that method calls can be chained together. + */ + @java.lang.Override + public _FinalStage failureReason(String failureReason) { + this.failureReason = Optional.ofNullable(failureReason); + return this; + } + + /** + *

    The reason for failure.

    + *

    Availability: Present when status is "FAILED".

    + *

    Possible values include:

    + *
      + *
    • UNABLE_TO_DOWNLOAD_FILE
    • + *
    • FILE_TYPE_NOT_SUPPORTED
    • + *
    • FILE_SIZE_TOO_LARGE
    • + *
    • CORRUPT_FILE
    • + *
    • FIELD_DETECTION_ERROR
    • + *
    • PASSWORD_PROTECTED_FILE
    • + *
    • FAILED_TO_CONVERT_TO_PDF
    • + *
    • EMPTY_SCHEMA
    • + *
    • INTERNAL_ERROR
    • + *
    • INVALID_OPTIONS
    • + *
    • OUT_OF_CREDITS
    • + *
    + *

    Note: Additional failure reasons may be added in the future. Your integration should handle unknown values gracefully.

    + */ + @java.lang.Override + @JsonSetter(value = "failureReason", nulls = Nulls.SKIP) + public _FinalStage failureReason(Optional failureReason) { + this.failureReason = failureReason; + return this; + } + + @java.lang.Override + public FormDetectionRun build() { + return new FormDetectionRun( + id, + file, + status, + failureReason, + failureMessage, + config, + output, + metrics, + usage, + additionalProperties); + } + } +} diff --git a/src/main/java/ai/extend/types/FormDetectionRunMetrics.java b/src/main/java/ai/extend/types/FormDetectionRunMetrics.java new file mode 100644 index 0000000..8613ea5 --- /dev/null +++ b/src/main/java/ai/extend/types/FormDetectionRunMetrics.java @@ -0,0 +1,347 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package ai.extend.types; + +import ai.extend.core.ObjectMappers; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +@JsonInclude(JsonInclude.Include.NON_ABSENT) +@JsonDeserialize(builder = FormDetectionRunMetrics.Builder.class) +public final class FormDetectionRunMetrics { + private final double processingTimeMs; + + private final int pageCount; + + private final int fieldCount; + + private final int fieldsDetectedCount; + + private final int fieldsAnnotatedCount; + + private final double fieldDetectionTimeMs; + + private final double fieldAnnotationTimeMs; + + private final Map additionalProperties; + + private FormDetectionRunMetrics( + double processingTimeMs, + int pageCount, + int fieldCount, + int fieldsDetectedCount, + int fieldsAnnotatedCount, + double fieldDetectionTimeMs, + double fieldAnnotationTimeMs, + Map additionalProperties) { + this.processingTimeMs = processingTimeMs; + this.pageCount = pageCount; + this.fieldCount = fieldCount; + this.fieldsDetectedCount = fieldsDetectedCount; + this.fieldsAnnotatedCount = fieldsAnnotatedCount; + this.fieldDetectionTimeMs = fieldDetectionTimeMs; + this.fieldAnnotationTimeMs = fieldAnnotationTimeMs; + this.additionalProperties = additionalProperties; + } + + /** + * @return Total processing time in milliseconds. + */ + @JsonProperty("processingTimeMs") + public double getProcessingTimeMs() { + return processingTimeMs; + } + + /** + * @return The number of pages in the document. + */ + @JsonProperty("pageCount") + public int getPageCount() { + return pageCount; + } + + /** + * @return The total number of fields in the generated schema. + */ + @JsonProperty("fieldCount") + public int getFieldCount() { + return fieldCount; + } + + /** + * @return The number of fields that were automatically detected. + */ + @JsonProperty("fieldsDetectedCount") + public int getFieldsDetectedCount() { + return fieldsDetectedCount; + } + + /** + * @return The number of fields annotated with positions. + */ + @JsonProperty("fieldsAnnotatedCount") + public int getFieldsAnnotatedCount() { + return fieldsAnnotatedCount; + } + + /** + * @return The time taken to detect fields, in milliseconds. + */ + @JsonProperty("fieldDetectionTimeMs") + public double getFieldDetectionTimeMs() { + return fieldDetectionTimeMs; + } + + /** + * @return The time taken to annotate field positions, in milliseconds. + */ + @JsonProperty("fieldAnnotationTimeMs") + public double getFieldAnnotationTimeMs() { + return fieldAnnotationTimeMs; + } + + @java.lang.Override + public boolean equals(Object other) { + if (this == other) return true; + return other instanceof FormDetectionRunMetrics && equalTo((FormDetectionRunMetrics) other); + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + private boolean equalTo(FormDetectionRunMetrics other) { + return processingTimeMs == other.processingTimeMs + && pageCount == other.pageCount + && fieldCount == other.fieldCount + && fieldsDetectedCount == other.fieldsDetectedCount + && fieldsAnnotatedCount == other.fieldsAnnotatedCount + && fieldDetectionTimeMs == other.fieldDetectionTimeMs + && fieldAnnotationTimeMs == other.fieldAnnotationTimeMs; + } + + @java.lang.Override + public int hashCode() { + return Objects.hash( + this.processingTimeMs, + this.pageCount, + this.fieldCount, + this.fieldsDetectedCount, + this.fieldsAnnotatedCount, + this.fieldDetectionTimeMs, + this.fieldAnnotationTimeMs); + } + + @java.lang.Override + public String toString() { + return ObjectMappers.stringify(this); + } + + public static ProcessingTimeMsStage builder() { + return new Builder(); + } + + public interface ProcessingTimeMsStage { + /** + *

    Total processing time in milliseconds.

    + */ + PageCountStage processingTimeMs(double processingTimeMs); + + Builder from(FormDetectionRunMetrics other); + } + + public interface PageCountStage { + /** + *

    The number of pages in the document.

    + */ + FieldCountStage pageCount(int pageCount); + } + + public interface FieldCountStage { + /** + *

    The total number of fields in the generated schema.

    + */ + FieldsDetectedCountStage fieldCount(int fieldCount); + } + + public interface FieldsDetectedCountStage { + /** + *

    The number of fields that were automatically detected.

    + */ + FieldsAnnotatedCountStage fieldsDetectedCount(int fieldsDetectedCount); + } + + public interface FieldsAnnotatedCountStage { + /** + *

    The number of fields annotated with positions.

    + */ + FieldDetectionTimeMsStage fieldsAnnotatedCount(int fieldsAnnotatedCount); + } + + public interface FieldDetectionTimeMsStage { + /** + *

    The time taken to detect fields, in milliseconds.

    + */ + FieldAnnotationTimeMsStage fieldDetectionTimeMs(double fieldDetectionTimeMs); + } + + public interface FieldAnnotationTimeMsStage { + /** + *

    The time taken to annotate field positions, in milliseconds.

    + */ + _FinalStage fieldAnnotationTimeMs(double fieldAnnotationTimeMs); + } + + public interface _FinalStage { + FormDetectionRunMetrics build(); + } + + @JsonIgnoreProperties(ignoreUnknown = true) + public static final class Builder + implements ProcessingTimeMsStage, + PageCountStage, + FieldCountStage, + FieldsDetectedCountStage, + FieldsAnnotatedCountStage, + FieldDetectionTimeMsStage, + FieldAnnotationTimeMsStage, + _FinalStage { + private double processingTimeMs; + + private int pageCount; + + private int fieldCount; + + private int fieldsDetectedCount; + + private int fieldsAnnotatedCount; + + private double fieldDetectionTimeMs; + + private double fieldAnnotationTimeMs; + + @JsonAnySetter + private Map additionalProperties = new HashMap<>(); + + private Builder() {} + + @java.lang.Override + public Builder from(FormDetectionRunMetrics other) { + processingTimeMs(other.getProcessingTimeMs()); + pageCount(other.getPageCount()); + fieldCount(other.getFieldCount()); + fieldsDetectedCount(other.getFieldsDetectedCount()); + fieldsAnnotatedCount(other.getFieldsAnnotatedCount()); + fieldDetectionTimeMs(other.getFieldDetectionTimeMs()); + fieldAnnotationTimeMs(other.getFieldAnnotationTimeMs()); + return this; + } + + /** + *

    Total processing time in milliseconds.

    + *

    Total processing time in milliseconds.

    + * @return Reference to {@code this} so that method calls can be chained together. + */ + @java.lang.Override + @JsonSetter("processingTimeMs") + public PageCountStage processingTimeMs(double processingTimeMs) { + this.processingTimeMs = processingTimeMs; + return this; + } + + /** + *

    The number of pages in the document.

    + *

    The number of pages in the document.

    + * @return Reference to {@code this} so that method calls can be chained together. + */ + @java.lang.Override + @JsonSetter("pageCount") + public FieldCountStage pageCount(int pageCount) { + this.pageCount = pageCount; + return this; + } + + /** + *

    The total number of fields in the generated schema.

    + *

    The total number of fields in the generated schema.

    + * @return Reference to {@code this} so that method calls can be chained together. + */ + @java.lang.Override + @JsonSetter("fieldCount") + public FieldsDetectedCountStage fieldCount(int fieldCount) { + this.fieldCount = fieldCount; + return this; + } + + /** + *

    The number of fields that were automatically detected.

    + *

    The number of fields that were automatically detected.

    + * @return Reference to {@code this} so that method calls can be chained together. + */ + @java.lang.Override + @JsonSetter("fieldsDetectedCount") + public FieldsAnnotatedCountStage fieldsDetectedCount(int fieldsDetectedCount) { + this.fieldsDetectedCount = fieldsDetectedCount; + return this; + } + + /** + *

    The number of fields annotated with positions.

    + *

    The number of fields annotated with positions.

    + * @return Reference to {@code this} so that method calls can be chained together. + */ + @java.lang.Override + @JsonSetter("fieldsAnnotatedCount") + public FieldDetectionTimeMsStage fieldsAnnotatedCount(int fieldsAnnotatedCount) { + this.fieldsAnnotatedCount = fieldsAnnotatedCount; + return this; + } + + /** + *

    The time taken to detect fields, in milliseconds.

    + *

    The time taken to detect fields, in milliseconds.

    + * @return Reference to {@code this} so that method calls can be chained together. + */ + @java.lang.Override + @JsonSetter("fieldDetectionTimeMs") + public FieldAnnotationTimeMsStage fieldDetectionTimeMs(double fieldDetectionTimeMs) { + this.fieldDetectionTimeMs = fieldDetectionTimeMs; + return this; + } + + /** + *

    The time taken to annotate field positions, in milliseconds.

    + *

    The time taken to annotate field positions, in milliseconds.

    + * @return Reference to {@code this} so that method calls can be chained together. + */ + @java.lang.Override + @JsonSetter("fieldAnnotationTimeMs") + public _FinalStage fieldAnnotationTimeMs(double fieldAnnotationTimeMs) { + this.fieldAnnotationTimeMs = fieldAnnotationTimeMs; + return this; + } + + @java.lang.Override + public FormDetectionRunMetrics build() { + return new FormDetectionRunMetrics( + processingTimeMs, + pageCount, + fieldCount, + fieldsDetectedCount, + fieldsAnnotatedCount, + fieldDetectionTimeMs, + fieldAnnotationTimeMs, + additionalProperties); + } + } +} diff --git a/src/main/java/ai/extend/types/FormDetectionRunStatus.java b/src/main/java/ai/extend/types/FormDetectionRunStatus.java new file mode 100644 index 0000000..6750924 --- /dev/null +++ b/src/main/java/ai/extend/types/FormDetectionRunStatus.java @@ -0,0 +1,94 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package ai.extend.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +public final class FormDetectionRunStatus { + public static final FormDetectionRunStatus PROCESSING = new FormDetectionRunStatus(Value.PROCESSING, "PROCESSING"); + + public static final FormDetectionRunStatus PROCESSED = new FormDetectionRunStatus(Value.PROCESSED, "PROCESSED"); + + public static final FormDetectionRunStatus FAILED = new FormDetectionRunStatus(Value.FAILED, "FAILED"); + + private final Value value; + + private final String string; + + FormDetectionRunStatus(Value value, String string) { + this.value = value; + this.string = string; + } + + public Value getEnumValue() { + return value; + } + + @java.lang.Override + @JsonValue + public String toString() { + return this.string; + } + + @java.lang.Override + public boolean equals(Object other) { + return (this == other) + || (other instanceof FormDetectionRunStatus + && this.string.equals(((FormDetectionRunStatus) other).string)); + } + + @java.lang.Override + public int hashCode() { + return this.string.hashCode(); + } + + public T visit(Visitor visitor) { + switch (value) { + case PROCESSING: + return visitor.visitProcessing(); + case PROCESSED: + return visitor.visitProcessed(); + case FAILED: + return visitor.visitFailed(); + case UNKNOWN: + default: + return visitor.visitUnknown(string); + } + } + + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static FormDetectionRunStatus valueOf(String value) { + switch (value) { + case "PROCESSING": + return PROCESSING; + case "PROCESSED": + return PROCESSED; + case "FAILED": + return FAILED; + default: + return new FormDetectionRunStatus(Value.UNKNOWN, value); + } + } + + public enum Value { + PROCESSING, + + PROCESSED, + + FAILED, + + UNKNOWN + } + + public interface Visitor { + T visitProcessing(); + + T visitProcessed(); + + T visitFailed(); + + T visitUnknown(String unknownType); + } +} diff --git a/src/main/java/ai/extend/types/LegacyExtractionAdvancedOptions.java b/src/main/java/ai/extend/types/LegacyExtractionAdvancedOptions.java index 22357a7..71e093c 100644 --- a/src/main/java/ai/extend/types/LegacyExtractionAdvancedOptions.java +++ b/src/main/java/ai/extend/types/LegacyExtractionAdvancedOptions.java @@ -145,6 +145,7 @@ public Optional getAdvancedFigureParsingEnabled() { * When enabled, each field in the output metadata will include a reviewAgentScore (1-5) * and may include additional insights of type issue or review_summary to help identify * fields that may need manual review. + *

    Enabling the review agent incurs additional credits.

    *

    To learn more, view the Review Agent Documentation

    */ @JsonProperty("reviewAgent") @@ -409,6 +410,7 @@ public Builder advancedFigureParsingEnabled(Boolean advancedFigureParsingEnabled * When enabled, each field in the output metadata will include a reviewAgentScore (1-5) * and may include additional insights of type issue or review_summary to help identify * fields that may need manual review.

    + *

    Enabling the review agent incurs additional credits.

    *

    To learn more, view the Review Agent Documentation

    */ @JsonSetter(value = "reviewAgent", nulls = Nulls.SKIP) diff --git a/src/main/java/ai/extend/types/ParseConfigAdvancedOptions.java b/src/main/java/ai/extend/types/ParseConfigAdvancedOptions.java index 372c5b3..274016d 100644 --- a/src/main/java/ai/extend/types/ParseConfigAdvancedOptions.java +++ b/src/main/java/ai/extend/types/ParseConfigAdvancedOptions.java @@ -33,6 +33,10 @@ public final class ParseConfigAdvancedOptions { private final Optional excelSkipCalculation; + private final Optional excelIncludeCellMetadata; + + private final Optional excelIncludeCellFormatting; + private final Optional verticalGroupingThreshold; private final Optional returnOcr; @@ -54,6 +58,8 @@ private ParseConfigAdvancedOptions( Optional excelSkipHiddenContent, Optional excelUseRawCellValues, Optional excelSkipCalculation, + Optional excelIncludeCellMetadata, + Optional excelIncludeCellFormatting, Optional verticalGroupingThreshold, Optional returnOcr, Optional alwaysConvertToPdf, @@ -67,6 +73,8 @@ private ParseConfigAdvancedOptions( this.excelSkipHiddenContent = excelSkipHiddenContent; this.excelUseRawCellValues = excelUseRawCellValues; this.excelSkipCalculation = excelSkipCalculation; + this.excelIncludeCellMetadata = excelIncludeCellMetadata; + this.excelIncludeCellFormatting = excelIncludeCellFormatting; this.verticalGroupingThreshold = verticalGroupingThreshold; this.returnOcr = returnOcr; this.alwaysConvertToPdf = alwaysConvertToPdf; @@ -93,7 +101,7 @@ public Optional> getPageRanges() { * @return Controls how Excel files are parsed. *
      *
    • basic: Fast, deterministic parsing.
    • - *
    • advanced: Enable layout block detection for complex spreadsheets.
    • + *
    • advanced: Enable layout block detection for complex spreadsheets. This mode incurs additional credits when enabled.
    • *
    *

    For .xls files, basic mode is always used.

    */ @@ -126,6 +134,22 @@ public Optional getExcelSkipCalculation() { return excelSkipCalculation; } + /** + * @return Whether to include spreadsheet cell provenance when parsing Excel files in advanced mode. When enabled, table cell block details include source cell references and formulas, text or heading block details can include source ranges, and HTML table output includes data-cell and data-formula attributes. + */ + @JsonProperty("excelIncludeCellMetadata") + public Optional getExcelIncludeCellMetadata() { + return excelIncludeCellMetadata; + } + + /** + * @return Whether to include spreadsheet cell formatting when parsing Excel files in advanced mode. When enabled, table cell block details include structured formatting such as bold, italic, font color, and background color, and HTML table output preserves inline cell styles. + */ + @JsonProperty("excelIncludeCellFormatting") + public Optional getExcelIncludeCellFormatting() { + return excelIncludeCellFormatting; + } + /** * @return Multiplier for the Y-axis threshold used to determine if text blocks should be placed on the same line or not (0.1-5.0, default 1.0). Higher values group elements that are further apart vertically. Only applies when the spatial target is set. */ @@ -204,6 +228,8 @@ private boolean equalTo(ParseConfigAdvancedOptions other) { && excelSkipHiddenContent.equals(other.excelSkipHiddenContent) && excelUseRawCellValues.equals(other.excelUseRawCellValues) && excelSkipCalculation.equals(other.excelSkipCalculation) + && excelIncludeCellMetadata.equals(other.excelIncludeCellMetadata) + && excelIncludeCellFormatting.equals(other.excelIncludeCellFormatting) && verticalGroupingThreshold.equals(other.verticalGroupingThreshold) && returnOcr.equals(other.returnOcr) && alwaysConvertToPdf.equals(other.alwaysConvertToPdf) @@ -221,6 +247,8 @@ public int hashCode() { this.excelSkipHiddenContent, this.excelUseRawCellValues, this.excelSkipCalculation, + this.excelIncludeCellMetadata, + this.excelIncludeCellFormatting, this.verticalGroupingThreshold, this.returnOcr, this.alwaysConvertToPdf, @@ -252,6 +280,10 @@ public static final class Builder { private Optional excelSkipCalculation = Optional.empty(); + private Optional excelIncludeCellMetadata = Optional.empty(); + + private Optional excelIncludeCellFormatting = Optional.empty(); + private Optional verticalGroupingThreshold = Optional.empty(); private Optional returnOcr = Optional.empty(); @@ -277,6 +309,8 @@ public Builder from(ParseConfigAdvancedOptions other) { excelSkipHiddenContent(other.getExcelSkipHiddenContent()); excelUseRawCellValues(other.getExcelUseRawCellValues()); excelSkipCalculation(other.getExcelSkipCalculation()); + excelIncludeCellMetadata(other.getExcelIncludeCellMetadata()); + excelIncludeCellFormatting(other.getExcelIncludeCellFormatting()); verticalGroupingThreshold(other.getVerticalGroupingThreshold()); returnOcr(other.getReturnOcr()); alwaysConvertToPdf(other.getAlwaysConvertToPdf()); @@ -315,7 +349,7 @@ public Builder pageRanges(List pageRanges) { *

    Controls how Excel files are parsed.

    *
      *
    • basic: Fast, deterministic parsing.
    • - *
    • advanced: Enable layout block detection for complex spreadsheets.
    • + *
    • advanced: Enable layout block detection for complex spreadsheets. This mode incurs additional credits when enabled.
    • *
    *

    For .xls files, basic mode is always used.

    */ @@ -372,6 +406,34 @@ public Builder excelSkipCalculation(Boolean excelSkipCalculation) { return this; } + /** + *

    Whether to include spreadsheet cell provenance when parsing Excel files in advanced mode. When enabled, table cell block details include source cell references and formulas, text or heading block details can include source ranges, and HTML table output includes data-cell and data-formula attributes.

    + */ + @JsonSetter(value = "excelIncludeCellMetadata", nulls = Nulls.SKIP) + public Builder excelIncludeCellMetadata(Optional excelIncludeCellMetadata) { + this.excelIncludeCellMetadata = excelIncludeCellMetadata; + return this; + } + + public Builder excelIncludeCellMetadata(Boolean excelIncludeCellMetadata) { + this.excelIncludeCellMetadata = Optional.ofNullable(excelIncludeCellMetadata); + return this; + } + + /** + *

    Whether to include spreadsheet cell formatting when parsing Excel files in advanced mode. When enabled, table cell block details include structured formatting such as bold, italic, font color, and background color, and HTML table output preserves inline cell styles.

    + */ + @JsonSetter(value = "excelIncludeCellFormatting", nulls = Nulls.SKIP) + public Builder excelIncludeCellFormatting(Optional excelIncludeCellFormatting) { + this.excelIncludeCellFormatting = excelIncludeCellFormatting; + return this; + } + + public Builder excelIncludeCellFormatting(Boolean excelIncludeCellFormatting) { + this.excelIncludeCellFormatting = Optional.ofNullable(excelIncludeCellFormatting); + return this; + } + /** *

    Multiplier for the Y-axis threshold used to determine if text blocks should be placed on the same line or not (0.1-5.0, default 1.0). Higher values group elements that are further apart vertically. Only applies when the spatial target is set.

    */ @@ -479,6 +541,8 @@ public ParseConfigAdvancedOptions build() { excelSkipHiddenContent, excelUseRawCellValues, excelSkipCalculation, + excelIncludeCellMetadata, + excelIncludeCellFormatting, verticalGroupingThreshold, returnOcr, alwaysConvertToPdf, diff --git a/src/main/java/ai/extend/types/ParseConfigBlockOptionsTables.java b/src/main/java/ai/extend/types/ParseConfigBlockOptionsTables.java index e124070..ec61c78 100644 --- a/src/main/java/ai/extend/types/ParseConfigBlockOptionsTables.java +++ b/src/main/java/ai/extend/types/ParseConfigBlockOptionsTables.java @@ -84,7 +84,7 @@ public Optional getCellBlocksEnabled() { } /** - * @return Options for agentic table processing using VLM-based review and correction. + * @return Options for agentic table processing using VLM-based review and correction. Enabling this incurs additional credits on pages where agentic table correction is triggered. */ @JsonProperty("agentic") public Optional getAgentic() { @@ -216,7 +216,7 @@ public Builder cellBlocksEnabled(Boolean cellBlocksEnabled) { } /** - *

    Options for agentic table processing using VLM-based review and correction.

    + *

    Options for agentic table processing using VLM-based review and correction. Enabling this incurs additional credits on pages where agentic table correction is triggered.

    */ @JsonSetter(value = "agentic", nulls = Nulls.SKIP) public Builder agentic(Optional agentic) { diff --git a/src/main/java/ai/extend/types/ParseConfigBlockOptionsText.java b/src/main/java/ai/extend/types/ParseConfigBlockOptionsText.java index ec9c7b2..7de132e 100644 --- a/src/main/java/ai/extend/types/ParseConfigBlockOptionsText.java +++ b/src/main/java/ai/extend/types/ParseConfigBlockOptionsText.java @@ -44,7 +44,7 @@ public Optional getSignatureDetectionEnabled() { } /** - * @return Options for agentic text processing using VLM-based review and correction. + * @return Options for agentic text processing using VLM-based review and correction. Enabling this incurs additional credits on pages where agentic text correction is triggered. */ @JsonProperty("agentic") public Optional getAgentic() { @@ -112,7 +112,7 @@ public Builder signatureDetectionEnabled(Boolean signatureDetectionEnabled) { } /** - *

    Options for agentic text processing using VLM-based review and correction.

    + *

    Options for agentic text processing using VLM-based review and correction. Enabling this incurs additional credits on pages where agentic text correction is triggered.

    */ @JsonSetter(value = "agentic", nulls = Nulls.SKIP) public Builder agentic(Optional agentic) { diff --git a/src/main/java/ai/extend/types/RunUsageBreakdownEntryObject.java b/src/main/java/ai/extend/types/RunUsageBreakdownEntryObject.java index 7415f9e..009b8c1 100644 --- a/src/main/java/ai/extend/types/RunUsageBreakdownEntryObject.java +++ b/src/main/java/ai/extend/types/RunUsageBreakdownEntryObject.java @@ -22,6 +22,9 @@ public final class RunUsageBreakdownEntryObject { public static final RunUsageBreakdownEntryObject EXTRACT_RUN = new RunUsageBreakdownEntryObject(Value.EXTRACT_RUN, "extract_run"); + public static final RunUsageBreakdownEntryObject FORM_DETECTION_RUN = + new RunUsageBreakdownEntryObject(Value.FORM_DETECTION_RUN, "form_detection_run"); + private final Value value; private final String string; @@ -65,6 +68,8 @@ public T visit(Visitor visitor) { return visitor.visitParseRun(); case EXTRACT_RUN: return visitor.visitExtractRun(); + case FORM_DETECTION_RUN: + return visitor.visitFormDetectionRun(); case UNKNOWN: default: return visitor.visitUnknown(string); @@ -84,6 +89,8 @@ public static RunUsageBreakdownEntryObject valueOf(String value) { return PARSE_RUN; case "extract_run": return EXTRACT_RUN; + case "form_detection_run": + return FORM_DETECTION_RUN; default: return new RunUsageBreakdownEntryObject(Value.UNKNOWN, value); } @@ -100,6 +107,8 @@ public enum Value { EDIT_RUN, + FORM_DETECTION_RUN, + UNKNOWN } @@ -114,6 +123,8 @@ public interface Visitor { T visitEditRun(); + T visitFormDetectionRun(); + T visitUnknown(String unknownType); } } diff --git a/src/main/java/ai/extend/types/SplitStepDefinition.java b/src/main/java/ai/extend/types/SplitStepDefinition.java index 222cb62..1b457ea 100644 --- a/src/main/java/ai/extend/types/SplitStepDefinition.java +++ b/src/main/java/ai/extend/types/SplitStepDefinition.java @@ -48,8 +48,8 @@ public String getName() { /** * @return Optional on create/update. Required before the workflow can be deployed. Omitted in responses when the step is not yet configured. - *

    Reference to the splitter used by this step. The next[].classificationId values must match split classification id values (not type strings) from the referenced splitter's configuration. For example, if the splitter defines { "id": "cls_receipt", "type": "receipt" }, use "cls_receipt" as the classificationId.

    - *

    The splitter version is required and must be a pinned version (semver like "0.1" or "draft"). "latest" is not allowed.

    + *

    When present, must contain exactly one of splitter (saved processor reference) or splitterConfig (inline configuration) — not both.

    + *

    The next[].classificationId values must match split classification id values (not type strings) from the splitter's configuration — the referenced version's config for a saved reference, or the inline splitClassifications array for an inline config. For example, if the splitter defines { "id": "cls_receipt", "type": "receipt" }, use "cls_receipt" as the classificationId.

    *

    See the Split step docs.

    */ @JsonProperty("config") @@ -58,7 +58,7 @@ public Optional getConfig() { } /** - * @return Can only be set when config is present. Each entry must include a classificationId matching a split classification id from the referenced splitter's configuration. Use the classification's stable id (e.g. "cls_receipt"), not the type string. + * @return Can only be set when config is present. Each entry must include a classificationId matching a split classification id from the splitter's configuration (saved or inline). Use the classification's stable id (e.g. "cls_receipt"), not the type string. *

    See the Split step docs.

    */ @JsonProperty("next") @@ -106,8 +106,8 @@ public interface _FinalStage { /** *

    Optional on create/update. Required before the workflow can be deployed. Omitted in responses when the step is not yet configured.

    - *

    Reference to the splitter used by this step. The next[].classificationId values must match split classification id values (not type strings) from the referenced splitter's configuration. For example, if the splitter defines { "id": "cls_receipt", "type": "receipt" }, use "cls_receipt" as the classificationId.

    - *

    The splitter version is required and must be a pinned version (semver like "0.1" or "draft"). "latest" is not allowed.

    + *

    When present, must contain exactly one of splitter (saved processor reference) or splitterConfig (inline configuration) — not both.

    + *

    The next[].classificationId values must match split classification id values (not type strings) from the splitter's configuration — the referenced version's config for a saved reference, or the inline splitClassifications array for an inline config. For example, if the splitter defines { "id": "cls_receipt", "type": "receipt" }, use "cls_receipt" as the classificationId.

    *

    See the Split step docs.

    */ _FinalStage config(Optional config); @@ -115,7 +115,7 @@ public interface _FinalStage { _FinalStage config(SplitStepDefinitionConfig config); /** - *

    Can only be set when config is present. Each entry must include a classificationId matching a split classification id from the referenced splitter's configuration. Use the classification's stable id (e.g. "cls_receipt"), not the type string.

    + *

    Can only be set when config is present. Each entry must include a classificationId matching a split classification id from the splitter's configuration (saved or inline). Use the classification's stable id (e.g. "cls_receipt"), not the type string.

    *

    See the Split step docs.

    */ _FinalStage next(Optional> next); @@ -152,7 +152,7 @@ public _FinalStage name(@NotNull String name) { } /** - *

    Can only be set when config is present. Each entry must include a classificationId matching a split classification id from the referenced splitter's configuration. Use the classification's stable id (e.g. "cls_receipt"), not the type string.

    + *

    Can only be set when config is present. Each entry must include a classificationId matching a split classification id from the splitter's configuration (saved or inline). Use the classification's stable id (e.g. "cls_receipt"), not the type string.

    *

    See the Split step docs.

    * @return Reference to {@code this} so that method calls can be chained together. */ @@ -163,7 +163,7 @@ public _FinalStage next(List next) { } /** - *

    Can only be set when config is present. Each entry must include a classificationId matching a split classification id from the referenced splitter's configuration. Use the classification's stable id (e.g. "cls_receipt"), not the type string.

    + *

    Can only be set when config is present. Each entry must include a classificationId matching a split classification id from the splitter's configuration (saved or inline). Use the classification's stable id (e.g. "cls_receipt"), not the type string.

    *

    See the Split step docs.

    */ @java.lang.Override @@ -175,8 +175,8 @@ public _FinalStage next(Optional> next) { /** *

    Optional on create/update. Required before the workflow can be deployed. Omitted in responses when the step is not yet configured.

    - *

    Reference to the splitter used by this step. The next[].classificationId values must match split classification id values (not type strings) from the referenced splitter's configuration. For example, if the splitter defines { "id": "cls_receipt", "type": "receipt" }, use "cls_receipt" as the classificationId.

    - *

    The splitter version is required and must be a pinned version (semver like "0.1" or "draft"). "latest" is not allowed.

    + *

    When present, must contain exactly one of splitter (saved processor reference) or splitterConfig (inline configuration) — not both.

    + *

    The next[].classificationId values must match split classification id values (not type strings) from the splitter's configuration — the referenced version's config for a saved reference, or the inline splitClassifications array for an inline config. For example, if the splitter defines { "id": "cls_receipt", "type": "receipt" }, use "cls_receipt" as the classificationId.

    *

    See the Split step docs.

    * @return Reference to {@code this} so that method calls can be chained together. */ @@ -188,8 +188,8 @@ public _FinalStage config(SplitStepDefinitionConfig config) { /** *

    Optional on create/update. Required before the workflow can be deployed. Omitted in responses when the step is not yet configured.

    - *

    Reference to the splitter used by this step. The next[].classificationId values must match split classification id values (not type strings) from the referenced splitter's configuration. For example, if the splitter defines { "id": "cls_receipt", "type": "receipt" }, use "cls_receipt" as the classificationId.

    - *

    The splitter version is required and must be a pinned version (semver like "0.1" or "draft"). "latest" is not allowed.

    + *

    When present, must contain exactly one of splitter (saved processor reference) or splitterConfig (inline configuration) — not both.

    + *

    The next[].classificationId values must match split classification id values (not type strings) from the splitter's configuration — the referenced version's config for a saved reference, or the inline splitClassifications array for an inline config. For example, if the splitter defines { "id": "cls_receipt", "type": "receipt" }, use "cls_receipt" as the classificationId.

    *

    See the Split step docs.

    */ @java.lang.Override diff --git a/src/main/java/ai/extend/types/SplitStepDefinitionConfig.java b/src/main/java/ai/extend/types/SplitStepDefinitionConfig.java index 8bed34d..193e115 100644 --- a/src/main/java/ai/extend/types/SplitStepDefinitionConfig.java +++ b/src/main/java/ai/extend/types/SplitStepDefinitionConfig.java @@ -10,29 +10,49 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.annotation.Nulls; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import java.util.HashMap; import java.util.Map; import java.util.Objects; -import org.jetbrains.annotations.NotNull; +import java.util.Optional; @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonDeserialize(builder = SplitStepDefinitionConfig.Builder.class) public final class SplitStepDefinitionConfig { - private final SplitterRef splitter; + private final Optional splitter; + + private final Optional splitterConfig; private final Map additionalProperties; - private SplitStepDefinitionConfig(SplitterRef splitter, Map additionalProperties) { + private SplitStepDefinitionConfig( + Optional splitter, + Optional splitterConfig, + Map additionalProperties) { this.splitter = splitter; + this.splitterConfig = splitterConfig; this.additionalProperties = additionalProperties; } + /** + * @return Reference to a saved splitter. Provide either this or splitterConfig, not both. + *

    The version is required and must be a pinned version (semver like "0.1" or "draft"). "latest" is not allowed.

    + */ @JsonProperty("splitter") - public SplitterRef getSplitter() { + public Optional getSplitter() { return splitter; } + /** + * @return Inline splitter configuration. Provide either this or splitter, not both. Same shape as the config accepted by Create Split Run. + *

    Inline configs are returned verbatim in responses (there is no saved processor, so no version is involved).

    + */ + @JsonProperty("splitterConfig") + public Optional getSplitterConfig() { + return splitterConfig; + } + @java.lang.Override public boolean equals(Object other) { if (this == other) return true; @@ -45,12 +65,12 @@ public Map getAdditionalProperties() { } private boolean equalTo(SplitStepDefinitionConfig other) { - return splitter.equals(other.splitter); + return splitter.equals(other.splitter) && splitterConfig.equals(other.splitterConfig); } @java.lang.Override public int hashCode() { - return Objects.hash(this.splitter); + return Objects.hash(this.splitter, this.splitterConfig); } @java.lang.Override @@ -58,45 +78,59 @@ public String toString() { return ObjectMappers.stringify(this); } - public static SplitterStage builder() { + public static Builder builder() { return new Builder(); } - public interface SplitterStage { - _FinalStage splitter(@NotNull SplitterRef splitter); - - Builder from(SplitStepDefinitionConfig other); - } - - public interface _FinalStage { - SplitStepDefinitionConfig build(); - } - @JsonIgnoreProperties(ignoreUnknown = true) - public static final class Builder implements SplitterStage, _FinalStage { - private SplitterRef splitter; + public static final class Builder { + private Optional splitter = Optional.empty(); + + private Optional splitterConfig = Optional.empty(); @JsonAnySetter private Map additionalProperties = new HashMap<>(); private Builder() {} - @java.lang.Override public Builder from(SplitStepDefinitionConfig other) { splitter(other.getSplitter()); + splitterConfig(other.getSplitterConfig()); + return this; + } + + /** + *

    Reference to a saved splitter. Provide either this or splitterConfig, not both.

    + *

    The version is required and must be a pinned version (semver like "0.1" or "draft"). "latest" is not allowed.

    + */ + @JsonSetter(value = "splitter", nulls = Nulls.SKIP) + public Builder splitter(Optional splitter) { + this.splitter = splitter; + return this; + } + + public Builder splitter(SplitterRef splitter) { + this.splitter = Optional.ofNullable(splitter); + return this; + } + + /** + *

    Inline splitter configuration. Provide either this or splitter, not both. Same shape as the config accepted by Create Split Run.

    + *

    Inline configs are returned verbatim in responses (there is no saved processor, so no version is involved).

    + */ + @JsonSetter(value = "splitterConfig", nulls = Nulls.SKIP) + public Builder splitterConfig(Optional splitterConfig) { + this.splitterConfig = splitterConfig; return this; } - @java.lang.Override - @JsonSetter("splitter") - public _FinalStage splitter(@NotNull SplitterRef splitter) { - this.splitter = Objects.requireNonNull(splitter, "splitter must not be null"); + public Builder splitterConfig(SplitConfig splitterConfig) { + this.splitterConfig = Optional.ofNullable(splitterConfig); return this; } - @java.lang.Override public SplitStepDefinitionConfig build() { - return new SplitStepDefinitionConfig(splitter, additionalProperties); + return new SplitStepDefinitionConfig(splitter, splitterConfig, additionalProperties); } } } diff --git a/src/main/java/ai/extend/types/TableCellDetails.java b/src/main/java/ai/extend/types/TableCellDetails.java index f1cceab..7f40592 100644 --- a/src/main/java/ai/extend/types/TableCellDetails.java +++ b/src/main/java/ai/extend/types/TableCellDetails.java @@ -10,10 +10,12 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.annotation.Nulls; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import java.util.HashMap; import java.util.Map; import java.util.Objects; +import java.util.Optional; @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonDeserialize(builder = TableCellDetails.Builder.class) @@ -22,11 +24,26 @@ public final class TableCellDetails { private final int columnIndex; + private final Optional cellReference; + + private final Optional formula; + + private final Optional formatting; + private final Map additionalProperties; - private TableCellDetails(int rowIndex, int columnIndex, Map additionalProperties) { + private TableCellDetails( + int rowIndex, + int columnIndex, + Optional cellReference, + Optional formula, + Optional formatting, + Map additionalProperties) { this.rowIndex = rowIndex; this.columnIndex = columnIndex; + this.cellReference = cellReference; + this.formula = formula; + this.formatting = formatting; this.additionalProperties = additionalProperties; } @@ -48,6 +65,30 @@ public int getColumnIndex() { return columnIndex; } + /** + * @return Source spreadsheet cell or range in A1 notation, such as B2 or A1:C1 for a merged cell. Only set for Excel table cells when advancedOptions.excelIncludeCellMetadata is enabled. + */ + @JsonProperty("cellReference") + public Optional getCellReference() { + return cellReference; + } + + /** + * @return Source spreadsheet formula text with a leading =, when the cell has a formula. Only set for Excel table cells when advancedOptions.excelIncludeCellMetadata is enabled. + */ + @JsonProperty("formula") + public Optional getFormula() { + return formula; + } + + /** + * @return Structured spreadsheet cell formatting. Only set when advancedOptions.excelIncludeCellFormatting is enabled and formatting is present. + */ + @JsonProperty("formatting") + public Optional getFormatting() { + return formatting; + } + @java.lang.Override public boolean equals(Object other) { if (this == other) return true; @@ -60,12 +101,16 @@ public Map getAdditionalProperties() { } private boolean equalTo(TableCellDetails other) { - return rowIndex == other.rowIndex && columnIndex == other.columnIndex; + return rowIndex == other.rowIndex + && columnIndex == other.columnIndex + && cellReference.equals(other.cellReference) + && formula.equals(other.formula) + && formatting.equals(other.formatting); } @java.lang.Override public int hashCode() { - return Objects.hash(this.rowIndex, this.columnIndex); + return Objects.hash(this.rowIndex, this.columnIndex, this.cellReference, this.formula, this.formatting); } @java.lang.Override @@ -89,6 +134,27 @@ public interface ColumnIndexStage { public interface _FinalStage { TableCellDetails build(); + + /** + *

    Source spreadsheet cell or range in A1 notation, such as B2 or A1:C1 for a merged cell. Only set for Excel table cells when advancedOptions.excelIncludeCellMetadata is enabled.

    + */ + _FinalStage cellReference(Optional cellReference); + + _FinalStage cellReference(String cellReference); + + /** + *

    Source spreadsheet formula text with a leading =, when the cell has a formula. Only set for Excel table cells when advancedOptions.excelIncludeCellMetadata is enabled.

    + */ + _FinalStage formula(Optional formula); + + _FinalStage formula(String formula); + + /** + *

    Structured spreadsheet cell formatting. Only set when advancedOptions.excelIncludeCellFormatting is enabled and formatting is present.

    + */ + _FinalStage formatting(Optional formatting); + + _FinalStage formatting(CellFormatting formatting); } @JsonIgnoreProperties(ignoreUnknown = true) @@ -97,6 +163,12 @@ public static final class Builder implements RowIndexStage, ColumnIndexStage, _F private int columnIndex; + private Optional formatting = Optional.empty(); + + private Optional formula = Optional.empty(); + + private Optional cellReference = Optional.empty(); + @JsonAnySetter private Map additionalProperties = new HashMap<>(); @@ -106,6 +178,9 @@ private Builder() {} public Builder from(TableCellDetails other) { rowIndex(other.getRowIndex()); columnIndex(other.getColumnIndex()); + cellReference(other.getCellReference()); + formula(other.getFormula()); + formatting(other.getFormatting()); return this; } @@ -123,9 +198,70 @@ public _FinalStage columnIndex(int columnIndex) { return this; } + /** + *

    Structured spreadsheet cell formatting. Only set when advancedOptions.excelIncludeCellFormatting is enabled and formatting is present.

    + * @return Reference to {@code this} so that method calls can be chained together. + */ + @java.lang.Override + public _FinalStage formatting(CellFormatting formatting) { + this.formatting = Optional.ofNullable(formatting); + return this; + } + + /** + *

    Structured spreadsheet cell formatting. Only set when advancedOptions.excelIncludeCellFormatting is enabled and formatting is present.

    + */ + @java.lang.Override + @JsonSetter(value = "formatting", nulls = Nulls.SKIP) + public _FinalStage formatting(Optional formatting) { + this.formatting = formatting; + return this; + } + + /** + *

    Source spreadsheet formula text with a leading =, when the cell has a formula. Only set for Excel table cells when advancedOptions.excelIncludeCellMetadata is enabled.

    + * @return Reference to {@code this} so that method calls can be chained together. + */ + @java.lang.Override + public _FinalStage formula(String formula) { + this.formula = Optional.ofNullable(formula); + return this; + } + + /** + *

    Source spreadsheet formula text with a leading =, when the cell has a formula. Only set for Excel table cells when advancedOptions.excelIncludeCellMetadata is enabled.

    + */ + @java.lang.Override + @JsonSetter(value = "formula", nulls = Nulls.SKIP) + public _FinalStage formula(Optional formula) { + this.formula = formula; + return this; + } + + /** + *

    Source spreadsheet cell or range in A1 notation, such as B2 or A1:C1 for a merged cell. Only set for Excel table cells when advancedOptions.excelIncludeCellMetadata is enabled.

    + * @return Reference to {@code this} so that method calls can be chained together. + */ + @java.lang.Override + public _FinalStage cellReference(String cellReference) { + this.cellReference = Optional.ofNullable(cellReference); + return this; + } + + /** + *

    Source spreadsheet cell or range in A1 notation, such as B2 or A1:C1 for a merged cell. Only set for Excel table cells when advancedOptions.excelIncludeCellMetadata is enabled.

    + */ + @java.lang.Override + @JsonSetter(value = "cellReference", nulls = Nulls.SKIP) + public _FinalStage cellReference(Optional cellReference) { + this.cellReference = cellReference; + return this; + } + @java.lang.Override public TableCellDetails build() { - return new TableCellDetails(rowIndex, columnIndex, additionalProperties); + return new TableCellDetails( + rowIndex, columnIndex, cellReference, formula, formatting, additionalProperties); } } } diff --git a/src/main/java/ai/extend/types/TextDetails.java b/src/main/java/ai/extend/types/TextDetails.java new file mode 100644 index 0000000..42f82c0 --- /dev/null +++ b/src/main/java/ai/extend/types/TextDetails.java @@ -0,0 +1,109 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package ai.extend.types; + +import ai.extend.core.ObjectMappers; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.annotation.Nulls; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; + +@JsonInclude(JsonInclude.Include.NON_ABSENT) +@JsonDeserialize(builder = TextDetails.Builder.class) +public final class TextDetails { + private final Optional cellReference; + + private final Map additionalProperties; + + private TextDetails(Optional cellReference, Map additionalProperties) { + this.cellReference = cellReference; + this.additionalProperties = additionalProperties; + } + + /** + * @return Indicates this is a text details object + */ + @JsonProperty("type") + public String getType() { + return "text_details"; + } + + /** + * @return Source spreadsheet cell or range in A1 notation for Excel-derived text or heading blocks. Only set when advancedOptions.excelIncludeCellMetadata is enabled. + */ + @JsonProperty("cellReference") + public Optional getCellReference() { + return cellReference; + } + + @java.lang.Override + public boolean equals(Object other) { + if (this == other) return true; + return other instanceof TextDetails && equalTo((TextDetails) other); + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + private boolean equalTo(TextDetails other) { + return cellReference.equals(other.cellReference); + } + + @java.lang.Override + public int hashCode() { + return Objects.hash(this.cellReference); + } + + @java.lang.Override + public String toString() { + return ObjectMappers.stringify(this); + } + + public static Builder builder() { + return new Builder(); + } + + @JsonIgnoreProperties(ignoreUnknown = true) + public static final class Builder { + private Optional cellReference = Optional.empty(); + + @JsonAnySetter + private Map additionalProperties = new HashMap<>(); + + private Builder() {} + + public Builder from(TextDetails other) { + cellReference(other.getCellReference()); + return this; + } + + /** + *

    Source spreadsheet cell or range in A1 notation for Excel-derived text or heading blocks. Only set when advancedOptions.excelIncludeCellMetadata is enabled.

    + */ + @JsonSetter(value = "cellReference", nulls = Nulls.SKIP) + public Builder cellReference(Optional cellReference) { + this.cellReference = cellReference; + return this; + } + + public Builder cellReference(String cellReference) { + this.cellReference = Optional.ofNullable(cellReference); + return this; + } + + public TextDetails build() { + return new TextDetails(cellReference, additionalProperties); + } + } +} diff --git a/src/main/java/ai/extend/types/WorkflowInlineExtractConfig.java b/src/main/java/ai/extend/types/WorkflowInlineExtractConfig.java new file mode 100644 index 0000000..16a8872 --- /dev/null +++ b/src/main/java/ai/extend/types/WorkflowInlineExtractConfig.java @@ -0,0 +1,273 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package ai.extend.types; + +import ai.extend.core.ObjectMappers; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.annotation.Nulls; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; + +@JsonInclude(JsonInclude.Include.NON_ABSENT) +@JsonDeserialize(builder = WorkflowInlineExtractConfig.Builder.class) +public final class WorkflowInlineExtractConfig { + private final Optional baseProcessor; + + private final Optional baseVersion; + + private final Optional extractionRules; + + private final Map schema; + + private final Optional advancedOptions; + + private final Optional parseConfig; + + private final Map additionalProperties; + + private WorkflowInlineExtractConfig( + Optional baseProcessor, + Optional baseVersion, + Optional extractionRules, + Map schema, + Optional advancedOptions, + Optional parseConfig, + Map additionalProperties) { + this.baseProcessor = baseProcessor; + this.baseVersion = baseVersion; + this.extractionRules = extractionRules; + this.schema = schema; + this.advancedOptions = advancedOptions; + this.parseConfig = parseConfig; + this.additionalProperties = additionalProperties; + } + + @JsonProperty("baseProcessor") + public Optional getBaseProcessor() { + return baseProcessor; + } + + /** + * @return The version of the "extraction_performance" or "extraction_light" processor to use. If not provided, the latest stable version for the selected baseProcessor will be used automatically. See Extraction Changelog for more details. + */ + @JsonProperty("baseVersion") + public Optional getBaseVersion() { + return baseVersion; + } + + /** + * @return Custom rules to guide the extraction process in natural language. + */ + @JsonProperty("extractionRules") + public Optional getExtractionRules() { + return extractionRules; + } + + /** + * @return JSON Schema definition of the data to extract. Required for inline workflow configs. + *

    See the JSON Schema guide for details and examples of schema configuration.

    + */ + @JsonProperty("schema") + public Map getSchema() { + return schema; + } + + /** + * @return Advanced configuration options. + */ + @JsonProperty("advancedOptions") + public Optional getAdvancedOptions() { + return advancedOptions; + } + + /** + * @return Configuration options for the parsing process. + */ + @JsonProperty("parseConfig") + public Optional getParseConfig() { + return parseConfig; + } + + @java.lang.Override + public boolean equals(Object other) { + if (this == other) return true; + return other instanceof WorkflowInlineExtractConfig && equalTo((WorkflowInlineExtractConfig) other); + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + private boolean equalTo(WorkflowInlineExtractConfig other) { + return baseProcessor.equals(other.baseProcessor) + && baseVersion.equals(other.baseVersion) + && extractionRules.equals(other.extractionRules) + && schema.equals(other.schema) + && advancedOptions.equals(other.advancedOptions) + && parseConfig.equals(other.parseConfig); + } + + @java.lang.Override + public int hashCode() { + return Objects.hash( + this.baseProcessor, + this.baseVersion, + this.extractionRules, + this.schema, + this.advancedOptions, + this.parseConfig); + } + + @java.lang.Override + public String toString() { + return ObjectMappers.stringify(this); + } + + public static Builder builder() { + return new Builder(); + } + + @JsonIgnoreProperties(ignoreUnknown = true) + public static final class Builder { + private Optional baseProcessor = Optional.empty(); + + private Optional baseVersion = Optional.empty(); + + private Optional extractionRules = Optional.empty(); + + private Map schema = new LinkedHashMap<>(); + + private Optional advancedOptions = Optional.empty(); + + private Optional parseConfig = Optional.empty(); + + @JsonAnySetter + private Map additionalProperties = new HashMap<>(); + + private Builder() {} + + public Builder from(WorkflowInlineExtractConfig other) { + baseProcessor(other.getBaseProcessor()); + baseVersion(other.getBaseVersion()); + extractionRules(other.getExtractionRules()); + schema(other.getSchema()); + advancedOptions(other.getAdvancedOptions()); + parseConfig(other.getParseConfig()); + return this; + } + + @JsonSetter(value = "baseProcessor", nulls = Nulls.SKIP) + public Builder baseProcessor(Optional baseProcessor) { + this.baseProcessor = baseProcessor; + return this; + } + + public Builder baseProcessor(ExtractBaseProcessor baseProcessor) { + this.baseProcessor = Optional.ofNullable(baseProcessor); + return this; + } + + /** + *

    The version of the "extraction_performance" or "extraction_light" processor to use. If not provided, the latest stable version for the selected baseProcessor will be used automatically. See Extraction Changelog for more details.

    + */ + @JsonSetter(value = "baseVersion", nulls = Nulls.SKIP) + public Builder baseVersion(Optional baseVersion) { + this.baseVersion = baseVersion; + return this; + } + + public Builder baseVersion(String baseVersion) { + this.baseVersion = Optional.ofNullable(baseVersion); + return this; + } + + /** + *

    Custom rules to guide the extraction process in natural language.

    + */ + @JsonSetter(value = "extractionRules", nulls = Nulls.SKIP) + public Builder extractionRules(Optional extractionRules) { + this.extractionRules = extractionRules; + return this; + } + + public Builder extractionRules(String extractionRules) { + this.extractionRules = Optional.ofNullable(extractionRules); + return this; + } + + /** + *

    JSON Schema definition of the data to extract. Required for inline workflow configs.

    + *

    See the JSON Schema guide for details and examples of schema configuration.

    + */ + @JsonSetter(value = "schema", nulls = Nulls.SKIP) + public Builder schema(Map schema) { + this.schema.clear(); + if (schema != null) { + this.schema.putAll(schema); + } + return this; + } + + public Builder putAllSchema(Map schema) { + if (schema != null) { + this.schema.putAll(schema); + } + return this; + } + + public Builder schema(String key, Object value) { + this.schema.put(key, value); + return this; + } + + /** + *

    Advanced configuration options.

    + */ + @JsonSetter(value = "advancedOptions", nulls = Nulls.SKIP) + public Builder advancedOptions(Optional advancedOptions) { + this.advancedOptions = advancedOptions; + return this; + } + + public Builder advancedOptions(ExtractAdvancedOptions advancedOptions) { + this.advancedOptions = Optional.ofNullable(advancedOptions); + return this; + } + + /** + *

    Configuration options for the parsing process.

    + */ + @JsonSetter(value = "parseConfig", nulls = Nulls.SKIP) + public Builder parseConfig(Optional parseConfig) { + this.parseConfig = parseConfig; + return this; + } + + public Builder parseConfig(ParseConfig parseConfig) { + this.parseConfig = Optional.ofNullable(parseConfig); + return this; + } + + public WorkflowInlineExtractConfig build() { + return new WorkflowInlineExtractConfig( + baseProcessor, + baseVersion, + extractionRules, + schema, + advancedOptions, + parseConfig, + additionalProperties); + } + } +} diff --git a/src/main/java/ai/extend/types/WorkflowRunSummary.java b/src/main/java/ai/extend/types/WorkflowRunSummary.java index 3c16aa8..b1f31de 100644 --- a/src/main/java/ai/extend/types/WorkflowRunSummary.java +++ b/src/main/java/ai/extend/types/WorkflowRunSummary.java @@ -16,7 +16,9 @@ import com.fasterxml.jackson.annotation.Nulls; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import java.time.OffsetDateTime; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; @@ -49,6 +51,8 @@ public final class WorkflowRunSummary { private final Optional rejectionNote; + private final List files; + private final OffsetDateTime createdAt; private final OffsetDateTime updatedAt; @@ -70,6 +74,7 @@ private WorkflowRunSummary( Optional endTime, Optional batchId, Optional rejectionNote, + List files, OffsetDateTime createdAt, OffsetDateTime updatedAt, Optional usage, @@ -86,6 +91,7 @@ private WorkflowRunSummary( this.endTime = endTime; this.batchId = batchId; this.rejectionNote = rejectionNote; + this.files = files; this.createdAt = createdAt; this.updatedAt = updatedAt; this.usage = usage; @@ -217,6 +223,14 @@ public Optional getRejectionNote() { return rejectionNote; } + /** + * @return The input files that this workflow run was executed on. Provided directly on the list response so you don't need to fetch each run individually to inspect its input. + */ + @JsonProperty("files") + public List getFiles() { + return files; + } + @JsonProperty("createdAt") public OffsetDateTime getCreatedAt() { return createdAt; @@ -311,6 +325,7 @@ private boolean equalTo(WorkflowRunSummary other) { && endTime.equals(other.endTime) && batchId.equals(other.batchId) && rejectionNote.equals(other.rejectionNote) + && files.equals(other.files) && createdAt.equals(other.createdAt) && updatedAt.equals(other.updatedAt) && usage.equals(other.usage); @@ -331,6 +346,7 @@ public int hashCode() { this.endTime, this.batchId, this.rejectionNote, + this.files, this.createdAt, this.updatedAt, this.usage); @@ -456,6 +472,15 @@ public interface _FinalStage { _FinalStage rejectionNote(Nullable rejectionNote); + /** + *

    The input files that this workflow run was executed on. Provided directly on the list response so you don't need to fetch each run individually to inspect its input.

    + */ + _FinalStage files(List files); + + _FinalStage addFiles(FileSummary files); + + _FinalStage addAllFiles(List files); + /** *

    Usage credits consumed by this workflow run. Omits breakdown — fetch the full workflow run by id to see the per-line items for every contributing child run.

    *

    Availability: Will not be returned for runs created before October 7, 2025 or for customers on legacy billing systems.

    @@ -493,6 +518,8 @@ public static final class Builder private Optional usage = Optional.empty(); + private List files = new ArrayList<>(); + private Optional rejectionNote = Optional.empty(); private Optional batchId = Optional.empty(); @@ -526,6 +553,7 @@ public Builder from(WorkflowRunSummary other) { endTime(other.getEndTime()); batchId(other.getBatchId()); rejectionNote(other.getRejectionNote()); + files(other.getFiles()); createdAt(other.getCreatedAt()); updatedAt(other.getUpdatedAt()); usage(other.getUsage()); @@ -634,6 +662,41 @@ public _FinalStage usage(Optional usage) { return this; } + /** + *

    The input files that this workflow run was executed on. Provided directly on the list response so you don't need to fetch each run individually to inspect its input.

    + * @return Reference to {@code this} so that method calls can be chained together. + */ + @java.lang.Override + public _FinalStage addAllFiles(List files) { + if (files != null) { + this.files.addAll(files); + } + return this; + } + + /** + *

    The input files that this workflow run was executed on. Provided directly on the list response so you don't need to fetch each run individually to inspect its input.

    + * @return Reference to {@code this} so that method calls can be chained together. + */ + @java.lang.Override + public _FinalStage addFiles(FileSummary files) { + this.files.add(files); + return this; + } + + /** + *

    The input files that this workflow run was executed on. Provided directly on the list response so you don't need to fetch each run individually to inspect its input.

    + */ + @java.lang.Override + @JsonSetter(value = "files", nulls = Nulls.SKIP) + public _FinalStage files(List files) { + this.files.clear(); + if (files != null) { + this.files.addAll(files); + } + return this; + } + /** *

    The note that was added when the workflow run was rejected.

    *

    Example: "Invalid invoice format"

    @@ -922,6 +985,7 @@ public WorkflowRunSummary build() { endTime, batchId, rejectionNote, + files, createdAt, updatedAt, usage,