@inkeep/agents-core 0.63.3 → 0.64.2

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 (98) hide show
  1. package/dist/api-client/eval-api-client.d.ts +2 -12
  2. package/dist/api-client/eval-api-client.js +0 -15
  3. package/dist/api-client/index.d.ts +2 -2
  4. package/dist/auth/auth-schema.d.ts +86 -86
  5. package/dist/auth/auth-validation-schemas.d.ts +137 -137
  6. package/dist/auth/auth.d.ts +6 -6
  7. package/dist/auth/auth.js +28 -9
  8. package/dist/auth/entitlement-constants.d.ts +11 -0
  9. package/dist/auth/entitlement-constants.js +10 -0
  10. package/dist/auth/entitlement-lock.d.ts +6 -0
  11. package/dist/auth/entitlement-lock.js +13 -0
  12. package/dist/auth/entitlements.d.ts +11 -0
  13. package/dist/auth/entitlements.js +55 -0
  14. package/dist/auth/init.js +2 -4
  15. package/dist/auth/permissions.d.ts +13 -13
  16. package/dist/client-exports.d.ts +6 -4
  17. package/dist/client-exports.js +4 -2
  18. package/dist/constants/models.d.ts +2 -1
  19. package/dist/constants/models.js +6 -1
  20. package/dist/constants/otel-attributes.d.ts +2 -0
  21. package/dist/constants/otel-attributes.js +2 -0
  22. package/dist/data-access/index.d.ts +5 -4
  23. package/dist/data-access/index.js +4 -3
  24. package/dist/data-access/manage/agents.d.ts +65 -23
  25. package/dist/data-access/manage/artifactComponents.d.ts +6 -6
  26. package/dist/data-access/manage/contextConfigs.d.ts +4 -4
  27. package/dist/data-access/manage/dataComponents.d.ts +2 -2
  28. package/dist/data-access/manage/evalConfig.d.ts +49 -3
  29. package/dist/data-access/manage/evalConfig.js +61 -3
  30. package/dist/data-access/manage/functionTools.d.ts +6 -6
  31. package/dist/data-access/manage/projectLifecycle.d.ts +1 -1
  32. package/dist/data-access/manage/skills.d.ts +9 -9
  33. package/dist/data-access/manage/subAgentExternalAgentRelations.d.ts +18 -12
  34. package/dist/data-access/manage/subAgentRelations.d.ts +22 -16
  35. package/dist/data-access/manage/subAgentTeamAgentRelations.d.ts +24 -12
  36. package/dist/data-access/manage/subAgents.d.ts +45 -9
  37. package/dist/data-access/manage/tools.d.ts +18 -18
  38. package/dist/data-access/manage/tools.js +41 -4
  39. package/dist/data-access/manage/triggers.d.ts +2 -2
  40. package/dist/data-access/runtime/apiKeys.d.ts +8 -8
  41. package/dist/data-access/runtime/apps.d.ts +38 -47
  42. package/dist/data-access/runtime/cascade-delete.d.ts +1 -1
  43. package/dist/data-access/runtime/conversations.d.ts +17 -17
  44. package/dist/data-access/runtime/entitlements.d.ts +13 -0
  45. package/dist/data-access/runtime/entitlements.js +33 -0
  46. package/dist/data-access/runtime/ledgerArtifacts.d.ts +1 -1
  47. package/dist/data-access/runtime/messages.d.ts +13 -13
  48. package/dist/data-access/runtime/scheduledTriggerInvocations.d.ts +47 -2
  49. package/dist/data-access/runtime/scheduledTriggerInvocations.js +34 -1
  50. package/dist/data-access/runtime/tasks.d.ts +6 -6
  51. package/dist/data-access/runtime/workflowExecutions.d.ts +1 -1
  52. package/dist/data-reconciliation/types.d.ts +1 -1
  53. package/dist/db/clean.d.ts +1 -1
  54. package/dist/db/manage/manage-schema.d.ts +766 -688
  55. package/dist/db/manage/manage-schema.js +154 -134
  56. package/dist/db/runtime/runtime-schema.d.ts +499 -392
  57. package/dist/db/runtime/runtime-schema.js +20 -3
  58. package/dist/dolt/backfill-skill-files.d.ts +41 -0
  59. package/dist/dolt/backfill-skill-files.js +209 -0
  60. package/dist/dolt/run-sql-file-on-all-branches.d.ts +29 -0
  61. package/dist/dolt/run-sql-file-on-all-branches.js +177 -0
  62. package/dist/index.d.ts +20 -16
  63. package/dist/index.js +12 -8
  64. package/dist/middleware/create-protected-route.d.ts +3 -0
  65. package/dist/middleware/create-protected-route.js +7 -2
  66. package/dist/middleware/entitlement-meta.d.ts +9 -0
  67. package/dist/middleware/entitlement-meta.js +11 -0
  68. package/dist/middleware/index.d.ts +2 -1
  69. package/dist/middleware/index.js +2 -1
  70. package/dist/types/entities.d.ts +8 -3
  71. package/dist/types/index.d.ts +3 -3
  72. package/dist/types/utility.d.ts +6 -6
  73. package/dist/utils/error.d.ts +54 -51
  74. package/dist/utils/error.js +3 -0
  75. package/dist/utils/index.d.ts +3 -3
  76. package/dist/utils/index.js +2 -2
  77. package/dist/utils/mcp-client.d.ts +1 -1
  78. package/dist/utils/mcp-client.js +1 -1
  79. package/dist/utils/model-factory.js +24 -9
  80. package/dist/utils/usage-cost-middleware.d.ts +2 -1
  81. package/dist/utils/usage-cost-middleware.js +22 -5
  82. package/dist/validation/drizzle-schema-helpers.d.ts +3 -3
  83. package/dist/validation/index.d.ts +2 -2
  84. package/dist/validation/index.js +2 -2
  85. package/dist/validation/schemas/skills.d.ts +43 -43
  86. package/dist/validation/schemas.d.ts +2376 -1441
  87. package/dist/validation/schemas.js +22 -24
  88. package/drizzle/manage/0016_complex_klaw.sql +2 -0
  89. package/drizzle/manage/0017_brief_doctor_strange.sql +29 -0
  90. package/drizzle/manage/meta/0016_snapshot.json +3530 -0
  91. package/drizzle/manage/meta/0017_snapshot.json +3748 -0
  92. package/drizzle/manage/meta/_journal.json +14 -0
  93. package/drizzle/runtime/0029_burly_satana.sql +13 -0
  94. package/drizzle/runtime/0030_set-allow-anonymous-for-existing-apps.sql +56 -0
  95. package/drizzle/runtime/meta/0029_snapshot.json +4756 -0
  96. package/drizzle/runtime/meta/_journal.json +14 -0
  97. package/package.json +3 -1
  98. /package/drizzle/runtime/meta/{0023_snapshot.json → 0025_snapshot.json} +0 -0
