wave-agent-sdk 0.18.5 → 0.18.6

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.
@@ -894,7 +894,86 @@ export class AIManager {
894
894
  await this.messageManager.saveSession();
895
895
  // Set loading to false first
896
896
  this.setIsLoading(false);
897
- // Inject pending notifications from background tasks
897
+ // Clear temporary rules
898
+ this.permissionManager?.clearTemporaryRules();
899
+ // Clear abort controllers
900
+ this.abortController = null;
901
+ this.toolAbortController = null;
902
+ // Execute Stop/SubagentStop hooks only if the operation was not aborted
903
+ const isCurrentlyAborted = abortController.signal.aborted || toolAbortController.signal.aborted;
904
+ if (!isCurrentlyAborted) {
905
+ // Record committed snapshots to message history for the final turn
906
+ if (this.reversionManager) {
907
+ const snapshots = this.reversionManager.getAndClearCommittedSnapshots();
908
+ if (snapshots.length > 0) {
909
+ this.messageManager.addFileHistoryBlock(snapshots);
910
+ }
911
+ }
912
+ // Goal evaluation — supersedes Stop hooks when active
913
+ const goalManager = this.container.has("GoalManager")
914
+ ? this.container.get("GoalManager")
915
+ : undefined;
916
+ let goalContinuing = false;
917
+ if (goalManager?.isGoalActive() && !this.subagentType) {
918
+ // 1. Increment turn count and check circuit breakers
919
+ goalManager.incrementTurnCount();
920
+ const circuitBreaker = goalManager.checkCircuitBreakers();
921
+ if (circuitBreaker) {
922
+ goalManager.clearGoal();
923
+ logger?.info(`[Goal] ${circuitBreaker}`);
924
+ this.messageManager.addUserMessage({
925
+ content: `<system-reminder>${circuitBreaker}</system-reminder>`,
926
+ isMeta: true,
927
+ });
928
+ // Fall through to normal Stop hooks on the final turn
929
+ }
930
+ else {
931
+ // 2. Evaluate goal
932
+ const evaluation = await goalManager.evaluateGoal(abortController.signal);
933
+ if (evaluation.isMet) {
934
+ goalManager.clearGoal();
935
+ logger?.info(`[Goal] Goal achieved: ${evaluation.reason}`);
936
+ this.messageManager.addUserMessage({
937
+ content: `<system-reminder>Goal achieved: ${evaluation.reason}</system-reminder>`,
938
+ isMeta: true,
939
+ });
940
+ // Fall through to normal Stop hooks on the final turn
941
+ }
942
+ else {
943
+ const goal = goalManager.getGoal();
944
+ goal.lastReason = evaluation.reason;
945
+ logger?.info(`[Goal] Not yet met: ${evaluation.reason}`);
946
+ this.messageManager.addUserMessage({
947
+ content: `<system-reminder>Goal not yet met: ${evaluation.reason}. Continue working toward: ${goal.condition}</system-reminder>`,
948
+ isMeta: true,
949
+ });
950
+ // Keep loading state active to prevent UI flicker
951
+ this.setIsLoading(true);
952
+ goalContinuing = true;
953
+ // Restart outer loop to continue goal pursuit
954
+ shouldRestart = true;
955
+ turnOffset = 0;
956
+ }
957
+ }
958
+ }
959
+ // Skip Stop hooks when goal evaluator is continuing the conversation
960
+ if (goalContinuing) {
961
+ // Goal evaluator supersedes Stop hooks
962
+ }
963
+ else {
964
+ const shouldContinue = await this.executeStopHooks();
965
+ // If Stop/SubagentStop hooks indicate we should continue (due to blocking errors),
966
+ // restart the AI conversation cycle
967
+ if (shouldContinue) {
968
+ logger?.info(`${this.subagentType ? "SubagentStop" : "Stop"} hooks indicate issues need fixing, continuing conversation...`);
969
+ // Restart the conversation to let AI fix the issues
970
+ shouldRestart = true;
971
+ turnOffset = 0;
972
+ }
973
+ }
974
+ }
975
+ // Inject pending notifications from background tasks (after Stop hooks,
976
+ // aligned with Claude Code which fires Stop hooks unconditionally)
898
977
  const notificationQueue = this.container.has("NotificationQueue")
899
978
  ? this.container.get("NotificationQueue")
900
979
  : undefined;
@@ -916,87 +995,6 @@ export class AIManager {
916
995
  shouldRestart = true;
917
996
  turnOffset = 0;
918
997
  }
919
- else {
920
- // Clear temporary rules
921
- this.permissionManager?.clearTemporaryRules();
922
- // Clear abort controllers
923
- this.abortController = null;
924
- this.toolAbortController = null;
925
- // Execute Stop/SubagentStop hooks only if the operation was not aborted
926
- const isCurrentlyAborted = abortController.signal.aborted ||
927
- toolAbortController.signal.aborted;
928
- if (!isCurrentlyAborted) {
929
- // Record committed snapshots to message history for the final turn
930
- if (this.reversionManager) {
931
- const snapshots = this.reversionManager.getAndClearCommittedSnapshots();
932
- if (snapshots.length > 0) {
933
- this.messageManager.addFileHistoryBlock(snapshots);
934
- }
935
- }
936
- // Goal evaluation — supersedes Stop hooks when active
937
- const goalManager = this.container.has("GoalManager")
938
- ? this.container.get("GoalManager")
939
- : undefined;
940
- let goalContinuing = false;
941
- if (goalManager?.isGoalActive() && !this.subagentType) {
942
- // 1. Increment turn count and check circuit breakers
943
- goalManager.incrementTurnCount();
944
- const circuitBreaker = goalManager.checkCircuitBreakers();
945
- if (circuitBreaker) {
946
- goalManager.clearGoal();
947
- logger?.info(`[Goal] ${circuitBreaker}`);
948
- this.messageManager.addUserMessage({
949
- content: `<system-reminder>${circuitBreaker}</system-reminder>`,
950
- isMeta: true,
951
- });
952
- // Fall through to normal Stop hooks on the final turn
953
- }
954
- else {
955
- // 2. Evaluate goal
956
- const evaluation = await goalManager.evaluateGoal(abortController.signal);
957
- if (evaluation.isMet) {
958
- goalManager.clearGoal();
959
- logger?.info(`[Goal] Goal achieved: ${evaluation.reason}`);
960
- this.messageManager.addUserMessage({
961
- content: `<system-reminder>Goal achieved: ${evaluation.reason}</system-reminder>`,
962
- isMeta: true,
963
- });
964
- // Fall through to normal Stop hooks on the final turn
965
- }
966
- else {
967
- const goal = goalManager.getGoal();
968
- goal.lastReason = evaluation.reason;
969
- logger?.info(`[Goal] Not yet met: ${evaluation.reason}`);
970
- this.messageManager.addUserMessage({
971
- content: `<system-reminder>Goal not yet met: ${evaluation.reason}. Continue working toward: ${goal.condition}</system-reminder>`,
972
- isMeta: true,
973
- });
974
- // Keep loading state active to prevent UI flicker
975
- this.setIsLoading(true);
976
- goalContinuing = true;
977
- // Restart outer loop to continue goal pursuit
978
- shouldRestart = true;
979
- turnOffset = 0;
980
- }
981
- }
982
- }
983
- // Skip Stop hooks when goal evaluator is continuing the conversation
984
- if (goalContinuing) {
985
- // Goal evaluator supersedes Stop hooks
986
- }
987
- else {
988
- const shouldContinue = await this.executeStopHooks();
989
- // If Stop/SubagentStop hooks indicate we should continue (due to blocking errors),
990
- // restart the AI conversation cycle
991
- if (shouldContinue) {
992
- logger?.info(`${this.subagentType ? "SubagentStop" : "Stop"} hooks indicate issues need fixing, continuing conversation...`);
993
- // Restart the conversation to let AI fix the issues
994
- shouldRestart = true;
995
- turnOffset = 0;
996
- }
997
- }
998
- }
999
- }
1000
998
  }
