@hatchet-dev/typescript-sdk 1.21.1 → 1.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/clients/hatchet-client/client-config.d.ts +27 -133
  2. package/clients/hatchet-client/client-config.js +24 -24
  3. package/legacy/legacy-client.js +2 -2
  4. package/legacy/step.d.ts +22 -121
  5. package/legacy/step.js +7 -4
  6. package/legacy/workflow.d.ts +46 -420
  7. package/legacy/workflow.js +5 -5
  8. package/package.json +12 -6
  9. package/protoc/dispatcher/dispatcher.d.ts +4 -0
  10. package/protoc/dispatcher/dispatcher.js +41 -1
  11. package/util/config-loader/config-loader.js +2 -2
  12. package/util/uuid.js +2 -2
  13. package/v1/agent/claude.d.ts +17 -0
  14. package/v1/agent/claude.js +83 -0
  15. package/v1/agent/openai.d.ts +4 -0
  16. package/v1/agent/openai.js +83 -0
  17. package/v1/client/client.js +2 -2
  18. package/v1/client/features/crons.d.ts +3 -15
  19. package/v1/client/features/crons.js +8 -8
  20. package/v1/client/features/schedules.d.ts +6 -20
  21. package/v1/client/features/schedules.js +10 -10
  22. package/v1/client/worker/context.d.ts +11 -1
  23. package/v1/client/worker/context.js +14 -0
  24. package/v1/client/worker/worker-internal.js +2 -2
  25. package/v1/declaration.d.ts +18 -1
  26. package/v1/declaration.js +10 -0
  27. package/v1/examples/agent/agent-claude.d.ts +1 -0
  28. package/v1/examples/agent/agent-claude.js +68 -0
  29. package/v1/examples/agent/agent-openai.d.ts +1 -0
  30. package/v1/examples/agent/agent-openai.js +72 -0
  31. package/v1/examples/agent/worker.d.ts +1 -0
  32. package/v1/examples/agent/worker.js +24 -0
  33. package/v1/examples/agent/workflow.d.ts +26 -0
  34. package/v1/examples/agent/workflow.js +48 -0
  35. package/v1/examples/durable/workflow.d.ts +6 -2
  36. package/v1/examples/durable/workflow.js +9 -6
  37. package/v1/examples/durable_eviction/workflow.js +6 -0
  38. package/v1/examples/e2e-worker.js +7 -0
  39. package/v1/examples/simple/run.js +5 -0
  40. package/v1/examples/simple/zod.d.ts +2 -6
  41. package/v1/examples/simple/zod.js +1 -1
  42. package/v1/examples/support_agent/run.d.ts +1 -0
  43. package/v1/examples/support_agent/run.js +42 -0
  44. package/v1/examples/support_agent/workflow.d.ts +43 -0
  45. package/v1/examples/support_agent/workflow.js +140 -0
  46. package/v1/examples/welcome_email/run.d.ts +1 -0
  47. package/v1/examples/welcome_email/run.js +40 -0
  48. package/v1/examples/welcome_email/workflow.d.ts +11 -0
  49. package/v1/examples/welcome_email/workflow.js +52 -0
  50. package/version.d.ts +1 -1
  51. package/version.js +1 -1
