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.
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bingocode",
3
- "version": "1.1.125",
3
+ "version": "1.1.127",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "claude": "bin/claude-win.cjs",
@@ -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
+ }
@@ -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
- `If an approach fails, diagnose why before switching tactics—read the error, check your assumptions, try a focused fix. Don't retry the identical action blindly, but don't abandon a viable approach after a single failure either. Escalate to the user with ${ASK_USER_QUESTION_TOOL_NAME} only when you're genuinely stuck after investigation, not as a first response to friction.`,
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
- Carefully consider the reversibility and blast radius of actions. Generally you can freely take local, reversible actions like editing files or running tests. But for actions that are hard to reverse, affect shared systems beyond your local environment, or could otherwise be risky or destructive, check with the user before proceeding. The cost of pausing to confirm is low, while the cost of an unwanted action (lost work, unintended messages sent, deleted branches) can be very high. For actions like these, consider the context, the action, and user instructions, and by default transparently communicate the action and ask for confirmation before proceeding. This default can be changed by user instructions - if explicitly asked to operate more autonomously, then you may proceed without confirmation, but still attend to the risks and consequences when taking actions. A user approving an action (like a git push) once does NOT mean that they approve it in all contexts, so unless actions are authorized in advance in durable instructions like CLAUDE.md files, always confirm first. Authorization stands for the scope specified, not beyond. Match the scope of your actions to what was actually requested.
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
- Examples of the kind of risky actions that warrant user confirmation:
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
- When you encounter an obstacle, do not use destructive actions as a shortcut to simply make it go away. For instance, try to identify root causes and fix underlying issues rather than bypassing safety checks (e.g. --no-verify). If you discover unexpected state like unfamiliar files, branches, or configuration, investigate before deleting or overwriting, as it may represent the user's in-progress work. For example, typically resolve merge conflicts rather than discarding changes; similarly, if a lock file exists, investigate what process holds it rather than deleting it. In short: only take risky actions carefully, and when in doubt, ask before acting. Follow both the spirit and letter of these instructions - measure twice, cut once.`
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
- IMPORTANT: Go straight to the point. Try the simplest approach first without going in circles. Do not overdo it. Be extra concise.
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
@@ -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 && !body.model.toLowerCase().includes('deepseek')) {
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')