@opengeni/db 5.0.1 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. package/dist/automations.d.ts +0 -2
  2. package/dist/canonical-human-identities.d.ts +4 -0
  3. package/dist/canonical-human-identities.js +3 -3
  4. package/dist/capability-components.d.ts +5 -13
  5. package/dist/capability-integrations.d.ts +23 -8
  6. package/dist/capability-reconciliation.d.ts +5 -0
  7. package/dist/capability-reconciliation.js +21 -0
  8. package/dist/capability-reconciliation.js.map +1 -0
  9. package/dist/{chunk-6T2GGYWE.js → chunk-4UJCXBR2.js} +4 -5800
  10. package/dist/chunk-4UJCXBR2.js.map +1 -0
  11. package/dist/{chunk-MWMXWHJD.js → chunk-7JCDSMX2.js} +2 -2
  12. package/dist/chunk-AJA2ZIUW.js +219 -0
  13. package/dist/chunk-AJA2ZIUW.js.map +1 -0
  14. package/dist/chunk-CDAT6EKW.js +247 -0
  15. package/dist/chunk-CDAT6EKW.js.map +1 -0
  16. package/dist/{chunk-DPONPYJD.js → chunk-CJI6G254.js} +70 -18
  17. package/dist/chunk-CJI6G254.js.map +1 -0
  18. package/dist/chunk-G32NVMRJ.js +276 -0
  19. package/dist/chunk-G32NVMRJ.js.map +1 -0
  20. package/dist/chunk-GABXCG3N.js +5811 -0
  21. package/dist/chunk-GABXCG3N.js.map +1 -0
  22. package/dist/{chunk-ERKVSPDX.js → chunk-LVY33EWL.js} +3 -3
  23. package/dist/{chunk-45CP2YKY.js → chunk-MAMBI2HR.js} +9 -3
  24. package/dist/{chunk-45CP2YKY.js.map → chunk-MAMBI2HR.js.map} +1 -1
  25. package/dist/{chunk-F73UKJY6.js → chunk-MN5PZMEK.js} +91 -108
  26. package/dist/chunk-MN5PZMEK.js.map +1 -0
  27. package/dist/chunk-PJI4MUZ7.js +131 -0
  28. package/dist/chunk-PJI4MUZ7.js.map +1 -0
  29. package/dist/{chunk-T6BWIGWJ.js → chunk-RIYHP2WU.js} +2 -2
  30. package/dist/{chunk-7HMK3B45.js → chunk-RL2MUXM3.js} +16 -7
  31. package/dist/chunk-RL2MUXM3.js.map +1 -0
  32. package/dist/{chunk-HQDVI2DB.js → chunk-SYKHLPTK.js} +4 -3
  33. package/dist/{chunk-HQDVI2DB.js.map → chunk-SYKHLPTK.js.map} +1 -1
  34. package/dist/{chunk-T6YLHJLS.js → chunk-XIXVVBW2.js} +198 -51
  35. package/dist/chunk-XIXVVBW2.js.map +1 -0
  36. package/dist/chunk-ZPJ6V2VG.js +156 -0
  37. package/dist/chunk-ZPJ6V2VG.js.map +1 -0
  38. package/dist/codex-capacity-recovery.d.ts +12 -0
  39. package/dist/codex-failure-eligibility.d.ts +9 -0
  40. package/dist/company-profile-schema.d.ts +4 -2
  41. package/dist/connect-attempts.d.ts +15 -0
  42. package/dist/connect-attempts.js +25 -0
  43. package/dist/connect-attempts.js.map +1 -0
  44. package/dist/connection-authority.d.ts +7 -63
  45. package/dist/connection-refresh-lock.d.ts +4 -0
  46. package/dist/connection-token-resolver.d.ts +8 -43
  47. package/dist/database-timing.d.ts +10 -0
  48. package/dist/database.d.ts +4 -0
  49. package/dist/editable-artifact-durable-export.js +2 -2
  50. package/dist/editable-artifacts.d.ts +9 -0
  51. package/dist/editable-artifacts.js +7 -5
  52. package/dist/index.d.ts +447 -78
  53. package/dist/index.js +12705 -12872
  54. package/dist/index.js.map +1 -1
  55. package/dist/insights-usage-bundle.d.ts +3 -0
  56. package/dist/integration-bindings.d.ts +1 -1
  57. package/dist/integration-facets.d.ts +18 -1
  58. package/dist/knowledge-entries-schema.d.ts +2 -0
  59. package/dist/knowledge-entries.d.ts +1 -0
  60. package/dist/knowledge-indexing.d.ts +1 -0
  61. package/dist/live-session-attempt.d.ts +35 -137
  62. package/dist/managed-auth-session-sets.js +3 -3
  63. package/dist/mcp-account-bindings.d.ts +4 -0
  64. package/dist/mcp-oauth.d.ts +11 -0
  65. package/dist/mcp-operations.js +2 -2
  66. package/dist/migrate.js +1 -1
  67. package/dist/organization-integration-policy.d.ts +51 -0
  68. package/dist/organization-integration-policy.js +18 -0
  69. package/dist/organization-integration-policy.js.map +1 -0
  70. package/dist/organization-usage.d.ts +20 -0
  71. package/dist/plugin-packages.d.ts +9 -12
  72. package/dist/pr-review.d.ts +0 -11
  73. package/dist/preference-registry-schema.d.ts +17 -0
  74. package/dist/provision-roles.js +1 -1
  75. package/dist/retained-provider-commands.d.ts +124 -6
  76. package/dist/retained-provider-commands.js +29 -97
  77. package/dist/retained-provider-commands.js.map +1 -1
  78. package/dist/retired-session-create-metadata.d.ts +4 -0
  79. package/dist/runtime-posture.d.ts +7 -5
  80. package/dist/schema.d.ts +876 -656
  81. package/dist/schema.js +5 -7
  82. package/dist/session-admission-block.d.ts +32 -0
  83. package/dist/session-attempt-writers.d.ts +4 -0
  84. package/dist/session-background-commands.js +5 -4
  85. package/dist/session-command-output.js +8 -126
  86. package/dist/session-command-output.js.map +1 -1
  87. package/dist/session-control.d.ts +5 -1
  88. package/dist/session-event-slices.d.ts +10 -0
  89. package/dist/session-event-slices.js +8 -222
  90. package/dist/session-event-slices.js.map +1 -1
  91. package/dist/session-file-attachments.d.ts +28 -0
  92. package/dist/session-goal-reports.d.ts +43 -0
  93. package/dist/session-mcp-approval.d.ts +4 -0
  94. package/dist/session-mcp-credential-rotation.js +5 -4
  95. package/dist/session-mcp-credential-rotation.js.map +1 -1
  96. package/dist/session-message-search.d.ts +22 -0
  97. package/dist/session-queue-commands.d.ts +2 -6
  98. package/dist/session-retry.d.ts +36 -0
  99. package/dist/session-tenancy.js +3 -3
  100. package/dist/skill-source-release-impact.d.ts +18 -0
  101. package/dist/skill-source-release.d.ts +9 -0
  102. package/dist/skills.d.ts +7 -1
  103. package/dist/user-resource-authority.d.ts +0 -8
  104. package/dist/video-generation.js +3 -3
  105. package/dist/workspace-tool-defaults.js +5 -4
  106. package/dist/workspace-tool-defaults.js.map +1 -1
  107. package/drizzle/0468_knowledge_relationship_projection.sql +30 -0
  108. package/drizzle/0469_knowledge_source_discovery.sql +85 -0
  109. package/drizzle/0470_organization_integration_policy.sql +151 -0
  110. package/drizzle/0471_usage_events_account_recent_index.sql +4 -0
  111. package/drizzle/0472_usage_events_workspace_recent_index.sql +4 -0
  112. package/drizzle/0473_organization_usage_analytical_capability.sql +237 -0
  113. package/drizzle/0474_goal_report_requirements.sql +156 -0
  114. package/drizzle/0475_session_event_history_statistics.sql +15 -0
  115. package/drizzle/0476_session_event_history_policy_planning.sql +29 -0
  116. package/drizzle/0477_managed_sign_in_methods.sql +303 -0
  117. package/drizzle/0478_sender_owned_connections.sql +2772 -0
  118. package/drizzle/0479_connection_create_idempotency.sql +16 -0
  119. package/drizzle/0480_private_session_organization_key_administration.sql +154 -0
  120. package/drizzle/0481_personal_connection_visibility_cleanup.sql +45 -0
  121. package/drizzle/0482_remove_packs.sql +417 -0
  122. package/drizzle/0483_preclaim_admission_block.sql +85 -0
  123. package/drizzle/0484_insights_usage_projection.sql +211 -0
  124. package/drizzle/0485_inherited_mcp_approval_policies.sql +6 -0
  125. package/drizzle/0486_reasoning_configuration_message_forks.sql +35 -0
  126. package/drizzle/0487_skill_catalog_message_forks.sql +26 -0
  127. package/drizzle/0488_permanent_skill_removal.sql +207 -0
  128. package/drizzle/0489_modal_command_byte_offsets.sql +17 -0
  129. package/drizzle/0490_periodic_capture_attempt_cadence.sql +6 -0
  130. package/drizzle/0491_warm_capture_holder_reclamation.sql +57 -0
  131. package/drizzle/0492_codex_accepted_source_authority.sql +249 -0
  132. package/drizzle/0493_stopping_command_error_containment.sql +58 -0
  133. package/drizzle/0494_mcp_account_bindings.sql +334 -0
  134. package/drizzle/0495_consented_sandbox_recovery.sql +220 -0
  135. package/drizzle/0496_supervised_command_settlement.sql +386 -0
  136. package/drizzle/0497_modal_inventory_owner_read_capability.sql +112 -0
  137. package/drizzle/0498_enrollment_membership_fence.sql +87 -0
  138. package/drizzle/0499_session_attachment_access.sql +224 -0
  139. package/drizzle/0500_session_execution_epoch.sql +37 -0
  140. package/drizzle/0501_session_sharing_execution.sql +591 -0
  141. package/drizzle/0502_active_message_boundary_forks.sql +30 -0
  142. package/package.json +17 -5
  143. package/src/automations.ts +17 -73
  144. package/src/canonical-human-identities.ts +17 -5
  145. package/src/capability-components.ts +7 -24
  146. package/src/capability-integrations.ts +301 -21
  147. package/src/capability-reconciliation.ts +19 -0
  148. package/src/codex-capacity-recovery.ts +47 -0
  149. package/src/codex-failure-eligibility.ts +93 -0
  150. package/src/connect-attempts.ts +49 -18
  151. package/src/connection-authority.ts +12 -158
  152. package/src/connection-refresh-lock.ts +22 -0
  153. package/src/connection-token-resolver.ts +58 -530
  154. package/src/database-timing.ts +43 -0
  155. package/src/database.ts +61 -26
  156. package/src/editable-artifacts.ts +1 -1
  157. package/src/index.ts +3578 -1273
  158. package/src/insights-model-bundle.ts +19 -7
  159. package/src/insights-usage-bundle.ts +16 -19
  160. package/src/integration-bindings.ts +2 -7
  161. package/src/integration-facets.ts +73 -6
  162. package/src/knowledge-entries.ts +8 -1
  163. package/src/live-session-attempt.ts +0 -22
  164. package/src/mcp-account-bindings.ts +12 -0
  165. package/src/mcp-oauth.ts +26 -0
  166. package/src/organization-integration-policy.ts +235 -0
  167. package/src/organization-usage.ts +83 -0
  168. package/src/plugin-packages.ts +226 -42
  169. package/src/pr-review.ts +7 -69
  170. package/src/preference-registry-schema.ts +1 -0
  171. package/src/provision-roles.ts +50 -37
  172. package/src/retained-provider-commands.ts +286 -9
  173. package/src/retired-session-create-metadata.ts +16 -0
  174. package/src/runtime-posture.ts +217 -13
  175. package/src/schema.ts +104 -120
  176. package/src/session-admission-block.ts +29 -0
  177. package/src/session-attempt-writers.ts +48 -0
  178. package/src/session-control.ts +21 -5
  179. package/src/session-event-slices.ts +76 -26
  180. package/src/session-file-attachments.ts +66 -0
  181. package/src/session-goal-reports.ts +255 -0
  182. package/src/session-mcp-approval.ts +30 -0
  183. package/src/session-message-search.ts +348 -0
  184. package/src/session-queue-commands.ts +60 -36
  185. package/src/session-retry.ts +319 -0
  186. package/src/skill-config-migration.ts +11 -2
  187. package/src/skill-source-release-impact.ts +33 -0
  188. package/src/skill-source-release.ts +67 -26
  189. package/src/skills.ts +44 -6
  190. package/src/user-resource-authority.ts +0 -56
  191. package/dist/chunk-6T2GGYWE.js.map +0 -1
  192. package/dist/chunk-7HMK3B45.js.map +0 -1
  193. package/dist/chunk-DPONPYJD.js.map +0 -1
  194. package/dist/chunk-F73UKJY6.js.map +0 -1
  195. package/dist/chunk-T6YLHJLS.js.map +0 -1
  196. package/dist/host-mcp-binding-match.d.ts +0 -5
  197. package/dist/host-mcp-bindings.d.ts +0 -79
  198. package/dist/host-mcp-resolvers.d.ts +0 -47
  199. package/dist/host-mcp-task-authority.d.ts +0 -43
  200. package/dist/host-selection-identity.d.ts +0 -6
  201. package/dist/pack-components.d.ts +0 -83
  202. package/dist/pack-installations.d.ts +0 -86
  203. package/src/host-mcp-binding-match.ts +0 -34
  204. package/src/host-mcp-bindings.ts +0 -777
  205. package/src/host-mcp-resolvers.ts +0 -266
  206. package/src/host-mcp-task-authority.ts +0 -384
  207. package/src/host-selection-identity.ts +0 -29
  208. package/src/pack-components.ts +0 -980
  209. package/src/pack-installations.ts +0 -950
  210. /package/dist/{chunk-MWMXWHJD.js.map → chunk-7JCDSMX2.js.map} +0 -0
  211. /package/dist/{chunk-ERKVSPDX.js.map → chunk-LVY33EWL.js.map} +0 -0
  212. /package/dist/{chunk-T6BWIGWJ.js.map → chunk-RIYHP2WU.js.map} +0 -0
