@agent-native/core 0.114.12 → 0.114.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (241) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +21 -0
  3. package/corpus/core/docs/content/deployment.mdx +1 -1
  4. package/corpus/core/docs/content/frames.mdx +1 -1
  5. package/corpus/core/docs/content/integrations.mdx +27 -27
  6. package/corpus/core/docs/content/pr-visual-recap.mdx +17 -13
  7. package/corpus/core/docs/content/workspace-management.mdx +1 -1
  8. package/corpus/core/package.json +2 -1
  9. package/corpus/core/src/agent/engine/builder-engine.ts +4 -0
  10. package/corpus/core/src/application-state/index.ts +3 -0
  11. package/corpus/core/src/application-state/script-helpers.ts +12 -1
  12. package/corpus/core/src/application-state/store.ts +216 -15
  13. package/corpus/core/src/client/AgentPanel.tsx +10 -4
  14. package/corpus/core/src/client/ConnectBuilderCard.tsx +5 -1
  15. package/corpus/core/src/client/chat/markdown-renderer.tsx +3 -5
  16. package/corpus/core/src/client/error-format.ts +2 -1
  17. package/corpus/core/src/client/index.ts +1 -0
  18. package/corpus/core/src/client/integrations/IntegrationsPanel.tsx +2 -18
  19. package/corpus/core/src/client/resources/McpIntegrationDialog.tsx +43 -32
  20. package/corpus/core/src/client/resources/mcp-integration-catalog.ts +4 -2
  21. package/corpus/core/src/client/settings/BackgroundAgentSection.tsx +5 -1
  22. package/corpus/core/src/client/settings/SettingsPanel.tsx +4 -4
  23. package/corpus/core/src/client/settings/useBuilderStatus.ts +3 -0
  24. package/corpus/core/src/db/client.ts +44 -1
  25. package/corpus/core/src/localization/default-messages.ts +1 -7
  26. package/corpus/core/src/server/builder-browser.ts +4 -0
  27. package/corpus/core/src/server/builder-design-systems.ts +6 -1
  28. package/corpus/core/src/server/fusion-app.ts +5 -1
  29. package/corpus/core/src/shared/builder-link-tracking.ts +41 -0
  30. package/corpus/core/src/shared/index.ts +1 -0
  31. package/corpus/templates/analytics/AGENTS.md +10 -1
  32. package/corpus/templates/analytics/actions/save-dashboard-report-subscription.ts +10 -2
  33. package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +5 -4
  34. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +20 -32
  35. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/report-panel-window.ts +62 -0
  36. package/corpus/templates/analytics/changelog/2026-07-21-chart-series-controls-stay-open-while-moving-from-the-legend.md +6 -0
  37. package/corpus/templates/analytics/changelog/2026-07-21-dashboard-email-captures-complete-large-dashboards-in-chunks.md +6 -0
  38. package/corpus/templates/analytics/seeds/dashboards/agent-native-templates-first-party.json +4 -4
  39. package/corpus/templates/analytics/server/jobs/dashboard-report.ts +1 -8
  40. package/corpus/templates/analytics/server/lib/dashboard-report-subscriptions.ts +39 -7
  41. package/corpus/templates/analytics/server/lib/dashboard-report.ts +341 -251
  42. package/corpus/templates/analytics/server/lib/first-party-dashboard-repair.ts +114 -0
  43. package/corpus/templates/analytics/server/lib/first-party-metric-catalog.ts +84 -6
  44. package/corpus/templates/analytics/server/plugins/db.ts +13 -0
  45. package/corpus/templates/clips/app/components/player/video-player.tsx +10 -4
  46. package/corpus/templates/clips/changelog/2026-07-21-choose-which-whisper-model-to-use-in-settings.md +6 -0
  47. package/corpus/templates/clips/changelog/2026-07-21-fixed-organization-recording-visibility-default.md +6 -0
  48. package/corpus/templates/clips/changelog/2026-07-21-live-dictation-text-now-appears-above-the-desktop-recording-.md +6 -0
  49. package/corpus/templates/clips/changelog/2026-07-21-meeting-notes-stop-when-calls-end.md +6 -0
  50. package/corpus/templates/clips/desktop/src/app.tsx +66 -75
  51. package/corpus/templates/clips/desktop/src/hooks/useMeetingTranscription.ts +2 -0
  52. package/corpus/templates/clips/desktop/src/hooks/useWhisperSettings.ts +172 -0
  53. package/corpus/templates/clips/desktop/src/lib/meeting-call-app.ts +41 -0
  54. package/corpus/templates/clips/desktop/src/lib/silence-events.ts +1 -0
  55. package/corpus/templates/clips/desktop/src/lib/voice-dictation.ts +14 -3
  56. package/corpus/templates/clips/desktop/src/overlays/flow-bar.tsx +25 -0
  57. package/corpus/templates/clips/desktop/src/shared/config.ts +1 -0
  58. package/corpus/templates/clips/desktop/src/styles.css +100 -7
  59. package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +3 -4
  60. package/corpus/templates/clips/desktop/src-tauri/src/config.rs +32 -0
  61. package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +3 -0
  62. package/corpus/templates/clips/desktop/src-tauri/src/native_screen/custom_capture.rs +11 -4
  63. package/corpus/templates/clips/desktop/src-tauri/src/silence_detector.rs +268 -20
  64. package/corpus/templates/clips/desktop/src-tauri/src/whisper_model.rs +285 -164
  65. package/corpus/templates/clips/desktop/src-tauri/src/whisper_speech.rs +18 -7
  66. package/corpus/templates/clips/learnings.defaults.md +1 -1
  67. package/corpus/templates/clips/server/plugins/db.ts +11 -0
  68. package/corpus/templates/clips/shared/builder-credits.ts +1 -1
  69. package/corpus/templates/design/AGENTS.md +7 -3
  70. package/corpus/templates/design/actions/begin-node-rewrite-request.ts +78 -0
  71. package/corpus/templates/design/actions/cancel-node-rewrite-request.ts +17 -7
  72. package/corpus/templates/design/actions/propose-node-rewrite.ts +26 -18
  73. package/corpus/templates/design/actions/resolve-node-rewrite.ts +67 -19
  74. package/corpus/templates/design/app/components/design/FusionAppBanner.tsx +9 -1
  75. package/corpus/templates/design/app/components/design/edit-panel/component-section.tsx +5 -1
  76. package/corpus/templates/design/app/components/visual-editor/NodeRewriteProposal.tsx +1 -4
  77. package/corpus/templates/design/app/components/visual-editor/ReviewCanvasPins.tsx +2 -6
  78. package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +9 -1
  79. package/corpus/templates/design/shared/node-rewrite.ts +32 -0
  80. package/corpus/templates/forms/app/components/layout/Sidebar.tsx +6 -3
  81. package/corpus/templates/forms/app/pages/FormBuilderPage.tsx +11 -18
  82. package/corpus/templates/forms/app/pages/FormsListPage.tsx +9 -5
  83. package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +9 -1
  84. package/corpus/templates/slides/app/context/DeckContext.tsx +18 -0
  85. package/corpus/templates/slides/changelog/2026-07-21-decks-list-now-refreshes-when-you-switch-organizations.md +6 -0
  86. package/corpus/templates/tasks/app/components/custom-fields/FieldCreateBar.tsx +13 -19
  87. package/corpus/templates/tasks/app/components/custom-fields/FieldListRow.tsx +27 -22
  88. package/corpus/templates/tasks/app/components/custom-fields/FieldsList.tsx +26 -22
  89. package/corpus/templates/tasks/app/components/custom-fields/FieldsListSkeleton.tsx +4 -1
  90. package/corpus/templates/tasks/app/components/custom-fields/FieldsPage.tsx +4 -2
  91. package/corpus/templates/tasks/app/components/custom-fields/editor/FieldEditorSidebar.tsx +12 -3
  92. package/corpus/templates/tasks/app/components/custom-fields/editor/FieldTitleSection.tsx +6 -3
  93. package/corpus/templates/tasks/app/components/custom-fields/editor/config/CurrencyConfigControl.tsx +5 -2
  94. package/corpus/templates/tasks/app/components/custom-fields/editor/config/NumberConfigControl.tsx +5 -2
  95. package/corpus/templates/tasks/app/components/custom-fields/editor/config/PercentConfigControl.tsx +4 -1
  96. package/corpus/templates/tasks/app/components/custom-fields/editor/config/SelectConfigControl.tsx +17 -7
  97. package/corpus/templates/tasks/app/components/custom-fields/editor/config/select-colors.ts +37 -9
  98. package/corpus/templates/tasks/app/components/custom-fields/field-types.ts +23 -0
  99. package/corpus/templates/tasks/app/components/inbox/InboxList.tsx +24 -16
  100. package/corpus/templates/tasks/app/components/inbox/InboxListPage.tsx +5 -3
  101. package/corpus/templates/tasks/app/components/inbox/InboxListRow.tsx +7 -5
  102. package/corpus/templates/tasks/app/components/layout/Header.tsx +10 -10
  103. package/corpus/templates/tasks/app/components/layout/Layout.tsx +11 -7
  104. package/corpus/templates/tasks/app/components/layout/Sidebar.tsx +17 -10
  105. package/corpus/templates/tasks/app/components/shared/AddListItemInput.tsx +14 -8
  106. package/corpus/templates/tasks/app/components/shared/AlertDialog.tsx +6 -2
  107. package/corpus/templates/tasks/app/components/shared/BulkDeleteDialog.tsx +13 -6
  108. package/corpus/templates/tasks/app/components/shared/ChipSelect.tsx +12 -5
  109. package/corpus/templates/tasks/app/components/shared/DeleteItemDialog.tsx +6 -6
  110. package/corpus/templates/tasks/app/components/shared/ListViewHeader.tsx +3 -1
  111. package/corpus/templates/tasks/app/components/shared/SidePanel.tsx +5 -2
  112. package/corpus/templates/tasks/app/components/shared/list/ListRowDragHandle.tsx +3 -1
  113. package/corpus/templates/tasks/app/components/shared/selection/ListSelectionBar.tsx +46 -20
  114. package/corpus/templates/tasks/app/components/shared/selection/ListSelectionHeaderToggle.tsx +3 -1
  115. package/corpus/templates/tasks/app/components/shared/selection/ListSelectionToolbar.tsx +10 -6
  116. package/corpus/templates/tasks/app/components/tasks/TaskList.tsx +24 -13
  117. package/corpus/templates/tasks/app/components/tasks/TaskListHeaderRow.tsx +4 -1
  118. package/corpus/templates/tasks/app/components/tasks/TaskListPage.tsx +5 -3
  119. package/corpus/templates/tasks/app/components/tasks/TaskListRow.tsx +15 -6
  120. package/corpus/templates/tasks/app/components/tasks/fields/TaskFieldsSidebar.tsx +11 -6
  121. package/corpus/templates/tasks/app/components/tasks/fields/TaskTitleSection.tsx +8 -3
  122. package/corpus/templates/tasks/app/components/tasks/fields/controls/RichTextValueControl.tsx +12 -6
  123. package/corpus/templates/tasks/app/components/tasks/fields/controls/SingleSelectValueControl.tsx +6 -1
  124. package/corpus/templates/tasks/app/i18n/en-US.ts +209 -0
  125. package/corpus/templates/tasks/app/i18n/index.ts +34 -0
  126. package/corpus/templates/tasks/app/root.tsx +34 -2
  127. package/corpus/templates/tasks/app/routes/extensions.$id.tsx +2 -1
  128. package/corpus/templates/tasks/app/routes/extensions._index.tsx +2 -1
  129. package/corpus/templates/tasks/app/routes/fields.tsx +2 -1
  130. package/corpus/templates/tasks/app/routes/inbox.tsx +2 -1
  131. package/corpus/templates/tasks/app/routes/tasks.tsx +2 -1
  132. package/corpus/templates/tasks/app/routes/team.tsx +6 -3
  133. package/corpus/templates/tasks/changelog/2026-07-20-tasks-is-now-available-in-10-additional-languages.md +6 -0
  134. package/dist/agent/engine/builder-engine.d.ts.map +1 -1
  135. package/dist/agent/engine/builder-engine.js +4 -0
  136. package/dist/agent/engine/builder-engine.js.map +1 -1
  137. package/dist/application-state/index.d.ts +2 -2
  138. package/dist/application-state/index.d.ts.map +1 -1
  139. package/dist/application-state/index.js +2 -2
  140. package/dist/application-state/index.js.map +1 -1
  141. package/dist/application-state/script-helpers.d.ts +3 -1
  142. package/dist/application-state/script-helpers.d.ts.map +1 -1
  143. package/dist/application-state/script-helpers.js +7 -1
  144. package/dist/application-state/script-helpers.js.map +1 -1
  145. package/dist/application-state/store.d.ts +7 -1
  146. package/dist/application-state/store.d.ts.map +1 -1
  147. package/dist/application-state/store.js +143 -17
  148. package/dist/application-state/store.js.map +1 -1
  149. package/dist/client/AgentPanel.d.ts.map +1 -1
  150. package/dist/client/AgentPanel.js +10 -3
  151. package/dist/client/AgentPanel.js.map +1 -1
  152. package/dist/client/ConnectBuilderCard.d.ts.map +1 -1
  153. package/dist/client/ConnectBuilderCard.js +5 -1
  154. package/dist/client/ConnectBuilderCard.js.map +1 -1
  155. package/dist/client/chat/markdown-renderer.d.ts.map +1 -1
  156. package/dist/client/chat/markdown-renderer.js +3 -2
  157. package/dist/client/chat/markdown-renderer.js.map +1 -1
  158. package/dist/client/error-format.d.ts +1 -1
  159. package/dist/client/error-format.d.ts.map +1 -1
  160. package/dist/client/error-format.js +1 -1
  161. package/dist/client/error-format.js.map +1 -1
  162. package/dist/client/index.d.ts +1 -0
  163. package/dist/client/index.d.ts.map +1 -1
  164. package/dist/client/index.js +1 -0
  165. package/dist/client/index.js.map +1 -1
  166. package/dist/client/integrations/IntegrationsPanel.d.ts.map +1 -1
  167. package/dist/client/integrations/IntegrationsPanel.js +3 -4
  168. package/dist/client/integrations/IntegrationsPanel.js.map +1 -1
  169. package/dist/client/resources/McpIntegrationDialog.d.ts.map +1 -1
  170. package/dist/client/resources/McpIntegrationDialog.js +21 -7
  171. package/dist/client/resources/McpIntegrationDialog.js.map +1 -1
  172. package/dist/client/resources/mcp-integration-catalog.d.ts.map +1 -1
  173. package/dist/client/resources/mcp-integration-catalog.js +2 -2
  174. package/dist/client/resources/mcp-integration-catalog.js.map +1 -1
  175. package/dist/client/settings/BackgroundAgentSection.d.ts.map +1 -1
  176. package/dist/client/settings/BackgroundAgentSection.js +5 -1
  177. package/dist/client/settings/BackgroundAgentSection.js.map +1 -1
  178. package/dist/client/settings/SettingsPanel.js +1 -1
  179. package/dist/client/settings/SettingsPanel.js.map +1 -1
  180. package/dist/client/settings/useBuilderStatus.d.ts.map +1 -1
  181. package/dist/client/settings/useBuilderStatus.js +2 -0
  182. package/dist/client/settings/useBuilderStatus.js.map +1 -1
  183. package/dist/collab/routes.d.ts +1 -1
  184. package/dist/db/client.d.ts +7 -0
  185. package/dist/db/client.d.ts.map +1 -1
  186. package/dist/db/client.js +39 -1
  187. package/dist/db/client.js.map +1 -1
  188. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  189. package/dist/localization/default-messages.d.ts +0 -6
  190. package/dist/localization/default-messages.d.ts.map +1 -1
  191. package/dist/localization/default-messages.js +1 -7
  192. package/dist/localization/default-messages.js.map +1 -1
  193. package/dist/notifications/routes.d.ts +2 -2
  194. package/dist/observability/routes.d.ts +3 -3
  195. package/dist/resources/handlers.d.ts +1 -1
  196. package/dist/server/builder-browser.d.ts.map +1 -1
  197. package/dist/server/builder-browser.js +4 -0
  198. package/dist/server/builder-browser.js.map +1 -1
  199. package/dist/server/builder-design-systems.d.ts.map +1 -1
  200. package/dist/server/builder-design-systems.js +6 -1
  201. package/dist/server/builder-design-systems.js.map +1 -1
  202. package/dist/server/fusion-app.d.ts.map +1 -1
  203. package/dist/server/fusion-app.js +2 -1
  204. package/dist/server/fusion-app.js.map +1 -1
  205. package/dist/server/transcribe-voice.d.ts +1 -1
  206. package/dist/shared/builder-link-tracking.d.ts +14 -0
  207. package/dist/shared/builder-link-tracking.d.ts.map +1 -0
  208. package/dist/shared/builder-link-tracking.js +26 -0
  209. package/dist/shared/builder-link-tracking.js.map +1 -0
  210. package/dist/shared/index.d.ts +1 -0
  211. package/dist/shared/index.d.ts.map +1 -1
  212. package/dist/shared/index.js +1 -0
  213. package/dist/shared/index.js.map +1 -1
  214. package/docs/content/deployment.mdx +1 -1
  215. package/docs/content/frames.mdx +1 -1
  216. package/docs/content/integrations.mdx +27 -27
  217. package/docs/content/pr-visual-recap.mdx +17 -13
  218. package/docs/content/workspace-management.mdx +1 -1
  219. package/package.json +3 -2
  220. package/src/agent/engine/builder-engine.ts +4 -0
  221. package/src/application-state/index.ts +3 -0
  222. package/src/application-state/script-helpers.ts +12 -1
  223. package/src/application-state/store.ts +216 -15
  224. package/src/client/AgentPanel.tsx +10 -4
  225. package/src/client/ConnectBuilderCard.tsx +5 -1
  226. package/src/client/chat/markdown-renderer.tsx +3 -5
  227. package/src/client/error-format.ts +2 -1
  228. package/src/client/index.ts +1 -0
  229. package/src/client/integrations/IntegrationsPanel.tsx +2 -18
  230. package/src/client/resources/McpIntegrationDialog.tsx +43 -32
  231. package/src/client/resources/mcp-integration-catalog.ts +4 -2
  232. package/src/client/settings/BackgroundAgentSection.tsx +5 -1
  233. package/src/client/settings/SettingsPanel.tsx +4 -4
  234. package/src/client/settings/useBuilderStatus.ts +3 -0
  235. package/src/db/client.ts +44 -1
  236. package/src/localization/default-messages.ts +1 -7
  237. package/src/server/builder-browser.ts +4 -0
  238. package/src/server/builder-design-systems.ts +6 -1
  239. package/src/server/fusion-app.ts +5 -1
  240. package/src/shared/builder-link-tracking.ts +41 -0
  241. package/src/shared/index.ts +1 -0
