@cursor/july 0.1.28 → 0.1.29

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 (122) hide show
  1. package/dist/bin/agent-serve.js +20 -2
  2. package/dist/channels/slack/slack-channel.d.ts +19 -1
  3. package/dist/channels/slack/slack-channel.d.ts.map +1 -1
  4. package/dist/channels/slack/slack-channel.js +29 -0
  5. package/dist/docs/404.html +1 -1
  6. package/dist/docs/ab.html +2 -2
  7. package/dist/docs/assets/{app.CqjrYaT2.js → app.QdunVQKg.js} +1 -1
  8. package/dist/docs/assets/chunks/@localSearchIndexroot.DGe61XHA.js +1 -0
  9. package/dist/docs/assets/chunks/{VPLocalSearchBox.ag-MwUel.js → VPLocalSearchBox.B6EpUXYf.js} +1 -1
  10. package/dist/docs/assets/chunks/{theme.BS-DJWat.js → theme.BOTJVqh7.js} +2 -2
  11. package/dist/docs/building-with-agents.html +2 -2
  12. package/dist/docs/concepts.html +2 -2
  13. package/dist/docs/deployment.html +2 -2
  14. package/dist/docs/evals.html +2 -2
  15. package/dist/docs/example-agents/approval-buddy.html +2 -2
  16. package/dist/docs/example-agents/benny.html +2 -2
  17. package/dist/docs/example-agents/bugbot.html +2 -2
  18. package/dist/docs/example-agents/codebase-wiki.html +2 -2
  19. package/dist/docs/example-agents/codeowners-review.html +2 -2
  20. package/dist/docs/example-agents/concierge.html +2 -2
  21. package/dist/docs/example-agents/fsd.html +2 -2
  22. package/dist/docs/example-agents/index.html +2 -2
  23. package/dist/docs/example-agents/knowledge-base.html +2 -2
  24. package/dist/docs/example-agents/oncall.html +2 -2
  25. package/dist/docs/example-agents/security-reviewer.html +2 -2
  26. package/dist/docs/example-agents/slack-agent.html +2 -2
  27. package/dist/docs/example-agents/weather-agent.html +2 -2
  28. package/dist/docs/guides/agent-to-agent.html +2 -2
  29. package/dist/docs/guides/cloud-runtime.html +2 -2
  30. package/dist/docs/guides/github.html +2 -2
  31. package/dist/docs/guides/human-in-the-loop.html +2 -2
  32. package/dist/docs/guides/mcp-oauth.html +2 -2
  33. package/dist/docs/guides/slack.html +2 -2
  34. package/dist/docs/guides/webhooks.html +2 -2
  35. package/dist/docs/hillclimbing.html +2 -2
  36. package/dist/docs/index.html +2 -2
  37. package/dist/docs/quickstart.html +2 -2
  38. package/dist/docs/reference/agent-config.html +2 -2
  39. package/dist/docs/reference/channels.html +2 -2
  40. package/dist/docs/reference/cli.html +2 -2
  41. package/dist/docs/reference/connections.html +2 -2
  42. package/dist/docs/reference/hooks.html +2 -2
  43. package/dist/docs/reference/http-api.html +2 -2
  44. package/dist/docs/reference/instructions.html +2 -2
  45. package/dist/docs/reference/playground.html +2 -2
  46. package/dist/docs/reference/project-layout.html +2 -2
  47. package/dist/docs/reference/prompt.html +2 -2
  48. package/dist/docs/reference/schedules.html +2 -2
  49. package/dist/docs/reference/sessions.html +2 -2
  50. package/dist/docs/reference/skills.html +2 -2
  51. package/dist/docs/reference/subagents.html +2 -2
  52. package/dist/docs/reference/tools.html +2 -2
  53. package/dist/docs/scaffolding-agents.html +2 -2
  54. package/dist/docs/storage.html +2 -2
  55. package/dist/docs/troubleshooting.html +2 -2
  56. package/dist/internal/cloud-turn-cost.d.ts +34 -0
  57. package/dist/internal/cloud-turn-cost.d.ts.map +1 -0
  58. package/dist/internal/cloud-turn-cost.js +106 -0
  59. package/dist/internal/discovery.d.ts.map +1 -1
  60. package/dist/internal/discovery.js +1 -1
  61. package/dist/internal/event-log.d.ts +6 -0
  62. package/dist/internal/event-log.d.ts.map +1 -1
  63. package/dist/internal/event-log.js +16 -0
  64. package/dist/internal/host-platforms.d.ts +13 -0
  65. package/dist/internal/host-platforms.d.ts.map +1 -1
  66. package/dist/internal/host-platforms.js +25 -16
  67. package/dist/internal/http-channel.d.ts.map +1 -1
  68. package/dist/internal/http-channel.js +3 -1
  69. package/dist/internal/local-control-plane.d.ts +25 -0
  70. package/dist/internal/local-control-plane.d.ts.map +1 -0
  71. package/dist/internal/local-control-plane.js +172 -0
  72. package/dist/internal/platform-schedule-sync.d.ts +17 -0
  73. package/dist/internal/platform-schedule-sync.d.ts.map +1 -0
  74. package/dist/internal/platform-schedule-sync.js +72 -0
  75. package/dist/internal/platform-timers.d.ts +28 -0
  76. package/dist/internal/platform-timers.d.ts.map +1 -0
  77. package/dist/internal/platform-timers.js +120 -0
  78. package/dist/internal/reminder-runner.d.ts +16 -12
  79. package/dist/internal/reminder-runner.d.ts.map +1 -1
  80. package/dist/internal/reminder-runner.js +112 -61
  81. package/dist/internal/reminder-store.d.ts +5 -4
  82. package/dist/internal/reminder-store.d.ts.map +1 -1
  83. package/dist/internal/reminder-store.js +5 -4
  84. package/dist/internal/sdk-runner.d.ts.map +1 -1
  85. package/dist/internal/sdk-runner.js +44 -1
  86. package/dist/internal/server.d.ts.map +1 -1
  87. package/dist/internal/server.js +105 -11
  88. package/dist/internal/session-engine.d.ts +22 -1
  89. package/dist/internal/session-engine.d.ts.map +1 -1
  90. package/dist/internal/session-engine.js +110 -4
  91. package/dist/internal/storage-coordinator.d.ts +4 -15
  92. package/dist/internal/storage-coordinator.d.ts.map +1 -1
  93. package/dist/internal/storage-coordinator.js +4 -30
  94. package/dist/playground/assets/index-CquRB-l0.js +85 -0
  95. package/dist/playground/assets/{index-Bul1WfrB.css → index-Dj0bWpkn.css} +1 -1
  96. package/dist/playground/index.html +2 -2
  97. package/dist/storage.d.ts +0 -3
  98. package/dist/storage.d.ts.map +1 -1
  99. package/dist/storage.js +0 -3
  100. package/dist/types.d.ts +11 -2
  101. package/dist/types.d.ts.map +1 -1
  102. package/package.json +1 -1
  103. package/src/bin/agent-serve.ts +21 -2
  104. package/src/channels/slack/slack-channel.ts +46 -0
  105. package/src/internal/cloud-turn-cost.ts +158 -0
  106. package/src/internal/discovery.ts +1 -0
  107. package/src/internal/event-log.ts +17 -0
  108. package/src/internal/host-platforms.ts +40 -18
  109. package/src/internal/http-channel.ts +3 -1
  110. package/src/internal/local-control-plane.ts +188 -0
  111. package/src/internal/platform-schedule-sync.ts +81 -0
  112. package/src/internal/platform-timers.ts +173 -0
  113. package/src/internal/reminder-runner.ts +131 -67
  114. package/src/internal/reminder-store.ts +5 -4
  115. package/src/internal/sdk-runner.ts +49 -1
  116. package/src/internal/server.ts +121 -6
  117. package/src/internal/session-engine.ts +138 -3
  118. package/src/internal/storage-coordinator.ts +4 -41
  119. package/src/storage.ts +0 -5
  120. package/src/types.ts +11 -2
  121. package/dist/docs/assets/chunks/@localSearchIndexroot.VWQoPFJ1.js +0 -1
  122. package/dist/playground/assets/index-CkN74U_L.js +0 -87
