@agent-native/core 0.90.3 → 0.90.4

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 (191) hide show
  1. package/bin/agent-native.js +25 -3
  2. package/corpus/README.md +1 -1
  3. package/corpus/core/CHANGELOG.md +9 -0
  4. package/corpus/core/bin/agent-native.js +25 -3
  5. package/corpus/core/package.json +1 -1
  6. package/corpus/core/src/agent/engine/index.ts +1 -0
  7. package/corpus/core/src/agent/engine/registry.ts +63 -2
  8. package/corpus/core/src/cli/create.ts +35 -0
  9. package/corpus/core/src/cli/design-connect.ts +248 -0
  10. package/corpus/core/src/cli/index.ts +84 -7
  11. package/corpus/core/src/cli/workspacify.ts +34 -0
  12. package/corpus/core/src/client/history/VersionHistoryPanel.tsx +77 -47
  13. package/corpus/core/src/client/history/index.ts +3 -0
  14. package/corpus/core/src/client/history/use-history.ts +28 -0
  15. package/corpus/core/src/client/index.ts +8 -0
  16. package/corpus/core/src/client/review/index.ts +5 -0
  17. package/corpus/core/src/client/review/use-review.ts +40 -2
  18. package/corpus/core/src/history/actions/create-resource-version.ts +11 -8
  19. package/corpus/core/src/history/index.ts +0 -1
  20. package/corpus/core/src/history/registry.ts +24 -12
  21. package/corpus/core/src/history/store.ts +84 -53
  22. package/corpus/core/src/review/actions/consume-review-feedback.ts +15 -5
  23. package/corpus/core/src/review/actions/delete-review-comment.ts +15 -3
  24. package/corpus/core/src/review/actions/resolve-review-thread.ts +12 -5
  25. package/corpus/core/src/review/index.ts +0 -5
  26. package/corpus/core/src/review/registry.ts +24 -12
  27. package/corpus/core/src/review/store.ts +10 -7
  28. package/corpus/core/src/server/agent-chat-plugin.ts +6 -0
  29. package/corpus/core/src/server/credential-provider.ts +13 -3
  30. package/corpus/templates/assets/actions/_preset-skeleton-validation.ts +11 -11
  31. package/corpus/templates/assets/actions/generate-image.ts +64 -28
  32. package/corpus/templates/assets/app/components/generation/GenerationResults.tsx +1 -1
  33. package/corpus/templates/assets/app/routes/brand-kits.$id_.presets.$presetId.tsx +91 -74
  34. package/corpus/templates/assets/server/lib/generation.ts +29 -4
  35. package/corpus/templates/assets/server/lib/image-processing.ts +131 -0
  36. package/corpus/templates/calendar/.agents/skills/event-management/SKILL.md +24 -2
  37. package/corpus/templates/calendar/AGENTS.md +3 -0
  38. package/corpus/templates/calendar/actions/create-event.ts +8 -34
  39. package/corpus/templates/calendar/actions/event-action-helpers.ts +52 -0
  40. package/corpus/templates/calendar/actions/manage-event-draft.ts +7 -34
  41. package/corpus/templates/calendar/actions/update-event.ts +10 -23
  42. package/corpus/templates/calendar/app/components/calendar/AttendeeAutocomplete.tsx +47 -0
  43. package/corpus/templates/calendar/app/components/calendar/CreateEventDialog.tsx +23 -0
  44. package/corpus/templates/calendar/app/components/calendar/EventAttendeesSection.tsx +59 -2
  45. package/corpus/templates/calendar/app/components/calendar/EventDetailPanel.tsx +40 -1
  46. package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +34 -1
  47. package/corpus/templates/calendar/app/hooks/use-events.ts +6 -0
  48. package/corpus/templates/calendar/app/i18n/zh-TW.ts +4 -0
  49. package/corpus/templates/calendar/app/i18n-data.ts +40 -0
  50. package/corpus/templates/calendar/changelog/2026-07-07-you-can-mark-event-guests-as-optional-while-inviting-them-or.md +6 -0
  51. package/corpus/templates/calendar/server/handlers/events.ts +1 -0
  52. package/corpus/templates/calendar/server/lib/google-calendar.ts +4 -0
  53. package/corpus/templates/calendar/server/plugins/agent-chat.ts +1 -1
  54. package/corpus/templates/calendar/shared/api.ts +2 -0
  55. package/corpus/templates/clips/.agents/skills/ai-video-tools/SKILL.md +29 -3
  56. package/corpus/templates/clips/actions/generate-workflow.ts +19 -8
  57. package/corpus/templates/clips/actions/get-clips-ai-prefs.ts +36 -0
  58. package/corpus/templates/clips/actions/lib/clips-ai-prefs.ts +28 -0
  59. package/corpus/templates/clips/actions/regenerate-chapters.ts +21 -7
  60. package/corpus/templates/clips/actions/regenerate-summary.ts +26 -8
  61. package/corpus/templates/clips/actions/regenerate-title.ts +44 -7
  62. package/corpus/templates/clips/actions/update-clips-ai-prefs.ts +50 -0
  63. package/corpus/templates/clips/app/components/meetings/meeting-card.tsx +7 -2
  64. package/corpus/templates/clips/app/hooks/use-auto-title.ts +25 -10
  65. package/corpus/templates/clips/app/i18n/ar-SA.ts +28 -6
  66. package/corpus/templates/clips/app/i18n/de-DE.ts +28 -6
  67. package/corpus/templates/clips/app/i18n/en-US.ts +29 -6
  68. package/corpus/templates/clips/app/i18n/es-ES.ts +29 -6
  69. package/corpus/templates/clips/app/i18n/fr-FR.ts +30 -6
  70. package/corpus/templates/clips/app/i18n/hi-IN.ts +26 -6
  71. package/corpus/templates/clips/app/i18n/ja-JP.ts +27 -6
  72. package/corpus/templates/clips/app/i18n/ko-KR.ts +28 -6
  73. package/corpus/templates/clips/app/i18n/pt-BR.ts +28 -6
  74. package/corpus/templates/clips/app/i18n/zh-CN.ts +26 -6
  75. package/corpus/templates/clips/app/i18n/zh-TW.ts +25 -6
  76. package/corpus/templates/clips/app/routes/_app.meetings._index.tsx +73 -0
  77. package/corpus/templates/clips/app/routes/_app.settings._index.tsx +1 -0
  78. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +70 -2
  79. package/corpus/templates/clips/changelog/2026-07-07-ai-tools-can-include-the-full-video-not-just-the-transcript-.md +6 -0
  80. package/corpus/templates/clips/changelog/2026-07-07-clips-desktop-now-surfaces-meetings-and-dictate-directly-in-.md +6 -0
  81. package/corpus/templates/clips/changelog/2026-07-07-meeting-notes-now-explain-exactly-how-to-start-granola-style.md +6 -0
  82. package/corpus/templates/clips/changelog/2026-07-07-meeting-start-alerts-now-include-separate-start-notes-and-jo.md +6 -0
  83. package/corpus/templates/clips/changelog/2026-07-07-recordings-start-more-predictably-and-newly-saved-clips-refr.md +6 -0
  84. package/corpus/templates/clips/chrome-extension/public/manifest.json +1 -1
  85. package/corpus/templates/clips/desktop/src/app.tsx +435 -105
  86. package/corpus/templates/clips/desktop/src/lib/recorder.ts +27 -21
  87. package/corpus/templates/clips/desktop/src/overlays/meeting-notification.tsx +23 -22
  88. package/corpus/templates/clips/desktop/src/styles.css +167 -2
  89. package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +1 -1
  90. package/corpus/templates/clips/desktop/src-tauri/src/notifications.rs +3 -7
  91. package/corpus/templates/clips/desktop/src-tauri/src/tray_meetings.rs +5 -4
  92. package/corpus/templates/clips/server/routes/_agent-native/clips/user-prefs.put.ts +16 -8
  93. package/corpus/templates/clips/shared/clips-ai-prefs.ts +81 -0
  94. package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +16 -1
  95. package/corpus/templates/design/actions/add-localhost-screens.ts +1 -0
  96. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +345 -11
  97. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +89 -14
  98. package/corpus/templates/design/app/components/design/bridge-security.ts +7 -1
  99. package/corpus/templates/design/app/components/design/multi-screen/types.ts +1 -1
  100. package/corpus/templates/design/app/i18n/zh-TW.ts +3 -0
  101. package/corpus/templates/design/app/i18n-data.ts +41 -0
  102. package/corpus/templates/design/changelog/2026-07-07-local-visual-edit-uses-live-app-iframes-for-click-to-edit-pr.md +6 -0
  103. package/dist/agent/engine/index.d.ts +1 -1
  104. package/dist/agent/engine/index.d.ts.map +1 -1
  105. package/dist/agent/engine/index.js +1 -1
  106. package/dist/agent/engine/index.js.map +1 -1
  107. package/dist/agent/engine/registry.d.ts +14 -0
  108. package/dist/agent/engine/registry.d.ts.map +1 -1
  109. package/dist/agent/engine/registry.js +56 -2
  110. package/dist/agent/engine/registry.js.map +1 -1
  111. package/dist/cli/create.d.ts.map +1 -1
  112. package/dist/cli/create.js +31 -0
  113. package/dist/cli/create.js.map +1 -1
  114. package/dist/cli/design-connect.d.ts.map +1 -1
  115. package/dist/cli/design-connect.js +186 -0
  116. package/dist/cli/design-connect.js.map +1 -1
  117. package/dist/cli/index.js +76 -9
  118. package/dist/cli/index.js.map +1 -1
  119. package/dist/cli/workspacify.d.ts.map +1 -1
  120. package/dist/cli/workspacify.js +30 -0
  121. package/dist/cli/workspacify.js.map +1 -1
  122. package/dist/client/history/VersionHistoryPanel.d.ts +1 -1
  123. package/dist/client/history/VersionHistoryPanel.d.ts.map +1 -1
  124. package/dist/client/history/VersionHistoryPanel.js +12 -5
  125. package/dist/client/history/VersionHistoryPanel.js.map +1 -1
  126. package/dist/client/history/index.d.ts +1 -1
  127. package/dist/client/history/index.d.ts.map +1 -1
  128. package/dist/client/history/index.js +1 -1
  129. package/dist/client/history/index.js.map +1 -1
  130. package/dist/client/history/use-history.d.ts +12 -0
  131. package/dist/client/history/use-history.d.ts.map +1 -1
  132. package/dist/client/history/use-history.js +6 -0
  133. package/dist/client/history/use-history.js.map +1 -1
  134. package/dist/client/index.d.ts +2 -2
  135. package/dist/client/index.d.ts.map +1 -1
  136. package/dist/client/index.js +2 -2
  137. package/dist/client/index.js.map +1 -1
  138. package/dist/client/review/index.d.ts +1 -1
  139. package/dist/client/review/index.d.ts.map +1 -1
  140. package/dist/client/review/index.js +1 -1
  141. package/dist/client/review/index.js.map +1 -1
  142. package/dist/client/review/use-review.d.ts +23 -0
  143. package/dist/client/review/use-review.d.ts.map +1 -1
  144. package/dist/client/review/use-review.js +8 -0
  145. package/dist/client/review/use-review.js.map +1 -1
  146. package/dist/collab/awareness.d.ts +2 -2
  147. package/dist/collab/awareness.d.ts.map +1 -1
  148. package/dist/collab/routes.d.ts +1 -1
  149. package/dist/history/actions/create-resource-version.js +7 -4
  150. package/dist/history/actions/create-resource-version.js.map +1 -1
  151. package/dist/history/index.d.ts +1 -1
  152. package/dist/history/index.d.ts.map +1 -1
  153. package/dist/history/index.js +1 -1
  154. package/dist/history/index.js.map +1 -1
  155. package/dist/history/registry.d.ts.map +1 -1
  156. package/dist/history/registry.js +14 -12
  157. package/dist/history/registry.js.map +1 -1
  158. package/dist/history/store.d.ts.map +1 -1
  159. package/dist/history/store.js +74 -49
  160. package/dist/history/store.js.map +1 -1
  161. package/dist/observability/routes.d.ts +3 -3
  162. package/dist/progress/routes.d.ts +1 -1
  163. package/dist/review/actions/consume-review-feedback.d.ts +1 -0
  164. package/dist/review/actions/consume-review-feedback.js +8 -2
  165. package/dist/review/actions/consume-review-feedback.js.map +1 -1
  166. package/dist/review/actions/delete-review-comment.d.ts +2 -1
  167. package/dist/review/actions/delete-review-comment.js +11 -3
  168. package/dist/review/actions/delete-review-comment.js.map +1 -1
  169. package/dist/review/actions/resolve-review-thread.d.ts +2 -1
  170. package/dist/review/actions/resolve-review-thread.js +5 -2
  171. package/dist/review/actions/resolve-review-thread.js.map +1 -1
  172. package/dist/review/index.d.ts +1 -1
  173. package/dist/review/index.d.ts.map +1 -1
  174. package/dist/review/index.js +1 -1
  175. package/dist/review/index.js.map +1 -1
  176. package/dist/review/registry.d.ts.map +1 -1
  177. package/dist/review/registry.js +14 -12
  178. package/dist/review/registry.js.map +1 -1
  179. package/dist/review/store.d.ts +3 -3
  180. package/dist/review/store.d.ts.map +1 -1
  181. package/dist/review/store.js +7 -4
  182. package/dist/review/store.js.map +1 -1
  183. package/dist/secrets/routes.d.ts +9 -9
  184. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  185. package/dist/server/agent-chat-plugin.js +5 -0
  186. package/dist/server/agent-chat-plugin.js.map +1 -1
  187. package/dist/server/credential-provider.d.ts +2 -0
  188. package/dist/server/credential-provider.d.ts.map +1 -1
  189. package/dist/server/credential-provider.js +13 -3
  190. package/dist/server/credential-provider.js.map +1 -1
  191. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"use-review.d.ts","sourceRoot":"","sources":["../../../src/client/review/use-review.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,iBAAiB,EACjB,aAAa,EACb,sBAAsB,EACtB,YAAY,EACZ,iBAAiB,EAClB,MAAM,uBAAuB,CAAC;AAG/B,MAAM,WAAW,wBAAwB;IACvC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,YAAY,EAAE,iBAAiB,GAAG,IAAI,CAAC;CACxC;AAED,MAAM,WAAW,wBAAwB;IACvC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,IAAI,CAAC,EAAE,iBAAiB,CAAC;IACzB,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,gBAAgB,CAAC,EAAE,sBAAsB,GAAG,IAAI,CAAC;IACjD,QAAQ,CAAC,EAAE,aAAa,EAAE,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,uBAAuB;IACtC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,gBAAgB,CAAC,EAAE,sBAAsB,GAAG,IAAI,CAAC;IACjD,QAAQ,CAAC,EAAE,aAAa,EAAE,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,wBAAwB;IACvC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,wBAAwB;IACvC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,YAAY,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,wBAAwB,EAChC,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,4FAUhC;AAED,wBAAgB,sBAAsB,+GAIrC;AAED,wBAAgB,qBAAqB,8GAIpC;AAED,wBAAgB,sBAAsB;cAEtB,MAAM;cAAY,IAAI;6CAGrC;AAED,wBAAgB,sBAAsB;eAErB,MAAM;aAAW,IAAI;6CAGrC;AAED,wBAAgB,kBAAkB,+GAIjC"}