@@ -1,4 +1,4 @@
1
- import { getDbExec, isLocalDatabase, isConnectionError, isPostgres, intType, } from "../db/client.js";
1
+ import { getDbExec, getDialect, isLocalDatabase, isConnectionError, isPostgres, intType, } from "../db/client.js";
2
2
  import { ensureIndexExists, ensureTableExists } from "../db/ddl-guard.js";
3
3
  import { widenIntColumnsToBigInt } from "../db/widen-columns.js";
4
4
  import { emitAppStateChange, emitAppStateDelete } from "./emitter.js";
@@ -160,30 +160,156 @@ export async function appStateDelete(sessionId, key, options) {
160
160
  export async function appStateCompareAndSet(sessionId, key, expectedValue, nextValue, options) {
161
161
  await ensureTable();
162
162
  const client = getDbExec();
163
+ const changed = await executeAppStateCompareAndSet(client, sessionId, key, expectedValue, nextValue);
164
+ if (changed) {
165
+ if (nextValue === null) {
166
+ emitAppStateDelete(key, options?.requestSource, sessionId);
167
+ }
168
+ else {
169
+ emitAppStateChange(key, options?.requestSource, sessionId);
170
+ }
171
+ }
172
+ return changed;
173
+ }
174
+ const APP_STATE_CAS_MISMATCH = Symbol("app-state-cas-mismatch");
175
+ async function executeAppStateCompareAndSet(client, sessionId, key, expectedValue, nextValue) {
176
+ const statement = buildAppStateCompareAndSetStatement(sessionId, key, expectedValue, nextValue);
177
+ const result = await client.execute(statement);
178
+ return result.rowsAffected > 0;
179
+ }
180
+ function buildAppStateCompareAndSetStatement(sessionId, key, expectedValue, nextValue) {
181
+ if (expectedValue === null) {
182
+ if (nextValue === null) {
183
+ throw new Error("Application state CAS cannot replace absence with absence.");
184
+ }
185
+ const next = serializeAppStateValue(key, nextValue);
186
+ return {
187
+ sql: isPostgres()
188
+ ? `INSERT INTO application_state (session_id, key, value, updated_at) SELECT ?, ?, ?, ? WHERE NOT EXISTS (SELECT 1 FROM application_state WHERE session_id = ? AND key = ?) ON CONFLICT (session_id, key) DO NOTHING`
189
+ : `INSERT OR IGNORE INTO application_state (session_id, key, value, updated_at) SELECT ?, ?, ?, ? WHERE NOT EXISTS (SELECT 1 FROM application_state WHERE session_id = ? AND key = ?)`,
190
+ args: [sessionId, key, next, Date.now(), sessionId, key],
191
+ };
192
+ }
163
193
  const expected = JSON.stringify(expectedValue);
164
194
  if (nextValue === null) {
165
- const result = await client.execute({
195
+ return {
166
196
  sql: `DELETE FROM application_state WHERE session_id = ? AND key = ? AND value = ?`,
167
197
  args: [sessionId, key, expected],
168
- });
169
- const changed = result.rowsAffected > 0;
170
- if (changed)
171
- emitAppStateDelete(key, options?.requestSource, sessionId);
172
- return changed;
198
+ };
173
199
  }
174
- const next = JSON.stringify(nextValue);
200
+ const next = serializeAppStateValue(key, nextValue);
201
+ return {
202
+ sql: `UPDATE application_state SET value = ?, updated_at = ? WHERE session_id = ? AND key = ? AND value = ?`,
203
+ args: [next, Date.now(), sessionId, key, expected],
204
+ };
205
+ }
206
+ function buildD1CompareAndSetGuard(sessionId, guardKey, operation) {
207
+ const expected = operation.expectedValue;
208
+ const condition = expected === null
209
+ ? "NOT EXISTS (SELECT 1 FROM application_state WHERE session_id = ? AND key = ?)"
210
+ : "EXISTS (SELECT 1 FROM application_state WHERE session_id = ? AND key = ? AND value = ?)";
211
+ return {
212
+ sql: `INSERT INTO application_state (session_id, key, value, updated_at) SELECT ?, ?, '{}', ? WHERE NOT (${condition})`,
213
+ args: expected === null
214
+ ? [sessionId, guardKey, Date.now(), sessionId, operation.key]
215
+ : [
216
+ sessionId,
217
+ guardKey,
218
+ Date.now(),
219
+ sessionId,
220
+ operation.key,
221
+ JSON.stringify(expected),
222
+ ],
223
+ };
224
+ }
225
+ function isD1CompareAndSetMismatch(error) {
226
+ const message = error instanceof Error ? error.message : String(error);
227
+ return /unique constraint failed:\s*application_state\.session_id,\s*application_state\.key/i.test(message);
228
+ }
229
+ function serializeAppStateValue(key, value) {
230
+ const serialized = JSON.stringify(value);
175
231
  if (!isLocalDatabase() &&
176
- Buffer.byteLength(next, "utf8") > MAX_HOSTED_APP_STATE_VALUE_BYTES) {
232
+ Buffer.byteLength(serialized, "utf8") > MAX_HOSTED_APP_STATE_VALUE_BYTES) {
177
233
  throw new Error(`application_state value "${key}" is too large for hosted SQL storage. Store large files, base64, or blobs in file storage and write only a URL or handle.`);
178
234
  }
179
- const result = await client.execute({
180
- sql: `UPDATE application_state SET value = ?, updated_at = ? WHERE session_id = ? AND key = ? AND value = ?`,
181
- args: [next, Date.now(), sessionId, key, expected],
182
- });
183
- const changed = result.rowsAffected > 0;
184
- if (changed)
185
- emitAppStateChange(key, options?.requestSource, sessionId);
186
- return changed;
235
+ return serialized;
236
+ }
237
+ export async function appStateCompareAndSetMany(sessionId, operations, options) {
238
+ if (operations.length === 0)
239
+ return true;
240
+ const keys = new Set(operations.map(({ key }) => key));
241
+ if (keys.size !== operations.length) {
242
+ throw new Error("Application state multi-key CAS requires unique keys.");
243
+ }
244
+ for (const { key, nextValue } of operations) {
245
+ if (nextValue)
246
+ serializeAppStateValue(key, nextValue);
247
+ }
248
+ const orderedOperations = [...operations].sort((a, b) => a.key.localeCompare(b.key));
249
+ await ensureTable();
250
+ const client = getDbExec();
251
+ if (getDialect() === "d1") {
252
+ if (!client.atomicBatch) {
253
+ throw new Error("D1 application-state CAS requires atomic batch support.");
254
+ }
255
+ const guardKey = `__agent_native_cas_guard__:${Date.now()}:${Math.random().toString(36).slice(2)}`;
256
+ const guardInsert = {
257
+ sql: `INSERT INTO application_state (session_id, key, value, updated_at) VALUES (?, ?, '{}', ?)`,
258
+ args: [sessionId, guardKey, Date.now()],
259
+ };
260
+ const guards = orderedOperations.map((operation) => buildD1CompareAndSetGuard(sessionId, guardKey, operation));
261
+ const mutations = orderedOperations.map((operation) => buildAppStateCompareAndSetStatement(sessionId, operation.key, operation.expectedValue, operation.nextValue));
262
+ let results;
263
+ try {
264
+ results = await client.atomicBatch([
265
+ guardInsert,
266
+ ...guards,
267
+ ...mutations,
268
+ {
269
+ sql: `DELETE FROM application_state WHERE session_id = ? AND key = ?`,
270
+ args: [sessionId, guardKey],
271
+ },
272
+ ]);
273
+ }
274
+ catch (error) {
275
+ if (isD1CompareAndSetMismatch(error))
276
+ return false;
277
+ throw error;
278
+ }
279
+ const mutationResults = results.slice(1 + guards.length, 1 + guards.length + mutations.length);
280
+ if (mutationResults.length !== mutations.length ||
281
+ mutationResults.some((result) => result.rowsAffected !== 1)) {
282
+ throw new Error("D1 application-state CAS completed without applying every mutation.");
283
+ }
284
+ }
285
+ else {
286
+ if (!client.transaction) {
287
+ throw new Error("Application state multi-key CAS requires transactions.");
288
+ }
289
+ try {
290
+ await client.transaction(async (tx) => {
291
+ for (const operation of orderedOperations) {
292
+ const changed = await executeAppStateCompareAndSet(tx, sessionId, operation.key, operation.expectedValue, operation.nextValue);
293
+ if (!changed)
294
+ throw APP_STATE_CAS_MISMATCH;
295
+ }
296
+ });
297
+ }
298
+ catch (error) {
299
+ if (error === APP_STATE_CAS_MISMATCH)
300
+ return false;
301
+ throw error;
302
+ }
303
+ }
304
+ for (const { key, nextValue } of operations) {
305
+ if (nextValue === null) {
306
+ emitAppStateDelete(key, options?.requestSource, sessionId);
307
+ }
308
+ else {
309
+ emitAppStateChange(key, options?.requestSource, sessionId);
310
+ }
311
+ }
312
+ return true;
187
313
  }
188
314
  export async function appStateList(sessionId, keyPrefix) {
189
315
  await ensureTable();
@@ -1 +1 @@
1
- {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/application-state/store.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n getDbExec,\n isLocalDatabase,\n isConnectionError,\n isPostgres,\n intType,\n} from \"../db/client.js\";\nimport { ensureIndexExists, ensureTableExists } from \"../db/ddl-guard.js\";\nimport { widenIntColumnsToBigInt } from \"../db/widen-columns.js\";\nimport type { StoreWriteOptions } from \"../settings/store.js\";\nimport { emitAppStateChange, emitAppStateDelete } from \"./emitter.js\";\n\nlet _initPromise: Promise<void> | undefined;\nconst MAX_HOSTED_APP_STATE_VALUE_BYTES = 1024 * 1024;\n\n// Escapes LIKE wildcards (`%`, `_`) and the escape char itself so a caller's\n// literal prefix is matched verbatim. Used with `ESCAPE '!'` in prefix queries\n// below; without this, a prefix such as `user_settings` would treat `_` as a\n// single-char wildcard and over-match (e.g. delete `userXsettings`).\nfunction escapeLike(s: string): string {\n return s.replace(/[!%_]/g, (match) => `!${match}`);\n}\n\nasync function ensureTable(): Promise<void> {\n if (!_initPromise) {\n _initPromise = (async () => {\n const client = getDbExec();\n const createSql = `\n CREATE TABLE IF NOT EXISTS application_state (\n session_id TEXT NOT NULL,\n key TEXT NOT NULL,\n value TEXT NOT NULL,\n updated_at ${intType()} NOT NULL,\n PRIMARY KEY (session_id, key)\n )\n `;\n\n if (isPostgres()) {\n // Hot path: the `application_state` table and its poll indexes are\n // virtually always already present in production. Issuing `CREATE\n // TABLE`/ `CREATE INDEX` still takes a lock that, in a fresh\n // background-worker process behind a concurrent connection on the\n // shared Neon DB, can block ~indefinitely (ACCESS EXCLUSIVE for CREATE\n // TABLE; a write-blocking SHARE lock for CREATE INDEX). The ensure*\n // wrappers probe `information_schema`/`pg_indexes` first (plain reads,\n // no lock) and run DDL ONLY for what is actually missing, bounded by a\n // transaction-scoped `lock_timeout`. If a swallowed lock-timeout leaves\n // the schema still missing they RE-PROBE and THROW rather than letting\n // init memoize success against absent schema.\n await ensureTableExists(\"application_state\", createSql);\n // Older deployments created `updated_at` as 32-bit `INTEGER`; on Postgres\n // the `Date.now()` written by appStatePut() on every turn overflows int4.\n // Widen it in place (no-op once done / on fresh BIGINT databases).\n await widenIntColumnsToBigInt(\"application_state\", [\"updated_at\"]);\n // Indexes for the two hot poll paths. Probe pg_indexes first (no lock)\n // and skip the SHARE-locking CREATE INDEX when already present.\n await ensureIndexExists(\n \"app_state_updated_at_idx\",\n `CREATE INDEX IF NOT EXISTS app_state_updated_at_idx ON application_state (updated_at)`,\n );\n await ensureIndexExists(\n \"app_state_key_updated_idx\",\n `CREATE INDEX IF NOT EXISTS app_state_key_updated_idx ON application_state (key, updated_at)`,\n );\n return;\n }\n\n // SQLite (local dev): no lock problem — keep the original behaviour.\n await client.execute(createSql);\n // Older deployments created `updated_at` as 32-bit `INTEGER`; on Postgres\n // the `Date.now()` written by appStatePut() on every turn overflows int4.\n // Widen it in place (no-op once done / on fresh BIGINT databases).\n await widenIntColumnsToBigInt(\"application_state\", [\"updated_at\"]);\n // Indexes for the two hot poll paths:\n // - `SELECT … WHERE updated_at > ?` (watermark scan, every poll cycle)\n // - `SELECT … WHERE key = ? … ORDER BY updated_at ASC` (marker lookups)\n // Both are dialect-agnostic (no DESC/partial/PG-only syntax) so they\n // apply identically on SQLite and Postgres. IF NOT EXISTS makes them\n // idempotent across restarts on existing databases.\n for (const ddl of [\n `CREATE INDEX IF NOT EXISTS app_state_updated_at_idx ON application_state (updated_at)`,\n `CREATE INDEX IF NOT EXISTS app_state_key_updated_idx ON application_state (key, updated_at)`,\n ]) {\n try {\n await client.execute(ddl);\n } catch {\n // Index already exists or the dialect rejected a duplicate.\n }\n }\n })().catch((err) => {\n // Retry init on the next call after a failed startup.\n _initPromise = undefined;\n throw err;\n });\n }\n return _initPromise;\n}\n\nexport async function appStateGet(\n sessionId: string,\n key: string,\n): Promise<Record<string, unknown> | null> {\n try {\n await ensureTable();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT value FROM application_state WHERE session_id = ? AND key = ?`,\n args: [sessionId, key],\n });\n if (rows.length === 0) return null;\n return JSON.parse(rows[0].value as string);\n } catch (err) {\n // Transient WS / connection drops (Neon serverless) — caller polls every\n // 2s and will see the value on the next tick. Swallow rather than 500.\n if (isConnectionError(err)) return null;\n throw err;\n }\n}\n\n/**\n * Read several application-state keys for one session in a single SQL query.\n * Missing keys are returned as `null` so callers can preserve the requested\n * shape without issuing one fallback query per key.\n */\nexport async function appStateGetMany(\n sessionId: string,\n keys: readonly string[],\n): Promise<Record<string, Record<string, unknown> | null>> {\n const uniqueKeys = [...new Set(keys)];\n const values: Record<string, Record<string, unknown> | null> = {};\n for (const key of uniqueKeys) values[key] = null;\n if (uniqueKeys.length === 0) return values;\n\n try {\n await ensureTable();\n const client = getDbExec();\n const placeholders = uniqueKeys.map(() => \"?\").join(\", \");\n const { rows } = await client.execute({\n sql: `SELECT key, value FROM application_state WHERE session_id = ? AND key IN (${placeholders})`,\n args: [sessionId, ...uniqueKeys],\n });\n for (const row of rows) {\n values[row.key as string] = JSON.parse(row.value as string);\n }\n return values;\n } catch (err) {\n if (isConnectionError(err)) return values;\n throw err;\n }\n}\n\nexport async function appStatePut(\n sessionId: string,\n key: string,\n value: Record<string, unknown>,\n options?: StoreWriteOptions,\n): Promise<void> {\n await ensureTable();\n const client = getDbExec();\n const serialized = JSON.stringify(value);\n if (\n !isLocalDatabase() &&\n Buffer.byteLength(serialized, \"utf8\") > MAX_HOSTED_APP_STATE_VALUE_BYTES\n ) {\n throw new Error(\n `application_state value \"${key}\" is too large for hosted SQL storage. Store large files, base64, or blobs in file storage and write only a URL or handle.`,\n );\n }\n await client.execute({\n sql: isPostgres()\n ? `INSERT INTO application_state (session_id, key, value, updated_at) VALUES (?, ?, ?, ?) ON CONFLICT (session_id, key) DO UPDATE SET value=EXCLUDED.value, updated_at=EXCLUDED.updated_at`\n : `INSERT OR REPLACE INTO application_state (session_id, key, value, updated_at) VALUES (?, ?, ?, ?)`,\n args: [sessionId, key, serialized, Date.now()],\n });\n emitAppStateChange(key, options?.requestSource, sessionId);\n}\n\nexport async function appStateDelete(\n sessionId: string,\n key: string,\n options?: StoreWriteOptions,\n): Promise<boolean> {\n await ensureTable();\n const client = getDbExec();\n const result = await client.execute({\n sql: `DELETE FROM application_state WHERE session_id = ? AND key = ?`,\n args: [sessionId, key],\n });\n const deleted = result.rowsAffected > 0;\n if (deleted) emitAppStateDelete(key, options?.requestSource, sessionId);\n return deleted;\n}\n\nexport async function appStateCompareAndSet(\n sessionId: string,\n key: string,\n expectedValue: Record<string, unknown>,\n nextValue: Record<string, unknown> | null,\n options?: StoreWriteOptions,\n): Promise<boolean> {\n await ensureTable();\n const client = getDbExec();\n const expected = JSON.stringify(expectedValue);\n if (nextValue === null) {\n const result = await client.execute({\n sql: `DELETE FROM application_state WHERE session_id = ? AND key = ? AND value = ?`,\n args: [sessionId, key, expected],\n });\n const changed = result.rowsAffected > 0;\n if (changed) emitAppStateDelete(key, options?.requestSource, sessionId);\n return changed;\n }\n\n const next = JSON.stringify(nextValue);\n if (\n !isLocalDatabase() &&\n Buffer.byteLength(next, \"utf8\") > MAX_HOSTED_APP_STATE_VALUE_BYTES\n ) {\n throw new Error(\n `application_state value \"${key}\" is too large for hosted SQL storage. Store large files, base64, or blobs in file storage and write only a URL or handle.`,\n );\n }\n const result = await client.execute({\n sql: `UPDATE application_state SET value = ?, updated_at = ? WHERE session_id = ? AND key = ? AND value = ?`,\n args: [next, Date.now(), sessionId, key, expected],\n });\n const changed = result.rowsAffected > 0;\n if (changed) emitAppStateChange(key, options?.requestSource, sessionId);\n return changed;\n}\n\nexport async function appStateList(\n sessionId: string,\n keyPrefix: string,\n): Promise<Array<{ key: string; value: Record<string, unknown> }>> {\n await ensureTable();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT key, value FROM application_state WHERE session_id = ? AND key LIKE ? ESCAPE '!'`,\n args: [sessionId, escapeLike(keyPrefix) + \"%\"],\n });\n return rows.map((row) => ({\n key: row.key as string,\n value: JSON.parse(row.value as string),\n }));\n}\n\nexport async function appStateDeleteByPrefix(\n sessionId: string,\n keyPrefix: string,\n options?: StoreWriteOptions,\n): Promise<number> {\n await ensureTable();\n const client = getDbExec();\n\n // Get keys first so we can emit events\n const { rows } = await client.execute({\n sql: `SELECT key FROM application_state WHERE session_id = ? AND key LIKE ? ESCAPE '!'`,\n args: [sessionId, escapeLike(keyPrefix) + \"%\"],\n });\n\n if (rows.length === 0) return 0;\n\n const result = await client.execute({\n sql: `DELETE FROM application_state WHERE session_id = ? AND key LIKE ? ESCAPE '!'`,\n args: [sessionId, escapeLike(keyPrefix) + \"%\"],\n });\n\n for (const row of rows) {\n emitAppStateDelete(row.key as string, options?.requestSource, sessionId);\n }\n\n return result.rowsAffected;\n}\n"]}
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/application-state/store.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n getDbExec,\n getDialect,\n isLocalDatabase,\n isConnectionError,\n isPostgres,\n intType,\n type DbExec,\n} from \"../db/client.js\";\nimport { ensureIndexExists, ensureTableExists } from \"../db/ddl-guard.js\";\nimport { widenIntColumnsToBigInt } from \"../db/widen-columns.js\";\nimport type { StoreWriteOptions } from \"../settings/store.js\";\nimport { emitAppStateChange, emitAppStateDelete } from \"./emitter.js\";\n\nlet _initPromise: Promise<void> | undefined;\nconst MAX_HOSTED_APP_STATE_VALUE_BYTES = 1024 * 1024;\n\n// Escapes LIKE wildcards (`%`, `_`) and the escape char itself so a caller's\n// literal prefix is matched verbatim. Used with `ESCAPE '!'` in prefix queries\n// below; without this, a prefix such as `user_settings` would treat `_` as a\n// single-char wildcard and over-match (e.g. delete `userXsettings`).\nfunction escapeLike(s: string): string {\n return s.replace(/[!%_]/g, (match) => `!${match}`);\n}\n\nasync function ensureTable(): Promise<void> {\n if (!_initPromise) {\n _initPromise = (async () => {\n const client = getDbExec();\n const createSql = `\n CREATE TABLE IF NOT EXISTS application_state (\n session_id TEXT NOT NULL,\n key TEXT NOT NULL,\n value TEXT NOT NULL,\n updated_at ${intType()} NOT NULL,\n PRIMARY KEY (session_id, key)\n )\n `;\n\n if (isPostgres()) {\n // Hot path: the `application_state` table and its poll indexes are\n // virtually always already present in production. Issuing `CREATE\n // TABLE`/ `CREATE INDEX` still takes a lock that, in a fresh\n // background-worker process behind a concurrent connection on the\n // shared Neon DB, can block ~indefinitely (ACCESS EXCLUSIVE for CREATE\n // TABLE; a write-blocking SHARE lock for CREATE INDEX). The ensure*\n // wrappers probe `information_schema`/`pg_indexes` first (plain reads,\n // no lock) and run DDL ONLY for what is actually missing, bounded by a\n // transaction-scoped `lock_timeout`. If a swallowed lock-timeout leaves\n // the schema still missing they RE-PROBE and THROW rather than letting\n // init memoize success against absent schema.\n await ensureTableExists(\"application_state\", createSql);\n // Older deployments created `updated_at` as 32-bit `INTEGER`; on Postgres\n // the `Date.now()` written by appStatePut() on every turn overflows int4.\n // Widen it in place (no-op once done / on fresh BIGINT databases).\n await widenIntColumnsToBigInt(\"application_state\", [\"updated_at\"]);\n // Indexes for the two hot poll paths. Probe pg_indexes first (no lock)\n // and skip the SHARE-locking CREATE INDEX when already present.\n await ensureIndexExists(\n \"app_state_updated_at_idx\",\n `CREATE INDEX IF NOT EXISTS app_state_updated_at_idx ON application_state (updated_at)`,\n );\n await ensureIndexExists(\n \"app_state_key_updated_idx\",\n `CREATE INDEX IF NOT EXISTS app_state_key_updated_idx ON application_state (key, updated_at)`,\n );\n return;\n }\n\n // SQLite (local dev): no lock problem — keep the original behaviour.\n await client.execute(createSql);\n // Older deployments created `updated_at` as 32-bit `INTEGER`; on Postgres\n // the `Date.now()` written by appStatePut() on every turn overflows int4.\n // Widen it in place (no-op once done / on fresh BIGINT databases).\n await widenIntColumnsToBigInt(\"application_state\", [\"updated_at\"]);\n // Indexes for the two hot poll paths:\n // - `SELECT … WHERE updated_at > ?` (watermark scan, every poll cycle)\n // - `SELECT … WHERE key = ? … ORDER BY updated_at ASC` (marker lookups)\n // Both are dialect-agnostic (no DESC/partial/PG-only syntax) so they\n // apply identically on SQLite and Postgres. IF NOT EXISTS makes them\n // idempotent across restarts on existing databases.\n for (const ddl of [\n `CREATE INDEX IF NOT EXISTS app_state_updated_at_idx ON application_state (updated_at)`,\n `CREATE INDEX IF NOT EXISTS app_state_key_updated_idx ON application_state (key, updated_at)`,\n ]) {\n try {\n await client.execute(ddl);\n } catch {\n // Index already exists or the dialect rejected a duplicate.\n }\n }\n })().catch((err) => {\n // Retry init on the next call after a failed startup.\n _initPromise = undefined;\n throw err;\n });\n }\n return _initPromise;\n}\n\nexport async function appStateGet(\n sessionId: string,\n key: string,\n): Promise<Record<string, unknown> | null> {\n try {\n await ensureTable();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT value FROM application_state WHERE session_id = ? AND key = ?`,\n args: [sessionId, key],\n });\n if (rows.length === 0) return null;\n return JSON.parse(rows[0].value as string);\n } catch (err) {\n // Transient WS / connection drops (Neon serverless) — caller polls every\n // 2s and will see the value on the next tick. Swallow rather than 500.\n if (isConnectionError(err)) return null;\n throw err;\n }\n}\n\n/**\n * Read several application-state keys for one session in a single SQL query.\n * Missing keys are returned as `null` so callers can preserve the requested\n * shape without issuing one fallback query per key.\n */\nexport async function appStateGetMany(\n sessionId: string,\n keys: readonly string[],\n): Promise<Record<string, Record<string, unknown> | null>> {\n const uniqueKeys = [...new Set(keys)];\n const values: Record<string, Record<string, unknown> | null> = {};\n for (const key of uniqueKeys) values[key] = null;\n if (uniqueKeys.length === 0) return values;\n\n try {\n await ensureTable();\n const client = getDbExec();\n const placeholders = uniqueKeys.map(() => \"?\").join(\", \");\n const { rows } = await client.execute({\n sql: `SELECT key, value FROM application_state WHERE session_id = ? AND key IN (${placeholders})`,\n args: [sessionId, ...uniqueKeys],\n });\n for (const row of rows) {\n values[row.key as string] = JSON.parse(row.value as string);\n }\n return values;\n } catch (err) {\n if (isConnectionError(err)) return values;\n throw err;\n }\n}\n\nexport async function appStatePut(\n sessionId: string,\n key: string,\n value: Record<string, unknown>,\n options?: StoreWriteOptions,\n): Promise<void> {\n await ensureTable();\n const client = getDbExec();\n const serialized = JSON.stringify(value);\n if (\n !isLocalDatabase() &&\n Buffer.byteLength(serialized, \"utf8\") > MAX_HOSTED_APP_STATE_VALUE_BYTES\n ) {\n throw new Error(\n `application_state value \"${key}\" is too large for hosted SQL storage. Store large files, base64, or blobs in file storage and write only a URL or handle.`,\n );\n }\n await client.execute({\n sql: isPostgres()\n ? `INSERT INTO application_state (session_id, key, value, updated_at) VALUES (?, ?, ?, ?) ON CONFLICT (session_id, key) DO UPDATE SET value=EXCLUDED.value, updated_at=EXCLUDED.updated_at`\n : `INSERT OR REPLACE INTO application_state (session_id, key, value, updated_at) VALUES (?, ?, ?, ?)`,\n args: [sessionId, key, serialized, Date.now()],\n });\n emitAppStateChange(key, options?.requestSource, sessionId);\n}\n\nexport async function appStateDelete(\n sessionId: string,\n key: string,\n options?: StoreWriteOptions,\n): Promise<boolean> {\n await ensureTable();\n const client = getDbExec();\n const result = await client.execute({\n sql: `DELETE FROM application_state WHERE session_id = ? AND key = ?`,\n args: [sessionId, key],\n });\n const deleted = result.rowsAffected > 0;\n if (deleted) emitAppStateDelete(key, options?.requestSource, sessionId);\n return deleted;\n}\n\nexport async function appStateCompareAndSet(\n sessionId: string,\n key: string,\n expectedValue: Record<string, unknown> | null,\n nextValue: Record<string, unknown> | null,\n options?: StoreWriteOptions,\n): Promise<boolean> {\n await ensureTable();\n const client = getDbExec();\n const changed = await executeAppStateCompareAndSet(\n client,\n sessionId,\n key,\n expectedValue,\n nextValue,\n );\n if (changed) {\n if (nextValue === null) {\n emitAppStateDelete(key, options?.requestSource, sessionId);\n } else {\n emitAppStateChange(key, options?.requestSource, sessionId);\n }\n }\n return changed;\n}\n\nexport interface AppStateCompareAndSetOperation {\n key: string;\n expectedValue: Record<string, unknown> | null;\n nextValue: Record<string, unknown> | null;\n}\n\nconst APP_STATE_CAS_MISMATCH = Symbol(\"app-state-cas-mismatch\");\n\nasync function executeAppStateCompareAndSet(\n client: DbExec,\n sessionId: string,\n key: string,\n expectedValue: Record<string, unknown> | null,\n nextValue: Record<string, unknown> | null,\n): Promise<boolean> {\n const statement = buildAppStateCompareAndSetStatement(\n sessionId,\n key,\n expectedValue,\n nextValue,\n );\n const result = await client.execute(statement);\n return result.rowsAffected > 0;\n}\n\nfunction buildAppStateCompareAndSetStatement(\n sessionId: string,\n key: string,\n expectedValue: Record<string, unknown> | null,\n nextValue: Record<string, unknown> | null,\n): { sql: string; args: unknown[] } {\n if (expectedValue === null) {\n if (nextValue === null) {\n throw new Error(\n \"Application state CAS cannot replace absence with absence.\",\n );\n }\n const next = serializeAppStateValue(key, nextValue);\n return {\n sql: isPostgres()\n ? `INSERT INTO application_state (session_id, key, value, updated_at) SELECT ?, ?, ?, ? WHERE NOT EXISTS (SELECT 1 FROM application_state WHERE session_id = ? AND key = ?) ON CONFLICT (session_id, key) DO NOTHING`\n : `INSERT OR IGNORE INTO application_state (session_id, key, value, updated_at) SELECT ?, ?, ?, ? WHERE NOT EXISTS (SELECT 1 FROM application_state WHERE session_id = ? AND key = ?)`,\n args: [sessionId, key, next, Date.now(), sessionId, key],\n };\n }\n\n const expected = JSON.stringify(expectedValue);\n if (nextValue === null) {\n return {\n sql: `DELETE FROM application_state WHERE session_id = ? AND key = ? AND value = ?`,\n args: [sessionId, key, expected],\n };\n }\n\n const next = serializeAppStateValue(key, nextValue);\n return {\n sql: `UPDATE application_state SET value = ?, updated_at = ? WHERE session_id = ? AND key = ? AND value = ?`,\n args: [next, Date.now(), sessionId, key, expected],\n };\n}\n\nfunction buildD1CompareAndSetGuard(\n sessionId: string,\n guardKey: string,\n operation: AppStateCompareAndSetOperation,\n): { sql: string; args: unknown[] } {\n const expected = operation.expectedValue;\n const condition =\n expected === null\n ? \"NOT EXISTS (SELECT 1 FROM application_state WHERE session_id = ? AND key = ?)\"\n : \"EXISTS (SELECT 1 FROM application_state WHERE session_id = ? AND key = ? AND value = ?)\";\n return {\n sql: `INSERT INTO application_state (session_id, key, value, updated_at) SELECT ?, ?, '{}', ? WHERE NOT (${condition})`,\n args:\n expected === null\n ? [sessionId, guardKey, Date.now(), sessionId, operation.key]\n : [\n sessionId,\n guardKey,\n Date.now(),\n sessionId,\n operation.key,\n JSON.stringify(expected),\n ],\n };\n}\n\nfunction isD1CompareAndSetMismatch(error: unknown): boolean {\n const message = error instanceof Error ? error.message : String(error);\n return /unique constraint failed:\\s*application_state\\.session_id,\\s*application_state\\.key/i.test(\n message,\n );\n}\n\nfunction serializeAppStateValue(\n key: string,\n value: Record<string, unknown>,\n): string {\n const serialized = JSON.stringify(value);\n if (\n !isLocalDatabase() &&\n Buffer.byteLength(serialized, \"utf8\") > MAX_HOSTED_APP_STATE_VALUE_BYTES\n ) {\n throw new Error(\n `application_state value \"${key}\" is too large for hosted SQL storage. Store large files, base64, or blobs in file storage and write only a URL or handle.`,\n );\n }\n return serialized;\n}\n\nexport async function appStateCompareAndSetMany(\n sessionId: string,\n operations: readonly AppStateCompareAndSetOperation[],\n options?: StoreWriteOptions,\n): Promise<boolean> {\n if (operations.length === 0) return true;\n const keys = new Set(operations.map(({ key }) => key));\n if (keys.size !== operations.length) {\n throw new Error(\"Application state multi-key CAS requires unique keys.\");\n }\n for (const { key, nextValue } of operations) {\n if (nextValue) serializeAppStateValue(key, nextValue);\n }\n const orderedOperations = [...operations].sort((a, b) =>\n a.key.localeCompare(b.key),\n );\n\n await ensureTable();\n const client = getDbExec();\n if (getDialect() === \"d1\") {\n if (!client.atomicBatch) {\n throw new Error(\n \"D1 application-state CAS requires atomic batch support.\",\n );\n }\n const guardKey = `__agent_native_cas_guard__:${Date.now()}:${Math.random().toString(36).slice(2)}`;\n const guardInsert = {\n sql: `INSERT INTO application_state (session_id, key, value, updated_at) VALUES (?, ?, '{}', ?)`,\n args: [sessionId, guardKey, Date.now()],\n };\n const guards = orderedOperations.map((operation) =>\n buildD1CompareAndSetGuard(sessionId, guardKey, operation),\n );\n const mutations = orderedOperations.map((operation) =>\n buildAppStateCompareAndSetStatement(\n sessionId,\n operation.key,\n operation.expectedValue,\n operation.nextValue,\n ),\n );\n let results;\n try {\n results = await client.atomicBatch([\n guardInsert,\n ...guards,\n ...mutations,\n {\n sql: `DELETE FROM application_state WHERE session_id = ? AND key = ?`,\n args: [sessionId, guardKey],\n },\n ]);\n } catch (error) {\n if (isD1CompareAndSetMismatch(error)) return false;\n throw error;\n }\n const mutationResults = results.slice(\n 1 + guards.length,\n 1 + guards.length + mutations.length,\n );\n if (\n mutationResults.length !== mutations.length ||\n mutationResults.some((result) => result.rowsAffected !== 1)\n ) {\n throw new Error(\n \"D1 application-state CAS completed without applying every mutation.\",\n );\n }\n } else {\n if (!client.transaction) {\n throw new Error(\"Application state multi-key CAS requires transactions.\");\n }\n try {\n await client.transaction(async (tx) => {\n for (const operation of orderedOperations) {\n const changed = await executeAppStateCompareAndSet(\n tx,\n sessionId,\n operation.key,\n operation.expectedValue,\n operation.nextValue,\n );\n if (!changed) throw APP_STATE_CAS_MISMATCH;\n }\n });\n } catch (error) {\n if (error === APP_STATE_CAS_MISMATCH) return false;\n throw error;\n }\n }\n\n for (const { key, nextValue } of operations) {\n if (nextValue === null) {\n emitAppStateDelete(key, options?.requestSource, sessionId);\n } else {\n emitAppStateChange(key, options?.requestSource, sessionId);\n }\n }\n return true;\n}\n\nexport async function appStateList(\n sessionId: string,\n keyPrefix: string,\n): Promise<Array<{ key: string; value: Record<string, unknown> }>> {\n await ensureTable();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT key, value FROM application_state WHERE session_id = ? AND key LIKE ? ESCAPE '!'`,\n args: [sessionId, escapeLike(keyPrefix) + \"%\"],\n });\n return rows.map((row) => ({\n key: row.key as string,\n value: JSON.parse(row.value as string),\n }));\n}\n\nexport async function appStateDeleteByPrefix(\n sessionId: string,\n keyPrefix: string,\n options?: StoreWriteOptions,\n): Promise<number> {\n await ensureTable();\n const client = getDbExec();\n\n // Get keys first so we can emit events\n const { rows } = await client.execute({\n sql: `SELECT key FROM application_state WHERE session_id = ? AND key LIKE ? ESCAPE '!'`,\n args: [sessionId, escapeLike(keyPrefix) + \"%\"],\n });\n\n if (rows.length === 0) return 0;\n\n const result = await client.execute({\n sql: `DELETE FROM application_state WHERE session_id = ? AND key LIKE ? ESCAPE '!'`,\n args: [sessionId, escapeLike(keyPrefix) + \"%\"],\n });\n\n for (const row of rows) {\n emitAppStateDelete(row.key as string, options?.requestSource, sessionId);\n }\n\n return result.rowsAffected;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"AgentPanel.d.ts","sourceRoot":"","sources":["../../src/client/AgentPanel.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AgentPanel.d.ts","sourceRoot":"","sources":["../../src/client/AgentPanel.tsx"],"names":[],"mappings":"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"}
@@ -39,6 +39,7 @@ const MultiTabAssistantChatLazy = lazy(() => import("./MultiTabAssistantChat.js"
39
39
  })));
