@poncho-ai/harness 0.36.4 → 0.37.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/.turbo/turbo-build.log +4 -4
- package/CHANGELOG.md +12 -0
- package/dist/index.js +59 -13
- package/package.json +1 -1
- package/scripts/migrate-to-engine.mjs +61 -36
- package/src/storage/schema.ts +32 -0
- package/src/storage/sql-dialect.ts +29 -11
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @poncho-ai/harness@0.
|
|
2
|
+
> @poncho-ai/harness@0.37.1 build /home/runner/work/poncho-ai/poncho-ai/packages/harness
|
|
3
3
|
> node scripts/embed-docs.js && tsup src/index.ts --format esm --dts
|
|
4
4
|
|
|
5
5
|
[embed-docs] Generated poncho-docs.ts with 4 topics
|
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
[34mCLI[39m tsup v8.5.1
|
|
9
9
|
[34mCLI[39m Target: es2022
|
|
10
10
|
[34mESM[39m Build start
|
|
11
|
-
[32mESM[39m [1mdist/index.js [22m[
|
|
11
|
+
[32mESM[39m [1mdist/index.js [22m[32m389.90 KB[39m
|
|
12
12
|
[32mESM[39m [1mdist/isolate-TCWTUVG4.js [22m[32m47.34 KB[39m
|
|
13
|
-
[32mESM[39m ⚡️ Build success in
|
|
13
|
+
[32mESM[39m ⚡️ Build success in 211ms
|
|
14
14
|
[34mDTS[39m Build start
|
|
15
|
-
[32mDTS[39m ⚡️ Build success in
|
|
15
|
+
[32mDTS[39m ⚡️ Build success in 6845ms
|
|
16
16
|
[32mDTS[39m [1mdist/index.d.ts [22m[32m56.62 KB[39m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @poncho-ai/harness
|
|
2
2
|
|
|
3
|
+
## 0.37.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`fb61a62`](https://github.com/cesr/poncho-ai/commit/fb61a6259367f0a62d0acd7a20ef2fae93013819) Thanks [@cesr](https://github.com/cesr)! - fix: migration script now discovers and migrates all agent directories instead of only the first one
|
|
8
|
+
|
|
9
|
+
## 0.37.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- [`86bc5ac`](https://github.com/cesr/poncho-ai/commit/86bc5ac2a73b80a286228cd9e3b663b50b3d82e7) Thanks [@cesr](https://github.com/cesr)! - perf: promote parentConversationId, pendingApprovals, and channelMeta to dedicated columns so list/summary queries no longer fetch the full data JSONB blob — dramatically reduces database egress
|
|
14
|
+
|
|
3
15
|
## 0.36.4
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/dist/index.js
CHANGED
|
@@ -3177,6 +3177,36 @@ var migrations = [
|
|
|
3177
3177
|
]
|
|
3178
3178
|
];
|
|
3179
3179
|
}
|
|
3180
|
+
},
|
|
3181
|
+
{
|
|
3182
|
+
version: 4,
|
|
3183
|
+
name: "promote_summary_fields_to_columns",
|
|
3184
|
+
up: (d) => {
|
|
3185
|
+
const jsonType = d === "sqlite" ? "TEXT" : "JSONB";
|
|
3186
|
+
return [
|
|
3187
|
+
`ALTER TABLE conversations ADD COLUMN parent_conversation_id TEXT`,
|
|
3188
|
+
`ALTER TABLE conversations ADD COLUMN has_pending_approvals INTEGER NOT NULL DEFAULT 0`,
|
|
3189
|
+
`ALTER TABLE conversations ADD COLUMN channel_meta ${jsonType}`,
|
|
3190
|
+
// Backfill from data blob
|
|
3191
|
+
...d === "sqlite" ? [
|
|
3192
|
+
`UPDATE conversations SET
|
|
3193
|
+
parent_conversation_id = json_extract(data, '$.parentConversationId'),
|
|
3194
|
+
has_pending_approvals = CASE
|
|
3195
|
+
WHEN json_array_length(COALESCE(json_extract(data, '$.pendingApprovals'), '[]')) > 0 THEN 1
|
|
3196
|
+
ELSE 0
|
|
3197
|
+
END,
|
|
3198
|
+
channel_meta = json_extract(data, '$.channelMeta')`
|
|
3199
|
+
] : [
|
|
3200
|
+
`UPDATE conversations SET
|
|
3201
|
+
parent_conversation_id = data->>'parentConversationId',
|
|
3202
|
+
has_pending_approvals = CASE
|
|
3203
|
+
WHEN jsonb_array_length(COALESCE(data->'pendingApprovals', '[]'::jsonb)) > 0 THEN 1
|
|
3204
|
+
ELSE 0
|
|
3205
|
+
END,
|
|
3206
|
+
channel_meta = data->'channelMeta'`
|
|
3207
|
+
]
|
|
3208
|
+
];
|
|
3209
|
+
}
|
|
3180
3210
|
}
|
|
3181
3211
|
];
|
|
3182
3212
|
|
|
@@ -3275,7 +3305,8 @@ var SqlStorageEngine = class {
|
|
|
3275
3305
|
const filterTenant = tenantId !== void 0;
|
|
3276
3306
|
const params = [this.agentId];
|
|
3277
3307
|
let sql = `SELECT id, title, updated_at, created_at, owner_id, tenant_id,
|
|
3278
|
-
message_count,
|
|
3308
|
+
message_count, parent_conversation_id,
|
|
3309
|
+
has_pending_approvals, channel_meta
|
|
3279
3310
|
FROM conversations WHERE agent_id = $1`;
|
|
3280
3311
|
if (filterTenant) {
|
|
3281
3312
|
sql += ` AND tenant_id = $2`;
|
|
@@ -3322,8 +3353,9 @@ var SqlStorageEngine = class {
|
|
|
3322
3353
|
const data = JSON.stringify(conv);
|
|
3323
3354
|
await this.executor.run(
|
|
3324
3355
|
rewrite(
|
|
3325
|
-
`INSERT INTO conversations (id, agent_id, tenant_id, owner_id, title, data, message_count, created_at, updated_at
|
|
3326
|
-
|
|
3356
|
+
`INSERT INTO conversations (id, agent_id, tenant_id, owner_id, title, data, message_count, created_at, updated_at,
|
|
3357
|
+
parent_conversation_id, has_pending_approvals, channel_meta)
|
|
3358
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)`,
|
|
3327
3359
|
this.dialect
|
|
3328
3360
|
),
|
|
3329
3361
|
[
|
|
@@ -3335,7 +3367,10 @@ var SqlStorageEngine = class {
|
|
|
3335
3367
|
data,
|
|
3336
3368
|
0,
|
|
3337
3369
|
new Date(now2).toISOString(),
|
|
3338
|
-
new Date(now2).toISOString()
|
|
3370
|
+
new Date(now2).toISOString(),
|
|
3371
|
+
null,
|
|
3372
|
+
0,
|
|
3373
|
+
null
|
|
3339
3374
|
]
|
|
3340
3375
|
);
|
|
3341
3376
|
return conv;
|
|
@@ -3358,16 +3393,23 @@ var SqlStorageEngine = class {
|
|
|
3358
3393
|
const tid = normalizeTenant2(conversation.tenantId);
|
|
3359
3394
|
const now2 = new Date(conversation.updatedAt).toISOString();
|
|
3360
3395
|
const created = new Date(conversation.createdAt).toISOString();
|
|
3396
|
+
const parentConvId = conversation.parentConversationId ?? null;
|
|
3397
|
+
const hasPendingApprovals = (conversation.pendingApprovals?.length ?? 0) > 0 ? 1 : 0;
|
|
3398
|
+
const channelMetaJson = conversation.channelMeta ? JSON.stringify(conversation.channelMeta) : null;
|
|
3361
3399
|
await this.executor.run(
|
|
3362
3400
|
rewrite(
|
|
3363
3401
|
`INSERT INTO conversations (id, agent_id, tenant_id, owner_id, title, data, message_count, created_at, updated_at,
|
|
3364
|
-
tool_result_archive, harness_messages, continuation_messages
|
|
3365
|
-
|
|
3402
|
+
tool_result_archive, harness_messages, continuation_messages,
|
|
3403
|
+
parent_conversation_id, has_pending_approvals, channel_meta)
|
|
3404
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15)
|
|
3366
3405
|
${this.dialect.upsert(["id"])}
|
|
3367
3406
|
data = excluded.data, title = excluded.title, message_count = excluded.message_count,
|
|
3368
3407
|
updated_at = excluded.updated_at, tenant_id = excluded.tenant_id, owner_id = excluded.owner_id,
|
|
3369
3408
|
tool_result_archive = excluded.tool_result_archive, harness_messages = excluded.harness_messages,
|
|
3370
|
-
continuation_messages = excluded.continuation_messages
|
|
3409
|
+
continuation_messages = excluded.continuation_messages,
|
|
3410
|
+
parent_conversation_id = excluded.parent_conversation_id,
|
|
3411
|
+
has_pending_approvals = excluded.has_pending_approvals,
|
|
3412
|
+
channel_meta = excluded.channel_meta`,
|
|
3371
3413
|
this.dialect
|
|
3372
3414
|
),
|
|
3373
3415
|
[
|
|
@@ -3382,7 +3424,10 @@ var SqlStorageEngine = class {
|
|
|
3382
3424
|
now2,
|
|
3383
3425
|
archiveJson,
|
|
3384
3426
|
harnessJson,
|
|
3385
|
-
continuationJson
|
|
3427
|
+
continuationJson,
|
|
3428
|
+
parentConvId,
|
|
3429
|
+
hasPendingApprovals,
|
|
3430
|
+
channelMetaJson
|
|
3386
3431
|
]
|
|
3387
3432
|
);
|
|
3388
3433
|
},
|
|
@@ -3411,7 +3456,8 @@ var SqlStorageEngine = class {
|
|
|
3411
3456
|
const pattern = `%${query}%`;
|
|
3412
3457
|
const params = [this.agentId, pattern, pattern];
|
|
3413
3458
|
let sql = `SELECT id, title, updated_at, created_at, owner_id, tenant_id,
|
|
3414
|
-
message_count,
|
|
3459
|
+
message_count, parent_conversation_id,
|
|
3460
|
+
has_pending_approvals, channel_meta
|
|
3415
3461
|
FROM conversations
|
|
3416
3462
|
WHERE agent_id = $1 AND (title LIKE $2 OR data LIKE $3)`;
|
|
3417
3463
|
if (filterTenant) {
|
|
@@ -3841,8 +3887,8 @@ var SqlStorageEngine = class {
|
|
|
3841
3887
|
return data;
|
|
3842
3888
|
}
|
|
3843
3889
|
rowToSummary(row) {
|
|
3844
|
-
const data = this.parseConversation(row.data);
|
|
3845
3890
|
const tid = row.tenant_id;
|
|
3891
|
+
const rawChannelMeta = row.channel_meta;
|
|
3846
3892
|
return {
|
|
3847
3893
|
conversationId: row.id,
|
|
3848
3894
|
title: row.title,
|
|
@@ -3851,9 +3897,9 @@ var SqlStorageEngine = class {
|
|
|
3851
3897
|
ownerId: row.owner_id,
|
|
3852
3898
|
tenantId: tid === DEFAULT_TENANT2 ? null : tid,
|
|
3853
3899
|
messageCount: row.message_count,
|
|
3854
|
-
hasPendingApprovals:
|
|
3855
|
-
parentConversationId:
|
|
3856
|
-
channelMeta:
|
|
3900
|
+
hasPendingApprovals: !!row.has_pending_approvals,
|
|
3901
|
+
parentConversationId: row.parent_conversation_id || void 0,
|
|
3902
|
+
channelMeta: rawChannelMeta ? typeof rawChannelMeta === "string" ? JSON.parse(rawChannelMeta) : rawChannelMeta : void 0
|
|
3857
3903
|
};
|
|
3858
3904
|
}
|
|
3859
3905
|
rowToReminder(row) {
|
package/package.json
CHANGED
|
@@ -106,30 +106,26 @@ async function readJsonSafe(filePath) {
|
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
-
async function
|
|
109
|
+
async function findAgentDirs(workingDir) {
|
|
110
110
|
const ponchoDir = resolve(workingDir, ".poncho");
|
|
111
|
+
const results = [];
|
|
111
112
|
try {
|
|
112
113
|
const entries = await readdir(ponchoDir, { withFileTypes: true });
|
|
113
114
|
for (const e of entries) {
|
|
114
115
|
if (e.isDirectory() && !e.name.startsWith(".")) {
|
|
115
|
-
|
|
116
|
+
results.push({ dir: resolve(ponchoDir, e.name), id: e.name });
|
|
116
117
|
}
|
|
117
118
|
}
|
|
118
119
|
} catch { /* no .poncho dir */ }
|
|
119
|
-
return
|
|
120
|
+
return results;
|
|
120
121
|
}
|
|
121
122
|
|
|
122
123
|
// ---------------------------------------------------------------------------
|
|
123
124
|
// Read from local
|
|
124
125
|
// ---------------------------------------------------------------------------
|
|
125
126
|
|
|
126
|
-
async function
|
|
127
|
-
|
|
128
|
-
if (!agent) {
|
|
129
|
-
console.error("No .poncho agent directory found in", workingDir);
|
|
130
|
-
process.exit(1);
|
|
131
|
-
}
|
|
132
|
-
console.log(`Found local agent: ${agent.id} at ${agent.dir}`);
|
|
127
|
+
async function readLocalAgent(agent) {
|
|
128
|
+
console.log(` Reading agent: ${agent.id} at ${agent.dir}`);
|
|
133
129
|
|
|
134
130
|
const data = { agentId: agent.id, conversations: [], memories: [], todos: [], reminders: [] };
|
|
135
131
|
|
|
@@ -189,6 +185,29 @@ async function readLocal(workingDir) {
|
|
|
189
185
|
return data;
|
|
190
186
|
}
|
|
191
187
|
|
|
188
|
+
async function readLocal(workingDir) {
|
|
189
|
+
const agents = await findAgentDirs(workingDir);
|
|
190
|
+
if (agents.length === 0) {
|
|
191
|
+
console.error("No .poncho agent directory found in", workingDir);
|
|
192
|
+
process.exit(1);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// If --agent-id is specified, filter to that agent
|
|
196
|
+
const filtered = AGENT_ID ? agents.filter((a) => a.id === AGENT_ID) : agents;
|
|
197
|
+
if (filtered.length === 0) {
|
|
198
|
+
console.error(`Agent "${AGENT_ID}" not found. Available agents: ${agents.map((a) => a.id).join(", ")}`);
|
|
199
|
+
process.exit(1);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
console.log(`Found ${filtered.length} agent(s) to migrate`);
|
|
203
|
+
|
|
204
|
+
const results = [];
|
|
205
|
+
for (const agent of filtered) {
|
|
206
|
+
results.push(await readLocalAgent(agent));
|
|
207
|
+
}
|
|
208
|
+
return results;
|
|
209
|
+
}
|
|
210
|
+
|
|
192
211
|
// ---------------------------------------------------------------------------
|
|
193
212
|
// Read from Upstash
|
|
194
213
|
// ---------------------------------------------------------------------------
|
|
@@ -323,9 +342,12 @@ async function readUpstash(agentId) {
|
|
|
323
342
|
async function readFromEngine(sourceProvider, agentId) {
|
|
324
343
|
if (!agentId) {
|
|
325
344
|
// Try to detect from .poncho directory
|
|
326
|
-
const
|
|
327
|
-
if (
|
|
328
|
-
else {
|
|
345
|
+
const agents = await findAgentDirs(WORKING_DIR);
|
|
346
|
+
if (agents.length === 1) agentId = agents[0].id;
|
|
347
|
+
else if (agents.length > 1) {
|
|
348
|
+
console.error(`Multiple agents found: ${agents.map((a) => a.id).join(", ")}. Use --agent-id to specify one.`);
|
|
349
|
+
process.exit(1);
|
|
350
|
+
} else {
|
|
329
351
|
console.error("--agent-id is required for engine source (or run from a project with .poncho/)");
|
|
330
352
|
process.exit(1);
|
|
331
353
|
}
|
|
@@ -513,40 +535,43 @@ async function main() {
|
|
|
513
535
|
console.log(`Working dir: ${WORKING_DIR}`);
|
|
514
536
|
if (DRY_RUN) console.log("(dry run — no data will be written)\n");
|
|
515
537
|
|
|
516
|
-
// Read source
|
|
517
|
-
let
|
|
538
|
+
// Read source — local returns an array (one per agent), others return a single object
|
|
539
|
+
let dataList;
|
|
518
540
|
if (SOURCE === "local") {
|
|
519
|
-
|
|
541
|
+
dataList = await readLocal(WORKING_DIR);
|
|
520
542
|
} else if (SOURCE === "upstash") {
|
|
521
|
-
|
|
543
|
+
dataList = [await readUpstash(AGENT_ID)];
|
|
522
544
|
} else if (SOURCE === "sqlite" || SOURCE === "postgresql") {
|
|
523
|
-
|
|
545
|
+
dataList = [await readFromEngine(SOURCE, AGENT_ID)];
|
|
524
546
|
} else {
|
|
525
547
|
console.error(`Unknown source: ${SOURCE}. Use "local", "upstash", "sqlite", or "postgresql".`);
|
|
526
548
|
process.exit(1);
|
|
527
549
|
}
|
|
528
550
|
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
551
|
+
for (const data of dataList) {
|
|
552
|
+
console.log(`\nAgent: ${data.agentId}`);
|
|
553
|
+
console.log(` Read from ${SOURCE}:`);
|
|
554
|
+
console.log(` Conversations: ${data.conversations.length}`);
|
|
555
|
+
console.log(` Memories: ${data.memories?.length ?? 0}`);
|
|
556
|
+
console.log(` Todo lists: ${data.todos.length}`);
|
|
557
|
+
console.log(` Reminders: ${data.reminders.length}`);
|
|
558
|
+
if (data.vfsFiles?.length) console.log(` VFS files: ${data.vfsFiles.length}`);
|
|
559
|
+
|
|
560
|
+
if (data.conversations.length === 0 && !data.memories?.length && data.todos.length === 0 && data.reminders.length === 0 && !data.vfsFiles?.length) {
|
|
561
|
+
console.log(" Nothing to migrate for this agent.");
|
|
562
|
+
continue;
|
|
563
|
+
}
|
|
535
564
|
|
|
536
|
-
|
|
537
|
-
console.log("\nNothing to migrate.");
|
|
538
|
-
process.exit(0);
|
|
539
|
-
}
|
|
565
|
+
const result = await writeToEngine(data);
|
|
540
566
|
|
|
541
|
-
|
|
542
|
-
|
|
567
|
+
console.log(` ${DRY_RUN ? "Would import" : "Imported"} to ${TARGET}:`);
|
|
568
|
+
console.log(` Conversations: ${result.convCount}`);
|
|
569
|
+
console.log(` Memories: ${result.memoryCount}`);
|
|
570
|
+
console.log(` Todos: ${result.todoCount}`);
|
|
571
|
+
console.log(` Reminders: ${result.reminderCount}`);
|
|
572
|
+
if (result.vfsCount) console.log(` VFS files: ${result.vfsCount}`);
|
|
573
|
+
}
|
|
543
574
|
|
|
544
|
-
console.log(`\n${DRY_RUN ? "Would import" : "Imported"} to ${TARGET}:`);
|
|
545
|
-
console.log(` Conversations: ${result.convCount}`);
|
|
546
|
-
console.log(` Memories: ${result.memoryCount}`);
|
|
547
|
-
console.log(` Todos: ${result.todoCount}`);
|
|
548
|
-
console.log(` Reminders: ${result.reminderCount}`);
|
|
549
|
-
if (result.vfsCount) console.log(` VFS files: ${result.vfsCount}`);
|
|
550
575
|
console.log("\nDone!");
|
|
551
576
|
}
|
|
552
577
|
|
package/src/storage/schema.ts
CHANGED
|
@@ -142,4 +142,36 @@ export const migrations: Migration[] = [
|
|
|
142
142
|
];
|
|
143
143
|
},
|
|
144
144
|
},
|
|
145
|
+
{
|
|
146
|
+
version: 4,
|
|
147
|
+
name: "promote_summary_fields_to_columns",
|
|
148
|
+
up: (d) => {
|
|
149
|
+
const jsonType = d === "sqlite" ? "TEXT" : "JSONB";
|
|
150
|
+
return [
|
|
151
|
+
`ALTER TABLE conversations ADD COLUMN parent_conversation_id TEXT`,
|
|
152
|
+
`ALTER TABLE conversations ADD COLUMN has_pending_approvals INTEGER NOT NULL DEFAULT 0`,
|
|
153
|
+
`ALTER TABLE conversations ADD COLUMN channel_meta ${jsonType}`,
|
|
154
|
+
// Backfill from data blob
|
|
155
|
+
...(d === "sqlite"
|
|
156
|
+
? [
|
|
157
|
+
`UPDATE conversations SET
|
|
158
|
+
parent_conversation_id = json_extract(data, '$.parentConversationId'),
|
|
159
|
+
has_pending_approvals = CASE
|
|
160
|
+
WHEN json_array_length(COALESCE(json_extract(data, '$.pendingApprovals'), '[]')) > 0 THEN 1
|
|
161
|
+
ELSE 0
|
|
162
|
+
END,
|
|
163
|
+
channel_meta = json_extract(data, '$.channelMeta')`,
|
|
164
|
+
]
|
|
165
|
+
: [
|
|
166
|
+
`UPDATE conversations SET
|
|
167
|
+
parent_conversation_id = data->>'parentConversationId',
|
|
168
|
+
has_pending_approvals = CASE
|
|
169
|
+
WHEN jsonb_array_length(COALESCE(data->'pendingApprovals', '[]'::jsonb)) > 0 THEN 1
|
|
170
|
+
ELSE 0
|
|
171
|
+
END,
|
|
172
|
+
channel_meta = data->'channelMeta'`,
|
|
173
|
+
]),
|
|
174
|
+
];
|
|
175
|
+
},
|
|
176
|
+
},
|
|
145
177
|
];
|
|
@@ -189,7 +189,8 @@ export abstract class SqlStorageEngine implements StorageEngine {
|
|
|
189
189
|
const filterTenant = tenantId !== undefined;
|
|
190
190
|
const params: unknown[] = [this.agentId];
|
|
191
191
|
let sql = `SELECT id, title, updated_at, created_at, owner_id, tenant_id,
|
|
192
|
-
message_count,
|
|
192
|
+
message_count, parent_conversation_id,
|
|
193
|
+
has_pending_approvals, channel_meta
|
|
193
194
|
FROM conversations WHERE agent_id = $1`;
|
|
194
195
|
if (filterTenant) {
|
|
195
196
|
sql += ` AND tenant_id = $2`;
|
|
@@ -258,8 +259,9 @@ export abstract class SqlStorageEngine implements StorageEngine {
|
|
|
258
259
|
const data = JSON.stringify(conv);
|
|
259
260
|
await this.executor.run(
|
|
260
261
|
rewrite(
|
|
261
|
-
`INSERT INTO conversations (id, agent_id, tenant_id, owner_id, title, data, message_count, created_at, updated_at
|
|
262
|
-
|
|
262
|
+
`INSERT INTO conversations (id, agent_id, tenant_id, owner_id, title, data, message_count, created_at, updated_at,
|
|
263
|
+
parent_conversation_id, has_pending_approvals, channel_meta)
|
|
264
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)`,
|
|
263
265
|
this.dialect,
|
|
264
266
|
),
|
|
265
267
|
[
|
|
@@ -272,6 +274,9 @@ export abstract class SqlStorageEngine implements StorageEngine {
|
|
|
272
274
|
0,
|
|
273
275
|
new Date(now).toISOString(),
|
|
274
276
|
new Date(now).toISOString(),
|
|
277
|
+
null,
|
|
278
|
+
0,
|
|
279
|
+
null,
|
|
275
280
|
],
|
|
276
281
|
);
|
|
277
282
|
return conv;
|
|
@@ -296,16 +301,23 @@ export abstract class SqlStorageEngine implements StorageEngine {
|
|
|
296
301
|
const tid = normalizeTenant(conversation.tenantId);
|
|
297
302
|
const now = new Date(conversation.updatedAt).toISOString();
|
|
298
303
|
const created = new Date(conversation.createdAt).toISOString();
|
|
304
|
+
const parentConvId = conversation.parentConversationId ?? null;
|
|
305
|
+
const hasPendingApprovals = (conversation.pendingApprovals?.length ?? 0) > 0 ? 1 : 0;
|
|
306
|
+
const channelMetaJson = conversation.channelMeta ? JSON.stringify(conversation.channelMeta) : null;
|
|
299
307
|
await this.executor.run(
|
|
300
308
|
rewrite(
|
|
301
309
|
`INSERT INTO conversations (id, agent_id, tenant_id, owner_id, title, data, message_count, created_at, updated_at,
|
|
302
|
-
tool_result_archive, harness_messages, continuation_messages
|
|
303
|
-
|
|
310
|
+
tool_result_archive, harness_messages, continuation_messages,
|
|
311
|
+
parent_conversation_id, has_pending_approvals, channel_meta)
|
|
312
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15)
|
|
304
313
|
${this.dialect.upsert(["id"])}
|
|
305
314
|
data = excluded.data, title = excluded.title, message_count = excluded.message_count,
|
|
306
315
|
updated_at = excluded.updated_at, tenant_id = excluded.tenant_id, owner_id = excluded.owner_id,
|
|
307
316
|
tool_result_archive = excluded.tool_result_archive, harness_messages = excluded.harness_messages,
|
|
308
|
-
continuation_messages = excluded.continuation_messages
|
|
317
|
+
continuation_messages = excluded.continuation_messages,
|
|
318
|
+
parent_conversation_id = excluded.parent_conversation_id,
|
|
319
|
+
has_pending_approvals = excluded.has_pending_approvals,
|
|
320
|
+
channel_meta = excluded.channel_meta`,
|
|
309
321
|
this.dialect,
|
|
310
322
|
),
|
|
311
323
|
[
|
|
@@ -321,6 +333,9 @@ export abstract class SqlStorageEngine implements StorageEngine {
|
|
|
321
333
|
archiveJson,
|
|
322
334
|
harnessJson,
|
|
323
335
|
continuationJson,
|
|
336
|
+
parentConvId,
|
|
337
|
+
hasPendingApprovals,
|
|
338
|
+
channelMetaJson,
|
|
324
339
|
],
|
|
325
340
|
);
|
|
326
341
|
},
|
|
@@ -359,7 +374,8 @@ export abstract class SqlStorageEngine implements StorageEngine {
|
|
|
359
374
|
// SQLite uses positional ? so we can't reuse $2, need separate params
|
|
360
375
|
const params: unknown[] = [this.agentId, pattern, pattern];
|
|
361
376
|
let sql = `SELECT id, title, updated_at, created_at, owner_id, tenant_id,
|
|
362
|
-
message_count,
|
|
377
|
+
message_count, parent_conversation_id,
|
|
378
|
+
has_pending_approvals, channel_meta
|
|
363
379
|
FROM conversations
|
|
364
380
|
WHERE agent_id = $1 AND (title LIKE $2 OR data LIKE $3)`;
|
|
365
381
|
if (filterTenant) {
|
|
@@ -882,8 +898,8 @@ export abstract class SqlStorageEngine implements StorageEngine {
|
|
|
882
898
|
}
|
|
883
899
|
|
|
884
900
|
private rowToSummary(row: QueryRow): ConversationSummary {
|
|
885
|
-
const data = this.parseConversation(row.data);
|
|
886
901
|
const tid = row.tenant_id as string;
|
|
902
|
+
const rawChannelMeta = row.channel_meta;
|
|
887
903
|
return {
|
|
888
904
|
conversationId: row.id as string,
|
|
889
905
|
title: row.title as string,
|
|
@@ -892,9 +908,11 @@ export abstract class SqlStorageEngine implements StorageEngine {
|
|
|
892
908
|
ownerId: row.owner_id as string,
|
|
893
909
|
tenantId: tid === DEFAULT_TENANT ? null : tid,
|
|
894
910
|
messageCount: row.message_count as number,
|
|
895
|
-
hasPendingApprovals: (
|
|
896
|
-
parentConversationId:
|
|
897
|
-
channelMeta:
|
|
911
|
+
hasPendingApprovals: !!(row.has_pending_approvals),
|
|
912
|
+
parentConversationId: (row.parent_conversation_id as string) || undefined,
|
|
913
|
+
channelMeta: rawChannelMeta
|
|
914
|
+
? (typeof rawChannelMeta === "string" ? JSON.parse(rawChannelMeta) : rawChannelMeta)
|
|
915
|
+
: undefined,
|
|
898
916
|
};
|
|
899
917
|
}
|
|
900
918
|
|