@pellux/goodvibes-sdk 0.18.43 → 0.18.47

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 (85) hide show
  1. package/dist/_internal/platform/config/manager.d.ts +12 -0
  2. package/dist/_internal/platform/config/manager.d.ts.map +1 -1
  3. package/dist/_internal/platform/config/manager.js +30 -0
  4. package/dist/_internal/platform/core/orchestrator-turn-helpers.js +1 -1
  5. package/dist/_internal/platform/core/orchestrator-turn-loop.js +1 -1
  6. package/dist/_internal/platform/daemon/facade.d.ts +19 -0
  7. package/dist/_internal/platform/daemon/facade.d.ts.map +1 -1
  8. package/dist/_internal/platform/daemon/facade.js +90 -1
  9. package/dist/_internal/platform/daemon/host-mode-watcher.d.ts +49 -0
  10. package/dist/_internal/platform/daemon/host-mode-watcher.d.ts.map +1 -0
  11. package/dist/_internal/platform/daemon/host-mode-watcher.js +41 -0
  12. package/dist/_internal/platform/daemon/http-listener.d.ts +17 -0
  13. package/dist/_internal/platform/daemon/http-listener.d.ts.map +1 -1
  14. package/dist/_internal/platform/daemon/http-listener.js +87 -1
  15. package/dist/_internal/platform/providers/anthropic-compat.d.ts.map +1 -1
  16. package/dist/_internal/platform/providers/anthropic-compat.js +9 -6
  17. package/dist/_internal/platform/providers/anthropic-sdk-provider.d.ts.map +1 -1
  18. package/dist/_internal/platform/providers/anthropic-sdk-provider.js +9 -6
  19. package/dist/_internal/platform/providers/anthropic.d.ts.map +1 -1
  20. package/dist/_internal/platform/providers/anthropic.js +9 -6
  21. package/dist/_internal/platform/providers/auto-register.d.ts +2 -3
  22. package/dist/_internal/platform/providers/auto-register.d.ts.map +1 -1
  23. package/dist/_internal/platform/providers/auto-register.js +1 -8
  24. package/dist/_internal/platform/providers/gemini.d.ts.map +1 -1
  25. package/dist/_internal/platform/providers/gemini.js +5 -5
  26. package/dist/_internal/platform/providers/index.d.ts +1 -0
  27. package/dist/_internal/platform/providers/index.d.ts.map +1 -1
  28. package/dist/_internal/platform/providers/index.js +1 -0
  29. package/dist/_internal/platform/providers/interface.d.ts +12 -1
  30. package/dist/_internal/platform/providers/interface.d.ts.map +1 -1
  31. package/dist/_internal/platform/providers/llama-cpp.d.ts.map +1 -1
  32. package/dist/_internal/platform/providers/llama-cpp.js +4 -3
  33. package/dist/_internal/platform/providers/lm-studio-helpers.d.ts +2 -3
  34. package/dist/_internal/platform/providers/lm-studio-helpers.d.ts.map +1 -1
  35. package/dist/_internal/platform/providers/lm-studio-helpers.js +0 -9
  36. package/dist/_internal/platform/providers/lm-studio.d.ts.map +1 -1
  37. package/dist/_internal/platform/providers/lm-studio.js +7 -3
  38. package/dist/_internal/platform/providers/ollama.d.ts.map +1 -1
  39. package/dist/_internal/platform/providers/ollama.js +3 -3
  40. package/dist/_internal/platform/providers/openai-codex.d.ts.map +1 -1
  41. package/dist/_internal/platform/providers/openai-codex.js +3 -10
  42. package/dist/_internal/platform/providers/openai-compat.d.ts.map +1 -1
  43. package/dist/_internal/platform/providers/openai-compat.js +11 -7
  44. package/dist/_internal/platform/providers/openai.d.ts.map +1 -1
  45. package/dist/_internal/platform/providers/openai.js +11 -7
  46. package/dist/_internal/platform/providers/provider-api.d.ts +4 -0
  47. package/dist/_internal/platform/providers/provider-api.d.ts.map +1 -1
  48. package/dist/_internal/platform/providers/provider-not-found-error.d.ts +16 -0
  49. package/dist/_internal/platform/providers/provider-not-found-error.d.ts.map +1 -0
  50. package/dist/_internal/platform/providers/provider-not-found-error.js +24 -0
  51. package/dist/_internal/platform/providers/registry.d.ts +44 -2
  52. package/dist/_internal/platform/providers/registry.d.ts.map +1 -1
  53. package/dist/_internal/platform/providers/registry.js +73 -13
  54. package/dist/_internal/platform/providers/stop-reason-maps.d.ts +30 -0
  55. package/dist/_internal/platform/providers/stop-reason-maps.d.ts.map +1 -0
  56. package/dist/_internal/platform/providers/stop-reason-maps.js +89 -0
  57. package/dist/_internal/platform/runtime/contracts/migrations/event-envelope.d.ts +1 -1
  58. package/dist/_internal/platform/runtime/contracts/version.d.ts +1 -1
  59. package/dist/_internal/platform/runtime/contracts/version.js +1 -1
  60. package/dist/_internal/platform/runtime/events/domain-map.d.ts +10 -0
  61. package/dist/_internal/platform/runtime/events/domain-map.d.ts.map +1 -1
  62. package/dist/_internal/platform/runtime/events/index.d.ts +1 -1
  63. package/dist/_internal/platform/runtime/events/index.d.ts.map +1 -1
  64. package/dist/_internal/platform/runtime/forensics/classifier.d.ts.map +1 -1
  65. package/dist/_internal/platform/runtime/forensics/classifier.js +1 -4
  66. package/dist/_internal/platform/runtime/index.d.ts +1 -1
  67. package/dist/_internal/platform/runtime/index.d.ts.map +1 -1
  68. package/dist/_internal/platform/version.js +1 -1
  69. package/dist/_internal/transport-http/auth.d.ts +17 -0
  70. package/dist/_internal/transport-http/auth.d.ts.map +1 -1
  71. package/dist/_internal/transport-http/auth.js +22 -0
  72. package/dist/_internal/transport-http/http-core.d.ts.map +1 -1
  73. package/dist/_internal/transport-http/http-core.js +5 -3
  74. package/dist/_internal/transport-http/index.d.ts +2 -2
  75. package/dist/_internal/transport-http/index.d.ts.map +1 -1
  76. package/dist/_internal/transport-http/index.js +1 -1
  77. package/dist/_internal/transport-realtime/runtime-events.d.ts +3 -2
  78. package/dist/_internal/transport-realtime/runtime-events.d.ts.map +1 -1
  79. package/dist/_internal/transport-realtime/runtime-events.js +4 -10
  80. package/dist/client.d.ts +19 -3
  81. package/dist/client.d.ts.map +1 -1
  82. package/dist/client.js +5 -2
  83. package/dist/index.d.ts +1 -1
  84. package/dist/index.d.ts.map +1 -1
  85. package/package.json +1 -1
