@looopy-ai/core 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +9 -0
- package/dist/core/agent.d.ts +53 -0
- package/dist/core/agent.js +416 -0
- package/dist/core/cleanup.d.ts +12 -0
- package/dist/core/cleanup.js +45 -0
- package/dist/core/index.d.ts +3 -0
- package/dist/core/index.js +3 -0
- package/dist/core/iteration.d.ts +5 -0
- package/dist/core/iteration.js +60 -0
- package/dist/core/logger.d.ts +11 -0
- package/dist/core/logger.js +31 -0
- package/dist/core/loop.d.ts +5 -0
- package/dist/core/loop.js +125 -0
- package/dist/core/tools.d.ts +4 -0
- package/dist/core/tools.js +78 -0
- package/dist/core/types.d.ts +30 -0
- package/dist/core/types.js +1 -0
- package/dist/events/index.d.ts +3 -0
- package/dist/events/index.js +2 -0
- package/dist/events/utils.d.ts +250 -0
- package/dist/events/utils.js +263 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +8 -0
- package/dist/observability/index.d.ts +1 -0
- package/dist/observability/index.js +1 -0
- package/dist/observability/spans/agent-turn.d.ts +31 -0
- package/dist/observability/spans/agent-turn.js +94 -0
- package/dist/observability/spans/index.d.ts +5 -0
- package/dist/observability/spans/index.js +5 -0
- package/dist/observability/spans/iteration.d.ts +14 -0
- package/dist/observability/spans/iteration.js +41 -0
- package/dist/observability/spans/llm-call.d.ts +14 -0
- package/dist/observability/spans/llm-call.js +50 -0
- package/dist/observability/spans/loop.d.ts +14 -0
- package/dist/observability/spans/loop.js +40 -0
- package/dist/observability/spans/tool.d.ts +14 -0
- package/dist/observability/spans/tool.js +44 -0
- package/dist/observability/tracing.d.ts +58 -0
- package/dist/observability/tracing.js +203 -0
- package/dist/providers/chat-completions/aggregate.d.ts +4 -0
- package/dist/providers/chat-completions/aggregate.js +152 -0
- package/dist/providers/chat-completions/content.d.ts +25 -0
- package/dist/providers/chat-completions/content.js +229 -0
- package/dist/providers/chat-completions/index.d.ts +4 -0
- package/dist/providers/chat-completions/index.js +4 -0
- package/dist/providers/chat-completions/streaming.d.ts +12 -0
- package/dist/providers/chat-completions/streaming.js +3 -0
- package/dist/providers/chat-completions/types.d.ts +39 -0
- package/dist/providers/chat-completions/types.js +1 -0
- package/dist/providers/index.d.ts +2 -0
- package/dist/providers/index.js +1 -0
- package/dist/providers/litellm-provider.d.ts +43 -0
- package/dist/providers/litellm-provider.js +377 -0
- package/dist/server/event-buffer.d.ts +37 -0
- package/dist/server/event-buffer.js +116 -0
- package/dist/server/event-router.d.ts +31 -0
- package/dist/server/event-router.js +91 -0
- package/dist/server/index.d.ts +3 -0
- package/dist/server/index.js +3 -0
- package/dist/server/sse.d.ts +60 -0
- package/dist/server/sse.js +159 -0
- package/dist/stores/artifacts/artifact-scheduler.d.ts +50 -0
- package/dist/stores/artifacts/artifact-scheduler.js +86 -0
- package/dist/stores/artifacts/index.d.ts +3 -0
- package/dist/stores/artifacts/index.js +3 -0
- package/dist/stores/artifacts/internal-event-artifact-store.d.ts +54 -0
- package/dist/stores/artifacts/internal-event-artifact-store.js +126 -0
- package/dist/stores/artifacts/memory-artifact-store.d.ts +52 -0
- package/dist/stores/artifacts/memory-artifact-store.js +268 -0
- package/dist/stores/filesystem/filesystem-agent-store.d.ts +18 -0
- package/dist/stores/filesystem/filesystem-agent-store.js +61 -0
- package/dist/stores/filesystem/filesystem-artifact-store.d.ts +59 -0
- package/dist/stores/filesystem/filesystem-artifact-store.js +325 -0
- package/dist/stores/filesystem/filesystem-context-store.d.ts +37 -0
- package/dist/stores/filesystem/filesystem-context-store.js +245 -0
- package/dist/stores/filesystem/filesystem-message-store.d.ts +28 -0
- package/dist/stores/filesystem/filesystem-message-store.js +149 -0
- package/dist/stores/filesystem/filesystem-task-state-store.d.ts +27 -0
- package/dist/stores/filesystem/filesystem-task-state-store.js +220 -0
- package/dist/stores/filesystem/index.d.ts +10 -0
- package/dist/stores/filesystem/index.js +5 -0
- package/dist/stores/index.d.ts +5 -0
- package/dist/stores/index.js +5 -0
- package/dist/stores/memory/memory-state-store.d.ts +15 -0
- package/dist/stores/memory/memory-state-store.js +55 -0
- package/dist/stores/messages/hybrid-message-store.d.ts +29 -0
- package/dist/stores/messages/hybrid-message-store.js +72 -0
- package/dist/stores/messages/index.d.ts +4 -0
- package/dist/stores/messages/index.js +4 -0
- package/dist/stores/messages/interfaces.d.ts +42 -0
- package/dist/stores/messages/interfaces.js +18 -0
- package/dist/stores/messages/mem0-message-store.d.ts +34 -0
- package/dist/stores/messages/mem0-message-store.js +218 -0
- package/dist/stores/messages/memory-message-store.d.ts +27 -0
- package/dist/stores/messages/memory-message-store.js +183 -0
- package/dist/tools/artifact-tools.d.ts +4 -0
- package/dist/tools/artifact-tools.js +277 -0
- package/dist/tools/client-tool-provider.d.ts +25 -0
- package/dist/tools/client-tool-provider.js +139 -0
- package/dist/tools/index.d.ts +4 -0
- package/dist/tools/index.js +4 -0
- package/dist/tools/local-tools.d.ts +13 -0
- package/dist/tools/local-tools.js +70 -0
- package/dist/tools/mcp-client.d.ts +29 -0
- package/dist/tools/mcp-client.js +62 -0
- package/dist/tools/mcp-tool-provider.d.ts +22 -0
- package/dist/tools/mcp-tool-provider.js +86 -0
- package/dist/types/a2a.d.ts +36 -0
- package/dist/types/a2a.js +1 -0
- package/dist/types/agent.d.ts +14 -0
- package/dist/types/agent.js +1 -0
- package/dist/types/artifact.d.ts +126 -0
- package/dist/types/artifact.js +1 -0
- package/dist/types/context.d.ts +13 -0
- package/dist/types/context.js +1 -0
- package/dist/types/event.d.ts +360 -0
- package/dist/types/event.js +30 -0
- package/dist/types/index.d.ts +9 -0
- package/dist/types/index.js +9 -0
- package/dist/types/llm.d.ts +24 -0
- package/dist/types/llm.js +1 -0
- package/dist/types/message.d.ts +9 -0
- package/dist/types/message.js +1 -0
- package/dist/types/state.d.ts +86 -0
- package/dist/types/state.js +1 -0
- package/dist/types/tools.d.ts +57 -0
- package/dist/types/tools.js +53 -0
- package/dist/utils/error.d.ts +8 -0
- package/dist/utils/error.js +23 -0
- package/dist/utils/process-signals.d.ts +3 -0
- package/dist/utils/process-signals.js +67 -0
- package/package.json +54 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { ArtifactStore, DatasetSchema, StoredArtifact } from '../../types/artifact';
|
|
2
|
+
export declare class InMemoryArtifactStore implements ArtifactStore {
|
|
3
|
+
private artifacts;
|
|
4
|
+
private getContextStore;
|
|
5
|
+
createFileArtifact(params: {
|
|
6
|
+
artifactId: string;
|
|
7
|
+
taskId: string;
|
|
8
|
+
contextId: string;
|
|
9
|
+
name?: string;
|
|
10
|
+
description?: string;
|
|
11
|
+
mimeType?: string;
|
|
12
|
+
encoding?: 'utf-8' | 'base64';
|
|
13
|
+
override?: boolean;
|
|
14
|
+
}): Promise<string>;
|
|
15
|
+
appendFileChunk(contextId: string, artifactId: string, chunk: string, options?: {
|
|
16
|
+
isLastChunk?: boolean;
|
|
17
|
+
encoding?: 'utf-8' | 'base64';
|
|
18
|
+
}): Promise<void>;
|
|
19
|
+
getFileContent(contextId: string, artifactId: string): Promise<string>;
|
|
20
|
+
createDataArtifact(params: {
|
|
21
|
+
artifactId: string;
|
|
22
|
+
taskId: string;
|
|
23
|
+
contextId: string;
|
|
24
|
+
name?: string;
|
|
25
|
+
description?: string;
|
|
26
|
+
override?: boolean;
|
|
27
|
+
}): Promise<string>;
|
|
28
|
+
writeData(contextId: string, artifactId: string, data: Record<string, unknown>): Promise<void>;
|
|
29
|
+
getDataContent(contextId: string, artifactId: string): Promise<Record<string, unknown>>;
|
|
30
|
+
createDatasetArtifact(params: {
|
|
31
|
+
artifactId: string;
|
|
32
|
+
taskId: string;
|
|
33
|
+
contextId: string;
|
|
34
|
+
name?: string;
|
|
35
|
+
description?: string;
|
|
36
|
+
schema?: DatasetSchema;
|
|
37
|
+
override?: boolean;
|
|
38
|
+
}): Promise<string>;
|
|
39
|
+
appendDatasetBatch(contextId: string, artifactId: string, rows: Record<string, unknown>[], options?: {
|
|
40
|
+
isLastBatch?: boolean;
|
|
41
|
+
}): Promise<void>;
|
|
42
|
+
getDatasetRows(contextId: string, artifactId: string): Promise<Record<string, unknown>[]>;
|
|
43
|
+
getArtifact(contextId: string, artifactId: string): Promise<StoredArtifact | null>;
|
|
44
|
+
listArtifacts(contextId: string, taskId?: string): Promise<string[]>;
|
|
45
|
+
deleteArtifact(contextId: string, artifactId: string): Promise<void>;
|
|
46
|
+
queryArtifacts(params: {
|
|
47
|
+
contextId: string;
|
|
48
|
+
taskId?: string;
|
|
49
|
+
}): Promise<string[]>;
|
|
50
|
+
getArtifactByContext(contextId: string, artifactId: string): Promise<StoredArtifact | null>;
|
|
51
|
+
getTaskArtifacts(taskId: string): Promise<string[]>;
|
|
52
|
+
}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
export class InMemoryArtifactStore {
|
|
3
|
+
artifacts = new Map();
|
|
4
|
+
getContextStore(contextId) {
|
|
5
|
+
let contextStore = this.artifacts.get(contextId);
|
|
6
|
+
if (!contextStore) {
|
|
7
|
+
contextStore = new Map();
|
|
8
|
+
this.artifacts.set(contextId, contextStore);
|
|
9
|
+
}
|
|
10
|
+
return contextStore;
|
|
11
|
+
}
|
|
12
|
+
async createFileArtifact(params) {
|
|
13
|
+
const contextStore = this.getContextStore(params.contextId);
|
|
14
|
+
const existing = contextStore.get(params.artifactId);
|
|
15
|
+
if (existing && !params.override) {
|
|
16
|
+
throw new Error(`Artifact already exists: ${params.artifactId} in context ${params.contextId}. ` +
|
|
17
|
+
`Use override: true to replace it, or use a different artifactId.`);
|
|
18
|
+
}
|
|
19
|
+
const now = new Date().toISOString();
|
|
20
|
+
const createdAt = existing ? existing.createdAt : now;
|
|
21
|
+
const artifact = {
|
|
22
|
+
type: 'file',
|
|
23
|
+
artifactId: params.artifactId,
|
|
24
|
+
taskId: params.taskId,
|
|
25
|
+
contextId: params.contextId,
|
|
26
|
+
name: params.name,
|
|
27
|
+
description: params.description,
|
|
28
|
+
mimeType: params.mimeType || 'text/plain',
|
|
29
|
+
encoding: params.encoding || 'utf-8',
|
|
30
|
+
chunks: [],
|
|
31
|
+
totalChunks: 0,
|
|
32
|
+
totalSize: 0,
|
|
33
|
+
status: 'building',
|
|
34
|
+
version: existing && params.override ? existing.version + 1 : 1,
|
|
35
|
+
operations: [
|
|
36
|
+
{
|
|
37
|
+
operationId: randomUUID(),
|
|
38
|
+
type: params.override ? 'reset' : 'create',
|
|
39
|
+
timestamp: now,
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
createdAt,
|
|
43
|
+
updatedAt: now,
|
|
44
|
+
};
|
|
45
|
+
contextStore.set(params.artifactId, artifact);
|
|
46
|
+
return params.artifactId;
|
|
47
|
+
}
|
|
48
|
+
async appendFileChunk(contextId, artifactId, chunk, options) {
|
|
49
|
+
const contextStore = this.getContextStore(contextId);
|
|
50
|
+
const artifact = contextStore.get(artifactId);
|
|
51
|
+
if (!artifact) {
|
|
52
|
+
throw new Error(`Artifact not found: ${artifactId} in context ${contextId}`);
|
|
53
|
+
}
|
|
54
|
+
if (artifact.type !== 'file') {
|
|
55
|
+
throw new Error(`Artifact ${artifactId} is not a file artifact (type: ${artifact.type})`);
|
|
56
|
+
}
|
|
57
|
+
const now = new Date().toISOString();
|
|
58
|
+
if (chunk && chunk.length > 0) {
|
|
59
|
+
const encoding = options?.encoding || artifact.encoding || 'utf-8';
|
|
60
|
+
const chunkSize = Buffer.byteLength(chunk, encoding);
|
|
61
|
+
const artifactChunk = {
|
|
62
|
+
index: artifact.chunks.length,
|
|
63
|
+
data: chunk,
|
|
64
|
+
size: chunkSize,
|
|
65
|
+
timestamp: now,
|
|
66
|
+
};
|
|
67
|
+
artifact.chunks.push(artifactChunk);
|
|
68
|
+
artifact.totalChunks = artifact.chunks.length;
|
|
69
|
+
artifact.totalSize += chunkSize;
|
|
70
|
+
artifact.operations.push({
|
|
71
|
+
operationId: randomUUID(),
|
|
72
|
+
type: 'append',
|
|
73
|
+
timestamp: now,
|
|
74
|
+
chunkIndex: artifactChunk.index,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
artifact.updatedAt = now;
|
|
78
|
+
artifact.version += 1;
|
|
79
|
+
if (options?.isLastChunk) {
|
|
80
|
+
artifact.status = 'complete';
|
|
81
|
+
artifact.completedAt = now;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
async getFileContent(contextId, artifactId) {
|
|
85
|
+
const contextStore = this.getContextStore(contextId);
|
|
86
|
+
const artifact = contextStore.get(artifactId);
|
|
87
|
+
if (!artifact) {
|
|
88
|
+
throw new Error(`Artifact not found: ${artifactId} in context ${contextId}`);
|
|
89
|
+
}
|
|
90
|
+
if (artifact.type !== 'file') {
|
|
91
|
+
throw new Error(`Artifact ${artifactId} is not a file artifact (type: ${artifact.type})`);
|
|
92
|
+
}
|
|
93
|
+
return artifact.chunks.map((chunk) => chunk.data).join('');
|
|
94
|
+
}
|
|
95
|
+
async createDataArtifact(params) {
|
|
96
|
+
const contextStore = this.getContextStore(params.contextId);
|
|
97
|
+
const existing = contextStore.get(params.artifactId);
|
|
98
|
+
if (existing && !params.override) {
|
|
99
|
+
throw new Error(`Artifact already exists: ${params.artifactId} in context ${params.contextId}. ` +
|
|
100
|
+
`Use override: true to replace it, or use a different artifactId.`);
|
|
101
|
+
}
|
|
102
|
+
const now = new Date().toISOString();
|
|
103
|
+
const createdAt = existing ? existing.createdAt : now;
|
|
104
|
+
const artifact = {
|
|
105
|
+
type: 'data',
|
|
106
|
+
artifactId: params.artifactId,
|
|
107
|
+
taskId: params.taskId,
|
|
108
|
+
contextId: params.contextId,
|
|
109
|
+
name: params.name,
|
|
110
|
+
description: params.description,
|
|
111
|
+
data: {},
|
|
112
|
+
status: 'building',
|
|
113
|
+
version: existing && params.override ? existing.version + 1 : 1,
|
|
114
|
+
operations: [
|
|
115
|
+
{
|
|
116
|
+
operationId: randomUUID(),
|
|
117
|
+
type: params.override ? 'reset' : 'create',
|
|
118
|
+
timestamp: now,
|
|
119
|
+
},
|
|
120
|
+
],
|
|
121
|
+
createdAt,
|
|
122
|
+
updatedAt: now,
|
|
123
|
+
};
|
|
124
|
+
contextStore.set(params.artifactId, artifact);
|
|
125
|
+
return params.artifactId;
|
|
126
|
+
}
|
|
127
|
+
async writeData(contextId, artifactId, data) {
|
|
128
|
+
const contextStore = this.getContextStore(contextId);
|
|
129
|
+
const artifact = contextStore.get(artifactId);
|
|
130
|
+
if (!artifact) {
|
|
131
|
+
throw new Error(`Artifact not found: ${artifactId} in context ${contextId}`);
|
|
132
|
+
}
|
|
133
|
+
if (artifact.type !== 'data') {
|
|
134
|
+
throw new Error(`Artifact ${artifactId} is not a data artifact (type: ${artifact.type})`);
|
|
135
|
+
}
|
|
136
|
+
const now = new Date().toISOString();
|
|
137
|
+
artifact.data = data;
|
|
138
|
+
artifact.updatedAt = now;
|
|
139
|
+
artifact.version += 1;
|
|
140
|
+
artifact.status = 'complete';
|
|
141
|
+
artifact.completedAt = now;
|
|
142
|
+
artifact.operations.push({
|
|
143
|
+
operationId: randomUUID(),
|
|
144
|
+
type: 'replace',
|
|
145
|
+
timestamp: now,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
async getDataContent(contextId, artifactId) {
|
|
149
|
+
const contextStore = this.getContextStore(contextId);
|
|
150
|
+
const artifact = contextStore.get(artifactId);
|
|
151
|
+
if (!artifact) {
|
|
152
|
+
throw new Error(`Artifact not found: ${artifactId} in context ${contextId}`);
|
|
153
|
+
}
|
|
154
|
+
if (artifact.type !== 'data') {
|
|
155
|
+
throw new Error(`Artifact ${artifactId} is not a data artifact (type: ${artifact.type})`);
|
|
156
|
+
}
|
|
157
|
+
return artifact.data;
|
|
158
|
+
}
|
|
159
|
+
async createDatasetArtifact(params) {
|
|
160
|
+
const contextStore = this.getContextStore(params.contextId);
|
|
161
|
+
const existing = contextStore.get(params.artifactId);
|
|
162
|
+
if (existing && !params.override) {
|
|
163
|
+
throw new Error(`Artifact already exists: ${params.artifactId} in context ${params.contextId}. ` +
|
|
164
|
+
`Use override: true to replace it, or use a different artifactId.`);
|
|
165
|
+
}
|
|
166
|
+
const now = new Date().toISOString();
|
|
167
|
+
const createdAt = existing ? existing.createdAt : now;
|
|
168
|
+
const artifact = {
|
|
169
|
+
type: 'dataset',
|
|
170
|
+
artifactId: params.artifactId,
|
|
171
|
+
taskId: params.taskId,
|
|
172
|
+
contextId: params.contextId,
|
|
173
|
+
name: params.name,
|
|
174
|
+
description: params.description,
|
|
175
|
+
schema: params.schema,
|
|
176
|
+
rows: [],
|
|
177
|
+
totalChunks: 0,
|
|
178
|
+
totalSize: 0,
|
|
179
|
+
status: 'building',
|
|
180
|
+
version: existing && params.override ? existing.version + 1 : 1,
|
|
181
|
+
operations: [
|
|
182
|
+
{
|
|
183
|
+
operationId: randomUUID(),
|
|
184
|
+
type: params.override ? 'reset' : 'create',
|
|
185
|
+
timestamp: now,
|
|
186
|
+
},
|
|
187
|
+
],
|
|
188
|
+
createdAt,
|
|
189
|
+
updatedAt: now,
|
|
190
|
+
};
|
|
191
|
+
contextStore.set(params.artifactId, artifact);
|
|
192
|
+
return params.artifactId;
|
|
193
|
+
}
|
|
194
|
+
async appendDatasetBatch(contextId, artifactId, rows, options) {
|
|
195
|
+
const contextStore = this.getContextStore(contextId);
|
|
196
|
+
const artifact = contextStore.get(artifactId);
|
|
197
|
+
if (!artifact) {
|
|
198
|
+
throw new Error(`Artifact not found: ${artifactId} in context ${contextId}`);
|
|
199
|
+
}
|
|
200
|
+
if (artifact.type !== 'dataset') {
|
|
201
|
+
throw new Error(`Artifact ${artifactId} is not a dataset artifact (type: ${artifact.type})`);
|
|
202
|
+
}
|
|
203
|
+
const now = new Date().toISOString();
|
|
204
|
+
if (rows && rows.length > 0) {
|
|
205
|
+
artifact.rows.push(...rows);
|
|
206
|
+
artifact.totalChunks += 1;
|
|
207
|
+
artifact.totalSize = artifact.rows.length;
|
|
208
|
+
artifact.operations.push({
|
|
209
|
+
operationId: randomUUID(),
|
|
210
|
+
type: 'append',
|
|
211
|
+
timestamp: now,
|
|
212
|
+
chunkIndex: artifact.totalChunks - 1,
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
artifact.updatedAt = now;
|
|
216
|
+
artifact.version += 1;
|
|
217
|
+
if (options?.isLastBatch) {
|
|
218
|
+
artifact.status = 'complete';
|
|
219
|
+
artifact.completedAt = now;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
async getDatasetRows(contextId, artifactId) {
|
|
223
|
+
const contextStore = this.getContextStore(contextId);
|
|
224
|
+
const artifact = contextStore.get(artifactId);
|
|
225
|
+
if (!artifact) {
|
|
226
|
+
throw new Error(`Artifact not found: ${artifactId} in context ${contextId}`);
|
|
227
|
+
}
|
|
228
|
+
if (artifact.type !== 'dataset') {
|
|
229
|
+
throw new Error(`Artifact ${artifactId} is not a dataset artifact (type: ${artifact.type})`);
|
|
230
|
+
}
|
|
231
|
+
return artifact.rows;
|
|
232
|
+
}
|
|
233
|
+
async getArtifact(contextId, artifactId) {
|
|
234
|
+
const contextStore = this.getContextStore(contextId);
|
|
235
|
+
return contextStore.get(artifactId) || null;
|
|
236
|
+
}
|
|
237
|
+
async listArtifacts(contextId, taskId) {
|
|
238
|
+
const contextStore = this.getContextStore(contextId);
|
|
239
|
+
const ids = [];
|
|
240
|
+
for (const [id, artifact] of contextStore.entries()) {
|
|
241
|
+
if (!taskId || artifact.taskId === taskId) {
|
|
242
|
+
ids.push(id);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return ids;
|
|
246
|
+
}
|
|
247
|
+
async deleteArtifact(contextId, artifactId) {
|
|
248
|
+
const contextStore = this.getContextStore(contextId);
|
|
249
|
+
contextStore.delete(artifactId);
|
|
250
|
+
}
|
|
251
|
+
async queryArtifacts(params) {
|
|
252
|
+
return this.listArtifacts(params.contextId, params.taskId);
|
|
253
|
+
}
|
|
254
|
+
async getArtifactByContext(contextId, artifactId) {
|
|
255
|
+
return this.getArtifact(contextId, artifactId);
|
|
256
|
+
}
|
|
257
|
+
async getTaskArtifacts(taskId) {
|
|
258
|
+
const ids = [];
|
|
259
|
+
for (const contextStore of this.artifacts.values()) {
|
|
260
|
+
for (const [id, artifact] of contextStore.entries()) {
|
|
261
|
+
if (artifact.taskId === taskId) {
|
|
262
|
+
ids.push(id);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
return ids;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { AgentState, AgentStore } from '../../types/agent';
|
|
2
|
+
export interface FileSystemAgentStoreConfig {
|
|
3
|
+
basePath?: string;
|
|
4
|
+
agentId: string;
|
|
5
|
+
stateFileName?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare class FileSystemAgentStore implements AgentStore {
|
|
8
|
+
private readonly basePath;
|
|
9
|
+
private readonly agentId;
|
|
10
|
+
private readonly stateFileName;
|
|
11
|
+
constructor(config: FileSystemAgentStoreConfig);
|
|
12
|
+
load(contextId: string): Promise<AgentState | null>;
|
|
13
|
+
save(contextId: string, state: AgentState): Promise<void>;
|
|
14
|
+
delete(contextId: string): Promise<void>;
|
|
15
|
+
private getContextDir;
|
|
16
|
+
private getStateFilePath;
|
|
17
|
+
private sanitizeName;
|
|
18
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { mkdir, rm, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
export class FileSystemAgentStore {
|
|
5
|
+
basePath;
|
|
6
|
+
agentId;
|
|
7
|
+
stateFileName;
|
|
8
|
+
constructor(config) {
|
|
9
|
+
this.basePath = config.basePath || './_agent_store';
|
|
10
|
+
this.agentId = config.agentId;
|
|
11
|
+
this.stateFileName = config.stateFileName || 'agent-state.json';
|
|
12
|
+
}
|
|
13
|
+
async load(contextId) {
|
|
14
|
+
try {
|
|
15
|
+
const filePath = this.getStateFilePath(contextId);
|
|
16
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
17
|
+
const parsed = JSON.parse(content);
|
|
18
|
+
return {
|
|
19
|
+
...parsed,
|
|
20
|
+
createdAt: new Date(parsed.createdAt),
|
|
21
|
+
lastActivity: new Date(parsed.lastActivity),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
if (error.code === 'ENOENT') {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
throw error;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
async save(contextId, state) {
|
|
32
|
+
const contextDir = this.getContextDir(contextId);
|
|
33
|
+
await mkdir(contextDir, { recursive: true });
|
|
34
|
+
const filePath = this.getStateFilePath(contextId);
|
|
35
|
+
const serializable = {
|
|
36
|
+
...state,
|
|
37
|
+
createdAt: state.createdAt.toISOString(),
|
|
38
|
+
lastActivity: state.lastActivity.toISOString(),
|
|
39
|
+
};
|
|
40
|
+
await writeFile(filePath, JSON.stringify(serializable, null, 2), 'utf-8');
|
|
41
|
+
}
|
|
42
|
+
async delete(contextId) {
|
|
43
|
+
const filePath = this.getStateFilePath(contextId);
|
|
44
|
+
try {
|
|
45
|
+
await rm(filePath, { force: true });
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
getContextDir(contextId) {
|
|
51
|
+
const safeAgentId = this.sanitizeName(this.agentId);
|
|
52
|
+
const safeContextId = this.sanitizeName(contextId);
|
|
53
|
+
return join(this.basePath, `agent=${safeAgentId}`, `context=${safeContextId}`);
|
|
54
|
+
}
|
|
55
|
+
getStateFilePath(contextId) {
|
|
56
|
+
return join(this.getContextDir(contextId), this.stateFileName);
|
|
57
|
+
}
|
|
58
|
+
sanitizeName(name) {
|
|
59
|
+
return name.replace(/[^a-zA-Z0-9_-]/g, '_');
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { ArtifactStore, DatasetSchema, StoredArtifact } from '../../types/artifact';
|
|
2
|
+
export interface FileSystemArtifactStoreConfig {
|
|
3
|
+
basePath?: string;
|
|
4
|
+
agentId: string;
|
|
5
|
+
}
|
|
6
|
+
export declare class FileSystemArtifactStore implements ArtifactStore {
|
|
7
|
+
private basePath;
|
|
8
|
+
private agentId;
|
|
9
|
+
constructor(config: FileSystemArtifactStoreConfig);
|
|
10
|
+
createFileArtifact(params: {
|
|
11
|
+
artifactId: string;
|
|
12
|
+
taskId: string;
|
|
13
|
+
contextId: string;
|
|
14
|
+
name?: string;
|
|
15
|
+
description?: string;
|
|
16
|
+
mimeType?: string;
|
|
17
|
+
encoding?: 'utf-8' | 'base64';
|
|
18
|
+
override?: boolean;
|
|
19
|
+
}): Promise<string>;
|
|
20
|
+
appendFileChunk(contextId: string, artifactId: string, chunk: string, options?: {
|
|
21
|
+
isLastChunk?: boolean;
|
|
22
|
+
}): Promise<void>;
|
|
23
|
+
getFileContent(contextId: string, artifactId: string): Promise<string>;
|
|
24
|
+
createDataArtifact(params: {
|
|
25
|
+
artifactId: string;
|
|
26
|
+
taskId: string;
|
|
27
|
+
contextId: string;
|
|
28
|
+
name?: string;
|
|
29
|
+
description?: string;
|
|
30
|
+
override?: boolean;
|
|
31
|
+
}): Promise<string>;
|
|
32
|
+
writeData(contextId: string, artifactId: string, data: Record<string, unknown>): Promise<void>;
|
|
33
|
+
getDataContent(contextId: string, artifactId: string): Promise<Record<string, unknown>>;
|
|
34
|
+
createDatasetArtifact(params: {
|
|
35
|
+
artifactId: string;
|
|
36
|
+
taskId: string;
|
|
37
|
+
contextId: string;
|
|
38
|
+
name?: string;
|
|
39
|
+
description?: string;
|
|
40
|
+
schema?: DatasetSchema;
|
|
41
|
+
override?: boolean;
|
|
42
|
+
}): Promise<string>;
|
|
43
|
+
appendDatasetBatch(contextId: string, artifactId: string, rows: Record<string, unknown>[], options?: {
|
|
44
|
+
isLastBatch?: boolean;
|
|
45
|
+
}): Promise<void>;
|
|
46
|
+
getDatasetRows(contextId: string, artifactId: string): Promise<Record<string, unknown>[]>;
|
|
47
|
+
getArtifact(contextId: string, artifactId: string): Promise<StoredArtifact | null>;
|
|
48
|
+
deleteArtifact(contextId: string, artifactId: string): Promise<void>;
|
|
49
|
+
listArtifacts(contextId: string, taskId?: string): Promise<string[]>;
|
|
50
|
+
queryArtifacts(query: {
|
|
51
|
+
taskId?: string;
|
|
52
|
+
contextId?: string;
|
|
53
|
+
status?: 'building' | 'complete' | 'failed';
|
|
54
|
+
}): Promise<string[]>;
|
|
55
|
+
getTaskArtifacts(_taskId: string): Promise<string[]>;
|
|
56
|
+
private getArtifactDir;
|
|
57
|
+
private saveMetadata;
|
|
58
|
+
private loadMetadata;
|
|
59
|
+
}
|