@inkeep/agents-core 0.58.13 → 0.58.15

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.
Files changed (93) hide show
  1. package/dist/auth/auth-schema.d.ts +107 -107
  2. package/dist/auth/auth-validation-schemas.d.ts +152 -152
  3. package/dist/auth/auth.d.ts +9 -9
  4. package/dist/auth/auth.js +17 -45
  5. package/dist/auth/permissions.d.ts +9 -9
  6. package/dist/data-access/index.d.ts +6 -1
  7. package/dist/data-access/index.js +6 -1
  8. package/dist/data-access/manage/agentFull.js +28 -12
  9. package/dist/data-access/manage/agents.d.ts +40 -39
  10. package/dist/data-access/manage/agents.js +33 -33
  11. package/dist/data-access/manage/artifactComponents.d.ts +8 -8
  12. package/dist/data-access/manage/artifactComponents.js +14 -13
  13. package/dist/data-access/manage/audit-queries.d.ts +29 -0
  14. package/dist/data-access/manage/audit-queries.js +30 -0
  15. package/dist/data-access/manage/contextConfigs.d.ts +4 -4
  16. package/dist/data-access/manage/contextConfigs.js +7 -6
  17. package/dist/data-access/manage/credentialReferences.js +12 -11
  18. package/dist/data-access/manage/dataComponents.d.ts +4 -4
  19. package/dist/data-access/manage/dataComponents.js +13 -11
  20. package/dist/data-access/manage/evalConfig.js +42 -41
  21. package/dist/data-access/manage/externalAgents.js +8 -7
  22. package/dist/data-access/manage/functionTools.d.ts +11 -15
  23. package/dist/data-access/manage/functionTools.js +27 -65
  24. package/dist/data-access/manage/functions.js +7 -10
  25. package/dist/data-access/manage/projects.js +37 -36
  26. package/dist/data-access/manage/scheduledTriggers.js +10 -6
  27. package/dist/data-access/manage/scheduledWorkflows.js +3 -2
  28. package/dist/data-access/manage/scope-helpers.d.ts +2 -1
  29. package/dist/data-access/manage/scope-helpers.js +2 -1
  30. package/dist/data-access/manage/skills.d.ts +11 -11
  31. package/dist/data-access/manage/skills.js +14 -9
  32. package/dist/data-access/manage/subAgentExternalAgentRelations.d.ts +12 -12
  33. package/dist/data-access/manage/subAgentRelations.d.ts +18 -18
  34. package/dist/data-access/manage/subAgentRelations.js +28 -26
  35. package/dist/data-access/manage/subAgentTeamAgentRelations.d.ts +12 -12
  36. package/dist/data-access/manage/subAgentTeamAgentRelations.js +16 -16
  37. package/dist/data-access/manage/subAgents.d.ts +21 -21
  38. package/dist/data-access/manage/subAgents.js +8 -7
  39. package/dist/data-access/manage/tools.d.ts +15 -15
  40. package/dist/data-access/manage/tools.js +8 -6
  41. package/dist/data-access/manage/triggers.d.ts +2 -2
  42. package/dist/data-access/manage/triggers.js +12 -8
  43. package/dist/data-access/runtime/apiKeys.d.ts +16 -16
  44. package/dist/data-access/runtime/apiKeys.js +16 -12
  45. package/dist/data-access/runtime/apps.d.ts +6 -6
  46. package/dist/data-access/runtime/apps.js +8 -7
  47. package/dist/data-access/runtime/audit-queries.d.ts +41 -0
  48. package/dist/data-access/runtime/audit-queries.js +37 -0
  49. package/dist/data-access/runtime/auth.d.ts +18 -0
  50. package/dist/data-access/runtime/auth.js +35 -0
  51. package/dist/data-access/runtime/cascade-delete.js +29 -24
  52. package/dist/data-access/runtime/contextCache.d.ts +1 -0
  53. package/dist/data-access/runtime/contextCache.js +9 -8
  54. package/dist/data-access/runtime/conversations.d.ts +16 -16
  55. package/dist/data-access/runtime/conversations.js +8 -12
  56. package/dist/data-access/runtime/evalRuns.js +23 -22
  57. package/dist/data-access/runtime/github-work-app-installations.js +32 -21
  58. package/dist/data-access/runtime/ledgerArtifacts.js +9 -24
  59. package/dist/data-access/runtime/messages.d.ts +21 -21
  60. package/dist/data-access/runtime/messages.js +9 -8
  61. package/dist/data-access/runtime/projects.js +6 -5
  62. package/dist/data-access/runtime/scheduledTriggerInvocations.d.ts +3 -3
  63. package/dist/data-access/runtime/scheduledTriggerInvocations.js +16 -26
  64. package/dist/data-access/runtime/slack-work-app-mcp.js +6 -5
  65. package/dist/data-access/runtime/tasks.d.ts +9 -5
  66. package/dist/data-access/runtime/tasks.js +4 -5
  67. package/dist/data-access/runtime/triggerInvocations.js +4 -8
  68. package/dist/data-access/runtime/workAppSlack.js +21 -14
  69. package/dist/data-reconciliation/audit.d.ts +6 -0
  70. package/dist/data-reconciliation/audit.js +37 -0
  71. package/dist/data-reconciliation/index.d.ts +4 -0
  72. package/dist/data-reconciliation/index.js +5 -0
  73. package/dist/data-reconciliation/reconcile.d.ts +6 -0
  74. package/dist/data-reconciliation/reconcile.js +58 -0
  75. package/dist/data-reconciliation/types.d.ts +116 -0
  76. package/dist/data-reconciliation/types.js +7 -0
  77. package/dist/db/manage/manage-schema.d.ts +453 -453
  78. package/dist/db/runtime/runtime-schema.d.ts +326 -326
  79. package/dist/index.d.ts +12 -2
  80. package/dist/index.js +12 -1
  81. package/dist/retry/index.d.ts +3 -0
  82. package/dist/retry/index.js +4 -0
  83. package/dist/retry/retryable-errors.d.ts +10 -0
  84. package/dist/retry/retryable-errors.js +72 -0
  85. package/dist/retry/withRetry.d.ts +15 -0
  86. package/dist/retry/withRetry.js +37 -0
  87. package/dist/setup/setup.d.ts +1 -0
  88. package/dist/setup/setup.js +25 -8
  89. package/dist/utils/error.d.ts +51 -51
  90. package/dist/validation/drizzle-schema-helpers.d.ts +3 -3
  91. package/dist/validation/schemas.d.ts +1987 -1990
  92. package/dist/validation/schemas.js +5 -1
  93. package/package.json +1 -1
