@inkeep/agents-run-api 0.0.0-dev-20250910232631
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/LICENSE.md +49 -0
- package/README.md +117 -0
- package/dist/__tests__/setup.d.ts +4 -0
- package/dist/__tests__/setup.d.ts.map +1 -0
- package/dist/__tests__/setup.js +80 -0
- package/dist/__tests__/utils/testProject.d.ts +18 -0
- package/dist/__tests__/utils/testProject.d.ts.map +1 -0
- package/dist/__tests__/utils/testProject.js +26 -0
- package/dist/__tests__/utils/testRequest.d.ts +8 -0
- package/dist/__tests__/utils/testRequest.d.ts.map +1 -0
- package/dist/__tests__/utils/testRequest.js +32 -0
- package/dist/__tests__/utils/testTenant.d.ts +64 -0
- package/dist/__tests__/utils/testTenant.d.ts.map +1 -0
- package/dist/__tests__/utils/testTenant.js +71 -0
- package/dist/a2a/client.d.ts +182 -0
- package/dist/a2a/client.d.ts.map +1 -0
- package/dist/a2a/client.js +645 -0
- package/dist/a2a/handlers.d.ts +4 -0
- package/dist/a2a/handlers.d.ts.map +1 -0
- package/dist/a2a/handlers.js +656 -0
- package/dist/a2a/transfer.d.ts +18 -0
- package/dist/a2a/transfer.d.ts.map +1 -0
- package/dist/a2a/transfer.js +22 -0
- package/dist/a2a/types.d.ts +63 -0
- package/dist/a2a/types.d.ts.map +1 -0
- package/dist/a2a/types.js +1 -0
- package/dist/agents/Agent.d.ts +151 -0
- package/dist/agents/Agent.d.ts.map +1 -0
- package/dist/agents/Agent.js +1164 -0
- package/dist/agents/ModelFactory.d.ts +62 -0
- package/dist/agents/ModelFactory.d.ts.map +1 -0
- package/dist/agents/ModelFactory.js +208 -0
- package/dist/agents/SystemPromptBuilder.d.ts +14 -0
- package/dist/agents/SystemPromptBuilder.d.ts.map +1 -0
- package/dist/agents/SystemPromptBuilder.js +62 -0
- package/dist/agents/ToolSessionManager.d.ts +53 -0
- package/dist/agents/ToolSessionManager.d.ts.map +1 -0
- package/dist/agents/ToolSessionManager.js +106 -0
- package/dist/agents/artifactTools.d.ts +30 -0
- package/dist/agents/artifactTools.d.ts.map +1 -0
- package/dist/agents/artifactTools.js +463 -0
- package/dist/agents/generateTaskHandler.d.ts +41 -0
- package/dist/agents/generateTaskHandler.d.ts.map +1 -0
- package/dist/agents/generateTaskHandler.js +350 -0
- package/dist/agents/relationTools.d.ts +35 -0
- package/dist/agents/relationTools.d.ts.map +1 -0
- package/dist/agents/relationTools.js +246 -0
- package/dist/agents/types.d.ts +23 -0
- package/dist/agents/types.d.ts.map +1 -0
- package/dist/agents/types.js +1 -0
- package/dist/agents/versions/V1Config.d.ts +21 -0
- package/dist/agents/versions/V1Config.d.ts.map +1 -0
- package/dist/agents/versions/V1Config.js +285 -0
- package/dist/app.d.ts +5 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +219 -0
- package/dist/data/agentGraph.d.ts +4 -0
- package/dist/data/agentGraph.d.ts.map +1 -0
- package/dist/data/agentGraph.js +73 -0
- package/dist/data/agents.d.ts +4 -0
- package/dist/data/agents.d.ts.map +1 -0
- package/dist/data/agents.js +78 -0
- package/dist/data/conversations.d.ts +59 -0
- package/dist/data/conversations.d.ts.map +1 -0
- package/dist/data/conversations.js +216 -0
- package/dist/data/db/clean.d.ts +6 -0
- package/dist/data/db/clean.d.ts.map +1 -0
- package/dist/data/db/clean.js +77 -0
- package/dist/data/db/dbClient.d.ts +3 -0
- package/dist/data/db/dbClient.d.ts.map +1 -0
- package/dist/data/db/dbClient.js +13 -0
- package/dist/env.d.ts +45 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +64 -0
- package/dist/handlers/executionHandler.d.ts +36 -0
- package/dist/handlers/executionHandler.d.ts.map +1 -0
- package/dist/handlers/executionHandler.js +415 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/instrumentation.d.ts +13 -0
- package/dist/instrumentation.d.ts.map +1 -0
- package/dist/instrumentation.js +66 -0
- package/dist/logger.d.ts +4 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +32 -0
- package/dist/middleware/api-key-auth.d.ts +22 -0
- package/dist/middleware/api-key-auth.d.ts.map +1 -0
- package/dist/middleware/api-key-auth.js +139 -0
- package/dist/middleware/index.d.ts +2 -0
- package/dist/middleware/index.d.ts.map +1 -0
- package/dist/middleware/index.js +1 -0
- package/dist/openapi.d.ts +2 -0
- package/dist/openapi.d.ts.map +1 -0
- package/dist/openapi.js +36 -0
- package/dist/routes/agents.d.ts +10 -0
- package/dist/routes/agents.d.ts.map +1 -0
- package/dist/routes/agents.js +158 -0
- package/dist/routes/chat.d.ts +10 -0
- package/dist/routes/chat.d.ts.map +1 -0
- package/dist/routes/chat.js +307 -0
- package/dist/routes/chatDataStream.d.ts +10 -0
- package/dist/routes/chatDataStream.d.ts.map +1 -0
- package/dist/routes/chatDataStream.js +185 -0
- package/dist/routes/mcp.d.ts +10 -0
- package/dist/routes/mcp.d.ts.map +1 -0
- package/dist/routes/mcp.js +500 -0
- package/dist/tracer.d.ts +24 -0
- package/dist/tracer.d.ts.map +1 -0
- package/dist/tracer.js +107 -0
- package/dist/types/chat.d.ts +25 -0
- package/dist/types/chat.d.ts.map +1 -0
- package/dist/types/chat.js +1 -0
- package/dist/types/execution-context.d.ts +14 -0
- package/dist/types/execution-context.d.ts.map +1 -0
- package/dist/types/execution-context.js +14 -0
- package/dist/utils/agent-operations.d.ts +93 -0
- package/dist/utils/agent-operations.d.ts.map +1 -0
- package/dist/utils/agent-operations.js +78 -0
- package/dist/utils/artifact-component-schema.d.ts +29 -0
- package/dist/utils/artifact-component-schema.d.ts.map +1 -0
- package/dist/utils/artifact-component-schema.js +119 -0
- package/dist/utils/artifact-parser.d.ts +71 -0
- package/dist/utils/artifact-parser.d.ts.map +1 -0
- package/dist/utils/artifact-parser.js +253 -0
- package/dist/utils/cleanup.d.ts +19 -0
- package/dist/utils/cleanup.d.ts.map +1 -0
- package/dist/utils/cleanup.js +66 -0
- package/dist/utils/data-component-schema.d.ts +6 -0
- package/dist/utils/data-component-schema.d.ts.map +1 -0
- package/dist/utils/data-component-schema.js +43 -0
- package/dist/utils/graph-session.d.ts +230 -0
- package/dist/utils/graph-session.d.ts.map +1 -0
- package/dist/utils/graph-session.js +1199 -0
- package/dist/utils/incremental-stream-parser.d.ts +62 -0
- package/dist/utils/incremental-stream-parser.d.ts.map +1 -0
- package/dist/utils/incremental-stream-parser.js +330 -0
- package/dist/utils/response-formatter.d.ts +26 -0
- package/dist/utils/response-formatter.d.ts.map +1 -0
- package/dist/utils/response-formatter.js +158 -0
- package/dist/utils/stream-helpers.d.ts +186 -0
- package/dist/utils/stream-helpers.d.ts.map +1 -0
- package/dist/utils/stream-helpers.js +603 -0
- package/dist/utils/stream-registry.d.ts +18 -0
- package/dist/utils/stream-registry.d.ts.map +1 -0
- package/dist/utils/stream-registry.js +33 -0
- package/package.json +95 -0
- package/templates/v1/artifact.xml +7 -0
- package/templates/v1/data-component.xml +9 -0
- package/templates/v1/system-prompt.xml +52 -0
- package/templates/v1/thinking-preparation.xml +34 -0
- package/templates/v1/tool.xml +12 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Create execution context from middleware values
|
|
3
|
+
*/
|
|
4
|
+
export function createExecutionContext(params) {
|
|
5
|
+
return {
|
|
6
|
+
apiKey: params.apiKey,
|
|
7
|
+
tenantId: params.tenantId,
|
|
8
|
+
projectId: params.projectId,
|
|
9
|
+
graphId: params.graphId,
|
|
10
|
+
baseUrl: params.baseUrl || process.env.API_URL || 'http://localhost:3003',
|
|
11
|
+
apiKeyId: params.apiKeyId,
|
|
12
|
+
agentId: params.agentId,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent initialization operation event
|
|
3
|
+
*/
|
|
4
|
+
export interface AgentInitializingEvent {
|
|
5
|
+
type: 'agent_initializing';
|
|
6
|
+
ctx: {
|
|
7
|
+
sessionId: string;
|
|
8
|
+
graphId: string;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Agent ready operation event
|
|
13
|
+
*/
|
|
14
|
+
export interface AgentReadyEvent {
|
|
15
|
+
type: 'agent_ready';
|
|
16
|
+
ctx: {
|
|
17
|
+
sessionId: string;
|
|
18
|
+
graphId: string;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Completion operation event
|
|
23
|
+
*/
|
|
24
|
+
export interface CompletionEvent {
|
|
25
|
+
type: 'completion';
|
|
26
|
+
ctx: {
|
|
27
|
+
agent: string;
|
|
28
|
+
iteration: number;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Error operation event
|
|
33
|
+
*/
|
|
34
|
+
export interface ErrorEvent {
|
|
35
|
+
type: 'error';
|
|
36
|
+
ctx: {
|
|
37
|
+
error: string;
|
|
38
|
+
agent?: string;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Agent thinking operation event
|
|
43
|
+
*/
|
|
44
|
+
export interface AgentThinkingEvent {
|
|
45
|
+
type: 'agent_thinking';
|
|
46
|
+
ctx: {
|
|
47
|
+
agent: string;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Status update operation event with flexible structured/unstructured data
|
|
52
|
+
*/
|
|
53
|
+
export interface StatusUpdateEvent {
|
|
54
|
+
type: 'status_update';
|
|
55
|
+
label?: string;
|
|
56
|
+
ctx: {
|
|
57
|
+
summary?: string;
|
|
58
|
+
[key: string]: any;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Discriminated union of all operation events
|
|
63
|
+
*/
|
|
64
|
+
export type OperationEvent = AgentInitializingEvent | AgentReadyEvent | AgentThinkingEvent | CompletionEvent | ErrorEvent | StatusUpdateEvent;
|
|
65
|
+
/**
|
|
66
|
+
* Creates an agent initializing operation
|
|
67
|
+
*/
|
|
68
|
+
export declare function agentInitializingOp(sessionId: string, graphId: string): AgentInitializingEvent;
|
|
69
|
+
/**
|
|
70
|
+
* Creates an agent ready operation
|
|
71
|
+
*/
|
|
72
|
+
export declare function agentReadyOp(sessionId: string, graphId: string): AgentReadyEvent;
|
|
73
|
+
/**
|
|
74
|
+
* Creates an agent thinking operation
|
|
75
|
+
*/
|
|
76
|
+
export declare function agentThinkingOp(agent: string): AgentThinkingEvent;
|
|
77
|
+
/**
|
|
78
|
+
* Creates a completion operation
|
|
79
|
+
*/
|
|
80
|
+
export declare function completionOp(agentId: string, iterations: number): CompletionEvent;
|
|
81
|
+
/**
|
|
82
|
+
* Creates an error operation
|
|
83
|
+
*/
|
|
84
|
+
export declare function errorOp(error: string, agentId?: string): ErrorEvent;
|
|
85
|
+
/**
|
|
86
|
+
* Generate a unique tool execution ID for lifecycle tracking
|
|
87
|
+
*/
|
|
88
|
+
export declare function generateToolId(): string;
|
|
89
|
+
/**
|
|
90
|
+
* Creates a status update operation with flexible data
|
|
91
|
+
*/
|
|
92
|
+
export declare function statusUpdateOp(ctx: Record<string, any>): StatusUpdateEvent;
|
|
93
|
+
//# sourceMappingURL=agent-operations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-operations.d.ts","sourceRoot":"","sources":["../../src/utils/agent-operations.ts"],"names":[],"mappings":"AAMA;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,oBAAoB,CAAC;IAC3B,GAAG,EAAE;QACH,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,aAAa,CAAC;IACpB,GAAG,EAAE;QACH,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,YAAY,CAAC;IACnB,GAAG,EAAE;QACH,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,OAAO,CAAC;IACd,GAAG,EAAE;QACH,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,gBAAgB,CAAC;IACvB,GAAG,EAAE;QACH,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,eAAe,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,EAAE;QACH,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACpB,CAAC;CACH;AAED;;GAEG;AACH,MAAM,MAAM,cAAc,GACtB,sBAAsB,GACtB,eAAe,GACf,kBAAkB,GAClB,eAAe,GACf,UAAU,GACV,iBAAiB,CAAC;AAMtB;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,sBAAsB,CAQ9F;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,eAAe,CAQhF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,kBAAkB,CAOjE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,eAAe,CAQjF;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,UAAU,CAQnE;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,iBAAiB,CAK1E"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { nanoid } from 'nanoid';
|
|
2
|
+
// =============================================================================
|
|
3
|
+
// OPERATION FUNCTIONS
|
|
4
|
+
// =============================================================================
|
|
5
|
+
/**
|
|
6
|
+
* Creates an agent initializing operation
|
|
7
|
+
*/
|
|
8
|
+
export function agentInitializingOp(sessionId, graphId) {
|
|
9
|
+
return {
|
|
10
|
+
type: 'agent_initializing',
|
|
11
|
+
ctx: {
|
|
12
|
+
sessionId,
|
|
13
|
+
graphId,
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Creates an agent ready operation
|
|
19
|
+
*/
|
|
20
|
+
export function agentReadyOp(sessionId, graphId) {
|
|
21
|
+
return {
|
|
22
|
+
type: 'agent_ready',
|
|
23
|
+
ctx: {
|
|
24
|
+
sessionId,
|
|
25
|
+
graphId,
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Creates an agent thinking operation
|
|
31
|
+
*/
|
|
32
|
+
export function agentThinkingOp(agent) {
|
|
33
|
+
return {
|
|
34
|
+
type: 'agent_thinking',
|
|
35
|
+
ctx: {
|
|
36
|
+
agent,
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Creates a completion operation
|
|
42
|
+
*/
|
|
43
|
+
export function completionOp(agentId, iterations) {
|
|
44
|
+
return {
|
|
45
|
+
type: 'completion',
|
|
46
|
+
ctx: {
|
|
47
|
+
agent: agentId,
|
|
48
|
+
iteration: iterations,
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Creates an error operation
|
|
54
|
+
*/
|
|
55
|
+
export function errorOp(error, agentId) {
|
|
56
|
+
return {
|
|
57
|
+
type: 'error',
|
|
58
|
+
ctx: {
|
|
59
|
+
error,
|
|
60
|
+
agent: agentId,
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Generate a unique tool execution ID for lifecycle tracking
|
|
66
|
+
*/
|
|
67
|
+
export function generateToolId() {
|
|
68
|
+
return `tool_${nanoid(8)}`;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Creates a status update operation with flexible data
|
|
72
|
+
*/
|
|
73
|
+
export function statusUpdateOp(ctx) {
|
|
74
|
+
return {
|
|
75
|
+
type: 'status_update',
|
|
76
|
+
ctx,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { ArtifactComponentApiSelect, DataComponentInsert } from '@inkeep/agents-core';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
/**
|
|
4
|
+
* Converts artifact component configurations to Zod schema for structured generation
|
|
5
|
+
*/
|
|
6
|
+
export declare function createArtifactComponentsSchema(artifactComponents?: ArtifactComponentApiSelect[]): z.ZodObject<{}, z.core.$strip> | z.ZodUnion<any>;
|
|
7
|
+
/**
|
|
8
|
+
* Create schema for artifact component summary props only (for quick display)
|
|
9
|
+
*/
|
|
10
|
+
export declare function createArtifactComponentsSummarySchema(artifactComponents?: ArtifactComponentApiSelect[]): z.ZodUnion<any> | z.ZodObject<{}, z.core.$strip>;
|
|
11
|
+
/**
|
|
12
|
+
* Create schema for artifact component full props only (for detailed display)
|
|
13
|
+
*/
|
|
14
|
+
export declare function createArtifactComponentsFullSchema(artifactComponents?: ArtifactComponentApiSelect[]): z.ZodUnion<any> | z.ZodObject<{}, z.core.$strip>;
|
|
15
|
+
/**
|
|
16
|
+
* Standard artifact reference component schema for tool responses
|
|
17
|
+
*/
|
|
18
|
+
export declare class ArtifactReferenceSchema {
|
|
19
|
+
private static readonly ARTIFACT_PROPS_SCHEMA;
|
|
20
|
+
/**
|
|
21
|
+
* Get the standard Zod schema for artifact reference components
|
|
22
|
+
*/
|
|
23
|
+
static getSchema(): z.ZodType<any>;
|
|
24
|
+
/**
|
|
25
|
+
* Get complete DataComponent by adding missing fields to base definition
|
|
26
|
+
*/
|
|
27
|
+
static getDataComponent(tenantId: string, projectId?: string): DataComponentInsert;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=artifact-component-schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifact-component-schema.d.ts","sourceRoot":"","sources":["../../src/utils/artifact-component-schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC3F,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB;;GAEG;AACH,wBAAgB,8BAA8B,CAAC,kBAAkB,CAAC,EAAE,0BAA0B,EAAE,oDA2B/F;AAED;;GAEG;AACH,wBAAgB,qCAAqC,CACnD,kBAAkB,CAAC,EAAE,0BAA0B,EAAE,oDAsBlD;AAED;;GAEG;AACH,wBAAgB,kCAAkC,CAChD,kBAAkB,CAAC,EAAE,0BAA0B,EAAE,oDAsBlD;AAED;;GAEG;AACH,qBAAa,uBAAuB;IAElC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,qBAAqB,CAe3C;IAEF;;OAEG;IACH,MAAM,CAAC,SAAS,IAAI,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC;IAQlC;;OAEG;IACH,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,GAAE,MAAW,GAAG,mBAAmB;CAWvF"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { getLogger } from '../logger';
|
|
3
|
+
import { jsonSchemaToZod } from './data-component-schema';
|
|
4
|
+
const _logger = getLogger('ArtifactComponentSchema');
|
|
5
|
+
/**
|
|
6
|
+
* Converts artifact component configurations to Zod schema for structured generation
|
|
7
|
+
*/
|
|
8
|
+
export function createArtifactComponentsSchema(artifactComponents) {
|
|
9
|
+
// Convert artifact component configs to a union schema
|
|
10
|
+
const componentSchemas = artifactComponents?.map((component) => {
|
|
11
|
+
// Convert the JSON Schema props to Zod - handle both summaryProps and fullProps
|
|
12
|
+
const summaryPropsSchema = jsonSchemaToZod(component.summaryProps);
|
|
13
|
+
const fullPropsSchema = jsonSchemaToZod(component.fullProps);
|
|
14
|
+
// Return schema with both summary and full props
|
|
15
|
+
return z
|
|
16
|
+
.object({
|
|
17
|
+
id: z.string().describe(component.id),
|
|
18
|
+
name: z.literal(component.name).describe(component.name),
|
|
19
|
+
summaryProps: summaryPropsSchema,
|
|
20
|
+
fullProps: fullPropsSchema,
|
|
21
|
+
})
|
|
22
|
+
.describe(`${component.name}: ${component.description}`);
|
|
23
|
+
}) || [];
|
|
24
|
+
// Return union of all component schemas - z.union requires at least 2 schemas
|
|
25
|
+
if (componentSchemas.length === 0) {
|
|
26
|
+
return z.object({}); // Empty object for no components
|
|
27
|
+
}
|
|
28
|
+
if (componentSchemas.length === 1) {
|
|
29
|
+
return componentSchemas[0]; // Single schema doesn't need union
|
|
30
|
+
}
|
|
31
|
+
return z.union(componentSchemas); // Safe union with 2+ schemas
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Create schema for artifact component summary props only (for quick display)
|
|
35
|
+
*/
|
|
36
|
+
export function createArtifactComponentsSummarySchema(artifactComponents) {
|
|
37
|
+
const componentSchemas = artifactComponents?.map((component) => {
|
|
38
|
+
const summaryPropsSchema = jsonSchemaToZod(component.summaryProps);
|
|
39
|
+
return z
|
|
40
|
+
.object({
|
|
41
|
+
id: z.string().describe(component.id),
|
|
42
|
+
name: z.literal(component.name).describe(component.name),
|
|
43
|
+
summaryProps: summaryPropsSchema,
|
|
44
|
+
})
|
|
45
|
+
.describe(`${component.name} Summary: ${component.description}`);
|
|
46
|
+
}) || [];
|
|
47
|
+
if (componentSchemas.length === 0) {
|
|
48
|
+
return z.object({});
|
|
49
|
+
}
|
|
50
|
+
if (componentSchemas.length === 1) {
|
|
51
|
+
return componentSchemas[0];
|
|
52
|
+
}
|
|
53
|
+
return z.union(componentSchemas);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Create schema for artifact component full props only (for detailed display)
|
|
57
|
+
*/
|
|
58
|
+
export function createArtifactComponentsFullSchema(artifactComponents) {
|
|
59
|
+
const componentSchemas = artifactComponents?.map((component) => {
|
|
60
|
+
const fullPropsSchema = jsonSchemaToZod(component.fullProps);
|
|
61
|
+
return z
|
|
62
|
+
.object({
|
|
63
|
+
id: z.string().describe(component.id),
|
|
64
|
+
name: z.literal(component.name).describe(component.name),
|
|
65
|
+
fullProps: fullPropsSchema,
|
|
66
|
+
})
|
|
67
|
+
.describe(`${component.name} Full: ${component.description}`);
|
|
68
|
+
}) || [];
|
|
69
|
+
if (componentSchemas.length === 0) {
|
|
70
|
+
return z.object({});
|
|
71
|
+
}
|
|
72
|
+
if (componentSchemas.length === 1) {
|
|
73
|
+
return componentSchemas[0];
|
|
74
|
+
}
|
|
75
|
+
return z.union(componentSchemas);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Standard artifact reference component schema for tool responses
|
|
79
|
+
*/
|
|
80
|
+
export class ArtifactReferenceSchema {
|
|
81
|
+
// Standard artifact props schema - single source of truth
|
|
82
|
+
static ARTIFACT_PROPS_SCHEMA = {
|
|
83
|
+
type: 'object',
|
|
84
|
+
properties: {
|
|
85
|
+
artifact_id: {
|
|
86
|
+
type: 'string',
|
|
87
|
+
description: 'The EXACT artifact_id from save_tool_result tool output. NEVER invent or make up IDs.',
|
|
88
|
+
},
|
|
89
|
+
task_id: {
|
|
90
|
+
type: 'string',
|
|
91
|
+
description: 'The EXACT task_id from save_tool_result tool output. NEVER invent or make up IDs.',
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
required: ['artifact_id', 'task_id'],
|
|
95
|
+
};
|
|
96
|
+
/**
|
|
97
|
+
* Get the standard Zod schema for artifact reference components
|
|
98
|
+
*/
|
|
99
|
+
static getSchema() {
|
|
100
|
+
return z.object({
|
|
101
|
+
id: z.string(),
|
|
102
|
+
name: z.literal('Artifact'),
|
|
103
|
+
props: jsonSchemaToZod(ArtifactReferenceSchema.ARTIFACT_PROPS_SCHEMA),
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Get complete DataComponent by adding missing fields to base definition
|
|
108
|
+
*/
|
|
109
|
+
static getDataComponent(tenantId, projectId = '') {
|
|
110
|
+
return {
|
|
111
|
+
id: 'The EXACT artifact_id from save_tool_result tool output. NEVER invent or make up IDs.',
|
|
112
|
+
tenantId: tenantId,
|
|
113
|
+
projectId: projectId,
|
|
114
|
+
name: 'Artifact',
|
|
115
|
+
description: 'Reference to saved content from tool results that grounds information in verifiable sources.',
|
|
116
|
+
props: ArtifactReferenceSchema.ARTIFACT_PROPS_SCHEMA,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
export interface StreamPart {
|
|
2
|
+
kind: 'text' | 'data';
|
|
3
|
+
text?: string;
|
|
4
|
+
data?: any;
|
|
5
|
+
}
|
|
6
|
+
export interface ArtifactData {
|
|
7
|
+
artifactId: string;
|
|
8
|
+
taskId: string;
|
|
9
|
+
name: string;
|
|
10
|
+
description: string;
|
|
11
|
+
artifactType?: string;
|
|
12
|
+
artifactSummary: any;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Unified artifact parser that handles all artifact-related parsing and formatting
|
|
16
|
+
* Used by both ResponseFormatter and IncrementalStreamParser to eliminate redundancy
|
|
17
|
+
*/
|
|
18
|
+
export declare class ArtifactParser {
|
|
19
|
+
private tenantId;
|
|
20
|
+
private static readonly ARTIFACT_REGEX;
|
|
21
|
+
private static readonly ARTIFACT_CHECK_REGEX;
|
|
22
|
+
private static readonly INCOMPLETE_ARTIFACT_REGEX;
|
|
23
|
+
constructor(tenantId: string);
|
|
24
|
+
/**
|
|
25
|
+
* Check if text contains complete artifact markers
|
|
26
|
+
*/
|
|
27
|
+
hasArtifactMarkers(text: string): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Check if text has incomplete artifact marker (for streaming)
|
|
30
|
+
* More robust detection that handles streaming fragments
|
|
31
|
+
*/
|
|
32
|
+
hasIncompleteArtifact(text: string): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Find safe text boundary before incomplete artifacts (for streaming)
|
|
35
|
+
* Enhanced to handle streaming chunks that split in the middle of artifacts
|
|
36
|
+
*/
|
|
37
|
+
findSafeTextBoundary(text: string): number;
|
|
38
|
+
/**
|
|
39
|
+
* Get all artifacts for a context (with caching opportunity)
|
|
40
|
+
*/
|
|
41
|
+
getContextArtifacts(contextId: string): Promise<Map<string, any>>;
|
|
42
|
+
/**
|
|
43
|
+
* Convert raw artifact to standardized data format
|
|
44
|
+
*/
|
|
45
|
+
private formatArtifactData;
|
|
46
|
+
/**
|
|
47
|
+
* Parse text with artifact markers into parts array
|
|
48
|
+
* Can work with or without pre-fetched artifact map
|
|
49
|
+
*/
|
|
50
|
+
parseText(text: string, artifactMap?: Map<string, any>): Promise<StreamPart[]>;
|
|
51
|
+
/**
|
|
52
|
+
* Process object/dataComponents for artifact components
|
|
53
|
+
*/
|
|
54
|
+
parseObject(obj: any, artifactMap?: Map<string, any>): Promise<StreamPart[]>;
|
|
55
|
+
/**
|
|
56
|
+
* Check if object is an artifact component
|
|
57
|
+
*/
|
|
58
|
+
private isArtifactComponent;
|
|
59
|
+
/**
|
|
60
|
+
* Get artifact data from map or fetch directly
|
|
61
|
+
*/
|
|
62
|
+
private getArtifactData;
|
|
63
|
+
/**
|
|
64
|
+
* Parse partial JSON buffer (for streaming)
|
|
65
|
+
*/
|
|
66
|
+
parsePartialJSON(buffer: string): {
|
|
67
|
+
complete: any[];
|
|
68
|
+
remaining: string;
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=artifact-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifact-parser.d.ts","sourceRoot":"","sources":["../../src/utils/artifact-parser.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,GAAG,CAAC;CACZ;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,GAAG,CAAC;CACtB;AAED;;;GAGG;AACH,qBAAa,cAAc;IAWb,OAAO,CAAC,QAAQ;IAT5B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CACsB;IAC5D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,oBAAoB,CACmB;IAG/D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,yBAAyB,CACQ;gBAErC,QAAQ,EAAE,MAAM;IAEpC;;OAEG;IACH,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAIzC;;;OAGG;IACH,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAU5C;;;OAGG;IACH,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAqC1C;;OAEG;IACG,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAqCvE;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAW1B;;;OAGG;IACG,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IA2CpF;;OAEG;IACG,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,WAAW,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAoClF;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAI3B;;OAEG;YACW,eAAe;IAwC7B;;OAEG;IACH,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG;QAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE;CA2BzE"}
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import { getLedgerArtifacts, getTask, listTaskIdsByContextId } from '@inkeep/agents-core';
|
|
2
|
+
import dbClient from '../data/db/dbClient';
|
|
3
|
+
import { getLogger } from '../logger';
|
|
4
|
+
const logger = getLogger('ArtifactParser');
|
|
5
|
+
/**
|
|
6
|
+
* Unified artifact parser that handles all artifact-related parsing and formatting
|
|
7
|
+
* Used by both ResponseFormatter and IncrementalStreamParser to eliminate redundancy
|
|
8
|
+
*/
|
|
9
|
+
export class ArtifactParser {
|
|
10
|
+
tenantId;
|
|
11
|
+
// Shared regex patterns
|
|
12
|
+
static ARTIFACT_REGEX = /<artifact:ref\s+id="([^"]*?)"\s+task="([^"]*?)"\s*\/>/gs;
|
|
13
|
+
static ARTIFACT_CHECK_REGEX = /<artifact:ref\s+(?=.*id="[^"]+")(?=.*task="[^"]+")[^>]*\/>/;
|
|
14
|
+
// Regex for catching any partial artifact pattern (< + any prefix of "artifact:ref")
|
|
15
|
+
static INCOMPLETE_ARTIFACT_REGEX = /<(a(r(t(i(f(a(c(t(:(r(e(f?)?)?)?)?)?)?)?)?)?)?)?)?$/g;
|
|
16
|
+
constructor(tenantId) {
|
|
17
|
+
this.tenantId = tenantId;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Check if text contains complete artifact markers
|
|
21
|
+
*/
|
|
22
|
+
hasArtifactMarkers(text) {
|
|
23
|
+
return ArtifactParser.ARTIFACT_CHECK_REGEX.test(text);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Check if text has incomplete artifact marker (for streaming)
|
|
27
|
+
* More robust detection that handles streaming fragments
|
|
28
|
+
*/
|
|
29
|
+
hasIncompleteArtifact(text) {
|
|
30
|
+
// Use safe, non-backtracking patterns to prevent ReDoS attacks
|
|
31
|
+
// Check if text ends with any partial artifact pattern
|
|
32
|
+
return (/^.*<(?:artifact(?::ref)?|a(?:r(?:t(?:i(?:f(?:a(?:c(?:t(?::(?:r(?:e(?:f)?)?)?)?)?)?)?)?)?)?)?)?$/.test(text) ||
|
|
33
|
+
/^.*<artifact:ref(?:[^>]*)$/.test(text) || // Incomplete artifact:ref at end
|
|
34
|
+
this.findSafeTextBoundary(text) < text.length);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Find safe text boundary before incomplete artifacts (for streaming)
|
|
38
|
+
* Enhanced to handle streaming chunks that split in the middle of artifacts
|
|
39
|
+
*/
|
|
40
|
+
findSafeTextBoundary(text) {
|
|
41
|
+
// First check for incomplete artifact patterns at the end
|
|
42
|
+
// Use safe patterns that don't cause exponential backtracking
|
|
43
|
+
const endPatterns = [
|
|
44
|
+
/^.*<artifact:ref(?:[^/>]+(?:[^>]*[^/])?)?$/, // artifact:ref that doesn't end with />
|
|
45
|
+
/^.*<(?:artifact(?::ref)?|a(?:r(?:t(?:i(?:f(?:a(?:c(?:t(?::(?:r(?:e(?:f)?)?)?)?)?)?)?)?)?)?)?)?$/, // Safe partial artifact pattern
|
|
46
|
+
];
|
|
47
|
+
for (const pattern of endPatterns) {
|
|
48
|
+
const match = text.match(pattern);
|
|
49
|
+
if (match && match.index !== undefined) {
|
|
50
|
+
return match.index;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// Look for incomplete artifact patterns anywhere in text
|
|
54
|
+
const matches = [...text.matchAll(ArtifactParser.INCOMPLETE_ARTIFACT_REGEX)];
|
|
55
|
+
if (matches.length === 0) {
|
|
56
|
+
return text.length;
|
|
57
|
+
}
|
|
58
|
+
// Check each match from the end to find an incomplete artifact
|
|
59
|
+
for (let i = matches.length - 1; i >= 0; i--) {
|
|
60
|
+
const match = matches[i];
|
|
61
|
+
const startIdx = match.index;
|
|
62
|
+
const textAfterMatch = text.slice(startIdx);
|
|
63
|
+
// If the text after this match doesn't contain a closing '/>', it's incomplete
|
|
64
|
+
if (!textAfterMatch.includes('/>')) {
|
|
65
|
+
return startIdx;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return text.length;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Get all artifacts for a context (with caching opportunity)
|
|
72
|
+
*/
|
|
73
|
+
async getContextArtifacts(contextId) {
|
|
74
|
+
const artifacts = new Map();
|
|
75
|
+
try {
|
|
76
|
+
const taskIds = await listTaskIdsByContextId(dbClient)({
|
|
77
|
+
contextId: contextId,
|
|
78
|
+
});
|
|
79
|
+
for (const taskId of taskIds) {
|
|
80
|
+
// Get task to retrieve projectId
|
|
81
|
+
const task = await getTask(dbClient)({
|
|
82
|
+
id: taskId,
|
|
83
|
+
});
|
|
84
|
+
if (!task) {
|
|
85
|
+
logger.warn({ taskId }, 'Task not found when fetching artifacts');
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
const taskArtifacts = await getLedgerArtifacts(dbClient)({
|
|
89
|
+
scopes: { tenantId: this.tenantId, projectId: task.projectId },
|
|
90
|
+
taskId,
|
|
91
|
+
});
|
|
92
|
+
for (const artifact of taskArtifacts) {
|
|
93
|
+
const key = `${artifact.artifactId}:${artifact.taskId}`;
|
|
94
|
+
artifacts.set(key, artifact);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
logger.debug({ contextId, count: artifacts.size }, 'Loaded context artifacts');
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
logger.error({ error, contextId }, 'Error loading context artifacts');
|
|
101
|
+
}
|
|
102
|
+
return artifacts;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Convert raw artifact to standardized data format
|
|
106
|
+
*/
|
|
107
|
+
formatArtifactData(artifact, artifactId, taskId) {
|
|
108
|
+
return {
|
|
109
|
+
artifactId,
|
|
110
|
+
taskId,
|
|
111
|
+
name: artifact.name || 'Processing...',
|
|
112
|
+
description: artifact.description || 'Name and description being generated...',
|
|
113
|
+
artifactType: artifact.metadata?.artifactType,
|
|
114
|
+
artifactSummary: artifact.parts?.[0]?.data?.summary || {},
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Parse text with artifact markers into parts array
|
|
119
|
+
* Can work with or without pre-fetched artifact map
|
|
120
|
+
*/
|
|
121
|
+
async parseText(text, artifactMap) {
|
|
122
|
+
const parts = [];
|
|
123
|
+
const matches = [...text.matchAll(ArtifactParser.ARTIFACT_REGEX)];
|
|
124
|
+
if (matches.length === 0) {
|
|
125
|
+
return [{ kind: 'text', text }];
|
|
126
|
+
}
|
|
127
|
+
let lastIndex = 0;
|
|
128
|
+
for (const match of matches) {
|
|
129
|
+
const [fullMatch, artifactId, taskId] = match;
|
|
130
|
+
const matchStart = match.index;
|
|
131
|
+
// Add text before artifact
|
|
132
|
+
if (matchStart > lastIndex) {
|
|
133
|
+
const textBefore = text.slice(lastIndex, matchStart);
|
|
134
|
+
if (textBefore.trim()) {
|
|
135
|
+
parts.push({ kind: 'text', text: textBefore });
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// Get artifact data
|
|
139
|
+
const artifactData = await this.getArtifactData(artifactId, taskId, artifactMap);
|
|
140
|
+
if (artifactData) {
|
|
141
|
+
parts.push({ kind: 'data', data: artifactData });
|
|
142
|
+
}
|
|
143
|
+
// If no artifact found, marker is simply removed
|
|
144
|
+
lastIndex = matchStart + fullMatch.length;
|
|
145
|
+
}
|
|
146
|
+
// Add remaining text
|
|
147
|
+
if (lastIndex < text.length) {
|
|
148
|
+
const remainingText = text.slice(lastIndex);
|
|
149
|
+
if (remainingText.trim()) {
|
|
150
|
+
parts.push({ kind: 'text', text: remainingText });
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return parts;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Process object/dataComponents for artifact components
|
|
157
|
+
*/
|
|
158
|
+
async parseObject(obj, artifactMap) {
|
|
159
|
+
// Handle dataComponents array
|
|
160
|
+
if (obj?.dataComponents && Array.isArray(obj.dataComponents)) {
|
|
161
|
+
const parts = [];
|
|
162
|
+
for (const component of obj.dataComponents) {
|
|
163
|
+
if (this.isArtifactComponent(component)) {
|
|
164
|
+
const artifactData = await this.getArtifactData(component.props.artifact_id, component.props.task_id, artifactMap);
|
|
165
|
+
if (artifactData) {
|
|
166
|
+
parts.push({ kind: 'data', data: artifactData });
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
parts.push({ kind: 'data', data: component });
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return parts;
|
|
174
|
+
}
|
|
175
|
+
// Handle single object
|
|
176
|
+
if (this.isArtifactComponent(obj)) {
|
|
177
|
+
const artifactData = await this.getArtifactData(obj.props.artifact_id, obj.props.task_id, artifactMap);
|
|
178
|
+
return artifactData ? [{ kind: 'data', data: artifactData }] : [];
|
|
179
|
+
}
|
|
180
|
+
return [{ kind: 'data', data: obj }];
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Check if object is an artifact component
|
|
184
|
+
*/
|
|
185
|
+
isArtifactComponent(obj) {
|
|
186
|
+
return obj?.props?.artifact_id && obj?.props?.task_id;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Get artifact data from map or fetch directly
|
|
190
|
+
*/
|
|
191
|
+
async getArtifactData(artifactId, taskId, artifactMap) {
|
|
192
|
+
const key = `${artifactId}:${taskId}`;
|
|
193
|
+
// Try map first
|
|
194
|
+
if (artifactMap?.has(key)) {
|
|
195
|
+
const artifact = artifactMap.get(key);
|
|
196
|
+
return this.formatArtifactData(artifact, artifactId, taskId);
|
|
197
|
+
}
|
|
198
|
+
// Fetch directly if no map
|
|
199
|
+
try {
|
|
200
|
+
// Get task to retrieve projectId
|
|
201
|
+
const task = await getTask(dbClient)({
|
|
202
|
+
id: taskId,
|
|
203
|
+
});
|
|
204
|
+
if (!task) {
|
|
205
|
+
logger.warn({ taskId }, 'Task not found when fetching artifact');
|
|
206
|
+
return null;
|
|
207
|
+
}
|
|
208
|
+
const artifacts = await getLedgerArtifacts(dbClient)({
|
|
209
|
+
scopes: { tenantId: this.tenantId, projectId: task.projectId },
|
|
210
|
+
artifactId,
|
|
211
|
+
taskId,
|
|
212
|
+
});
|
|
213
|
+
if (artifacts.length > 0) {
|
|
214
|
+
return this.formatArtifactData(artifacts[0], artifactId, taskId);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
catch (error) {
|
|
218
|
+
logger.warn({ artifactId, taskId, error }, 'Failed to fetch artifact');
|
|
219
|
+
}
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Parse partial JSON buffer (for streaming)
|
|
224
|
+
*/
|
|
225
|
+
parsePartialJSON(buffer) {
|
|
226
|
+
const complete = [];
|
|
227
|
+
let remaining = buffer;
|
|
228
|
+
let braceCount = 0;
|
|
229
|
+
let start = -1;
|
|
230
|
+
for (let i = 0; i < buffer.length; i++) {
|
|
231
|
+
if (buffer[i] === '{') {
|
|
232
|
+
if (braceCount === 0)
|
|
233
|
+
start = i;
|
|
234
|
+
braceCount++;
|
|
235
|
+
}
|
|
236
|
+
else if (buffer[i] === '}') {
|
|
237
|
+
braceCount--;
|
|
238
|
+
if (braceCount === 0 && start !== -1) {
|
|
239
|
+
const jsonStr = buffer.slice(start, i + 1);
|
|
240
|
+
try {
|
|
241
|
+
complete.push(JSON.parse(jsonStr));
|
|
242
|
+
remaining = buffer.slice(i + 1);
|
|
243
|
+
start = -1;
|
|
244
|
+
}
|
|
245
|
+
catch {
|
|
246
|
+
// Invalid JSON, continue
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return { complete, remaining };
|
|
252
|
+
}
|
|
253
|
+
}
|