wave-agent-sdk 0.16.9 → 0.16.10

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.
@@ -1 +1 @@
1
- {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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"}
package/dist/agent.js CHANGED
@@ -9,6 +9,7 @@ import { ConfigurationService } from "./services/configurationService.js";
9
9
  import { setupAgentContainer } from "./utils/containerSetup.js";
10
10
  import { initializeTelemetry, shutdownTelemetry, } from "./telemetry/instrumentation.js";
11
11
  import { logOTelEvent } from "./telemetry/events.js";
12
+ import { remoteSettingsService } from "./services/remoteSettingsService.js";
12
13
  export class Agent {
13
14
  // Dynamic configuration getter methods
14
15
  getGatewayConfig() {
@@ -524,6 +525,8 @@ export class Agent {
524
525
  catch (error) {
525
526
  this.logger?.error("Error shutting down live configuration reload:", error);
526
527
  }
528
+ // Cleanup remote settings polling
529
+ remoteSettingsService.shutdown();
527
530
  // Cleanup memory store
528
531
  }
529
532
  /**
@@ -102,6 +102,7 @@ export declare class ConfigurationService {
102
102
  * Set the active model in the session
103
103
  */
104
104
  setModel(model: string): void;
105
+ private persistModelToSettings;
105
106
  /**
106
107
  * Get all configured models from settings.json and environment
107
108
  */
@@ -1 +1 @@
1
- {"version":3,"file":"configurationService.d.ts","sourceRoot":"","sources":["../../src/services/configurationService.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"configurationService.d.ts","sourceRoot":"","sources":["../../src/services/configurationService.ts"],"names":[],"mappings":"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"}
@@ -14,6 +14,7 @@ import { isValidEnvironmentVars, } from "../types/environment.js";
14
14
  import { ConfigurationError, CONFIG_ERRORS, } from "../types/index.js";
15
15
  import { DEFAULT_WAVE_MAX_INPUT_TOKENS, DEFAULT_WAVE_MAX_OUTPUT_TOKENS, } from "../utils/constants.js";
16
16
  import { parseCustomHeaders } from "../utils/stringUtils.js";
17
+ import { getRemoteSettingsSync, mergeRemoteSettings, } from "./remoteSettingsService.js";
17
18
  /**
18
19
  * Default ConfigurationService implementation
19
20
  *
@@ -62,17 +63,22 @@ export class ConfigurationService {
62
63
  warnings: validation.warnings,
63
64
  };
64
65
  }
66
+ // Merge remote settings (highest priority: Remote > Local > Project > User)
67
+ const remoteSettings = getRemoteSettingsSync();
68
+ const finalConfig = remoteSettings
69
+ ? mergeRemoteSettings(mergedConfig, remoteSettings)
70
+ : mergedConfig;
65
71
  // Success case
66
- this.currentConfiguration = mergedConfig;
72
+ this.currentConfiguration = finalConfig;
67
73
  // Set environment variables from merged config and inject system variables
68
74
  const env = {
69
- ...(mergedConfig.env || {}),
75
+ ...(finalConfig.env || {}),
70
76
  WAVE_PROJECT_DIR: workdir,
71
77
  };
72
78
  this.setEnvironmentVars(env);
73
- mergedConfig.env = env;
79
+ finalConfig.env = env;
74
80
  return {
75
- configuration: mergedConfig,
81
+ configuration: finalConfig,
76
82
  success: true,
77
83
  sourcePath: "merged configuration",
78
84
  warnings: validation.warnings,
@@ -394,7 +400,10 @@ export class ConfigurationService {
394
400
  */
395
401
  resolveModelConfig(model, fastModel, maxTokens, permissionMode) {
396
402
  // Resolve agent model: override > options > process.env (includes settings.json env)
397
- const resolvedAgentModel = model || this.options.model || process.env.WAVE_MODEL;
403
+ const resolvedAgentModel = model ||
404
+ this.options.model ||
405
+ process.env.WAVE_MODEL ||
406
+ this.currentConfiguration?.model;
398
407
  // Resolve fast model: override > options > process.env (includes settings.json env)
399
408
  const resolvedFastModel = fastModel || this.options.fastModel || process.env.WAVE_FAST_MODEL;
400
409
  // Validate required fields
@@ -547,6 +556,26 @@ export class ConfigurationService {
547
556
  */
548
557
  setModel(model) {
549
558
  this.options.model = model;
559
+ this.persistModelToSettings(model);
560
+ }
561
+ async persistModelToSettings(model) {
562
+ const configPath = getUserConfigPaths()[0]; // ~/.wave/settings.json
563
+ const configDir = path.dirname(configPath);
564
+ if (!existsSync(configDir)) {
565
+ await fs.mkdir(configDir, { recursive: true });
566
+ }
567
+ let config = {};
568
+ if (existsSync(configPath)) {
569
+ try {
570
+ const content = await fs.readFile(configPath, "utf-8");
571
+ config = JSON.parse(content);
572
+ }
573
+ catch {
574
+ // Start fresh if corrupted
575
+ }
576
+ }
577
+ config.model = model;
578
+ await fs.writeFile(configPath, JSON.stringify(config, null, 2), "utf-8");
550
579
  }
551
580
  /**
552
581
  * Get all configured models from settings.json and environment
@@ -558,6 +587,10 @@ export class ConfigurationService {
558
587
  if (currentModel) {
559
588
  models.add(currentModel);
560
589
  }
590
+ // Persisted model from settings (includes remote-merged)
591
+ if (this.currentConfiguration?.model) {
592
+ models.add(this.currentConfiguration.model);
593
+ }
561
594
  // Add models from merged configuration
562
595
  if (this.currentConfiguration?.models) {
563
596
  Object.keys(this.currentConfiguration.models).forEach((model) => {
@@ -894,6 +927,7 @@ export function loadWaveConfigFromFile(filePath) {
894
927
  permissions: config.permissions || undefined,
895
928
  enabledPlugins: config.enabledPlugins || undefined,
896
929
  language: config.language || undefined,
930
+ model: config.model || undefined,
897
931
  autoMemoryEnabled: config.autoMemoryEnabled !== undefined
898
932
  ? config.autoMemoryEnabled
899
933
  : undefined,
@@ -1007,6 +1041,10 @@ export function loadMergedWaveConfig(workdir) {
1007
1041
  if (config.language !== undefined) {
1008
1042
  mergedConfig.language = config.language;
1009
1043
  }
1044
+ // Merge model (last one wins)
1045
+ if (config.model !== undefined) {
1046
+ mergedConfig.model = config.model;
1047
+ }
1010
1048
  // Merge autoMemoryEnabled (last one wins)
1011
1049
  if (config.autoMemoryEnabled !== undefined) {
1012
1050
  mergedConfig.autoMemoryEnabled = config.autoMemoryEnabled;
@@ -1049,6 +1087,7 @@ export function loadMergedWaveConfig(workdir) {
1049
1087
  ? mergedConfig.enabledPlugins
1050
1088
  : undefined,
1051
1089
  language: mergedConfig.language,
1090
+ model: mergedConfig.model,
1052
1091
  autoMemoryEnabled: mergedConfig.autoMemoryEnabled,
1053
1092
  marketplaces: mergedConfig.marketplaces &&
1054
1093
  Object.keys(mergedConfig.marketplaces).length > 0
@@ -1 +1 @@
1
- {"version":3,"file":"initializationService.d.ts","sourceRoot":"","sources":["../../src/services/initializationService.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,OAAO,EACP,MAAM,EACN,YAAY,EACZ,WAAW,EACZ,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AAC9E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAC1E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAC1E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAGpD,MAAM,WAAW,qBAAqB;IACpC,YAAY,EAAE,YAAY,CAAC;IAC3B,eAAe,EAAE,eAAe,CAAC;IACjC,SAAS,EAAE,SAAS,CAAC;IACrB,WAAW,EAAE,WAAW,CAAC;IACzB,aAAa,EAAE,aAAa,CAAC;IAC7B,OAAO,EAAE,YAAY,CAAC;IACtB,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,UAAU,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,WAAW,CAAC;IACxB,oBAAoB,EAAE,oBAAoB,CAAC;IAC3C,WAAW,EAAE,WAAW,CAAC;IACzB,cAAc,EAAE,cAAc,CAAC;IAC/B,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,WAAW,EAAE,WAAW,CAAC;IACzB,wBAAwB,EAAE,MAAM,IAAI,CAAC;CACtC;AAED,qBAAa,qBAAqB;WACZ,UAAU,CAC5B,OAAO,EAAE,qBAAqB,EAC9B,OAAO,CAAC,EAAE;QACR,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,mBAAmB,CAAC,EAAE,OAAO,CAAC;QAC9B,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;KACtB,GACA,OAAO,CAAC,IAAI,CAAC;CAqRjB"}
1
+ {"version":3,"file":"initializationService.d.ts","sourceRoot":"","sources":["../../src/services/initializationService.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,OAAO,EACP,MAAM,EACN,YAAY,EACZ,WAAW,EACZ,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AAC9E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAC1E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAC1E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAIpD,MAAM,WAAW,qBAAqB;IACpC,YAAY,EAAE,YAAY,CAAC;IAC3B,eAAe,EAAE,eAAe,CAAC;IACjC,SAAS,EAAE,SAAS,CAAC;IACrB,WAAW,EAAE,WAAW,CAAC;IACzB,aAAa,EAAE,aAAa,CAAC;IAC7B,OAAO,EAAE,YAAY,CAAC;IACtB,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,UAAU,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,WAAW,CAAC;IACxB,oBAAoB,EAAE,oBAAoB,CAAC;IAC3C,WAAW,EAAE,WAAW,CAAC;IACzB,cAAc,EAAE,cAAc,CAAC;IAC/B,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,WAAW,EAAE,WAAW,CAAC;IACzB,wBAAwB,EAAE,MAAM,IAAI,CAAC;CACtC;AAED,qBAAa,qBAAqB;WACZ,UAAU,CAC5B,OAAO,EAAE,qBAAqB,EAC9B,OAAO,CAAC,EAAE;QACR,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,mBAAmB,CAAC,EAAE,OAAO,CAAC;QAC9B,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;KACtB,GACA,OAAO,CAAC,IAAI,CAAC;CAiSjB"}
@@ -2,6 +2,7 @@ import { handleSessionRestoration } from "./session.js";
2
2
  import { setGlobalLogger } from "../utils/globalLogger.js";
3
3
  import { LspManager } from "../managers/lspManager.js";
4
4
  import { USER_MEMORY_FILE } from "../utils/constants.js";
5
+ import { remoteSettingsService } from "./remoteSettingsService.js";
5
6
  export class InitializationService {
6
7
  static async initialize(context, options) {
7
8
  const { skillManager, subagentManager, container, toolManager, pluginManager, options: agentOptions, slashCommandManager, logger, mcpManager, workdir, lspManager, configurationService, hookManager, messageManager, memoryRuleManager, liveConfigManager, taskManager, resolveAndValidateConfig, } = context;
@@ -162,6 +163,16 @@ export class InitializationService {
162
163
  logger?.error("Failed to initialize live configuration reload:", error);
163
164
  // Don't throw error to prevent app startup failure - continue without live reload
164
165
  }
166
+ // Initialize remote settings (fetch server-managed config)
167
+ try {
168
+ const phaseStart = performance.now();
169
+ await remoteSettingsService.initialize();
170
+ logger?.debug(`Initialization Phase [Remote Settings] took ${(performance.now() - phaseStart).toFixed(2)}ms`);
171
+ }
172
+ catch (error) {
173
+ logger?.error("Failed to initialize remote settings:", error);
174
+ // Don't throw error to prevent app startup failure - continue without remote settings
175
+ }
165
176
  // Memory is lazy-cached on first getCombinedMemoryContent call
166
177
  // No explicit loading needed during initialization
167
178
  // Handle session restoration or set provided messages
@@ -0,0 +1,21 @@
1
+ import type { RemoteSettingsFetchResult } from "../types/configuration.js";
2
+ import type { WaveConfiguration } from "../types/configuration.js";
3
+ export declare function initialize(): void;
4
+ export declare function getRemoteSettingsSync(): WaveConfiguration | null;
5
+ export declare function refresh(): Promise<RemoteSettingsFetchResult>;
6
+ export declare function clear(): void;
7
+ export declare function shutdown(): void;
8
+ export declare function mergeRemoteSettings(localMerged: WaveConfiguration, remote: WaveConfiguration): WaveConfiguration;
9
+ /**
10
+ * Singleton object for consumers that prefer a namespace-style import.
11
+ * Usage: import { remoteSettingsService } from "./remoteSettingsService.js"
12
+ */
13
+ export declare const remoteSettingsService: {
14
+ readonly initialize: typeof initialize;
15
+ readonly getRemoteSettingsSync: typeof getRemoteSettingsSync;
16
+ readonly refresh: typeof refresh;
17
+ readonly clear: typeof clear;
18
+ readonly shutdown: typeof shutdown;
19
+ readonly mergeRemoteSettings: typeof mergeRemoteSettings;
20
+ };
21
+ //# sourceMappingURL=remoteSettingsService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remoteSettingsService.d.ts","sourceRoot":"","sources":["../../src/services/remoteSettingsService.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAEV,yBAAyB,EAE1B,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AA0JnE,wBAAgB,UAAU,IAAI,IAAI,CASjC;AAED,wBAAgB,qBAAqB,IAAI,iBAAiB,GAAG,IAAI,CAEhE;AAED,wBAAsB,OAAO,IAAI,OAAO,CAAC,yBAAyB,CAAC,CAKlE;AAED,wBAAgB,KAAK,IAAI,IAAI,CAO5B;AAED,wBAAgB,QAAQ,IAAI,IAAI,CAK/B;AAqCD,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,iBAAiB,EAC9B,MAAM,EAAE,iBAAiB,GACxB,iBAAiB,CA4DnB;AAED;;;GAGG;AACH,eAAO,MAAM,qBAAqB;;;;;;;CAOxB,CAAC"}
@@ -0,0 +1,279 @@
1
+ import * as fs from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import * as path from "node:path";
4
+ import { authService } from "./authService.js";
5
+ import { logger } from "../utils/globalLogger.js";
6
+ const CACHE_FILE = path.join(homedir(), ".wave", "remote-settings.json");
7
+ const POLLING_INTERVAL_MS = 60 * 60 * 1000; // 60 minutes
8
+ const FETCH_TIMEOUT_MS = 10000;
9
+ let _cachedSettings = null;
10
+ let _pollingTimer = null;
11
+ function loadCacheFromDisk() {
12
+ try {
13
+ if (!fs.existsSync(CACHE_FILE)) {
14
+ return;
15
+ }
16
+ const raw = fs.readFileSync(CACHE_FILE, "utf-8");
17
+ const parsed = JSON.parse(raw);
18
+ _cachedSettings = parsed;
19
+ logger.debug("remoteSettings: loaded cache from disk", {
20
+ checksum: parsed.checksum,
21
+ });
22
+ }
23
+ catch (err) {
24
+ logger.debug("remoteSettings: failed to load cache from disk", { err });
25
+ }
26
+ }
27
+ function writeCacheToDisk() {
28
+ if (!_cachedSettings) {
29
+ return;
30
+ }
31
+ try {
32
+ const dir = path.dirname(CACHE_FILE);
33
+ if (!fs.existsSync(dir)) {
34
+ fs.mkdirSync(dir, { recursive: true });
35
+ }
36
+ fs.writeFileSync(CACHE_FILE, JSON.stringify(_cachedSettings, null, 2), {
37
+ mode: 0o600,
38
+ });
39
+ logger.debug("remoteSettings: wrote cache to disk", {
40
+ checksum: _cachedSettings.checksum,
41
+ });
42
+ }
43
+ catch (err) {
44
+ logger.debug("remoteSettings: failed to write cache to disk", { err });
45
+ }
46
+ }
47
+ function removeCacheFromDisk() {
48
+ try {
49
+ if (fs.existsSync(CACHE_FILE)) {
50
+ fs.unlinkSync(CACHE_FILE);
51
+ }
52
+ }
53
+ catch (err) {
54
+ logger.debug("remoteSettings: failed to remove cache file", { err });
55
+ }
56
+ }
57
+ async function fetchRemoteSettings() {
58
+ if (!authService.isSSOAuthenticated()) {
59
+ logger.debug("remoteSettings: skipping fetch — not SSO authenticated");
60
+ return { success: false, error: "Not SSO authenticated" };
61
+ }
62
+ const token = authService.getSSOToken();
63
+ const serverUrl = authService.getServerUrl();
64
+ if (!token || !serverUrl) {
65
+ return { success: false, error: "Missing SSO token or server URL" };
66
+ }
67
+ const headers = {
68
+ Authorization: `Bearer ${token}`,
69
+ };
70
+ if (_cachedSettings?.checksum) {
71
+ headers["If-None-Match"] = _cachedSettings.checksum;
72
+ }
73
+ try {
74
+ const response = await fetch(`${serverUrl}/api/wave/settings`, {
75
+ method: "GET",
76
+ headers,
77
+ signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
78
+ });
79
+ if (response.status === 304) {
80
+ logger.debug("remoteSettings: 304 unchanged", {
81
+ checksum: _cachedSettings?.checksum,
82
+ });
83
+ return {
84
+ success: true,
85
+ settings: _cachedSettings.settings,
86
+ checksum: _cachedSettings.checksum,
87
+ };
88
+ }
89
+ if (response.status === 404) {
90
+ logger.debug("remoteSettings: 404 not configured — clearing stale cache");
91
+ _cachedSettings = null;
92
+ removeCacheFromDisk();
93
+ return { success: true, notConfigured: true, settings: null };
94
+ }
95
+ if (!response.ok) {
96
+ const body = await response.text().catch(() => "");
97
+ logger.debug("remoteSettings: fetch failed", {
98
+ status: response.status,
99
+ body: body.slice(0, 200),
100
+ });
101
+ return {
102
+ success: false,
103
+ error: `HTTP ${response.status}`,
104
+ settings: _cachedSettings?.settings ?? null,
105
+ };
106
+ }
107
+ const data = (await response.json());
108
+ _cachedSettings = {
109
+ uuid: data.uuid,
110
+ checksum: data.checksum,
111
+ settings: data.settings,
112
+ fetchedAt: new Date().toISOString(),
113
+ };
114
+ writeCacheToDisk();
115
+ logger.debug("remoteSettings: fetched new settings", {
116
+ checksum: data.checksum,
117
+ });
118
+ return {
119
+ success: true,
120
+ settings: data.settings,
121
+ checksum: data.checksum,
122
+ };
123
+ }
124
+ catch (err) {
125
+ logger.debug("remoteSettings: network error, using cache", { err });
126
+ return {
127
+ success: false,
128
+ error: err instanceof Error ? err.message : String(err),
129
+ settings: _cachedSettings?.settings ?? null,
130
+ };
131
+ }
132
+ }
133
+ function startPolling() {
134
+ if (_pollingTimer) {
135
+ return;
136
+ }
137
+ _pollingTimer = setInterval(async () => {
138
+ try {
139
+ await fetchRemoteSettings();
140
+ }
141
+ catch (err) {
142
+ logger.debug("remoteSettings: polling fetch error", { err });
143
+ }
144
+ }, POLLING_INTERVAL_MS);
145
+ _pollingTimer.unref();
146
+ }
147
+ export function initialize() {
148
+ loadCacheFromDisk();
149
+ // Fire-and-forget the initial fetch, then start background polling
150
+ fetchRemoteSettings()
151
+ .then(() => startPolling())
152
+ .catch((err) => {
153
+ logger.debug("remoteSettings: initial fetch failed", { err });
154
+ startPolling();
155
+ });
156
+ }
157
+ export function getRemoteSettingsSync() {
158
+ return _cachedSettings?.settings ?? null;
159
+ }
160
+ export async function refresh() {
161
+ // Clear in-memory so we force a fresh fetch
162
+ _cachedSettings = null;
163
+ removeCacheFromDisk();
164
+ return fetchRemoteSettings();
165
+ }
166
+ export function clear() {
167
+ _cachedSettings = null;
168
+ removeCacheFromDisk();
169
+ if (_pollingTimer) {
170
+ clearInterval(_pollingTimer);
171
+ _pollingTimer = null;
172
+ }
173
+ }
174
+ export function shutdown() {
175
+ if (_pollingTimer) {
176
+ clearInterval(_pollingTimer);
177
+ _pollingTimer = null;
178
+ }
179
+ }
180
+ function dedupe(arr) {
181
+ return [...new Set(arr)];
182
+ }
183
+ function mergeHooks(local, remote) {
184
+ if (!remote && !local) {
185
+ return undefined;
186
+ }
187
+ if (!remote) {
188
+ return local;
189
+ }
190
+ if (!local) {
191
+ return remote;
192
+ }
193
+ const merged = { ...local };
194
+ for (const [event, remoteHooks] of Object.entries(remote)) {
195
+ const localHooks = merged[event] ?? [];
196
+ // Concatenate + dedupe by JSON serialization
197
+ const combined = [...localHooks, ...(remoteHooks ?? [])];
198
+ const seen = new Set();
199
+ merged[event] = combined.filter((h) => {
200
+ const key = JSON.stringify(h);
201
+ if (seen.has(key)) {
202
+ return false;
203
+ }
204
+ seen.add(key);
205
+ return true;
206
+ });
207
+ }
208
+ return merged;
209
+ }
210
+ export function mergeRemoteSettings(localMerged, remote) {
211
+ const result = { ...localMerged };
212
+ // env: merge by key, remote wins per-key
213
+ if (remote.env || localMerged.env) {
214
+ result.env = { ...localMerged.env, ...remote.env };
215
+ }
216
+ // permissions
217
+ if (remote.permissions || localMerged.permissions) {
218
+ const lp = localMerged.permissions ?? {};
219
+ const rp = remote.permissions ?? {};
220
+ result.permissions = {
221
+ // allow: concatenate + dedupe
222
+ allow: lp.allow || rp.allow
223
+ ? dedupe([...(lp.allow ?? []), ...(rp.allow ?? [])])
224
+ : undefined,
225
+ // deny: concatenate + dedupe
226
+ deny: lp.deny || rp.deny
227
+ ? dedupe([...(lp.deny ?? []), ...(rp.deny ?? [])])
228
+ : undefined,
229
+ // permissionMode: remote wins (scalar)
230
+ permissionMode: rp.permissionMode ?? lp.permissionMode,
231
+ // additionalDirectories: concatenate + dedupe
232
+ additionalDirectories: lp.additionalDirectories || rp.additionalDirectories
233
+ ? dedupe([
234
+ ...(lp.additionalDirectories ?? []),
235
+ ...(rp.additionalDirectories ?? []),
236
+ ])
237
+ : undefined,
238
+ };
239
+ // Clean up undefined keys
240
+ if (!result.permissions.allow)
241
+ delete result.permissions.allow;
242
+ if (!result.permissions.deny)
243
+ delete result.permissions.deny;
244
+ if (!result.permissions.permissionMode)
245
+ delete result.permissions.permissionMode;
246
+ if (!result.permissions.additionalDirectories)
247
+ delete result.permissions.additionalDirectories;
248
+ }
249
+ // hooks: concatenate per-event
250
+ result.hooks = mergeHooks(localMerged.hooks, remote.hooks);
251
+ // Scalar / last-write-wins fields: remote wins
252
+ if (remote.language !== undefined)
253
+ result.language = remote.language;
254
+ if (remote.model !== undefined)
255
+ result.model = remote.model;
256
+ if (remote.autoMemoryEnabled !== undefined)
257
+ result.autoMemoryEnabled = remote.autoMemoryEnabled;
258
+ if (remote.autoMemoryFrequency !== undefined)
259
+ result.autoMemoryFrequency = remote.autoMemoryFrequency;
260
+ if (remote.models !== undefined)
261
+ result.models = remote.models;
262
+ if (remote.marketplaces !== undefined)
263
+ result.marketplaces = remote.marketplaces;
264
+ if (remote.enabledPlugins !== undefined)
265
+ result.enabledPlugins = remote.enabledPlugins;
266
+ return result;
267
+ }
268
+ /**
269
+ * Singleton object for consumers that prefer a namespace-style import.
270
+ * Usage: import { remoteSettingsService } from "./remoteSettingsService.js"
271
+ */
272
+ export const remoteSettingsService = {
273
+ initialize,
274
+ getRemoteSettingsSync,
275
+ refresh,
276
+ clear,
277
+ shutdown,
278
+ mergeRemoteSettings,
279
+ };
@@ -40,6 +40,8 @@ export interface WaveConfiguration {
40
40
  autoMemoryEnabled?: boolean;
41
41
  /** Frequency of auto-memory extraction turns */
42
42
  autoMemoryFrequency?: number;
43
+ /** Persisted model selection (from /model command) */
44
+ model?: string;
43
45
  /** Model-specific configuration overrides */
44
46
  models?: Record<string, Partial<ModelConfig>>;
45
47
  /** Scoped marketplace declarations */
@@ -124,5 +126,23 @@ interface Logger {
124
126
  info: (...args: unknown[]) => void;
125
127
  debug: (...args: unknown[]) => void;
126
128
  }
129
+ export interface RemoteSettingsResponse {
130
+ uuid: string;
131
+ checksum: string;
132
+ settings: WaveConfiguration;
133
+ }
134
+ export interface RemoteSettingsCache {
135
+ uuid: string;
136
+ checksum: string;
137
+ settings: WaveConfiguration;
138
+ fetchedAt: string;
139
+ }
140
+ export interface RemoteSettingsFetchResult {
141
+ success: boolean;
142
+ settings?: WaveConfiguration | null;
143
+ checksum?: string;
144
+ error?: string;
145
+ notConfigured?: boolean;
146
+ }
127
147
  export {};
128
148
  //# sourceMappingURL=configuration.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"configuration.d.ts","sourceRoot":"","sources":["../../src/types/configuration.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"configuration.d.ts","sourceRoot":"","sources":["../../src/types/configuration.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"containerSetup.d.ts","sourceRoot":"","sources":["../../src/utils/containerSetup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAwB3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAM3E,OAAO,KAAK,EAAE,YAAY,EAAmB,MAAM,mBAAmB,CAAC;AACvE,OAAO,KAAK,EACV,cAAc,EACd,KAAK,EACL,IAAI,EACJ,cAAc,EAEf,MAAM,mBAAmB,CAAC;AAK3B,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,oBAAoB,EAAE,oBAAoB,CAAC;IAC3C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,OAAO,CAAC;IAGhB,uBAAuB,EAAE,CAAC,KAAK,EAAE,cAAc,EAAE,KAAK,IAAI,CAAC;IAC3D,aAAa,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;IACvC,sBAAsB,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IACvD,wBAAwB,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IACzD,iBAAiB,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IAClD,iBAAiB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAED,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,0BAA0B,GACvC,SAAS,CA6RX"}
1
+ {"version":3,"file":"containerSetup.d.ts","sourceRoot":"","sources":["../../src/utils/containerSetup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAwB3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAM3E,OAAO,KAAK,EAAE,YAAY,EAAmB,MAAM,mBAAmB,CAAC;AACvE,OAAO,KAAK,EACV,cAAc,EACd,KAAK,EACL,IAAI,EACJ,cAAc,EAEf,MAAM,mBAAmB,CAAC;AAM3B,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,oBAAoB,EAAE,oBAAoB,CAAC;IAC3C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,OAAO,CAAC;IAGhB,uBAAuB,EAAE,CAAC,KAAK,EAAE,cAAc,EAAE,KAAK,IAAI,CAAC;IAC3D,aAAa,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;IACvC,sBAAsB,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IACvD,wBAAwB,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IACzD,iBAAiB,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IAClD,iBAAiB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAED,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,0BAA0B,GACvC,SAAS,CAsSX"}
@@ -29,6 +29,7 @@ import { USER_MEMORY_FILE } from "./constants.js";
29
29
  import { getGitMainRepoRoot } from "./gitUtils.js";
30
30
  import { logger } from "./globalLogger.js";
31
31
  import { authService } from "../services/authService.js";
32
+ import { remoteSettingsService } from "../services/remoteSettingsService.js";
32
33
  export function setupAgentContainer(setupOptions) {
33
34
  const { options, workdir, configurationService, systemPrompt, stream, onBackgroundTasksChange, onTasksChange, onPermissionModeChange, handlePlanModeTransition, setPermissionMode, addPermissionRule, addUsage, } = setupOptions;
34
35
  const callbacks = options.callbacks || {};
@@ -109,6 +110,15 @@ export function setupAgentContainer(setupOptions) {
109
110
  mcpManager.refreshCredentials(newServerUrl, newToken);
110
111
  }
111
112
  });
113
+ // Wire up auth change callback to refresh/clear remote settings
114
+ authService.onAuthChange((event) => {
115
+ if (event === "login") {
116
+ remoteSettingsService.refresh();
117
+ }
118
+ else if (event === "logout") {
119
+ remoteSettingsService.clear();
120
+ }
121
+ });
112
122
  const lspManager = options.lspManager || new LspManager(container);
113
123
  container.register("LspManager", lspManager);
114
124
  const permissionManager = new PermissionManager(container, {
@@ -1 +1 @@
1
- {"version":3,"file":"openaiClient.d.ts","sourceRoot":"","sources":["../../src/utils/openaiClient.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sCAAsC,EACtC,mCAAmC,EACnC,mBAAmB,EACnB,cAAc,EACf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGnD,KAAK,YAAY,GACb,sCAAsC,GACtC,mCAAmC,CAAC;AAExC,UAAU,WAAW,CAAC,CAAC;IACrB,IAAI,EAAE,CAAC,CAAC;IACR,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED,UAAU,UAAU,CAAC,CAAC,CAAE,SAAQ,OAAO,CAAC,CAAC,CAAC;IACxC,YAAY,IAAI,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;CACzC;AAED,qBAAa,YAAY;IACX,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,aAAa;IAEzC,IAAI,IAAI;;qBAGO,CAAC,SAAS,YAAY,UACrB,CAAC,YACC;gBAAE,MAAM,CAAC,EAAE,WAAW,CAAA;aAAE,KACjC,UAAU,CACX,CAAC,SAAS,mCAAmC,GACzC,aAAa,CAAC,mBAAmB,CAAC,GAClC,cAAc,CACnB;;MA2BN;YAEa,OAAO;YAqIN,oBAAoB;CAqCpC"}
1
+ {"version":3,"file":"openaiClient.d.ts","sourceRoot":"","sources":["../../src/utils/openaiClient.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sCAAsC,EACtC,mCAAmC,EACnC,mBAAmB,EACnB,cAAc,EACf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGnD,KAAK,YAAY,GACb,sCAAsC,GACtC,mCAAmC,CAAC;AAExC,UAAU,WAAW,CAAC,CAAC;IACrB,IAAI,EAAE,CAAC,CAAC;IACR,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED,UAAU,UAAU,CAAC,CAAC,CAAE,SAAQ,OAAO,CAAC,CAAC,CAAC;IACxC,YAAY,IAAI,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;CACzC;AAED,qBAAa,YAAY;IACX,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,aAAa;IAEzC,IAAI,IAAI;;qBAGO,CAAC,SAAS,YAAY,UACrB,CAAC,YACC;gBAAE,MAAM,CAAC,EAAE,WAAW,CAAA;aAAE,KACjC,UAAU,CACX,CAAC,SAAS,mCAAmC,GACzC,aAAa,CAAC,mBAAmB,CAAC,GAClC,cAAc,CACnB;;MA2BN;YAEa,OAAO;YAwIN,oBAAoB;CAqCpC"}
@@ -107,8 +107,10 @@ export class OpenAIClient {
107
107
  : response.statusText);
108
108
  error.status = response.status;
109
109
  error.body = errorBody;
110
- if (response.status === 429 && attempt < maxRetries) {
111
- logger.warn("OpenAI API 429 Too Many Requests, retrying...", {
110
+ const retryableStatus = response.status === 429 ||
111
+ (response.status >= 500 && response.status !== 501);
112
+ if (retryableStatus && attempt < maxRetries) {
113
+ logger.warn("OpenAI API error, retrying...", {
112
114
  attempt: attempt + 1,
113
115
  status: response.status,
114
116
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wave-agent-sdk",
3
- "version": "0.16.9",
3
+ "version": "0.16.10",
4
4
  "description": "SDK for building AI-powered development tools and agents",
5
5
  "keywords": [
6
6
  "ai",
package/src/agent.ts CHANGED
@@ -51,6 +51,7 @@ import {
51
51
  shutdownTelemetry,
52
52
  } from "./telemetry/instrumentation.js";
53
53
  import { logOTelEvent } from "./telemetry/events.js";
54
+ import { remoteSettingsService } from "./services/remoteSettingsService.js";
54
55
 
55
56
  export class Agent {
56
57
  private messageManager: MessageManager;
@@ -720,6 +721,8 @@ export class Agent {
720
721
  error,
721
722
  );
722
723
  }
724
+ // Cleanup remote settings polling
725
+ remoteSettingsService.shutdown();
723
726
  // Cleanup memory store
724
727
  }
725
728
 
@@ -44,6 +44,10 @@ import {
44
44
  } from "../utils/constants.js";
45
45
  import { ClientOptions } from "openai";
46
46
  import { parseCustomHeaders } from "../utils/stringUtils.js";
47
+ import {
48
+ getRemoteSettingsSync,
49
+ mergeRemoteSettings,
50
+ } from "./remoteSettingsService.js";
47
51
 
48
52
  /**
49
53
  * Default ConfigurationService implementation
@@ -101,19 +105,25 @@ export class ConfigurationService {
101
105
  };
102
106
  }
103
107
 
108
+ // Merge remote settings (highest priority: Remote > Local > Project > User)
109
+ const remoteSettings = getRemoteSettingsSync();
110
+ const finalConfig = remoteSettings
111
+ ? mergeRemoteSettings(mergedConfig, remoteSettings)
112
+ : mergedConfig;
113
+
104
114
  // Success case
105
- this.currentConfiguration = mergedConfig;
115
+ this.currentConfiguration = finalConfig;
106
116
 
107
117
  // Set environment variables from merged config and inject system variables
108
118
  const env = {
109
- ...(mergedConfig.env || {}),
119
+ ...(finalConfig.env || {}),
110
120
  WAVE_PROJECT_DIR: workdir,
111
121
  };
112
122
  this.setEnvironmentVars(env);
113
- mergedConfig.env = env;
123
+ finalConfig.env = env;
114
124
 
115
125
  return {
116
- configuration: mergedConfig,
126
+ configuration: finalConfig,
117
127
  success: true,
118
128
  sourcePath: "merged configuration",
119
129
  warnings: validation.warnings,
@@ -498,7 +508,10 @@ export class ConfigurationService {
498
508
  ): ModelConfig {
499
509
  // Resolve agent model: override > options > process.env (includes settings.json env)
500
510
  const resolvedAgentModel =
501
- model || this.options.model || process.env.WAVE_MODEL;
511
+ model ||
512
+ this.options.model ||
513
+ process.env.WAVE_MODEL ||
514
+ this.currentConfiguration?.model;
502
515
 
503
516
  // Resolve fast model: override > options > process.env (includes settings.json env)
504
517
  const resolvedFastModel =
@@ -686,6 +699,28 @@ export class ConfigurationService {
686
699
  */
687
700
  setModel(model: string): void {
688
701
  this.options.model = model;
702
+ this.persistModelToSettings(model);
703
+ }
704
+
705
+ private async persistModelToSettings(model: string): Promise<void> {
706
+ const configPath = getUserConfigPaths()[0]; // ~/.wave/settings.json
707
+ const configDir = path.dirname(configPath);
708
+ if (!existsSync(configDir)) {
709
+ await fs.mkdir(configDir, { recursive: true });
710
+ }
711
+
712
+ let config: WaveConfiguration = {};
713
+ if (existsSync(configPath)) {
714
+ try {
715
+ const content = await fs.readFile(configPath, "utf-8");
716
+ config = JSON.parse(content);
717
+ } catch {
718
+ // Start fresh if corrupted
719
+ }
720
+ }
721
+
722
+ config.model = model;
723
+ await fs.writeFile(configPath, JSON.stringify(config, null, 2), "utf-8");
689
724
  }
690
725
 
691
726
  /**
@@ -700,6 +735,11 @@ export class ConfigurationService {
700
735
  models.add(currentModel);
701
736
  }
702
737
 
738
+ // Persisted model from settings (includes remote-merged)
739
+ if (this.currentConfiguration?.model) {
740
+ models.add(this.currentConfiguration.model);
741
+ }
742
+
703
743
  // Add models from merged configuration
704
744
  if (this.currentConfiguration?.models) {
705
745
  Object.keys(this.currentConfiguration.models).forEach((model) => {
@@ -1129,6 +1169,7 @@ export function loadWaveConfigFromFile(
1129
1169
  permissions: config.permissions || undefined,
1130
1170
  enabledPlugins: config.enabledPlugins || undefined,
1131
1171
  language: config.language || undefined,
1172
+ model: config.model || undefined,
1132
1173
  autoMemoryEnabled:
1133
1174
  config.autoMemoryEnabled !== undefined
1134
1175
  ? config.autoMemoryEnabled
@@ -1258,6 +1299,11 @@ export function loadMergedWaveConfig(
1258
1299
  mergedConfig.language = config.language;
1259
1300
  }
1260
1301
 
1302
+ // Merge model (last one wins)
1303
+ if (config.model !== undefined) {
1304
+ mergedConfig.model = config.model;
1305
+ }
1306
+
1261
1307
  // Merge autoMemoryEnabled (last one wins)
1262
1308
  if (config.autoMemoryEnabled !== undefined) {
1263
1309
  mergedConfig.autoMemoryEnabled = config.autoMemoryEnabled;
@@ -1306,6 +1352,7 @@ export function loadMergedWaveConfig(
1306
1352
  ? mergedConfig.enabledPlugins
1307
1353
  : undefined,
1308
1354
  language: mergedConfig.language,
1355
+ model: mergedConfig.model,
1309
1356
  autoMemoryEnabled: mergedConfig.autoMemoryEnabled,
1310
1357
  marketplaces:
1311
1358
  mergedConfig.marketplaces &&
@@ -22,6 +22,7 @@ import type { MemoryRuleManager } from "../managers/MemoryRuleManager.js";
22
22
  import type { LiveConfigManager } from "../managers/liveConfigManager.js";
23
23
  import type { TaskManager } from "./taskManager.js";
24
24
  import type { PermissionManager } from "../managers/permissionManager.js";
25
+ import { remoteSettingsService } from "./remoteSettingsService.js";
25
26
 
26
27
  export interface InitializationContext {
27
28
  skillManager: SkillManager;
@@ -288,6 +289,18 @@ export class InitializationService {
288
289
  // Don't throw error to prevent app startup failure - continue without live reload
289
290
  }
290
291
 
292
+ // Initialize remote settings (fetch server-managed config)
293
+ try {
294
+ const phaseStart = performance.now();
295
+ await remoteSettingsService.initialize();
296
+ logger?.debug(
297
+ `Initialization Phase [Remote Settings] took ${(performance.now() - phaseStart).toFixed(2)}ms`,
298
+ );
299
+ } catch (error) {
300
+ logger?.error("Failed to initialize remote settings:", error);
301
+ // Don't throw error to prevent app startup failure - continue without remote settings
302
+ }
303
+
291
304
  // Memory is lazy-cached on first getCombinedMemoryContent call
292
305
  // No explicit loading needed during initialization
293
306
 
@@ -0,0 +1,314 @@
1
+ import * as fs from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import * as path from "node:path";
4
+
5
+ import { authService } from "./authService.js";
6
+ import type {
7
+ RemoteSettingsCache,
8
+ RemoteSettingsFetchResult,
9
+ RemoteSettingsResponse,
10
+ } from "../types/configuration.js";
11
+ import type { WaveConfiguration } from "../types/configuration.js";
12
+ import type { HookEvent, HookEventConfig } from "../types/hooks.js";
13
+ import { logger } from "../utils/globalLogger.js";
14
+
15
+ const CACHE_FILE = path.join(homedir(), ".wave", "remote-settings.json");
16
+ const POLLING_INTERVAL_MS = 60 * 60 * 1000; // 60 minutes
17
+ const FETCH_TIMEOUT_MS = 10_000;
18
+
19
+ let _cachedSettings: RemoteSettingsCache | null = null;
20
+ let _pollingTimer: ReturnType<typeof setInterval> | null = null;
21
+
22
+ function loadCacheFromDisk(): void {
23
+ try {
24
+ if (!fs.existsSync(CACHE_FILE)) {
25
+ return;
26
+ }
27
+ const raw = fs.readFileSync(CACHE_FILE, "utf-8");
28
+ const parsed: RemoteSettingsCache = JSON.parse(raw);
29
+ _cachedSettings = parsed;
30
+ logger.debug("remoteSettings: loaded cache from disk", {
31
+ checksum: parsed.checksum,
32
+ });
33
+ } catch (err) {
34
+ logger.debug("remoteSettings: failed to load cache from disk", { err });
35
+ }
36
+ }
37
+
38
+ function writeCacheToDisk(): void {
39
+ if (!_cachedSettings) {
40
+ return;
41
+ }
42
+ try {
43
+ const dir = path.dirname(CACHE_FILE);
44
+ if (!fs.existsSync(dir)) {
45
+ fs.mkdirSync(dir, { recursive: true });
46
+ }
47
+ fs.writeFileSync(CACHE_FILE, JSON.stringify(_cachedSettings, null, 2), {
48
+ mode: 0o600,
49
+ });
50
+ logger.debug("remoteSettings: wrote cache to disk", {
51
+ checksum: _cachedSettings.checksum,
52
+ });
53
+ } catch (err) {
54
+ logger.debug("remoteSettings: failed to write cache to disk", { err });
55
+ }
56
+ }
57
+
58
+ function removeCacheFromDisk(): void {
59
+ try {
60
+ if (fs.existsSync(CACHE_FILE)) {
61
+ fs.unlinkSync(CACHE_FILE);
62
+ }
63
+ } catch (err) {
64
+ logger.debug("remoteSettings: failed to remove cache file", { err });
65
+ }
66
+ }
67
+
68
+ async function fetchRemoteSettings(): Promise<RemoteSettingsFetchResult> {
69
+ if (!authService.isSSOAuthenticated()) {
70
+ logger.debug("remoteSettings: skipping fetch — not SSO authenticated");
71
+ return { success: false, error: "Not SSO authenticated" };
72
+ }
73
+
74
+ const token = authService.getSSOToken();
75
+ const serverUrl = authService.getServerUrl();
76
+ if (!token || !serverUrl) {
77
+ return { success: false, error: "Missing SSO token or server URL" };
78
+ }
79
+
80
+ const headers: Record<string, string> = {
81
+ Authorization: `Bearer ${token}`,
82
+ };
83
+ if (_cachedSettings?.checksum) {
84
+ headers["If-None-Match"] = _cachedSettings.checksum;
85
+ }
86
+
87
+ try {
88
+ const response = await fetch(`${serverUrl}/api/wave/settings`, {
89
+ method: "GET",
90
+ headers,
91
+ signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
92
+ });
93
+
94
+ if (response.status === 304) {
95
+ logger.debug("remoteSettings: 304 unchanged", {
96
+ checksum: _cachedSettings?.checksum,
97
+ });
98
+ return {
99
+ success: true,
100
+ settings: _cachedSettings!.settings,
101
+ checksum: _cachedSettings!.checksum,
102
+ };
103
+ }
104
+
105
+ if (response.status === 404) {
106
+ logger.debug("remoteSettings: 404 not configured — clearing stale cache");
107
+ _cachedSettings = null;
108
+ removeCacheFromDisk();
109
+ return { success: true, notConfigured: true, settings: null };
110
+ }
111
+
112
+ if (!response.ok) {
113
+ const body = await response.text().catch(() => "");
114
+ logger.debug("remoteSettings: fetch failed", {
115
+ status: response.status,
116
+ body: body.slice(0, 200),
117
+ });
118
+ return {
119
+ success: false,
120
+ error: `HTTP ${response.status}`,
121
+ settings: _cachedSettings?.settings ?? null,
122
+ };
123
+ }
124
+
125
+ const data = (await response.json()) as RemoteSettingsResponse;
126
+ _cachedSettings = {
127
+ uuid: data.uuid,
128
+ checksum: data.checksum,
129
+ settings: data.settings,
130
+ fetchedAt: new Date().toISOString(),
131
+ };
132
+ writeCacheToDisk();
133
+ logger.debug("remoteSettings: fetched new settings", {
134
+ checksum: data.checksum,
135
+ });
136
+ return {
137
+ success: true,
138
+ settings: data.settings,
139
+ checksum: data.checksum,
140
+ };
141
+ } catch (err) {
142
+ logger.debug("remoteSettings: network error, using cache", { err });
143
+ return {
144
+ success: false,
145
+ error: err instanceof Error ? err.message : String(err),
146
+ settings: _cachedSettings?.settings ?? null,
147
+ };
148
+ }
149
+ }
150
+
151
+ function startPolling(): void {
152
+ if (_pollingTimer) {
153
+ return;
154
+ }
155
+ _pollingTimer = setInterval(async () => {
156
+ try {
157
+ await fetchRemoteSettings();
158
+ } catch (err) {
159
+ logger.debug("remoteSettings: polling fetch error", { err });
160
+ }
161
+ }, POLLING_INTERVAL_MS);
162
+ _pollingTimer.unref();
163
+ }
164
+
165
+ export function initialize(): void {
166
+ loadCacheFromDisk();
167
+ // Fire-and-forget the initial fetch, then start background polling
168
+ fetchRemoteSettings()
169
+ .then(() => startPolling())
170
+ .catch((err) => {
171
+ logger.debug("remoteSettings: initial fetch failed", { err });
172
+ startPolling();
173
+ });
174
+ }
175
+
176
+ export function getRemoteSettingsSync(): WaveConfiguration | null {
177
+ return _cachedSettings?.settings ?? null;
178
+ }
179
+
180
+ export async function refresh(): Promise<RemoteSettingsFetchResult> {
181
+ // Clear in-memory so we force a fresh fetch
182
+ _cachedSettings = null;
183
+ removeCacheFromDisk();
184
+ return fetchRemoteSettings();
185
+ }
186
+
187
+ export function clear(): void {
188
+ _cachedSettings = null;
189
+ removeCacheFromDisk();
190
+ if (_pollingTimer) {
191
+ clearInterval(_pollingTimer);
192
+ _pollingTimer = null;
193
+ }
194
+ }
195
+
196
+ export function shutdown(): void {
197
+ if (_pollingTimer) {
198
+ clearInterval(_pollingTimer);
199
+ _pollingTimer = null;
200
+ }
201
+ }
202
+
203
+ function dedupe(arr: string[]): string[] {
204
+ return [...new Set(arr)];
205
+ }
206
+
207
+ function mergeHooks(
208
+ local: Partial<Record<HookEvent, HookEventConfig[]>> | undefined,
209
+ remote: Partial<Record<HookEvent, HookEventConfig[]>> | undefined,
210
+ ): Partial<Record<HookEvent, HookEventConfig[]>> | undefined {
211
+ if (!remote && !local) {
212
+ return undefined;
213
+ }
214
+ if (!remote) {
215
+ return local;
216
+ }
217
+ if (!local) {
218
+ return remote;
219
+ }
220
+ const merged: Partial<Record<HookEvent, HookEventConfig[]>> = { ...local };
221
+ for (const [event, remoteHooks] of Object.entries(remote)) {
222
+ const localHooks = merged[event as HookEvent] ?? [];
223
+ // Concatenate + dedupe by JSON serialization
224
+ const combined = [...localHooks, ...(remoteHooks ?? [])];
225
+ const seen = new Set<string>();
226
+ merged[event as HookEvent] = combined.filter((h) => {
227
+ const key = JSON.stringify(h);
228
+ if (seen.has(key)) {
229
+ return false;
230
+ }
231
+ seen.add(key);
232
+ return true;
233
+ });
234
+ }
235
+ return merged;
236
+ }
237
+
238
+ export function mergeRemoteSettings(
239
+ localMerged: WaveConfiguration,
240
+ remote: WaveConfiguration,
241
+ ): WaveConfiguration {
242
+ const result: WaveConfiguration = { ...localMerged };
243
+
244
+ // env: merge by key, remote wins per-key
245
+ if (remote.env || localMerged.env) {
246
+ result.env = { ...localMerged.env, ...remote.env };
247
+ }
248
+
249
+ // permissions
250
+ if (remote.permissions || localMerged.permissions) {
251
+ const lp = localMerged.permissions ?? {};
252
+ const rp = remote.permissions ?? {};
253
+ result.permissions = {
254
+ // allow: concatenate + dedupe
255
+ allow:
256
+ lp.allow || rp.allow
257
+ ? dedupe([...(lp.allow ?? []), ...(rp.allow ?? [])])
258
+ : undefined,
259
+ // deny: concatenate + dedupe
260
+ deny:
261
+ lp.deny || rp.deny
262
+ ? dedupe([...(lp.deny ?? []), ...(rp.deny ?? [])])
263
+ : undefined,
264
+ // permissionMode: remote wins (scalar)
265
+ permissionMode: rp.permissionMode ?? lp.permissionMode,
266
+ // additionalDirectories: concatenate + dedupe
267
+ additionalDirectories:
268
+ lp.additionalDirectories || rp.additionalDirectories
269
+ ? dedupe([
270
+ ...(lp.additionalDirectories ?? []),
271
+ ...(rp.additionalDirectories ?? []),
272
+ ])
273
+ : undefined,
274
+ };
275
+ // Clean up undefined keys
276
+ if (!result.permissions.allow) delete result.permissions.allow;
277
+ if (!result.permissions.deny) delete result.permissions.deny;
278
+ if (!result.permissions.permissionMode)
279
+ delete result.permissions.permissionMode;
280
+ if (!result.permissions.additionalDirectories)
281
+ delete result.permissions.additionalDirectories;
282
+ }
283
+
284
+ // hooks: concatenate per-event
285
+ result.hooks = mergeHooks(localMerged.hooks, remote.hooks);
286
+
287
+ // Scalar / last-write-wins fields: remote wins
288
+ if (remote.language !== undefined) result.language = remote.language;
289
+ if (remote.model !== undefined) result.model = remote.model;
290
+ if (remote.autoMemoryEnabled !== undefined)
291
+ result.autoMemoryEnabled = remote.autoMemoryEnabled;
292
+ if (remote.autoMemoryFrequency !== undefined)
293
+ result.autoMemoryFrequency = remote.autoMemoryFrequency;
294
+ if (remote.models !== undefined) result.models = remote.models;
295
+ if (remote.marketplaces !== undefined)
296
+ result.marketplaces = remote.marketplaces;
297
+ if (remote.enabledPlugins !== undefined)
298
+ result.enabledPlugins = remote.enabledPlugins;
299
+
300
+ return result;
301
+ }
302
+
303
+ /**
304
+ * Singleton object for consumers that prefer a namespace-style import.
305
+ * Usage: import { remoteSettingsService } from "./remoteSettingsService.js"
306
+ */
307
+ export const remoteSettingsService = {
308
+ initialize,
309
+ getRemoteSettingsSync,
310
+ refresh,
311
+ clear,
312
+ shutdown,
313
+ mergeRemoteSettings,
314
+ } as const;
@@ -44,6 +44,8 @@ export interface WaveConfiguration {
44
44
  autoMemoryEnabled?: boolean;
45
45
  /** Frequency of auto-memory extraction turns */
46
46
  autoMemoryFrequency?: number;
47
+ /** Persisted model selection (from /model command) */
48
+ model?: string;
47
49
  /** Model-specific configuration overrides */
48
50
  models?: Record<string, Partial<ModelConfig>>;
49
51
  /** Scoped marketplace declarations */
@@ -138,3 +140,24 @@ interface Logger {
138
140
  info: (...args: unknown[]) => void;
139
141
  debug: (...args: unknown[]) => void;
140
142
  }
143
+
144
+ export interface RemoteSettingsResponse {
145
+ uuid: string;
146
+ checksum: string;
147
+ settings: WaveConfiguration;
148
+ }
149
+
150
+ export interface RemoteSettingsCache {
151
+ uuid: string;
152
+ checksum: string;
153
+ settings: WaveConfiguration;
154
+ fetchedAt: string;
155
+ }
156
+
157
+ export interface RemoteSettingsFetchResult {
158
+ success: boolean;
159
+ settings?: WaveConfiguration | null;
160
+ checksum?: string;
161
+ error?: string;
162
+ notConfigured?: boolean;
163
+ }
@@ -39,6 +39,7 @@ import type {
39
39
 
40
40
  import { logger } from "./globalLogger.js";
41
41
  import { authService } from "../services/authService.js";
42
+ import { remoteSettingsService } from "../services/remoteSettingsService.js";
42
43
 
43
44
  export interface AgentContainerSetupOptions {
44
45
  options: AgentOptions;
@@ -170,6 +171,15 @@ export function setupAgentContainer(
170
171
  }
171
172
  });
172
173
 
174
+ // Wire up auth change callback to refresh/clear remote settings
175
+ authService.onAuthChange((event) => {
176
+ if (event === "login") {
177
+ remoteSettingsService.refresh();
178
+ } else if (event === "logout") {
179
+ remoteSettingsService.clear();
180
+ }
181
+ });
182
+
173
183
  const lspManager = options.lspManager || new LspManager(container);
174
184
  container.register("LspManager", lspManager);
175
185
 
@@ -176,8 +176,11 @@ export class OpenAIClient {
176
176
  error.status = response.status;
177
177
  error.body = errorBody;
178
178
 
179
- if (response.status === 429 && attempt < maxRetries) {
180
- logger.warn("OpenAI API 429 Too Many Requests, retrying...", {
179
+ const retryableStatus =
180
+ response.status === 429 ||
181
+ (response.status >= 500 && response.status !== 501);
182
+ if (retryableStatus && attempt < maxRetries) {
183
+ logger.warn("OpenAI API error, retrying...", {
181
184
  attempt: attempt + 1,
182
185
  status: response.status,
183
186
  });