bingocode 1.1.125 → 1.1.127
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/.claude/settings.local.json +5 -1
- package/bin/bingo-win.cjs +16 -0
- package/package.json +1 -1
- package/scripts/install-bun.cjs +89 -0
- package/scripts/install-skills.cjs +7 -0
- package/src/constants/prompts.ts +24 -12
- package/src/ink/terminal.ts +7 -1
- package/src/server/proxy/streaming/openaiChatStreamToAnthropic.ts +2 -2
- package/src/server/proxy/transform/anthropicToOpenaiChat.ts +1 -1
- package/src/utils/goalEvaluator.ts +4 -1
|
@@ -7,7 +7,11 @@
|
|
|
7
7
|
"Bash(curl -s \"https://docs.anthropic.com/en/api/messages-streaming\" --max-time 30 -A \"Mozilla/5.0\")",
|
|
8
8
|
"Bash(curl -sv \"https://docs.anthropic.com/en/api/messages\" --max-time 30)",
|
|
9
9
|
"Bash(curl -sv \"https://raw.githubusercontent.com/anthropics/anthropic-sdk-python/main/api.md\" --max-time 30)",
|
|
10
|
-
"Bash(curl -s \"https://raw.githubusercontent.com/anthropics/anthropic-sdk-python/refs/heads/main/README.md\" --max-time 30)"
|
|
10
|
+
"Bash(curl -s \"https://raw.githubusercontent.com/anthropics/anthropic-sdk-python/refs/heads/main/README.md\" --max-time 30)",
|
|
11
|
+
"Bash(findstr /i goal)",
|
|
12
|
+
"Bash(bun run:*)",
|
|
13
|
+
"Bash(bunx tsc:*)",
|
|
14
|
+
"Bash(node_modules/.bin/tsc --noEmit --skipLibCheck)"
|
|
11
15
|
]
|
|
12
16
|
}
|
|
13
17
|
}
|
package/bin/bingo-win.cjs
CHANGED
|
@@ -74,6 +74,22 @@ function bunExists() {
|
|
|
74
74
|
|
|
75
75
|
// 安装 bun
|
|
76
76
|
function installBun() {
|
|
77
|
+
// 优先:从包内 runtime/bun.exe 直接部署(离线,无需 PowerShell 权限)
|
|
78
|
+
const bundledBun = path.join(ROOT_DIR, 'runtime', 'bun.exe');
|
|
79
|
+
if (fs.existsSync(bundledBun)) {
|
|
80
|
+
console.log('[bingocode] 正在从包内部署 bun.exe...');
|
|
81
|
+
try {
|
|
82
|
+
const destDir = path.join(os.homedir(), '.bun', 'bin');
|
|
83
|
+
if (!fs.existsSync(destDir)) fs.mkdirSync(destDir, { recursive: true });
|
|
84
|
+
fs.copyFileSync(bundledBun, bunPath);
|
|
85
|
+
console.log('[bingocode] bun 已部署,正在启动...');
|
|
86
|
+
return true;
|
|
87
|
+
} catch (err) {
|
|
88
|
+
console.warn(`[bingocode] 包内部署失败: ${err.message},尝试在线安装...`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// 兜底:在线安装
|
|
77
93
|
console.log('[bingocode] bun 未检测到,正在自动安装...');
|
|
78
94
|
try {
|
|
79
95
|
const result = spawnSync(
|
package/package.json
CHANGED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* postinstall helper: deploy bundled bun.exe → ~/.bun/bin/bun.exe
|
|
4
|
+
*
|
|
5
|
+
* Rules:
|
|
6
|
+
* - Only runs on Windows (win32). No-op on Linux/Mac.
|
|
7
|
+
* - Skips if ~/.bun/bin/bun.exe already exists (respect user's own install).
|
|
8
|
+
* - Appends %USERPROFILE%\.bun\bin to HKCU\Environment PATH via reg.exe (no admin needed).
|
|
9
|
+
* - CJS, no dependencies beyond Node built-ins.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
'use strict'
|
|
13
|
+
|
|
14
|
+
const fs = require('node:fs')
|
|
15
|
+
const path = require('node:path')
|
|
16
|
+
const os = require('node:os')
|
|
17
|
+
const { spawnSync } = require('node:child_process')
|
|
18
|
+
|
|
19
|
+
// Only relevant on Windows
|
|
20
|
+
if (process.platform !== 'win32') process.exit(0)
|
|
21
|
+
|
|
22
|
+
const home = os.homedir()
|
|
23
|
+
if (!home) process.exit(0)
|
|
24
|
+
|
|
25
|
+
const dest = path.join(home, '.bun', 'bin', 'bun.exe')
|
|
26
|
+
|
|
27
|
+
// Already installed — skip
|
|
28
|
+
if (fs.existsSync(dest)) {
|
|
29
|
+
console.log('[bingocode] bun already present, skipping bundled deploy.')
|
|
30
|
+
process.exit(0)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const src = path.join(__dirname, '..', 'runtime', 'bun.exe')
|
|
34
|
+
if (!fs.existsSync(src)) {
|
|
35
|
+
console.warn('[bingocode] runtime/bun.exe not found in package, skipping.')
|
|
36
|
+
process.exit(0)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Copy bun.exe
|
|
40
|
+
try {
|
|
41
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true })
|
|
42
|
+
fs.copyFileSync(src, dest)
|
|
43
|
+
fs.chmodSync(dest, 0o755)
|
|
44
|
+
console.log(`[bingocode] deployed bun.exe → ${dest}`)
|
|
45
|
+
} catch (err) {
|
|
46
|
+
console.warn(`[bingocode] failed to deploy bun.exe: ${err.message}`)
|
|
47
|
+
process.exit(0)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Add ~/.bun/bin to HKCU PATH (no admin required)
|
|
51
|
+
try {
|
|
52
|
+
const bunBinDir = path.dirname(dest)
|
|
53
|
+
|
|
54
|
+
// Read current HKCU PATH
|
|
55
|
+
const query = spawnSync(
|
|
56
|
+
'reg',
|
|
57
|
+
['query', 'HKCU\\Environment', '/v', 'PATH'],
|
|
58
|
+
{ encoding: 'utf8', shell: false }
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
let currentPath = ''
|
|
62
|
+
if (query.status === 0 && query.stdout) {
|
|
63
|
+
const match = query.stdout.match(/PATH\s+REG(?:_EXPAND)?_SZ\s+(.+)/i)
|
|
64
|
+
if (match) currentPath = match[1].trim()
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Already in PATH
|
|
68
|
+
if (currentPath.toLowerCase().includes(bunBinDir.toLowerCase())) {
|
|
69
|
+
console.log('[bingocode] PATH already contains bun bin dir.')
|
|
70
|
+
process.exit(0)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const newPath = currentPath ? `${currentPath};${bunBinDir}` : bunBinDir
|
|
74
|
+
|
|
75
|
+
const reg = spawnSync(
|
|
76
|
+
'reg',
|
|
77
|
+
['add', 'HKCU\\Environment', '/v', 'PATH', '/t', 'REG_EXPAND_SZ', '/d', newPath, '/f'],
|
|
78
|
+
{ encoding: 'utf8', shell: false }
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
if (reg.status === 0) {
|
|
82
|
+
console.log(`[bingocode] added ${bunBinDir} to user PATH.`)
|
|
83
|
+
console.log('[bingocode] NOTE: restart your terminal for PATH change to take effect.')
|
|
84
|
+
} else {
|
|
85
|
+
console.warn(`[bingocode] could not update PATH: ${reg.stderr}`)
|
|
86
|
+
}
|
|
87
|
+
} catch (err) {
|
|
88
|
+
console.warn(`[bingocode] PATH update failed (non-fatal): ${err.message}`)
|
|
89
|
+
}
|
|
@@ -46,3 +46,10 @@ for (const skill of skills) {
|
|
|
46
46
|
console.warn(`[bingocode] could not install skill ${skill}: ${err.message}`)
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
|
+
|
|
50
|
+
// Deploy bundled bun.exe (Windows only, skips if already present)
|
|
51
|
+
try {
|
|
52
|
+
require('./install-bun.cjs')
|
|
53
|
+
} catch (err) {
|
|
54
|
+
console.warn(`[bingocode] bun deploy step failed (non-fatal): ${err.message}`)
|
|
55
|
+
}
|
package/src/constants/prompts.ts
CHANGED
|
@@ -230,8 +230,9 @@ function getSimpleDoingTasksSection(): string {
|
|
|
230
230
|
`In general, do not propose changes to code you haven't read. If a user asks about or wants you to modify a file, read it first. Understand existing code before suggesting modifications.`,
|
|
231
231
|
`Do not create files unless they're absolutely necessary for achieving your goal. Generally prefer editing an existing file to creating a new one, as this prevents file bloat and builds on existing work more effectively.`,
|
|
232
232
|
`Avoid giving time estimates or predictions for how long tasks will take, whether for your own work or for users planning projects. Focus on what needs to be done, not how long it might take.`,
|
|
233
|
-
`
|
|
233
|
+
`On failure: diagnose before switching tactics. Don't retry blindly or abandon after one failure. Escalate with ${ASK_USER_QUESTION_TOOL_NAME} at objective thresholds: same error 3×, same file edited 4×, non-zero exit after 2 distinct fixes.`,
|
|
234
234
|
`Be careful not to introduce security vulnerabilities such as command injection, XSS, SQL injection, and other OWASP top 10 vulnerabilities. If you notice that you wrote insecure code, immediately fix it. Prioritize writing safe, secure, and correct code.`,
|
|
235
|
+
`Done = outcome verified + no new regressions + result stated. If unverifiable, say so. Never claim done on "looks right".`,
|
|
235
236
|
...codeStyleSubitems,
|
|
236
237
|
`Avoid backwards-compatibility hacks like renaming unused _vars, re-exporting types, adding // removed comments for removed code, etc. If you are certain that something is unused, you can delete it completely.`,
|
|
237
238
|
// @[MODEL LAUNCH]: False-claims mitigation for Capybara v8 (29-30% FC rate vs v4's 16.7%)
|
|
@@ -255,15 +256,21 @@ function getSimpleDoingTasksSection(): string {
|
|
|
255
256
|
function getActionsSection(): string {
|
|
256
257
|
return `# Executing actions with care
|
|
257
258
|
|
|
258
|
-
|
|
259
|
+
Two axes govern every action — reversibility and blast radius:
|
|
260
|
+
- Local + reversible (edit files, run tests): proceed freely.
|
|
261
|
+
- Hard-to-reverse OR affects shared state OR risky/destructive: confirm with user first.
|
|
259
262
|
|
|
260
|
-
|
|
261
|
-
- Destructive operations: deleting files/branches, dropping database tables, killing processes, rm -rf, overwriting uncommitted changes
|
|
262
|
-
- Hard-to-reverse operations: force-pushing (can also overwrite upstream), git reset --hard, amending published commits, removing or downgrading packages/dependencies, modifying CI/CD pipelines
|
|
263
|
-
- Actions visible to others or that affect shared state: pushing code, creating/closing/commenting on PRs or issues, sending messages (Slack, email, GitHub), posting to external services, modifying shared infrastructure or permissions
|
|
264
|
-
- Uploading content to third-party web tools (diagram renderers, pastebins, gists) publishes it - consider whether it could be sensitive before sending, since it may be cached or indexed even if later deleted.
|
|
263
|
+
The cost of asking is near zero; the cost of an unwanted action (lost work, deleted branches, sent messages) can be very high.
|
|
265
264
|
|
|
266
|
-
|
|
265
|
+
Risk categories requiring confirmation:
|
|
266
|
+
- Destructive: deleting files/branches, dropping tables, killing processes, rm -rf, overwriting uncommitted changes
|
|
267
|
+
- Hard-to-reverse: force-push, git reset --hard, amending published commits, removing or downgrading packages/dependencies, modifying CI/CD pipelines
|
|
268
|
+
- Shared-state visible: pushing code, creating/closing/commenting on PRs or issues, sending messages (Slack, email, GitHub), posting to external services, modifying shared infrastructure or permissions
|
|
269
|
+
- Third-party upload: diagram renderers, pastebins, gists — may be cached or indexed even if deleted later
|
|
270
|
+
|
|
271
|
+
Authorization: one-time approval covers only that scope — confirm again outside it, unless CLAUDE.md says otherwise. If asked to operate autonomously, proceed but remain risk-aware.
|
|
272
|
+
|
|
273
|
+
Obstacles: diagnose root causes; do not use destructive actions as shortcuts (e.g. --no-verify). Investigate unexpected state (unfamiliar files, branches, lock files) before deleting or overwriting — it may be in-progress work. Measure twice, cut once.`
|
|
267
274
|
}
|
|
268
275
|
|
|
269
276
|
function getUsingYourToolsSection(enabledTools: Set<string>): string {
|
|
@@ -415,21 +422,26 @@ These user-facing text instructions do not apply to code or tool calls.`
|
|
|
415
422
|
}
|
|
416
423
|
return `# Output efficiency
|
|
417
424
|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
Keep your text output brief and direct. Lead with the answer or action, not the reasoning. Skip filler words, preamble, and unnecessary transitions. Do not restate what the user said — just do it. When explaining, include only what is necessary for the user to understand.
|
|
425
|
+
Lead with the answer. Be concise. Skip preamble, filler, and restatement.
|
|
421
426
|
|
|
422
427
|
Focus text output on:
|
|
423
428
|
- Decisions that need the user's input
|
|
424
429
|
- High-level status updates at natural milestones
|
|
425
430
|
- Errors or blockers that change the plan
|
|
426
431
|
|
|
432
|
+
Format by situation:
|
|
433
|
+
- Direct question or simple task → single sentence or one short paragraph, no headers
|
|
434
|
+
- Multi-step result with distinct outcomes → bullet list, no prose wrapper
|
|
435
|
+
- Explanation of a decision or tradeoff → two sentences max, lead with conclusion
|
|
436
|
+
- Error report → one line: what failed, why, what you'll try next
|
|
437
|
+
|
|
427
438
|
If you can say it in one sentence, don't use three. Prefer short, direct sentences over long explanations. This does not apply to code or tool calls.`
|
|
428
439
|
}
|
|
429
440
|
|
|
430
441
|
function getSimpleToneAndStyleSection(): string {
|
|
431
442
|
const items = [
|
|
432
443
|
`Only use emojis if the user explicitly requests it. Avoid using emojis in all communication unless asked.`,
|
|
444
|
+
`Mirror the user's language in all responses unless a language preference is configured.`,
|
|
433
445
|
process.env.USER_TYPE === 'ant'
|
|
434
446
|
? null
|
|
435
447
|
: `Your responses should be short and concise.`,
|
|
@@ -838,7 +850,7 @@ function getFunctionResultClearingSection(model: string): string | null {
|
|
|
838
850
|
Old tool results will be automatically cleared from context to free up space. The ${config.keepRecent} most recent results are always kept.`
|
|
839
851
|
}
|
|
840
852
|
|
|
841
|
-
const SUMMARIZE_TOOL_RESULTS_SECTION = `When working with tool results, write down any important information you might need later in your response, as the original tool result may be cleared later.`
|
|
853
|
+
const SUMMARIZE_TOOL_RESULTS_SECTION = `When working with tool results, write down any important information you might need later in your response, as the original tool result may be cleared later. After compaction: don't assume prior state holds — re-read files and re-run verifications before continuing.`
|
|
842
854
|
|
|
843
855
|
function getBriefSection(): string | null {
|
|
844
856
|
if (!(feature('KAIROS') || feature('KAIROS_BRIEF'))) return null
|
package/src/ink/terminal.ts
CHANGED
|
@@ -173,8 +173,14 @@ export function supportsExtendedKeys(): boolean {
|
|
|
173
173
|
* SetConsoleCursorPosition follows the cursor into scrollback
|
|
174
174
|
* (microsoft/terminal#14774), yanking users to the top of their buffer
|
|
175
175
|
* mid-stream. WT_SESSION catches WSL-in-Windows-Terminal where platform
|
|
176
|
-
* is linux but output still routes through conhost.
|
|
176
|
+
* is linux but output still routes through conhost.
|
|
177
|
+
*
|
|
178
|
+
* xterm.js (VS Code, Cursor, Windsurf integrated terminals) does NOT have
|
|
179
|
+
* this bug — cursor-up (CSI A) clamps at viewport top without yanking into
|
|
180
|
+
* scrollback. Even when WT_SESSION is set (e.g. VS Code running inside
|
|
181
|
+
* Windows Terminal), the actual pty renderer is xterm.js, so we exempt it. */
|
|
177
182
|
export function hasCursorUpViewportYankBug(): boolean {
|
|
183
|
+
if (isXtermJs()) return false
|
|
178
184
|
return process.platform === 'win32' || !!process.env.WT_SESSION
|
|
179
185
|
}
|
|
180
186
|
|
|
@@ -478,7 +478,7 @@ function handleFinishReason(
|
|
|
478
478
|
const stopReason = mapFinishReason(finishReason)
|
|
479
479
|
|
|
480
480
|
// Capture input_tokens if available in this chunk
|
|
481
|
-
if (chunk.usage?.prompt_tokens) state.inputTokens = chunk.usage.prompt_tokens
|
|
481
|
+
if (chunk.usage?.prompt_tokens != null) state.inputTokens = chunk.usage.prompt_tokens
|
|
482
482
|
|
|
483
483
|
const usage = chunk.usage
|
|
484
484
|
? { input_tokens: chunk.usage.prompt_tokens || 0, output_tokens: chunk.usage.completion_tokens || 0 }
|
|
@@ -509,7 +509,7 @@ function mergeUsageIntoHeldDelta(
|
|
|
509
509
|
): void {
|
|
510
510
|
if (!state.heldMessageDelta) return
|
|
511
511
|
|
|
512
|
-
if (usage.prompt_tokens) state.inputTokens = usage.prompt_tokens
|
|
512
|
+
if (usage.prompt_tokens != null) state.inputTokens = usage.prompt_tokens
|
|
513
513
|
const data = state.heldMessageDelta.data as Record<string, unknown>
|
|
514
514
|
data.usage = { input_tokens: state.inputTokens, output_tokens: usage.completion_tokens || 0 }
|
|
515
515
|
state.messageDeltaSent = true
|
|
@@ -88,7 +88,7 @@ export function anthropicToOpenaiChat(body: AnthropicRequest): OpenAIChatRequest
|
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
// thinking → reasoning_effort
|
|
91
|
-
if (body.thinking
|
|
91
|
+
if (body.thinking) {
|
|
92
92
|
const budget = body.thinking.budget_tokens
|
|
93
93
|
if (budget !== undefined) {
|
|
94
94
|
if (budget <= 1024) result.reasoning_effort = 'low'
|
|
@@ -19,7 +19,10 @@ export async function evaluateGoal(
|
|
|
19
19
|
goalCondition: string,
|
|
20
20
|
messages: MessageType[],
|
|
21
21
|
): Promise<GoalEvalResult> {
|
|
22
|
-
const client = new Anthropic(
|
|
22
|
+
const client = new Anthropic({
|
|
23
|
+
baseURL: process.env.ANTHROPIC_BASE_URL ?? undefined,
|
|
24
|
+
apiKey: process.env.ANTHROPIC_API_KEY ?? 'dummy',
|
|
25
|
+
})
|
|
23
26
|
|
|
24
27
|
const recentAssistantTexts = messages
|
|
25
28
|
.filter(m => m.type === 'assistant' || m.role === 'assistant')
|