@hatchet-dev/typescript-sdk 1.22.0 → 1.22.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hatchet-dev/typescript-sdk",
3
- "version": "1.22.0",
3
+ "version": "1.22.2",
4
4
  "description": "Background task orchestration & visibility for developers",
5
5
  "types": "dist/index.d.ts",
6
6
  "files": [
@@ -50,24 +50,22 @@
50
50
  "@bufbuild/protobuf": "^2.11.0",
51
51
  "@types/qs": "^6.15.0",
52
52
  "abort-controller-x": "^0.5.0",
53
- "axios": "^1.13.5",
53
+ "axios": "^1.15.2",
54
54
  "long": "^5.3.1",
55
55
  "nice-grpc": "^2.1.14",
56
56
  "nice-grpc-common": "^2.0.2",
57
- "protobufjs": "^7.4.0",
57
+ "protobufjs": "^7.5.5",
58
58
  "qs": "^6.14.2",
59
59
  "semver": "^7.7.4",
60
- "yaml": "^2.8.2",
60
+ "yaml": "^2.8.3",
61
61
  "zod-to-json-schema": "^3.24.2"
62
62
  },
63
63
  "peerDependencies": {
64
- "zod": "^3.25.0 || ^4.0.0"
65
- },
66
- "optionalDependencies": {
64
+ "zod": "^3.25.0 || ^4.0.0",
67
65
  "@anthropic-ai/claude-agent-sdk": "^0.2.87",
68
66
  "@grpc/grpc-js": "^1.14.3",
69
67
  "@modelcontextprotocol/sdk": "^1.29.0",
70
- "@openai/agents": "0.8.3",
68
+ "@openai/agents": "0.8.5",
71
69
  "@opentelemetry/api": "^1.9.0",
72
70
  "@opentelemetry/core": "^2.0.0",
73
71
  "@opentelemetry/exporter-trace-otlp-grpc": "^0.215.0",
@@ -75,6 +73,41 @@
75
73
  "@opentelemetry/sdk-trace-base": "^2.0.0",
76
74
  "prom-client": "^15.1.3"
77
75
  },
