@hatchet-dev/typescript-sdk 1.23.0 → 1.24.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.
- package/clients/hatchet-client/client-config.d.ts +2 -0
- package/clients/hatchet-client/client-config.js +8 -0
- package/opentelemetry/instrumentor.js +78 -17
- package/opentelemetry/types.d.ts +1 -0
- package/opentelemetry/types.js +1 -0
- package/package.json +4 -3
- package/util/config-loader/config-loader.js +1 -0
- package/v1/client/features/runs.d.ts +27 -0
- package/v1/client/features/runs.js +68 -1
- package/v1/client/features/workflows.js +2 -2
- package/v1/examples/aws/s3/worker.d.ts +1 -0
- package/v1/examples/aws/s3/worker.js +177 -0
- package/v1/examples/support_agent_tools/agent-claude.d.ts +1 -0
- package/v1/examples/support_agent_tools/agent-claude.js +109 -0
- package/v1/examples/support_agent_tools/agent-openai.d.ts +1 -0
- package/v1/examples/support_agent_tools/agent-openai.js +73 -0
- package/v1/examples/support_agent_tools/tools.d.ts +45 -0
- package/v1/examples/support_agent_tools/tools.js +144 -0
- package/v1/examples/support_agent_tools/worker.d.ts +1 -0
- package/v1/examples/support_agent_tools/worker.js +24 -0
- package/v1/index.d.ts +1 -0
- package/version.d.ts +1 -1
- package/version.js +1 -1
|
@@ -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
|
-
}, (
|
|
358
|
-
const
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
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
|
-
|
|
372
|
-
|
|
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
|
};
|
package/opentelemetry/types.d.ts
CHANGED
|
@@ -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
|
};
|
package/opentelemetry/types.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hatchet-dev/typescript-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.24.0",
|
|
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.
|
|
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.
|
|
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;
|
|
@@ -3,6 +3,24 @@ import { V1TaskStatus } from '../../../clients/rest/generated/data-contracts';
|
|
|
3
3
|
import { RunListenerClient } from '../../../clients/listeners/run-listener/child-listener-client';
|
|
4
4
|
import { WorkflowsClient } from './workflows';
|
|
5
5
|
import { HatchetClient } from '../client';
|
|
6
|
+
import { runStatusToJSON } from '../../../protoc/v1/workflows';
|
|
7
|
+
export type RunDetail = {
|
|
8
|
+
status: V1TaskStatus;
|
|
9
|
+
done: boolean;
|
|
10
|
+
input: unknown;
|
|
11
|
+
additionalMetadata: unknown;
|
|
12
|
+
isEvicted: boolean;
|
|
13
|
+
taskRuns: Record<string, TaskRunDetail>;
|
|
14
|
+
};
|
|
15
|
+
export type TaskRunDetail = {
|
|
16
|
+
externalId: string;
|
|
17
|
+
readableId: string;
|
|
18
|
+
status: V1TaskStatus;
|
|
19
|
+
output: unknown;
|
|
20
|
+
error?: string;
|
|
21
|
+
isEvicted: boolean;
|
|
22
|
+
};
|
|
23
|
+
export { runStatusToJSON };
|
|
6
24
|
export type RunFilter = {
|
|
7
25
|
since?: Date;
|
|
8
26
|
until?: Date;
|
|
@@ -72,7 +90,10 @@ export declare class RunsClient {
|
|
|
72
90
|
tenantId: string;
|
|
73
91
|
workflows: WorkflowsClient;
|
|
74
92
|
listener: RunListenerClient;
|
|
93
|
+
private _config;
|
|
94
|
+
private _adminGrpc;
|
|
75
95
|
constructor(client: HatchetClient);
|
|
96
|
+
private get adminGrpc();
|
|
76
97
|
/**
|
|
77
98
|
* Gets a task or workflow run by its ID.
|
|
78
99
|
* @param run - The ID of the run to get.
|
|
@@ -85,6 +106,12 @@ export declare class RunsClient {
|
|
|
85
106
|
* @returns A promise that resolves to the status of the run.
|
|
86
107
|
*/
|
|
87
108
|
get_status<T = any>(run: string | WorkflowRunRef<T>): Promise<V1TaskStatus>;
|
|
109
|
+
/**
|
|
110
|
+
* Gets run details
|
|
111
|
+
* @param run - The workflow run ID (string) or a WorkflowRunRef.
|
|
112
|
+
* @returns A promise resolving to GetRunDetailsResponse with task run statuses and outputs.
|
|
113
|
+
*/
|
|
114
|
+
getDetails<T = any>(run: string | WorkflowRunRef<T>): Promise<RunDetail>;
|
|
88
115
|
/**
|
|
89
116
|
* Lists all task and workflow runs for the current tenant.
|
|
90
117
|
* @param opts - The options for the list operation.
|
|
@@ -32,9 +32,57 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
32
32
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
33
33
|
};
|
|
34
34
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
35
|
-
exports.RunsClient = void 0;
|
|
35
|
+
exports.RunsClient = exports.runStatusToJSON = void 0;
|
|
36
36
|
const workflow_run_ref_1 = __importDefault(require("../../../util/workflow-run-ref"));
|
|
37
|
+
const data_contracts_1 = require("../../../clients/rest/generated/data-contracts");
|
|
37
38
|
const child_listener_client_1 = require("../../../clients/listeners/run-listener/child-listener-client");
|
|
39
|
+
const workflows_1 = require("../../../protoc/v1/workflows");
|
|
40
|
+
Object.defineProperty(exports, "runStatusToJSON", { enumerable: true, get: function () { return workflows_1.runStatusToJSON; } });
|
|
41
|
+
const grpc_helpers_1 = require("../../../util/grpc-helpers");
|
|
42
|
+
// EVICTED is not in V1TaskStatus; treat as RUNNING per the proto comment.
|
|
43
|
+
const PROTO_STATUS_MAP = {
|
|
44
|
+
[workflows_1.RunStatus.QUEUED]: data_contracts_1.V1TaskStatus.QUEUED,
|
|
45
|
+
[workflows_1.RunStatus.RUNNING]: data_contracts_1.V1TaskStatus.RUNNING,
|
|
46
|
+
[workflows_1.RunStatus.COMPLETED]: data_contracts_1.V1TaskStatus.COMPLETED,
|
|
47
|
+
[workflows_1.RunStatus.FAILED]: data_contracts_1.V1TaskStatus.FAILED,
|
|
48
|
+
[workflows_1.RunStatus.CANCELLED]: data_contracts_1.V1TaskStatus.CANCELLED,
|
|
49
|
+
[workflows_1.RunStatus.EVICTED]: data_contracts_1.V1TaskStatus.RUNNING,
|
|
50
|
+
[workflows_1.RunStatus.UNRECOGNIZED]: data_contracts_1.V1TaskStatus.RUNNING,
|
|
51
|
+
};
|
|
52
|
+
function decodeBytes(b) {
|
|
53
|
+
if (!(b === null || b === void 0 ? void 0 : b.length))
|
|
54
|
+
return null;
|
|
55
|
+
try {
|
|
56
|
+
return JSON.parse(new TextDecoder().decode(b));
|
|
57
|
+
}
|
|
58
|
+
catch (_a) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function toRunDetail(raw) {
|
|
63
|
+
var _a;
|
|
64
|
+
return {
|
|
65
|
+
status: (_a = PROTO_STATUS_MAP[raw.status]) !== null && _a !== void 0 ? _a : data_contracts_1.V1TaskStatus.RUNNING,
|
|
66
|
+
done: raw.done,
|
|
67
|
+
input: decodeBytes(raw.input),
|
|
68
|
+
additionalMetadata: decodeBytes(raw.additionalMetadata),
|
|
69
|
+
isEvicted: raw.isEvicted,
|
|
70
|
+
taskRuns: Object.fromEntries(Object.entries(raw.taskRuns).map(([id, tr]) => {
|
|
71
|
+
var _a;
|
|
72
|
+
return [
|
|
73
|
+
id,
|
|
74
|
+
{
|
|
75
|
+
externalId: tr.externalId,
|
|
76
|
+
readableId: tr.readableId,
|
|
77
|
+
status: (_a = PROTO_STATUS_MAP[tr.status]) !== null && _a !== void 0 ? _a : data_contracts_1.V1TaskStatus.RUNNING,
|
|
78
|
+
output: decodeBytes(tr.output),
|
|
79
|
+
error: tr.error,
|
|
80
|
+
isEvicted: tr.isEvicted,
|
|
81
|
+
},
|
|
82
|
+
];
|
|
83
|
+
})),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
38
86
|
/**
|
|
39
87
|
* The runs client is a client for interacting with task and workflow runs within Hatchet.
|
|
40
88
|
*/
|
|
@@ -44,6 +92,14 @@ class RunsClient {
|
|
|
44
92
|
this.tenantId = client.tenantId;
|
|
45
93
|
this.workflows = client.workflows;
|
|
46
94
|
this.listener = client._listener;
|
|
95
|
+
this._config = client.config;
|
|
96
|
+
}
|
|
97
|
+
get adminGrpc() {
|
|
98
|
+
if (!this._adminGrpc) {
|
|
99
|
+
const { client } = (0, grpc_helpers_1.createGrpcClient)(this._config, workflows_1.AdminServiceDefinition);
|
|
100
|
+
this._adminGrpc = client;
|
|
101
|
+
}
|
|
102
|
+
return this._adminGrpc;
|
|
47
103
|
}
|
|
48
104
|
/**
|
|
49
105
|
* Gets a task or workflow run by its ID.
|
|
@@ -69,6 +125,17 @@ class RunsClient {
|
|
|
69
125
|
return data;
|
|
70
126
|
});
|
|
71
127
|
}
|
|
128
|
+
/**
|
|
129
|
+
* Gets run details
|
|
130
|
+
* @param run - The workflow run ID (string) or a WorkflowRunRef.
|
|
131
|
+
* @returns A promise resolving to GetRunDetailsResponse with task run statuses and outputs.
|
|
132
|
+
*/
|
|
133
|
+
getDetails(run) {
|
|
134
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
135
|
+
const runId = typeof run === 'string' ? run : yield run.getWorkflowRunId();
|
|
136
|
+
return toRunDetail(yield this.adminGrpc.getRunDetails({ externalId: runId }));
|
|
137
|
+
});
|
|
138
|
+
}
|
|
72
139
|
/**
|
|
73
140
|
* Lists all task and workflow runs for the current tenant.
|
|
74
141
|
* @param opts - The options for the list operation.
|
|
@@ -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
|
|
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/v1/index.d.ts
CHANGED
package/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const HATCHET_VERSION = "1.
|
|
1
|
+
export declare const HATCHET_VERSION = "1.24.0";
|
package/version.js
CHANGED