@agent-native/core 0.122.1 → 0.122.3
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 +1 -13
- package/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +12 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/agent/production-agent.ts +65 -1
- package/corpus/core/src/agent/run-loop-with-resume.ts +12 -0
- package/corpus/core/src/agent/run-store.ts +61 -1
- package/corpus/core/src/integrations/a2a-continuation-processor.ts +182 -0
- package/corpus/core/src/integrations/a2a-continuations-store.ts +122 -12
- package/corpus/core/src/integrations/integration-campaign-recovery.ts +127 -0
- package/corpus/core/src/integrations/integration-campaigns-store.ts +1039 -0
- package/corpus/core/src/integrations/integration-durable-dispatch.ts +28 -3
- package/corpus/core/src/integrations/pending-tasks-retry-job.ts +8 -0
- package/corpus/core/src/integrations/plugin.ts +453 -35
- package/corpus/core/src/integrations/webhook-handler.ts +469 -11
- package/corpus/core/src/server/builder-design-systems.ts +1 -1
- package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +15 -0
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/report-panel-window.ts +3 -3
- package/corpus/templates/analytics/changelog/2026-07-25-analytics-dashboards-and-scheduled-reports-are-faster-and-mo.md +6 -0
- package/corpus/templates/analytics/server/db/schema.ts +12 -0
- package/corpus/templates/analytics/server/lib/dashboard-panel-query.ts +8 -4
- package/corpus/templates/analytics/server/lib/dashboard-report.ts +136 -5
- package/corpus/templates/analytics/server/lib/dashboard-time-scope.ts +250 -1
- package/corpus/templates/analytics/server/lib/first-party-analytics-cache.ts +167 -0
- package/corpus/templates/analytics/server/lib/first-party-analytics.ts +34 -9
- package/corpus/templates/analytics/server/lib/first-party-dashboard-repair.ts +105 -23
- package/corpus/templates/analytics/server/lib/first-party-unbounded-panel-repair.ts +169 -0
- package/corpus/templates/analytics/server/plugins/db.ts +41 -1
- package/corpus/templates/analytics/shared/dashboard-report-timeouts.ts +6 -3
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +7 -3
- package/corpus/templates/content/app/components/editor/body-hydration.ts +10 -0
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +1 -0
- package/corpus/templates/content/app/root.tsx +12 -1
- package/corpus/templates/content/changelog/2026-07-23-new-pages-open-immediately-while-slow-network-work-continues.md +6 -0
- package/corpus/templates/content/changelog/2026-07-25-database-preview-actions-open-reliably.md +6 -0
- package/corpus/templates/content/e2e/playwright.config.ts +1 -1
- package/corpus/templates/design/actions/edit-design.ts +66 -27
- package/corpus/templates/design/changelog/2026-07-25-design-edits-retry-concurrent-changes.md +6 -0
- package/corpus/templates/design/server/source-workspace.ts +5 -1
- package/corpus/templates/forms/.agents/skills/form-responses/SKILL.md +6 -4
- package/corpus/templates/forms/actions/create-form.ts +5 -1
- package/corpus/templates/forms/actions/export-responses.ts +22 -11
- package/corpus/templates/forms/actions/update-form.ts +5 -1
- package/corpus/templates/forms/changelog/2026-07-25-fields-can-be-created-without-ids.md +6 -0
- package/corpus/templates/forms/changelog/2026-07-25-response-exports-use-file-storage.md +6 -0
- package/corpus/templates/forms/server/lib/validate-fields.ts +43 -0
- package/corpus/templates/slides/actions/extract-pdf.ts +4 -4
- package/corpus/templates/slides/actions/import-file.ts +3 -4
- package/corpus/templates/slides/changelog/2026-07-25-gemini-image-models-updated.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-25-pdf-imports-tolerate-missing-canvas.md +6 -0
- package/corpus/templates/slides/server/handlers/image-providers/gemini.ts +5 -2
- package/corpus/templates/slides/server/lib/pdf-parse-setup.ts +150 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +63 -1
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-loop-with-resume.d.ts +7 -1
- package/dist/agent/run-loop-with-resume.d.ts.map +1 -1
- package/dist/agent/run-loop-with-resume.js +7 -0
- package/dist/agent/run-loop-with-resume.js.map +1 -1
- package/dist/agent/run-store.d.ts.map +1 -1
- package/dist/agent/run-store.js +49 -0
- package/dist/agent/run-store.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +2 -2
- package/dist/integrations/a2a-continuation-processor.d.ts +14 -0
- package/dist/integrations/a2a-continuation-processor.d.ts.map +1 -1
- package/dist/integrations/a2a-continuation-processor.js +134 -1
- package/dist/integrations/a2a-continuation-processor.js.map +1 -1
- package/dist/integrations/a2a-continuations-store.d.ts +23 -0
- package/dist/integrations/a2a-continuations-store.d.ts.map +1 -1
- package/dist/integrations/a2a-continuations-store.js +99 -13
- package/dist/integrations/a2a-continuations-store.js.map +1 -1
- package/dist/integrations/integration-campaign-recovery.d.ts +16 -0
- package/dist/integrations/integration-campaign-recovery.d.ts.map +1 -0
- package/dist/integrations/integration-campaign-recovery.js +94 -0
- package/dist/integrations/integration-campaign-recovery.js.map +1 -0
- package/dist/integrations/integration-campaigns-store.d.ts +121 -0
- package/dist/integrations/integration-campaigns-store.d.ts.map +1 -0
- package/dist/integrations/integration-campaigns-store.js +784 -0
- package/dist/integrations/integration-campaigns-store.js.map +1 -0
- package/dist/integrations/integration-durable-dispatch.d.ts +3 -0
- package/dist/integrations/integration-durable-dispatch.d.ts.map +1 -1
- package/dist/integrations/integration-durable-dispatch.js +22 -3
- package/dist/integrations/integration-durable-dispatch.js.map +1 -1
- package/dist/integrations/pending-tasks-retry-job.d.ts.map +1 -1
- package/dist/integrations/pending-tasks-retry-job.js +6 -0
- package/dist/integrations/pending-tasks-retry-job.js.map +1 -1
- package/dist/integrations/plugin.d.ts.map +1 -1
- package/dist/integrations/plugin.js +325 -18
- package/dist/integrations/plugin.js.map +1 -1
- package/dist/integrations/webhook-handler.d.ts +16 -1
- package/dist/integrations/webhook-handler.d.ts.map +1 -1
- package/dist/integrations/webhook-handler.js +368 -13
- package/dist/integrations/webhook-handler.js.map +1 -1
- package/dist/observability/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +14 -14
- package/dist/provider-api/actions/provider-api.d.ts +8 -8
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/builder-design-systems.js +1 -1
- package/dist/server/builder-design-systems.js.map +1 -1
- package/package.json +3 -3
- package/src/agent/production-agent.ts +65 -1
- package/src/agent/run-loop-with-resume.ts +12 -0
- package/src/agent/run-store.ts +61 -1
- package/src/integrations/a2a-continuation-processor.ts +182 -0
- package/src/integrations/a2a-continuations-store.ts +122 -12
- package/src/integrations/integration-campaign-recovery.ts +127 -0
- package/src/integrations/integration-campaigns-store.ts +1039 -0
- package/src/integrations/integration-durable-dispatch.ts +28 -3
- package/src/integrations/pending-tasks-retry-job.ts +8 -0
- package/src/integrations/plugin.ts +453 -35
- package/src/integrations/webhook-handler.ts +469 -11
- package/src/server/builder-design-systems.ts +1 -1
|
@@ -280,6 +280,28 @@ export async function getA2AContinuationForIntegrationTask(integrationTaskId) {
|
|
|
280
280
|
});
|
|
281
281
|
return rows[0] ? rowToContinuation(rows[0]) : null;
|
|
282
282
|
}
|
|
283
|
+
export async function hasActiveA2AContinuationsForIntegrationTask(integrationTaskId) {
|
|
284
|
+
await ensureTable();
|
|
285
|
+
const { rows } = await getDbExec().execute({
|
|
286
|
+
sql: `SELECT 1 AS active FROM integration_a2a_continuations
|
|
287
|
+
WHERE integration_task_id = ?
|
|
288
|
+
AND status IN ('pending', 'processing', 'delivering')
|
|
289
|
+
LIMIT 1`,
|
|
290
|
+
args: [integrationTaskId],
|
|
291
|
+
});
|
|
292
|
+
return rows.length > 0;
|
|
293
|
+
}
|
|
294
|
+
export async function failA2AContinuationsForIntegrationTask(integrationTaskId, errorMessage) {
|
|
295
|
+
await ensureTable();
|
|
296
|
+
const now = Date.now();
|
|
297
|
+
await getDbExec().execute({
|
|
298
|
+
sql: `UPDATE integration_a2a_continuations
|
|
299
|
+
SET status = 'failed', error_message = ?, updated_at = ?, completed_at = ?
|
|
300
|
+
WHERE integration_task_id = ?
|
|
301
|
+
AND status IN ('pending', 'processing', 'delivering')`,
|
|
302
|
+
args: [errorMessage.slice(0, 2000), now, now, integrationTaskId],
|
|
303
|
+
});
|
|
304
|
+
}
|
|
283
305
|
export async function getA2AContinuationsForIntegrationTaskAgent(integrationTaskId, agentUrl, dedupeKey) {
|
|
284
306
|
await ensureTable();
|
|
285
307
|
const client = getDbExec();
|
|
@@ -375,41 +397,105 @@ export async function claimA2AContinuation(id) {
|
|
|
375
397
|
return fetched;
|
|
376
398
|
}
|
|
377
399
|
export async function claimDueA2AContinuations(limit = 5) {
|
|
400
|
+
const ids = await recoverDueA2AContinuationIds(limit);
|
|
401
|
+
const claimed = [];
|
|
402
|
+
for (const id of ids) {
|
|
403
|
+
const continuation = await claimA2AContinuation(id);
|
|
404
|
+
if (continuation)
|
|
405
|
+
claimed.push(continuation);
|
|
406
|
+
}
|
|
407
|
+
return claimed;
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* Makes stale leases eligible again and returns a bounded set of due ids.
|
|
411
|
+
*
|
|
412
|
+
* This intentionally does not claim anything. Durable schedulers use it only
|
|
413
|
+
* to wake the normal processor, whose atomic claim remains the sole progress
|
|
414
|
+
* and delivery owner under overlapping scheduler/self-dispatch executions.
|
|
415
|
+
*/
|
|
416
|
+
export async function recoverDueA2AContinuationIds(limit = 5, integrationTaskIds) {
|
|
378
417
|
await ensureTable();
|
|
379
418
|
const client = getDbExec();
|
|
380
419
|
const now = Date.now();
|
|
381
420
|
const processingCutoff = now - PROCESSING_STUCK_AFTER_MS;
|
|
382
421
|
const staleNextCheckCutoff = now - PROCESSING_NEXT_CHECK_STALE_AFTER_MS;
|
|
422
|
+
if (integrationTaskIds && integrationTaskIds.length === 0)
|
|
423
|
+
return [];
|
|
424
|
+
const taskFilter = integrationTaskIds?.length
|
|
425
|
+
? ` AND integration_task_id IN (${integrationTaskIds.map(() => "?").join(", ")})`
|
|
426
|
+
: "";
|
|
427
|
+
const taskArgs = integrationTaskIds ?? [];
|
|
383
428
|
// If a processor dies while holding a delivery claim, retry the final send.
|
|
384
429
|
// The stale cutoff preserves the in-flight delivery guard while keeping
|
|
385
430
|
// final integration replies at-least-once.
|
|
386
431
|
await client.execute({
|
|
387
432
|
sql: `UPDATE integration_a2a_continuations
|
|
388
433
|
SET status = ?, next_check_at = ?, updated_at = ?
|
|
389
|
-
WHERE status = 'delivering' AND updated_at <=
|
|
390
|
-
args: ["pending", now, now, now - 5 * 60 * 1000],
|
|
434
|
+
WHERE status = 'delivering' AND updated_at <= ?${taskFilter}`,
|
|
435
|
+
args: ["pending", now, now, now - 5 * 60 * 1000, ...taskArgs],
|
|
391
436
|
});
|
|
392
437
|
await client.execute({
|
|
393
438
|
sql: `UPDATE integration_a2a_continuations
|
|
394
439
|
SET status = ?, next_check_at = ?, updated_at = ?
|
|
395
440
|
WHERE status = 'processing'
|
|
396
|
-
AND (updated_at <= ? OR next_check_at <= ?)`,
|
|
397
|
-
args: [
|
|
441
|
+
AND (updated_at <= ? OR next_check_at <= ?)${taskFilter}`,
|
|
442
|
+
args: [
|
|
443
|
+
"pending",
|
|
444
|
+
now,
|
|
445
|
+
now,
|
|
446
|
+
processingCutoff,
|
|
447
|
+
staleNextCheckCutoff,
|
|
448
|
+
...taskArgs,
|
|
449
|
+
],
|
|
398
450
|
});
|
|
399
451
|
const { rows } = await client.execute({
|
|
400
452
|
sql: `SELECT id FROM integration_a2a_continuations
|
|
401
|
-
WHERE status = 'pending' AND next_check_at <=
|
|
453
|
+
WHERE status = 'pending' AND next_check_at <= ?${taskFilter}
|
|
402
454
|
ORDER BY next_check_at ASC
|
|
403
455
|
LIMIT ?`,
|
|
404
|
-
args: [now, limit],
|
|
456
|
+
args: [now, ...taskArgs, limit],
|
|
405
457
|
});
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
458
|
+
return rows.map((row) => row.id);
|
|
459
|
+
}
|
|
460
|
+
export async function listRecoverableA2AIntegrationTaskIds(limit = 50) {
|
|
461
|
+
const tasks = await listRecoverableA2AIntegrationTasks(limit);
|
|
462
|
+
return tasks.map((task) => task.id);
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* Read due continuation owners and their rollout scope in one query. Recovery
|
|
466
|
+
* can filter the canary in memory without an N+1 pending-task lookup loop.
|
|
467
|
+
*/
|
|
468
|
+
export async function listRecoverableA2AIntegrationTasks(limit = 50) {
|
|
469
|
+
await ensureTable();
|
|
470
|
+
const now = Date.now();
|
|
471
|
+
const { rows } = await getDbExec().execute({
|
|
472
|
+
sql: `SELECT DISTINCT c.integration_task_id, t.platform,
|
|
473
|
+
t.external_thread_id, t.dispatch_scope, t.status
|
|
474
|
+
FROM integration_a2a_continuations c
|
|
475
|
+
INNER JOIN integration_pending_tasks t
|
|
476
|
+
ON t.id = c.integration_task_id
|
|
477
|
+
WHERE t.status = 'processing'
|
|
478
|
+
AND ((c.status = 'pending' AND c.next_check_at <= ?)
|
|
479
|
+
OR (c.status = 'processing' AND
|
|
480
|
+
(c.updated_at <= ? OR c.next_check_at <= ?))
|
|
481
|
+
OR (c.status = 'delivering' AND c.updated_at <= ?))
|
|
482
|
+
ORDER BY c.integration_task_id ASC
|
|
483
|
+
LIMIT ?`,
|
|
484
|
+
args: [
|
|
485
|
+
now,
|
|
486
|
+
now - PROCESSING_STUCK_AFTER_MS,
|
|
487
|
+
now - PROCESSING_NEXT_CHECK_STALE_AFTER_MS,
|
|
488
|
+
now - 5 * 60 * 1000,
|
|
489
|
+
Math.max(1, Math.min(Math.floor(limit), 200)),
|
|
490
|
+
],
|
|
491
|
+
});
|
|
492
|
+
return rows.map((row) => ({
|
|
493
|
+
id: String(row.integration_task_id),
|
|
494
|
+
platform: String(row.platform),
|
|
495
|
+
externalThreadId: String(row.external_thread_id),
|
|
496
|
+
dispatchScope: row.dispatch_scope ?? null,
|
|
497
|
+
status: String(row.status),
|
|
498
|
+
}));
|
|
413
499
|
}
|
|
414
500
|
export async function claimA2AContinuationDelivery(id) {
|
|
415
501
|
await ensureTable();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"a2a-continuations-store.js","sourceRoot":"","sources":["../../src/integrations/a2a-continuations-store.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n getDbExec,\n isPostgres,\n intType,\n retryOnDdlRace,\n} from \"../db/client.js\";\nimport {\n ensureTableExists,\n ensureColumnExists,\n ensureIndexExists,\n} from \"../db/ddl-guard.js\";\nimport { isDuplicateColumnError } from \"../db/migrations.js\";\nimport type { IncomingMessage, PlatformRunProgressRef } from \"./types.js\";\n\nlet _initPromise: Promise<void> | undefined;\nconst PROCESSING_STUCK_AFTER_MS = 5 * 60 * 1000;\nconst PROCESSING_NEXT_CHECK_STALE_AFTER_MS = 60 * 1000;\n\n// Build the CREATE SQL lazily (not at module scope) so intType() runs at\n// RUNTIME, not import time — a module-scope call breaks any consumer whose\n// db/client mock doesn't stub intType (e.g. db-admin specs).\nfunction buildCreateSql(): string {\n return `\n CREATE TABLE IF NOT EXISTS integration_a2a_continuations (\n id TEXT PRIMARY KEY,\n integration_task_id TEXT NOT NULL,\n platform TEXT NOT NULL,\n external_thread_id TEXT NOT NULL,\n incoming_payload TEXT NOT NULL,\n placeholder_ref TEXT,\n progress_ref TEXT,\n progress_ref_claimed ${intType()} NOT NULL DEFAULT 0,\n owner_email TEXT NOT NULL,\n org_id TEXT,\n agent_name TEXT NOT NULL,\n agent_url TEXT NOT NULL,\n dedupe_key TEXT,\n a2a_task_id TEXT NOT NULL,\n a2a_auth_token TEXT,\n status TEXT NOT NULL,\n attempts ${intType()} NOT NULL DEFAULT 0,\n next_check_at ${intType()} NOT NULL,\n error_message TEXT,\n created_at ${intType()} NOT NULL,\n updated_at ${intType()} NOT NULL,\n completed_at ${intType()}\n )\n`;\n}\n\nasync function ensureTable(): Promise<void> {\n if (!_initPromise) {\n _initPromise = (async () => {\n const client = getDbExec();\n const createSql = buildCreateSql();\n if (isPostgres()) {\n // PG guard: probe via information_schema, only issue DDL if missing, bounded lock_timeout\n await ensureTableExists(\"integration_a2a_continuations\", createSql);\n await ensureIndexExists(\n \"idx_a2a_continuations_status_next\",\n `CREATE INDEX IF NOT EXISTS idx_a2a_continuations_status_next ON integration_a2a_continuations(status, next_check_at)`,\n );\n await ensureIndexExists(\n \"idx_a2a_continuations_integration_task\",\n `CREATE INDEX IF NOT EXISTS idx_a2a_continuations_integration_task ON integration_a2a_continuations(integration_task_id)`,\n );\n await ensureIndexExists(\n \"idx_a2a_continuations_remote_task\",\n `CREATE UNIQUE INDEX IF NOT EXISTS idx_a2a_continuations_remote_task ON integration_a2a_continuations(integration_task_id, agent_url, a2a_task_id)`,\n );\n await ensureColumnExists(\n \"integration_a2a_continuations\",\n \"a2a_auth_token\",\n `ALTER TABLE integration_a2a_continuations ADD COLUMN IF NOT EXISTS a2a_auth_token TEXT`,\n );\n await ensureColumnExists(\n \"integration_a2a_continuations\",\n \"dedupe_key\",\n `ALTER TABLE integration_a2a_continuations ADD COLUMN IF NOT EXISTS dedupe_key TEXT`,\n );\n await ensureColumnExists(\n \"integration_a2a_continuations\",\n \"progress_ref\",\n `ALTER TABLE integration_a2a_continuations ADD COLUMN IF NOT EXISTS progress_ref TEXT`,\n );\n await ensureColumnExists(\n \"integration_a2a_continuations\",\n \"progress_ref_claimed\",\n `ALTER TABLE integration_a2a_continuations ADD COLUMN IF NOT EXISTS progress_ref_claimed ${intType()} NOT NULL DEFAULT 0`,\n );\n await backfillProgressRefOwners(client);\n await ensureIndexExists(\n \"idx_a2a_continuations_dedupe_key\",\n `CREATE INDEX IF NOT EXISTS idx_a2a_continuations_dedupe_key ON integration_a2a_continuations(integration_task_id, agent_url, dedupe_key)`,\n );\n await ensureIndexExists(\n \"idx_a2a_continuations_one_progress_owner\",\n `CREATE UNIQUE INDEX IF NOT EXISTS idx_a2a_continuations_one_progress_owner ON integration_a2a_continuations(integration_task_id) WHERE progress_ref_claimed = 1`,\n );\n return;\n }\n // SQLite (local dev): keep existing behavior\n await retryOnDdlRace(() => client.execute(createSql));\n await retryOnDdlRace(() =>\n client.execute(\n `CREATE INDEX IF NOT EXISTS idx_a2a_continuations_status_next ON integration_a2a_continuations(status, next_check_at)`,\n ),\n );\n await retryOnDdlRace(() =>\n client.execute(\n `CREATE INDEX IF NOT EXISTS idx_a2a_continuations_integration_task ON integration_a2a_continuations(integration_task_id)`,\n ),\n );\n await retryOnDdlRace(() =>\n client.execute(\n `CREATE UNIQUE INDEX IF NOT EXISTS idx_a2a_continuations_remote_task ON integration_a2a_continuations(integration_task_id, agent_url, a2a_task_id)`,\n ),\n );\n await addColumnIfMissing(\"a2a_auth_token\", \"TEXT\");\n await addColumnIfMissing(\"dedupe_key\", \"TEXT\");\n await addColumnIfMissing(\"progress_ref\", \"TEXT\");\n await addColumnIfMissing(\n \"progress_ref_claimed\",\n `${intType()} NOT NULL DEFAULT 0`,\n );\n await backfillProgressRefOwners(client);\n await retryOnDdlRace(() =>\n client.execute(\n `CREATE INDEX IF NOT EXISTS idx_a2a_continuations_dedupe_key ON integration_a2a_continuations(integration_task_id, agent_url, dedupe_key)`,\n ),\n );\n await retryOnDdlRace(() =>\n client.execute(\n `CREATE UNIQUE INDEX IF NOT EXISTS idx_a2a_continuations_one_progress_owner ON integration_a2a_continuations(integration_task_id) WHERE progress_ref_claimed = 1`,\n ),\n );\n })().catch((err) => {\n // Retry init on the next call after a failed startup.\n _initPromise = undefined;\n throw err;\n });\n }\n return _initPromise;\n}\n\nasync function addColumnIfMissing(name: string, definition: string) {\n try {\n await retryOnDdlRace(() =>\n getDbExec().execute(\n `ALTER TABLE integration_a2a_continuations ADD COLUMN ${name} ${definition}`,\n ),\n );\n } catch (err) {\n if (isDuplicateColumnError(err)) return;\n throw err;\n }\n}\n\nasync function backfillProgressRefOwners(\n client: ReturnType<typeof getDbExec>,\n): Promise<void> {\n await client.execute(`\n UPDATE integration_a2a_continuations AS candidate\n SET progress_ref_claimed = 1\n WHERE candidate.progress_ref IS NOT NULL\n AND candidate.status NOT IN ('completed', 'failed')\n AND candidate.progress_ref_claimed = 0\n AND NOT EXISTS (\n SELECT 1\n FROM integration_a2a_continuations AS owner\n WHERE owner.integration_task_id = candidate.integration_task_id\n AND owner.progress_ref_claimed = 1\n )\n AND candidate.id = (\n SELECT selected.id\n FROM integration_a2a_continuations AS selected\n WHERE selected.integration_task_id = candidate.integration_task_id\n AND selected.progress_ref IS NOT NULL\n AND selected.status NOT IN ('completed', 'failed')\n ORDER BY selected.created_at ASC, selected.id ASC\n LIMIT 1\n )\n `);\n}\n\nexport type A2AContinuationStatus =\n | \"pending\"\n | \"processing\"\n | \"delivering\"\n | \"completed\"\n | \"failed\";\n\nexport interface A2AContinuation {\n id: string;\n integrationTaskId: string;\n platform: string;\n externalThreadId: string;\n incoming: IncomingMessage;\n placeholderRef: string | null;\n progressRef: PlatformRunProgressRef | null;\n progressRefClaimed: boolean;\n ownerEmail: string;\n orgId: string | null;\n agentName: string;\n agentUrl: string;\n dedupeKey: string | null;\n a2aTaskId: string;\n a2aAuthToken: string | null;\n status: A2AContinuationStatus;\n attempts: number;\n nextCheckAt: number;\n errorMessage: string | null;\n createdAt: number;\n updatedAt: number;\n completedAt: number | null;\n}\n\nconst MAX_PROGRESS_REF_KIND_CHARS = 128;\nconst MAX_PROGRESS_REF_STREAM_TS_CHARS = 256;\n\n/**\n * Keep only the tiny, adapter-owned continuation reference. Invalid rows are\n * treated as unavailable rather than throwing during a retry sweep.\n */\nfunction parseProgressRef(value: unknown): PlatformRunProgressRef | null {\n if (typeof value !== \"string\" || value.length === 0) return null;\n try {\n const parsed = JSON.parse(value) as unknown;\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n return null;\n }\n const { kind, streamTs } = parsed as Record<string, unknown>;\n if (\n typeof kind !== \"string\" ||\n typeof streamTs !== \"string\" ||\n kind.length === 0 ||\n streamTs.length === 0 ||\n kind.length > MAX_PROGRESS_REF_KIND_CHARS ||\n streamTs.length > MAX_PROGRESS_REF_STREAM_TS_CHARS\n ) {\n return null;\n }\n return { kind, streamTs };\n } catch {\n return null;\n }\n}\n\nfunction serializeProgressRef(value: unknown): string | null {\n const parsed = parseProgressRef(\n typeof value === \"string\" ? value : JSON.stringify(value),\n );\n return parsed ? JSON.stringify(parsed) : null;\n}\n\nfunction rowToContinuation(row: Record<string, unknown>): A2AContinuation {\n return {\n id: row.id as string,\n integrationTaskId: row.integration_task_id as string,\n platform: row.platform as string,\n externalThreadId: row.external_thread_id as string,\n incoming: JSON.parse(row.incoming_payload as string) as IncomingMessage,\n placeholderRef: (row.placeholder_ref as string | null) ?? null,\n progressRef: parseProgressRef(row.progress_ref),\n progressRefClaimed: Number(row.progress_ref_claimed ?? 0) === 1,\n ownerEmail: row.owner_email as string,\n orgId: (row.org_id as string | null) ?? null,\n agentName: row.agent_name as string,\n agentUrl: row.agent_url as string,\n dedupeKey: (row.dedupe_key as string | null) ?? null,\n a2aTaskId: row.a2a_task_id as string,\n a2aAuthToken: (row.a2a_auth_token as string | null) ?? null,\n status: row.status as A2AContinuationStatus,\n attempts: Number(row.attempts ?? 0),\n nextCheckAt: Number(row.next_check_at ?? 0),\n errorMessage: (row.error_message as string | null) ?? null,\n createdAt: Number(row.created_at ?? 0),\n updatedAt: Number(row.updated_at ?? 0),\n completedAt:\n row.completed_at == null ? null : Number(row.completed_at as number),\n };\n}\n\nexport async function insertA2AContinuation(input: {\n integrationTaskId: string;\n platform: string;\n externalThreadId: string;\n incoming: IncomingMessage;\n placeholderRef?: string | null;\n progressRef?: PlatformRunProgressRef | null;\n ownerEmail: string;\n orgId?: string | null;\n agentName: string;\n agentUrl: string;\n dedupeKey?: string | null;\n a2aTaskId: string;\n a2aAuthToken?: string | null;\n}): Promise<A2AContinuation> {\n await ensureTable();\n const client = getDbExec();\n const now = Date.now();\n const id = `a2a-cont-${now}-${Math.random().toString(36).slice(2, 8)}`;\n const payload = JSON.stringify(input.incoming);\n const progressRef = serializeProgressRef(input.progressRef);\n\n try {\n await client.execute({\n sql: `INSERT INTO integration_a2a_continuations\n (id, integration_task_id, platform, external_thread_id, incoming_payload,\n placeholder_ref, progress_ref, progress_ref_claimed, owner_email, org_id, agent_name, agent_url, dedupe_key, a2a_task_id, a2a_auth_token,\n status, attempts, next_check_at, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n id,\n input.integrationTaskId,\n input.platform,\n input.externalThreadId,\n payload,\n input.placeholderRef ?? null,\n null,\n 0,\n input.ownerEmail,\n input.orgId ?? null,\n input.agentName,\n input.agentUrl,\n input.dedupeKey ?? null,\n input.a2aTaskId,\n input.a2aAuthToken ?? null,\n \"pending\",\n 0,\n now,\n now,\n now,\n ],\n });\n } catch (err: any) {\n if (!isDuplicateContinuationError(err)) throw err;\n const existing = await findA2AContinuation(\n input.integrationTaskId,\n input.agentUrl,\n input.a2aTaskId,\n );\n if (existing) {\n // A retry can reach this row after the original invocation created it\n // without a resumable progress surface (or with one that has gone\n // stale). Keep the most recent valid adapter reference for active work,\n // but never resurrect short-lived delivery state after a terminal row\n // has deliberately scrubbed it.\n if (\n progressRef &&\n existing.status !== \"completed\" &&\n existing.status !== \"failed\"\n ) {\n if (existing.progressRefClaimed) {\n if (JSON.stringify(existing.progressRef) !== progressRef) {\n await client.execute({\n sql: `UPDATE integration_a2a_continuations\n SET progress_ref = ?, updated_at = ?\n WHERE id = ? AND status NOT IN ('completed', 'failed')\n AND progress_ref_claimed = 1\n AND (progress_ref IS NULL OR progress_ref <> ?)`,\n args: [progressRef, now, existing.id, progressRef],\n });\n }\n } else {\n await claimA2AContinuationProgressRef(existing.id, progressRef);\n }\n return (await getA2AContinuation(existing.id)) ?? existing;\n }\n return existing;\n }\n throw err;\n }\n\n if (progressRef) {\n await claimA2AContinuationProgressRef(id, progressRef);\n }\n return (await getA2AContinuation(id))!;\n}\n\n/**\n * A native platform stream has one terminal completion. Claim it for a single\n * downstream continuation, and retain the ownership marker after terminal\n * cleanup scrubs the short-lived stream reference. The partial unique index\n * makes concurrent downstream inserts safe across processes.\n */\nasync function claimA2AContinuationProgressRef(\n id: string,\n progressRef: string,\n): Promise<void> {\n try {\n await getDbExec().execute({\n sql: `UPDATE integration_a2a_continuations\n SET progress_ref = ?, progress_ref_claimed = 1\n WHERE id = ? AND progress_ref_claimed = 0`,\n args: [progressRef, id],\n });\n } catch (err) {\n // A sibling continuation already owns this stream and will finalize it.\n // This continuation still delivers through the normal response path.\n if (isDuplicateContinuationError(err)) return;\n throw err;\n }\n}\n\nexport async function getA2AContinuationForIntegrationTask(\n integrationTaskId: string,\n): Promise<A2AContinuation | null> {\n await ensureTable();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT * FROM integration_a2a_continuations\n WHERE integration_task_id = ?\n ORDER BY created_at ASC\n LIMIT 1`,\n args: [integrationTaskId],\n });\n return rows[0] ? rowToContinuation(rows[0] as Record<string, unknown>) : null;\n}\n\nexport async function getA2AContinuationsForIntegrationTaskAgent(\n integrationTaskId: string,\n agentUrl: string,\n dedupeKey?: string | null,\n): Promise<A2AContinuation[]> {\n await ensureTable();\n const client = getDbExec();\n const { rows } = await client.execute(\n dedupeKey\n ? {\n sql: `SELECT * FROM integration_a2a_continuations\n WHERE integration_task_id = ? AND agent_url = ? AND dedupe_key = ?\n ORDER BY created_at ASC`,\n args: [integrationTaskId, agentUrl, dedupeKey],\n }\n : {\n sql: `SELECT * FROM integration_a2a_continuations\n WHERE integration_task_id = ? AND agent_url = ?\n ORDER BY created_at ASC`,\n args: [integrationTaskId, agentUrl],\n },\n );\n return rows.map((row) => rowToContinuation(row as Record<string, unknown>));\n}\n\nfunction isDuplicateContinuationError(err: unknown): boolean {\n const e = err as { code?: string; message?: string } | null;\n if (!e) return false;\n if (e.code === \"23505\") return true;\n const msg = String(e.message ?? \"\").toLowerCase();\n return (\n msg.includes(\"unique\") ||\n msg.includes(\"duplicate entry\") ||\n msg.includes(\"duplicate key\")\n );\n}\n\nasync function findA2AContinuation(\n integrationTaskId: string,\n agentUrl: string,\n a2aTaskId: string,\n): Promise<A2AContinuation | null> {\n await ensureTable();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT * FROM integration_a2a_continuations\n WHERE integration_task_id = ? AND agent_url = ? AND a2a_task_id = ?\n LIMIT 1`,\n args: [integrationTaskId, agentUrl, a2aTaskId],\n });\n return rows[0] ? rowToContinuation(rows[0] as Record<string, unknown>) : null;\n}\n\nexport async function getA2AContinuation(\n id: string,\n): Promise<A2AContinuation | null> {\n await ensureTable();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT * FROM integration_a2a_continuations WHERE id = ? LIMIT 1`,\n args: [id],\n });\n return rows[0] ? rowToContinuation(rows[0] as Record<string, unknown>) : null;\n}\n\nexport async function claimA2AContinuation(\n id: string,\n): Promise<A2AContinuation | null> {\n await ensureTable();\n const client = getDbExec();\n const now = Date.now();\n const processingCutoff = now - PROCESSING_STUCK_AFTER_MS;\n const staleNextCheckCutoff = now - PROCESSING_NEXT_CHECK_STALE_AFTER_MS;\n const result = await client.execute({\n sql: isPostgres()\n ? `UPDATE integration_a2a_continuations\n SET status = ?, attempts = attempts + 1, updated_at = ?\n WHERE id = ?\n AND (\n status = 'pending'\n OR (\n status = 'processing'\n AND (updated_at <= ? OR next_check_at <= ?)\n )\n )\n RETURNING *`\n : `UPDATE integration_a2a_continuations\n SET status = ?, attempts = attempts + 1, updated_at = ?\n WHERE id = ?\n AND (\n status = 'pending'\n OR (\n status = 'processing'\n AND (updated_at <= ? OR next_check_at <= ?)\n )\n )`,\n args: [\"processing\", now, id, processingCutoff, staleNextCheckCutoff],\n });\n const rows = result.rows ?? [];\n if (isPostgres()) {\n return rows[0]\n ? rowToContinuation(rows[0] as Record<string, unknown>)\n : null;\n }\n const affected = (result as any)?.rowsAffected ?? (result as any)?.rowCount;\n if (affected === 0) return null;\n const fetched = await getA2AContinuation(id);\n if (!fetched || fetched.status !== \"processing\") return null;\n return fetched;\n}\n\nexport async function claimDueA2AContinuations(\n limit = 5,\n): Promise<A2AContinuation[]> {\n await ensureTable();\n const client = getDbExec();\n const now = Date.now();\n const processingCutoff = now - PROCESSING_STUCK_AFTER_MS;\n const staleNextCheckCutoff = now - PROCESSING_NEXT_CHECK_STALE_AFTER_MS;\n // If a processor dies while holding a delivery claim, retry the final send.\n // The stale cutoff preserves the in-flight delivery guard while keeping\n // final integration replies at-least-once.\n await client.execute({\n sql: `UPDATE integration_a2a_continuations\n SET status = ?, next_check_at = ?, updated_at = ?\n WHERE status = 'delivering' AND updated_at <= ?`,\n args: [\"pending\", now, now, now - 5 * 60 * 1000],\n });\n await client.execute({\n sql: `UPDATE integration_a2a_continuations\n SET status = ?, next_check_at = ?, updated_at = ?\n WHERE status = 'processing'\n AND (updated_at <= ? OR next_check_at <= ?)`,\n args: [\"pending\", now, now, processingCutoff, staleNextCheckCutoff],\n });\n const { rows } = await client.execute({\n sql: `SELECT id FROM integration_a2a_continuations\n WHERE status = 'pending' AND next_check_at <= ?\n ORDER BY next_check_at ASC\n LIMIT ?`,\n args: [now, limit],\n });\n const claimed: A2AContinuation[] = [];\n for (const row of rows) {\n const continuation = await claimA2AContinuation(row.id as string);\n if (continuation) claimed.push(continuation);\n }\n return claimed;\n}\n\nexport async function claimA2AContinuationDelivery(\n id: string,\n): Promise<A2AContinuation | null> {\n await ensureTable();\n const client = getDbExec();\n const now = Date.now();\n const result = await client.execute({\n sql: isPostgres()\n ? `UPDATE integration_a2a_continuations\n SET status = ?, updated_at = ?\n WHERE id = ? AND status = 'processing'\n RETURNING *`\n : `UPDATE integration_a2a_continuations\n SET status = ?, updated_at = ?\n WHERE id = ? AND status = 'processing'`,\n args: [\"delivering\", now, id],\n });\n const rows = result.rows ?? [];\n if (isPostgres()) {\n return rows[0]\n ? rowToContinuation(rows[0] as Record<string, unknown>)\n : null;\n }\n const affected = (result as any)?.rowsAffected ?? (result as any)?.rowCount;\n if (affected === 0) return null;\n const fetched = await getA2AContinuation(id);\n if (!fetched || fetched.status !== \"delivering\") return null;\n return fetched;\n}\n\nexport async function rescheduleA2AContinuation(\n id: string,\n delayMs: number,\n): Promise<void> {\n await ensureTable();\n const client = getDbExec();\n const now = Date.now();\n await client.execute({\n sql: `UPDATE integration_a2a_continuations\n SET status = ?, next_check_at = ?, updated_at = ?\n WHERE id = ? AND status IN ('processing', 'delivering')`,\n args: [\"pending\", now + delayMs, now, id],\n });\n}\n\nexport async function completeA2AContinuation(id: string): Promise<void> {\n await ensureTable();\n const client = getDbExec();\n const now = Date.now();\n await client.execute({\n sql: `UPDATE integration_a2a_continuations\n SET status = ?, updated_at = ?, completed_at = ?,\n incoming_payload = ?, a2a_auth_token = NULL, progress_ref = NULL\n WHERE id = ? AND status IN ('processing', 'delivering', 'completed')`,\n args: [\"completed\", now, now, \"{}\", id],\n });\n}\n\nexport async function failA2AContinuation(\n id: string,\n errorMessage: string,\n): Promise<void> {\n await ensureTable();\n const client = getDbExec();\n const now = Date.now();\n await client.execute({\n sql: `UPDATE integration_a2a_continuations\n SET status = ?, updated_at = ?, error_message = ?,\n incoming_payload = ?, a2a_auth_token = NULL, progress_ref = NULL\n WHERE id = ? AND status <> 'completed'`,\n args: [\"failed\", now, errorMessage.slice(0, 2000), \"{}\", id],\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"a2a-continuations-store.js","sourceRoot":"","sources":["../../src/integrations/a2a-continuations-store.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n getDbExec,\n isPostgres,\n intType,\n retryOnDdlRace,\n} from \"../db/client.js\";\nimport {\n ensureTableExists,\n ensureColumnExists,\n ensureIndexExists,\n} from \"../db/ddl-guard.js\";\nimport { isDuplicateColumnError } from \"../db/migrations.js\";\nimport type { IncomingMessage, PlatformRunProgressRef } from \"./types.js\";\n\nlet _initPromise: Promise<void> | undefined;\nconst PROCESSING_STUCK_AFTER_MS = 5 * 60 * 1000;\nconst PROCESSING_NEXT_CHECK_STALE_AFTER_MS = 60 * 1000;\n\n// Build the CREATE SQL lazily (not at module scope) so intType() runs at\n// RUNTIME, not import time — a module-scope call breaks any consumer whose\n// db/client mock doesn't stub intType (e.g. db-admin specs).\nfunction buildCreateSql(): string {\n return `\n CREATE TABLE IF NOT EXISTS integration_a2a_continuations (\n id TEXT PRIMARY KEY,\n integration_task_id TEXT NOT NULL,\n platform TEXT NOT NULL,\n external_thread_id TEXT NOT NULL,\n incoming_payload TEXT NOT NULL,\n placeholder_ref TEXT,\n progress_ref TEXT,\n progress_ref_claimed ${intType()} NOT NULL DEFAULT 0,\n owner_email TEXT NOT NULL,\n org_id TEXT,\n agent_name TEXT NOT NULL,\n agent_url TEXT NOT NULL,\n dedupe_key TEXT,\n a2a_task_id TEXT NOT NULL,\n a2a_auth_token TEXT,\n status TEXT NOT NULL,\n attempts ${intType()} NOT NULL DEFAULT 0,\n next_check_at ${intType()} NOT NULL,\n error_message TEXT,\n created_at ${intType()} NOT NULL,\n updated_at ${intType()} NOT NULL,\n completed_at ${intType()}\n )\n`;\n}\n\nasync function ensureTable(): Promise<void> {\n if (!_initPromise) {\n _initPromise = (async () => {\n const client = getDbExec();\n const createSql = buildCreateSql();\n if (isPostgres()) {\n // PG guard: probe via information_schema, only issue DDL if missing, bounded lock_timeout\n await ensureTableExists(\"integration_a2a_continuations\", createSql);\n await ensureIndexExists(\n \"idx_a2a_continuations_status_next\",\n `CREATE INDEX IF NOT EXISTS idx_a2a_continuations_status_next ON integration_a2a_continuations(status, next_check_at)`,\n );\n await ensureIndexExists(\n \"idx_a2a_continuations_integration_task\",\n `CREATE INDEX IF NOT EXISTS idx_a2a_continuations_integration_task ON integration_a2a_continuations(integration_task_id)`,\n );\n await ensureIndexExists(\n \"idx_a2a_continuations_remote_task\",\n `CREATE UNIQUE INDEX IF NOT EXISTS idx_a2a_continuations_remote_task ON integration_a2a_continuations(integration_task_id, agent_url, a2a_task_id)`,\n );\n await ensureColumnExists(\n \"integration_a2a_continuations\",\n \"a2a_auth_token\",\n `ALTER TABLE integration_a2a_continuations ADD COLUMN IF NOT EXISTS a2a_auth_token TEXT`,\n );\n await ensureColumnExists(\n \"integration_a2a_continuations\",\n \"dedupe_key\",\n `ALTER TABLE integration_a2a_continuations ADD COLUMN IF NOT EXISTS dedupe_key TEXT`,\n );\n await ensureColumnExists(\n \"integration_a2a_continuations\",\n \"progress_ref\",\n `ALTER TABLE integration_a2a_continuations ADD COLUMN IF NOT EXISTS progress_ref TEXT`,\n );\n await ensureColumnExists(\n \"integration_a2a_continuations\",\n \"progress_ref_claimed\",\n `ALTER TABLE integration_a2a_continuations ADD COLUMN IF NOT EXISTS progress_ref_claimed ${intType()} NOT NULL DEFAULT 0`,\n );\n await backfillProgressRefOwners(client);\n await ensureIndexExists(\n \"idx_a2a_continuations_dedupe_key\",\n `CREATE INDEX IF NOT EXISTS idx_a2a_continuations_dedupe_key ON integration_a2a_continuations(integration_task_id, agent_url, dedupe_key)`,\n );\n await ensureIndexExists(\n \"idx_a2a_continuations_one_progress_owner\",\n `CREATE UNIQUE INDEX IF NOT EXISTS idx_a2a_continuations_one_progress_owner ON integration_a2a_continuations(integration_task_id) WHERE progress_ref_claimed = 1`,\n );\n return;\n }\n // SQLite (local dev): keep existing behavior\n await retryOnDdlRace(() => client.execute(createSql));\n await retryOnDdlRace(() =>\n client.execute(\n `CREATE INDEX IF NOT EXISTS idx_a2a_continuations_status_next ON integration_a2a_continuations(status, next_check_at)`,\n ),\n );\n await retryOnDdlRace(() =>\n client.execute(\n `CREATE INDEX IF NOT EXISTS idx_a2a_continuations_integration_task ON integration_a2a_continuations(integration_task_id)`,\n ),\n );\n await retryOnDdlRace(() =>\n client.execute(\n `CREATE UNIQUE INDEX IF NOT EXISTS idx_a2a_continuations_remote_task ON integration_a2a_continuations(integration_task_id, agent_url, a2a_task_id)`,\n ),\n );\n await addColumnIfMissing(\"a2a_auth_token\", \"TEXT\");\n await addColumnIfMissing(\"dedupe_key\", \"TEXT\");\n await addColumnIfMissing(\"progress_ref\", \"TEXT\");\n await addColumnIfMissing(\n \"progress_ref_claimed\",\n `${intType()} NOT NULL DEFAULT 0`,\n );\n await backfillProgressRefOwners(client);\n await retryOnDdlRace(() =>\n client.execute(\n `CREATE INDEX IF NOT EXISTS idx_a2a_continuations_dedupe_key ON integration_a2a_continuations(integration_task_id, agent_url, dedupe_key)`,\n ),\n );\n await retryOnDdlRace(() =>\n client.execute(\n `CREATE UNIQUE INDEX IF NOT EXISTS idx_a2a_continuations_one_progress_owner ON integration_a2a_continuations(integration_task_id) WHERE progress_ref_claimed = 1`,\n ),\n );\n })().catch((err) => {\n // Retry init on the next call after a failed startup.\n _initPromise = undefined;\n throw err;\n });\n }\n return _initPromise;\n}\n\nasync function addColumnIfMissing(name: string, definition: string) {\n try {\n await retryOnDdlRace(() =>\n getDbExec().execute(\n `ALTER TABLE integration_a2a_continuations ADD COLUMN ${name} ${definition}`,\n ),\n );\n } catch (err) {\n if (isDuplicateColumnError(err)) return;\n throw err;\n }\n}\n\nasync function backfillProgressRefOwners(\n client: ReturnType<typeof getDbExec>,\n): Promise<void> {\n await client.execute(`\n UPDATE integration_a2a_continuations AS candidate\n SET progress_ref_claimed = 1\n WHERE candidate.progress_ref IS NOT NULL\n AND candidate.status NOT IN ('completed', 'failed')\n AND candidate.progress_ref_claimed = 0\n AND NOT EXISTS (\n SELECT 1\n FROM integration_a2a_continuations AS owner\n WHERE owner.integration_task_id = candidate.integration_task_id\n AND owner.progress_ref_claimed = 1\n )\n AND candidate.id = (\n SELECT selected.id\n FROM integration_a2a_continuations AS selected\n WHERE selected.integration_task_id = candidate.integration_task_id\n AND selected.progress_ref IS NOT NULL\n AND selected.status NOT IN ('completed', 'failed')\n ORDER BY selected.created_at ASC, selected.id ASC\n LIMIT 1\n )\n `);\n}\n\nexport type A2AContinuationStatus =\n | \"pending\"\n | \"processing\"\n | \"delivering\"\n | \"completed\"\n | \"failed\";\n\nexport interface A2AContinuation {\n id: string;\n integrationTaskId: string;\n platform: string;\n externalThreadId: string;\n incoming: IncomingMessage;\n placeholderRef: string | null;\n progressRef: PlatformRunProgressRef | null;\n progressRefClaimed: boolean;\n ownerEmail: string;\n orgId: string | null;\n agentName: string;\n agentUrl: string;\n dedupeKey: string | null;\n a2aTaskId: string;\n a2aAuthToken: string | null;\n status: A2AContinuationStatus;\n attempts: number;\n nextCheckAt: number;\n errorMessage: string | null;\n createdAt: number;\n updatedAt: number;\n completedAt: number | null;\n}\n\nconst MAX_PROGRESS_REF_KIND_CHARS = 128;\nconst MAX_PROGRESS_REF_STREAM_TS_CHARS = 256;\n\n/**\n * Keep only the tiny, adapter-owned continuation reference. Invalid rows are\n * treated as unavailable rather than throwing during a retry sweep.\n */\nfunction parseProgressRef(value: unknown): PlatformRunProgressRef | null {\n if (typeof value !== \"string\" || value.length === 0) return null;\n try {\n const parsed = JSON.parse(value) as unknown;\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n return null;\n }\n const { kind, streamTs } = parsed as Record<string, unknown>;\n if (\n typeof kind !== \"string\" ||\n typeof streamTs !== \"string\" ||\n kind.length === 0 ||\n streamTs.length === 0 ||\n kind.length > MAX_PROGRESS_REF_KIND_CHARS ||\n streamTs.length > MAX_PROGRESS_REF_STREAM_TS_CHARS\n ) {\n return null;\n }\n return { kind, streamTs };\n } catch {\n return null;\n }\n}\n\nfunction serializeProgressRef(value: unknown): string | null {\n const parsed = parseProgressRef(\n typeof value === \"string\" ? value : JSON.stringify(value),\n );\n return parsed ? JSON.stringify(parsed) : null;\n}\n\nfunction rowToContinuation(row: Record<string, unknown>): A2AContinuation {\n return {\n id: row.id as string,\n integrationTaskId: row.integration_task_id as string,\n platform: row.platform as string,\n externalThreadId: row.external_thread_id as string,\n incoming: JSON.parse(row.incoming_payload as string) as IncomingMessage,\n placeholderRef: (row.placeholder_ref as string | null) ?? null,\n progressRef: parseProgressRef(row.progress_ref),\n progressRefClaimed: Number(row.progress_ref_claimed ?? 0) === 1,\n ownerEmail: row.owner_email as string,\n orgId: (row.org_id as string | null) ?? null,\n agentName: row.agent_name as string,\n agentUrl: row.agent_url as string,\n dedupeKey: (row.dedupe_key as string | null) ?? null,\n a2aTaskId: row.a2a_task_id as string,\n a2aAuthToken: (row.a2a_auth_token as string | null) ?? null,\n status: row.status as A2AContinuationStatus,\n attempts: Number(row.attempts ?? 0),\n nextCheckAt: Number(row.next_check_at ?? 0),\n errorMessage: (row.error_message as string | null) ?? null,\n createdAt: Number(row.created_at ?? 0),\n updatedAt: Number(row.updated_at ?? 0),\n completedAt:\n row.completed_at == null ? null : Number(row.completed_at as number),\n };\n}\n\nexport async function insertA2AContinuation(input: {\n integrationTaskId: string;\n platform: string;\n externalThreadId: string;\n incoming: IncomingMessage;\n placeholderRef?: string | null;\n progressRef?: PlatformRunProgressRef | null;\n ownerEmail: string;\n orgId?: string | null;\n agentName: string;\n agentUrl: string;\n dedupeKey?: string | null;\n a2aTaskId: string;\n a2aAuthToken?: string | null;\n}): Promise<A2AContinuation> {\n await ensureTable();\n const client = getDbExec();\n const now = Date.now();\n const id = `a2a-cont-${now}-${Math.random().toString(36).slice(2, 8)}`;\n const payload = JSON.stringify(input.incoming);\n const progressRef = serializeProgressRef(input.progressRef);\n\n try {\n await client.execute({\n sql: `INSERT INTO integration_a2a_continuations\n (id, integration_task_id, platform, external_thread_id, incoming_payload,\n placeholder_ref, progress_ref, progress_ref_claimed, owner_email, org_id, agent_name, agent_url, dedupe_key, a2a_task_id, a2a_auth_token,\n status, attempts, next_check_at, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n id,\n input.integrationTaskId,\n input.platform,\n input.externalThreadId,\n payload,\n input.placeholderRef ?? null,\n null,\n 0,\n input.ownerEmail,\n input.orgId ?? null,\n input.agentName,\n input.agentUrl,\n input.dedupeKey ?? null,\n input.a2aTaskId,\n input.a2aAuthToken ?? null,\n \"pending\",\n 0,\n now,\n now,\n now,\n ],\n });\n } catch (err: any) {\n if (!isDuplicateContinuationError(err)) throw err;\n const existing = await findA2AContinuation(\n input.integrationTaskId,\n input.agentUrl,\n input.a2aTaskId,\n );\n if (existing) {\n // A retry can reach this row after the original invocation created it\n // without a resumable progress surface (or with one that has gone\n // stale). Keep the most recent valid adapter reference for active work,\n // but never resurrect short-lived delivery state after a terminal row\n // has deliberately scrubbed it.\n if (\n progressRef &&\n existing.status !== \"completed\" &&\n existing.status !== \"failed\"\n ) {\n if (existing.progressRefClaimed) {\n if (JSON.stringify(existing.progressRef) !== progressRef) {\n await client.execute({\n sql: `UPDATE integration_a2a_continuations\n SET progress_ref = ?, updated_at = ?\n WHERE id = ? AND status NOT IN ('completed', 'failed')\n AND progress_ref_claimed = 1\n AND (progress_ref IS NULL OR progress_ref <> ?)`,\n args: [progressRef, now, existing.id, progressRef],\n });\n }\n } else {\n await claimA2AContinuationProgressRef(existing.id, progressRef);\n }\n return (await getA2AContinuation(existing.id)) ?? existing;\n }\n return existing;\n }\n throw err;\n }\n\n if (progressRef) {\n await claimA2AContinuationProgressRef(id, progressRef);\n }\n return (await getA2AContinuation(id))!;\n}\n\n/**\n * A native platform stream has one terminal completion. Claim it for a single\n * downstream continuation, and retain the ownership marker after terminal\n * cleanup scrubs the short-lived stream reference. The partial unique index\n * makes concurrent downstream inserts safe across processes.\n */\nasync function claimA2AContinuationProgressRef(\n id: string,\n progressRef: string,\n): Promise<void> {\n try {\n await getDbExec().execute({\n sql: `UPDATE integration_a2a_continuations\n SET progress_ref = ?, progress_ref_claimed = 1\n WHERE id = ? AND progress_ref_claimed = 0`,\n args: [progressRef, id],\n });\n } catch (err) {\n // A sibling continuation already owns this stream and will finalize it.\n // This continuation still delivers through the normal response path.\n if (isDuplicateContinuationError(err)) return;\n throw err;\n }\n}\n\nexport async function getA2AContinuationForIntegrationTask(\n integrationTaskId: string,\n): Promise<A2AContinuation | null> {\n await ensureTable();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT * FROM integration_a2a_continuations\n WHERE integration_task_id = ?\n ORDER BY created_at ASC\n LIMIT 1`,\n args: [integrationTaskId],\n });\n return rows[0] ? rowToContinuation(rows[0] as Record<string, unknown>) : null;\n}\n\nexport async function hasActiveA2AContinuationsForIntegrationTask(\n integrationTaskId: string,\n): Promise<boolean> {\n await ensureTable();\n const { rows } = await getDbExec().execute({\n sql: `SELECT 1 AS active FROM integration_a2a_continuations\n WHERE integration_task_id = ?\n AND status IN ('pending', 'processing', 'delivering')\n LIMIT 1`,\n args: [integrationTaskId],\n });\n return rows.length > 0;\n}\n\nexport async function failA2AContinuationsForIntegrationTask(\n integrationTaskId: string,\n errorMessage: string,\n): Promise<void> {\n await ensureTable();\n const now = Date.now();\n await getDbExec().execute({\n sql: `UPDATE integration_a2a_continuations\n SET status = 'failed', error_message = ?, updated_at = ?, completed_at = ?\n WHERE integration_task_id = ?\n AND status IN ('pending', 'processing', 'delivering')`,\n args: [errorMessage.slice(0, 2000), now, now, integrationTaskId],\n });\n}\n\nexport async function getA2AContinuationsForIntegrationTaskAgent(\n integrationTaskId: string,\n agentUrl: string,\n dedupeKey?: string | null,\n): Promise<A2AContinuation[]> {\n await ensureTable();\n const client = getDbExec();\n const { rows } = await client.execute(\n dedupeKey\n ? {\n sql: `SELECT * FROM integration_a2a_continuations\n WHERE integration_task_id = ? AND agent_url = ? AND dedupe_key = ?\n ORDER BY created_at ASC`,\n args: [integrationTaskId, agentUrl, dedupeKey],\n }\n : {\n sql: `SELECT * FROM integration_a2a_continuations\n WHERE integration_task_id = ? AND agent_url = ?\n ORDER BY created_at ASC`,\n args: [integrationTaskId, agentUrl],\n },\n );\n return rows.map((row) => rowToContinuation(row as Record<string, unknown>));\n}\n\nfunction isDuplicateContinuationError(err: unknown): boolean {\n const e = err as { code?: string; message?: string } | null;\n if (!e) return false;\n if (e.code === \"23505\") return true;\n const msg = String(e.message ?? \"\").toLowerCase();\n return (\n msg.includes(\"unique\") ||\n msg.includes(\"duplicate entry\") ||\n msg.includes(\"duplicate key\")\n );\n}\n\nasync function findA2AContinuation(\n integrationTaskId: string,\n agentUrl: string,\n a2aTaskId: string,\n): Promise<A2AContinuation | null> {\n await ensureTable();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT * FROM integration_a2a_continuations\n WHERE integration_task_id = ? AND agent_url = ? AND a2a_task_id = ?\n LIMIT 1`,\n args: [integrationTaskId, agentUrl, a2aTaskId],\n });\n return rows[0] ? rowToContinuation(rows[0] as Record<string, unknown>) : null;\n}\n\nexport async function getA2AContinuation(\n id: string,\n): Promise<A2AContinuation | null> {\n await ensureTable();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT * FROM integration_a2a_continuations WHERE id = ? LIMIT 1`,\n args: [id],\n });\n return rows[0] ? rowToContinuation(rows[0] as Record<string, unknown>) : null;\n}\n\nexport async function claimA2AContinuation(\n id: string,\n): Promise<A2AContinuation | null> {\n await ensureTable();\n const client = getDbExec();\n const now = Date.now();\n const processingCutoff = now - PROCESSING_STUCK_AFTER_MS;\n const staleNextCheckCutoff = now - PROCESSING_NEXT_CHECK_STALE_AFTER_MS;\n const result = await client.execute({\n sql: isPostgres()\n ? `UPDATE integration_a2a_continuations\n SET status = ?, attempts = attempts + 1, updated_at = ?\n WHERE id = ?\n AND (\n status = 'pending'\n OR (\n status = 'processing'\n AND (updated_at <= ? OR next_check_at <= ?)\n )\n )\n RETURNING *`\n : `UPDATE integration_a2a_continuations\n SET status = ?, attempts = attempts + 1, updated_at = ?\n WHERE id = ?\n AND (\n status = 'pending'\n OR (\n status = 'processing'\n AND (updated_at <= ? OR next_check_at <= ?)\n )\n )`,\n args: [\"processing\", now, id, processingCutoff, staleNextCheckCutoff],\n });\n const rows = result.rows ?? [];\n if (isPostgres()) {\n return rows[0]\n ? rowToContinuation(rows[0] as Record<string, unknown>)\n : null;\n }\n const affected = (result as any)?.rowsAffected ?? (result as any)?.rowCount;\n if (affected === 0) return null;\n const fetched = await getA2AContinuation(id);\n if (!fetched || fetched.status !== \"processing\") return null;\n return fetched;\n}\n\nexport async function claimDueA2AContinuations(\n limit = 5,\n): Promise<A2AContinuation[]> {\n const ids = await recoverDueA2AContinuationIds(limit);\n const claimed: A2AContinuation[] = [];\n for (const id of ids) {\n const continuation = await claimA2AContinuation(id);\n if (continuation) claimed.push(continuation);\n }\n return claimed;\n}\n\n/**\n * Makes stale leases eligible again and returns a bounded set of due ids.\n *\n * This intentionally does not claim anything. Durable schedulers use it only\n * to wake the normal processor, whose atomic claim remains the sole progress\n * and delivery owner under overlapping scheduler/self-dispatch executions.\n */\nexport async function recoverDueA2AContinuationIds(\n limit = 5,\n integrationTaskIds?: string[],\n): Promise<string[]> {\n await ensureTable();\n const client = getDbExec();\n const now = Date.now();\n const processingCutoff = now - PROCESSING_STUCK_AFTER_MS;\n const staleNextCheckCutoff = now - PROCESSING_NEXT_CHECK_STALE_AFTER_MS;\n if (integrationTaskIds && integrationTaskIds.length === 0) return [];\n const taskFilter = integrationTaskIds?.length\n ? ` AND integration_task_id IN (${integrationTaskIds.map(() => \"?\").join(\", \")})`\n : \"\";\n const taskArgs = integrationTaskIds ?? [];\n // If a processor dies while holding a delivery claim, retry the final send.\n // The stale cutoff preserves the in-flight delivery guard while keeping\n // final integration replies at-least-once.\n await client.execute({\n sql: `UPDATE integration_a2a_continuations\n SET status = ?, next_check_at = ?, updated_at = ?\n WHERE status = 'delivering' AND updated_at <= ?${taskFilter}`,\n args: [\"pending\", now, now, now - 5 * 60 * 1000, ...taskArgs],\n });\n await client.execute({\n sql: `UPDATE integration_a2a_continuations\n SET status = ?, next_check_at = ?, updated_at = ?\n WHERE status = 'processing'\n AND (updated_at <= ? OR next_check_at <= ?)${taskFilter}`,\n args: [\n \"pending\",\n now,\n now,\n processingCutoff,\n staleNextCheckCutoff,\n ...taskArgs,\n ],\n });\n const { rows } = await client.execute({\n sql: `SELECT id FROM integration_a2a_continuations\n WHERE status = 'pending' AND next_check_at <= ?${taskFilter}\n ORDER BY next_check_at ASC\n LIMIT ?`,\n args: [now, ...taskArgs, limit],\n });\n return rows.map((row) => row.id as string);\n}\n\nexport async function listRecoverableA2AIntegrationTaskIds(\n limit = 50,\n): Promise<string[]> {\n const tasks = await listRecoverableA2AIntegrationTasks(limit);\n return tasks.map((task) => task.id);\n}\n\nexport interface RecoverableA2AIntegrationTask {\n id: string;\n platform: string;\n externalThreadId: string;\n dispatchScope: string | null;\n status: string;\n}\n\n/**\n * Read due continuation owners and their rollout scope in one query. Recovery\n * can filter the canary in memory without an N+1 pending-task lookup loop.\n */\nexport async function listRecoverableA2AIntegrationTasks(\n limit = 50,\n): Promise<RecoverableA2AIntegrationTask[]> {\n await ensureTable();\n const now = Date.now();\n const { rows } = await getDbExec().execute({\n sql: `SELECT DISTINCT c.integration_task_id, t.platform,\n t.external_thread_id, t.dispatch_scope, t.status\n FROM integration_a2a_continuations c\n INNER JOIN integration_pending_tasks t\n ON t.id = c.integration_task_id\n WHERE t.status = 'processing'\n AND ((c.status = 'pending' AND c.next_check_at <= ?)\n OR (c.status = 'processing' AND\n (c.updated_at <= ? OR c.next_check_at <= ?))\n OR (c.status = 'delivering' AND c.updated_at <= ?))\n ORDER BY c.integration_task_id ASC\n LIMIT ?`,\n args: [\n now,\n now - PROCESSING_STUCK_AFTER_MS,\n now - PROCESSING_NEXT_CHECK_STALE_AFTER_MS,\n now - 5 * 60 * 1000,\n Math.max(1, Math.min(Math.floor(limit), 200)),\n ],\n });\n return rows.map((row) => ({\n id: String(row.integration_task_id),\n platform: String(row.platform),\n externalThreadId: String(row.external_thread_id),\n dispatchScope: (row.dispatch_scope as string | null) ?? null,\n status: String(row.status),\n }));\n}\n\nexport async function claimA2AContinuationDelivery(\n id: string,\n): Promise<A2AContinuation | null> {\n await ensureTable();\n const client = getDbExec();\n const now = Date.now();\n const result = await client.execute({\n sql: isPostgres()\n ? `UPDATE integration_a2a_continuations\n SET status = ?, updated_at = ?\n WHERE id = ? AND status = 'processing'\n RETURNING *`\n : `UPDATE integration_a2a_continuations\n SET status = ?, updated_at = ?\n WHERE id = ? AND status = 'processing'`,\n args: [\"delivering\", now, id],\n });\n const rows = result.rows ?? [];\n if (isPostgres()) {\n return rows[0]\n ? rowToContinuation(rows[0] as Record<string, unknown>)\n : null;\n }\n const affected = (result as any)?.rowsAffected ?? (result as any)?.rowCount;\n if (affected === 0) return null;\n const fetched = await getA2AContinuation(id);\n if (!fetched || fetched.status !== \"delivering\") return null;\n return fetched;\n}\n\nexport async function rescheduleA2AContinuation(\n id: string,\n delayMs: number,\n): Promise<void> {\n await ensureTable();\n const client = getDbExec();\n const now = Date.now();\n await client.execute({\n sql: `UPDATE integration_a2a_continuations\n SET status = ?, next_check_at = ?, updated_at = ?\n WHERE id = ? AND status IN ('processing', 'delivering')`,\n args: [\"pending\", now + delayMs, now, id],\n });\n}\n\nexport async function completeA2AContinuation(id: string): Promise<void> {\n await ensureTable();\n const client = getDbExec();\n const now = Date.now();\n await client.execute({\n sql: `UPDATE integration_a2a_continuations\n SET status = ?, updated_at = ?, completed_at = ?,\n incoming_payload = ?, a2a_auth_token = NULL, progress_ref = NULL\n WHERE id = ? AND status IN ('processing', 'delivering', 'completed')`,\n args: [\"completed\", now, now, \"{}\", id],\n });\n}\n\nexport async function failA2AContinuation(\n id: string,\n errorMessage: string,\n): Promise<void> {\n await ensureTable();\n const client = getDbExec();\n const now = Date.now();\n await client.execute({\n sql: `UPDATE integration_a2a_continuations\n SET status = ?, updated_at = ?, error_message = ?,\n incoming_payload = ?, a2a_auth_token = NULL, progress_ref = NULL\n WHERE id = ? AND status <> 'completed'`,\n args: [\"failed\", now, errorMessage.slice(0, 2000), \"{}\", id],\n });\n}\n"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface IntegrationCampaignRecoveryResult {
|
|
2
|
+
selected: number;
|
|
3
|
+
dispatched: number;
|
|
4
|
+
skipped: number;
|
|
5
|
+
failed: number;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Wake due campaign chunks without claiming or executing them in the sweep.
|
|
9
|
+
* The signed process-task endpoint owns the lease and all mutations.
|
|
10
|
+
*/
|
|
11
|
+
export declare function recoverDueIntegrationCampaigns(options: {
|
|
12
|
+
limit?: number;
|
|
13
|
+
event?: unknown;
|
|
14
|
+
webhookBaseUrl?: string;
|
|
15
|
+
}): Promise<IntegrationCampaignRecoveryResult>;
|
|
16
|
+
//# sourceMappingURL=integration-campaign-recovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integration-campaign-recovery.d.ts","sourceRoot":"","sources":["../../src/integrations/integration-campaign-recovery.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,iCAAiC;IAChD,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAiBD;;;GAGG;AACH,wBAAsB,8BAA8B,CAAC,OAAO,EAAE;IAC5D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,GAAG,OAAO,CAAC,iCAAiC,CAAC,CAkF7C"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { getIntegrationCampaign, failDisabledIntegrationCampaignTask, listDueIntegrationCampaignIds, } from "./integration-campaigns-store.js";
|
|
2
|
+
import { dispatchPendingIntegrationTask, isIntegrationDurableDispatchEnabledForTask, } from "./integration-durable-dispatch.js";
|
|
3
|
+
import { getNextPendingTaskForThread, getPendingTask, } from "./pending-tasks-store.js";
|
|
4
|
+
function hasConfirmedDeliveryReceipt(payload) {
|
|
5
|
+
try {
|
|
6
|
+
const parsed = JSON.parse(payload);
|
|
7
|
+
return (parsed.kind === "response-delivery" &&
|
|
8
|
+
parsed.deliveryReceipt?.status === "delivered");
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Wake due campaign chunks without claiming or executing them in the sweep.
|
|
16
|
+
* The signed process-task endpoint owns the lease and all mutations.
|
|
17
|
+
*/
|
|
18
|
+
export async function recoverDueIntegrationCampaigns(options) {
|
|
19
|
+
const ids = await listDueIntegrationCampaignIds(options.limit ?? 20);
|
|
20
|
+
const result = {
|
|
21
|
+
selected: ids.length,
|
|
22
|
+
dispatched: 0,
|
|
23
|
+
skipped: 0,
|
|
24
|
+
failed: 0,
|
|
25
|
+
};
|
|
26
|
+
for (const id of ids) {
|
|
27
|
+
try {
|
|
28
|
+
const campaign = await getIntegrationCampaign(id);
|
|
29
|
+
if (!campaign) {
|
|
30
|
+
result.skipped += 1;
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
const task = await getPendingTask(campaign.integrationTaskId);
|
|
34
|
+
if (!task || task.status !== "processing") {
|
|
35
|
+
result.skipped += 1;
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
const durableDispatchEnabled = isIntegrationDurableDispatchEnabledForTask({
|
|
39
|
+
platform: task.platform,
|
|
40
|
+
externalThreadId: task.externalThreadId,
|
|
41
|
+
platformContext: task.dispatchScope
|
|
42
|
+
? { channelId: task.dispatchScope }
|
|
43
|
+
: undefined,
|
|
44
|
+
});
|
|
45
|
+
const confirmedReceipt = hasConfirmedDeliveryReceipt(task.payload);
|
|
46
|
+
if (!durableDispatchEnabled && !confirmedReceipt) {
|
|
47
|
+
await failDisabledIntegrationCampaignTask(task.id);
|
|
48
|
+
const nextTask = await getNextPendingTaskForThread(task.platform, task.externalThreadId);
|
|
49
|
+
if (nextTask) {
|
|
50
|
+
await dispatchPendingIntegrationTask({
|
|
51
|
+
taskId: nextTask.id,
|
|
52
|
+
task: {
|
|
53
|
+
platform: task.platform,
|
|
54
|
+
externalThreadId: task.externalThreadId,
|
|
55
|
+
platformContext: nextTask.dispatchScope
|
|
56
|
+
? { channelId: nextTask.dispatchScope }
|
|
57
|
+
: undefined,
|
|
58
|
+
},
|
|
59
|
+
event: options.event,
|
|
60
|
+
baseUrl: options.webhookBaseUrl,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
result.skipped += 1;
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
const outcome = await dispatchPendingIntegrationTask({
|
|
67
|
+
taskId: task.id,
|
|
68
|
+
task: {
|
|
69
|
+
platform: task.platform,
|
|
70
|
+
externalThreadId: task.externalThreadId,
|
|
71
|
+
platformContext: task.dispatchScope
|
|
72
|
+
? { channelId: task.dispatchScope }
|
|
73
|
+
: undefined,
|
|
74
|
+
},
|
|
75
|
+
event: options.event,
|
|
76
|
+
baseUrl: options.webhookBaseUrl,
|
|
77
|
+
campaignContinuation: true,
|
|
78
|
+
...(confirmedReceipt && !durableDispatchEnabled
|
|
79
|
+
? { allowPortableConfirmedReceiptReconciliation: true }
|
|
80
|
+
: {}),
|
|
81
|
+
});
|
|
82
|
+
if (outcome === "failed")
|
|
83
|
+
result.failed += 1;
|
|
84
|
+
else
|
|
85
|
+
result.dispatched += 1;
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
result.failed += 1;
|
|
89
|
+
console.error(`[integrations] Failed to wake integration campaign ${id}:`, error);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return result;
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=integration-campaign-recovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integration-campaign-recovery.js","sourceRoot":"","sources":["../../src/integrations/integration-campaign-recovery.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n getIntegrationCampaign,\n failDisabledIntegrationCampaignTask,\n listDueIntegrationCampaignIds,\n} from \"./integration-campaigns-store.js\";\nimport {\n dispatchPendingIntegrationTask,\n isIntegrationDurableDispatchEnabledForTask,\n} from \"./integration-durable-dispatch.js\";\nimport {\n getNextPendingTaskForThread,\n getPendingTask,\n} from \"./pending-tasks-store.js\";\n\nexport interface IntegrationCampaignRecoveryResult {\n selected: number;\n dispatched: number;\n skipped: number;\n failed: number;\n}\n\nfunction hasConfirmedDeliveryReceipt(payload: string): boolean {\n try {\n const parsed = JSON.parse(payload) as {\n kind?: unknown;\n deliveryReceipt?: { status?: unknown };\n };\n return (\n parsed.kind === \"response-delivery\" &&\n parsed.deliveryReceipt?.status === \"delivered\"\n );\n } catch {\n return false;\n }\n}\n\n/**\n * Wake due campaign chunks without claiming or executing them in the sweep.\n * The signed process-task endpoint owns the lease and all mutations.\n */\nexport async function recoverDueIntegrationCampaigns(options: {\n limit?: number;\n event?: unknown;\n webhookBaseUrl?: string;\n}): Promise<IntegrationCampaignRecoveryResult> {\n const ids = await listDueIntegrationCampaignIds(options.limit ?? 20);\n const result: IntegrationCampaignRecoveryResult = {\n selected: ids.length,\n dispatched: 0,\n skipped: 0,\n failed: 0,\n };\n\n for (const id of ids) {\n try {\n const campaign = await getIntegrationCampaign(id);\n if (!campaign) {\n result.skipped += 1;\n continue;\n }\n const task = await getPendingTask(campaign.integrationTaskId);\n if (!task || task.status !== \"processing\") {\n result.skipped += 1;\n continue;\n }\n const durableDispatchEnabled = isIntegrationDurableDispatchEnabledForTask(\n {\n platform: task.platform,\n externalThreadId: task.externalThreadId,\n platformContext: task.dispatchScope\n ? { channelId: task.dispatchScope }\n : undefined,\n },\n );\n const confirmedReceipt = hasConfirmedDeliveryReceipt(task.payload);\n if (!durableDispatchEnabled && !confirmedReceipt) {\n await failDisabledIntegrationCampaignTask(task.id);\n const nextTask = await getNextPendingTaskForThread(\n task.platform,\n task.externalThreadId,\n );\n if (nextTask) {\n await dispatchPendingIntegrationTask({\n taskId: nextTask.id,\n task: {\n platform: task.platform,\n externalThreadId: task.externalThreadId,\n platformContext: nextTask.dispatchScope\n ? { channelId: nextTask.dispatchScope }\n : undefined,\n },\n event: options.event,\n baseUrl: options.webhookBaseUrl,\n });\n }\n result.skipped += 1;\n continue;\n }\n const outcome = await dispatchPendingIntegrationTask({\n taskId: task.id,\n task: {\n platform: task.platform,\n externalThreadId: task.externalThreadId,\n platformContext: task.dispatchScope\n ? { channelId: task.dispatchScope }\n : undefined,\n },\n event: options.event,\n baseUrl: options.webhookBaseUrl,\n campaignContinuation: true,\n ...(confirmedReceipt && !durableDispatchEnabled\n ? { allowPortableConfirmedReceiptReconciliation: true }\n : {}),\n });\n if (outcome === \"failed\") result.failed += 1;\n else result.dispatched += 1;\n } catch (error) {\n result.failed += 1;\n console.error(\n `[integrations] Failed to wake integration campaign ${id}:`,\n error,\n );\n }\n }\n\n return result;\n}\n"]}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
export type IntegrationCampaignStatus = "pending" | "processing" | "waiting" | "completed" | "failed";
|
|
2
|
+
export interface IntegrationCampaign {
|
|
3
|
+
id: string;
|
|
4
|
+
integrationTaskId: string;
|
|
5
|
+
threadId: string;
|
|
6
|
+
turnId: string;
|
|
7
|
+
status: IntegrationCampaignStatus;
|
|
8
|
+
chunkCount: number;
|
|
9
|
+
currentRunId: string | null;
|
|
10
|
+
leaseToken: string | null;
|
|
11
|
+
leaseExpiresAt: number | null;
|
|
12
|
+
nextRunAt: number;
|
|
13
|
+
progressRef: string | null;
|
|
14
|
+
checkpoint: string | null;
|
|
15
|
+
errorMessage: string | null;
|
|
16
|
+
createdAt: number;
|
|
17
|
+
updatedAt: number;
|
|
18
|
+
completedAt: number | null;
|
|
19
|
+
}
|
|
20
|
+
export type ClaimIntegrationCampaignResult = {
|
|
21
|
+
kind: "claimed";
|
|
22
|
+
campaign: IntegrationCampaign;
|
|
23
|
+
} | {
|
|
24
|
+
kind: "not-due";
|
|
25
|
+
} | {
|
|
26
|
+
kind: "chunk-limit";
|
|
27
|
+
campaign: IntegrationCampaign;
|
|
28
|
+
};
|
|
29
|
+
export declare function ensureIntegrationCampaignsTable(): Promise<void>;
|
|
30
|
+
export declare function getIntegrationCampaign(id: string): Promise<IntegrationCampaign | null>;
|
|
31
|
+
export declare function getIntegrationCampaignForTask(integrationTaskId: string): Promise<IntegrationCampaign | null>;
|
|
32
|
+
export declare function createIntegrationCampaign(input: {
|
|
33
|
+
integrationTaskId: string;
|
|
34
|
+
threadId: string;
|
|
35
|
+
turnId: string;
|
|
36
|
+
progressRef?: string | null;
|
|
37
|
+
checkpoint?: string | null;
|
|
38
|
+
nextRunAt?: number;
|
|
39
|
+
}): Promise<IntegrationCampaign>;
|
|
40
|
+
export declare function claimIntegrationCampaign(id: string, input: {
|
|
41
|
+
runId: string;
|
|
42
|
+
leaseToken: string;
|
|
43
|
+
leaseDurationMs: number;
|
|
44
|
+
maxChunks: number;
|
|
45
|
+
}): Promise<ClaimIntegrationCampaignResult>;
|
|
46
|
+
export declare function claimIntegrationCampaignDeliveryForTask(integrationTaskId: string, input: {
|
|
47
|
+
runId: string;
|
|
48
|
+
leaseToken: string;
|
|
49
|
+
leaseDurationMs: number;
|
|
50
|
+
}): Promise<IntegrationCampaign | null>;
|
|
51
|
+
export declare function heartbeatIntegrationCampaign(id: string, input: {
|
|
52
|
+
runId: string;
|
|
53
|
+
leaseToken: string;
|
|
54
|
+
leaseDurationMs: number;
|
|
55
|
+
}): Promise<boolean>;
|
|
56
|
+
export declare function scheduleNextIntegrationCampaign(id: string, input: {
|
|
57
|
+
runId: string;
|
|
58
|
+
leaseToken: string;
|
|
59
|
+
nextRunAt: number;
|
|
60
|
+
progressRef?: string | null;
|
|
61
|
+
checkpoint?: string | null;
|
|
62
|
+
}): Promise<boolean>;
|
|
63
|
+
export declare function waitForA2AIntegrationCampaign(id: string, input: {
|
|
64
|
+
runId: string;
|
|
65
|
+
leaseToken: string;
|
|
66
|
+
nextRunAt: number;
|
|
67
|
+
progressRef?: string | null;
|
|
68
|
+
}): Promise<boolean>;
|
|
69
|
+
export declare function completeIntegrationCampaign(id: string, input: {
|
|
70
|
+
runId: string;
|
|
71
|
+
leaseToken: string;
|
|
72
|
+
}): Promise<boolean>;
|
|
73
|
+
export declare function completeIntegrationCampaignTask(id: string, input: {
|
|
74
|
+
integrationTaskId: string;
|
|
75
|
+
runId: string;
|
|
76
|
+
leaseToken: string;
|
|
77
|
+
}): Promise<boolean>;
|
|
78
|
+
export declare function failIntegrationCampaign(id: string, input: {
|
|
79
|
+
runId: string;
|
|
80
|
+
leaseToken: string;
|
|
81
|
+
errorMessage: string;
|
|
82
|
+
}): Promise<boolean>;
|
|
83
|
+
export declare function failExhaustedIntegrationCampaign(id: string, input: {
|
|
84
|
+
maxChunks: number;
|
|
85
|
+
errorMessage: string;
|
|
86
|
+
}): Promise<boolean>;
|
|
87
|
+
export declare function terminalizeIntegrationCampaignForTask(integrationTaskId: string, input: {
|
|
88
|
+
status: "completed" | "failed";
|
|
89
|
+
errorMessage?: string;
|
|
90
|
+
}): Promise<boolean>;
|
|
91
|
+
export declare function failIntegrationCampaignTaskDeliveryContainment(integrationTaskId: string, errorMessage: string): Promise<boolean>;
|
|
92
|
+
/**
|
|
93
|
+
* Fail closed when a durable campaign's rollout scope is removed. Both rows
|
|
94
|
+
* transition in one transaction so the per-thread processing lock cannot be
|
|
95
|
+
* stranded while the campaign is no longer recoverable.
|
|
96
|
+
*/
|
|
97
|
+
export declare function failDisabledIntegrationCampaignTask(integrationTaskId: string, errorMessage?: string): Promise<void>;
|
|
98
|
+
export declare function transitionIntegrationCampaignTaskToDeliveryRetry(integrationTaskId: string, input: {
|
|
99
|
+
payload: string;
|
|
100
|
+
errorMessage: string;
|
|
101
|
+
campaignStatus: "completed" | "failed";
|
|
102
|
+
campaignId: string;
|
|
103
|
+
runId: string;
|
|
104
|
+
leaseToken: string;
|
|
105
|
+
}): Promise<boolean>;
|
|
106
|
+
export declare function transitionIntegrationCampaignTaskToA2AReceiptRetry(integrationTaskId: string, input: {
|
|
107
|
+
payload: string;
|
|
108
|
+
errorMessage: string;
|
|
109
|
+
campaignId: string;
|
|
110
|
+
runId: string;
|
|
111
|
+
leaseToken: string;
|
|
112
|
+
nextRunAt: number;
|
|
113
|
+
}): Promise<boolean>;
|
|
114
|
+
export declare function refreshIntegrationCampaignTaskA2AReceiptRetry(integrationTaskId: string, input: {
|
|
115
|
+
payload: string;
|
|
116
|
+
errorMessage: string;
|
|
117
|
+
}): Promise<boolean>;
|
|
118
|
+
export declare function completeIntegrationCampaignTaskAfterA2A(integrationTaskId: string): Promise<boolean>;
|
|
119
|
+
export declare function listDueIntegrationCampaignIds(limit?: number): Promise<string[]>;
|
|
120
|
+
export declare function hasActiveIntegrationCampaign(integrationTaskId: string): Promise<boolean>;
|
|
121
|
+
//# sourceMappingURL=integration-campaigns-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integration-campaigns-store.d.ts","sourceRoot":"","sources":["../../src/integrations/integration-campaigns-store.ts"],"names":[],"mappings":"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"}
|