76
+ "peerDependenciesMeta": {
77
+ "zod": {
78
+ "optional": false
79
+ },
80
+ "@anthropic-ai/claude-agent-sdk": {
81
+ "optional": true
82
+ },
83
+ "@grpc/grpc-js": {
84
+ "optional": true
85
+ },
86
+ "@modelcontextprotocol/sdk": {
87
+ "optional": true
88
+ },
89
+ "@openai/agents": {
90
+ "optional": true
91
+ },
92
+ "@opentelemetry/api": {
93
+ "optional": true
94
+ },
95
+ "@opentelemetry/core": {
96
+ "optional": true
97
+ },
98
+ "@opentelemetry/exporter-trace-otlp-grpc": {
99
+ "optional": true
100
+ },
101
+ "@opentelemetry/instrumentation": {
102
+ "optional": true
103
+ },
104
+ "@opentelemetry/sdk-trace-base": {
105
+ "optional": true
106
+ },
107
+ "prom-client": {
108
+ "optional": true
109
+ }
110
+ },
78
111
  "scripts": {
79
112
  "build": "echo 'build hatchet sdk with `npm run tsc:build` to ensure it is not build during the publish step' && exit 0",
80
113
  "postinstall": "node scripts/version-check.js",
@@ -412,8 +412,8 @@ export declare class DurableContext<T, K = {}> extends Context<T, K> {
412
412
  * @param payloadSchema - An optional Zod schema to validate and parse the event payload.
413
413
  * @returns The event payload, validated against the schema if provided.
414
414
  */
415
- waitForEvent<T extends z.ZodTypeAny>(key: string, expression?: string, payloadSchema?: T, scope?: string, lookbackWindow?: Duration, label?: string): Promise<z.infer<T>>;
416
415
  waitForEvent(key: string, expression?: string, payloadSchema?: undefined, scope?: string, lookbackWindow?: Duration, label?: string): Promise<Record<string, any>>;
416
+ waitForEvent<T extends z.ZodTypeAny>(key: string, expression?: string, payloadSchema?: T, scope?: string, lookbackWindow?: Duration, label?: string): Promise<z.infer<T>>;
417
417
  /**
418
418
  * Durably sleep until a specific timestamp.
419
419
  * Uses the memoized `now()` to compute the remaining duration, then delegates to `sleepFor`.
@@ -42,6 +42,7 @@ const workflow_20 = require("./webhooks/workflow");
42
42
  const workflow_21 = require("./child_index/workflow");
43
43
  const workflow_22 = require("./support_agent/workflow");
44
44
  const workflow_23 = require("./welcome_email/workflow");
45
+ const workflow_24 = require("./pdf_pipeline/workflow");
45
46
  const workflows = [
46
47
  workflow_1.bulkChild,
47
48
  workflow_1.bulkParentWorkflow,
@@ -101,6 +102,7 @@ const workflows = [
101
102
  workflow_22.generateReply,
102
103
  workflow_22.escalateTicket,
103
104
  workflow_23.welcomeEmail,
105
+ workflow_24.pdfPipeline,
104
106
  ];
105
107
  function main() {
106
108
  return __awaiter(this, void 0, void 0, function* () {
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ // > Trigger the pipeline
13
+ const workflow_1 = require("./workflow");
14
+ const sample_pdf_1 = require("./sample-pdf");
15
+ function main() {
16
+ return __awaiter(this, void 0, void 0, function* () {
17
+ const pdfBytes = (0, sample_pdf_1.makeSamplePdf)('Invoice from Acme Corp. Total amount due: 150 dollars. Payment terms: Net 30.');
18
+ const input = {
19
+ filename: 'sample-invoice.pdf',
20
+ contentBase64: pdfBytes.toString('base64'),
21
+ };
22
+ const result = yield workflow_1.pdfPipeline.run(input);
23
+ console.log('Pipeline result:', result);
24
+ });
25
+ }
26
+ // !!
27
+ if (require.main === module) {
28
+ main()
29
+ .catch(console.error)
30
+ .finally(() => process.exit(0));
31
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Create a minimal single-page PDF containing the given text.
3
+ * Uses no external dependencies — constructs the PDF binary directly.
4
+ */
5
+ export declare function makeSamplePdf(text: string): Buffer;
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.makeSamplePdf = makeSamplePdf;
4
+ /**
5
+ * Create a minimal single-page PDF containing the given text.
6
+ * Uses no external dependencies — constructs the PDF binary directly.
7
+ */
8
+ function makeSamplePdf(text) {
9
+ const stream = `BT /F1 12 Tf 72 720 Td (${text}) Tj ET`;
10
+ const objects = [
11
+ '1 0 obj\n<< /Type /Catalog /Pages 2 0 R >>\nendobj',
12
+ '2 0 obj\n<< /Type /Pages /Kids [3 0 R] /Count 1 >>\nendobj',
13
+ `3 0 obj\n<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Contents 4 0 R /Resources << /Font << /F1 5 0 R >> >> >>\nendobj`,
14
+ `4 0 obj\n<< /Length ${stream.length} >>\nstream\n${stream}\nendstream\nendobj`,
15
+ '5 0 obj\n<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica >>\nendobj',
16
+ ];
17
+ let body = '%PDF-1.4\n';
18
+ const offsets = [];
19
+ for (const obj of objects) {
20
+ offsets.push(body.length);
21
+ body += obj + '\n\n';
22
+ }
23
+ const xrefOffset = body.length;
24
+ let xref = `xref\n0 ${objects.length + 1}\n`;
25
+ xref += '0000000000 65535 f \n';
26
+ for (const off of offsets) {
27
+ xref += String(off).padStart(10, '0') + ' 00000 n \n';
28
+ }
29
+ body += xref;
30
+ body += `trailer\n<< /Size ${objects.length + 1} /Root 1 0 R >>\n`;
31
+ body += `startxref\n${xrefOffset}\n%%EOF`;
32
+ return Buffer.from(body, 'latin1');
33
+ }
@@ -0,0 +1,27 @@
1
+ export type PdfInput = {
2
+ filename: string;
3
+ contentBase64: string;
4
+ };
5
+ export type ExtractOutput = {
6
+ text: string;
7
+ pageCount: number;
8
+ };
9
+ export type ClassifyOutput = {
10
+ category: string;
11
+ };
12
+ export type SummaryOutput = {
13
+ summary: string;
14
+ wordCount: number;
15
+ };
16
+ export type KeywordsOutput = {
17
+ keywords: string[];
18
+ };
19
+ export type PipelineResult = {
20
+ filename: string;
21
+ category: string;
22
+ summary: string;
23
+ keywords: string[];
24
+ wordCount: number;
25
+ pageCount: number;
26
+ };
27
+ export declare const pdfPipeline: import("../..").WorkflowDeclaration<PdfInput, {}, {}>;
@@ -0,0 +1,179 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.pdfPipeline = void 0;
13
+ const fs_1 = require("fs");
14
+ const path_1 = require("path");
15
+ const os_1 = require("os");
16
+ const hatchet_client_1 = require("../hatchet-client");
17
+ // !!
18
+ const STOPWORDS = new Set([
19
+ 'a',
20
+ 'an',
21
+ 'and',
22
+ 'are',
23
+ 'as',
24
+ 'at',
25
+ 'be',
26
+ 'by',
27
+ 'for',
28
+ 'from',
29
+ 'in',
30
+ 'is',
31
+ 'it',
32
+ 'of',
33
+ 'on',
34
+ 'or',
35
+ 'that',
36
+ 'the',
37
+ 'to',
38
+ 'with',
39
+ ]);
40
+ const MIN_WORD_LENGTH = 3;
41
+ const MAX_KEYWORDS = 6;
42
+ const FALLBACK_TEXT = 'Invoice from Acme Corp. Total amount due: 150 dollars. Payment terms: Net 30.';
43
+ /**
44
+ * Extract text from a PDF buffer using pdf2json.
45
+ * The file-path API is the most reliable path for this example.
46
+ */
47
+ function extractPdfText(pdfBuffer) {
48
+ return __awaiter(this, void 0, void 0, function* () {
49
+ let PDFParser;
50
+ try {
51
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
52
+ PDFParser = require('pdf2json');
53
+ }
54
+ catch (_a) {
55
+ // pdf2json not installed: return deterministic fallback text
56
+ return { text: FALLBACK_TEXT, pageCount: 1 };
57
+ }
58
+ const tmpDir = (0, fs_1.mkdtempSync)((0, path_1.join)((0, os_1.tmpdir)(), 'hatchet-pdf-'));
59
+ const tmpFile = (0, path_1.join)(tmpDir, 'input.pdf');
60
+ (0, fs_1.writeFileSync)(tmpFile, pdfBuffer);
61
+ try {
62
+ const pdfData = yield new Promise((resolve, reject) => {
63
+ const parser = new PDFParser();
64
+ parser.on('pdfParser_dataReady', resolve);
65
+ parser.on('pdfParser_dataError', (err) => reject(new Error(err.parserError)));
66
+ parser.loadPDF(tmpFile);
67
+ });
68
+ const pageCount = pdfData.Pages.length;
69
+ const text = pdfData.Pages.map((page) => page.Texts.map((t) => t.R.map((r) => decodeURIComponent(r.T)).join('')).join(' ')).join('\n');
70
+ return { text, pageCount };
71
+ }
72
+ finally {
73
+ try {
74
+ (0, fs_1.rmSync)(tmpDir, { recursive: true, force: true });
75
+ }
76
+ catch (_b) {
77
+ // best-effort cleanup
78
+ }
79
+ }
80
+ });
81
+ }
82
+ // > Define the DAG
83
+ exports.pdfPipeline = hatchet_client_1.hatchet.workflow({
84
+ name: 'pdf-pipeline',
85
+ });
86
+ // !!
87
+ // > Extract text task
88
+ const extractText = exports.pdfPipeline.task({
89
+ name: 'extract_text',
90
+ fn: (input) => __awaiter(void 0, void 0, void 0, function* () {
91
+ const decoded = Buffer.from(input.contentBase64, 'base64');
92
+ const { text, pageCount } = yield extractPdfText(decoded);
93
+ return { text, pageCount };
94
+ }),
95
+ });
96
+ // !!
97
+ // > Classify task
98
+ const classifyDocument = exports.pdfPipeline.task({
99
+ name: 'classify_document',
100
+ parents: [extractText],
101
+ fn: (input, ctx) => __awaiter(void 0, void 0, void 0, function* () {
102
+ const { text } = yield ctx.parentOutput(extractText);
103
+ const lower = text.toLowerCase();
104
+ let category;
105
+ if (['invoice', 'amount due', 'payment', 'bill'].some((w) => lower.includes(w))) {
106
+ category = 'invoice';
107
+ }
108
+ else if (['receipt', 'paid', 'transaction'].some((w) => lower.includes(w))) {
109
+ category = 'receipt';
110
+ }
111
+ else if (['report', 'analysis', 'findings', 'conclusion'].some((w) => lower.includes(w))) {
112
+ category = 'report';
113
+ }
114
+ else if (['dear', 'sincerely', 'regards'].some((w) => lower.includes(w))) {
115
+ category = 'letter';
116
+ }
117
+ else {
118
+ category = 'other';
119
+ }
120
+ return { category };
121
+ }),
122
+ });
123
+ // !!
124
+ // > Summarize task
125
+ const summarizeText = exports.pdfPipeline.task({
126
+ name: 'summarize_text',
127
+ parents: [extractText],
128
+ fn: (input, ctx) => __awaiter(void 0, void 0, void 0, function* () {
129
+ const { text } = yield ctx.parentOutput(extractText);
130
+ const words = text.split(/\s+/).filter(Boolean);
131
+ const maxWords = 50;
132
+ let summary = words.slice(0, maxWords).join(' ');
133
+ if (words.length > maxWords) {
134
+ summary += '...';
135
+ }
136
+ return { summary, wordCount: words.length };
137
+ }),
138
+ });
139
+ // !!
140
+ // > Extract keywords task
141
+ const extractKeywords = exports.pdfPipeline.task({
142
+ name: 'extract_keywords',
143
+ parents: [extractText],
144
+ fn: (input, ctx) => __awaiter(void 0, void 0, void 0, function* () {
145
+ var _a, _b;
146
+ const { text } = yield ctx.parentOutput(extractText);
147
+ const words = (_a = text.toLowerCase().match(/[a-z]+/g)) !== null && _a !== void 0 ? _a : [];
148
+ const filtered = words.filter((w) => w.length >= MIN_WORD_LENGTH && !STOPWORDS.has(w));
149
+ const counts = new Map();
150
+ for (const w of filtered) {
151
+ counts.set(w, ((_b = counts.get(w)) !== null && _b !== void 0 ? _b : 0) + 1);
152
+ }
153
+ const sorted = [...counts.entries()]
154
+ .sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]))
155
+ .slice(0, MAX_KEYWORDS);
156
+ return { keywords: sorted.map(([word]) => word) };
157
+ }),
158
+ });
159
+ // !!
160
+ // > Format result task
161
+ exports.pdfPipeline.task({
162
+ name: 'format_result',
163
+ parents: [extractText, classifyDocument, summarizeText, extractKeywords],
164
+ fn: (input, ctx) => __awaiter(void 0, void 0, void 0, function* () {
165
+ const extract = yield ctx.parentOutput(extractText);
166
+ const classify = yield ctx.parentOutput(classifyDocument);
167
+ const summary = yield ctx.parentOutput(summarizeText);
168
+ const keywords = yield ctx.parentOutput(extractKeywords);
169
+ return {
170
+ filename: input.filename,
171
+ category: classify.category,
172
+ summary: summary.summary,
173
+ keywords: keywords.keywords,
174
+ wordCount: summary.wordCount,
175
+ pageCount: extract.pageCount,
176
+ };
177
+ }),
178
+ });
179
+ // !!
package/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const HATCHET_VERSION = "1.22.0";
1
+ export declare const HATCHET_VERSION = "1.22.2";
package/version.js CHANGED
@@ -1,4 +1,4 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.HATCHET_VERSION = void 0;
4
- exports.HATCHET_VERSION = '1.22.0';
4
+ exports.HATCHET_VERSION = '1.22.2';