@@ -0,0 +1,68 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ // eslint-disable-next-line
20
+ const workflow_1 = require("./workflow");
21
+ const claude_agent_sdk_1 = require("@anthropic-ai/claude-agent-sdk");
22
+ const claude_agent_sdk_2 = require("@anthropic-ai/claude-agent-sdk");
23
+ function main() {
24
+ return __awaiter(this, void 0, void 0, function* () {
25
+ // Generate a tool from a standalone task
26
+ // const temperatureTool = getTemperature.mcpTool('claude');
27
+ var _a, e_1, _b, _c;
28
+ // Or from a workflow
29
+ const temperatureTool = workflow_1.getTemperatureWorkflow.mcpTool('claude');
30
+ // Wrap the tool in an in-process MCP server
31
+ const weatherServer = (0, claude_agent_sdk_2.createSdkMcpServer)({
32
+ name: 'weather',
33
+ version: '1.0.0',
34
+ tools: [temperatureTool],
35
+ });
36
+ try {
37
+ for (var _d = true, _e = __asyncValues((0, claude_agent_sdk_1.query)({
38
+ prompt: "What's the temperature in San Francisco?",
39
+ options: {
40
+ mcpServers: { weather: weatherServer },
41
+ allowedTools: [`mcp__${weatherServer.name}__${temperatureTool.name}`],
42
+ },
43
+ })), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
44
+ _c = _f.value;
45
+ _d = false;
46
+ const message = _c;
47
+ // "result" is the final message after all tool calls complete
48
+ if (message.type === 'result' && message.subtype === 'success') {
49
+ console.log(message.result);
50
+ }
51
+ }
52
+ }
53
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
54
+ finally {
55
+ try {
56
+ if (!_d && !_a && (_b = _e.return)) yield _b.call(_e);
57
+ }
58
+ finally { if (e_1) throw e_1.error; }
59
+ }
60
+ });
61
+ }
62
+ if (require.main === module) {
63
+ main()
64
+ .catch(console.error)
65
+ .finally(() => {
66
+ process.exit(0);
67
+ });
68
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,72 @@
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
+ // eslint-disable-next-line
46
+ const workflow_1 = require("./workflow");
47
+ function main() {
48
+ return __awaiter(this, void 0, void 0, function* () {
49
+ // Generate a tool from a standalone task
50
+ // const temperatureTool = getTemperature.mcpTool('openai');
51
+ // Or from a workflow.
52
+ // mcpTool validates Zod v4 is installed before loading @openai/agents, so call it first
53
+ // to get a clear error message if the wrong Zod version is present.
54
+ const temperatureTool = workflow_1.getTemperatureWorkflow.mcpTool('openai');
55
+ // Dynamic import — @openai/agents crashes at load time with Zod v3, so we delay
56
+ // the import until after mcpTool has already verified Zod v4 is available.
57
+ const { Agent, run } = yield Promise.resolve().then(() => __importStar(require('@openai/agents')));
58
+ const agent = new Agent({
59
+ name: 'Agent',
60
+ tools: [temperatureTool],
61
+ });
62
+ const result = yield run(agent, 'What is the weather in San Francisco?');
63
+ console.log(result.finalOutput);
64
+ });
65
+ }
66
+ if (require.main === module) {
67
+ main()
68
+ .catch(console.error)
69
+ .finally(() => {
70
+ process.exit(0);
71
+ });
72
+ }
@@ -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 workflow_1 = require("./workflow");
14
+ function main() {
15
+ return __awaiter(this, void 0, void 0, function* () {
16
+ const worker = yield hatchet_client_1.hatchet.worker('temperature-worker', {
17
+ workflows: [workflow_1.getTemperature, workflow_1.getTemperatureWorkflow],
18
+ });
19
+ yield worker.start();
20
+ });
21
+ }
22
+ if (require.main === module) {
23
+ main();
24
+ }
@@ -0,0 +1,26 @@
1
+ import { z } from 'zod/v4';
2
+ declare const TemperatureInput: z.ZodObject<{
3
+ locationName: z.ZodString;
4
+ coords: z.ZodObject<{
5
+ latitude: z.ZodNumber;
6
+ longitude: z.ZodNumber;
7
+ }, z.core.$strip>;
8
+ }, z.core.$strip>;
9
+ export type TemperatureInputWithZod = z.infer<typeof TemperatureInput>;
10
+ export declare const getTemperature: import("../..").TaskWorkflowDeclaration<{
11
+ locationName: string;
12
+ coords: {
13
+ latitude: number;
14
+ longitude: number;
15
+ };
16
+ }, {
17
+ text: string;
18
+ }, {}, {}, {}, {}>;
19
+ export declare const getTemperatureWorkflow: import("../..").WorkflowDeclaration<{
20
+ locationName: string;
21
+ coords: {
22
+ latitude: number;
23
+ longitude: number;
24
+ };
25
+ }, {}, {}>;
26
+ export {};
@@ -0,0 +1,48 @@
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.getTemperatureWorkflow = exports.getTemperature = void 0;
13
+ // > Declaring a Task
14
+ const hatchet_client_1 = require("../hatchet-client");
15
+ const v4_1 = require("zod/v4");
16
+ // Note that for agent tools, Zod must be used to create the input and output types for workflows/tasks
17
+ const TemperatureCoordinates = v4_1.z.object({
18
+ latitude: v4_1.z.number(),
19
+ longitude: v4_1.z.number(),
20
+ });
21
+ const TemperatureInput = v4_1.z.object({
22
+ locationName: v4_1.z.string(),
23
+ coords: TemperatureCoordinates,
24
+ });
25
+ const temperatureRequest = (input) => __awaiter(void 0, void 0, void 0, function* () {
26
+ const response = yield fetch(`https://api.open-meteo.com/v1/forecast?latitude=${input.coords.latitude}&longitude=${input.coords.longitude}&current=temperature_2m&temperature_unit=fahrenheit`);
27
+ const data = yield response.json();
28
+ return {
29
+ text: `Temperature: ${data.current.temperature_2m}°F`,
30
+ };
31
+ });
32
+ exports.getTemperature = hatchet_client_1.hatchet.task({
33
+ name: 'getTemperature',
34
+ retries: 3,
35
+ fn: temperatureRequest,
36
+ inputValidator: TemperatureInput,
37
+ description: 'Get the current temperature at a location',
38
+ });
39
+ exports.getTemperatureWorkflow = hatchet_client_1.hatchet.workflow({
40
+ name: 'getTemperatureWorkflow',
41
+ inputValidator: TemperatureInput,
42
+ description: 'Get the current temperature at a location',
43
+ });
44
+ exports.getTemperatureWorkflow.task({
45
+ name: 'getTemperature',
46
+ fn: temperatureRequest,
47
+ });
48
+ // !!
@@ -71,8 +71,12 @@ export declare const waitForTwoEventsSecondPushedFirst: import("../..").TaskWork
71
71
  scope: string;
72
72
  }, {
73
73
  elapsed: number;
74
- event1: any;
75
- event2: any;
74
+ event1: {
75
+ order: string;
76
+ };
77
+ event2: {
78
+ order: string;
79
+ };
76
80
  }, {}, {}, {}, {}>;
