@context-action/core 0.8.1 โ 0.8.6
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/README.md +104 -3
- package/dist/index.cjs +361 -19
- package/dist/index.d.cts +127 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +127 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +355 -19
- package/dist/index.js.map +1 -1
- package/package.json +37 -23
package/dist/index.js
CHANGED
|
@@ -314,27 +314,91 @@ var ActionGuard = class {
|
|
|
314
314
|
this.guards = /* @__PURE__ */ new Map();
|
|
315
315
|
this.maxIdleTime = 6e4;
|
|
316
316
|
this.cleanupIntervalMs = 3e4;
|
|
317
|
+
this.maxGuards = 1e3;
|
|
318
|
+
this.accessOrder = [];
|
|
317
319
|
if (autoCleanup) this.startAutoCleanup();
|
|
318
320
|
}
|
|
319
321
|
/**
|
|
320
322
|
* Start automatic cleanup of idle guard states
|
|
321
|
-
*
|
|
323
|
+
*
|
|
322
324
|
* @internal
|
|
323
325
|
*/
|
|
324
326
|
startAutoCleanup() {
|
|
325
327
|
this.cleanupInterval = setInterval(() => {
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
328
|
+
this.performCleanup();
|
|
329
|
+
}, this.cleanupIntervalMs);
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* ๐ง Optimized cleanup with early exit and batched operations
|
|
333
|
+
*
|
|
334
|
+
* @internal
|
|
335
|
+
*/
|
|
336
|
+
performCleanup() {
|
|
337
|
+
const guardCount = this.guards.size;
|
|
338
|
+
if (guardCount === 0) return;
|
|
339
|
+
const now = Date.now();
|
|
340
|
+
const keysToDelete = [];
|
|
341
|
+
if (guardCount <= 10) this.guards.forEach((state, key) => {
|
|
342
|
+
const isIdle = now - state.lastExecuted > this.maxIdleTime;
|
|
343
|
+
const hasActiveTimers = state.debounceTimer || state.throttleTimer;
|
|
344
|
+
if (isIdle && !hasActiveTimers) keysToDelete.push(key);
|
|
345
|
+
});
|
|
346
|
+
else {
|
|
347
|
+
const entriesToCheck = Math.min(this.accessOrder.length, Math.ceil(guardCount / 4));
|
|
348
|
+
for (let i = 0; i < entriesToCheck; i++) {
|
|
349
|
+
const key = this.accessOrder[i];
|
|
350
|
+
if (!key) continue;
|
|
351
|
+
const state = this.guards.get(key);
|
|
352
|
+
if (!state) {
|
|
353
|
+
keysToDelete.push(key);
|
|
354
|
+
continue;
|
|
355
|
+
}
|
|
329
356
|
const isIdle = now - state.lastExecuted > this.maxIdleTime;
|
|
330
357
|
const hasActiveTimers = state.debounceTimer || state.throttleTimer;
|
|
331
358
|
if (isIdle && !hasActiveTimers) keysToDelete.push(key);
|
|
332
|
-
});
|
|
333
|
-
if (keysToDelete.length > 0) {
|
|
334
|
-
keysToDelete.forEach((key) => this.guards.delete(key));
|
|
335
|
-
if (typeof process !== "undefined" && process.env?.DEBUG_CONTEXT_ACTION) console.debug(`[ActionGuard] Cleaned up ${keysToDelete.length} idle guards`);
|
|
336
359
|
}
|
|
337
|
-
}
|
|
360
|
+
}
|
|
361
|
+
if (keysToDelete.length > 0) {
|
|
362
|
+
keysToDelete.forEach((key) => {
|
|
363
|
+
this.guards.delete(key);
|
|
364
|
+
const accessIndex = this.accessOrder.indexOf(key);
|
|
365
|
+
if (accessIndex !== -1) this.accessOrder.splice(accessIndex, 1);
|
|
366
|
+
});
|
|
367
|
+
if (typeof process !== "undefined" && process.env?.DEBUG_CONTEXT_ACTION) console.debug(`[ActionGuard] Cleaned up ${keysToDelete.length} idle guards`);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* ๐ง Update access order for LRU tracking
|
|
372
|
+
*
|
|
373
|
+
* @internal
|
|
374
|
+
*/
|
|
375
|
+
updateAccessOrder(key) {
|
|
376
|
+
const existingIndex = this.accessOrder.indexOf(key);
|
|
377
|
+
if (existingIndex !== -1) this.accessOrder.splice(existingIndex, 1);
|
|
378
|
+
this.accessOrder.push(key);
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* ๐ง Evict oldest guards if max limit exceeded
|
|
382
|
+
*
|
|
383
|
+
* @internal
|
|
384
|
+
*/
|
|
385
|
+
evictIfNeeded() {
|
|
386
|
+
if (this.guards.size >= this.maxGuards) {
|
|
387
|
+
const evictCount = Math.ceil(this.maxGuards * .1);
|
|
388
|
+
this.accessOrder.slice(0, evictCount).forEach((key) => {
|
|
389
|
+
const state = this.guards.get(key);
|
|
390
|
+
if (state) {
|
|
391
|
+
if (state.debounceTimer) {
|
|
392
|
+
clearTimeout(state.debounceTimer);
|
|
393
|
+
if (state.debounceResolve) state.debounceResolve(false);
|
|
394
|
+
}
|
|
395
|
+
if (state.throttleTimer) clearTimeout(state.throttleTimer);
|
|
396
|
+
}
|
|
397
|
+
this.guards.delete(key);
|
|
398
|
+
});
|
|
399
|
+
this.accessOrder = this.accessOrder.slice(evictCount);
|
|
400
|
+
if (typeof process !== "undefined" && process.env?.DEBUG_CONTEXT_ACTION) console.debug(`[ActionGuard] Evicted ${evictCount} oldest guards due to limit`);
|
|
401
|
+
}
|
|
338
402
|
}
|
|
339
403
|
/**
|
|
340
404
|
* Apply debouncing to an action
|
|
@@ -359,6 +423,7 @@ var ActionGuard = class {
|
|
|
359
423
|
* @internal
|
|
360
424
|
*/
|
|
361
425
|
async debounce(actionKey, debounceMs) {
|
|
426
|
+
this.evictIfNeeded();
|
|
362
427
|
/** Get or create guard state for this action */
|
|
363
428
|
let state = this.guards.get(actionKey);
|
|
364
429
|
if (!state) {
|
|
@@ -373,6 +438,7 @@ var ActionGuard = class {
|
|
|
373
438
|
};
|
|
374
439
|
this.guards.set(actionKey, state);
|
|
375
440
|
}
|
|
441
|
+
this.updateAccessOrder(actionKey);
|
|
376
442
|
/** Clear any existing debounce timer to restart the delay period */
|
|
377
443
|
if (state.debounceTimer) {
|
|
378
444
|
clearTimeout(state.debounceTimer);
|
|
@@ -417,6 +483,7 @@ var ActionGuard = class {
|
|
|
417
483
|
* @internal
|
|
418
484
|
*/
|
|
419
485
|
throttle(actionKey, throttleMs) {
|
|
486
|
+
this.evictIfNeeded();
|
|
420
487
|
/** Get or create guard state for this action */
|
|
421
488
|
let state = this.guards.get(actionKey);
|
|
422
489
|
if (!state) {
|
|
@@ -431,6 +498,7 @@ var ActionGuard = class {
|
|
|
431
498
|
};
|
|
432
499
|
this.guards.set(actionKey, state);
|
|
433
500
|
}
|
|
501
|
+
this.updateAccessOrder(actionKey);
|
|
434
502
|
const now = Date.now();
|
|
435
503
|
const timeSinceLastExecution = now - state.lastExecuted;
|
|
436
504
|
/** Check if enough time has passed since last execution */
|
|
@@ -548,6 +616,7 @@ var ActionGuard = class {
|
|
|
548
616
|
this.cleanupInterval = void 0;
|
|
549
617
|
}
|
|
550
618
|
this.clearAll();
|
|
619
|
+
this.accessOrder = [];
|
|
551
620
|
}
|
|
552
621
|
/**
|
|
553
622
|
* ๐ Get statistics about active guards
|
|
@@ -632,7 +701,11 @@ var OperationQueue = class {
|
|
|
632
701
|
* - ์์
์๋ฃ ์ ๋๊ธฐ ์ค์ธ ํ๋ก์ธ์ค์๊ฒ ์๋ ์๋ฆผ
|
|
633
702
|
*/
|
|
634
703
|
async processQueue() {
|
|
635
|
-
if (this.processingPromise)
|
|
704
|
+
if (this.processingPromise) {
|
|
705
|
+
await this.processingPromise;
|
|
706
|
+
if (this.queue.length > 0 && !this.processingPromise) return this.processQueue();
|
|
707
|
+
return;
|
|
708
|
+
}
|
|
636
709
|
this.processingPromise = this._doProcess();
|
|
637
710
|
try {
|
|
638
711
|
await this.processingPromise;
|
|
@@ -744,6 +817,95 @@ var OperationQueue = class {
|
|
|
744
817
|
}
|
|
745
818
|
};
|
|
746
819
|
|
|
820
|
+
//#endregion
|
|
821
|
+
//#region src/errors.ts
|
|
822
|
+
/**
|
|
823
|
+
* Action payload ๊ฒ์ฆ ์คํจ ์๋ฌ
|
|
824
|
+
*
|
|
825
|
+
* dispatch ์ Zod ์คํค๋ง ๊ฒ์ฆ์ด ์คํจํ๋ฉด ๋ฐ์ํฉ๋๋ค.
|
|
826
|
+
* (validationMode๊ฐ 'strict'์ผ ๋๋ง throw)
|
|
827
|
+
*
|
|
828
|
+
* @example
|
|
829
|
+
* ```typescript
|
|
830
|
+
* try {
|
|
831
|
+
* dispatch('updateUser', { id: '', name: 'John' });
|
|
832
|
+
* } catch (error) {
|
|
833
|
+
* if (error instanceof ActionValidationError) {
|
|
834
|
+
* console.log('Action:', error.action);
|
|
835
|
+
* console.log('Issues:', error.issues);
|
|
836
|
+
* console.log('Formatted:', error.formattedErrors);
|
|
837
|
+
* }
|
|
838
|
+
* }
|
|
839
|
+
* ```
|
|
840
|
+
*/
|
|
841
|
+
var ActionValidationError = class ActionValidationError extends Error {
|
|
842
|
+
/**
|
|
843
|
+
* @param action - ๊ฒ์ฆ ์คํจํ action ์ด๋ฆ
|
|
844
|
+
* @param zodError - Zod ๊ฒ์ฆ ์๋ฌ ๊ฐ์ฒด (ZodError compatible)
|
|
845
|
+
*/
|
|
846
|
+
constructor(action, zodError) {
|
|
847
|
+
const message = `Action "${action}" payload validation failed: ${zodError && typeof zodError === "object" && "message" in zodError ? String(zodError.message) : "Validation failed"}`;
|
|
848
|
+
super(message);
|
|
849
|
+
this.name = "ActionValidationError";
|
|
850
|
+
this.action = action;
|
|
851
|
+
this.zodError = zodError;
|
|
852
|
+
Object.setPrototypeOf(this, ActionValidationError.prototype);
|
|
853
|
+
}
|
|
854
|
+
/**
|
|
855
|
+
* Zod ๊ฒ์ฆ ์ด์ ๋ชฉ๋ก
|
|
856
|
+
*/
|
|
857
|
+
get issues() {
|
|
858
|
+
if (this.zodError && typeof this.zodError === "object" && "issues" in this.zodError && Array.isArray(this.zodError.issues)) return this.zodError.issues;
|
|
859
|
+
return [];
|
|
860
|
+
}
|
|
861
|
+
/**
|
|
862
|
+
* ํฌ๋งท๋ ์๋ฌ ๊ฐ์ฒด (ํ๋๋ณ ์๋ฌ ๋ฉ์์ง)
|
|
863
|
+
*/
|
|
864
|
+
get formattedErrors() {
|
|
865
|
+
if (this.zodError && typeof this.zodError === "object" && "format" in this.zodError && typeof this.zodError.format === "function") return this.zodError.format();
|
|
866
|
+
return {};
|
|
867
|
+
}
|
|
868
|
+
/**
|
|
869
|
+
* ํ๋ซ ์๋ฌ ๋งต (ํ๋๋ช
โ ์๋ฌ ๋ฉ์์ง ๋ฐฐ์ด)
|
|
870
|
+
*/
|
|
871
|
+
get flattenedErrors() {
|
|
872
|
+
if (this.zodError && typeof this.zodError === "object" && "flatten" in this.zodError && typeof this.zodError.flatten === "function") return this.zodError.flatten();
|
|
873
|
+
return {
|
|
874
|
+
fieldErrors: {},
|
|
875
|
+
formErrors: []
|
|
876
|
+
};
|
|
877
|
+
}
|
|
878
|
+
/**
|
|
879
|
+
* ์ฒซ ๋ฒ์งธ ์๋ฌ ๋ฉ์์ง
|
|
880
|
+
*/
|
|
881
|
+
get firstError() {
|
|
882
|
+
return this.issues[0]?.message;
|
|
883
|
+
}
|
|
884
|
+
/**
|
|
885
|
+
* ์๋ฌ ๋ฐ์ ํ๋ ๊ฒฝ๋ก ๋ชฉ๋ก
|
|
886
|
+
*/
|
|
887
|
+
get errorPaths() {
|
|
888
|
+
return this.issues.map((issue) => issue.path.map((p) => String(p)).join("."));
|
|
889
|
+
}
|
|
890
|
+
/**
|
|
891
|
+
* JSON ์ง๋ ฌํ
|
|
892
|
+
*/
|
|
893
|
+
toJSON() {
|
|
894
|
+
return {
|
|
895
|
+
name: this.name,
|
|
896
|
+
action: this.action,
|
|
897
|
+
message: this.message,
|
|
898
|
+
issues: this.issues
|
|
899
|
+
};
|
|
900
|
+
}
|
|
901
|
+
};
|
|
902
|
+
/**
|
|
903
|
+
* ActionValidationError ํ์
๊ฐ๋
|
|
904
|
+
*/
|
|
905
|
+
function isActionValidationError(error) {
|
|
906
|
+
return error instanceof ActionValidationError;
|
|
907
|
+
}
|
|
908
|
+
|
|
747
909
|
//#endregion
|
|
748
910
|
//#region src/ActionRegister.ts
|
|
749
911
|
/**
|
|
@@ -761,6 +923,35 @@ var OperationQueue = class {
|
|
|
761
923
|
*
|
|
762
924
|
* @public
|
|
763
925
|
*/
|
|
926
|
+
/**
|
|
927
|
+
* Type guard to determine if an object is DispatchOptions
|
|
928
|
+
* Extracted as utility function for reuse and performance
|
|
929
|
+
*
|
|
930
|
+
* @param obj - Object to check
|
|
931
|
+
* @returns True if object is DispatchOptions
|
|
932
|
+
* @internal
|
|
933
|
+
*/
|
|
934
|
+
function isDispatchOptions(obj) {
|
|
935
|
+
if (!obj || typeof obj !== "object") return false;
|
|
936
|
+
if ("debounce" in obj && typeof obj.debounce === "number") return true;
|
|
937
|
+
if ("throttle" in obj && typeof obj.throttle === "number") return true;
|
|
938
|
+
if ("executionMode" in obj) return true;
|
|
939
|
+
if ("signal" in obj && obj.signal instanceof AbortSignal) return true;
|
|
940
|
+
if ("immediate" in obj && typeof obj.immediate === "boolean") return true;
|
|
941
|
+
if ("queuePriority" in obj && typeof obj.queuePriority === "number") return true;
|
|
942
|
+
if ("timeout" in obj && typeof obj.timeout === "number") return true;
|
|
943
|
+
if ("retryOnError" in obj && typeof obj.retryOnError === "object") return true;
|
|
944
|
+
if ("autoAbort" in obj && typeof obj.autoAbort === "object") return true;
|
|
945
|
+
if ("filter" in obj && typeof obj.filter === "object" && obj.filter !== null) {
|
|
946
|
+
const filter = obj.filter;
|
|
947
|
+
if ("handlerIds" in filter || "excludeHandlerIds" in filter || "priority" in filter || "custom" in filter) return true;
|
|
948
|
+
}
|
|
949
|
+
if ("result" in obj && typeof obj.result === "object" && obj.result !== null) {
|
|
950
|
+
const result = obj.result;
|
|
951
|
+
if ("strategy" in result || "merger" in result || "collect" in result || "maxResults" in result || "includeErrors" in result) return true;
|
|
952
|
+
}
|
|
953
|
+
return false;
|
|
954
|
+
}
|
|
764
955
|
var ActionRegister = class {
|
|
765
956
|
constructor(config = {}) {
|
|
766
957
|
this.pipelines = /* @__PURE__ */ new Map();
|
|
@@ -809,18 +1000,16 @@ var ActionRegister = class {
|
|
|
809
1000
|
* @public
|
|
810
1001
|
*/
|
|
811
1002
|
get actions() {
|
|
812
|
-
|
|
1003
|
+
if (!this._actionsProxy) this._actionsProxy = new Proxy({}, { get: (_target, prop) => {
|
|
813
1004
|
if (typeof prop === "string" && this.pipelines.has(prop)) {
|
|
814
1005
|
const actionKey = prop;
|
|
815
1006
|
return (payloadOrOptions, options) => {
|
|
816
|
-
const isDispatchOptions = (obj) => {
|
|
817
|
-
return obj && typeof obj === "object" && ("debounce" in obj || "throttle" in obj || "executionMode" in obj || "signal" in obj || "immediate" in obj || "filter" in obj || "result" in obj);
|
|
818
|
-
};
|
|
819
1007
|
if (payloadOrOptions && isDispatchOptions(payloadOrOptions)) return this.dispatch(actionKey, void 0, payloadOrOptions);
|
|
820
1008
|
else return this.dispatch(actionKey, payloadOrOptions, options);
|
|
821
1009
|
};
|
|
822
1010
|
}
|
|
823
1011
|
} });
|
|
1012
|
+
return this._actionsProxy;
|
|
824
1013
|
}
|
|
825
1014
|
/**
|
|
826
1015
|
* Actions-based dispatching with result collection
|
|
@@ -846,18 +1035,16 @@ var ActionRegister = class {
|
|
|
846
1035
|
* @returns Proxy object with action functions that return ExecutionResult
|
|
847
1036
|
*/
|
|
848
1037
|
get actionsWithResult() {
|
|
849
|
-
|
|
1038
|
+
if (!this._actionsWithResultProxy) this._actionsWithResultProxy = new Proxy({}, { get: (_target, prop) => {
|
|
850
1039
|
if (typeof prop === "string" && this.pipelines.has(prop)) {
|
|
851
1040
|
const actionKey = prop;
|
|
852
1041
|
return (payloadOrOptions, options) => {
|
|
853
|
-
const isDispatchOptions = (obj) => {
|
|
854
|
-
return obj && typeof obj === "object" && ("debounce" in obj || "throttle" in obj || "executionMode" in obj || "signal" in obj || "immediate" in obj || "filter" in obj || "result" in obj);
|
|
855
|
-
};
|
|
856
1042
|
if (payloadOrOptions && isDispatchOptions(payloadOrOptions)) return this.dispatchWithResult(actionKey, void 0, payloadOrOptions);
|
|
857
1043
|
else return this.dispatchWithResult(actionKey, payloadOrOptions, options);
|
|
858
1044
|
};
|
|
859
1045
|
}
|
|
860
1046
|
} });
|
|
1047
|
+
return this._actionsWithResultProxy;
|
|
861
1048
|
}
|
|
862
1049
|
/**
|
|
863
1050
|
* Register an action handler with optional configuration
|
|
@@ -1042,6 +1229,20 @@ var ActionRegister = class {
|
|
|
1042
1229
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1043
1230
|
});
|
|
1044
1231
|
if (payload instanceof Event && true) console.warn(`Event object passed to action "${String(action)}"`, payload.type);
|
|
1232
|
+
if (this.registryConfig?.schema && this.registryConfig?.validateOnDispatch !== false) {
|
|
1233
|
+
const actionSchema = this.registryConfig.schema[action];
|
|
1234
|
+
if (actionSchema) {
|
|
1235
|
+
const result = actionSchema.safeParse(payload);
|
|
1236
|
+
if (!result.success) {
|
|
1237
|
+
const mode = this.registryConfig.validationMode ?? "strict";
|
|
1238
|
+
if (mode === "strict") throw new ActionValidationError(action, result.error);
|
|
1239
|
+
else if (mode === "warn") {
|
|
1240
|
+
console.warn(`Action "${String(action)}" payload validation failed:`, result.error.message);
|
|
1241
|
+
this.log(`Validation warning for action '${String(action)}'`, { issues: result.error.issues }, "warn");
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1045
1246
|
const [effectiveSignal, autoAbortController, cleanup] = this.createAbortSignal(options);
|
|
1046
1247
|
if (options?.autoAbort?.onControllerCreated && autoAbortController) options.autoAbort.onControllerCreated(autoAbortController);
|
|
1047
1248
|
if (effectiveSignal?.aborted) {
|
|
@@ -1927,5 +2128,140 @@ function isReactActionError(error) {
|
|
|
1927
2128
|
}
|
|
1928
2129
|
|
|
1929
2130
|
//#endregion
|
|
1930
|
-
|
|
2131
|
+
//#region src/action-schema.ts
|
|
2132
|
+
/**
|
|
2133
|
+
* Zod ์คํค๋ง๋ฅผ JSON Schema๋ก ๋ณํ (Zod 4 ๋ค์ดํฐ๋ธ API)
|
|
2134
|
+
*
|
|
2135
|
+
* @param schema - Zod ์คํค๋ง
|
|
2136
|
+
* @returns JSON Schema (draft-7)
|
|
2137
|
+
*/
|
|
2138
|
+
function zodToJsonSchema(schema, zodModule) {
|
|
2139
|
+
return zodModule.toJSONSchema(schema, {
|
|
2140
|
+
target: "draft-7",
|
|
2141
|
+
metadata: zodModule.globalRegistry
|
|
2142
|
+
});
|
|
2143
|
+
}
|
|
2144
|
+
/**
|
|
2145
|
+
* Zod ์คํค๋ง ๊ธฐ๋ฐ Action ์ ์
|
|
2146
|
+
*
|
|
2147
|
+
* defineTool ํจํด์ ๊ธฐ๋ฐ์ผ๋ก context-action์ ๋ง๊ฒ ๊ตฌํ:
|
|
2148
|
+
* - Single Source of Truth: Zod ์คํค๋ง๋ก ํ์
+ ๊ฒ์ฆ + ๋ฉํ๋ฐ์ดํฐ ํตํฉ
|
|
2149
|
+
* - ๋ฐํ์ ๊ฒ์ฆ: validate(), safeParse()
|
|
2150
|
+
* - Tool Chain ํธํ: toMCP(), toOpenAI(), toAnthropic()
|
|
2151
|
+
*
|
|
2152
|
+
* @param options - Action ์ ์ ์ต์
|
|
2153
|
+
* @param zodModule - Zod ๋ชจ๋ (peerDependency๋ก ์ฃผ์
)
|
|
2154
|
+
* @returns UnifiedAction ์ธ์คํด์ค
|
|
2155
|
+
*
|
|
2156
|
+
* @example
|
|
2157
|
+
* ```typescript
|
|
2158
|
+
* import { z } from 'zod';
|
|
2159
|
+
* import { defineAction } from '@context-action/core';
|
|
2160
|
+
*
|
|
2161
|
+
* const updateUserAction = defineAction({
|
|
2162
|
+
* name: 'updateUser',
|
|
2163
|
+
* description: 'Update user profile',
|
|
2164
|
+
* parameters: z.object({
|
|
2165
|
+
* id: z.string().min(1).meta({ description: 'User ID' }),
|
|
2166
|
+
* name: z.string().min(2).max(50).meta({ description: 'User name' }),
|
|
2167
|
+
* email: z.string().email().optional(),
|
|
2168
|
+
* }),
|
|
2169
|
+
* }, z);
|
|
2170
|
+
*
|
|
2171
|
+
* // ๊ฒ์ฆ
|
|
2172
|
+
* const validated = updateUserAction.validate({ id: '123', name: 'John' });
|
|
2173
|
+
*
|
|
2174
|
+
* // Tool chain ๋ณํ
|
|
2175
|
+
* const mcpTool = updateUserAction.toMCP();
|
|
2176
|
+
* ```
|
|
2177
|
+
*/
|
|
2178
|
+
function defineAction(options, zodModule) {
|
|
2179
|
+
const { name, description, parameters } = options;
|
|
2180
|
+
const jsonSchema = zodToJsonSchema(parameters, zodModule);
|
|
2181
|
+
return {
|
|
2182
|
+
name,
|
|
2183
|
+
description,
|
|
2184
|
+
zodSchema: parameters,
|
|
2185
|
+
jsonSchema,
|
|
2186
|
+
validate: (payload) => {
|
|
2187
|
+
return parameters.parse(payload);
|
|
2188
|
+
},
|
|
2189
|
+
safeParse: (payload) => {
|
|
2190
|
+
return parameters.safeParse(payload);
|
|
2191
|
+
},
|
|
2192
|
+
toJSONSchema: () => jsonSchema,
|
|
2193
|
+
toMCP: () => ({
|
|
2194
|
+
name,
|
|
2195
|
+
description,
|
|
2196
|
+
inputSchema: jsonSchema
|
|
2197
|
+
}),
|
|
2198
|
+
toOpenAI: () => ({
|
|
2199
|
+
type: "function",
|
|
2200
|
+
function: {
|
|
2201
|
+
name,
|
|
2202
|
+
description,
|
|
2203
|
+
parameters: {
|
|
2204
|
+
type: "object",
|
|
2205
|
+
properties: jsonSchema.properties ?? {},
|
|
2206
|
+
required: jsonSchema.required
|
|
2207
|
+
}
|
|
2208
|
+
}
|
|
2209
|
+
}),
|
|
2210
|
+
toAnthropic: () => ({
|
|
2211
|
+
name,
|
|
2212
|
+
description,
|
|
2213
|
+
input_schema: jsonSchema
|
|
2214
|
+
})
|
|
2215
|
+
};
|
|
2216
|
+
}
|
|
2217
|
+
/**
|
|
2218
|
+
* ๋ค์ค Action ์คํค๋ง ์์ฑ
|
|
2219
|
+
*
|
|
2220
|
+
* ์ฌ๋ฌ defineAction์ ๋ฌถ์ด์ ActionSchemaMap ์์ฑ
|
|
2221
|
+
*
|
|
2222
|
+
* @param actions - UnifiedAction ๋งต
|
|
2223
|
+
* @returns ActionSchemaMap
|
|
2224
|
+
*
|
|
2225
|
+
* @example
|
|
2226
|
+
* ```typescript
|
|
2227
|
+
* const userActionSchema = createActionSchema({
|
|
2228
|
+
* updateUser: defineAction({ ... }, z),
|
|
2229
|
+
* deleteUser: defineAction({ ... }, z),
|
|
2230
|
+
* });
|
|
2231
|
+
*
|
|
2232
|
+
* type UserActions = InferActionPayloadMap<typeof userActionSchema>;
|
|
2233
|
+
* ```
|
|
2234
|
+
*/
|
|
2235
|
+
function createActionSchema(actions) {
|
|
2236
|
+
return actions;
|
|
2237
|
+
}
|
|
2238
|
+
/**
|
|
2239
|
+
* Zod ๋ชจ๋์ ๋ฐ์ธ๋ฉํ defineAction ํฉํ ๋ฆฌ ์์ฑ
|
|
2240
|
+
*
|
|
2241
|
+
* ๋งค๋ฒ z ๋ชจ๋์ ์ ๋ฌํ์ง ์์๋ ๋๋๋ก ํฉํ ๋ฆฌ ํจํด ์ ๊ณต
|
|
2242
|
+
*
|
|
2243
|
+
* @param zodModule - Zod ๋ชจ๋
|
|
2244
|
+
* @returns defineAction ํจ์ (z ๋ฐ์ธ๋ฉ๋จ)
|
|
2245
|
+
*
|
|
2246
|
+
* @example
|
|
2247
|
+
* ```typescript
|
|
2248
|
+
* import { z } from 'zod';
|
|
2249
|
+
* import { createActionFactory } from '@context-action/core';
|
|
2250
|
+
*
|
|
2251
|
+
* const defineAction = createActionFactory(z);
|
|
2252
|
+
*
|
|
2253
|
+
* const updateUser = defineAction({
|
|
2254
|
+
* name: 'updateUser',
|
|
2255
|
+
* parameters: z.object({ id: z.string() }),
|
|
2256
|
+
* });
|
|
2257
|
+
* ```
|
|
2258
|
+
*/
|
|
2259
|
+
function createActionFactory(zodModule) {
|
|
2260
|
+
return (options) => {
|
|
2261
|
+
return defineAction(options, zodModule);
|
|
2262
|
+
};
|
|
2263
|
+
}
|
|
2264
|
+
|
|
2265
|
+
//#endregion
|
|
2266
|
+
export { ActionGuard, ActionRegister, ActionValidationError, ReactActionError, ReactDevUtils, createActionFactory, createActionHandler, createActionSchema, defineAction, executeParallel, executeRace, executeSequential, isActionValidationError, isReactActionError, zodToJsonSchema };
|
|
1931
2267
|
//# sourceMappingURL=index.js.map
|