@plucky-ai/node 0.2.0 → 0.2.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.
package/dist/index.mjs ADDED
@@ -0,0 +1,1107 @@
1
+ import { createApiClient, createApiClient as createApiClient$1 } from "@plucky-ai/api-contracts/client";
2
+ import { ValidationError, enhanceRoute, eventIterator, isContractProcedure, mergeErrorMap, mergeMeta, mergePrefix, mergeRoute, mergeTags, oc, validateORPCError } from "@orpc/contract";
3
+ import z$1, { z } from "zod";
4
+ import { ORPCError, mapEventIterator, toORPCError } from "@orpc/client";
5
+ //#region ../llm-schemas/dist/index.mjs
6
+ const TextContentBlockSchema = z.object({
7
+ type: z.literal("text"),
8
+ text: z.string()
9
+ });
10
+ const ToolUseContentBlockSchema = z.object({
11
+ type: z.literal("tool_use"),
12
+ id: z.string(),
13
+ name: z.string(),
14
+ input: z.unknown(),
15
+ defaultLoadingText: z.string().nullable().optional(),
16
+ defaultSuccessText: z.string().nullable().optional(),
17
+ partial_json: z.string().nullable().optional()
18
+ });
19
+ const ToolResultContentBlockSchema = z.object({
20
+ type: z.literal("tool_result"),
21
+ toolUseId: z.string(),
22
+ content: z.string(),
23
+ successText: z.string().nullish()
24
+ });
25
+ const ContentBlockSchema = z.union([
26
+ TextContentBlockSchema,
27
+ ToolUseContentBlockSchema,
28
+ ToolResultContentBlockSchema
29
+ ]);
30
+ const ContentFieldSchema = z.union([z.string(), z.array(ContentBlockSchema)]);
31
+ const InputMessageSchema = z.object({
32
+ role: z.enum(["user", "assistant"]),
33
+ content: ContentFieldSchema
34
+ });
35
+ InputMessageSchema.extend({ content: z.array(ContentBlockSchema) });
36
+ const SavedInputMessageSchema = InputMessageSchema.extend({
37
+ id: z.string(),
38
+ content: z.array(ContentBlockSchema),
39
+ createdAt: z.coerce.date()
40
+ });
41
+ const UsageSchema = z.object({
42
+ inputTokens: z.number(),
43
+ outputTokens: z.number(),
44
+ cacheReadInputTokens: z.number().optional(),
45
+ cacheCreationInputTokens: z.number().optional()
46
+ });
47
+ const OutputMessageSchema = InputMessageSchema.extend({
48
+ id: z.string(),
49
+ content: z.array(ContentBlockSchema),
50
+ usage: UsageSchema
51
+ });
52
+ const SavedOutputMessageSchema = OutputMessageSchema.extend({ createdAt: z.coerce.date() });
53
+ const SavedMessageSchema = z.union([SavedInputMessageSchema, SavedOutputMessageSchema]);
54
+ z.union([
55
+ InputMessageSchema,
56
+ OutputMessageSchema,
57
+ SavedInputMessageSchema,
58
+ SavedOutputMessageSchema
59
+ ]);
60
+ z.object({ messages: z.array(SavedMessageSchema) });
61
+ const MessageStartEventSchema = z.object({
62
+ type: z.literal("message_start"),
63
+ data: z.object({
64
+ type: z.literal("message_start"),
65
+ message: z.object({
66
+ id: z.string(),
67
+ role: z.enum(["user", "assistant"]),
68
+ content: z.array(ContentBlockSchema)
69
+ })
70
+ })
71
+ });
72
+ const MessageDeltaEventSchema = z.object({
73
+ type: z.literal("message_delta"),
74
+ data: z.object({
75
+ type: z.literal("message_delta"),
76
+ delta: z.object({
77
+ stop_reason: z.enum(["end_turn", "tool_use"]),
78
+ stop_sequence: z.string().nullable()
79
+ }),
80
+ usage: UsageSchema.optional()
81
+ })
82
+ });
83
+ const MessageStopEventSchema = z.object({
84
+ type: z.literal("message_stop"),
85
+ data: z.object({ type: z.literal("message_stop") })
86
+ });
87
+ const ContentBlockStartEventSchema = z.object({
88
+ type: z.literal("content_block_start"),
89
+ data: z.object({
90
+ type: z.literal("content_block_start"),
91
+ index: z.number(),
92
+ contentBlock: ContentBlockSchema
93
+ })
94
+ });
95
+ const ContentBlockDeltaEventSchema = z.object({
96
+ type: z.literal("content_block_delta"),
97
+ data: z.object({
98
+ type: z.literal("content_block_delta"),
99
+ index: z.number(),
100
+ delta: z.union([z.object({
101
+ type: z.literal("text_delta"),
102
+ text: z.string()
103
+ }), z.object({
104
+ type: z.literal("input_json_delta"),
105
+ partial_json: z.string()
106
+ })])
107
+ })
108
+ });
109
+ const ContentBlockStopEventSchema = z.object({
110
+ type: z.literal("content_block_stop"),
111
+ data: z.object({
112
+ type: z.literal("content_block_stop"),
113
+ index: z.number()
114
+ })
115
+ });
116
+ const ErrorEventSchema = z.object({
117
+ type: z.literal("error"),
118
+ data: z.object({
119
+ type: z.literal("error"),
120
+ error: z.object({
121
+ code: z.string(),
122
+ message: z.string()
123
+ })
124
+ })
125
+ });
126
+ const PingEventSchema = z.object({
127
+ type: z.literal("ping"),
128
+ data: z.object({
129
+ type: z.literal("ping"),
130
+ timestamp: z.number()
131
+ })
132
+ });
133
+ const MessageStreamEventSchema = z.union([
134
+ MessageStartEventSchema,
135
+ MessageDeltaEventSchema,
136
+ MessageStopEventSchema,
137
+ ContentBlockStartEventSchema,
138
+ ContentBlockDeltaEventSchema,
139
+ ContentBlockStopEventSchema,
140
+ ErrorEventSchema,
141
+ PingEventSchema
142
+ ]);
143
+ //#endregion
144
+ //#region ../../node_modules/.pnpm/@orpc+shared@1.13.6_@opentelemetry+api@1.9.0/node_modules/@orpc/shared/dist/index.mjs
145
+ function resolveMaybeOptionalOptions(rest) {
146
+ return rest[0] ?? {};
147
+ }
148
+ function toArray(value) {
149
+ return Array.isArray(value) ? value : value === void 0 || value === null ? [] : [value];
150
+ }
151
+ const ORPC_SHARED_PACKAGE_NAME = "@orpc/shared";
152
+ const ORPC_SHARED_PACKAGE_VERSION = "1.13.6";
153
+ function sequential(fn) {
154
+ let lastOperationPromise = Promise.resolve();
155
+ return (...args) => {
156
+ return lastOperationPromise = lastOperationPromise.catch(() => {}).then(() => {
157
+ return fn(...args);
158
+ });
159
+ };
160
+ }
161
+ const SPAN_ERROR_STATUS = 2;
162
+ const GLOBAL_OTEL_CONFIG_KEY = `__${ORPC_SHARED_PACKAGE_NAME}@${ORPC_SHARED_PACKAGE_VERSION}/otel/config__`;
163
+ function getGlobalOtelConfig() {
164
+ return globalThis[GLOBAL_OTEL_CONFIG_KEY];
165
+ }
166
+ function startSpan(name, options = {}, context) {
167
+ return (getGlobalOtelConfig()?.tracer)?.startSpan(name, options, context);
168
+ }
169
+ function setSpanError(span, error, options = {}) {
170
+ if (!span) return;
171
+ const exception = toOtelException(error);
172
+ span.recordException(exception);
173
+ if (!options.signal?.aborted || options.signal.reason !== error) span.setStatus({
174
+ code: SPAN_ERROR_STATUS,
175
+ message: exception.message
176
+ });
177
+ }
178
+ function toOtelException(error) {
179
+ if (error instanceof Error) {
180
+ const exception = {
181
+ message: error.message,
182
+ name: error.name,
183
+ stack: error.stack
184
+ };
185
+ if ("code" in error && (typeof error.code === "string" || typeof error.code === "number")) exception.code = error.code;
186
+ return exception;
187
+ }
188
+ return { message: String(error) };
189
+ }
190
+ async function runWithSpan({ name, context, ...options }, fn) {
191
+ const tracer = getGlobalOtelConfig()?.tracer;
192
+ if (!tracer) return fn();
193
+ const callback = async (span) => {
194
+ try {
195
+ return await fn(span);
196
+ } catch (e) {
197
+ setSpanError(span, e, options);
198
+ throw e;
199
+ } finally {
200
+ span.end();
201
+ }
202
+ };
203
+ if (context) return tracer.startActiveSpan(name, options, context, callback);
204
+ else return tracer.startActiveSpan(name, options, callback);
205
+ }
206
+ async function runInSpanContext(span, fn) {
207
+ const otelConfig = getGlobalOtelConfig();
208
+ if (!span || !otelConfig) return fn();
209
+ const ctx = otelConfig.trace.setSpan(otelConfig.context.active(), span);
210
+ return otelConfig.context.with(ctx, fn);
211
+ }
212
+ function isAsyncIteratorObject(maybe) {
213
+ if (!maybe || typeof maybe !== "object") return false;
214
+ return "next" in maybe && typeof maybe.next === "function" && Symbol.asyncIterator in maybe && typeof maybe[Symbol.asyncIterator] === "function";
215
+ }
216
+ const fallbackAsyncDisposeSymbol = Symbol.for("asyncDispose");
217
+ const asyncDisposeSymbol = Symbol.asyncDispose ?? fallbackAsyncDisposeSymbol;
218
+ var AsyncIteratorClass = class {
219
+ #isDone = false;
220
+ #isExecuteComplete = false;
221
+ #cleanup;
222
+ #next;
223
+ constructor(next, cleanup) {
224
+ this.#cleanup = cleanup;
225
+ this.#next = sequential(async () => {
226
+ if (this.#isDone) return {
227
+ done: true,
228
+ value: void 0
229
+ };
230
+ try {
231
+ const result = await next();
232
+ if (result.done) this.#isDone = true;
233
+ return result;
234
+ } catch (err) {
235
+ this.#isDone = true;
236
+ throw err;
237
+ } finally {
238
+ if (this.#isDone && !this.#isExecuteComplete) {
239
+ this.#isExecuteComplete = true;
240
+ await this.#cleanup("next");
241
+ }
242
+ }
243
+ });
244
+ }
245
+ next() {
246
+ return this.#next();
247
+ }
248
+ async return(value) {
249
+ this.#isDone = true;
250
+ if (!this.#isExecuteComplete) {
251
+ this.#isExecuteComplete = true;
252
+ await this.#cleanup("return");
253
+ }
254
+ return {
255
+ done: true,
256
+ value
257
+ };
258
+ }
259
+ async throw(err) {
260
+ this.#isDone = true;
261
+ if (!this.#isExecuteComplete) {
262
+ this.#isExecuteComplete = true;
263
+ await this.#cleanup("throw");
264
+ }
265
+ throw err;
266
+ }
267
+ /**
268
+ * asyncDispose symbol only available in esnext, we should fallback to Symbol.for('asyncDispose')
269
+ */
270
+ async [asyncDisposeSymbol]() {
271
+ this.#isDone = true;
272
+ if (!this.#isExecuteComplete) {
273
+ this.#isExecuteComplete = true;
274
+ await this.#cleanup("dispose");
275
+ }
276
+ }
277
+ [Symbol.asyncIterator]() {
278
+ return this;
279
+ }
280
+ };
281
+ function asyncIteratorWithSpan({ name, ...options }, iterator) {
282
+ let span;
283
+ return new AsyncIteratorClass(async () => {
284
+ span ??= startSpan(name);
285
+ try {
286
+ const result = await runInSpanContext(span, () => iterator.next());
287
+ span?.addEvent(result.done ? "completed" : "yielded");
288
+ return result;
289
+ } catch (err) {
290
+ setSpanError(span, err, options);
291
+ throw err;
292
+ }
293
+ }, async (reason) => {
294
+ try {
295
+ if (reason !== "next") await runInSpanContext(span, () => iterator.return?.());
296
+ } catch (err) {
297
+ setSpanError(span, err, options);
298
+ throw err;
299
+ } finally {
300
+ span?.end();
301
+ }
302
+ });
303
+ }
304
+ function intercept(interceptors, options, main) {
305
+ const next = (options2, index) => {
306
+ const interceptor = interceptors[index];
307
+ if (!interceptor) return main(options2);
308
+ return interceptor({
309
+ ...options2,
310
+ next: (newOptions = options2) => next(newOptions, index + 1)
311
+ });
312
+ };
313
+ return next(options, 0);
314
+ }
315
+ function isObject(value) {
316
+ if (!value || typeof value !== "object") return false;
317
+ const proto = Object.getPrototypeOf(value);
318
+ return proto === Object.prototype || !proto || !proto.constructor;
319
+ }
320
+ function value(value2, ...args) {
321
+ if (typeof value2 === "function") return value2(...args);
322
+ return value2;
323
+ }
324
+ function overlayProxy(target, partial) {
325
+ return new Proxy(typeof target === "function" ? partial : target, {
326
+ get(_, prop) {
327
+ const targetValue = prop in partial ? partial : value(target);
328
+ const v = Reflect.get(targetValue, prop);
329
+ return typeof v === "function" ? v.bind(targetValue) : v;
330
+ },
331
+ has(_, prop) {
332
+ return Reflect.has(partial, prop) || Reflect.has(value(target), prop);
333
+ }
334
+ });
335
+ }
336
+ //#endregion
337
+ //#region ../../node_modules/.pnpm/@orpc+standard-server@1.13.6_@opentelemetry+api@1.9.0/node_modules/@orpc/standard-server/dist/index.mjs
338
+ var HibernationEventIterator = class extends AsyncIteratorClass {
339
+ /**
340
+ * this property is not transferred to the client, so it should be optional for type safety
341
+ */
342
+ hibernationCallback;
343
+ constructor(hibernationCallback) {
344
+ super(async () => {
345
+ throw new Error("Cannot iterate over hibernating iterator directly");
346
+ }, async (reason) => {
347
+ if (reason !== "next") throw new Error("Cannot cleanup hibernating iterator directly");
348
+ });
349
+ this.hibernationCallback = hibernationCallback;
350
+ }
351
+ };
352
+ //#endregion
353
+ //#region ../../node_modules/.pnpm/@orpc+server@1.13.6_@opentelemetry+api@1.9.0_crossws@0.3.5_ws@8.19.0/node_modules/@orpc/server/dist/shared/server.Ds4HPpvH.mjs
354
+ const LAZY_SYMBOL = Symbol("ORPC_LAZY_SYMBOL");
355
+ function lazy(loader, meta = {}) {
356
+ return { [LAZY_SYMBOL]: {
357
+ loader,
358
+ meta
359
+ } };
360
+ }
361
+ function isLazy(item) {
362
+ return (typeof item === "object" || typeof item === "function") && item !== null && LAZY_SYMBOL in item;
363
+ }
364
+ function getLazyMeta(lazied) {
365
+ return lazied[LAZY_SYMBOL].meta;
366
+ }
367
+ function unlazy(lazied) {
368
+ return isLazy(lazied) ? lazied[LAZY_SYMBOL].loader() : Promise.resolve({ default: lazied });
369
+ }
370
+ function isStartWithMiddlewares(middlewares, compare) {
371
+ if (compare.length > middlewares.length) return false;
372
+ for (let i = 0; i < middlewares.length; i++) {
373
+ if (compare[i] === void 0) return true;
374
+ if (middlewares[i] !== compare[i]) return false;
375
+ }
376
+ return true;
377
+ }
378
+ function mergeMiddlewares(first, second, options) {
379
+ if (options.dedupeLeading && isStartWithMiddlewares(second, first)) return second;
380
+ return [...first, ...second];
381
+ }
382
+ function addMiddleware(middlewares, addition) {
383
+ return [...middlewares, addition];
384
+ }
385
+ var Procedure = class {
386
+ /**
387
+ * This property holds the defined options.
388
+ */
389
+ "~orpc";
390
+ constructor(def) {
391
+ this["~orpc"] = def;
392
+ }
393
+ };
394
+ function isProcedure(item) {
395
+ if (item instanceof Procedure) return true;
396
+ return isContractProcedure(item) && "middlewares" in item["~orpc"] && "inputValidationIndex" in item["~orpc"] && "outputValidationIndex" in item["~orpc"] && "handler" in item["~orpc"];
397
+ }
398
+ function mergeCurrentContext(context, other) {
399
+ return {
400
+ ...context,
401
+ ...other
402
+ };
403
+ }
404
+ function createORPCErrorConstructorMap(errors) {
405
+ return new Proxy(errors, { get(target, code) {
406
+ if (typeof code !== "string") return Reflect.get(target, code);
407
+ const item = (...rest) => {
408
+ const options = resolveMaybeOptionalOptions(rest);
409
+ const config = errors[code];
410
+ return new ORPCError(code, {
411
+ defined: Boolean(config),
412
+ status: config?.status,
413
+ message: options.message ?? config?.message,
414
+ data: options.data,
415
+ cause: options.cause
416
+ });
417
+ };
418
+ return item;
419
+ } });
420
+ }
421
+ function middlewareOutputFn(output) {
422
+ return {
423
+ output,
424
+ context: {}
425
+ };
426
+ }
427
+ function createProcedureClient(lazyableProcedure, ...rest) {
428
+ const options = resolveMaybeOptionalOptions(rest);
429
+ return async (...[input, callerOptions]) => {
430
+ const path = toArray(options.path);
431
+ const { default: procedure } = await unlazy(lazyableProcedure);
432
+ const clientContext = callerOptions?.context ?? {};
433
+ const context = await value(options.context ?? {}, clientContext);
434
+ const errors = createORPCErrorConstructorMap(procedure["~orpc"].errorMap);
435
+ const validateError = async (e) => {
436
+ if (e instanceof ORPCError) return await validateORPCError(procedure["~orpc"].errorMap, e);
437
+ return e;
438
+ };
439
+ try {
440
+ const output = await runWithSpan({
441
+ name: "call_procedure",
442
+ signal: callerOptions?.signal
443
+ }, (span) => {
444
+ span?.setAttribute("procedure.path", [...path]);
445
+ return intercept(toArray(options.interceptors), {
446
+ context,
447
+ input,
448
+ errors,
449
+ path,
450
+ procedure,
451
+ signal: callerOptions?.signal,
452
+ lastEventId: callerOptions?.lastEventId
453
+ }, (interceptorOptions) => executeProcedureInternal(interceptorOptions.procedure, interceptorOptions));
454
+ });
455
+ if (isAsyncIteratorObject(output)) {
456
+ if (output instanceof HibernationEventIterator) return output;
457
+ return overlayProxy(output, mapEventIterator(asyncIteratorWithSpan({
458
+ name: "consume_event_iterator_output",
459
+ signal: callerOptions?.signal
460
+ }, output), {
461
+ value: (v) => v,
462
+ error: (e) => validateError(e)
463
+ }));
464
+ }
465
+ return output;
466
+ } catch (e) {
467
+ throw await validateError(e);
468
+ }
469
+ };
470
+ }
471
+ async function validateInput(procedure, input) {
472
+ const schema = procedure["~orpc"].inputSchema;
473
+ if (!schema) return input;
474
+ return runWithSpan({ name: "validate_input" }, async () => {
475
+ const result = await schema["~standard"].validate(input);
476
+ if (result.issues) throw new ORPCError("BAD_REQUEST", {
477
+ message: "Input validation failed",
478
+ data: { issues: result.issues },
479
+ cause: new ValidationError({
480
+ message: "Input validation failed",
481
+ issues: result.issues,
482
+ data: input
483
+ })
484
+ });
485
+ return result.value;
486
+ });
487
+ }
488
+ async function validateOutput(procedure, output) {
489
+ const schema = procedure["~orpc"].outputSchema;
490
+ if (!schema) return output;
491
+ return runWithSpan({ name: "validate_output" }, async () => {
492
+ const result = await schema["~standard"].validate(output);
493
+ if (result.issues) throw new ORPCError("INTERNAL_SERVER_ERROR", {
494
+ message: "Output validation failed",
495
+ cause: new ValidationError({
496
+ message: "Output validation failed",
497
+ issues: result.issues,
498
+ data: output
499
+ })
500
+ });
501
+ return result.value;
502
+ });
503
+ }
504
+ async function executeProcedureInternal(procedure, options) {
505
+ const middlewares = procedure["~orpc"].middlewares;
506
+ const inputValidationIndex = Math.min(Math.max(0, procedure["~orpc"].inputValidationIndex), middlewares.length);
507
+ const outputValidationIndex = Math.min(Math.max(0, procedure["~orpc"].outputValidationIndex), middlewares.length);
508
+ const next = async (index, context, input) => {
509
+ let currentInput = input;
510
+ if (index === inputValidationIndex) currentInput = await validateInput(procedure, currentInput);
511
+ const mid = middlewares[index];
512
+ const output = mid ? await runWithSpan({
513
+ name: `middleware.${mid.name}`,
514
+ signal: options.signal
515
+ }, async (span) => {
516
+ span?.setAttribute("middleware.index", index);
517
+ span?.setAttribute("middleware.name", mid.name);
518
+ return (await mid({
519
+ ...options,
520
+ context,
521
+ next: async (...[nextOptions]) => {
522
+ const nextContext = nextOptions?.context ?? {};
523
+ return {
524
+ output: await next(index + 1, mergeCurrentContext(context, nextContext), currentInput),
525
+ context: nextContext
526
+ };
527
+ }
528
+ }, currentInput, middlewareOutputFn)).output;
529
+ }) : await runWithSpan({
530
+ name: "handler",
531
+ signal: options.signal
532
+ }, () => procedure["~orpc"].handler({
533
+ ...options,
534
+ context,
535
+ input: currentInput
536
+ }));
537
+ if (index === outputValidationIndex) return await validateOutput(procedure, output);
538
+ return output;
539
+ };
540
+ return next(0, options.context, options.input);
541
+ }
542
+ function getRouter(router, path) {
543
+ let current = router;
544
+ for (let i = 0; i < path.length; i++) {
545
+ const segment = path[i];
546
+ if (!current) return;
547
+ if (isProcedure(current)) return;
548
+ if (!isLazy(current)) {
549
+ current = current[segment];
550
+ continue;
551
+ }
552
+ const lazied = current;
553
+ const rest = path.slice(i);
554
+ return lazy(async () => {
555
+ return unlazy(getRouter((await unlazy(lazied)).default, rest));
556
+ }, getLazyMeta(lazied));
557
+ }
558
+ return current;
559
+ }
560
+ function createAccessibleLazyRouter(lazied) {
561
+ return new Proxy(lazied, { get(target, key) {
562
+ if (typeof key !== "string") return Reflect.get(target, key);
563
+ return createAccessibleLazyRouter(getRouter(lazied, [key]));
564
+ } });
565
+ }
566
+ function enhanceRouter(router, options) {
567
+ if (isLazy(router)) {
568
+ const laziedMeta = getLazyMeta(router);
569
+ const enhancedPrefix = laziedMeta?.prefix ? mergePrefix(options.prefix, laziedMeta?.prefix) : options.prefix;
570
+ return createAccessibleLazyRouter(lazy(async () => {
571
+ const { default: unlaziedRouter } = await unlazy(router);
572
+ return unlazy(enhanceRouter(unlaziedRouter, options));
573
+ }, {
574
+ ...laziedMeta,
575
+ prefix: enhancedPrefix
576
+ }));
577
+ }
578
+ if (isProcedure(router)) {
579
+ const newMiddlewares = mergeMiddlewares(options.middlewares, router["~orpc"].middlewares, { dedupeLeading: options.dedupeLeadingMiddlewares });
580
+ const newMiddlewareAdded = newMiddlewares.length - router["~orpc"].middlewares.length;
581
+ return new Procedure({
582
+ ...router["~orpc"],
583
+ route: enhanceRoute(router["~orpc"].route, options),
584
+ errorMap: mergeErrorMap(options.errorMap, router["~orpc"].errorMap),
585
+ middlewares: newMiddlewares,
586
+ inputValidationIndex: router["~orpc"].inputValidationIndex + newMiddlewareAdded,
587
+ outputValidationIndex: router["~orpc"].outputValidationIndex + newMiddlewareAdded
588
+ });
589
+ }
590
+ const enhanced = {};
591
+ for (const key in router) enhanced[key] = enhanceRouter(router[key], options);
592
+ return enhanced;
593
+ }
594
+ //#endregion
595
+ //#region ../../node_modules/.pnpm/@orpc+server@1.13.6_@opentelemetry+api@1.9.0_crossws@0.3.5_ws@8.19.0/node_modules/@orpc/server/dist/index.mjs
596
+ const DEFAULT_CONFIG = {
597
+ initialInputValidationIndex: 0,
598
+ initialOutputValidationIndex: 0,
599
+ dedupeLeadingMiddlewares: true
600
+ };
601
+ function fallbackConfig(key, value) {
602
+ if (value === void 0) return DEFAULT_CONFIG[key];
603
+ return value;
604
+ }
605
+ function decorateMiddleware(middleware) {
606
+ const decorated = ((...args) => middleware(...args));
607
+ decorated.mapInput = (mapInput) => {
608
+ return decorateMiddleware((options, input, ...rest) => middleware(options, mapInput(input), ...rest));
609
+ };
610
+ decorated.concat = (concatMiddleware, mapInput) => {
611
+ const mapped = mapInput ? decorateMiddleware(concatMiddleware).mapInput(mapInput) : concatMiddleware;
612
+ return decorateMiddleware((options, input, output, ...rest) => {
613
+ return middleware({
614
+ ...options,
615
+ next: (...[nextOptions1]) => mapped({
616
+ ...options,
617
+ context: {
618
+ ...options.context,
619
+ ...nextOptions1?.context
620
+ },
621
+ next: (...[nextOptions2]) => options.next({ context: {
622
+ ...nextOptions1?.context,
623
+ ...nextOptions2?.context
624
+ } })
625
+ }, input, output, ...rest)
626
+ }, input, output, ...rest);
627
+ });
628
+ };
629
+ return decorated;
630
+ }
631
+ function createActionableClient(client) {
632
+ const action = async (input) => {
633
+ try {
634
+ return [null, await client(input)];
635
+ } catch (error) {
636
+ if (error instanceof Error && "digest" in error && typeof error.digest === "string" && error.digest.startsWith("NEXT_")) throw error;
637
+ if (error instanceof Response && "options" in error && isObject(error.options) || isObject(error) && error.isNotFound === true) throw error;
638
+ return [toORPCError(error).toJSON(), void 0];
639
+ }
640
+ };
641
+ return action;
642
+ }
643
+ var DecoratedProcedure = class DecoratedProcedure extends Procedure {
644
+ /**
645
+ * Adds type-safe custom errors.
646
+ * The provided errors are spared-merged with any existing errors.
647
+ *
648
+ * @see {@link https://orpc.dev/docs/error-handling#type%E2%80%90safe-error-handling Type-Safe Error Handling Docs}
649
+ */
650
+ errors(errors) {
651
+ return new DecoratedProcedure({
652
+ ...this["~orpc"],
653
+ errorMap: mergeErrorMap(this["~orpc"].errorMap, errors)
654
+ });
655
+ }
656
+ /**
657
+ * Sets or updates the metadata.
658
+ * The provided metadata is spared-merged with any existing metadata.
659
+ *
660
+ * @see {@link https://orpc.dev/docs/metadata Metadata Docs}
661
+ */
662
+ meta(meta) {
663
+ return new DecoratedProcedure({
664
+ ...this["~orpc"],
665
+ meta: mergeMeta(this["~orpc"].meta, meta)
666
+ });
667
+ }
668
+ /**
669
+ * Sets or updates the route definition.
670
+ * The provided route is spared-merged with any existing route.
671
+ * This option is typically relevant when integrating with OpenAPI.
672
+ *
673
+ * @see {@link https://orpc.dev/docs/openapi/routing OpenAPI Routing Docs}
674
+ * @see {@link https://orpc.dev/docs/openapi/input-output-structure OpenAPI Input/Output Structure Docs}
675
+ */
676
+ route(route) {
677
+ return new DecoratedProcedure({
678
+ ...this["~orpc"],
679
+ route: mergeRoute(this["~orpc"].route, route)
680
+ });
681
+ }
682
+ use(middleware, mapInput) {
683
+ const mapped = mapInput ? decorateMiddleware(middleware).mapInput(mapInput) : middleware;
684
+ return new DecoratedProcedure({
685
+ ...this["~orpc"],
686
+ middlewares: addMiddleware(this["~orpc"].middlewares, mapped)
687
+ });
688
+ }
689
+ /**
690
+ * Make this procedure callable (works like a function while still being a procedure).
691
+ *
692
+ * @see {@link https://orpc.dev/docs/client/server-side Server-side Client Docs}
693
+ */
694
+ callable(...rest) {
695
+ const client = createProcedureClient(this, ...rest);
696
+ return new Proxy(client, {
697
+ get: (target, key) => {
698
+ return Reflect.has(this, key) ? Reflect.get(this, key) : Reflect.get(target, key);
699
+ },
700
+ has: (target, key) => {
701
+ return Reflect.has(this, key) || Reflect.has(target, key);
702
+ }
703
+ });
704
+ }
705
+ /**
706
+ * Make this procedure compatible with server action.
707
+ *
708
+ * @see {@link https://orpc.dev/docs/server-action Server Action Docs}
709
+ */
710
+ actionable(...rest) {
711
+ const action = createActionableClient(createProcedureClient(this, ...rest));
712
+ return new Proxy(action, {
713
+ get: (target, key) => {
714
+ return Reflect.has(this, key) ? Reflect.get(this, key) : Reflect.get(target, key);
715
+ },
716
+ has: (target, key) => {
717
+ return Reflect.has(this, key) || Reflect.has(target, key);
718
+ }
719
+ });
720
+ }
721
+ };
722
+ new class Builder {
723
+ /**
724
+ * This property holds the defined options.
725
+ */
726
+ "~orpc";
727
+ constructor(def) {
728
+ this["~orpc"] = def;
729
+ }
730
+ /**
731
+ * Sets or overrides the config.
732
+ *
733
+ * @see {@link https://orpc.dev/docs/client/server-side#middlewares-order Middlewares Order Docs}
734
+ * @see {@link https://orpc.dev/docs/best-practices/dedupe-middleware#configuration Dedupe Middleware Docs}
735
+ */
736
+ $config(config) {
737
+ const inputValidationCount = this["~orpc"].inputValidationIndex - fallbackConfig("initialInputValidationIndex", this["~orpc"].config.initialInputValidationIndex);
738
+ const outputValidationCount = this["~orpc"].outputValidationIndex - fallbackConfig("initialOutputValidationIndex", this["~orpc"].config.initialOutputValidationIndex);
739
+ return new Builder({
740
+ ...this["~orpc"],
741
+ config,
742
+ dedupeLeadingMiddlewares: fallbackConfig("dedupeLeadingMiddlewares", config.dedupeLeadingMiddlewares),
743
+ inputValidationIndex: fallbackConfig("initialInputValidationIndex", config.initialInputValidationIndex) + inputValidationCount,
744
+ outputValidationIndex: fallbackConfig("initialOutputValidationIndex", config.initialOutputValidationIndex) + outputValidationCount
745
+ });
746
+ }
747
+ /**
748
+ * Set or override the initial context.
749
+ *
750
+ * @see {@link https://orpc.dev/docs/context Context Docs}
751
+ */
752
+ $context() {
753
+ return new Builder({
754
+ ...this["~orpc"],
755
+ middlewares: [],
756
+ inputValidationIndex: fallbackConfig("initialInputValidationIndex", this["~orpc"].config.initialInputValidationIndex),
757
+ outputValidationIndex: fallbackConfig("initialOutputValidationIndex", this["~orpc"].config.initialOutputValidationIndex)
758
+ });
759
+ }
760
+ /**
761
+ * Sets or overrides the initial meta.
762
+ *
763
+ * @see {@link https://orpc.dev/docs/metadata Metadata Docs}
764
+ */
765
+ $meta(initialMeta) {
766
+ return new Builder({
767
+ ...this["~orpc"],
768
+ meta: initialMeta
769
+ });
770
+ }
771
+ /**
772
+ * Sets or overrides the initial route.
773
+ * This option is typically relevant when integrating with OpenAPI.
774
+ *
775
+ * @see {@link https://orpc.dev/docs/openapi/routing OpenAPI Routing Docs}
776
+ * @see {@link https://orpc.dev/docs/openapi/input-output-structure OpenAPI Input/Output Structure Docs}
777
+ */
778
+ $route(initialRoute) {
779
+ return new Builder({
780
+ ...this["~orpc"],
781
+ route: initialRoute
782
+ });
783
+ }
784
+ /**
785
+ * Sets or overrides the initial input schema.
786
+ *
787
+ * @see {@link https://orpc.dev/docs/procedure#initial-configuration Initial Procedure Configuration Docs}
788
+ */
789
+ $input(initialInputSchema) {
790
+ return new Builder({
791
+ ...this["~orpc"],
792
+ inputSchema: initialInputSchema
793
+ });
794
+ }
795
+ /**
796
+ * Creates a middleware.
797
+ *
798
+ * @see {@link https://orpc.dev/docs/middleware Middleware Docs}
799
+ */
800
+ middleware(middleware) {
801
+ return decorateMiddleware(middleware);
802
+ }
803
+ /**
804
+ * Adds type-safe custom errors.
805
+ * The provided errors are spared-merged with any existing errors.
806
+ *
807
+ * @see {@link https://orpc.dev/docs/error-handling#type%E2%80%90safe-error-handling Type-Safe Error Handling Docs}
808
+ */
809
+ errors(errors) {
810
+ return new Builder({
811
+ ...this["~orpc"],
812
+ errorMap: mergeErrorMap(this["~orpc"].errorMap, errors)
813
+ });
814
+ }
815
+ use(middleware, mapInput) {
816
+ const mapped = mapInput ? decorateMiddleware(middleware).mapInput(mapInput) : middleware;
817
+ return new Builder({
818
+ ...this["~orpc"],
819
+ middlewares: addMiddleware(this["~orpc"].middlewares, mapped)
820
+ });
821
+ }
822
+ /**
823
+ * Sets or updates the metadata.
824
+ * The provided metadata is spared-merged with any existing metadata.
825
+ *
826
+ * @see {@link https://orpc.dev/docs/metadata Metadata Docs}
827
+ */
828
+ meta(meta) {
829
+ return new Builder({
830
+ ...this["~orpc"],
831
+ meta: mergeMeta(this["~orpc"].meta, meta)
832
+ });
833
+ }
834
+ /**
835
+ * Sets or updates the route definition.
836
+ * The provided route is spared-merged with any existing route.
837
+ * This option is typically relevant when integrating with OpenAPI.
838
+ *
839
+ * @see {@link https://orpc.dev/docs/openapi/routing OpenAPI Routing Docs}
840
+ * @see {@link https://orpc.dev/docs/openapi/input-output-structure OpenAPI Input/Output Structure Docs}
841
+ */
842
+ route(route) {
843
+ return new Builder({
844
+ ...this["~orpc"],
845
+ route: mergeRoute(this["~orpc"].route, route)
846
+ });
847
+ }
848
+ /**
849
+ * Defines the input validation schema.
850
+ *
851
+ * @see {@link https://orpc.dev/docs/procedure#input-output-validation Input Validation Docs}
852
+ */
853
+ input(schema) {
854
+ return new Builder({
855
+ ...this["~orpc"],
856
+ inputSchema: schema,
857
+ inputValidationIndex: fallbackConfig("initialInputValidationIndex", this["~orpc"].config.initialInputValidationIndex) + this["~orpc"].middlewares.length
858
+ });
859
+ }
860
+ /**
861
+ * Defines the output validation schema.
862
+ *
863
+ * @see {@link https://orpc.dev/docs/procedure#input-output-validation Output Validation Docs}
864
+ */
865
+ output(schema) {
866
+ return new Builder({
867
+ ...this["~orpc"],
868
+ outputSchema: schema,
869
+ outputValidationIndex: fallbackConfig("initialOutputValidationIndex", this["~orpc"].config.initialOutputValidationIndex) + this["~orpc"].middlewares.length
870
+ });
871
+ }
872
+ /**
873
+ * Defines the handler of the procedure.
874
+ *
875
+ * @see {@link https://orpc.dev/docs/procedure Procedure Docs}
876
+ */
877
+ handler(handler) {
878
+ return new DecoratedProcedure({
879
+ ...this["~orpc"],
880
+ handler
881
+ });
882
+ }
883
+ /**
884
+ * Prefixes all procedures in the router.
885
+ * The provided prefix is post-appended to any existing router prefix.
886
+ *
887
+ * @note This option does not affect procedures that do not define a path in their route definition.
888
+ *
889
+ * @see {@link https://orpc.dev/docs/openapi/routing#route-prefixes OpenAPI Route Prefixes Docs}
890
+ */
891
+ prefix(prefix) {
892
+ return new Builder({
893
+ ...this["~orpc"],
894
+ prefix: mergePrefix(this["~orpc"].prefix, prefix)
895
+ });
896
+ }
897
+ /**
898
+ * Adds tags to all procedures in the router.
899
+ * This helpful when you want to group procedures together in the OpenAPI specification.
900
+ *
901
+ * @see {@link https://orpc.dev/docs/openapi/openapi-specification#operation-metadata OpenAPI Operation Metadata Docs}
902
+ */
903
+ tag(...tags) {
904
+ return new Builder({
905
+ ...this["~orpc"],
906
+ tags: mergeTags(this["~orpc"].tags, tags)
907
+ });
908
+ }
909
+ /**
910
+ * Applies all of the previously defined options to the specified router.
911
+ *
912
+ * @see {@link https://orpc.dev/docs/router#extending-router Extending Router Docs}
913
+ */
914
+ router(router) {
915
+ return enhanceRouter(router, this["~orpc"]);
916
+ }
917
+ /**
918
+ * Create a lazy router
919
+ * And applies all of the previously defined options to the specified router.
920
+ *
921
+ * @see {@link https://orpc.dev/docs/router#extending-router Extending Router Docs}
922
+ */
923
+ lazy(loader) {
924
+ return enhanceRouter(lazy(loader), this["~orpc"]);
925
+ }
926
+ }({
927
+ config: {},
928
+ route: {},
929
+ meta: {},
930
+ errorMap: {},
931
+ inputValidationIndex: fallbackConfig("initialInputValidationIndex"),
932
+ outputValidationIndex: fallbackConfig("initialOutputValidationIndex"),
933
+ middlewares: [],
934
+ dedupeLeadingMiddlewares: true
935
+ });
936
+ //#endregion
937
+ //#region ../api-contracts/dist/src-bLbxYIy4.mjs
938
+ var apps_default = {
939
+ find: oc.route({
940
+ method: "GET",
941
+ path: "/apps/{id}",
942
+ tags: ["Apps"],
943
+ summary: "Get an app",
944
+ description: "Retrieve an app by its ID"
945
+ }).input(z$1.object({ id: z$1.string() })).output(z$1.object({
946
+ id: z$1.string(),
947
+ name: z$1.string(),
948
+ createdAt: z$1.coerce.date()
949
+ })),
950
+ list: oc.route({
951
+ method: "GET",
952
+ path: "/apps",
953
+ tags: ["Apps"],
954
+ summary: "List apps",
955
+ description: "Retrieve all apps"
956
+ }).output(z$1.object({ results: z$1.array(z$1.object({
957
+ id: z$1.string(),
958
+ name: z$1.string(),
959
+ createdAt: z$1.coerce.date()
960
+ })) }))
961
+ };
962
+ const ChatSchema = z$1.object({
963
+ id: z$1.string(),
964
+ title: z$1.string(),
965
+ userId: z$1.string(),
966
+ createdAt: z$1.coerce.date()
967
+ });
968
+ var chats_default = {
969
+ create: oc.route({
970
+ method: "POST",
971
+ path: "/chats",
972
+ tags: ["Chats"],
973
+ summary: "Create a chat",
974
+ description: "Create a new chat session"
975
+ }).input(z$1.object({
976
+ title: z$1.string(),
977
+ userId: z$1.string().min(1)
978
+ })).output(ChatSchema),
979
+ find: oc.route({
980
+ method: "GET",
981
+ path: "/chats/{id}",
982
+ tags: ["Chats"],
983
+ summary: "Get a chat",
984
+ description: "Retrieve a chat by its ID"
985
+ }).input(z$1.object({ id: z$1.string() })).output(ChatSchema),
986
+ list: oc.route({
987
+ method: "GET",
988
+ path: "/chats",
989
+ tags: ["Chats"],
990
+ summary: "List chats",
991
+ description: "Retrieve all chats with pagination support"
992
+ }).input(z$1.object({
993
+ userId: z$1.string().min(1).optional(),
994
+ limit: z$1.coerce.number().int().min(1).max(100).default(20),
995
+ cursor: z$1.string().optional()
996
+ })).output(z$1.object({
997
+ results: z$1.array(ChatSchema),
998
+ nextCursor: z$1.string().nullable(),
999
+ hasMore: z$1.boolean()
1000
+ }))
1001
+ };
1002
+ const MessageSchema = z$1.object({
1003
+ id: z$1.string(),
1004
+ role: z$1.enum(["user", "assistant"]),
1005
+ content: z$1.array(ContentBlockSchema),
1006
+ createdAt: z$1.coerce.date(),
1007
+ error: z$1.object({
1008
+ code: z$1.string(),
1009
+ message: z$1.string()
1010
+ }).nullable()
1011
+ });
1012
+ var messages_default = { create: oc.route({
1013
+ method: "POST",
1014
+ path: "/messages",
1015
+ tags: ["Messages"],
1016
+ summary: "Create a message",
1017
+ description: "Create a user message in a chat"
1018
+ }).input(z$1.object({
1019
+ id: z$1.string().optional(),
1020
+ chatId: z$1.string(),
1021
+ content: ContentFieldSchema
1022
+ })).output(MessageSchema) };
1023
+ const toolSchema = z$1.object({
1024
+ name: z$1.string(),
1025
+ description: z$1.string(),
1026
+ defaultLoadingText: z$1.string().nullish(),
1027
+ defaultSuccessText: z$1.string().nullish(),
1028
+ inputSchema: z$1.any().optional()
1029
+ });
1030
+ var responses_default = { create: oc.route({
1031
+ method: "POST",
1032
+ path: "/responses",
1033
+ tags: ["Responses"],
1034
+ summary: "Create a response",
1035
+ description: "Send a user message to a chat and stream the assistant response. Returns a Server-Sent Events (SSE) stream of message events.",
1036
+ successDescription: "SSE stream of message events (message_start, content_block_delta, message_delta, message_stop, etc.)."
1037
+ }).input(z$1.object({
1038
+ id: z$1.string().optional().describe("Optional client-generated message ID."),
1039
+ chatId: z$1.string().describe("The chat ID to send the message to."),
1040
+ content: ContentFieldSchema.describe("The message content (text or structured blocks)."),
1041
+ tools: z$1.array(toolSchema).default([]).describe("Tools available to the assistant for this request."),
1042
+ tags: z$1.array(z$1.string()).optional().describe("Tags to attach to this response."),
1043
+ model: z$1.string().optional().describe("Override the model for this request.")
1044
+ })).output(eventIterator(MessageStreamEventSchema)) };
1045
+ /**
1046
+ * Header name constants for the public API
1047
+ */
1048
+ const API_KEY_HEADER = "x-api-key";
1049
+ /**
1050
+ * Schema for the API key header
1051
+ * API keys are prefixed with 'sk_' (secret key)
1052
+ */
1053
+ const ApiKeyHeaderSchema = z.string().min(1, "API key is required");
1054
+ z.object({ [API_KEY_HEADER]: ApiKeyHeaderSchema });
1055
+ const contract = {
1056
+ apps: apps_default,
1057
+ chats: chats_default,
1058
+ messages: messages_default,
1059
+ responses: responses_default
1060
+ };
1061
+ //#endregion
1062
+ //#region src/index.ts
1063
+ const DEFAULT_BASE_URL = "https://api.plucky.ai";
1064
+ /**
1065
+ * Plucky API client for Node.js
1066
+ *
1067
+ * @example
1068
+ * ```ts
1069
+ * import Plucky from '@plucky-ai/node'
1070
+ *
1071
+ * const plucky = new Plucky({ apiKey: 'sk_...' })
1072
+ *
1073
+ * const chats = await plucky.chats.list()
1074
+ * ```
1075
+ */
1076
+ var Plucky = class {
1077
+ client;
1078
+ /**
1079
+ * Access to chat operations
1080
+ */
1081
+ chats;
1082
+ /**
1083
+ * Access to app operations
1084
+ */
1085
+ apps;
1086
+ constructor(options) {
1087
+ const { apiKey, baseUrl = DEFAULT_BASE_URL, fetch: customFetch } = options;
1088
+ if (!apiKey) throw new Error("API key is required. Get one at https://app.plucky.ai");
1089
+ this.client = createApiClient$1({
1090
+ apiKey,
1091
+ baseUrl,
1092
+ fetch: customFetch
1093
+ });
1094
+ this.chats = this.client.chats;
1095
+ this.apps = this.client.apps;
1096
+ }
1097
+ /**
1098
+ * Get the underlying API client for advanced use cases
1099
+ */
1100
+ get api() {
1101
+ return this.client;
1102
+ }
1103
+ };
1104
+ //#endregion
1105
+ export { API_KEY_HEADER, Plucky, Plucky as default, contract, createApiClient };
1106
+
1107
+ //# sourceMappingURL=index.mjs.map