@salesforce/sfdx-agent-sdk 0.75.0 → 0.76.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/CHANGELOG.md CHANGED
@@ -3,6 +3,11 @@
3
3
  All notable changes to `@salesforce/sfdx-agent-sdk` are documented in this file.
4
4
  Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
5
5
 
6
+ ## [0.76.0] - 2026-09-08
7
+
8
+ ### Features
9
+ - **agent-sdk**: self-describing usage fields on getContextUsage + telemetry @W-24125085@ ([#802](https://github.com/forcedotcom/agentic-dx/pull/802))
10
+
6
11
  ## [0.75.0] - 2026-09-08
7
12
 
8
13
  _No changes — released alongside dependent packages._
package/README.md CHANGED
@@ -725,18 +725,40 @@ type UsageMetadata = {
725
725
 
726
726
  type ContextUsage = {
727
727
  /**
728
- * Last per-step usage reading observed on this session. Pre-first-turn and
729
- * immediately after `clearHistory()` this is `{}` (every token field undefined).
728
+ * Legacy alias for `lastStepUsage` (identical value). Retained so existing
729
+ * callers don't break; new consumers should read `lastStepUsage`. `{}`
730
+ * pre-first-turn / post-`clearHistory()`.
730
731
  */
731
732
  usage: UsageMetadata;
733
+ /**
734
+ * The last model step's usage — the "how full is my context" reading.
735
+ * ≡ `usage`. Always populated; `{}` pre-first-turn / post-`clearHistory()`.
736
+ */
737
+ lastStepUsage: UsageMetadata;
738
+ /**
739
+ * The whole-turn aggregate (`finish.usage`) from the last completed turn — the
740
+ * billing/throughput total. Sums every step and can exceed `contextWindow`, so
741
+ * it is NOT an occupancy reading; read `stepCount` to interpret it. Absent
742
+ * pre-first-turn, after `clearHistory()`, and when the turn produced no
743
+ * `finish.usage`.
744
+ */
745
+ turnUsage?: UsageMetadata;
746
+ /** Model steps in the last completed turn. Absent pre-first-turn / post-`clearHistory()`. */
747
+ stepCount?: number;
732
748
  /** The model's total context-window size in tokens. Always populated. */
733
749
  contextWindow: number;
734
750
  /**
735
- * `(usage.inputTokens + usage.cachedInputTokens + usage.cacheWriteInputTokens) / contextWindow`,
736
- * clamped to [0, 1]. Cached prompt tokens are summed in because they occupy the
737
- * model's context window — on Bedrock-Claude, the bulk of the prompt is reported
738
- * via `cachedInputTokens` / `cacheWriteInputTokens`, not `inputTokens`. `undefined`
739
- * when ALL three input-bearing fields are missing.
751
+ * The raw numerator behind `usedFraction` the last step's effective input
752
+ * `(inputTokens ?? 0) + (cachedInputTokens ?? 0) + (cacheWriteInputTokens ?? 0)`.
753
+ * `undefined` under the same condition as `usedFraction`.
754
+ */
755
+ contextTokens: number | undefined;
756
+ /**
757
+ * `contextTokens / contextWindow`, clamped to [0, 1]. Cached prompt tokens are
758
+ * summed into `contextTokens` because they occupy the model's context window —
759
+ * on Bedrock-Claude, the bulk of the prompt is reported via `cachedInputTokens`
760
+ * / `cacheWriteInputTokens`, not `inputTokens`. `undefined` when ALL three
761
+ * input-bearing fields are missing.
740
762
  */
741
763
  usedFraction: number | undefined;
742
764
  };
@@ -765,9 +787,17 @@ const pct = ctx.usedFraction !== undefined ? `${Math.round(ctx.usedFraction * 10
765
787
  return `${used} / ${limit} tokens (${pct})`;
766
788
  ```
767
789
 
768
- The snapshot uses **last-step** semantics, not the per-turn billing aggregate — `finish.usage` sums all steps in a turn
769
- and double-counts persistent context, which is the wrong denominator for "how full is my context." For per-turn billing
770
- totals, subscribe to `chat-stream-completed` telemetry instead.
790
+ Occupancy (`contextTokens` / `usedFraction`) uses **last-step** semantics, not the per-turn billing aggregate —
791
+ `finish.usage` sums all steps in a turn and double-counts persistent context, which is the wrong denominator for "how
792
+ full is my context." When you do want the per-turn total, read `turnUsage` (and `stepCount` to interpret it) on the same
793
+ snapshot, or subscribe to `chat-stream-completed` telemetry — both carry the identical aggregate.
794
+
795
+ > **`usage` is deprecated.** `usage` still works and is unchanged, but it is marked `@deprecated` (W-24125085) — read
796
+ > the explicit names instead: `lastStepUsage` for occupancy, `turnUsage` + `stepCount` for the per-turn total. The alias
797
+ > points at different measurements per surface, which is exactly the ambiguity the explicit names remove: on
798
+ > `ContextUsage` / the REST `context-usage` response `usage` aliases the **last step**, while on `chat-stream-completed`
799
+ > telemetry it aliases the **whole-turn aggregate**. Removal is gated on a future major once consumers have migrated
800
+ > (W-24125086).
771
801
 
772
802
  ### Error Handling
773
803
 
@@ -193,16 +193,22 @@ export interface ChatSession {
193
193
  /**
194
194
  * Snapshot of how much of the model's context window the most recent
195
195
  * turn used. Always returns a `ContextUsage` — pre-first-turn and
196
- * immediately after `clearHistory()`, `usage` is `{}` and `usedFraction`
197
- * is `undefined`, but `contextWindow` is always populated from the
198
- * agent's currently-bound model.
196
+ * immediately after `clearHistory()`, `usage` / `lastStepUsage` are `{}`,
197
+ * `turnUsage` / `stepCount` are absent, and `usedFraction` / `contextTokens`
198
+ * are `undefined`, but `contextWindow` is always populated from the agent's
199
+ * currently-bound model.
199
200
  *
200
- * `usage` carries the **last per-step** reading from the model the
201
- * size of the prompt the model saw on its most recent invocation,
202
- * which is the right "how full is my context" answer for deciding
203
- * when to call `compactThread()`. This is **not** the per-turn billing
204
- * aggregate; consumers who want billing totals should subscribe to
205
- * `chat-stream-completed` telemetry.
201
+ * Two self-describing measurements (Phase 2, W-24125085), with `usage`
202
+ * retained as the legacy alias for the last-step reading:
203
+ *
204
+ * - **`lastStepUsage`** (≡ `usage`) the **last per-step** reading from the
205
+ * model, the size of the prompt the model saw on its most recent
206
+ * invocation. The right "how full is my context" answer for deciding when
207
+ * to call `compactThread()`; `usedFraction` / `contextTokens` derive from it.
208
+ * - **`turnUsage`** (+ `stepCount`) — the whole-turn billing/throughput
209
+ * aggregate (`finish.usage`). It sums every step and can exceed
210
+ * `contextWindow`, so it is **not** an occupancy reading. Equivalent to the
211
+ * per-turn total on `chat-stream-completed` telemetry.
206
212
  *
207
213
  * The `contextWindow` is read live from the agent's currently-bound
208
214
  * model, so it reflects any `Agent.updateAgentConfig()` model swap
@@ -339,6 +345,19 @@ export declare class DefaultChatSession implements ChatSession {
339
345
  * thread starts unprimed.
340
346
  */
341
347
  private latestUsage;
348
+ /**
349
+ * The whole-turn aggregate (`finish.usage`) and model-step count from the
350
+ * last COMPLETED turn, retained as session state so {@link getContextUsage}
351
+ * can return them as `turnUsage` / `stepCount` (Phase 1 counted `stepCount`
352
+ * as a `wrapEventStream` local; Phase 2, W-24125085, promotes both to
353
+ * session state — mirroring {@link latestUsage}). Set in `wrapEventStream`'s
354
+ * natural-completion branch (never on an errored / abandoned turn), read by
355
+ * `getContextUsage`, and reset by `clearHistory()`. `latestTurnUsage` is
356
+ * `undefined` (not `{}`) pre-first-turn so `turnUsage` is *absent* rather
357
+ * than empty; `latestStepCount` is `0` so `stepCount` is likewise omitted.
358
+ */
359
+ private latestTurnUsage;
360
+ private latestStepCount;
342
361
  private disposed;
343
362
  /**
344
363
  * True while a turn started by {@link chat} is in flight — from the `chat()`
@@ -459,8 +478,10 @@ export declare class DefaultChatSession implements ChatSession {
459
478
  /**
460
479
  * @requirements
461
480
  * - MUST delegate to `this.harness.clearMessages()`, passing `this.agentId` and `this.threadId`.
462
- * - MUST reset `latestUsage` to `{}` so the next `getContextUsage()` reports a fresh
463
- * "no reading yet" snapshot until the next turn produces one.
481
+ * - MUST reset `latestUsage` to `{}` and drop the retained per-turn state
482
+ * (`latestTurnUsage` / `latestStepCount`) so the next `getContextUsage()`
483
+ * reports a fresh "no reading yet" snapshot (`turnUsage` / `stepCount`
484
+ * absent) until the next turn produces one.
464
485
  */
465
486
  clearHistory(): Promise<void>;
466
487
  /**
@@ -72,6 +72,19 @@ export class DefaultChatSession {
72
72
  * thread starts unprimed.
73
73
  */
74
74
  latestUsage = {};
75
+ /**
76
+ * The whole-turn aggregate (`finish.usage`) and model-step count from the
77
+ * last COMPLETED turn, retained as session state so {@link getContextUsage}
78
+ * can return them as `turnUsage` / `stepCount` (Phase 1 counted `stepCount`
79
+ * as a `wrapEventStream` local; Phase 2, W-24125085, promotes both to
80
+ * session state — mirroring {@link latestUsage}). Set in `wrapEventStream`'s
81
+ * natural-completion branch (never on an errored / abandoned turn), read by
82
+ * `getContextUsage`, and reset by `clearHistory()`. `latestTurnUsage` is
83
+ * `undefined` (not `{}`) pre-first-turn so `turnUsage` is *absent* rather
84
+ * than empty; `latestStepCount` is `0` so `stepCount` is likewise omitted.
85
+ */
86
+ latestTurnUsage = undefined;
87
+ latestStepCount = 0;
75
88
  disposed = false;
76
89
  /**
77
90
  * True while a turn started by {@link chat} is in flight — from the `chat()`
@@ -311,12 +324,34 @@ export class DefaultChatSession {
311
324
  }, finishedAt);
312
325
  }
313
326
  else {
327
+ // Retain the turn's aggregate + step count as session state so a later
328
+ // `getContextUsage()` can return `turnUsage` / `stepCount` (the last-step
329
+ // `latestUsage` is already retained per step-finish). Only the natural-
330
+ // completion branch runs this — an errored or abandoned turn leaves the
331
+ // last COMPLETED turn's figures in place, matching the completion log,
332
+ // which is likewise emitted only here. COPY `finishUsage` on retain so the
333
+ // retained state does NOT alias the object the emit sites below forward by
334
+ // reference: otherwise a telemetry/log subscriber mutating the emitted
335
+ // `turnUsage` would corrupt `latestTurnUsage` and surface on a later
336
+ // `getContextUsage()` (which spreads on read, carrying the mutation).
337
+ this.latestTurnUsage = finishUsage === undefined ? undefined : { ...finishUsage };
338
+ this.latestStepCount = stepCount;
314
339
  this.telemetryBus.emitTelemetry({
315
340
  type: 'chat-stream-completed',
316
341
  agentId: this.agentId,
317
342
  threadId: this.threadId,
318
343
  durationMs,
344
+ // Self-describing usage on telemetry (W-24125085, Phase 2): `usage`
345
+ // stays as the legacy alias for the whole-turn aggregate, now also
346
+ // named `turnUsage`; `lastStepUsage` carries the last-step reading
347
+ // (spread so consumer mutation can't leak into retained state); and
348
+ // `stepCount` makes the aggregate interpretable. Omitted-when-absent
349
+ // for `stepCount` only — `usage`/`turnUsage` keep the prior field's
350
+ // always-present shape (both are `finishUsage`, so they stay ≡).
319
351
  usage: finishUsage,
352
+ turnUsage: finishUsage,
353
+ lastStepUsage: { ...this.latestUsage },
354
+ ...(stepCount > 0 ? { stepCount } : {}),
320
355
  }, finishedAt);
321
356
  // Fold the turn's usage + post-turn context-window occupancy onto the
322
357
  // existing completion log so an operator can read both without
@@ -334,11 +369,14 @@ export class DefaultChatSession {
334
369
  // step reports, and `contextUsageLogFields()` stays empty pre-first-turn /
335
370
  // post-`clearHistory()`.
336
371
  //
337
- // `turnUsage` forwards `finishUsage` BY REFERENCE (unlike `lastStepUsage`,
338
- // which spreads `latestUsage`): `finishUsage` is a turn-local value discarded
339
- // when this method returns, so no consumer can observe mutation of it;
340
- // `latestUsage` is retained session state a later `getContextUsage()` reads,
341
- // so it must be copied.
372
+ // Both emit sites (this log and the telemetry event above) forward
373
+ // `turnUsage`/`usage` as `finishUsage` BY REFERENCE. That stays safe because
374
+ // `finishUsage` is a turn-local value discarded when this method returns the
375
+ // retained `latestTurnUsage` is a COPY of it (see above), so it does not alias
376
+ // `finishUsage` and no consumer can corrupt session state by mutating the
377
+ // emitted object. `lastStepUsage` instead spreads `latestUsage` (retained
378
+ // session state a later `getContextUsage()` reads), so it is copied at the
379
+ // emit site.
342
380
  this.logBus.emitLog({
343
381
  level: 'info',
344
382
  message: 'Chat stream completed',
@@ -434,13 +472,17 @@ export class DefaultChatSession {
434
472
  /**
435
473
  * @requirements
436
474
  * - MUST delegate to `this.harness.clearMessages()`, passing `this.agentId` and `this.threadId`.
437
- * - MUST reset `latestUsage` to `{}` so the next `getContextUsage()` reports a fresh
438
- * "no reading yet" snapshot until the next turn produces one.
475
+ * - MUST reset `latestUsage` to `{}` and drop the retained per-turn state
476
+ * (`latestTurnUsage` / `latestStepCount`) so the next `getContextUsage()`
477
+ * reports a fresh "no reading yet" snapshot (`turnUsage` / `stepCount`
478
+ * absent) until the next turn produces one.
439
479
  */
440
480
  async clearHistory() {
441
481
  this.assertNotDisposed();
442
482
  await this.harness.clearMessages(this.agentId, this.threadId);
443
483
  this.latestUsage = {};
484
+ this.latestTurnUsage = undefined;
485
+ this.latestStepCount = 0;
444
486
  }
445
487
  /**
446
488
  * @requirements
@@ -468,15 +510,29 @@ export class DefaultChatSession {
468
510
  getContextUsage() {
469
511
  this.assertNotDisposed();
470
512
  const contextWindow = this.getContextWindow();
471
- const effectiveInputTokens = this.effectiveInputTokens();
472
- const usedFraction = effectiveInputTokens === undefined
473
- ? undefined
474
- : Math.min(1, Math.max(0, effectiveInputTokens / contextWindow));
475
- // Spread `latestUsage` so consumer mutation of the returned `usage`
476
- // object cannot leak back into the session's internal state on a
477
- // subsequent `getContextUsage()` call. `UsageMetadata`'s fields are
478
- // all primitives, so a shallow copy is sufficient.
479
- return { usage: { ...this.latestUsage }, contextWindow, usedFraction };
513
+ const contextTokens = this.effectiveInputTokens();
514
+ const usedFraction = contextTokens === undefined ? undefined : Math.min(1, Math.max(0, contextTokens / contextWindow));
515
+ // Spread `latestUsage` so consumer mutation of the returned object cannot
516
+ // leak back into the session's retained state on a later call. `usage` is
517
+ // the legacy alias for `lastStepUsage` (Phase 2, W-24125085) the SAME
518
+ // object, so a consumer migrating from `usage` reads identical data.
519
+ // `UsageMetadata`'s fields are all primitives, so a shallow copy suffices.
520
+ const lastStepUsage = { ...this.latestUsage };
521
+ return {
522
+ usage: lastStepUsage,
523
+ lastStepUsage,
524
+ contextWindow,
525
+ // `contextTokens` mirrors `usedFraction`'s presence (both `undefined`
526
+ // when the latest reading carries no input-side tokens).
527
+ contextTokens,
528
+ usedFraction,
529
+ // `turnUsage` (spread for the same anti-leak reason) and `stepCount`
530
+ // describe the last COMPLETED turn; omitted pre-first-turn /
531
+ // post-`clearHistory()` and (for `turnUsage`) when the turn produced
532
+ // no `finish.usage`, matching the completion log's omit-when-absent.
533
+ ...(this.latestTurnUsage !== undefined ? { turnUsage: { ...this.latestTurnUsage } } : {}),
534
+ ...(this.latestStepCount > 0 ? { stepCount: this.latestStepCount } : {}),
535
+ };
480
536
  }
481
537
  /**
482
538
  * The last-step context numerator — the sum of all three input-bearing usage
@@ -42,7 +42,31 @@ export type ChatStreamCompletedEvent = Base<'chat-stream-completed'> & {
42
42
  agentId: string;
43
43
  threadId: string;
44
44
  durationMs: number;
45
+ /**
46
+ * @deprecated Use {@link turnUsage} (identical value). `usage` is the
47
+ * ambiguous legacy name — it aliases the *whole-turn aggregate* here but the
48
+ * *last step* on `ContextUsage`, which is exactly the confusion the explicit
49
+ * names remove. Retained so existing telemetry consumers don't break
50
+ * (W-24125085); slated for removal in a future major (W-24125086).
51
+ *
52
+ * The whole-turn aggregate (`finish.usage`).
53
+ */
45
54
  usage?: UsageMetadata;
55
+ /**
56
+ * The whole-turn aggregate (`finish.usage`) — the billing/throughput total.
57
+ * Identical to {@link usage} (the legacy alias). Sums every step; read
58
+ * {@link stepCount} to interpret it.
59
+ */
60
+ turnUsage?: UsageMetadata;
61
+ /**
62
+ * The last model step's usage — the right "how full is my context" reading
63
+ * (the same measurement `ChatSession.getContextUsage()` returns). Carries
64
+ * forward the last reported reading across a usage gap (W-22692131); `{}`
65
+ * only when no step has reported since session start / `clearHistory()`.
66
+ */
67
+ lastStepUsage?: UsageMetadata;
68
+ /** Number of model steps in the turn. Absent when the turn had no reporting step. */
69
+ stepCount?: number;
46
70
  };
47
71
  export type ChatStreamErrorEvent = Base<'chat-stream-error'> & {
48
72
  agentId: string;
@@ -42,20 +42,33 @@ export type UsageMetadata = {
42
42
  * smaller model, or warn the user as the conversation approaches the
43
43
  * model's context limit.
44
44
  *
45
- * `usage` carries the **last per-step** reading from the model —
46
- * specifically the `usage` from the latest `step-finish` event whose `usage`
47
- * was defined. This is the size of the prompt the model saw on its last
48
- * invocation, which is the right "how full is my context" reading. This is
49
- * **not** the per-turn billing aggregate (which sums steps and double-counts
50
- * persistent context). For per-turn billing totals, subscribe to
51
- * `chat-stream-completed` telemetry instead.
45
+ * Two self-describing measurements name the two things a reader might want
46
+ * (Phase 2, W-24125085), and the ambiguous **`usage` is retained as a
47
+ * documented alias** for the last-step reading so no existing consumer breaks:
48
+ *
49
+ * - **`lastStepUsage`** (≡ `usage`) the `usage` from the latest `step-finish`
50
+ * event whose `usage` was defined: the size of the prompt the model saw on
51
+ * its last invocation, the right "how full is my context" reading. New
52
+ * consumers should read `lastStepUsage`; `usage` is the legacy alias.
53
+ * - **`turnUsage`** — the whole-turn aggregate (`finish.usage`): the
54
+ * billing/throughput total. It sums every step and can exceed `contextWindow`,
55
+ * so it is **not** an occupancy reading; read `stepCount` alongside it to
56
+ * interpret its size.
52
57
  *
53
58
  * Field shapes:
54
59
  *
55
- * - `usage` is always populated. Pre-first-turn (or post-`clearHistory()`)
56
- * it is the empty object `{}` — i.e., a `UsageMetadata` whose token fields
57
- * are all `undefined` — making "no reading yet" indistinguishable from
58
- * "harness reported every field as undefined."
60
+ * - `usage` / `lastStepUsage` are always populated (and identical).
61
+ * Pre-first-turn (or post-`clearHistory()`) they are the empty object `{}` —
62
+ * i.e., a `UsageMetadata` whose token fields are all `undefined` — making
63
+ * "no reading yet" indistinguishable from "harness reported every field as
64
+ * undefined."
65
+ * - `turnUsage` and `stepCount` describe the last **completed** turn and are
66
+ * **absent** pre-first-turn, after `clearHistory()`, and (for `turnUsage`)
67
+ * when the completed turn produced no `finish.usage`.
68
+ * - `contextTokens` is the raw numerator behind `usedFraction`; `undefined`
69
+ * under the same condition as `usedFraction`. Added so the SDK exposes the
70
+ * same three occupancy fields (`contextTokens` / `contextWindow` /
71
+ * `usedFraction`) as the completion log.
59
72
  * - `contextWindow` is always populated, contractually. Every `Model`
60
73
  * bound to an `Agent` via `ModelConnectivityInfo.model` must publish a
61
74
  * `contextWindow`; see the `sfdx-agent-sdk` ARCHITECTURE.md Critical
@@ -70,17 +83,56 @@ export type UsageMetadata = {
70
83
  */
71
84
  export type ContextUsage = {
72
85
  /**
73
- * Last per-step usage reading observed on this session. Pre-first-turn
74
- * and immediately after `clearHistory()` this is `{}` (every token field
75
- * undefined).
86
+ * @deprecated Use {@link lastStepUsage} (identical value). `usage` is the
87
+ * ambiguous legacy name it aliases the *last step* here but the *whole-turn
88
+ * aggregate* on `chat-stream-completed` telemetry, which is exactly the
89
+ * confusion the explicit names remove. Retained so existing callers don't
90
+ * break (W-24125085); slated for removal in a future major (W-24125086).
91
+ *
92
+ * Last per-step usage reading. Pre-first-turn and immediately after
93
+ * `clearHistory()` this is `{}` (every token field undefined).
76
94
  */
77
95
  usage: UsageMetadata;
96
+ /**
97
+ * The last model step's usage — the size of the prompt the model saw on its
98
+ * most recent invocation, the right "how full is my context" reading.
99
+ * Identical to {@link usage} (the legacy alias). Always populated; `{}`
100
+ * pre-first-turn / post-`clearHistory()`.
101
+ */
102
+ lastStepUsage: UsageMetadata;
103
+ /**
104
+ * The whole-turn aggregate (`finish.usage`) from the last **completed** turn —
105
+ * the billing/throughput total. It sums every step and can exceed
106
+ * {@link contextWindow}, so read {@link stepCount} to interpret it:
107
+ * `lastStepUsage.inputTokens ≤ turnUsage.inputTokens ≤ lastStepUsage.inputTokens × stepCount`
108
+ * (the lower bound is strict only when `stepCount > 1`). **Absent**
109
+ * pre-first-turn, after `clearHistory()`, and when the completed turn
110
+ * produced no `finish.usage`. This is the value `chat-stream-completed`
111
+ * telemetry carries as its `usage` alias.
112
+ */
113
+ turnUsage?: UsageMetadata;
114
+ /**
115
+ * Number of model steps in the last **completed** turn (counts every step,
116
+ * including one whose `step-finish` reported undefined usage — W-22692131).
117
+ * Makes {@link turnUsage} interpretable next to {@link lastStepUsage}.
118
+ * **Absent** pre-first-turn / post-`clearHistory()`.
119
+ */
120
+ stepCount?: number;
78
121
  /**
79
122
  * The model's total context-window size in tokens. Read live at call
80
123
  * time from the agent's currently-bound `ModelConnectivityInfo.model`,
81
124
  * so it stays correct across `Agent.updateAgentConfig()` model swaps.
82
125
  */
83
126
  contextWindow: number;
127
+ /**
128
+ * The exact numerator behind {@link usedFraction}: the last step's effective
129
+ * input `(inputTokens ?? 0) + (cachedInputTokens ?? 0) + (cacheWriteInputTokens ?? 0)`.
130
+ * `undefined` under the same condition as `usedFraction` (all three
131
+ * input-bearing fields missing on the latest reading). Added in Phase 2
132
+ * (W-24125085) so occupancy reads identically to the completion log's three
133
+ * fields — `contextTokens` / `contextWindow` / `usedFraction`.
134
+ */
135
+ contextTokens: number | undefined;
84
136
  /**
85
137
  * `(usage.inputTokens + usage.cachedInputTokens + usage.cacheWriteInputTokens) /
86
138
  * contextWindow`, clamped to `[0, 1]`. The denominator-numerator includes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/sfdx-agent-sdk",
3
- "version": "0.75.0",
3
+ "version": "0.76.0",
4
4
  "description": "Harness-agnostic agentic infrastructure for Salesforce developer experience tooling",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -48,9 +48,9 @@
48
48
  },
49
49
  "devDependencies": {
50
50
  "@eslint/js": "^10.0.1",
51
- "@salesforce/sfdx-agent-harness-claude": "0.71.0",
52
- "@salesforce/sfdx-agent-harness-mastra": "0.74.0",
53
- "@salesforce/sfdx-agent-harness-openai": "0.40.0",
51
+ "@salesforce/sfdx-agent-harness-claude": "0.72.0",
52
+ "@salesforce/sfdx-agent-harness-mastra": "0.75.0",
53
+ "@salesforce/sfdx-agent-harness-openai": "0.41.0",
54
54
  "@types/node": "^22.20.1",
55
55
  "@vitest/coverage-istanbul": "^4.1.11",
56
56
  "@vitest/eslint-plugin": "^1.6.27",