march-ai-sdk 0.3.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 +732 -0
- package/dist/app-C_umwZXh.d.ts +790 -0
- package/dist/extensions/langgraph.d.ts +144 -0
- package/dist/extensions/langgraph.js +326 -0
- package/dist/extensions/langgraph.js.map +1 -0
- package/dist/extensions/vercel-ai.d.ts +124 -0
- package/dist/extensions/vercel-ai.js +177 -0
- package/dist/extensions/vercel-ai.js.map +1 -0
- package/dist/index.d.ts +260 -0
- package/dist/index.js +1695 -0
- package/dist/index.js.map +1 -0
- package/dist/proto/gateway.proto +99 -0
- package/package.json +83 -0
- package/src/agent-state-client.ts +115 -0
- package/src/agent.ts +293 -0
- package/src/api-paths.ts +60 -0
- package/src/app.ts +235 -0
- package/src/artifact.ts +59 -0
- package/src/attachment-client.ts +78 -0
- package/src/checkpoint-client.ts +175 -0
- package/src/conversation-client.ts +109 -0
- package/src/conversation-message.ts +61 -0
- package/src/conversation.ts +123 -0
- package/src/exceptions.ts +78 -0
- package/src/extensions/index.ts +6 -0
- package/src/extensions/langgraph.ts +351 -0
- package/src/extensions/vercel-ai.ts +177 -0
- package/src/gateway-client.ts +420 -0
- package/src/heartbeat.ts +89 -0
- package/src/index.ts +70 -0
- package/src/memory-client.ts +125 -0
- package/src/memory.ts +68 -0
- package/src/message.ts +178 -0
- package/src/proto/gateway.proto +99 -0
- package/src/streamer.ts +242 -0
- package/src/types.ts +196 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* March Agent SDK - Attachment Client
|
|
3
|
+
* Port of Python march_agent/attachment_client.py
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { APIException } from './exceptions.js'
|
|
7
|
+
import { AttachmentInfoSchema, type AttachmentInfo } from './types.js'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Re-export AttachmentInfo for convenience
|
|
11
|
+
*/
|
|
12
|
+
export { type AttachmentInfo } from './types.js'
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Create AttachmentInfo from API data
|
|
16
|
+
*/
|
|
17
|
+
export function createAttachmentInfo(data: Record<string, unknown>): AttachmentInfo {
|
|
18
|
+
return AttachmentInfoSchema.parse({
|
|
19
|
+
url: data.url,
|
|
20
|
+
filename: data.filename || data.file_name,
|
|
21
|
+
contentType: data.content_type || data.contentType,
|
|
22
|
+
size: data.size,
|
|
23
|
+
fileType: data.file_type || data.fileType,
|
|
24
|
+
})
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* HTTP client for downloading attachments.
|
|
29
|
+
*/
|
|
30
|
+
export class AttachmentClient {
|
|
31
|
+
private readonly baseUrl: string
|
|
32
|
+
|
|
33
|
+
constructor(baseUrl: string) {
|
|
34
|
+
this.baseUrl = baseUrl.replace(/\/$/, '')
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Build full URL for an attachment.
|
|
39
|
+
*/
|
|
40
|
+
private buildUrl(attachmentUrl: string): string {
|
|
41
|
+
// If already absolute URL, use as-is
|
|
42
|
+
if (attachmentUrl.startsWith('http://') || attachmentUrl.startsWith('https://')) {
|
|
43
|
+
return attachmentUrl
|
|
44
|
+
}
|
|
45
|
+
// Otherwise, prepend base URL
|
|
46
|
+
return `${this.baseUrl}${attachmentUrl.startsWith('/') ? '' : '/'}${attachmentUrl}`
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Download attachment as bytes (Buffer).
|
|
51
|
+
*/
|
|
52
|
+
async download(url: string): Promise<Buffer> {
|
|
53
|
+
const fullUrl = this.buildUrl(url)
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
const response = await fetch(fullUrl)
|
|
57
|
+
|
|
58
|
+
if (!response.ok) {
|
|
59
|
+
throw new APIException(`Failed to download attachment: ${response.status}`, response.status)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const arrayBuffer = await response.arrayBuffer()
|
|
63
|
+
return Buffer.from(arrayBuffer)
|
|
64
|
+
} catch (error) {
|
|
65
|
+
if (error instanceof APIException) throw error
|
|
66
|
+
throw new APIException(`Failed to download attachment: ${error}`)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Download attachment as base64 string.
|
|
72
|
+
* Useful for LLM vision APIs.
|
|
73
|
+
*/
|
|
74
|
+
async downloadAsBase64(url: string): Promise<string> {
|
|
75
|
+
const buffer = await this.download(url)
|
|
76
|
+
return buffer.toString('base64')
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* March Agent SDK - Checkpoint Client
|
|
3
|
+
* Port of Python march_agent/checkpoint_client.py
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { APIException } from './exceptions.js'
|
|
7
|
+
|
|
8
|
+
export interface CheckpointConfig {
|
|
9
|
+
configurable: {
|
|
10
|
+
thread_id: string
|
|
11
|
+
checkpoint_ns?: string
|
|
12
|
+
checkpoint_id?: string
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface CheckpointData {
|
|
17
|
+
v: number
|
|
18
|
+
id: string
|
|
19
|
+
ts: string
|
|
20
|
+
channel_values: Record<string, unknown>
|
|
21
|
+
channel_versions: Record<string, string>
|
|
22
|
+
versions_seen: Record<string, Record<string, string>>
|
|
23
|
+
pending_sends?: unknown[]
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface CheckpointMetadata {
|
|
27
|
+
source: string
|
|
28
|
+
step: number
|
|
29
|
+
writes?: unknown
|
|
30
|
+
parents?: Record<string, string>
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface CheckpointTuple {
|
|
34
|
+
config: CheckpointConfig
|
|
35
|
+
checkpoint: CheckpointData
|
|
36
|
+
metadata: CheckpointMetadata
|
|
37
|
+
parent_config?: CheckpointConfig
|
|
38
|
+
pending_writes?: unknown[]
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface CheckpointListOptions {
|
|
42
|
+
threadId?: string
|
|
43
|
+
checkpointNs?: string
|
|
44
|
+
before?: string
|
|
45
|
+
limit?: number
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Async HTTP client for checkpoint-store API.
|
|
50
|
+
* Used by LangGraph integration for persisting graph state.
|
|
51
|
+
*/
|
|
52
|
+
export class CheckpointClient {
|
|
53
|
+
private readonly baseUrl: string
|
|
54
|
+
|
|
55
|
+
constructor(baseUrl: string) {
|
|
56
|
+
this.baseUrl = baseUrl.replace(/\/$/, '')
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Store a checkpoint.
|
|
61
|
+
*/
|
|
62
|
+
async put(
|
|
63
|
+
config: CheckpointConfig,
|
|
64
|
+
checkpoint: CheckpointData,
|
|
65
|
+
metadata: CheckpointMetadata,
|
|
66
|
+
newVersions: Record<string, unknown> = {}
|
|
67
|
+
): Promise<{ config: CheckpointConfig }> {
|
|
68
|
+
const url = `${this.baseUrl}/checkpoints/`
|
|
69
|
+
const payload = {
|
|
70
|
+
config,
|
|
71
|
+
checkpoint,
|
|
72
|
+
metadata,
|
|
73
|
+
new_versions: newVersions,
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
const response = await fetch(url, {
|
|
78
|
+
method: 'PUT',
|
|
79
|
+
headers: { 'Content-Type': 'application/json' },
|
|
80
|
+
body: JSON.stringify(payload),
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
if (!response.ok) {
|
|
84
|
+
const errorText = await response.text()
|
|
85
|
+
throw new APIException(`Failed to store checkpoint: ${response.status} - ${errorText}`, response.status)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return await response.json() as { config: CheckpointConfig }
|
|
89
|
+
} catch (error) {
|
|
90
|
+
if (error instanceof APIException) throw error
|
|
91
|
+
throw new APIException(`Failed to store checkpoint: ${error}`)
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Get a checkpoint tuple.
|
|
97
|
+
*/
|
|
98
|
+
async getTuple(
|
|
99
|
+
threadId: string,
|
|
100
|
+
checkpointNs: string = '',
|
|
101
|
+
checkpointId?: string
|
|
102
|
+
): Promise<CheckpointTuple | null> {
|
|
103
|
+
const url = new URL(`${this.baseUrl}/checkpoints/${threadId}`)
|
|
104
|
+
url.searchParams.set('checkpoint_ns', checkpointNs)
|
|
105
|
+
if (checkpointId) {
|
|
106
|
+
url.searchParams.set('checkpoint_id', checkpointId)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
try {
|
|
110
|
+
const response = await fetch(url.toString())
|
|
111
|
+
|
|
112
|
+
if (response.status === 404) {
|
|
113
|
+
return null
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (!response.ok) {
|
|
117
|
+
const errorText = await response.text()
|
|
118
|
+
throw new APIException(`Failed to get checkpoint: ${response.status} - ${errorText}`, response.status)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const result = await response.json() as CheckpointTuple | null
|
|
122
|
+
return result || null
|
|
123
|
+
} catch (error) {
|
|
124
|
+
if (error instanceof APIException) throw error
|
|
125
|
+
throw new APIException(`Failed to get checkpoint: ${error}`)
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* List checkpoints.
|
|
131
|
+
*/
|
|
132
|
+
async list(options: CheckpointListOptions = {}): Promise<CheckpointTuple[]> {
|
|
133
|
+
const url = new URL(`${this.baseUrl}/checkpoints/`)
|
|
134
|
+
|
|
135
|
+
if (options.threadId) url.searchParams.set('thread_id', options.threadId)
|
|
136
|
+
if (options.checkpointNs !== undefined) url.searchParams.set('checkpoint_ns', options.checkpointNs)
|
|
137
|
+
if (options.before) url.searchParams.set('before', options.before)
|
|
138
|
+
if (options.limit) url.searchParams.set('limit', String(options.limit))
|
|
139
|
+
|
|
140
|
+
try {
|
|
141
|
+
const response = await fetch(url.toString())
|
|
142
|
+
|
|
143
|
+
if (!response.ok) {
|
|
144
|
+
const errorText = await response.text()
|
|
145
|
+
throw new APIException(`Failed to list checkpoints: ${response.status} - ${errorText}`, response.status)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return await response.json() as CheckpointTuple[]
|
|
149
|
+
} catch (error) {
|
|
150
|
+
if (error instanceof APIException) throw error
|
|
151
|
+
throw new APIException(`Failed to list checkpoints: ${error}`)
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Delete all checkpoints for a thread.
|
|
157
|
+
*/
|
|
158
|
+
async deleteThread(threadId: string): Promise<{ thread_id: string; deleted: number }> {
|
|
159
|
+
const url = `${this.baseUrl}/checkpoints/${threadId}`
|
|
160
|
+
|
|
161
|
+
try {
|
|
162
|
+
const response = await fetch(url, { method: 'DELETE' })
|
|
163
|
+
|
|
164
|
+
if (!response.ok) {
|
|
165
|
+
const errorText = await response.text()
|
|
166
|
+
throw new APIException(`Failed to delete checkpoints: ${response.status} - ${errorText}`, response.status)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return await response.json() as { thread_id: string; deleted: number }
|
|
170
|
+
} catch (error) {
|
|
171
|
+
if (error instanceof APIException) throw error
|
|
172
|
+
throw new APIException(`Failed to delete checkpoints: ${error}`)
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* March Agent SDK - Conversation Client
|
|
3
|
+
* Port of Python march_agent/conversation_client.py
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { APIException } from './exceptions.js'
|
|
7
|
+
import type { ConversationData, GetMessagesOptions, ConversationMessageData } from './types.js'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* HTTP client for interacting with conversation-store API.
|
|
11
|
+
*/
|
|
12
|
+
export class ConversationClient {
|
|
13
|
+
private readonly baseUrl: string
|
|
14
|
+
|
|
15
|
+
constructor(baseUrl: string) {
|
|
16
|
+
this.baseUrl = baseUrl.replace(/\/$/, '')
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Get conversation metadata.
|
|
21
|
+
*/
|
|
22
|
+
async getConversation(conversationId: string): Promise<ConversationData> {
|
|
23
|
+
const url = `${this.baseUrl}/conversations/${conversationId}`
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
const response = await fetch(url)
|
|
27
|
+
|
|
28
|
+
if (response.status === 404) {
|
|
29
|
+
throw new APIException(`Conversation ${conversationId} not found`, 404)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (!response.ok) {
|
|
33
|
+
throw new APIException(`Failed to fetch conversation: ${response.status}`, response.status)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return await response.json() as ConversationData
|
|
37
|
+
} catch (error) {
|
|
38
|
+
if (error instanceof APIException) throw error
|
|
39
|
+
throw new APIException(`Failed to fetch conversation: ${error}`)
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Get messages from a conversation.
|
|
45
|
+
*/
|
|
46
|
+
async getMessages(
|
|
47
|
+
conversationId: string,
|
|
48
|
+
options: GetMessagesOptions = {}
|
|
49
|
+
): Promise<ConversationMessageData[]> {
|
|
50
|
+
const url = new URL(`${this.baseUrl}/conversations/${conversationId}/messages`)
|
|
51
|
+
|
|
52
|
+
const params: Record<string, string> = {
|
|
53
|
+
limit: String(Math.min(options.limit ?? 100, 1000)),
|
|
54
|
+
offset: String(options.offset ?? 0),
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (options.role) params.role = options.role
|
|
58
|
+
if (options.from) params.from = options.from
|
|
59
|
+
if (options.to) params.to = options.to
|
|
60
|
+
|
|
61
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
62
|
+
url.searchParams.set(key, value)
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
try {
|
|
66
|
+
const response = await fetch(url.toString())
|
|
67
|
+
|
|
68
|
+
if (response.status === 404) {
|
|
69
|
+
throw new APIException(`Conversation ${conversationId} not found`, 404)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (!response.ok) {
|
|
73
|
+
throw new APIException(`Failed to fetch messages: ${response.status}`, response.status)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return await response.json() as ConversationMessageData[]
|
|
77
|
+
} catch (error) {
|
|
78
|
+
if (error instanceof APIException) throw error
|
|
79
|
+
throw new APIException(`Failed to fetch messages: ${error}`)
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Update conversation fields (PATCH).
|
|
85
|
+
*/
|
|
86
|
+
async updateConversation(
|
|
87
|
+
conversationId: string,
|
|
88
|
+
data: Partial<ConversationData>
|
|
89
|
+
): Promise<ConversationData> {
|
|
90
|
+
const url = `${this.baseUrl}/conversations/${conversationId}`
|
|
91
|
+
|
|
92
|
+
try {
|
|
93
|
+
const response = await fetch(url, {
|
|
94
|
+
method: 'PATCH',
|
|
95
|
+
headers: { 'Content-Type': 'application/json' },
|
|
96
|
+
body: JSON.stringify(data),
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
if (!response.ok) {
|
|
100
|
+
throw new APIException(`Failed to update conversation: ${response.status}`, response.status)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return await response.json() as ConversationData
|
|
104
|
+
} catch (error) {
|
|
105
|
+
if (error instanceof APIException) throw error
|
|
106
|
+
throw new APIException(`Failed to update conversation: ${error}`)
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* March Agent SDK - Conversation Message
|
|
3
|
+
* Port of Python march_agent/conversation_message.py
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { ConversationMessageData } from './types.js'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Represents a message from conversation history.
|
|
10
|
+
*/
|
|
11
|
+
export class ConversationMessage {
|
|
12
|
+
readonly id: string
|
|
13
|
+
readonly conversationId: string
|
|
14
|
+
readonly role: 'user' | 'assistant' | 'system'
|
|
15
|
+
readonly content: string
|
|
16
|
+
readonly from?: string
|
|
17
|
+
readonly to?: string
|
|
18
|
+
readonly createdAt: Date
|
|
19
|
+
readonly metadata?: Record<string, unknown>
|
|
20
|
+
|
|
21
|
+
constructor(data: ConversationMessageData) {
|
|
22
|
+
this.id = data.id
|
|
23
|
+
this.conversationId = data.conversationId
|
|
24
|
+
this.role = data.role
|
|
25
|
+
this.content = data.content
|
|
26
|
+
this.from = data.from
|
|
27
|
+
this.to = data.to
|
|
28
|
+
this.createdAt = new Date(data.createdAt)
|
|
29
|
+
this.metadata = data.metadata
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Create from API response
|
|
34
|
+
*/
|
|
35
|
+
static fromApiResponse(data: Record<string, unknown>): ConversationMessage {
|
|
36
|
+
return new ConversationMessage({
|
|
37
|
+
id: data.id as string,
|
|
38
|
+
conversationId: data.conversation_id as string,
|
|
39
|
+
role: data.role as 'user' | 'assistant' | 'system',
|
|
40
|
+
content: data.content as string,
|
|
41
|
+
from: data.from as string | undefined,
|
|
42
|
+
to: data.to as string | undefined,
|
|
43
|
+
createdAt: data.created_at as string,
|
|
44
|
+
metadata: data.metadata as Record<string, unknown> | undefined,
|
|
45
|
+
})
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Check if this is a user message
|
|
50
|
+
*/
|
|
51
|
+
isUser(): boolean {
|
|
52
|
+
return this.role === 'user'
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Check if this is an assistant message
|
|
57
|
+
*/
|
|
58
|
+
isAssistant(): boolean {
|
|
59
|
+
return this.role === 'assistant'
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* March Agent SDK - Conversation Helper
|
|
3
|
+
* Port of Python march_agent/conversation.py
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { ConversationClient } from './conversation-client.js'
|
|
7
|
+
import { ConversationMessage } from './conversation-message.js'
|
|
8
|
+
// Types are inlined to avoid unused import warnings
|
|
9
|
+
|
|
10
|
+
export interface GetHistoryOptions {
|
|
11
|
+
limit?: number
|
|
12
|
+
offset?: number
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface GetAgentHistoryOptions extends GetHistoryOptions {
|
|
16
|
+
agentName?: string
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Helper class for accessing conversation history.
|
|
21
|
+
* Provides convenient methods for fetching messages.
|
|
22
|
+
*/
|
|
23
|
+
export class Conversation {
|
|
24
|
+
readonly conversationId: string
|
|
25
|
+
private readonly client: ConversationClient
|
|
26
|
+
private readonly agentName?: string
|
|
27
|
+
|
|
28
|
+
constructor(
|
|
29
|
+
conversationId: string,
|
|
30
|
+
client: ConversationClient,
|
|
31
|
+
agentName?: string
|
|
32
|
+
) {
|
|
33
|
+
this.conversationId = conversationId
|
|
34
|
+
this.client = client
|
|
35
|
+
this.agentName = agentName
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Get all messages in the conversation.
|
|
40
|
+
*/
|
|
41
|
+
async getHistory(options: GetHistoryOptions = {}): Promise<ConversationMessage[]> {
|
|
42
|
+
const messages = await this.client.getMessages(this.conversationId, {
|
|
43
|
+
limit: options.limit ?? 100,
|
|
44
|
+
offset: options.offset ?? 0,
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
return messages.map((m) => ConversationMessage.fromApiResponse(m as unknown as Record<string, unknown>))
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Get messages to/from the current agent.
|
|
52
|
+
* Useful for getting conversation history for a specific agent.
|
|
53
|
+
*/
|
|
54
|
+
async getAgentHistory(options: GetAgentHistoryOptions = {}): Promise<ConversationMessage[]> {
|
|
55
|
+
const targetAgent = options.agentName ?? this.agentName
|
|
56
|
+
if (!targetAgent) {
|
|
57
|
+
// If no agent name, return all messages
|
|
58
|
+
return this.getHistory(options)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Get messages where the agent is either sender or receiver
|
|
62
|
+
const [toAgent, fromAgent] = await Promise.all([
|
|
63
|
+
this.client.getMessages(this.conversationId, {
|
|
64
|
+
to: targetAgent,
|
|
65
|
+
limit: options.limit ?? 50,
|
|
66
|
+
offset: options.offset ?? 0,
|
|
67
|
+
}),
|
|
68
|
+
this.client.getMessages(this.conversationId, {
|
|
69
|
+
from: targetAgent,
|
|
70
|
+
limit: options.limit ?? 50,
|
|
71
|
+
offset: options.offset ?? 0,
|
|
72
|
+
}),
|
|
73
|
+
])
|
|
74
|
+
|
|
75
|
+
// Combine and sort by creation time
|
|
76
|
+
const allMessages = [...toAgent, ...fromAgent]
|
|
77
|
+
const uniqueMessages = Array.from(
|
|
78
|
+
new Map(allMessages.map((m) => [m.id, m])).values()
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
// Sort by createdAt
|
|
82
|
+
uniqueMessages.sort((a, b) => {
|
|
83
|
+
const dateA = new Date(a.createdAt).getTime()
|
|
84
|
+
const dateB = new Date(b.createdAt).getTime()
|
|
85
|
+
return dateA - dateB
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
return uniqueMessages.map((m) =>
|
|
89
|
+
ConversationMessage.fromApiResponse(m as unknown as Record<string, unknown>)
|
|
90
|
+
)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Get the last N messages.
|
|
95
|
+
*/
|
|
96
|
+
async getLastMessages(count: number): Promise<ConversationMessage[]> {
|
|
97
|
+
return this.getHistory({ limit: count })
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Get user messages only.
|
|
102
|
+
*/
|
|
103
|
+
async getUserMessages(options: GetHistoryOptions = {}): Promise<ConversationMessage[]> {
|
|
104
|
+
const messages = await this.client.getMessages(this.conversationId, {
|
|
105
|
+
...options,
|
|
106
|
+
role: 'user',
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
return messages.map((m) => ConversationMessage.fromApiResponse(m as unknown as Record<string, unknown>))
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Get assistant messages only.
|
|
114
|
+
*/
|
|
115
|
+
async getAssistantMessages(options: GetHistoryOptions = {}): Promise<ConversationMessage[]> {
|
|
116
|
+
const messages = await this.client.getMessages(this.conversationId, {
|
|
117
|
+
...options,
|
|
118
|
+
role: 'assistant',
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
return messages.map((m) => ConversationMessage.fromApiResponse(m as unknown as Record<string, unknown>))
|
|
122
|
+
}
|
|
123
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* March Agent SDK - Custom Errors
|
|
3
|
+
* Port of Python march_agent/exceptions.py
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Base error class for March Agent SDK
|
|
8
|
+
*/
|
|
9
|
+
export class MarchAgentError extends Error {
|
|
10
|
+
constructor(message: string) {
|
|
11
|
+
super(message)
|
|
12
|
+
this.name = 'MarchAgentError'
|
|
13
|
+
Error.captureStackTrace?.(this, this.constructor)
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Error during agent registration with AI Inventory
|
|
19
|
+
*/
|
|
20
|
+
export class RegistrationError extends MarchAgentError {
|
|
21
|
+
constructor(message: string) {
|
|
22
|
+
super(message)
|
|
23
|
+
this.name = 'RegistrationError'
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Error during Kafka operations (produce/consume)
|
|
29
|
+
*/
|
|
30
|
+
export class KafkaError extends MarchAgentError {
|
|
31
|
+
constructor(message: string) {
|
|
32
|
+
super(message)
|
|
33
|
+
this.name = 'KafkaError'
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Error in SDK configuration
|
|
39
|
+
*/
|
|
40
|
+
export class ConfigurationError extends MarchAgentError {
|
|
41
|
+
constructor(message: string) {
|
|
42
|
+
super(message)
|
|
43
|
+
this.name = 'ConfigurationError'
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Error from API calls to backend services
|
|
49
|
+
*/
|
|
50
|
+
export class APIException extends MarchAgentError {
|
|
51
|
+
statusCode?: number
|
|
52
|
+
|
|
53
|
+
constructor(message: string, statusCode?: number) {
|
|
54
|
+
super(message)
|
|
55
|
+
this.name = 'APIException'
|
|
56
|
+
this.statusCode = statusCode
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Error during heartbeat operations
|
|
62
|
+
*/
|
|
63
|
+
export class HeartbeatError extends MarchAgentError {
|
|
64
|
+
constructor(message: string) {
|
|
65
|
+
super(message)
|
|
66
|
+
this.name = 'HeartbeatError'
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Error during gRPC connection/communication
|
|
72
|
+
*/
|
|
73
|
+
export class GatewayError extends MarchAgentError {
|
|
74
|
+
constructor(message: string) {
|
|
75
|
+
super(message)
|
|
76
|
+
this.name = 'GatewayError'
|
|
77
|
+
}
|
|
78
|
+
}
|