@agent-native/core 0.201.0-nightly-20261005153421 → 0.201.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/README.md +22 -22
  2. package/dist/a2a/server.d.ts +2 -2
  3. package/dist/a2a/server.js +13 -2
  4. package/dist/agent/thread-data-builder.d.ts +4 -0
  5. package/dist/agent/thread-data-builder.js +8 -0
  6. package/dist/agent-sql/analysis.d.ts +31 -0
  7. package/dist/agent-sql/analysis.js +169 -0
  8. package/dist/agent-sql/index.d.ts +4 -0
  9. package/dist/agent-sql/index.js +4 -0
  10. package/dist/agent-sql/lexer.d.ts +37 -0
  11. package/dist/agent-sql/lexer.js +357 -0
  12. package/dist/agent-sql/postgres.d.ts +51 -0
  13. package/dist/agent-sql/postgres.js +197 -0
  14. package/dist/agent-sql/query.d.ts +30 -0
  15. package/dist/agent-sql/query.js +514 -0
  16. package/dist/catalog.json +24 -24
  17. package/dist/client/analytics/index.d.ts +1 -1
  18. package/dist/client/analytics/index.js +1 -1
  19. package/dist/client/analytics.d.ts +8 -0
  20. package/dist/client/analytics.js +17 -2
  21. package/dist/client/session-replay.js +3 -2
  22. package/dist/identity/offboard.js +31 -3
  23. package/dist/identity/rekey.d.ts +12 -1
  24. package/dist/identity/rekey.js +77 -6
  25. package/dist/identity/retired-emails.d.ts +23 -0
  26. package/dist/identity/retired-emails.js +55 -0
  27. package/dist/mcp/actions/create-org-service-token.js +20 -8
  28. package/dist/mcp/actions/service-token-access.d.ts +1 -0
  29. package/dist/mcp/actions/service-token-access.js +41 -24
  30. package/dist/mcp/build-server.d.ts +20 -6
  31. package/dist/mcp/build-server.js +131 -35
  32. package/dist/mcp/connect-route.d.ts +4 -3
  33. package/dist/mcp/connect-route.js +140 -82
  34. package/dist/mcp/connect-store.d.ts +17 -11
  35. package/dist/mcp/connect-store.js +88 -60
  36. package/dist/mcp/credential-issuance.d.ts +23 -0
  37. package/dist/mcp/credential-issuance.js +77 -0
  38. package/dist/mcp/credential-membership.d.ts +26 -0
  39. package/dist/mcp/credential-membership.js +67 -0
  40. package/dist/mcp/oauth-route.js +133 -45
  41. package/dist/mcp/oauth-store.d.ts +15 -5
  42. package/dist/mcp/oauth-store.js +119 -34
  43. package/dist/mcp/oauth-token.d.ts +4 -0
  44. package/dist/mcp/oauth-token.js +5 -0
  45. package/dist/mcp/screen-memory-stdio.d.ts +7 -7
  46. package/dist/mcp/server.js +14 -0
  47. package/dist/onboarding/default-steps.js +1 -1
  48. package/dist/org/handlers.d.ts +1 -1
  49. package/dist/org/index.d.ts +2 -2
  50. package/dist/org/membership.d.ts +3 -1
  51. package/dist/org/membership.js +5 -2
  52. package/dist/provider-api/actions/custom-provider-registration.d.ts +12 -12
  53. package/dist/provider-api/actions/provider-api.d.ts +10 -10
  54. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  55. package/dist/resource-changes/store.d.ts +2 -0
  56. package/dist/resource-changes/store.js +4 -0
  57. package/dist/resources/handlers.d.ts +1 -1
  58. package/dist/scripts/db/exec.js +28 -101
  59. package/dist/scripts/db/patch.js +14 -34
  60. package/dist/scripts/db/postgres-client.d.ts +8 -1
  61. package/dist/scripts/db/postgres-client.js +20 -6
  62. package/dist/scripts/db/query.js +31 -33
  63. package/dist/scripts/db/safety.d.ts +47 -2
  64. package/dist/scripts/db/safety.js +383 -137
  65. package/dist/scripts/db/scoping.d.ts +1 -0
  66. package/dist/scripts/db/scoping.js +3 -2
  67. package/dist/search/index-store.d.ts +21 -0
  68. package/dist/search/index-store.js +47 -0
  69. package/dist/search/indexer.js +35 -32
  70. package/dist/search/registry.d.ts +6 -3
  71. package/dist/search/registry.js +30 -8
  72. package/dist/secrets/routes.d.ts +6 -6
  73. package/dist/server/agent-chat-plugin.js +18 -6
  74. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  75. package/dist/server/agent-engine-default-model-route.d.ts +1 -1
  76. package/dist/server/agent-run-context.js +9 -0
  77. package/dist/server/attribution.d.ts +2 -0
  78. package/dist/server/attribution.js +7 -1
  79. package/dist/server/auth.js +9 -0
  80. package/dist/server/credential-membership-unavailable.d.ts +13 -0
  81. package/dist/server/credential-membership-unavailable.js +22 -0
  82. package/dist/server/index.d.ts +1 -0
  83. package/dist/server/index.js +1 -0
  84. package/dist/server/onboarding-html.js +1 -1
  85. package/dist/server/realtime-token.d.ts +1 -1
  86. package/dist/server/recap-image-route.js +4 -0
  87. package/dist/server/release-schema.js +4 -0
  88. package/dist/shared/docs-url.d.ts +3 -1
  89. package/dist/shared/docs-url.js +6 -3
  90. package/dist/shared/environment-lanes.d.ts +8 -0
  91. package/dist/shared/environment-lanes.js +26 -0
  92. package/dist/templates/chat/.agents/skills/security/SKILL.md +9 -2
  93. package/dist/templates/chat/.agents/skills/storing-data/SKILL.md +12 -7
  94. package/dist/templates/chat/README.md +2 -2
  95. package/dist/templates/default/.agents/skills/security/SKILL.md +9 -2
  96. package/dist/templates/default/.agents/skills/storing-data/SKILL.md +12 -7
  97. package/dist/templates/default/app/routes/home.tsx +5 -1
  98. package/dist/templates/headless/.agents/skills/security/SKILL.md +9 -2
  99. package/dist/templates/headless/.agents/skills/storing-data/SKILL.md +12 -7
  100. package/dist/templates/workspace-core/.agents/skills/security/SKILL.md +9 -2
  101. package/dist/templates/workspace-core/.agents/skills/storing-data/SKILL.md +12 -7
  102. package/dist/tracking/providers.js +13 -1
  103. package/docs/content/authentication.mdx +5 -1
  104. package/docs/content/durable-background-runs.mdx +17 -8
  105. package/docs/content/external-agents.mdx +3 -1
  106. package/docs/content/mcp-protocol.mdx +6 -2
  107. package/docs/content/security.mdx +1 -1
  108. package/package.json +5 -4
  109. package/src/templates/chat/.agents/skills/security/SKILL.md +9 -2
  110. package/src/templates/chat/.agents/skills/storing-data/SKILL.md +12 -7
  111. package/src/templates/chat/README.md +2 -2
  112. package/src/templates/default/.agents/skills/security/SKILL.md +9 -2
  113. package/src/templates/default/.agents/skills/storing-data/SKILL.md +12 -7
  114. package/src/templates/default/app/routes/home.tsx +5 -1
  115. package/src/templates/headless/.agents/skills/security/SKILL.md +9 -2
  116. package/src/templates/headless/.agents/skills/storing-data/SKILL.md +12 -7
  117. package/src/templates/workspace-core/.agents/skills/security/SKILL.md +9 -2
  118. package/src/templates/workspace-core/.agents/skills/storing-data/SKILL.md +12 -7
