@skillful-ai/skai-sdk 1.0.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/package.json +34 -0
- package/src/clients/admin-client.d.ts +33 -0
- package/src/clients/admin-client.js +41 -0
- package/src/clients/admin-client.js.map +1 -0
- package/src/clients/agents-client.d.ts +98 -0
- package/src/clients/agents-client.js +344 -0
- package/src/clients/agents-client.js.map +1 -0
- package/src/clients/base-client.d.ts +22 -0
- package/src/clients/base-client.js +148 -0
- package/src/clients/base-client.js.map +1 -0
- package/src/clients/index.d.ts +3 -0
- package/src/clients/index.js +7 -0
- package/src/clients/index.js.map +1 -0
- package/src/constants.d.ts +6 -0
- package/src/constants.js +13 -0
- package/src/constants.js.map +1 -0
- package/src/errors.d.ts +18 -0
- package/src/errors.js +23 -0
- package/src/errors.js.map +1 -0
- package/src/index.d.ts +37 -0
- package/src/index.js +50 -0
- package/src/index.js.map +1 -0
- package/src/streaming/index.d.ts +6 -0
- package/src/streaming/index.js +13 -0
- package/src/streaming/index.js.map +1 -0
- package/src/types/admin-api-types.d.ts +46 -0
- package/src/types/admin-api-types.js +32 -0
- package/src/types/admin-api-types.js.map +1 -0
- package/src/types/agents-api-types.d.ts +192 -0
- package/src/types/agents-api-types.js +135 -0
- package/src/types/agents-api-types.js.map +1 -0
- package/src/types/api-types.d.ts +20 -0
- package/src/types/api-types.js +12 -0
- package/src/types/api-types.js.map +1 -0
- package/src/types/index.d.ts +3 -0
- package/src/types/index.js +7 -0
- package/src/types/index.js.map +1 -0
- package/src/types/streaming.d.ts +109 -0
- package/src/types/streaming.js +55 -0
- package/src/types/streaming.js.map +1 -0
- package/src/utils/index.d.ts +1 -0
- package/src/utils/index.js +5 -0
- package/src/utils/index.js.map +1 -0
- package/src/utils/logger-adapter.d.ts +7 -0
- package/src/utils/logger-adapter.js +54 -0
- package/src/utils/logger-adapter.js.map +1 -0
- package/src/utils/skai-helpers.d.ts +19 -0
- package/src/utils/skai-helpers.js +47 -0
- package/src/utils/skai-helpers.js.map +1 -0
- package/src/utils/stream-metrics.d.ts +55 -0
- package/src/utils/stream-metrics.js +132 -0
- package/src/utils/stream-metrics.js.map +1 -0
- package/src/utils/stream-parser.d.ts +49 -0
- package/src/utils/stream-parser.js +181 -0
- package/src/utils/stream-parser.js.map +1 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { FastifyBaseLogger } from 'fastify';
|
|
2
|
+
import { SkaiAgentsClient, SkaiAgentsClientConfig } from '../clients/agents-client';
|
|
3
|
+
import { SkaiAdminClient, SkaiAdminClientConfig } from '../clients/admin-client';
|
|
4
|
+
import { Logger } from '../clients/base-client';
|
|
5
|
+
/**
|
|
6
|
+
* Factory function to create a SKAI Agents client instance
|
|
7
|
+
*/
|
|
8
|
+
export declare function createSkaiAgentsClient(log: FastifyBaseLogger | Logger, config: SkaiAgentsClientConfig): SkaiAgentsClient;
|
|
9
|
+
/**
|
|
10
|
+
* Factory function to create a SKAI Admin client instance
|
|
11
|
+
*/
|
|
12
|
+
export declare function createSkaiAdminClient(log: FastifyBaseLogger | Logger, config: SkaiAdminClientConfig): SkaiAdminClient;
|
|
13
|
+
/**
|
|
14
|
+
* SKAI API connection status checker for a given base URL
|
|
15
|
+
*/
|
|
16
|
+
export declare function checkSkaiApiStatus(log: FastifyBaseLogger | Logger, baseUrl: string): Promise<{
|
|
17
|
+
isHealthy: boolean;
|
|
18
|
+
error?: string;
|
|
19
|
+
}>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createSkaiAgentsClient = createSkaiAgentsClient;
|
|
4
|
+
exports.createSkaiAdminClient = createSkaiAdminClient;
|
|
5
|
+
exports.checkSkaiApiStatus = checkSkaiApiStatus;
|
|
6
|
+
const tslib_1 = require("tslib");
|
|
7
|
+
const agents_client_1 = require("../clients/agents-client");
|
|
8
|
+
const admin_client_1 = require("../clients/admin-client");
|
|
9
|
+
const logger_adapter_1 = require("./logger-adapter");
|
|
10
|
+
/**
|
|
11
|
+
* Factory function to create a SKAI Agents client instance
|
|
12
|
+
*/
|
|
13
|
+
function createSkaiAgentsClient(log, config) {
|
|
14
|
+
const logger = 'info' in log ? log : (0, logger_adapter_1.createFastifyLoggerAdapter)(log);
|
|
15
|
+
return new agents_client_1.SkaiAgentsClient(logger, config);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Factory function to create a SKAI Admin client instance
|
|
19
|
+
*/
|
|
20
|
+
function createSkaiAdminClient(log, config) {
|
|
21
|
+
const logger = 'info' in log ? log : (0, logger_adapter_1.createFastifyLoggerAdapter)(log);
|
|
22
|
+
return new admin_client_1.SkaiAdminClient(logger, config);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* SKAI API connection status checker for a given base URL
|
|
26
|
+
*/
|
|
27
|
+
function checkSkaiApiStatus(log, baseUrl) {
|
|
28
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
29
|
+
try {
|
|
30
|
+
const logger = 'info' in log ? log : (0, logger_adapter_1.createFastifyLoggerAdapter)(log);
|
|
31
|
+
// Create a minimal client just for health checking
|
|
32
|
+
const response = yield fetch(`${baseUrl}/api/health`);
|
|
33
|
+
const isHealthy = response.ok;
|
|
34
|
+
return { isHealthy };
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
38
|
+
const logger = 'info' in log ? log : (0, logger_adapter_1.createFastifyLoggerAdapter)(log);
|
|
39
|
+
logger.error({ error: errorMessage }, 'SKAI API health check failed');
|
|
40
|
+
return {
|
|
41
|
+
isHealthy: false,
|
|
42
|
+
error: errorMessage,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=skai-helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skai-helpers.js","sourceRoot":"","sources":["../../../../../../packages/custom/skai-sdk/src/utils/skai-helpers.ts"],"names":[],"mappings":";;AASA,wDAMC;AAKD,sDAMC;AAKD,gDAyBC;;AAvDD,4DAAmF;AACnF,0DAAgF;AAEhF,qDAA6D;AAE7D;;GAEG;AACH,SAAgB,sBAAsB,CAClC,GAA+B,EAC/B,MAA8B;IAE9B,MAAM,MAAM,GAAG,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAA,2CAA0B,EAAC,GAAG,CAAC,CAAA;IACpE,OAAO,IAAI,gCAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AAC/C,CAAC;AAED;;GAEG;AACH,SAAgB,qBAAqB,CACjC,GAA+B,EAC/B,MAA6B;IAE7B,MAAM,MAAM,GAAG,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAA,2CAA0B,EAAC,GAAG,CAAC,CAAA;IACpE,OAAO,IAAI,8BAAe,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AAC9C,CAAC;AAED;;GAEG;AACH,SAAsB,kBAAkB,CACpC,GAA+B,EAC/B,OAAe;;QAKf,IAAI,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAA,2CAA0B,EAAC,GAAG,CAAC,CAAA;YAEpE,mDAAmD;YACnD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,aAAa,CAAC,CAAA;YACrD,MAAM,SAAS,GAAG,QAAQ,CAAC,EAAE,CAAA;YAE7B,OAAO,EAAE,SAAS,EAAE,CAAA;QACxB,CAAC;QACD,OAAO,KAAK,EAAE,CAAC;YACX,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAA;YAC7E,MAAM,MAAM,GAAG,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAA,2CAA0B,EAAC,GAAG,CAAC,CAAA;YACpE,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,8BAA8B,CAAC,CAAA;YACrE,OAAO;gBACH,SAAS,EAAE,KAAK;gBAChB,KAAK,EAAE,YAAY;aACtB,CAAA;QACL,CAAC;IACL,CAAC;CAAA"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SKAI Stream Metrics Tracker
|
|
3
|
+
*/
|
|
4
|
+
import { SkaiStreamMetrics, SkaiStreamValidationResult } from '../types/streaming';
|
|
5
|
+
/**
|
|
6
|
+
* Stream metrics tracker class
|
|
7
|
+
*/
|
|
8
|
+
export declare class SkaiStreamMetricsTracker {
|
|
9
|
+
private metrics;
|
|
10
|
+
constructor(startTime?: number);
|
|
11
|
+
/**
|
|
12
|
+
* Record a chunk being received
|
|
13
|
+
*/
|
|
14
|
+
recordChunk(chunkSize: number): void;
|
|
15
|
+
/**
|
|
16
|
+
* Record a content token being processed
|
|
17
|
+
*/
|
|
18
|
+
recordToken(tokenContent: string): void;
|
|
19
|
+
/**
|
|
20
|
+
* Record stream completion
|
|
21
|
+
*/
|
|
22
|
+
recordCompletion(): void;
|
|
23
|
+
/**
|
|
24
|
+
* Get current metrics snapshot
|
|
25
|
+
*/
|
|
26
|
+
getMetrics(): Readonly<SkaiStreamMetrics>;
|
|
27
|
+
/**
|
|
28
|
+
* Get stream duration in milliseconds
|
|
29
|
+
*/
|
|
30
|
+
getDuration(): number;
|
|
31
|
+
/**
|
|
32
|
+
* Get stream duration in seconds
|
|
33
|
+
*/
|
|
34
|
+
getDurationSeconds(): number;
|
|
35
|
+
/**
|
|
36
|
+
* Get average bytes per chunk
|
|
37
|
+
*/
|
|
38
|
+
getAverageBytesPerChunk(): number;
|
|
39
|
+
/**
|
|
40
|
+
* Get time since last activity
|
|
41
|
+
*/
|
|
42
|
+
getTimeSinceLastActivity(): number;
|
|
43
|
+
/**
|
|
44
|
+
* Check if stream is considered inactive
|
|
45
|
+
*/
|
|
46
|
+
isInactive(timeoutMs: number): boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Validate stream completion and return result
|
|
49
|
+
*/
|
|
50
|
+
validateCompletion(expectedContent?: boolean): SkaiStreamValidationResult;
|
|
51
|
+
/**
|
|
52
|
+
* Generate debug log object for stream metrics
|
|
53
|
+
*/
|
|
54
|
+
toLogObject(): Record<string, unknown>;
|
|
55
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* SKAI Stream Metrics Tracker
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.SkaiStreamMetricsTracker = void 0;
|
|
7
|
+
/**
|
|
8
|
+
* Stream metrics tracker class
|
|
9
|
+
*/
|
|
10
|
+
class SkaiStreamMetricsTracker {
|
|
11
|
+
constructor(startTime = Date.now()) {
|
|
12
|
+
this.metrics = {
|
|
13
|
+
startTime,
|
|
14
|
+
endTime: 0,
|
|
15
|
+
totalChunks: 0,
|
|
16
|
+
totalBytes: 0,
|
|
17
|
+
totalTokens: 0,
|
|
18
|
+
contentLength: 0,
|
|
19
|
+
firstChunkTime: null,
|
|
20
|
+
lastActivityTime: startTime,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Record a chunk being received
|
|
25
|
+
*/
|
|
26
|
+
recordChunk(chunkSize) {
|
|
27
|
+
this.metrics.totalChunks++;
|
|
28
|
+
this.metrics.totalBytes += chunkSize;
|
|
29
|
+
this.metrics.lastActivityTime = Date.now();
|
|
30
|
+
if (this.metrics.firstChunkTime === null) {
|
|
31
|
+
this.metrics.firstChunkTime = Date.now() - this.metrics.startTime;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Record a content token being processed
|
|
36
|
+
*/
|
|
37
|
+
recordToken(tokenContent) {
|
|
38
|
+
this.metrics.totalTokens++;
|
|
39
|
+
this.metrics.contentLength += tokenContent.length;
|
|
40
|
+
this.metrics.lastActivityTime = Date.now();
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Record stream completion
|
|
44
|
+
*/
|
|
45
|
+
recordCompletion() {
|
|
46
|
+
this.metrics.endTime = Date.now();
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Get current metrics snapshot
|
|
50
|
+
*/
|
|
51
|
+
getMetrics() {
|
|
52
|
+
return Object.assign({}, this.metrics);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Get stream duration in milliseconds
|
|
56
|
+
*/
|
|
57
|
+
getDuration() {
|
|
58
|
+
const endTime = this.metrics.endTime || Date.now();
|
|
59
|
+
return endTime - this.metrics.startTime;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Get stream duration in seconds
|
|
63
|
+
*/
|
|
64
|
+
getDurationSeconds() {
|
|
65
|
+
return Number((this.getDuration() / 1000).toFixed(2));
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Get average bytes per chunk
|
|
69
|
+
*/
|
|
70
|
+
getAverageBytesPerChunk() {
|
|
71
|
+
return this.metrics.totalChunks > 0
|
|
72
|
+
? Math.round(this.metrics.totalBytes / this.metrics.totalChunks)
|
|
73
|
+
: 0;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Get time since last activity
|
|
77
|
+
*/
|
|
78
|
+
getTimeSinceLastActivity() {
|
|
79
|
+
return Date.now() - this.metrics.lastActivityTime;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Check if stream is considered inactive
|
|
83
|
+
*/
|
|
84
|
+
isInactive(timeoutMs) {
|
|
85
|
+
return this.getTimeSinceLastActivity() > timeoutMs;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Validate stream completion and return result
|
|
89
|
+
*/
|
|
90
|
+
validateCompletion(expectedContent = true) {
|
|
91
|
+
const metrics = this.getMetrics();
|
|
92
|
+
// Check if we received any content
|
|
93
|
+
if (expectedContent && metrics.totalTokens === 0 && metrics.contentLength === 0) {
|
|
94
|
+
return {
|
|
95
|
+
isValid: false,
|
|
96
|
+
errorMessage: 'Stream completed but no response content was generated',
|
|
97
|
+
metrics,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
// Check if stream actually completed (not just timed out)
|
|
101
|
+
if (metrics.endTime === 0) {
|
|
102
|
+
return {
|
|
103
|
+
isValid: false,
|
|
104
|
+
errorMessage: 'Stream did not complete normally',
|
|
105
|
+
metrics,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
return {
|
|
109
|
+
isValid: true,
|
|
110
|
+
metrics,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Generate debug log object for stream metrics
|
|
115
|
+
*/
|
|
116
|
+
toLogObject() {
|
|
117
|
+
const metrics = this.getMetrics();
|
|
118
|
+
return {
|
|
119
|
+
totalChunks: metrics.totalChunks,
|
|
120
|
+
totalBytes: metrics.totalBytes,
|
|
121
|
+
totalTokens: metrics.totalTokens,
|
|
122
|
+
contentLength: metrics.contentLength,
|
|
123
|
+
durationMs: this.getDuration(),
|
|
124
|
+
durationSeconds: this.getDurationSeconds(),
|
|
125
|
+
firstChunkTimeMs: metrics.firstChunkTime,
|
|
126
|
+
avgBytesPerChunk: this.getAverageBytesPerChunk(),
|
|
127
|
+
timeSinceLastActivityMs: this.getTimeSinceLastActivity(),
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
exports.SkaiStreamMetricsTracker = SkaiStreamMetricsTracker;
|
|
132
|
+
//# sourceMappingURL=stream-metrics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream-metrics.js","sourceRoot":"","sources":["../../../../../../packages/custom/skai-sdk/src/utils/stream-metrics.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SKAI Stream Parser Utilities
|
|
3
|
+
*/
|
|
4
|
+
import { SkaiMetadataToken, SkaiStreamLineParseResult, SkaiStreamParsingResult } from '../types/streaming';
|
|
5
|
+
/**
|
|
6
|
+
* Custom errors for SKAI streaming
|
|
7
|
+
*/
|
|
8
|
+
export declare class SkaiStreamError extends Error {
|
|
9
|
+
readonly tokenData?: unknown;
|
|
10
|
+
constructor(message: string, tokenData?: unknown);
|
|
11
|
+
}
|
|
12
|
+
export declare class SkaiStreamTimeoutError extends Error {
|
|
13
|
+
constructor(inactivityMs: number);
|
|
14
|
+
}
|
|
15
|
+
export declare class SkaiStreamValidationError extends Error {
|
|
16
|
+
constructor(message: string);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Parse a streaming line and determine its type
|
|
20
|
+
*/
|
|
21
|
+
export declare function parseStreamLine(line: string): SkaiStreamLineParseResult;
|
|
22
|
+
/**
|
|
23
|
+
* Parse and validate metadata token content
|
|
24
|
+
*/
|
|
25
|
+
export declare function parseMetadataToken(tokenJson: string): SkaiMetadataToken[];
|
|
26
|
+
/**
|
|
27
|
+
* Check if metadata token indicates an error condition
|
|
28
|
+
*/
|
|
29
|
+
export declare function checkForErrorToken(token: SkaiMetadataToken): string | null;
|
|
30
|
+
/**
|
|
31
|
+
* Process content token and extract text
|
|
32
|
+
*/
|
|
33
|
+
export declare function processContentToken(tokenJson: string): string;
|
|
34
|
+
/**
|
|
35
|
+
* Process a batch of streaming lines
|
|
36
|
+
*/
|
|
37
|
+
export declare function processStreamLines(lines: string[]): SkaiStreamParsingResult;
|
|
38
|
+
/**
|
|
39
|
+
* Create a preview of content for logging
|
|
40
|
+
*/
|
|
41
|
+
export declare function createContentPreview(content: string, maxLength?: number): string;
|
|
42
|
+
/**
|
|
43
|
+
* Check if stream has been inactive for too long
|
|
44
|
+
*/
|
|
45
|
+
export declare function checkStreamTimeout(lastActivityTime: number, currentTime?: number): void;
|
|
46
|
+
/**
|
|
47
|
+
* Validate stream completion
|
|
48
|
+
*/
|
|
49
|
+
export declare function validateStreamCompletion(tokens: number, contentLength: number): void;
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* SKAI Stream Parser Utilities
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.SkaiStreamValidationError = exports.SkaiStreamTimeoutError = exports.SkaiStreamError = void 0;
|
|
7
|
+
exports.parseStreamLine = parseStreamLine;
|
|
8
|
+
exports.parseMetadataToken = parseMetadataToken;
|
|
9
|
+
exports.checkForErrorToken = checkForErrorToken;
|
|
10
|
+
exports.processContentToken = processContentToken;
|
|
11
|
+
exports.processStreamLines = processStreamLines;
|
|
12
|
+
exports.createContentPreview = createContentPreview;
|
|
13
|
+
exports.checkStreamTimeout = checkStreamTimeout;
|
|
14
|
+
exports.validateStreamCompletion = validateStreamCompletion;
|
|
15
|
+
const streaming_1 = require("../types/streaming");
|
|
16
|
+
/**
|
|
17
|
+
* Custom errors for SKAI streaming
|
|
18
|
+
*/
|
|
19
|
+
class SkaiStreamError extends Error {
|
|
20
|
+
constructor(message, tokenData) {
|
|
21
|
+
super(`SKAI Agent Error: ${message}`);
|
|
22
|
+
this.tokenData = tokenData;
|
|
23
|
+
this.name = 'SkaiStreamError';
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
exports.SkaiStreamError = SkaiStreamError;
|
|
27
|
+
class SkaiStreamTimeoutError extends Error {
|
|
28
|
+
constructor(inactivityMs) {
|
|
29
|
+
super(`SKAI Agent stream timeout: No activity for ${Math.round(inactivityMs / 1000)} seconds`);
|
|
30
|
+
this.name = 'SkaiStreamTimeoutError';
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
exports.SkaiStreamTimeoutError = SkaiStreamTimeoutError;
|
|
34
|
+
class SkaiStreamValidationError extends Error {
|
|
35
|
+
constructor(message) {
|
|
36
|
+
super(`SKAI Agent Error: ${message}`);
|
|
37
|
+
this.name = 'SkaiStreamValidationError';
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
exports.SkaiStreamValidationError = SkaiStreamValidationError;
|
|
41
|
+
/**
|
|
42
|
+
* Parse a streaming line and determine its type
|
|
43
|
+
*/
|
|
44
|
+
function parseStreamLine(line) {
|
|
45
|
+
if (line.startsWith(`${streaming_1.SkaiTokenType.CONTENT}:`)) {
|
|
46
|
+
return { type: streaming_1.SkaiStreamLineType.CONTENT, content: line.substring(2) };
|
|
47
|
+
}
|
|
48
|
+
if (line.startsWith(`${streaming_1.SkaiTokenType.METADATA}:`)) {
|
|
49
|
+
return { type: streaming_1.SkaiStreamLineType.METADATA, content: line.substring(2) };
|
|
50
|
+
}
|
|
51
|
+
return { type: streaming_1.SkaiStreamLineType.UNKNOWN };
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Parse and validate metadata token content
|
|
55
|
+
*/
|
|
56
|
+
function parseMetadataToken(tokenJson) {
|
|
57
|
+
try {
|
|
58
|
+
const parsed = JSON.parse(tokenJson);
|
|
59
|
+
return Array.isArray(parsed) ? parsed : [parsed];
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
throw new Error(`Failed to parse metadata token: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Check if metadata token indicates an error condition
|
|
67
|
+
*/
|
|
68
|
+
function checkForErrorToken(token) {
|
|
69
|
+
var _a;
|
|
70
|
+
// Direct error token
|
|
71
|
+
if (token.type === streaming_1.SkaiMetadataType.ERROR) {
|
|
72
|
+
const errorData = token.data;
|
|
73
|
+
return (errorData === null || errorData === void 0 ? void 0 : errorData.message) || 'Unknown agent error';
|
|
74
|
+
}
|
|
75
|
+
// Exception event token
|
|
76
|
+
if (token.type === streaming_1.SkaiMetadataType.EVENTS) {
|
|
77
|
+
const eventsData = token.data;
|
|
78
|
+
const title = ((_a = eventsData === null || eventsData === void 0 ? void 0 : eventsData.title) === null || _a === void 0 ? void 0 : _a.toLowerCase()) || '';
|
|
79
|
+
for (const keyword of streaming_1.SKAI_STREAM_CONFIG.EXCEPTION_KEYWORDS) {
|
|
80
|
+
if (title.includes(keyword)) {
|
|
81
|
+
return (eventsData === null || eventsData === void 0 ? void 0 : eventsData.title) || `Exception detected: ${keyword}`;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Process content token and extract text
|
|
89
|
+
*/
|
|
90
|
+
function processContentToken(tokenJson) {
|
|
91
|
+
try {
|
|
92
|
+
return JSON.parse(tokenJson);
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
throw new Error(`Failed to parse content token: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Process a batch of streaming lines
|
|
100
|
+
*/
|
|
101
|
+
function processStreamLines(lines) {
|
|
102
|
+
const result = {
|
|
103
|
+
content: '',
|
|
104
|
+
tokens: 0,
|
|
105
|
+
isComplete: false,
|
|
106
|
+
hasErrors: false,
|
|
107
|
+
errors: [],
|
|
108
|
+
};
|
|
109
|
+
for (const line of lines) {
|
|
110
|
+
if (!line.trim())
|
|
111
|
+
continue;
|
|
112
|
+
const parsedLine = parseStreamLine(line);
|
|
113
|
+
switch (parsedLine.type) {
|
|
114
|
+
case streaming_1.SkaiStreamLineType.CONTENT:
|
|
115
|
+
try {
|
|
116
|
+
if (parsedLine.content) {
|
|
117
|
+
const contentText = processContentToken(parsedLine.content);
|
|
118
|
+
result.content += contentText;
|
|
119
|
+
result.tokens++;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
result.errors.push(error instanceof Error ? error.message : 'Content parsing error');
|
|
124
|
+
}
|
|
125
|
+
break;
|
|
126
|
+
case streaming_1.SkaiStreamLineType.METADATA:
|
|
127
|
+
try {
|
|
128
|
+
if (parsedLine.content) {
|
|
129
|
+
const tokens = parseMetadataToken(parsedLine.content);
|
|
130
|
+
for (const token of tokens) {
|
|
131
|
+
const errorMessage = checkForErrorToken(token);
|
|
132
|
+
if (errorMessage) {
|
|
133
|
+
result.hasErrors = true;
|
|
134
|
+
result.errors.push(errorMessage);
|
|
135
|
+
throw new SkaiStreamError(errorMessage, token);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
if (error instanceof SkaiStreamError) {
|
|
142
|
+
throw error; // Re-throw SKAI errors
|
|
143
|
+
}
|
|
144
|
+
result.errors.push(error instanceof Error ? error.message : 'Metadata parsing error');
|
|
145
|
+
}
|
|
146
|
+
break;
|
|
147
|
+
case streaming_1.SkaiStreamLineType.UNKNOWN:
|
|
148
|
+
default:
|
|
149
|
+
// Ignore unknown line types
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return result;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Create a preview of content for logging
|
|
157
|
+
*/
|
|
158
|
+
function createContentPreview(content, maxLength = streaming_1.SKAI_STREAM_CONFIG.TOKEN_PREVIEW_LENGTH) {
|
|
159
|
+
if (content.length <= maxLength) {
|
|
160
|
+
return content;
|
|
161
|
+
}
|
|
162
|
+
return content.substring(0, maxLength) + '...';
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Check if stream has been inactive for too long
|
|
166
|
+
*/
|
|
167
|
+
function checkStreamTimeout(lastActivityTime, currentTime = Date.now()) {
|
|
168
|
+
const inactivityMs = currentTime - lastActivityTime;
|
|
169
|
+
if (inactivityMs > streaming_1.SKAI_STREAM_CONFIG.INACTIVITY_TIMEOUT_MS) {
|
|
170
|
+
throw new SkaiStreamTimeoutError(inactivityMs);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Validate stream completion
|
|
175
|
+
*/
|
|
176
|
+
function validateStreamCompletion(tokens, contentLength) {
|
|
177
|
+
if (tokens === 0 && contentLength === 0) {
|
|
178
|
+
throw new SkaiStreamValidationError('Stream completed but no response content was generated');
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=stream-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream-parser.js","sourceRoot":"","sources":["../../../../../../packages/custom/skai-sdk/src/utils/stream-parser.ts"],"names":[],"mappings":"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"}
|