@cursor/july 0.1.25 → 0.1.27

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 (288) hide show
  1. package/dist/ab.d.ts +6 -0
  2. package/dist/ab.d.ts.map +1 -1
  3. package/dist/ab.js +1 -0
  4. package/dist/artifacts.d.ts +34 -0
  5. package/dist/artifacts.d.ts.map +1 -0
  6. package/dist/artifacts.js +57 -0
  7. package/dist/bin/agent-serve.js +31 -9
  8. package/dist/channels/github/github-channel.d.ts +1 -1
  9. package/dist/channels/github/github-channel.d.ts.map +1 -1
  10. package/dist/channels/github/github-channel.js +14 -1
  11. package/dist/channels/github/types.d.ts +6 -1
  12. package/dist/channels/github/types.d.ts.map +1 -1
  13. package/dist/channels/slack/api.d.ts +2 -1
  14. package/dist/channels/slack/api.d.ts.map +1 -1
  15. package/dist/channels/slack/api.js +1 -0
  16. package/dist/channels/slack/cursor-account.d.ts +2 -1
  17. package/dist/channels/slack/cursor-account.d.ts.map +1 -1
  18. package/dist/channels/slack/cursor-account.js +1 -1
  19. package/dist/channels/slack/dispatch.d.ts +4 -1
  20. package/dist/channels/slack/dispatch.d.ts.map +1 -1
  21. package/dist/channels/slack/dispatch.js +3 -3
  22. package/dist/channels/slack/interactive.d.ts +2 -1
  23. package/dist/channels/slack/interactive.d.ts.map +1 -1
  24. package/dist/channels/slack/interactive.js +1 -0
  25. package/dist/channels/slack/slack-channel.d.ts.map +1 -1
  26. package/dist/channels/slack/slack-channel.js +4 -3
  27. package/dist/channels/slack/types.d.ts +6 -1
  28. package/dist/channels/slack/types.d.ts.map +1 -1
  29. package/dist/docs/404.html +1 -1
  30. package/dist/docs/ab.html +2 -2
  31. package/dist/docs/assets/{app.DYcC9FY-.js → app.BICLoJYF.js} +1 -1
  32. package/dist/docs/assets/chunks/@localSearchIndexroot.CQJytDwU.js +1 -0
  33. package/dist/docs/assets/chunks/{VPLocalSearchBox.o4N_knTV.js → VPLocalSearchBox.wN4Ko9dT.js} +1 -1
  34. package/dist/docs/assets/chunks/{theme.DQ-njyo0.js → theme.dnnTE-Co.js} +2 -2
  35. package/dist/docs/building-with-agents.html +2 -2
  36. package/dist/docs/concepts.html +2 -2
  37. package/dist/docs/deployment.html +2 -2
  38. package/dist/docs/evals.html +2 -2
  39. package/dist/docs/example-agents/approval-buddy.html +2 -2
  40. package/dist/docs/example-agents/benny.html +2 -2
  41. package/dist/docs/example-agents/bugbot.html +2 -2
  42. package/dist/docs/example-agents/codebase-wiki.html +2 -2
  43. package/dist/docs/example-agents/codeowners-review.html +2 -2
  44. package/dist/docs/example-agents/concierge.html +2 -2
  45. package/dist/docs/example-agents/fsd.html +2 -2
  46. package/dist/docs/example-agents/index.html +2 -2
  47. package/dist/docs/example-agents/knowledge-base.html +2 -2
  48. package/dist/docs/example-agents/oncall.html +2 -2
  49. package/dist/docs/example-agents/security-reviewer.html +2 -2
  50. package/dist/docs/example-agents/slack-agent.html +2 -2
  51. package/dist/docs/example-agents/weather-agent.html +2 -2
  52. package/dist/docs/guides/agent-to-agent.html +2 -2
  53. package/dist/docs/guides/cloud-runtime.html +2 -2
  54. package/dist/docs/guides/github.html +2 -2
  55. package/dist/docs/guides/human-in-the-loop.html +2 -2
  56. package/dist/docs/guides/mcp-oauth.html +2 -2
  57. package/dist/docs/guides/slack.html +2 -2
  58. package/dist/docs/guides/webhooks.html +2 -2
  59. package/dist/docs/hillclimbing.html +2 -2
  60. package/dist/docs/index.html +2 -2
  61. package/dist/docs/quickstart.html +2 -2
  62. package/dist/docs/reference/agent-config.html +2 -2
  63. package/dist/docs/reference/channels.html +2 -2
  64. package/dist/docs/reference/cli.html +2 -2
  65. package/dist/docs/reference/connections.html +2 -2
  66. package/dist/docs/reference/hooks.html +2 -2
  67. package/dist/docs/reference/http-api.html +2 -2
  68. package/dist/docs/reference/instructions.html +2 -2
  69. package/dist/docs/reference/playground.html +2 -2
  70. package/dist/docs/reference/project-layout.html +2 -2
  71. package/dist/docs/reference/prompt.html +2 -2
  72. package/dist/docs/reference/schedules.html +2 -2
  73. package/dist/docs/reference/sessions.html +2 -2
  74. package/dist/docs/reference/skills.html +2 -2
  75. package/dist/docs/reference/subagents.html +2 -2
  76. package/dist/docs/reference/tools.html +2 -2
  77. package/dist/docs/scaffolding-agents.html +2 -2
  78. package/dist/docs/storage.html +2 -2
  79. package/dist/docs/troubleshooting.html +2 -2
  80. package/dist/evals/assertions.d.ts +10 -1
  81. package/dist/evals/assertions.d.ts.map +1 -1
  82. package/dist/evals/assertions.js +12 -0
  83. package/dist/evals.d.ts +1 -1
  84. package/dist/evals.d.ts.map +1 -1
  85. package/dist/index.d.ts +1 -0
  86. package/dist/index.d.ts.map +1 -1
  87. package/dist/index.js +1 -0
  88. package/dist/internal/ab-fold.d.ts.map +1 -1
  89. package/dist/internal/ab-fold.js +4 -0
  90. package/dist/internal/ab-snapshot.d.ts.map +1 -1
  91. package/dist/internal/ab-snapshot.js +1 -0
  92. package/dist/internal/artifacts-store.d.ts +45 -0
  93. package/dist/internal/artifacts-store.d.ts.map +1 -0
  94. package/dist/internal/artifacts-store.js +250 -0
  95. package/dist/internal/builtin-tools/artifacts.d.ts +10 -0
  96. package/dist/internal/builtin-tools/artifacts.d.ts.map +1 -0
  97. package/dist/internal/builtin-tools/artifacts.js +73 -0
  98. package/dist/internal/builtin-tools/index.d.ts +8 -1
  99. package/dist/internal/builtin-tools/index.d.ts.map +1 -1
  100. package/dist/internal/builtin-tools/index.js +15 -0
  101. package/dist/internal/cli-ax.d.ts +11 -0
  102. package/dist/internal/cli-ax.d.ts.map +1 -1
  103. package/dist/internal/cli-ax.js +80 -0
  104. package/dist/internal/cli-slack.d.ts.map +1 -1
  105. package/dist/internal/cli-slack.js +14 -6
  106. package/dist/internal/discovery.d.ts.map +1 -1
  107. package/dist/internal/discovery.js +83 -2
  108. package/dist/internal/distribution.d.ts.map +1 -1
  109. package/dist/internal/distribution.js +1 -0
  110. package/dist/internal/model-pricing.d.ts +49 -0
  111. package/dist/internal/model-pricing.d.ts.map +1 -0
  112. package/dist/internal/model-pricing.js +377 -0
  113. package/dist/internal/reminder-runner.d.ts.map +1 -1
  114. package/dist/internal/reminder-runner.js +1 -0
  115. package/dist/internal/schedule-runner.d.ts.map +1 -1
  116. package/dist/internal/schedule-runner.js +1 -0
  117. package/dist/internal/sdk-runner.d.ts.map +1 -1
  118. package/dist/internal/sdk-runner.js +9 -1
  119. package/dist/internal/server.d.ts.map +1 -1
  120. package/dist/internal/server.js +39 -0
  121. package/dist/internal/session-cost.d.ts +49 -0
  122. package/dist/internal/session-cost.d.ts.map +1 -0
  123. package/dist/internal/session-cost.js +175 -0
  124. package/dist/internal/session-engine.d.ts +35 -1
  125. package/dist/internal/session-engine.d.ts.map +1 -1
  126. package/dist/internal/session-engine.js +128 -7
  127. package/dist/internal/storage-coordinator.d.ts +15 -0
  128. package/dist/internal/storage-coordinator.d.ts.map +1 -1
  129. package/dist/internal/storage-coordinator.js +52 -0
  130. package/dist/internal/trajectory.d.ts +9 -1
  131. package/dist/internal/trajectory.d.ts.map +1 -1
  132. package/dist/internal/trajectory.js +32 -5
  133. package/dist/playground/assets/index-BDCeW4uc.js +86 -0
  134. package/dist/playground/assets/index-Bul1WfrB.css +1 -0
  135. package/dist/playground/index.html +2 -2
  136. package/dist/storage.d.ts +4 -0
  137. package/dist/storage.d.ts.map +1 -1
  138. package/dist/storage.js +4 -0
  139. package/dist/types.d.ts +164 -1
  140. package/dist/types.d.ts.map +1 -1
  141. package/package.json +26 -26
  142. package/src/ab.ts +7 -0
  143. package/src/bin/agent-serve.ts +30 -2
  144. package/src/channels/github/github-channel.ts +19 -2
  145. package/src/channels/github/types.ts +6 -0
  146. package/src/channels/slack/api.ts +3 -1
  147. package/src/channels/slack/cursor-account.ts +3 -1
  148. package/src/channels/slack/dispatch.ts +12 -1
  149. package/src/channels/slack/interactive.ts +3 -0
  150. package/src/channels/slack/slack-channel.ts +6 -0
  151. package/src/channels/slack/types.ts +6 -0
  152. package/src/internal/ab-fold.ts +4 -0
  153. package/src/internal/ab-snapshot.ts +1 -0
  154. package/src/internal/cli-ax.ts +95 -0
  155. package/src/internal/model-pricing.ts +426 -0
  156. package/src/internal/reminder-runner.ts +1 -0
  157. package/src/internal/schedule-runner.ts +1 -0
  158. package/src/internal/sdk-runner.ts +10 -2
  159. package/src/internal/server.ts +2 -0
  160. package/src/internal/session-cost.ts +231 -0
  161. package/src/internal/session-engine.ts +32 -1
  162. package/src/internal/trajectory.ts +45 -3
  163. package/src/types.ts +42 -2
  164. package/dist/channels/github/instrument.d.ts +0 -20
  165. package/dist/channels/github/instrument.d.ts.map +0 -1
  166. package/dist/docs/assets/chunks/@localSearchIndexroot.BQTzJjR_.js +0 -1
  167. package/dist/internal/json-dir-store.d.ts +0 -32
  168. package/dist/internal/json-dir-store.d.ts.map +0 -1
  169. package/dist/internal/json-dir-store.js +0 -100
  170. package/dist/playground/assets/index-CjOQ4hN9.css +0 -1
  171. package/dist/playground/assets/index-DqXdAFGa.js +0 -85
  172. package/src/bin/agent-serve.version.test.ts +0 -64
  173. package/src/channels/github/api.test.ts +0 -64
  174. package/src/channels/github/auth.test.ts +0 -105
  175. package/src/channels/github/cursor-account.test.ts +0 -204
  176. package/src/channels/github/forward.test.ts +0 -457
  177. package/src/channels/github/github.test.ts +0 -943
  178. package/src/channels/github/replay.test.ts +0 -179
  179. package/src/channels/slack/api.post-message.test.ts +0 -148
  180. package/src/channels/slack/approvals.test.ts +0 -328
  181. package/src/channels/slack/block-actions.test.ts +0 -452
  182. package/src/channels/slack/bot-mentions.test.ts +0 -267
  183. package/src/channels/slack/channel-watch.test.ts +0 -363
  184. package/src/channels/slack/cursor-account.test.ts +0 -253
  185. package/src/channels/slack/defaults.final-post.test.ts +0 -182
  186. package/src/channels/slack/dispatch.test.ts +0 -795
  187. package/src/channels/slack/eval-directive.test.ts +0 -273
  188. package/src/channels/slack/message-body.test.ts +0 -54
  189. package/src/channels/slack/nudge-store.test.ts +0 -143
  190. package/src/channels/slack/slack.test.ts +0 -391
  191. package/src/channels/slack/stop.test.ts +0 -23
  192. package/src/channels/slack/thread-context.test.ts +0 -202
  193. package/src/evals/assertions.test.ts +0 -617
  194. package/src/evals/expect.test.ts +0 -144
  195. package/src/evals/judge.test.ts +0 -181
  196. package/src/evals/loaders.test.ts +0 -132
  197. package/src/evals/matchers.test.ts +0 -95
  198. package/src/evals/reporters.test.ts +0 -303
  199. package/src/evals/run-facts.test.ts +0 -259
  200. package/src/internal/ab-snapshot.test.ts +0 -325
  201. package/src/internal/approval-gate.test.ts +0 -49
  202. package/src/internal/approvals.integration.test.ts +0 -383
  203. package/src/internal/artifacts-store.test.ts +0 -283
  204. package/src/internal/authored-loaders.test.ts +0 -31
  205. package/src/internal/builtin-tools/artifacts.test.ts +0 -247
  206. package/src/internal/builtin-tools/reminders.test.ts +0 -201
  207. package/src/internal/channel-route-schema.test.ts +0 -294
  208. package/src/internal/chat-attach.test.ts +0 -262
  209. package/src/internal/cli-deploy.test.ts +0 -1991
  210. package/src/internal/cli-docs.test.ts +0 -161
  211. package/src/internal/cli-mcp.test.ts +0 -789
  212. package/src/internal/cli-skills.test.ts +0 -133
  213. package/src/internal/cli-slack.test.ts +0 -1654
  214. package/src/internal/cloud-merge.test.ts +0 -74
  215. package/src/internal/cron.test.ts +0 -22
  216. package/src/internal/cursor/account-mcp.test.ts +0 -807
  217. package/src/internal/cursor/backend-client.test.ts +0 -591
  218. package/src/internal/cursor/credentials.test.ts +0 -351
  219. package/src/internal/cursor/github-credentials.test.ts +0 -136
  220. package/src/internal/cursor-account-mcp-auth.test.ts +0 -310
  221. package/src/internal/cursor-account.integration.test.ts +0 -441
  222. package/src/internal/cursor-event-relay.test.ts +0 -746
  223. package/src/internal/cursor-github-credentials.integration.test.ts +0 -271
  224. package/src/internal/cursor-slack-relay.test.ts +0 -525
  225. package/src/internal/deploy-source.test.ts +0 -111
  226. package/src/internal/discovery.artifact-tool.test.ts +0 -136
  227. package/src/internal/discovery.artifacts.test.ts +0 -119
  228. package/src/internal/discovery.builtin-tools.test.ts +0 -94
  229. package/src/internal/discovery.concurrency.test.ts +0 -60
  230. package/src/internal/discovery.cursor-account.test.ts +0 -133
  231. package/src/internal/discovery.cwd.test.ts +0 -83
  232. package/src/internal/discovery.hosting.test.ts +0 -80
  233. package/src/internal/discovery.identity.test.ts +0 -44
  234. package/src/internal/docs-site.test.ts +0 -66
  235. package/src/internal/duration.test.ts +0 -29
  236. package/src/internal/eval-judge-model.test.ts +0 -187
  237. package/src/internal/eval-run-store.cancel.test.ts +0 -142
  238. package/src/internal/eval-run-store.storage.test.ts +0 -211
  239. package/src/internal/eval-runner.http.test.ts +0 -403
  240. package/src/internal/eval-runner.run.test.ts +0 -928
  241. package/src/internal/evals-client.test.ts +0 -307
  242. package/src/internal/event-mapper.test.ts +0 -243
  243. package/src/internal/github-fanout.test.ts +0 -213
  244. package/src/internal/handleAgentServeTrigger.test.ts +0 -185
  245. package/src/internal/host-kv.test.ts +0 -82
  246. package/src/internal/host-platforms.test.ts +0 -126
  247. package/src/internal/http-channel.test.ts +0 -402
  248. package/src/internal/init-project.test.ts +0 -270
  249. package/src/internal/install-cursor-skills.test.ts +0 -262
  250. package/src/internal/local-env.test.ts +0 -120
  251. package/src/internal/log-ring.test.ts +0 -31
  252. package/src/internal/logs-client.test.ts +0 -350
  253. package/src/internal/mcp-endpoint.test.ts +0 -436
  254. package/src/internal/mcp-host.test.ts +0 -298
  255. package/src/internal/mcp-oauth.test.ts +0 -148
  256. package/src/internal/net.test.ts +0 -17
  257. package/src/internal/peer-connections.test.ts +0 -128
  258. package/src/internal/peer-mcp.integration.test.ts +0 -289
  259. package/src/internal/playground/toolchain.test.ts +0 -53
  260. package/src/internal/playground-cli.test.ts +0 -187
  261. package/src/internal/playground-proxy.test.ts +0 -376
  262. package/src/internal/prompt-context.integration.test.ts +0 -232
  263. package/src/internal/prompt-context.test.ts +0 -127
  264. package/src/internal/reminder-runner.test.ts +0 -390
  265. package/src/internal/reminder-store.test.ts +0 -53
  266. package/src/internal/request-headers.test.ts +0 -27
  267. package/src/internal/resolve-prod-target.test.ts +0 -787
  268. package/src/internal/resolved-connections.test.ts +0 -295
  269. package/src/internal/router.test.ts +0 -57
  270. package/src/internal/sdk-runner.test.ts +0 -290
  271. package/src/internal/server.artifacts.test.ts +0 -303
  272. package/src/internal/session-engine.artifacts.test.ts +0 -243
  273. package/src/internal/session-engine.coalesce.test.ts +0 -169
  274. package/src/internal/session-engine.concurrency.test.ts +0 -250
  275. package/src/internal/session-engine.host-oauth-mcp.test.ts +0 -110
  276. package/src/internal/session-engine.interrupt.test.ts +0 -577
  277. package/src/internal/session-engine.storage.test.ts +0 -547
  278. package/src/internal/session-urls.test.ts +0 -28
  279. package/src/internal/sessions-client.test.ts +0 -518
  280. package/src/internal/storage-coordinator.test.ts +0 -517
  281. package/src/internal/tool-call.test.ts +0 -458
  282. package/src/internal/tool-result.test.ts +0 -52
  283. package/src/internal/trajectory.approvals.test.ts +0 -83
  284. package/src/internal/trajectory.subagents.test.ts +0 -198
  285. package/src/internal/turn-governor.test.ts +0 -137
  286. package/src/internal/update-check.test.ts +0 -485
  287. package/src/internal/workspace.test.ts +0 -207
  288. package/src/storage-backends/cursor-hosted.test.ts +0 -121