package/README.md CHANGED
@@ -15,7 +15,7 @@
15
15
 
16
16
  # Agent-Native
17
17
 
18
- Agent-Native is an open-source TypeScript framework for building agents that pair autonomous work with a purpose-built UI. Define each capability once as an [action](https://agent-native.com/docs/actions-overview): the agent uses it as a tool, and the UI calls it from code.
18
+ Agent-Native is an open-source TypeScript framework for building agents that pair autonomous work with a purpose-built UI. Define each capability once as an [action](https://agent-native.com/docs/actions-overview?utm_source=npm&utm_medium=referral&utm_content=core-readme): the agent uses it as a tool, and the UI calls it from code.
19
19
 
20
20
  ## Quick start
21
21
 
@@ -23,7 +23,7 @@ Agent-Native is an open-source TypeScript framework for building agents that pai
23
23
  npx --yes @agent-native/core@latest create my-agent --standalone --template chat
24
24
  ```
25
25
 
26
- Follow the [getting started guide](https://agent-native.com/docs/getting-started) for a full intro to the framework.
26
+ Follow the [getting started guide](https://agent-native.com/docs/getting-started?utm_source=npm&utm_medium=referral&utm_content=core-readme) for a full intro to the framework.
27
27
 
28
28
  ## Why build agents with UIs?
29
29
 
@@ -33,9 +33,9 @@ Knowledge work needs that same kind of environment. A UI shows what an agent can
33
33
 
34
34
  ## How Agent-Native works
35
35
 
36
- - **[Shared actions](https://agent-native.com/docs/actions-overview).** The agent calls each capability as a tool, and the UI calls it from code. Both paths use the same validation, permissions, and implementation.
37
- - **[Shared data](https://agent-native.com/docs/server-database).** Work done by the agent appears in the UI, and work done in the UI is available to the agent.
38
- - **[Shared application state](https://agent-native.com/docs/context-awareness).** The agent receives relevant UI state, such as the current page, selected record, or active view.
36
+ - **[Shared actions](https://agent-native.com/docs/actions-overview?utm_source=npm&utm_medium=referral&utm_content=core-readme).** The agent calls each capability as a tool, and the UI calls it from code. Both paths use the same validation, permissions, and implementation.
37
+ - **[Shared data](https://agent-native.com/docs/server-database?utm_source=npm&utm_medium=referral&utm_content=core-readme).** Work done by the agent appears in the UI, and work done in the UI is available to the agent.
38
+ - **[Shared application state](https://agent-native.com/docs/context-awareness?utm_source=npm&utm_medium=referral&utm_content=core-readme).** The agent receives relevant UI state, such as the current page, selected record, or active view.
39
39
 
40
40
  The agent does not click through the UI. It works through the same action layer as the UI.
41
41
 
@@ -64,12 +64,12 @@ The agent receives `hello` as a tool. React calls the same function with `useAct
64
64
 
65
65
  ## Included
66
66
 
67
- - **[Agent chat](https://agent-native.com/docs/agent-surfaces):** Let people delegate work, ask questions, and review results in the same UI.
68
- - **[Authentication and permissions](https://agent-native.com/docs/authentication):** Control who can access and change shared work.
69
- - **[Skills and memory](https://agent-native.com/docs/agent-resources):** Give agents reusable expertise and persistent context.
70
- - **[Automations](https://agent-native.com/docs/automations):** Run agent work on schedules or events.
71
- - **[Agent teams](https://agent-native.com/docs/agent-teams):** Delegate work to specialist agents in the same workspace or across connected agents.
72
- - **[PostgreSQL backend](https://agent-native.com/docs/server-database):** Use PostgreSQL in production and PGlite for local development on any Nitro-compatible host.
67
+ - **[Agent chat](https://agent-native.com/docs/agent-surfaces?utm_source=npm&utm_medium=referral&utm_content=core-readme):** Let people delegate work, ask questions, and review results in the same UI.
68
+ - **[Authentication and permissions](https://agent-native.com/docs/authentication?utm_source=npm&utm_medium=referral&utm_content=core-readme):** Control who can access and change shared work.
69
+ - **[Skills and memory](https://agent-native.com/docs/agent-resources?utm_source=npm&utm_medium=referral&utm_content=core-readme):** Give agents reusable expertise and persistent context.
70
+ - **[Automations](https://agent-native.com/docs/automations?utm_source=npm&utm_medium=referral&utm_content=core-readme):** Run agent work on schedules or events.
71
+ - **[Agent teams](https://agent-native.com/docs/agent-teams?utm_source=npm&utm_medium=referral&utm_content=core-readme):** Delegate work to specialist agents in the same workspace or across connected agents.
72
+ - **[PostgreSQL backend](https://agent-native.com/docs/server-database?utm_source=npm&utm_medium=referral&utm_content=core-readme):** Use PostgreSQL in production and PGlite for local development on any Nitro-compatible host.
73
73
 
74
74
  ### Example: edit a running app visually
75
75
 
@@ -108,7 +108,7 @@ Start from one of these agents or use it as an example for your own.
108
108
 
109
109
  **Clips**
110
110
 
111
- <a href="https://agent-native.com/apps/clips/">
111
+ <a href="https://agent-native.com/apps/clips/?utm_source=npm&utm_medium=referral&utm_content=core-readme">
112
112
  <picture>
113
113
  <source media="(prefers-color-scheme: dark)" srcset="https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2F4dc9c87b9a224132855e1cb68cd89f9e?format=webp&width=800">
114
114
  <img src="https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2F462fdb643d5d403a8c54540c5c3292f6?format=webp&width=800" alt="Clips app screenshot" width="100%">
@@ -126,7 +126,7 @@ Record and understand meetings, screens, and voice notes.
126
126
 
127
127
  **Design**
128
128
 
129
- <a href="https://agent-native.com/apps/design/">
129
+ <a href="https://agent-native.com/apps/design/?utm_source=npm&utm_medium=referral&utm_content=core-readme">
130
130
  <picture>
131
131
  <source media="(prefers-color-scheme: dark)" srcset="https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2F072f66a3e360464fb48617670ceee46f?format=webp&width=800">
132
132
  <img src="https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2Fc9f693f170294bde8ebc733cff368af9?format=webp&width=800" alt="Design app screenshot" width="100%">
@@ -144,7 +144,7 @@ Generate and refine interactive designs.
144
144
 
145
145
  **Slides**
146
146
 
147
- <a href="https://agent-native.com/apps/slides/">
147
+ <a href="https://agent-native.com/apps/slides/?utm_source=npm&utm_medium=referral&utm_content=core-readme">
148
148
  <picture>
149
149
  <source media="(prefers-color-scheme: dark)" srcset="https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2F710f5b7586cc41deaa0e6f8de658a499?format=webp&width=800">
150
150
  <img src="https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2F6223a64717a04931a6f509696019f48b?format=webp&width=800" alt="Slides app screenshot" width="100%">
@@ -164,7 +164,7 @@ Create and edit on-brand presentations.
164
164
 
165
165
  **Analytics**
166
166
 
167
- <a href="https://agent-native.com/apps/analytics/">
167
+ <a href="https://agent-native.com/apps/analytics/?utm_source=npm&utm_medium=referral&utm_content=core-readme">
168
168
  <picture>
169
169
  <source media="(prefers-color-scheme: dark)" srcset="https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2Fba632b39758d448594f7e5d2403e5d0f?format=webp&width=800">
170
170
  <img src="https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2F976ea93771b64b9e8c1b3eb12e606e07?format=webp&width=800" alt="Analytics app screenshot" width="100%">
@@ -182,7 +182,7 @@ Ask questions of your data and build dashboards.
182
182
 
183
183
  **Calendar**
184
184
 
185
- <a href="https://agent-native.com/apps/calendar/">
185
+ <a href="https://agent-native.com/apps/calendar/?utm_source=npm&utm_medium=referral&utm_content=core-readme">
186
186
  <picture>
187
187
  <source media="(prefers-color-scheme: dark)" srcset="https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2F91d4c18d256b49e6bca24c23ce90a4f2?format=webp&width=800">
188
188
  <img src="https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2F8d9d48bb2f1d498f9601ac28c64edd4c?format=webp&width=800" alt="Calendar app screenshot" width="100%">
@@ -200,7 +200,7 @@ Find time, schedule events, and manage bookings.
200
200
 
201
201
  **Mail**
202
202
 
203
- <a href="https://agent-native.com/apps/mail/">
203
+ <a href="https://agent-native.com/apps/mail/?utm_source=npm&utm_medium=referral&utm_content=core-readme">
204
204
  <picture>
205
205
  <source media="(prefers-color-scheme: dark)" srcset="https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2F216aaef9859144ffa3eb9498fa1132da?format=webp&width=800">
206
206
  <img src="https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2F064aee3ec5cd44879b9c186f63a6d6f4?format=webp&width=800" alt="Mail app screenshot" width="100%">
@@ -220,7 +220,7 @@ Prioritize email, draft replies, and follow up.
220
220
 
221
221
  **Assets**
222
222
 
223
- <a href="https://agent-native.com/apps/assets/">
223
+ <a href="https://agent-native.com/apps/assets/?utm_source=npm&utm_medium=referral&utm_content=core-readme">
224
224
  <picture>
225
225
  <source media="(prefers-color-scheme: dark)" srcset="https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2Fde445dd867744e9bac5d3e5d04c903b2?format=webp&width=800">
226
226
  <img src="https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2Fac5701f0871f4edbb06fa9cdb12b166e?format=webp&width=800" alt="Assets app screenshot" width="100%">
@@ -238,7 +238,7 @@ Create and organize on-brand media.
238
238
 
239
239
  **Content**
240
240
 
241
- <a href="https://agent-native.com/apps/content/">
241
+ <a href="https://agent-native.com/apps/content/?utm_source=npm&utm_medium=referral&utm_content=core-readme">
242
242
  <picture>
243
243
  <source media="(prefers-color-scheme: dark)" srcset="https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2Fa9f30380b03b4fd1a7d2ab371ddfd798?format=webp&width=800">
244
244
  <img src="https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2F979f792c79834470a513a9d9b733dd84?format=webp&width=800" alt="Content app screenshot" width="100%">
@@ -256,7 +256,7 @@ Draft, organize, and publish content.
256
256
 
257
257
  **Plans**
258
258
 
259
- <a href="https://agent-native.com/apps/plan/">
259
+ <a href="https://agent-native.com/apps/plan/?utm_source=npm&utm_medium=referral&utm_content=core-readme">
260
260
  <picture>
261
261
  <source media="(prefers-color-scheme: dark)" srcset="https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2Fe89439e917044fc9ac9663737e35bf1f?format=webp&width=800">
262
262
  <img src="https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2F98427229c8c84c30afee56172503c294?format=webp&width=800" alt="Plans app screenshot" width="100%">
@@ -271,11 +271,11 @@ Create and review visual plans with diagrams, wireframes, and prototypes.
271
271
  </tr>
272
272
  </table>
273
273
 
274
- Explore the [full app gallery](https://agent-native.com/apps), or start with the [framework guide](https://agent-native.com/docs/getting-started).
274
+ Explore the [full app gallery](https://agent-native.com/apps?utm_source=npm&utm_medium=referral&utm_content=core-readme), or start with the [framework guide](https://agent-native.com/docs/getting-started?utm_source=npm&utm_medium=referral&utm_content=core-readme).
275
275
 
276
276
  ## Documentation and community
277
277
 
278
- - Read the [documentation](https://agent-native.com/docs).
278
+ - Read the [documentation](https://agent-native.com/docs?utm_source=npm&utm_medium=referral&utm_content=core-readme).
279
279
  - Join [Discord](https://discord.gg/qm82StQ2NC) to ask questions, share what you're building, and get help.
280
280
 
281
281
  ## Contributing
@@ -21,8 +21,8 @@ export interface A2ATokenPayload {
21
21
  * plus any org-level secret for that domain), then verifies the JWT — checking
22
22
  * `aud`/`iss` when the token carries them and `exp` always. Returns the
23
23
  * caller's email (`sub`) and org domain on success, or `{ email: null,
24
- * orgDomain: null }` on any failure (malformed, bad signature, expired, or no
25
- * secret configured), never throwing.
24
+ * orgDomain: null }` on any failure (malformed, bad signature, expired, no
25
+ * secret configured, or an MCP credential), never throwing.
26
26
  *
27
27
  * Exported so workspaces can accept A2A callers on the HTTP action route with
28
28
  * the same routine — including org-level fallback secrets — instead of
@@ -67,6 +67,15 @@ function audienceForRoute(baseAudience, options) {
67
67
  ? [routeAudience, baseAudience]
68
68
  : routeAudience;
69
69
  }
70
+ /**
71
+ * MCP connect tokens and MCP OAuth access tokens can be signed with the A2A
72
+ * secret, but they are long-lived bearers whose revocation and membership
73
+ * checks live in the MCP endpoint's `verifyAuth`. A2A callers sign a
74
+ * short-lived token per call, so an MCP credential is never an A2A token.
75
+ */
76
+ function isMcpCredential(payload) {
77
+ return (payload.scope === "mcp-connect" || payload.typ === "agent-native-mcp-oauth");
78
+ }
70
79
  function tokenHasAudienceClaim(token) {
71
80
  return typeof jose.decodeJwt(token).aud !== "undefined";
72
81
  }
@@ -81,8 +90,8 @@ function isDirectReadSkill(skill) {
81
90
  * plus any org-level secret for that domain), then verifies the JWT — checking
82
91
  * `aud`/`iss` when the token carries them and `exp` always. Returns the
83
92
  * caller's email (`sub`) and org domain on success, or `{ email: null,
84
- * orgDomain: null }` on any failure (malformed, bad signature, expired, or no
85
- * secret configured), never throwing.
93
+ * orgDomain: null }` on any failure (malformed, bad signature, expired, no
94
+ * secret configured, or an MCP credential), never throwing.
86
95
  *
87
96
  * Exported so workspaces can accept A2A callers on the HTTP action route with
88
97
  * the same routine — including org-level fallback secrets — instead of
@@ -166,6 +175,8 @@ export async function verifyA2AToken(token, event, audienceOptions) {
166
175
  for (const secret of candidateSecrets) {
167
176
  try {
168
177
  const { payload } = await jose.jwtVerify(token, new TextEncoder().encode(secret), verifyOptions);
178
+ if (isMcpCredential(payload))
179
+ return { email: null, orgDomain: null };
169
180
  const orgId = typeof payload.org_id === "string" && payload.org_id.trim()
170
181
  ? payload.org_id.trim()
171
182
  : undefined;
@@ -100,9 +100,13 @@ export interface MergeThreadDataOptions {
100
100
  export declare function hasClaimedQueuedMessage(repo: any, messageId: string): boolean;
101
101
  export declare function claimQueuedMessage(repo: any, messageId: string): any;
102
102
  export declare function applySubmittedUserMessage(repo: any, userMessage: UserMessage, queuedMessage?: {
103
+ kind?: "queued-message";
103
104
  id: string;
104
105
  claimId?: string;
105
106
  now?: number;
107
+ } | {
108
+ kind: "background-operation";
109
+ id: string;
106
110
  }): {
107
111
  status: "submitted" | "already_submitted";
108
112
  repo: any;
@@ -1140,6 +1140,14 @@ export function applySubmittedUserMessage(repo, userMessage, queuedMessage) {
1140
1140
  typeof message === "object" &&
1141
1141
  message.id === queuedMessage.id)
1142
1142
  : undefined;
1143
+ if (queuedMessage.kind === "background-operation") {
1144
+ if (queued)
1145
+ return { status: "claim_expired" };
1146
+ return {
1147
+ status: "submitted",
1148
+ repo: upsertUserMessage(claimQueuedMessage(repo, queuedMessage.id), userMessage),
1149
+ };
1150
+ }
1143
1151
  const claim = queued?.promotionClaim;
1144
1152
  if (!queued ||
1145
1153
  typeof queuedMessage.claimId !== "string" ||
@@ -0,0 +1,31 @@
1
+ import type { AgentSqlToken } from "./lexer.js";
2
+ /**
3
+ * Splits tokens into statements on `;`. A trailing `;` does not start a new
4
+ * statement, so `SELECT 1;` is one statement.
5
+ */
6
+ export declare function splitAgentSqlStatements(tokens: AgentSqlToken[]): AgentSqlToken[][];
7
+ /** The first keyword of a statement, ignoring leading parentheses. */
8
+ export declare function leadingAgentSqlKeyword(tokens: AgentSqlToken[]): string | null;
9
+ export interface AgentSqlQualifiedReference {
10
+ /** Every name before the last dot, as the database resolves them. */
11
+ qualifiers: string[];
12
+ name: string;
13
+ /** Index of the first token of the reference. */
14
+ index: number;
15
+ }
16
+ /**
17
+ * Every dotted name chain, such as `a.b` or `a.b.c`. The lexer has already
18
+ * removed comments and whitespace, so spacing or comments around the dot do
19
+ * not hide a chain. Column references (`alias.column`) are included; callers
20
+ * decide which qualifiers matter.
21
+ */
22
+ export declare function agentSqlQualifiedReferences(tokens: AgentSqlToken[]): AgentSqlQualifiedReference[];
23
+ /** Names immediately followed by `(`, i.e. function calls and type modifiers. */
24
+ export declare function agentSqlCalledNames(tokens: AgentSqlToken[]): string[];
25
+ /**
26
+ * Type-conversion candidates in Postgres expressions. Calls are included
27
+ * because `name(value)` can resolve as a cast instead of a function.
28
+ */
29
+ export declare function agentSqlTypeNames(tokens: AgentSqlToken[]): Set<string>;
30
+ /** Every unquoted and quoted identifier value in the statement. */
31
+ export declare function agentSqlIdentifierNames(tokens: AgentSqlToken[]): Set<string>;
@@ -0,0 +1,169 @@
1
+ function isName(token) {
2
+ return token?.kind === "word" || token?.kind === "quoted-identifier";
3
+ }
4
+ function isPunctuation(token, text) {
5
+ return token?.kind === "punctuation" && token.text === text;
6
+ }
7
+ /**
8
+ * Splits tokens into statements on `;`. A trailing `;` does not start a new
9
+ * statement, so `SELECT 1;` is one statement.
10
+ */
11
+ export function splitAgentSqlStatements(tokens) {
12
+ const statements = [];
13
+ let current = [];
14
+ for (const token of tokens) {
15
+ if (isPunctuation(token, ";")) {
16
+ if (current.length > 0)
17
+ statements.push(current);
18
+ current = [];
19
+ continue;
20
+ }
21
+ current.push(token);
22
+ }
23
+ if (current.length > 0)
24
+ statements.push(current);
25
+ return statements;
26
+ }
27
+ /** The first keyword of a statement, ignoring leading parentheses. */
28
+ export function leadingAgentSqlKeyword(tokens) {
29
+ for (const token of tokens) {
30
+ if (isPunctuation(token, "("))
31
+ continue;
32
+ return token.kind === "word" ? token.value : null;
33
+ }
34
+ return null;
35
+ }
36
+ /**
37
+ * Every dotted name chain, such as `a.b` or `a.b.c`. The lexer has already
38
+ * removed comments and whitespace, so spacing or comments around the dot do
39
+ * not hide a chain. Column references (`alias.column`) are included; callers
40
+ * decide which qualifiers matter.
41
+ */
42
+ export function agentSqlQualifiedReferences(tokens) {
43
+ const references = [];
44
+ for (let index = 0; index < tokens.length; index++) {
45
+ if (!isName(tokens[index]))
46
+ continue;
47
+ // Start only at the head of a chain.
48
+ if (index > 0 && isPunctuation(tokens[index - 1], "."))
49
+ continue;
50
+ const parts = [tokens[index].value];
51
+ let cursor = index;
52
+ while (isPunctuation(tokens[cursor + 1], ".") &&
53
+ (isName(tokens[cursor + 2]) ||
54
+ (tokens[cursor + 2]?.kind === "operator" &&
55
+ tokens[cursor + 2].text === "*"))) {
56
+ parts.push(tokens[cursor + 2].value);
57
+ cursor += 2;
58
+ }
59
+ if (parts.length > 1) {
60
+ references.push({
61
+ qualifiers: parts.slice(0, -1),
62
+ name: parts[parts.length - 1],
63
+ index,
64
+ });
65
+ }
66
+ }
67
+ return references;
68
+ }
69
+ /** Names immediately followed by `(`, i.e. function calls and type modifiers. */
70
+ export function agentSqlCalledNames(tokens) {
71
+ const names = [];
72
+ for (let index = 0; index < tokens.length - 1; index++) {
73
+ if (isName(tokens[index]) && isPunctuation(tokens[index + 1], "(")) {
74
+ names.push(tokens[index].value);
75
+ }
76
+ }
77
+ return names;
78
+ }
79
+ /**
80
+ * Type-conversion candidates in Postgres expressions. Calls are included
81
+ * because `name(value)` can resolve as a cast instead of a function.
82
+ */
83
+ export function agentSqlTypeNames(tokens) {
84
+ const names = new Set();
85
+ const declarationNames = new Set();
86
+ const closingParentheses = new Map();
87
+ const openingParentheses = [];
88
+ const parentheses = [];
89
+ function nameEnd(index) {
90
+ if (!isName(tokens[index]))
91
+ return null;
92
+ while (isPunctuation(tokens[index + 1], ".") && isName(tokens[index + 2])) {
93
+ index += 2;
94
+ }
95
+ return index;
96
+ }
97
+ function addType(index) {
98
+ const end = nameEnd(index);
99
+ if (end !== null)
100
+ names.add(tokens[end].value);
101
+ }
102
+ // INSERT target column lists are declarations, even though their target
103
+ // name followed by `(` otherwise looks like a type-conversion call.
104
+ for (let index = 0; index < tokens.length; index++) {
105
+ if (isPunctuation(tokens[index], "("))
106
+ openingParentheses.push(index);
107
+ else if (isPunctuation(tokens[index], ")")) {
108
+ const open = openingParentheses.pop();
109
+ if (open !== undefined)
110
+ closingParentheses.set(open, index);
111
+ }
112
+ if (tokens[index].kind !== "word" || tokens[index].value !== "into")
113
+ continue;
114
+ const end = nameEnd(index + 1);
115
+ if (end === null)
116
+ continue;
117
+ declarationNames.add(end);
118
+ }
119
+ for (let index = 0; index < tokens.length; index++) {
120
+ const token = tokens[index];
121
+ if (isPunctuation(token, "::"))
122
+ addType(index + 1);
123
+ if (token.kind === "word" &&
124
+ token.value === "as" &&
125
+ parentheses.at(-1)?.cast) {
126
+ addType(index + 1);
127
+ }
128
+ if (isPunctuation(token, "(")) {
129
+ const previous = tokens[index - 1];
130
+ parentheses.push({
131
+ cast: previous?.kind === "word" && previous.value === "cast",
132
+ });
133
+ }
134
+ else if (isPunctuation(token, ")")) {
135
+ parentheses.pop();
136
+ }
137
+ if (!isName(token))
138
+ continue;
139
+ if (tokens[index + 1]?.kind === "string")
140
+ names.add(token.value);
141
+ if (!isPunctuation(tokens[index + 1], "("))
142
+ continue;
143
+ if (declarationNames.has(index))
144
+ continue;
145
+ const previous = tokens[index - 1];
146
+ if (previous?.kind === "word" && previous.value === "as")
147
+ continue;
148
+ const close = closingParentheses.get(index + 1);
149
+ if (close !== undefined &&
150
+ tokens[close + 1]?.kind === "word" &&
151
+ tokens[close + 1].value === "as" &&
152
+ (isPunctuation(tokens[close + 2], "(") ||
153
+ (tokens[close + 2]?.kind === "word" &&
154
+ ["materialized", "not"].includes(tokens[close + 2].value)))) {
155
+ continue;
156
+ }
157
+ names.add(token.value);
158
+ }
159
+ return names;
160
+ }
161
+ /** Every unquoted and quoted identifier value in the statement. */
162
+ export function agentSqlIdentifierNames(tokens) {
163
+ const names = new Set();
164
+ for (const token of tokens) {
165
+ if (isName(token))
166
+ names.add(token.value);
167
+ }
168
+ return names;
169
+ }
@@ -0,0 +1,4 @@
1
+ export { AgentSqlSyntaxError, lexAgentSql, type AgentSqlDialect, type AgentSqlSyntaxErrorCode, type AgentSqlToken, type AgentSqlTokenKind, } from "./lexer.js";
2
+ export { agentSqlCalledNames, agentSqlIdentifierNames, agentSqlQualifiedReferences, agentSqlTypeNames, leadingAgentSqlKeyword, splitAgentSqlStatements, type AgentSqlQualifiedReference, } from "./analysis.js";
3
+ export { AgentSqlPolicyError, assertAgentPostgresExpressionTokenPolicy, assertAgentPostgresTokenPolicy, readAgentPostgresStatement, verifyAgentPostgresExpressions, verifyAgentPostgresResolution, type AgentPostgresStatement, type AgentSqlPolicyErrorCode, type AgentSqlQueryRunner, } from "./postgres.js";
4
+ export { readAgentSqlQuery, rewriteAgentSqlQuerySources, type AgentSqlQuery, type AgentSqlQueryCte, type AgentSqlQuerySource, } from "./query.js";
@@ -0,0 +1,4 @@
1
+ export { AgentSqlSyntaxError, lexAgentSql, } from "./lexer.js";
2
+ export { agentSqlCalledNames, agentSqlIdentifierNames, agentSqlQualifiedReferences, agentSqlTypeNames, leadingAgentSqlKeyword, splitAgentSqlStatements, } from "./analysis.js";
3
+ export { AgentSqlPolicyError, assertAgentPostgresExpressionTokenPolicy, assertAgentPostgresTokenPolicy, readAgentPostgresStatement, verifyAgentPostgresExpressions, verifyAgentPostgresResolution, } from "./postgres.js";
4
+ export { readAgentSqlQuery, rewriteAgentSqlQuerySources, } from "./query.js";
@@ -0,0 +1,37 @@
1
+ export type AgentSqlDialect = "postgres" | "bigquery";
2
+ export type AgentSqlTokenKind =
3
+ /** Unquoted keyword or identifier. `value` is case-folded. */
4
+ "word"
5
+ /** `"name"` on Postgres, `` `name` `` on BigQuery. `value` is the exact name. */
6
+ | "quoted-identifier" | "string" | "number"
7
+ /** `?`, `$1`, or BigQuery `@name` / `@@name`. */
8
+ | "parameter" | "operator" | "punctuation";
9
+ export interface AgentSqlToken {
10
+ kind: AgentSqlTokenKind;
11
+ /** Source text of the token. */
12
+ text: string;
13
+ /** Identifier name as the database resolves it; source text otherwise. */
14
+ value: string;
15
+ start: number;
16
+ end: number;
17
+ }
18
+ export type AgentSqlSyntaxErrorCode = "unterminated" | "unsupported_syntax" | "unexpected_character";
19
+ /**
20
+ * The lexer could not read the SQL the way the database would. Callers must
21
+ * refuse to run the statement: a guard that skipped what it could not read
22
+ * would be checking different text from what executes.
23
+ */
24
+ export declare class AgentSqlSyntaxError extends Error {
25
+ readonly code: AgentSqlSyntaxErrorCode;
26
+ readonly position: number;
27
+ constructor(code: AgentSqlSyntaxErrorCode, message: string, position: number);
28
+ }
29
+ /**
30
+ * Splits agent-authored SQL into the tokens the target database will see.
31
+ * Comments and whitespace are dropped; everything else is kept with its
32
+ * source offsets. Throws {@link AgentSqlSyntaxError} for anything the lexer
33
+ * cannot read the same way the database does.
34
+ */
35
+ export declare function lexAgentSql(sql: string, options: {
36
+ dialect: AgentSqlDialect;
37
+ }): AgentSqlToken[];