@dudousxd/nestjs-agent-opencode 0.1.1 → 0.2.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.
package/dist/index.cjs CHANGED
@@ -38,6 +38,8 @@ __export(index_exports, {
38
38
  OpenCodeToolsTokens: () => OpenCodeToolsTokens,
39
39
  OpenCodeTurn: () => OpenCodeTurn,
40
40
  OpenCodeTurns: () => OpenCodeTurns,
41
+ addUsage: () => addUsage,
42
+ emptyUsage: () => emptyUsage,
41
43
  keyValueOpenCodeSessionStore: () => keyValueOpenCodeSessionStore,
42
44
  openCode: () => openCode,
43
45
  openCodeControllers: () => openCodeControllers,
@@ -45,7 +47,8 @@ __export(index_exports, {
45
47
  sessionOf: () => sessionOf,
46
48
  toElicitation: () => toElicitation,
47
49
  toFormAnswer: () => toFormAnswer,
48
- toQuestion: () => toQuestion
50
+ toQuestion: () => toQuestion,
51
+ usageOf: () => usageOf
49
52
  });
50
53
  module.exports = __toCommonJS(index_exports);
51
54
 
@@ -287,6 +290,41 @@ function toFormAnswer(form, answers = {}) {
287
290
  __name(toFormAnswer, "toFormAnswer");
288
291
 
289
292
  // src/turn.ts
293
+ function emptyUsage() {
294
+ return {
295
+ inputTokens: 0,
296
+ outputTokens: 0,
297
+ cacheReadTokens: 0,
298
+ cacheWriteTokens: 0,
299
+ reasoningTokens: 0,
300
+ costUsd: 0
301
+ };
302
+ }
303
+ __name(emptyUsage, "emptyUsage");
304
+ function addUsage(a, b) {
305
+ const x = a ?? emptyUsage();
306
+ const y = b ?? emptyUsage();
307
+ return {
308
+ inputTokens: x.inputTokens + (y.inputTokens ?? 0),
309
+ outputTokens: x.outputTokens + (y.outputTokens ?? 0),
310
+ cacheReadTokens: (x.cacheReadTokens ?? 0) + (y.cacheReadTokens ?? 0),
311
+ cacheWriteTokens: (x.cacheWriteTokens ?? 0) + (y.cacheWriteTokens ?? 0),
312
+ reasoningTokens: (x.reasoningTokens ?? 0) + (y.reasoningTokens ?? 0),
313
+ costUsd: x.costUsd + (y.costUsd ?? 0)
314
+ };
315
+ }
316
+ __name(addUsage, "addUsage");
317
+ function subUsage(a, b) {
318
+ return {
319
+ inputTokens: a.inputTokens - b.inputTokens,
320
+ outputTokens: a.outputTokens - b.outputTokens,
321
+ cacheReadTokens: a.cacheReadTokens - b.cacheReadTokens,
322
+ cacheWriteTokens: a.cacheWriteTokens - b.cacheWriteTokens,
323
+ reasoningTokens: a.reasoningTokens - b.reasoningTokens,
324
+ costUsd: a.costUsd - b.costUsd
325
+ };
326
+ }
327
+ __name(subUsage, "subUsage");
290
328
  var ASK_TOOL_NAME = "ask";
291
329
  var FAILED_STATUSES = /* @__PURE__ */ new Set([
292
330
  "error",
@@ -352,11 +390,11 @@ var OpenCodeTurn = class {
352
390
  hidden = /* @__PURE__ */ new Set();
353
391
  milestones = [];
354
392
  waiting;
355
- usage = {
356
- inputTokens: 0,
357
- outputTokens: 0
358
- };
359
- costUsd;
393
+ /** What this turn object saw spent, and how much of it a milestone already reported. */
394
+ spent = emptyUsage();
395
+ reported = emptyUsage();
396
+ priced = false;
397
+ model;
360
398
  stepOpen = false;
361
399
  sawText = false;
362
400
  separator = false;
@@ -366,6 +404,11 @@ var OpenCodeTurn = class {
366
404
  stepError;
367
405
  constructor(a) {
368
406
  this.a = a;
407
+ this.model = modelOfLabel(a.input.model);
408
+ }
409
+ /** What the run spent so far: carried from before this turn object, plus what it saw. */
410
+ totalUsage() {
411
+ return addUsage(this.a.carried, this.spent);
369
412
  }
370
413
  get sessionId() {
371
414
  return this.a.sessionId;
@@ -448,7 +491,15 @@ var OpenCodeTurn = class {
448
491
  this.chain = this.chain.then(() => ask.kind === "approval" ? this.decided(ask, reply, tell) : this.answered(ask, reply, tell)).then(resolve, reject);
449
492
  });
450
493
  }
451
- reach(milestone) {
494
+ reach(reached) {
495
+ const usage = subUsage(this.spent, this.reported);
496
+ this.reported = {
497
+ ...this.spent
498
+ };
499
+ const milestone = {
500
+ ...reached,
501
+ usage
502
+ };
452
503
  const waiting = this.waiting;
453
504
  if (waiting !== void 0) {
454
505
  this.waiting = void 0;
@@ -604,9 +655,22 @@ var OpenCodeTurn = class {
604
655
  }
605
656
  }
606
657
  async onEvent(e) {
607
- if (this.ended) return;
608
658
  const d = e.data ?? {};
659
+ if (e.type === "session.usage.recorded") {
660
+ await this.usageRecorded(d);
661
+ return;
662
+ }
663
+ if (this.ended) return;
609
664
  switch (e.type) {
665
+ case "session.step.started":
666
+ case "session.model.selected": {
667
+ const model = d.model;
668
+ if (typeof model?.id === "string" && typeof model.providerID === "string") this.model = {
669
+ providerID: model.providerID,
670
+ id: model.id
671
+ };
672
+ return;
673
+ }
610
674
  case "session.text.delta": {
611
675
  const delta = typeof d.delta === "string" ? d.delta : "";
612
676
  if (!delta) return;
@@ -760,41 +824,63 @@ ${delta}` : delta;
760
824
  });
761
825
  }
762
826
  }
763
- async stepEnded(d) {
764
- const usage = {
765
- inputTokens: Number(d.tokens?.input) || 0,
766
- outputTokens: Number(d.tokens?.output) || 0,
767
- ...Number(d.tokens?.cache?.read) ? {
768
- cacheReadTokens: Number(d.tokens.cache.read)
769
- } : {},
770
- ...Number(d.tokens?.cache?.write) ? {
771
- cacheWriteTokens: Number(d.tokens.cache.write)
772
- } : {}
773
- };
774
- const costUsd = typeof d.cost === "number" ? d.cost : void 0;
775
- this.usage.inputTokens += usage.inputTokens;
776
- this.usage.outputTokens += usage.outputTokens;
777
- if (costUsd !== void 0) this.costUsd = (this.costUsd ?? 0) + costUsd;
827
+ modelId() {
828
+ return this.model !== void 0 ? `${this.model.providerID}/${this.model.id}` : this.a.modelLabel;
829
+ }
830
+ /** One model call's usage and cost, into the ledger and the run's total. */
831
+ async spend(d, purpose) {
832
+ const usage = usageOf(d.tokens);
833
+ const reportedCostUsd = typeof d.cost === "number" && Number.isFinite(d.cost) && d.cost >= 0 ? d.cost : void 0;
834
+ const fallback = reportedCostUsd !== void 0 ? {
835
+ costUsd: reportedCostUsd,
836
+ costSource: "provider"
837
+ } : {};
838
+ let cost = fallback;
839
+ if (this.a.priceStep !== void 0) {
840
+ cost = await this.a.priceStep({
841
+ model: this.model,
842
+ usage,
843
+ reportedCostUsd
844
+ }).catch(() => fallback);
845
+ }
846
+ this.spent = addUsage(this.spent, {
847
+ inputTokens: usage.inputTokens,
848
+ outputTokens: usage.outputTokens,
849
+ cacheReadTokens: usage.cacheReadTokens ?? 0,
850
+ cacheWriteTokens: usage.cacheWriteTokens ?? 0,
851
+ reasoningTokens: usage.reasoningTokens ?? 0,
852
+ costUsd: cost.costUsd ?? 0
853
+ });
854
+ if (cost.costUsd !== void 0) this.priced = true;
778
855
  await this.a.store.recordUsage({
779
856
  threadId: this.a.input.threadId,
780
857
  actorRef: this.a.input.actor.id,
781
- modelId: this.a.modelLabel,
782
- purpose: "chat",
858
+ modelId: this.modelId(),
859
+ purpose,
783
860
  usage,
784
- ...costUsd !== void 0 ? {
785
- costUsd
786
- } : {}
861
+ ...cost
787
862
  });
863
+ return {
864
+ usage,
865
+ cost
866
+ };
867
+ }
868
+ /** `session.usage.recorded`: a call OpenCode made besides the steps (the title, a compaction). */
869
+ async usageRecorded(d) {
870
+ await this.spend(d, d.source === "title" ? "title" : "history_summary");
871
+ }
872
+ async stepEnded(d) {
873
+ const { usage, cost } = await this.spend(d, "chat");
788
874
  if (!this.stepOpen) return;
789
875
  this.stepOpen = false;
790
876
  await this.write({
791
877
  kind: "step-finish",
792
878
  usage,
793
- costUsd: costUsd ?? null,
879
+ costUsd: cost.costUsd ?? null,
794
880
  ...this.segment.reasoningMs > 0 ? {
795
881
  reasoningMs: this.segment.reasoningMs
796
882
  } : {},
797
- model: this.a.modelLabel
883
+ model: this.modelId()
798
884
  });
799
885
  }
800
886
  /**
@@ -813,12 +899,7 @@ ${delta}` : delta;
813
899
  content: s.text,
814
900
  runId: this.a.runId,
815
901
  ...final ? {
816
- usage: {
817
- ...this.usage,
818
- ...this.costUsd !== void 0 ? {
819
- costUsd: this.costUsd
820
- } : {}
821
- }
902
+ usage: this.messageUsage()
822
903
  } : {},
823
904
  ...this.a.input.agentName !== void 0 ? {
824
905
  agentName: this.a.input.agentName
@@ -846,6 +927,26 @@ ${delta}` : delta;
846
927
  ]);
847
928
  return message.id;
848
929
  }
930
+ /** The run's usage as its last message carries it: the whole run, cache tokens included. */
931
+ messageUsage() {
932
+ const total = this.totalUsage();
933
+ return {
934
+ inputTokens: total.inputTokens,
935
+ outputTokens: total.outputTokens,
936
+ ...total.cacheReadTokens > 0 ? {
937
+ cacheReadTokens: total.cacheReadTokens
938
+ } : {},
939
+ ...total.cacheWriteTokens > 0 ? {
940
+ cacheWriteTokens: total.cacheWriteTokens
941
+ } : {},
942
+ ...total.reasoningTokens > 0 ? {
943
+ reasoningTokens: total.reasoningTokens
944
+ } : {},
945
+ ...this.priced || (this.a.carried?.costUsd ?? 0) > 0 ? {
946
+ costUsd: total.costUsd
947
+ } : {}
948
+ };
949
+ }
849
950
  /** A request recorded by an earlier process (a turn resumed after a restart). */
850
951
  async alreadyRecorded(id) {
851
952
  return (await this.a.store.toolCallApproval?.(id) ?? null) !== null;
@@ -1215,6 +1316,35 @@ ${delta}` : delta;
1215
1316
  });
1216
1317
  }
1217
1318
  };
1319
+ function modelOfLabel(label) {
1320
+ const slash = label?.indexOf("/") ?? -1;
1321
+ if (label === void 0 || slash <= 0 || slash === label.length - 1) return void 0;
1322
+ return {
1323
+ providerID: label.slice(0, slash),
1324
+ id: label.slice(slash + 1)
1325
+ };
1326
+ }
1327
+ __name(modelOfLabel, "modelOfLabel");
1328
+ function usageOf(tokens) {
1329
+ const n = /* @__PURE__ */ __name((v) => typeof v === "number" && Number.isFinite(v) && v > 0 ? v : 0, "n");
1330
+ const read = n(tokens?.cache?.read);
1331
+ const write = n(tokens?.cache?.write);
1332
+ const reasoning = n(tokens?.reasoning);
1333
+ return {
1334
+ inputTokens: n(tokens?.input) + read + write,
1335
+ outputTokens: n(tokens?.output),
1336
+ ...read > 0 ? {
1337
+ cacheReadTokens: read
1338
+ } : {},
1339
+ ...write > 0 ? {
1340
+ cacheWriteTokens: write
1341
+ } : {},
1342
+ ...reasoning > 0 ? {
1343
+ reasoningTokens: reasoning
1344
+ } : {}
1345
+ };
1346
+ }
1347
+ __name(usageOf, "usageOf");
1218
1348
 
1219
1349
  // src/mcp.ts
1220
1350
  var LOOP_SERVED_KINDS = /* @__PURE__ */ new Set([
@@ -1646,7 +1776,7 @@ var OpenCodeTurns = class {
1646
1776
  spent = /* @__PURE__ */ new Set();
1647
1777
  /** When the tools endpoint was last registered for a location (`server|boot|directory|actor`). */
1648
1778
  toolsIssued = /* @__PURE__ */ new Map();
1649
- constructor(host, sessions, settings, store, sink, deps, registry, skills, memory, queue, toolsTokens2) {
1779
+ constructor(host, sessions, settings, store, sink, deps, registry, skills, memory, queue, toolsTokens2, pricingStore, agentOptions) {
1650
1780
  this.host = host;
1651
1781
  this.sessions = sessions;
1652
1782
  this.settings = settings;
@@ -1658,6 +1788,30 @@ var OpenCodeTurns = class {
1658
1788
  this.memory = memory;
1659
1789
  this.queue = queue;
1660
1790
  this.toolsTokens = toolsTokens2;
1791
+ this.prices = new import_nestjs_agent_core4.ModelPriceResolver({
1792
+ pricingStore,
1793
+ catalog: agentOptions?.priceCatalog,
1794
+ log: {
1795
+ info: /* @__PURE__ */ __name((message) => this.logger.log(message), "info"),
1796
+ warn: /* @__PURE__ */ __name((message) => this.logger.warn(message), "warn")
1797
+ }
1798
+ });
1799
+ }
1800
+ prices;
1801
+ /**
1802
+ * What a model call OpenCode made cost, by the same rule the library's loop records its own steps
1803
+ * at: a reported figure wins, else an estimate off the model's price — see
1804
+ * {@link OpenCodeEngineSettings.cost}.
1805
+ */
1806
+ async priceStep(step) {
1807
+ const { model, usage, reportedCostUsd } = step;
1808
+ const tokens = usage.inputTokens + usage.outputTokens;
1809
+ const reported = reportedCostUsd !== void 0 && (reportedCostUsd > 0 || tokens === 0);
1810
+ if (reported && this.settings.cost !== "estimate") {
1811
+ return (0, import_nestjs_agent_core4.resolveUsageCost)(usage, reportedCostUsd, void 0);
1812
+ }
1813
+ const price = model !== void 0 && tokens > 0 ? await this.prices.priceFor(priceRef(model)) : void 0;
1814
+ return (0, import_nestjs_agent_core4.resolveUsageCost)(usage, price === void 0 ? reportedCostUsd : void 0, price);
1661
1815
  }
1662
1816
  /** The tools server's name in OpenCode. */
1663
1817
  get toolsServer() {
@@ -2247,8 +2401,8 @@ ${body}
2247
2401
  }
2248
2402
  // ---- prompt / observe / reply --------------------------------------------------------------
2249
2403
  /** Start listening to the session (so nothing it says is missed), then send the user message. */
2250
- async prompt(runId, input, handle) {
2251
- const live = await this.ensureLive(runId, input, handle, false);
2404
+ async prompt(runId, input, handle, spent) {
2405
+ const live = await this.ensureLive(runId, input, handle, false, spent);
2252
2406
  try {
2253
2407
  const prompt = await this.host.promptFor?.({
2254
2408
  input,
@@ -2278,9 +2432,12 @@ ${body}
2278
2432
  * Wait for the turn's next milestone. In a process that was not following the turn (a resumed
2279
2433
  * durable run), the turn is rebuilt and first catches up on requests OpenCode raised meanwhile;
2280
2434
  * `session.wait` is the safety net for a terminal event that was missed.
2435
+ *
2436
+ * `spent` is what the run spent before (the sum of the `usage` of its earlier milestones): a turn
2437
+ * rebuilt here starts from it, so the answer it persists carries the whole run's usage.
2281
2438
  */
2282
- async observe(runId, input, handle) {
2283
- const live = await this.ensureLive(runId, input, handle, true);
2439
+ async observe(runId, input, handle, spent) {
2440
+ const live = await this.ensureLive(runId, input, handle, true, spent);
2284
2441
  const { turn, client } = live;
2285
2442
  if (turn.hasMilestone()) return this.reached(runId, input, handle, await turn.next());
2286
2443
  let done = false;
@@ -2319,23 +2476,23 @@ ${body}
2319
2476
  * request is gone with it: a new session is opened, told what the person decided, and prompted
2320
2477
  * to go on.
2321
2478
  */
2322
- async reply(runId, input, handle, ask, reply) {
2479
+ async reply(runId, input, handle, ask, reply, spent) {
2323
2480
  const server = await this.host.server(input.actor);
2324
2481
  if (server.key !== handle.serverKey || server.bootId !== handle.bootId) {
2325
- return this.continueAfterRestart(runId, input, server, ask, reply);
2482
+ return this.continueAfterRestart(runId, input, server, ask, reply, spent);
2326
2483
  }
2327
- const live = await this.ensureLive(runId, input, handle, false);
2484
+ const live = await this.ensureLive(runId, input, handle, false, spent);
2328
2485
  await live.turn.decide(ask, reply);
2329
2486
  return handle;
2330
2487
  }
2331
- async continueAfterRestart(runId, input, server, ask, reply) {
2488
+ async continueAfterRestart(runId, input, server, ask, reply, spent) {
2332
2489
  const approved = "approved" in reply && reply.approved === true;
2333
2490
  const note = ask.kind === "approval" ? approved ? `The user approved the action ${ask.action} you asked permission for. Continue the task.` : `The user did not approve the action ${ask.action}. Continue without it and explain.` : `The user answered your question: ${JSON.stringify("answers" in reply ? reply.answers : {})}. Continue.`;
2334
2491
  const thread = await this.store.getThread(input.threadId);
2335
2492
  const handle = await this.createSession(runId, input, server, thread?.messages ?? [], note);
2336
2493
  await this.refreshInstructions(runId, input, server.client, handle.sessionId);
2337
2494
  this.drop(runId);
2338
- const live = await this.ensureLive(runId, input, handle, false);
2495
+ const live = await this.ensureLive(runId, input, handle, false, spent);
2339
2496
  await live.turn.decide(ask, reply, {
2340
2497
  tellOpenCode: false
2341
2498
  });
@@ -2355,7 +2512,7 @@ ${body}
2355
2512
  sessionID: known.sessionId
2356
2513
  });
2357
2514
  }
2358
- async ensureLive(runId, input, handle, catchUp) {
2515
+ async ensureLive(runId, input, handle, catchUp, spent) {
2359
2516
  const current = this.live.get(runId);
2360
2517
  if (current !== void 0 && current.handle.sessionId === handle.sessionId) return current;
2361
2518
  current?.stop();
@@ -2381,6 +2538,10 @@ ${body}
2381
2538
  } : {}
2382
2539
  }), "approvalFor"),
2383
2540
  modelLabel: input.model ?? "opencode",
2541
+ priceStep: /* @__PURE__ */ __name((step) => this.priceStep(step), "priceStep"),
2542
+ ...spent !== void 0 ? {
2543
+ carried: spent
2544
+ } : {},
2384
2545
  logger: this.logger,
2385
2546
  onGranted: /* @__PURE__ */ __name((action, id) => {
2386
2547
  const grants = this.grants.get(runId) ?? [];
@@ -2427,20 +2588,14 @@ ${body}
2427
2588
  }
2428
2589
  return milestone;
2429
2590
  }
2430
- /** What the run produced, as the host's settle hooks see it. */
2431
- async runResult(runId, input, outcome, durationMs) {
2591
+ /**
2592
+ * What the run produced, as the host's settle hooks see it. `usage` is what the run spent — the
2593
+ * runner's sum of its milestones' usage, which a resumed run reads back from its journal — else
2594
+ * what the turn this process follows saw.
2595
+ */
2596
+ async runResult(runId, input, outcome, durationMs, usage) {
2432
2597
  const thread = await this.store.getThread(input.threadId);
2433
2598
  const messages = (thread?.messages ?? []).filter((m) => m.role === "assistant" && m.runId === runId);
2434
- const usage = {
2435
- inputTokens: 0,
2436
- outputTokens: 0,
2437
- costUsd: 0
2438
- };
2439
- for (const m of messages) {
2440
- usage.inputTokens += m.usage?.inputTokens ?? 0;
2441
- usage.outputTokens += m.usage?.outputTokens ?? 0;
2442
- usage.costUsd += m.usage?.costUsd ?? 0;
2443
- }
2444
2599
  return {
2445
2600
  runId,
2446
2601
  input,
@@ -2485,15 +2640,31 @@ ${body}
2485
2640
  this.logger.warn(`onSettled failed: ${errorText(error, "error")}`);
2486
2641
  }
2487
2642
  }
2488
- /** End the run's stream and bookkeeping for how its execution ended. */
2489
- async settle(runId, input, outcome, durationMs) {
2643
+ /**
2644
+ * What the run spent: the runner's sum of its milestones, or what the turn this process follows
2645
+ * saw (which starts from that sum) when it saw more — a run that failed or was cancelled between
2646
+ * two milestones.
2647
+ */
2648
+ spentBy(runId, spent) {
2649
+ const seen = this.live.get(runId)?.turn.totalUsage();
2650
+ if (spent === void 0) return seen ?? emptyUsage();
2651
+ if (seen === void 0) return spent;
2652
+ const tokens = /* @__PURE__ */ __name((u) => u.inputTokens + u.outputTokens, "tokens");
2653
+ return tokens(seen) > tokens(spent) ? seen : spent;
2654
+ }
2655
+ /**
2656
+ * End the run's stream and bookkeeping for how its execution ended. `spent` is what the run spent
2657
+ * (the sum of its milestones' `usage`); omit → what the turn this process follows saw.
2658
+ */
2659
+ async settle(runId, input, outcome, durationMs, spent) {
2490
2660
  if (outcome.status === "failed") {
2491
- await this.settleFailed(runId, input, outcome.error, durationMs);
2661
+ await this.settleFailed(runId, input, outcome.error, durationMs, spent);
2492
2662
  return;
2493
2663
  }
2664
+ const usage = this.spentBy(runId, spent);
2494
2665
  this.forget(runId);
2495
2666
  const writer = await this.sink.open(runId);
2496
- const result = await this.runResult(runId, input, outcome, durationMs);
2667
+ const result = await this.runResult(runId, input, outcome, durationMs, usage);
2497
2668
  await this.amend(writer, result);
2498
2669
  if (outcome.status === "interrupted") {
2499
2670
  this.logger.log(`agent run ${runId} cancelled`);
@@ -2521,13 +2692,14 @@ ${body}
2521
2692
  }
2522
2693
  await this.settled(result);
2523
2694
  }
2524
- async settleFailed(runId, input, error, durationMs = 0) {
2695
+ async settleFailed(runId, input, error, durationMs = 0, spent) {
2696
+ const usage = this.spentBy(runId, spent);
2525
2697
  this.forget(runId);
2526
2698
  const writer = await this.sink.open(runId);
2527
2699
  const result = await this.runResult(runId, input, {
2528
2700
  status: "failed",
2529
2701
  error
2530
- }, durationMs);
2702
+ }, durationMs, usage);
2531
2703
  const worded = (await this.amend(writer, result)).error;
2532
2704
  const message = worded ?? (0, import_nestjs_agent_core4.streamFailure)(new Error(error)).message;
2533
2705
  this.logger.error(`agent run ${runId} failed: ${error}`);
@@ -2597,6 +2769,10 @@ OpenCodeTurns = _ts_decorate2([
2597
2769
  _ts_param2(9, (0, import_common4.Inject)(import_nestjs_agent.AGENT_CHAT_QUEUE)),
2598
2770
  _ts_param2(10, (0, import_common4.Optional)()),
2599
2771
  _ts_param2(10, (0, import_common4.Inject)(OPENCODE_TOOLS_TOKENS)),
2772
+ _ts_param2(11, (0, import_common4.Optional)()),
2773
+ _ts_param2(11, (0, import_common4.Inject)(import_nestjs_agent_core4.AGENT_PRICING_STORE)),
2774
+ _ts_param2(12, (0, import_common4.Optional)()),
2775
+ _ts_param2(12, (0, import_common4.Inject)(import_nestjs_agent_core4.AGENT_OPTIONS)),
2600
2776
  _ts_metadata2("design:type", Function),
2601
2777
  _ts_metadata2("design:paramtypes", [
2602
2778
  typeof OpenCodeHost === "undefined" ? Object : OpenCodeHost,
@@ -2609,6 +2785,8 @@ OpenCodeTurns = _ts_decorate2([
2609
2785
  typeof SkillsConfig === "undefined" ? Object : SkillsConfig,
2610
2786
  typeof MemoryConfig === "undefined" ? Object : MemoryConfig,
2611
2787
  typeof ChatQueueService === "undefined" ? Object : ChatQueueService,
2788
+ Object,
2789
+ typeof AgentPricingStore === "undefined" ? Object : AgentPricingStore,
2612
2790
  Object
2613
2791
  ])
2614
2792
  ], OpenCodeTurns);
@@ -2651,6 +2829,19 @@ function uiEmitter(scope, push) {
2651
2829
  };
2652
2830
  }
2653
2831
  __name(uiEmitter, "uiEmitter");
2832
+ function priceRef(model) {
2833
+ const aliases = [
2834
+ model.id
2835
+ ];
2836
+ const tail = model.id.slice(model.id.lastIndexOf("/") + 1);
2837
+ if (tail !== model.id && (0, import_nestjs_agent_core4.parseBedrockModelId)(tail) !== void 0) aliases.push(tail);
2838
+ return {
2839
+ modelId: `${model.providerID}/${model.id}`,
2840
+ provider: model.providerID,
2841
+ aliases
2842
+ };
2843
+ }
2844
+ __name(priceRef, "priceRef");
2654
2845
 
2655
2846
  // src/runner.ts
2656
2847
  function _ts_decorate3(decorators, target, key, desc) {
@@ -2752,18 +2943,20 @@ var OpenCodeAgentRunner = class {
2752
2943
  async run(runId, input) {
2753
2944
  const started = Date.now();
2754
2945
  this.inputs.set(runId, input);
2946
+ let spent = emptyUsage();
2755
2947
  try {
2756
2948
  let handle = await this.turns.begin(runId, input);
2757
2949
  if (this.cancelled.has(runId)) throw new import_nestjs_agent_core5.RunCancelledError();
2758
- await this.turns.prompt(runId, input, handle);
2950
+ await this.turns.prompt(runId, input, handle, spent);
2759
2951
  for (; ; ) {
2760
- const milestone = await this.turns.observe(runId, input, handle);
2952
+ const milestone = await this.turns.observe(runId, input, handle, spent);
2953
+ spent = addUsage(spent, milestone.usage);
2761
2954
  if (milestone.kind === "finished") {
2762
- await this.turns.settle(runId, input, milestone.outcome, Date.now() - started);
2955
+ await this.turns.settle(runId, input, milestone.outcome, Date.now() - started, spent);
2763
2956
  return;
2764
2957
  }
2765
2958
  const reply = await this.park(runId, milestone.ask.id, milestone.ask.kind === "approval" ? "approval" : "answers", milestone.timeoutMs);
2766
- handle = await this.turns.reply(runId, input, handle, milestone.ask, reply);
2959
+ handle = await this.turns.reply(runId, input, handle, milestone.ask, reply, spent);
2767
2960
  }
2768
2961
  } catch (error) {
2769
2962
  if (error instanceof import_nestjs_agent_core5.RunCancelledError) {
@@ -2773,7 +2966,7 @@ var OpenCodeAgentRunner = class {
2773
2966
  }, Date.now() - started);
2774
2967
  return;
2775
2968
  }
2776
- await this.turns.settleFailed(runId, input, errorText(error, "the turn failed"));
2969
+ await this.turns.settleFailed(runId, input, errorText(error, "the turn failed"), Date.now() - started);
2777
2970
  } finally {
2778
2971
  this.inputs.delete(runId);
2779
2972
  }
@@ -2926,6 +3119,8 @@ __name(openCodeProviders, "openCodeProviders");
2926
3119
  OpenCodeToolsTokens,
2927
3120
  OpenCodeTurn,
2928
3121
  OpenCodeTurns,
3122
+ addUsage,
3123
+ emptyUsage,
2929
3124
  keyValueOpenCodeSessionStore,
2930
3125
  openCode,
2931
3126
  openCodeControllers,
@@ -2933,6 +3128,7 @@ __name(openCodeProviders, "openCodeProviders");
2933
3128
  sessionOf,
2934
3129
  toElicitation,
2935
3130
  toFormAnswer,
2936
- toQuestion
3131
+ toQuestion,
3132
+ usageOf
2937
3133
  });
2938
3134
  //# sourceMappingURL=index.cjs.map