40
40
  import { useQuery, useQueryClient } from "@tanstack/react-query";
41
41
  import { Link, useLocation, useNavigate } from "react-router";
42
+ import { withBuilderUtmTrackingParams } from "../shared/builder-link-tracking.js";
42
43
  import { consumeAgentSidebarUrlOpenOverride, dispatchAgentSidebarStateChange, getInitialAgentSidebarOpen, setAgentSidebarOpenPreference, subscribeAgentSidebarUrlChanges, SIDEBAR_STATE_CHANGE_EVENT, } from "./agent-sidebar-state.js";
43
44
  import { trackEvent } from "./analytics.js";
44
45
  import { agentNativePath, appPath } from "./api-path.js";
@@ -352,13 +353,19 @@ export function resolveAgentPanelChatSurface(explicitSurface, desktopCodeSurface
352
353
  }
353
354
  function CodeAccessUnavailablePanel({ title, description, ctaLabel, ctaHref, secondaryCtaLabel = "Use Builder", secondaryCtaHref, compact = false, }) {
354
355
  const { connectUrl: builderConnectUrl } = useBuilderConnectUrl();
355
- const builderHref = secondaryCtaHref ??
356
- (builderConnectUrl
356
+ const builderHref = secondaryCtaHref
357
+ ? withBuilderUtmTrackingParams(secondaryCtaHref, {
358
+ campaign: "product",
359
+ content: "code_access_unavailable_panel",
360
+ })
361
+ : builderConnectUrl
357
362
  ? withBuilderConnectTrackingParams(builderConnectUrl, {
358
363
  source: "code_access_unavailable_panel",
359
364
  flow: "background_agent",
360
365
  })
361
- : "https://builder.io");
366
+ : withBuilderUtmTrackingParams("https://builder.io", {
367
+ content: "code_access_unavailable_panel",
368
+ });
362
369
  return (_jsxs("div", { className: cn("rounded-lg border border-border bg-muted/35 text-center", compact ? "mx-3 mt-2 px-3 py-2.5" : "max-w-[300px] px-4 py-4"), children: [_jsx("div", { className: cn("mx-auto flex items-center justify-center rounded-full bg-background text-muted-foreground", compact ? "mb-2 h-8 w-8" : "mb-3 h-10 w-10"), children: _jsx(IconTerminal2, { className: compact ? "h-4 w-4" : "h-5 w-5" }) }), _jsx("p", { className: "text-sm font-medium text-foreground", children: title }), _jsx("p", { className: cn("mt-1 text-muted-foreground", compact ? "text-[11px] leading-snug" : "text-xs leading-relaxed"), children: description }), _jsxs("div", { className: "mt-3 flex flex-wrap items-center justify-center gap-2", children: [ctaHref ? (_jsxs("a", { href: ctaHref, target: "_blank", rel: "noreferrer", className: "inline-flex items-center gap-1.5 rounded-md bg-foreground px-3 py-1.5 text-xs font-medium text-background hover:opacity-90", children: [ctaLabel, _jsx(IconExternalLink, { className: "h-3 w-3" })] })) : null, _jsxs("a", { href: builderHref, target: "_blank", rel: "noreferrer", onClick: () => {
363
370
  trackEvent("builder connect clicked", {
364
371
  feature: "builder",