@turingpulse/sdk 1.0.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/.github/dependabot.yml +38 -0
- package/.github/workflows/ci.yml +246 -0
- package/.github/workflows/framework-compat.yml +169 -0
- package/.github/workflows/security.yml +336 -0
- package/CHANGELOG.md +29 -0
- package/LICENSE +13 -0
- package/MIGRATION.md +30 -0
- package/README.md +221 -0
- package/dist/attachments.d.ts +28 -0
- package/dist/attachments.d.ts.map +1 -0
- package/dist/attachments.js +59 -0
- package/dist/attachments.js.map +1 -0
- package/dist/config.d.ts +72 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +78 -0
- package/dist/config.js.map +1 -0
- package/dist/context.d.ts +126 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +163 -0
- package/dist/context.js.map +1 -0
- package/dist/decorators.d.ts +6 -0
- package/dist/decorators.d.ts.map +1 -0
- package/dist/decorators.js +52 -0
- package/dist/decorators.js.map +1 -0
- package/dist/deploy.d.ts +89 -0
- package/dist/deploy.d.ts.map +1 -0
- package/dist/deploy.js +203 -0
- package/dist/deploy.js.map +1 -0
- package/dist/errors.d.ts +18 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +34 -0
- package/dist/errors.js.map +1 -0
- package/dist/eventBuilder.d.ts +21 -0
- package/dist/eventBuilder.d.ts.map +1 -0
- package/dist/eventBuilder.js +127 -0
- package/dist/eventBuilder.js.map +1 -0
- package/dist/fingerprint.d.ts +158 -0
- package/dist/fingerprint.d.ts.map +1 -0
- package/dist/fingerprint.js +339 -0
- package/dist/fingerprint.js.map +1 -0
- package/dist/governance.d.ts +47 -0
- package/dist/governance.d.ts.map +1 -0
- package/dist/governance.js +104 -0
- package/dist/governance.js.map +1 -0
- package/dist/http.d.ts +62 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +181 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/instrumentation.d.ts +40 -0
- package/dist/instrumentation.d.ts.map +1 -0
- package/dist/instrumentation.js +31 -0
- package/dist/instrumentation.js.map +1 -0
- package/dist/integrations/mastra.d.ts +64 -0
- package/dist/integrations/mastra.d.ts.map +1 -0
- package/dist/integrations/mastra.js +256 -0
- package/dist/integrations/mastra.js.map +1 -0
- package/dist/kpi.d.ts +21 -0
- package/dist/kpi.d.ts.map +1 -0
- package/dist/kpi.js +83 -0
- package/dist/kpi.js.map +1 -0
- package/dist/llmDetector.d.ts +22 -0
- package/dist/llmDetector.d.ts.map +1 -0
- package/dist/llmDetector.js +269 -0
- package/dist/llmDetector.js.map +1 -0
- package/dist/plugin.d.ts +33 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +312 -0
- package/dist/plugin.js.map +1 -0
- package/dist/registry.d.ts +13 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +18 -0
- package/dist/registry.js.map +1 -0
- package/dist/tracing.d.ts +10 -0
- package/dist/tracing.d.ts.map +1 -0
- package/dist/tracing.js +30 -0
- package/dist/tracing.js.map +1 -0
- package/dist/triggerState.d.ts +5 -0
- package/dist/triggerState.d.ts.map +1 -0
- package/dist/triggerState.js +19 -0
- package/dist/triggerState.js.map +1 -0
- package/dist/utils.d.ts +27 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +72 -0
- package/dist/utils.js.map +1 -0
- package/package.json +37 -0
- package/packages/anthropic/package.json +16 -0
- package/packages/anthropic/src/index.ts +5 -0
- package/packages/anthropic/src/wrapper.ts +102 -0
- package/packages/anthropic/tsconfig.build.json +20 -0
- package/packages/langchain/package.json +16 -0
- package/packages/langchain/src/index.ts +7 -0
- package/packages/langchain/src/wrapper.ts +51 -0
- package/packages/mastra/package.json +17 -0
- package/packages/mastra/src/index.ts +8 -0
- package/packages/mastra/src/wrapper.ts +301 -0
- package/packages/openai/package.json +16 -0
- package/packages/openai/src/index.ts +8 -0
- package/packages/openai/src/wrapper.ts +103 -0
- package/packages/openai/tsconfig.build.json +20 -0
- package/packages/openclaw/openclaw.plugin.json +100 -0
- package/packages/openclaw/package.json +41 -0
- package/packages/openclaw/src/buffer.ts +99 -0
- package/packages/openclaw/src/config.ts +139 -0
- package/packages/openclaw/src/hooks/governance.ts +267 -0
- package/packages/openclaw/src/hooks/lifecycle.ts +75 -0
- package/packages/openclaw/src/hooks/telemetry.ts +207 -0
- package/packages/openclaw/src/index.ts +91 -0
- package/packages/openclaw/src/mapper.ts +233 -0
- package/packages/openclaw/src/session-tracker.ts +181 -0
- package/packages/openclaw/src/types.ts +220 -0
- package/packages/openclaw/tests/buffer.test.ts +148 -0
- package/packages/openclaw/tests/config.test.ts +122 -0
- package/packages/openclaw/tests/governance.test.ts +232 -0
- package/packages/openclaw/tests/mapper.test.ts +242 -0
- package/packages/openclaw/tests/session-tracker.test.ts +124 -0
- package/packages/openclaw/tsconfig.json +18 -0
- package/packages/openclaw/vitest.config.ts +8 -0
- package/packages/vercel-ai/package.json +16 -0
- package/packages/vercel-ai/src/index.ts +5 -0
- package/packages/vercel-ai/src/wrapper.ts +49 -0
- package/scripts/bump-version.sh +58 -0
- package/scripts/update-readme-compat.mjs +151 -0
- package/src/__tests__/fingerprint.test.ts +328 -0
- package/src/attachments.ts +88 -0
- package/src/config.ts +164 -0
- package/src/context.ts +258 -0
- package/src/decorators.ts +61 -0
- package/src/deploy.ts +260 -0
- package/src/errors.ts +44 -0
- package/src/eventBuilder.ts +153 -0
- package/src/fingerprint.ts +421 -0
- package/src/governance.ts +156 -0
- package/src/http.ts +241 -0
- package/src/index.ts +57 -0
- package/src/instrumentation.ts +68 -0
- package/src/integrations/mastra.ts +335 -0
- package/src/kpi.ts +112 -0
- package/src/llmDetector.ts +330 -0
- package/src/plugin.ts +384 -0
- package/src/registry.ts +27 -0
- package/src/tracing.ts +39 -0
- package/src/triggerState.ts +27 -0
- package/src/utils.ts +78 -0
- package/tests/compat/anthropic.test.ts +61 -0
- package/tests/compat/cohere.test.ts +57 -0
- package/tests/compat/google-genai.test.ts +61 -0
- package/tests/compat/langchain-openai.test.ts +41 -0
- package/tests/compat/langchain.test.ts +64 -0
- package/tests/compat/mistral.test.ts +58 -0
- package/tests/compat/openai.test.ts +71 -0
- package/tests/compat/vercel-ai.test.ts +56 -0
- package/tests/plugins/anthropic-wrapper.test.ts +120 -0
- package/tests/plugins/langchain-wrapper.test.ts +128 -0
- package/tests/plugins/openai-wrapper.test.ts +165 -0
- package/tsconfig.json +21 -0
- package/vitest.config.ts +9 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface TriggerEntry {
|
|
2
|
+
key: string;
|
|
3
|
+
fn: (...args: unknown[]) => unknown;
|
|
4
|
+
description?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare class TriggerRegistry {
|
|
7
|
+
private readonly entries;
|
|
8
|
+
register(key: string, fn: (...args: unknown[]) => unknown, description?: string): void;
|
|
9
|
+
unregister(key: string): void;
|
|
10
|
+
get(key: string): TriggerEntry | undefined;
|
|
11
|
+
list(): TriggerEntry[];
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmC;IAE3D,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI;IAItF,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAI7B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAI1C,IAAI,IAAI,YAAY,EAAE;CAGvB"}
|
package/dist/registry.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export class TriggerRegistry {
|
|
2
|
+
constructor() {
|
|
3
|
+
this.entries = new Map();
|
|
4
|
+
}
|
|
5
|
+
register(key, fn, description) {
|
|
6
|
+
this.entries.set(key, { key, fn, description });
|
|
7
|
+
}
|
|
8
|
+
unregister(key) {
|
|
9
|
+
this.entries.delete(key);
|
|
10
|
+
}
|
|
11
|
+
get(key) {
|
|
12
|
+
return this.entries.get(key);
|
|
13
|
+
}
|
|
14
|
+
list() {
|
|
15
|
+
return Array.from(this.entries.values());
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAMA,MAAM,OAAO,eAAe;IAA5B;QACmB,YAAO,GAAG,IAAI,GAAG,EAAwB,CAAC;IAiB7D,CAAC;IAfC,QAAQ,CAAC,GAAW,EAAE,EAAmC,EAAE,WAAoB;QAC7E,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC;IAClD,CAAC;IAED,UAAU,CAAC,GAAW;QACpB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAED,GAAG,CAAC,GAAW;QACb,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC/B,CAAC;IAED,IAAI;QACF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC3C,CAAC;CACF"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { TuringPulseConfig } from './config';
|
|
2
|
+
type Attributes = Record<string, string>;
|
|
3
|
+
export declare class TracingManager {
|
|
4
|
+
private readonly config;
|
|
5
|
+
private readonly tracer;
|
|
6
|
+
constructor(config: TuringPulseConfig);
|
|
7
|
+
withSpan<T>(name: string, attributes: Attributes, enabled: boolean, fn: () => T): T;
|
|
8
|
+
}
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=tracing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracing.d.ts","sourceRoot":"","sources":["../src/tracing.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAG7C,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEzC,qBAAa,cAAc;IAGb,OAAO,CAAC,QAAQ,CAAC,MAAM;IAFnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;gBAEK,MAAM,EAAE,iBAAiB;IAItD,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC;CAwBpF"}
|
package/dist/tracing.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { trace, SpanStatusCode } from '@opentelemetry/api';
|
|
2
|
+
import { isPromise } from './utils';
|
|
3
|
+
export class TracingManager {
|
|
4
|
+
constructor(config) {
|
|
5
|
+
this.config = config;
|
|
6
|
+
this.tracer = trace.getTracer(config.traceServiceName);
|
|
7
|
+
}
|
|
8
|
+
withSpan(name, attributes, enabled, fn) {
|
|
9
|
+
if (!this.config.traceEnabled || !enabled) {
|
|
10
|
+
return fn();
|
|
11
|
+
}
|
|
12
|
+
return this.tracer.startActiveSpan(name, { attributes }, (span) => {
|
|
13
|
+
try {
|
|
14
|
+
const result = fn();
|
|
15
|
+
if (isPromise(result)) {
|
|
16
|
+
return result.finally(() => span.end());
|
|
17
|
+
}
|
|
18
|
+
span.end();
|
|
19
|
+
return result;
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
span.recordException(error);
|
|
23
|
+
span.setStatus({ code: SpanStatusCode.ERROR });
|
|
24
|
+
span.end();
|
|
25
|
+
throw error;
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=tracing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracing.js","sourceRoot":"","sources":["../src/tracing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAG3D,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAIpC,MAAM,OAAO,cAAc;IAGzB,YAA6B,MAAyB;QAAzB,WAAM,GAAN,MAAM,CAAmB;QACpD,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;IACzD,CAAC;IAED,QAAQ,CAAI,IAAY,EAAE,UAAsB,EAAE,OAAgB,EAAE,EAAW;QAC7E,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,IAAI,CAAC,OAAO,EAAE,CAAC;YAC1C,OAAO,EAAE,EAAE,CAAC;QACd,CAAC;QACD,OAAO,IAAI,CAAC,MAAM,CAAC,eAAe,CAChC,IAAI,EACJ,EAAE,UAAU,EAAE,EACd,CAAC,IAAI,EAAE,EAAE;YACP,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,EAAE,EAAE,CAAC;gBACpB,IAAI,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;oBACtB,OAAO,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAM,CAAC;gBAC/C,CAAC;gBACD,IAAI,CAAC,GAAG,EAAE,CAAC;gBACX,OAAO,MAAM,CAAC;YAChB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,CAAC,eAAe,CAAC,KAAc,CAAC,CAAC;gBACrC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,cAAc,CAAC,KAAK,EAAE,CAAC,CAAC;gBAC/C,IAAI,CAAC,GAAG,EAAE,CAAC;gBACX,MAAM,KAAK,CAAC;YACd,CAAC;QACH,CAAC,CACF,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function queueTrigger(key: string, fn: (...args: unknown[]) => unknown, description?: string): void;
|
|
2
|
+
export declare function flushPending(plugin: {
|
|
3
|
+
registerTrigger: (key: string, fn: (...args: unknown[]) => unknown, description?: string) => string;
|
|
4
|
+
}): void;
|
|
5
|
+
//# sourceMappingURL=triggerState.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"triggerState.d.ts","sourceRoot":"","sources":["../src/triggerState.ts"],"names":[],"mappings":"AAUA,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAEzG;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE;IAAE,eAAe,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,EAAE,WAAW,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;CAAE,GAAG,IAAI,CAYlJ"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { markTriggerRegistered } from './utils';
|
|
2
|
+
const pending = [];
|
|
3
|
+
export function queueTrigger(key, fn, description) {
|
|
4
|
+
pending.push({ key, fn, description });
|
|
5
|
+
}
|
|
6
|
+
export function flushPending(plugin) {
|
|
7
|
+
if (!pending.length) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
while (pending.length) {
|
|
11
|
+
const item = pending.shift();
|
|
12
|
+
if (!item) {
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
plugin.registerTrigger(item.key, item.fn, item.description);
|
|
16
|
+
markTriggerRegistered(item.fn);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=triggerState.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"triggerState.js","sourceRoot":"","sources":["../src/triggerState.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAQhD,MAAM,OAAO,GAAqB,EAAE,CAAC;AAErC,MAAM,UAAU,YAAY,CAAC,GAAW,EAAE,EAAmC,EAAE,WAAoB;IACjG,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAA+G;IAC1I,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QACpB,OAAO;IACT,CAAC;IACD,OAAO,OAAO,CAAC,MAAM,EAAE,CAAC;QACtB,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;QAC7B,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,SAAS;QACX,CAAC;QACD,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QAC5D,qBAAqB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjC,CAAC;AACH,CAAC"}
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert a camelCase string to snake_case.
|
|
3
|
+
* e.g. "runId" → "run_id", "durationMs" → "duration_ms"
|
|
4
|
+
*/
|
|
5
|
+
export declare function toSnake(s: string): string;
|
|
6
|
+
/** Type guard for thenables (Promises). Shared by plugin and tracing. */
|
|
7
|
+
export declare function isPromise<T>(value: T | Promise<T>): value is Promise<T>;
|
|
8
|
+
/** Type guard for async iterables (streaming responses). */
|
|
9
|
+
export declare function isAsyncIterable(value: unknown): value is AsyncIterable<unknown>;
|
|
10
|
+
/** Safe access to process.env — returns undefined in browser environments. */
|
|
11
|
+
export declare function safeEnv(key: string): string | undefined;
|
|
12
|
+
/** Keys that must never be assigned as own properties to prevent prototype pollution. */
|
|
13
|
+
export declare const FORBIDDEN_KEYS: Set<string>;
|
|
14
|
+
/** Extract only the safe message string from an unknown error. */
|
|
15
|
+
export declare function safeErrorMessage(err: unknown): string;
|
|
16
|
+
/** Mark a function as having its trigger registered. */
|
|
17
|
+
export declare function markTriggerRegistered(fn: (...args: unknown[]) => unknown): void;
|
|
18
|
+
/** Check whether a function's trigger has been registered. */
|
|
19
|
+
export declare function isTriggerRegistered(fn: (...args: unknown[]) => unknown): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Deep-convert all object keys from camelCase to snake_case.
|
|
22
|
+
* Arrays are recursed; primitives are returned as-is.
|
|
23
|
+
* This is necessary because the ingestion service (Python) expects
|
|
24
|
+
* snake_case keys while the TypeScript interfaces use camelCase.
|
|
25
|
+
*/
|
|
26
|
+
export declare function toSnakeCaseDeep(obj: unknown): unknown;
|
|
27
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAEzC;AAED,yEAAyE;AACzE,wBAAgB,SAAS,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,OAAO,CAAC,CAAC,CAAC,CAEvE;AAED,4DAA4D;AAC5D,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,aAAa,CAAC,OAAO,CAAC,CAM/E;AAED,8EAA8E;AAC9E,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAMvD;AAED,yFAAyF;AACzF,eAAO,MAAM,cAAc,aAAqD,CAAC;AAEjF,kEAAkE;AAClE,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAIrD;AAID,wDAAwD;AACxD,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,GAAG,IAAI,CAM/E;AAED,8DAA8D;AAC9D,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,GAAG,OAAO,CAEhF;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAcrD"}
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert a camelCase string to snake_case.
|
|
3
|
+
* e.g. "runId" → "run_id", "durationMs" → "duration_ms"
|
|
4
|
+
*/
|
|
5
|
+
export function toSnake(s) {
|
|
6
|
+
return s.replace(/[A-Z]/g, (ch) => `_${ch.toLowerCase()}`);
|
|
7
|
+
}
|
|
8
|
+
/** Type guard for thenables (Promises). Shared by plugin and tracing. */
|
|
9
|
+
export function isPromise(value) {
|
|
10
|
+
return typeof value?.then === 'function';
|
|
11
|
+
}
|
|
12
|
+
/** Type guard for async iterables (streaming responses). */
|
|
13
|
+
export function isAsyncIterable(value) {
|
|
14
|
+
return (value !== null &&
|
|
15
|
+
typeof value === 'object' &&
|
|
16
|
+
typeof value[Symbol.asyncIterator] === 'function');
|
|
17
|
+
}
|
|
18
|
+
/** Safe access to process.env — returns undefined in browser environments. */
|
|
19
|
+
export function safeEnv(key) {
|
|
20
|
+
try {
|
|
21
|
+
return typeof process !== 'undefined' && process.env ? process.env[key] : undefined;
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/** Keys that must never be assigned as own properties to prevent prototype pollution. */
|
|
28
|
+
export const FORBIDDEN_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
|
|
29
|
+
/** Extract only the safe message string from an unknown error. */
|
|
30
|
+
export function safeErrorMessage(err) {
|
|
31
|
+
if (err instanceof Error)
|
|
32
|
+
return err.message;
|
|
33
|
+
if (typeof err === 'string')
|
|
34
|
+
return err;
|
|
35
|
+
return 'unknown error';
|
|
36
|
+
}
|
|
37
|
+
const TRIGGER_PROP = '__turingpulseTriggerRegistered';
|
|
38
|
+
/** Mark a function as having its trigger registered. */
|
|
39
|
+
export function markTriggerRegistered(fn) {
|
|
40
|
+
Object.defineProperty(fn, TRIGGER_PROP, {
|
|
41
|
+
value: true,
|
|
42
|
+
configurable: true,
|
|
43
|
+
writable: true,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
/** Check whether a function's trigger has been registered. */
|
|
47
|
+
export function isTriggerRegistered(fn) {
|
|
48
|
+
return Boolean(fn[TRIGGER_PROP]);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Deep-convert all object keys from camelCase to snake_case.
|
|
52
|
+
* Arrays are recursed; primitives are returned as-is.
|
|
53
|
+
* This is necessary because the ingestion service (Python) expects
|
|
54
|
+
* snake_case keys while the TypeScript interfaces use camelCase.
|
|
55
|
+
*/
|
|
56
|
+
export function toSnakeCaseDeep(obj) {
|
|
57
|
+
if (Array.isArray(obj)) {
|
|
58
|
+
return obj.map(toSnakeCaseDeep);
|
|
59
|
+
}
|
|
60
|
+
if (obj !== null && typeof obj === 'object' && !(obj instanceof Date)) {
|
|
61
|
+
const out = Object.create(null);
|
|
62
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
63
|
+
const snaked = toSnake(k);
|
|
64
|
+
if (FORBIDDEN_KEYS.has(k) || FORBIDDEN_KEYS.has(snaked))
|
|
65
|
+
continue;
|
|
66
|
+
out[snaked] = toSnakeCaseDeep(v);
|
|
67
|
+
}
|
|
68
|
+
return out;
|
|
69
|
+
}
|
|
70
|
+
return obj;
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,OAAO,CAAC,CAAS;IAC/B,OAAO,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;AAC7D,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,SAAS,CAAI,KAAqB;IAChD,OAAO,OAAQ,KAAoB,EAAE,IAAI,KAAK,UAAU,CAAC;AAC3D,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,OAAO,CACL,KAAK,KAAK,IAAI;QACd,OAAO,KAAK,KAAK,QAAQ;QACzB,OAAQ,KAAgC,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,UAAU,CAC9E,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,OAAO,CAAC,GAAW;IACjC,IAAI,CAAC;QACH,OAAO,OAAO,OAAO,KAAK,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACtF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,yFAAyF;AACzF,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC,CAAC;AAEjF,kEAAkE;AAClE,MAAM,UAAU,gBAAgB,CAAC,GAAY;IAC3C,IAAI,GAAG,YAAY,KAAK;QAAE,OAAO,GAAG,CAAC,OAAO,CAAC;IAC7C,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,GAAG,CAAC;IACxC,OAAO,eAAe,CAAC;AACzB,CAAC;AAED,MAAM,YAAY,GAAG,gCAAgC,CAAC;AAEtD,wDAAwD;AACxD,MAAM,UAAU,qBAAqB,CAAC,EAAmC;IACvE,MAAM,CAAC,cAAc,CAAC,EAAE,EAAE,YAAY,EAAE;QACtC,KAAK,EAAE,IAAI;QACX,YAAY,EAAE,IAAI;QAClB,QAAQ,EAAE,IAAI;KACf,CAAC,CAAC;AACL,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,mBAAmB,CAAC,EAAmC;IACrE,OAAO,OAAO,CAAE,EAAyC,CAAC,YAAY,CAAC,CAAC,CAAC;AAC3E,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,GAAY;IAC1C,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAClC,CAAC;IACD,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,CAAC,GAAG,YAAY,IAAI,CAAC,EAAE,CAAC;QACtE,MAAM,GAAG,GAA4B,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACzD,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAA8B,CAAC,EAAE,CAAC;YACpE,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;YAC1B,IAAI,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC;gBAAE,SAAS;YAClE,GAAG,CAAC,MAAM,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;QACnC,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@turingpulse/sdk",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
5
|
+
"description": "TypeScript decorators and helpers for TuringPulse observability, governance, and KPI mapping.",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "dist/index.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"workspaces": [
|
|
10
|
+
"packages/*"
|
|
11
|
+
],
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"import": "./dist/index.js",
|
|
15
|
+
"types": "./dist/index.d.ts"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsc -p tsconfig.json",
|
|
20
|
+
"lint": "tsc -p tsconfig.json --noEmit",
|
|
21
|
+
"test": "vitest run",
|
|
22
|
+
"test:watch": "vitest"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@turingpulse/interfaces": ">=1.0.0",
|
|
26
|
+
"@opentelemetry/api": "^1.9.0",
|
|
27
|
+
"node-fetch": "^3.3.2",
|
|
28
|
+
"uuid": "^9.0.1"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@types/node": "^22.7.4",
|
|
32
|
+
"vitest": "^3.0.0"
|
|
33
|
+
},
|
|
34
|
+
"peerDependencies": {
|
|
35
|
+
"typescript": ">=5.0.0"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@turingpulse/sdk-anthropic",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
5
|
+
"description": "TuringPulse SDK integration for Anthropic (TypeScript)",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "dist/index.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"@turingpulse/sdk": ">=1.0.0"
|
|
11
|
+
},
|
|
12
|
+
"peerDependencies": {
|
|
13
|
+
"@anthropic-ai/sdk": ">=0.30.0",
|
|
14
|
+
"typescript": ">=5.0.0"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { withInstrumentation, GovernanceDirective, ConfigurationError, currentContext } from '@turingpulse/sdk';
|
|
2
|
+
|
|
3
|
+
let _originalCreate: unknown = null;
|
|
4
|
+
let _patchedProto: Record<string, unknown> | null = null;
|
|
5
|
+
|
|
6
|
+
interface PatchAnthropicOptions {
|
|
7
|
+
name?: string;
|
|
8
|
+
governance?: GovernanceDirective;
|
|
9
|
+
/**
|
|
10
|
+
* Pass your own imported Anthropic module to avoid module resolution mismatches.
|
|
11
|
+
* Accepts the default export class from `import Anthropic from '@anthropic-ai/sdk'`
|
|
12
|
+
* or the full module namespace.
|
|
13
|
+
*/
|
|
14
|
+
anthropicModule?: unknown;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function resolveMessagesProto(mod: unknown): Record<string, unknown> | undefined {
|
|
18
|
+
const cls = (mod as Record<string, unknown>)?.default ?? mod;
|
|
19
|
+
const messages = (cls as Record<string, unknown>)?.Messages as Record<string, unknown> | undefined;
|
|
20
|
+
return messages?.prototype as Record<string, unknown> | undefined;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Monkey-patch Anthropic messages.create for TuringPulse instrumentation.
|
|
25
|
+
*/
|
|
26
|
+
export async function patchAnthropic(options: PatchAnthropicOptions = {}): Promise<void> {
|
|
27
|
+
const effectiveName = options.name || (typeof process !== 'undefined' ? process.env?.TP_WORKFLOW_NAME : undefined) || '';
|
|
28
|
+
if (!effectiveName) {
|
|
29
|
+
throw new ConfigurationError('patchAnthropic() requires name or TP_WORKFLOW_NAME env var.');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
let messagesProto: Record<string, unknown> | undefined;
|
|
33
|
+
|
|
34
|
+
if (options.anthropicModule) {
|
|
35
|
+
messagesProto = resolveMessagesProto(options.anthropicModule);
|
|
36
|
+
} else {
|
|
37
|
+
try {
|
|
38
|
+
const mod = await import('@anthropic-ai/sdk');
|
|
39
|
+
messagesProto = resolveMessagesProto(mod);
|
|
40
|
+
} catch {
|
|
41
|
+
throw new Error('@anthropic-ai/sdk package is required: npm install @anthropic-ai/sdk');
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (!messagesProto) {
|
|
46
|
+
console.warn('Cannot locate Anthropic.Messages.prototype — skipping patch');
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (_originalCreate !== null) {
|
|
51
|
+
console.warn('Anthropic is already patched — skipping');
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
_originalCreate = messagesProto.create;
|
|
56
|
+
_patchedProto = messagesProto;
|
|
57
|
+
|
|
58
|
+
const wrappedCreate = withInstrumentation(
|
|
59
|
+
async function anthropicCreate(this: unknown, ...args: unknown[]): Promise<unknown> {
|
|
60
|
+
const original = _originalCreate as (...args: unknown[]) => Promise<unknown>;
|
|
61
|
+
const response = await original.apply(this, args);
|
|
62
|
+
|
|
63
|
+
const ctx = currentContext();
|
|
64
|
+
if (ctx) {
|
|
65
|
+
ctx.framework = 'anthropic';
|
|
66
|
+
ctx.nodeType = 'llm';
|
|
67
|
+
|
|
68
|
+
const resp = response as Record<string, unknown>;
|
|
69
|
+
const usage = resp?.usage as { input_tokens?: number; output_tokens?: number } | undefined;
|
|
70
|
+
if (usage) {
|
|
71
|
+
ctx.setTokens(usage.input_tokens ?? 0, usage.output_tokens ?? 0);
|
|
72
|
+
}
|
|
73
|
+
const modelName = (resp?.model as string) ?? 'unknown';
|
|
74
|
+
ctx.setModel(modelName, 'anthropic');
|
|
75
|
+
|
|
76
|
+
const firstArg = args[0] as Record<string, unknown> | undefined;
|
|
77
|
+
if (firstArg?.messages) {
|
|
78
|
+
ctx.setIO(JSON.stringify(firstArg.messages), JSON.stringify(resp?.content));
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return response;
|
|
83
|
+
},
|
|
84
|
+
{ name: effectiveName, governance: options.governance },
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
messagesProto.create = wrappedCreate;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Restore original Anthropic methods.
|
|
92
|
+
*/
|
|
93
|
+
export async function unpatchAnthropic(): Promise<void> {
|
|
94
|
+
if (_originalCreate === null) return;
|
|
95
|
+
|
|
96
|
+
if (_patchedProto) {
|
|
97
|
+
_patchedProto.create = _originalCreate;
|
|
98
|
+
_patchedProto = null;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
_originalCreate = null;
|
|
102
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "Bundler",
|
|
6
|
+
"strict": true,
|
|
7
|
+
"declaration": true,
|
|
8
|
+
"declarationMap": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"forceConsistentCasingInFileNames": true,
|
|
12
|
+
"outDir": "dist",
|
|
13
|
+
"rootDir": "src",
|
|
14
|
+
"sourceMap": true,
|
|
15
|
+
"paths": {
|
|
16
|
+
"@turingpulse/sdk": ["../../src/index.ts"]
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"include": ["src"]
|
|
20
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@turingpulse/sdk-langchain",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
5
|
+
"description": "TuringPulse SDK integration for LangChain.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "dist/index.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"@turingpulse/sdk": ">=1.0.0",
|
|
11
|
+
"@langchain/core": ">=1.1.24"
|
|
12
|
+
},
|
|
13
|
+
"peerDependencies": {
|
|
14
|
+
"typescript": ">=5.0.0"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { withInstrumentation, GovernanceDirective, currentContext } from '@turingpulse/sdk';
|
|
2
|
+
|
|
3
|
+
interface LangchainInstrumentOptions {
|
|
4
|
+
name: string;
|
|
5
|
+
governance?: GovernanceDirective;
|
|
6
|
+
model?: string;
|
|
7
|
+
provider?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Wrap a LangChain Runnable for TuringPulse observability.
|
|
12
|
+
*/
|
|
13
|
+
export function instrumentLangchain(
|
|
14
|
+
runnable: { invoke: (input: unknown, config?: unknown) => Promise<unknown> },
|
|
15
|
+
options: LangchainInstrumentOptions,
|
|
16
|
+
): (input: unknown, config?: unknown) => Promise<unknown> {
|
|
17
|
+
const { name, governance, model, provider = 'openai' } = options;
|
|
18
|
+
|
|
19
|
+
const wrappedFn = withInstrumentation(
|
|
20
|
+
async function langchainInvoke(input: unknown, config?: unknown): Promise<unknown> {
|
|
21
|
+
const result = await runnable.invoke(input, config);
|
|
22
|
+
|
|
23
|
+
const ctx = currentContext();
|
|
24
|
+
if (ctx) {
|
|
25
|
+
ctx.framework = 'langchain';
|
|
26
|
+
ctx.nodeType = 'llm';
|
|
27
|
+
if (model) ctx.setModel(model, provider);
|
|
28
|
+
|
|
29
|
+
const resp = result as Record<string, unknown> | null;
|
|
30
|
+
const content = typeof resp?.content === 'string' ? resp.content : '';
|
|
31
|
+
|
|
32
|
+
const responseMeta = resp?.response_metadata as Record<string, unknown> | undefined;
|
|
33
|
+
const tokenUsage = responseMeta?.tokenUsage as { promptTokens?: number; completionTokens?: number } | undefined;
|
|
34
|
+
if (tokenUsage) {
|
|
35
|
+
ctx.setTokens(tokenUsage.promptTokens ?? 0, tokenUsage.completionTokens ?? 0);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const detectedModel = (responseMeta?.model_name as string) ?? model;
|
|
39
|
+
if (detectedModel) ctx.setModel(detectedModel, provider);
|
|
40
|
+
|
|
41
|
+
const inputStr = typeof input === 'string' ? input : JSON.stringify(input);
|
|
42
|
+
ctx.setIO(inputStr, content || JSON.stringify(result));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return result;
|
|
46
|
+
},
|
|
47
|
+
{ name, governance },
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
return wrappedFn as (input: unknown, config?: unknown) => Promise<unknown>;
|
|
51
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@turingpulse/sdk-mastra",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
5
|
+
"description": "TuringPulse SDK integration for Mastra",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "dist/index.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"@turingpulse/sdk": ">=1.0.0",
|
|
11
|
+
"@turingpulse/interfaces": ">=1.0.0"
|
|
12
|
+
},
|
|
13
|
+
"peerDependencies": {
|
|
14
|
+
"@mastra/core": ">=1.4.0",
|
|
15
|
+
"typescript": ">=5.0.0"
|
|
16
|
+
}
|
|
17
|
+
}
|