@@ -1,4 +1,5 @@
1
1
  import { workAppSlackChannelAgentConfigs, workAppSlackUserMappings, workAppSlackWorkspaces } from "../../db/runtime/runtime-schema.js";
2
+ import { projectScopedWhere, tenantScopedWhere } from "../manage/scope-helpers.js";
2
3
  import { and, eq } from "drizzle-orm";
3
4
  import { existsSync, readFileSync, writeFileSync } from "node:fs";
4
5
  import { dirname, join } from "node:path";
@@ -18,7 +19,7 @@ const createWorkAppSlackWorkspace = (db) => async (data) => {
18
19
  return result;
19
20
  };
20
21
  const findWorkAppSlackWorkspaceByTeamId = (db) => async (tenantId, slackTeamId) => {
21
- return (await db.select().from(workAppSlackWorkspaces).where(and(eq(workAppSlackWorkspaces.tenantId, tenantId), eq(workAppSlackWorkspaces.slackTeamId, slackTeamId))).limit(1))[0] || null;
22
+ return (await db.select().from(workAppSlackWorkspaces).where(and(tenantScopedWhere(workAppSlackWorkspaces, { tenantId }), eq(workAppSlackWorkspaces.slackTeamId, slackTeamId))).limit(1))[0] || null;
22
23
  };