@@ -29,6 +29,7 @@ import {
29
29
  type AxCliOptions,
30
30
  cmdCall,
31
31
  cmdChat,
32
+ cmdCost,
32
33
  cmdEval,
33
34
  cmdEvalCancel,
34
35
  cmdEvalStatus,
@@ -55,6 +56,7 @@ import {
55
56
  } from "../internal/cli-deploy.js";
56
57
  import {
57
58
  CLI_COMMAND_NAME as CLI,
59
+ PACKAGE_NAME,
58
60
  packageVersion,
59
61
  } from "../internal/distribution.js";
60
62
  import { loadAgentLocalEnv } from "../internal/local-env.js";
@@ -85,6 +87,8 @@ Usage:
85
87
  ${CLI} session <sessionId> [--url <baseUrl> | --prod]
86
88
  [--json | --text | --events]
87
89
  [--slug <slug>] [--team <id>] [--dir <path>]
90
+ ${CLI} cost [sessionId] [--url <baseUrl> | --prod] [--json]
91
+ [--slug <slug>] [--team <id>] [--dir <path>]
88
92
  ${CLI} playground [--url <baseUrl> | --prod] [--session <id>] [--print]
89
93
  [--slug <slug>] [--team <id>] [--dir <path>]
90
94
  ${CLI} docs [--port <n>] [--host <host>] [--print]
@@ -161,6 +165,10 @@ Commands:
161
165
  session Show one session. Default: text trajectory. --json for trajectory
162
166
  JSON; --events for the raw event list. To continue interactively,
163
167
  use \`${CLI} resume [id]\`.
168
+ cost Pull cost metrics. With a session id: per-turn token usage and
169
+ estimated cost for that session. Without one: one row per
170
+ session plus a total. Costs are the engine's recorded estimates
171
+ from turn.completed events; --json for machine-readable reports.
164
172
  playground Open the web playground. --prod starts a loopback proxy that
165
173
  injects hosted engine credentials (browsers cannot set them).
166
174
  --print skips opening a browser. Ctrl-C stops the proxy.
@@ -908,6 +916,22 @@ async function main(argv: string[]): Promise<number> {
908
916
  );
909
917
  }
910
918
 
919
+ case "cost": {
920
+ return cmdCost(
921
+ positionals[0] ?? values["session-id"] ?? values.session,
922
+ axFromOptions({
923
+ dir,
924
+ url: values.url,
925
+ prod: values.prod,
926
+ team: values.team,
927
+ apiKey: values["api-key"],
928
+ slug: values.slug,
929
+ bearerToken: values["bearer-token"],
930
+ json: values.json,
931
+ })
932
+ );
933
+ }
934
+
911
935
  case "playground": {
912
936
  return cmdPlayground(
913
937
  axFromOptions({
@@ -1383,11 +1407,15 @@ function printServeBanner(
1383
1407
  ): void {
1384
1408
  const c = stdoutPalette();
1385
1409
  const agents = handle.agents;
1410
+ // Name the framework build in the boot line: hosted engines install the
1411
+ // published package at provision time, so the serve log is the only
1412
+ // durable record of which build a deployment's turns actually ran on.
1413
+ const versionTag = c.dim(`(${PACKAGE_NAME} ${packageVersion()})`);
1386
1414
  if (agents.length > 1) {
1387
- process.stdout.write(`${agents.length} agents listening\n`);
1415
+ process.stdout.write(`${agents.length} agents listening ${versionTag}\n`);
1388
1416
  } else {
1389
1417
  const info = projectInfo(agents[0]?.project ?? handle.project);
1390
- process.stdout.write(`${info.name} listening\n`);
1418
+ process.stdout.write(`${info.name} listening ${versionTag}\n`);
1391
1419
  }
1392
1420
 
1393
1421
  const playgroundUrl = resolvePlaygroundBannerUrl(handle, opts.noPlayground);
@@ -10,6 +10,7 @@ import {
10
10
  import { isDevMode } from "../../internal/dev-mode.js";
11
11
  import type {
12
12
  AgentCloudOptions,
13
+ ArtifactsApi,
13
14
  AuthContext,
14
15
  ChannelDefinition,
15
16
  ChannelEventHandlers,
@@ -68,7 +69,7 @@ import type {
68
69
  */
69
70
  type GitHubParsedContext = Omit<
70
71
  GitHubEventContext,
71
- "github" | "thread" | "host"
72
+ "github" | "thread" | "host" | "artifacts"
72
73
  >;
73
74
 
74
75
  const DEFAULT_PULL_REQUEST_ACTIONS: ReadonlySet<string> = new Set([
@@ -737,6 +738,7 @@ async function handlePullRequest(input: {
737
738
  bindingState: binding,
738
739
  installationId,
739
740
  host: input.args.host,
741
+ artifacts: input.args.artifacts,
740
742
  });
741
743
  const dispatch =
742
744
  input.options.onPullRequest === undefined
@@ -828,6 +830,7 @@ async function handleIssueComment(input: {
828
830
  bindingState: binding,
829
831
  installationId,
830
832
  host: input.args.host,
833
+ artifacts: input.args.artifacts,
831
834
  });
832
835
 
833
836
  const dispatch =
@@ -918,6 +921,7 @@ async function handleReviewComment(input: {
918
921
  bindingState: binding,
919
922
  installationId,
920
923
  host: input.args.host,
924
+ artifacts: input.args.artifacts,
921
925
  });
922
926
 
923
927
  const dispatch =
@@ -994,6 +998,7 @@ async function handleIssue(input: {
994
998
  bindingState: binding,
995
999
  installationId,
996
1000
  host: input.args.host,
1001
+ artifacts: input.args.artifacts,
997
1002
  });
998
1003
  const dispatch = await input.options.onIssue(ctx, parsed.issue);
999
1004
  if (dispatch === null) {
@@ -1053,6 +1058,7 @@ async function handleCheckSuite(input: {
1053
1058
  ctx: parsed.unanchoredCtx,
1054
1059
  installationId,
1055
1060
  host: input.args.host,
1061
+ artifacts: input.args.artifacts,
1056
1062
  }),
1057
1063
  parsed.checkSuite
1058
1064
  );
@@ -1079,6 +1085,7 @@ async function handleCheckSuite(input: {
1079
1085
  bindingState: binding,
1080
1086
  installationId,
1081
1087
  host: input.args.host,
1088
+ artifacts: input.args.artifacts,
1082
1089
  });
1083
1090
  const dispatch = await input.options.onCheckSuite(ctx, parsed.checkSuite);
1084
1091
  if (dispatch === null) {
@@ -1143,6 +1150,7 @@ async function handleCheckRun(input: {
1143
1150
  ctx: parsed.unanchoredCtx,
1144
1151
  installationId,
1145
1152
  host: input.args.host,
1153
+ artifacts: input.args.artifacts,
1146
1154
  }),
1147
1155
  parsed.checkRun
1148
1156
  );
@@ -1169,6 +1177,7 @@ async function handleCheckRun(input: {
1169
1177
  bindingState: binding,
1170
1178
  installationId,
1171
1179
  host: input.args.host,
1180
+ artifacts: input.args.artifacts,
1172
1181
  });
1173
1182
  const dispatch = await input.options.onCheckRun(ctx, parsed.checkRun);
1174
1183
  if (dispatch === null) {
@@ -1229,6 +1238,7 @@ async function handleWorkflowRun(input: {
1229
1238
  ctx: parsed.unanchoredCtx,
1230
1239
  installationId,
1231
1240
  host: input.args.host,
1241
+ artifacts: input.args.artifacts,
1232
1242
  }),
1233
1243
  parsed.workflowRun
1234
1244
  );
@@ -1255,6 +1265,7 @@ async function handleWorkflowRun(input: {
1255
1265
  bindingState: binding,
1256
1266
  installationId,
1257
1267
  host: input.args.host,
1268
+ artifacts: input.args.artifacts,
1258
1269
  });
1259
1270
  const dispatch = await input.options.onWorkflowRun(ctx, parsed.workflowRun);
1260
1271
  if (dispatch === null) {
@@ -1326,6 +1337,7 @@ async function handleStatus(input: {
1326
1337
  bindingState: binding,
1327
1338
  installationId,
1328
1339
  host: input.args.host,
1340
+ artifacts: input.args.artifacts,
1329
1341
  });
1330
1342
  const dispatch = await input.options.onStatus(ctx, parsed.status);
1331
1343
  if (dispatch === null) {
@@ -1399,6 +1411,7 @@ async function handleGenericEvent(input: {
1399
1411
  bindingState: binding,
1400
1412
  installationId,
1401
1413
  host: input.args.host,
1414
+ artifacts: input.args.artifacts,
1402
1415
  });
1403
1416
  const dispatch = await input.options.onEvent(ctx, parsed.event);
1404
1417
  if (dispatch === null) {
@@ -2224,11 +2237,12 @@ function escapeRegExp(value: string): string {
2224
2237
  */
2225
2238
  function enrichEventContext(input: {
2226
2239
  bindingConfig: GitHubBindingConfig;
2227
- ctx: Omit<GitHubEventContext, "github" | "thread" | "host"> &
2240
+ ctx: Omit<GitHubEventContext, "github" | "thread" | "host" | "artifacts"> &
2228
2241
  Partial<Pick<GitHubEventContext, "github" | "thread">>;
2229
2242
  bindingState: GitHubBindingState;
2230
2243
  installationId?: number;
2231
2244
  host: HostContext;
2245
+ artifacts: ArtifactsApi;
2232
2246
  }): GitHubEventContext {
2233
2247
  const { github, thread } = buildGitHubBinding({
2234
2248
  config: input.bindingConfig,
@@ -2242,6 +2256,7 @@ function enrichEventContext(input: {
2242
2256
  github,
2243
2257
  thread,
2244
2258
  host: input.host,
2259
+ artifacts: input.artifacts,
2245
2260
  };
2246
2261
  }
2247
2262
 
@@ -2254,6 +2269,7 @@ function enrichCiContext(input: {
2254
2269
  ctx: GitHubParsedContext;
2255
2270
  installationId?: number;
2256
2271
  host: HostContext;
2272
+ artifacts: ArtifactsApi;
2257
2273
  }): GitHubEventContext {
2258
2274
  const binding = githubBindingStateForEvent({
2259
2275
  kind: input.ctx.conversation.kind,
@@ -2269,6 +2285,7 @@ function enrichCiContext(input: {
2269
2285
  bindingState: binding,
2270
2286
  installationId: input.installationId,
2271
2287
  host: input.host,
2288
+ artifacts: input.artifacts,
2272
2289
  });
2273
2290
  }
2274
2291
 
@@ -1,5 +1,6 @@
1
1
  import type {
2
2
  AgentCloudOptions,
3
+ ArtifactsApi,
3
4
  AuthContext,
4
5
  AuthPolicy,
5
6
  ChannelEventHandlers,
@@ -306,6 +307,11 @@ export interface GitHubEventContext {
306
307
  thread: GitHubThread;
307
308
  /** Shared host services (MCP / host GitHub / Slack). Same as tool `ctx.host`. */
308
309
  host: HostContext;
310
+ /**
311
+ * Durable artifacts (unbound — the hook runs before any session is
312
+ * admitted; pass `sessionId` in `tag` input to attribute one).
313
+ */
314
+ artifacts: ArtifactsApi;
309
315
  }
310
316
 
311
317
  /**
@@ -3,7 +3,7 @@
3
3
  */
4
4
 
5
5
  import { ErrorCode, type WebAPIPlatformError, WebClient } from "@slack/web-api";
6
- import type { HostContext } from "../../types.js";
6
+ import type { ArtifactsApi, HostContext } from "../../types.js";
7
7
  import {
8
8
  SLACK_DEFAULT_LOADING_MESSAGES,
9
9
  SLACK_LOADING_MESSAGE_MAX_LEN,
@@ -540,6 +540,7 @@ export function buildSlackBinding(args: {
540
540
  threadTs: string;
541
541
  teamId?: string;
542
542
  host: HostContext;
543
+ artifacts: ArtifactsApi;
543
544
  onThreadTsChanged?: (threadTs: string) => void;
544
545
  log?: SlackLog;
545
546
  }): SlackBinding {
@@ -643,5 +644,6 @@ export function buildSlackBinding(args: {
643
644
  ...(args.teamId === undefined ? {} : { teamId: args.teamId }),
644
645
  },
645
646
  host: args.host,
647
+ artifacts: args.artifacts,
646
648
  };
647
649
  }
@@ -12,7 +12,7 @@
12
12
  * dispatches relayed envelopes through the pack's normal inbound path.
13
13
  */
14
14
 
15
- import type { HostContext, SendMessageFn } from "../../types.js";
15
+ import type { ArtifactsApi, HostContext, SendMessageFn } from "../../types.js";
16
16
  import { dispatchInboundMessage } from "./dispatch.js";
17
17
  import type { EventIdDedupe } from "./event-id-dedupe.js";
18
18
  import { slackTextToMarkdown } from "./inbound.js";
@@ -114,6 +114,7 @@ export async function dispatchCursorSlackEnvelope(args: {
114
114
  envelope: CursorSlackEnvelope;
115
115
  send: SendMessageFn;
116
116
  host: HostContext;
117
+ artifacts: ArtifactsApi;
117
118
  hasContinuationSession?: (continuationToken: string) => Promise<boolean>;
118
119
  isContinuationBusy?: (continuationToken: string) => Promise<boolean>;
119
120
  getContinuationLastBotMessageTs?: (
@@ -167,6 +168,7 @@ export async function dispatchCursorSlackEnvelope(args: {
167
168
  send: args.send,
168
169
  credentials: runtime.credentials,
169
170
  host: args.host,
171
+ artifacts: args.artifacts,
170
172
  log,
171
173
  evalCommandsEnabled: runtime.options.evalCommands !== false,
172
174
  cursorAgentName: envelope.agentName,
@@ -2,7 +2,12 @@
2
2
  * Shared inbound dispatch for Slack Events API bodies and Socket Mode.
3
3
  */
4
4
 
5
- import type { HostContext, JsonValue, SendMessageFn } from "../../types.js";
5
+ import type {
6
+ ArtifactsApi,
7
+ HostContext,
8
+ JsonValue,
9
+ SendMessageFn,
10
+ } from "../../types.js";
6
11
  import { buildSlackBinding, slackContinuationKey } from "./api.js";
7
12
  import { firstLineTitle, maybeSetThreadTitle } from "./assistant.js";
8
13
  import type { SlackBotMentionGate } from "./bot-mentions.js";
@@ -65,6 +70,8 @@ export interface SlackInboundDispatchDeps extends SlackContinuationProbes {
65
70
  credentials: SlackCredentials | undefined;
66
71
  eventIds: EventIdDedupe;
67
72
  host: HostContext;
73
+ /** Unbound artifacts facade handed to handler bindings (`ctx.artifacts`). */
74
+ artifacts: ArtifactsApi;
68
75
  log?: SlackLog;
69
76
  /** Dispatch on `app_mention`. Defaults to `true`. */
70
77
  mentionsEnabled?: boolean;
@@ -110,6 +117,7 @@ export async function dispatchInboundMessage(args: {
110
117
  send: SendMessageFn;
111
118
  credentials: SlackCredentials | undefined;
112
119
  host: HostContext;
120
+ artifacts: ArtifactsApi;
113
121
  hasContinuationSession?: (continuationToken: string) => Promise<boolean>;
114
122
  isContinuationBusy?: (continuationToken: string) => Promise<boolean>;
115
123
  getContinuationLastBotMessageTs?: (
@@ -132,6 +140,7 @@ export async function dispatchInboundMessage(args: {
132
140
  channelId: message.channelId,
133
141
  threadTs: message.threadTs,
134
142
  host: args.host,
143
+ artifacts: args.artifacts,
135
144
  log,
136
145
  ...(message.teamId === undefined ? {} : { teamId: message.teamId }),
137
146
  });
@@ -450,6 +459,7 @@ export function dispatchInboundFromEventBody(
450
459
  send: deps.send,
451
460
  credentials: deps.credentials,
452
461
  host: deps.host,
462
+ artifacts: deps.artifacts,
453
463
  log,
454
464
  evalCommandsEnabled: deps.evalCommandsEnabled,
455
465
  cursorAgentName: deps.cursorAgentName,
@@ -490,6 +500,7 @@ export function dispatchInboundFromEventBody(
490
500
  send: deps.send,
491
501
  credentials: deps.credentials,
492
502
  host: deps.host,
503
+ artifacts: deps.artifacts,
493
504
  log,
494
505
  evalCommandsEnabled: deps.evalCommandsEnabled,
495
506
  cursorAgentName: deps.cursorAgentName,
@@ -9,6 +9,7 @@
9
9
 
10
10
  import type {
11
11
  ApprovalDecision,
12
+ ArtifactsApi,
12
13
  AuthContext,
13
14
  ChannelSession,
14
15
  HostContext,
@@ -275,6 +276,7 @@ export interface SlackBlockActionDispatchDeps extends SlackContinuationProbes {
275
276
  send: SendMessageFn;
276
277
  credentials: SlackCredentials | undefined;
277
278
  host: HostContext;
279
+ artifacts: ArtifactsApi;
278
280
  log?: SlackLog;
279
281
  }
280
282
 
@@ -347,6 +349,7 @@ export async function dispatchBlockAction(
347
349
  send: deps.send,
348
350
  credentials: deps.credentials,
349
351
  host: deps.host,
352
+ artifacts: deps.artifacts,
350
353
  log,
351
354
  // Click text is synthetic — never treat it as a stop/eval directive.
352
355
  evalCommandsEnabled: false,
@@ -9,6 +9,7 @@
9
9
 
10
10
  import { allowAll, defineChannel } from "../../channels.js";
11
11
  import type {
12
+ ArtifactsApi,
12
13
  ChannelDefinition,
13
14
  ChannelEventHandlers,
14
15
  HostContext,
@@ -215,6 +216,7 @@ export function slackChannel<const Name extends string = string>(
215
216
  send: SendMessageFn;
216
217
  waitUntil: (promise: Promise<unknown>) => void;
217
218
  host: HostContext;
219
+ artifacts: ArtifactsApi;
218
220
  hasContinuationSession?: (continuationToken: string) => Promise<boolean>;
219
221
  isContinuationBusy?: (continuationToken: string) => Promise<boolean>;
220
222
  getContinuationLastBotMessageTs?: (
@@ -230,6 +232,7 @@ export function slackChannel<const Name extends string = string>(
230
232
  credentials,
231
233
  eventIds,
232
234
  host: args.host,
235
+ artifacts: args.artifacts,
233
236
  log: getLog(),
234
237
  mentionsEnabled,
235
238
  directMessagesEnabled,
@@ -410,6 +413,7 @@ export function slackChannel<const Name extends string = string>(
410
413
  send: args.send,
411
414
  credentials,
412
415
  host: args.host,
416
+ artifacts: args.artifacts,
413
417
  log: getLog(),
414
418
  evalCommandsEnabled,
415
419
  ...(args.hasContinuationSession === undefined
@@ -454,6 +458,7 @@ export function slackChannel<const Name extends string = string>(
454
458
  send: args.send,
455
459
  waitUntil: args.waitUntil,
456
460
  host: args.host,
461
+ artifacts: args.artifacts,
457
462
  ...(args.hasContinuationSession === undefined
458
463
  ? {}
459
464
  : { hasContinuationSession: args.hasContinuationSession }),
@@ -496,6 +501,7 @@ export function slackChannel<const Name extends string = string>(
496
501
  send: args.send,
497
502
  credentials,
498
503
  host: args.host,
504
+ artifacts: args.artifacts,
499
505
  log: getLog(),
500
506
  hasContinuationSession: args.hasContinuationSession,
501
507
  isContinuationBusy: args.isContinuationBusy,
@@ -4,6 +4,7 @@
4
4
 
5
5
  import type {
6
6
  AgentCloudOptions,
7
+ ArtifactsApi,
7
8
  AuthContext,
8
9
  ChannelEventHandlers,
9
10
  HostContext,
@@ -189,6 +190,11 @@ export interface SlackBinding {
189
190
  };
190
191
  /** Shared host services (MCP / GitHub / Slack). */
191
192
  host: HostContext;
193
+ /**
194
+ * Durable artifacts (unbound — the handler runs before any session is
195
+ * admitted; pass `sessionId` in `tag` input to attribute one).
196
+ */
197
+ artifacts: ArtifactsApi;
192
198
  }
193
199
 
194
200
  export type SlackMessageHandler = (
@@ -187,6 +187,10 @@ export function applyBuiltinMetrics(
187
187
  m.cacheReadTokens += usage.cacheReadTokens;
188
188
  m.cacheWriteTokens += usage.cacheWriteTokens;
189
189
  }
190
+ const cost = event.data.cost;
191
+ if (cost !== undefined) {
192
+ m.costUsd += cost.totalUsd;
193
+ }
190
194
  addWallTime(accum, event.at);
191
195
  break;
192
196
  }
@@ -323,6 +323,7 @@ function addMetrics(target: ABMetrics, delta: ABMetrics): void {
323
323
  target.outputTokens += delta.outputTokens;
324
324
  target.cacheReadTokens += delta.cacheReadTokens;
325
325
  target.cacheWriteTokens += delta.cacheWriteTokens;
326
+ target.costUsd += delta.costUsd;
326
327
  target.wallTimeMs += delta.wallTimeMs;
327
328
  for (const [key, value] of Object.entries(delta.custom)) {
328
329
  target.custom[key] = (target.custom[key] ?? 0) + value;
@@ -50,6 +50,7 @@ import {
50
50
  } from "./init-project.js";
51
51
  import { offerInstallCursorSkills } from "./install-cursor-skills.js";
52
52
  import { runLogsTail, sanitizeCustomerError } from "./logs-client.js";
53
+ import { mapPool } from "./map-pool.js";
53
54
  import { openBrowser } from "./open-browser.js";
54
55
  import { startPlaygroundProxy } from "./playground-proxy.js";
55
56
  import {
@@ -59,6 +60,12 @@ import {
59
60
  resolveProdTarget,
60
61
  } from "./resolve-prod-target.js";
61
62
  import { runSession } from "./run-client.js";
63
+ import {
64
+ buildSessionCostReport,
65
+ formatSessionCostText,
66
+ formatSessionsCostText,
67
+ type SessionCostRow,
68
+ } from "./session-cost.js";
62
69
  import {
63
70
  fetchSessionEvents,
64
71
  formatSessionsTable,
@@ -1771,6 +1778,94 @@ export async function cmdSession(
1771
1778
  }
1772
1779
  }
1773
1780
 
1781
+ /** Sessions fetched concurrently when `cost` aggregates every session. */
1782
+ const COST_FETCH_CONCURRENCY = 4;
1783
+
1784
+ /**
1785
+ * `cost [sessionId]` — pull per-session cost metrics.
1786
+ *
1787
+ * With a session id: per-turn token usage + estimated cost for that session.
1788
+ * Without one: one row per session (all sessions on the target) plus a
1789
+ * total row. `--json` prints the underlying report(s); text is the default.
1790
+ * Costs are the engine's recorded estimates on `turn.completed` events
1791
+ * (see `model-pricing.ts`); turns persisted before cost tracking simply
1792
+ * count as unpriced.
1793
+ */
1794
+ export async function cmdCost(
1795
+ sessionId: string | undefined,
1796
+ options: AxCliOptions
1797
+ ): Promise<number> {
1798
+ const target = await resolveSessionTarget(options);
1799
+ if (typeof target === "number") {
1800
+ return target;
1801
+ }
1802
+ const auth = {
1803
+ bearerToken: options.bearerToken,
1804
+ headers: target.headers,
1805
+ };
1806
+
1807
+ try {
1808
+ const resolved = trimNonEmpty(sessionId);
1809
+ if (resolved !== undefined) {
1810
+ const events = await fetchSessionEvents({
1811
+ baseUrl: target.agentUrl,
1812
+ sessionId: resolved,
1813
+ auth,
1814
+ fetchImpl: options.fetchImpl,
1815
+ });
1816
+ const report = buildSessionCostReport(events);
1817
+ if (report.sessionId === "") {
1818
+ report.sessionId = resolved;
1819
+ }
1820
+ if (options.json === true) {
1821
+ process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
1822
+ } else {
1823
+ process.stdout.write(formatSessionCostText(report));
1824
+ }
1825
+ return 0;
1826
+ }
1827
+
1828
+ const listed = await listSessionsWithSource({
1829
+ baseUrl: target.agentUrl,
1830
+ auth,
1831
+ fetchImpl: options.fetchImpl,
1832
+ });
1833
+ const rows = await mapPool(
1834
+ listed.sessions,
1835
+ COST_FETCH_CONCURRENCY,
1836
+ async (session): Promise<SessionCostRow> => {
1837
+ const events = await fetchSessionEvents({
1838
+ baseUrl: target.agentUrl,
1839
+ sessionId: session.sessionId,
1840
+ auth,
1841
+ fetchImpl: options.fetchImpl,
1842
+ });
1843
+ const report = buildSessionCostReport(events);
1844
+ return {
1845
+ sessionId: session.sessionId,
1846
+ channelId: session.channelId,
1847
+ title: session.title,
1848
+ updatedAt: session.updatedAt,
1849
+ totals: report.totals,
1850
+ };
1851
+ }
1852
+ );
1853
+ if (options.json === true) {
1854
+ process.stdout.write(`${JSON.stringify({ sessions: rows }, null, 2)}\n`);
1855
+ } else {
1856
+ process.stdout.write(formatSessionsCostText(rows));
1857
+ }
1858
+ return 0;
1859
+ } catch (error) {
1860
+ process.stderr.write(
1861
+ `${sanitizeCustomerError(
1862
+ error instanceof Error ? error.message : String(error)
1863
+ )}\n`
1864
+ );
1865
+ return 1;
1866
+ }
1867
+ }
1868
+
1774
1869
  /**
1775
1870
  * `playground` — open the web UI against local / `--url` / `--prod`.
1776
1871
  *