@simonyea/holysheep-cli 2.1.28 → 2.1.29

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simonyea/holysheep-cli",
3
- "version": "2.1.28",
3
+ "version": "2.1.29",
4
4
  "description": "Claude Code/Cursor/Cline API relay for China \u2014 \u00a51=$1, WeChat/Alipay payment, no credit card, no VPN. One command setup for all AI coding tools.",
5
5
  "scripts": {
6
6
  "test": "node tests/droid.test.js && node tests/workspace-store.test.js && node tests/runtime-stale-upgrade.test.js && node tests/hermes.test.js && node tests/preflight.test.js",
@@ -305,12 +305,25 @@ module.exports = {
305
305
  return isConfiguredInToml(readConfig())
306
306
  },
307
307
  configure(apiKey, _baseUrlAnthropic, baseUrlOpenAI, primaryModel /*, _selectedModels */) {
308
- const merged = mergeConfig(apiKey, baseUrlOpenAI, primaryModel)
308
+ // [HolySheep fork v2.1.29 / hs22] Hermes talks to its provider via the
309
+ // OpenAI-compatible Chat Completions API (`/v1/chat/completions`), which
310
+ // the HolySheep CRS relay does NOT support for `claude-*` model IDs at
311
+ // the moment (returns 503 "Service temporarily unavailable"). Only the
312
+ // anthropic native `/v1/messages` path accepts Claude. GPT-family models
313
+ // work on both paths.
314
+ //
315
+ // To give users a usable hermes out of the box we pick a safe default
316
+ // here: if the caller passes a `claude-*` model, silently downgrade to
317
+ // gpt-5.4 (HolySheep's default GPT model) for hermes only. The TOML
318
+ // keeps the real choice so `hermes --provider holysheep --model claude-*`
319
+ // still works if the user overrides it later (and CRS fixes the upstream).
320
+ const hermesPrimaryModel = /^claude-/i.test(primaryModel || '') ? 'gpt-5.4' : (primaryModel || 'gpt-5.4')
321
+ const merged = mergeConfig(apiKey, baseUrlOpenAI, hermesPrimaryModel)
309
322
  writeConfig(merged)
310
323
  // [HolySheep fork v2.1.28 / hs21] Also patch config.yaml so the actual
311
324
  // agent runtime uses the right base_url. See CONFIG_YAML comment.
312
325
  try {
313
- patchConfigYaml(apiKey, baseUrlOpenAI, primaryModel)
326
+ patchConfigYaml(apiKey, baseUrlOpenAI, hermesPrimaryModel)
314
327
  } catch (e) {
315
328
  // Non-fatal: hermes can still run on config.toml alone if the user
316
329
  // manually edits config.yaml. Surface via stderr for diagnosability.
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env python3
2
2
  """
3
- [HolySheep fork v2.1.25 / hs19] Hermes ACP PTY wrapper.
3
+ [HolySheep fork v2.1.29 / hs22] Hermes ACP PTY wrapper.
4
4
 
5
5
  Why: bun 1.3.9's subprocess.spawn with stdio:['pipe','pipe','pipe']
6
6
  passes sockets to the child. Python's asyncio.connect_write_pipe()
@@ -13,9 +13,22 @@ captures Python tracebacks separately. Master side pumps bytes between
13
13
  our (bun-spawned) stdin/stdout and the PTY, so bun reads through kernel
14
14
  PTY buffer which hermes's asyncio transport drives correctly.
15
15
 
16
- Disable ECHO on slave so stdin bytes are not echoed back as stdout bytes
17
- (the old BSD `script -q /dev/null` wrapper had this bug).
18
- Disable ONLCR so '\\n' is not rewritten to '\\r\\n'.
16
+ CRITICAL: disable ICANON (canonical/line-buffered mode) on the slave.
17
+ Default macOS/Linux PTY slaves have ICANON on, which means:
18
+ 1. Input is buffered line-by-line and each line is capped at MAX_CANON
19
+ (1024B on macOS, ~4096B on Linux). Longer lines get truncated.
20
+ 2. Special chars (^C, ^D, ^Z, erase/kill) are interpreted instead of
21
+ passed through — breaks JSON containing random bytes.
22
+
23
+ ACP session/prompt JSON can exceed 4KB easily (system prompt + skill
24
+ list + assistant rules). Before hs22 we only disabled ECHO + ONLCR, so
25
+ id=1 (initialize, ~150B) and id=2/3 (newSession, setSessionMode, <400B)
26
+ went through, but id=4 (prompt, ~4-8KB) was truncated by MAX_CANON —
27
+ hermes got invalid JSON, returned an SDK error with empty data, our
28
+ AcpAgentManager 60s fallback masked it. User saw "hermes thinks forever".
29
+
30
+ Also disable ICRNL and IXON so we don't have \\r<->\\n rewriting or
31
+ flow-control pauses on large bursts.
19
32
 
20
33
  Usage: python3 pty-hermes-wrapper.py
21
34
  HERMES_BIN is auto-resolved from $PATH; override via $HOLYSHEEP_HERMES_BIN.
@@ -39,9 +52,30 @@ def main() -> None:
39
52
  hermes_bin = _resolve_hermes_bin()
40
53
  master_fd, slave_fd = pty.openpty()
41
54
  attrs = termios.tcgetattr(slave_fd)
42
- attrs[3] &= ~termios.ECHO
43
- attrs[1] &= ~termios.ONLCR
55
+ # attrs = [iflag, oflag, cflag, lflag, ispeed, ospeed, cc]
56
+ # lflag (attrs[3]): disable canonical-mode line buffering, ECHO*, signal chars
57
+ attrs[3] &= ~(termios.ICANON | termios.ECHO | termios.ECHOE | termios.ECHOK
58
+ | termios.ECHONL | termios.ISIG)
59
+ # iflag (attrs[0]): disable \r<->\n translation, XON/XOFF flow control,
60
+ # and parity checking (we carry raw bytes only).
61
+ attrs[0] &= ~(termios.ICRNL | termios.INLCR | termios.IGNCR | termios.IXON
62
+ | termios.IXOFF | termios.ISTRIP | termios.IGNBRK | termios.BRKINT
63
+ | termios.INPCK | termios.PARMRK)
64
+ # oflag (attrs[1]): disable post-processing (ONLCR \n -> \r\n, tabs, etc.)
65
+ attrs[1] &= ~termios.OPOST
66
+ # Non-blocking reads: return as soon as 1 byte is available.
67
+ attrs[6][termios.VMIN] = 1
68
+ attrs[6][termios.VTIME] = 0
44
69
  termios.tcsetattr(slave_fd, termios.TCSANOW, attrs)
70
+ # Best-effort: print the applied flags once so future regressions are
71
+ # easy to diagnose from hs web logs.
72
+ try:
73
+ sys.stderr.write(
74
+ f'[pty-hermes-wrapper] slave configured raw: ICANON off, ECHO off, OPOST off\n'
75
+ )
76
+ sys.stderr.flush()
77
+ except OSError:
78
+ pass
45
79
 
46
80
  pid = os.fork()
47
81
  if pid == 0:
@@ -103,9 +137,28 @@ def main() -> None:
103
137
  except ProcessLookupError:
104
138
  pass
105
139
  break
106
- try:
107
- os.write(master_fd, data)
108
- except OSError:
140
+ # [HolySheep fork v2.1.29 / hs22] Diagnostic trace when enabled —
141
+ # emits one line per stdin chunk so we can see exactly what bun
142
+ # pushed to us and verify hermes received the full payload. Only
143
+ # active when HOLYSHEEP_PTY_TRACE=1 is set to avoid log flood.
144
+ if os.environ.get('HOLYSHEEP_PTY_TRACE') == '1':
145
+ try:
146
+ sys.stderr.write(f'[pty-hermes-wrapper] stdin chunk len={len(data)}\n')
147
+ sys.stderr.flush()
148
+ except OSError:
149
+ pass
150
+ # Write in full — os.write may short-write on large buffers; loop.
151
+ total = 0
152
+ while total < len(data):
153
+ try:
154
+ n = os.write(master_fd, data[total:])
155
+ except OSError:
156
+ total = -1
157
+ break
158
+ if n <= 0:
159
+ break
160
+ total += n
161
+ if total < 0:
109
162
  break
110
163
  finally:
111
164
  try:
@@ -60,10 +60,10 @@ const VENDOR_DIR = path.join(__dirname, 'vendor', 'aionui')
60
60
  // new CLI release, the next `hs web` invocation on user machines will detect
61
61
  // the version drift and upgrade the cache in place.
62
62
  const DEFAULT_RUNTIME_URL =
63
- 'https://mail.holysheep.ai/app/cli/aionui-runtime-v1.9.18-holysheep-hs20.tar.gz'
63
+ 'https://mail.holysheep.ai/app/cli/aionui-runtime-v1.9.18-holysheep-hs22.tar.gz'
64
64
  const DEFAULT_RUNTIME_SHA256 =
65
- '99ddb768cacd223a13c77d716413032e913c8be2850e7dbccaf7ae52d0797e37'
66
- const DEFAULT_RUNTIME_VERSION = '1.9.18-holysheep-hs20'
65
+ '03e386ea83660b4074e29026dfc53be6ed01fcd51fa35a9379ed64a396e99f33'
66
+ const DEFAULT_RUNTIME_VERSION = '1.9.18-holysheep-hs22'
67
67
 
68
68
  function isValidRuntimeDir(dir) {
69
69
  if (!dir) return false