23
24
  /**
24
25
  * Find a workspace by Slack team ID only (without tenant filter).
@@ -39,7 +40,7 @@ const findWorkAppSlackWorkspaceByNangoConnectionId = (db) => async (nangoConnect
39
40
  return (await db.select().from(workAppSlackWorkspaces).where(eq(workAppSlackWorkspaces.nangoConnectionId, nangoConnectionId)))[0] || null;
40
41
  };
41
42
  const listWorkAppSlackWorkspacesByTenant = (db) => async (tenantId) => {
42
- return db.select().from(workAppSlackWorkspaces).where(eq(workAppSlackWorkspaces.tenantId, tenantId));
43
+ return db.select().from(workAppSlackWorkspaces).where(tenantScopedWhere(workAppSlackWorkspaces, { tenantId }));
43
44
  };
44
45
  const updateWorkAppSlackWorkspace = (db) => async (id, data) => {
45
46
  const [result] = await db.update(workAppSlackWorkspaces).set({
@@ -55,7 +56,7 @@ const deleteWorkAppSlackWorkspaceByNangoConnectionId = (db) => async (nangoConne
55
56
  return (await db.delete(workAppSlackWorkspaces).where(eq(workAppSlackWorkspaces.nangoConnectionId, nangoConnectionId)).returning()).length > 0;
56
57
  };
57
58
  const findWorkAppSlackUserMapping = (db) => async (tenantId, slackUserId, slackTeamId, clientId = DEFAULT_CLIENT_ID) => {
58
- return (await db.select().from(workAppSlackUserMappings).where(and(eq(workAppSlackUserMappings.tenantId, tenantId), eq(workAppSlackUserMappings.clientId, clientId), eq(workAppSlackUserMappings.slackUserId, slackUserId), eq(workAppSlackUserMappings.slackTeamId, slackTeamId))).limit(1))[0] || null;
59
+ return (await db.select().from(workAppSlackUserMappings).where(and(tenantScopedWhere(workAppSlackUserMappings, { tenantId }), eq(workAppSlackUserMappings.clientId, clientId), eq(workAppSlackUserMappings.slackUserId, slackUserId), eq(workAppSlackUserMappings.slackTeamId, slackTeamId))).limit(1))[0] || null;
59
60
  };
60
61
  const findWorkAppSlackUserMappingByInkeepUserId = (db) => async (inkeepUserId) => {
61
62
  return db.select().from(workAppSlackUserMappings).where(eq(workAppSlackUserMappings.inkeepUserId, inkeepUserId));
@@ -68,7 +69,7 @@ const findWorkAppSlackUserMappingBySlackUser = (db) => async (slackUserId, slack
68
69
  return (await db.select().from(workAppSlackUserMappings).where(and(eq(workAppSlackUserMappings.clientId, clientId), eq(workAppSlackUserMappings.slackUserId, slackUserId), eq(workAppSlackUserMappings.slackTeamId, slackTeamId))).limit(1))[0] || null;
69
70
  };
70
71
  const listWorkAppSlackUserMappingsByTeam = (db) => async (tenantId, slackTeamId) => {
71
- return db.select().from(workAppSlackUserMappings).where(and(eq(workAppSlackUserMappings.tenantId, tenantId), eq(workAppSlackUserMappings.slackTeamId, slackTeamId)));
72
+ return db.select().from(workAppSlackUserMappings).where(and(tenantScopedWhere(workAppSlackUserMappings, { tenantId }), eq(workAppSlackUserMappings.slackTeamId, slackTeamId)));
72
73
  };
73
74
  const createWorkAppSlackUserMapping = (db) => async (data) => {
74
75
  const id = `wsum_${nanoid(21)}`;
@@ -84,10 +85,10 @@ const createWorkAppSlackUserMapping = (db) => async (data) => {
84
85
  return result;
85
86
  };
86
87
  const deleteWorkAppSlackUserMapping = (db) => async (tenantId, slackUserId, slackTeamId, clientId = DEFAULT_CLIENT_ID) => {
87
- return (await db.delete(workAppSlackUserMappings).where(and(eq(workAppSlackUserMappings.tenantId, tenantId), eq(workAppSlackUserMappings.clientId, clientId), eq(workAppSlackUserMappings.slackUserId, slackUserId), eq(workAppSlackUserMappings.slackTeamId, slackTeamId))).returning()).length > 0;
88
+ return (await db.delete(workAppSlackUserMappings).where(and(tenantScopedWhere(workAppSlackUserMappings, { tenantId }), eq(workAppSlackUserMappings.clientId, clientId), eq(workAppSlackUserMappings.slackUserId, slackUserId), eq(workAppSlackUserMappings.slackTeamId, slackTeamId))).returning()).length > 0;
88
89
  };
89
90
  const deleteAllWorkAppSlackUserMappingsByTeam = (db) => async (tenantId, slackTeamId, clientId = DEFAULT_CLIENT_ID) => {
90
- return (await db.delete(workAppSlackUserMappings).where(and(eq(workAppSlackUserMappings.tenantId, tenantId), eq(workAppSlackUserMappings.clientId, clientId), eq(workAppSlackUserMappings.slackTeamId, slackTeamId))).returning()).length;
91
+ return (await db.delete(workAppSlackUserMappings).where(and(tenantScopedWhere(workAppSlackUserMappings, { tenantId }), eq(workAppSlackUserMappings.clientId, clientId), eq(workAppSlackUserMappings.slackTeamId, slackTeamId))).returning()).length;
91
92
  };
92
93
  const createWorkAppSlackChannelAgentConfig = (db) => async (data) => {
93
94
  const id = `wscac_${nanoid(21)}`;
@@ -101,10 +102,10 @@ const createWorkAppSlackChannelAgentConfig = (db) => async (data) => {
101
102
  return result;
102
103
  };
103
104
  const findWorkAppSlackChannelAgentConfig = (db) => async (tenantId, slackTeamId, slackChannelId) => {
104
- return (await db.select().from(workAppSlackChannelAgentConfigs).where(and(eq(workAppSlackChannelAgentConfigs.tenantId, tenantId), eq(workAppSlackChannelAgentConfigs.slackTeamId, slackTeamId), eq(workAppSlackChannelAgentConfigs.slackChannelId, slackChannelId))).limit(1))[0] || null;
105
+ return (await db.select().from(workAppSlackChannelAgentConfigs).where(and(tenantScopedWhere(workAppSlackChannelAgentConfigs, { tenantId }), eq(workAppSlackChannelAgentConfigs.slackTeamId, slackTeamId), eq(workAppSlackChannelAgentConfigs.slackChannelId, slackChannelId))).limit(1))[0] || null;
105
106
  };
106
107
  const listWorkAppSlackChannelAgentConfigsByTeam = (db) => async (tenantId, slackTeamId) => {
107
- return db.select().from(workAppSlackChannelAgentConfigs).where(and(eq(workAppSlackChannelAgentConfigs.tenantId, tenantId), eq(workAppSlackChannelAgentConfigs.slackTeamId, slackTeamId)));
108
+ return db.select().from(workAppSlackChannelAgentConfigs).where(and(tenantScopedWhere(workAppSlackChannelAgentConfigs, { tenantId }), eq(workAppSlackChannelAgentConfigs.slackTeamId, slackTeamId)));
108
109
  };
109
110
  /**
110
111
  * Atomic upsert using onConflictDoUpdate to avoid TOCTOU race conditions.
@@ -138,16 +139,22 @@ const upsertWorkAppSlackChannelAgentConfig = (db) => async (data) => {
138
139
  return result;
139
140
  };
140
141
  const deleteWorkAppSlackChannelAgentConfig = (db) => async (tenantId, slackTeamId, slackChannelId) => {
141
- return (await db.delete(workAppSlackChannelAgentConfigs).where(and(eq(workAppSlackChannelAgentConfigs.tenantId, tenantId), eq(workAppSlackChannelAgentConfigs.slackTeamId, slackTeamId), eq(workAppSlackChannelAgentConfigs.slackChannelId, slackChannelId))).returning()).length > 0;
142
+ return (await db.delete(workAppSlackChannelAgentConfigs).where(and(tenantScopedWhere(workAppSlackChannelAgentConfigs, { tenantId }), eq(workAppSlackChannelAgentConfigs.slackTeamId, slackTeamId), eq(workAppSlackChannelAgentConfigs.slackChannelId, slackChannelId))).returning()).length > 0;
142
143
  };
143
144
  const deleteAllWorkAppSlackChannelAgentConfigsByTeam = (db) => async (tenantId, slackTeamId) => {
144
- return (await db.delete(workAppSlackChannelAgentConfigs).where(and(eq(workAppSlackChannelAgentConfigs.tenantId, tenantId), eq(workAppSlackChannelAgentConfigs.slackTeamId, slackTeamId))).returning()).length;
145
+ return (await db.delete(workAppSlackChannelAgentConfigs).where(and(tenantScopedWhere(workAppSlackChannelAgentConfigs, { tenantId }), eq(workAppSlackChannelAgentConfigs.slackTeamId, slackTeamId))).returning()).length;
145
146
  };
146
147
  const deleteWorkAppSlackChannelAgentConfigsByAgent = (db) => async (tenantId, projectId, agentId) => {
147
- return (await db.delete(workAppSlackChannelAgentConfigs).where(and(eq(workAppSlackChannelAgentConfigs.tenantId, tenantId), eq(workAppSlackChannelAgentConfigs.projectId, projectId), eq(workAppSlackChannelAgentConfigs.agentId, agentId))).returning()).length;
148
+ return (await db.delete(workAppSlackChannelAgentConfigs).where(and(projectScopedWhere(workAppSlackChannelAgentConfigs, {
149
+ tenantId,
150
+ projectId
151
+ }), eq(workAppSlackChannelAgentConfigs.agentId, agentId))).returning()).length;
148
152
  };
149
153
  const deleteWorkAppSlackChannelAgentConfigsByProject = (db) => async (tenantId, projectId) => {
150
- return (await db.delete(workAppSlackChannelAgentConfigs).where(and(eq(workAppSlackChannelAgentConfigs.tenantId, tenantId), eq(workAppSlackChannelAgentConfigs.projectId, projectId))).returning()).length;
154
+ return (await db.delete(workAppSlackChannelAgentConfigs).where(projectScopedWhere(workAppSlackChannelAgentConfigs, {
155
+ tenantId,
156
+ projectId
157
+ })).returning()).length;
151
158
  };
152
159
  const clearWorkspaceDefaultsByAgent = (db) => async (tenantId, projectId, agentId) => {
153
160
  return (await db.update(workAppSlackWorkspaces).set({
@@ -155,7 +162,7 @@ const clearWorkspaceDefaultsByAgent = (db) => async (tenantId, projectId, agentI
155
162
  defaultProjectId: null,
156
163
  defaultGrantAccessToMembers: null,
157
164
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
158
- }).where(and(eq(workAppSlackWorkspaces.tenantId, tenantId), eq(workAppSlackWorkspaces.defaultProjectId, projectId), eq(workAppSlackWorkspaces.defaultAgentId, agentId))).returning()).length;
165
+ }).where(and(tenantScopedWhere(workAppSlackWorkspaces, { tenantId }), eq(workAppSlackWorkspaces.defaultProjectId, projectId), eq(workAppSlackWorkspaces.defaultAgentId, agentId))).returning()).length;
159
166
  };
160
167
  const clearWorkspaceDefaultsByProject = (db) => async (tenantId, projectId) => {
161
168
  return (await db.update(workAppSlackWorkspaces).set({
@@ -163,7 +170,7 @@ const clearWorkspaceDefaultsByProject = (db) => async (tenantId, projectId) => {
163
170
  defaultProjectId: null,
164
171
  defaultGrantAccessToMembers: null,
165
172
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
166
- }).where(and(eq(workAppSlackWorkspaces.tenantId, tenantId), eq(workAppSlackWorkspaces.defaultProjectId, projectId))).returning()).length;
173
+ }).where(and(tenantScopedWhere(workAppSlackWorkspaces, { tenantId }), eq(workAppSlackWorkspaces.defaultProjectId, projectId))).returning()).length;
167
174
  };
168
175
  const DEV_CONFIG_FILENAME = ".slack-dev.json";
169
176
  function findSlackDevConfigPath() {
@@ -0,0 +1,6 @@
1
+ import { AuditContext, AuditReport, EntityEffectRegistry } from "./types.js";
2
+
3
+ //#region src/data-reconciliation/audit.d.ts
4
+ declare function audit(registry: EntityEffectRegistry, ctx: AuditContext): Promise<AuditReport>;
5
+ //#endregion
6
+ export { audit };
@@ -0,0 +1,37 @@
1
+ //#region src/data-reconciliation/audit.ts
2
+ async function audit(registry, ctx) {
3
+ const report = {
4
+ entries: [],
5
+ checkedEntities: [],
6
+ skippedEntities: []
7
+ };
8
+ for (const [table, handlers] of Object.entries(registry)) {
9
+ if (!handlers?.check) {
10
+ report.skippedEntities.push(table);
11
+ continue;
12
+ }
13
+ report.checkedEntities.push(table);
14
+ try {
15
+ const result = await handlers.check(ctx);
16
+ report.entries.push({
17
+ table,
18
+ result
19
+ });
20
+ } catch (error) {
21
+ const errorMessage = error instanceof Error ? error.message : String(error);
22
+ ctx.logger.warn({
23
+ table,
24
+ error: errorMessage
25
+ }, `Audit check failed for entity: ${table}`);
26
+ report.entries.push({
27
+ table,
28
+ result: null,
29
+ error: error instanceof Error ? error.message : String(error)
30
+ });
31
+ }
32
+ }
33
+ return report;
34
+ }
35
+
36
+ //#endregion
37
+ export { audit };
@@ -0,0 +1,4 @@
1
+ import { AppliedEffect, AuditContext, AuditReport, EntityAuditEntry, EntityDiff, EntityEffectHandlers, EntityEffectRegistry, EntityOperation, EntityRowByTable, FailedEffect, OrphanedRuntimeRowsResult, ReconcileContext, ReconcileResult, ScheduledTriggerAuditResult, SkippedDiff, defineHandlers } from "./types.js";
2
+ import { audit } from "./audit.js";
3
+ import { reconcile } from "./reconcile.js";
4
+ export { AppliedEffect, AuditContext, AuditReport, EntityAuditEntry, EntityDiff, EntityEffectHandlers, EntityEffectRegistry, EntityOperation, EntityRowByTable, FailedEffect, OrphanedRuntimeRowsResult, ReconcileContext, ReconcileResult, ScheduledTriggerAuditResult, SkippedDiff, audit, defineHandlers, reconcile };
@@ -0,0 +1,5 @@
1
+ import { audit } from "./audit.js";
2
+ import { reconcile } from "./reconcile.js";
3
+ import { defineHandlers } from "./types.js";
4
+
5
+ export { audit, defineHandlers, reconcile };
@@ -0,0 +1,6 @@
1
+ import { EntityDiff, EntityEffectRegistry, ReconcileContext, ReconcileResult } from "./types.js";
2
+
3
+ //#region src/data-reconciliation/reconcile.d.ts
4
+ declare function reconcile(registry: EntityEffectRegistry, diffs: EntityDiff[], ctx: ReconcileContext): Promise<ReconcileResult>;
5
+ //#endregion
6
+ export { reconcile };
@@ -0,0 +1,58 @@
1
+ //#region src/data-reconciliation/reconcile.ts
2
+ async function reconcile(registry, diffs, ctx) {
3
+ const result = {
4
+ applied: [],
5
+ skipped: [],
6
+ failed: []
7
+ };
8
+ const operations = diffs.map(async (diff) => {
9
+ const handlers = registry[diff.table];
10
+ if (!handlers) {
11
+ result.skipped.push({
12
+ table: diff.table,
13
+ operation: diff.operation,
14
+ primaryKey: diff.primaryKey,
15
+ reason: "no registry entry"
16
+ });
17
+ return;
18
+ }
19
+ try {
20
+ if (diff.operation === "insert" && handlers.onCreated && diff.after) await handlers.onCreated(diff.after, ctx);
21
+ else if (diff.operation === "update" && handlers.onUpdated && diff.before && diff.after) await handlers.onUpdated(diff.before, diff.after, ctx);
22
+ else if (diff.operation === "delete" && handlers.onDeleted && diff.before) await handlers.onDeleted(diff.before, ctx);
23
+ else {
24
+ result.skipped.push({
25
+ table: diff.table,
26
+ operation: diff.operation,
27
+ primaryKey: diff.primaryKey,
28
+ reason: `no handler for ${diff.operation}`
29
+ });
30
+ return;
31
+ }
32
+ result.applied.push({
33
+ table: diff.table,
34
+ operation: diff.operation,
35
+ primaryKey: diff.primaryKey
36
+ });
37
+ } catch (error) {
38
+ const errorMessage = error instanceof Error ? error.message : String(error);
39
+ ctx.logger.error({
40
+ table: diff.table,
41
+ operation: diff.operation,
42
+ primaryKey: diff.primaryKey,
43
+ error: errorMessage
44
+ }, `Reconcile effect failed for ${diff.table}.${diff.operation}`);
45
+ result.failed.push({
46
+ table: diff.table,
47
+ operation: diff.operation,
48
+ primaryKey: diff.primaryKey,
49
+ error: errorMessage
50
+ });
51
+ }
52
+ });
53
+ await Promise.allSettled(operations);
54
+ return result;
55
+ }
56
+
57
+ //#endregion
58
+ export { reconcile };
@@ -0,0 +1,116 @@
1
+ import { PinoLogger } from "../utils/logger.js";
2
+ import { AgentsManageDatabaseClient } from "../db/manage/manage-client.js";
3
+ import { AgentsRunDatabaseClient } from "../db/runtime/runtime-client.js";
4
+ import { ScheduledTrigger } from "../validation/schemas.js";
5
+ import { AgentSelect, ContextConfigSelect, SubAgentSelect, ToolSelect } from "../types/entities.js";
6
+
7
+ //#region src/data-reconciliation/types.d.ts
8
+ type EntityRowByTable = {
9
+ scheduled_triggers: ScheduledTrigger;
10
+ tools: ToolSelect;
11
+ context_configs: ContextConfigSelect;
12
+ agent: AgentSelect;
13
+ sub_agents: SubAgentSelect;
14
+ };
15
+ type EntityOperation = 'insert' | 'update' | 'delete';
16
+ type EntityDiff<TTable extends keyof EntityRowByTable = keyof EntityRowByTable> = {
17
+ table: TTable;
18
+ operation: 'insert';
19
+ primaryKey: Record<string, string>;
20
+ before: null;
21
+ after: EntityRowByTable[TTable];
22
+ } | {
23
+ table: TTable;
24
+ operation: 'update';
25
+ primaryKey: Record<string, string>;
26
+ before: EntityRowByTable[TTable];
27
+ after: EntityRowByTable[TTable];
28
+ } | {
29
+ table: TTable;
30
+ operation: 'delete';
31
+ primaryKey: Record<string, string>;
32
+ before: EntityRowByTable[TTable];
33
+ after: null;
34
+ };
35
+ type EntityEffectHandlers<TTable extends keyof EntityRowByTable> = {
36
+ onCreated?: (after: EntityRowByTable[TTable], ctx: ReconcileContext) => Promise<void>;
37
+ onUpdated?: (before: EntityRowByTable[TTable], after: EntityRowByTable[TTable], ctx: ReconcileContext) => Promise<void>;
38
+ onDeleted?: (before: EntityRowByTable[TTable], ctx: ReconcileContext) => Promise<void>;
39
+ check?: (ctx: AuditContext) => Promise<unknown>;
40
+ };
41
+ type EntityEffectRegistry = { [K in keyof EntityRowByTable]?: EntityEffectHandlers<K> };
42
+ declare function defineHandlers<TTable extends keyof EntityRowByTable>(_table: TTable, handlers: EntityEffectHandlers<TTable>): EntityEffectHandlers<TTable>;
43
+ type ReconcileContext = {
44
+ manageDb: AgentsManageDatabaseClient;
45
+ runDb: AgentsRunDatabaseClient;
46
+ scopes: {
47
+ tenantId: string;
48
+ projectId: string;
49
+ };
50
+ fullBranchName: string;
51
+ logger: PinoLogger;
52
+ };
53
+ type AuditContext = ReconcileContext;
54
+ type AppliedEffect = {
55
+ table: string;
56
+ operation: EntityOperation;
57
+ primaryKey: Record<string, string>;
58
+ };
59
+ type FailedEffect = AppliedEffect & {
60
+ error: string;
61
+ };
62
+ type SkippedDiff = {
63
+ table: string;
64
+ operation: EntityOperation;
65
+ primaryKey: Record<string, string>;
66
+ reason: string;
67
+ };
68
+ type ReconcileResult = {
69
+ applied: AppliedEffect[];
70
+ skipped: SkippedDiff[];
71
+ failed: FailedEffect[];
72
+ };
73
+ type EntityAuditEntry<TResult = unknown> = {
74
+ table: string;
75
+ result: TResult;
76
+ error?: string;
77
+ };
78
+ type AuditReport = {
79
+ entries: EntityAuditEntry[];
80
+ checkedEntities: string[];
81
+ skippedEntities: string[];
82
+ };
83
+ type ScheduledTriggerAuditResult = {
84
+ missingWorkflows: Array<{
85
+ triggerId: string;
86
+ triggerName: string;
87
+ }>;
88
+ orphanedWorkflows: Array<{
89
+ workflowRunId: string;
90
+ scheduledTriggerId: string;
91
+ }>;
92
+ staleWorkflows: Array<{
93
+ triggerId: string;
94
+ triggerName: string;
95
+ workflowId: string;
96
+ }>;
97
+ deadWorkflows: Array<{
98
+ triggerId: string;
99
+ triggerName: string;
100
+ workflowRunId: string;
101
+ runStatus: string;
102
+ }>;
103
+ verificationFailures: Array<{
104
+ workflowRunId: string;
105
+ error: string;
106
+ }>;
107
+ };
108
+ type OrphanedRuntimeRowsResult = {
109
+ orphanedRows: Array<{
110
+ table: string;
111
+ id: string;
112
+ referencedEntityId: string;
113
+ }>;
114
+ };
115
+ //#endregion
116
+ export { AppliedEffect, AuditContext, AuditReport, EntityAuditEntry, EntityDiff, EntityEffectHandlers, EntityEffectRegistry, EntityOperation, EntityRowByTable, FailedEffect, OrphanedRuntimeRowsResult, ReconcileContext, ReconcileResult, ScheduledTriggerAuditResult, SkippedDiff, defineHandlers };
@@ -0,0 +1,7 @@
1
+ //#region src/data-reconciliation/types.ts
2
+ function defineHandlers(_table, handlers) {
3
+ return handlers;
4
+ }
5
+
6
+ //#endregion
7
+ export { defineHandlers };