risicare 0.2.2 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -10
- package/dist/frameworks/instructor.cjs +45 -17
- package/dist/frameworks/instructor.cjs.map +1 -1
- package/dist/frameworks/instructor.js +47 -17
- package/dist/frameworks/instructor.js.map +1 -1
- package/dist/frameworks/langchain.cjs +73 -6
- package/dist/frameworks/langchain.cjs.map +1 -1
- package/dist/frameworks/langchain.d.cts +20 -4
- package/dist/frameworks/langchain.d.ts +20 -4
- package/dist/frameworks/langchain.js +75 -6
- package/dist/frameworks/langchain.js.map +1 -1
- package/dist/frameworks/langgraph.cjs +73 -6
- package/dist/frameworks/langgraph.cjs.map +1 -1
- package/dist/frameworks/langgraph.js +75 -6
- package/dist/frameworks/langgraph.js.map +1 -1
- package/dist/frameworks/llamaindex.cjs +41 -14
- package/dist/frameworks/llamaindex.cjs.map +1 -1
- package/dist/frameworks/llamaindex.js +43 -14
- package/dist/frameworks/llamaindex.js.map +1 -1
- package/dist/index.cjs +1705 -74
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +597 -6
- package/dist/index.d.ts +597 -6
- package/dist/index.js +1723 -74
- package/dist/index.js.map +1 -1
- package/dist/providers/anthropic/index.cjs +74 -24
- package/dist/providers/anthropic/index.cjs.map +1 -1
- package/dist/providers/anthropic/index.js +76 -24
- package/dist/providers/anthropic/index.js.map +1 -1
- package/dist/providers/bedrock/index.cjs +81 -24
- package/dist/providers/bedrock/index.cjs.map +1 -1
- package/dist/providers/bedrock/index.js +83 -24
- package/dist/providers/bedrock/index.js.map +1 -1
- package/dist/providers/cerebras/index.cjs +78 -25
- package/dist/providers/cerebras/index.cjs.map +1 -1
- package/dist/providers/cerebras/index.js +80 -25
- package/dist/providers/cerebras/index.js.map +1 -1
- package/dist/providers/cohere/index.cjs +95 -25
- package/dist/providers/cohere/index.cjs.map +1 -1
- package/dist/providers/cohere/index.js +97 -25
- package/dist/providers/cohere/index.js.map +1 -1
- package/dist/providers/google/index.cjs +77 -25
- package/dist/providers/google/index.cjs.map +1 -1
- package/dist/providers/google/index.js +79 -25
- package/dist/providers/google/index.js.map +1 -1
- package/dist/providers/groq/index.cjs +80 -25
- package/dist/providers/groq/index.cjs.map +1 -1
- package/dist/providers/groq/index.js +82 -25
- package/dist/providers/groq/index.js.map +1 -1
- package/dist/providers/huggingface/index.cjs +80 -25
- package/dist/providers/huggingface/index.cjs.map +1 -1
- package/dist/providers/huggingface/index.js +82 -25
- package/dist/providers/huggingface/index.js.map +1 -1
- package/dist/providers/mistral/index.cjs +72 -24
- package/dist/providers/mistral/index.cjs.map +1 -1
- package/dist/providers/mistral/index.js +74 -24
- package/dist/providers/mistral/index.js.map +1 -1
- package/dist/providers/ollama/index.cjs +83 -25
- package/dist/providers/ollama/index.cjs.map +1 -1
- package/dist/providers/ollama/index.js +85 -25
- package/dist/providers/ollama/index.js.map +1 -1
- package/dist/providers/openai/index.cjs +118 -28
- package/dist/providers/openai/index.cjs.map +1 -1
- package/dist/providers/openai/index.js +120 -28
- package/dist/providers/openai/index.js.map +1 -1
- package/dist/providers/together/index.cjs +80 -25
- package/dist/providers/together/index.cjs.map +1 -1
- package/dist/providers/together/index.js +82 -25
- package/dist/providers/together/index.js.map +1 -1
- package/dist/providers/vercel-ai/index.cjs +45 -17
- package/dist/providers/vercel-ai/index.cjs.map +1 -1
- package/dist/providers/vercel-ai/index.js +47 -17
- package/dist/providers/vercel-ai/index.js.map +1 -1
- package/package.json +5 -4
package/dist/index.d.cts
CHANGED
|
@@ -371,9 +371,10 @@ declare function getMetrics(): {
|
|
|
371
371
|
queueUtilization: number;
|
|
372
372
|
};
|
|
373
373
|
/**
|
|
374
|
-
* Report a caught exception to the
|
|
374
|
+
* Report a caught exception to the error diagnosis pipeline.
|
|
375
375
|
*
|
|
376
376
|
* Creates an error span that triggers diagnosis and fix generation.
|
|
377
|
+
* Deduplicates identical errors within a 5-minute window (SHA256 fingerprint).
|
|
377
378
|
* This function never throws and is non-blocking.
|
|
378
379
|
*
|
|
379
380
|
* @param error - The caught exception (Error object or string)
|
|
@@ -429,6 +430,17 @@ declare function withAgent<T>(options: AgentOptions, fn: () => T): T;
|
|
|
429
430
|
* Wraps a function to execute within an agent context. All spans created
|
|
430
431
|
* inside will be tagged with the agent's identity.
|
|
431
432
|
*
|
|
433
|
+
* Two equivalent calling forms are supported:
|
|
434
|
+
*
|
|
435
|
+
* // 2-arg form
|
|
436
|
+
* const research = agent({ name: 'researcher' }, async (q) => { ... });
|
|
437
|
+
*
|
|
438
|
+
* // Curried form (decorator factory)
|
|
439
|
+
* const research = agent({ name: 'researcher' })(async (q) => { ... });
|
|
440
|
+
*
|
|
441
|
+
* Both return a wrapped function — call it to actually run the body inside
|
|
442
|
+
* the agent context.
|
|
443
|
+
*
|
|
432
444
|
* @example
|
|
433
445
|
* const research = agent({ name: 'researcher', role: 'worker' }, async (query: string) => {
|
|
434
446
|
* const result = await openai.chat.completions.create({ ... });
|
|
@@ -438,10 +450,8 @@ declare function withAgent<T>(options: AgentOptions, fn: () => T): T;
|
|
|
438
450
|
* const answer = await research('What is quantum computing?');
|
|
439
451
|
*/
|
|
440
452
|
|
|
441
|
-
/**
|
|
442
|
-
* Wrap a function with agent context and an automatic span.
|
|
443
|
-
*/
|
|
444
453
|
declare function agent<TArgs extends unknown[], TReturn>(options: AgentOptions, fn: (...args: TArgs) => TReturn): (...args: TArgs) => TReturn;
|
|
454
|
+
declare function agent(options: AgentOptions): <TArgs extends unknown[], TReturn>(fn: (...args: TArgs) => TReturn) => (...args: TArgs) => TReturn;
|
|
445
455
|
|
|
446
456
|
/**
|
|
447
457
|
* Session context — groups multiple traces from the same user interaction.
|
|
@@ -482,10 +492,19 @@ declare function withSession<T>(options: SessionOptions, fn: () => T): T;
|
|
|
482
492
|
/**
|
|
483
493
|
* Wrap a function with session context.
|
|
484
494
|
*
|
|
495
|
+
* Two equivalent calling forms are supported (F-54 ergonomics):
|
|
496
|
+
*
|
|
497
|
+
* // 2-arg form
|
|
498
|
+
* const handle = session({ sessionId: 's1' }, async (req) => { ... });
|
|
499
|
+
*
|
|
500
|
+
* // Curried form (decorator factory)
|
|
501
|
+
* const handle = session({ sessionId: 's1' })(async (req) => { ... });
|
|
502
|
+
*
|
|
485
503
|
* @param optionsOrResolver - Static session options, or a function that derives them from args
|
|
486
|
-
* @param fn - The function to wrap
|
|
504
|
+
* @param fn - The function to wrap. If omitted, returns a decorator factory.
|
|
487
505
|
*/
|
|
488
506
|
declare function session<TArgs extends unknown[], TReturn>(optionsOrResolver: SessionOptions | ((...args: TArgs) => SessionOptions), fn: (...args: TArgs) => TReturn): (...args: TArgs) => TReturn;
|
|
507
|
+
declare function session<TArgs extends unknown[]>(optionsOrResolver: SessionOptions | ((...args: TArgs) => SessionOptions)): <TR>(fn: (...args: TArgs) => TR) => (...args: TArgs) => TR;
|
|
489
508
|
|
|
490
509
|
/**
|
|
491
510
|
* Phase decorators — decision phase tracking (Tier 4).
|
|
@@ -638,6 +657,11 @@ interface TraceContext {
|
|
|
638
657
|
}
|
|
639
658
|
/**
|
|
640
659
|
* Get the current trace context as a serializable object.
|
|
660
|
+
*
|
|
661
|
+
* When called inside a span context, returns the active span's IDs.
|
|
662
|
+
* When called outside a span (e.g. inside session() but before agent()),
|
|
663
|
+
* pre-allocates a trace ID and stores it in context so the next
|
|
664
|
+
* startSpan() call inherits it — preventing trace ID mismatch.
|
|
641
665
|
*/
|
|
642
666
|
declare function getTraceContext(): TraceContext;
|
|
643
667
|
/**
|
|
@@ -728,4 +752,571 @@ declare function suppressProviderInstrumentation<T>(fn: () => T): T;
|
|
|
728
752
|
*/
|
|
729
753
|
declare function isProviderInstrumentationSuppressed(): boolean;
|
|
730
754
|
|
|
731
|
-
|
|
755
|
+
/**
|
|
756
|
+
* Fix Runtime Configuration.
|
|
757
|
+
*
|
|
758
|
+
* Settings for the fix runtime including caching, refresh intervals,
|
|
759
|
+
* A/B testing, and fix application behavior.
|
|
760
|
+
*
|
|
761
|
+
* Port of Python SDK's runtime/config.py adapted for Node.js patterns.
|
|
762
|
+
*/
|
|
763
|
+
interface FixRuntimeConfig {
|
|
764
|
+
/** API endpoint URL (e.g., "https://app.risicare.ai") */
|
|
765
|
+
apiEndpoint: string;
|
|
766
|
+
/** API key for authentication (format: "rsk-{random}") */
|
|
767
|
+
apiKey: string;
|
|
768
|
+
/** Whether the fix runtime is enabled (default: true) */
|
|
769
|
+
enabled?: boolean;
|
|
770
|
+
/** Whether caching is enabled (default: true) */
|
|
771
|
+
cacheEnabled?: boolean;
|
|
772
|
+
/** Cache entry TTL in milliseconds (default: 300_000 = 5 min) */
|
|
773
|
+
cacheTtlMs?: number;
|
|
774
|
+
/** Maximum number of cache entries (default: 1000) */
|
|
775
|
+
cacheMaxEntries?: number;
|
|
776
|
+
/** Whether to auto-refresh fixes in background (default: true) */
|
|
777
|
+
autoRefresh?: boolean;
|
|
778
|
+
/** Background refresh interval in milliseconds (default: 60_000 = 1 min) */
|
|
779
|
+
refreshIntervalMs?: number;
|
|
780
|
+
/** Log but don't apply fixes (default: false) */
|
|
781
|
+
dryRun?: boolean;
|
|
782
|
+
/** Whether A/B testing bucketing is active (default: true) */
|
|
783
|
+
abTestingEnabled?: boolean;
|
|
784
|
+
/** Timeout for API requests in milliseconds (default: 1000) */
|
|
785
|
+
timeoutMs?: number;
|
|
786
|
+
/** Enable debug logging (default: false) */
|
|
787
|
+
debug?: boolean;
|
|
788
|
+
}
|
|
789
|
+
type FixType = 'prompt' | 'parameter' | 'retry' | 'fallback' | 'guard' | 'routing' | 'tool';
|
|
790
|
+
interface ActiveFix {
|
|
791
|
+
fixId: string;
|
|
792
|
+
deploymentId?: string;
|
|
793
|
+
errorCode: string;
|
|
794
|
+
fixType: FixType;
|
|
795
|
+
config: Record<string, unknown>;
|
|
796
|
+
trafficPercentage: number;
|
|
797
|
+
version: number;
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
/**
|
|
801
|
+
* Fix Cache — Local cache for active fixes with TTL eviction.
|
|
802
|
+
*
|
|
803
|
+
* Provides fast lookup of fixes keyed by error code with exact match
|
|
804
|
+
* and wildcard fallback. No locks needed — JS is single-threaded.
|
|
805
|
+
*
|
|
806
|
+
* Port of Python SDK's runtime/cache.py.
|
|
807
|
+
*/
|
|
808
|
+
|
|
809
|
+
interface CacheStats {
|
|
810
|
+
hits: number;
|
|
811
|
+
misses: number;
|
|
812
|
+
evictions: number;
|
|
813
|
+
size: number;
|
|
814
|
+
lastRefresh: number | null;
|
|
815
|
+
}
|
|
816
|
+
declare class FixCache {
|
|
817
|
+
private readonly _ttlMs;
|
|
818
|
+
private readonly _maxEntries;
|
|
819
|
+
private readonly _enabled;
|
|
820
|
+
private _cache;
|
|
821
|
+
private _stats;
|
|
822
|
+
constructor(config?: Pick<FixRuntimeConfig, 'cacheEnabled' | 'cacheTtlMs' | 'cacheMaxEntries'>);
|
|
823
|
+
/** Whether caching is enabled. */
|
|
824
|
+
get enabled(): boolean;
|
|
825
|
+
/**
|
|
826
|
+
* Get a fix by error code.
|
|
827
|
+
*
|
|
828
|
+
* Checks exact match first, then scans for wildcard matches.
|
|
829
|
+
* Expired entries are evicted on access.
|
|
830
|
+
*/
|
|
831
|
+
get(errorCode: string): ActiveFix | null;
|
|
832
|
+
/**
|
|
833
|
+
* Add a single fix to the cache.
|
|
834
|
+
*
|
|
835
|
+
* Evicts the oldest entry if at capacity.
|
|
836
|
+
*/
|
|
837
|
+
set(fix: ActiveFix): void;
|
|
838
|
+
/**
|
|
839
|
+
* Replace all cached fixes (bulk refresh).
|
|
840
|
+
*
|
|
841
|
+
* Clears the cache and populates with the given fixes.
|
|
842
|
+
*/
|
|
843
|
+
setAll(fixes: ActiveFix[]): void;
|
|
844
|
+
/**
|
|
845
|
+
* Get all non-expired fixes.
|
|
846
|
+
*/
|
|
847
|
+
getAll(): ActiveFix[];
|
|
848
|
+
/** Clear all cache entries. Returns the number of entries cleared. */
|
|
849
|
+
clear(): number;
|
|
850
|
+
/** Get cache statistics. */
|
|
851
|
+
get stats(): CacheStats;
|
|
852
|
+
/** Evict the oldest cache entry. */
|
|
853
|
+
private _evictOldest;
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
/**
|
|
857
|
+
* Fix Applier — Applies fixes to agent operations.
|
|
858
|
+
*
|
|
859
|
+
* Handles different fix types:
|
|
860
|
+
* - PromptFix: Modify system/user prompts (prepend, append, replace, few_shot)
|
|
861
|
+
* - ParameterFix: Adjust LLM parameters (temperature, model, etc.)
|
|
862
|
+
* - RetryFix: Retry with exponential backoff + jitter
|
|
863
|
+
* - FallbackFix: Switch to fallback model or default response
|
|
864
|
+
* - GuardFix: Input/output validation (content filter, format check, length)
|
|
865
|
+
*
|
|
866
|
+
* Port of Python SDK's runtime/applier.py adapted for Node.js.
|
|
867
|
+
*/
|
|
868
|
+
|
|
869
|
+
interface ApplyResult {
|
|
870
|
+
applied: boolean;
|
|
871
|
+
fixId?: string;
|
|
872
|
+
deploymentId?: string;
|
|
873
|
+
fixType?: string;
|
|
874
|
+
modifications: Record<string, unknown>;
|
|
875
|
+
error?: string;
|
|
876
|
+
}
|
|
877
|
+
declare class FixApplier {
|
|
878
|
+
private readonly _config;
|
|
879
|
+
private readonly _cache;
|
|
880
|
+
private _applicationLog;
|
|
881
|
+
constructor(config: FixRuntimeConfig, cache: FixCache);
|
|
882
|
+
/**
|
|
883
|
+
* Get applicable fix for an error code.
|
|
884
|
+
*
|
|
885
|
+
* Considers A/B testing bucket if sessionId is provided. Uses
|
|
886
|
+
* crypto.createHash('md5') for deterministic bucketing across restarts.
|
|
887
|
+
*/
|
|
888
|
+
getFixForError(errorCode: string, sessionId?: string): ActiveFix | null;
|
|
889
|
+
/**
|
|
890
|
+
* Apply a prompt fix to messages.
|
|
891
|
+
*
|
|
892
|
+
* Supports 4 modification types:
|
|
893
|
+
* - prepend: Add content before first system message
|
|
894
|
+
* - append: Add content after first system message
|
|
895
|
+
* - replace: Regex replace across all messages
|
|
896
|
+
* - few_shot: Insert user/assistant example pairs after system message
|
|
897
|
+
*/
|
|
898
|
+
applyPromptFix(fix: ActiveFix, messages: Record<string, unknown>[]): {
|
|
899
|
+
messages: Record<string, unknown>[];
|
|
900
|
+
result: ApplyResult;
|
|
901
|
+
};
|
|
902
|
+
/**
|
|
903
|
+
* Apply a parameter fix — merge config.parameters into params.
|
|
904
|
+
*/
|
|
905
|
+
applyParameterFix(fix: ActiveFix, params: Record<string, unknown>): {
|
|
906
|
+
params: Record<string, unknown>;
|
|
907
|
+
result: ApplyResult;
|
|
908
|
+
};
|
|
909
|
+
/**
|
|
910
|
+
* Apply a retry fix to an async operation.
|
|
911
|
+
*
|
|
912
|
+
* Retries with exponential backoff + jitter using
|
|
913
|
+
* `await new Promise(r => setTimeout(r, delay))`.
|
|
914
|
+
*/
|
|
915
|
+
applyRetryFix<T>(fix: ActiveFix, operation: () => Promise<T>): Promise<{
|
|
916
|
+
value: T;
|
|
917
|
+
result: ApplyResult;
|
|
918
|
+
}>;
|
|
919
|
+
/**
|
|
920
|
+
* Apply a fallback fix.
|
|
921
|
+
*
|
|
922
|
+
* - 'model': Replace params.model with the fallback model
|
|
923
|
+
* - 'default': Set params._fallbackResponse for the caller to use
|
|
924
|
+
*/
|
|
925
|
+
applyFallbackFix(fix: ActiveFix, params: Record<string, unknown>): {
|
|
926
|
+
params: Record<string, unknown>;
|
|
927
|
+
result: ApplyResult;
|
|
928
|
+
};
|
|
929
|
+
/**
|
|
930
|
+
* Apply a guard fix (validation).
|
|
931
|
+
*
|
|
932
|
+
* Guard types:
|
|
933
|
+
* - content_filter: Regex-based blocked patterns
|
|
934
|
+
* - format_check: JSON.parse() validity
|
|
935
|
+
* - input_validation / output_validation: min/max length
|
|
936
|
+
*/
|
|
937
|
+
applyGuardFix(fix: ActiveFix, content: string, isInput?: boolean): {
|
|
938
|
+
content: string;
|
|
939
|
+
passed: boolean;
|
|
940
|
+
result: ApplyResult;
|
|
941
|
+
};
|
|
942
|
+
/** Log a fix application result. */
|
|
943
|
+
logApplication(result: ApplyResult): void;
|
|
944
|
+
/** Get the application log. */
|
|
945
|
+
getApplicationLog(): ApplyResult[];
|
|
946
|
+
/**
|
|
947
|
+
* Safely compile a regex pattern from untrusted input.
|
|
948
|
+
* Returns null if invalid or too long.
|
|
949
|
+
*/
|
|
950
|
+
private _safeCompileRegex;
|
|
951
|
+
/** Prepend content to the first message matching the target role. */
|
|
952
|
+
private _prependToTarget;
|
|
953
|
+
/** Append content to the first message matching the target role. */
|
|
954
|
+
private _appendToTarget;
|
|
955
|
+
/** Regex replace across all messages. */
|
|
956
|
+
private _replaceInMessages;
|
|
957
|
+
/** Add few-shot examples after the first system message. */
|
|
958
|
+
private _addFewShotExamples;
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
/**
|
|
962
|
+
* Fix Loader — Fetches active fixes from the Risicare API.
|
|
963
|
+
*
|
|
964
|
+
* Handles:
|
|
965
|
+
* - Initial loading of fixes on startup
|
|
966
|
+
* - Periodic background refresh via setInterval (unref'd)
|
|
967
|
+
* - Exponential backoff on failure
|
|
968
|
+
* - Circuit breaker: after 3 consecutive failures, stop trying for 30s
|
|
969
|
+
*
|
|
970
|
+
* Uses native fetch (Node.js 18+) with AbortController for timeouts.
|
|
971
|
+
*
|
|
972
|
+
* Port of Python SDK's runtime/loader.py adapted for Node.js.
|
|
973
|
+
*/
|
|
974
|
+
|
|
975
|
+
declare class FixLoader {
|
|
976
|
+
private readonly _config;
|
|
977
|
+
private readonly _cache;
|
|
978
|
+
private _refreshTimer;
|
|
979
|
+
private _lastLoadTime;
|
|
980
|
+
private _consecutiveFailures;
|
|
981
|
+
private _circuitOpenUntil;
|
|
982
|
+
private _onLoadCallbacks;
|
|
983
|
+
private static readonly CIRCUIT_BREAKER_THRESHOLD;
|
|
984
|
+
private static readonly CIRCUIT_BREAKER_COOLDOWN_MS;
|
|
985
|
+
constructor(config: FixRuntimeConfig, cache: FixCache);
|
|
986
|
+
/** Timestamp of last successful load. */
|
|
987
|
+
get lastLoadTime(): number | null;
|
|
988
|
+
/**
|
|
989
|
+
* Start the loader: perform initial load and start background refresh.
|
|
990
|
+
*
|
|
991
|
+
* Never throws — failures are logged and the runtime degrades gracefully.
|
|
992
|
+
*/
|
|
993
|
+
start(): void;
|
|
994
|
+
/** Stop the loader: clear the refresh interval. */
|
|
995
|
+
stop(): void;
|
|
996
|
+
/**
|
|
997
|
+
* Register a callback invoked after each successful load.
|
|
998
|
+
*/
|
|
999
|
+
onLoad(callback: (fixes: ActiveFix[]) => void): void;
|
|
1000
|
+
/**
|
|
1001
|
+
* Load fixes from the API.
|
|
1002
|
+
*
|
|
1003
|
+
* Name kept as "loadSync" for parity with the Python SDK, but this
|
|
1004
|
+
* returns a Promise in JS (there's no synchronous fetch in Node.js).
|
|
1005
|
+
*/
|
|
1006
|
+
loadSync(): Promise<ActiveFix[]>;
|
|
1007
|
+
/** Get currently cached fixes without hitting the API. */
|
|
1008
|
+
getCached(): ActiveFix[];
|
|
1009
|
+
private _parseResponse;
|
|
1010
|
+
private _onLoadSuccess;
|
|
1011
|
+
private _onLoadFailure;
|
|
1012
|
+
private _startRefreshInterval;
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
/**
|
|
1016
|
+
* Fix Interceptors — Hook into LLM/tool calls to apply fixes.
|
|
1017
|
+
*
|
|
1018
|
+
* Interceptors are registered with the runtime and called during agent
|
|
1019
|
+
* execution to apply relevant fixes at three interception points:
|
|
1020
|
+
* - preCall: Before the LLM/tool call (prompt/parameter/fallback fixes)
|
|
1021
|
+
* - postCall: After the call (output guard validation)
|
|
1022
|
+
* - onError: When an error occurs (retry/fallback decisions)
|
|
1023
|
+
*
|
|
1024
|
+
* Port of Python SDK's runtime/interceptors.py adapted for Node.js.
|
|
1025
|
+
*/
|
|
1026
|
+
|
|
1027
|
+
interface InterceptContext {
|
|
1028
|
+
/** Type of operation: "llm_call", "tool_call", "agent_delegate" */
|
|
1029
|
+
operationType: string;
|
|
1030
|
+
/** Name of the operation: model name, tool name, agent name */
|
|
1031
|
+
operationName: string;
|
|
1032
|
+
/** Session ID for A/B testing bucketing */
|
|
1033
|
+
sessionId?: string;
|
|
1034
|
+
/** Trace ID for correlation */
|
|
1035
|
+
traceId?: string;
|
|
1036
|
+
/** Error code (set when retrying after error) */
|
|
1037
|
+
errorCode?: string;
|
|
1038
|
+
/** Error message (set when retrying after error) */
|
|
1039
|
+
errorMessage?: string;
|
|
1040
|
+
/** Current attempt number (1-based) */
|
|
1041
|
+
attempt: number;
|
|
1042
|
+
/** Fixes applied during this intercept lifecycle */
|
|
1043
|
+
appliedFixes: ApplyResult[];
|
|
1044
|
+
}
|
|
1045
|
+
interface FixInterceptor {
|
|
1046
|
+
/**
|
|
1047
|
+
* Called before an LLM/tool call.
|
|
1048
|
+
* Returns modified messages and params.
|
|
1049
|
+
*/
|
|
1050
|
+
preCall(ctx: InterceptContext, messages: unknown[] | null, params: Record<string, unknown>): {
|
|
1051
|
+
messages: unknown[] | null;
|
|
1052
|
+
params: Record<string, unknown>;
|
|
1053
|
+
};
|
|
1054
|
+
/**
|
|
1055
|
+
* Called after an LLM/tool call.
|
|
1056
|
+
* Returns modified response and whether to continue.
|
|
1057
|
+
*/
|
|
1058
|
+
postCall(ctx: InterceptContext, response: unknown): {
|
|
1059
|
+
response: unknown;
|
|
1060
|
+
shouldContinue: boolean;
|
|
1061
|
+
};
|
|
1062
|
+
/**
|
|
1063
|
+
* Called when an error occurs.
|
|
1064
|
+
* Returns whether to retry and optional modified params.
|
|
1065
|
+
*/
|
|
1066
|
+
onError(ctx: InterceptContext, error: Error): {
|
|
1067
|
+
shouldRetry: boolean;
|
|
1068
|
+
modifiedParams: Record<string, unknown> | null;
|
|
1069
|
+
};
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
/**
|
|
1073
|
+
* Fix Runtime — Main orchestrator for the fix application system.
|
|
1074
|
+
*
|
|
1075
|
+
* Manages:
|
|
1076
|
+
* - Loading active fixes from the API (via FixLoader)
|
|
1077
|
+
* - Caching fixes locally (via FixCache)
|
|
1078
|
+
* - Applying fixes via interceptors (via DefaultFixInterceptor)
|
|
1079
|
+
* - Tracking fix effectiveness
|
|
1080
|
+
*
|
|
1081
|
+
* Singleton management via globalThis (same pattern as the tracer).
|
|
1082
|
+
*
|
|
1083
|
+
* Port of Python SDK's runtime/runtime.py adapted for Node.js.
|
|
1084
|
+
*/
|
|
1085
|
+
|
|
1086
|
+
declare class FixRuntime {
|
|
1087
|
+
private readonly _config;
|
|
1088
|
+
private readonly _cache;
|
|
1089
|
+
private readonly _loader;
|
|
1090
|
+
private readonly _applier;
|
|
1091
|
+
private readonly _interceptor;
|
|
1092
|
+
private _started;
|
|
1093
|
+
private _fixApplications;
|
|
1094
|
+
private _fixSuccesses;
|
|
1095
|
+
constructor(config: FixRuntimeConfig);
|
|
1096
|
+
/** Runtime configuration (with defaults resolved). */
|
|
1097
|
+
get config(): Required<FixRuntimeConfig>;
|
|
1098
|
+
/** Whether the runtime is enabled and started. */
|
|
1099
|
+
get isEnabled(): boolean;
|
|
1100
|
+
/** The fix cache. */
|
|
1101
|
+
get cache(): FixCache;
|
|
1102
|
+
/** The fix loader. */
|
|
1103
|
+
get loader(): FixLoader;
|
|
1104
|
+
/** The fix applier. */
|
|
1105
|
+
get applier(): FixApplier;
|
|
1106
|
+
/** The interceptor. */
|
|
1107
|
+
get interceptor(): FixInterceptor;
|
|
1108
|
+
/**
|
|
1109
|
+
* Start the runtime.
|
|
1110
|
+
*
|
|
1111
|
+
* Triggers initial fix load and starts background refresh.
|
|
1112
|
+
* Never throws — failures degrade gracefully.
|
|
1113
|
+
*/
|
|
1114
|
+
start(): void;
|
|
1115
|
+
/**
|
|
1116
|
+
* Stop the runtime.
|
|
1117
|
+
*
|
|
1118
|
+
* Stops background refresh and clears the cache.
|
|
1119
|
+
* Never throws.
|
|
1120
|
+
*/
|
|
1121
|
+
stop(): void;
|
|
1122
|
+
/**
|
|
1123
|
+
* Intercept a call: create context and run preCall fixes.
|
|
1124
|
+
*
|
|
1125
|
+
* Returns modified messages/params and the InterceptContext for
|
|
1126
|
+
* use in subsequent interceptResponse / interceptError calls.
|
|
1127
|
+
*/
|
|
1128
|
+
interceptCall(operationType: string, operationName: string, messages: unknown[] | null, params: Record<string, unknown>, options?: {
|
|
1129
|
+
sessionId?: string;
|
|
1130
|
+
traceId?: string;
|
|
1131
|
+
errorCode?: string;
|
|
1132
|
+
}): {
|
|
1133
|
+
messages: unknown[] | null;
|
|
1134
|
+
params: Record<string, unknown>;
|
|
1135
|
+
ctx: InterceptContext;
|
|
1136
|
+
};
|
|
1137
|
+
/**
|
|
1138
|
+
* Intercept a response: run postCall fixes (output validation).
|
|
1139
|
+
*/
|
|
1140
|
+
interceptResponse(ctx: InterceptContext, response: unknown): {
|
|
1141
|
+
response: unknown;
|
|
1142
|
+
shouldContinue: boolean;
|
|
1143
|
+
};
|
|
1144
|
+
/**
|
|
1145
|
+
* Intercept an error: decide on retry/fallback.
|
|
1146
|
+
*/
|
|
1147
|
+
interceptError(ctx: InterceptContext, error: Error): {
|
|
1148
|
+
shouldRetry: boolean;
|
|
1149
|
+
modifiedParams: Record<string, unknown> | null;
|
|
1150
|
+
};
|
|
1151
|
+
/**
|
|
1152
|
+
* Get applicable fix for an error code.
|
|
1153
|
+
*/
|
|
1154
|
+
getFix(errorCode: string, sessionId?: string): ActiveFix | null;
|
|
1155
|
+
/**
|
|
1156
|
+
* Manually refresh fixes from the API.
|
|
1157
|
+
*/
|
|
1158
|
+
refreshFixes(): Promise<ActiveFix[]>;
|
|
1159
|
+
/** Get effectiveness statistics for all fixes. */
|
|
1160
|
+
getEffectivenessStats(): Record<string, {
|
|
1161
|
+
applications: number;
|
|
1162
|
+
successes: number;
|
|
1163
|
+
successRate: number;
|
|
1164
|
+
}>;
|
|
1165
|
+
private _trackSuccess;
|
|
1166
|
+
private _trackFailure;
|
|
1167
|
+
}
|
|
1168
|
+
/** Get the global FixRuntime instance, if initialized. */
|
|
1169
|
+
declare function getFixRuntime(): FixRuntime | undefined;
|
|
1170
|
+
/**
|
|
1171
|
+
* Initialize and start the global FixRuntime.
|
|
1172
|
+
*
|
|
1173
|
+
* If already initialized, returns the existing instance.
|
|
1174
|
+
* Never throws — initialization failures degrade gracefully.
|
|
1175
|
+
*/
|
|
1176
|
+
declare function initFixRuntime(config: FixRuntimeConfig): FixRuntime;
|
|
1177
|
+
/**
|
|
1178
|
+
* Shutdown and remove the global FixRuntime.
|
|
1179
|
+
*
|
|
1180
|
+
* Never throws.
|
|
1181
|
+
*/
|
|
1182
|
+
declare function shutdownFixRuntime(): void;
|
|
1183
|
+
|
|
1184
|
+
/**
|
|
1185
|
+
* Webhook signature verification helpers (CON-195 / B-7, F-34).
|
|
1186
|
+
*
|
|
1187
|
+
* Customers receive Risicare webhooks at endpoints they configure. Each
|
|
1188
|
+
* delivery is signed by the sender (`packages/workers/src/workers/
|
|
1189
|
+
* webhook_dispatch.py`) with HMAC-SHA256 over `<timestamp>.<payload_bytes>`
|
|
1190
|
+
* using the per-webhook shared secret. The signature is delivered in the
|
|
1191
|
+
* `X-Risicare-Signature` header in Stripe-style format `t=<unix>,v1=<hex>`,
|
|
1192
|
+
* and the timestamp is also exposed verbatim as `X-Risicare-Timestamp`.
|
|
1193
|
+
*
|
|
1194
|
+
* This module is the TypeScript port of `risicare-sdk/src/risicare/
|
|
1195
|
+
* webhooks.py`. It enforces THREE checks (all must pass):
|
|
1196
|
+
*
|
|
1197
|
+
* 1. Header parsing — both headers must be present and well-formed.
|
|
1198
|
+
* 2. Time skew — `Math.abs(now - timestamp) <= toleranceS` (default
|
|
1199
|
+
* 5 minutes). This is what makes captured signed payloads
|
|
1200
|
+
* non-replayable past the tolerance window.
|
|
1201
|
+
* 3. HMAC equality — constant-time compare against a fresh signature
|
|
1202
|
+
* computed from the secret + the SAME timestamp + the raw body.
|
|
1203
|
+
*
|
|
1204
|
+
* Example (Express/Node receiver):
|
|
1205
|
+
*
|
|
1206
|
+
* import express from 'express';
|
|
1207
|
+
* import { verifyWebhookSignature, WebhookVerificationError } from 'risicare';
|
|
1208
|
+
*
|
|
1209
|
+
* const app = express();
|
|
1210
|
+
* // IMPORTANT: use raw body, not parsed JSON — the signature is
|
|
1211
|
+
* // over the EXACT bytes received; JSON re-serialization changes
|
|
1212
|
+
* // key ordering / whitespace and the signature will not match.
|
|
1213
|
+
* app.post('/risicare-webhook', express.raw({ type: '*\/*' }), (req, res) => {
|
|
1214
|
+
* try {
|
|
1215
|
+
* verifyWebhookSignature(req.body, req.headers, YOUR_WEBHOOK_SECRET);
|
|
1216
|
+
* } catch (e) {
|
|
1217
|
+
* if (e instanceof WebhookVerificationError) {
|
|
1218
|
+
* return res.status(401).send(e.message);
|
|
1219
|
+
* }
|
|
1220
|
+
* throw e;
|
|
1221
|
+
* }
|
|
1222
|
+
* // ... process the verified event ...
|
|
1223
|
+
* res.status(200).end();
|
|
1224
|
+
* });
|
|
1225
|
+
*
|
|
1226
|
+
* The helper is dependency-light (Node `crypto` stdlib only) so customers
|
|
1227
|
+
* can use it without pulling in the rest of the SDK if they only need
|
|
1228
|
+
* verification.
|
|
1229
|
+
*
|
|
1230
|
+
* Edge runtime note: this verifier is synchronous and uses Node's
|
|
1231
|
+
* `crypto.timingSafeEqual` + `crypto.createHmac`. It will not run in
|
|
1232
|
+
* Cloudflare Workers / Vercel Edge / Deno Deploy as-is. An async Web
|
|
1233
|
+
* Crypto variant can be added if customers request it.
|
|
1234
|
+
*/
|
|
1235
|
+
/**
|
|
1236
|
+
* Default skew window (seconds). 5 minutes matches Stripe / GitHub /
|
|
1237
|
+
* common industry practice. Customers can override per-call if their
|
|
1238
|
+
* clock infrastructure warrants a tighter or looser bound.
|
|
1239
|
+
*
|
|
1240
|
+
* Mirrors `DEFAULT_TIMESTAMP_TOLERANCE_S` in the Python SDK.
|
|
1241
|
+
*/
|
|
1242
|
+
declare const DEFAULT_TIMESTAMP_TOLERANCE_S = 300;
|
|
1243
|
+
/**
|
|
1244
|
+
* Raised when a webhook delivery fails any verification check.
|
|
1245
|
+
*
|
|
1246
|
+
* Customers should catch this specifically rather than a generic `Error`
|
|
1247
|
+
* so verification failures are not conflated with other input problems
|
|
1248
|
+
* (e.g. body-parsing errors at the framework layer).
|
|
1249
|
+
*
|
|
1250
|
+
* The `message` is safe to log — it never includes the secret, the
|
|
1251
|
+
* expected signature, or the computed signature.
|
|
1252
|
+
*/
|
|
1253
|
+
declare class WebhookVerificationError extends Error {
|
|
1254
|
+
constructor(message: string);
|
|
1255
|
+
}
|
|
1256
|
+
/**
|
|
1257
|
+
* Options for `verifyWebhookSignature`. All fields are optional.
|
|
1258
|
+
*/
|
|
1259
|
+
interface VerifyWebhookOptions {
|
|
1260
|
+
/**
|
|
1261
|
+
* Maximum clock-skew tolerance in seconds. Defaults to
|
|
1262
|
+
* `DEFAULT_TIMESTAMP_TOLERANCE_S` (300). Setting to 0 is supported
|
|
1263
|
+
* (strict same-second match) but discouraged in distributed
|
|
1264
|
+
* deployments.
|
|
1265
|
+
*/
|
|
1266
|
+
toleranceS?: number;
|
|
1267
|
+
/**
|
|
1268
|
+
* Test hook — override "current time" in unix seconds.
|
|
1269
|
+
* Customers should not pass this.
|
|
1270
|
+
*/
|
|
1271
|
+
_now?: number;
|
|
1272
|
+
}
|
|
1273
|
+
/**
|
|
1274
|
+
* Header-like inputs accepted by `verifyWebhookSignature`.
|
|
1275
|
+
*
|
|
1276
|
+
* Covers (a) Web API `Headers` (case-insensitive `.get`), (b) Node
|
|
1277
|
+
* `IncomingHttpHeaders` (plain object with lowercase keys, possibly
|
|
1278
|
+
* array-valued for multi-set headers), (c) `Map<string, string>`
|
|
1279
|
+
* (case-sensitive `.get`), and (d) plain `Record` (case-sensitive
|
|
1280
|
+
* property lookup, possibly array-valued).
|
|
1281
|
+
*
|
|
1282
|
+
* Lookup strategy: try the canonical mixed-case name first
|
|
1283
|
+
* (`X-Risicare-Signature`). If that returns undefined, fall back to the
|
|
1284
|
+
* lowercased form (`x-risicare-signature`). Mirrors the Python
|
|
1285
|
+
* `_get_header` helper.
|
|
1286
|
+
*/
|
|
1287
|
+
type HeaderLookup = Headers | Map<string, string> | Record<string, string | string[] | undefined>;
|
|
1288
|
+
/**
|
|
1289
|
+
* Payload shapes accepted by `verifyWebhookSignature`.
|
|
1290
|
+
*
|
|
1291
|
+
* `Buffer extends Uint8Array` in Node, so callers passing `Buffer`
|
|
1292
|
+
* satisfy the `Uint8Array` arm. `ArrayBuffer` is explicitly accepted
|
|
1293
|
+
* for callers using Web-API request bodies. `string` is UTF-8 encoded
|
|
1294
|
+
* internally.
|
|
1295
|
+
*
|
|
1296
|
+
* Crucially, callers must pass the EXACT bytes received over the
|
|
1297
|
+
* wire. Parsing JSON and re-serializing changes byte order and
|
|
1298
|
+
* whitespace; the signature will not match.
|
|
1299
|
+
*/
|
|
1300
|
+
type WebhookPayload = Uint8Array | ArrayBuffer | string;
|
|
1301
|
+
/**
|
|
1302
|
+
* Verify a Risicare webhook delivery. Throws `WebhookVerificationError`
|
|
1303
|
+
* on any failure; returns `undefined` on success.
|
|
1304
|
+
*
|
|
1305
|
+
* @param payload Raw request body bytes — the EXACT bytes received over
|
|
1306
|
+
* the wire. Re-serializing parsed JSON will change byte ordering and
|
|
1307
|
+
* break the signature.
|
|
1308
|
+
* @param headers Header lookup. Web `Headers`, `Map<string,string>`,
|
|
1309
|
+
* Node `IncomingHttpHeaders`, or plain `Record` all work. Lookup is
|
|
1310
|
+
* case-insensitive (canonical mixed-case tried first, then lowercase).
|
|
1311
|
+
* @param secret The shared secret configured on the Risicare webhook
|
|
1312
|
+
* record. Returned by `POST /v1/webhooks` once at create time.
|
|
1313
|
+
* @param opts Optional overrides — `toleranceS` (default 300) and
|
|
1314
|
+
* `_now` (test hook).
|
|
1315
|
+
*
|
|
1316
|
+
* @throws WebhookVerificationError on any of: missing headers, malformed
|
|
1317
|
+
* signature, timestamp outside tolerance, HMAC mismatch, or invalid
|
|
1318
|
+
* payload type.
|
|
1319
|
+
*/
|
|
1320
|
+
declare function verifyWebhookSignature(payload: WebhookPayload, headers: HeaderLookup, secret: string, opts?: VerifyWebhookOptions): void;
|
|
1321
|
+
|
|
1322
|
+
export { type ActiveFix, type AgentContext, type AgentOptions, AgentRole, DEFAULT_TIMESTAMP_TOLERANCE_S, type FixRuntimeConfig, type HeaderLookup, MessageType, type RisicareConfig, SemanticPhase, type SessionContext, type SessionOptions, Span, SpanKind, type SpanOptions, SpanStatus, type StartSpanOptions, type TraceContext, type TracedStreamOptions, Tracer, type VerifyWebhookOptions, type WebhookPayload, WebhookVerificationError, agent, disable, enable, extractTraceContext, flush, getCurrentAgent, getCurrentAgentId, getCurrentContext, getCurrentPhase, getCurrentSession, getCurrentSessionId, getCurrentSpan, getCurrentSpanId, getCurrentTraceId, getFixRuntime, getMetrics, getSpanById, getTraceContent, getTraceContext, getTracer, init, initFixRuntime, injectTraceContext, isEnabled, isProviderInstrumentationSuppressed, registerSpan, reportError, score, session, shutdown, shutdownFixRuntime, suppressProviderInstrumentation, traceAct, traceCoordinate, traceDecide, traceDelegate, traceMessage, traceObserve, traceThink, tracedStream, unregisterSpan, verifyWebhookSignature, withAgent, withPhase, withSession };
|