77
81
  export declare const memoNowCaching: import("../..").TaskWorkflowDeclaration<import("../..").JsonObject, {
78
82
  start_time: string;
@@ -13,7 +13,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.durableSpawnDag = exports.dagChildWorkflow = exports.memoNowCaching = exports.waitForTwoEventsSecondPushedFirst = exports.waitForOrEventLookback = exports.waitForEventLookback = exports.LOOKBACK_WINDOW = exports.durableReplayReset = exports.REPLAY_RESET_MEMOIZED_MAX_SECONDS = exports.REPLAY_RESET_SLEEP_SECONDS = exports.durableNonDeterminism = exports.durableWithExplicitSpawn = exports.durableSleepEventSpawn = exports.durableWithBulkSpawn = exports.durableWithSpawn = exports.spawnChildTask = exports.waitForSleepTwice = exports.durableWorkflow = exports.SLEEP_TIME = exports.SLEEP_TIME_SECONDS = exports.EVENT_KEY = void 0;
16
- const zod_1 = require("zod");
16
+ const v4_1 = require("zod/v4");
17
17
  const conditions_1 = require("../../conditions");
18
18
  const non_determinism_error_1 = require("../../../util/errors/non-determinism-error");
19
19
  const sleep_1 = __importDefault(require("../../../util/sleep"));
@@ -226,9 +226,12 @@ exports.durableReplayReset = hatchet_client_1.hatchet.durableTask({
226
226
  }),
227
227
  });
228
228
  exports.LOOKBACK_WINDOW = '1m';
