@pikku/mongodb 0.12.21 → 0.12.23
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/CHANGELOG.md +48 -0
- package/README.md +9 -1
- package/dist/src/mongodb-workflow-run-service.js +3 -13
- package/dist/src/mongodb-workflow-service.d.ts +38 -22
- package/dist/src/mongodb-workflow-service.js +130 -88
- package/package.json +10 -6
- package/run-tests.sh +21 -6
- package/dist/tsconfig.tsbuildinfo +0 -1
- package/src/index.ts +0 -14
- package/src/mongodb-agent-run-service.ts +0 -234
- package/src/mongodb-agent-storage-service.ts +0 -632
- package/src/mongodb-channel-store.ts +0 -109
- package/src/mongodb-deployment-service.ts +0 -136
- package/src/mongodb-eventhub-store.ts +0 -52
- package/src/mongodb-secret-service.ts +0 -232
- package/src/mongodb-services.test.ts +0 -235
- package/src/mongodb-session-store.ts +0 -50
- package/src/mongodb-workflow-run-service.ts +0 -235
- package/src/mongodb-workflow-service.test.ts +0 -238
- package/src/mongodb-workflow-service.ts +0 -687
- package/src/pikku-mongodb.ts +0 -41
- package/tsconfig.json +0 -17
package/run-tests.sh
CHANGED
|
@@ -34,20 +34,35 @@ files=($(find src -type f -name "*.test.ts"))
|
|
|
34
34
|
# Check if any files matched the pattern
|
|
35
35
|
if [ ${#files[@]} -eq 0 ]; then
|
|
36
36
|
echo "No test files found matching pattern: $pattern"
|
|
37
|
+
if [ "${STRICT_TEST_DISCOVERY}" = "1" ]; then
|
|
38
|
+
exit 1
|
|
39
|
+
fi
|
|
37
40
|
exit 0
|
|
38
41
|
fi
|
|
39
42
|
|
|
40
|
-
# Construct the
|
|
41
|
-
|
|
43
|
+
# Construct the bun command
|
|
44
|
+
#
|
|
45
|
+
# --parallel gives every test file its own worker process, which is what node's
|
|
46
|
+
# `--test` did. Several suites keep module-level caches (a TypeScript program, a
|
|
47
|
+
# temp fixture directory) that a shared process would leak between files.
|
|
48
|
+
#
|
|
49
|
+
# --timeout because bun caps a test at 5s by default where node had no cap, and
|
|
50
|
+
# the suites that build real TypeScript programs run well past that.
|
|
51
|
+
bun_cmd=(bun test --parallel --timeout 120000)
|
|
42
52
|
|
|
43
53
|
# Append options based on flags
|
|
44
54
|
if [ "$watch_mode" = true ]; then
|
|
45
|
-
|
|
55
|
+
# --watch reruns in one process; parallel workers have nothing to watch.
|
|
56
|
+
bun_cmd=(bun test --watch --timeout 120000)
|
|
46
57
|
fi
|
|
47
58
|
|
|
48
59
|
if [ "$coverage_mode" = true ]; then
|
|
49
|
-
|
|
60
|
+
# --coverage-dir=. keeps lcov.info at the package root: CI merges every
|
|
61
|
+
# package's report by prefixing its SF paths with the file's own directory,
|
|
62
|
+
# so a nested coverage/ directory would re-root them one level too deep.
|
|
63
|
+
bun_cmd+=(--coverage --coverage-reporter=lcov --coverage-reporter=text --coverage-dir=.)
|
|
64
|
+
export PIKKU_TEST_COVERAGE=1
|
|
50
65
|
fi
|
|
51
66
|
|
|
52
|
-
# Execute the
|
|
53
|
-
"${
|
|
67
|
+
# Execute the bun command with the expanded list of files
|
|
68
|
+
"${bun_cmd[@]}" "${files[@]}"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"root":["../src/index.ts","../src/mongodb-agent-run-service.ts","../src/mongodb-agent-storage-service.ts","../src/mongodb-channel-store.ts","../src/mongodb-deployment-service.ts","../src/mongodb-eventhub-store.ts","../src/mongodb-secret-service.ts","../src/mongodb-session-store.ts","../src/mongodb-workflow-run-service.ts","../src/mongodb-workflow-service.ts","../src/pikku-mongodb.ts"],"version":"6.0.3"}
|
package/src/index.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export { PikkuMongoDB } from './pikku-mongodb.js'
|
|
2
|
-
|
|
3
|
-
export { MongoDBChannelStore } from './mongodb-channel-store.js'
|
|
4
|
-
export { MongoDBEventHubStore } from './mongodb-eventhub-store.js'
|
|
5
|
-
export { MongoDBWorkflowService } from './mongodb-workflow-service.js'
|
|
6
|
-
export { MongoDBWorkflowRunService } from './mongodb-workflow-run-service.js'
|
|
7
|
-
export { MongoDBDeploymentService } from './mongodb-deployment-service.js'
|
|
8
|
-
export { MongoDBAgentStorageService } from './mongodb-agent-storage-service.js'
|
|
9
|
-
export { MongoDBAgentRunService } from './mongodb-agent-run-service.js'
|
|
10
|
-
export { MongoDBSecretService } from './mongodb-secret-service.js'
|
|
11
|
-
|
|
12
|
-
export type { WorkflowRunService } from '@pikku/core/workflow'
|
|
13
|
-
export type { AgentRunService, AgentRunRow } from '@pikku/core/agent'
|
|
14
|
-
export { MongoDBSessionStore } from './mongodb-session-store.js'
|
|
@@ -1,234 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
AgentThread,
|
|
3
|
-
AgentMessage,
|
|
4
|
-
AgentRunRow,
|
|
5
|
-
AgentRunService,
|
|
6
|
-
} from '@pikku/core/agent'
|
|
7
|
-
import type { Db, Collection } from 'mongodb'
|
|
8
|
-
|
|
9
|
-
// Owner ids are untrusted input to the regex, so metacharacters must not be
|
|
10
|
-
// able to widen the prefix match.
|
|
11
|
-
const escapeRegExp = (value: string) =>
|
|
12
|
-
value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
13
|
-
|
|
14
|
-
interface AgentThreadDoc {
|
|
15
|
-
_id: string
|
|
16
|
-
resourceId: string
|
|
17
|
-
title: string | null
|
|
18
|
-
metadata: any | null
|
|
19
|
-
createdAt: Date
|
|
20
|
-
updatedAt: Date
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
interface AgentMessageDoc {
|
|
24
|
-
_id: string
|
|
25
|
-
threadId: string
|
|
26
|
-
role: string
|
|
27
|
-
content: string | null
|
|
28
|
-
createdAt: Date
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
interface AgentToolCallDoc {
|
|
32
|
-
_id: string
|
|
33
|
-
threadId: string
|
|
34
|
-
messageId: string
|
|
35
|
-
runId: string | null
|
|
36
|
-
toolName: string
|
|
37
|
-
args: any
|
|
38
|
-
result: string | null
|
|
39
|
-
approvalStatus: string | null
|
|
40
|
-
approvalType: string | null
|
|
41
|
-
agentRunId: string | null
|
|
42
|
-
displayToolName: string | null
|
|
43
|
-
displayArgs: any | null
|
|
44
|
-
createdAt: Date
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
interface AgentRunDoc {
|
|
48
|
-
_id: string
|
|
49
|
-
agentName: string
|
|
50
|
-
threadId: string
|
|
51
|
-
resourceId: string
|
|
52
|
-
status: string
|
|
53
|
-
errorMessage: string | null
|
|
54
|
-
suspendReason: string | null
|
|
55
|
-
missingRpcs: any | null
|
|
56
|
-
usageInputTokens: number
|
|
57
|
-
usageOutputTokens: number
|
|
58
|
-
usageModel: string
|
|
59
|
-
createdAt: Date
|
|
60
|
-
updatedAt: Date
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export class MongoDBAgentRunService implements AgentRunService {
|
|
64
|
-
private threads: Collection<AgentThreadDoc>
|
|
65
|
-
private messages: Collection<AgentMessageDoc>
|
|
66
|
-
private toolCalls: Collection<AgentToolCallDoc>
|
|
67
|
-
private runs: Collection<AgentRunDoc>
|
|
68
|
-
|
|
69
|
-
constructor(db: Db) {
|
|
70
|
-
this.threads = db.collection<AgentThreadDoc>('agent_threads')
|
|
71
|
-
this.messages = db.collection<AgentMessageDoc>('agent_message')
|
|
72
|
-
this.toolCalls = db.collection<AgentToolCallDoc>('agent_tool_call')
|
|
73
|
-
this.runs = db.collection<AgentRunDoc>('agent_run')
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
async listThreads(options?: {
|
|
77
|
-
agentName?: string
|
|
78
|
-
resourceId?: string
|
|
79
|
-
owners?: string[]
|
|
80
|
-
limit?: number
|
|
81
|
-
offset?: number
|
|
82
|
-
}): Promise<AgentThread[]> {
|
|
83
|
-
const {
|
|
84
|
-
agentName,
|
|
85
|
-
resourceId,
|
|
86
|
-
owners,
|
|
87
|
-
limit = 50,
|
|
88
|
-
offset = 0,
|
|
89
|
-
} = options ?? {}
|
|
90
|
-
|
|
91
|
-
// An owners constraint is an authorization boundary, so an empty list must
|
|
92
|
-
// match nothing rather than degrade to "no filter".
|
|
93
|
-
if (owners && owners.length === 0) return []
|
|
94
|
-
|
|
95
|
-
let filter: Record<string, any> = {}
|
|
96
|
-
|
|
97
|
-
if (resourceId) {
|
|
98
|
-
filter.resourceId = resourceId
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
if (owners) {
|
|
102
|
-
filter.$or = owners.flatMap((owner) => [
|
|
103
|
-
{ resourceId: owner },
|
|
104
|
-
{ resourceId: { $regex: `^${escapeRegExp(owner)}:` } },
|
|
105
|
-
])
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
if (agentName) {
|
|
109
|
-
const threadIds = await this.runs.distinct('threadId', {
|
|
110
|
-
agentName,
|
|
111
|
-
})
|
|
112
|
-
filter._id = { $in: threadIds }
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const result = await this.threads
|
|
116
|
-
.find(filter)
|
|
117
|
-
.sort({ updatedAt: -1 })
|
|
118
|
-
.skip(offset)
|
|
119
|
-
.limit(limit)
|
|
120
|
-
.toArray()
|
|
121
|
-
|
|
122
|
-
return result.map((row) => this.mapThreadRow(row))
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
async getThread(threadId: string): Promise<AgentThread | null> {
|
|
126
|
-
const row = await this.threads.findOne({ _id: threadId })
|
|
127
|
-
if (!row) return null
|
|
128
|
-
return this.mapThreadRow(row)
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
async getThreadMessages(threadId: string): Promise<AgentMessage[]> {
|
|
132
|
-
const [msgResult, tcResult] = await Promise.all([
|
|
133
|
-
this.messages.find({ threadId }).sort({ createdAt: 1 }).toArray(),
|
|
134
|
-
this.toolCalls.find({ threadId }).sort({ createdAt: 1 }).toArray(),
|
|
135
|
-
])
|
|
136
|
-
|
|
137
|
-
const tcByMessage = new Map<string, (typeof tcResult)[number][]>()
|
|
138
|
-
for (const tc of tcResult) {
|
|
139
|
-
const msgId = tc.messageId
|
|
140
|
-
if (!tcByMessage.has(msgId)) tcByMessage.set(msgId, [])
|
|
141
|
-
tcByMessage.get(msgId)!.push(tc)
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
const messages: AgentMessage[] = []
|
|
145
|
-
for (const row of msgResult) {
|
|
146
|
-
const msg: AgentMessage = {
|
|
147
|
-
id: row._id,
|
|
148
|
-
role: row.role as AgentMessage['role'],
|
|
149
|
-
content: row.content ?? undefined,
|
|
150
|
-
createdAt: new Date(row.createdAt),
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
const tcs = tcByMessage.get(msg.id)
|
|
154
|
-
if (tcs?.length) {
|
|
155
|
-
msg.toolCalls = tcs.map((tc) => ({
|
|
156
|
-
id: tc._id,
|
|
157
|
-
name: tc.toolName,
|
|
158
|
-
args: tc.args as Record<string, unknown>,
|
|
159
|
-
}))
|
|
160
|
-
|
|
161
|
-
const completed = tcs.filter((tc) => tc.result != null)
|
|
162
|
-
if (completed.length) {
|
|
163
|
-
messages.push(msg)
|
|
164
|
-
messages.push({
|
|
165
|
-
id: `tool-results-${msg.id}`,
|
|
166
|
-
role: 'tool',
|
|
167
|
-
toolResults: completed.map((tc) => ({
|
|
168
|
-
id: tc._id,
|
|
169
|
-
name: tc.toolName,
|
|
170
|
-
result: tc.result!,
|
|
171
|
-
})),
|
|
172
|
-
createdAt: msg.createdAt,
|
|
173
|
-
})
|
|
174
|
-
continue
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
messages.push(msg)
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
return messages
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
async getThreadRuns(threadId: string): Promise<AgentRunRow[]> {
|
|
185
|
-
const result = await this.runs
|
|
186
|
-
.find({ threadId })
|
|
187
|
-
.sort({ createdAt: -1 })
|
|
188
|
-
.toArray()
|
|
189
|
-
|
|
190
|
-
return result.map((row) => this.mapRunRow(row))
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
async deleteThread(threadId: string): Promise<boolean> {
|
|
194
|
-
await this.toolCalls.deleteMany({ threadId })
|
|
195
|
-
await this.messages.deleteMany({ threadId })
|
|
196
|
-
await this.runs.deleteMany({ threadId })
|
|
197
|
-
const result = await this.threads.deleteOne({ _id: threadId })
|
|
198
|
-
return result.deletedCount > 0
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
async getDistinctAgentNames(): Promise<string[]> {
|
|
202
|
-
const result = await this.runs.distinct('agentName')
|
|
203
|
-
return result.sort()
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
private mapThreadRow(row: AgentThreadDoc): AgentThread {
|
|
207
|
-
return {
|
|
208
|
-
id: row._id,
|
|
209
|
-
resourceId: row.resourceId,
|
|
210
|
-
title: row.title ?? undefined,
|
|
211
|
-
metadata: row.metadata ?? undefined,
|
|
212
|
-
createdAt: new Date(row.createdAt),
|
|
213
|
-
updatedAt: new Date(row.updatedAt),
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
private mapRunRow(row: AgentRunDoc): AgentRunRow {
|
|
218
|
-
return {
|
|
219
|
-
runId: row._id,
|
|
220
|
-
agentName: row.agentName,
|
|
221
|
-
threadId: row.threadId,
|
|
222
|
-
resourceId: row.resourceId,
|
|
223
|
-
status: row.status,
|
|
224
|
-
errorMessage: row.errorMessage ?? undefined,
|
|
225
|
-
suspendReason: row.suspendReason ?? undefined,
|
|
226
|
-
missingRpcs: row.missingRpcs ?? undefined,
|
|
227
|
-
usageInputTokens: Number(row.usageInputTokens),
|
|
228
|
-
usageOutputTokens: Number(row.usageOutputTokens),
|
|
229
|
-
usageModel: row.usageModel,
|
|
230
|
-
createdAt: new Date(row.createdAt),
|
|
231
|
-
updatedAt: new Date(row.updatedAt),
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
}
|