@salesforce/sfdx-agent-harness-openai 0.0.1

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 (53) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/LICENSE.txt +21 -0
  3. package/README.md +55 -0
  4. package/dist/gen-sink.d.ts +8 -0
  5. package/dist/gen-sink.js +13 -0
  6. package/dist/gen-sink.js.map +1 -0
  7. package/dist/index.d.ts +3 -0
  8. package/dist/index.js +16 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/mcp-error-classifier.d.ts +36 -0
  11. package/dist/mcp-error-classifier.js +166 -0
  12. package/dist/mcp-error-classifier.js.map +1 -0
  13. package/dist/openai-agents-harness-factory.d.ts +36 -0
  14. package/dist/openai-agents-harness-factory.js +39 -0
  15. package/dist/openai-agents-harness-factory.js.map +1 -0
  16. package/dist/openai-agents-harness.d.ts +302 -0
  17. package/dist/openai-agents-harness.js +1014 -0
  18. package/dist/openai-agents-harness.js.map +1 -0
  19. package/dist/openai-approval-coordinator.d.ts +231 -0
  20. package/dist/openai-approval-coordinator.js +422 -0
  21. package/dist/openai-approval-coordinator.js.map +1 -0
  22. package/dist/openai-built-in-policies.d.ts +29 -0
  23. package/dist/openai-built-in-policies.js +33 -0
  24. package/dist/openai-built-in-policies.js.map +1 -0
  25. package/dist/openai-event-adapter.d.ts +119 -0
  26. package/dist/openai-event-adapter.js +322 -0
  27. package/dist/openai-event-adapter.js.map +1 -0
  28. package/dist/openai-mcp-config-mapper.d.ts +58 -0
  29. package/dist/openai-mcp-config-mapper.js +133 -0
  30. package/dist/openai-mcp-config-mapper.js.map +1 -0
  31. package/dist/openai-mcp-state.d.ts +67 -0
  32. package/dist/openai-mcp-state.js +6 -0
  33. package/dist/openai-mcp-state.js.map +1 -0
  34. package/dist/openai-message-mapper.d.ts +79 -0
  35. package/dist/openai-message-mapper.js +374 -0
  36. package/dist/openai-message-mapper.js.map +1 -0
  37. package/dist/openai-model-provider.d.ts +46 -0
  38. package/dist/openai-model-provider.js +144 -0
  39. package/dist/openai-model-provider.js.map +1 -0
  40. package/dist/openai-session-store.d.ts +149 -0
  41. package/dist/openai-session-store.js +328 -0
  42. package/dist/openai-session-store.js.map +1 -0
  43. package/dist/openai-tool-mapper.d.ts +121 -0
  44. package/dist/openai-tool-mapper.js +231 -0
  45. package/dist/openai-tool-mapper.js.map +1 -0
  46. package/dist/openai-tool-redaction.d.ts +55 -0
  47. package/dist/openai-tool-redaction.js +82 -0
  48. package/dist/openai-tool-redaction.js.map +1 -0
  49. package/dist/test/tsconfig.tsbuildinfo +1 -0
  50. package/dist/text-stream.d.ts +30 -0
  51. package/dist/text-stream.js +103 -0
  52. package/dist/text-stream.js.map +1 -0
  53. package/package.json +66 -0
