@context-action/core 0.8.8 โ 0.9.2
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 +17 -0
- package/dist/index.cjs +8 -428
- package/dist/index.d.cts +26 -133
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +26 -133
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -420
- package/dist/index.js.map +1 -1
- package/package.json +6 -13
package/README.md
CHANGED
|
@@ -53,6 +53,23 @@ await actions.dispatch('increment');
|
|
|
53
53
|
await actions.dispatch('setCount', 42);
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
+
## Tool protocol boundary
|
|
57
|
+
|
|
58
|
+
MCP, JSON Schema, provider conversion, action schemas, and approval queues are
|
|
59
|
+
owned by [`@context-action/tool-protocol`](../tool-protocol/README.md). Core
|
|
60
|
+
only owns action registration and execution. This keeps the runtime usable
|
|
61
|
+
without a tool-calling or Zod dependency.
|
|
62
|
+
|
|
63
|
+
Install the protocol package separately when an integration needs it:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
npm install @context-action/tool-protocol zod
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
The React-facing registry remains in `@context-action/react`; protocol symbols
|
|
70
|
+
such as `defineAction`, `listAllTools`, and `ToolManagementInterface` must be
|
|
71
|
+
imported from `@context-action/tool-protocol`.
|
|
72
|
+
|
|
56
73
|
## ๐ Vanilla JavaScript Support
|
|
57
74
|
|
|
58
75
|
**@context-action/core works perfectly with vanilla JavaScript!** No React, Vue, or any framework required.
|
package/dist/index.cjs
CHANGED
|
@@ -105,7 +105,6 @@ async function executeSequential(context, createController) {
|
|
|
105
105
|
}
|
|
106
106
|
i = jumpIndex;
|
|
107
107
|
context.jumpToPriority = void 0;
|
|
108
|
-
continue;
|
|
109
108
|
} else {
|
|
110
109
|
context.jumpToPriority = void 0;
|
|
111
110
|
i++;
|
|
@@ -986,55 +985,6 @@ function isActionRegisterDestroyedError(error) {
|
|
|
986
985
|
|
|
987
986
|
//#endregion
|
|
988
987
|
//#region src/ActionRegister.ts
|
|
989
|
-
const dispatchOptionKeys = /* @__PURE__ */ new Set([
|
|
990
|
-
"autoAbort",
|
|
991
|
-
"debounce",
|
|
992
|
-
"executionMode",
|
|
993
|
-
"filter",
|
|
994
|
-
"immediate",
|
|
995
|
-
"queuePriority",
|
|
996
|
-
"result",
|
|
997
|
-
"retryOnError",
|
|
998
|
-
"signal",
|
|
999
|
-
"throttle",
|
|
1000
|
-
"timeout"
|
|
1001
|
-
]);
|
|
1002
|
-
function isRecord(value) {
|
|
1003
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
1004
|
-
}
|
|
1005
|
-
function isOptionalNumber(value) {
|
|
1006
|
-
return value === void 0 || typeof value === "number";
|
|
1007
|
-
}
|
|
1008
|
-
function isOptionalBoolean(value) {
|
|
1009
|
-
return value === void 0 || typeof value === "boolean";
|
|
1010
|
-
}
|
|
1011
|
-
/**
|
|
1012
|
-
* Recognize the deprecated options-first void-action proxy call.
|
|
1013
|
-
*
|
|
1014
|
-
* Every supplied field is validated so ordinary payloads that merely overlap
|
|
1015
|
-
* one option name are not silently reinterpreted as dispatch options.
|
|
1016
|
-
*/
|
|
1017
|
-
function isDispatchOptions(value) {
|
|
1018
|
-
if (!isRecord(value)) return false;
|
|
1019
|
-
const keys = Object.keys(value);
|
|
1020
|
-
if (keys.length === 0 || keys.some((key) => !dispatchOptionKeys.has(key))) return false;
|
|
1021
|
-
return keys.every((key) => {
|
|
1022
|
-
const optionValue = value[key];
|
|
1023
|
-
switch (key) {
|
|
1024
|
-
case "debounce":
|
|
1025
|
-
case "queuePriority":
|
|
1026
|
-
case "throttle":
|
|
1027
|
-
case "timeout": return isOptionalNumber(optionValue);
|
|
1028
|
-
case "immediate": return isOptionalBoolean(optionValue);
|
|
1029
|
-
case "executionMode": return optionValue === void 0 || optionValue === "sequential" || optionValue === "parallel" || optionValue === "race";
|
|
1030
|
-
case "signal": return optionValue === void 0 || isRecord(optionValue) && typeof optionValue.aborted === "boolean" && typeof optionValue.addEventListener === "function";
|
|
1031
|
-
case "retryOnError": return optionValue === void 0 || isRecord(optionValue) && typeof optionValue.maxAttempts === "number" && typeof optionValue.delay === "number";
|
|
1032
|
-
case "autoAbort": return optionValue === void 0 || isRecord(optionValue) && typeof optionValue.enabled === "boolean" && isOptionalBoolean(optionValue.allowHandlerAbort) && (optionValue.onControllerCreated === void 0 || typeof optionValue.onControllerCreated === "function");
|
|
1033
|
-
case "filter": return optionValue === void 0 || isRecord(optionValue) && (optionValue.handlerIds === void 0 || Array.isArray(optionValue.handlerIds) && optionValue.handlerIds.every((item) => typeof item === "string")) && (optionValue.excludeHandlerIds === void 0 || Array.isArray(optionValue.excludeHandlerIds) && optionValue.excludeHandlerIds.every((item) => typeof item === "string")) && (optionValue.priority === void 0 || isRecord(optionValue.priority)) && (optionValue.custom === void 0 || typeof optionValue.custom === "function");
|
|
1034
|
-
case "result": return optionValue === void 0 || isRecord(optionValue) && (optionValue.strategy === void 0 || optionValue.strategy === "first" || optionValue.strategy === "last" || optionValue.strategy === "all" || optionValue.strategy === "merge" || optionValue.strategy === "custom") && (optionValue.merger === void 0 || typeof optionValue.merger === "function") && isOptionalBoolean(optionValue.collect) && isOptionalNumber(optionValue.maxResults) && isOptionalBoolean(optionValue.includeErrors);
|
|
1035
|
-
}
|
|
1036
|
-
});
|
|
1037
|
-
}
|
|
1038
988
|
/**
|
|
1039
989
|
* Action Register for managing action handlers with priority-based execution
|
|
1040
990
|
*
|
|
@@ -1057,10 +1007,8 @@ var ActionRegister = class {
|
|
|
1057
1007
|
this.actionExecutionModes = /* @__PURE__ */ new Map();
|
|
1058
1008
|
this.unregisterFunctions = /* @__PURE__ */ new Map();
|
|
1059
1009
|
this.lastRegisteredTimestamps = /* @__PURE__ */ new Map();
|
|
1060
|
-
this.filterCacheDisabled = true;
|
|
1061
1010
|
this.handlerIdCounter = 0;
|
|
1062
1011
|
this.controllerPool = [];
|
|
1063
|
-
this.maxControllerPoolSize = 10;
|
|
1064
1012
|
this.lifecycleState = "active";
|
|
1065
1013
|
this.lifecycleController = new AbortController();
|
|
1066
1014
|
this.activeDispatches = /* @__PURE__ */ new Set();
|
|
@@ -1098,7 +1046,6 @@ var ActionRegister = class {
|
|
|
1098
1046
|
* // Function-based dispatching
|
|
1099
1047
|
* await registry.actions.userLogin({ userId: '123', email: 'test@example.com' });
|
|
1100
1048
|
* await registry.actions.resetApp();
|
|
1101
|
-
* await registry.actions.resetApp({ debounce: 100 }); // Legacy options-first form
|
|
1102
1049
|
* await registry.actions.resetApp(undefined, { debounce: 100 });
|
|
1103
1050
|
* ```
|
|
1104
1051
|
*
|
|
@@ -1107,9 +1054,8 @@ var ActionRegister = class {
|
|
|
1107
1054
|
get actions() {
|
|
1108
1055
|
if (!this._actionsProxy) this._actionsProxy = new Proxy({}, { get: (_target, prop) => {
|
|
1109
1056
|
const actionKey = prop;
|
|
1110
|
-
if (typeof prop === "string" && this.pipelines.has(actionKey)) return (
|
|
1111
|
-
|
|
1112
|
-
return this.dispatch(actionKey, payloadOrOptions, options);
|
|
1057
|
+
if (typeof prop === "string" && this.pipelines.has(actionKey)) return (payload, options) => {
|
|
1058
|
+
return this.dispatch(actionKey, payload, options);
|
|
1113
1059
|
};
|
|
1114
1060
|
} });
|
|
1115
1061
|
return this._actionsProxy;
|
|
@@ -1144,9 +1090,8 @@ var ActionRegister = class {
|
|
|
1144
1090
|
get actionsWithResult() {
|
|
1145
1091
|
if (!this._actionsWithResultProxy) this._actionsWithResultProxy = new Proxy({}, { get: (_target, prop) => {
|
|
1146
1092
|
const actionKey = prop;
|
|
1147
|
-
if (typeof prop === "string" && this.pipelines.has(actionKey)) return (
|
|
1148
|
-
|
|
1149
|
-
return this.dispatchWithResult(actionKey, payloadOrOptions, options);
|
|
1093
|
+
if (typeof prop === "string" && this.pipelines.has(actionKey)) return (payload, options) => {
|
|
1094
|
+
return this.dispatchWithResult(actionKey, payload, options);
|
|
1150
1095
|
};
|
|
1151
1096
|
} });
|
|
1152
1097
|
return this._actionsWithResultProxy;
|
|
@@ -1279,7 +1224,7 @@ var ActionRegister = class {
|
|
|
1279
1224
|
const existing = pipeline[existingIndex];
|
|
1280
1225
|
const existingUnregister = this.unregisterFunctions.get(handlerId);
|
|
1281
1226
|
if (registration.config.replaceExisting) {
|
|
1282
|
-
if (existing
|
|
1227
|
+
if (existing?.config.cleanup && typeof existing.config.cleanup === "function") try {
|
|
1283
1228
|
existing.config.cleanup();
|
|
1284
1229
|
} catch (cleanupError) {
|
|
1285
1230
|
this.log(`Cleanup error for replaced handler: ${String(action)}`, cleanupError, "warn");
|
|
@@ -1950,21 +1895,6 @@ var ActionRegister = class {
|
|
|
1950
1895
|
return null;
|
|
1951
1896
|
}
|
|
1952
1897
|
/**
|
|
1953
|
-
* ๐ง Generate optimized cache key for filter options
|
|
1954
|
-
*/
|
|
1955
|
-
generateFilterCacheKey(filterOptions) {
|
|
1956
|
-
if (!filterOptions) return "no-filter";
|
|
1957
|
-
const parts = [];
|
|
1958
|
-
if (filterOptions.handlerIds?.length) parts.push(`h:${filterOptions.handlerIds.slice().sort().join(",")}`);
|
|
1959
|
-
if (filterOptions.excludeHandlerIds?.length) parts.push(`e:${filterOptions.excludeHandlerIds.slice().sort().join(",")}`);
|
|
1960
|
-
if (filterOptions.priority) {
|
|
1961
|
-
const { min, max } = filterOptions.priority;
|
|
1962
|
-
if (min !== void 0 || max !== void 0) parts.push(`p:${min ?? "*"}-${max ?? "*"}`);
|
|
1963
|
-
}
|
|
1964
|
-
if (filterOptions.custom) return "custom-" + Date.now() + Math.random();
|
|
1965
|
-
return parts.length > 0 ? parts.join("|") : "no-filter";
|
|
1966
|
-
}
|
|
1967
|
-
/**
|
|
1968
1898
|
* ๐ง Create or reuse PipelineController from pool for better performance
|
|
1969
1899
|
*/
|
|
1970
1900
|
getControllerFromPool(context, autoAbortController, autoAbortOptions) {
|
|
@@ -2004,12 +1934,6 @@ var ActionRegister = class {
|
|
|
2004
1934
|
};
|
|
2005
1935
|
return controller;
|
|
2006
1936
|
}
|
|
2007
|
-
/**
|
|
2008
|
-
* ๐ง Return controller to pool for reuse
|
|
2009
|
-
*/
|
|
2010
|
-
returnControllerToPool(controller) {
|
|
2011
|
-
if (this.controllerPool.length < this.maxControllerPoolSize) this.controllerPool.push(controller);
|
|
2012
|
-
}
|
|
2013
1937
|
filterHandlers(handlers, filterOptions) {
|
|
2014
1938
|
if (!filterOptions) return handlers;
|
|
2015
1939
|
const handlerIdSet = filterOptions.handlerIds ? new Set(filterOptions.handlerIds) : null;
|
|
@@ -2017,7 +1941,7 @@ var ActionRegister = class {
|
|
|
2017
1941
|
return handlers.filter((registration) => {
|
|
2018
1942
|
const config = registration.config;
|
|
2019
1943
|
if (handlerIdSet && !handlerIdSet.has(config.id)) return false;
|
|
2020
|
-
if (excludeIdSet
|
|
1944
|
+
if (excludeIdSet?.has(config.id)) return false;
|
|
2021
1945
|
if (filterOptions.priority) {
|
|
2022
1946
|
const priority = config.priority;
|
|
2023
1947
|
if (filterOptions.priority.min !== void 0 && priority < filterOptions.priority.min) return false;
|
|
@@ -2300,7 +2224,7 @@ var ActionRegister = class {
|
|
|
2300
2224
|
removeRegistration(action, registration, runCleanup = true) {
|
|
2301
2225
|
const pipeline = this.pipelines.get(action);
|
|
2302
2226
|
if (!pipeline) return false;
|
|
2303
|
-
const index = pipeline.
|
|
2227
|
+
const index = pipeline.indexOf(registration);
|
|
2304
2228
|
if (index === -1) return false;
|
|
2305
2229
|
pipeline.splice(index, 1);
|
|
2306
2230
|
this.unregisterFunctions.delete(registration.id);
|
|
@@ -2411,359 +2335,15 @@ var ActionRegister = class {
|
|
|
2411
2335
|
}
|
|
2412
2336
|
};
|
|
2413
2337
|
|
|
2414
|
-
//#endregion
|
|
2415
|
-
//#region src/react-helpers.ts
|
|
2416
|
-
/**
|
|
2417
|
-
* ๐ง Create action handler registration configuration for React components
|
|
2418
|
-
*
|
|
2419
|
-
* Creates a configuration object that can be used with React's useEffect to properly
|
|
2420
|
-
* register and unregister action handlers with lifecycle management and cleanup.
|
|
2421
|
-
* This is NOT a hook - it's a factory function for React hook integration.
|
|
2422
|
-
*
|
|
2423
|
-
* @template T - ActionPayloadMap type
|
|
2424
|
-
* @template K - Action key type
|
|
2425
|
-
*
|
|
2426
|
-
* @param registry - ActionRegister instance
|
|
2427
|
-
* @param action - Action name to register handler for
|
|
2428
|
-
* @param handler - Handler function (should be memoized with useCallback)
|
|
2429
|
-
* @param config - Handler configuration
|
|
2430
|
-
*
|
|
2431
|
-
* @returns Configuration object with register/unregister functions
|
|
2432
|
-
*
|
|
2433
|
-
* @example Basic Usage with useEffect
|
|
2434
|
-
* ```tsx
|
|
2435
|
-
* import { useCallback, useEffect } from 'react';
|
|
2436
|
-
* import { createActionHandler } from '@context-action/core/react-helpers';
|
|
2437
|
-
*
|
|
2438
|
-
* function MyComponent() {
|
|
2439
|
-
* const registry = useActionRegister();
|
|
2440
|
-
*
|
|
2441
|
-
* const handleUserUpdate = useCallback(async (payload, controller) => {
|
|
2442
|
-
* // Handler logic here
|
|
2443
|
-
* }, []);
|
|
2444
|
-
*
|
|
2445
|
-
* useEffect(() => {
|
|
2446
|
-
* const { register, unregister } = createActionHandler(
|
|
2447
|
-
* registry,
|
|
2448
|
-
* 'updateUser',
|
|
2449
|
-
* handleUserUpdate,
|
|
2450
|
-
* { priority: 10 }
|
|
2451
|
-
* );
|
|
2452
|
-
*
|
|
2453
|
-
* const cleanup = register();
|
|
2454
|
-
* return () => {
|
|
2455
|
-
* cleanup();
|
|
2456
|
-
* unregister();
|
|
2457
|
-
* };
|
|
2458
|
-
* }, [registry, handleUserUpdate]);
|
|
2459
|
-
* }
|
|
2460
|
-
* ```
|
|
2461
|
-
*
|
|
2462
|
-
* @example With Automatic Cleanup
|
|
2463
|
-
* ```tsx
|
|
2464
|
-
* const [userId, setUserId] = useState('123');
|
|
2465
|
-
*
|
|
2466
|
-
* const handleUserUpdate = useCallback(async (payload, controller) => {
|
|
2467
|
-
* console.log('Updating user:', userId, payload);
|
|
2468
|
-
* }, [userId]);
|
|
2469
|
-
*
|
|
2470
|
-
* useEffect(() => {
|
|
2471
|
-
* const handlerManager = createActionHandler(
|
|
2472
|
-
* registry,
|
|
2473
|
-
* 'updateUser',
|
|
2474
|
-
* handleUserUpdate,
|
|
2475
|
-
* { priority: 10 }
|
|
2476
|
-
* );
|
|
2477
|
-
*
|
|
2478
|
-
* // Simplified registration with automatic cleanup
|
|
2479
|
-
* return handlerManager.registerWithCleanup();
|
|
2480
|
-
* }, [registry, handleUserUpdate, userId]);
|
|
2481
|
-
* ```
|
|
2482
|
-
*
|
|
2483
|
-
* @public
|
|
2484
|
-
*/
|
|
2485
|
-
function createActionHandler(registry, action, handler, config) {
|
|
2486
|
-
const timestamp = Date.now();
|
|
2487
|
-
const random = Math.random().toString(36).substr(2, 5);
|
|
2488
|
-
const finalConfig = {
|
|
2489
|
-
priority: config?.priority ?? 0,
|
|
2490
|
-
id: config?.id || `react_${String(action)}_${timestamp}_${random}`,
|
|
2491
|
-
blocking: config?.blocking ?? false,
|
|
2492
|
-
once: config?.once ?? false,
|
|
2493
|
-
debounce: config?.debounce ?? void 0,
|
|
2494
|
-
throttle: config?.throttle ?? void 0,
|
|
2495
|
-
replaceExisting: true
|
|
2496
|
-
};
|
|
2497
|
-
let currentUnregister;
|
|
2498
|
-
let isRegistered = false;
|
|
2499
|
-
return {
|
|
2500
|
-
/**
|
|
2501
|
-
* Register the handler and return cleanup function
|
|
2502
|
-
*/
|
|
2503
|
-
register() {
|
|
2504
|
-
if (isRegistered && currentUnregister) currentUnregister();
|
|
2505
|
-
currentUnregister = registry.register(action, handler, finalConfig);
|
|
2506
|
-
isRegistered = true;
|
|
2507
|
-
return currentUnregister;
|
|
2508
|
-
},
|
|
2509
|
-
/**
|
|
2510
|
-
* Unregister the handler if currently registered
|
|
2511
|
-
*/
|
|
2512
|
-
unregister() {
|
|
2513
|
-
if (isRegistered && currentUnregister) {
|
|
2514
|
-
currentUnregister();
|
|
2515
|
-
currentUnregister = void 0;
|
|
2516
|
-
isRegistered = false;
|
|
2517
|
-
}
|
|
2518
|
-
},
|
|
2519
|
-
/**
|
|
2520
|
-
* Register and return cleanup function (React useEffect pattern)
|
|
2521
|
-
*/
|
|
2522
|
-
registerWithCleanup() {
|
|
2523
|
-
const unregisterFn = this.register();
|
|
2524
|
-
return () => {
|
|
2525
|
-
unregisterFn();
|
|
2526
|
-
this.unregister();
|
|
2527
|
-
};
|
|
2528
|
-
},
|
|
2529
|
-
config: finalConfig
|
|
2530
|
-
};
|
|
2531
|
-
}
|
|
2532
|
-
/**
|
|
2533
|
-
* ๐ React development utilities
|
|
2534
|
-
*
|
|
2535
|
-
* Provides debugging and development helpers specifically for React environments.
|
|
2536
|
-
*/
|
|
2537
|
-
const ReactDevUtils = {
|
|
2538
|
-
/**
|
|
2539
|
-
* Enable detailed React integration debugging
|
|
2540
|
-
*/
|
|
2541
|
-
enableDebugMode() {
|
|
2542
|
-
if (typeof window !== "undefined") window.__CONTEXT_ACTION_REACT_DEBUG__ = true;
|
|
2543
|
-
},
|
|
2544
|
-
/**
|
|
2545
|
-
* Disable React integration debugging
|
|
2546
|
-
*/
|
|
2547
|
-
disableDebugMode() {
|
|
2548
|
-
if (typeof window !== "undefined") window.__CONTEXT_ACTION_REACT_DEBUG__ = false;
|
|
2549
|
-
},
|
|
2550
|
-
/**
|
|
2551
|
-
* Check if React debug mode is enabled
|
|
2552
|
-
*/
|
|
2553
|
-
isDebugMode() {
|
|
2554
|
-
return typeof window !== "undefined" && Boolean(window.__CONTEXT_ACTION_REACT_DEBUG__);
|
|
2555
|
-
},
|
|
2556
|
-
/**
|
|
2557
|
-
* Log React-specific debugging information
|
|
2558
|
-
*/
|
|
2559
|
-
log(component, action, message, data) {
|
|
2560
|
-
if (this.isDebugMode()) console.log(`๐ฏ [React-ActionRegister] [${component}] ${action}: ${message}`, data || "");
|
|
2561
|
-
},
|
|
2562
|
-
/**
|
|
2563
|
-
* Get React integration statistics
|
|
2564
|
-
*/
|
|
2565
|
-
getStats(registry) {
|
|
2566
|
-
const registryInfo = registry.getRegistryInfo();
|
|
2567
|
-
let reactHandlers = 0;
|
|
2568
|
-
registry.getRegisteredActions().forEach((action) => {
|
|
2569
|
-
const stats = registry.getActionStats(action);
|
|
2570
|
-
if (stats) stats.handlersByPriority.forEach((priorityGroup) => {
|
|
2571
|
-
priorityGroup.handlers.forEach((handler) => {
|
|
2572
|
-
if (handler.id.includes("react")) reactHandlers++;
|
|
2573
|
-
});
|
|
2574
|
-
});
|
|
2575
|
-
});
|
|
2576
|
-
return {
|
|
2577
|
-
totalHandlers: registryInfo.totalHandlers,
|
|
2578
|
-
reactHandlers,
|
|
2579
|
-
registryInfo
|
|
2580
|
-
};
|
|
2581
|
-
}
|
|
2582
|
-
};
|
|
2583
|
-
/**
|
|
2584
|
-
* ๐ React Error Boundary integration
|
|
2585
|
-
*
|
|
2586
|
-
* Utilities for integrating ActionRegister errors with React Error Boundaries.
|
|
2587
|
-
*/
|
|
2588
|
-
var ReactActionError = class ReactActionError extends Error {
|
|
2589
|
-
constructor(message, action, payload, handlerId = void 0, originalError) {
|
|
2590
|
-
super(message);
|
|
2591
|
-
this.name = "ReactActionError";
|
|
2592
|
-
this.action = action;
|
|
2593
|
-
this.payload = payload;
|
|
2594
|
-
this.handlerId = handlerId;
|
|
2595
|
-
this.timestamp = Date.now();
|
|
2596
|
-
if (originalError && originalError.stack) this.stack = originalError.stack;
|
|
2597
|
-
}
|
|
2598
|
-
/**
|
|
2599
|
-
* Create a React Error Boundary compatible error
|
|
2600
|
-
*/
|
|
2601
|
-
static fromActionError(originalError, action, payload, handlerId) {
|
|
2602
|
-
return new ReactActionError(`Action '${action}' failed: ${originalError.message}`, action, payload, handlerId, originalError);
|
|
2603
|
-
}
|
|
2604
|
-
};
|
|
2605
|
-
/**
|
|
2606
|
-
* ๐ Type guard for React Action Errors
|
|
2607
|
-
*
|
|
2608
|
-
* @param error - Error to check
|
|
2609
|
-
* @returns True if error is a ReactActionError
|
|
2610
|
-
*/
|
|
2611
|
-
function isReactActionError(error) {
|
|
2612
|
-
return error instanceof ReactActionError;
|
|
2613
|
-
}
|
|
2614
|
-
|
|
2615
|
-
//#endregion
|
|
2616
|
-
//#region src/action-schema.ts
|
|
2617
|
-
/**
|
|
2618
|
-
* Zod ์คํค๋ง๋ฅผ JSON Schema๋ก ๋ณํ (Zod 4 ๋ค์ดํฐ๋ธ API)
|
|
2619
|
-
*
|
|
2620
|
-
* @param schema - Zod ์คํค๋ง
|
|
2621
|
-
* @returns JSON Schema (draft-7)
|
|
2622
|
-
*/
|
|
2623
|
-
function zodToJsonSchema(schema, zodModule) {
|
|
2624
|
-
return zodModule.toJSONSchema(schema, {
|
|
2625
|
-
target: "draft-7",
|
|
2626
|
-
metadata: zodModule.globalRegistry
|
|
2627
|
-
});
|
|
2628
|
-
}
|
|
2629
|
-
/**
|
|
2630
|
-
* Zod ์คํค๋ง ๊ธฐ๋ฐ Action ์ ์
|
|
2631
|
-
*
|
|
2632
|
-
* defineTool ํจํด์ ๊ธฐ๋ฐ์ผ๋ก context-action์ ๋ง๊ฒ ๊ตฌํ:
|
|
2633
|
-
* - Single Source of Truth: Zod ์คํค๋ง๋ก ํ์
+ ๊ฒ์ฆ + ๋ฉํ๋ฐ์ดํฐ ํตํฉ
|
|
2634
|
-
* - ๋ฐํ์ ๊ฒ์ฆ: validate(), safeParse()
|
|
2635
|
-
* - Tool Chain ํธํ: toMCP(), toOpenAI(), toAnthropic()
|
|
2636
|
-
*
|
|
2637
|
-
* @param options - Action ์ ์ ์ต์
|
|
2638
|
-
* @param zodModule - Zod ๋ชจ๋ (peerDependency๋ก ์ฃผ์
)
|
|
2639
|
-
* @returns UnifiedAction ์ธ์คํด์ค
|
|
2640
|
-
*
|
|
2641
|
-
* @example
|
|
2642
|
-
* ```typescript
|
|
2643
|
-
* import { z } from 'zod';
|
|
2644
|
-
* import { defineAction } from '@context-action/core';
|
|
2645
|
-
*
|
|
2646
|
-
* const updateUserAction = defineAction({
|
|
2647
|
-
* name: 'updateUser',
|
|
2648
|
-
* description: 'Update user profile',
|
|
2649
|
-
* parameters: z.object({
|
|
2650
|
-
* id: z.string().min(1).meta({ description: 'User ID' }),
|
|
2651
|
-
* name: z.string().min(2).max(50).meta({ description: 'User name' }),
|
|
2652
|
-
* email: z.string().email().optional(),
|
|
2653
|
-
* }),
|
|
2654
|
-
* }, z);
|
|
2655
|
-
*
|
|
2656
|
-
* // ๊ฒ์ฆ
|
|
2657
|
-
* const validated = updateUserAction.validate({ id: '123', name: 'John' });
|
|
2658
|
-
*
|
|
2659
|
-
* // Tool chain ๋ณํ
|
|
2660
|
-
* const mcpTool = updateUserAction.toMCP();
|
|
2661
|
-
* ```
|
|
2662
|
-
*/
|
|
2663
|
-
function defineAction(options, zodModule) {
|
|
2664
|
-
const { name, description, parameters } = options;
|
|
2665
|
-
const jsonSchema = zodToJsonSchema(parameters, zodModule);
|
|
2666
|
-
return {
|
|
2667
|
-
name,
|
|
2668
|
-
description,
|
|
2669
|
-
zodSchema: parameters,
|
|
2670
|
-
jsonSchema,
|
|
2671
|
-
validate: (payload) => {
|
|
2672
|
-
return parameters.parse(payload);
|
|
2673
|
-
},
|
|
2674
|
-
safeParse: (payload) => {
|
|
2675
|
-
return parameters.safeParse(payload);
|
|
2676
|
-
},
|
|
2677
|
-
toJSONSchema: () => jsonSchema,
|
|
2678
|
-
toMCP: () => ({
|
|
2679
|
-
name,
|
|
2680
|
-
description,
|
|
2681
|
-
inputSchema: jsonSchema
|
|
2682
|
-
}),
|
|
2683
|
-
toOpenAI: () => ({
|
|
2684
|
-
type: "function",
|
|
2685
|
-
function: {
|
|
2686
|
-
name,
|
|
2687
|
-
description,
|
|
2688
|
-
parameters: {
|
|
2689
|
-
type: "object",
|
|
2690
|
-
properties: jsonSchema.properties ?? {},
|
|
2691
|
-
required: jsonSchema.required
|
|
2692
|
-
}
|
|
2693
|
-
}
|
|
2694
|
-
}),
|
|
2695
|
-
toAnthropic: () => ({
|
|
2696
|
-
name,
|
|
2697
|
-
description,
|
|
2698
|
-
input_schema: jsonSchema
|
|
2699
|
-
})
|
|
2700
|
-
};
|
|
2701
|
-
}
|
|
2702
|
-
/**
|
|
2703
|
-
* ๋ค์ค Action ์คํค๋ง ์์ฑ
|
|
2704
|
-
*
|
|
2705
|
-
* ์ฌ๋ฌ defineAction์ ๋ฌถ์ด์ ActionSchemaMap ์์ฑ
|
|
2706
|
-
*
|
|
2707
|
-
* @param actions - UnifiedAction ๋งต
|
|
2708
|
-
* @returns ActionSchemaMap
|
|
2709
|
-
*
|
|
2710
|
-
* @example
|
|
2711
|
-
* ```typescript
|
|
2712
|
-
* const userActionSchema = createActionSchema({
|
|
2713
|
-
* updateUser: defineAction({ ... }, z),
|
|
2714
|
-
* deleteUser: defineAction({ ... }, z),
|
|
2715
|
-
* });
|
|
2716
|
-
*
|
|
2717
|
-
* type UserActions = InferActionPayloadMap<typeof userActionSchema>;
|
|
2718
|
-
* ```
|
|
2719
|
-
*/
|
|
2720
|
-
function createActionSchema(actions) {
|
|
2721
|
-
return actions;
|
|
2722
|
-
}
|
|
2723
|
-
/**
|
|
2724
|
-
* Zod ๋ชจ๋์ ๋ฐ์ธ๋ฉํ defineAction ํฉํ ๋ฆฌ ์์ฑ
|
|
2725
|
-
*
|
|
2726
|
-
* ๋งค๋ฒ z ๋ชจ๋์ ์ ๋ฌํ์ง ์์๋ ๋๋๋ก ํฉํ ๋ฆฌ ํจํด ์ ๊ณต
|
|
2727
|
-
*
|
|
2728
|
-
* @param zodModule - Zod ๋ชจ๋
|
|
2729
|
-
* @returns defineAction ํจ์ (z ๋ฐ์ธ๋ฉ๋จ)
|
|
2730
|
-
*
|
|
2731
|
-
* @example
|
|
2732
|
-
* ```typescript
|
|
2733
|
-
* import { z } from 'zod';
|
|
2734
|
-
* import { createActionFactory } from '@context-action/core';
|
|
2735
|
-
*
|
|
2736
|
-
* const defineAction = createActionFactory(z);
|
|
2737
|
-
*
|
|
2738
|
-
* const updateUser = defineAction({
|
|
2739
|
-
* name: 'updateUser',
|
|
2740
|
-
* parameters: z.object({ id: z.string() }),
|
|
2741
|
-
* });
|
|
2742
|
-
* ```
|
|
2743
|
-
*/
|
|
2744
|
-
function createActionFactory(zodModule) {
|
|
2745
|
-
return (options) => {
|
|
2746
|
-
return defineAction(options, zodModule);
|
|
2747
|
-
};
|
|
2748
|
-
}
|
|
2749
|
-
|
|
2750
2338
|
//#endregion
|
|
2751
2339
|
exports.ActionGuard = ActionGuard;
|
|
2752
2340
|
exports.ActionRegister = ActionRegister;
|
|
2753
2341
|
exports.ActionRegisterDestroyedError = ActionRegisterDestroyedError;
|
|
2754
2342
|
exports.ActionTimeoutError = ActionTimeoutError;
|
|
2755
2343
|
exports.ActionValidationError = ActionValidationError;
|
|
2756
|
-
exports.ReactActionError = ReactActionError;
|
|
2757
|
-
exports.ReactDevUtils = ReactDevUtils;
|
|
2758
|
-
exports.createActionFactory = createActionFactory;
|
|
2759
|
-
exports.createActionHandler = createActionHandler;
|
|
2760
|
-
exports.createActionSchema = createActionSchema;
|
|
2761
|
-
exports.defineAction = defineAction;
|
|
2762
2344
|
exports.executeParallel = executeParallel;
|
|
2763
2345
|
exports.executeRace = executeRace;
|
|
2764
2346
|
exports.executeSequential = executeSequential;
|
|
2765
2347
|
exports.isActionRegisterDestroyedError = isActionRegisterDestroyedError;
|
|
2766
2348
|
exports.isActionTimeoutError = isActionTimeoutError;
|
|
2767
|
-
exports.isActionValidationError = isActionValidationError;
|
|
2768
|
-
exports.isReactActionError = isReactActionError;
|
|
2769
|
-
exports.zodToJsonSchema = zodToJsonSchema;
|
|
2349
|
+
exports.isActionValidationError = isActionValidationError;
|