bingocode 1.1.184 → 1.1.186
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/package.json +1 -1
- package/src/bootstrap/state.ts +2 -100
- package/src/commands/exec/exec.tsx +23 -0
- package/src/commands/exec/index.ts +15 -0
- package/src/commands.ts +754 -752
- package/src/components/PromptInput/PromptInput.tsx +11 -9
- package/src/constants/prompts.ts +940 -926
- package/src/hooks/useGoalEvaluator.ts +49 -28
- package/src/utils/attachments.ts +17 -1
- package/src/utils/settings/types.ts +6 -0
|
@@ -3,21 +3,23 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Fires after each turn completes (triggered by lastQueryCompletionTime change).
|
|
5
5
|
* Evaluates progress toward active goal using env-aware evaluator v2.
|
|
6
|
+
*
|
|
7
|
+
* Migrated from old state.ts flat fields to the new GoalStore API.
|
|
8
|
+
* All state access goes through GoalStore — no more STATE.goalCondition fallbacks.
|
|
6
9
|
*/
|
|
7
10
|
|
|
8
11
|
import { useEffect, useRef } from 'react'
|
|
9
12
|
import type { MutableRefObject } from 'react'
|
|
10
13
|
import type { MessageType } from '../components/messages.js'
|
|
11
14
|
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
} from '../
|
|
20
|
-
import { getGoalState, recalculateProgress } from '../utils/goalStore.js'
|
|
15
|
+
getGoalState,
|
|
16
|
+
recalculateProgress,
|
|
17
|
+
incrementIteration,
|
|
18
|
+
recordEvalGap,
|
|
19
|
+
getActiveGoalId,
|
|
20
|
+
getReadySubGoals,
|
|
21
|
+
getBlockedSubGoals,
|
|
22
|
+
} from '../utils/goalStore.js'
|
|
21
23
|
import { enqueue } from '../utils/messageQueueManager.js'
|
|
22
24
|
import { evaluateGoal } from '../utils/goalEvaluator.js'
|
|
23
25
|
|
|
@@ -47,7 +49,8 @@ export function useGoalEvaluator({
|
|
|
47
49
|
const evaluating = useRef(false)
|
|
48
50
|
|
|
49
51
|
useEffect(() => {
|
|
50
|
-
const
|
|
52
|
+
const goalState = getGoalState()
|
|
53
|
+
const condition = goalState.userGoal?.text ?? null
|
|
51
54
|
if (!condition) return
|
|
52
55
|
if (isQueryActive) return
|
|
53
56
|
if (lastQueryCompletionTime === 0) return
|
|
@@ -59,56 +62,71 @@ export function useGoalEvaluator({
|
|
|
59
62
|
|
|
60
63
|
void (async () => {
|
|
61
64
|
try {
|
|
62
|
-
const iterCount =
|
|
63
|
-
const maxIter =
|
|
65
|
+
const iterCount = goalState.metrics.iterationCount
|
|
66
|
+
const maxIter = goalState.metrics.maxIterations
|
|
64
67
|
|
|
65
|
-
// Max iterations check
|
|
68
|
+
// Max iterations check — circuit breaker
|
|
66
69
|
if (iterCount >= maxIter) {
|
|
67
|
-
|
|
70
|
+
// Clear goal from store (delegates to clear() which resets engine too)
|
|
71
|
+
const { clear } = require('../utils/goalStore.js')
|
|
72
|
+
clear()
|
|
68
73
|
enqueue({
|
|
69
|
-
value:
|
|
74
|
+
value: `Goal not achieved after ${maxIter} iterations. Goal was: "${condition}"`,
|
|
70
75
|
mode: 'task-notification',
|
|
71
76
|
priority: 'now',
|
|
72
77
|
})
|
|
73
78
|
return
|
|
74
79
|
}
|
|
75
80
|
|
|
76
|
-
// Get
|
|
81
|
+
// Get messages + current sub-goal for evaluation context
|
|
77
82
|
const messages = messagesRef.current
|
|
78
|
-
const goalState = getGoalState()
|
|
79
83
|
const currentSubGoal = goalState.immediateGoal
|
|
80
84
|
? goalState.dag.nodes.get(goalState.immediateGoal.subGoalId)
|
|
81
85
|
: undefined
|
|
82
86
|
|
|
83
|
-
// Run environment-aware evaluation
|
|
87
|
+
// Run environment-aware evaluation (rule engine + semantic + final)
|
|
84
88
|
const result = await evaluateGoal(condition, messages, currentSubGoal)
|
|
85
89
|
|
|
86
|
-
// Race: user may have cleared goal during
|
|
87
|
-
if (
|
|
90
|
+
// Race: user may have cleared goal during async evaluation
|
|
91
|
+
if (!getActiveGoalId()) return
|
|
88
92
|
|
|
89
|
-
|
|
90
|
-
|
|
93
|
+
incrementIteration()
|
|
94
|
+
recordEvalGap(result.gap)
|
|
91
95
|
recalculateProgress()
|
|
92
96
|
|
|
97
|
+
// Check active sub-goals and blocked count for drift diagnosis
|
|
98
|
+
const ready = getReadySubGoals()
|
|
99
|
+
const blocked = getBlockedSubGoals()
|
|
100
|
+
if (blocked.length > 0 && ready.length === 0) {
|
|
101
|
+
// All sub-goals blocked — need to replan or escalate
|
|
102
|
+
void ready
|
|
103
|
+
void blocked
|
|
104
|
+
}
|
|
105
|
+
|
|
93
106
|
// Circuit breaker: 3 consecutive same gap
|
|
94
|
-
const evalHistory =
|
|
107
|
+
const evalHistory = goalState.metrics.evalHistory
|
|
95
108
|
const isRepeatedGap = evalHistory.consecutiveSameGapCount >= 3 && result.gap !== null
|
|
96
109
|
|
|
97
110
|
if (result.satisfied) {
|
|
98
|
-
|
|
111
|
+
// Goal achieved — clear from store and file system
|
|
112
|
+
const { clearAndDelete } = require('../utils/goalStore.js')
|
|
113
|
+
clearAndDelete()
|
|
99
114
|
enqueue({
|
|
100
|
-
value:
|
|
115
|
+
value: `Goal achieved (iteration ${iterCount + 1}): ${result.reason}`,
|
|
101
116
|
mode: 'task-notification',
|
|
102
117
|
priority: 'now',
|
|
103
118
|
})
|
|
104
119
|
} else if (isRepeatedGap) {
|
|
105
|
-
|
|
120
|
+
// Circuit breaker — same gap repeated 3 times, stop looping
|
|
121
|
+
const { clear } = require('../utils/goalStore.js')
|
|
122
|
+
clear()
|
|
106
123
|
enqueue({
|
|
107
|
-
value:
|
|
124
|
+
value: `Goal evaluator stopped — same gap "${result.gap}" ${evalHistory.consecutiveSameGapCount}x. Adjust approach or output EVAL blocks.`,
|
|
108
125
|
mode: 'task-notification',
|
|
109
126
|
priority: 'now',
|
|
110
127
|
})
|
|
111
128
|
} else {
|
|
129
|
+
// Not yet satisfied — continue
|
|
112
130
|
const continueMsg = result.gap
|
|
113
131
|
? `Goal not yet met (${iterCount + 1}/${maxIter}). Gap: ${result.gap}. Continue toward: "${condition}"`
|
|
114
132
|
: `Goal not yet met (${iterCount + 1}/${maxIter}, reason: ${result.reason}). Continue toward: "${condition}"`
|
|
@@ -118,9 +136,12 @@ export function useGoalEvaluator({
|
|
|
118
136
|
priority: 'now',
|
|
119
137
|
})
|
|
120
138
|
}
|
|
139
|
+
} catch (err) {
|
|
140
|
+
// Evaluation error is non-fatal — log and continue
|
|
141
|
+
console.error('[GoalEvaluator] Evaluation error:', err)
|
|
121
142
|
} finally {
|
|
122
143
|
evaluating.current = false
|
|
123
144
|
}
|
|
124
145
|
})()
|
|
125
|
-
}, [lastQueryCompletionTime, isQueryActive])
|
|
146
|
+
}, [lastQueryCompletionTime, isQueryActive]) // messagesRef is stable ref — not included as dep
|
|
126
147
|
}
|
package/src/utils/attachments.ts
CHANGED
|
@@ -63,7 +63,7 @@ import {
|
|
|
63
63
|
isValidImagePaste,
|
|
64
64
|
} from 'src/types/textInputTypes.js'
|
|
65
65
|
import { randomUUID, type UUID } from 'crypto'
|
|
66
|
-
import { getSettings_DEPRECATED } from './settings/settings.js'
|
|
66
|
+
import { getInitialSettings, getSettings_DEPRECATED } from './settings/settings.js'
|
|
67
67
|
import { getSnippetForTwoFileDiff } from 'src/tools/FileEditTool/utils.js'
|
|
68
68
|
import type {
|
|
69
69
|
ContentBlockParam,
|
|
@@ -915,6 +915,9 @@ export async function getAttachments(
|
|
|
915
915
|
maybe('critical_system_reminder', () =>
|
|
916
916
|
Promise.resolve(getCriticalSystemReminderAttachment(toolUseContext)),
|
|
917
917
|
),
|
|
918
|
+
maybe('exec_mode_reminder', () =>
|
|
919
|
+
Promise.resolve(getExecModeReminderAttachment()),
|
|
920
|
+
),
|
|
918
921
|
...(feature('COMPACTION_REMINDERS')
|
|
919
922
|
? [
|
|
920
923
|
maybe('compaction_reminder', () =>
|
|
@@ -1590,6 +1593,19 @@ function getCriticalSystemReminderAttachment(
|
|
|
1590
1593
|
return [{ type: 'critical_system_reminder', content: reminder }]
|
|
1591
1594
|
}
|
|
1592
1595
|
|
|
1596
|
+
function getExecModeReminderAttachment(): Attachment[] {
|
|
1597
|
+
if (!getInitialSettings().execMode) {
|
|
1598
|
+
return []
|
|
1599
|
+
}
|
|
1600
|
+
return [
|
|
1601
|
+
{
|
|
1602
|
+
type: 'system_reminder' as const,
|
|
1603
|
+
content:
|
|
1604
|
+
'/exec active — Dispatch first. Protect context. Report decisions, blockers, results.',
|
|
1605
|
+
},
|
|
1606
|
+
]
|
|
1607
|
+
}
|
|
1608
|
+
|
|
1593
1609
|
function getOutputStyleAttachment(): Attachment[] {
|
|
1594
1610
|
const settings = getSettings_DEPRECATED()
|
|
1595
1611
|
const outputStyle = settings?.outputStyle || 'default'
|
|
@@ -725,6 +725,12 @@ export const SettingsSchema = lazySchema(() =>
|
|
|
725
725
|
.describe(
|
|
726
726
|
'When true, fast mode does not persist across sessions. Each session starts with fast mode off.',
|
|
727
727
|
),
|
|
728
|
+
execMode: z
|
|
729
|
+
.boolean()
|
|
730
|
+
.optional()
|
|
731
|
+
.describe(
|
|
732
|
+
'Priority dispatch, context protection, compressed reporting.',
|
|
733
|
+
),
|
|
728
734
|
promptSuggestionEnabled: z
|
|
729
735
|
.boolean()
|
|
730
736
|
.optional()
|