@@ -4,7 +4,8 @@
4
4
  * function XOR prompt.
5
5
  */
6
6
  import type { ReminderCreateInput, ReminderInfo } from "../types.js";
7
- import { type ReminderRecord } from "./reminder-store.js";
7
+ import type { PlatformTimers } from "./platform-timers.js";
8
+ import type { ReminderRecord } from "./reminder-store.js";
8
9
  import { type SessionEngine } from "./session-engine.js";
9
10
  export { ReminderValidationError } from "./reminder-schedule.js";
10
11
  export declare class UnknownReminderError extends Error {
@@ -14,24 +15,25 @@ export declare class UnknownReminderError extends Error {
14
15
  export declare class ReminderRunner {
15
16
  private readonly engine;
16
17
  private readonly logger;
17
- private readonly store;
18
+ private readonly platformTimers?;
19
+ private readonly records;
18
20
  private readonly handlers;
19
21
  private readonly timers;
20
22
  private readonly firing;
21
23
  /** Single-flight idle gates keyed by `channelId:continuationToken`. */
22
24
  private readonly idleGates;
23
25
  private started;
24
- constructor(engine: SessionEngine, logger?: (line: string) => void);
25
- get storeRoot(): string;
26
- /** Start deadline timers for armed reminders (call after restore). */
27
- start(): Promise<void>;
26
+ constructor(engine: SessionEngine, logger?: (line: string) => void, platformTimers?: PlatformTimers | undefined);
28
27
  /**
29
- * Pull reminder records from `defineStorage` into `<stateRoot>/reminders`
30
- * when local disk is empty for that id. Failures are logged and skipped.
28
+ * Load reminder documents from the control plane into memory. Does not
29
+ * arm in-process timers the CP owns clocks.
31
30
  */
32
- private hydrateFromStorage;
33
- /** Persist locally and mirror into the authored storage sink when present. */
31
+ hydrate(): Promise<void>;
32
+ /** Start deadline timers for armed reminders (tests / no control plane). */
33
+ start(): Promise<void>;
34
34
  private persist;
35
+ private getRecord;
36
+ private allRecords;
35
37
  stop(): void;
36
38
  create(input: ReminderCreateInput): Promise<ReminderInfo>;
37
39
  list(filter?: {
@@ -49,8 +51,10 @@ export declare class ReminderRunner {
49
51
  * time and disarms as `session_gone`.
50
52
  */
51
53
  rekeyContinuation(channelId: string, oldToken: string, newToken: string): Promise<number>;
52
- /** Fire one reminder immediately (dev / hillclimb). */
53
- dispatch(reminderId: string): Promise<{
54
+ /** Fire one reminder immediately (dev / hillclimb / control plane). */
55
+ dispatch(reminderId: string, opts?: {
56
+ expectedFireCount?: number;
57
+ }): Promise<{
54
58
  reminderId: string;
55
59
  outcome: "fired" | "noop";
56
60
  reason?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"reminder-runner.d.ts","sourceRoot":"","sources":["../../src/internal/reminder-runner.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAEV,mBAAmB,EAGnB,YAAY,EAEb,MAAM,aAAa,CAAC;AASrB,OAAO,EAEL,KAAK,cAAc,EAEpB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAoB,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAE3E,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAEjE,qBAAa,oBAAqB,SAAQ,KAAK;IAG3C,QAAQ,CAAC,oBAAoB,EAAE,MAAM,EAAE;IAFzC,YACE,UAAU,EAAE,MAAM,EACT,oBAAoB,EAAE,MAAM,EAAE,EAIxC;CACF;AAyDD,qBAAa,cAAc;IAUvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAVzB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgB;IACtC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmC;IAC5D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqC;IAC5D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAC5C,uEAAuE;IACvE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAoC;IAC9D,OAAO,CAAC,OAAO,CAAS;IAExB,YACmB,MAAM,EAAE,aAAa,EACrB,MAAM,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAe,EAG3D;IAED,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,sEAAsE;IAChE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CA+B3B;IAED;;;OAGG;YACW,kBAAkB;IA6BhC,8EAA8E;YAChE,OAAO;IAKrB,IAAI,IAAI,IAAI,CAOX;IAEK,MAAM,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,YAAY,CAAC,CA8D9D;IAEK,IAAI,CAAC,MAAM,CAAC,EAAE;QAClB,MAAM,CAAC,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAC;QAClC,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,iBAAiB,CAAC,EAAE,MAAM,CAAC;KAC5B,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CA4B1B;IAEK,MAAM,CACV,EAAE,EAAE,MAAM,EACV,MAAM,SAAoB,GACzB,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC,CAkBnC;IAED,iFAAiF;IAC3E,qBAAqB,CACzB,iBAAiB,EAAE,MAAM,EACzB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC,CAUjB;IAED;;;;;OAKG;IACG,iBAAiB,CACrB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,CAAC,CAkBjB;IAED,uDAAuD;IACjD,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC;QAC1C,UAAU,EAAE,MAAM,CAAC;QACnB,OAAO,EAAE,OAAO,GAAG,MAAM,CAAC;QAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC,CAQD;IAED,OAAO,CAAC,QAAQ;IA4ChB,OAAO,CAAC,UAAU;YAQJ,IAAI;YA6GJ,aAAa;IAY3B,OAAO,CAAC,eAAe;IAsBvB;;;OAGG;YACW,mBAAmB;YAcnB,aAAa;YAcb,YAAY;IA0C1B,OAAO,CAAC,gBAAgB;IA0DxB,OAAO,CAAC,iBAAiB;YAeX,MAAM;YAYN,SAAS;CAoFxB;AAGD,YAAY,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"reminder-runner.d.ts","sourceRoot":"","sources":["../../src/internal/reminder-runner.ts"],"names":[],"mappings":"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"}
@@ -13,10 +13,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
13
13
  });
14
14
  };
15
15
  import { randomBytes } from "node:crypto";
16
- import { join } from "node:path";
17
16
  import { parseDuration } from "./duration.js";
18
17
  import { defaultBusyPolicy, MAX_TIMER_MS, nextCronFireMs, ReminderValidationError, resolveSchedule, } from "./reminder-schedule.js";
19
- import { ReminderStore, } from "./reminder-store.js";
20
18
  import { APP_AUTH } from "./schedule-runner.js";
21
19
  import { SessionBusyError } from "./session-engine.js";
22
20
  export { ReminderValidationError } from "./reminder-schedule.js";
@@ -71,35 +69,72 @@ function buildFirePrompt(record) {
71
69
  return lines.join("\n");
72
70
  }
73
71
  export class ReminderRunner {
74
- constructor(engine, logger = () => { }) {
72
+ constructor(engine, logger = () => { }, platformTimers) {
75
73
  this.engine = engine;
76
74
  this.logger = logger;
75
+ this.platformTimers = platformTimers;
76
+ this.records = new Map();
77
77
  this.handlers = new Map();
78
78
  this.timers = new Map();
79
79
  this.firing = new Set();
80
80
  /** Single-flight idle gates keyed by `channelId:continuationToken`. */
81
81
  this.idleGates = new Map();
82
82
  this.started = false;
83
- this.store = new ReminderStore(join(engine.stateRoot, "reminders"));
84
83
  }
85
- get storeRoot() {
86
- return join(this.engine.stateRoot, "reminders");
84
+ /**
85
+ * Load reminder documents from the control plane into memory. Does not
86
+ * arm in-process timers — the CP owns clocks.
87
+ */
88
+ hydrate() {
89
+ return __awaiter(this, void 0, void 0, function* () {
90
+ if (this.platformTimers === undefined) {
91
+ return;
92
+ }
93
+ let remote = [];
94
+ try {
95
+ remote = yield this.platformTimers.listReminders();
96
+ }
97
+ catch (error) {
98
+ this.logger(`[agentkit] reminders: control-plane list failed: ${error instanceof Error ? error.message : String(error)}`);
99
+ return;
100
+ }
101
+ this.records.clear();
102
+ for (const record of remote) {
103
+ this.records.set(record.id, record);
104
+ }
105
+ let disarmedOrphan = 0;
106
+ for (const record of [...this.records.values()]) {
107
+ if (record.status !== "armed") {
108
+ continue;
109
+ }
110
+ if ((record.hasRunHandler === true || record.hasUntilFn === true) &&
111
+ this.handlers.get(record.id) === undefined) {
112
+ yield this.disarm(record, "handler_lost_on_restart");
113
+ disarmedOrphan += 1;
114
+ }
115
+ }
116
+ if (remote.length > 0 || disarmedOrphan > 0) {
117
+ this.logger(`[agentkit] reminders: hydrated ${remote.length} reminder(s) from control plane` +
118
+ (disarmedOrphan > 0
119
+ ? `; disarmed ${disarmedOrphan} without live handlers`
120
+ : ""));
121
+ }
122
+ });
87
123
  }
88
- /** Start deadline timers for armed reminders (call after restore). */
124
+ /** Start deadline timers for armed reminders (tests / no control plane). */
89
125
  start() {
90
126
  return __awaiter(this, void 0, void 0, function* () {
91
127
  if (this.started)
92
128
  return;
93
129
  this.started = true;
94
- // Materialize sink-backed reminders onto local disk before arming
95
- // (local wins when both sides have the same id).
96
- yield this.hydrateFromStorage();
97
- const armed = yield this.store.listArmed();
130
+ yield this.hydrate();
131
+ if (this.platformTimers !== undefined) {
132
+ return;
133
+ }
134
+ const armed = [...this.records.values()].filter((r) => r.status === "armed");
98
135
  let restored = 0;
99
136
  let disarmedOrphan = 0;
100
137
  for (const record of armed) {
101
- // Run / function-until handlers are in-memory only. After restart they
102
- // are gone — disarm rather than falling back to a generic prompt fire.
103
138
  if ((record.hasRunHandler === true || record.hasUntilFn === true) &&
104
139
  this.handlers.get(record.id) === undefined) {
105
140
  yield this.disarm(record, "handler_lost_on_restart");
@@ -117,45 +152,49 @@ export class ReminderRunner {
117
152
  }
118
153
  });
119
154
  }
120
- /**
121
- * Pull reminder records from `defineStorage` into `<stateRoot>/reminders`
122
- * when local disk is empty for that id. Failures are logged and skipped.
123
- */
124
- hydrateFromStorage() {
155
+ persist(record) {
125
156
  return __awaiter(this, void 0, void 0, function* () {
126
- const storage = this.engine.storage;
127
- if (storage === undefined || !storage.canBulkRestore) {
128
- return;
157
+ if (this.platformTimers !== undefined) {
158
+ yield this.platformTimers.putReminder(record);
129
159
  }
130
- let hydrated = 0;
131
- try {
132
- const remote = yield storage.listReminders();
133
- for (const record of remote) {
134
- const local = yield this.store.get(record.id);
135
- if (local !== undefined) {
136
- continue;
160
+ this.records.set(record.id, record);
161
+ });
162
+ }
163
+ getRecord(id) {
164
+ return __awaiter(this, void 0, void 0, function* () {
165
+ if (this.platformTimers !== undefined) {
166
+ try {
167
+ const remote = yield this.platformTimers.getReminder(id);
168
+ if (remote === undefined) {
169
+ this.records.delete(id);
170
+ return undefined;
137
171
  }
138
- // Local write only — re-mirroring would just echo the sink.
139
- yield this.store.save(record);
140
- hydrated += 1;
172
+ this.records.set(id, remote);
173
+ return remote;
174
+ }
175
+ catch (error) {
176
+ this.logger(`[agentkit] reminders: control-plane get failed for ${id}: ${error instanceof Error ? error.message : String(error)}`);
177
+ return this.records.get(id);
141
178
  }
142
179
  }
143
- catch (error) {
144
- const message = error instanceof Error ? error.message : String(error);
145
- this.logger(`[agentkit] reminders: storage hydrate failed: ${message}`);
146
- return;
147
- }
148
- if (hydrated > 0) {
149
- this.logger(`[agentkit] reminders: hydrated ${hydrated} reminder(s) from storage`);
150
- }
180
+ return this.records.get(id);
151
181
  });
152
182
  }
153
- /** Persist locally and mirror into the authored storage sink when present. */
154
- persist(record) {
183
+ allRecords() {
155
184
  return __awaiter(this, void 0, void 0, function* () {
156
- var _a;
157
- yield this.store.save(record);
158
- (_a = this.engine.storage) === null || _a === void 0 ? void 0 : _a.reminder(record);
185
+ if (this.platformTimers !== undefined) {
186
+ try {
187
+ const remote = yield this.platformTimers.listReminders();
188
+ this.records.clear();
189
+ for (const record of remote) {
190
+ this.records.set(record.id, record);
191
+ }
192
+ }
193
+ catch (error) {
194
+ this.logger(`[agentkit] reminders: control-plane list failed: ${error instanceof Error ? error.message : String(error)}`);
195
+ }
196
+ }
197
+ return [...this.records.values()];
159
198
  });
160
199
  }
161
200
  stop() {
@@ -217,7 +256,7 @@ export class ReminderRunner {
217
256
  run: input.run,
218
257
  untilFn,
219
258
  });
220
- if (this.started) {
259
+ if (this.started && this.platformTimers === undefined) {
221
260
  this.armTimer(record);
222
261
  }
223
262
  return toInfo(record);
@@ -225,7 +264,7 @@ export class ReminderRunner {
225
264
  }
226
265
  list(filter) {
227
266
  return __awaiter(this, void 0, void 0, function* () {
228
- const all = yield this.store.list();
267
+ const all = yield this.allRecords();
229
268
  return all
230
269
  .filter((r) => {
231
270
  if ((filter === null || filter === void 0 ? void 0 : filter.status) !== undefined && r.status !== filter.status) {
@@ -251,7 +290,7 @@ export class ReminderRunner {
251
290
  }
252
291
  cancel(id_1) {
253
292
  return __awaiter(this, arguments, void 0, function* (id, reason = "explicit_cancel") {
254
- const record = yield this.store.get(id);
293
+ const record = yield this.getRecord(id);
255
294
  if (record === undefined) {
256
295
  return undefined;
257
296
  }
@@ -268,7 +307,7 @@ export class ReminderRunner {
268
307
  /** Cancel all armed reminders matching a continuation token (e.g. PR closed). */
269
308
  cancelForContinuation(continuationToken, reason) {
270
309
  return __awaiter(this, void 0, void 0, function* () {
271
- const armed = yield this.store.listArmed();
310
+ const armed = (yield this.allRecords()).filter((r) => r.status === "armed");
272
311
  let n = 0;
273
312
  for (const record of armed) {
274
313
  if (record.continuationToken === continuationToken) {
@@ -287,7 +326,7 @@ export class ReminderRunner {
287
326
  */
288
327
  rekeyContinuation(channelId, oldToken, newToken) {
289
328
  return __awaiter(this, void 0, void 0, function* () {
290
- const armed = yield this.store.listArmed();
329
+ const armed = (yield this.allRecords()).filter((r) => r.status === "armed");
291
330
  let n = 0;
292
331
  for (const record of armed) {
293
332
  if (record.channelId !== channelId ||
@@ -300,14 +339,22 @@ export class ReminderRunner {
300
339
  return n;
301
340
  });
302
341
  }
303
- /** Fire one reminder immediately (dev / hillclimb). */
304
- dispatch(reminderId) {
305
- return __awaiter(this, void 0, void 0, function* () {
306
- const record = yield this.store.get(reminderId);
342
+ /** Fire one reminder immediately (dev / hillclimb / control plane). */
343
+ dispatch(reminderId_1) {
344
+ return __awaiter(this, arguments, void 0, function* (reminderId, opts = {}) {
345
+ const record = yield this.getRecord(reminderId);
307
346
  if (record === undefined) {
308
- const ids = (yield this.store.list()).map((r) => r.id);
347
+ const ids = (yield this.allRecords()).map((r) => r.id);
309
348
  throw new UnknownReminderError(reminderId, ids);
310
349
  }
350
+ if (opts.expectedFireCount !== undefined &&
351
+ record.fireCount !== opts.expectedFireCount) {
352
+ return {
353
+ reminderId,
354
+ outcome: "noop",
355
+ reason: "stale_fire_count",
356
+ };
357
+ }
311
358
  const result = yield this.fire(record.id, { force: true });
312
359
  return Object.assign({ reminderId }, result);
313
360
  });
@@ -327,7 +374,7 @@ export class ReminderRunner {
327
374
  // Keep recurring reminders alive after unexpected throws.
328
375
  // One-shots stay armed so a failed wake can be retried / dispatched.
329
376
  try {
330
- const current = yield this.store.get(record.id);
377
+ const current = yield this.getRecord(record.id);
331
378
  if (current === undefined || current.status !== "armed")
332
379
  return;
333
380
  const oneShot = current.scheduleKind === "delay" || current.scheduleKind === "at";
@@ -362,7 +409,7 @@ export class ReminderRunner {
362
409
  }
363
410
  this.firing.add(id);
364
411
  try {
365
- const record = yield this.store.get(id);
412
+ const record = yield this.getRecord(id);
366
413
  if (record === undefined || record.status !== "armed") {
367
414
  this.clearTimer(id);
368
415
  return { outcome: "noop", reason: "not_armed" };
@@ -399,7 +446,7 @@ export class ReminderRunner {
399
446
  return { outcome: "fired", reason: "skipped_busy" };
400
447
  }
401
448
  yield this.whenSessionIdle(record.channelId, record.continuationToken);
402
- const still = yield this.store.get(id);
449
+ const still = yield this.getRecord(id);
403
450
  if (still === undefined || still.status !== "armed") {
404
451
  return { outcome: "noop", reason: "disarmed_while_waiting" };
405
452
  }
@@ -417,7 +464,7 @@ export class ReminderRunner {
417
464
  return { outcome: "noop", reason: "missing_handler" };
418
465
  }
419
466
  // Cancel / disarm during the handler must win over reschedule.
420
- const latest = yield this.store.get(id);
467
+ const latest = yield this.getRecord(id);
421
468
  if (result.action === "stop") {
422
469
  if (latest !== undefined && latest.status === "armed") {
423
470
  yield this.disarm(latest, "run_stop");
@@ -590,7 +637,7 @@ export class ReminderRunner {
590
637
  }
591
638
  afterFire(record, _outcome, reschedule) {
592
639
  return __awaiter(this, void 0, void 0, function* () {
593
- const current = yield this.store.get(record.id);
640
+ const current = yield this.getRecord(record.id);
594
641
  if (current === undefined || current.status !== "armed") {
595
642
  return;
596
643
  }
@@ -619,7 +666,9 @@ export class ReminderRunner {
619
666
  ? String(reschedule.delay)
620
667
  : String(reschedule.at), updatedAt: new Date().toISOString() });
621
668
  yield this.persist(updated);
622
- this.armTimer(updated);
669
+ if (this.platformTimers === undefined) {
670
+ this.armTimer(updated);
671
+ }
623
672
  return;
624
673
  }
625
674
  if (oneShot) {
@@ -642,7 +691,9 @@ export class ReminderRunner {
642
691
  }
643
692
  const updated = Object.assign(Object.assign({}, current), { fireCount: current.fireCount + 1, nextFireAtMs, updatedAt: new Date().toISOString() });
644
693
  yield this.persist(updated);
645
- this.armTimer(updated);
694
+ if (this.platformTimers === undefined) {
695
+ this.armTimer(updated);
696
+ }
646
697
  });
647
698
  }
648
699
  }
@@ -1,10 +1,11 @@
1
1
  /**
2
- * Durable reminder instance store under `<stateRoot>/reminders/`.
2
+ * Reminder document store used by the local control plane
3
+ * (`<stateRoot>/control-plane/reminders/`).
3
4
  *
4
5
  * Handlers (`run` / function `until`) are not serializable — they live only
5
- * in the in-memory {@link ReminderRunner} registry. Disk holds schedule,
6
- * prompt, target, and status so one-shots / recurring ticks survive restart
7
- * for prompt-form reminders.
6
+ * in the in-memory {@link ReminderRunner} registry. The control plane holds
7
+ * schedule, prompt, target, and status so prompt-form reminders survive
8
+ * restart.
8
9
  */
9
10
  import type { ReminderBusyPolicy, ReminderScheduleKind, ReminderStatus } from "../types.js";
10
11
  export declare const REMINDER_SNAPSHOT_VERSION: 1;
@@ -1 +1 @@
1
- {"version":3,"file":"reminder-store.d.ts","sourceRoot":"","sources":["../../src/internal/reminder-store.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAWH,OAAO,KAAK,EACV,kBAAkB,EAClB,oBAAoB,EACpB,cAAc,EACf,MAAM,aAAa,CAAC;AAErB,eAAO,MAAM,yBAAyB,EAAG,CAAU,CAAC;AAEpD,YAAY,EACV,kBAAkB,EAClB,oBAAoB,EACpB,cAAc,GACf,MAAM,aAAa,CAAC;AAErB,yDAAyD;AACzD,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,yBAAyB,CAAC;IAC1C,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,SAAS,EAAE,MAAM,CAAC;IAClB,yEAAyE;IACzE,iBAAiB,EAAE,MAAM,CAAC;IAC1B,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,YAAY,EAAE,oBAAoB,CAAC;IACnC,4EAA4E;IAC5E,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,aAAa,EAAE,OAAO,CAAC;IACvB,yEAAyE;IACzE,UAAU,EAAE,OAAO,CAAC;IACpB,+EAA+E;IAC/E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,kBAAkB,CAAC;IAC/B,MAAM,EAAE,cAAc,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,yEAAyE;AACzE,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,cAAc,CAkBxE;AAED,qBAAa,aAAa;IACZ,OAAO,CAAC,QAAQ,CAAC,OAAO;IAApC,YAA6B,OAAO,EAAE,MAAM,EAAI;IAEhD,OAAO,CAAC,QAAQ;IAIV,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAEhC;IAEK,IAAI,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC,CAiBtC;IAEK,SAAS,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC,CAG3C;IAEK,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CAsBzD;IAEK,IAAI,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAYhD;IAEK,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEtC;CACF"}
1
+ {"version":3,"file":"reminder-store.d.ts","sourceRoot":"","sources":["../../src/internal/reminder-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAWH,OAAO,KAAK,EACV,kBAAkB,EAClB,oBAAoB,EACpB,cAAc,EACf,MAAM,aAAa,CAAC;AAErB,eAAO,MAAM,yBAAyB,EAAG,CAAU,CAAC;AAEpD,YAAY,EACV,kBAAkB,EAClB,oBAAoB,EACpB,cAAc,GACf,MAAM,aAAa,CAAC;AAErB,yDAAyD;AACzD,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,yBAAyB,CAAC;IAC1C,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,SAAS,EAAE,MAAM,CAAC;IAClB,yEAAyE;IACzE,iBAAiB,EAAE,MAAM,CAAC;IAC1B,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,YAAY,EAAE,oBAAoB,CAAC;IACnC,4EAA4E;IAC5E,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,aAAa,EAAE,OAAO,CAAC;IACvB,yEAAyE;IACzE,UAAU,EAAE,OAAO,CAAC;IACpB,+EAA+E;IAC/E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,kBAAkB,CAAC;IAC/B,MAAM,EAAE,cAAc,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,yEAAyE;AACzE,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,cAAc,CAkBxE;AAED,qBAAa,aAAa;IACZ,OAAO,CAAC,QAAQ,CAAC,OAAO;IAApC,YAA6B,OAAO,EAAE,MAAM,EAAI;IAEhD,OAAO,CAAC,QAAQ;IAIV,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAEhC;IAEK,IAAI,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC,CAiBtC;IAEK,SAAS,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC,CAG3C;IAEK,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CAsBzD;IAEK,IAAI,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAYhD;IAEK,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEtC;CACF"}
@@ -1,10 +1,11 @@
1
1
  /**
2
- * Durable reminder instance store under `<stateRoot>/reminders/`.
2
+ * Reminder document store used by the local control plane
3
+ * (`<stateRoot>/control-plane/reminders/`).
3
4
  *
4
5
  * Handlers (`run` / function `until`) are not serializable — they live only
5
- * in the in-memory {@link ReminderRunner} registry. Disk holds schedule,
6
- * prompt, target, and status so one-shots / recurring ticks survive restart
7
- * for prompt-form reminders.
6
+ * in the in-memory {@link ReminderRunner} registry. The control plane holds
7
+ * schedule, prompt, target, and status so prompt-form reminders survive
8
+ * restart.
8
9
  */
9
10
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
10
11
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
@@ -1 +1 @@
1
- {"version":3,"file":"sdk-runner.d.ts","sourceRoot":"","sources":["../../src/internal/sdk-runner.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAOL,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,SAAS,EAEf,MAAM,aAAa,CAAC;AACrB,OAAO,EAEL,KAAK,YAAY,EAEjB,KAAK,iBAAiB,EACtB,KAAK,WAAW,EAEjB,MAAM,aAAa,CAAC;AAErB,2EAA2E;AAC3E,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAC1D;;;;;OAKG;IACH,OAAO,CAAC,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IACjE,OAAO,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAED;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG,IAAI,CACrC,iBAAiB,EACf,cAAc,GACd,gBAAgB,GAChB,SAAS,GACT,YAAY,GACZ,WAAW,GACX,OAAO,CACV,CAAC;AAEF,6EAA6E;AAC7E,MAAM,MAAM,cAAc,GACtB;IAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAA;CAAE,GACzB;IAAE,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAcxD,MAAM,WAAW,sBAAsB;IACrC,6EAA6E;IAC7E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,6DAA6D;IAC7D,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC;AAwBD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAKvE;AAED,qBAAa,eAAgB,YAAW,WAAW;IAKrC,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwC;IAC/D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA+C;IACtE,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAkC;IAElE,YAA6B,OAAO,GAAE,sBAA2B,EAAI;IAE/D,OAAO,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,WAAW,CAAC,CAkC9D;YAEa,cAAc;IAyE5B;;;;OAIG;IACG,OAAO,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,cAAc,CAAC,CAepE;IAEK,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAY7B;IAED,OAAO,CAAC,QAAQ;IA0BhB;;;;OAIG;IACH,OAAO,CAAC,UAAU;IASlB,OAAO,CAAC,GAAG;IAIX,OAAO,CAAC,aAAa;IAUrB,OAAO,CAAC,kBAAkB;IAc1B;;;OAGG;YACW,iBAAiB;YAkBjB,SAAS;YAOT,cAAc;YA6Bd,cAAc;IA6C5B,OAAO,CAAC,QAAQ;CAUjB;AAED,4EAA4E;AAC5E,wBAAgB,0BAA0B,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAE9D;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,MAAM,GACd,OAAO,CAMT;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,YAAY,GAAG,cAAc,CAQpE;AAmED,wBAAgB,eAAe,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,GAAG,MAAM,CAExE"}
1
+ {"version":3,"file":"sdk-runner.d.ts","sourceRoot":"","sources":["../../src/internal/sdk-runner.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAOL,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,SAAS,EAEf,MAAM,aAAa,CAAC;AACrB,OAAO,EAEL,KAAK,YAAY,EAEjB,KAAK,iBAAiB,EACtB,KAAK,WAAW,EAEjB,MAAM,aAAa,CAAC;AAGrB,2EAA2E;AAC3E,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAC1D;;;;;OAKG;IACH,OAAO,CAAC,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IACjE,OAAO,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAED;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG,IAAI,CACrC,iBAAiB,EACf,cAAc,GACd,gBAAgB,GAChB,SAAS,GACT,YAAY,GACZ,WAAW,GACX,OAAO,CACV,CAAC;AAEF,6EAA6E;AAC7E,MAAM,MAAM,cAAc,GACtB;IAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAA;CAAE,GACzB;IAAE,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAcxD,MAAM,WAAW,sBAAsB;IACrC,6EAA6E;IAC7E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,6DAA6D;IAC7D,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC;AAwBD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAKvE;AAED,qBAAa,eAAgB,YAAW,WAAW;IAKrC,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwC;IAC/D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA+C;IACtE,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAkC;IAElE,YAA6B,OAAO,GAAE,sBAA2B,EAAI;IAE/D,OAAO,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,WAAW,CAAC,CAkC9D;YAEa,cAAc;IAmF5B;;;;OAIG;IACG,OAAO,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,cAAc,CAAC,CAepE;IAEK,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAY7B;IAED,OAAO,CAAC,QAAQ;IA0BhB;;;;OAIG;IACH,OAAO,CAAC,UAAU;IASlB,OAAO,CAAC,GAAG;IAIX,OAAO,CAAC,aAAa;IAUrB,OAAO,CAAC,kBAAkB;IAc1B;;;OAGG;YACW,iBAAiB;YAkBjB,SAAS;YAOT,cAAc;YA6Bd,cAAc;IA6C5B,OAAO,CAAC,QAAQ;CAUjB;AAED,4EAA4E;AAC5E,wBAAgB,0BAA0B,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAE9D;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,MAAM,GACd,OAAO,CAMT;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,YAAY,GAAG,cAAc,CAQpE;AAwGD,wBAAgB,eAAe,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,GAAG,MAAM,CAExE"}
@@ -17,6 +17,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
17
17
  import { mkdir } from "node:fs/promises";
18
18
  import { Agent, createAgentPlatform, JsonlLocalAgentStore, } from "@cursor/sdk";
19
19
  import { DEFAULT_MODEL, } from "../types.js";
20
+ import { mapSdkTokenUsage, usageTokenSum } from "./cloud-turn-cost.js";
20
21
  /**
21
22
  * How long one SDK agent handle (and the Connect transport inside it) may be
22
23
  * reused before the runner retires it.
@@ -127,7 +128,7 @@ export class CursorSdkRunner {
127
128
  }
128
129
  try {
129
130
  const result = yield run.wait();
130
- const outcome = toTurnOutcome(result);
131
+ let outcome = toTurnOutcome(result);
131
132
  if (outcome.status === "error") {
132
133
  // An error result usually means the handle's transport is poisoned
133
134
  // — most often a cached access token that aged past its 60-minute
@@ -137,6 +138,15 @@ export class CursorSdkRunner {
137
138
  // transport instead of failing every turn until a restart.
138
139
  this.evictAgent(request.sessionId, agentPromise);
139
140
  }
141
+ else if (request.runtime === "cloud" &&
142
+ outcome.status === "finished" &&
143
+ usageTokenSum(outcome.usage) <= 0 &&
144
+ result.id !== "") {
145
+ // Cloud `wait()` drops usage after stream reconnect / getRun replay,
146
+ // or returns an all-zero stub. `getUsage` still has the run's tokens
147
+ // (eventually); without them traces/ABs never record an estimated cost.
148
+ outcome = yield fillMissingCloudUsage(agent, result.id, outcome);
149
+ }
140
150
  return outcome;
141
151
  }
142
152
  finally {
@@ -389,6 +399,39 @@ function toTurnOutcome(result) {
389
399
  ? { errorMessage: runErrorMessage(result) }
390
400
  : {})), (usage === undefined ? {} : { usage }));
391
401
  }
402
+ /** Billing can lag briefly after `wait()`; retry before giving up on cost. */
403
+ const CLOUD_USAGE_RETRY_DELAYS_MS = [0, 400, 1200];
404
+ /**
405
+ * Cloud `wait()` often omits usage after a stream drop. Pull the run's
406
+ * tokens from the usage API so the engine can still estimate cost.
407
+ * Failures are ignored: a missing estimate is better than failing the turn.
408
+ */
409
+ function fillMissingCloudUsage(agent, runId, outcome) {
410
+ return __awaiter(this, void 0, void 0, function* () {
411
+ for (const delayMs of CLOUD_USAGE_RETRY_DELAYS_MS) {
412
+ if (delayMs > 0) {
413
+ yield sleep(delayMs);
414
+ }
415
+ try {
416
+ const billed = yield agent.getUsage({ runId });
417
+ const mapped = mapSdkTokenUsage(billed.usage);
418
+ if (usageTokenSum(mapped) <= 0) {
419
+ continue;
420
+ }
421
+ return Object.assign(Object.assign({}, outcome), { usage: mapped });
422
+ }
423
+ catch (_a) {
424
+ // Transient usage-API failures should still burn the retry budget.
425
+ }
426
+ }
427
+ return outcome;
428
+ });
429
+ }
430
+ function sleep(ms) {
431
+ return new Promise((resolve) => {
432
+ setTimeout(resolve, ms);
433
+ });
434
+ }
392
435
  export function runErrorMessage(result) {
393
436
  var _a, _b;
394
437
  return ((_b = (_a = result.error) === null || _a === void 0 ? void 0 : _a.message) === null || _b === void 0 ? void 0 : _b.trim()) || "The Cursor agent run failed";
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/internal/server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA4BH,OAAO,KAAK,EACV,YAAY,EACZ,gBAAgB,EAOhB,YAAY,EACb,MAAM,aAAa,CAAC;AAqFrB,OAAO,EAAE,KAAK,WAAW,EAAmB,MAAM,iBAAiB,CAAC;AAiBpE,8EAA8E;AAC9E,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,YAAY,CAAC;CACvB;AAYD,6EAA6E;AAC7E,MAAM,WAAW,0BAA0B;IACzC,oEAAoE;IACpE,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,UAAU,EAAE,EACpB,OAAO,GAAE,YAAY,GAAG,0BAA+B,GACtD,OAAO,CAAC,gBAAgB,CAAC,CA4pB3B"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/internal/server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA4BH,OAAO,KAAK,EACV,YAAY,EACZ,gBAAgB,EAOhB,YAAY,EACb,MAAM,aAAa,CAAC;AA8FrB,OAAO,EAAE,KAAK,WAAW,EAAmB,MAAM,iBAAiB,CAAC;AAiBpE,8EAA8E;AAC9E,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,YAAY,CAAC;CACvB;AAaD,6EAA6E;AAC7E,MAAM,WAAW,0BAA0B;IACzC,oEAAoE;IACpE,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,UAAU,EAAE,EACpB,OAAO,GAAE,YAAY,GAAG,0BAA+B,GACtD,OAAO,CAAC,gBAAgB,CAAC,CAsrB3B"}