@@ -1,8 +1,8 @@
1
1
  import { __exportAll } from "../../_virtual/rolldown_runtime.js";
2
2
  import { account, deviceCode, invitation, member, organization, session, ssoProvider, user, verification } from "../../auth/auth-schema.js";
3
3
  import { USAGE_GENERATION_TYPES } from "../../constants/otel-attributes.js";
4
- import { relations } from "drizzle-orm";
5
- import { boolean, foreignKey, index, integer, jsonb, pgTable, primaryKey, text, timestamp, unique, uniqueIndex, varchar } from "drizzle-orm/pg-core";
4
+ import { relations, sql } from "drizzle-orm";
5
+ import { boolean, check, foreignKey, index, integer, jsonb, pgTable, primaryKey, text, timestamp, unique, uniqueIndex, varchar } from "drizzle-orm/pg-core";
6
6
 
7
7
  //#region src/db/runtime/runtime-schema.ts
8
8
  var runtime_schema_exports = /* @__PURE__ */ __exportAll({
@@ -24,6 +24,7 @@ var runtime_schema_exports = /* @__PURE__ */ __exportAll({
24
24
  member: () => member,
25
25
  messages: () => messages,
26
26
  messagesRelations: () => messagesRelations,
27
+ orgEntitlement: () => orgEntitlement,
27
28
  organization: () => organization,
28
29
  projectMetadata: () => projectMetadata,
29
30
  scheduledTriggerInvocations: () => scheduledTriggerInvocations,
@@ -870,6 +871,22 @@ const workAppSlackMcpToolAccessConfig = pgTable("work_app_slack_mcp_tool_access_
870
871
  name: "work_app_slack_mcp_tool_access_config_tenant_fk"
871
872
  }).onDelete("cascade")
872
873
  ]);
874
+ const orgEntitlement = pgTable("org_entitlement", {
875
+ id: varchar("id", { length: 256 }).primaryKey(),
876
+ organizationId: varchar("organization_id", { length: 256 }).notNull(),
877
+ resourceType: text("resource_type").notNull(),
878
+ maxValue: integer("max_value").notNull(),
879
+ ...timestamps
880
+ }, (table) => [
881
+ unique("org_entitlement_org_resource_unique").on(table.organizationId, table.resourceType),
882
+ index("org_entitlement_org_idx").on(table.organizationId),
883
+ foreignKey({
884
+ columns: [table.organizationId],
885
+ foreignColumns: [organization.id],
886
+ name: "org_entitlement_organization_fk"
887
+ }).onDelete("cascade"),
888
+ check("org_entitlement_resource_type_format", sql`resource_type ~ '^[a-z]+:[a-z][a-z0-9_]*$'`)
889
+ ]);
873
890
 
874
891
  //#endregion
875
- export { USAGE_GENERATION_TYPES, account, apiKeys, apps, contextCache, conversations, conversationsRelations, datasetRun, datasetRunConversationRelations, deviceCode, evaluationResult, evaluationRun, invitation, ledgerArtifacts, ledgerArtifactsRelations, member, messages, messagesRelations, organization, projectMetadata, runtime_schema_exports, scheduledTriggerInvocations, scheduledTriggers, schedulerState, session, ssoProvider, taskRelations, taskRelationsRelations, tasks, tasksRelations, triggerInvocations, user, userProfile, userProfileRelations, verification, workAppGitHubInstallations, workAppGitHubInstallationsRelations, workAppGitHubMcpToolAccessMode, workAppGitHubMcpToolRepositoryAccess, workAppGitHubMcpToolRepositoryAccessRelations, workAppGitHubProjectAccessMode, workAppGitHubProjectRepositoryAccess, workAppGitHubProjectRepositoryAccessRelations, workAppGitHubRepositories, workAppGitHubRepositoriesRelations, workAppSlackChannelAgentConfigs, workAppSlackMcpToolAccessConfig, workAppSlackUserMappings, workAppSlackWorkspaces, workflowExecutions };
892
+ export { USAGE_GENERATION_TYPES, account, apiKeys, apps, contextCache, conversations, conversationsRelations, datasetRun, datasetRunConversationRelations, deviceCode, evaluationResult, evaluationRun, invitation, ledgerArtifacts, ledgerArtifactsRelations, member, messages, messagesRelations, orgEntitlement, organization, projectMetadata, runtime_schema_exports, scheduledTriggerInvocations, scheduledTriggers, schedulerState, session, ssoProvider, taskRelations, taskRelationsRelations, tasks, tasksRelations, triggerInvocations, user, userProfile, userProfileRelations, verification, workAppGitHubInstallations, workAppGitHubInstallationsRelations, workAppGitHubMcpToolAccessMode, workAppGitHubMcpToolRepositoryAccess, workAppGitHubMcpToolRepositoryAccessRelations, workAppGitHubProjectAccessMode, workAppGitHubProjectRepositoryAccess, workAppGitHubProjectRepositoryAccessRelations, workAppGitHubRepositories, workAppGitHubRepositoriesRelations, workAppSlackChannelAgentConfigs, workAppSlackMcpToolAccessConfig, workAppSlackUserMappings, workAppSlackWorkspaces, workflowExecutions };
@@ -0,0 +1,41 @@
1
+ //#region src/dolt/backfill-skill-files.d.ts
2
+ type SkillBackfillSource = {
3
+ tenantId: string;
4
+ projectId: string;
5
+ id: string;
6
+ name: string;
7
+ description: string;
8
+ content: string;
9
+ metadata: Record<string, string> | null;
10
+ createdAt: string;
11
+ updatedAt: string;
12
+ };
13
+ type ExistingSkillEntryFile = {
14
+ tenantId: string;
15
+ projectId: string;
16
+ skillId: string;
17
+ };
18
+ type BackfillSkillFilesArgs = {
19
+ apply: boolean;
20
+ branchNames: string[];
21
+ continueOnError: boolean;
22
+ help: boolean;
23
+ includeMain: boolean;
24
+ };
25
+ declare function buildLegacySkillFileId(skill: Pick<SkillBackfillSource, 'tenantId' | 'projectId' | 'id'>): string;
26
+ declare function buildMissingSkillFileRows(sourceSkills: SkillBackfillSource[], existingSkillEntryFiles: ExistingSkillEntryFile[]): {
27
+ tenantId: string;
28
+ id: string;
29
+ projectId: string;
30
+ skillId: string;
31
+ filePath: string;
32
+ content: string;
33
+ createdAt: string;
34
+ updatedAt: string;
35
+ }[];
36
+ declare function parseBackfillSkillFilesArgs(argv: string[]): BackfillSkillFilesArgs;
37
+ declare function getBackfillSkillFilesUsage(): string;
38
+ declare function backfillSkillFilesAcrossAllBranches(options: Omit<BackfillSkillFilesArgs, 'help'>): Promise<void>;
39
+ declare function main(argv?: string[]): Promise<void>;
40
+ //#endregion
41
+ export { BackfillSkillFilesArgs, backfillSkillFilesAcrossAllBranches, buildLegacySkillFileId, buildMissingSkillFileRows, getBackfillSkillFilesUsage, main, parseBackfillSkillFilesArgs };
@@ -0,0 +1,209 @@
1
+ import { manage_schema_exports, skillFiles, skills } from "../db/manage/manage-schema.js";
2
+ import { loadEnvironmentFiles } from "../env.js";
3
+ import { createAgentsManageDatabasePool } from "../db/manage/manage-client.js";
4
+ import { doltReset } from "./commit.js";
5
+ import { doltListBranches } from "./branch.js";
6
+ import { confirmMigration } from "../db/utils.js";
7
+ import { eq } from "drizzle-orm";
8
+ import { stringify } from "yaml";
9
+ import { drizzle } from "drizzle-orm/node-postgres";
10
+ import { createHash } from "node:crypto";
11
+
12
+ //#region src/dolt/backfill-skill-files.ts
13
+ const DEFAULT_AUTHOR = {
14
+ name: "migration-script",
15
+ email: "migration@inkeep.com"
16
+ };
17
+ const DEFAULT_COMMIT_MESSAGE = "Backfill legacy SKILL.md skill files";
18
+ const SKILL_ENTRY_FILE_PATH = "SKILL.md";
19
+ function serializeSkillEntryFile(skill) {
20
+ return [
21
+ "---",
22
+ stringify({
23
+ name: skill.name,
24
+ description: skill.description,
25
+ metadata: skill.metadata ?? void 0
26
+ }).trimEnd(),
27
+ "---",
28
+ "",
29
+ skill.content
30
+ ].join("\n");
31
+ }
32
+ function buildLegacySkillFileId(skill) {
33
+ return `legacy-${createHash("md5").update(`${skill.tenantId}:${skill.projectId}:${skill.id}:${SKILL_ENTRY_FILE_PATH}`).digest("hex")}`;
34
+ }
35
+ function buildMissingSkillFileRows(sourceSkills, existingSkillEntryFiles) {
36
+ const existingKeys = new Set(existingSkillEntryFiles.map((file) => `${file.tenantId}:${file.projectId}:${file.skillId}:${SKILL_ENTRY_FILE_PATH}`));
37
+ return sourceSkills.filter((skill) => !existingKeys.has(`${skill.tenantId}:${skill.projectId}:${skill.id}:${SKILL_ENTRY_FILE_PATH}`)).map((skill) => ({
38
+ tenantId: skill.tenantId,
39
+ id: buildLegacySkillFileId(skill),
40
+ projectId: skill.projectId,
41
+ skillId: skill.id,
42
+ filePath: SKILL_ENTRY_FILE_PATH,
43
+ content: serializeSkillEntryFile(skill),
44
+ createdAt: skill.createdAt,
45
+ updatedAt: skill.updatedAt
46
+ }));
47
+ }
48
+ function readNextArg(argv, index, flag) {
49
+ const value = argv[index + 1];
50
+ if (!value || value.startsWith("--")) throw new Error(`Missing value for ${flag}`);
51
+ return value;
52
+ }
53
+ function parseBackfillSkillFilesArgs(argv) {
54
+ const parsed = {
55
+ apply: false,
56
+ branchNames: [],
57
+ continueOnError: false,
58
+ help: false,
59
+ includeMain: true
60
+ };
61
+ for (let index = 0; index < argv.length; index += 1) {
62
+ const arg = argv[index];
63
+ switch (arg) {
64
+ case "--apply":
65
+ parsed.apply = true;
66
+ break;
67
+ case "--branch":
68
+ parsed.branchNames.push(readNextArg(argv, index, arg));
69
+ index += 1;
70
+ break;
71
+ case "--continue-on-error":
72
+ parsed.continueOnError = true;
73
+ break;
74
+ case "--help":
75
+ case "-h":
76
+ parsed.help = true;
77
+ break;
78
+ case "--skip-main":
79
+ parsed.includeMain = false;
80
+ break;
81
+ default: throw new Error(`Unknown argument: ${arg}`);
82
+ }
83
+ }
84
+ return parsed;
85
+ }
86
+ function getBackfillSkillFilesUsage() {
87
+ return [
88
+ "Backfill legacy SKILL.md files from skills rows across Dolt branches.",
89
+ "",
90
+ "Usage:",
91
+ " tsx packages/agents-core/scripts/backfill-skill-files.ts [options]",
92
+ "",
93
+ "Options:",
94
+ " --apply Persist and commit changes. Default is dry-run.",
95
+ " --branch <name> Limit execution to a branch. Repeatable.",
96
+ " --skip-main Exclude main.",
97
+ " --continue-on-error Continue processing remaining branches after failures.",
98
+ " --help, -h Show this help text."
99
+ ].join("\n");
100
+ }
101
+ async function tableExists(connection, tableName) {
102
+ return (await connection.query(`SELECT 1
103
+ FROM information_schema.tables
104
+ WHERE table_schema = 'public'
105
+ AND table_name = $1
106
+ LIMIT 1`, [tableName])).rows.length > 0;
107
+ }
108
+ async function backfillSkillFilesAcrossAllBranches(options) {
109
+ loadEnvironmentFiles();
110
+ const connectionString = process.env.INKEEP_AGENTS_MANAGE_DATABASE_URL;
111
+ await confirmMigration(connectionString);
112
+ const pool = createAgentsManageDatabasePool({
113
+ connectionString,
114
+ poolSize: 2
115
+ });
116
+ try {
117
+ const targetBranches = (await doltListBranches(drizzle(pool, { schema: manage_schema_exports }))()).filter((branch) => {
118
+ if (!options.includeMain && branch.name === "main") return false;
119
+ if (options.branchNames.length > 0 && !options.branchNames.includes(branch.name)) return false;
120
+ return true;
121
+ });
122
+ if (targetBranches.length === 0) {
123
+ console.log("No matching branches found.");
124
+ return;
125
+ }
126
+ console.log(`${options.apply ? "Applying" : "Dry-running"} SKILL.md backfill on ${targetBranches.length} branch(es)\n`);
127
+ let changedBranches = 0;
128
+ let noopBranches = 0;
129
+ let skippedBranches = 0;
130
+ let failedBranches = 0;
131
+ let insertedRows = 0;
132
+ for (const branch of targetBranches) {
133
+ const connection = await pool.connect();
134
+ const branchDb = drizzle(connection, { schema: manage_schema_exports });
135
+ try {
136
+ await connection.query("SELECT DOLT_CHECKOUT($1)", [branch.name]);
137
+ const hasSkillsTable = await tableExists(connection, "skills");
138
+ const hasSkillFilesTable = await tableExists(connection, "skill_files");
139
+ if (!hasSkillsTable || !hasSkillFilesTable) {
140
+ skippedBranches += 1;
141
+ console.log(`Branch "${branch.name}": skipped (missing skills or skill_files table)`);
142
+ continue;
143
+ }
144
+ const missingRows = buildMissingSkillFileRows(await branchDb.select({
145
+ tenantId: skills.tenantId,
146
+ projectId: skills.projectId,
147
+ id: skills.id,
148
+ name: skills.name,
149
+ description: skills.description,
150
+ content: skills.content,
151
+ metadata: skills.metadata,
152
+ createdAt: skills.createdAt,
153
+ updatedAt: skills.updatedAt
154
+ }).from(skills), await branchDb.select({
155
+ tenantId: skillFiles.tenantId,
156
+ projectId: skillFiles.projectId,
157
+ skillId: skillFiles.skillId
158
+ }).from(skillFiles).where(eq(skillFiles.filePath, SKILL_ENTRY_FILE_PATH)));
159
+ if (missingRows.length === 0) {
160
+ noopBranches += 1;
161
+ console.log(`Branch "${branch.name}": no changes`);
162
+ continue;
163
+ }
164
+ if (options.apply) {
165
+ await branchDb.insert(skillFiles).values(missingRows).onConflictDoNothing();
166
+ await connection.query("SELECT DOLT_COMMIT('-a', '-m', $1, '--author', $2)", [DEFAULT_COMMIT_MESSAGE, `${DEFAULT_AUTHOR.name} <${DEFAULT_AUTHOR.email}>`]);
167
+ console.log(`Branch "${branch.name}": inserted ${missingRows.length} SKILL.md file(s)`);
168
+ } else console.log(`Branch "${branch.name}": would insert ${missingRows.length} SKILL.md file(s)`);
169
+ changedBranches += 1;
170
+ insertedRows += missingRows.length;
171
+ } catch (error) {
172
+ failedBranches += 1;
173
+ try {
174
+ await doltReset(branchDb)({ hard: true });
175
+ } catch {}
176
+ const message = error instanceof Error ? error.message : String(error);
177
+ console.error(`Branch "${branch.name}": failed`);
178
+ console.error(` ${message}`);
179
+ if (!options.continueOnError) throw error;
180
+ } finally {
181
+ try {
182
+ await connection.query("SELECT DOLT_CHECKOUT('main')");
183
+ } catch {}
184
+ connection.release();
185
+ }
186
+ }
187
+ console.log("");
188
+ console.log(`Summary: ${changedBranches} changed, ${noopBranches} no-op, ${skippedBranches} skipped, ${failedBranches} failed, ${insertedRows} SKILL.md file(s) ${options.apply ? "inserted" : "would be inserted"}`);
189
+ if (failedBranches > 0) process.exitCode = 1;
190
+ } finally {
191
+ await pool.end();
192
+ }
193
+ }
194
+ async function main(argv = process.argv.slice(2)) {
195
+ const parsedArgs = parseBackfillSkillFilesArgs(argv);
196
+ if (parsedArgs.help) {
197
+ console.log(getBackfillSkillFilesUsage());
198
+ return;
199
+ }
200
+ await backfillSkillFilesAcrossAllBranches({
201
+ apply: parsedArgs.apply,
202
+ branchNames: parsedArgs.branchNames,
203
+ continueOnError: parsedArgs.continueOnError,
204
+ includeMain: parsedArgs.includeMain
205
+ });
206
+ }
207
+
208
+ //#endregion
209
+ export { backfillSkillFilesAcrossAllBranches, buildLegacySkillFileId, buildMissingSkillFileRows, getBackfillSkillFilesUsage, main, parseBackfillSkillFilesArgs };
@@ -0,0 +1,29 @@
1
+ //#region src/dolt/run-sql-file-on-all-branches.d.ts
2
+ type RunSqlFileOnAllBranchesArgs = {
3
+ apply: boolean;
4
+ branchNames: string[];
5
+ continueOnError: boolean;
6
+ filePath?: string;
7
+ help: boolean;
8
+ includeMain: boolean;
9
+ };
10
+ declare function buildDefaultCommitMessage(sqlFilePath: string): string;
11
+ declare function resolveSqlFilePath(inputPath: string, cwd?: string): string;
12
+ declare function parseRunSqlFileOnAllBranchesArgs(argv: string[]): RunSqlFileOnAllBranchesArgs;
13
+ declare function getRunSqlFileOnAllBranchesUsage(): string;
14
+ type RunSqlFileOnAllBranchesOptions = {
15
+ apply: boolean;
16
+ author: {
17
+ email: string;
18
+ name: string;
19
+ };
20
+ branchNames: string[];
21
+ commitMessage: string;
22
+ continueOnError: boolean;
23
+ includeMain: boolean;
24
+ sqlFilePath: string;
25
+ };
26
+ declare function runSqlFileOnAllBranches(options: RunSqlFileOnAllBranchesOptions): Promise<void>;
27
+ declare function main(argv?: string[]): Promise<void>;
28
+ //#endregion
29
+ export { RunSqlFileOnAllBranchesArgs, buildDefaultCommitMessage, getRunSqlFileOnAllBranchesUsage, main, parseRunSqlFileOnAllBranchesArgs, resolveSqlFilePath, runSqlFileOnAllBranches };
@@ -0,0 +1,177 @@
1
+ import { manage_schema_exports } from "../db/manage/manage-schema.js";
2
+ import { loadEnvironmentFiles } from "../env.js";
3
+ import { createAgentsManageDatabasePool } from "../db/manage/manage-client.js";
4
+ import { doltReset, doltStatus } from "./commit.js";
5
+ import { doltListBranches } from "./branch.js";
6
+ import { confirmMigration } from "../db/utils.js";
7
+ import { existsSync, readFileSync } from "node:fs";
8
+ import path from "node:path";
9
+ import { drizzle } from "drizzle-orm/node-postgres";
10
+ import { fileURLToPath } from "node:url";
11
+
12
+ //#region src/dolt/run-sql-file-on-all-branches.ts
13
+ const DEFAULT_AUTHOR = {
14
+ name: "migration-script",
15
+ email: "migration@inkeep.com"
16
+ };
17
+ const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", "..");
18
+ const repoRoot = path.resolve(packageRoot, "..", "..");
19
+ function buildDefaultCommitMessage(sqlFilePath) {
20
+ return `Apply backfill SQL from ${path.basename(sqlFilePath)}`;
21
+ }
22
+ function resolveSqlFilePath(inputPath, cwd = process.cwd()) {
23
+ const candidates = path.isAbsolute(inputPath) ? [inputPath] : [
24
+ path.resolve(cwd, inputPath),
25
+ path.resolve(packageRoot, inputPath),
26
+ path.resolve(repoRoot, inputPath)
27
+ ];
28
+ for (const candidate of candidates) if (existsSync(candidate)) return candidate;
29
+ throw new Error(`SQL file not found: ${inputPath}`);
30
+ }
31
+ function readNextArg(argv, index, flag) {
32
+ const value = argv[index + 1];
33
+ if (!value || value.startsWith("--")) throw new Error(`Missing value for ${flag}`);
34
+ return value;
35
+ }
36
+ function parseRunSqlFileOnAllBranchesArgs(argv) {
37
+ const parsed = {
38
+ apply: false,
39
+ branchNames: [],
40
+ continueOnError: false,
41
+ help: false,
42
+ includeMain: true
43
+ };
44
+ for (let index = 0; index < argv.length; index += 1) {
45
+ const arg = argv[index];
46
+ switch (arg) {
47
+ case "--apply":
48
+ parsed.apply = true;
49
+ break;
50
+ case "--branch":
51
+ parsed.branchNames.push(readNextArg(argv, index, arg));
52
+ index += 1;
53
+ break;
54
+ case "--continue-on-error":
55
+ parsed.continueOnError = true;
56
+ break;
57
+ case "--file":
58
+ case "-f":
59
+ parsed.filePath = readNextArg(argv, index, arg);
60
+ index += 1;
61
+ break;
62
+ case "--help":
63
+ case "-h":
64
+ parsed.help = true;
65
+ break;
66
+ case "--skip-main":
67
+ parsed.includeMain = false;
68
+ break;
69
+ default: throw new Error(`Unknown argument: ${arg}`);
70
+ }
71
+ }
72
+ if (!parsed.help && !parsed.filePath) throw new Error("Missing required argument: --file <path-to-sql>");
73
+ return parsed;
74
+ }
75
+ function getRunSqlFileOnAllBranchesUsage() {
76
+ return [
77
+ "Run a SQL backfill file across Dolt branches.",
78
+ "",
79
+ "Usage:",
80
+ " tsx packages/agents-core/scripts/run-manage-backfill-on-all-branches.ts --file <path> [options]",
81
+ "",
82
+ "Options:",
83
+ " --apply Persist and commit changes. Default is dry-run.",
84
+ " --file, -f <path> SQL file to execute.",
85
+ " --branch <name> Limit execution to a branch. Repeatable.",
86
+ " --skip-main Exclude main.",
87
+ " --continue-on-error Continue processing remaining branches after failures.",
88
+ " --help, -h Show this help text."
89
+ ].join("\n");
90
+ }
91
+ async function runSqlFileOnAllBranches(options) {
92
+ loadEnvironmentFiles();
93
+ const connectionString = process.env.INKEEP_AGENTS_MANAGE_DATABASE_URL;
94
+ await confirmMigration(connectionString);
95
+ const resolvedSqlFilePath = resolveSqlFilePath(options.sqlFilePath);
96
+ const sqlFileContents = readFileSync(resolvedSqlFilePath, "utf8").trim();
97
+ if (!sqlFileContents) throw new Error(`SQL file is empty: ${resolvedSqlFilePath}`);
98
+ const pool = createAgentsManageDatabasePool({
99
+ connectionString,
100
+ poolSize: 2
101
+ });
102
+ try {
103
+ const targetBranches = (await doltListBranches(drizzle(pool, { schema: manage_schema_exports }))()).filter((branch) => {
104
+ if (!options.includeMain && branch.name === "main") return false;
105
+ if (options.branchNames.length > 0 && !options.branchNames.includes(branch.name)) return false;
106
+ return true;
107
+ });
108
+ if (targetBranches.length === 0) {
109
+ console.log("No matching branches found.");
110
+ return;
111
+ }
112
+ console.log(`${options.apply ? "Applying" : "Dry-running"} ${path.basename(resolvedSqlFilePath)} on ${targetBranches.length} branch(es)\n`);
113
+ let changedBranches = 0;
114
+ let noopBranches = 0;
115
+ let failedBranches = 0;
116
+ for (const branch of targetBranches) {
117
+ const connection = await pool.connect();
118
+ const branchDb = drizzle(connection, { schema: manage_schema_exports });
119
+ try {
120
+ await connection.query("SELECT DOLT_CHECKOUT($1)", [branch.name]);
121
+ await connection.query(sqlFileContents);
122
+ const status = await doltStatus(branchDb)();
123
+ if (status.length === 0) {
124
+ noopBranches += 1;
125
+ console.log(`Branch "${branch.name}": no changes`);
126
+ continue;
127
+ }
128
+ if (options.apply) {
129
+ await connection.query("SELECT DOLT_COMMIT('-a', '-m', $1, '--author', $2)", [options.commitMessage, `${options.author.name} <${options.author.email}>`]);
130
+ console.log(`Branch "${branch.name}": applied and committed`);
131
+ } else {
132
+ await doltReset(branchDb)({ hard: true });
133
+ console.log(`Branch "${branch.name}": would change (${status.length} tracked change(s))`);
134
+ }
135
+ changedBranches += 1;
136
+ } catch (error) {
137
+ failedBranches += 1;
138
+ try {
139
+ await doltReset(branchDb)({ hard: true });
140
+ } catch {}
141
+ const message = error instanceof Error ? error.message : String(error);
142
+ console.error(`Branch "${branch.name}": failed`);
143
+ console.error(` ${message}`);
144
+ if (!options.continueOnError) throw error;
145
+ } finally {
146
+ try {
147
+ await connection.query("SELECT DOLT_CHECKOUT('main')");
148
+ } catch {}
149
+ connection.release();
150
+ }
151
+ }
152
+ console.log("");
153
+ console.log(`Summary: ${changedBranches} changed, ${noopBranches} no-op, ${failedBranches} failed`);
154
+ if (failedBranches > 0) process.exitCode = 1;
155
+ } finally {
156
+ await pool.end();
157
+ }
158
+ }
159
+ async function main(argv = process.argv.slice(2)) {
160
+ const parsedArgs = parseRunSqlFileOnAllBranchesArgs(argv);
161
+ if (parsedArgs.help) {
162
+ console.log(getRunSqlFileOnAllBranchesUsage());
163
+ return;
164
+ }
165
+ await runSqlFileOnAllBranches({
166
+ apply: parsedArgs.apply,
167
+ author: DEFAULT_AUTHOR,
168
+ branchNames: parsedArgs.branchNames,
169
+ commitMessage: buildDefaultCommitMessage(parsedArgs.filePath ?? "backfill.sql"),
170
+ continueOnError: parsedArgs.continueOnError,
171
+ includeMain: parsedArgs.includeMain,
172
+ sqlFilePath: parsedArgs.filePath ?? ""
173
+ });
174
+ }
175
+
176
+ //#endregion
177
+ export { buildDefaultCommitMessage, getRunSqlFileOnAllBranchesUsage, main, parseRunSqlFileOnAllBranchesArgs, resolveSqlFilePath, runSqlFileOnAllBranches };