@@ -25,6 +25,10 @@ export type ConfigOverrides = ConfigCliOverrides & ({
25
25
  export interface ConfigSetOptions {
26
26
  bypassManagedLock?: boolean;
27
27
  }
28
+ /** Callback invoked when a watched config key changes. */
29
+ export type ConfigChangeCallback<K extends ConfigKey> = (newValue: ConfigValue<K>, oldValue: ConfigValue<K>) => void;
30
+ /** Unsubscribe handle returned by ConfigManager.subscribe(). */
31
+ export type ConfigUnsubscribe = () => void;
28
32
  /**
29
33
  * ConfigManager — Layered, mutable, persistent config system.
30
34
  *
@@ -39,6 +43,7 @@ export declare class ConfigManager {
39
43
  private readonly workingDirectory;
40
44
  private readonly homeDirectory;
41
45
  private hookDispatcher;
46
+ private readonly _listeners;
42
47
  constructor(overrides: ConfigOverrides);
43
48
  getControlPlaneConfigDir(): string;
44
49
  getWorkingDirectory(): string | null;
@@ -49,6 +54,13 @@ export declare class ConfigManager {
49
54
  get<K extends ConfigKey>(key: K): ConfigValue<K>;
50
55
  /** Set a config value by dot-path key and auto-save to disk. */
51
56
  set<K extends ConfigKey>(key: K, value: ConfigValue<K>, options?: ConfigSetOptions): void;
57
+ /**
58
+ * Subscribe to changes on a specific config key.
59
+ * Returns an unsubscribe function. Safe to call multiple times.
60
+ */
61
+ subscribe<K extends ConfigKey>(key: K, cb: ConfigChangeCallback<K>): ConfigUnsubscribe;
62
+ /** Notify synchronous subscribers of a key change. */
63
+ private notifyListeners;
52
64
  /**
53
65
  * Fire the Change:config hook for a config key change.
54
66
  * Best-effort: the hook dispatcher may not be initialised during startup.
@@ -1 +1 @@
1
- {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../../../src/_internal/platform/config/manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../../../src/_internal/platform/config/manager.ts"],"names":[],"mappings":"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"}
@@ -65,6 +65,7 @@ export class ConfigManager {
65
65
  workingDirectory;
66
66
  homeDirectory;
67
67
  hookDispatcher = null;
68
+ _listeners = new Map();
68
69
  constructor(overrides) {
69
70
  const roots = overrides;
70
71
  const configDir = requireAbsoluteOwnedPath(roots.configDir, 'configDir');
@@ -157,8 +158,37 @@ export class ConfigManager {
157
158
  const previousValue = parent[field];
158
159
  parent[field] = value;
159
160
  this.save();
161
+ this.notifyListeners(key, previousValue, value);
160
162
  this.emitConfigHook(key, previousValue, value);
161
163
  }
164
+ /**
165
+ * Subscribe to changes on a specific config key.
166
+ * Returns an unsubscribe function. Safe to call multiple times.
167
+ */
168
+ subscribe(key, cb) {
169
+ if (!this._listeners.has(key)) {
170
+ this._listeners.set(key, new Set());
171
+ }
172
+ // Cast via unknown -> (n: unknown, o: unknown) => void to avoid deeply-recursive ConfigValue<K> comparison
173
+ // that exceeds TypeScript's stack depth limit on the 100-entry conditional type.
174
+ const wrapped = (newVal, oldVal) => cb(newVal, oldVal);
175
+ this._listeners.get(key).add(wrapped);
176
+ return () => {
177
+ this._listeners.get(key)?.delete(wrapped);
178
+ };
179
+ }
180
+ /** Notify synchronous subscribers of a key change. */
181
+ notifyListeners(key, oldValue, newValue) {
182
+ const set = this._listeners.get(key);
183
+ if (!set)
184
+ return;
185
+ for (const cb of set) {
186
+ try {
187
+ cb(newValue, oldValue);
188
+ }
189
+ catch { /* listener errors must not abort set() */ }
190
+ }
191
+ }
162
192
  /**
163
193
  * Fire the Change:config hook for a config key change.
164
194
  * Best-effort: the hook dispatcher may not be initialised during startup.
@@ -206,7 +206,7 @@ export function handleFinalResponseOutcome(args) {
206
206
  export function emitMalformedToolUseWarning(args) {
207
207
  logger.warn('Orchestrator: provider reported stopReason=tool_use but returned no tool calls (malformed response)', {
208
208
  model: args.providerRegistry.getCurrentModel().id,
209
- stopReason: 'tool_use',
209
+ stopReason: 'tool_call',
210
210
  });
211
211
  if (args.isReconciliationEnabled) {
212
212
  args.conversation.addSystemMessage('[Tool Reconciliation] Provider returned stop_reason=tool_use but no tool calls were included in the response. ' +
@@ -231,7 +231,7 @@ export async function executeOrchestratorTurnLoop(context) {
231
231
  }
232
232
  const reasoningForMsg = reasoningAccumulated || undefined;
233
233
  const reasoningSummaryForMsg = response.reasoningSummary || undefined;
234
- if (response.stopReason === 'tool_use' && response.toolCalls.length === 0) {
234
+ if (response.stopReason === 'tool_call' && response.toolCalls.length === 0) {
235
235
  emitMalformedToolUseWarning({
236
236
  conversation: context.conversation,
237
237
  providerRegistry: context.providerRegistry,
@@ -61,6 +61,14 @@ export declare class DaemonServer {
61
61
  private agentTaskAdapterUnsub;
62
62
  private tlsState;
63
63
  private approvalBrokerUnsubscribe;
64
+ /** Unsubscribe from controlPlane config key watchers; cleared on stop(). */
65
+ private _configWatchUnsub;
66
+ /** True while a config-driven restart is in progress — prevents re-entrancy. */
67
+ private _restarting;
68
+ /** Awaitable promise for the active restart cycle; null when idle. */
69
+ private _restartingPromise;
70
+ /** True if a config change arrived while _restarting was set; triggers a second cycle. */
71
+ private _restartDirty;
64
72
  constructor(config?: DaemonConfig, _configManager?: ConfigManager);
65
73
  listRecentControlPlaneEvents(limit?: number): readonly import('../control-plane/gateway.js').ControlPlaneRecentEvent[];
66
74
  /**
@@ -80,7 +88,18 @@ export declare class DaemonServer {
80
88
  * against a 10-second timeout so a hung service cannot block the full
81
89
  * shutdown sequence (C1 fix).
82
90
  */
91
+ /**
92
+ * Wait for any in-progress config-driven restart to settle.
93
+ * Callers that change config mid-flight and need to know when the server
94
+ * has rebounded should await this before inspecting state.
95
+ */
96
+ waitForRestart(): Promise<void>;
83
97
  stop(): Promise<void>;
98
+ /**
99
+ * Subscribe to controlPlane binding keys and restart the server on change.
100
+ * Called once from start() after the server is up. Clears itself on stop().
101
+ */
102
+ private _attachControlPlaneConfigWatcher;
84
103
  /**
85
104
  * Returns true if the server is currently running.
86
105
  */
@@ -1 +1 @@
1
- {"version":3,"file":"facade.d.ts","sourceRoot":"","sources":["../../../../src/_internal/platform/daemon/facade.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"facade.d.ts","sourceRoot":"","sources":["../../../../src/_internal/platform/daemon/facade.ts"],"names":[],"mappings":"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"}
@@ -10,6 +10,8 @@ import { GlobalNetworkTransportInstaller, resolveInboundTlsContext, } from '../r
10
10
  import { createRuntimeServices } from '../runtime/services.js';
11
11
  import { readAutomationReasoningEffort, readAutomationWakeMode, readExternalContentSource, readStringList, } from './helpers.js';
12
12
  import { requirePortAvailable } from './port-check.js';
13
+ import { resolveHostBinding } from './host-resolver.js';
14
+ import { createHostModeRestartWatcher } from './host-mode-watcher.js';
13
15
  // ---------------------------------------------------------------------------
14
16
  // DaemonServer
15
17
  // ---------------------------------------------------------------------------
@@ -74,6 +76,14 @@ export class DaemonServer {
74
76
  agentTaskAdapterUnsub = null;
75
77
  tlsState = null;
76
78
  approvalBrokerUnsubscribe = null;
79
+ /** Unsubscribe from controlPlane config key watchers; cleared on stop(). */
80
+ _configWatchUnsub = null;
81
+ /** True while a config-driven restart is in progress — prevents re-entrancy. */
82
+ _restarting = false;
83
+ /** Awaitable promise for the active restart cycle; null when idle. */
84
+ _restartingPromise = null;
85
+ /** True if a config change arrived while _restarting was set; triggers a second cycle. */
86
+ _restartDirty = false;
77
87
  constructor(config = {}, _configManager) {
78
88
  this.config = config;
79
89
  const resolved = resolveDaemonFacadeRuntime(config, _configManager);
@@ -218,7 +228,10 @@ export class DaemonServer {
218
228
  runtimeStore: this.runtimeStore,
219
229
  });
220
230
  const self = this;
221
- await requirePortAvailable(this.port, this.host, 'daemon');
231
+ // Skip real OS port check when a mock serveFactory is injected (test-only path).
232
+ if (this.serveFactory === Bun.serve) {
233
+ await requirePortAvailable(this.port, this.host, 'daemon');
234
+ }
222
235
  this.transportEventsHelper.emitTransportInitializing();
223
236
  try {
224
237
  this.tlsState = resolveInboundTlsContext(this.configManager, 'controlPlane');
@@ -279,6 +292,7 @@ export class DaemonServer {
279
292
  this.watcherRegistry.startWatcher('daemon-heartbeat');
280
293
  }
281
294
  this.controlPlaneGateway.setServerState({ enabled: true, host: this.host, port: this.port });
295
+ this._attachControlPlaneConfigWatcher();
282
296
  this.transportEventsHelper.emitTransportConnected();
283
297
  logger.info('DaemonServer started', {
284
298
  port: this.port,
@@ -317,9 +331,27 @@ export class DaemonServer {
317
331
  * against a 10-second timeout so a hung service cannot block the full
318
332
  * shutdown sequence (C1 fix).
319
333
  */
334
+ /**
335
+ * Wait for any in-progress config-driven restart to settle.
336
+ * Callers that change config mid-flight and need to know when the server
337
+ * has rebounded should await this before inspecting state.
338
+ */
339
+ async waitForRestart() {
340
+ // Loop to handle dirty-flag chained restarts: each cycle may spawn another.
341
+ while (this._restartingPromise)
342
+ await this._restartingPromise;
343
+ }
320
344
  async stop() {
321
345
  if (this.server === null)
322
346
  return;
347
+ // Tear down config watcher only on intentional stop, not mid-restart.
348
+ // During a restart cycle (_restarting=true) the watcher must stay active so
349
+ // config changes that arrive between stop() and the subsequent start() can be
350
+ // captured by the dirty flag.
351
+ if (!this._restarting) {
352
+ this._configWatchUnsub?.();
353
+ this._configWatchUnsub = null;
354
+ }
323
355
  // Synchronous pre-stop teardown
324
356
  this.watcherRegistry.stopWatcher('daemon-heartbeat', 'daemon-stopped');
325
357
  if (this.replyPoller !== null) {
@@ -346,6 +378,63 @@ export class DaemonServer {
346
378
  this.transportEventsHelper.emitTransportDisconnected('Daemon server stopped', false);
347
379
  logger.info('DaemonServer stopped');
348
380
  }
381
+ /**
382
+ * Subscribe to controlPlane binding keys and restart the server on change.
383
+ * Called once from start() after the server is up. Clears itself on stop().
384
+ */
385
+ _attachControlPlaneConfigWatcher() {
386
+ if (this._configWatchUnsub)
387
+ return; // idempotent
388
+ const restart = () => {
389
+ if (this._restarting) {
390
+ // A change arrived mid-restart — queue a second cycle via dirty flag.
391
+ // Check _restarting BEFORE isRunning: stop() runs synchronously inside the
392
+ // restart IIFE, so isRunning may be false even while a restart is in progress.
393
+ this._restartDirty = true;
394
+ return;
395
+ }
396
+ if (!this.isRunning)
397
+ return;
398
+ this._restarting = true;
399
+ this._restartingPromise = (async () => {
400
+ try {
401
+ logger.info('DaemonServer: controlPlane binding changed, restarting daemon server…');
402
+ await this.stop();
403
+ // Re-resolve host/port from updated config
404
+ const newBinding = resolveHostBinding(this.configManager.get('controlPlane.hostMode') ?? 'local', String(this.configManager.get('controlPlane.host') ?? '127.0.0.1'), Number(this.configManager.get('controlPlane.port') ?? 3421), 'controlPlane');
405
+ this.host = newBinding.host;
406
+ this.port = newBinding.port;
407
+ await this.start();
408
+ }
409
+ catch (err) {
410
+ logger.error('DaemonServer: restart after config change failed', { error: summarizeError(err) });
411
+ }
412
+ finally {
413
+ this._restarting = false;
414
+ // If a config change arrived while we were restarting, kick off a second
415
+ // cycle BEFORE nulling _restartingPromise so waitForRestart() chains correctly.
416
+ if (this._restartDirty) {
417
+ this._restartDirty = false;
418
+ restart(); // sets this._restartingPromise to the new cycle
419
+ }
420
+ else {
421
+ this._restartingPromise = null;
422
+ }
423
+ }
424
+ })();
425
+ };
426
+ // getIsRunning must also return true while a restart cycle is in progress
427
+ // (_restarting=true) so that config changes arriving mid-restart reach the
428
+ // dirty-flag path inside `restart`. When the server is intentionally stopped
429
+ // (not mid-restart) isRunning and _restarting are both false.
430
+ const watcher = createHostModeRestartWatcher({
431
+ configManager: this.configManager,
432
+ keys: ['controlPlane.hostMode', 'controlPlane.host', 'controlPlane.port'],
433
+ onRestart: restart,
434
+ getIsRunning: () => this.isRunning || this._restarting,
435
+ });
436
+ this._configWatchUnsub = () => watcher.unsubscribe();
437
+ }
349
438
  /**
350
439
  * Returns true if the server is currently running.
351
440
  */
@@ -0,0 +1,49 @@
1
+ /**
2
+ * host-mode-watcher.ts
3
+ *
4
+ * Shared helper that creates a config-key watcher for host-mode restart logic.
5
+ * Extracted so the restart guard + dirty-flag loop-back pattern can be tested
6
+ * independently of DaemonServer or HttpListener.
7
+ *
8
+ * Both facade.ts and http-listener.ts delegate to this helper, passing their
9
+ * own `onRestart` closure and `getIsRunning` accessor.
10
+ */
11
+ import type { ConfigManager } from '../config/manager.js';
12
+ import type { ConfigKey } from '@pellux/goodvibes-sdk/platform/config/schema';
13
+ export interface HostModeWatcherOptions {
14
+ /** The ConfigManager to subscribe on. */
15
+ configManager: ConfigManager;
16
+ /** Config keys that should trigger a restart when changed. */
17
+ keys: ConfigKey[];
18
+ /**
19
+ * Called when a key change is detected and the server is running.
20
+ * The implementation is responsible for performing stop + restart.
21
+ * The caller is responsible for re-entrancy / dirty-flag semantics: if a
22
+ * new change arrives while a prior restart is in progress, `onRestart`
23
+ * will be invoked again. The caller must either guard against overlapping
24
+ * cycles or queue the second cycle via its own dirty-flag mechanism.
25
+ */
26
+ onRestart: () => void;
27
+ /** Returns true when the server/listener is currently running. */
28
+ getIsRunning: () => boolean;
29
+ }
30
+ export interface HostModeWatcherHandle {
31
+ /** Detach all subscriptions — safe to call multiple times. */
32
+ unsubscribe: () => void;
33
+ }
34
+ /**
35
+ * Create a host-mode restart watcher.
36
+ *
37
+ * Behaviour:
38
+ * - Subscribes to each key in `keys`.
39
+ * - When a key changes and `getIsRunning()` is true, calls `onRestart()`.
40
+ * - The caller's `onRestart` implementation handles re-entrancy / dirty-flag
41
+ * logic internally (the watcher does NOT duplicate that logic).
42
+ * - `unsubscribe()` removes all subscriptions; subsequent key changes are
43
+ * silently ignored.
44
+ *
45
+ * @param opts - Watcher configuration.
46
+ * @returns A handle with an `unsubscribe` method.
47
+ */
48
+ export declare function createHostModeRestartWatcher(opts: HostModeWatcherOptions): HostModeWatcherHandle;
49
+ //# sourceMappingURL=host-mode-watcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-mode-watcher.d.ts","sourceRoot":"","sources":["../../../../src/_internal/platform/daemon/host-mode-watcher.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8CAA8C,CAAC;AAE9E,MAAM,WAAW,sBAAsB;IACrC,yCAAyC;IACzC,aAAa,EAAE,aAAa,CAAC;IAC7B,8DAA8D;IAC9D,IAAI,EAAE,SAAS,EAAE,CAAC;IAClB;;;;;;;OAOG;IACH,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,kEAAkE;IAClE,YAAY,EAAE,MAAM,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,qBAAqB;IACpC,8DAA8D;IAC9D,WAAW,EAAE,MAAM,IAAI,CAAC;CACzB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,sBAAsB,GAAG,qBAAqB,CAiBhG"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * host-mode-watcher.ts
3
+ *
4
+ * Shared helper that creates a config-key watcher for host-mode restart logic.
5
+ * Extracted so the restart guard + dirty-flag loop-back pattern can be tested
6
+ * independently of DaemonServer or HttpListener.
7
+ *
8
+ * Both facade.ts and http-listener.ts delegate to this helper, passing their
9
+ * own `onRestart` closure and `getIsRunning` accessor.
10
+ */
11
+ /**
12
+ * Create a host-mode restart watcher.
13
+ *
14
+ * Behaviour:
15
+ * - Subscribes to each key in `keys`.
16
+ * - When a key changes and `getIsRunning()` is true, calls `onRestart()`.
17
+ * - The caller's `onRestart` implementation handles re-entrancy / dirty-flag
18
+ * logic internally (the watcher does NOT duplicate that logic).
19
+ * - `unsubscribe()` removes all subscriptions; subsequent key changes are
20
+ * silently ignored.
21
+ *
22
+ * @param opts - Watcher configuration.
23
+ * @returns A handle with an `unsubscribe` method.
24
+ */
25
+ export function createHostModeRestartWatcher(opts) {
26
+ const { configManager, keys, onRestart, getIsRunning } = opts;
27
+ const listener = () => {
28
+ if (!getIsRunning())
29
+ return;
30
+ onRestart();
31
+ };
32
+ const unsubs = keys.map((key) => configManager.subscribe(key, listener));
33
+ return {
34
+ unsubscribe: () => {
35
+ for (const u of unsubs)
36
+ u();
37
+ // Clear the array so subsequent calls are no-ops.
38
+ unsubs.length = 0;
39
+ },
40
+ };
41
+ }
@@ -39,6 +39,14 @@ export declare class HttpListener {
39
39
  private readonly configManager;
40
40
  private readonly serveFactory;
41
41
  private tlsState;
42
+ /** Unsubscribe from httpListener config key watchers; cleared on stop(). */
43
+ private _configWatchUnsub;
44
+ /** True while a config-driven restart is in progress — prevents re-entrancy. */
45
+ private _restarting;
46
+ /** Awaitable promise for the active restart cycle; null when idle. */
47
+ private _restartingPromise;
48
+ /** True if a config change arrived while _restarting was set; triggers a second cycle. */
49
+ private _restartDirty;
42
50
  constructor(config: HttpListenerConfig);
43
51
  /**
44
52
  * Enable the listener. Requires danger.httpListener = true in config.
@@ -50,10 +58,19 @@ export declare class HttpListener {
50
58
  * Start listening. Refuses to start if not enabled.
51
59
  */
52
60
  start(): Promise<void>;
61
+ /**
62
+ * Wait for any in-progress config-driven restart to settle.
63
+ */
64
+ waitForRestart(): Promise<void>;
53
65
  /**
54
66
  * Stop the listener.
55
67
  */
56
68
  stop(): Promise<void>;
69
+ /**
70
+ * Subscribe to httpListener binding keys and restart the server on change.
71
+ * Called once from start() after the server is up. Clears itself on stop().
72
+ */
73
+ private _attachHttpListenerConfigWatcher;
57
74
  /**
58
75
  * Returns true if the listener is currently running.
59
76
  */
@@ -1 +1 @@
1
- {"version":3,"file":"http-listener.d.ts","sourceRoot":"","sources":["../../../../src/_internal/platform/daemon/http-listener.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAMxD,OAAO,EAAE,eAAe,EAAE,MAAM,mDAAmD,CAAC;AACpF,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAUrD,UAAU,kBAAkB;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,aAAa,EAAE,aAAa,CAAC;IAC7B,YAAY,CAAC,EAAE,OAAO,GAAG,CAAC,KAAK,CAAC;IAChC,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yEAAyE;IACzE,QAAQ,EAAE,eAAe,CAAC;CAC3B;AAED,UAAU,gBAAgB;IACxB,YAAY,EAAE,OAAO,CAAC;CACvB;AA0ED;;;;;;;;GAQG;AACH,qBAAa,YAAY;IAcX,OAAO,CAAC,MAAM;IAb1B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAA6C;IAC3D,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,cAAc,CAAW;IACjC,OAAO,CAAC,cAAc,CAAwB;IAC9C,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,QAAQ,CAAkB;IAClC,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgB;IAC9C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAmB;IAChD,OAAO,CAAC,QAAQ,CAA0C;gBAEtC,MAAM,EAAE,kBAAkB;IAiB9C;;;;OAIG;IACH,MAAM,CAAC,YAAY,EAAE,gBAAgB,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO;IAU/D;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAkC5B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAU3B;;OAEG;IACH,IAAI,SAAS,IAAI,OAAO,CAEvB;IAMD,OAAO,CAAC,SAAS;YAOH,aAAa;YAYb,aAAa;YAsCb,WAAW;YA6BX,aAAa;CAgD5B"}
1
+ {"version":3,"file":"http-listener.d.ts","sourceRoot":"","sources":["../../../../src/_internal/platform/daemon/http-listener.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAMxD,OAAO,EAAE,eAAe,EAAE,MAAM,mDAAmD,CAAC;AACpF,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAWrD,UAAU,kBAAkB;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,aAAa,EAAE,aAAa,CAAC;IAC7B,YAAY,CAAC,EAAE,OAAO,GAAG,CAAC,KAAK,CAAC;IAChC,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yEAAyE;IACzE,QAAQ,EAAE,eAAe,CAAC;CAC3B;AAED,UAAU,gBAAgB;IACxB,YAAY,EAAE,OAAO,CAAC;CACvB;AA0ED;;;;;;;;GAQG;AACH,qBAAa,YAAY;IAsBX,OAAO,CAAC,MAAM;IArB1B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAA6C;IAC3D,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,cAAc,CAAW;IACjC,OAAO,CAAC,cAAc,CAAwB;IAC9C,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,QAAQ,CAAkB;IAClC,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgB;IAC9C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAmB;IAChD,OAAO,CAAC,QAAQ,CAA0C;IAC1D,4EAA4E;IAC5E,OAAO,CAAC,iBAAiB,CAA6B;IACtD,gFAAgF;IAChF,OAAO,CAAC,WAAW,CAAS;IAC5B,sEAAsE;IACtE,OAAO,CAAC,kBAAkB,CAA8B;IACxD,0FAA0F;IAC1F,OAAO,CAAC,aAAa,CAAS;gBAEV,MAAM,EAAE,kBAAkB;IAiB9C;;;;OAIG;IACH,MAAM,CAAC,YAAY,EAAE,gBAAgB,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO;IAU/D;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAsC5B;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAKrC;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAoB3B;;;OAGG;IACH,OAAO,CAAC,gCAAgC;IAwDxC;;OAEG;IACH,IAAI,SAAS,IAAI,OAAO,CAEvB;IAMD,OAAO,CAAC,SAAS;YAOH,aAAa;YAYb,aAAa;YAsCb,WAAW;YA6BX,aAAa;CAgD5B"}
@@ -7,6 +7,7 @@ import { extractForwardedClientIp, resolveInboundTlsContext } from '../runtime/n
7
7
  import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils/error-display';
8
8
  import { requirePortAvailable } from './port-check.js';
9
9
  import { resolveHostBinding } from './host-resolver.js';
10
+ import { createHostModeRestartWatcher } from './host-mode-watcher.js';
10
11
  // ---------------------------------------------------------------------------
11
12
  // Rate limiter (sliding window per IP, in-memory)
12
13
  // ---------------------------------------------------------------------------
@@ -95,6 +96,14 @@ export class HttpListener {
95
96
  configManager;
96
97
  serveFactory;
97
98
  tlsState = null;
99
+ /** Unsubscribe from httpListener config key watchers; cleared on stop(). */
100
+ _configWatchUnsub = null;
101
+ /** True while a config-driven restart is in progress — prevents re-entrancy. */
102
+ _restarting = false;
103
+ /** Awaitable promise for the active restart cycle; null when idle. */
104
+ _restartingPromise = null;
105
+ /** True if a config change arrived while _restarting was set; triggers a second cycle. */
106
+ _restartDirty = false;
98
107
  constructor(config) {
99
108
  this.config = config;
100
109
  this.configManager = config.configManager;
@@ -136,7 +145,10 @@ export class HttpListener {
136
145
  logger.info('HttpListener: already running');
137
146
  return;
138
147
  }
139
- await requirePortAvailable(this.port, this.host, 'HTTP listener');
148
+ // Skip real OS port check when a mock serveFactory is injected (test-only path).
149
+ if (this.serveFactory === Bun.serve) {
150
+ await requirePortAvailable(this.port, this.host, 'HTTP listener');
151
+ }
140
152
  const self = this;
141
153
  this.tlsState = resolveInboundTlsContext(this.configManager, 'httpListener');
142
154
  this.server = this.serveFactory({
@@ -147,6 +159,7 @@ export class HttpListener {
147
159
  return self.handleRequest(req);
148
160
  },
149
161
  });
162
+ this._attachHttpListenerConfigWatcher();
150
163
  logger.info('HttpListener started', {
151
164
  port: this.port,
152
165
  host: this.host,
@@ -155,12 +168,28 @@ export class HttpListener {
155
168
  trustProxy: this.tlsState.trustProxy,
156
169
  });
157
170
  }
171
+ /**
172
+ * Wait for any in-progress config-driven restart to settle.
173
+ */
174
+ async waitForRestart() {
175
+ // Loop to handle dirty-flag chained restarts: each cycle may spawn another.
176
+ while (this._restartingPromise)
177
+ await this._restartingPromise;
178
+ }
158
179
  /**
159
180
  * Stop the listener.
160
181
  */
161
182
  async stop() {
162
183
  if (this.server === null)
163
184
  return;
185
+ // Tear down config watcher only on intentional stop, not mid-restart.
186
+ // During a restart cycle (_restarting=true) the watcher must stay active so
187
+ // config changes that arrive between stop() and the subsequent start() can be
188
+ // captured by the dirty flag.
189
+ if (!this._restarting) {
190
+ this._configWatchUnsub?.();
191
+ this._configWatchUnsub = null;
192
+ }
164
193
  // Stop rate limiter sweep interval before tearing down (C5 fix)
165
194
  this.rateLimiter.stop();
166
195
  this.server.stop(true);
@@ -168,6 +197,63 @@ export class HttpListener {
168
197
  this.tlsState = null;
169
198
  logger.info('HttpListener stopped');
170
199
  }
200
+ /**
201
+ * Subscribe to httpListener binding keys and restart the server on change.
202
+ * Called once from start() after the server is up. Clears itself on stop().
203
+ */
204
+ _attachHttpListenerConfigWatcher() {
205
+ if (this._configWatchUnsub)
206
+ return; // idempotent
207
+ const restart = () => {
208
+ if (this._restarting) {
209
+ // A change arrived mid-restart — queue a second cycle via dirty flag.
210
+ // Check _restarting BEFORE isRunning: stop() runs synchronously inside the
211
+ // restart IIFE, so isRunning may be false even while a restart is in progress.
212
+ this._restartDirty = true;
213
+ return;
214
+ }
215
+ if (!this.isRunning)
216
+ return;
217
+ this._restarting = true;
218
+ this._restartingPromise = (async () => {
219
+ try {
220
+ logger.info('HttpListener: httpListener binding changed, restarting HTTP listener…');
221
+ await this.stop();
222
+ // Re-resolve host/port from updated config
223
+ const newBinding = resolveHostBinding(this.configManager.get('httpListener.hostMode') ?? 'local', String(this.configManager.get('httpListener.host') ?? '127.0.0.1'), Number(this.configManager.get('httpListener.port') ?? 3422), 'httpListener');
224
+ this.host = newBinding.host;
225
+ this.port = newBinding.port;
226
+ await this.start();
227
+ }
228
+ catch (err) {
229
+ logger.error('HttpListener: restart after config change failed', { error: summarizeError(err) });
230
+ }
231
+ finally {
232
+ this._restarting = false;
233
+ // If a config change arrived while we were restarting, kick off a second
234
+ // cycle BEFORE nulling _restartingPromise so waitForRestart() chains correctly.
235
+ if (this._restartDirty) {
236
+ this._restartDirty = false;
237
+ restart(); // sets this._restartingPromise to the new cycle
238
+ }
239
+ else {
240
+ this._restartingPromise = null;
241
+ }
242
+ }
243
+ })();
244
+ };
245
+ // getIsRunning must also return true while a restart cycle is in progress
246
+ // (_restarting=true) so that config changes arriving mid-restart reach the
247
+ // dirty-flag path inside `restart`. When the server is intentionally stopped
248
+ // (not mid-restart) isRunning and _restarting are both false.
249
+ const watcher = createHostModeRestartWatcher({
250
+ configManager: this.configManager,
251
+ keys: ['httpListener.hostMode', 'httpListener.host', 'httpListener.port'],
252
+ onRestart: restart,
253
+ getIsRunning: () => this.isRunning || this._restarting,
254
+ });
255
+ this._configWatchUnsub = () => watcher.unsubscribe();
256
+ }
171
257
  /**
172
258
  * Returns true if the listener is currently running.
173
259
  */
@@ -1 +1 @@
1
- {"version":3,"file":"anthropic-compat.d.ts","sourceRoot":"","sources":["../../../../src/_internal/platform/providers/anthropic-compat.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,WAAW,EACX,YAAY,EACZ,uBAAuB,EACvB,2BAA2B,EAC5B,MAAM,gBAAgB,CAAC;AA6CxB,MAAM,WAAW,sBAAsB;IACrC,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAC;IACb,sFAAsF;IACtF,OAAO,EAAE,MAAM,CAAC;IAChB,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,4DAA4D;IAC5D,YAAY,EAAE,MAAM,CAAC;IACrB,iDAAiD;IACjD,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,0DAA0D;IAC1D,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,gFAAgF;IAChF,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,gFAAgF;IAChF,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,uEAAuE;IACvE,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,iGAAiG;IACjG,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,+DAA+D;IAC/D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qDAAqD;IACrD,cAAc,CAAC,EAAE,WAAW,GAAG,QAAQ,CAAC;IACxC,+CAA+C;IAC/C,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;;GAQG;AACH,qBAAa,uBAAwB,YAAW,WAAW;IACzD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;IAE1B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,cAAc,CAAyB;IAC/C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAoB;IAChD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAoB;IACjD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoB;IAC5C,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAC,CAAS;IACjD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAyB;IACxD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAU;IACzC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAU;IAC9C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAS;gBAE9B,IAAI,EAAE,sBAAsB;IAkBlC,IAAI,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IAwMhD,eAAe,CAAC,IAAI,EAAE,2BAA2B,GAAG,OAAO,CAAC,uBAAuB,CAAC;CA6C3F"}
1
+ {"version":3,"file":"anthropic-compat.d.ts","sourceRoot":"","sources":["../../../../src/_internal/platform/providers/anthropic-compat.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,WAAW,EACX,YAAY,EAEZ,uBAAuB,EACvB,2BAA2B,EAC5B,MAAM,gBAAgB,CAAC;AA8CxB,MAAM,WAAW,sBAAsB;IACrC,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAC;IACb,sFAAsF;IACtF,OAAO,EAAE,MAAM,CAAC;IAChB,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,4DAA4D;IAC5D,YAAY,EAAE,MAAM,CAAC;IACrB,iDAAiD;IACjD,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,0DAA0D;IAC1D,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,gFAAgF;IAChF,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,gFAAgF;IAChF,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,uEAAuE;IACvE,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,iGAAiG;IACjG,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,+DAA+D;IAC/D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qDAAqD;IACrD,cAAc,CAAC,EAAE,WAAW,GAAG,QAAQ,CAAC;IACxC,+CAA+C;IAC/C,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;;GAQG;AACH,qBAAa,uBAAwB,YAAW,WAAW;IACzD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;IAE1B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,cAAc,CAAyB;IAC/C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAoB;IAChD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAoB;IACjD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoB;IAC5C,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAC,CAAS;IACjD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAyB;IACxD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAU;IACzC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAU;IAC9C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAS;gBAE9B,IAAI,EAAE,sBAAsB;IAkBlC,IAAI,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IA4MhD,eAAe,CAAC,IAAI,EAAE,2BAA2B,GAAG,OAAO,CAAC,uBAAuB,CAAC;CA6C3F"}
@@ -1,5 +1,6 @@
1
1
  import { REASONING_BUDGET_MAP } from './interface.js';
2
2
  import { ProviderError } from '@pellux/goodvibes-sdk/platform/types/errors';
3
+ import { mapAnthropicStopReason } from './stop-reason-maps.js';
3
4
  import { withRetry } from '@pellux/goodvibes-sdk/platform/utils/retry';
4
5
  import { logger } from '@pellux/goodvibes-sdk/platform/utils/logger';
5
6
  import { toAnthropicTools, toAnthropicMessages, fromAnthropicContent, } from './tool-formats.js';
@@ -120,7 +121,8 @@ export class AnthropicCompatProvider {
120
121
  let outputTokens = 0;
121
122
  let cacheReadTokens = 0;
122
123
  let cacheWriteTokens = 0;
123
- let stopReason = 'end';
124
+ let rawStopReason;
125
+ let stopReason = 'unknown';
124
126
  // Accumulate tool use blocks by index
125
127
  const toolBlocks = new Map();
126
128
  const reader = res.body?.getReader();
@@ -188,10 +190,10 @@ export class AnthropicCompatProvider {
188
190
  }
189
191
  }
190
192
  else if (event.type === 'message_delta') {
191
- if (event.delta?.stop_reason === 'tool_use')
192
- stopReason = 'tool_use';
193
- else if (event.delta?.stop_reason === 'max_tokens')
194
- stopReason = 'max_tokens';
193
+ if (event.delta?.stop_reason) {
194
+ rawStopReason = event.delta.stop_reason;
195
+ stopReason = mapAnthropicStopReason(rawStopReason);
196
+ }
195
197
  if (event.usage?.output_tokens)
196
198
  outputTokens = event.usage.output_tokens;
197
199
  if (event.usage?.cache_read_input_tokens != null)
@@ -239,7 +241,8 @@ export class AnthropicCompatProvider {
239
241
  content: text,
240
242
  toolCalls,
241
243
  usage: { inputTokens, outputTokens, cacheReadTokens, cacheWriteTokens },
242
- stopReason,
244
+ stopReason: stopReason === 'unknown' && text ? 'completed' : stopReason,
245
+ ...(rawStopReason !== undefined ? { providerStopReason: rawStopReason } : {}),
243
246
  };
244
247
  });
245
248
  }
@@ -1 +1 @@
1
- {"version":3,"file":"anthropic-sdk-provider.d.ts","sourceRoot":"","sources":["../../../../src/_internal/platform/providers/anthropic-sdk-provider.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,WAAW,EACX,YAAY,EACZ,WAAW,EACX,uBAAuB,EACvB,2BAA2B,EAC5B,MAAM,gBAAgB,CAAC;AAexB,KAAK,4BAA4B,GAAG;IAClC,QAAQ,EAAE;QACR,MAAM,EAAE,OAAO,CAAC;KACjB,CAAC;CACH,CAAC;AAoBF,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,WAAW,CAAC;IACvC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IACvC,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;CACnC;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,YAAY,EAAE,MAAM,4BAA4B,CAAC;IAC1D,QAAQ,CAAC,IAAI,EAAE,8BAA8B,CAAC;IAC9C,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAED,qBAAa,oBAAqB,YAAW,WAAW;IAI1C,OAAO,CAAC,QAAQ,CAAC,OAAO;IAHpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;gBAEG,OAAO,EAAE,2BAA2B;IAK3D,IAAI,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IAkHhD,eAAe,CAAC,IAAI,EAAE,2BAA2B,GAAG,OAAO,CAAC,uBAAuB,CAAC;CAqC3F"}
1
+ {"version":3,"file":"anthropic-sdk-provider.d.ts","sourceRoot":"","sources":["../../../../src/_internal/platform/providers/anthropic-sdk-provider.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,WAAW,EACX,YAAY,EAEZ,WAAW,EACX,uBAAuB,EACvB,2BAA2B,EAC5B,MAAM,gBAAgB,CAAC;AAgBxB,KAAK,4BAA4B,GAAG;IAClC,QAAQ,EAAE;QACR,MAAM,EAAE,OAAO,CAAC;KACjB,CAAC;CACH,CAAC;AAoBF,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,WAAW,CAAC;IACvC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IACvC,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;CACnC;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,YAAY,EAAE,MAAM,4BAA4B,CAAC;IAC1D,QAAQ,CAAC,IAAI,EAAE,8BAA8B,CAAC;IAC9C,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAED,qBAAa,oBAAqB,YAAW,WAAW;IAI1C,OAAO,CAAC,QAAQ,CAAC,OAAO;IAHpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;gBAEG,OAAO,EAAE,2BAA2B;IAK3D,IAAI,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IAsHhD,eAAe,CAAC,IAAI,EAAE,2BAA2B,GAAG,OAAO,CAAC,uBAAuB,CAAC;CAqC3F"}