wave-agent-sdk 0.17.11 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/builtin/skills/code-review/SKILL.md +137 -0
  2. package/builtin/skills/simplify/SKILL.md +55 -0
  3. package/dist/managers/aiManager.d.ts.map +1 -1
  4. package/dist/managers/aiManager.js +2 -7
  5. package/dist/managers/messageManager.d.ts +5 -5
  6. package/dist/managers/messageManager.d.ts.map +1 -1
  7. package/dist/managers/messageManager.js +18 -6
  8. package/dist/managers/skillManager.d.ts.map +1 -1
  9. package/dist/managers/skillManager.js +2 -1
  10. package/dist/managers/subagentManager.d.ts +5 -5
  11. package/dist/managers/subagentManager.d.ts.map +1 -1
  12. package/dist/managers/subagentManager.js +6 -6
  13. package/dist/services/authService.d.ts +2 -2
  14. package/dist/services/authService.d.ts.map +1 -1
  15. package/dist/services/authService.js +7 -7
  16. package/dist/services/remoteSettingsService.d.ts +6 -0
  17. package/dist/services/remoteSettingsService.d.ts.map +1 -1
  18. package/dist/services/remoteSettingsService.js +29 -0
  19. package/dist/utils/containerSetup.d.ts.map +1 -1
  20. package/dist/utils/containerSetup.js +7 -2
  21. package/dist/utils/messageOperations.d.ts +7 -1
  22. package/dist/utils/messageOperations.d.ts.map +1 -1
  23. package/dist/utils/messageOperations.js +6 -4
  24. package/package.json +1 -1
  25. package/src/managers/aiManager.ts +2 -7
  26. package/src/managers/messageManager.ts +40 -12
  27. package/src/managers/skillManager.ts +3 -1
  28. package/src/managers/subagentManager.ts +24 -9
  29. package/src/services/authService.ts +13 -10
  30. package/src/services/remoteSettingsService.ts +35 -0
  31. package/src/utils/containerSetup.ts +8 -2
  32. package/src/utils/messageOperations.ts +15 -5
  33. package/dist/utils/microcompact.d.ts +0 -7
  34. package/dist/utils/microcompact.d.ts.map +0 -1
  35. package/dist/utils/microcompact.js +0 -78
  36. package/src/utils/microcompact.ts +0 -101
@@ -101,9 +101,9 @@ export function setupAgentContainer(setupOptions) {
101
101
  });
102
102
  container.register("McpManager", mcpManager);
103
103
  // Wire up auth change callback to refresh/clear remote settings