229
- const lookbackEventPayloadSchema = zod_1.z.object({
230
- order: zod_1.z.string(),
231
- user_id: zod_1.z.number(),
229
+ const lookbackEventPayloadSchema = v4_1.z.object({
230
+ order: v4_1.z.string(),
231
+ user_id: v4_1.z.number(),
232
+ });
233
+ const twoEventsPayloadSchema = v4_1.z.object({
234
+ order: v4_1.z.string(),
232
235
  });
233
236
  exports.waitForEventLookback = hatchet_client_1.hatchet.durableTask({
234
237
  name: 'wait-for-event-lookback',
@@ -262,8 +265,8 @@ exports.waitForTwoEventsSecondPushedFirst = hatchet_client_1.hatchet.durableTask
262
265
  executionTimeout: '10m',
263
266
  fn: (input, ctx) => __awaiter(void 0, void 0, void 0, function* () {
264
267
  const start = Date.now();
265
- const event1 = yield ctx.waitForEvent('key1', undefined, undefined, input.scope, exports.LOOKBACK_WINDOW);
266
- const event2 = yield ctx.waitForEvent('key2', undefined, undefined, input.scope, exports.LOOKBACK_WINDOW);
268
+ const event1 = yield ctx.waitForEvent('key1', undefined, twoEventsPayloadSchema, input.scope, exports.LOOKBACK_WINDOW);
269
+ const event2 = yield ctx.waitForEvent('key2', undefined, twoEventsPayloadSchema, input.scope, exports.LOOKBACK_WINDOW);
267
270
  return {
268
271
  elapsed: (Date.now() - start) / 1000,
269
272
  event1,
@@ -18,11 +18,13 @@ const hatchet_client_1 = require("../hatchet-client");
18
18
  exports.EVICTION_TTL_SECONDS = 5;
19
19
  exports.LONG_SLEEP_SECONDS = 15;
20
20
  exports.EVENT_KEY = 'durable-eviction:event';
21
+ // > Eviction Policy
21
22
  const EVICTION_POLICY = {
22
23
  ttl: `${exports.EVICTION_TTL_SECONDS}s`,
23
24
  allowCapacityEviction: true,
24
25
  priority: 0,
25
26
  };
27
+ // !!
26
28
  exports.childTask = hatchet_client_1.hatchet.task({
27
29
  name: 'eviction-child-task',
28
30
  fn: () => __awaiter(void 0, void 0, void 0, function* () {
@@ -30,6 +32,7 @@ exports.childTask = hatchet_client_1.hatchet.task({
30
32
  return { child_status: 'completed' };
31
33
  }),
32
34
  });
35
+ // > Evictable Sleep
33
36
  exports.evictableSleep = hatchet_client_1.hatchet.durableTask({
34
37
  name: 'evictable-sleep',
35
38
  executionTimeout: '5m',
@@ -39,6 +42,7 @@ exports.evictableSleep = hatchet_client_1.hatchet.durableTask({
39
42
  return { status: 'completed' };
40
43
  }),
41
44
  });
45
+ // !!
42
46
  // NOTE: DO NOT REGISTER ON E2E TEST WORKER
43
47
  exports.evictableSleepForGracefulTermination = hatchet_client_1.hatchet.durableTask({
44
48
  name: 'evictable-sleep-for-graceful-termination',
@@ -114,6 +118,7 @@ exports.capacityEvictableSleep = hatchet_client_1.hatchet.durableTask({
114
118
  return { status: 'completed' };
115
119
  }),
116
120
  });
121
+ // > Non Evictable Sleep
117
122
  exports.nonEvictableSleep = hatchet_client_1.hatchet.durableTask({
118
123
  name: 'non-evictable-sleep',
119
124
  executionTimeout: '5m',
@@ -127,3 +132,4 @@ exports.nonEvictableSleep = hatchet_client_1.hatchet.durableTask({
127
132
  return { status: 'completed' };
128
133
  }),
129
134
  });
135
+ // !!
@@ -40,6 +40,8 @@ const workflow_18 = require("./streaming/workflow");
40
40
  const workflow_19 = require("./timeout/workflow");
41
41
  const workflow_20 = require("./webhooks/workflow");
42
42
  const workflow_21 = require("./child_index/workflow");
43
+ const workflow_22 = require("./support_agent/workflow");
44
+ const workflow_23 = require("./welcome_email/workflow");
43
45
  const workflows = [
44
46
  workflow_1.bulkChild,
45
47
  workflow_1.bulkParentWorkflow,
@@ -94,6 +96,11 @@ const workflows = [
94
96
  workflow_21.childIndexParent,
95
97
  workflow_21.scenarioTask,
96
98
  workflow_21.orchestratorTask,
99
+ workflow_22.supportAgent,
100
+ workflow_22.triageTicket,
101
+ workflow_22.generateReply,
102
+ workflow_22.escalateTicket,
103
+ workflow_23.welcomeEmail,
97
104
  ];
98
105
  function main() {
99
106
  return __awaiter(this, void 0, void 0, function* () {
@@ -13,6 +13,7 @@ exports.extra = extra;
13
13
  const hatchet_client_1 = require("../hatchet-client");
14
14
  const workflow_1 = require("./workflow");
15
15
  const workflow_with_child_1 = require("./workflow-with-child");
16
+ const zod_1 = require("./zod");
16
17
  function main() {
17
18
  return __awaiter(this, void 0, void 0, function* () {
18
19
  // > Running a Task
@@ -23,6 +24,10 @@ function main() {
23
24
  test: 'test',
24
25
  },
25
26
  });
27
+ const res3 = yield zod_1.simpleWithZod.run({
28
+ Message: 'HeLlO WoRlD',
29
+ });
30
+ console.log(res3.TransformedMessage);
26
31
  // 👀 Access the results of the Task
27
32
  console.log(res.TransformedMessage);
28
33
  // !!
@@ -1,11 +1,7 @@
1
- import * as z from 'zod';
1
+ import * as z from 'zod/v4';
2
2
  declare const SimpleInputSchema: z.ZodObject<{
3
3
  Message: z.ZodString;
4
- }, "strip", z.ZodTypeAny, {
5
- Message: string;
6
- }, {
7
- Message: string;
8
- }>;
4
+ }, z.core.$strip>;
9
5
  export type SimpleInputWithZod = z.infer<typeof SimpleInputSchema>;
10
6
  export declare const simpleWithZod: import("../..").TaskWorkflowDeclaration<{
11
7
  Message: string;
@@ -44,7 +44,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
44
44
  Object.defineProperty(exports, "__esModule", { value: true });
45
45
  exports.simpleWithZod = void 0;
46
46
  // > Declaring a Task
47
- const z = __importStar(require("zod"));
47
+ const z = __importStar(require("zod/v4"));
48
48
  const hatchet_client_1 = require("../hatchet-client");
49
49
  const SimpleInputSchema = z.object({
50
50
  Message: z.string(),
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,42 @@
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 workflow_1 = require("./workflow");
14
+ // > Trigger the workflow
15
+ function main() {
16
+ return __awaiter(this, void 0, void 0, function* () {
17
+ const input = {
18
+ ticketId: 'ticket-42',
19
+ customerEmail: 'alice@example.com',
20
+ subject: 'Login broken',
21
+ body: "I can't log in since this morning.",
22
+ };
23
+ // Start the support agent workflow
24
+ const ref = yield workflow_1.supportAgent.runNoWait(input);
25
+ const runId = yield ref.getWorkflowRunId();
26
+ console.log(`Started workflow run: ${runId}`);
27
+ // Push a customer reply event (scoped to this ticket)
28
+ console.log('Pushing customer reply event...');
29
+ yield hatchet_client_1.hatchet.events.push(workflow_1.REPLY_EVENT_KEY, { message: 'I cleared my cookies and it works now. Thanks!' }, { scope: input.ticketId });
30
+ // Wait for the workflow to complete
31
+ const result = yield ref.output;
32
+ console.log('Workflow completed:', result);
33
+ });
34
+ }
35
+ // !!
36
+ if (require.main === module) {
37
+ main()
38
+ .catch(console.error)
39
+ .finally(() => {
40
+ process.exit(0);
41
+ });
42
+ }
@@ -0,0 +1,43 @@
1
+ export declare const REPLY_EVENT_KEY = "support:customer-reply";
2
+ export declare const TIMEOUT_SECONDS = 5;
3
+ export type SupportTicketInput = {
4
+ ticketId: string;
5
+ customerEmail: string;
6
+ subject: string;
7
+ body: string;
8
+ };
9
+ export type TriageOutput = {
10
+ category: string;
11
+ priority: string;
12
+ };
13
+ export type ReplyOutput = {
14
+ message: string;
15
+ };
16
+ export type EscalationOutput = {
17
+ reason: string;
18
+ assignedTo: string;
19
+ };
20
+ export declare const triageTicket: import("../..").TaskWorkflowDeclaration<SupportTicketInput, {
21
+ category: string;
22
+ priority: string;
23
+ }, {}, {}, {}, {}>;
24
+ export declare const generateReply: import("../..").TaskWorkflowDeclaration<SupportTicketInput, {
25
+ message: any;
26
+ }, {}, {}, {}, {}>;
27
+ export declare const escalateTicket: import("../..").TaskWorkflowDeclaration<SupportTicketInput, {
28
+ reason: string;
29
+ assignedTo: string;
30
+ }, {}, {}, {}, {}>;
31
+ export declare const supportAgent: import("../..").TaskWorkflowDeclaration<SupportTicketInput, {
32
+ ticketId: string;
33
+ status: "escalated";
34
+ triageCategory: string;
35
+ triagePriority: string;
36
+ initialReply: any;
37
+ } | {
38
+ ticketId: string;
39
+ status: "resolved";
40
+ triageCategory: string;
41
+ triagePriority: string;
42
+ initialReply: any;
43
+ }, {}, {}, {}, {}>;
@@ -0,0 +1,140 @@
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.supportAgent = exports.escalateTicket = exports.generateReply = exports.triageTicket = exports.TIMEOUT_SECONDS = exports.REPLY_EVENT_KEY = void 0;
13
+ const conditions_1 = require("../../conditions");
14
+ const duration_1 = require("../../client/duration");
15
+ const hatchet_client_1 = require("../hatchet-client");
16
+ exports.REPLY_EVENT_KEY = 'support:customer-reply';
17
+ const REPLY_LABEL = 'reply';
18
+ const TIMEOUT_LABEL = 'timeout';
19
+ exports.TIMEOUT_SECONDS = 5;
20
+ const LOOKBACK_WINDOW = '5m';
21
+ // !!
22
+ // > Triage task
23
+ // Classify the ticket into a category and priority.
24
+ exports.triageTicket = hatchet_client_1.hatchet.task({
25
+ name: 'triage-ticket',
26
+ fn: (input) => __awaiter(void 0, void 0, void 0, function* () {
27
+ const text = `${input.subject} ${input.body}`.toLowerCase();
28
+ let category;
29
+ if (['bill', 'charge', 'payment', 'invoice'].some((w) => text.includes(w))) {
30
+ category = 'billing';
31
+ }
32
+ else if (['login', 'password', 'auth', 'access'].some((w) => text.includes(w))) {
33
+ category = 'account';
34
+ }
35
+ else {
36
+ category = 'technical';
37
+ }
38
+ let priority;
39
+ if (['urgent', 'critical', 'down', 'outage'].some((w) => text.includes(w))) {
40
+ priority = 'high';
41
+ }
42
+ else if (['twice', 'broken', 'error'].some((w) => text.includes(w))) {
43
+ priority = 'medium';
44
+ }
45
+ else {
46
+ priority = 'low';
47
+ }
48
+ return { category, priority };
49
+ }),
50
+ });
51
+ // !!
52
+ // > Generate reply task
53
+ // Generate an initial support reply using Claude.
54
+ exports.generateReply = hatchet_client_1.hatchet.task({
55
+ name: 'generate-reply',
56
+ fn: (input) => __awaiter(void 0, void 0, void 0, function* () {
57
+ const apiKey = process.env.ANTHROPIC_API_KEY;
58
+ if (!apiKey) {
59
+ return {
60
+ message: `Thank you for contacting support about: ${input.subject}. We are looking into this and will get back to you shortly.`,
61
+ };
62
+ }
63
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
64
+ const anthropic = require('@anthropic-ai/sdk');
65
+ const Anthropic = anthropic.default || anthropic;
66
+ const client = new Anthropic({ apiKey });
67
+ const response = yield client.messages.create({
68
+ model: 'claude-sonnet-4-20250514',
69
+ max_tokens: 300,
70
+ messages: [
71
+ {
72
+ role: 'user',
73
+ content: `You are a friendly support agent. Write a brief, helpful initial ` +
74
+ `reply to this support ticket.\n\n` +
75
+ `Subject: ${input.subject}\n` +
76
+ `Message: ${input.body}\n\n` +
77
+ `Keep the reply under 3 sentences.`,
78
+ },
79
+ ],
80
+ });
81
+ const [block] = response.content;
82
+ const text = (block === null || block === void 0 ? void 0 : block.type) === 'text' ? block.text : '';
83
+ return { message: text };
84
+ }),
85
+ });
86
+ // !!
87
+ // > Escalate task
88
+ // Escalate an unresolved ticket to the human support team.
89
+ exports.escalateTicket = hatchet_client_1.hatchet.task({
90
+ name: 'escalate-ticket',
91
+ fn: (input) => __awaiter(void 0, void 0, void 0, function* () {
92
+ return {
93
+ reason: `No customer reply within ${exports.TIMEOUT_SECONDS}s timeout`,
94
+ assignedTo: 'support-team@example.com',
95
+ };
96
+ }),
97
+ });
98
+ // !!
99
+ // > Support agent workflow
100
+ exports.supportAgent = hatchet_client_1.hatchet.durableTask({
101
+ name: 'support-agent',
102
+ executionTimeout: '10m',
103
+ fn: (input, ctx) => __awaiter(void 0, void 0, void 0, function* () {
104
+ var _a, _b;
105
+ // Step 1: Triage the ticket
106
+ const triage = yield exports.triageTicket.run(input);
107
+ // Step 2: Generate an initial reply
108
+ const reply = yield exports.generateReply.run(input);
109
+ // Step 3: Wait for a customer reply or timeout
110
+ const now = yield ctx.now();
111
+ const considerEventsSince = new Date(now.getTime() - (0, duration_1.durationToMs)(LOOKBACK_WINDOW)).toISOString();
112
+ const waitResult = yield ctx.waitFor((0, conditions_1.Or)(new conditions_1.SleepCondition(`${exports.TIMEOUT_SECONDS}s`, TIMEOUT_LABEL), new conditions_1.UserEventCondition(exports.REPLY_EVENT_KEY, '', REPLY_LABEL, undefined, input.ticketId, considerEventsSince)));
113
+ // Determine which condition fired. ctx.waitFor returns
114
+ // { CREATE: { <label>: ... } } where <label> is the readableDataKey
115
+ // we assigned above ('timeout' or 'reply').
116
+ const create = (_a = waitResult['CREATE']) !== null && _a !== void 0 ? _a : waitResult;
117
+ const resolvedLabel = (_b = Object.keys(create)[0]) !== null && _b !== void 0 ? _b : '';
118
+ const customerReplied = resolvedLabel === REPLY_LABEL;
119
+ if (!customerReplied) {
120
+ // Step 4a: Timeout -> escalate
121
+ yield exports.escalateTicket.run(input);
122
+ return {
123
+ ticketId: input.ticketId,
124
+ status: 'escalated',
125
+ triageCategory: triage.category,
126
+ triagePriority: triage.priority,
127
+ initialReply: reply.message,
128
+ };
129
+ }
130
+ // Step 4b: Customer replied -> resolve
131
+ return {
132
+ ticketId: input.ticketId,
133
+ status: 'resolved',
134
+ triageCategory: triage.category,
135
+ triagePriority: triage.priority,
136
+ initialReply: reply.message,
137
+ };
138
+ }),
139
+ });
140
+ // !!
@@ -0,0 +1 @@
1
+ export {};