@@ -1,980 +0,0 @@
1
- import { createHash } from "node:crypto";
2
-
3
- import {
4
- stableJson,
5
- type CapabilityPackComponentReference,
6
- type PackComponentResolution,
7
- type SkillActor,
8
- } from "@opengeni/contracts";
9
- import { and, asc, eq, inArray, ne, notInArray, or, sql } from "drizzle-orm";
10
-
11
- import {
12
- cleanupOrphanedCapabilityComponents,
13
- effectiveCapabilityOwnerSql,
14
- } from "./capability-components";
15
- import {
16
- listInstalledApiIntegrationsInRlsContext,
17
- type ApiIntegrationRuntime,
18
- } from "./capability-integrations";
19
- import { withRlsContext, withWorkspaceRls, type Database } from "./database";
20
- import type { SkillSourceReleaseReceipt } from "./skill-source-release";
21
- import {
22
- addIntegrationFacetBindingOwner,
23
- removeIntegrationFacetBindingOwner,
24
- removeIntegrationFacetBindingOwnersForOwner,
25
- } from "./integration-bindings";
26
- import * as schema from "./schema";
27
-
28
- type PackComponentKind = PackComponentResolution["kind"];
29
-
30
- export type PackInlineSkillRequirement = {
31
- key: string;
32
- capabilityId: string;
33
- name: string;
34
- activationMode: "workspace_managed" | "session_selected";
35
- contentSha256: string;
36
- };
37
-
38
- type ResolvedPackComponentTarget = {
39
- resolution: PackComponentResolution;
40
- facetInstallationIds: string[];
41
- bindingIds: string[];
42
- metadata: Record<string, unknown>;
43
- };
44
-
45
- export type StoredPackInstallationComponent = {
46
- id: string;
47
- packInstallationId: string;
48
- key: string;
49
- kind: PackComponentKind;
50
- capabilityId: string;
51
- resolvedId: string;
52
- digest: string;
53
- metadata: Record<string, unknown>;
54
- };
55
-
56
- export class PackComponentResolutionError extends Error {
57
- readonly name = "PackComponentResolutionError";
58
-
59
- constructor(
60
- readonly componentKey: string,
61
- readonly status: "missing" | "mismatch",
62
- ) {
63
- super(`Pack component ${componentKey} is ${status}`);
64
- }
65
- }
66
-
67
- export async function resolvePackComponentReferences(
68
- db: Database,
69
- workspaceId: string,
70
- references: readonly CapabilityPackComponentReference[],
71
- ): Promise<PackComponentResolution[]> {
72
- return await withWorkspaceRls(
73
- db,
74
- workspaceId,
75
- async (scopedDb) =>
76
- await resolvePackComponentTargets(scopedDb, workspaceId, references).then((targets) =>
77
- targets.map((target) => target.resolution),
78
- ),
79
- );
80
- }
81
-
82
- /**
83
- * Resolve inline Pack Skills against effective owners by case-insensitive
84
- * runtime name. Exact content is shareable; different content under the same
85
- * active name is a conflict. The current Pack owner may be excluded so an
86
- * update can replace its own previous inline Skill safely.
87
- */
88
- export async function resolvePackInlineSkillReferences(
89
- db: Database,
90
- workspaceId: string,
91
- requirements: readonly PackInlineSkillRequirement[],
92
- excludePackInstallationId?: string,
93
- ): Promise<PackComponentResolution[]> {
94
- if (requirements.length === 0) return [];
95
- return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
96
- const normalizedNames = [
97
- ...new Set(requirements.map((requirement) => requirement.name.toLowerCase())),
98
- ];
99
- const rows = await scopedDb
100
- .select({
101
- facetInstallationId: schema.capabilityFacetInstallations.id,
102
- name: schema.capabilitySkillFacets.name,
103
- activationMode: schema.capabilityFacets.activationMode,
104
- contentSha256: schema.capabilitySkillFacets.contentSha256,
105
- })
106
- .from(schema.capabilitySkillFacets)
107
- .innerJoin(
108
- schema.capabilityFacets,
109
- eq(schema.capabilityFacets.id, schema.capabilitySkillFacets.facetId),
110
- )
111
- .innerJoin(
112
- schema.capabilityFacetInstallations,
113
- eq(schema.capabilityFacetInstallations.facetId, schema.capabilitySkillFacets.facetId),
114
- )
115
- .innerJoin(
116
- schema.capabilityPluginInstallations,
117
- eq(
118
- schema.capabilityPluginInstallations.id,
119
- schema.capabilityFacetInstallations.pluginInstallationId,
120
- ),
121
- )
122
- .where(
123
- and(
124
- eq(schema.capabilityFacetInstallations.workspaceId, workspaceId),
125
- eq(schema.capabilityFacetInstallations.status, "active"),
126
- eq(schema.capabilityPluginInstallations.status, "active"),
127
- inArray(sql<string>`lower(${schema.capabilitySkillFacets.name})`, normalizedNames),
128
- sql`exists (
129
- select 1 from ${schema.capabilityComponentOwners} owner
130
- where owner.facet_installation_id = ${schema.capabilityFacetInstallations.id}
131
- and ${effectiveCapabilityOwnerSql(sql`owner.owner_kind`, sql`owner.owner_id`)}
132
- and ${
133
- excludePackInstallationId
134
- ? sql`not (
135
- owner.owner_kind = 'pack'
136
- and owner.owner_id = ${excludePackInstallationId}
137
- )`
138
- : sql`true`
139
- }
140
- )`,
141
- ),
142
- )
143
- .orderBy(
144
- asc(schema.capabilitySkillFacets.name),
145
- asc(schema.capabilitySkillFacets.contentSha256),
146
- );
147
- return requirements.map((requirement) => {
148
- const candidates = rows.filter(
149
- (row) => row.name.toLowerCase() === requirement.name.toLowerCase(),
150
- );
151
- const exact = candidates.find(
152
- (candidate) =>
153
- candidate.contentSha256 === requirement.contentSha256 &&
154
- candidate.activationMode === requirement.activationMode,
155
- );
156
- const mismatch =
157
- candidates.find(
158
- (candidate) =>
159
- candidate.contentSha256 !== requirement.contentSha256 ||
160
- candidate.activationMode !== requirement.activationMode,
161
- ) ?? null;
162
- return {
163
- key: requirement.key,
164
- kind: "inline_skill" as const,
165
- capabilityId: requirement.capabilityId,
166
- required: true,
167
- status: candidates.length === 0 || exact ? "ready" : "mismatch",
168
- expectedDigest: requirement.contentSha256,
169
- actualDigest: exact?.contentSha256 ?? mismatch?.contentSha256 ?? requirement.contentSha256,
170
- resolvedId:
171
- candidates.length === 0 ? requirement.capabilityId : (exact?.facetInstallationId ?? null),
172
- label: requirement.name,
173
- };
174
- });
175
- });
176
- }
177
-
178
- export async function adoptPackComponentReferences(
179
- db: Database,
180
- input: {
181
- accountId: string;
182
- workspaceId: string;
183
- packInstallationId: string;
184
- references: readonly CapabilityPackComponentReference[];
185
- },
186
- ): Promise<{
187
- components: StoredPackInstallationComponent[];
188
- retainedFacetInstallationIds: string[];
189
- retainedBindingIds: string[];
190
- }> {
191
- return await withRlsContext(
192
- db,
193
- { accountId: input.accountId, workspaceId: input.workspaceId },
194
- async (scopedDb) =>
195
- await scopedDb.transaction(async (txRaw) => {
196
- const tx = txRaw as unknown as Database;
197
- await tx.execute(
198
- sql`select pg_advisory_xact_lock(hashtextextended(${`pack-components:${input.workspaceId}:${input.packInstallationId}`}, 0))`,
199
- );
200
- const [installation] = await tx
201
- .select({ id: schema.packInstallations.id })
202
- .from(schema.packInstallations)
203
- .where(
204
- and(
205
- eq(schema.packInstallations.workspaceId, input.workspaceId),
206
- eq(schema.packInstallations.id, input.packInstallationId),
207
- ),
208
- )
209
- .for("update")
210
- .limit(1);
211
- if (!installation) throw new Error("Pack installation was not found");
212
-
213
- const targets = await resolvePackComponentTargets(tx, input.workspaceId, input.references);
214
- const retainedFacetInstallationIds: string[] = [];
215
- const retainedBindingIds: string[] = [];
216
- const components: StoredPackInstallationComponent[] = [];
217
- for (const target of targets) {
218
- if (target.resolution.status !== "ready") {
219
- if (target.resolution.required) {
220
- throw new PackComponentResolutionError(
221
- target.resolution.key,
222
- target.resolution.status,
223
- );
224
- }
225
- continue;
226
- }
227
- for (const facetInstallationId of target.facetInstallationIds) {
228
- await tx
229
- .insert(schema.capabilityComponentOwners)
230
- .values({
231
- accountId: input.accountId,
232
- workspaceId: input.workspaceId,
233
- facetInstallationId,
234
- ownerKind: "pack",
235
- ownerId: input.packInstallationId,
236
- removable: true,
237
- })
238
- .onConflictDoNothing();
239
- retainedFacetInstallationIds.push(facetInstallationId);
240
- }
241
- for (const bindingId of target.bindingIds) {
242
- await addIntegrationFacetBindingOwner(tx, bindingId, {
243
- accountId: input.accountId,
244
- workspaceId: input.workspaceId,
245
- owner: { kind: "pack", id: input.packInstallationId, removable: true },
246
- });
247
- retainedBindingIds.push(bindingId);
248
- }
249
- const [row] = await tx
250
- .insert(schema.packInstallationComponents)
251
- .values({
252
- accountId: input.accountId,
253
- workspaceId: input.workspaceId,
254
- packInstallationId: input.packInstallationId,
255
- componentKey: target.resolution.key,
256
- kind: target.resolution.kind,
257
- capabilityId: target.resolution.capabilityId,
258
- resolvedId: target.resolution.resolvedId!,
259
- digest: target.resolution.actualDigest!,
260
- metadata: {
261
- ...target.metadata,
262
- facetInstallationIds: [...new Set(target.facetInstallationIds)],
263
- bindingIds: [...new Set(target.bindingIds)],
264
- },
265
- updatedAt: new Date(),
266
- })
267
- .onConflictDoUpdate({
268
- target: [
269
- schema.packInstallationComponents.packInstallationId,
270
- schema.packInstallationComponents.componentKey,
271
- ],
272
- set: {
273
- kind: target.resolution.kind,
274
- capabilityId: target.resolution.capabilityId,
275
- resolvedId: target.resolution.resolvedId!,
276
- digest: target.resolution.actualDigest!,
277
- metadata: {
278
- ...target.metadata,
279
- facetInstallationIds: [...new Set(target.facetInstallationIds)],
280
- bindingIds: [...new Set(target.bindingIds)],
281
- },
282
- updatedAt: new Date(),
283
- },
284
- })
285
- .returning();
286
- if (!row) throw new Error(`Failed to record Pack component ${target.resolution.key}`);
287
- components.push(mapStoredPackComponent(row));
288
- }
289
- return {
290
- components,
291
- retainedFacetInstallationIds: [...new Set(retainedFacetInstallationIds)],
292
- retainedBindingIds: [...new Set(retainedBindingIds)],
293
- };
294
- }),
295
- );
296
- }
297
-
298
- export async function listPackInstallationComponents(
299
- db: Database,
300
- workspaceId: string,
301
- packInstallationId: string,
302
- ): Promise<StoredPackInstallationComponent[]> {
303
- return await withWorkspaceRls(
304
- db,
305
- workspaceId,
306
- async (scopedDb) =>
307
- await listPackInstallationComponentsInRlsContext(scopedDb, workspaceId, packInstallationId),
308
- );
309
- }
310
-
311
- export async function recordPackInlineSkillComponent(
312
- db: Database,
313
- input: {
314
- accountId: string;
315
- workspaceId: string;
316
- packInstallationId: string;
317
- componentKey: string;
318
- capabilityId: string;
319
- facetInstallationId: string;
320
- contentSha256: string;
321
- name: string;
322
- },
323
- ): Promise<StoredPackInstallationComponent> {
324
- return await withRlsContext(
325
- db,
326
- { accountId: input.accountId, workspaceId: input.workspaceId },
327
- async (scopedDb) => {
328
- const [row] = await scopedDb
329
- .insert(schema.packInstallationComponents)
330
- .values({
331
- accountId: input.accountId,
332
- workspaceId: input.workspaceId,
333
- packInstallationId: input.packInstallationId,
334
- componentKey: input.componentKey,
335
- kind: "inline_skill",
336
- capabilityId: input.capabilityId,
337
- resolvedId: input.facetInstallationId,
338
- digest: input.contentSha256,
339
- metadata: {
340
- name: input.name,
341
- facetInstallationIds: [input.facetInstallationId],
342
- bindingIds: [],
343
- },
344
- updatedAt: new Date(),
345
- })
346
- .onConflictDoUpdate({
347
- target: [
348
- schema.packInstallationComponents.packInstallationId,
349
- schema.packInstallationComponents.componentKey,
350
- ],
351
- set: {
352
- kind: "inline_skill",
353
- capabilityId: input.capabilityId,
354
- resolvedId: input.facetInstallationId,
355
- digest: input.contentSha256,
356
- metadata: {
357
- name: input.name,
358
- facetInstallationIds: [input.facetInstallationId],
359
- bindingIds: [],
360
- },
361
- updatedAt: new Date(),
362
- },
363
- })
364
- .returning();
365
- if (!row) throw new Error(`Failed to record inline Pack Skill ${input.componentKey}`);
366
- return mapStoredPackComponent(row);
367
- },
368
- );
369
- }
370
-
371
- export async function finalizePackComponentOwnership(
372
- db: Database,
373
- input: {
374
- accountId: string;
375
- workspaceId: string;
376
- packInstallationId: string;
377
- retainedComponentKeys: string[];
378
- retainedFacetInstallationIds: string[];
379
- retainedBindingIds: string[];
380
- skillActor?: SkillActor;
381
- },
382
- ): Promise<{ skillReleases: SkillSourceReleaseReceipt[] }> {
383
- return await withRlsContext(
384
- db,
385
- { accountId: input.accountId, workspaceId: input.workspaceId },
386
- async (scopedDb) =>
387
- await scopedDb.transaction(async (txRaw) => {
388
- const tx = txRaw as unknown as Database;
389
- const retainedFacets = new Set(input.retainedFacetInstallationIds);
390
- let skillReleases: SkillSourceReleaseReceipt[] = [];
391
- const ownedFacets = await tx
392
- .select({
393
- id: schema.capabilityComponentOwners.id,
394
- facetInstallationId: schema.capabilityComponentOwners.facetInstallationId,
395
- })
396
- .from(schema.capabilityComponentOwners)
397
- .where(
398
- and(
399
- eq(schema.capabilityComponentOwners.workspaceId, input.workspaceId),
400
- eq(schema.capabilityComponentOwners.ownerKind, "pack"),
401
- eq(schema.capabilityComponentOwners.ownerId, input.packInstallationId),
402
- ),
403
- );
404
- const staleFacets = ownedFacets.filter(
405
- (owner) => !retainedFacets.has(owner.facetInstallationId),
406
- );
407
- if (staleFacets.length > 0) {
408
- await tx.delete(schema.capabilityComponentOwners).where(
409
- inArray(
410
- schema.capabilityComponentOwners.id,
411
- staleFacets.map((owner) => owner.id),
412
- ),
413
- );
414
- skillReleases = await cleanupOrphanedCapabilityComponents(
415
- tx,
416
- input.workspaceId,
417
- staleFacets.map((owner) => owner.facetInstallationId),
418
- input.skillActor,
419
- );
420
- }
421
- const retainedBindings = new Set(input.retainedBindingIds);
422
- const ownedBindings = await tx
423
- .select({ bindingId: schema.integrationFacetBindingOwners.bindingId })
424
- .from(schema.integrationFacetBindingOwners)
425
- .where(
426
- and(
427
- eq(schema.integrationFacetBindingOwners.workspaceId, input.workspaceId),
428
- eq(schema.integrationFacetBindingOwners.ownerKind, "pack"),
429
- eq(schema.integrationFacetBindingOwners.ownerId, input.packInstallationId),
430
- ),
431
- );
432
- for (const bindingId of [
433
- ...new Set(
434
- ownedBindings
435
- .map((owner) => owner.bindingId)
436
- .filter((ownedBindingId) => !retainedBindings.has(ownedBindingId)),
437
- ),
438
- ]) {
439
- await removeIntegrationFacetBindingOwner(tx, {
440
- workspaceId: input.workspaceId,
441
- bindingId,
442
- owner: { kind: "pack", id: input.packInstallationId },
443
- });
444
- }
445
- const retainedKeys = [...new Set(input.retainedComponentKeys)];
446
- await tx
447
- .delete(schema.packInstallationComponents)
448
- .where(
449
- and(
450
- eq(schema.packInstallationComponents.workspaceId, input.workspaceId),
451
- eq(schema.packInstallationComponents.packInstallationId, input.packInstallationId),
452
- retainedKeys.length > 0
453
- ? notInArray(schema.packInstallationComponents.componentKey, retainedKeys)
454
- : sql`true`,
455
- ),
456
- );
457
- return { skillReleases };
458
- }),
459
- );
460
- }
461
-
462
- export async function previewPackComponentRelease(
463
- db: Database,
464
- workspaceId: string,
465
- packInstallationId: string,
466
- ): Promise<
467
- Array<{
468
- key: string;
469
- kind: PackComponentKind;
470
- capabilityId: string;
471
- retainedByOtherOwners: boolean;
472
- }>
473
- > {
474
- return await withWorkspaceRls(
475
- db,
476
- workspaceId,
477
- async (scopedDb) =>
478
- await previewPackComponentReleaseInRlsContext(scopedDb, workspaceId, packInstallationId),
479
- );
480
- }
481
-
482
- async function previewPackComponentReleaseInRlsContext(
483
- scopedDb: Database,
484
- workspaceId: string,
485
- packInstallationId: string,
486
- ): Promise<
487
- Array<{
488
- key: string;
489
- kind: PackComponentKind;
490
- capabilityId: string;
491
- retainedByOtherOwners: boolean;
492
- }>
493
- > {
494
- const components = await listPackInstallationComponentsInRlsContext(
495
- scopedDb,
496
- workspaceId,
497
- packInstallationId,
498
- );
499
- const result = [];
500
- for (const component of components) {
501
- const facetIds = stringArray(component.metadata.facetInstallationIds);
502
- const bindingIds = stringArray(component.metadata.bindingIds);
503
- const [facetOwner] =
504
- facetIds.length === 0
505
- ? []
506
- : await scopedDb
507
- .select({ id: schema.capabilityComponentOwners.id })
508
- .from(schema.capabilityComponentOwners)
509
- .where(
510
- and(
511
- inArray(schema.capabilityComponentOwners.facetInstallationId, facetIds),
512
- effectiveCapabilityOwnerSql(
513
- schema.capabilityComponentOwners.ownerKind,
514
- schema.capabilityComponentOwners.ownerId,
515
- ),
516
- or(
517
- ne(schema.capabilityComponentOwners.ownerKind, "pack"),
518
- ne(schema.capabilityComponentOwners.ownerId, packInstallationId),
519
- ),
520
- ),
521
- )
522
- .limit(1);
523
- const [bindingOwner] =
524
- bindingIds.length === 0
525
- ? []
526
- : await scopedDb
527
- .select({ id: schema.integrationFacetBindingOwners.id })
528
- .from(schema.integrationFacetBindingOwners)
529
- .where(
530
- and(
531
- inArray(schema.integrationFacetBindingOwners.bindingId, bindingIds),
532
- effectiveCapabilityOwnerSql(
533
- schema.integrationFacetBindingOwners.ownerKind,
534
- schema.integrationFacetBindingOwners.ownerId,
535
- ),
536
- or(
537
- ne(schema.integrationFacetBindingOwners.ownerKind, "pack"),
538
- ne(schema.integrationFacetBindingOwners.ownerId, packInstallationId),
539
- ),
540
- ),
541
- )
542
- .limit(1);
543
- result.push({
544
- key: component.key,
545
- kind: component.kind,
546
- capabilityId: component.capabilityId,
547
- retainedByOtherOwners: Boolean(facetOwner || bindingOwner),
548
- });
549
- }
550
- return result;
551
- }
552
-
553
- export async function releasePackComponents(
554
- db: Database,
555
- input: {
556
- accountId: string;
557
- workspaceId: string;
558
- packInstallationId: string;
559
- skillActor?: SkillActor;
560
- },
561
- ): Promise<{ retainedComponents: string[]; skillReleases?: SkillSourceReleaseReceipt[] }> {
562
- return await withRlsContext(
563
- db,
564
- { accountId: input.accountId, workspaceId: input.workspaceId },
565
- async (scopedDb) =>
566
- await scopedDb.transaction(async (txRaw) => {
567
- const tx = txRaw as unknown as Database;
568
- const preview = await previewPackComponentReleaseInRlsContext(
569
- tx,
570
- input.workspaceId,
571
- input.packInstallationId,
572
- );
573
- await removeIntegrationFacetBindingOwnersForOwner(tx, {
574
- workspaceId: input.workspaceId,
575
- owner: { kind: "pack", id: input.packInstallationId },
576
- });
577
- const deletedOwners = await tx
578
- .delete(schema.capabilityComponentOwners)
579
- .where(
580
- and(
581
- eq(schema.capabilityComponentOwners.workspaceId, input.workspaceId),
582
- eq(schema.capabilityComponentOwners.ownerKind, "pack"),
583
- eq(schema.capabilityComponentOwners.ownerId, input.packInstallationId),
584
- ),
585
- )
586
- .returning({ facetInstallationId: schema.capabilityComponentOwners.facetInstallationId });
587
- const skillReleases = await cleanupOrphanedCapabilityComponents(
588
- tx,
589
- input.workspaceId,
590
- deletedOwners.map((row) => row.facetInstallationId),
591
- input.skillActor,
592
- );
593
- await tx
594
- .delete(schema.packInstallationComponents)
595
- .where(
596
- and(
597
- eq(schema.packInstallationComponents.workspaceId, input.workspaceId),
598
- eq(schema.packInstallationComponents.packInstallationId, input.packInstallationId),
599
- ),
600
- );
601
- return {
602
- ...(skillReleases.length ? { skillReleases } : {}),
603
- retainedComponents: preview
604
- .filter((component) => component.retainedByOtherOwners)
605
- .map((component) => component.capabilityId),
606
- };
607
- }),
608
- );
609
- }
610
-
611
- async function resolvePackComponentTargets(
612
- db: Database,
613
- workspaceId: string,
614
- references: readonly CapabilityPackComponentReference[],
615
- ): Promise<ResolvedPackComponentTarget[]> {
616
- const integrations = await listInstalledApiIntegrationsInRlsContext(db, workspaceId);
617
- const targets: ResolvedPackComponentTarget[] = [];
618
- for (const reference of references) {
619
- if (reference.kind === "plugin") {
620
- targets.push(await resolvePluginReference(db, workspaceId, reference));
621
- } else if (reference.kind === "skill") {
622
- targets.push(await resolveSkillReference(db, workspaceId, reference));
623
- } else if (reference.kind === "integration") {
624
- targets.push(await resolveIntegrationReference(db, workspaceId, reference, integrations));
625
- } else {
626
- targets.push(await resolveFacetReference(db, workspaceId, reference, integrations));
627
- }
628
- }
629
- return targets;
630
- }
631
-
632
- async function resolvePluginReference(
633
- db: Database,
634
- workspaceId: string,
635
- reference: Extract<CapabilityPackComponentReference, { kind: "plugin" }>,
636
- ): Promise<ResolvedPackComponentTarget> {
637
- const [row] = await db
638
- .select({
639
- pluginInstallationId: schema.capabilityPluginInstallations.id,
640
- status: schema.capabilityPluginInstallations.status,
641
- version: schema.capabilityPluginVersions.version,
642
- manifestDigest: schema.capabilityPluginVersions.manifestDigest,
643
- name: schema.capabilityPlugins.name,
644
- })
645
- .from(schema.capabilityPluginInstallations)
646
- .innerJoin(
647
- schema.capabilityPlugins,
648
- eq(schema.capabilityPlugins.id, schema.capabilityPluginInstallations.pluginId),
649
- )
650
- .innerJoin(
651
- schema.capabilityPluginVersions,
652
- eq(schema.capabilityPluginVersions.id, schema.capabilityPluginInstallations.pluginVersionId),
653
- )
654
- .where(
655
- and(
656
- eq(schema.capabilityPluginInstallations.workspaceId, workspaceId),
657
- eq(schema.capabilityPlugins.pluginKey, reference.pluginKey),
658
- ),
659
- )
660
- .limit(1);
661
- const expectedDigest = reference.manifestDigest;
662
- const exact =
663
- row?.status === "active" &&
664
- row.version === reference.version &&
665
- row.manifestDigest === reference.manifestDigest;
666
- const facetInstallationIds = !row
667
- ? []
668
- : (
669
- await db
670
- .select({ id: schema.capabilityComponentOwners.facetInstallationId })
671
- .from(schema.capabilityComponentOwners)
672
- .where(
673
- and(
674
- eq(schema.capabilityComponentOwners.workspaceId, workspaceId),
675
- eq(schema.capabilityComponentOwners.ownerKind, "plugin"),
676
- eq(schema.capabilityComponentOwners.ownerId, row.pluginInstallationId),
677
- ),
678
- )
679
- ).map((entry) => entry.id);
680
- const bindingIds = !row
681
- ? []
682
- : (
683
- await db
684
- .select({ id: schema.integrationFacetBindingOwners.bindingId })
685
- .from(schema.integrationFacetBindingOwners)
686
- .where(
687
- and(
688
- eq(schema.integrationFacetBindingOwners.workspaceId, workspaceId),
689
- eq(schema.integrationFacetBindingOwners.ownerKind, "plugin"),
690
- eq(schema.integrationFacetBindingOwners.ownerId, row.pluginInstallationId),
691
- ),
692
- )
693
- ).map((entry) => entry.id);
694
- return {
695
- resolution: {
696
- key: reference.key,
697
- kind: "plugin",
698
- capabilityId: `plugin:${reference.pluginKey}`,
699
- required: reference.required,
700
- status: !row ? "missing" : exact ? "ready" : "mismatch",
701
- expectedDigest,
702
- actualDigest: row?.manifestDigest ?? null,
703
- resolvedId: exact ? row.pluginInstallationId : null,
704
- label: row?.name ?? reference.pluginKey,
705
- },
706
- facetInstallationIds: exact ? facetInstallationIds : [],
707
- bindingIds: exact ? bindingIds : [],
708
- metadata: { pluginKey: reference.pluginKey, version: reference.version },
709
- };
710
- }
711
-
712
- async function resolveSkillReference(
713
- db: Database,
714
- workspaceId: string,
715
- reference: Extract<CapabilityPackComponentReference, { kind: "skill" }>,
716
- ): Promise<ResolvedPackComponentTarget> {
717
- const rows = await db
718
- .select({
719
- facetInstallationId: schema.capabilityFacetInstallations.id,
720
- contentSha256: schema.capabilitySkillFacets.contentSha256,
721
- name: schema.capabilitySkillFacets.name,
722
- })
723
- .from(schema.capabilitySkillFacets)
724
- .innerJoin(
725
- schema.capabilityFacetInstallations,
726
- eq(schema.capabilityFacetInstallations.facetId, schema.capabilitySkillFacets.facetId),
727
- )
728
- .innerJoin(
729
- schema.capabilityPluginInstallations,
730
- eq(
731
- schema.capabilityPluginInstallations.id,
732
- schema.capabilityFacetInstallations.pluginInstallationId,
733
- ),
734
- )
735
- .where(
736
- and(
737
- eq(schema.capabilityFacetInstallations.workspaceId, workspaceId),
738
- eq(schema.capabilitySkillFacets.capabilityId, reference.capabilityId),
739
- eq(schema.capabilityFacetInstallations.status, "active"),
740
- eq(schema.capabilityPluginInstallations.status, "active"),
741
- sql`exists (
742
- select 1 from ${schema.capabilityComponentOwners} owner
743
- where owner.facet_installation_id = ${schema.capabilityFacetInstallations.id}
744
- and ${effectiveCapabilityOwnerSql(sql`owner.owner_kind`, sql`owner.owner_id`)}
745
- )`,
746
- ),
747
- )
748
- .limit(8);
749
- const exact = rows.find((row) => row.contentSha256 === reference.contentSha256);
750
- const actual = exact ?? rows[0] ?? null;
751
- return {
752
- resolution: {
753
- key: reference.key,
754
- kind: "skill",
755
- capabilityId: reference.capabilityId,
756
- required: reference.required,
757
- status: rows.length === 0 ? "missing" : exact ? "ready" : "mismatch",
758
- expectedDigest: reference.contentSha256,
759
- actualDigest: actual?.contentSha256 ?? null,
760
- resolvedId: exact?.facetInstallationId ?? null,
761
- label: actual?.name ?? reference.capabilityId,
762
- },
763
- facetInstallationIds: exact ? [exact.facetInstallationId] : [],
764
- bindingIds: [],
765
- metadata: {},
766
- };
767
- }
768
-
769
- async function resolveIntegrationReference(
770
- db: Database,
771
- workspaceId: string,
772
- reference: Extract<CapabilityPackComponentReference, { kind: "integration" }>,
773
- integrations: readonly ApiIntegrationRuntime[],
774
- ): Promise<ResolvedPackComponentTarget> {
775
- const candidates = integrations.filter(
776
- (integration) =>
777
- integration.capabilityId === reference.capabilityId &&
778
- integration.instanceKey === reference.instanceKey,
779
- );
780
- const exact = candidates.find(
781
- (integration) =>
782
- integration.revision.id === reference.revisionId &&
783
- integration.revision.contentSha256 === reference.contentSha256,
784
- );
785
- const actual = exact ?? candidates[0] ?? null;
786
- const facetInstallationIds = exact
787
- ? await integrationFacetInstallationIds(db, exact.pluginInstallationId)
788
- : [];
789
- return {
790
- resolution: {
791
- key: reference.key,
792
- kind: "integration",
793
- capabilityId: reference.capabilityId,
794
- required: reference.required,
795
- status: candidates.length === 0 ? "missing" : exact ? "ready" : "mismatch",
796
- expectedDigest: reference.contentSha256,
797
- actualDigest: actual?.revision.contentSha256 ?? null,
798
- resolvedId: exact?.instanceId ?? null,
799
- label: actual?.displayName ?? reference.capabilityId,
800
- },
801
- facetInstallationIds,
802
- bindingIds: exact ? [exact.instanceId] : [],
803
- metadata: {
804
- instanceKey: reference.instanceKey,
805
- revisionId: reference.revisionId,
806
- },
807
- };
808
- }
809
-
810
- async function resolveFacetReference(
811
- db: Database,
812
- workspaceId: string,
813
- reference: Extract<CapabilityPackComponentReference, { kind: "facet" }>,
814
- integrations: readonly ApiIntegrationRuntime[],
815
- ): Promise<ResolvedPackComponentTarget> {
816
- const integration = integrations.find(
817
- (candidate) =>
818
- candidate.capabilityId === reference.capabilityId &&
819
- candidate.instanceKey === reference.instanceKey,
820
- );
821
- if (!integration) {
822
- return missingTarget(reference, "facet", reference.capabilityId, reference.configDigest);
823
- }
824
- const [integrationFacetInstallationId] = await integrationFacetInstallationIds(
825
- db,
826
- integration.pluginInstallationId,
827
- "integration",
828
- );
829
- if (!integrationFacetInstallationId) {
830
- return missingTarget(reference, "facet", reference.capabilityId, reference.configDigest);
831
- }
832
- const [binding] = await db
833
- .select({
834
- id: schema.integrationFacetBindings.id,
835
- config: schema.integrationFacetBindings.config,
836
- status: schema.integrationFacetBindings.status,
837
- displayName: schema.integrationFacetBindings.displayName,
838
- })
839
- .from(schema.integrationFacetBindings)
840
- .innerJoin(
841
- schema.integrationFacetDefinitions,
842
- eq(schema.integrationFacetDefinitions.id, schema.integrationFacetBindings.facetDefinitionId),
843
- )
844
- .where(
845
- and(
846
- eq(schema.integrationFacetBindings.workspaceId, workspaceId),
847
- eq(
848
- schema.integrationFacetBindings.integrationFacetInstallationId,
849
- integrationFacetInstallationId,
850
- ),
851
- eq(schema.integrationFacetDefinitions.facetKey, reference.facetKey),
852
- eq(schema.integrationFacetBindings.bindingKey, reference.bindingKey),
853
- ),
854
- )
855
- .limit(1);
856
- const actualDigest = binding ? sha256(stableJson(binding.config)) : null;
857
- const exact =
858
- binding?.status === "active" &&
859
- actualDigest !== null &&
860
- actualDigest === reference.configDigest;
861
- return {
862
- resolution: {
863
- key: reference.key,
864
- kind: "facet",
865
- capabilityId: reference.capabilityId,
866
- required: reference.required,
867
- status: !binding ? "missing" : exact ? "ready" : "mismatch",
868
- expectedDigest: reference.configDigest,
869
- actualDigest,
870
- resolvedId: exact ? binding.id : null,
871
- label: binding?.displayName ?? reference.facetKey,
872
- },
873
- facetInstallationIds: exact ? [integrationFacetInstallationId] : [],
874
- bindingIds: exact ? [binding.id] : [],
875
- metadata: {
876
- instanceKey: reference.instanceKey,
877
- facetKey: reference.facetKey,
878
- bindingKey: reference.bindingKey,
879
- },
880
- };
881
- }
882
-
883
- async function integrationFacetInstallationIds(
884
- db: Database,
885
- pluginInstallationId: string,
886
- onlyKind?: "integration" | "api",
887
- ): Promise<string[]> {
888
- const rows = await db
889
- .select({ id: schema.capabilityFacetInstallations.id, kind: schema.capabilityFacets.kind })
890
- .from(schema.capabilityFacetInstallations)
891
- .innerJoin(
892
- schema.capabilityFacets,
893
- eq(schema.capabilityFacets.id, schema.capabilityFacetInstallations.facetId),
894
- )
895
- .where(
896
- and(
897
- eq(schema.capabilityFacetInstallations.pluginInstallationId, pluginInstallationId),
898
- onlyKind
899
- ? eq(schema.capabilityFacets.kind, onlyKind)
900
- : inArray(schema.capabilityFacets.kind, ["integration", "api"]),
901
- ),
902
- );
903
- return rows.map((row) => row.id);
904
- }
905
-
906
- async function listPackInstallationComponentsInRlsContext(
907
- scopedDb: Database,
908
- workspaceId: string,
909
- packInstallationId: string,
910
- ): Promise<StoredPackInstallationComponent[]> {
911
- const rows = await scopedDb
912
- .select()
913
- .from(schema.packInstallationComponents)
914
- .where(
915
- and(
916
- eq(schema.packInstallationComponents.workspaceId, workspaceId),
917
- eq(schema.packInstallationComponents.packInstallationId, packInstallationId),
918
- ),
919
- )
920
- .orderBy(asc(schema.packInstallationComponents.componentKey));
921
- return rows.map(mapStoredPackComponent);
922
- }
923
-
924
- function missingTarget(
925
- reference: { key: string; required: boolean },
926
- kind: PackComponentKind,
927
- capabilityId: string,
928
- expectedDigest: string,
929
- ): ResolvedPackComponentTarget {
930
- return {
931
- resolution: {
932
- key: reference.key,
933
- kind,
934
- capabilityId,
935
- required: reference.required,
936
- status: "missing",
937
- expectedDigest,
938
- actualDigest: null,
939
- resolvedId: null,
940
- label: capabilityId,
941
- },
942
- facetInstallationIds: [],
943
- bindingIds: [],
944
- metadata: {},
945
- };
946
- }
947
-
948
- function mapStoredPackComponent(
949
- row: typeof schema.packInstallationComponents.$inferSelect,
950
- ): StoredPackInstallationComponent {
951
- if (
952
- row.kind !== "plugin" &&
953
- row.kind !== "skill" &&
954
- row.kind !== "integration" &&
955
- row.kind !== "facet" &&
956
- row.kind !== "inline_skill"
957
- ) {
958
- throw new Error(`Unknown Pack component kind: ${row.kind}`);
959
- }
960
- return {
961
- id: row.id,
962
- packInstallationId: row.packInstallationId,
963
- key: row.componentKey,
964
- kind: row.kind,
965
- capabilityId: row.capabilityId,
966
- resolvedId: row.resolvedId,
967
- digest: row.digest,
968
- metadata: row.metadata,
969
- };
970
- }
971
-
972
- function stringArray(value: unknown): string[] {
973
- return Array.isArray(value)
974
- ? value.filter((entry): entry is string => typeof entry === "string")
975
- : [];
976
- }
977
-
978
- function sha256(value: string): string {
979
- return createHash("sha256").update(value).digest("hex");
980
- }