@hatchet-dev/typescript-sdk 1.23.0 → 1.23.1

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.
@@ -16,6 +16,7 @@ declare const ClientTLSConfigSchema: z.ZodObject<{
16
16
  export declare const OpenTelemetryConfigSchema: z.ZodObject<{
17
17
  excludedAttributes: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
18
18
  includeTaskNameInSpanName: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
19
+ individualRunSpansForBulkRun: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
19
20
  }, z.core.$strip>;
20
21
  export type OpenTelemetryConfig = z.infer<typeof OpenTelemetryConfigSchema>;
21
22
  export declare const ClientConfigSchema: z.ZodObject<{
@@ -49,6 +50,7 @@ export declare const ClientConfigSchema: z.ZodObject<{
49
50
  otel: z.ZodOptional<z.ZodObject<{
50
51
  excludedAttributes: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
51
52
  includeTaskNameInSpanName: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
53
+ individualRunSpansForBulkRun: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
52
54
  }, z.core.$strip>>;
53
55
  middleware: z.ZodOptional<z.ZodObject<{
54
56
  before: z.ZodOptional<z.ZodAny>;
@@ -24,6 +24,14 @@ exports.OpenTelemetryConfigSchema = v4_1.z.object({
24
24
  * e.g., "hatchet.start_step_run.my_task" instead of "hatchet.start_step_run"
25
25
  */
26
26
  includeTaskNameInSpanName: v4_1.z.boolean().optional().default(false),
27
+ /**
28
+ * If true, a child `hatchet.run_workflow` span is created for each item in a
29
+ * bulk run (`runWorkflows`), nested under the parent `hatchet.run_workflows`
30
+ * span, and each item's traceparent points at its own span. Defaults to false
31
+ * to preserve the existing span structure for downstream OpenTelemetry
32
+ * collectors.
33
+ */
34
+ individualRunSpansForBulkRun: v4_1.z.boolean().optional().default(false),
27
35
  });
28
36
  const TaskMiddlewareSchema = v4_1.z
29
37
  .object({
@@ -35,7 +35,7 @@ catch (_a) {
35
35
  const otelApi = require('@opentelemetry/api');
36
36
  const otelInstrumentation = require('@opentelemetry/instrumentation');
37
37
  /* eslint-enable @typescript-eslint/no-require-imports */
38
- const { context, propagation, SpanKind, SpanStatusCode, diag } = otelApi;
38
+ const { context, propagation, SpanKind, SpanStatusCode, diag, trace } = otelApi;
39
39
  const { InstrumentationBase, InstrumentationNodeModuleDefinition, InstrumentationNodeModuleFile, isWrapped, } = otelInstrumentation;
40
40
  const INSTRUMENTOR_NAME = '@hatchet-dev/typescript-sdk';
41
41
  // FIXME: refactor version check to use the new pattern introduced in #2954
@@ -354,23 +354,84 @@ class HatchetInstrumentor extends InstrumentationBase {
354
354
  return tracer.startActiveSpan('hatchet.run_workflows', {
355
355
  kind: SpanKind.PRODUCER,
356
356
  attributes,
357
- }, (span) => {
358
- const enhancedWorkflowRuns = workflowRuns.map((run) => {
359
- var _a, _b;
360
- const enhancedMetadata = Object.assign({}, ((_b = (_a = run.options) === null || _a === void 0 ? void 0 : _a.additionalMetadata) !== null && _b !== void 0 ? _b : {}));
361
- injectContext(enhancedMetadata);
362
- return Object.assign(Object.assign({}, run), { options: Object.assign(Object.assign({}, run.options), { additionalMetadata: enhancedMetadata }) });
363
- });
364
- return original
365
- .call(this, enhancedWorkflowRuns, batchSize)
366
- .catch((error) => {
367
- span.recordException(error);
368
- span.setStatus({ code: SpanStatusCode.ERROR, message: error === null || error === void 0 ? void 0 : error.message });
357
+ }, (batchSpan) => {
358
+ const individualSpans = getConfig().individualRunSpansForBulkRun;
359
+ const itemSpans = [];
360
+ let enhancedWorkflowRuns;
361
+ try {
362
+ enhancedWorkflowRuns = workflowRuns.map((run) => {
363
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
364
+ const enhancedMetadata = Object.assign({}, ((_b = (_a = run.options) === null || _a === void 0 ? void 0 : _a.additionalMetadata) !== null && _b !== void 0 ? _b : {}));
365
+ if (individualSpans) {
366
+ const itemAttributes = filterAttributes({
367
+ [opentelemetry_1.OTelAttribute.WORKFLOW_NAME]: run.workflowName,
368
+ [opentelemetry_1.OTelAttribute.ACTION_PAYLOAD]: JSON.stringify(run.input),
369
+ [opentelemetry_1.OTelAttribute.PARENT_ID]: (_c = run.options) === null || _c === void 0 ? void 0 : _c.parentId,
370
+ [opentelemetry_1.OTelAttribute.PARENT_STEP_RUN_ID]: (_d = run.options) === null || _d === void 0 ? void 0 : _d.parentStepRunId,
371
+ [opentelemetry_1.OTelAttribute.CHILD_INDEX]: (_e = run.options) === null || _e === void 0 ? void 0 : _e.childIndex,
372
+ [opentelemetry_1.OTelAttribute.CHILD_KEY]: (_f = run.options) === null || _f === void 0 ? void 0 : _f.childKey,
373
+ [opentelemetry_1.OTelAttribute.ADDITIONAL_METADATA]: ((_g = run.options) === null || _g === void 0 ? void 0 : _g.additionalMetadata)
374
+ ? JSON.stringify(run.options.additionalMetadata)
375
+ : undefined,
376
+ [opentelemetry_1.OTelAttribute.PRIORITY]: (_h = run.options) === null || _h === void 0 ? void 0 : _h.priority,
377
+ [opentelemetry_1.OTelAttribute.DESIRED_WORKER_ID]: (_j = run.options) === null || _j === void 0 ? void 0 : _j.desiredWorkerId,
378
+ }, getConfig().excludedAttributes);
379
+ const itemSpan = tracer.startSpan('hatchet.run_workflow', {
380
+ kind: SpanKind.PRODUCER,
381
+ attributes: itemAttributes,
382
+ });
383
+ itemSpans.push(itemSpan);
384
+ propagation.inject(trace.setSpan(context.active(), itemSpan), enhancedMetadata);
385
+ }
386
+ else {
387
+ // Legacy behaviour: inject the active (batch) span context so the
388
+ // span structure seen by downstream collectors is unchanged.
389
+ injectContext(enhancedMetadata);
390
+ }
391
+ return Object.assign(Object.assign({}, run), { options: Object.assign(Object.assign({}, run.options), { additionalMetadata: enhancedMetadata }) });
392
+ });
393
+ }
394
+ catch (error) {
395
+ const err = error;
396
+ batchSpan.recordException(err);
397
+ batchSpan.setStatus({ code: SpanStatusCode.ERROR, message: err === null || err === void 0 ? void 0 : err.message });
398
+ itemSpans.forEach((s) => {
399
+ s.recordException(err);
400
+ s.setStatus({ code: SpanStatusCode.ERROR, message: err === null || err === void 0 ? void 0 : err.message });
401
+ s.end();
402
+ });
403
+ batchSpan.end();
369
404
  throw error;
370
- })
371
- .finally(() => {
372
- span.end();
373
- });
405
+ }
406
+ try {
407
+ return original
408
+ .call(this, enhancedWorkflowRuns, batchSize)
409
+ .catch((error) => {
410
+ batchSpan.recordException(error);
411
+ batchSpan.setStatus({ code: SpanStatusCode.ERROR, message: error === null || error === void 0 ? void 0 : error.message });
412
+ itemSpans.forEach((s) => {
413
+ s.recordException(error);
414
+ s.setStatus({ code: SpanStatusCode.ERROR, message: error === null || error === void 0 ? void 0 : error.message });
415
+ });
416
+ throw error;
417
+ })
418
+ .finally(() => {
419
+ itemSpans.forEach((s) => s.end());
420
+ batchSpan.end();
421
+ });
422
+ }
423
+ catch (error) {
424
+ const err = error;
425
+ batchSpan.recordException(err);
426
+ batchSpan.setStatus({ code: SpanStatusCode.ERROR, message: err === null || err === void 0 ? void 0 : err.message });
427
+ itemSpans.forEach((s) => {
428
+ s.recordException(err);
429
+ s.setStatus({ code: SpanStatusCode.ERROR, message: err === null || err === void 0 ? void 0 : err.message });
430
+ s.end();
431
+ });
432
+ batchSpan.end();
433
+ throw error;
434
+ }
374
435
  });
375
436
  });
376
437
  };
@@ -2,5 +2,6 @@ export type { OpenTelemetryConfig } from '../clients/hatchet-client/client-confi
2
2
  export declare const DEFAULT_CONFIG: {
3
3
  excludedAttributes: string[];
4
4
  includeTaskNameInSpanName: boolean;
5
+ individualRunSpansForBulkRun: boolean;
5
6
  enableHatchetCollector: boolean;
6
7
  };
@@ -4,5 +4,6 @@ exports.DEFAULT_CONFIG = void 0;
4
4
  exports.DEFAULT_CONFIG = {
5
5
  excludedAttributes: [],
6
6
  includeTaskNameInSpanName: false,
7
+ individualRunSpansForBulkRun: false,
7
8
  enableHatchetCollector: true,
8
9
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hatchet-dev/typescript-sdk",
3
- "version": "1.23.0",
3
+ "version": "1.23.1",
4
4
  "description": "Background task orchestration & visibility for developers",
5
5
  "types": "dist/index.d.ts",
6
6
  "files": [
@@ -19,6 +19,7 @@
19
19
  "author": "",
20
20
  "license": "MIT",
21
21
  "devDependencies": {
22
+ "@aws-sdk/client-s3": "^3.1042.0",
22
23
  "@eslint/js": "^10.0.1",
23
24
  "@types/jest": "^29.5.14",
24
25
  "@types/node": "^22.13.14",
@@ -43,7 +44,7 @@
43
44
  "@anthropic-ai/claude-agent-sdk": "^0.3.148",
44
45
  "@grpc/grpc-js": "^1.14.3",
45
46
  "@modelcontextprotocol/sdk": "^1.29.0",
46
- "@openai/agents": "0.11.4",
47
+ "@openai/agents": "0.11.6",
47
48
  "@opentelemetry/api": "^1.9.0",
48
49
  "@opentelemetry/core": "^2.0.0",
49
50
  "@opentelemetry/exporter-trace-otlp-grpc": "^0.218.0",
@@ -75,7 +76,7 @@
75
76
  "@anthropic-ai/claude-agent-sdk": "^0.3.148",
76
77
  "@grpc/grpc-js": "^1.14.3",
77
78
  "@modelcontextprotocol/sdk": "^1.29.0",
78
- "@openai/agents": "0.11.4",
79
+ "@openai/agents": "0.11.6",
79
80
  "@opentelemetry/api": "^1.9.0",
80
81
  "@opentelemetry/core": "^2.0.0",
81
82
  "@opentelemetry/exporter-trace-otlp-grpc": "^0.218.0",
@@ -86,6 +86,7 @@ class ConfigLoader {
86
86
  const otelConfig = (_5 = (_4 = override === null || override === void 0 ? void 0 : override.otel) !== null && _4 !== void 0 ? _4 : yaml === null || yaml === void 0 ? void 0 : yaml.otel) !== null && _5 !== void 0 ? _5 : {
87
87
  excludedAttributes: this.parseJsonArray(this.env('HATCHET_CLIENT_OPENTELEMETRY_EXCLUDED_ATTRIBUTES') || '[]'),
88
88
  includeTaskNameInSpanName: this.env('HATCHET_CLIENT_OPENTELEMETRY_INCLUDE_TASK_NAME_IN_SPAN_NAME') === 'true',
89
+ individualRunSpansForBulkRun: this.env('HATCHET_CLIENT_OPENTELEMETRY_INDIVIDUAL_RUN_SPANS_FOR_BULK_RUN') === 'true',
89
90
  };
90
91
  const grpcMaxRecvMessageLength = (_8 = (_7 = (_6 = override === null || override === void 0 ? void 0 : override.grpc_max_recv_message_length) !== null && _6 !== void 0 ? _6 : yaml === null || yaml === void 0 ? void 0 : yaml.grpc_max_recv_message_length) !== null && _7 !== void 0 ? _7 : this.parseIntEnv('HATCHET_CLIENT_GRPC_MAX_RECV_MESSAGE_LENGTH')) !== null && _8 !== void 0 ? _8 : 4 * 1024 * 1024;
91
92
  const grpcMaxSendMessageLength = (_11 = (_10 = (_9 = override === null || override === void 0 ? void 0 : override.grpc_max_send_message_length) !== null && _9 !== void 0 ? _9 : yaml === null || yaml === void 0 ? void 0 : yaml.grpc_max_send_message_length) !== null && _10 !== void 0 ? _10 : this.parseIntEnv('HATCHET_CLIENT_GRPC_MAX_SEND_MESSAGE_LENGTH')) !== null && _11 !== void 0 ? _11 : 4 * 1024 * 1024;
@@ -79,6 +79,7 @@ class WorkflowsClient {
79
79
  */
80
80
  get(workflow) {
81
81
  return __awaiter(this, void 0, void 0, function* () {
82
+ var _a;
82
83
  // Get workflow name string
83
84
  const name = (0, exports.workflowNameString)(workflow);
84
85
  // Check cache first
@@ -94,8 +95,7 @@ class WorkflowsClient {
94
95
  name,
95
96
  });
96
97
  if (data && data.rows && data.rows.length > 0) {
97
- const [wf] = data.rows;
98
- // Cache the result
98
+ const wf = (_a = data.rows.find((row) => row.name === name)) !== null && _a !== void 0 ? _a : data.rows[0];
99
99
  this.workflowCache.set(name, {
100
100
  workflow: wf,
101
101
  expiry: Date.now() + this.cacheTTL,
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,177 @@
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
+ var __asyncValues = (this && this.__asyncValues) || function (o) {
12
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
13
+ var m = o[Symbol.asyncIterator], i;
14
+ return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
15
+ function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
16
+ function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
17
+ };
18
+ var _a, _b, _c, _d;
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ const client_s3_1 = require("@aws-sdk/client-s3");
21
+ const v1_1 = require("../../..");
22
+ const hatchet_client_1 = require("../../hatchet-client");
23
+ const BUCKET_PREFIX = (_a = process.env.S3_WORKER_BUCKET_PREFIX) !== null && _a !== void 0 ? _a : 'bucket-';
24
+ const MAX_CONCURRENT_BUCKET_POLLERS = parseInt((_b = process.env.S3_WORKER_MAX_CONCURRENT_BUCKET_POLLERS) !== null && _b !== void 0 ? _b : '10');
25
+ const MAX_RUNS_PER_BUCKET = parseInt((_c = process.env.S3_WORKER_MAX_RUNS_PER_BUCKET) !== null && _c !== void 0 ? _c : '20');
26
+ const SLOTS = parseInt((_d = process.env.S3_WORKER_SLOTS) !== null && _d !== void 0 ? _d : '40');
27
+ // > Client Setup
28
+ const s3 = new client_s3_1.S3Client({ forcePathStyle: true });
29
+ // !!
30
+ // > Fetch S3 Buckets
31
+ const fetchBucketsWorkflow = hatchet_client_1.hatchet.workflow({
32
+ name: 'fetch_s3_buckets',
33
+ on: {
34
+ cron: '* * * * *',
35
+ },
36
+ concurrency: {
37
+ expression: "'singleton'",
38
+ maxRuns: 1,
39
+ limitStrategy: v1_1.ConcurrencyLimitStrategy.CANCEL_NEWEST,
40
+ },
41
+ });
42
+ // !!
43
+ // > Fetch S3 Objects
44
+ const fetchObjectsWorkflow = hatchet_client_1.hatchet.workflow({
45
+ name: 'fetch_s3_objects',
46
+ concurrency: [
47
+ {
48
+ expression: 'input.bucket',
49
+ maxRuns: 1,
50
+ limitStrategy: v1_1.ConcurrencyLimitStrategy.CANCEL_NEWEST,
51
+ },
52
+ {
53
+ expression: "'constant'",
54
+ maxRuns: MAX_CONCURRENT_BUCKET_POLLERS,
55
+ limitStrategy: v1_1.ConcurrencyLimitStrategy.GROUP_ROUND_ROBIN,
56
+ },
57
+ ],
58
+ });
59
+ // !!
60
+ // > Process S3 Objects
61
+ const processObjectWorkflow = hatchet_client_1.hatchet.workflow({
62
+ name: 'process_object',
63
+ concurrency: {
64
+ expression: 'input.bucket',
65
+ maxRuns: MAX_RUNS_PER_BUCKET,
66
+ limitStrategy: v1_1.ConcurrencyLimitStrategy.GROUP_ROUND_ROBIN,
67
+ },
68
+ });
69
+ // !!
70
+ // > Fetch S3 Buckets Task
71
+ fetchBucketsWorkflow.task({
72
+ name: 'fetch_buckets',
73
+ fn: () => __awaiter(void 0, void 0, void 0, function* () {
74
+ var _a, e_1, _b, _c;
75
+ var _d;
76
+ try {
77
+ for (var _e = true, _f = __asyncValues((0, client_s3_1.paginateListBuckets)({ client: s3, pageSize: 10 }, { Prefix: BUCKET_PREFIX })), _g; _g = yield _f.next(), _a = _g.done, !_a; _e = true) {
78
+ _c = _g.value;
79
+ _e = false;
80
+ const page = _c;
81
+ const items = ((_d = page.Buckets) !== null && _d !== void 0 ? _d : [])
82
+ .filter((bucket) => bucket.Name !== undefined)
83
+ .map((bucket) => ({
84
+ input: { bucket: bucket.Name },
85
+ opts: {
86
+ childKey: bucket.Name,
87
+ additionalMetadata: { 'bucket-name': bucket.Name },
88
+ },
89
+ }));
90
+ if (items.length > 0) {
91
+ yield fetchObjectsWorkflow.runManyNoWait(items);
92
+ }
93
+ }
94
+ }
95
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
96
+ finally {
97
+ try {
98
+ if (!_e && !_a && (_b = _f.return)) yield _b.call(_f);
99
+ }
100
+ finally { if (e_1) throw e_1.error; }
101
+ }
102
+ return {};
103
+ }),
104
+ });
105
+ // !!
106
+ // > Fetch S3 Objects Task
107
+ fetchObjectsWorkflow.task({
108
+ name: 'fetch_objects',
109
+ fn: (input) => __awaiter(void 0, void 0, void 0, function* () {
110
+ var _a, e_2, _b, _c;
111
+ var _d;
112
+ try {
113
+ for (var _e = true, _f = __asyncValues((0, client_s3_1.paginateListObjectsV2)({ client: s3, pageSize: 100 }, { Bucket: input.bucket })), _g; _g = yield _f.next(), _a = _g.done, !_a; _e = true) {
114
+ _c = _g.value;
115
+ _e = false;
116
+ const page = _c;
117
+ const items = ((_d = page.Contents) !== null && _d !== void 0 ? _d : [])
118
+ .filter((obj) => obj.Key !== undefined)
119
+ .map((obj) => ({
120
+ input: { bucket: input.bucket, key: obj.Key },
121
+ opts: {
122
+ childKey: `${input.bucket}/${obj.Key}`,
123
+ },
124
+ }));
125
+ if (items.length > 0) {
126
+ yield processObjectWorkflow.runManyNoWait(items);
127
+ }
128
+ }
129
+ }
130
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
131
+ finally {
132
+ try {
133
+ if (!_e && !_a && (_b = _f.return)) yield _b.call(_f);
134
+ }
135
+ finally { if (e_2) throw e_2.error; }
136
+ }
137
+ return {};
138
+ }),
139
+ });
140
+ // !!
141
+ // > Download and Process S3 Objects Task
142
+ processObjectWorkflow.task({
143
+ name: 'process_object',
144
+ fn: (input, ctx) => __awaiter(void 0, void 0, void 0, function* () {
145
+ let body;
146
+ try {
147
+ const response = yield s3.send(new client_s3_1.GetObjectCommand({ Bucket: input.bucket, Key: input.key }));
148
+ if (!response.Body) {
149
+ return {};
150
+ }
151
+ body = Buffer.from(yield response.Body.transformToByteArray());
152
+ }
153
+ catch (err) {
154
+ if (err instanceof client_s3_1.NoSuchKey || err instanceof client_s3_1.NoSuchBucket) {
155
+ yield ctx.log(`skipping ${input.bucket}/${input.key}: not found`);
156
+ return {};
157
+ }
158
+ throw err;
159
+ }
160
+ // TODO: actual image processing here
161
+ yield s3.send(new client_s3_1.DeleteObjectCommand({ Bucket: input.bucket, Key: input.key }));
162
+ return {};
163
+ }),
164
+ });
165
+ // !!
166
+ function main() {
167
+ return __awaiter(this, void 0, void 0, function* () {
168
+ const worker = yield hatchet_client_1.hatchet.worker('s3-worker', {
169
+ workflows: [fetchBucketsWorkflow, fetchObjectsWorkflow, processObjectWorkflow],
170
+ slots: SLOTS,
171
+ });
172
+ yield worker.start();
173
+ });
174
+ }
175
+ if (require.main === module) {
176
+ main();
177
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
36
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
37
+ return new (P || (P = Promise))(function (resolve, reject) {
38
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
39
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
40
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
41
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
42
+ });
43
+ };
44
+ var __asyncValues = (this && this.__asyncValues) || function (o) {
45
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
46
+ var m = o[Symbol.asyncIterator], i;
47
+ return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
48
+ function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
49
+ function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
50
+ };
51
+ Object.defineProperty(exports, "__esModule", { value: true });
52
+ const tools_1 = require("./tools");
53
+ function main() {
54
+ return __awaiter(this, void 0, void 0, function* () {
55
+ var _a, e_1, _b, _c;
56
+ const lookupCustomerTool = (0, tools_1.createLookupCustomerToolClaude)();
57
+ const checkOrderStatusTool = (0, tools_1.createCheckOrderStatusToolClaude)();
58
+ const ticketTool = (0, tools_1.createTicketToolClaude)();
59
+ // The Claude Agent SDK is ESM-only, so avoid loading it at module import time.
60
+ // Run this example with an ESM-compatible TypeScript runner.
61
+ const { query, createSdkMcpServer } = yield Promise.resolve().then(() => __importStar(require('@anthropic-ai/claude-agent-sdk')));
62
+ // Wrap the tools in an in-process MCP server
63
+ const supportServer = createSdkMcpServer({
64
+ name: 'support',
65
+ version: '1.0.0',
66
+ tools: [lookupCustomerTool, checkOrderStatusTool, ticketTool],
67
+ });
68
+ try {
69
+ for (var _d = true, _e = __asyncValues(query({
70
+ prompt: 'Customer C-100 says order ORD-9987 has not arrived. ' +
71
+ 'Look up the customer, check the order status, and create a ' +
72
+ 'support ticket if the order has a known issue or delayed delivery. ' +
73
+ 'If you create a ticket, use priority "high", subject ' +
74
+ '"Delayed order ORD-9987", and a body that summarizes the known ' +
75
+ 'carrier delay. Then summarize what happened.',
76
+ options: {
77
+ mcpServers: { support: supportServer },
78
+ allowedTools: [
79
+ `mcp__${supportServer.name}__${lookupCustomerTool.name}`,
80
+ `mcp__${supportServer.name}__${checkOrderStatusTool.name}`,
81
+ `mcp__${supportServer.name}__${ticketTool.name}`,
82
+ ],
83
+ },
84
+ })), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
85
+ _c = _f.value;
86
+ _d = false;
87
+ const message = _c;
88
+ // "result" is the final message after all tool calls complete
89
+ if (message.type === 'result' && message.subtype === 'success') {
90
+ console.log(message.result);
91
+ }
92
+ }
93
+ }
94
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
95
+ finally {
96
+ try {
97
+ if (!_d && !_a && (_b = _e.return)) yield _b.call(_e);
98
+ }
99
+ finally { if (e_1) throw e_1.error; }
100
+ }
101
+ });
102
+ }
103
+ if (require.main === module) {
104
+ main()
105
+ .catch(console.error)
106
+ .finally(() => {
107
+ process.exit(0);
108
+ });
109
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
36
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
37
+ return new (P || (P = Promise))(function (resolve, reject) {
38
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
39
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
40
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
41
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
42
+ });
43
+ };
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ const tools_1 = require("./tools");
46
+ function main() {
47
+ return __awaiter(this, void 0, void 0, function* () {
48
+ const lookupCustomerTool = (0, tools_1.createLookupCustomerToolOpenai)();
49
+ const checkOrderStatusTool = (0, tools_1.createCheckOrderStatusToolOpenai)();
50
+ const ticketTool = (0, tools_1.createTicketToolOpenai)();
51
+ // Dynamic import — @openai/agents crashes at load time with Zod v3, so we delay
52
+ // the import until after mcpTool has already verified Zod v4 is available.
53
+ const { Agent, run } = yield Promise.resolve().then(() => __importStar(require('@openai/agents')));
54
+ const agent = new Agent({
55
+ name: 'support-agent',
56
+ tools: [lookupCustomerTool, checkOrderStatusTool, ticketTool],
57
+ });
58
+ const result = yield run(agent, 'Customer C-100 says order ORD-9987 has not arrived. ' +
59
+ 'Look up the customer, check the order status, and create a ' +
60
+ 'support ticket if the order has a known issue or delayed delivery. ' +
61
+ 'If you create a ticket, use priority "high", subject ' +
62
+ '"Delayed order ORD-9987", and a body that summarizes the known ' +
63
+ 'carrier delay. Then summarize what happened.');
64
+ console.log(result.finalOutput);
65
+ });
66
+ }
67
+ if (require.main === module) {
68
+ main()
69
+ .catch(console.error)
70
+ .finally(() => {
71
+ process.exit(0);
72
+ });
73
+ }
@@ -0,0 +1,45 @@
1
+ type CustomerInfo = {
2
+ customerId: string;
3
+ name: string;
4
+ email: string;
5
+ plan: string;
6
+ accountStatus: string;
7
+ defaultOrderId: string;
8
+ supportTier: string;
9
+ };
10
+ type OrderStatus = {
11
+ orderId: string;
12
+ status: string;
13
+ lastUpdated: string;
14
+ estimatedDelivery: string;
15
+ knownIssue: string | null;
16
+ carrier: string;
17
+ trackingNumber: string;
18
+ };
19
+ type TicketResult = {
20
+ ticketId: string;
21
+ status: string;
22
+ priority: string;
23
+ routingTeam: string;
24
+ summary: string;
25
+ };
26
+ export declare const lookupCustomer: import("../..").TaskWorkflowDeclaration<{
27
+ customerId: string;
28
+ }, CustomerInfo, {}, {}, {}, {}>;
29
+ export declare const checkOrderStatus: import("../..").TaskWorkflowDeclaration<{
30
+ orderId: string;
31
+ }, OrderStatus, {}, {}, {}, {}>;
32
+ export declare const createTicket: import("../..").TaskWorkflowDeclaration<{
33
+ customerId: string;
34
+ orderId: string;
35
+ subject: string;
36
+ body: string;
37
+ priority: string;
38
+ }, TicketResult, {}, {}, {}, {}>;
39
+ export declare function createLookupCustomerToolClaude(): import("@anthropic-ai/claude-agent-sdk").SdkMcpToolDefinition;
40
+ export declare function createCheckOrderStatusToolClaude(): import("@anthropic-ai/claude-agent-sdk").SdkMcpToolDefinition;
41
+ export declare function createTicketToolClaude(): import("@anthropic-ai/claude-agent-sdk").SdkMcpToolDefinition;
42
+ export declare function createLookupCustomerToolOpenai(): import("@openai/agents").FunctionTool;
43
+ export declare function createCheckOrderStatusToolOpenai(): import("@openai/agents").FunctionTool;
44
+ export declare function createTicketToolOpenai(): import("@openai/agents").FunctionTool;
45
+ export {};
@@ -0,0 +1,144 @@
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.createTicket = exports.checkOrderStatus = exports.lookupCustomer = void 0;
13
+ exports.createLookupCustomerToolClaude = createLookupCustomerToolClaude;
14
+ exports.createCheckOrderStatusToolClaude = createCheckOrderStatusToolClaude;
15
+ exports.createTicketToolClaude = createTicketToolClaude;
16
+ exports.createLookupCustomerToolOpenai = createLookupCustomerToolOpenai;
17
+ exports.createCheckOrderStatusToolOpenai = createCheckOrderStatusToolOpenai;
18
+ exports.createTicketToolOpenai = createTicketToolOpenai;
19
+ // > Setup
20
+ const v4_1 = require("zod/v4");
21
+ const hatchet_client_1 = require("../hatchet-client");
22
+ // !!
23
+ // > Models
24
+ const CustomerLookupInput = v4_1.z.object({
25
+ customerId: v4_1.z.string(),
26
+ });
27
+ const OrderStatusInput = v4_1.z.object({
28
+ orderId: v4_1.z.string(),
29
+ });
30
+ const CreateTicketInput = v4_1.z.object({
31
+ customerId: v4_1.z.string(),
32
+ orderId: v4_1.z.string(),
33
+ subject: v4_1.z.string(),
34
+ body: v4_1.z.string(),
35
+ priority: v4_1.z.string(),
36
+ });
37
+ // !!
38
+ // > Fixture data
39
+ const CUSTOMERS = {
40
+ 'C-100': {
41
+ customerId: 'C-100',
42
+ name: 'Alice Martin',
43
+ email: 'alice@example.com',
44
+ plan: 'business',
45
+ accountStatus: 'active',
46
+ defaultOrderId: 'ORD-9987',
47
+ supportTier: 'priority',
48
+ },
49
+ };
50
+ const ORDERS = {
51
+ 'ORD-9987': {
52
+ orderId: 'ORD-9987',
53
+ status: 'delayed',
54
+ lastUpdated: '2026-05-20T14:30:00Z',
55
+ estimatedDelivery: '2026-05-28',
56
+ knownIssue: 'Carrier reported weather delay at regional hub',
57
+ carrier: 'FastShip',
58
+ trackingNumber: 'FS-482910',
59
+ },
60
+ };
61
+ // !!
62
+ // > Lookup customer
63
+ exports.lookupCustomer = hatchet_client_1.hatchet.task({
64
+ name: 'lookup-customer',
65
+ inputValidator: CustomerLookupInput,
66
+ description: 'Look up a customer by ID and return their profile, plan, and support tier.',
67
+ fn: (input) => __awaiter(void 0, void 0, void 0, function* () {
68
+ const customer = CUSTOMERS[input.customerId];
69
+ if (!customer) {
70
+ return {
71
+ customerId: input.customerId,
72
+ name: 'Unknown',
73
+ email: 'unknown@example.com',
74
+ plan: 'none',
75
+ accountStatus: 'not_found',
76
+ defaultOrderId: '',
77
+ supportTier: 'standard',
78
+ };
79
+ }
80
+ return customer;
81
+ }),
82
+ });
83
+ // !!
84
+ // > Check order status
85
+ exports.checkOrderStatus = hatchet_client_1.hatchet.task({
86
+ name: 'check-order-status',
87
+ inputValidator: OrderStatusInput,
88
+ description: 'Check the current status, carrier, and any known issues for an order.',
89
+ fn: (input) => __awaiter(void 0, void 0, void 0, function* () {
90
+ const order = ORDERS[input.orderId];
91
+ if (!order) {
92
+ return {
93
+ orderId: input.orderId,
94
+ status: 'not_found',
95
+ lastUpdated: '',
96
+ estimatedDelivery: '',
97
+ knownIssue: null,
98
+ carrier: 'unknown',
99
+ trackingNumber: '',
100
+ };
101
+ }
102
+ return order;
103
+ }),
104
+ });
105
+ // !!
106
+ // > Create ticket
107
+ exports.createTicket = hatchet_client_1.hatchet.task({
108
+ name: 'create-ticket',
109
+ inputValidator: CreateTicketInput,
110
+ description: 'Create a support ticket for a customer issue and return the ticket ID and routing.',
111
+ fn: (input) => __awaiter(void 0, void 0, void 0, function* () {
112
+ const ticketId = `TICKET-${input.customerId}-001`;
113
+ return {
114
+ ticketId,
115
+ status: 'open',
116
+ priority: input.priority,
117
+ routingTeam: 'shipping-support',
118
+ summary: `Ticket ${ticketId} created for ${input.customerId} regarding order ${input.orderId}: ${input.subject}`,
119
+ };
120
+ }),
121
+ });
122
+ // !!
123
+ // > Create Claude tools
124
+ function createLookupCustomerToolClaude() {
125
+ return exports.lookupCustomer.mcpTool('claude');
126
+ }
127
+ function createCheckOrderStatusToolClaude() {
128
+ return exports.checkOrderStatus.mcpTool('claude');
129
+ }
130
+ function createTicketToolClaude() {
131
+ return exports.createTicket.mcpTool('claude');
132
+ }
133
+ // !!
134
+ // > Create openai tools
135
+ function createLookupCustomerToolOpenai() {
136
+ return exports.lookupCustomer.mcpTool('openai');
137
+ }
138
+ function createCheckOrderStatusToolOpenai() {
139
+ return exports.checkOrderStatus.mcpTool('openai');
140
+ }
141
+ function createTicketToolOpenai() {
142
+ return exports.createTicket.mcpTool('openai');
143
+ }
144
+ // !!
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,24 @@
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
+ const hatchet_client_1 = require("../hatchet-client");
13
+ const tools_1 = require("./tools");
14
+ function main() {
15
+ return __awaiter(this, void 0, void 0, function* () {
16
+ const worker = yield hatchet_client_1.hatchet.worker('support-tools-worker', {
17
+ workflows: [tools_1.lookupCustomer, tools_1.checkOrderStatus, tools_1.createTicket],
18
+ });
19
+ yield worker.start();
20
+ });
21
+ }
22
+ if (require.main === module) {
23
+ main();
24
+ }
package/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const HATCHET_VERSION = "1.23.0";
1
+ export declare const HATCHET_VERSION = "1.23.1";
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.23.0';
4
+ exports.HATCHET_VERSION = '1.23.1';