@agent-native/core 0.130.0 → 0.130.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/corpus/README.md +1 -1
- package/corpus/core/CHANGELOG.md +6 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/integrations/a2a-continuation-processor.ts +481 -122
- package/corpus/core/src/integrations/a2a-continuations-store.ts +345 -14
- package/corpus/core/src/integrations/adapters/slack.ts +243 -53
- package/corpus/core/src/integrations/integration-campaign-recovery.ts +4 -1
- package/corpus/core/src/integrations/plugin.ts +39 -21
- package/corpus/core/src/integrations/task-queue-stats.ts +146 -0
- package/corpus/core/src/integrations/types.ts +25 -4
- package/corpus/core/src/integrations/webhook-handler.ts +18 -5
- package/corpus/templates/dispatch/changelog/2026-07-26-slack-replies-recover-after-connected-app-updates.md +6 -0
- package/corpus/templates/slides/.agents/skills/design-systems/SKILL.md +15 -0
- package/corpus/templates/slides/actions/delete-design-system.ts +145 -0
- package/corpus/templates/slides/actions/list-design-systems.ts +94 -2
- package/corpus/templates/slides/app/components/design-system/DesignSystemCard.tsx +43 -1
- package/corpus/templates/slides/app/hooks/use-design-systems.ts +2 -0
- package/corpus/templates/slides/app/i18n/en-US.ts +7 -0
- package/corpus/templates/slides/app/pages/DesignSystems.tsx +56 -1
- package/corpus/templates/slides/changelog/2026-07-28-delete-a-design-system-you-own-from-the-design-systems-page-.md +6 -0
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/integrations/a2a-continuation-processor.d.ts +5 -0
- package/dist/integrations/a2a-continuation-processor.d.ts.map +1 -1
- package/dist/integrations/a2a-continuation-processor.js +293 -79
- package/dist/integrations/a2a-continuation-processor.js.map +1 -1
- package/dist/integrations/a2a-continuations-store.d.ts +23 -1
- package/dist/integrations/a2a-continuations-store.d.ts.map +1 -1
- package/dist/integrations/a2a-continuations-store.js +249 -15
- package/dist/integrations/a2a-continuations-store.js.map +1 -1
- package/dist/integrations/adapters/slack.d.ts.map +1 -1
- package/dist/integrations/adapters/slack.js +155 -31
- package/dist/integrations/adapters/slack.js.map +1 -1
- package/dist/integrations/integration-campaign-recovery.d.ts.map +1 -1
- package/dist/integrations/integration-campaign-recovery.js +3 -1
- package/dist/integrations/integration-campaign-recovery.js.map +1 -1
- package/dist/integrations/plugin.d.ts.map +1 -1
- package/dist/integrations/plugin.js +29 -12
- package/dist/integrations/plugin.js.map +1 -1
- package/dist/integrations/task-queue-stats.d.ts +12 -0
- package/dist/integrations/task-queue-stats.d.ts.map +1 -1
- package/dist/integrations/task-queue-stats.js +106 -0
- package/dist/integrations/task-queue-stats.js.map +1 -1
- package/dist/integrations/types.d.ts +24 -6
- package/dist/integrations/types.d.ts.map +1 -1
- package/dist/integrations/types.js.map +1 -1
- package/dist/integrations/webhook-handler.d.ts.map +1 -1
- package/dist/integrations/webhook-handler.js +12 -3
- package/dist/integrations/webhook-handler.js.map +1 -1
- package/dist/observability/routes.d.ts +3 -3
- package/dist/progress/routes.d.ts +1 -1
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/package.json +1 -1
- package/src/integrations/a2a-continuation-processor.ts +481 -122
- package/src/integrations/a2a-continuations-store.ts +345 -14
- package/src/integrations/adapters/slack.ts +243 -53
- package/src/integrations/integration-campaign-recovery.ts +4 -1
- package/src/integrations/plugin.ts +39 -21
- package/src/integrations/task-queue-stats.ts +146 -0
- package/src/integrations/types.ts +25 -4
- package/src/integrations/webhook-handler.ts +18 -5
|
@@ -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 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"]}
|
|
1
|
+
{"version":3,"file":"a2a-continuations-store.js","sourceRoot":"","sources":["../../src/integrations/a2a-continuations-store.ts"],"names":[],"mappings":"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","sourcesContent":["import type { A2AArtifactIdentity } from \"../a2a/artifact-response.js\";\nimport {\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;\nconst TERMINAL_HISTORY_FINALIZATION_LEASE_MS = 60 * 1000;\nconst MAX_VERIFIED_ARTIFACT_CHECKPOINT_CHARS = 16_000;\nconst MAX_TERMINAL_HISTORY_PAYLOAD_CHARS = 64_000;\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 verified_artifact_checkpoint TEXT,\n terminal_delivery_kind TEXT,\n terminal_delivery_confirmed_at ${intType()},\n terminal_history_payload 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 ensureColumnExists(\n \"integration_a2a_continuations\",\n \"verified_artifact_checkpoint\",\n `ALTER TABLE integration_a2a_continuations ADD COLUMN IF NOT EXISTS verified_artifact_checkpoint TEXT`,\n );\n await ensureColumnExists(\n \"integration_a2a_continuations\",\n \"terminal_delivery_kind\",\n `ALTER TABLE integration_a2a_continuations ADD COLUMN IF NOT EXISTS terminal_delivery_kind TEXT`,\n );\n await ensureColumnExists(\n \"integration_a2a_continuations\",\n \"terminal_delivery_confirmed_at\",\n `ALTER TABLE integration_a2a_continuations ADD COLUMN IF NOT EXISTS terminal_delivery_confirmed_at ${intType()}`,\n );\n await ensureColumnExists(\n \"integration_a2a_continuations\",\n \"terminal_history_payload\",\n `ALTER TABLE integration_a2a_continuations ADD COLUMN IF NOT EXISTS terminal_history_payload TEXT`,\n );\n await backfillLegacyCompletedDeliveries(client);\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 addColumnIfMissing(\"verified_artifact_checkpoint\", \"TEXT\");\n await addColumnIfMissing(\"terminal_delivery_kind\", \"TEXT\");\n await addColumnIfMissing(\"terminal_delivery_confirmed_at\", intType());\n await addColumnIfMissing(\"terminal_history_payload\", \"TEXT\");\n await backfillLegacyCompletedDeliveries(client);\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\nexport async function ensureA2AContinuationsTable(): Promise<void> {\n await ensureTable();\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\nasync function backfillLegacyCompletedDeliveries(\n client: ReturnType<typeof getDbExec>,\n): Promise<void> {\n await client.execute(`\n UPDATE integration_a2a_continuations\n SET terminal_delivery_kind = 'success',\n terminal_delivery_confirmed_at = COALESCE(completed_at, updated_at)\n WHERE status = 'completed'\n AND terminal_delivery_confirmed_at IS NULL\n `);\n}\n\nexport type A2AContinuationStatus =\n | \"pending\"\n | \"processing\"\n | \"delivering\"\n | \"completed\"\n | \"failed\";\n\nexport type A2ATerminalDeliveryKind = \"success\" | \"failure\";\n\nexport interface A2ATerminalHistoryPayload {\n text: string;\n deliveredAt: string;\n messageRefs: string[];\n artifacts: A2AArtifactIdentity[];\n}\n\nexport type A2AContinuationTaskOutcome =\n | \"active\"\n | \"terminal-delivered\"\n | \"terminal-without-delivery\"\n | \"missing\";\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 verifiedArtifactCheckpoint: string | null;\n terminalDeliveryKind: A2ATerminalDeliveryKind | null;\n terminalDeliveryConfirmedAt: number | null;\n terminalHistoryPayload: A2ATerminalHistoryPayload | 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 verifiedArtifactCheckpoint:\n (row.verified_artifact_checkpoint as string | null) ?? null,\n terminalDeliveryKind:\n row.terminal_delivery_kind === \"success\" ||\n row.terminal_delivery_kind === \"failure\"\n ? row.terminal_delivery_kind\n : null,\n terminalDeliveryConfirmedAt:\n row.terminal_delivery_confirmed_at == null\n ? null\n : Number(row.terminal_delivery_confirmed_at),\n terminalHistoryPayload: parseTerminalHistoryPayload(\n row.terminal_history_payload,\n ),\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\nfunction parseTerminalHistoryPayload(\n value: unknown,\n): A2ATerminalHistoryPayload | null {\n if (typeof value !== \"string\" || !value) return null;\n try {\n const parsed = JSON.parse(value) as Partial<A2ATerminalHistoryPayload>;\n if (\n typeof parsed.text !== \"string\" ||\n typeof parsed.deliveredAt !== \"string\" ||\n !Array.isArray(parsed.messageRefs) ||\n !parsed.messageRefs.every((ref) => typeof ref === \"string\") ||\n !Array.isArray(parsed.artifacts)\n ) {\n return null;\n }\n return {\n text: parsed.text,\n deliveredAt: parsed.deliveredAt,\n messageRefs: parsed.messageRefs,\n artifacts: parsed.artifacts.filter(\n (artifact): artifact is A2AArtifactIdentity =>\n !!artifact &&\n typeof artifact === \"object\" &&\n !Array.isArray(artifact) &&\n typeof (artifact as { id?: unknown }).id === \"string\" &&\n typeof (artifact as { resourceType?: unknown }).resourceType ===\n \"string\" &&\n typeof (artifact as { sourceAction?: unknown }).sourceAction ===\n \"string\",\n ),\n };\n } catch {\n return null;\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 getA2AContinuationTaskOutcome(\n integrationTaskId: string,\n): Promise<A2AContinuationTaskOutcome> {\n await ensureTable();\n const { rows } = await getDbExec().execute({\n sql: `SELECT status, terminal_delivery_confirmed_at\n FROM integration_a2a_continuations\n WHERE integration_task_id = ?`,\n args: [integrationTaskId],\n });\n if (rows.length === 0) return \"missing\";\n if (\n rows.some((row) =>\n [\"pending\", \"processing\", \"delivering\"].includes(String(row.status)),\n )\n ) {\n return \"active\";\n }\n return rows.every((row) => row.terminal_delivery_confirmed_at != null)\n ? \"terminal-delivered\"\n : \"terminal-without-delivery\";\n}\n\nexport async function hasPendingConfirmedA2ADeliveryForIntegrationTask(\n integrationTaskId: string,\n): Promise<boolean> {\n await ensureTable();\n const { rows } = await getDbExec().execute({\n sql: `SELECT 1 AS confirmed FROM integration_a2a_continuations\n WHERE integration_task_id = ?\n AND status IN ('pending', 'processing', 'delivering')\n AND terminal_delivery_confirmed_at IS NOT NULL\n LIMIT 1`,\n args: [integrationTaskId],\n });\n return rows.length > 0;\n}\n\nexport async function hasOnlyLegacyFailedA2AContinuationsForIntegrationTask(\n integrationTaskId: string,\n): Promise<boolean> {\n await ensureTable();\n const { rows } = await getDbExec().execute({\n sql: `SELECT status, terminal_delivery_kind,\n terminal_delivery_confirmed_at, terminal_history_payload\n FROM integration_a2a_continuations\n WHERE integration_task_id = ?`,\n args: [integrationTaskId],\n });\n return (\n rows.length > 0 &&\n rows.every(\n (row) =>\n String(row.status) === \"failed\" &&\n row.terminal_delivery_kind == null &&\n row.terminal_delivery_confirmed_at == null &&\n row.terminal_history_payload == null,\n )\n );\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 verified_artifact_checkpoint = NULL\n WHERE integration_task_id = ?\n AND status IN ('pending', 'processing', 'delivering')\n AND terminal_delivery_confirmed_at IS NULL`,\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 confirmedDeliveryOnly = false,\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 const receiptFilter = confirmedDeliveryOnly\n ? \" AND terminal_delivery_confirmed_at IS NOT NULL\"\n : \"\";\n // If a processor dies after a provider receipt, retry history-only custody\n // as soon as its short follow-up deadline passes. A pre-receipt delivery\n // claim retains the longer stale cutoff before an at-least-once resend.\n await client.execute({\n sql: `UPDATE integration_a2a_continuations\n SET status = ?, next_check_at = ?, updated_at = ?\n WHERE status = 'delivering'\n AND ((terminal_delivery_confirmed_at IS NOT NULL AND next_check_at <= ?)\n OR updated_at <= ?)${taskFilter}${receiptFilter}`,\n args: [\"pending\", now, 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}${receiptFilter}`,\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}${receiptFilter}\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 hasPendingConfirmedDelivery: boolean;\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 EXISTS (\n SELECT 1 FROM integration_a2a_continuations receipt\n WHERE receipt.integration_task_id = c.integration_task_id\n AND receipt.terminal_delivery_confirmed_at IS NOT NULL\n AND receipt.status IN ('pending', 'processing', 'delivering')\n ) AS has_pending_confirmed_delivery\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\n ((c.terminal_delivery_confirmed_at IS NOT NULL AND c.next_check_at <= ?)\n OR 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,\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 hasPendingConfirmedDelivery:\n row.has_pending_confirmed_delivery === true ||\n Number(row.has_pending_confirmed_delivery ?? 0) === 1,\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 retainA2AUnconfirmedDeliveryClaim(\n id: string,\n): Promise<void> {\n await ensureTable();\n const now = Date.now();\n await getDbExec().execute({\n sql: `UPDATE integration_a2a_continuations\n SET next_check_at = ?, updated_at = ?\n WHERE id = ? AND status = 'delivering'\n AND terminal_delivery_confirmed_at IS NULL`,\n args: [now + PROCESSING_STUCK_AFTER_MS, now, id],\n });\n}\n\nexport async function saveA2AVerifiedArtifactCheckpoint(\n id: string,\n checkpoint: string,\n): Promise<string | null> {\n await ensureTable();\n const normalized = checkpoint.trim();\n if (!normalized) return null;\n if (normalized.length > MAX_VERIFIED_ARTIFACT_CHECKPOINT_CHARS) {\n throw new Error(\n `Verified artifact checkpoint exceeds ${MAX_VERIFIED_ARTIFACT_CHECKPOINT_CHARS} characters`,\n );\n }\n const now = Date.now();\n await getDbExec().execute({\n sql: `UPDATE integration_a2a_continuations\n SET verified_artifact_checkpoint = ?, updated_at = ?\n WHERE id = ? AND status IN ('pending', 'processing', 'delivering')`,\n args: [normalized, now, id],\n });\n const persisted = await getA2AContinuation(id);\n return persisted?.verifiedArtifactCheckpoint === normalized\n ? normalized\n : null;\n}\n\nexport async function recordA2ATerminalDeliveryReceipt(\n id: string,\n kind: A2ATerminalDeliveryKind,\n historyPayload: A2ATerminalHistoryPayload,\n errorMessage?: string,\n): Promise<A2AContinuation> {\n await ensureTable();\n const serializedPayload = JSON.stringify(historyPayload);\n if (serializedPayload.length > MAX_TERMINAL_HISTORY_PAYLOAD_CHARS) {\n throw new Error(\n `Terminal A2A history payload exceeds ${MAX_TERMINAL_HISTORY_PAYLOAD_CHARS} characters`,\n );\n }\n const now = Date.now();\n await getDbExec().execute({\n sql: `UPDATE integration_a2a_continuations\n SET status = 'delivering', terminal_delivery_kind = ?,\n terminal_delivery_confirmed_at = COALESCE(terminal_delivery_confirmed_at, ?),\n terminal_history_payload = ?, next_check_at = ?, updated_at = ?,\n error_message = ?\n WHERE id = ?\n AND status IN ('processing', 'delivering')\n AND (terminal_delivery_confirmed_at IS NULL\n OR terminal_delivery_kind = ?)`,\n args: [\n kind,\n now,\n serializedPayload,\n now + TERMINAL_HISTORY_FINALIZATION_LEASE_MS,\n now,\n errorMessage?.slice(0, 2000) ?? null,\n id,\n kind,\n ],\n });\n const persisted = await getA2AContinuation(id);\n if (\n persisted?.status !== \"delivering\" ||\n persisted.terminalDeliveryKind !== kind ||\n persisted.terminalDeliveryConfirmedAt == null ||\n JSON.stringify(persisted.terminalHistoryPayload) !== serializedPayload\n ) {\n throw new Error(\"Terminal A2A delivery confirmation did not persist\");\n }\n return persisted;\n}\n\nexport async function finalizeA2ATerminalHistory(id: string): Promise<void> {\n await ensureTable();\n const continuation = await getA2AContinuation(id);\n if (\n continuation &&\n (continuation.status === \"completed\" || continuation.status === \"failed\") &&\n continuation.terminalDeliveryConfirmedAt != null &&\n continuation.terminalHistoryPayload == null\n ) {\n return;\n }\n if (\n !continuation?.terminalDeliveryKind ||\n continuation.terminalDeliveryConfirmedAt == null ||\n !continuation.terminalHistoryPayload\n ) {\n throw new Error(\"Terminal A2A history cannot finalize without a receipt\");\n }\n const now = Date.now();\n const status =\n continuation.terminalDeliveryKind === \"success\" ? \"completed\" : \"failed\";\n await getDbExec().execute({\n sql: `UPDATE integration_a2a_continuations\n SET status = ?, updated_at = ?, completed_at = ?, incoming_payload = ?,\n a2a_auth_token = NULL, progress_ref = NULL,\n verified_artifact_checkpoint = NULL, terminal_history_payload = NULL\n WHERE id = ? AND status IN ('pending', 'processing', 'delivering')\n AND terminal_delivery_confirmed_at IS NOT NULL`,\n args: [status, now, now, \"{}\", id],\n });\n const persisted = await getA2AContinuation(id);\n if (\n persisted?.status !== status ||\n persisted.terminalHistoryPayload != null\n ) {\n throw new Error(\"Terminal A2A history finalization did not persist\");\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 verified_artifact_checkpoint = NULL,\n terminal_delivery_kind = COALESCE(terminal_delivery_kind, 'success'),\n terminal_delivery_confirmed_at = COALESCE(terminal_delivery_confirmed_at, ?),\n terminal_history_payload = NULL\n WHERE id = ? AND status IN ('processing', 'delivering', 'completed')`,\n args: [\"completed\", now, 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 verified_artifact_checkpoint = NULL\n WHERE id = ? AND status <> 'completed'`,\n args: [\"failed\", now, errorMessage.slice(0, 2000), \"{}\", id],\n });\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slack.d.ts","sourceRoot":"","sources":["../../../src/integrations/adapters/slack.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"slack.d.ts","sourceRoot":"","sources":["../../../src/integrations/adapters/slack.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EACV,eAAe,EACf,eAAe,EAUhB,MAAM,aAAa,CAAC;AAsErB,MAAM,WAAW,mBAAmB;IAClC,8DAA8D;IAC9D,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,eAAe,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAC7E,kEAAkE;IAClE,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,eAAe,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACjE,oEAAoE;IACpE,oBAAoB,CAAC,EAAE,CAAC,QAAQ,EAAE,eAAe,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACxE;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,YAAY,CAC1B,OAAO,GAAE,mBAAwB,GAChC,eAAe,CAwnBjB;AAkBD,wBAAsB,+BAA+B,CACnD,QAAQ,EAAE,eAAe,GACxB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAS7B"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
1
2
|
import { createError, getHeader, readRawBody } from "h3";
|
|
2
3
|
import { resolveSecret } from "../../server/credential-provider.js";
|
|
3
4
|
import { getRequestContext } from "../../server/request-context.js";
|
|
@@ -26,6 +27,9 @@ const SLACK_IDENTITY_NEGATIVE_CACHE_TTL_MS = 30 * 1_000;
|
|
|
26
27
|
const SLACK_IDENTITY_CACHE_MAX_ENTRIES = 1_000;
|
|
27
28
|
const SLACK_TOKEN_IDENTITY_CACHE_TTL_MS = 10 * 60 * 1_000;
|
|
28
29
|
const SLACK_TOKEN_IDENTITY_NEGATIVE_CACHE_TTL_MS = 30 * 1_000;
|
|
30
|
+
const SLACK_DELIVERY_RECONCILIATION_PAGE_LIMIT = 200;
|
|
31
|
+
const SLACK_DELIVERY_RECONCILIATION_MAX_PAGES = 3;
|
|
32
|
+
const SLACK_DELIVERY_MARKER_PREFIX = "agent_native_terminal_";
|
|
29
33
|
const slackTokenIdentityCache = new Map();
|
|
30
34
|
const slackIdentityCache = new Map();
|
|
31
35
|
// Deduped system notices send at most once per key per TTL so senders are
|
|
@@ -361,6 +365,13 @@ export function slackAdapter(options = {}) {
|
|
|
361
365
|
}
|
|
362
366
|
const restChunks = chunks.slice(1);
|
|
363
367
|
const messageRefs = [];
|
|
368
|
+
const freshChunkIndexes = [
|
|
369
|
+
...(!placeholderRef ? [0] : []),
|
|
370
|
+
...restChunks.map((_, index) => index + 1),
|
|
371
|
+
];
|
|
372
|
+
const reconciledRefs = opts?.idempotencyKey && freshChunkIndexes.length > 0
|
|
373
|
+
? await reconcileSlackDeliveryChunks(token, channelId, threadTs, opts.idempotencyKey, freshChunkIndexes, opts.reconcileAfter, opts.signal)
|
|
374
|
+
: new Map();
|
|
364
375
|
const finalBlocks = blocks ??
|
|
365
376
|
buildResponseBlocks(firstChunk, {
|
|
366
377
|
threadDeepLinkUrl: message.platformContext
|
|
@@ -377,19 +388,24 @@ export function slackAdapter(options = {}) {
|
|
|
377
388
|
try {
|
|
378
389
|
if (placeholderRef) {
|
|
379
390
|
// Replace the "thinking…" placeholder in place.
|
|
380
|
-
const
|
|
391
|
+
const data = (await slackApiJson("https://slack.com/api/chat.update", {
|
|
381
392
|
method: "POST",
|
|
382
393
|
headers: {
|
|
383
394
|
Authorization: `Bearer ${token}`,
|
|
384
395
|
"Content-Type": "application/json",
|
|
385
396
|
},
|
|
386
397
|
body: JSON.stringify({ ...baseBody, ts: placeholderRef }),
|
|
387
|
-
|
|
388
|
-
|
|
398
|
+
signal: opts?.signal,
|
|
399
|
+
}));
|
|
389
400
|
if (!data.ok) {
|
|
390
401
|
console.error("[slack] chat.update error:", data.error);
|
|
402
|
+
if (opts?.strictTargetRef) {
|
|
403
|
+
throw new Error(data.error || "chat.update failed");
|
|
404
|
+
}
|
|
391
405
|
// Fall back to a fresh post so the user still sees a reply
|
|
392
|
-
const postedTs = await postFresh(token, channelId, threadTs,
|
|
406
|
+
const postedTs = await postFresh(token, channelId, threadTs, opts?.idempotencyKey
|
|
407
|
+
? withSlackDeliveryMarker(baseBody, opts.idempotencyKey, 0)
|
|
408
|
+
: baseBody, opts?.signal);
|
|
393
409
|
if (postedTs)
|
|
394
410
|
messageRefs.push(postedTs);
|
|
395
411
|
}
|
|
@@ -398,9 +414,17 @@ export function slackAdapter(options = {}) {
|
|
|
398
414
|
}
|
|
399
415
|
}
|
|
400
416
|
else {
|
|
401
|
-
const
|
|
402
|
-
if (
|
|
403
|
-
messageRefs.push(
|
|
417
|
+
const reconciledRef = reconciledRefs.get(0);
|
|
418
|
+
if (reconciledRef) {
|
|
419
|
+
messageRefs.push(reconciledRef);
|
|
420
|
+
}
|
|
421
|
+
else {
|
|
422
|
+
const postedTs = await postFresh(token, channelId, threadTs, opts?.idempotencyKey
|
|
423
|
+
? withSlackDeliveryMarker(baseBody, opts.idempotencyKey, 0)
|
|
424
|
+
: baseBody, opts?.signal);
|
|
425
|
+
if (postedTs)
|
|
426
|
+
messageRefs.push(postedTs);
|
|
427
|
+
}
|
|
404
428
|
}
|
|
405
429
|
// Clear the AI-assistant "is thinking…" status now that we've
|
|
406
430
|
// delivered the final answer. Empty status clears it.
|
|
@@ -408,14 +432,23 @@ export function slackAdapter(options = {}) {
|
|
|
408
432
|
setSlackAssistantStatus(token, channelId, threadTs, "");
|
|
409
433
|
}
|
|
410
434
|
// Overflow chunks (rare) — post as plain follow-ups in the same thread
|
|
411
|
-
for (const chunk of restChunks) {
|
|
412
|
-
const
|
|
435
|
+
for (const [index, chunk] of restChunks.entries()) {
|
|
436
|
+
const chunkIndex = index + 1;
|
|
437
|
+
const reconciledRef = reconciledRefs.get(chunkIndex);
|
|
438
|
+
if (reconciledRef) {
|
|
439
|
+
messageRefs.push(reconciledRef);
|
|
440
|
+
continue;
|
|
441
|
+
}
|
|
442
|
+
const overflowBody = {
|
|
413
443
|
channel: channelId,
|
|
414
444
|
text: chunk,
|
|
415
445
|
unfurl_links: false,
|
|
416
446
|
unfurl_media: false,
|
|
417
447
|
mrkdwn: true,
|
|
418
|
-
}
|
|
448
|
+
};
|
|
449
|
+
const postedTs = await postFresh(token, channelId, threadTs, opts?.idempotencyKey
|
|
450
|
+
? withSlackDeliveryMarker(overflowBody, opts.idempotencyKey, chunkIndex)
|
|
451
|
+
: overflowBody, opts?.signal);
|
|
419
452
|
if (postedTs)
|
|
420
453
|
messageRefs.push(postedTs);
|
|
421
454
|
}
|
|
@@ -497,15 +530,14 @@ export function slackAdapter(options = {}) {
|
|
|
497
530
|
if (target.threadRef)
|
|
498
531
|
body.thread_ts = target.threadRef;
|
|
499
532
|
try {
|
|
500
|
-
const
|
|
533
|
+
const data = (await slackApiJson("https://slack.com/api/chat.postMessage", {
|
|
501
534
|
method: "POST",
|
|
502
535
|
headers: {
|
|
503
536
|
Authorization: `Bearer ${token}`,
|
|
504
537
|
"Content-Type": "application/json",
|
|
505
538
|
},
|
|
506
539
|
body: JSON.stringify(body),
|
|
507
|
-
});
|
|
508
|
-
const data = (await res.json());
|
|
540
|
+
}));
|
|
509
541
|
if (!data.ok) {
|
|
510
542
|
throw new Error(data.error || "chat.postMessage failed");
|
|
511
543
|
}
|
|
@@ -838,7 +870,7 @@ function markdownToSlackMrkdwn(text) {
|
|
|
838
870
|
* Pure best-effort — failures never block the response.
|
|
839
871
|
*/
|
|
840
872
|
function setSlackAssistantStatus(token, channelId, threadTs, status) {
|
|
841
|
-
|
|
873
|
+
slackApiJson("https://slack.com/api/assistant.threads.setStatus", {
|
|
842
874
|
method: "POST",
|
|
843
875
|
headers: {
|
|
844
876
|
Authorization: `Bearer ${token}`,
|
|
@@ -882,7 +914,7 @@ function buildResponseBlocks(text, opts) {
|
|
|
882
914
|
* Post a fresh message to a thread. Used as the placeholder-fallback path
|
|
883
915
|
* (e.g. when chat.update fails) and for follow-up overflow chunks.
|
|
884
916
|
*/
|
|
885
|
-
async function postFresh(token, channelId, threadTs, body) {
|
|
917
|
+
async function postFresh(token, channelId, threadTs, body, signal) {
|
|
886
918
|
const hasBlocks = Array.isArray(body.blocks) && body.blocks.length > 0;
|
|
887
919
|
if (typeof body.text === "string" &&
|
|
888
920
|
body.text.trim().length === 0 &&
|
|
@@ -895,35 +927,128 @@ async function postFresh(token, channelId, threadTs, body) {
|
|
|
895
927
|
};
|
|
896
928
|
if (threadTs && !payload.thread_ts)
|
|
897
929
|
payload.thread_ts = threadTs;
|
|
898
|
-
const
|
|
930
|
+
const data = (await slackApiJson("https://slack.com/api/chat.postMessage", {
|
|
899
931
|
method: "POST",
|
|
900
932
|
headers: {
|
|
901
933
|
Authorization: `Bearer ${token}`,
|
|
902
934
|
"Content-Type": "application/json",
|
|
903
935
|
},
|
|
904
936
|
body: JSON.stringify(payload),
|
|
905
|
-
|
|
906
|
-
|
|
937
|
+
signal,
|
|
938
|
+
}));
|
|
907
939
|
if (!data.ok) {
|
|
908
940
|
console.error("[slack] chat.postMessage error:", data.error);
|
|
909
941
|
throw new Error(data.error || "chat.postMessage failed");
|
|
910
942
|
}
|
|
911
943
|
return data.ts;
|
|
912
944
|
}
|
|
913
|
-
|
|
945
|
+
function slackDeliveryMarker(key, chunkIndex) {
|
|
946
|
+
const digest = createHash("sha256")
|
|
947
|
+
.update(`${key}:${chunkIndex}`)
|
|
948
|
+
.digest("hex")
|
|
949
|
+
.slice(0, 32);
|
|
950
|
+
return `${SLACK_DELIVERY_MARKER_PREFIX}${digest}`;
|
|
951
|
+
}
|
|
952
|
+
function withSlackDeliveryMarker(body, key, chunkIndex) {
|
|
953
|
+
const marker = slackDeliveryMarker(key, chunkIndex);
|
|
954
|
+
const blocks = Array.isArray(body.blocks) ? body.blocks : [];
|
|
955
|
+
if (blocks.length > 0) {
|
|
956
|
+
const [first, ...rest] = blocks;
|
|
957
|
+
if (first && typeof first === "object" && !Array.isArray(first)) {
|
|
958
|
+
return {
|
|
959
|
+
...body,
|
|
960
|
+
blocks: [
|
|
961
|
+
{ ...first, block_id: marker },
|
|
962
|
+
...rest,
|
|
963
|
+
],
|
|
964
|
+
};
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
return {
|
|
968
|
+
...body,
|
|
969
|
+
blocks: [
|
|
970
|
+
{
|
|
971
|
+
type: "section",
|
|
972
|
+
block_id: marker,
|
|
973
|
+
text: { type: "mrkdwn", text: String(body.text ?? "") },
|
|
974
|
+
},
|
|
975
|
+
],
|
|
976
|
+
};
|
|
977
|
+
}
|
|
978
|
+
async function reconcileSlackDeliveryChunks(token, channelId, threadTs, key, chunkIndexes, reconcileAfter, signal) {
|
|
979
|
+
if (!threadTs) {
|
|
980
|
+
throw new Error("Cannot reconcile an idempotent Slack delivery without a thread timestamp");
|
|
981
|
+
}
|
|
982
|
+
const refs = new Map();
|
|
983
|
+
const expectedMarkers = new Map(chunkIndexes.map((chunkIndex) => [
|
|
984
|
+
slackDeliveryMarker(key, chunkIndex),
|
|
985
|
+
chunkIndex,
|
|
986
|
+
]));
|
|
987
|
+
let cursor = "";
|
|
988
|
+
for (let page = 0; page < SLACK_DELIVERY_RECONCILIATION_MAX_PAGES; page += 1) {
|
|
989
|
+
const url = new URL("https://slack.com/api/conversations.replies");
|
|
990
|
+
url.searchParams.set("channel", channelId);
|
|
991
|
+
url.searchParams.set("ts", threadTs);
|
|
992
|
+
url.searchParams.set("limit", String(SLACK_DELIVERY_RECONCILIATION_PAGE_LIMIT));
|
|
993
|
+
if (cursor)
|
|
994
|
+
url.searchParams.set("cursor", cursor);
|
|
995
|
+
if (typeof reconcileAfter === "number" && reconcileAfter > 0) {
|
|
996
|
+
url.searchParams.set("oldest", String(Math.floor(reconcileAfter / 1000)));
|
|
997
|
+
url.searchParams.set("inclusive", "true");
|
|
998
|
+
}
|
|
999
|
+
const body = (await slackApiJson(url.toString(), {
|
|
1000
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
1001
|
+
signal,
|
|
1002
|
+
}));
|
|
1003
|
+
if (!body.ok) {
|
|
1004
|
+
throw new Error(body.error || "conversations.replies failed");
|
|
1005
|
+
}
|
|
1006
|
+
for (const message of body.messages ?? []) {
|
|
1007
|
+
if (typeof message.ts !== "string")
|
|
1008
|
+
continue;
|
|
1009
|
+
for (const block of message.blocks ?? []) {
|
|
1010
|
+
if (typeof block.block_id !== "string")
|
|
1011
|
+
continue;
|
|
1012
|
+
const chunkIndex = expectedMarkers.get(block.block_id);
|
|
1013
|
+
if (chunkIndex !== undefined)
|
|
1014
|
+
refs.set(chunkIndex, message.ts);
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
if (refs.size === expectedMarkers.size)
|
|
1018
|
+
return refs;
|
|
1019
|
+
cursor = body.response_metadata?.next_cursor?.trim() ?? "";
|
|
1020
|
+
if (!cursor)
|
|
1021
|
+
return refs;
|
|
1022
|
+
}
|
|
1023
|
+
throw new Error("Slack delivery reconciliation exceeded the bounded thread scan");
|
|
1024
|
+
}
|
|
1025
|
+
async function slackApiJson(url, init, timeoutMs = SLACK_API_TIMEOUT_MS) {
|
|
914
1026
|
const controller = typeof AbortController !== "undefined" ? new AbortController() : undefined;
|
|
1027
|
+
const externalSignal = init.signal;
|
|
1028
|
+
const abortFromExternal = () => controller?.abort(externalSignal?.reason);
|
|
1029
|
+
if (controller && externalSignal) {
|
|
1030
|
+
if (externalSignal.aborted)
|
|
1031
|
+
abortFromExternal();
|
|
1032
|
+
else {
|
|
1033
|
+
externalSignal.addEventListener("abort", abortFromExternal, {
|
|
1034
|
+
once: true,
|
|
1035
|
+
});
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
915
1038
|
const timer = controller
|
|
916
1039
|
? setTimeout(() => controller.abort(), timeoutMs)
|
|
917
1040
|
: undefined;
|
|
918
1041
|
try {
|
|
919
|
-
|
|
1042
|
+
const response = await fetch(url, {
|
|
920
1043
|
...init,
|
|
921
1044
|
signal: controller?.signal ?? init.signal,
|
|
922
1045
|
});
|
|
1046
|
+
return (await response.json());
|
|
923
1047
|
}
|
|
924
1048
|
finally {
|
|
925
1049
|
if (timer)
|
|
926
1050
|
clearTimeout(timer);
|
|
1051
|
+
externalSignal?.removeEventListener("abort", abortFromExternal);
|
|
927
1052
|
}
|
|
928
1053
|
}
|
|
929
1054
|
async function resolveSlackThreadPermalink(channelId, threadTs, resolvedToken) {
|
|
@@ -937,8 +1062,7 @@ async function resolveSlackThreadPermalink(channelId, threadTs, resolvedToken) {
|
|
|
937
1062
|
const url = new URL("https://slack.com/api/chat.getPermalink");
|
|
938
1063
|
url.searchParams.set("channel", channelId);
|
|
939
1064
|
url.searchParams.set("message_ts", threadTs);
|
|
940
|
-
const
|
|
941
|
-
const data = (await res.json());
|
|
1065
|
+
const data = (await slackApiJson(url.toString(), { headers: { Authorization: `Bearer ${token}` } }, SLACK_PERMALINK_TIMEOUT_MS));
|
|
942
1066
|
if (!data.ok || typeof data.permalink !== "string")
|
|
943
1067
|
return undefined;
|
|
944
1068
|
const permalink = new URL(data.permalink);
|
|
@@ -1013,8 +1137,7 @@ async function slackJson(token, method, params, timeoutMs = 2_000) {
|
|
|
1013
1137
|
for (const [key, value] of Object.entries(params)) {
|
|
1014
1138
|
url.searchParams.set(key, value);
|
|
1015
1139
|
}
|
|
1016
|
-
const
|
|
1017
|
-
const body = (await response.json());
|
|
1140
|
+
const body = await slackApiJson(url.toString(), { headers: { Authorization: `Bearer ${token}` } }, timeoutMs);
|
|
1018
1141
|
return body.ok ? body : null;
|
|
1019
1142
|
}
|
|
1020
1143
|
catch {
|
|
@@ -1307,16 +1430,16 @@ function delegatedProgressDetails(agent, state, elapsedSeconds, detail) {
|
|
|
1307
1430
|
}
|
|
1308
1431
|
return update ? `${progress} — ${update}` : progress;
|
|
1309
1432
|
}
|
|
1310
|
-
async function postSlackJson(token, method, body) {
|
|
1311
|
-
const
|
|
1433
|
+
async function postSlackJson(token, method, body, signal) {
|
|
1434
|
+
const data = await slackApiJson(`https://slack.com/api/${method}`, {
|
|
1312
1435
|
method: "POST",
|
|
1313
1436
|
headers: {
|
|
1314
1437
|
Authorization: `Bearer ${token}`,
|
|
1315
1438
|
"Content-Type": "application/json",
|
|
1316
1439
|
},
|
|
1317
1440
|
body: JSON.stringify(body),
|
|
1441
|
+
signal,
|
|
1318
1442
|
});
|
|
1319
|
-
const data = (await response.json());
|
|
1320
1443
|
if (!data.ok)
|
|
1321
1444
|
throw new Error(data.error || `${method} failed`);
|
|
1322
1445
|
return data;
|
|
@@ -1438,6 +1561,7 @@ function createSlackRunProgress(token, incoming, channel, threadTs, streamTs) {
|
|
|
1438
1561
|
const taskId = (prefix, explicit) => `${prefix}:${explicit || ++sequence}`.slice(0, 240);
|
|
1439
1562
|
return {
|
|
1440
1563
|
ref: { kind: "slack-stream", streamTs },
|
|
1564
|
+
responseTargetRef: streamTs,
|
|
1441
1565
|
async onEvent(event) {
|
|
1442
1566
|
if (!cancelControl) {
|
|
1443
1567
|
const context = getIntegrationRequestContext();
|
|
@@ -1589,7 +1713,7 @@ function createSlackRunProgress(token, incoming, channel, threadTs, streamTs) {
|
|
|
1589
1713
|
});
|
|
1590
1714
|
}
|
|
1591
1715
|
},
|
|
1592
|
-
async complete(message) {
|
|
1716
|
+
async complete(message, opts) {
|
|
1593
1717
|
if (pendingTimer)
|
|
1594
1718
|
clearTimeout(pendingTimer);
|
|
1595
1719
|
const finalChunks = [...tasks.entries()].map(([id, task]) => ({
|
|
@@ -1633,18 +1757,18 @@ function createSlackRunProgress(token, incoming, channel, threadTs, streamTs) {
|
|
|
1633
1757
|
...(messageBlocks.length || controlBlocks.length
|
|
1634
1758
|
? { blocks: [...messageBlocks, ...controlBlocks].slice(0, 50) }
|
|
1635
1759
|
: {}),
|
|
1636
|
-
});
|
|
1760
|
+
}, opts?.signal);
|
|
1637
1761
|
setSlackAssistantStatus(token, channel, threadTs, "");
|
|
1638
1762
|
return { status: "delivered", messageRefs: [streamTs] };
|
|
1639
1763
|
},
|
|
1640
|
-
async fail(message) {
|
|
1764
|
+
async fail(message, opts) {
|
|
1641
1765
|
if (pendingTimer)
|
|
1642
1766
|
clearTimeout(pendingTimer);
|
|
1643
1767
|
await postSlackJson(token, "chat.stopStream", {
|
|
1644
1768
|
channel,
|
|
1645
1769
|
ts: streamTs,
|
|
1646
1770
|
markdown_text: message.slice(0, SLACK_MAX_LENGTH),
|
|
1647
|
-
}).catch(() => { });
|
|
1771
|
+
}, opts?.signal).catch(() => { });
|
|
1648
1772
|
setSlackAssistantStatus(token, channel, threadTs, "");
|
|
1649
1773
|
},
|
|
1650
1774
|
};
|