1
+ {"version":3,"file":"use-review.d.ts","sourceRoot":"","sources":["../../../src/client/review/use-review.ts"],"names":[],"mappings":"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"}
@@ -4,6 +4,11 @@ export function useReviewComments(params, options) {
4
4
  enabled: options?.enabled ?? Boolean(params.resourceType && params.resourceId),
5
5
  });
6
6
  }
7
+ export function useReviewFeedback(params, options) {
8
+ return useActionQuery("get-review-feedback", params, {
9
+ enabled: options?.enabled ?? Boolean(params.resourceType && params.resourceId),
10
+ });
11
+ }
7
12
  export function useCreateReviewComment() {
8
13
  return useActionMutation("create-review-comment");
9
14
  }
@@ -16,6 +21,9 @@ export function useResolveReviewThread() {
16
21
  export function useDeleteReviewComment() {
17
22
  return useActionMutation("delete-review-comment");
18
23
  }
24
+ export function useConsumeReviewFeedback() {
25
+ return useActionMutation("consume-review-feedback");
26
+ }
19
27
  export function useSetReviewStatus() {
20
28
  return useActionMutation("set-review-status");
21
29
  }
@@ -1 +1 @@
1
- {"version":3,"file":"use-review.js","sourceRoot":"","sources":["../../../src/client/review/use-review.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AA6DrE,MAAM,UAAU,iBAAiB,CAC/B,MAAgC,EAChC,OAA+B;IAE/B,OAAO,cAAc,CACnB,sBAAsB,EACtB,MAAM,EACN;QACE,OAAO,EACL,OAAO,EAAE,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,YAAY,IAAI,MAAM,CAAC,UAAU,CAAC;KACxE,CACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,sBAAsB;IACpC,OAAO,iBAAiB,CACtB,uBAAuB,CACxB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,qBAAqB;IACnC,OAAO,iBAAiB,CACtB,sBAAsB,CACvB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,sBAAsB;IACpC,OAAO,iBAAiB,CAGtB,uBAAuB,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,sBAAsB;IACpC,OAAO,iBAAiB,CAGtB,uBAAuB,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,OAAO,iBAAiB,CACtB,mBAAmB,CACpB,CAAC;AACJ,CAAC","sourcesContent":["import type {\n ReviewComment,\n ReviewCommentKind,\n ReviewMention,\n ReviewResolutionTarget,\n ReviewStatus,\n ReviewStatusEntry,\n} from \"../../review/types.js\";\nimport { useActionMutation, useActionQuery } from \"../use-action.js\";\n\nexport interface ListReviewCommentsParams {\n resourceType: string;\n resourceId: string;\n includeResolved?: boolean;\n includeDeleted?: boolean;\n targetId?: string | null;\n limit?: number;\n}\n\nexport interface ListReviewCommentsResult {\n comments: ReviewComment[];\n reviewStatus: ReviewStatusEntry | null;\n}\n\nexport interface CreateReviewCommentInput {\n resourceType: string;\n resourceId: string;\n targetId?: string | null;\n kind?: ReviewCommentKind;\n anchor?: unknown | null;\n body: string;\n authorName?: string | null;\n resolutionTarget?: ReviewResolutionTarget | null;\n mentions?: ReviewMention[];\n metadata?: Record<string, unknown>;\n}\n\nexport interface ReplyReviewCommentInput {\n resourceType: string;\n resourceId: string;\n commentId: string;\n body: string;\n authorName?: string | null;\n resolutionTarget?: ReviewResolutionTarget | null;\n mentions?: ReviewMention[];\n metadata?: Record<string, unknown>;\n}\n\nexport interface ResolveReviewThreadInput {\n resourceType: string;\n resourceId: string;\n threadId?: string;\n commentId?: string;\n}\n\nexport interface DeleteReviewCommentInput {\n resourceType: string;\n resourceId: string;\n commentId: string;\n}\n\nexport interface SetReviewStatusInput {\n resourceType: string;\n resourceId: string;\n status: ReviewStatus;\n note?: string | null;\n metadata?: Record<string, unknown>;\n}\n\nexport function useReviewComments(\n params: ListReviewCommentsParams,\n options?: { enabled?: boolean },\n) {\n return useActionQuery<ListReviewCommentsResult>(\n \"list-review-comments\",\n params,\n {\n enabled:\n options?.enabled ?? Boolean(params.resourceType && params.resourceId),\n },\n );\n}\n\nexport function useCreateReviewComment() {\n return useActionMutation<ReviewComment, CreateReviewCommentInput>(\n \"create-review-comment\",\n );\n}\n\nexport function useReplyReviewComment() {\n return useActionMutation<ReviewComment, ReplyReviewCommentInput>(\n \"reply-review-comment\",\n );\n}\n\nexport function useResolveReviewThread() {\n return useActionMutation<\n { threadId: string; resolved: true },\n ResolveReviewThreadInput\n >(\"resolve-review-thread\");\n}\n\nexport function useDeleteReviewComment() {\n return useActionMutation<\n { commentId: string; deleted: true },\n DeleteReviewCommentInput\n >(\"delete-review-comment\");\n}\n\nexport function useSetReviewStatus() {\n return useActionMutation<ReviewStatusEntry, SetReviewStatusInput>(\n \"set-review-status\",\n );\n}\n"]}
1
+ {"version":3,"file":"use-review.js","sourceRoot":"","sources":["../../../src/client/review/use-review.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AA8ErE,MAAM,UAAU,iBAAiB,CAC/B,MAAgC,EAChC,OAA+B;IAE/B,OAAO,cAAc,CACnB,sBAAsB,EACtB,MAAM,EACN;QACE,OAAO,EACL,OAAO,EAAE,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,YAAY,IAAI,MAAM,CAAC,UAAU,CAAC;KACxE,CACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,MAA+B,EAC/B,OAA+B;IAE/B,OAAO,cAAc,CACnB,qBAAqB,EACrB,MAAM,EACN;QACE,OAAO,EACL,OAAO,EAAE,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,YAAY,IAAI,MAAM,CAAC,UAAU,CAAC;KACxE,CACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,sBAAsB;IACpC,OAAO,iBAAiB,CACtB,uBAAuB,CACxB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,qBAAqB;IACnC,OAAO,iBAAiB,CACtB,sBAAsB,CACvB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,sBAAsB;IACpC,OAAO,iBAAiB,CAGtB,uBAAuB,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,sBAAsB;IACpC,OAAO,iBAAiB,CAGtB,uBAAuB,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,wBAAwB;IACtC,OAAO,iBAAiB,CAGtB,yBAAyB,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,OAAO,iBAAiB,CACtB,mBAAmB,CACpB,CAAC;AACJ,CAAC","sourcesContent":["import type {\n ReviewComment,\n ReviewCommentKind,\n ReviewMention,\n ReviewResolutionTarget,\n ReviewStatus,\n ReviewStatusEntry,\n} from \"../../review/types.js\";\nimport { useActionMutation, useActionQuery } from \"../use-action.js\";\n\nexport interface ListReviewCommentsParams {\n resourceType: string;\n resourceId: string;\n includeResolved?: boolean;\n includeDeleted?: boolean;\n targetId?: string | null;\n limit?: number;\n}\n\nexport interface ListReviewCommentsResult {\n comments: ReviewComment[];\n reviewStatus: ReviewStatusEntry | null;\n}\n\nexport interface GetReviewFeedbackParams {\n resourceType: string;\n resourceId: string;\n includeHumanTargeted?: boolean;\n limit?: number;\n}\n\nexport interface GetReviewFeedbackResult {\n comments: ReviewComment[];\n}\n\nexport interface CreateReviewCommentInput {\n resourceType: string;\n resourceId: string;\n targetId?: string | null;\n kind?: ReviewCommentKind;\n anchor?: unknown | null;\n body: string;\n authorName?: string | null;\n resolutionTarget?: ReviewResolutionTarget | null;\n mentions?: ReviewMention[];\n metadata?: Record<string, unknown>;\n}\n\nexport interface ReplyReviewCommentInput {\n resourceType: string;\n resourceId: string;\n commentId: string;\n body: string;\n authorName?: string | null;\n resolutionTarget?: ReviewResolutionTarget | null;\n mentions?: ReviewMention[];\n metadata?: Record<string, unknown>;\n}\n\nexport interface ResolveReviewThreadInput {\n resourceType: string;\n resourceId: string;\n threadId?: string;\n commentId?: string;\n}\n\nexport interface DeleteReviewCommentInput {\n resourceType: string;\n resourceId: string;\n commentId: string;\n}\n\nexport interface ConsumeReviewFeedbackInput {\n resourceType: string;\n resourceId: string;\n commentIds: string[];\n}\n\nexport interface SetReviewStatusInput {\n resourceType: string;\n resourceId: string;\n status: ReviewStatus;\n note?: string | null;\n metadata?: Record<string, unknown>;\n}\n\nexport function useReviewComments(\n params: ListReviewCommentsParams,\n options?: { enabled?: boolean },\n) {\n return useActionQuery<ListReviewCommentsResult>(\n \"list-review-comments\",\n params,\n {\n enabled:\n options?.enabled ?? Boolean(params.resourceType && params.resourceId),\n },\n );\n}\n\nexport function useReviewFeedback(\n params: GetReviewFeedbackParams,\n options?: { enabled?: boolean },\n) {\n return useActionQuery<GetReviewFeedbackResult>(\n \"get-review-feedback\",\n params,\n {\n enabled:\n options?.enabled ?? Boolean(params.resourceType && params.resourceId),\n },\n );\n}\n\nexport function useCreateReviewComment() {\n return useActionMutation<ReviewComment, CreateReviewCommentInput>(\n \"create-review-comment\",\n );\n}\n\nexport function useReplyReviewComment() {\n return useActionMutation<ReviewComment, ReplyReviewCommentInput>(\n \"reply-review-comment\",\n );\n}\n\nexport function useResolveReviewThread() {\n return useActionMutation<\n { threadId: string; resolved: true; updatedCount: number },\n ResolveReviewThreadInput\n >(\"resolve-review-thread\");\n}\n\nexport function useDeleteReviewComment() {\n return useActionMutation<\n { commentId: string; deleted: true; updatedCount: number },\n DeleteReviewCommentInput\n >(\"delete-review-comment\");\n}\n\nexport function useConsumeReviewFeedback() {\n return useActionMutation<\n { consumedCommentIds: string[]; updatedCount: number },\n ConsumeReviewFeedbackInput\n >(\"consume-review-feedback\");\n}\n\nexport function useSetReviewStatus() {\n return useActionMutation<ReviewStatusEntry, SetReviewStatusInput>(\n \"set-review-status\",\n );\n}\n"]}
@@ -60,11 +60,11 @@ export declare const postAwareness: import("h3").EventHandlerWithFetch<import("h
60
60
  error: string;
61
61
  states?: undefined;
62
62
  } | {
63
- error?: undefined;
64
63
  states: {
65
64
  clientId: number;
66
65
  state: string;
67
66
  }[];
67
+ error?: undefined;
68
68
  }>>;
69
69
  /**
70
70
  * GET /_agent-native/collab/:docId/users
@@ -75,10 +75,10 @@ export declare const getActiveUsers: import("h3").EventHandlerWithFetch<import("
75
75
  error: string;
76
76
  users?: undefined;
77
77
  } | {
78
- error?: undefined;
79
78
  users: {
80
79
  clientId: number;
81
80
  lastSeen: number;
82
81
  }[];
82
+ error?: undefined;
83
83
  }>>;
84
84
  //# sourceMappingURL=awareness.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"awareness.d.ts","sourceRoot":"","sources":["../../src/collab/awareness.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAe3C,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAOD,eAAO,MAAM,sBAAsB,EAAG,kBAA2B,CAAC;AAElE,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,WAAW,CAAC;IACpB,IAAI,EAAE,kBAAkB,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,MAAM,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnD,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAOD,wBAAgB,mBAAmB,IAAI,YAAY,CAElD;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,cAAc,GAAG,SAAS,GAChC,IAAI,CAON;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,EAClD,KAAK,CAAC,EAAE,cAAc,GACrB,IAAI,CAgBN;AAKD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAO1E;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,IAAI,CAOnE;AA6BD;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa;;;;;;kBAqDa,MAAM;eAAS,MAAM;;GAoB1D,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,cAAc;;;;;;kBAYM,MAAM;kBAAY,MAAM;;GAMvD,CAAC"}
1
+ {"version":3,"file":"awareness.d.ts","sourceRoot":"","sources":["../../src/collab/awareness.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAe3C,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAOD,eAAO,MAAM,sBAAsB,EAAG,kBAA2B,CAAC;AAElE,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,WAAW,CAAC;IACpB,IAAI,EAAE,kBAAkB,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,MAAM,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnD,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAOD,wBAAgB,mBAAmB,IAAI,YAAY,CAElD;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,cAAc,GAAG,SAAS,GAChC,IAAI,CAON;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,EAClD,KAAK,CAAC,EAAE,cAAc,GACrB,IAAI,CAgBN;AAKD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAO1E;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,IAAI,CAOnE;AA6BD;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa;;;;;kBAqDa,MAAM;eAAS,MAAM;;;GAoB1D,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,cAAc;;;;;kBAYM,MAAM;kBAAY,MAAM;;;GAMvD,CAAC"}
@@ -26,8 +26,8 @@ export declare const getCollabState: import("h3").EventHandlerWithFetch<import("
26
26
  * Body: { update: string (base64), requestSource?: string }
27
27
  */
28
28
  export declare const postCollabUpdate: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
29
- error: string;
30
29
  ok?: undefined;
30
+ error: string;
31
31
  } | {
32
32
  error?: undefined;
33
33
  ok: boolean;
@@ -17,14 +17,17 @@ export default defineAction({
17
17
  const actionCtx = ctx;
18
18
  const access = await assertVersionedResourceAccess(args.resourceType, args.resourceId, actionCtx, "editor");
19
19
  const registration = getVersionedResource(args.resourceType);
20
- const snapshot = args.snapshot !== undefined
21
- ? args.snapshot
22
- : await registration?.getSnapshot?.({
20
+ // Prefer the registered server snapshot when available so editors/agents
21
+ // cannot plant arbitrary restore payloads for managed resource types.
22
+ const serverSnapshot = registration?.getSnapshot
23
+ ? await registration.getSnapshot({
23
24
  resourceType: args.resourceType,
24
25
  resourceId: args.resourceId,
25
26
  ctx: actionCtx,
26
27
  access,
27
- });
28
+ })
29
+ : undefined;
30
+ const snapshot = serverSnapshot !== undefined ? serverSnapshot : args.snapshot;
28
31
  if (snapshot === undefined) {
29
32
  throw new Error(`No snapshot was provided and ${args.resourceType} has no getSnapshot history handler`);
30
33
  }
@@ -1 +1 @@
1
- {"version":3,"file":"create-resource-version.js","sourceRoot":"","sources":["../../../src/history/actions/create-resource-version.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from \"zod\";\n\nimport { defineAction } from \"../../action.js\";\nimport {\n assertVersionedResourceAccess,\n getVersionedResource,\n normalizeHistoryVisibility,\n} from \"../registry.js\";\nimport { insertResourceVersion } from \"../store.js\";\nimport type { HistoryActorKind, VersionedResourceContext } from \"../types.js\";\n\nconst schema = z.object({\n resourceType: z.string().min(1),\n resourceId: z.string().min(1),\n title: z.string().optional(),\n summary: z.string().optional(),\n snapshot: z.unknown().optional(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n});\n\nexport default defineAction({\n description: \"Create a reusable version-history snapshot for a resource.\",\n schema,\n run: async (args, ctx) => {\n const actionCtx = ctx as VersionedResourceContext | undefined;\n const access = await assertVersionedResourceAccess(\n args.resourceType,\n args.resourceId,\n actionCtx,\n \"editor\",\n );\n const registration = getVersionedResource(args.resourceType);\n const snapshot =\n args.snapshot !== undefined\n ? args.snapshot\n : await registration?.getSnapshot?.({\n resourceType: args.resourceType,\n resourceId: args.resourceId,\n ctx: actionCtx,\n access,\n });\n\n if (snapshot === undefined) {\n throw new Error(\n `No snapshot was provided and ${args.resourceType} has no getSnapshot history handler`,\n );\n }\n\n return insertResourceVersion({\n resourceType: args.resourceType,\n resourceId: args.resourceId,\n createdBy: actionCtx?.userEmail ?? null,\n actorKind: actorKindFromContext(actionCtx),\n ownerEmail: access.ownerEmail ?? actionCtx?.userEmail ?? null,\n orgId: access.orgId ?? actionCtx?.orgId ?? null,\n visibility: normalizeHistoryVisibility(access.visibility),\n title: args.title,\n summary: args.summary,\n snapshot,\n metadata: args.metadata,\n });\n },\n audit: {\n target: (args, result) => {\n const version = result as {\n ownerEmail?: string | null;\n orgId?: string | null;\n visibility?: \"private\" | \"org\" | \"public\";\n };\n return {\n type: args.resourceType,\n id: args.resourceId,\n ownerEmail: version.ownerEmail,\n orgId: version.orgId,\n visibility: version.visibility,\n };\n },\n },\n});\n\nfunction actorKindFromContext(\n ctx: VersionedResourceContext | undefined,\n): HistoryActorKind {\n const caller = typeof ctx?.caller === \"string\" ? ctx.caller : \"\";\n if (caller === \"agent\" || caller === \"tool\") {\n return \"agent\";\n }\n return ctx?.userEmail ? \"human\" : \"system\";\n}\n"]}
1
+ {"version":3,"file":"create-resource-version.js","sourceRoot":"","sources":["../../../src/history/actions/create-resource-version.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from \"zod\";\n\nimport { defineAction } from \"../../action.js\";\nimport {\n assertVersionedResourceAccess,\n getVersionedResource,\n normalizeHistoryVisibility,\n} from \"../registry.js\";\nimport { insertResourceVersion } from \"../store.js\";\nimport type { HistoryActorKind, VersionedResourceContext } from \"../types.js\";\n\nconst schema = z.object({\n resourceType: z.string().min(1),\n resourceId: z.string().min(1),\n title: z.string().optional(),\n summary: z.string().optional(),\n snapshot: z.unknown().optional(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n});\n\nexport default defineAction({\n description: \"Create a reusable version-history snapshot for a resource.\",\n schema,\n run: async (args, ctx) => {\n const actionCtx = ctx as VersionedResourceContext | undefined;\n const access = await assertVersionedResourceAccess(\n args.resourceType,\n args.resourceId,\n actionCtx,\n \"editor\",\n );\n const registration = getVersionedResource(args.resourceType);\n // Prefer the registered server snapshot when available so editors/agents\n // cannot plant arbitrary restore payloads for managed resource types.\n const serverSnapshot = registration?.getSnapshot\n ? await registration.getSnapshot({\n resourceType: args.resourceType,\n resourceId: args.resourceId,\n ctx: actionCtx,\n access,\n })\n : undefined;\n const snapshot =\n serverSnapshot !== undefined ? serverSnapshot : args.snapshot;\n\n if (snapshot === undefined) {\n throw new Error(\n `No snapshot was provided and ${args.resourceType} has no getSnapshot history handler`,\n );\n }\n\n return insertResourceVersion({\n resourceType: args.resourceType,\n resourceId: args.resourceId,\n createdBy: actionCtx?.userEmail ?? null,\n actorKind: actorKindFromContext(actionCtx),\n ownerEmail: access.ownerEmail ?? actionCtx?.userEmail ?? null,\n orgId: access.orgId ?? actionCtx?.orgId ?? null,\n visibility: normalizeHistoryVisibility(access.visibility),\n title: args.title,\n summary: args.summary,\n snapshot,\n metadata: args.metadata,\n });\n },\n audit: {\n target: (args, result) => {\n const version = result as {\n ownerEmail?: string | null;\n orgId?: string | null;\n visibility?: \"private\" | \"org\" | \"public\";\n };\n return {\n type: args.resourceType,\n id: args.resourceId,\n ownerEmail: version.ownerEmail,\n orgId: version.orgId,\n visibility: version.visibility,\n };\n },\n },\n});\n\nfunction actorKindFromContext(\n ctx: VersionedResourceContext | undefined,\n): HistoryActorKind {\n const caller = typeof ctx?.caller === \"string\" ? ctx.caller : \"\";\n if (caller === \"agent\" || caller === \"tool\") {\n return \"agent\";\n }\n return ctx?.userEmail ? \"human\" : \"system\";\n}\n"]}
@@ -1,4 +1,4 @@
1
1
  export type { HistoryActorKind, HistoryResourceRole, ResourceHistoryScope, ResourceVersion, VersionedResourceAccess, VersionedResourceContext, VersionedResourceRegistration, VersionedResourceRestoreContext, VersionedResourceSnapshotContext, } from "./types.js";
2
2
  export { __resetVersionedResourcesForTests, assertVersionedResourceAccess, getVersionedResource, listVersionedResources, registerVersionedResource, resolveVersionedResourceAccess, } from "./registry.js";
3
- export { __resetHistoryInitForTests, ensureResourceVersionsTable, getResourceVersionById, getResourceVersionByNumber, insertResourceVersion, queryResourceVersions, } from "./store.js";
3
+ export { __resetHistoryInitForTests, ensureResourceVersionsTable, getResourceVersionById, getResourceVersionByNumber, queryResourceVersions, } from "./store.js";
4
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/history/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,gBAAgB,EAChB,mBAAmB,EACnB,oBAAoB,EACpB,eAAe,EACf,uBAAuB,EACvB,wBAAwB,EACxB,6BAA6B,EAC7B,+BAA+B,EAC/B,gCAAgC,GACjC,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,iCAAiC,EACjC,6BAA6B,EAC7B,oBAAoB,EACpB,sBAAsB,EACtB,yBAAyB,EACzB,8BAA8B,GAC/B,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,0BAA0B,EAC1B,2BAA2B,EAC3B,sBAAsB,EACtB,0BAA0B,EAC1B,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/history/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,gBAAgB,EAChB,mBAAmB,EACnB,oBAAoB,EACpB,eAAe,EACf,uBAAuB,EACvB,wBAAwB,EACxB,6BAA6B,EAC7B,+BAA+B,EAC/B,gCAAgC,GACjC,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,iCAAiC,EACjC,6BAA6B,EAC7B,oBAAoB,EACpB,sBAAsB,EACtB,yBAAyB,EACzB,8BAA8B,GAC/B,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,0BAA0B,EAC1B,2BAA2B,EAC3B,sBAAsB,EACtB,0BAA0B,EAC1B,qBAAqB,GACtB,MAAM,YAAY,CAAC"}
@@ -1,3 +1,3 @@
1
1
  export { __resetVersionedResourcesForTests, assertVersionedResourceAccess, getVersionedResource, listVersionedResources, registerVersionedResource, resolveVersionedResourceAccess, } from "./registry.js";
2
- export { __resetHistoryInitForTests, ensureResourceVersionsTable, getResourceVersionById, getResourceVersionByNumber, insertResourceVersion, queryResourceVersions, } from "./store.js";
2
+ export { __resetHistoryInitForTests, ensureResourceVersionsTable, getResourceVersionById, getResourceVersionByNumber, queryResourceVersions, } from "./store.js";
3
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/history/index.ts"],"names":[],"mappings":"AAWA,OAAO,EACL,iCAAiC,EACjC,6BAA6B,EAC7B,oBAAoB,EACpB,sBAAsB,EACtB,yBAAyB,EACzB,8BAA8B,GAC/B,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,0BAA0B,EAC1B,2BAA2B,EAC3B,sBAAsB,EACtB,0BAA0B,EAC1B,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,YAAY,CAAC","sourcesContent":["export type {\n HistoryActorKind,\n HistoryResourceRole,\n ResourceHistoryScope,\n ResourceVersion,\n VersionedResourceAccess,\n VersionedResourceContext,\n VersionedResourceRegistration,\n VersionedResourceRestoreContext,\n VersionedResourceSnapshotContext,\n} from \"./types.js\";\nexport {\n __resetVersionedResourcesForTests,\n assertVersionedResourceAccess,\n getVersionedResource,\n listVersionedResources,\n registerVersionedResource,\n resolveVersionedResourceAccess,\n} from \"./registry.js\";\nexport {\n __resetHistoryInitForTests,\n ensureResourceVersionsTable,\n getResourceVersionById,\n getResourceVersionByNumber,\n insertResourceVersion,\n queryResourceVersions,\n} from \"./store.js\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/history/index.ts"],"names":[],"mappings":"AAWA,OAAO,EACL,iCAAiC,EACjC,6BAA6B,EAC7B,oBAAoB,EACpB,sBAAsB,EACtB,yBAAyB,EACzB,8BAA8B,GAC/B,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,0BAA0B,EAC1B,2BAA2B,EAC3B,sBAAsB,EACtB,0BAA0B,EAC1B,qBAAqB,GACtB,MAAM,YAAY,CAAC","sourcesContent":["export type {\n HistoryActorKind,\n HistoryResourceRole,\n ResourceHistoryScope,\n ResourceVersion,\n VersionedResourceAccess,\n VersionedResourceContext,\n VersionedResourceRegistration,\n VersionedResourceRestoreContext,\n VersionedResourceSnapshotContext,\n} from \"./types.js\";\nexport {\n __resetVersionedResourcesForTests,\n assertVersionedResourceAccess,\n getVersionedResource,\n listVersionedResources,\n registerVersionedResource,\n resolveVersionedResourceAccess,\n} from \"./registry.js\";\nexport {\n __resetHistoryInitForTests,\n ensureResourceVersionsTable,\n getResourceVersionById,\n getResourceVersionByNumber,\n queryResourceVersions,\n} from \"./store.js\";\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/history/registry.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiB,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACtE,OAAO,KAAK,EACV,mBAAmB,EACnB,uBAAuB,EACvB,wBAAwB,EACxB,6BAA6B,EAC9B,MAAM,YAAY,CAAC;AAIpB,wBAAgB,yBAAyB,CACvC,YAAY,EAAE,6BAA6B,GAC1C,IAAI,CAON;AAED,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,GACX,6BAA6B,GAAG,SAAS,CAE3C;AAED,wBAAgB,sBAAsB,IAAI,6BAA6B,EAAE,CAExE;AAED,wBAAsB,8BAA8B,CAClD,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,GAAG,CAAC,EAAE,wBAAwB,GAC7B,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC,CA8BzC;AAED,wBAAsB,6BAA6B,CACjD,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,wBAAwB,GAAG,SAAS,EACzC,WAAW,EAAE,mBAAmB,GAC/B,OAAO,CAAC,uBAAuB,CAAC,CAYlC;AAED,wBAAgB,0BAA0B,CACxC,UAAU,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS,GACxC,UAAU,CAIZ;AAED,wBAAgB,iCAAiC,IAAI,IAAI,CAExD"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/history/registry.ts"],"names":[],"mappings":"AAMA,OAAO,EAAiB,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACtE,OAAO,KAAK,EACV,mBAAmB,EACnB,uBAAuB,EACvB,wBAAwB,EACxB,6BAA6B,EAC9B,MAAM,YAAY,CAAC;AAIpB,wBAAgB,yBAAyB,CACvC,YAAY,EAAE,6BAA6B,GAC1C,IAAI,CAON;AAED,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,GACX,6BAA6B,GAAG,SAAS,CAE3C;AAED,wBAAgB,sBAAsB,IAAI,6BAA6B,EAAE,CAExE;AAYD,wBAAsB,8BAA8B,CAClD,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,GAAG,CAAC,EAAE,wBAAwB,GAC7B,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC,CA4BzC;AAED,wBAAsB,6BAA6B,CACjD,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,wBAAwB,GAAG,SAAS,EACzC,WAAW,EAAE,mBAAmB,GAC/B,OAAO,CAAC,uBAAuB,CAAC,CAYlC;AAED,wBAAgB,0BAA0B,CACxC,UAAU,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS,GACxC,UAAU,CAIZ;AAED,wBAAgB,iCAAiC,IAAI,IAAI,CAExD"}
@@ -1,4 +1,4 @@
1
- import { ForbiddenError, resolveAccess } from "../sharing/access.js";
1
+ import { ForbiddenError, resolveAccess, } from "../sharing/access.js";
2
2
  import { getShareableResource } from "../sharing/registry.js";
3
3
  import { roleSatisfies } from "../sharing/schema.js";
4
4
  const registrations = new Map();
@@ -14,13 +14,21 @@ export function getVersionedResource(type) {
14
14
  export function listVersionedResources() {
15
15
  return Array.from(registrations.values());
16
16
  }
17
+ function accessContextFrom(ctx) {
18
+ if (!ctx)
19
+ return undefined;
20
+ return {
21
+ userEmail: ctx.userEmail ?? undefined,
22
+ orgId: ctx.orgId ?? undefined,
23
+ };
24
+ }
17
25
  export async function resolveVersionedResourceAccess(resourceType, resourceId, ctx) {
18
26
  const registration = getVersionedResource(resourceType);
19
27
  if (registration?.resolveAccess) {
20
28
  return registration.resolveAccess(resourceId, ctx);
21
29
  }
22
30
  if (getShareableResource(resourceType)) {
23
- const access = await resolveAccess(resourceType, resourceId);
31
+ const access = await resolveAccess(resourceType, resourceId, accessContextFrom(ctx));
24
32
  if (!access) {
25
33
  return null;
26
34
  }
@@ -32,16 +40,10 @@ export async function resolveVersionedResourceAccess(resourceType, resourceId, c
32
40
  resource: access.resource,
33
41
  };
34
42
  }
35
- const userEmail = ctx?.userEmail ?? null;
36
- if (!userEmail) {
37
- return null;
38
- }
39
- return {
40
- role: "owner",
41
- ownerEmail: userEmail,
42
- orgId: ctx?.orgId ?? null,
43
- visibility: "private",
44
- };
43
+ // Fail closed: unregistered types, and registered types without an access
44
+ // resolver that aren't shareable, never invent ownership. bypassScope on
45
+ // history queries is only safe after a real resource ACL.
46
+ return null;
45
47
  }
46
48
  export async function assertVersionedResourceAccess(resourceType, resourceId, ctx, minimumRole) {
47
49
  const access = await resolveVersionedResourceAccess(resourceType, resourceId, ctx);
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/history/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAmB,MAAM,sBAAsB,CAAC;AAQtE,MAAM,aAAa,GAAG,IAAI,GAAG,EAAyC,CAAC;AAEvE,MAAM,UAAU,yBAAyB,CACvC,YAA2C;IAE3C,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CACb,8DAA8D,CAC/D,CAAC;IACJ,CAAC;IACD,aAAa,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,IAAY;IAEZ,OAAO,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,sBAAsB;IACpC,OAAO,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,8BAA8B,CAClD,YAAoB,EACpB,UAAkB,EAClB,GAA8B;IAE9B,MAAM,YAAY,GAAG,oBAAoB,CAAC,YAAY,CAAC,CAAC;IACxD,IAAI,YAAY,EAAE,aAAa,EAAE,CAAC;QAChC,OAAO,YAAY,CAAC,aAAa,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;IACrD,CAAC;IAED,IAAI,oBAAoB,CAAC,YAAY,CAAC,EAAE,CAAC;QACvC,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;QAC7D,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO;YACL,IAAI,EAAE,MAAM,CAAC,IAA2B;YACxC,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC,UAAU,IAAI,IAAI;YAC9C,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,KAAK,IAAI,IAAI;YACpC,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC,UAAU;YACtC,QAAQ,EAAE,MAAM,CAAC,QAAQ;SAC1B,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAG,GAAG,EAAE,SAAS,IAAI,IAAI,CAAC;IACzC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO;QACL,IAAI,EAAE,OAAO;QACb,UAAU,EAAE,SAAS;QACrB,KAAK,EAAE,GAAG,EAAE,KAAK,IAAI,IAAI;QACzB,UAAU,EAAE,SAAS;KACtB,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,6BAA6B,CACjD,YAAoB,EACpB,UAAkB,EAClB,GAAyC,EACzC,WAAgC;IAEhC,MAAM,MAAM,GAAG,MAAM,8BAA8B,CACjD,YAAY,EACZ,UAAU,EACV,GAAG,CACJ,CAAC;IACF,IAAI,CAAC,MAAM,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,EAAE,WAAW,CAAC,EAAE,CAAC;QACxD,MAAM,IAAI,cAAc,CACtB,yBAAyB,YAAY,IAAI,UAAU,EAAE,CACtD,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,0BAA0B,CACxC,UAAyC;IAEzC,OAAO,UAAU,KAAK,KAAK,IAAI,UAAU,KAAK,QAAQ;QACpD,CAAC,CAAC,UAAU;QACZ,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,iCAAiC;IAC/C,aAAa,CAAC,KAAK,EAAE,CAAC;AACxB,CAAC","sourcesContent":["import { ForbiddenError, resolveAccess } from \"../sharing/access.js\";\nimport { getShareableResource } from \"../sharing/registry.js\";\nimport { roleSatisfies, type Visibility } from \"../sharing/schema.js\";\nimport type {\n HistoryResourceRole,\n VersionedResourceAccess,\n VersionedResourceContext,\n VersionedResourceRegistration,\n} from \"./types.js\";\n\nconst registrations = new Map<string, VersionedResourceRegistration>();\n\nexport function registerVersionedResource(\n registration: VersionedResourceRegistration,\n): void {\n if (!registration.type.trim()) {\n throw new Error(\n \"registerVersionedResource requires a non-empty resource type\",\n );\n }\n registrations.set(registration.type, registration);\n}\n\nexport function getVersionedResource(\n type: string,\n): VersionedResourceRegistration | undefined {\n return registrations.get(type);\n}\n\nexport function listVersionedResources(): VersionedResourceRegistration[] {\n return Array.from(registrations.values());\n}\n\nexport async function resolveVersionedResourceAccess(\n resourceType: string,\n resourceId: string,\n ctx?: VersionedResourceContext,\n): Promise<VersionedResourceAccess | null> {\n const registration = getVersionedResource(resourceType);\n if (registration?.resolveAccess) {\n return registration.resolveAccess(resourceId, ctx);\n }\n\n if (getShareableResource(resourceType)) {\n const access = await resolveAccess(resourceType, resourceId);\n if (!access) {\n return null;\n }\n return {\n role: access.role as HistoryResourceRole,\n ownerEmail: access.resource.ownerEmail ?? null,\n orgId: access.resource.orgId ?? null,\n visibility: access.resource.visibility,\n resource: access.resource,\n };\n }\n\n const userEmail = ctx?.userEmail ?? null;\n if (!userEmail) {\n return null;\n }\n return {\n role: \"owner\",\n ownerEmail: userEmail,\n orgId: ctx?.orgId ?? null,\n visibility: \"private\",\n };\n}\n\nexport async function assertVersionedResourceAccess(\n resourceType: string,\n resourceId: string,\n ctx: VersionedResourceContext | undefined,\n minimumRole: HistoryResourceRole,\n): Promise<VersionedResourceAccess> {\n const access = await resolveVersionedResourceAccess(\n resourceType,\n resourceId,\n ctx,\n );\n if (!access || !roleSatisfies(access.role, minimumRole)) {\n throw new ForbiddenError(\n `Not allowed to access ${resourceType}:${resourceId}`,\n );\n }\n return access;\n}\n\nexport function normalizeHistoryVisibility(\n visibility: Visibility | null | undefined,\n): Visibility {\n return visibility === \"org\" || visibility === \"public\"\n ? visibility\n : \"private\";\n}\n\nexport function __resetVersionedResourcesForTests(): void {\n registrations.clear();\n}\n"]}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/history/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,aAAa,GAEd,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAmB,MAAM,sBAAsB,CAAC;AAQtE,MAAM,aAAa,GAAG,IAAI,GAAG,EAAyC,CAAC;AAEvE,MAAM,UAAU,yBAAyB,CACvC,YAA2C;IAE3C,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CACb,8DAA8D,CAC/D,CAAC;IACJ,CAAC;IACD,aAAa,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,IAAY;IAEZ,OAAO,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,sBAAsB;IACpC,OAAO,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC,CAAC;AAC5C,CAAC;AAED,SAAS,iBAAiB,CACxB,GAA8B;IAE9B,IAAI,CAAC,GAAG;QAAE,OAAO,SAAS,CAAC;IAC3B,OAAO;QACL,SAAS,EAAE,GAAG,CAAC,SAAS,IAAI,SAAS;QACrC,KAAK,EAAE,GAAG,CAAC,KAAK,IAAI,SAAS;KAC9B,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,8BAA8B,CAClD,YAAoB,EACpB,UAAkB,EAClB,GAA8B;IAE9B,MAAM,YAAY,GAAG,oBAAoB,CAAC,YAAY,CAAC,CAAC;IACxD,IAAI,YAAY,EAAE,aAAa,EAAE,CAAC;QAChC,OAAO,YAAY,CAAC,aAAa,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;IACrD,CAAC;IAED,IAAI,oBAAoB,CAAC,YAAY,CAAC,EAAE,CAAC;QACvC,MAAM,MAAM,GAAG,MAAM,aAAa,CAChC,YAAY,EACZ,UAAU,EACV,iBAAiB,CAAC,GAAG,CAAC,CACvB,CAAC;QACF,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO;YACL,IAAI,EAAE,MAAM,CAAC,IAA2B;YACxC,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC,UAAU,IAAI,IAAI;YAC9C,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,KAAK,IAAI,IAAI;YACpC,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC,UAAU;YACtC,QAAQ,EAAE,MAAM,CAAC,QAAQ;SAC1B,CAAC;IACJ,CAAC;IAED,0EAA0E;IAC1E,yEAAyE;IACzE,0DAA0D;IAC1D,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,6BAA6B,CACjD,YAAoB,EACpB,UAAkB,EAClB,GAAyC,EACzC,WAAgC;IAEhC,MAAM,MAAM,GAAG,MAAM,8BAA8B,CACjD,YAAY,EACZ,UAAU,EACV,GAAG,CACJ,CAAC;IACF,IAAI,CAAC,MAAM,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,EAAE,WAAW,CAAC,EAAE,CAAC;QACxD,MAAM,IAAI,cAAc,CACtB,yBAAyB,YAAY,IAAI,UAAU,EAAE,CACtD,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,0BAA0B,CACxC,UAAyC;IAEzC,OAAO,UAAU,KAAK,KAAK,IAAI,UAAU,KAAK,QAAQ;QACpD,CAAC,CAAC,UAAU;QACZ,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,iCAAiC;IAC/C,aAAa,CAAC,KAAK,EAAE,CAAC;AACxB,CAAC","sourcesContent":["import {\n ForbiddenError,\n resolveAccess,\n type AccessContext,\n} from \"../sharing/access.js\";\nimport { getShareableResource } from \"../sharing/registry.js\";\nimport { roleSatisfies, type Visibility } from \"../sharing/schema.js\";\nimport type {\n HistoryResourceRole,\n VersionedResourceAccess,\n VersionedResourceContext,\n VersionedResourceRegistration,\n} from \"./types.js\";\n\nconst registrations = new Map<string, VersionedResourceRegistration>();\n\nexport function registerVersionedResource(\n registration: VersionedResourceRegistration,\n): void {\n if (!registration.type.trim()) {\n throw new Error(\n \"registerVersionedResource requires a non-empty resource type\",\n );\n }\n registrations.set(registration.type, registration);\n}\n\nexport function getVersionedResource(\n type: string,\n): VersionedResourceRegistration | undefined {\n return registrations.get(type);\n}\n\nexport function listVersionedResources(): VersionedResourceRegistration[] {\n return Array.from(registrations.values());\n}\n\nfunction accessContextFrom(\n ctx?: VersionedResourceContext,\n): AccessContext | undefined {\n if (!ctx) return undefined;\n return {\n userEmail: ctx.userEmail ?? undefined,\n orgId: ctx.orgId ?? undefined,\n };\n}\n\nexport async function resolveVersionedResourceAccess(\n resourceType: string,\n resourceId: string,\n ctx?: VersionedResourceContext,\n): Promise<VersionedResourceAccess | null> {\n const registration = getVersionedResource(resourceType);\n if (registration?.resolveAccess) {\n return registration.resolveAccess(resourceId, ctx);\n }\n\n if (getShareableResource(resourceType)) {\n const access = await resolveAccess(\n resourceType,\n resourceId,\n accessContextFrom(ctx),\n );\n if (!access) {\n return null;\n }\n return {\n role: access.role as HistoryResourceRole,\n ownerEmail: access.resource.ownerEmail ?? null,\n orgId: access.resource.orgId ?? null,\n visibility: access.resource.visibility,\n resource: access.resource,\n };\n }\n\n // Fail closed: unregistered types, and registered types without an access\n // resolver that aren't shareable, never invent ownership. bypassScope on\n // history queries is only safe after a real resource ACL.\n return null;\n}\n\nexport async function assertVersionedResourceAccess(\n resourceType: string,\n resourceId: string,\n ctx: VersionedResourceContext | undefined,\n minimumRole: HistoryResourceRole,\n): Promise<VersionedResourceAccess> {\n const access = await resolveVersionedResourceAccess(\n resourceType,\n resourceId,\n ctx,\n );\n if (!access || !roleSatisfies(access.role, minimumRole)) {\n throw new ForbiddenError(\n `Not allowed to access ${resourceType}:${resourceId}`,\n );\n }\n return access;\n}\n\nexport function normalizeHistoryVisibility(\n visibility: Visibility | null | undefined,\n): Visibility {\n return visibility === \"org\" || visibility === \"public\"\n ? visibility\n : \"private\";\n}\n\nexport function __resetVersionedResourcesForTests(): void {\n registrations.clear();\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/history/store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EACV,gBAAgB,EAChB,oBAAoB,EACpB,eAAe,EAChB,MAAM,YAAY,CAAC;AAIpB,MAAM,WAAW,0BAA0B;IACzC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC3C;AAED,MAAM,WAAW,0BAA0B;IACzC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,oBAAoB,CAAC;IAC5B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,2BAA2B,IAAI,OAAO,CAAC,IAAI,CAAC,CAkDjE;AAED,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,0BAA0B,GAChC,OAAO,CAAC,eAAe,CAAC,CAwE1B;AAED,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,0BAA0B,GAChC,OAAO,CAAC,eAAe,EAAE,CAAC,CAiB5B;AAED,wBAAsB,sBAAsB,CAC1C,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,oBAAoB,EAC3B,OAAO,GAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAA;CAAO,GACtC,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAejC;AAED,wBAAsB,0BAA0B,CAC9C,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,oBAAoB,EAC3B,OAAO,GAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAA;CAAO,GACtC,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAkBjC;AAED,wBAAgB,0BAA0B,IAAI,IAAI,CAEjD"}
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/history/store.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EACV,gBAAgB,EAChB,oBAAoB,EACpB,eAAe,EAChB,MAAM,YAAY,CAAC;AAMpB,MAAM,WAAW,0BAA0B;IACzC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC3C;AAED,MAAM,WAAW,0BAA0B;IACzC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,oBAAoB,CAAC;IAC5B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,2BAA2B,IAAI,OAAO,CAAC,IAAI,CAAC,CAkDjE;AAED,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,0BAA0B,GAChC,OAAO,CAAC,eAAe,CAAC,CAgG1B;AAED,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,0BAA0B,GAChC,OAAO,CAAC,eAAe,EAAE,CAAC,CAiB5B;AAED,wBAAsB,sBAAsB,CAC1C,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,oBAAoB,EAC3B,OAAO,GAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAA;CAAO,GACtC,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAejC;AAED,wBAAsB,0BAA0B,CAC9C,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,oBAAoB,EAC3B,OAAO,GAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAA;CAAO,GACtC,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAkBjC;AAED,wBAAgB,0BAA0B,IAAI,IAAI,CAEjD"}
@@ -1,6 +1,7 @@
1
- import { getDbExec, intType, isPostgres } from "../db/client.js";
1
+ import { getDbExec, intType, isPostgres, isUniqueViolation, } from "../db/client.js";
2
2
  import { ensureIndexExists, ensureTableExists } from "../db/ddl-guard.js";
3
3
  let historyTableInitPromise;
4
+ const VERSION_INSERT_MAX_ATTEMPTS = 8;
4
5
  export async function ensureResourceVersionsTable() {
5
6
  if (!historyTableInitPromise) {
6
7
  historyTableInitPromise = (async () => {
@@ -22,7 +23,7 @@ export async function ensureResourceVersionsTable() {
22
23
  metadata_json TEXT
23
24
  )`;
24
25
  const indexes = [
25
- `CREATE INDEX IF NOT EXISTS idx_agent_resource_versions_resource
26
+ `CREATE UNIQUE INDEX IF NOT EXISTS idx_agent_resource_versions_resource_number
26
27
  ON agent_resource_versions (resource_type, resource_id, version_number)`,
27
28
  `CREATE INDEX IF NOT EXISTS idx_agent_resource_versions_owner
28
29
  ON agent_resource_versions (owner_email, created_at)`,
@@ -31,7 +32,7 @@ export async function ensureResourceVersionsTable() {
31
32
  ];
32
33
  if (isPostgres()) {
33
34
  await ensureTableExists("agent_resource_versions", createSql);
34
- await ensureIndexExists("idx_agent_resource_versions_resource", indexes[0]);
35
+ await ensureIndexExists("idx_agent_resource_versions_resource_number", indexes[0]);
35
36
  await ensureIndexExists("idx_agent_resource_versions_owner", indexes[1]);
36
37
  await ensureIndexExists("idx_agent_resource_versions_org", indexes[2]);
37
38
  }
@@ -48,36 +49,49 @@ export async function ensureResourceVersionsTable() {
48
49
  export async function insertResourceVersion(input) {
49
50
  await ensureResourceVersionsTable();
50
51
  const client = getDbExec();
51
- const maxRows = await client.execute({
52
- sql: `SELECT MAX(version_number) as max_version
52
+ const visibility = input.visibility === "org" || input.visibility === "public"
53
+ ? input.visibility
54
+ : "private";
55
+ const actorKind = input.actorKind ?? "human";
56
+ const createdBy = input.createdBy ?? null;
57
+ const ownerEmail = input.ownerEmail ?? input.createdBy ?? null;
58
+ const orgId = input.orgId ?? null;
59
+ const title = input.title ?? null;
60
+ const summary = input.summary ?? null;
61
+ const metadata = input.metadata ?? null;
62
+ const snapshotJson = JSON.stringify(input.snapshot);
63
+ const metadataJson = stringifyOptionalJson(metadata);
64
+ let lastError;
65
+ for (let attempt = 0; attempt < VERSION_INSERT_MAX_ATTEMPTS; attempt++) {
66
+ const maxRows = await client.execute({
67
+ sql: `SELECT MAX(version_number) as max_version
53
68
  FROM agent_resource_versions
54
69
  WHERE resource_type = ? AND resource_id = ?`,
55
- args: [input.resourceType, input.resourceId],
56
- });
57
- const versionNumber = Number(maxRows.rows?.[0]?.max_version ??
58
- 0) + 1;
59
- const id = createVersionId();
60
- const createdAt = new Date().toISOString();
61
- const version = {
62
- id,
63
- resourceType: input.resourceType,
64
- resourceId: input.resourceId,
65
- versionNumber,
66
- createdAt,
67
- createdBy: input.createdBy ?? null,
68
- actorKind: input.actorKind ?? "human",
69
- ownerEmail: input.ownerEmail ?? input.createdBy ?? null,
70
- orgId: input.orgId ?? null,
71
- visibility: input.visibility === "org" || input.visibility === "public"
72
- ? input.visibility
73
- : "private",
74
- title: input.title ?? null,
75
- summary: input.summary ?? null,
76
- snapshot: input.snapshot,
77
- metadata: input.metadata ?? null,
78
- };
79
- await client.execute({
80
- sql: `INSERT INTO agent_resource_versions (
70
+ args: [input.resourceType, input.resourceId],
71
+ });
72
+ const versionNumber = Number(maxRows.rows?.[0]
73
+ ?.max_version ?? 0) + 1;
74
+ const id = createVersionId();
75
+ const createdAt = new Date().toISOString();
76
+ const version = {
77
+ id,
78
+ resourceType: input.resourceType,
79
+ resourceId: input.resourceId,
80
+ versionNumber,
81
+ createdAt,
82
+ createdBy,
83
+ actorKind,
84
+ ownerEmail,
85
+ orgId,
86
+ visibility,
87
+ title,
88
+ summary,
89
+ snapshot: input.snapshot,
90
+ metadata,
91
+ };
92
+ try {
93
+ await client.execute({
94
+ sql: `INSERT INTO agent_resource_versions (
81
95
  id,
82
96
  resource_type,
83
97
  resource_id,
@@ -93,24 +107,35 @@ export async function insertResourceVersion(input) {
93
107
  snapshot_json,
94
108
  metadata_json
95
109
  ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
96
- args: [
97
- version.id,
98
- version.resourceType,
99
- version.resourceId,
100
- version.versionNumber,
101
- version.createdAt,
102
- version.createdBy,
103
- version.actorKind,
104
- version.ownerEmail,
105
- version.orgId,
106
- version.visibility,
107
- version.title,
108
- version.summary,
109
- JSON.stringify(version.snapshot),
110
- stringifyOptionalJson(version.metadata),
111
- ],
112
- });
113
- return version;
110
+ args: [
111
+ version.id,
112
+ version.resourceType,
113
+ version.resourceId,
114
+ version.versionNumber,
115
+ version.createdAt,
116
+ version.createdBy,
117
+ version.actorKind,
118
+ version.ownerEmail,
119
+ version.orgId,
120
+ version.visibility,
121
+ version.title,
122
+ version.summary,
123
+ snapshotJson,
124
+ metadataJson,
125
+ ],
126
+ });
127
+ return version;
128
+ }
129
+ catch (error) {
130
+ lastError = error;
131
+ if (!isUniqueViolation(error)) {
132
+ throw error;
133
+ }
134
+ }
135
+ }
136
+ throw lastError instanceof Error
137
+ ? lastError
138
+ : new Error("Failed to allocate a unique resource version number");
114
139
  }
115
140
  export async function queryResourceVersions(input) {
116
141
  await ensureResourceVersionsTable();
@@ -1 +1 @@
1
- {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/history/store.ts"],"names":[],"mappings":"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","sourcesContent":["import { getDbExec, intType, isPostgres } from \"../db/client.js\";\nimport { ensureIndexExists, ensureTableExists } from \"../db/ddl-guard.js\";\nimport type { Visibility } from \"../sharing/schema.js\";\nimport type {\n HistoryActorKind,\n ResourceHistoryScope,\n ResourceVersion,\n} from \"./types.js\";\n\nlet historyTableInitPromise: Promise<void> | undefined;\n\nexport interface InsertResourceVersionInput {\n resourceType: string;\n resourceId: string;\n createdBy?: string | null;\n actorKind?: HistoryActorKind;\n ownerEmail?: string | null;\n orgId?: string | null;\n visibility?: Visibility | null;\n title?: string | null;\n summary?: string | null;\n snapshot: unknown;\n metadata?: Record<string, unknown> | null;\n}\n\nexport interface QueryResourceVersionsInput {\n resourceType: string;\n resourceId: string;\n scope: ResourceHistoryScope;\n bypassScope?: boolean;\n limit?: number;\n offset?: number;\n}\n\nexport async function ensureResourceVersionsTable(): Promise<void> {\n if (!historyTableInitPromise) {\n historyTableInitPromise = (async () => {\n const client = getDbExec();\n const createSql = `CREATE TABLE IF NOT EXISTS agent_resource_versions (\n id TEXT PRIMARY KEY,\n resource_type TEXT NOT NULL,\n resource_id TEXT NOT NULL,\n version_number ${intType()} NOT NULL,\n created_at TEXT NOT NULL,\n created_by TEXT,\n actor_kind TEXT NOT NULL DEFAULT 'human',\n owner_email TEXT,\n org_id TEXT,\n visibility TEXT NOT NULL DEFAULT 'private',\n title TEXT,\n summary TEXT,\n snapshot_json TEXT NOT NULL,\n metadata_json TEXT\n )`;\n const indexes = [\n `CREATE INDEX IF NOT EXISTS idx_agent_resource_versions_resource\n ON agent_resource_versions (resource_type, resource_id, version_number)`,\n `CREATE INDEX IF NOT EXISTS idx_agent_resource_versions_owner\n ON agent_resource_versions (owner_email, created_at)`,\n `CREATE INDEX IF NOT EXISTS idx_agent_resource_versions_org\n ON agent_resource_versions (org_id, created_at)`,\n ];\n\n if (isPostgres()) {\n await ensureTableExists(\"agent_resource_versions\", createSql);\n await ensureIndexExists(\n \"idx_agent_resource_versions_resource\",\n indexes[0],\n );\n await ensureIndexExists(\n \"idx_agent_resource_versions_owner\",\n indexes[1],\n );\n await ensureIndexExists(\"idx_agent_resource_versions_org\", indexes[2]);\n } else {\n await client.execute(createSql);\n for (const indexSql of indexes) {\n await client.execute(indexSql);\n }\n }\n })();\n }\n\n await historyTableInitPromise;\n}\n\nexport async function insertResourceVersion(\n input: InsertResourceVersionInput,\n): Promise<ResourceVersion> {\n await ensureResourceVersionsTable();\n const client = getDbExec();\n const maxRows = await client.execute({\n sql: `SELECT MAX(version_number) as max_version\n FROM agent_resource_versions\n WHERE resource_type = ? AND resource_id = ?`,\n args: [input.resourceType, input.resourceId],\n });\n const versionNumber =\n Number(\n (maxRows.rows?.[0] as Record<string, unknown> | undefined)?.max_version ??\n 0,\n ) + 1;\n const id = createVersionId();\n const createdAt = new Date().toISOString();\n const version: ResourceVersion = {\n id,\n resourceType: input.resourceType,\n resourceId: input.resourceId,\n versionNumber,\n createdAt,\n createdBy: input.createdBy ?? null,\n actorKind: input.actorKind ?? \"human\",\n ownerEmail: input.ownerEmail ?? input.createdBy ?? null,\n orgId: input.orgId ?? null,\n visibility:\n input.visibility === \"org\" || input.visibility === \"public\"\n ? input.visibility\n : \"private\",\n title: input.title ?? null,\n summary: input.summary ?? null,\n snapshot: input.snapshot,\n metadata: input.metadata ?? null,\n };\n\n await client.execute({\n sql: `INSERT INTO agent_resource_versions (\n id,\n resource_type,\n resource_id,\n version_number,\n created_at,\n created_by,\n actor_kind,\n owner_email,\n org_id,\n visibility,\n title,\n summary,\n snapshot_json,\n metadata_json\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n version.id,\n version.resourceType,\n version.resourceId,\n version.versionNumber,\n version.createdAt,\n version.createdBy,\n version.actorKind,\n version.ownerEmail,\n version.orgId,\n version.visibility,\n version.title,\n version.summary,\n JSON.stringify(version.snapshot),\n stringifyOptionalJson(version.metadata),\n ],\n });\n\n return version;\n}\n\nexport async function queryResourceVersions(\n input: QueryResourceVersionsInput,\n): Promise<ResourceVersion[]> {\n await ensureResourceVersionsTable();\n const client = getDbExec();\n const { clause, params } = input.bypassScope\n ? { clause: \"1 = 1\", params: [] as unknown[] }\n : scopedResourceClause(input.scope);\n const limit = clampLimit(input.limit);\n const offset = Math.max(0, Math.floor(input.offset ?? 0));\n const result = await client.execute({\n sql: `SELECT ${listColumns()}\n FROM agent_resource_versions\n WHERE resource_type = ? AND resource_id = ? AND ${clause}\n ORDER BY version_number DESC\n LIMIT ? OFFSET ?`,\n args: [input.resourceType, input.resourceId, ...params, limit, offset],\n });\n return (result.rows ?? []).map((row) => mapVersionRow(row, false));\n}\n\nexport async function getResourceVersionById(\n id: string,\n scope: ResourceHistoryScope,\n options: { bypassScope?: boolean } = {},\n): Promise<ResourceVersion | null> {\n await ensureResourceVersionsTable();\n const client = getDbExec();\n const { clause, params } = options.bypassScope\n ? { clause: \"1 = 1\", params: [] as unknown[] }\n : scopedResourceClause(scope);\n const result = await client.execute({\n sql: `SELECT ${allColumns()}\n FROM agent_resource_versions\n WHERE id = ? AND ${clause}\n LIMIT 1`,\n args: [id, ...params],\n });\n const row = result.rows?.[0];\n return row ? mapVersionRow(row, true) : null;\n}\n\nexport async function getResourceVersionByNumber(\n resourceType: string,\n resourceId: string,\n versionNumber: number,\n scope: ResourceHistoryScope,\n options: { bypassScope?: boolean } = {},\n): Promise<ResourceVersion | null> {\n await ensureResourceVersionsTable();\n const client = getDbExec();\n const { clause, params } = options.bypassScope\n ? { clause: \"1 = 1\", params: [] as unknown[] }\n : scopedResourceClause(scope);\n const result = await client.execute({\n sql: `SELECT ${allColumns()}\n FROM agent_resource_versions\n WHERE resource_type = ?\n AND resource_id = ?\n AND version_number = ?\n AND ${clause}\n LIMIT 1`,\n args: [resourceType, resourceId, versionNumber, ...params],\n });\n const row = result.rows?.[0];\n return row ? mapVersionRow(row, true) : null;\n}\n\nexport function __resetHistoryInitForTests(): void {\n historyTableInitPromise = undefined;\n}\n\nfunction listColumns(): string {\n return [\n \"id\",\n \"resource_type\",\n \"resource_id\",\n \"version_number\",\n \"created_at\",\n \"created_by\",\n \"actor_kind\",\n \"owner_email\",\n \"org_id\",\n \"visibility\",\n \"title\",\n \"summary\",\n \"metadata_json\",\n ].join(\", \");\n}\n\nfunction allColumns(): string {\n return `${listColumns()}, snapshot_json`;\n}\n\nfunction scopedResourceClause(scope: ResourceHistoryScope): {\n clause: string;\n params: unknown[];\n} {\n const parts: string[] = [];\n const params: unknown[] = [];\n\n if (scope.userEmail) {\n parts.push(\"owner_email = ?\");\n params.push(scope.userEmail);\n }\n if (scope.orgId) {\n parts.push(\"(visibility = 'org' AND org_id = ?)\");\n params.push(scope.orgId);\n }\n parts.push(\"visibility = 'public'\");\n\n if (parts.length === 0) {\n return { clause: \"visibility = 'public'\", params: [] };\n }\n\n return { clause: `(${parts.join(\" OR \")})`, params };\n}\n\nfunction mapVersionRow(\n row: Record<string, unknown>,\n includeSnapshot: boolean,\n): ResourceVersion {\n const version: ResourceVersion = {\n id: String(row.id),\n resourceType: String(row.resource_type),\n resourceId: String(row.resource_id),\n versionNumber: Number(row.version_number),\n createdAt: String(row.created_at),\n createdBy: nullableString(row.created_by),\n actorKind: normalizeActorKind(row.actor_kind),\n ownerEmail: nullableString(row.owner_email),\n orgId: nullableString(row.org_id),\n visibility: normalizeVisibility(row.visibility),\n title: nullableString(row.title),\n summary: nullableString(row.summary),\n metadata: parseOptionalJson(row.metadata_json),\n };\n if (includeSnapshot) {\n version.snapshot = parseRequiredJson(row.snapshot_json);\n }\n return version;\n}\n\nfunction createVersionId(): string {\n return `ver_${globalThis.crypto.randomUUID()}`;\n}\n\nfunction clampLimit(value: number | undefined): number {\n if (!Number.isFinite(value)) {\n return 50;\n }\n return Math.min(200, Math.max(1, Math.floor(value ?? 50)));\n}\n\nfunction nullableString(value: unknown): string | null {\n return value === null || value === undefined ? null : String(value);\n}\n\nfunction normalizeVisibility(value: unknown): Visibility {\n return value === \"org\" || value === \"public\" ? value : \"private\";\n}\n\nfunction normalizeActorKind(value: unknown): HistoryActorKind {\n return value === \"agent\" || value === \"system\" ? value : \"human\";\n}\n\nfunction stringifyOptionalJson(value: unknown): string | null {\n return value === null || value === undefined ? null : JSON.stringify(value);\n}\n\nfunction parseOptionalJson(value: unknown): Record<string, unknown> | null {\n if (value === null || value === undefined || value === \"\") {\n return null;\n }\n const parsed = parseRequiredJson(value);\n return typeof parsed === \"object\" && parsed !== null && !Array.isArray(parsed)\n ? (parsed as Record<string, unknown>)\n : null;\n}\n\nfunction parseRequiredJson(value: unknown): unknown {\n if (typeof value !== \"string\") {\n return value;\n }\n return JSON.parse(value);\n}\n"]}
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/history/store.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n getDbExec,\n intType,\n isPostgres,\n isUniqueViolation,\n} from \"../db/client.js\";\nimport { ensureIndexExists, ensureTableExists } from \"../db/ddl-guard.js\";\nimport type { Visibility } from \"../sharing/schema.js\";\nimport type {\n HistoryActorKind,\n ResourceHistoryScope,\n ResourceVersion,\n} from \"./types.js\";\n\nlet historyTableInitPromise: Promise<void> | undefined;\n\nconst VERSION_INSERT_MAX_ATTEMPTS = 8;\n\nexport interface InsertResourceVersionInput {\n resourceType: string;\n resourceId: string;\n createdBy?: string | null;\n actorKind?: HistoryActorKind;\n ownerEmail?: string | null;\n orgId?: string | null;\n visibility?: Visibility | null;\n title?: string | null;\n summary?: string | null;\n snapshot: unknown;\n metadata?: Record<string, unknown> | null;\n}\n\nexport interface QueryResourceVersionsInput {\n resourceType: string;\n resourceId: string;\n scope: ResourceHistoryScope;\n bypassScope?: boolean;\n limit?: number;\n offset?: number;\n}\n\nexport async function ensureResourceVersionsTable(): Promise<void> {\n if (!historyTableInitPromise) {\n historyTableInitPromise = (async () => {\n const client = getDbExec();\n const createSql = `CREATE TABLE IF NOT EXISTS agent_resource_versions (\n id TEXT PRIMARY KEY,\n resource_type TEXT NOT NULL,\n resource_id TEXT NOT NULL,\n version_number ${intType()} NOT NULL,\n created_at TEXT NOT NULL,\n created_by TEXT,\n actor_kind TEXT NOT NULL DEFAULT 'human',\n owner_email TEXT,\n org_id TEXT,\n visibility TEXT NOT NULL DEFAULT 'private',\n title TEXT,\n summary TEXT,\n snapshot_json TEXT NOT NULL,\n metadata_json TEXT\n )`;\n const indexes = [\n `CREATE UNIQUE INDEX IF NOT EXISTS idx_agent_resource_versions_resource_number\n ON agent_resource_versions (resource_type, resource_id, version_number)`,\n `CREATE INDEX IF NOT EXISTS idx_agent_resource_versions_owner\n ON agent_resource_versions (owner_email, created_at)`,\n `CREATE INDEX IF NOT EXISTS idx_agent_resource_versions_org\n ON agent_resource_versions (org_id, created_at)`,\n ];\n\n if (isPostgres()) {\n await ensureTableExists(\"agent_resource_versions\", createSql);\n await ensureIndexExists(\n \"idx_agent_resource_versions_resource_number\",\n indexes[0],\n );\n await ensureIndexExists(\n \"idx_agent_resource_versions_owner\",\n indexes[1],\n );\n await ensureIndexExists(\"idx_agent_resource_versions_org\", indexes[2]);\n } else {\n await client.execute(createSql);\n for (const indexSql of indexes) {\n await client.execute(indexSql);\n }\n }\n })();\n }\n\n await historyTableInitPromise;\n}\n\nexport async function insertResourceVersion(\n input: InsertResourceVersionInput,\n): Promise<ResourceVersion> {\n await ensureResourceVersionsTable();\n const client = getDbExec();\n const visibility =\n input.visibility === \"org\" || input.visibility === \"public\"\n ? input.visibility\n : \"private\";\n const actorKind = input.actorKind ?? \"human\";\n const createdBy = input.createdBy ?? null;\n const ownerEmail = input.ownerEmail ?? input.createdBy ?? null;\n const orgId = input.orgId ?? null;\n const title = input.title ?? null;\n const summary = input.summary ?? null;\n const metadata = input.metadata ?? null;\n const snapshotJson = JSON.stringify(input.snapshot);\n const metadataJson = stringifyOptionalJson(metadata);\n\n let lastError: unknown;\n for (let attempt = 0; attempt < VERSION_INSERT_MAX_ATTEMPTS; attempt++) {\n const maxRows = await client.execute({\n sql: `SELECT MAX(version_number) as max_version\n FROM agent_resource_versions\n WHERE resource_type = ? AND resource_id = ?`,\n args: [input.resourceType, input.resourceId],\n });\n const versionNumber =\n Number(\n (maxRows.rows?.[0] as Record<string, unknown> | undefined)\n ?.max_version ?? 0,\n ) + 1;\n const id = createVersionId();\n const createdAt = new Date().toISOString();\n const version: ResourceVersion = {\n id,\n resourceType: input.resourceType,\n resourceId: input.resourceId,\n versionNumber,\n createdAt,\n createdBy,\n actorKind,\n ownerEmail,\n orgId,\n visibility,\n title,\n summary,\n snapshot: input.snapshot,\n metadata,\n };\n\n try {\n await client.execute({\n sql: `INSERT INTO agent_resource_versions (\n id,\n resource_type,\n resource_id,\n version_number,\n created_at,\n created_by,\n actor_kind,\n owner_email,\n org_id,\n visibility,\n title,\n summary,\n snapshot_json,\n metadata_json\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n version.id,\n version.resourceType,\n version.resourceId,\n version.versionNumber,\n version.createdAt,\n version.createdBy,\n version.actorKind,\n version.ownerEmail,\n version.orgId,\n version.visibility,\n version.title,\n version.summary,\n snapshotJson,\n metadataJson,\n ],\n });\n return version;\n } catch (error) {\n lastError = error;\n if (!isUniqueViolation(error)) {\n throw error;\n }\n }\n }\n\n throw lastError instanceof Error\n ? lastError\n : new Error(\"Failed to allocate a unique resource version number\");\n}\n\nexport async function queryResourceVersions(\n input: QueryResourceVersionsInput,\n): Promise<ResourceVersion[]> {\n await ensureResourceVersionsTable();\n const client = getDbExec();\n const { clause, params } = input.bypassScope\n ? { clause: \"1 = 1\", params: [] as unknown[] }\n : scopedResourceClause(input.scope);\n const limit = clampLimit(input.limit);\n const offset = Math.max(0, Math.floor(input.offset ?? 0));\n const result = await client.execute({\n sql: `SELECT ${listColumns()}\n FROM agent_resource_versions\n WHERE resource_type = ? AND resource_id = ? AND ${clause}\n ORDER BY version_number DESC\n LIMIT ? OFFSET ?`,\n args: [input.resourceType, input.resourceId, ...params, limit, offset],\n });\n return (result.rows ?? []).map((row) => mapVersionRow(row, false));\n}\n\nexport async function getResourceVersionById(\n id: string,\n scope: ResourceHistoryScope,\n options: { bypassScope?: boolean } = {},\n): Promise<ResourceVersion | null> {\n await ensureResourceVersionsTable();\n const client = getDbExec();\n const { clause, params } = options.bypassScope\n ? { clause: \"1 = 1\", params: [] as unknown[] }\n : scopedResourceClause(scope);\n const result = await client.execute({\n sql: `SELECT ${allColumns()}\n FROM agent_resource_versions\n WHERE id = ? AND ${clause}\n LIMIT 1`,\n args: [id, ...params],\n });\n const row = result.rows?.[0];\n return row ? mapVersionRow(row, true) : null;\n}\n\nexport async function getResourceVersionByNumber(\n resourceType: string,\n resourceId: string,\n versionNumber: number,\n scope: ResourceHistoryScope,\n options: { bypassScope?: boolean } = {},\n): Promise<ResourceVersion | null> {\n await ensureResourceVersionsTable();\n const client = getDbExec();\n const { clause, params } = options.bypassScope\n ? { clause: \"1 = 1\", params: [] as unknown[] }\n : scopedResourceClause(scope);\n const result = await client.execute({\n sql: `SELECT ${allColumns()}\n FROM agent_resource_versions\n WHERE resource_type = ?\n AND resource_id = ?\n AND version_number = ?\n AND ${clause}\n LIMIT 1`,\n args: [resourceType, resourceId, versionNumber, ...params],\n });\n const row = result.rows?.[0];\n return row ? mapVersionRow(row, true) : null;\n}\n\nexport function __resetHistoryInitForTests(): void {\n historyTableInitPromise = undefined;\n}\n\nfunction listColumns(): string {\n return [\n \"id\",\n \"resource_type\",\n \"resource_id\",\n \"version_number\",\n \"created_at\",\n \"created_by\",\n \"actor_kind\",\n \"owner_email\",\n \"org_id\",\n \"visibility\",\n \"title\",\n \"summary\",\n \"metadata_json\",\n ].join(\", \");\n}\n\nfunction allColumns(): string {\n return `${listColumns()}, snapshot_json`;\n}\n\nfunction scopedResourceClause(scope: ResourceHistoryScope): {\n clause: string;\n params: unknown[];\n} {\n const parts: string[] = [];\n const params: unknown[] = [];\n\n if (scope.userEmail) {\n parts.push(\"owner_email = ?\");\n params.push(scope.userEmail);\n }\n if (scope.orgId) {\n parts.push(\"(visibility = 'org' AND org_id = ?)\");\n params.push(scope.orgId);\n }\n parts.push(\"visibility = 'public'\");\n\n if (parts.length === 0) {\n return { clause: \"visibility = 'public'\", params: [] };\n }\n\n return { clause: `(${parts.join(\" OR \")})`, params };\n}\n\nfunction mapVersionRow(\n row: Record<string, unknown>,\n includeSnapshot: boolean,\n): ResourceVersion {\n const version: ResourceVersion = {\n id: String(row.id),\n resourceType: String(row.resource_type),\n resourceId: String(row.resource_id),\n versionNumber: Number(row.version_number),\n createdAt: String(row.created_at),\n createdBy: nullableString(row.created_by),\n actorKind: normalizeActorKind(row.actor_kind),\n ownerEmail: nullableString(row.owner_email),\n orgId: nullableString(row.org_id),\n visibility: normalizeVisibility(row.visibility),\n title: nullableString(row.title),\n summary: nullableString(row.summary),\n metadata: parseOptionalJson(row.metadata_json),\n };\n if (includeSnapshot) {\n version.snapshot = parseRequiredJson(row.snapshot_json);\n }\n return version;\n}\n\nfunction createVersionId(): string {\n return `ver_${globalThis.crypto.randomUUID()}`;\n}\n\nfunction clampLimit(value: number | undefined): number {\n if (!Number.isFinite(value)) {\n return 50;\n }\n return Math.min(200, Math.max(1, Math.floor(value ?? 50)));\n}\n\nfunction nullableString(value: unknown): string | null {\n return value === null || value === undefined ? null : String(value);\n}\n\nfunction normalizeVisibility(value: unknown): Visibility {\n return value === \"org\" || value === \"public\" ? value : \"private\";\n}\n\nfunction normalizeActorKind(value: unknown): HistoryActorKind {\n return value === \"agent\" || value === \"system\" ? value : \"human\";\n}\n\nfunction stringifyOptionalJson(value: unknown): string | null {\n return value === null || value === undefined ? null : JSON.stringify(value);\n}\n\nfunction parseOptionalJson(value: unknown): Record<string, unknown> | null {\n if (value === null || value === undefined || value === \"\") {\n return null;\n }\n const parsed = parseRequiredJson(value);\n return typeof parsed === \"object\" && parsed !== null && !Array.isArray(parsed)\n ? (parsed as Record<string, unknown>)\n : null;\n}\n\nfunction parseRequiredJson(value: unknown): unknown {\n if (typeof value !== \"string\") {\n return value;\n }\n return JSON.parse(value);\n}\n"]}
@@ -41,16 +41,16 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
41
41
  thumbsUpRate: number;
42
42
  avgEvalScore: number;
43
43
  } | {
44
- error?: undefined;
45
44
  summary: import("./types.js").TraceSummary;
46
45
  spans: import("./types.js").TraceSpan[];
47
46
  id?: undefined;
47
+ error?: undefined;
48
48
  ok?: undefined;
49
49
  } | {
50
- error?: undefined;
51
50
  summary?: undefined;
52
51
  spans?: undefined;
53
52
  id: string;
53
+ error?: undefined;
54
54
  ok?: undefined;
55
55
  } | {
56
56
  summary?: undefined;
@@ -59,10 +59,10 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
59
59
  error: any;
60
60
  ok?: undefined;
61
61
  } | {
62
- error?: undefined;
63
62
  summary?: undefined;
64
63
  spans?: undefined;
65
64
  id?: undefined;
65
+ error?: undefined;
66
66
  ok: boolean;
67
67
  }>>;
68
68
  //# sourceMappingURL=routes.d.ts.map
@@ -15,7 +15,7 @@ export declare function createProgressHandler(): import("h3").EventHandlerWithFe
15
15
  error: string;
16
16
  ok?: undefined;
17
17
  } | {
18
- error?: undefined;
19
18
  ok: boolean;
19
+ error?: undefined;
20
20
  }>>;
21
21
  //# sourceMappingURL=routes.d.ts.map
@@ -4,6 +4,7 @@ declare const _default: import("../../action.js").ActionDefinition<{
4
4
  commentIds: string[];
5
5
  }, {
6
6
  consumedCommentIds: string[];
7
+ updatedCount: number;
7
8
  }>;
8
9
  export default _default;
9
10
  //# sourceMappingURL=consume-review-feedback.d.ts.map
@@ -13,11 +13,17 @@ export default defineAction({
13
13
  run: async (args, ctx) => {
14
14
  const actionCtx = ctx;
15
15
  await assertReviewableResourceAccess(args.resourceType, args.resourceId, actionCtx, "editor");
16
- await consumeReviewFeedback(args.commentIds, undefined, {
16
+ const updatedCount = await consumeReviewFeedback(args.commentIds, undefined, {
17
17
  resourceType: args.resourceType,
18
18
  resourceId: args.resourceId,
19
19
  });
20
- return { consumedCommentIds: args.commentIds };
20
+ if (updatedCount < 1) {
21
+ throw new Error("No matching review comments to consume");
22
+ }
23
+ return {
24
+ consumedCommentIds: args.commentIds,
25
+ updatedCount,
26
+ };
21
27
  },
22
28
  audit: {
23
29
  target: (args) => ({