@salesforce/agentic-common 0.11.0 → 0.13.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,20 @@
3
3
  All notable changes to `@salesforce/agentic-common` are documented in this file.
4
4
  Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
5
5
 
6
+ ## [0.13.0] - 2026-06-24
7
+
8
+ ### Chores
9
+ - update dependencies and disable Mastra PostHog telemetry @W-23054815 ([#619](https://github.com/forcedotcom/agentic-dx/pull/619))
10
+ - **deps-dev**: bump @types/node from 22.19.21 to 22.20.0 in the dev-dependencies group ([#613](https://github.com/forcedotcom/agentic-dx/pull/613))
11
+
12
+ ## [0.12.0] - 2026-06-22
13
+
14
+ ### Features
15
+ - **agentic-common,harnesses**: route HTTPS_PROXY via injectable undici Dispatcher @W-23121596 ([#610](https://github.com/forcedotcom/agentic-dx/pull/610))
16
+
17
+ ### Docs
18
+ - align SDK + agentic-common docs with current public surface (post-PR-#607) ([#608](https://github.com/forcedotcom/agentic-dx/pull/608))
19
+
6
20
  ## [0.11.0] - 2026-06-19
7
21
 
8
22
  ### Features
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Shared primitives and common utilities for the Salesforce agentic DX packages. Provides a typed event bus, clock
4
4
  abstraction, ID generation, error utilities, log record shape, thin log-emit helpers, a Salesforce org connection
5
- interface, and the `JSONWebToken` family used by both the LLM gateway client and the agent-SDK's connectivity resolvers.
5
+ interface, and the `JSONWebToken` family used by the agent-SDK's connectivity resolvers.
6
6
 
7
7
  ## Quick Start
8
8
 
@@ -158,6 +158,30 @@ try {
158
158
  }
159
159
  ```
160
160
 
161
+ ### `resolveProxyDispatcher()` / `createProxyAwareFetch(dispatcher?)`
162
+
163
+ Proxy-routing helpers for Node's `fetch`. `resolveProxyDispatcher()` returns an `undici.EnvHttpProxyAgent` built from
164
+ `HTTPS_PROXY` / `HTTP_PROXY` / `NO_PROXY` env vars (or their lowercase forms — undici honors both casings), or
165
+ `undefined` when none is set. `createProxyAwareFetch(dispatcher?)` returns a `fetch`-compatible function that routes
166
+ outbound calls through the supplied dispatcher via `undici.fetch`; when `dispatcher` is `undefined`, it returns
167
+ `globalThis.fetch` unchanged so the no-proxy path has zero overhead.
168
+
169
+ Designed to be called from harness factories' `create()`; consumers normally don't call them directly. Both production
170
+ harness factories (`MastraHarnessFactory`, `ClaudeHarnessFactory`) build a proxy-aware fetch via these helpers and
171
+ thread it into every in-process HTTP call site (LLM gateway language-model builders + MCP remote transports). No
172
+ `globalThis` mutation.
173
+
174
+ `EnvHttpProxyAgent` captures `HTTPS_PROXY` and `HTTP_PROXY` at construction; `NO_PROXY` is re-evaluated per dispatch.
175
+ Set `HTTPS_PROXY` / `HTTP_PROXY` BEFORE the first `create()` call so the dispatcher snapshot reflects the right values.
176
+
177
+ ```typescript
178
+ import { createProxyAwareFetch, resolveProxyDispatcher } from '@salesforce/agentic-common';
179
+
180
+ const dispatcher = resolveProxyDispatcher();
181
+ const fetchFn = createProxyAwareFetch(dispatcher);
182
+ await fetchFn('https://example.com/v1/things');
183
+ ```
184
+
161
185
  ### `UniqueIDGenerator` / `UUIDGenerator`
162
186
 
163
187
  Interface + default implementation for generating unique identifiers. Tests can inject deterministic implementations.
@@ -258,10 +282,13 @@ function createJWT(options: {
258
282
  // Same fail-fast first-mint behavior, but uses an existing OrgConnection.
259
283
  function createJWTFromConnection(
260
284
  orgConnection: OrgConnection,
261
- options?: { mintingPath?: string; featureId?: string },
285
+ options?: CreateJWTFromConnectionOptions, // { mintingPath?: string; featureId?: string }
262
286
  ): Promise<JSONWebToken>;
263
287
  ```
264
288
 
289
+ `JWTOptions`, `CreateJWTFromConnectionOptions`, `RequiredJWTHeaders`, and `RequiredJWTPayload` are all exported types so
290
+ consumers can name the parameter / generic-instantiation shapes without redeclaring them.
291
+
265
292
  JWT lifecycle log records flow through `onLog`. The token's auto-refresh emits `'Refreshing expired JWT'` (debug),
266
293
  `'JWT refreshed'` (info, with `durationMs`), and `'JWT refresh failed'` (error, with the wrapped exception) so operators
267
294
  have visibility without subscribing to a separate telemetry channel.
@@ -292,12 +319,30 @@ type RetryCallbacks<T> = {
292
319
  isRetryableError?: (err: unknown) => boolean;
293
320
  isRetryableResult?: (result: T) => boolean;
294
321
  getRetryAfterMs?: (result: T) => number | undefined;
295
- onRetry?: (info: { attempt: number; delayMs: number; error?: unknown; result?: T }) => void;
296
- onExhausted?: (info: { attempts: number; error?: unknown; result?: T; reason: 'attempts' | 'deadline' }) => void;
322
+ onRetry?: (info: RetryAttemptInfo<T>) => void;
323
+ onExhausted?: (info: RetryExhaustedInfo<T>) => void;
297
324
  drainResult?: (result: T) => Promise<void>;
298
325
  };
326
+
327
+ type RetryAttemptInfo<T> = {
328
+ attempt: number; // 1-indexed attempt number that just failed
329
+ delayMs: number; // jittered or server-driven delay about to be waited
330
+ error?: unknown; // set if the attempt threw a retryable error
331
+ result?: T; // set if the attempt returned a retryable result
332
+ };
333
+
334
+ type RetryExhaustedInfo<T> = {
335
+ attempts: number; // total attempts made
336
+ error?: unknown;
337
+ result?: T;
338
+ reason: 'attempts' | 'deadline';
339
+ };
299
340
  ```
300
341
 
342
+ The fully-resolved defaults are exported as `DEFAULT_RETRY_OPTIONS`
343
+ (`{ maxAttempts: 3, initialDelayMs: 100, maxDelayMs: 2000, maxRetryAfterMs: 60_000, backoffFactor: 2, maxTotalElapsedMs: Infinity }`)
344
+ so consumers and tests can share one source of truth.
345
+
301
346
  Use `BackoffRetryer` in production:
302
347
 
303
348
  ```typescript
@@ -369,6 +414,20 @@ import { backfillCreatedAt, RealClock } from '@salesforce/agentic-common';
369
414
  const filled = backfillCreatedAt(messages, new RealClock());
370
415
  ```
371
416
 
417
+ ### `buildSummaryPrompt(transcript: string): string`
418
+
419
+ Returns a third-person summarization-prompt string asking the model to compress the supplied transcript into a context
420
+ summary. Used by both production harnesses (`@salesforce/sfdx-agent-harness-mastra` /
421
+ `@salesforce/sfdx-agent-harness-claude`) inside their `compactThread` flows so the prompt wording stays uniform across
422
+ implementations — a freshly-summarized thread reads the same regardless of which harness produced it.
423
+
424
+ ```typescript
425
+ import { buildSummaryPrompt } from '@salesforce/agentic-common';
426
+
427
+ const prompt = buildSummaryPrompt(transcriptText);
428
+ // → "Summarize the following conversation into a concise context summary. ..."
429
+ ```
430
+
372
431
  ## Development
373
432
 
374
433
  See [DEVELOPING.md](../../DEVELOPING.md) for build-from-source setup, scripts, and monorepo commands.
package/dist/index.d.ts CHANGED
@@ -5,6 +5,7 @@ export { type OrgConnectionFactory, RealOrgConnectionFactory } from './connectio
5
5
  export { getErrorMessage, getErrorMessageWithStack, isAbortError, wrapError } from './error-utils.js';
6
6
  export { EventBus, type EventListener, type SubscriberPresenceListener, type Unsubscribe } from './event-bus.js';
7
7
  export { type UniqueIDGenerator, UUIDGenerator } from './id-generator.js';
8
+ export { createProxyAwareFetch, resolveProxyDispatcher } from './proxy-dispatcher.js';
8
9
  export { type CreateJWTFromConnectionOptions, createJWT, createJWTFromConnection, DynamicJSONWebToken, FixedJSONWebToken, type JSONWebToken, type JWTOptions, type RequiredJWTHeaders, type RequiredJWTPayload, } from './jwt.js';
9
10
  export { LogBus, type LogLevel, type LogRecord } from './log.js';
10
11
  export { type FrontmatterSplit, splitFrontmatterAndBody } from './markdown-frontmatter.js';
package/dist/index.js CHANGED
@@ -9,6 +9,7 @@ export { RealOrgConnectionFactory } from './connection-factory.js';
9
9
  export { getErrorMessage, getErrorMessageWithStack, isAbortError, wrapError } from './error-utils.js';
10
10
  export { EventBus } from './event-bus.js';
11
11
  export { UUIDGenerator } from './id-generator.js';
12
+ export { createProxyAwareFetch, resolveProxyDispatcher } from './proxy-dispatcher.js';
12
13
  export { createJWT, createJWTFromConnection, DynamicJSONWebToken, FixedJSONWebToken, } from './jwt.js';
13
14
  export { LogBus } from './log.js';
14
15
  export { splitFrontmatterAndBody } from './markdown-frontmatter.js';
@@ -0,0 +1,39 @@
1
+ import { Dispatcher } from 'undici';
2
+ /**
3
+ * Resolves a `Dispatcher` from `HTTPS_PROXY` / `HTTP_PROXY` / `NO_PROXY` env
4
+ * vars (either casing — undici honors both), or `undefined` when none is set.
5
+ *
6
+ * `EnvHttpProxyAgent` reads `HTTPS_PROXY` and `HTTP_PROXY` at construction and
7
+ * pins them for the dispatcher's lifetime; `NO_PROXY` is re-evaluated per
8
+ * dispatch (see undici v8.5 source: `#noProxyChanged` / `#noProxyEnv`). Callers
9
+ * must set `HTTPS_PROXY` / `HTTP_PROXY` BEFORE invoking this function; later
10
+ * mutations of those two are not picked up by the returned dispatcher.
11
+ *
12
+ * Returning `undefined` when no proxy env is set preserves the zero-wrap fast
13
+ * path in `createProxyAwareFetch` — `globalThis.fetch` is returned unchanged.
14
+ * Constructing an `EnvHttpProxyAgent` unconditionally would push every
15
+ * no-proxy harness through the undici-fetch wrapper.
16
+ *
17
+ * Designed to be called from harness factories' `create()` to derive a default
18
+ * proxy-aware dispatcher per harness instance.
19
+ */
20
+ export declare function resolveProxyDispatcher(): Dispatcher | undefined;
21
+ /**
22
+ * Returns a `fetch`-compatible function that routes through `dispatcher` (via
23
+ * `undici.fetch`). When `dispatcher` is `undefined`, returns `globalThis.fetch`
24
+ * unchanged so the no-proxy path has zero overhead and no undici-wrapper
25
+ * shape leaks into the call site.
26
+ *
27
+ * Composes with the harness fetch wrappers (`createGatewayFetch`,
28
+ * `createAuthFetch`): those wrappers add per-request header merging on top
29
+ * of whatever inner `fetch` they're handed. Routing the inner fetch through
30
+ * an undici `Dispatcher` is what makes `HTTPS_PROXY` honoring happen — without
31
+ * any process-wide `setGlobalDispatcher` mutation.
32
+ *
33
+ * Verified against the SDKs we hand a `fetch` option to today
34
+ * (`@anthropic-ai/sdk`, `@anthropic-ai/bedrock-sdk`, `openai`, `@mastra/mcp`
35
+ * via `@modelcontextprotocol/sdk` `StreamableHTTPClientTransport`): every
36
+ * outbound HTTP call (including streaming SSE) routes through the injected
37
+ * `fetch`. See PR #609 for the SDK source-trace findings.
38
+ */
39
+ export declare function createProxyAwareFetch(dispatcher?: Dispatcher): typeof fetch;
@@ -0,0 +1,63 @@
1
+ /*
2
+ * Copyright 2026, Salesforce, Inc. All rights reserved.
3
+ * See LICENSE.txt for license terms.
4
+ */
5
+ import { Dispatcher, EnvHttpProxyAgent, fetch as undiciFetch } from 'undici';
6
+ /**
7
+ * Resolves a `Dispatcher` from `HTTPS_PROXY` / `HTTP_PROXY` / `NO_PROXY` env
8
+ * vars (either casing — undici honors both), or `undefined` when none is set.
9
+ *
10
+ * `EnvHttpProxyAgent` reads `HTTPS_PROXY` and `HTTP_PROXY` at construction and
11
+ * pins them for the dispatcher's lifetime; `NO_PROXY` is re-evaluated per
12
+ * dispatch (see undici v8.5 source: `#noProxyChanged` / `#noProxyEnv`). Callers
13
+ * must set `HTTPS_PROXY` / `HTTP_PROXY` BEFORE invoking this function; later
14
+ * mutations of those two are not picked up by the returned dispatcher.
15
+ *
16
+ * Returning `undefined` when no proxy env is set preserves the zero-wrap fast
17
+ * path in `createProxyAwareFetch` — `globalThis.fetch` is returned unchanged.
18
+ * Constructing an `EnvHttpProxyAgent` unconditionally would push every
19
+ * no-proxy harness through the undici-fetch wrapper.
20
+ *
21
+ * Designed to be called from harness factories' `create()` to derive a default
22
+ * proxy-aware dispatcher per harness instance.
23
+ */
24
+ export function resolveProxyDispatcher() {
25
+ if (!process.env['HTTPS_PROXY'] &&
26
+ !process.env['HTTP_PROXY'] &&
27
+ !process.env['https_proxy'] &&
28
+ !process.env['http_proxy']) {
29
+ return undefined;
30
+ }
31
+ return new EnvHttpProxyAgent();
32
+ }
33
+ /**
34
+ * Returns a `fetch`-compatible function that routes through `dispatcher` (via
35
+ * `undici.fetch`). When `dispatcher` is `undefined`, returns `globalThis.fetch`
36
+ * unchanged so the no-proxy path has zero overhead and no undici-wrapper
37
+ * shape leaks into the call site.
38
+ *
39
+ * Composes with the harness fetch wrappers (`createGatewayFetch`,
40
+ * `createAuthFetch`): those wrappers add per-request header merging on top
41
+ * of whatever inner `fetch` they're handed. Routing the inner fetch through
42
+ * an undici `Dispatcher` is what makes `HTTPS_PROXY` honoring happen — without
43
+ * any process-wide `setGlobalDispatcher` mutation.
44
+ *
45
+ * Verified against the SDKs we hand a `fetch` option to today
46
+ * (`@anthropic-ai/sdk`, `@anthropic-ai/bedrock-sdk`, `openai`, `@mastra/mcp`
47
+ * via `@modelcontextprotocol/sdk` `StreamableHTTPClientTransport`): every
48
+ * outbound HTTP call (including streaming SSE) routes through the injected
49
+ * `fetch`. See PR #609 for the SDK source-trace findings.
50
+ */
51
+ export function createProxyAwareFetch(dispatcher) {
52
+ if (!dispatcher)
53
+ return globalThis.fetch;
54
+ // Cast at the boundary: Node's `fetch` and undici's `fetch` have structurally-
55
+ // identical RequestInfo / Response shapes but TS treats them as distinct nominal
56
+ // types. Casting via `unknown` keeps the consumer-facing signature as
57
+ // `typeof fetch` (the WHATWG/Node type) while routing through undici under it.
58
+ return (input, init) => undiciFetch(input, {
59
+ ...init,
60
+ dispatcher,
61
+ });
62
+ }
63
+ //# sourceMappingURL=proxy-dispatcher.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/agentic-common",
3
- "version": "0.11.0",
3
+ "version": "0.13.0",
4
4
  "description": "Shared primitives and common utilities for the Salesforce agentic DX packages",
5
5
  "type": "module",
6
6
  "exports": {
@@ -30,11 +30,12 @@
30
30
  "LICENSE.txt"
31
31
  ],
32
32
  "dependencies": {
33
- "@salesforce/core": "^8.31.1"
33
+ "@salesforce/core": "^8.31.1",
34
+ "undici": "^8.5.0"
34
35
  },
35
36
  "devDependencies": {
36
37
  "@eslint/js": "^10.0.1",
37
- "@types/node": "^22.19.21",
38
+ "@types/node": "^22.20.0",
38
39
  "@vitest/coverage-istanbul": "^4.1.8",
39
40
  "@vitest/eslint-plugin": "^1.6.20",
40
41
  "eslint": "^10.5.0",
@@ -51,7 +52,7 @@
51
52
  "vitest": "^4.1.8"
52
53
  },
53
54
  "engines": {
54
- "node": ">=22.19.0"
55
+ "node": ">=22.22.0"
55
56
  },
56
57
  "lint-staged": {
57
58
  "*.{js,jsx,ts,tsx,json,md}": [