@anyformat/sdk 0.2.1 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +75 -7
- package/dist/index.cjs +354 -67
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +578 -143
- package/dist/index.d.ts +578 -143
- package/dist/index.js +345 -67
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -24,6 +24,54 @@ const result = await af
|
|
|
24
24
|
result.field("vendor")?.value; // -> "Acme Corp"
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
+
## Quick parse: one call → markdown
|
|
28
|
+
|
|
29
|
+
`af.parse()` runs the platform's atomic `/parse` operation (a fast lite parse)
|
|
30
|
+
and returns an opaque `jobId`. Poll `getParseMarkdown(jobId)` for the markdown —
|
|
31
|
+
no workflow to author or manage.
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
const jobId = await af.parse(file); // File | Blob
|
|
35
|
+
let markdown = await af.getParseMarkdown(jobId);
|
|
36
|
+
while (markdown === null) {
|
|
37
|
+
await new Promise((r) => setTimeout(r, 3000));
|
|
38
|
+
markdown = await af.getParseMarkdown(jobId); // null until done
|
|
39
|
+
}
|
|
40
|
+
console.log(markdown);
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Managing workflows
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
const workflows = await af.listWorkflows({ pageSize: 50 }); // -> Workflow[]
|
|
47
|
+
for (const wf of workflows) console.log(wf.id, wf.name);
|
|
48
|
+
|
|
49
|
+
await af.deleteWorkflow(workflows[0].id); // -> the deleted id
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Smart lookup
|
|
53
|
+
|
|
54
|
+
Resolve a field by matching the document against a reference file (CSV/catalog) instead of
|
|
55
|
+
reading it off the page — flag the field with `{ lookup: true }` and pass the file via
|
|
56
|
+
`lookupFiles`:
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
await af
|
|
60
|
+
.workflow("Invoice + vendor lookup")
|
|
61
|
+
.parse()
|
|
62
|
+
.extract(
|
|
63
|
+
[
|
|
64
|
+
Schema.string("vendor_name", "Vendor as printed on the invoice."),
|
|
65
|
+
Schema.string("vendor_id", "Canonical vendor code from the catalog, joined on vendor_name.", { lookup: true }),
|
|
66
|
+
],
|
|
67
|
+
{ lookupFiles: ["vendor_catalog.csv"], lookupSuggestion: "Join vendor_name → vendor_id." },
|
|
68
|
+
)
|
|
69
|
+
.run(file)
|
|
70
|
+
.wait();
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Full runnable example: [`examples/smart-lookup.mjs`](examples/smart-lookup.mjs).
|
|
74
|
+
|
|
27
75
|
## How it's built
|
|
28
76
|
|
|
29
77
|
The wire types and the low-level HTTP client are **generated** from the API's
|
|
@@ -34,8 +82,8 @@ ergonomic layer (`Schema`, `WorkflowBuilder`, `Result`, `Anyformat`) wraps it.
|
|
|
34
82
|
## Regenerating (and the drift guard)
|
|
35
83
|
|
|
36
84
|
```bash
|
|
37
|
-
|
|
38
|
-
|
|
85
|
+
bun run gen # dump the v2 OpenAPI offline + regenerate src/sdk
|
|
86
|
+
bun run gen:check # regenerate and fail if the committed output drifted
|
|
39
87
|
```
|
|
40
88
|
|
|
41
89
|
`gen:check` runs in CI and as a pre-commit hook (scoped to changes under
|
|
@@ -46,10 +94,30 @@ caught as a type error, not just a diff.
|
|
|
46
94
|
|
|
47
95
|
## Scripts
|
|
48
96
|
|
|
97
|
+
Install deps with `bun install --frozen-lockfile` (matches CI + the frontend
|
|
98
|
+
toolchain). Then:
|
|
99
|
+
|
|
49
100
|
| script | what |
|
|
50
101
|
| --- | --- |
|
|
51
|
-
| `
|
|
52
|
-
| `
|
|
53
|
-
| `
|
|
54
|
-
| `
|
|
55
|
-
| `
|
|
102
|
+
| `bun run gen` | dump spec + regenerate `src/sdk` |
|
|
103
|
+
| `bun run gen:check` | regenerate + assert no drift |
|
|
104
|
+
| `bun run build` | bundle to `dist/` (ESM + CJS + types) via tsup |
|
|
105
|
+
| `bun run typecheck` | `tsc --noEmit` |
|
|
106
|
+
| `bun run test` | vitest |
|
|
107
|
+
|
|
108
|
+
## Releasing
|
|
109
|
+
|
|
110
|
+
Cut on demand — a maintainer bumps the version in a PR, then pushes a `sdk-js-vX.Y.Z` tag on the release commit. Full flow + one-time setup: [`../RELEASING.md`](../RELEASING.md). Break-glass: `./publish.sh [--build-only|--dry-run]`.
|
|
111
|
+
|
|
112
|
+
## Node configuration knobs
|
|
113
|
+
|
|
114
|
+
Every knob is an option on `.parse({...})` / `.extract(fields, {...})`. `parse` options are a
|
|
115
|
+
`mode`-discriminated union, so a wrong-mode knob is a compile-time error.
|
|
116
|
+
|
|
117
|
+
**`.parse({...})`** — `mode` (`"standard"`/`"agentic"`/`"lite"`), `promptHint`, `figureEnhancement`,
|
|
118
|
+
`cache`; **agentic-only** `effort` (`"low"`/`"mid"`/`"accurate"`); **lite-only** `ocrEffort`
|
|
119
|
+
(`"medium"`/`"high"`), `region` (`"eu"`/`"global"`), `skipRoutingReview`, `figures`,
|
|
120
|
+
`textFormatting`, `routingEffort`.
|
|
121
|
+
|
|
122
|
+
**`.extract(fields, {...})`** — `mode` (`"standard"`/`"agentic"`/`"max"`/`"lite"`), `useImages`,
|
|
123
|
+
`lookupSuggestion`, `lookupReasoningEffort` (`"minimal"`/`"low"`/`"medium"`/`"high"`), `lookupFiles`.
|
package/dist/index.cjs
CHANGED
|
@@ -24,44 +24,144 @@ __export(index_exports, {
|
|
|
24
24
|
Anyformat: () => Anyformat,
|
|
25
25
|
AnyformatError: () => AnyformatError,
|
|
26
26
|
BadRequest: () => BadRequest,
|
|
27
|
+
BadRequestError: () => BadRequestError,
|
|
27
28
|
Forbidden: () => Forbidden,
|
|
29
|
+
ForbiddenError: () => ForbiddenError,
|
|
28
30
|
NotFound: () => NotFound,
|
|
31
|
+
NotFoundError: () => NotFoundError,
|
|
32
|
+
ParseView: () => ParseView,
|
|
29
33
|
RateLimited: () => RateLimited,
|
|
34
|
+
RateLimitedError: () => RateLimitedError,
|
|
30
35
|
Result: () => Result,
|
|
31
36
|
Run: () => Run,
|
|
32
37
|
SDKTimeout: () => SDKTimeout,
|
|
38
|
+
SDKTimeoutError: () => SDKTimeoutError,
|
|
33
39
|
Schema: () => Schema,
|
|
34
40
|
ServerError: () => ServerError,
|
|
35
41
|
Unauthorized: () => Unauthorized,
|
|
42
|
+
UnauthorizedError: () => UnauthorizedError,
|
|
43
|
+
Upload: () => Upload,
|
|
44
|
+
Workflow: () => Workflow,
|
|
36
45
|
WorkflowBuilder: () => WorkflowBuilder,
|
|
37
46
|
WorkflowBuilderError: () => WorkflowBuilderError
|
|
38
47
|
});
|
|
39
48
|
module.exports = __toCommonJS(index_exports);
|
|
40
49
|
|
|
50
|
+
// package.json
|
|
51
|
+
var package_default = {
|
|
52
|
+
name: "@anyformat/sdk",
|
|
53
|
+
version: "0.2.3",
|
|
54
|
+
description: "TypeScript SDK for the AnyFormat API",
|
|
55
|
+
license: "MIT",
|
|
56
|
+
author: "Anyformat <info@anyformat.ai>",
|
|
57
|
+
type: "module",
|
|
58
|
+
main: "./dist/index.cjs",
|
|
59
|
+
module: "./dist/index.js",
|
|
60
|
+
types: "./dist/index.d.ts",
|
|
61
|
+
exports: {
|
|
62
|
+
".": {
|
|
63
|
+
types: "./dist/index.d.ts",
|
|
64
|
+
import: "./dist/index.js",
|
|
65
|
+
require: "./dist/index.cjs"
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
files: [
|
|
69
|
+
"dist"
|
|
70
|
+
],
|
|
71
|
+
engines: {
|
|
72
|
+
node: ">=18"
|
|
73
|
+
},
|
|
74
|
+
scripts: {
|
|
75
|
+
"gen:spec": 'ROOT=$(unset GIT_DIR && git rev-parse --show-toplevel) && cd "$ROOT/anyformat/services/api" && uv run python "$ROOT/anyformat/libs/public/sdk-js/scripts/dump_openapi.py" "$ROOT/anyformat/libs/public/sdk-js/openapi/v2.json"',
|
|
76
|
+
"gen:client": "openapi-ts",
|
|
77
|
+
gen: "bun run gen:spec && bun run gen:client",
|
|
78
|
+
"gen:check": "bun run gen && git diff --exit-code -- openapi/v2.json src/sdk",
|
|
79
|
+
build: "tsup",
|
|
80
|
+
typecheck: "tsc --noEmit",
|
|
81
|
+
test: "vitest run",
|
|
82
|
+
prepublishOnly: "bun run build"
|
|
83
|
+
},
|
|
84
|
+
devDependencies: {
|
|
85
|
+
"@hey-api/openapi-ts": "^0.99.0",
|
|
86
|
+
"@types/node": "^25.9.1",
|
|
87
|
+
tsup: "^8.3.0",
|
|
88
|
+
typescript: "^5.6.0",
|
|
89
|
+
vitest: "^4.1.7"
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
|
|
41
93
|
// src/builder.ts
|
|
42
94
|
var import_node_fs = require("fs");
|
|
43
95
|
var import_node_path = require("path");
|
|
44
96
|
|
|
97
|
+
// src/parse-view.ts
|
|
98
|
+
var ParseView = class {
|
|
99
|
+
/** @internal */
|
|
100
|
+
constructor(parse) {
|
|
101
|
+
this.parse = parse;
|
|
102
|
+
}
|
|
103
|
+
parse;
|
|
104
|
+
get markdown() {
|
|
105
|
+
return this.parse.markdown ?? null;
|
|
106
|
+
}
|
|
107
|
+
get text() {
|
|
108
|
+
return this.parse.text ?? null;
|
|
109
|
+
}
|
|
110
|
+
get blocks() {
|
|
111
|
+
return this.parse.blocks ?? [];
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Document-level confidence (0-100) in the parsed content. May be `null` for
|
|
115
|
+
* some parse modes — fall back to `layoutConfidence`.
|
|
116
|
+
*/
|
|
117
|
+
get parseConfidence() {
|
|
118
|
+
return this.parse.parse_confidence ?? null;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Document-level confidence (0-100) in the page layout (block positions).
|
|
122
|
+
* `null` when not available.
|
|
123
|
+
*/
|
|
124
|
+
get layoutConfidence() {
|
|
125
|
+
return this.parse.layout_confidence ?? null;
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
|
|
45
129
|
// src/result.ts
|
|
46
130
|
var Result = class {
|
|
47
131
|
constructor(raw) {
|
|
48
132
|
this.raw = raw;
|
|
49
133
|
}
|
|
50
134
|
raw;
|
|
135
|
+
_parse;
|
|
51
136
|
get collectionId() {
|
|
52
137
|
return this.raw.collection_id;
|
|
53
138
|
}
|
|
54
139
|
get extractions() {
|
|
55
140
|
return this.raw.extractions ?? [];
|
|
56
141
|
}
|
|
142
|
+
/**
|
|
143
|
+
* Typed view over the parse node's output, or `null` when the workflow has
|
|
144
|
+
* no parse node. Cached so repeated access doesn't re-wrap.
|
|
145
|
+
*/
|
|
146
|
+
get parse() {
|
|
147
|
+
if (this._parse === void 0) {
|
|
148
|
+
const raw = this.raw.parse;
|
|
149
|
+
this._parse = raw ? new ParseView(raw) : null;
|
|
150
|
+
}
|
|
151
|
+
return this._parse;
|
|
152
|
+
}
|
|
57
153
|
/**
|
|
58
154
|
* Convenience accessor for a top-level scalar field on the first
|
|
59
155
|
* extraction (linear workflows). Returns `undefined` for missing fields
|
|
60
156
|
* or list-valued fields — read `extractions` directly for those.
|
|
157
|
+
*
|
|
158
|
+
* Parameterise with the declared schema type to type `.value`:
|
|
159
|
+
* `result.field<number>("total").value` is `number | null`.
|
|
61
160
|
*/
|
|
62
161
|
field(name) {
|
|
63
162
|
const value = this.extractions[0]?.fields?.[name];
|
|
64
|
-
|
|
163
|
+
if (value === void 0 || Array.isArray(value)) return void 0;
|
|
164
|
+
return value;
|
|
65
165
|
}
|
|
66
166
|
};
|
|
67
167
|
|
|
@@ -78,35 +178,41 @@ var APIError = class extends AnyformatError {
|
|
|
78
178
|
status;
|
|
79
179
|
body;
|
|
80
180
|
};
|
|
81
|
-
var
|
|
181
|
+
var BadRequestError = class extends APIError {
|
|
82
182
|
};
|
|
83
|
-
var
|
|
183
|
+
var UnauthorizedError = class extends APIError {
|
|
84
184
|
};
|
|
85
|
-
var
|
|
185
|
+
var ForbiddenError = class extends APIError {
|
|
86
186
|
};
|
|
87
|
-
var
|
|
187
|
+
var NotFoundError = class extends APIError {
|
|
88
188
|
};
|
|
89
|
-
var
|
|
189
|
+
var RateLimitedError = class extends APIError {
|
|
90
190
|
};
|
|
91
191
|
var ServerError = class extends APIError {
|
|
92
192
|
};
|
|
93
|
-
var
|
|
193
|
+
var BadRequest = BadRequestError;
|
|
194
|
+
var Unauthorized = UnauthorizedError;
|
|
195
|
+
var Forbidden = ForbiddenError;
|
|
196
|
+
var NotFound = NotFoundError;
|
|
197
|
+
var RateLimited = RateLimitedError;
|
|
198
|
+
var SDKTimeoutError = class extends AnyformatError {
|
|
94
199
|
};
|
|
200
|
+
var SDKTimeout = SDKTimeoutError;
|
|
95
201
|
var WorkflowBuilderError = class extends AnyformatError {
|
|
96
202
|
};
|
|
97
203
|
function toApiError(status, body) {
|
|
98
204
|
const message = `AnyFormat API error (${status})`;
|
|
99
205
|
switch (status) {
|
|
100
206
|
case 400:
|
|
101
|
-
return new
|
|
207
|
+
return new BadRequestError(status, message, body);
|
|
102
208
|
case 401:
|
|
103
|
-
return new
|
|
209
|
+
return new UnauthorizedError(status, message, body);
|
|
104
210
|
case 403:
|
|
105
|
-
return new
|
|
211
|
+
return new ForbiddenError(status, message, body);
|
|
106
212
|
case 404:
|
|
107
|
-
return new
|
|
213
|
+
return new NotFoundError(status, message, body);
|
|
108
214
|
case 429:
|
|
109
|
-
return new
|
|
215
|
+
return new RateLimitedError(status, message, body);
|
|
110
216
|
default:
|
|
111
217
|
return status >= 500 ? new ServerError(status, message, body) : new APIError(status, message, body);
|
|
112
218
|
}
|
|
@@ -923,9 +1029,29 @@ var createClient = (config = {}) => {
|
|
|
923
1029
|
};
|
|
924
1030
|
|
|
925
1031
|
// src/sdk/client.gen.ts
|
|
926
|
-
var client = createClient(createConfig({ baseUrl: "https://api
|
|
1032
|
+
var client = createClient(createConfig({ baseUrl: "https://api.anyformat.dev" }));
|
|
927
1033
|
|
|
928
1034
|
// src/sdk/sdk.gen.ts
|
|
1035
|
+
var v2Parse = (options) => (options.client ?? client).post({
|
|
1036
|
+
...formDataBodySerializer,
|
|
1037
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1038
|
+
url: "/v2/operations/parse",
|
|
1039
|
+
...options,
|
|
1040
|
+
headers: {
|
|
1041
|
+
"Content-Type": null,
|
|
1042
|
+
...options.headers
|
|
1043
|
+
}
|
|
1044
|
+
});
|
|
1045
|
+
var v2ParseResult = (options) => (options.client ?? client).get({
|
|
1046
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1047
|
+
url: "/v2/operations/parse/{job_id}",
|
|
1048
|
+
...options
|
|
1049
|
+
});
|
|
1050
|
+
var v2ListWorkflows = (options) => (options?.client ?? client).get({
|
|
1051
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1052
|
+
url: "/v2/workflows/",
|
|
1053
|
+
...options
|
|
1054
|
+
});
|
|
929
1055
|
var v2CreateWorkflow = (options) => (options.client ?? client).post({
|
|
930
1056
|
security: [{ scheme: "bearer", type: "http" }],
|
|
931
1057
|
url: "/v2/workflows/",
|
|
@@ -935,11 +1061,30 @@ var v2CreateWorkflow = (options) => (options.client ?? client).post({
|
|
|
935
1061
|
...options.headers
|
|
936
1062
|
}
|
|
937
1063
|
});
|
|
1064
|
+
var v2DeleteWorkflow = (options) => (options.client ?? client).delete({
|
|
1065
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1066
|
+
url: "/v2/workflows/{workflow_id}/",
|
|
1067
|
+
...options
|
|
1068
|
+
});
|
|
1069
|
+
var v2UpdateWorkflow = (options) => (options.client ?? client).put({
|
|
1070
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1071
|
+
url: "/v2/workflows/{workflow_id}/",
|
|
1072
|
+
...options,
|
|
1073
|
+
headers: {
|
|
1074
|
+
"Content-Type": "application/json",
|
|
1075
|
+
...options.headers
|
|
1076
|
+
}
|
|
1077
|
+
});
|
|
938
1078
|
var v2GetFileResults = (options) => (options.client ?? client).get({
|
|
939
1079
|
security: [{ scheme: "bearer", type: "http" }],
|
|
940
1080
|
url: "/v2/workflows/{workflow_id}/files/{collection_id}/results/",
|
|
941
1081
|
...options
|
|
942
1082
|
});
|
|
1083
|
+
var v2RunFile = (options) => (options.client ?? client).post({
|
|
1084
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1085
|
+
url: "/v2/workflows/{workflow_id}/files/{file_id}/run/",
|
|
1086
|
+
...options
|
|
1087
|
+
});
|
|
943
1088
|
var v2RunWorkflow = (options) => (options.client ?? client).post({
|
|
944
1089
|
...formDataBodySerializer,
|
|
945
1090
|
security: [{ scheme: "bearer", type: "http" }],
|
|
@@ -950,48 +1095,36 @@ var v2RunWorkflow = (options) => (options.client ?? client).post({
|
|
|
950
1095
|
...options.headers
|
|
951
1096
|
}
|
|
952
1097
|
});
|
|
1098
|
+
var v2UploadFile = (options) => (options.client ?? client).post({
|
|
1099
|
+
...formDataBodySerializer,
|
|
1100
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1101
|
+
url: "/v2/workflows/{workflow_id}/upload/",
|
|
1102
|
+
...options,
|
|
1103
|
+
headers: {
|
|
1104
|
+
"Content-Type": null,
|
|
1105
|
+
...options.headers
|
|
1106
|
+
}
|
|
1107
|
+
});
|
|
953
1108
|
|
|
954
1109
|
// src/run.ts
|
|
955
1110
|
var Run = class {
|
|
956
|
-
|
|
1111
|
+
/** @internal */
|
|
1112
|
+
constructor(client2, workflowId, id) {
|
|
957
1113
|
this.client = client2;
|
|
958
|
-
this.
|
|
959
|
-
this.
|
|
960
|
-
this.text = text;
|
|
1114
|
+
this.workflowId = workflowId;
|
|
1115
|
+
this.id = id;
|
|
961
1116
|
}
|
|
962
1117
|
client;
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
text;
|
|
966
|
-
workflowId = null;
|
|
967
|
-
collectionId = null;
|
|
968
|
-
/**
|
|
969
|
-
* Create the workflow and submit the document — exactly once per `Run`.
|
|
970
|
-
* Memoized so that retrying `wait()` after an `SDKTimeout` resumes polling
|
|
971
|
-
* the in-flight run instead of creating a duplicate workflow + submission.
|
|
972
|
-
*/
|
|
973
|
-
async submit() {
|
|
974
|
-
if (this.collectionId !== null) return;
|
|
975
|
-
const created = await v2CreateWorkflow({ client: this.client, body: this.request });
|
|
976
|
-
if (created.error) throw toApiError(created.response?.status ?? 500, created.error);
|
|
977
|
-
this.workflowId = created.data.id;
|
|
978
|
-
const submitted = await v2RunWorkflow({
|
|
979
|
-
client: this.client,
|
|
980
|
-
path: { workflow_id: this.workflowId },
|
|
981
|
-
body: { file: this.file, text: this.text }
|
|
982
|
-
});
|
|
983
|
-
if (submitted.error) throw toApiError(submitted.response?.status ?? 500, submitted.error);
|
|
984
|
-
this.collectionId = submitted.data.id;
|
|
985
|
-
}
|
|
1118
|
+
workflowId;
|
|
1119
|
+
id;
|
|
986
1120
|
async wait(opts = {}) {
|
|
987
|
-
const timeoutMs = opts.timeoutMs ??
|
|
988
|
-
const pollMs = opts.pollMs ??
|
|
989
|
-
await this.submit();
|
|
1121
|
+
const timeoutMs = opts.timeoutMs ?? 3e5;
|
|
1122
|
+
const pollMs = opts.pollMs ?? 3e3;
|
|
990
1123
|
const deadline = Date.now() + timeoutMs;
|
|
991
1124
|
while (Date.now() < deadline) {
|
|
992
1125
|
const results = await v2GetFileResults({
|
|
993
1126
|
client: this.client,
|
|
994
|
-
path: { workflow_id: this.workflowId, collection_id: this.
|
|
1127
|
+
path: { workflow_id: this.workflowId, collection_id: this.id }
|
|
995
1128
|
});
|
|
996
1129
|
if (!results.error) return new Result(results.data);
|
|
997
1130
|
if (results.response?.status !== 412) {
|
|
@@ -999,7 +1132,89 @@ var Run = class {
|
|
|
999
1132
|
}
|
|
1000
1133
|
await new Promise((resolve) => setTimeout(resolve, pollMs));
|
|
1001
1134
|
}
|
|
1002
|
-
throw new
|
|
1135
|
+
throw new SDKTimeoutError(`Extraction did not complete within ${timeoutMs}ms`);
|
|
1136
|
+
}
|
|
1137
|
+
};
|
|
1138
|
+
|
|
1139
|
+
// src/upload.ts
|
|
1140
|
+
var Upload = class {
|
|
1141
|
+
/** @internal */
|
|
1142
|
+
constructor(client2, workflowId, collectionId, fileId) {
|
|
1143
|
+
this.client = client2;
|
|
1144
|
+
this.workflowId = workflowId;
|
|
1145
|
+
this.collectionId = collectionId;
|
|
1146
|
+
this.fileId = fileId;
|
|
1147
|
+
}
|
|
1148
|
+
client;
|
|
1149
|
+
workflowId;
|
|
1150
|
+
collectionId;
|
|
1151
|
+
fileId;
|
|
1152
|
+
/** Trigger extraction on the staged file and return a pending `Run`. */
|
|
1153
|
+
async run() {
|
|
1154
|
+
if (!this.fileId) {
|
|
1155
|
+
throw new WorkflowBuilderError("This upload has no file_id \u2014 cannot run it");
|
|
1156
|
+
}
|
|
1157
|
+
const res = await v2RunFile({
|
|
1158
|
+
client: this.client,
|
|
1159
|
+
path: { workflow_id: this.workflowId, file_id: this.fileId }
|
|
1160
|
+
});
|
|
1161
|
+
if (res.error) throw toApiError(res.response?.status ?? 500, res.error);
|
|
1162
|
+
return new Run(this.client, this.workflowId, res.data.id ?? this.collectionId);
|
|
1163
|
+
}
|
|
1164
|
+
};
|
|
1165
|
+
|
|
1166
|
+
// src/workflow.ts
|
|
1167
|
+
function validateDocument(file, op) {
|
|
1168
|
+
if (file === null) {
|
|
1169
|
+
throw new WorkflowBuilderError(`${op}() requires a named file`);
|
|
1170
|
+
}
|
|
1171
|
+
const filename = file.name;
|
|
1172
|
+
if (typeof filename !== "string" || filename.length === 0) {
|
|
1173
|
+
throw new WorkflowBuilderError(
|
|
1174
|
+
`${op}() needs a named file so the server can detect its type \u2014 pass a File, e.g. new File([bytes], "invoice.pdf"), not a bare Blob`
|
|
1175
|
+
);
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
var Workflow = class {
|
|
1179
|
+
/** @internal */
|
|
1180
|
+
constructor(client2, id, name) {
|
|
1181
|
+
this.client = client2;
|
|
1182
|
+
this.id = id;
|
|
1183
|
+
this.name = name;
|
|
1184
|
+
}
|
|
1185
|
+
client;
|
|
1186
|
+
id;
|
|
1187
|
+
name;
|
|
1188
|
+
/** Submit a document against this workflow and return a pending `Run`. */
|
|
1189
|
+
async run(file = null) {
|
|
1190
|
+
validateDocument(file, "run");
|
|
1191
|
+
const submitted = await v2RunWorkflow({
|
|
1192
|
+
client: this.client,
|
|
1193
|
+
path: { workflow_id: this.id },
|
|
1194
|
+
body: { file }
|
|
1195
|
+
});
|
|
1196
|
+
if (submitted.error) throw toApiError(submitted.response?.status ?? 500, submitted.error);
|
|
1197
|
+
return new Run(this.client, this.id, submitted.data.id);
|
|
1198
|
+
}
|
|
1199
|
+
/**
|
|
1200
|
+
* Stage a document in this workflow WITHOUT running it (no credits spent).
|
|
1201
|
+
* Returns an `Upload`; call `.run()` on it to start extraction.
|
|
1202
|
+
*/
|
|
1203
|
+
async upload(file = null) {
|
|
1204
|
+
validateDocument(file, "upload");
|
|
1205
|
+
const staged = await v2UploadFile({
|
|
1206
|
+
client: this.client,
|
|
1207
|
+
path: { workflow_id: this.id },
|
|
1208
|
+
body: { file }
|
|
1209
|
+
});
|
|
1210
|
+
if (staged.error) throw toApiError(staged.response?.status ?? 500, staged.error);
|
|
1211
|
+
const collectionId = staged.data.file_collection_id;
|
|
1212
|
+
if (!collectionId) {
|
|
1213
|
+
throw new WorkflowBuilderError(
|
|
1214
|
+
"Upload succeeded but the server did not return a file_collection_id \u2014 cannot build an Upload handle"
|
|
1215
|
+
);
|
|
1216
|
+
}
|
|
1217
|
+
return new Upload(this.client, this.id, collectionId, staged.data.file_id ?? null);
|
|
1003
1218
|
}
|
|
1004
1219
|
};
|
|
1005
1220
|
|
|
@@ -1029,12 +1244,21 @@ var WorkflowBuilder = class {
|
|
|
1029
1244
|
}
|
|
1030
1245
|
parse(opts = {}) {
|
|
1031
1246
|
this.require(this.parseNode === null, "parse() can only be called once");
|
|
1247
|
+
const o = opts;
|
|
1032
1248
|
this.parseNode = {
|
|
1033
1249
|
type: "parse",
|
|
1034
|
-
id:
|
|
1035
|
-
mode:
|
|
1036
|
-
...
|
|
1037
|
-
figure_enhancement:
|
|
1250
|
+
id: o.id ?? this.nextId("parse"),
|
|
1251
|
+
mode: o.mode ?? "standard",
|
|
1252
|
+
...o.promptHint !== void 0 ? { prompt_hint: o.promptHint } : {},
|
|
1253
|
+
figure_enhancement: o.figureEnhancement ?? false,
|
|
1254
|
+
cache: o.cache ?? true,
|
|
1255
|
+
...o.effort !== void 0 ? { effort: o.effort } : {},
|
|
1256
|
+
...o.ocrEffort !== void 0 ? { ocr_effort: o.ocrEffort } : {},
|
|
1257
|
+
...o.region !== void 0 ? { region: o.region } : {},
|
|
1258
|
+
...o.skipRoutingReview !== void 0 ? { skip_routing_review: o.skipRoutingReview } : {},
|
|
1259
|
+
...o.figures !== void 0 ? { figures: o.figures } : {},
|
|
1260
|
+
...o.textFormatting !== void 0 ? { text_formatting: o.textFormatting } : {},
|
|
1261
|
+
...o.routingEffort !== void 0 ? { routing_effort: o.routingEffort } : {}
|
|
1038
1262
|
};
|
|
1039
1263
|
return this;
|
|
1040
1264
|
}
|
|
@@ -1081,9 +1305,12 @@ var WorkflowBuilder = class {
|
|
|
1081
1305
|
const node = {
|
|
1082
1306
|
type: "extract",
|
|
1083
1307
|
id: opts.id ?? this.nextId("extract"),
|
|
1308
|
+
...opts.mode !== void 0 ? { mode: opts.mode } : {},
|
|
1084
1309
|
extraction_schema: { fields },
|
|
1085
1310
|
...lookupFileUploads.length > 0 ? { lookup_file_uploads: lookupFileUploads } : {},
|
|
1086
|
-
...opts.lookupSuggestion !== void 0 ? { lookup_suggestion: opts.lookupSuggestion } : {}
|
|
1311
|
+
...opts.lookupSuggestion !== void 0 ? { lookup_suggestion: opts.lookupSuggestion } : {},
|
|
1312
|
+
...opts.lookupReasoningEffort !== void 0 ? { lookup_reasoning_effort: opts.lookupReasoningEffort } : {},
|
|
1313
|
+
...opts.useImages !== void 0 ? { use_images: opts.useImages } : {}
|
|
1087
1314
|
};
|
|
1088
1315
|
this.extracts.push([node, branchId]);
|
|
1089
1316
|
return this;
|
|
@@ -1165,30 +1392,22 @@ var WorkflowBuilder = class {
|
|
|
1165
1392
|
}
|
|
1166
1393
|
return { name: this.name, description: this.description, nodes, edges };
|
|
1167
1394
|
}
|
|
1168
|
-
/** Persist the workflow and return
|
|
1395
|
+
/** Persist the workflow and return a handle you can `.run(file)` on. */
|
|
1169
1396
|
async create() {
|
|
1170
1397
|
const res = await v2CreateWorkflow({ client: this.client, body: this.build() });
|
|
1171
1398
|
if (res.error) throw toApiError(res.response?.status ?? 500, res.error);
|
|
1172
|
-
return res.data.id;
|
|
1399
|
+
return new Workflow(this.client, res.data.id, res.data.name);
|
|
1173
1400
|
}
|
|
1174
|
-
/**
|
|
1175
|
-
|
|
1176
|
-
this.
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
);
|
|
1180
|
-
if (file !== null) {
|
|
1181
|
-
const filename = file.name;
|
|
1182
|
-
this.require(
|
|
1183
|
-
typeof filename === "string" && filename.length > 0,
|
|
1184
|
-
'run() needs a named file so the server can detect its type \u2014 pass a File, e.g. new File([bytes], "invoice.pdf"), not a bare Blob'
|
|
1185
|
-
);
|
|
1186
|
-
}
|
|
1187
|
-
return new Run(this.client, this.build(), file, opts.text ?? null);
|
|
1401
|
+
/** Replace an existing workflow's definition and return a handle you can `.run(file)` on. */
|
|
1402
|
+
async update(workflowId) {
|
|
1403
|
+
const res = await v2UpdateWorkflow({ client: this.client, path: { workflow_id: workflowId }, body: this.build() });
|
|
1404
|
+
if (res.error) throw toApiError(res.response?.status ?? 500, res.error);
|
|
1405
|
+
return new Workflow(this.client, res.data.id, res.data.name);
|
|
1188
1406
|
}
|
|
1189
1407
|
};
|
|
1190
1408
|
|
|
1191
1409
|
// src/client.ts
|
|
1410
|
+
var SDK_USER_AGENT = `anyformat-typescript-sdk-${package_default.version}`;
|
|
1192
1411
|
var Anyformat = class {
|
|
1193
1412
|
/** @internal */
|
|
1194
1413
|
_client;
|
|
@@ -1196,13 +1415,72 @@ var Anyformat = class {
|
|
|
1196
1415
|
this._client = createClient(
|
|
1197
1416
|
createConfig({
|
|
1198
1417
|
baseUrl: opts.baseUrl ?? "https://api.anyformat.ai",
|
|
1199
|
-
auth: opts.apiKey
|
|
1418
|
+
auth: opts.apiKey,
|
|
1419
|
+
// Identifies the caller in our logs (Datadog facet). Plain HTTP callers
|
|
1420
|
+
// send no such header and are logged as origin "api". User-Agent is
|
|
1421
|
+
// ignored by browsers (forbidden header) but used by Node fetch.
|
|
1422
|
+
headers: {
|
|
1423
|
+
"x-anyformat-origin": "js-sdk",
|
|
1424
|
+
"User-Agent": SDK_USER_AGENT
|
|
1425
|
+
}
|
|
1200
1426
|
})
|
|
1201
1427
|
);
|
|
1202
1428
|
}
|
|
1203
1429
|
workflow(name, description) {
|
|
1204
1430
|
return new WorkflowBuilder(this._client, name, description);
|
|
1205
1431
|
}
|
|
1432
|
+
async listWorkflows(opts) {
|
|
1433
|
+
const res = await v2ListWorkflows({
|
|
1434
|
+
client: this._client,
|
|
1435
|
+
query: { page: opts?.page, page_size: opts?.pageSize, status: opts?.status }
|
|
1436
|
+
});
|
|
1437
|
+
if (res.error) throw toApiError(res.response?.status ?? 500, res.error);
|
|
1438
|
+
return res.data.results.map((r) => new Workflow(this._client, r.id, r.name ?? ""));
|
|
1439
|
+
}
|
|
1440
|
+
async deleteWorkflow(workflowId) {
|
|
1441
|
+
const res = await v2DeleteWorkflow({
|
|
1442
|
+
client: this._client,
|
|
1443
|
+
path: { workflow_id: workflowId }
|
|
1444
|
+
});
|
|
1445
|
+
if (res.error) throw toApiError(res.response?.status ?? 500, res.error);
|
|
1446
|
+
return workflowId;
|
|
1447
|
+
}
|
|
1448
|
+
/** Stage a document in a workflow without running it. Returns an `Upload`. */
|
|
1449
|
+
upload(workflowId, file = null) {
|
|
1450
|
+
return new Workflow(this._client, workflowId, "").upload(file);
|
|
1451
|
+
}
|
|
1452
|
+
/** Trigger extraction on already-uploaded files. Returns a pending `Run` per file_id. */
|
|
1453
|
+
async runWorkflow(workflowId, fileIds) {
|
|
1454
|
+
const runs = [];
|
|
1455
|
+
for (const fileId of fileIds) {
|
|
1456
|
+
const res = await v2RunFile({
|
|
1457
|
+
client: this._client,
|
|
1458
|
+
path: { workflow_id: workflowId, file_id: fileId }
|
|
1459
|
+
});
|
|
1460
|
+
if (res.error) throw toApiError(res.response?.status ?? 500, res.error);
|
|
1461
|
+
runs.push(new Run(this._client, workflowId, res.data.id ?? fileId));
|
|
1462
|
+
}
|
|
1463
|
+
return runs;
|
|
1464
|
+
}
|
|
1465
|
+
/**
|
|
1466
|
+
* Parse a document with the platform's atomic `/parse` operation (fast lite
|
|
1467
|
+
* parse). Returns an opaque `jobId`; poll `getParseMarkdown(jobId)` for the
|
|
1468
|
+
* parsed markdown.
|
|
1469
|
+
*/
|
|
1470
|
+
async parse(file) {
|
|
1471
|
+
const res = await v2Parse({ client: this._client, body: { file } });
|
|
1472
|
+
if (res.error) throw toApiError(res.response?.status ?? 500, res.error);
|
|
1473
|
+
return res.data.job_id;
|
|
1474
|
+
}
|
|
1475
|
+
/**
|
|
1476
|
+
* Poll a parse job. Returns the parsed markdown once the job is done, or
|
|
1477
|
+
* `null` while it is still processing.
|
|
1478
|
+
*/
|
|
1479
|
+
async getParseMarkdown(jobId) {
|
|
1480
|
+
const res = await v2ParseResult({ client: this._client, path: { job_id: jobId } });
|
|
1481
|
+
if (res.error) throw toApiError(res.response?.status ?? 500, res.error);
|
|
1482
|
+
return res.data.status === "done" ? res.data.markdown ?? "" : null;
|
|
1483
|
+
}
|
|
1206
1484
|
};
|
|
1207
1485
|
|
|
1208
1486
|
// src/schema.ts
|
|
@@ -1228,15 +1506,24 @@ var Schema = {
|
|
|
1228
1506
|
Anyformat,
|
|
1229
1507
|
AnyformatError,
|
|
1230
1508
|
BadRequest,
|
|
1509
|
+
BadRequestError,
|
|
1231
1510
|
Forbidden,
|
|
1511
|
+
ForbiddenError,
|
|
1232
1512
|
NotFound,
|
|
1513
|
+
NotFoundError,
|
|
1514
|
+
ParseView,
|
|
1233
1515
|
RateLimited,
|
|
1516
|
+
RateLimitedError,
|
|
1234
1517
|
Result,
|
|
1235
1518
|
Run,
|
|
1236
1519
|
SDKTimeout,
|
|
1520
|
+
SDKTimeoutError,
|
|
1237
1521
|
Schema,
|
|
1238
1522
|
ServerError,
|
|
1239
1523
|
Unauthorized,
|
|
1524
|
+
UnauthorizedError,
|
|
1525
|
+
Upload,
|
|
1526
|
+
Workflow,
|
|
1240
1527
|
WorkflowBuilder,
|
|
1241
1528
|
WorkflowBuilderError
|
|
1242
1529
|
});
|