@salesforce/sfdx-agent-sdk 0.73.0 → 0.75.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 +12 -0
- package/dist/chat-session.d.ts +12 -7
- package/dist/chat-session.js +63 -27
- package/package.json +7 -7
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,18 @@
|
|
|
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.75.0] - 2026-09-08
|
|
7
|
+
|
|
8
|
+
_No changes — released alongside dependent packages._
|
|
9
|
+
|
|
10
|
+
## [0.74.0] - 2026-09-08
|
|
11
|
+
|
|
12
|
+
### Features
|
|
13
|
+
- **agent-sdk**: self-describing usage fields on chat-stream-completed log @W-24125082@ ([#800](https://github.com/forcedotcom/agentic-dx/pull/800))
|
|
14
|
+
|
|
15
|
+
### Chores
|
|
16
|
+
- **deps-dev**: bump the dev-dependencies group with 3 updates ([#795](https://github.com/forcedotcom/agentic-dx/pull/795))
|
|
17
|
+
|
|
6
18
|
## [0.73.0] - 2026-09-04
|
|
7
19
|
|
|
8
20
|
### Features
|
package/dist/chat-session.d.ts
CHANGED
|
@@ -498,13 +498,18 @@ export declare class DefaultChatSession implements ChatSession {
|
|
|
498
498
|
*/
|
|
499
499
|
private effectiveInputTokens;
|
|
500
500
|
/**
|
|
501
|
-
*
|
|
502
|
-
*
|
|
503
|
-
*
|
|
504
|
-
* (
|
|
505
|
-
*
|
|
506
|
-
*
|
|
507
|
-
* `
|
|
501
|
+
* Last-step usage + compact context-window occupancy for the
|
|
502
|
+
* `chat-stream-completed` log record: the last model step's full usage
|
|
503
|
+
* (`lastStepUsage`), the token amount that occupies the window
|
|
504
|
+
* (`contextTokens` — the last-step effective input), the window it is out of
|
|
505
|
+
* (`contextWindow`), and the occupancy ratio as a 0–1 float (`usedFraction`).
|
|
506
|
+
* `usedFraction` matches the SDK/service occupancy ratio exactly — the log no
|
|
507
|
+
* longer emits the redundant, lossy `contextUsedPercent` (a consumer wanting a
|
|
508
|
+
* percent computes `round(usedFraction * 100)`) (W-24125082, Phase 1). Empty
|
|
509
|
+
* when the turn reported no input-side usage, so the completion log stays
|
|
510
|
+
* unchanged pre-first-turn / post-`clearHistory()`. Shares
|
|
511
|
+
* {@link getContextUsage}'s last-step numerator via {@link effectiveInputTokens},
|
|
512
|
+
* read from the same `latestUsage` snapshot `wrapEventStream` captures.
|
|
508
513
|
*/
|
|
509
514
|
private contextUsageLogFields;
|
|
510
515
|
/**
|
package/dist/chat-session.js
CHANGED
|
@@ -202,22 +202,36 @@ export class DefaultChatSession {
|
|
|
202
202
|
let sawFinish = false;
|
|
203
203
|
let lastError;
|
|
204
204
|
let finishUsage;
|
|
205
|
+
// Count model steps in the turn so the completion log's `turnUsage`
|
|
206
|
+
// (the whole-turn aggregate) is interpretable next to `lastStepUsage`:
|
|
207
|
+
// lastStepUsage.inputTokens ≤ turnUsage.inputTokens ≤ lastStepUsage.inputTokens × stepCount
|
|
208
|
+
// The lower bound is strict (<) only when stepCount > 1; a single-step
|
|
209
|
+
// turn's aggregate equals its one step. `stepCount` counts EVERY model
|
|
210
|
+
// step, including one whose `step-finish` reported undefined usage
|
|
211
|
+
// (W-22692131) — in that gap case `lastStepUsage` carries forward the last
|
|
212
|
+
// reporting step, so the upper bound just carries extra slack.
|
|
213
|
+
let stepCount = 0;
|
|
205
214
|
try {
|
|
206
215
|
for await (const event of stream) {
|
|
207
216
|
this.chatEventBus.emit(event);
|
|
208
217
|
this.deriveToolTelemetry(event);
|
|
209
218
|
yield event;
|
|
210
|
-
if (event.type === 'step-finish'
|
|
211
|
-
//
|
|
212
|
-
//
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
219
|
+
if (event.type === 'step-finish') {
|
|
220
|
+
// Every step-finish is one model step; count it for the log's
|
|
221
|
+
// `stepCount` regardless of whether this step reported usage.
|
|
222
|
+
stepCount++;
|
|
223
|
+
if (event.usage !== undefined) {
|
|
224
|
+
// Snapshot the most recent per-step usage. Last-step semantics
|
|
225
|
+
// (not the per-turn `finish.usage` aggregate) — `finish.usage`
|
|
226
|
+
// sums every step inside the turn and double-counts persistent
|
|
227
|
+
// context, which is the wrong denominator for "how full is my
|
|
228
|
+
// context". An undefined usage on this step is intentionally
|
|
229
|
+
// ignored so the prior reading is carried forward — gateway-side
|
|
230
|
+
// gaps are rare but real (W-22692131) and clobbering with
|
|
231
|
+
// undefined would surface as a transient hole consumers can't
|
|
232
|
+
// distinguish from a fresh session.
|
|
233
|
+
this.latestUsage = event.usage;
|
|
234
|
+
}
|
|
221
235
|
}
|
|
222
236
|
if (event.type === 'finish') {
|
|
223
237
|
sawFinish = true;
|
|
@@ -304,13 +318,27 @@ export class DefaultChatSession {
|
|
|
304
318
|
durationMs,
|
|
305
319
|
usage: finishUsage,
|
|
306
320
|
}, finishedAt);
|
|
307
|
-
// Fold the post-turn context-window occupancy onto the
|
|
308
|
-
// completion log
|
|
309
|
-
//
|
|
310
|
-
//
|
|
311
|
-
//
|
|
312
|
-
//
|
|
313
|
-
//
|
|
321
|
+
// Fold the turn's usage + post-turn context-window occupancy onto the
|
|
322
|
+
// existing completion log so an operator can read both without
|
|
323
|
+
// subscribing to telemetry or adding a noisier log line. The two
|
|
324
|
+
// measurements carry self-describing names (W-24125082, Phase 1):
|
|
325
|
+
// - `turnUsage` — the whole-turn aggregate (`finish.usage`), the
|
|
326
|
+
// billing/throughput total; sums every step and can exceed the window.
|
|
327
|
+
// - `lastStepUsage` + the occupancy fields — the last model step, the
|
|
328
|
+
// right "how full is my context" reading (see contextUsageLogFields).
|
|
329
|
+
// - `stepCount` — makes `turnUsage` interpretable next to `lastStepUsage`.
|
|
330
|
+
// The ambiguous `usage` field is intentionally NOT emitted (the log is the
|
|
331
|
+
// free, unshipped surface — no alias needed; carrying a third duplicate
|
|
332
|
+
// object would only bloat every record). Both blocks preserve today's
|
|
333
|
+
// omit-when-absent behavior: `turnUsage`/`stepCount` are omitted before any
|
|
334
|
+
// step reports, and `contextUsageLogFields()` stays empty pre-first-turn /
|
|
335
|
+
// post-`clearHistory()`.
|
|
336
|
+
//
|
|
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.
|
|
314
342
|
this.logBus.emitLog({
|
|
315
343
|
level: 'info',
|
|
316
344
|
message: 'Chat stream completed',
|
|
@@ -319,7 +347,8 @@ export class DefaultChatSession {
|
|
|
319
347
|
agentId: this.agentId,
|
|
320
348
|
threadId: this.threadId,
|
|
321
349
|
durationMs,
|
|
322
|
-
...(finishUsage !== undefined ? {
|
|
350
|
+
...(finishUsage !== undefined ? { turnUsage: finishUsage } : {}),
|
|
351
|
+
...(stepCount > 0 ? { stepCount } : {}),
|
|
323
352
|
...this.contextUsageLogFields(),
|
|
324
353
|
},
|
|
325
354
|
}, finishedAt);
|
|
@@ -466,13 +495,18 @@ export class DefaultChatSession {
|
|
|
466
495
|
return (inputTokens ?? 0) + (cachedInputTokens ?? 0) + (cacheWriteInputTokens ?? 0);
|
|
467
496
|
}
|
|
468
497
|
/**
|
|
469
|
-
*
|
|
470
|
-
*
|
|
471
|
-
*
|
|
472
|
-
* (
|
|
473
|
-
*
|
|
474
|
-
*
|
|
475
|
-
* `
|
|
498
|
+
* Last-step usage + compact context-window occupancy for the
|
|
499
|
+
* `chat-stream-completed` log record: the last model step's full usage
|
|
500
|
+
* (`lastStepUsage`), the token amount that occupies the window
|
|
501
|
+
* (`contextTokens` — the last-step effective input), the window it is out of
|
|
502
|
+
* (`contextWindow`), and the occupancy ratio as a 0–1 float (`usedFraction`).
|
|
503
|
+
* `usedFraction` matches the SDK/service occupancy ratio exactly — the log no
|
|
504
|
+
* longer emits the redundant, lossy `contextUsedPercent` (a consumer wanting a
|
|
505
|
+
* percent computes `round(usedFraction * 100)`) (W-24125082, Phase 1). Empty
|
|
506
|
+
* when the turn reported no input-side usage, so the completion log stays
|
|
507
|
+
* unchanged pre-first-turn / post-`clearHistory()`. Shares
|
|
508
|
+
* {@link getContextUsage}'s last-step numerator via {@link effectiveInputTokens},
|
|
509
|
+
* read from the same `latestUsage` snapshot `wrapEventStream` captures.
|
|
476
510
|
*/
|
|
477
511
|
contextUsageLogFields() {
|
|
478
512
|
const contextTokens = this.effectiveInputTokens();
|
|
@@ -480,9 +514,11 @@ export class DefaultChatSession {
|
|
|
480
514
|
return {};
|
|
481
515
|
const contextWindow = this.getContextWindow();
|
|
482
516
|
return {
|
|
517
|
+
// Spread so a later `getContextUsage()` reader can't observe log-side mutation.
|
|
518
|
+
lastStepUsage: { ...this.latestUsage },
|
|
483
519
|
contextTokens,
|
|
484
520
|
contextWindow,
|
|
485
|
-
|
|
521
|
+
usedFraction: Math.min(1, Math.max(0, contextTokens / contextWindow)),
|
|
486
522
|
};
|
|
487
523
|
}
|
|
488
524
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforce/sfdx-agent-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.75.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.
|
|
52
|
-
"@salesforce/sfdx-agent-harness-mastra": "0.
|
|
53
|
-
"@salesforce/sfdx-agent-harness-openai": "0.
|
|
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",
|
|
54
54
|
"@types/node": "^22.20.1",
|
|
55
55
|
"@vitest/coverage-istanbul": "^4.1.11",
|
|
56
56
|
"@vitest/eslint-plugin": "^1.6.27",
|
|
@@ -60,12 +60,12 @@
|
|
|
60
60
|
"eslint-plugin-import": "^2.32.0",
|
|
61
61
|
"eslint-plugin-n": "^18.3.0",
|
|
62
62
|
"globals": "^17.12.0",
|
|
63
|
-
"lint-staged": "^17.
|
|
63
|
+
"lint-staged": "^17.4.1",
|
|
64
64
|
"prettier": "^3.9.6",
|
|
65
65
|
"rimraf": "^6.1.3",
|
|
66
|
-
"tsx": "^4.23.
|
|
66
|
+
"tsx": "^4.23.13",
|
|
67
67
|
"typescript": "^7.0.2",
|
|
68
|
-
"typescript-eslint": "^8.
|
|
68
|
+
"typescript-eslint": "^8.69.0",
|
|
69
69
|
"vitest": "^4.1.11"
|
|
70
70
|
},
|
|
71
71
|
"engines": {
|