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.
- package/dist/managers/aiManager.js +80 -82
- package/dist/utils/openaiClient.d.ts.map +1 -1
- package/dist/utils/openaiClient.js +2 -0
- package/package.json +1 -1
- package/scripts/install_ripgrep.js +1 -21
- package/src/managers/aiManager.ts +97 -97
- package/src/utils/openaiClient.ts +2 -0
- package/vendor/ripgrep/linux-aarch64/rg +0 -0
- package/vendor/ripgrep/macos-aarch64/rg +0 -0
- package/vendor/ripgrep/macos-x86_64/rg +0 -0
- package/vendor/ripgrep/windows-aarch64/rg.exe +0 -0
- package/vendor/ripgrep/windows-x86_64/rg.exe +0 -0
|
@@ -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
|
-
//
|
|
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;
|
|
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
|
@@ -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
|
|
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
|
-
//
|
|
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
|
|
Binary file
|
|
Binary file
|