1001
999
  if (!shouldRestart)
1002
1000
  break outer;
@@ -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;AAyBnD,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;YAuHN,oBAAoB;CAyCpC"}
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;AAyBnD,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;YAyHN,oBAAoB;CAyCpC"}
@@ -67,6 +67,7 @@ export class OpenAIClient {
67
67
  }
68
68
  if (attempt < MAX_RETRIES) {
69
69
  logger.warn("OpenAI API network error, retrying...", {
70
+ model: params.model,
70
71
  attempt: attempt + 1,
71
72
  error: e,
72
73
  });
@@ -106,6 +107,7 @@ export class OpenAIClient {
106
107
  if (retryableStatus && attempt < MAX_RETRIES) {
107
108
  lastRetryAfter = response.headers.get("retry-after");
108
109
  logger.warn("OpenAI API error, retrying...", {
110
+ model: params.model,
109
111
  attempt: attempt + 1,
110
112
  status: response.status,
111
113
  retryAfter: lastRetryAfter,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wave-agent-sdk",
3
- "version": "0.18.5",
3
+ "version": "0.18.6",
4
4
  "description": "SDK for building AI-powered development tools and agents",
5
5
  "keywords": [
6
6
  "ai",
@@ -9,18 +9,6 @@ const __dirname = path.dirname(__filename);
9
9
  const MANIFEST_PATH = path.resolve(__dirname, "../bin/rg");
10
10
  const VENDOR_DIR = path.resolve(__dirname, "../vendor/ripgrep");
11
11
 
12
- function getCurrentPlatform() {
13
- const platform = process.platform;
14
- const arch = process.arch;
15
- if (platform === "darwin")
16
- return `macos-${arch === "arm64" ? "aarch64" : "x86_64"}`;
17
- if (platform === "linux")
18
- return `linux-${arch === "arm64" ? "aarch64" : "x86_64"}`;
19
- if (platform === "win32")
20
- return `windows-${arch === "arm64" ? "aarch64" : "x86_64"}`;
21
- return null;
22
- }
23
-
24
12
  async function main() {
25
13
  if (!fs.existsSync(MANIFEST_PATH)) {
26
14
  console.error(`Manifest not found: ${MANIFEST_PATH}`);
@@ -30,15 +18,7 @@ async function main() {
30
18
  const manifestContent = fs.readFileSync(MANIFEST_PATH, "utf-8");
31
19
  const jsonContent = manifestContent.replace(/^#!.*\n/, "");
32
20
  const manifest = JSON.parse(jsonContent);
33
- const allPlatforms = manifest.platforms;
34
-
35
- // In CI, only download for the current platform
36
- const isCI = process.env.CI === "true";
37
- const currentPlatform = isCI ? getCurrentPlatform() : null;
38
- const platforms =
39
- currentPlatform && currentPlatform in allPlatforms
40
- ? { [currentPlatform]: allPlatforms[currentPlatform] }
41
- : allPlatforms;
21
+ const platforms = manifest.platforms;
42
22
 
43
23
  if (!fs.existsSync(VENDOR_DIR)) {
44
24
  fs.mkdirSync(VENDOR_DIR, { recursive: true });
@@ -1271,7 +1271,103 @@ export class AIManager {
1271
1271
  // Set loading to false first
1272
1272
  this.setIsLoading(false);
1273
1273
 
1274
- // Inject pending notifications from background tasks
1274
+ // Clear temporary rules
1275
+ this.permissionManager?.clearTemporaryRules();
1276
+
1277
+ // Clear abort controllers
1278
+ this.abortController = null;
1279
+ this.toolAbortController = null;
1280
+
1281
+ // Execute Stop/SubagentStop hooks only if the operation was not aborted
1282
+ const isCurrentlyAborted =
1283
+ abortController.signal.aborted || toolAbortController.signal.aborted;
1284
+
1285
+ if (!isCurrentlyAborted) {
1286
+ // Record committed snapshots to message history for the final turn
1287
+ if (this.reversionManager) {
1288
+ const snapshots =
1289
+ this.reversionManager.getAndClearCommittedSnapshots();
1290
+ if (snapshots.length > 0) {
1291
+ this.messageManager.addFileHistoryBlock(snapshots);
1292
+ }
1293
+ }
1294
+
1295
+ // Goal evaluation — supersedes Stop hooks when active
1296
+ const goalManager = this.container.has("GoalManager")
1297
+ ? this.container.get<import("./goalManager.js").GoalManager>(
1298
+ "GoalManager",
1299
+ )
1300
+ : undefined;
1301
+
1302
+ let goalContinuing = false;
1303
+
1304
+ if (goalManager?.isGoalActive() && !this.subagentType) {
1305
+ // 1. Increment turn count and check circuit breakers
1306
+ goalManager.incrementTurnCount();
1307
+ const circuitBreaker = goalManager.checkCircuitBreakers();
1308
+
1309
+ if (circuitBreaker) {
1310
+ goalManager.clearGoal();
1311
+ logger?.info(`[Goal] ${circuitBreaker}`);
1312
+ this.messageManager.addUserMessage({
1313
+ content: `<system-reminder>${circuitBreaker}</system-reminder>`,
1314
+ isMeta: true,
1315
+ });
1316
+ // Fall through to normal Stop hooks on the final turn
1317
+ } else {
1318
+ // 2. Evaluate goal
1319
+ const evaluation = await goalManager.evaluateGoal(
1320
+ abortController.signal,
1321
+ );
1322
+
1323
+ if (evaluation.isMet) {
1324
+ goalManager.clearGoal();
1325
+ logger?.info(`[Goal] Goal achieved: ${evaluation.reason}`);
1326
+ this.messageManager.addUserMessage({
1327
+ content: `<system-reminder>Goal achieved: ${evaluation.reason}</system-reminder>`,
1328
+ isMeta: true,
1329
+ });
1330
+ // Fall through to normal Stop hooks on the final turn
1331
+ } else {
1332
+ const goal = goalManager.getGoal()!;
1333
+ goal.lastReason = evaluation.reason;
1334
+ logger?.info(`[Goal] Not yet met: ${evaluation.reason}`);
1335
+ this.messageManager.addUserMessage({
1336
+ content: `<system-reminder>Goal not yet met: ${evaluation.reason}. Continue working toward: ${goal.condition}</system-reminder>`,
1337
+ isMeta: true,
1338
+ });
1339
+ // Keep loading state active to prevent UI flicker
1340
+ this.setIsLoading(true);
1341
+ goalContinuing = true;
1342
+ // Restart outer loop to continue goal pursuit
1343
+ shouldRestart = true;
1344
+ turnOffset = 0;
1345
+ }
1346
+ }
1347
+ }
1348
+
1349
+ // Skip Stop hooks when goal evaluator is continuing the conversation
1350
+ if (goalContinuing) {
1351
+ // Goal evaluator supersedes Stop hooks
1352
+ } else {
1353
+ const shouldContinue = await this.executeStopHooks();
1354
+
1355
+ // If Stop/SubagentStop hooks indicate we should continue (due to blocking errors),
1356
+ // restart the AI conversation cycle
1357
+ if (shouldContinue) {
1358
+ logger?.info(
1359
+ `${this.subagentType ? "SubagentStop" : "Stop"} hooks indicate issues need fixing, continuing conversation...`,
1360
+ );
1361
+
1362
+ // Restart the conversation to let AI fix the issues
1363
+ shouldRestart = true;
1364
+ turnOffset = 0;
1365
+ }
1366
+ }
1367
+ }
1368
+
1369
+ // Inject pending notifications from background tasks (after Stop hooks,
1370
+ // aligned with Claude Code which fires Stop hooks unconditionally)
1275
1371
  const notificationQueue = this.container.has("NotificationQueue")
1276
1372
  ? this.container.get<NotificationQueue>("NotificationQueue")
1277
1373
  : undefined;
@@ -1292,102 +1388,6 @@ export class AIManager {
1292
1388
  // Restart outer loop to process the notifications
1293
1389
  shouldRestart = true;
1294
1390
  turnOffset = 0;
1295
- } else {
1296
- // Clear temporary rules
1297
- this.permissionManager?.clearTemporaryRules();
1298
-
1299
- // Clear abort controllers
1300
- this.abortController = null;
1301
- this.toolAbortController = null;
1302
-
1303
- // Execute Stop/SubagentStop hooks only if the operation was not aborted
1304
- const isCurrentlyAborted =
1305
- abortController.signal.aborted ||
1306
- toolAbortController.signal.aborted;
1307
-
1308
- if (!isCurrentlyAborted) {
1309
- // Record committed snapshots to message history for the final turn
1310
- if (this.reversionManager) {
1311
- const snapshots =
1312
- this.reversionManager.getAndClearCommittedSnapshots();
1313
- if (snapshots.length > 0) {
1314
- this.messageManager.addFileHistoryBlock(snapshots);
1315
- }
1316
- }
1317
-
1318
- // Goal evaluation — supersedes Stop hooks when active
1319
- const goalManager = this.container.has("GoalManager")
1320
- ? this.container.get<import("./goalManager.js").GoalManager>(
1321
- "GoalManager",
1322
- )
1323
- : undefined;
1324
-
1325
- let goalContinuing = false;
1326
-
1327
- if (goalManager?.isGoalActive() && !this.subagentType) {
1328
- // 1. Increment turn count and check circuit breakers
1329
- goalManager.incrementTurnCount();
1330
- const circuitBreaker = goalManager.checkCircuitBreakers();
1331
-
1332
- if (circuitBreaker) {
1333
- goalManager.clearGoal();
1334
- logger?.info(`[Goal] ${circuitBreaker}`);
1335
- this.messageManager.addUserMessage({
1336
- content: `<system-reminder>${circuitBreaker}</system-reminder>`,
1337
- isMeta: true,
1338
- });
1339
- // Fall through to normal Stop hooks on the final turn
1340
- } else {
1341
- // 2. Evaluate goal
1342
- const evaluation = await goalManager.evaluateGoal(
1343
- abortController.signal,
1344
- );
1345
-
1346
- if (evaluation.isMet) {
1347
- goalManager.clearGoal();
1348
- logger?.info(`[Goal] Goal achieved: ${evaluation.reason}`);
1349
- this.messageManager.addUserMessage({
1350
- content: `<system-reminder>Goal achieved: ${evaluation.reason}</system-reminder>`,
1351
- isMeta: true,
1352
- });
1353
- // Fall through to normal Stop hooks on the final turn
1354
- } else {
1355
- const goal = goalManager.getGoal()!;
1356
- goal.lastReason = evaluation.reason;
1357
- logger?.info(`[Goal] Not yet met: ${evaluation.reason}`);
1358
- this.messageManager.addUserMessage({
1359
- content: `<system-reminder>Goal not yet met: ${evaluation.reason}. Continue working toward: ${goal.condition}</system-reminder>`,
1360
- isMeta: true,
1361
- });
1362
- // Keep loading state active to prevent UI flicker
1363
- this.setIsLoading(true);
1364
- goalContinuing = true;
1365
- // Restart outer loop to continue goal pursuit
1366
- shouldRestart = true;
1367
- turnOffset = 0;
1368
- }
1369
- }
1370
- }
1371
-
1372
- // Skip Stop hooks when goal evaluator is continuing the conversation
1373
- if (goalContinuing) {
1374
- // Goal evaluator supersedes Stop hooks
1375
- } else {
1376
- const shouldContinue = await this.executeStopHooks();
1377
-
1378
- // If Stop/SubagentStop hooks indicate we should continue (due to blocking errors),
1379
- // restart the AI conversation cycle
1380
- if (shouldContinue) {
1381
- logger?.info(
1382
- `${this.subagentType ? "SubagentStop" : "Stop"} hooks indicate issues need fixing, continuing conversation...`,
1383
- );
1384
-
1385
- // Restart the conversation to let AI fix the issues
1386
- shouldRestart = true;
1387
- turnOffset = 0;
1388
- }
1389
- }
1390
- }
1391
1391
  }
1392
1392
  }
1393
1393
 
@@ -133,6 +133,7 @@ export class OpenAIClient {
133
133
  }
134
134
  if (attempt < MAX_RETRIES) {
135
135
  logger.warn("OpenAI API network error, retrying...", {
136
+ model: params.model,
136
137
  attempt: attempt + 1,
137
138
  error: e,
138
139
  });
@@ -185,6 +186,7 @@ export class OpenAIClient {
185
186
  if (retryableStatus && attempt < MAX_RETRIES) {
186
187
  lastRetryAfter = response.headers.get("retry-after");
187
188
  logger.warn("OpenAI API error, retrying...", {
189
+ model: params.model,
188
190
  attempt: attempt + 1,
189
191
  status: response.status,
190
192
  retryAfter: lastRetryAfter,
Binary file
Binary file
Binary file