@@ -0,0 +1,422 @@
1
+ /*
2
+ * Copyright 2026, Salesforce, Inc. All rights reserved.
3
+ * See LICENSE.txt for license terms.
4
+ */
5
+ import { MaxTurnsExceededError, } from '@openai/agents';
6
+ import { isAbortError } from '@salesforce/agentic-common';
7
+ import { AgentSDKError, AgentSDKErrorType, } from '@salesforce/sfdx-agent-sdk';
8
+ import { GenSink } from '@salesforce/sfdx-agent-sdk/harness';
9
+ import { OpenAIEventAdapter } from './openai-event-adapter.js';
10
+ import { teeTextStream } from './text-stream.js';
11
+ /** Default per-`toolCallId` approval timeout — mirrors both sibling harnesses (10 min). */
12
+ const DEFAULT_TOOL_APPROVAL_TIMEOUT_MS = 600_000;
13
+ /**
14
+ * Owns one chat turn's lifecycle for a single `(agentId, threadId)`: the
15
+ * `@openai/agents` run(s), the per-turn `OpenAIEventAdapter`, the
16
+ * `GenSink<ChatEvent>` the consumer iterates, the approval settle ledgers, and a
17
+ * single teardown path.
18
+ *
19
+ * **Suspend / resume.** `@openai/agents` surfaces tool approvals as a batch of
20
+ * `result.interruptions` (`RunToolApprovalItem[]`) on the COMPLETED streamed run
21
+ * — not as a mid-stream event — and resumes via a FRESH `run(agent, state)`. So
22
+ * the pump is a loop: drain a run onto the sink, and if it completed with
23
+ * interruptions, settle each (policy `allow` ⇒ silent `state.approve`; `deny` ⇒
24
+ * silent `state.reject` with a denial message the model sees natively via a real
25
+ * `function_call_result`, no synthesized tool-result; `require-approval` ⇒ emit
26
+ * `tool-approval-request`, arm a timer, and park until the consumer settles),
27
+ * then re-`run(agent, state)` and drain the fresh result onto the SAME sink.
28
+ * Passing `session` on every resume is safe: the runner tracks
29
+ * `_currentTurnPersistedItemCount` on the state and persists only new items, so
30
+ * it stays the sole history writer with no double-write.
31
+ *
32
+ * **Idempotent settle (#589).** `approve` / `decline` are `void`-typed. A second
33
+ * settle on the same `toolCallId`, or a settle after the coordinator auto-resolved
34
+ * it (timeout / abort / dispose / pump-error), is a silent no-op — the consumer's
35
+ * intended outcome (id is settled) is already true. A `toolCallId` the coordinator
36
+ * never emitted an approval for is genuine misuse and throws
37
+ * `AgentSDKError(TOOL_CALL_NOT_FOUND)`.
38
+ *
39
+ * One coordinator serves one turn. `stream()` disposes any prior coordinator on
40
+ * the same `(agentId, threadId)` before constructing a fresh one, so a
41
+ * re-`stream()` mid-turn can't leave a stale pump running.
42
+ */
43
+ export class OpenAIApprovalCoordinator {
44
+ sink = new GenSink();
45
+ adapter;
46
+ /**
47
+ * Cancels the in-flight `run()`. Distinct from any consumer-supplied
48
+ * `abortSignal` so teardown can cancel the turn (dispose / destroyThread)
49
+ * even when the consumer passed no signal of its own.
50
+ */
51
+ abortController = new AbortController();
52
+ /** Removes the consumer's external-abort listener (if one was wired). */
53
+ detachExternalAbort;
54
+ /** True once the turn has reached a terminal state by any path. */
55
+ settled = false;
56
+ runner;
57
+ agent;
58
+ input;
59
+ session;
60
+ onSettled;
61
+ policy;
62
+ externalSignal;
63
+ toolApprovalTimeoutMs;
64
+ maxTurns;
65
+ consumerTools;
66
+ onConsumerToolErrors;
67
+ /** Approvals emitted this turn (surfaced a `tool-approval-request`), by `toolCallId`. */
68
+ emittedApprovals = new Set();
69
+ /** Approvals awaiting a consumer settle, by `toolCallId`. */
70
+ pendingApprovals = new Map();
71
+ /** Ids the consumer settled (approve / decline), so a repeat settle is a no-op. */
72
+ consumerSettled = new Set();
73
+ /** Ids the coordinator auto-settled (teardown), so a late consumer settle is a no-op. */
74
+ settledByCoordinator = new Set();
75
+ constructor(options) {
76
+ this.runner = options.runner;
77
+ this.agent = options.agent;
78
+ this.input = options.input;
79
+ this.session = options.session;
80
+ this.onSettled = options.onSettled;
81
+ this.policy = options.policy;
82
+ this.externalSignal = options.externalSignal;
83
+ this.toolApprovalTimeoutMs = options.toolApprovalTimeoutMs ?? DEFAULT_TOOL_APPROVAL_TIMEOUT_MS;
84
+ this.maxTurns = options.maxTurns;
85
+ this.consumerTools = options.consumerTools;
86
+ this.onConsumerToolErrors = options.onConsumerToolErrors;
87
+ this.adapter = new OpenAIEventAdapter(options.mcpCatalog);
88
+ }
89
+ /**
90
+ * Start pumping the run loop onto the sink (background task) and return the
91
+ * consumer's `ChatStreamResult`. Callers MUST have already thrown on an
92
+ * already-aborted signal (`stream()` does this synchronously at entry, per
93
+ * the pre-existing contract), so `start()` only wires the live-abort path.
94
+ */
95
+ start() {
96
+ if (this.externalSignal !== undefined) {
97
+ const onAbort = () => this.teardown(new AbortError(), 'abort');
98
+ this.externalSignal.addEventListener('abort', onAbort, { once: true });
99
+ this.detachExternalAbort = () => this.externalSignal?.removeEventListener('abort', onAbort);
100
+ }
101
+ void this.pump();
102
+ return teeTextStream(this.sink.generator());
103
+ }
104
+ /**
105
+ * Cancel the turn and release its resources. Used by `destroyThread`,
106
+ * `destroyAgent`, and `shutdown`. Idempotent (the `settled` guard in
107
+ * `teardown` collapses a second call to a no-op), and safe to call after the
108
+ * turn completed naturally.
109
+ */
110
+ dispose() {
111
+ this.teardown(new AgentSDKError('Harness disposed.', AgentSDKErrorType.DISPOSED), 'DISPOSED');
112
+ }
113
+ /**
114
+ * Approve a pending tool call. Buffers the decision and wakes the parked pump
115
+ * so it drives `state.approve(item)` + resume. Idempotent (#589): a repeat or
116
+ * post-teardown settle is a silent no-op; an id with no emitted approval is
117
+ * misuse and throws `TOOL_CALL_NOT_FOUND`.
118
+ */
119
+ approve(toolCallId) {
120
+ this.settleApproval('approve', toolCallId);
121
+ }
122
+ /**
123
+ * Decline a pending tool call. Buffers the decision and wakes the parked pump
124
+ * so it drives `state.reject(item, { message })` + resume — the run loop feeds
125
+ * a real `function_call_result` carrying the denial text back to the model, so
126
+ * the decline is model-visible with no synthesized result. Same idempotency
127
+ * contract as {@link approve}.
128
+ */
129
+ decline(toolCallId) {
130
+ this.settleApproval('decline', toolCallId);
131
+ }
132
+ /**
133
+ * Feed a consumer-executed tool's result back into the turn. Resolves the
134
+ * parked `execute` in the {@link ConsumerToolRegistry} keyed by `toolCallId`;
135
+ * the SDK run loop — blocked inside the pump's `await result.completed` on
136
+ * that parked promise — then continues the SAME run (emits `tool_output`, the
137
+ * model's follow-up, and a natural terminal `finish`) onto the same sink. No
138
+ * fresh `run()` and no synthetic `finish('tool-calls')`: unlike the approval
139
+ * path, the run never left. Idempotent (#589) and typed-throws
140
+ * (`TOOL_CALL_NOT_FOUND`) are owned by the registry.
141
+ */
142
+ submitToolResult(toolCallId, outcome) {
143
+ if (this.consumerTools === undefined) {
144
+ throw new AgentSDKError(`No parked consumer tool call for id "${toolCallId}".`, AgentSDKErrorType.TOOL_CALL_NOT_FOUND);
145
+ }
146
+ this.consumerTools.settle(toolCallId, outcome);
147
+ }
148
+ settleApproval(decision, toolCallId) {
149
+ // Lost-race no-op: already settled by the consumer or auto-settled by a
150
+ // teardown. The consumer's intended outcome (id is settled) already holds.
151
+ if (this.consumerSettled.has(toolCallId) || this.settledByCoordinator.has(toolCallId))
152
+ return;
153
+ const pending = this.pendingApprovals.get(toolCallId);
154
+ if (pending === undefined) {
155
+ // Never emitted an approval for this id — genuine misuse.
156
+ throw new AgentSDKError(`No pending tool-approval for tool call "${toolCallId}".`, AgentSDKErrorType.TOOL_CALL_NOT_FOUND);
157
+ }
158
+ this.consumerSettled.add(toolCallId);
159
+ clearTimeout(pending.timer);
160
+ this.pendingApprovals.delete(toolCallId);
161
+ pending.resolve(decision);
162
+ }
163
+ /**
164
+ * The turn's pump: run to a terminal state across one-or-more runs, draining
165
+ * each onto the SAME sink, settling any interruptions between runs. The SDK
166
+ * throws a mid-stream model error out of the iterator rather than emitting an
167
+ * event, so the `catch` synthesizes `error` + `finish('error')`.
168
+ */
169
+ async pump() {
170
+ try {
171
+ let result = (await this.runner.run(this.agent, this.input, this.runOptions()));
172
+ await this.drainRun(result);
173
+ // Resume loop: while the completed run carries interruptions, settle
174
+ // each and re-run onto the same sink until a run finishes clean.
175
+ while (!this.settled && result.interruptions.length > 0) {
176
+ await this.settleInterruptions(result);
177
+ if (this.settled)
178
+ return;
179
+ result = (await this.runner.run(this.agent, result.state, this.runOptions()));
180
+ await this.drainRun(result);
181
+ }
182
+ if (this.settled)
183
+ return;
184
+ // Flush any `step-finish` the adapter deferred for a tool-calling
185
+ // step whose outputs drained without a following `response_started`
186
+ // (the last step of the turn), so every step closes before the
187
+ // terminal `finish`.
188
+ for (const chatEvent of this.adapter.drainDeferredStepFinish())
189
+ this.sink.push(chatEvent);
190
+ // The run loop emits no dedicated terminal event and does not throw on
191
+ // clean completion, so synthesize the single terminal `finish`.
192
+ this.settled = true;
193
+ this.sink.push({ type: 'finish', finishReason: 'stop', ...usageField(this.adapter.lastUsage()) });
194
+ this.sink.end();
195
+ this.cleanup();
196
+ }
197
+ catch (error) {
198
+ if (this.settled)
199
+ return;
200
+ for (const startEvent of this.adapter.ensureStarted()) {
201
+ this.sink.push(startEvent);
202
+ }
203
+ // Exceeding the step limit is a normal terminal condition, not a
204
+ // failure: `run(..., { maxTurns })` throws `MaxTurnsExceededError`
205
+ // out of the streamed iterator (like every mid-stream signal), but
206
+ // the harness surfaces it as a terminal `finish('max-steps')` with
207
+ // NO preceding `error` event — matching the Mastra / Claude harnesses
208
+ // and the SDK's `FinishReason` contract. Any other throw is a real
209
+ // mid-stream failure and keeps the `error` + `finish('error')` pair.
210
+ if (error instanceof MaxTurnsExceededError) {
211
+ for (const chatEvent of this.adapter.drainDeferredStepFinish())
212
+ this.sink.push(chatEvent);
213
+ this.releaseParkedApprovals();
214
+ this.settled = true;
215
+ this.sink.push({ type: 'finish', finishReason: 'max-steps', ...usageField(this.adapter.lastUsage()) });
216
+ this.sink.end();
217
+ this.cleanup();
218
+ return;
219
+ }
220
+ const aborted = isAbortError(error) || this.abortController.signal.aborted;
221
+ this.releaseParkedApprovals();
222
+ this.settled = true;
223
+ this.sink.push({
224
+ type: 'error',
225
+ error: error instanceof Error ? error : new Error(String(error)),
226
+ code: aborted ? 'abort' : 'stream-error',
227
+ });
228
+ this.sink.push({ type: 'finish', finishReason: 'error' });
229
+ this.sink.end();
230
+ this.cleanup();
231
+ }
232
+ }
233
+ /**
234
+ * The `run()` options shared by the initial run and every resume, so the two
235
+ * can't drift.
236
+ *
237
+ * `reasoningItemIdPolicy: 'omit'` is load-bearing against the Salesforce
238
+ * gateway. The gateway is a stateless `/responses` pass-through
239
+ * (`store: false`), so it does not persist reasoning items by id. The SDK's
240
+ * default re-sends prior reasoning items BY ID REFERENCE (`rs_...`) on every
241
+ * follow-up model call — the initial run's second step (after a tool result)
242
+ * and every resume run — which the gateway rejects with
243
+ * `400 Item with id 'rs_...' not found. Items are not persisted when 'store'
244
+ * is set to false.` `'omit'` strips the id so the reasoning content is sent
245
+ * inline rather than referenced, which the stateless gateway accepts. (Server
246
+ * -side conversation state via `previousResponseId` is likewise unavailable
247
+ * here; the disk-backed `session` is our source of truth for prior turns.)
248
+ */
249
+ runOptions() {
250
+ return {
251
+ stream: true,
252
+ session: this.session,
253
+ signal: this.abortController.signal,
254
+ reasoningItemIdPolicy: 'omit',
255
+ // Forward the turn's step limit (`StreamOptions.maxSteps`) as
256
+ // `maxTurns`. Omitting the key entirely when unset preserves the
257
+ // SDK's own default rather than forcing `null` (unbounded).
258
+ ...(this.maxTurns !== undefined ? { maxTurns: this.maxTurns } : {}),
259
+ };
260
+ }
261
+ /**
262
+ * Drain one streamed run result: map every event onto the sink, then await
263
+ * the run's terminal completion so the SDK finishes writing session state
264
+ * (the runner owns the history write) before the caller decides
265
+ * the turn's next step. Does NOT emit any terminal `finish` — that is the
266
+ * pump's decision, since a run that ends with `interruptions` is resumed
267
+ * rather than finished.
268
+ */
269
+ async drainRun(result) {
270
+ for await (const event of result) {
271
+ for (const chatEvent of this.adapter.map(event)) {
272
+ // Record consumer-tool call ids the moment they're surfaced so a
273
+ // `submitToolResult` that races ahead of the parked `execute` (the
274
+ // SDK emits `tool_called` before awaiting `execute`) is buffered,
275
+ // not rejected.
276
+ if (chatEvent.type === 'tool-call' && this.consumerTools?.toolNames.has(chatEvent.toolName) === true) {
277
+ this.consumerTools.markEmitted(chatEvent.toolCallId);
278
+ }
279
+ this.sink.push(chatEvent);
280
+ }
281
+ }
282
+ await result.completed;
283
+ }
284
+ /**
285
+ * Settle every interruption on a completed run against the policy, mutating
286
+ * `result.state` in place so the caller can resume from it. `allow` / `deny`
287
+ * are resolved silently here; `require-approval` emits a
288
+ * `tool-approval-request`, arms a timer, and awaits the consumer's settle.
289
+ * Returns once all interruptions on this run have been approved or rejected
290
+ * (or the turn was torn down while a settle was parked).
291
+ */
292
+ async settleInterruptions(result) {
293
+ for (const item of result.interruptions) {
294
+ if (this.settled)
295
+ return;
296
+ const toolCallId = item.rawItem?.callId;
297
+ const toolName = item.toolName ?? item.name ?? item.rawItem?.name;
298
+ // An interruption with no callId/name can't be routed or settled —
299
+ // approve it so the run makes progress rather than deadlocking.
300
+ if (toolCallId === undefined || toolName === undefined) {
301
+ result.state.approve(item);
302
+ continue;
303
+ }
304
+ const decision = this.policy?.({ toolName }) ?? 'require-approval';
305
+ if (decision === 'allow') {
306
+ result.state.approve(item);
307
+ continue;
308
+ }
309
+ if (decision === 'deny') {
310
+ result.state.reject(item, { message: 'Tool call was not approved by policy.' });
311
+ continue;
312
+ }
313
+ const settled = await this.awaitApproval(toolCallId, toolName, item);
314
+ if (settled === undefined)
315
+ return; // torn down while parked
316
+ if (settled === 'approve')
317
+ result.state.approve(item);
318
+ else
319
+ result.state.reject(item, { message: 'User declined the tool call.' });
320
+ }
321
+ }
322
+ /**
323
+ * Emit a `tool-approval-request`, arm the per-`toolCallId` timeout, and return
324
+ * a promise that resolves when the consumer settles (or `undefined` if the
325
+ * turn is torn down while parked, in which case the pump exits).
326
+ */
327
+ awaitApproval(toolCallId, toolName, item) {
328
+ this.sink.push({
329
+ type: 'tool-approval-request',
330
+ toolCall: { toolCallId, toolName, args: parseArgs(item) },
331
+ });
332
+ this.emittedApprovals.add(toolCallId);
333
+ return new Promise((resolve) => {
334
+ const timer = setTimeout(() => {
335
+ this.teardown(new Error(`Tool approval timed out after ${this.toolApprovalTimeoutMs}ms for "${toolCallId}".`), 'tool-approval-timeout');
336
+ }, this.toolApprovalTimeoutMs);
337
+ this.pendingApprovals.set(toolCallId, { resolve, timer });
338
+ });
339
+ }
340
+ /**
341
+ * Single terminal path for abort / dispose / timeout. Releases every parked
342
+ * approval so nothing hangs, aborts the in-flight run, emits the terminal
343
+ * `error` + `finish('error')` pair (a `start` first if the turn produced no
344
+ * events), and settles. `code` distinguishes the reason to the consumer
345
+ * (`'abort'` / `'DISPOSED'` / `'tool-approval-timeout'`). The `settled` guard
346
+ * makes it single-shot and a no-op after natural completion.
347
+ */
348
+ teardown(error, code) {
349
+ if (this.settled)
350
+ return;
351
+ this.releaseParkedApprovals();
352
+ this.settled = true;
353
+ this.abortController.abort();
354
+ for (const startEvent of this.adapter.ensureStarted()) {
355
+ this.sink.push(startEvent);
356
+ }
357
+ this.sink.push({ type: 'error', error, code });
358
+ this.sink.push({ type: 'finish', finishReason: 'error' });
359
+ this.sink.end();
360
+ this.cleanup();
361
+ }
362
+ /**
363
+ * Release every parked approval AND every parked consumer-tool call: cancel
364
+ * each approval timer, record the id as coordinator-settled (so a late
365
+ * consumer settle is a no-op, #589), resolve the parked approval waiter with
366
+ * `undefined` so the pump exits its `awaitApproval`, and reject every parked
367
+ * consumer `execute` so the SDK run loop unblocks rather than hanging on a
368
+ * promise that will never settle. Shared by the error path and
369
+ * {@link teardown}. Does not set `settled` — callers own that ordering
370
+ * relative to the terminal emit.
371
+ */
372
+ releaseParkedApprovals() {
373
+ for (const [toolCallId, pending] of this.pendingApprovals) {
374
+ clearTimeout(pending.timer);
375
+ this.settledByCoordinator.add(toolCallId);
376
+ pending.resolve(undefined);
377
+ }
378
+ for (const toolCallId of this.emittedApprovals)
379
+ this.settledByCoordinator.add(toolCallId);
380
+ this.pendingApprovals.clear();
381
+ this.consumerTools?.rejectAll(new Error('Turn ended before the consumer tool result arrived.'));
382
+ }
383
+ /** Detach the external-abort listener and notify the harness exactly once. */
384
+ cleanup() {
385
+ this.detachExternalAbort?.();
386
+ this.detachExternalAbort = undefined;
387
+ // Stamp `isError` onto the persisted results of any consumer tool the
388
+ // consumer settled with `isError: true` — the run loop wrote them without
389
+ // it (the OpenAI item shape has no `isError` field). Fires on every
390
+ // terminal path (a tool can be settled with an error before an abort), and
391
+ // the harness's async stamp settles under the store's per-thread queue
392
+ // after the run's own writes.
393
+ const errored = this.consumerTools?.erroredToolCallIds() ?? [];
394
+ if (errored.length > 0)
395
+ this.onConsumerToolErrors?.(errored);
396
+ this.onSettled();
397
+ }
398
+ }
399
+ /** An `AbortError`-shaped `Error` so `isAbortError` and consumers classify it. */
400
+ class AbortError extends Error {
401
+ constructor() {
402
+ super('The operation was aborted.');
403
+ this.name = 'AbortError';
404
+ }
405
+ }
406
+ /** Parse the interruption's raw `arguments` JSON into an args object (best-effort). */
407
+ function parseArgs(item) {
408
+ const raw = item.arguments;
409
+ if (typeof raw !== 'string')
410
+ return {};
411
+ try {
412
+ const parsed = JSON.parse(raw);
413
+ return typeof parsed === 'object' && parsed !== null ? parsed : {};
414
+ }
415
+ catch {
416
+ return {};
417
+ }
418
+ }
419
+ function usageField(usage) {
420
+ return usage !== undefined ? { usage } : {};
421
+ }
422
+ //# sourceMappingURL=openai-approval-coordinator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-approval-coordinator.js","sourceRoot":"","sources":["../src/openai-approval-coordinator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import type { ToolPolicyRule } from '@salesforce/sfdx-agent-sdk';
2
+ /**
3
+ * OpenAI harness-specific built-in tool-approval rules — the `tiers.harness`
4
+ * slice passed to `resolveToolApprovalPolicy`. Per the SDK's R4 layering
5
+ * invariant, harness-specific built-ins live here, not in the SDK's
6
+ * harness-agnostic `BUILT_IN_TOOL_POLICIES`.
7
+ *
8
+ * **Empty today.** Unlike Claude (`Bash` / `Edit` / … registered by the CLI
9
+ * subprocess) and Mastra (`updateWorkingMemory` / `skill*` registered by the
10
+ * runtime), the OpenAI harness registers no runtime built-in tools of its own:
11
+ * a turn's tools are the consumer-declared (`AgentConfig.tools`) and — once MCP
12
+ * support lands — MCP tools, both of which the resolver already covers via
13
+ * `builtin` / `mcp` matchers on the consumer tier. So there is nothing
14
+ * harness-specific to pre-gate here today.
15
+ *
16
+ * The array is present (not omitted) so the harness always passes a
17
+ * `{ harness }` tier to `resolveToolApprovalPolicy` — a stable call shape — and
18
+ * so a future built-in has an obvious home. The `@openai/agents` hosted tools
19
+ * (`shell` / `apply_patch` / `computer`) each carry their OWN `needsApproval`
20
+ * flag in the SDK and are not wired into this harness yet; when they are, decide
21
+ * per-tool whether the gate belongs on the SDK flag or as a rule here.
22
+ *
23
+ * Frozen: adding an entry is a soft contract change consumers will have noticed;
24
+ * removing or modifying one is a breaking change. The drift test in
25
+ * `test/openai-built-in-policies.test.ts` pins the shape (currently: empty, all
26
+ * `builtin` matchers, all `source: 'built-in'` — vacuously true while empty, and
27
+ * the guard the first real entry must satisfy).
28
+ */
29
+ export declare const OPENAI_BUILT_IN_TOOL_POLICIES: ReadonlyArray<ToolPolicyRule>;
@@ -0,0 +1,33 @@
1
+ /*
2
+ * Copyright 2026, Salesforce, Inc. All rights reserved.
3
+ * See LICENSE.txt for license terms.
4
+ */
5
+ /**
6
+ * OpenAI harness-specific built-in tool-approval rules — the `tiers.harness`
7
+ * slice passed to `resolveToolApprovalPolicy`. Per the SDK's R4 layering
8
+ * invariant, harness-specific built-ins live here, not in the SDK's
9
+ * harness-agnostic `BUILT_IN_TOOL_POLICIES`.
10
+ *
11
+ * **Empty today.** Unlike Claude (`Bash` / `Edit` / … registered by the CLI
12
+ * subprocess) and Mastra (`updateWorkingMemory` / `skill*` registered by the
13
+ * runtime), the OpenAI harness registers no runtime built-in tools of its own:
14
+ * a turn's tools are the consumer-declared (`AgentConfig.tools`) and — once MCP
15
+ * support lands — MCP tools, both of which the resolver already covers via
16
+ * `builtin` / `mcp` matchers on the consumer tier. So there is nothing
17
+ * harness-specific to pre-gate here today.
18
+ *
19
+ * The array is present (not omitted) so the harness always passes a
20
+ * `{ harness }` tier to `resolveToolApprovalPolicy` — a stable call shape — and
21
+ * so a future built-in has an obvious home. The `@openai/agents` hosted tools
22
+ * (`shell` / `apply_patch` / `computer`) each carry their OWN `needsApproval`
23
+ * flag in the SDK and are not wired into this harness yet; when they are, decide
24
+ * per-tool whether the gate belongs on the SDK flag or as a rule here.
25
+ *
26
+ * Frozen: adding an entry is a soft contract change consumers will have noticed;
27
+ * removing or modifying one is a breaking change. The drift test in
28
+ * `test/openai-built-in-policies.test.ts` pins the shape (currently: empty, all
29
+ * `builtin` matchers, all `source: 'built-in'` — vacuously true while empty, and
30
+ * the guard the first real entry must satisfy).
31
+ */
32
+ export const OPENAI_BUILT_IN_TOOL_POLICIES = Object.freeze([]);
33
+ //# sourceMappingURL=openai-built-in-policies.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-built-in-policies.js","sourceRoot":"","sources":["../src/openai-built-in-policies.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAkC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC"}
@@ -0,0 +1,119 @@
1
+ import type { RunStreamEvent } from '@openai/agents';
2
+ import type { ChatEvent, FinishReason, UsageMetadata } from '@salesforce/sfdx-agent-sdk';
3
+ import type { McpCatalogEntry } from './openai-mcp-state.js';
4
+ /**
5
+ * Per-stream stateful mapper from `@openai/agents` `RunStreamEvent`s to the
6
+ * SDK's `ChatEvent` variants. A new instance is constructed per `stream()` call
7
+ * because it tracks `stepIndex` and the last-seen per-step usage.
8
+ *
9
+ * **Text + tool events.** The run loop emits three event families:
10
+ * `raw_model_stream_event` (the underlying model stream, carrying
11
+ * `output_text_delta` / `response_started` / `response_done`),
12
+ * `run_item_stream_event` (tool calls / outputs), and
13
+ * `agent_updated_stream_event` (handoffs — not used). This adapter maps the
14
+ * text and step-boundary events plus the `tool_called` / `tool_output` run-item
15
+ * events to `tool-call` / `tool-result` ChatEvents. The terminal `finish` is
16
+ * synthesized by the harness pump when the run stream completes, since the run
17
+ * loop does not emit a dedicated "run finished" event and mid-stream errors are
18
+ * thrown, not emitted.
19
+ *
20
+ * The adapter never emits an event whose `type` is not a member of the
21
+ * `ChatEvent` union. Unrecognized events are skipped.
22
+ */
23
+ export declare class OpenAIEventAdapter {
24
+ private readonly mcpCatalog?;
25
+ private stepIndex;
26
+ private started;
27
+ private lastStepUsage;
28
+ /**
29
+ * A `step-finish` buffered because its step produced tool calls. The
30
+ * `@openai/agents` run loop emits `response_done` for a tool-calling step
31
+ * BEFORE the `tool_called` / `tool_output` run-items for that step, so
32
+ * emitting `step-finish` inline would place the `tool-result` AFTER its
33
+ * step's `step-finish` — outside the step. We hold the `step-finish` until
34
+ * the step's tool outputs drain (or a new step starts / the run ends), so a
35
+ * `tool-result` always lands inside the `step-start`/`step-finish` bracket
36
+ * that produced it. Mirrors the Claude adapter's deferred-`step-finish`
37
+ * ordering (`pendingToolUseIds`).
38
+ */
39
+ private deferredStepFinish;
40
+ /** Outstanding `tool_output`s for the deferred step; `step-finish` flushes at 0. */
41
+ private pendingToolOutputs;
42
+ /**
43
+ * Optional MCP tool catalog (bare tool name → `{ serverName, annotations }`),
44
+ * used to enrich `tool-call` / `tool-result` events for MCP-sourced tools
45
+ * with `serverName` / `bareToolName` / `annotations`. Read live so a mid-turn
46
+ * discovery settle enriches later events. `undefined` (or a miss) leaves the
47
+ * fields unset — the contract for consumer / built-in tools.
48
+ */
49
+ constructor(mcpCatalog?: ReadonlyMap<string, McpCatalogEntry> | undefined);
50
+ /**
51
+ * Map one `RunStreamEvent` to zero or more `ChatEvent`s. Emits a synthetic
52
+ * `start` before the first mapped event.
53
+ */
54
+ map(event: RunStreamEvent): ChatEvent[];
55
+ /**
56
+ * Map a `run_item_stream_event` to a `tool-call` / `tool-result` ChatEvent.
57
+ * The run loop fires `tool_called` with a `RunToolCallItem` (the model's
58
+ * request) and `tool_output` with a `RunToolCallOutputItem` (the result).
59
+ *
60
+ * **MCP enrichment.** When the tool's (bare) name is in the {@link mcpCatalog},
61
+ * the event carries `serverName` / `bareToolName` / `annotations` so a consumer
62
+ * can build a `{ type: 'mcp', serverName, toolName }` policy matcher without
63
+ * string-splitting the display name. Consumer / built-in tools miss the
64
+ * catalog and surface with `serverName === undefined`, per the SDK contract.
65
+ * `isError` is not carried on the live `tool-result` event — the OpenAI
66
+ * `tool_output` item has no `isError` field; a consumer-reported failure is
67
+ * stamped onto the persisted record instead (see the session store). This
68
+ * maps the raw call/result the loop emits so a tool turn is observable and
69
+ * round-trips through history.
70
+ */
71
+ private mapRunItem;
72
+ /**
73
+ * Look up the (bare) tool name in the MCP catalog and return the enrichment
74
+ * fields for a `tool-call` / `tool-result` event, or an empty object when the
75
+ * tool is not MCP-sourced. `bareToolName` equals the display `toolName` here
76
+ * because `@openai/agents` registers MCP tools under their bare name.
77
+ */
78
+ private enrich;
79
+ /**
80
+ * The last per-step usage observed, used to populate the terminal `finish`
81
+ * event the pump synthesizes when the run stream completes cleanly.
82
+ */
83
+ lastUsage(): UsageMetadata | undefined;
84
+ /**
85
+ * Emit a synthetic `start` if the stream produced no events at all (e.g. a
86
+ * turn that failed before the first delta). Called by the pump on the error
87
+ * path so a consumer always sees a `start` before the terminal pair.
88
+ */
89
+ ensureStarted(): ChatEvent[];
90
+ private mapRaw;
91
+ /**
92
+ * Emit a held `step-finish` (if any) and reset the deferral state. Called
93
+ * when the step's tool outputs have drained, when a new step starts, and by
94
+ * the pump before the terminal `finish` so a deferred step-finish can never
95
+ * be dropped.
96
+ */
97
+ flushDeferredStepFinish(out: ChatEvent[]): void;
98
+ /** Emit any held `step-finish` as a standalone event list (pump terminal path). */
99
+ drainDeferredStepFinish(): ChatEvent[];
100
+ }
101
+ /**
102
+ * Maps the OpenAI Agents SDK's `response_done` usage shape (camelCase
103
+ * `inputTokens` / `outputTokens` / `totalTokens`, plus optional
104
+ * `inputTokensDetails` / `outputTokensDetails`) onto the SDK's
105
+ * {@link UsageMetadata}. Returns `undefined` when no usage was reported at all,
106
+ * so consumers see an honest "usage not reported" signal rather than a fake
107
+ * all-zero object (the missing-usage-faithfulness contract, W-22692131).
108
+ */
109
+ export declare function mapUsage(usage: OpenAIStreamUsage | undefined): UsageMetadata | undefined;
110
+ /** The usage shape carried on a `response_done` stream event. */
111
+ export type OpenAIStreamUsage = {
112
+ inputTokens?: number;
113
+ outputTokens?: number;
114
+ totalTokens?: number;
115
+ inputTokensDetails?: Record<string, number> | Array<Record<string, number>>;
116
+ outputTokensDetails?: Record<string, number> | Array<Record<string, number>>;
117
+ };
118
+ /** Re-export so the harness pump can reference the union without re-importing. */
119
+ export type { FinishReason };