@poncho-ai/harness 0.36.4 → 0.37.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.
@@ -1,5 +1,5 @@
1
1
 
2
- > @poncho-ai/harness@0.36.4 build /home/runner/work/poncho-ai/poncho-ai/packages/harness
2
+ > @poncho-ai/harness@0.37.0 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
  CLI tsup v8.5.1
9
9
  CLI Target: es2022
10
10
  ESM Build start
11
- ESM dist/index.js 387.69 KB
11
+ ESM dist/index.js 389.90 KB
12
12
  ESM dist/isolate-TCWTUVG4.js 47.34 KB
13
- ESM ⚡️ Build success in 182ms
13
+ ESM ⚡️ Build success in 206ms
14
14
  DTS Build start
15
- DTS ⚡️ Build success in 6917ms
15
+ DTS ⚡️ Build success in 7213ms
16
16
  DTS dist/index.d.ts 56.62 KB
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @poncho-ai/harness
2
2
 
3
+ ## 0.37.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`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
8
+
3
9
  ## 0.36.4
4
10
 
5
11
  ### 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, data
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
- VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)`,
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
- VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
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, data
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: (data.pendingApprovals?.length ?? 0) > 0,
3855
- parentConversationId: data.parentConversationId,
3856
- channelMeta: data.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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@poncho-ai/harness",
3
- "version": "0.36.4",
3
+ "version": "0.37.0",
4
4
  "description": "Agent execution runtime - conversation loop, tool dispatch, streaming",
5
5
  "repository": {
6
6
  "type": "git",
@@ -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, data
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
- VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)`,
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
- VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
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, data
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: (data.pendingApprovals?.length ?? 0) > 0,
896
- parentConversationId: data.parentConversationId,
897
- channelMeta: data.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