104
- authService.onAuthChange((event) => {
104
+ authService.onAuthChange(async (event) => {
105
105
  if (event === "login") {
106
- remoteSettingsService.refresh();
106
+ await remoteSettingsService.refresh();
107
107
  }
108
108
  else if (event === "logout") {
109
109
  remoteSettingsService.clear();
@@ -215,6 +215,11 @@ export function setupAgentContainer(setupOptions) {
215
215
  },
216
216
  });
217
217
  container.register("LiveConfigManager", liveConfigManager);
218
+ // Wire up remote settings hot-update: when polling detects changed settings,
219
+ // reload configuration so admin changes propagate to the running agent.
220
+ remoteSettingsService.onSettingsUpdate(async () => {
221
+ await liveConfigManager.reload();
222
+ });
218
223
  const subagentManager = new SubagentManager(container, {
219
224
  workdir,
220
225
  callbacks: {
@@ -44,6 +44,9 @@ export interface UpdateToolBlockParams {
44
44
  timestamp?: number;
45
45
  }
46
46
  export type AgentToolBlockUpdateParams = Omit<UpdateToolBlockParams, "messages">;
47
+ export type ToolBlockUpdateCallbackParams = Omit<AgentToolBlockUpdateParams, "messageId"> & {
48
+ messageId: string;
49
+ };
47
50
  export interface AddErrorBlockParams {
48
51
  messages: Message[];
49
52
  error: string;
@@ -83,7 +86,10 @@ export declare const addToolBlockToMessageInMessages: (messages: Message[], mess
83
86
  messages: Message[];
84
87
  toolBlockId: string;
85
88
  };
86
- export declare const updateToolBlockInMessage: ({ messages, id, messageId, parameters, result, success, error, stage, name, shortResult, startLineNumber, images, compactParams, parametersChunk, isManuallyBackgrounded, }: UpdateToolBlockParams) => Message[];
89
+ export declare const updateToolBlockInMessage: ({ messages, id, messageId, parameters, result, success, error, stage, name, shortResult, startLineNumber, images, compactParams, parametersChunk, isManuallyBackgrounded, }: UpdateToolBlockParams) => {
90
+ messages: Message[];
91
+ messageId?: string;
92
+ };
87
93
  export declare const addErrorBlockToMessage: ({ messages, error, }: AddErrorBlockParams) => Message[];
88
94
  export declare const addBangMessage: ({ messages, command, }: AddBangParams) => Message[];
89
95
  export declare const updateBangInMessage: ({ messages, command, output, }: UpdateBangParams) => Message[];
@@ -1 +1 @@
1
- {"version":3,"file":"messageOperations.d.ts","sourceRoot":"","sources":["../../src/utils/messageOperations.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"messageOperations.d.ts","sourceRoot":"","sources":["../../src/utils/messageOperations.ts"],"names":[],"mappings":"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"}
@@ -193,7 +193,7 @@ export const updateToolBlockInMessage = ({ messages, id, messageId, parameters,
193
193
  }
194
194
  }
195
195
  }
196
- return newMessages;
196
+ return { messages: newMessages, messageId };
197
197
  }
198
198
  // Find the last assistant or user message
199
199
  for (let i = newMessages.length - 1; i >= 0; i--) {
@@ -225,7 +225,8 @@ export const updateToolBlockInMessage = ({ messages, id, messageId, parameters,
225
225
  if (isManuallyBackgrounded !== undefined)
226
226
  toolBlock.isManuallyBackgrounded = isManuallyBackgrounded;
227
227
  }
228
- break; // Found and updated, stop searching
228
+ const foundMessageId = newMessages[i].id;
229
+ return { messages: newMessages, messageId: foundMessageId };
229
230
  }
230
231
  else if (newMessages[i].role === "assistant") {
231
232
  // If existing block not found in assistant message, create new one
@@ -246,11 +247,12 @@ export const updateToolBlockInMessage = ({ messages, id, messageId, parameters,
246
247
  parametersChunk: parametersChunk,
247
248
  isManuallyBackgrounded: isManuallyBackgrounded,
248
249
  });
249
- break; // Created and added, stop searching
250
+ const foundMessageId = newMessages[i].id;
251
+ return { messages: newMessages, messageId: foundMessageId };
250
252
  }
251
253
  }
252
254
  }
253
- return newMessages;
255
+ return { messages: newMessages };
254
256
  };
255
257
  // Add Error Block to the last assistant message
256
258
  export const addErrorBlockToMessage = ({ messages, error, }) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wave-agent-sdk",
3
- "version": "0.17.11",
3
+ "version": "0.18.0",
4
4
  "description": "SDK for building AI-powered development tools and agents",
5
5
  "keywords": [
6
6
  "ai",
@@ -1,7 +1,6 @@
1
1
  import { type CallAgentOptions } from "../services/aiService.js";
2
2
  import * as aiService from "../services/aiService.js";
3
3
  import { convertMessagesForAPI } from "../utils/convertMessagesForAPI.js";
4
- import { microcompactMessages } from "../utils/microcompact.js";
5
4
  import { parseTaskNotificationXml } from "../utils/notificationXml.js";
6
5
  import { calculateComprehensiveTotalTokens } from "../utils/tokenCalculation.js";
7
6
  import {
@@ -819,13 +818,9 @@ export class AIManager {
819
818
  // Add plan mode reminder as persistent meta message before getting messages
820
819
  this.maybeAddPlanModeMessage(currentMode);
821
820
 
822
- // Get recent message history with microcompact applied
821
+ // Get recent message history
823
822
  const rawMessages = this.messageManager.getMessages();
824
- const microcompactedMessages = microcompactMessages(rawMessages, {
825
- timeThresholdMS: 30 * 60 * 1000, // 30 minutes
826
- recentResultsToKeep: 3,
827
- });
828
- const recentMessages = convertMessagesForAPI(microcompactedMessages);
823
+ const recentMessages = convertMessagesForAPI(rawMessages);
829
824
 
830
825
  try {
831
826
  // Get combined memory content
@@ -12,6 +12,7 @@ import {
12
12
  addNotificationMessageToMessages,
13
13
  UserMessageParams,
14
14
  type AgentToolBlockUpdateParams,
15
+ type ToolBlockUpdateCallbackParams,
15
16
  type AddNotificationMessageParams,
16
17
  generateMessageId,
17
18
  } from "../utils/messageOperations.js";
@@ -40,12 +41,20 @@ export interface MessageManagerCallbacks {
40
41
  // Incremental callback
41
42
  onUserMessageAdded?: (params: UserMessageParams) => void;
42
43
  // MODIFIED: Remove arguments for separation of concerns
43
- onAssistantMessageAdded?: () => void;
44
+ onAssistantMessageAdded?: (messageId: string) => void;
44
45
  // NEW: Streaming content callback - FR-001: receives chunk and accumulated content
45
- onAssistantContentUpdated?: (chunk: string, accumulated: string) => void;
46
+ onAssistantContentUpdated?: (
47
+ messageId: string,
48
+ chunk: string,
49
+ accumulated: string,
50
+ ) => void;
46
51
  // NEW: Streaming reasoning callback
47
- onAssistantReasoningUpdated?: (chunk: string, accumulated: string) => void;
48
- onToolBlockUpdated?: (params: AgentToolBlockUpdateParams) => void;
52
+ onAssistantReasoningUpdated?: (
53
+ messageId: string,
54
+ chunk: string,
55
+ accumulated: string,
56
+ ) => void;
57
+ onToolBlockUpdated?: (params: ToolBlockUpdateCallbackParams) => void;
49
58
  onErrorBlockAdded?: (error: string) => void;
50
59
  onCompactBlockAdded?: (content: string) => void;
51
60
  onCompactionStateChange?: (isCompacting: boolean) => void;
@@ -419,7 +428,8 @@ export class MessageManager {
419
428
  additionalFieldsRecord,
420
429
  );
421
430
  this.setMessages(newMessages);
422
- this.callbacks.onAssistantMessageAdded?.();
431
+ const messageId = this.messages[this.messages.length - 1]?.id;
432
+ this.callbacks.onAssistantMessageAdded?.(messageId);
423
433
 
424
434
  // Note: Subagent-specific callbacks are now handled by SubagentManager
425
435
  }
@@ -460,12 +470,21 @@ export class MessageManager {
460
470
  public updateToolBlock(params: AgentToolBlockUpdateParams): void {
461
471
  // Finalize any streaming text/reasoning blocks before adding/updating a tool block
462
472
  this.finalizeCurrentStreamingBlocks();
463
- const newMessages = updateToolBlockInMessage({
464
- messages: this.messages,
465
- ...params,
466
- });
473
+ const { messages: newMessages, messageId: resolvedMessageId } =
474
+ updateToolBlockInMessage({
475
+ messages: this.messages,
476
+ ...params,
477
+ });
467
478
  this.setMessages(newMessages);
468
- this.callbacks.onToolBlockUpdated?.(params);
479
+ const callbackParams: ToolBlockUpdateCallbackParams = {
480
+ ...params,
481
+ messageId:
482
+ params.messageId ||
483
+ resolvedMessageId ||
484
+ this.messages[this.messages.length - 1]?.id ||
485
+ "",
486
+ };
487
+ this.callbacks.onToolBlockUpdated?.(callbackParams);
469
488
 
470
489
  // Note: Subagent-specific callbacks are now handled by SubagentManager
471
490
  }
@@ -482,7 +501,11 @@ export class MessageManager {
482
501
  const { messages: newMessages, toolBlockId } =
483
502
  addToolBlockToMessageInMessages(this.messages, messageId, params);
484
503
  this.setMessages(newMessages);
485
- this.callbacks.onToolBlockUpdated?.({ ...params, id: toolBlockId });
504
+ this.callbacks.onToolBlockUpdated?.({
505
+ ...params,
506
+ id: toolBlockId,
507
+ messageId,
508
+ });
486
509
  return toolBlockId;
487
510
  }
488
511
 
@@ -722,7 +745,11 @@ export class MessageManager {
722
745
  }
723
746
 
724
747
  // FR-001: Trigger callbacks with chunk and accumulated content
725
- this.callbacks.onAssistantContentUpdated?.(chunk, newAccumulatedContent);
748
+ this.callbacks.onAssistantContentUpdated?.(
749
+ lastMessage.id,
750
+ chunk,
751
+ newAccumulatedContent,
752
+ );
726
753
 
727
754
  // Note: Subagent-specific callbacks are now handled by SubagentManager
728
755
 
@@ -793,6 +820,7 @@ export class MessageManager {
793
820
 
794
821
  // Trigger callbacks with chunk and accumulated reasoning content
795
822
  this.callbacks.onAssistantReasoningUpdated?.(
823
+ lastMessage.id,
796
824
  chunk,
797
825
  newAccumulatedReasoning,
798
826
  );
@@ -503,7 +503,9 @@ export class SkillManager extends EventEmitter {
503
503
  private async executeBashInSkillContent(content: string): Promise<string> {
504
504
  const { commands } = parseBashCommands(content);
505
505
  if (commands.length > 0) {
506
- const results = await executeBashCommands(commands, this.workdir);
506
+ const currentWorkdir =
507
+ this.container.get<string>("Workdir") ?? this.workdir;
508
+ const results = await executeBashCommands(commands, currentWorkdir);
507
509
  return replaceBashCommandsWithOutput(content, results);
508
510
  }
509
511
  return content;
@@ -17,7 +17,7 @@ import { NotificationQueue } from "./notificationQueue.js";
17
17
  import { logger } from "../utils/globalLogger.js";
18
18
  import {
19
19
  UserMessageParams,
20
- type AgentToolBlockUpdateParams,
20
+ type ToolBlockUpdateCallbackParams,
21
21
  } from "../utils/messageOperations.js";
22
22
 
23
23
  import { Container } from "../utils/container.js";
@@ -26,30 +26,35 @@ import type { PermissionMode } from "../types/permissions.js";
26
26
  import { ConfigurationService } from "../services/configurationService.js";
27
27
 
28
28
  export interface SubagentManagerCallbacks {
29
- // Granular subagent message callbacks (015-subagent-message-callbacks)
29
+ // Granular subagent message callbacks (009-subagent)
30
30
  /** Triggered when subagent adds user message */
31
31
  onSubagentUserMessageAdded?: (
32
32
  subagentId: string,
33
33
  params: UserMessageParams,
34
34
  ) => void;
35
35
  /** Triggered when subagent creates assistant message */
36
- onSubagentAssistantMessageAdded?: (subagentId: string) => void;
36
+ onSubagentAssistantMessageAdded?: (
37
+ subagentId: string,
38
+ messageId: string,
39
+ ) => void;
37
40
  /** Triggered during subagent content streaming updates */
38
41
  onSubagentAssistantContentUpdated?: (
39
42
  subagentId: string,
43
+ messageId: string,
40
44
  chunk: string,
41
45
  accumulated: string,
42
46
  ) => void;
43
47
  /** Triggered during subagent reasoning streaming updates */
44
48
  onSubagentAssistantReasoningUpdated?: (
45
49
  subagentId: string,
50
+ messageId: string,
46
51
  chunk: string,
47
52
  accumulated: string,
48
53
  ) => void;
49
54
  /** Triggered when subagent tool block is updated */
50
55
  onSubagentToolBlockUpdated?: (
51
56
  subagentId: string,
52
- params: AgentToolBlockUpdateParams,
57
+ params: ToolBlockUpdateCallbackParams,
53
58
  ) => void;
54
59
  /** Triggered when subagent messages change */
55
60
  onSubagentMessagesChange?: (subagentId: string, messages: Message[]) => void;
@@ -777,35 +782,45 @@ export class SubagentManager {
777
782
  }
778
783
  },
779
784
 
780
- onAssistantMessageAdded: () => {
785
+ onAssistantMessageAdded: (messageId: string) => {
781
786
  // Forward assistant message events to parent via SubagentManager callbacks
782
787
  if (this.callbacks?.onSubagentAssistantMessageAdded) {
783
- this.callbacks.onSubagentAssistantMessageAdded(subagentId);
788
+ this.callbacks.onSubagentAssistantMessageAdded(subagentId, messageId);
784
789
  }
785
790
  },
786
791
 
787
- onAssistantContentUpdated: (chunk: string, accumulated: string) => {
792
+ onAssistantContentUpdated: (
793
+ messageId: string,
794
+ chunk: string,
795
+ accumulated: string,
796
+ ) => {
788
797
  // Forward assistant content updates to parent via SubagentManager callbacks
789
798
  if (this.callbacks?.onSubagentAssistantContentUpdated) {
790
799
  this.callbacks.onSubagentAssistantContentUpdated(
791
800
  subagentId,
801
+ messageId,
792
802
  chunk,
793
803
  accumulated,
794
804
  );
795
805
  }
796
806
  },
797
- onAssistantReasoningUpdated: (chunk: string, accumulated: string) => {
807
+ onAssistantReasoningUpdated: (
808
+ messageId: string,
809
+ chunk: string,
810
+ accumulated: string,
811
+ ) => {
798
812
  // Forward assistant reasoning updates to parent via SubagentManager callbacks
799
813
  if (this.callbacks?.onSubagentAssistantReasoningUpdated) {
800
814
  this.callbacks.onSubagentAssistantReasoningUpdated(
801
815
  subagentId,
816
+ messageId,
802
817
  chunk,
803
818
  accumulated,
804
819
  );
805
820
  }
806
821
  },
807
822
 
808
- onToolBlockUpdated: (params: AgentToolBlockUpdateParams) => {
823
+ onToolBlockUpdated: (params: ToolBlockUpdateCallbackParams) => {
809
824
  const instance = this.instances.get(subagentId);
810
825
  if (instance) {
811
826
  // Log tool execution to file only when finalized
@@ -28,8 +28,9 @@ let _anonymousId: string | undefined;
28
28
  export class AuthService {
29
29
  private static instance: AuthService;
30
30
  private _serverUrl: string | undefined;
31
- private onAuthChangeCallbacks: Array<(event: "login" | "logout") => void> =
32
- [];
31
+ private onAuthChangeCallbacks: Array<
32
+ (event: "login" | "logout") => void | Promise<void>
33
+ > = [];
33
34
  private _refreshPromise: Promise<boolean> | null = null;
34
35
  private _authFileMtime: number = 0;
35
36
  private static readonly REFRESH_BUFFER_MS = 5 * 60 * 1000;
@@ -53,7 +54,9 @@ export class AuthService {
53
54
  * Register a callback for auth state changes.
54
55
  * Returns an unsubscribe function.
55
56
  */
56
- onAuthChange(callback: (event: "login" | "logout") => void): () => void {
57
+ onAuthChange(
58
+ callback: (event: "login" | "logout") => void | Promise<void>,
59
+ ): () => void {
57
60
  this.onAuthChangeCallbacks.push(callback);
58
61
  return () => {
59
62
  this.onAuthChangeCallbacks = this.onAuthChangeCallbacks.filter(
@@ -62,10 +65,10 @@ export class AuthService {
62
65
  };
63
66
  }
64
67
 
65
- private notifyAuthChange(event: "login" | "logout"): void {
68
+ private async notifyAuthChange(event: "login" | "logout"): Promise<void> {
66
69
  for (const cb of this.onAuthChangeCallbacks) {
67
70
  try {
68
- cb(event);
71
+ await cb(event);
69
72
  } catch {
70
73
  // Don't let callback errors break auth flow
71
74
  }
@@ -112,7 +115,7 @@ export class AuthService {
112
115
  }
113
116
  }
114
117
 
115
- clearAuth(): void {
118
+ async clearAuth(): Promise<void> {
116
119
  const config = this.loadAuth();
117
120
  delete config.SSO_TOKEN;
118
121
  delete config.SSO_REFRESH_TOKEN;
@@ -125,7 +128,7 @@ export class AuthService {
125
128
  } else {
126
129
  this.saveAuth(config);
127
130
  }
128
- this.notifyAuthChange("logout");
131
+ await this.notifyAuthChange("logout");
129
132
  }
130
133
 
131
134
  getSSOToken(): string | undefined {
@@ -177,7 +180,7 @@ export class AuthService {
177
180
  user,
178
181
  });
179
182
 
180
- this.notifyAuthChange("login");
183
+ await this.notifyAuthChange("login");
181
184
 
182
185
  return token;
183
186
  }
@@ -385,7 +388,7 @@ export class AuthService {
385
388
  logger.info(
386
389
  `[Auth] Refresh token rejected (${response.status}), clearing auth`,
387
390
  );
388
- this.clearAuth();
391
+ await this.clearAuth();
389
392
  return false;
390
393
  }
391
394
 
@@ -412,7 +415,7 @@ export class AuthService {
412
415
  logger.info(
413
416
  `[Auth] Token refreshed successfully, new token expires at ${newExpiresAt ? new Date(newExpiresAt).toISOString() : "never"}`,
414
417
  );
415
- this.notifyAuthChange("login");
418
+ await this.notifyAuthChange("login");
416
419
  return true;
417
420
  } catch (err) {
418
421
  // Network error — don't clear auth (might be transient)
@@ -18,6 +18,32 @@ const FETCH_TIMEOUT_MS = 10_000;
18
18
 
19
19
  let _cachedSettings: RemoteSettingsCache | null = null;
20
20
  let _pollingTimer: ReturnType<typeof setInterval> | null = null;
21
+ let _onSettingsUpdateCallbacks: Array<() => void | Promise<void>> = [];
22
+
23
+ /**
24
+ * Register a callback invoked when remote settings change (checksum differs).
25
+ * Returns an unsubscribe function.
26
+ */
27
+ export function onSettingsUpdate(
28
+ callback: () => void | Promise<void>,
29
+ ): () => void {
30
+ _onSettingsUpdateCallbacks.push(callback);
31
+ return () => {
32
+ _onSettingsUpdateCallbacks = _onSettingsUpdateCallbacks.filter(
33
+ (cb) => cb !== callback,
34
+ );
35
+ };
36
+ }
37
+
38
+ async function notifySettingsUpdate(): Promise<void> {
39
+ for (const cb of _onSettingsUpdateCallbacks) {
40
+ try {
41
+ await cb();
42
+ } catch {
43
+ // Don't let callback errors break the fetch flow
44
+ }
45
+ }
46
+ }
21
47
 
22
48
  function loadCacheFromDisk(): void {
23
49
  try {
@@ -77,6 +103,8 @@ async function fetchRemoteSettings(): Promise<RemoteSettingsFetchResult> {
77
103
  return { success: false, error: "Missing SSO token or server URL" };
78
104
  }
79
105
 
106
+ const oldChecksum = _cachedSettings?.checksum;
107
+
80
108
  const headers: Record<string, string> = {
81
109
  Authorization: `Bearer ${token}`,
82
110
  };
@@ -107,6 +135,9 @@ async function fetchRemoteSettings(): Promise<RemoteSettingsFetchResult> {
107
135
  logger.debug("remoteSettings: 404 not configured — clearing stale cache");
108
136
  _cachedSettings = null;
109
137
  removeCacheFromDisk();
138
+ if (oldChecksum) {
139
+ await notifySettingsUpdate();
140
+ }
110
141
  return { success: true, notConfigured: true, settings: null };
111
142
  }
112
143
 
@@ -134,6 +165,9 @@ async function fetchRemoteSettings(): Promise<RemoteSettingsFetchResult> {
134
165
  logger.debug("remoteSettings: fetched new settings", {
135
166
  checksum: data.checksum,
136
167
  });
168
+ if (data.checksum !== oldChecksum) {
169
+ await notifySettingsUpdate();
170
+ }
137
171
  return {
138
172
  success: true,
139
173
  settings: data.settings,
@@ -312,4 +346,5 @@ export const remoteSettingsService = {
312
346
  clear,
313
347
  shutdown,
314
348
  mergeRemoteSettings,
349
+ onSettingsUpdate,
315
350
  } as const;
@@ -161,9 +161,9 @@ export function setupAgentContainer(
161
161
  container.register("McpManager", mcpManager);
162
162
 
163
163
  // Wire up auth change callback to refresh/clear remote settings
164
- authService.onAuthChange((event) => {
164
+ authService.onAuthChange(async (event) => {
165
165
  if (event === "login") {
166
- remoteSettingsService.refresh();
166
+ await remoteSettingsService.refresh();
167
167
  } else if (event === "logout") {
168
168
  remoteSettingsService.clear();
169
169
  }
@@ -300,6 +300,12 @@ export function setupAgentContainer(
300
300
  });
301
301
  container.register("LiveConfigManager", liveConfigManager);
302
302
 
303
+ // Wire up remote settings hot-update: when polling detects changed settings,
304
+ // reload configuration so admin changes propagate to the running agent.
305
+ remoteSettingsService.onSettingsUpdate(async () => {
306
+ await liveConfigManager.reload();
307
+ });
308
+
303
309
  const subagentManager = new SubagentManager(container, {
304
310
  workdir,
305
311
  callbacks: {
@@ -58,6 +58,14 @@ export type AgentToolBlockUpdateParams = Omit<
58
58
  "messages"
59
59
  >;
60
60
 
61
+ // Callback payload type — SDK always fills messageId (required)
62
+ export type ToolBlockUpdateCallbackParams = Omit<
63
+ AgentToolBlockUpdateParams,
64
+ "messageId"
65
+ > & {
66
+ messageId: string;
67
+ };
68
+
61
69
  export interface AddErrorBlockParams {
62
70
  messages: Message[];
63
71
  error: string;
@@ -289,7 +297,7 @@ export const updateToolBlockInMessage = ({
289
297
  compactParams,
290
298
  parametersChunk,
291
299
  isManuallyBackgrounded,
292
- }: UpdateToolBlockParams): Message[] => {
300
+ }: UpdateToolBlockParams): { messages: Message[]; messageId?: string } => {
293
301
  const newMessages = [...messages];
294
302
 
295
303
  // If messageId is provided, target that specific message
@@ -321,7 +329,7 @@ export const updateToolBlockInMessage = ({
321
329
  }
322
330
  }
323
331
  }
324
- return newMessages;
332
+ return { messages: newMessages, messageId };
325
333
  }
326
334
 
327
335
  // Find the last assistant or user message
@@ -350,7 +358,8 @@ export const updateToolBlockInMessage = ({
350
358
  if (isManuallyBackgrounded !== undefined)
351
359
  toolBlock.isManuallyBackgrounded = isManuallyBackgrounded;
352
360
  }
353
- break; // Found and updated, stop searching
361
+ const foundMessageId = newMessages[i].id;
362
+ return { messages: newMessages, messageId: foundMessageId };
354
363
  } else if (newMessages[i].role === "assistant") {
355
364
  // If existing block not found in assistant message, create new one
356
365
  // This handles cases where we're streaming tool parameters before execution
@@ -370,11 +379,12 @@ export const updateToolBlockInMessage = ({
370
379
  parametersChunk: parametersChunk,
371
380
  isManuallyBackgrounded: isManuallyBackgrounded,
372
381
  });
373
- break; // Created and added, stop searching
382
+ const foundMessageId = newMessages[i].id;
383
+ return { messages: newMessages, messageId: foundMessageId };
374
384
  }
375
385
  }
376
386
  }
377
- return newMessages;
387
+ return { messages: newMessages };
378
388
  };
379
389
 
380
390
  // Add Error Block to the last assistant message
@@ -1,7 +0,0 @@
1
- import type { Message } from "../types/messaging.js";
2
- export interface MicrocompactOptions {
3
- timeThresholdMS: number;
4
- recentResultsToKeep: number;
5
- }
6
- export declare function microcompactMessages(messages: Message[], options: MicrocompactOptions): Message[];
7
- //# sourceMappingURL=microcompact.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"microcompact.d.ts","sourceRoot":"","sources":["../../src/utils/microcompact.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAa,MAAM,uBAAuB,CAAC;AAEhE,MAAM,WAAW,mBAAmB;IAClC,eAAe,EAAE,MAAM,CAAC;IACxB,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAID,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,OAAO,EAAE,EACnB,OAAO,EAAE,mBAAmB,GAC3B,OAAO,EAAE,CAwFX"}
@@ -1,78 +0,0 @@
1
- const CLEARED_RESULT = "[Old tool result content cleared]";
2
- export function microcompactMessages(messages, options) {
3
- const { timeThresholdMS, recentResultsToKeep } = options;
4
- // 1. Find the latest tool block timestamp across all assistant messages
5
- let lastAssistantTime = 0;
6
- for (const msg of messages) {
7
- if (msg.role === "assistant") {
8
- for (const block of msg.blocks) {
9
- if (block.type === "tool" && block.stage === "end" && block.timestamp) {
10
- if (block.timestamp > lastAssistantTime) {
11
- lastAssistantTime = block.timestamp;
12
- }
13
- }
14
- }
15
- }
16
- }
17
- // 2. If no prior assistant messages with completed tools, return unchanged
18
- if (lastAssistantTime === 0) {
19
- return messages;
20
- }
21
- // 3. If within threshold, return unchanged
22
- if (Date.now() - lastAssistantTime < timeThresholdMS) {
23
- return messages;
24
- }
25
- const toolRefs = [];
26
- for (let mi = 0; mi < messages.length; mi++) {
27
- const msg = messages[mi];
28
- if (msg.role === "assistant") {
29
- for (let bi = 0; bi < msg.blocks.length; bi++) {
30
- const block = msg.blocks[bi];
31
- if (block.type === "tool" && block.stage === "end" && block.timestamp) {
32
- toolRefs.push({
33
- msgIndex: mi,
34
- blockIndex: bi,
35
- timestamp: block.timestamp,
36
- });
37
- }
38
- }
39
- }
40
- }
41
- toolRefs.sort((a, b) => b.timestamp - a.timestamp);
42
- // 5. Mark the top N as "keep"
43
- const keepSet = new Set();
44
- for (let i = 0; i < Math.min(recentResultsToKeep, toolRefs.length); i++) {
45
- const ref = toolRefs[i];
46
- keepSet.add(`${ref.msgIndex}:${ref.blockIndex}`);
47
- }
48
- // 6. Deep-copy messages and clear result + shortResult on non-kept blocks
49
- const result = messages.map((msg) => ({
50
- ...msg,
51
- blocks: msg.blocks.map((block) => {
52
- if (block.type === "tool" && block.stage === "end" && block.timestamp) {
53
- return { ...block };
54
- }
55
- return block;
56
- }),
57
- }));
58
- // Clear non-kept tool blocks
59
- for (const ref of toolRefs) {
60
- const key = `${ref.msgIndex}:${ref.blockIndex}`;
61
- if (!keepSet.has(key)) {
62
- result[ref.msgIndex] = {
63
- ...result[ref.msgIndex],
64
- blocks: result[ref.msgIndex].blocks.map((b, idx) => {
65
- if (idx === ref.blockIndex && b.type === "tool") {
66
- return {
67
- ...b,
68
- result: CLEARED_RESULT,
69
- shortResult: undefined,
70
- };
71
- }
72
- return b;
73
- }),
74
- };
75
- }
76
- }
77
- return result;
78
- }