@cnwenf/occ 2.1.335 → 2.1.337

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/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
  [![npm version](https://img.shields.io/npm/v/@cnwenf/occ.svg)](https://www.npmjs.com/package/@cnwenf/occ)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE)
7
7
  [![Runtime: Bun](https://img.shields.io/badge/Runtime-Bun-%23000000.svg)](https://bun.sh/)
8
- [![Tracks: Claude Code 2.1.270](https://img.shields.io/badge/Tracks-Claude%20Code%202.1.270-blueviolet.svg)](https://docs.anthropic.com/en/docs/claude-code)
8
+ [![Tracks: Claude Code 2.1.272](https://img.shields.io/badge/Tracks-Claude%20Code%202.1.272-blueviolet.svg)](https://docs.anthropic.com/en/docs/claude-code)
9
9
 
10
10
  [简体中文](./README.zh-CN.md) · **English**
11
11
 
@@ -13,7 +13,7 @@
13
13
 
14
14
  ## What is OCC
15
15
 
16
- **Open C Code (OCC)** is an open-source coding agent. Its capabilities are aligned with [Claude Code](https://docs.anthropic.com/en/docs/claude-code) (currently tracking `2.1.270` — fully aligned through official 2.1.270: the 2.1.268/2.1.269 portable subsets landed in OCC-122/OCC-123/OCC-84, and the 2.1.270 changelog change the read-only git Bash permission regression fix carries no portable client-side delta, verified independently by two forensic rounds OCC-124 + OCC-85; the OCC-125 strict self-acceptance round against the official 2.1.270 binary then landed two live-discovered gaps the full `/output-style` port (Gap-125a) and markdown-serializer html/default-token parity (Gap-125b) — per `docs/upstream-version-gap-occ125.md`). The code is fully open, auditable, backdoor-free, and your data stays under your control.
16
+ **Open C Code (OCC)** is an open-source coding agent. Its capabilities are aligned with [Claude Code](https://docs.anthropic.com/en/docs/claude-code) (currently tracking `2.1.272` — 2.1.270 fully aligned; 2.1.271/2.1.272 partial: the OCC-126 catch-up round landed the 2.1.272 Monitor-deadline behavior (`tengu_breezy_crescent` gate flip), `omitClaudeMd` for custom/plugin agents, the 2.1.271 Bash permission fixes (wildcard glob-arg read validation + declaration-flag charset parity), and the 2.1.272 fast-mode fixes, per `docs/upstream-version-gap-occ126.md`; still not landed from the 2.1.270→2.1.272 delta: `/config` panel fullscreen mouse support (PORTABLE-LARGE scope) and the spinner status ladder "deep in thought"/"picking the thought back up" (STAGED) — occ127 candidates, plus the pre-existing sandbox per-command `allowed_domains` gap; prior alignment through 2.1.270 landed via OCC-122/OCC-123/OCC-84/OCC-124/OCC-85/OCC-125). The code is fully open, auditable, backdoor-free, and your data stays under your control.
17
17
 
18
18
  If you worry that a closed-source CLI might hide backdoors, or that your code and credentials are uploaded to unauditable services, OCC is for you: all source is open and unobfuscated, the build is reproducible from source, and API credentials are sent only to endpoints you configure.
19
19
 
@@ -40,7 +40,7 @@ Requires a valid Anthropic API Key (or AWS Bedrock / Google Vertex / Azure Found
40
40
  - 🔧 **Full tool suite** — Bash, Read, Edit, Write, NotebookEdit, Grep, Glob, Agent, WebFetch, WebSearch, WebBrowser (real Chrome via CDP), Todo, Skills, and more.
41
41
  - 🤖 **Sub-agents** — spawn fork / async / background / remote agents; team swarms (`TeamCreate`/`TeamDelete`) and worktree isolation.
42
42
  - 🔀 **Workflow engine** — vm-sandboxed multi-agent workflow scripts; `/workflows` browse + async launch (`remote: true`) + progress tracking. _(live via `WORKFLOW_SCRIPTS`)_
43
- - 📊 **Monitor tool** — self-contained monitoring. _(live via `MONITOR_TOOL`)_
43
+ - 📊 **Monitor tool** — self-contained monitoring. _(live via `MONITOR_TOOL`; events and the deadline-expiry notice are recorded internally — chat delivery wiring is an occ127 follow-up, and the deadline kill itself is enforced)_
44
44
  - 🌐 **WebBrowser** — navigate, read page text, screenshot, and batch actions through a real Chrome instance (CDP).
45
45
  - 🛡️ **Permission model** — `default` / `acceptEdits` / `plan` / `bypassPermissions` modes, auto-approval, destructive-command blocking, path validation, rule matching.
46
46
  - 🪝 **Hooks** — `PreToolUse`, `PostToolUse`, `PermissionDenied`, `Stop`, and more, configurable via `settings.json`.
@@ -62,7 +62,7 @@ Requires a valid Anthropic API Key (or AWS Bedrock / Google Vertex / Azure Found
62
62
  | **Auditability** | Line-by-line reviewable | No |
63
63
  | **Telemetry** | Minimal (analytics stubbed) | Standard |
64
64
  | **Data sovereignty** | Credentials stay on your machine; requests only to endpoints you configure | Anthropic endpoints |
65
- | **Capability parity** | Tracks CC `2.1.270` (fully aligned) | Reference implementation |
65
+ | **Capability parity** | Tracks CC `2.1.272` (2.1.270 fully aligned; 2.1.271/2.1.272 partial) | Reference implementation |
66
66
  | **Providers** | Anthropic Direct, Bedrock, Vertex, Azure | Anthropic, Bedrock, Vertex |
67
67
  | **Cost** | Free & open-source (MIT) | Subscription |
68
68
  | **Build** | Reproducible from source | N/A |
@@ -143,7 +143,7 @@ Requires [Bun](https://bun.sh/) >= 1.3.11 (use `bun upgrade` — older Bun cause
143
143
 
144
144
  ```bash
145
145
  bun install
146
- bun run dev # run from source; version prints 2.1.270 (dev polyfill; build overrides with pkg.version) when working
146
+ bun run dev # run from source; version prints 2.1.272 (dev polyfill; build overrides with pkg.version) when working
147
147
  bun run build # output: dist/cli.js (~26 MB, single-file bundle)
148
148
  bun test # test suite (Bun test runner)
149
149
  bun run lint # Biome lint (formatter disabled to avoid large diffs)
@@ -157,7 +157,7 @@ For architecture, entry/bootstrap, tool system, UI layer, and module-status deta
157
157
 
158
158
  ## Status
159
159
 
160
- - Tracks Claude Code **`2.1.270`** (fully aligned through official 2.1.270 portable subsets through 2.1.269 landed in OCC-122/OCC-123/OCC-84; the 2.1.270 changelog change is the read-only-git Bash permission regression fix, which carries no portable client-side delta, verified independently by OCC-124 + OCC-85 — see `docs/upstream-version-gap-occ124.md` and `docs/upstream-version-gap-occ85.md`. The OCC-125 strict self-acceptance round against the official 2.1.270 binary landed two live-discovered gaps: Gap-125a `/output-style` full port + Gap-125b markdown-serializer html/default-token parity — see `docs/upstream-version-gap-occ125.md`).
160
+ - Tracks Claude Code **`2.1.272`** (2.1.270 fully aligned; 2.1.271/2.1.272 partial — the OCC-126 catch-up round landed the Monitor-deadline gate flip, `omitClaudeMd` for custom/plugin agents, the 2.1.271 Bash permission fixes, and the 2.1.272 fast-mode fixes — see `docs/upstream-version-gap-occ126.md`; still not landed from the 2.1.270→2.1.272 delta: `/config` fullscreen mouse support (PORTABLE-LARGE) and the spinner status ladder (STAGED), plus the pre-existing sandbox per-command `allowed_domains` gap; prior alignment through 2.1.270 landed via OCC-122/OCC-123/OCC-84, OCC-124 + OCC-85 — see `docs/upstream-version-gap-occ124.md` and `docs/upstream-version-gap-occ85.md` and OCC-125 — see `docs/upstream-version-gap-occ125.md`).
161
161
  - Published to npm as [`@cnwenf/occ`](https://www.npmjs.com/package/@cnwenf/occ).
162
162
  - Many modules are intentionally stubbed or feature-flagged off — see "Disabled / stubbed" above.
163
163
 
package/README.zh-CN.md CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  ## 这是什么
10
10
 
11
- **Open C Code(OCC)** 是一个开源的编码智能体。能力与 [Claude Code](https://docs.anthropic.com/en/docs/claude-code) 对齐(当前跟踪 `2.1.270`:已完全对齐至官方 2.1.270——2.1.268/2.1.269 的可移植子集已在 OCC-122/OCC-123/OCC-84 落地,2.1.270 唯一变更(Bash 只读 git 权限回归修复)无可移植客户端代码差异,经 OCC-124OCC-85 两轮独立取证核实,详见相应台账)。代码全开放、可审计、无暗门,数据由你掌控。
11
+ **Open C Code(OCC)** 是一个开源的编码智能体。能力与 [Claude Code](https://docs.anthropic.com/en/docs/claude-code) 对齐(当前跟踪 `2.1.272`:2.1.270 已完全对齐、2.1.271/2.1.272 部分对齐——OCC-126 追齐轮落地了 2.1.272 Monitor 超时门翻转、自定义/插件智能体的 `omitClaudeMd`、2.1.271 Bash 权限修复(通配符 glob 参数读校验 + 声明标志字符集对齐)与 2.1.272 fast mode 修复,台账见 `docs/upstream-version-gap-occ126.md`;2.1.270→2.1.272 增量中仍未落地:`/config` 全屏鼠标支持(PORTABLE-LARGE 范围)与 spinner 状态文案阶梯 "deep in thought"/"picking the thought back up"(STAGED)——occ127 候选,另有先于 2.1.270 已存在的 sandbox 按命令 `allowed_domains` 缺口;此前对齐至 2.1.270 经 OCC-122/OCC-123/OCC-84/OCC-124/OCC-85/OCC-125 落地)。代码全开放、可审计、无暗门,数据由你掌控。
12
12
 
13
13
  如果你担心闭源 CLI 可能植入后门、担心代码与凭据被上传到不可审计的服务,OCC 就是为你准备的:全部源码开放、无混淆,构建产物可由源码复现,API 凭据只发往你自己配置的端点。
14
14
 
@@ -21,7 +21,7 @@
21
21
 
22
22
  ## 现状
23
23
 
24
- - 跟踪 Claude Code **`2.1.270`**(已完全对齐至官方 2.1.270——2.1.268/2.1.269 的可移植子集已在 OCC-122/OCC-123/OCC-84 落地;2.1.270 唯一变更(Bash 只读 git 权限回归修复)无可移植客户端差异,经 OCC-124OCC-85 两轮独立取证核实 OCC 不受影响)。
24
+ - 跟踪 Claude Code **`2.1.272`**(2.1.270 已完全对齐、2.1.271/2.1.272 部分对齐——OCC-126 追齐轮落地 Monitor 超时门翻转、`omitClaudeMd`、2.1.271 Bash 权限修复与 2.1.272 fast mode 修复,台账见 `docs/upstream-version-gap-occ126.md`;2.1.270→2.1.272 增量中仍未落地:`/config` 全屏鼠标支持(PORTABLE-LARGE)与 spinner 状态文案阶梯(STAGED),另有先于 2.1.270 已存在的 sandbox 按命令 `allowed_domains` 缺口;此前对齐至 2.1.270 经 OCC-122/OCC-123/OCC-84/OCC-124/OCC-85/OCC-125 落地)。
25
25
  - 代码库有约 1300 个不阻塞的 `tsc` 类型错误(大量松散的 `unknown`/`never`/`{}` 类型),**不影响 Bun 运行时执行**。门槛是 Biome lint,不是 `tsc`。
26
26
  - 所有内部 feature flag(`feature(...)`)已被 polyfill 为 `false` —— 内部功能(COORDINATOR_MODE、KAIROS、PROACTIVE 等)全部关闭。
27
27
  - 已发布到 npm:[`@cnwenf/occ`](https://www.npmjs.com/package/@cnwenf/occ)。
@@ -80,7 +80,7 @@ Glob、Grep(默认启用);TaskCreate/Get/Update/List(Todo v2)、EnterW
80
80
 
81
81
  ```bash
82
82
  bun install
83
- bun run dev # 从源码运行;版本号显示 2.1.270(dev polyfill;build 用 pkg.version 覆盖)即正常
83
+ bun run dev # 从源码运行;版本号显示 2.1.272(dev polyfill;build 用 pkg.version 覆盖)即正常
84
84
  bun run build # 产物:dist/cli.js(~26MB,5300+ 模块,单文件 bundle)
85
85
  bun test # 测试套件
86
86
  bun run lint # Biome lint(禁用格式化以避免大 diff)
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env bun
2
- globalThis.MACRO={"VERSION":"2.1.335","BINARY_NAME":"occ","BUILD_TIME":"2026-09-14T23:25:57.529Z","FEEDBACK_CHANNEL":"","ISSUES_EXPLAINER":"","NATIVE_PACKAGE_URL":"","PACKAGE_URL":"@cnwenf/occ","VERSION_CHANGELOG":""};
2
+ globalThis.MACRO={"VERSION":"2.1.337","BINARY_NAME":"occ","BUILD_TIME":"2026-09-15T23:26:27.856Z","FEEDBACK_CHANNEL":"","ISSUES_EXPLAINER":"","NATIVE_PACKAGE_URL":"","PACKAGE_URL":"@cnwenf/occ","VERSION_CHANGELOG":""};
3
3
  // @bun
4
4
  var __create = Object.create;
5
5
  var __getProtoOf = Object.getPrototypeOf;
@@ -232750,6 +232750,7 @@ function parseAgentFromJson(name3, definition, source = "flagSettings") {
232750
232750
  ...parsed.skills && parsed.skills.length > 0 ? { skills: parsed.skills } : {},
232751
232751
  ...parsed.initialPrompt ? { initialPrompt: parsed.initialPrompt } : {},
232752
232752
  ...parsed.background ? { background: parsed.background } : {},
232753
+ ...parsed.omitClaudeMd ? { omitClaudeMd: parsed.omitClaudeMd } : {},
232753
232754
  ...parsed.memory ? { memory: parsed.memory } : {},
232754
232755
  ...parsed.isolation ? { isolation: parsed.isolation } : {}
232755
232756
  };
@@ -232809,6 +232810,8 @@ function parseAgentFromMarkdown(filePath, baseDir, frontmatter, content, source)
232809
232810
  logForDebugging(`Agent file ${filePath} has invalid background value '${backgroundRaw}'. Must be 'true', 'false', or omitted.`);
232810
232811
  }
232811
232812
  const background = backgroundRaw === "true" || backgroundRaw === true ? true : undefined;
232813
+ const omitClaudeMdRaw = frontmatter["omitClaudeMd"];
232814
+ const omitClaudeMd = omitClaudeMdRaw === "true" || omitClaudeMdRaw === true ? true : undefined;
232812
232815
  const VALID_MEMORY_SCOPES2 = ["user", "project", "local"];
232813
232816
  const memoryRaw = frontmatter["memory"];
232814
232817
  let memory;
@@ -232906,6 +232909,7 @@ function parseAgentFromMarkdown(filePath, baseDir, frontmatter, content, source)
232906
232909
  ...isValidPermissionMode ? { permissionMode: permissionModeRaw } : {},
232907
232910
  ...maxTurns !== undefined ? { maxTurns } : {},
232908
232911
  ...background ? { background } : {},
232912
+ ...omitClaudeMd ? { omitClaudeMd } : {},
232909
232913
  ...memory ? { memory } : {},
232910
232914
  ...isolation ? { isolation } : {},
232911
232915
  ...cacheTtl !== undefined ? { cacheTtl } : {}
@@ -232964,6 +232968,7 @@ var init_loadAgentsDir = __esm(() => {
232964
232968
  initialPrompt: exports_external.string().optional(),
232965
232969
  memory: exports_external.enum(["user", "project", "local"]).optional(),
232966
232970
  background: exports_external.boolean().optional(),
232971
+ omitClaudeMd: exports_external.boolean().optional(),
232967
232972
  isolation: (process.env.USER_TYPE === "ant" ? exports_external.enum(["worktree", "remote"]) : exports_external.enum(["worktree"])).optional()
232968
232973
  }));
232969
232974
  AgentsJsonSchema = lazySchema(() => exports_external.record(exports_external.string(), AgentJsonSchema()));
@@ -266498,29 +266503,39 @@ async function* withRetry(getClient2, operation, options) {
266498
266503
  } catch (error52) {
266499
266504
  lastError = error52;
266500
266505
  logForDebugging(`API error (attempt ${attempt}/${maxRetries + 1}): ${error52 instanceof APIError ? `${error52.status} ${error52.message}` : errorMessage(error52)}`, { level: "error" });
266506
+ const watchdogRetryEnabled = isRetryWatchdogEnabled();
266501
266507
  if (wasFastModeActive && !isPersistentRetryEnabled() && error52 instanceof APIError && (error52.status === 429 || is529Error(error52))) {
266502
266508
  const overageReason = error52.headers?.get("anthropic-ratelimit-unified-overage-disabled-reason");
266503
266509
  if (overageReason !== null && overageReason !== undefined) {
266504
266510
  handleFastModeOverageRejection(overageReason);
266505
266511
  retryContext.fastMode = false;
266512
+ if (watchdogRetryEnabled && attempt >= maxRetries)
266513
+ attempt = maxRetries;
266506
266514
  continue;
266507
266515
  }
266508
266516
  const retryAfterMs = getRetryAfterMs(error52);
266509
- if (retryAfterMs !== null && retryAfterMs < SHORT_RETRY_THRESHOLD_MS) {
266517
+ const isShortRetry = retryAfterMs !== null && retryAfterMs < SHORT_RETRY_THRESHOLD_MS;
266518
+ if (isShortRetry && !watchdogRetryEnabled) {
266510
266519
  await sleep2(retryAfterMs, options.signal, { abortError });
266511
266520
  continue;
266512
266521
  }
266513
- const cooldownMs = Math.max(retryAfterMs ?? DEFAULT_FAST_MODE_FALLBACK_HOLD_MS, MIN_COOLDOWN_MS);
266514
- const cooldownReason = is529Error(error52) ? "overloaded" : "rate_limit";
266515
- triggerFastModeCooldown(Date.now() + cooldownMs, cooldownReason);
266516
- if (isFastModeEnabled()) {
266517
- retryContext.fastMode = false;
266522
+ if (!isShortRetry) {
266523
+ const cooldownMs = Math.max(retryAfterMs ?? DEFAULT_FAST_MODE_FALLBACK_HOLD_MS, MIN_COOLDOWN_MS);
266524
+ const cooldownReason = is529Error(error52) ? "overloaded" : "rate_limit";
266525
+ triggerFastModeCooldown(Date.now() + cooldownMs, cooldownReason);
266526
+ if (isFastModeEnabled()) {
266527
+ retryContext.fastMode = false;
266528
+ }
266529
+ if (watchdogRetryEnabled && attempt >= maxRetries)
266530
+ attempt = maxRetries;
266531
+ continue;
266518
266532
  }
266519
- continue;
266520
266533
  }
266521
266534
  if (wasFastModeActive && isFastModeNotEnabledError(error52)) {
266522
266535
  handleFastModeRejectedByAPI();
266523
266536
  retryContext.fastMode = false;
266537
+ if (watchdogRetryEnabled && attempt >= maxRetries)
266538
+ attempt = maxRetries;
266524
266539
  continue;
266525
266540
  }
266526
266541
  if (is529Error(error52) && !shouldRetry529(options.querySource) && !isRetryWatchdogEnabled()) {
@@ -361041,10 +361056,17 @@ function collectCommands(node, commands7, varScope) {
361041
361056
  const arg = walkArgument(child, commands7, varScope);
361042
361057
  if (typeof arg !== "string")
361043
361058
  return arg;
361044
- if ((argv[0] === "declare" || argv[0] === "typeset" || argv[0] === "local") && /^-[a-zA-Z]*[niaA]/.test(arg)) {
361059
+ if ((argv[0] === "declare" || argv[0] === "typeset" || argv[0] === "local") && /^[+-].*[nialuAEFLRZ]/.test(arg)) {
361060
+ return {
361061
+ kind: "too-complex",
361062
+ reason: `declare flag ${arg} changes assignment semantics (nameref/integer/float/array/width-truncation/case-conversion)`,
361063
+ nodeType: "declaration_command"
361064
+ };
361065
+ }
361066
+ if ((argv[0] === "export" || argv[0] === "readonly") && /^[+-].*[iluEFLRZ]/.test(arg)) {
361045
361067
  return {
361046
361068
  kind: "too-complex",
361047
- reason: `declare flag ${arg} changes assignment semantics (nameref/integer/array)`,
361069
+ reason: `${argv[0]} flag ${arg} \u2014 zsh bin_typeset mathevals (-i/-E/-F), width-truncates (-L/-R/-Z), or case-converts (-l/-u) the assigned value`,
361048
361070
  nodeType: "declaration_command"
361049
361071
  };
361050
361072
  }
@@ -380838,10 +380860,32 @@ function parsePatternCommand(args, flagsWithArgs, defaults2 = []) {
380838
380860
  }
380839
380861
  return paths2.length > 0 ? paths2 : defaults2;
380840
380862
  }
380863
+ function globCharIndex(arg) {
380864
+ for (let i6 = 0;i6 < arg.length; i6++) {
380865
+ const c9 = arg[i6];
380866
+ if (c9 === "*" || c9 === "?")
380867
+ return i6;
380868
+ if (c9 === "[" && arg.indexOf("]", i6 + 1) !== -1)
380869
+ return i6;
380870
+ }
380871
+ return -1;
380872
+ }
380873
+ function collectUnextractedGlobArgs(args, extractedPaths) {
380874
+ const seen = new Set(extractedPaths);
380875
+ const out = [];
380876
+ for (const arg of args) {
380877
+ if (globCharIndex(arg) !== -1 && !seen.has(arg)) {
380878
+ seen.add(arg);
380879
+ out.push(arg);
380880
+ }
380881
+ }
380882
+ return out;
380883
+ }
380841
380884
  function validateCommandPaths(command4, args, cwd2, toolPermissionContext, compoundCommandHasCd, operationTypeOverride) {
380842
380885
  const extractor = PATH_EXTRACTORS[command4];
380843
- const paths2 = extractor(args);
380886
+ const extractedPaths = extractor(args);
380844
380887
  const operationType = operationTypeOverride ?? COMMAND_OPERATION_TYPE[command4];
380888
+ const paths2 = operationType === "read" ? [...extractedPaths, ...collectUnextractedGlobArgs(args, extractedPaths)] : extractedPaths;
380845
380889
  const validator = COMMAND_VALIDATOR[command4];
380846
380890
  if (validator && !validator(args)) {
380847
380891
  return {
@@ -381307,6 +381351,16 @@ var init_pathValidation2 = __esm(() => {
381307
381351
  sha256sum: filterOutFlags,
381308
381352
  sha1sum: filterOutFlags,
381309
381353
  md5sum: filterOutFlags,
381354
+ tac: filterOutFlags,
381355
+ rev: filterOutFlags,
381356
+ fold: filterOutFlags,
381357
+ expand: filterOutFlags,
381358
+ unexpand: filterOutFlags,
381359
+ fmt: filterOutFlags,
381360
+ comm: filterOutFlags,
381361
+ cmp: filterOutFlags,
381362
+ pr: filterOutFlags,
381363
+ tsort: filterOutFlags,
381310
381364
  tee: (args) => filterTeeDevicePaths(filterOutFlags(args)),
381311
381365
  tr: (args) => {
381312
381366
  const hasDelete = args.some((a5) => a5 === "-d" || a5 === "--delete" || a5.startsWith("-") && a5.includes("d"));
@@ -381499,7 +381553,17 @@ var init_pathValidation2 = __esm(() => {
381499
381553
  sha256sum: "compute SHA-256 checksums for files in",
381500
381554
  sha1sum: "compute SHA-1 checksums for files in",
381501
381555
  md5sum: "compute MD5 checksums for files in",
381502
- tee: "write to files in"
381556
+ tee: "write to files in",
381557
+ tac: "display files in reverse from",
381558
+ rev: "reverse lines of files from",
381559
+ fold: "wrap lines of files from",
381560
+ expand: "expand tabs in files from",
381561
+ unexpand: "convert spaces to tabs in files from",
381562
+ fmt: "format text from files in",
381563
+ comm: "compare sorted lines from files in",
381564
+ cmp: "compare bytes of files from",
381565
+ pr: "paginate files from",
381566
+ tsort: "topologically sort lines from files in"
381503
381567
  };
381504
381568
  COMMAND_OPERATION_TYPE = {
381505
381569
  cd: "read",
@@ -381538,7 +381602,17 @@ var init_pathValidation2 = __esm(() => {
381538
381602
  sha256sum: "read",
381539
381603
  sha1sum: "read",
381540
381604
  md5sum: "read",
381541
- tee: "write"
381605
+ tee: "write",
381606
+ tac: "read",
381607
+ rev: "read",
381608
+ fold: "read",
381609
+ expand: "read",
381610
+ unexpand: "read",
381611
+ fmt: "read",
381612
+ comm: "read",
381613
+ cmp: "read",
381614
+ pr: "read",
381615
+ tsort: "read"
381542
381616
  };
381543
381617
  COMMAND_VALIDATOR = {
381544
381618
  mv: (args) => !args.some((arg) => arg?.startsWith("-")),
@@ -584793,10 +584867,117 @@ ${output2.json}`
584793
584867
  var exports_MonitorTool = {};
584794
584868
  __export(exports_MonitorTool, {
584795
584869
  stopMonitor: () => stopMonitor,
584870
+ normalizeMonitorInput: () => normalizeMonitorInput,
584871
+ monitorExpiredNotice: () => monitorExpiredNotice,
584872
+ fireMonitorDeadline: () => fireMonitorDeadline,
584796
584873
  MonitorTool: () => MonitorTool,
584797
584874
  MONITOR_TOOL_NAME: () => MONITOR_TOOL_NAME
584798
584875
  });
584799
584876
  import { randomUUID as randomUUID22 } from "crypto";
584877
+ function monitorDeadlineCap() {
584878
+ return getIsNonInteractiveSession() ? MONITOR_DEADLINE_CAP_PRINT_MS : MONITOR_DEADLINE_CAP_MS;
584879
+ }
584880
+ function formatMonitorMinutes(ms) {
584881
+ return `${Math.round(ms / 60000)} minutes`;
584882
+ }
584883
+ function normalizeMonitorInput(input2) {
584884
+ return {
584885
+ timeoutMs: Math.min(input2.timeout_ms ?? DEFAULT_TIMEOUT_MS2, monitorDeadlineCap()),
584886
+ persistent: false
584887
+ };
584888
+ }
584889
+ function monitorExpiredNotice(timeoutMs, eventCount) {
584890
+ const duration3 = formatDuration(timeoutMs, { hideTrailingZeros: true });
584891
+ if (eventCount === 0) {
584892
+ return `[Monitor expired after ${duration3} with no events delivered. Re-arm it if you still need the watch \u2014 and widen the filter if silence was unexpected.]`;
584893
+ }
584894
+ return `[Monitor expired after ${duration3} with ${eventCount} ${pluralize2(eventCount, "event")} delivered. Re-arm it if you still need the watch.]`;
584895
+ }
584896
+ function deadlineSection() {
584897
+ return `Every monitor expires after \`timeout_ms\` (default ${formatMonitorMinutes(DEFAULT_TIMEOUT_MS2)}, at most ${formatMonitorMinutes(monitorDeadlineCap())}): it is killed and you get one notice with the event count. Re-arm it if you still need the watch; for a long watch (PR monitoring, log tails) set \`timeout_ms\` to the maximum and re-arm on each expiry, and widen the filter if an expiry with no events was unexpected.`;
584898
+ }
584899
+ function buildDescription2() {
584900
+ return `**OCC build note (event delivery not yet wired):** in this build, Monitor events and the expiry notice are recorded internally but are NOT delivered to the chat \u2014 the notification consumer is a tracked follow-up (occ127). The deadline itself IS enforced: every monitor is killed and deregistered at \`timeout_ms\`. Until delivery lands, use Bash \`run_in_background\` when you need a delivered completion notification, and read the delivery-dependent statements below ("notifications arrive in the chat", the expiry notice) as describing not-yet-available behavior.
584901
+
584902
+ Start a background monitor that streams events from a long-running script. Each stdout line is an event \u2014 you keep working and notifications arrive in the chat. Events arrive on their own schedule and are not replies from the user, even if one lands while you're waiting for the user to answer a question.
584903
+
584904
+ Pick by how many notifications you need:
584905
+ - **One** ("tell me when the server is ready / the build finishes") \u2192 use **Bash with \`run_in_background\`** and a command that exits when the condition is true, e.g. \`until grep -q "Ready in" dev.log; do sleep 0.5; done\`. You get a single completion notification when it exits.
584906
+ - **One per occurrence, indefinitely** ("tell me every time an ERROR line appears") \u2192 Monitor with an unbounded command (\`tail -f\`, \`inotifywait -m\`, \`while true\`).
584907
+ - **One per occurrence, until a known end** ("emit each CI step result, stop when the run completes") \u2192 Monitor with a command that emits lines and then exits.
584908
+
584909
+ Your script's stdout is the event stream. Each line becomes a notification. Exit ends the watch.
584910
+
584911
+ # Each matching log line is an event
584912
+ tail -f /var/log/app.log | grep --line-buffered "ERROR"
584913
+
584914
+ # Each file change is an event
584915
+ inotifywait -m --format '%e %f' /watched/dir
584916
+
584917
+ # Poll GitHub for new PR comments and emit one line per new comment
584918
+ last=$(date -u +%Y-%m-%dT%H:%M:%SZ)
584919
+ while true; do
584920
+ now=$(date -u +%Y-%m-%dT%H:%M:%SZ)
584921
+ gh api "repos/owner/repo/issues/123/comments?since=$last" --jq '.[] | "\\(.user.login): \\(.body)"'
584922
+ last=$now; sleep 30
584923
+ done
584924
+
584925
+ # Node script that emits events as they arrive (e.g. WebSocket listener)
584926
+ node watch-for-events.js
584927
+
584928
+ # Per-occurrence with a natural end: emit each CI check as it lands, exit when the run completes
584929
+ prev=""
584930
+ while true; do
584931
+ s=$(gh pr checks 123 --json name,bucket)
584932
+ cur=$(jq -r '.[] | select(.bucket!="pending") | "\\(.name): \\(.bucket)"' <<<"$s" | sort)
584933
+ comm -13 <(echo "$prev") <(echo "$cur")
584934
+ prev=$cur
584935
+ jq -e 'all(.bucket!="pending")' <<<"$s" >/dev/null && break
584936
+ sleep 30
584937
+ done
584938
+
584939
+ **Don't use an unbounded command for a single notification.** \`tail -f\`, \`inotifywait -m\`, and \`while true\` never exit on their own, so the monitor stays armed until timeout even after the event has fired. For "tell me when X is ready," use Bash \`run_in_background\` with an \`until\` loop instead (one notification, ends in seconds). Note that \`tail -f log | grep -m 1 ...\` does *not* fix this: if the log goes quiet after the match, \`tail\` never receives SIGPIPE and the pipeline hangs anyway.
584940
+
584941
+ **Script quality:**
584942
+ - Every pipe stage must flush per line or matches sit in its buffer unseen: \`grep\` needs \`--line-buffered\`, \`awk\` needs \`fflush()\`. \`head\` cannot flush at all \u2014 \`| head -N\` delivers nothing until N matches accumulate, then ends the stream.
584943
+ - In poll loops, handle transient failures (\`curl ... || true\`) \u2014 one failed request shouldn't kill the monitor.
584944
+ - Poll intervals: 30s+ for remote APIs (rate limits), 0.5-1s for local checks.
584945
+ - Write a specific \`description\` \u2014 it appears in every notification ("errors in deploy.log" not "watching logs").
584946
+ - Only stdout is the event stream. Stderr goes to the output file (readable via Read) but does not trigger notifications \u2014 for a command you run directly (e.g. \`python train.py 2>&1 | grep --line-buffered ...\`), merge stderr with \`2>&1\` so its failures reach your filter. (No effect on \`tail -f\` of an existing log \u2014 that file only contains what its writer redirected.)
584947
+
584948
+ **Coverage \u2014 silence is not success.** When watching a job or process for an outcome, your filter must match every terminal state, not just the happy path. A monitor that greps only for the success marker stays silent through a crashloop, a hung process, or an unexpected exit \u2014 and silence looks identical to "still running." Before arming, ask: *if this process crashed right now, would my filter emit anything?* If not, widen it.
584949
+
584950
+ # Wrong \u2014 silent on crash, hang, or any non-success exit
584951
+ tail -f run.log | grep --line-buffered "elapsed_steps="
584952
+
584953
+ # Right \u2014 one alternation covering progress + the failure signatures you'd act on
584954
+ tail -f run.log | grep -E --line-buffered "elapsed_steps=|Traceback|Error|FAILED|assert|Killed|OOM"
584955
+
584956
+ For poll loops checking job state, emit on every terminal status (\`succeeded|failed|cancelled|timeout\`), not just success. If you cannot confidently enumerate the failure signatures, broaden the grep alternation rather than narrow it \u2014 some extra noise is better than missing a crashloop.
584957
+
584958
+ **Output volume**: Every stdout line is a conversation message, so the filter should be selective \u2014 but selective means "the lines you'd act on," not "only good news." Never pipe raw logs; filter to exactly the success and failure signals you care about. Monitors that produce too many events are automatically stopped; restart with a tighter filter if this happens.
584959
+
584960
+ Stdout lines within 200ms are batched into a single notification, so multiline output from a single event groups naturally.
584961
+
584962
+ The script runs in the same shell environment as Bash. Exit ends the watch (exit code is reported). ${deadlineSection()} Use TaskStop to cancel early.
584963
+ **ws source** \u2014 open a WebSocket and stream each incoming text frame as an event. No shell, no polling: the server pushes, you get notified.
584964
+ Monitor({
584965
+ ws: {url: 'wss://events.example.com/stream', protocols: ['v1']},
584966
+ description: 'deploy events',
584967
+ })
584968
+ Each text frame becomes one notification (multiline frames stay as one event). Binary frames are reported as \`[binary frame, N bytes]\` rather than passed through. Socket close ends the watch with the close code surfaced; errors are surfaced before close. Same rate limiting as bash \u2014 a firehose will be suppressed and eventually stopped, so subscribe to a filtered feed where one exists.
584969
+ Prefer this over \`command: 'websocat wss://\u2026'\` \u2014 it avoids the extra process and line-buffering pitfalls. Use bash when you need to transform or filter frames with shell tools before they become events.`;
584970
+ }
584971
+ function fireMonitorDeadline(deps) {
584972
+ const registry2 = deps.registry ?? activeMonitors;
584973
+ const h5 = registry2.get(deps.taskId);
584974
+ if (!h5)
584975
+ return false;
584976
+ deps.emit(monitorExpiredNotice(deps.timeoutMs, deps.eventCount));
584977
+ h5.kill();
584978
+ registry2.delete(deps.taskId);
584979
+ return true;
584980
+ }
584800
584981
  function shellPath() {
584801
584982
  return process.env.SHELL || "/bin/sh";
584802
584983
  }
@@ -584889,77 +585070,13 @@ function stopMonitor(taskId) {
584889
585070
  activeMonitors.delete(taskId);
584890
585071
  return true;
584891
585072
  }
584892
- var MONITOR_TOOL_NAME = "Monitor", DEFAULT_TIMEOUT_MS2 = 300000, MAX_TIMEOUT_MS2 = 3600000, COMMAND_DESC = "Shell command or script. Each stdout line is an event; exit ends the watch.", DESCRIPTION19 = `Start a background monitor that streams events from a long-running script. Each stdout line is an event \u2014 you keep working and notifications arrive in the chat. Events arrive on their own schedule and are not replies from the user, even if one lands while you're waiting for the user to answer a question.
584893
-
584894
- Pick by how many notifications you need:
584895
- - **One** ("tell me when the server is ready / the build finishes") \u2192 use **Bash with \`run_in_background\`** and a command that exits when the condition is true, e.g. \`until grep -q "Ready in" dev.log; do sleep 0.5; done\`. You get a single completion notification when it exits.
584896
- - **One per occurrence, indefinitely** ("tell me every time an ERROR line appears") \u2192 Monitor with an unbounded command (\`tail -f\`, \`inotifywait -m\`, \`while true\`).
584897
- - **One per occurrence, until a known end** ("emit each CI step result, stop when the run completes") \u2192 Monitor with a command that emits lines and then exits.
584898
-
584899
- Your script's stdout is the event stream. Each line becomes a notification. Exit ends the watch.
584900
-
584901
- # Each matching log line is an event
584902
- tail -f /var/log/app.log | grep --line-buffered "ERROR"
584903
-
584904
- # Each file change is an event
584905
- inotifywait -m --format '%e %f' /watched/dir
584906
-
584907
- # Poll GitHub for new PR comments and emit one line per new comment
584908
- last=$(date -u +%Y-%m-%dT%H:%M:%SZ)
584909
- while true; do
584910
- now=$(date -u +%Y-%m-%dT%H:%M:%SZ)
584911
- gh api "repos/owner/repo/issues/123/comments?since=$last" --jq '.[] | "\\(.user.login): \\(.body)"'
584912
- last=$now; sleep 30
584913
- done
584914
-
584915
- # Node script that emits events as they arrive (e.g. WebSocket listener)
584916
- node watch-for-events.js
584917
-
584918
- # Per-occurrence with a natural end: emit each CI check as it lands, exit when the run completes
584919
- prev=""
584920
- while true; do
584921
- s=$(gh pr checks 123 --json name,bucket)
584922
- cur=$(jq -r '.[] | select(.bucket!="pending") | "\\(.name): \\(.bucket)"' <<<"$s" | sort)
584923
- comm -13 <(echo "$prev") <(echo "$cur")
584924
- prev=$cur
584925
- jq -e 'all(.bucket!="pending")' <<<"$s" >/dev/null && break
584926
- sleep 30
584927
- done
584928
-
584929
- **Don't use an unbounded command for a single notification.** \`tail -f\`, \`inotifywait -m\`, and \`while true\` never exit on their own, so the monitor stays armed until timeout even after the event has fired. For "tell me when X is ready," use Bash \`run_in_background\` with an \`until\` loop instead (one notification, ends in seconds). Note that \`tail -f log | grep -m 1 ...\` does *not* fix this: if the log goes quiet after the match, \`tail\` never receives SIGPIPE and the pipeline hangs anyway.
584930
-
584931
- **Script quality:**
584932
- - Every pipe stage must flush per line or matches sit in its buffer unseen: \`grep\` needs \`--line-buffered\`, \`awk\` needs \`fflush()\`. \`head\` cannot flush at all \u2014 \`| head -N\` delivers nothing until N matches accumulate, then ends the stream.
584933
- - In poll loops, handle transient failures (\`curl ... || true\`) \u2014 one failed request shouldn't kill the monitor.
584934
- - Poll intervals: 30s+ for remote APIs (rate limits), 0.5-1s for local checks.
584935
- - Write a specific \`description\` \u2014 it appears in every notification ("errors in deploy.log" not "watching logs").
584936
- - Only stdout is the event stream. Stderr goes to the output file (readable via Read) but does not trigger notifications \u2014 for a command you run directly (e.g. \`python train.py 2>&1 | grep --line-buffered ...\`), merge stderr with \`2>&1\` so its failures reach your filter. (No effect on \`tail -f\` of an existing log \u2014 that file only contains what its writer redirected.)
584937
-
584938
- **Coverage \u2014 silence is not success.** When watching a job or process for an outcome, your filter must match every terminal state, not just the happy path. A monitor that greps only for the success marker stays silent through a crashloop, a hung process, or an unexpected exit \u2014 and silence looks identical to "still running." Before arming, ask: *if this process crashed right now, would my filter emit anything?* If not, widen it.
584939
-
584940
- # Wrong \u2014 silent on crash, hang, or any non-success exit
584941
- tail -f run.log | grep --line-buffered "elapsed_steps="
584942
-
584943
- # Right \u2014 one alternation covering progress + the failure signatures you'd act on
584944
- tail -f run.log | grep -E --line-buffered "elapsed_steps=|Traceback|Error|FAILED|assert|Killed|OOM"
584945
-
584946
- For poll loops checking job state, emit on every terminal status (\`succeeded|failed|cancelled|timeout\`), not just success. If you cannot confidently enumerate the failure signatures, broaden the grep alternation rather than narrow it \u2014 some extra noise is better than missing a crashloop.
584947
-
584948
- **Output volume**: Every stdout line is a conversation message, so the filter should be selective \u2014 but selective means "the lines you'd act on," not "only good news." Never pipe raw logs; filter to exactly the success and failure signals you care about. Monitors that produce too many events are automatically stopped; restart with a tighter filter if this happens.
584949
-
584950
- Stdout lines within 200ms are batched into a single notification, so multiline output from a single event groups naturally.
584951
-
584952
- The script runs in the same shell environment as Bash. Exit ends the watch (exit code is reported). Timeout \u2192 killed. Set \`persistent: true\` for session-length watches (PR monitoring, log tails) \u2014 the monitor runs until you call TaskStop or the session ends. Use TaskStop to cancel early.
584953
- **ws source** \u2014 open a WebSocket and stream each incoming text frame as an event. No shell, no polling: the server pushes, you get notified.
584954
- Monitor({
584955
- ws: {url: 'wss://events.example.com/stream', protocols: ['v1']},
584956
- description: 'deploy events',
584957
- })
584958
- Each text frame becomes one notification (multiline frames stay as one event). Binary frames are reported as \`[binary frame, N bytes]\` rather than passed through. Socket close ends the watch with the close code surfaced; errors are surfaced before close. Same rate limiting as bash \u2014 a firehose will be suppressed and eventually stopped, so subscribe to a filtered feed where one exists.
584959
- Prefer this over \`command: 'websocat wss://\u2026'\` \u2014 it avoids the extra process and line-buffering pitfalls. Use bash when you need to transform or filter frames with shell tools before they become events.`, inputSchema38, outputSchema35, activeMonitors, MonitorTool;
585073
+ var MONITOR_TOOL_NAME = "Monitor", DEFAULT_TIMEOUT_MS2 = 300000, MAX_TIMEOUT_MS2 = 3600000, MONITOR_DEADLINE_CAP_MS = 1800000, MONITOR_DEADLINE_CAP_PRINT_MS = 600000, COMMAND_DESC = "Shell command or script. Each stdout line is an event; exit ends the watch.", inputSchema38, outputSchema35, activeMonitors, MonitorTool;
584960
585074
  var init_MonitorTool = __esm(() => {
584961
585075
  init_v4();
584962
585076
  init_Tool();
585077
+ init_state();
585078
+ init_format();
585079
+ init_oauthLoginExpiry();
584963
585080
  inputSchema38 = lazySchema(() => exports_external.strictObject({
584964
585081
  command: exports_external.string().min(1).describe(COMMAND_DESC).optional(),
584965
585082
  ws: exports_external.object({
@@ -584983,10 +585100,10 @@ var init_MonitorTool = __esm(() => {
584983
585100
  maxResultSizeChars: 1e5,
584984
585101
  shouldDefer: true,
584985
585102
  async description() {
584986
- return DESCRIPTION19;
585103
+ return buildDescription2();
584987
585104
  },
584988
585105
  async prompt() {
584989
- return DESCRIPTION19;
585106
+ return buildDescription2();
584990
585107
  },
584991
585108
  get inputSchema() {
584992
585109
  return inputSchema38();
@@ -585008,8 +585125,7 @@ var init_MonitorTool = __esm(() => {
585008
585125
  },
585009
585126
  async call(input2, _context) {
585010
585127
  const taskId = `monitor-${randomUUID22()}`;
585011
- const persistent = input2.persistent ?? false;
585012
- const timeoutMs = persistent ? 0 : input2.timeout_ms ?? DEFAULT_TIMEOUT_MS2;
585128
+ const { timeoutMs, persistent } = normalizeMonitorInput(input2);
585013
585129
  const events2 = [];
585014
585130
  const emit2 = (line) => {
585015
585131
  events2.push(line);
@@ -585019,17 +585135,16 @@ var init_MonitorTool = __esm(() => {
585019
585135
  } else if (input2.ws) {
585020
585136
  streamWs(input2.ws.url, input2.ws.protocols, taskId, emit2).catch(() => {});
585021
585137
  }
585022
- if (timeoutMs > 0) {
585023
- const timer2 = setTimeout(() => {
585024
- const h5 = activeMonitors.get(taskId);
585025
- if (h5) {
585026
- h5.kill();
585027
- activeMonitors.delete(taskId);
585028
- }
585029
- }, timeoutMs);
585030
- if (typeof timer2 === "object" && timer2 && "unref" in timer2) {
585031
- timer2.unref();
585032
- }
585138
+ const timer2 = setTimeout(() => {
585139
+ fireMonitorDeadline({
585140
+ taskId,
585141
+ timeoutMs,
585142
+ eventCount: events2.length,
585143
+ emit: emit2
585144
+ });
585145
+ }, timeoutMs);
585146
+ if (typeof timer2 === "object" && timer2 && "unref" in timer2) {
585147
+ timer2.unref();
585033
585148
  }
585034
585149
  return {
585035
585150
  data: {
@@ -585069,7 +585184,7 @@ function isPushDisabled() {
585069
585184
  return true;
585070
585185
  }
585071
585186
  }
585072
- var PUSH_NOTIFICATION_TOOL_NAME = "PushNotification", DESCRIPTION20 = "Send a notification to the user via their terminal and, when Remote Control is connected, also push to their mobile device", inputSchema39, outputSchema36, noopTerminal, PushNotificationTool;
585187
+ var PUSH_NOTIFICATION_TOOL_NAME = "PushNotification", DESCRIPTION19 = "Send a notification to the user via their terminal and, when Remote Control is connected, also push to their mobile device", inputSchema39, outputSchema36, noopTerminal, PushNotificationTool;
585073
585188
  var init_PushNotificationTool = __esm(() => {
585074
585189
  init_v4();
585075
585190
  init_Tool();
@@ -585097,10 +585212,10 @@ var init_PushNotificationTool = __esm(() => {
585097
585212
  maxResultSizeChars: 1000,
585098
585213
  shouldDefer: true,
585099
585214
  async description() {
585100
- return DESCRIPTION20;
585215
+ return DESCRIPTION19;
585101
585216
  },
585102
585217
  async prompt() {
585103
- return DESCRIPTION20;
585218
+ return DESCRIPTION19;
585104
585219
  },
585105
585220
  get inputSchema() {
585106
585221
  return inputSchema39();
@@ -585421,7 +585536,7 @@ If you receive a JSON message with \`type: "shutdown_request"\` or \`type: "plan
585421
585536
  Approving shutdown terminates your process. Rejecting plan sends the teammate back to revise. Don't originate \`shutdown_request\` unless asked. Don't send structured JSON status messages \u2014 use TaskUpdate.
585422
585537
  `.trim();
585423
585538
  }
585424
- var DESCRIPTION21 = "Send a message to another agent";
585539
+ var DESCRIPTION20 = "Send a message to another agent";
585425
585540
  var init_prompt24 = __esm(() => {
585426
585541
  init_featureFlags();
585427
585542
  });
@@ -585942,7 +586057,7 @@ var init_SendMessageTool = __esm(() => {
585942
586057
  return { result: true };
585943
586058
  },
585944
586059
  async description() {
585945
- return DESCRIPTION21;
586060
+ return DESCRIPTION20;
585946
586061
  },
585947
586062
  async prompt() {
585948
586063
  return getPrompt6();
@@ -586190,7 +586305,7 @@ async function listCloudSessions() {
586190
586305
  async function listRemoteBridgeSessions() {
586191
586306
  return [];
586192
586307
  }
586193
- var LIST_AGENTS_TOOL_NAME = "ListAgents", DESCRIPTION22 = `Lists agents you can SendMessage to \u2014 in-process subagents you spawned, other local Claude sessions on this machine, your Claude sessions running in the cloud (when this session has cloud access), and (when Remote Control is connected) remote bridge sessions, which you can only reply to. Names are the address: send with \`SendMessage({to: "<name>", message: "..."})\`, copying the name exactly as a row prints it. Append a row's \` [ref]\` only when the bare name is not enough \u2014 two rows share it, or an error asks you to disambiguate.`, inputSchema41, AgentTypeSchema, outputSchema37, ListPeersTool;
586308
+ var LIST_AGENTS_TOOL_NAME = "ListAgents", DESCRIPTION21 = `Lists agents you can SendMessage to \u2014 in-process subagents you spawned, other local Claude sessions on this machine, your Claude sessions running in the cloud (when this session has cloud access), and (when Remote Control is connected) remote bridge sessions, which you can only reply to. Names are the address: send with \`SendMessage({to: "<name>", message: "..."})\`, copying the name exactly as a row prints it. Append a row's \` [ref]\` only when the bare name is not enough \u2014 two rows share it, or an error asks you to disambiguate.`, inputSchema41, AgentTypeSchema, outputSchema37, ListPeersTool;
586194
586309
  var init_ListPeersTool = __esm(() => {
586195
586310
  init_v4();
586196
586311
  init_Tool();
@@ -586216,10 +586331,10 @@ var init_ListPeersTool = __esm(() => {
586216
586331
  maxResultSizeChars: 50000,
586217
586332
  shouldDefer: true,
586218
586333
  async description() {
586219
- return DESCRIPTION22;
586334
+ return DESCRIPTION21;
586220
586335
  },
586221
586336
  async prompt() {
586222
- return DESCRIPTION22;
586337
+ return DESCRIPTION21;
586223
586338
  },
586224
586339
  get inputSchema() {
586225
586340
  return inputSchema41();
@@ -588000,7 +588115,7 @@ function buildWorkflowProgressHandler(runId, seedPhases, emit2, onAgentEvent) {
588000
588115
  });
588001
588116
  };
588002
588117
  }
588003
- var import_react86, inputSchema42, outputSchema38, DESCRIPTION23 = `Run a multi-step workflow from a self-contained JavaScript script. The script runs in a sandboxed vm with access to primitives: agent(prompt, opts?) to spawn a subagent, parallel(items) for concurrent execution (max 4096 items, ~10 concurrent), pipeline(items, ...stages) for streaming, phase(title, fn?) to group agents (optional callback form: phase('title', async () => { ...parallel/agent... }) runs fn within the phase and returns its result), log(...args) for workflow-scoped logging, budget {total, remaining(), spent()} for token caps, and workflow(nameOrRef) / resolveWorkflow(name) for sub-workflows. Scripts are deterministic for resume (no Date/Math.random/import). Use the Workflow tool on substantive multi-agent tasks.
588118
+ var import_react86, inputSchema42, outputSchema38, DESCRIPTION22 = `Run a multi-step workflow from a self-contained JavaScript script. The script runs in a sandboxed vm with access to primitives: agent(prompt, opts?) to spawn a subagent, parallel(items) for concurrent execution (max 4096 items, ~10 concurrent), pipeline(items, ...stages) for streaming, phase(title, fn?) to group agents (optional callback form: phase('title', async () => { ...parallel/agent... }) runs fn within the phase and returns its result), log(...args) for workflow-scoped logging, budget {total, remaining(), spent()} for token caps, and workflow(nameOrRef) / resolveWorkflow(name) for sub-workflows. Scripts are deterministic for resume (no Date/Math.random/import). Use the Workflow tool on substantive multi-agent tasks.
588004
588119
 
588005
588120
  - Ultracode is on for the session (a system-reminder confirms it) \u2014 see **Ultracode** below.
588006
588121
 
@@ -588059,10 +588174,10 @@ var init_WorkflowTool = __esm(() => {
588059
588174
  async description() {
588060
588175
  const size = getInitialSettings()?.dynamicWorkflowSize ?? "medium";
588061
588176
  const sizeHint = size === "small" ? "When creating a dynamic workflow, prefer a small number of agents (~3)." : size === "large" ? "When creating a dynamic workflow, prefer a large number of agents (~12)." : "When creating a dynamic workflow, prefer a medium number of agents (~6).";
588062
- return `${DESCRIPTION23} ${sizeHint} (Per the dynamicWorkflowSize setting \u2014 advisory, not a cap.)`;
588177
+ return `${DESCRIPTION22} ${sizeHint} (Per the dynamicWorkflowSize setting \u2014 advisory, not a cap.)`;
588063
588178
  },
588064
588179
  async prompt() {
588065
- return `${DESCRIPTION23}
588180
+ return `${DESCRIPTION22}
588066
588181
 
588067
588182
  Use this tool to run a workflow script. The script must start with \`export const meta = { name, description, phases }\` and export a default async function: \`export default async ({ agent, parallel, pipeline, phase, log, budget, workflow, resolveWorkflow, args }) => { ... }\`.`;
588068
588183
  },
@@ -624050,7 +624165,7 @@ var init_p_map = __esm(() => {
624050
624165
  });
624051
624166
 
624052
624167
  // src/tools/MCPTool/prompt.ts
624053
- var PROMPT10 = "", DESCRIPTION24 = "";
624168
+ var PROMPT10 = "", DESCRIPTION23 = "";
624054
624169
 
624055
624170
  // src/components/design-system/ProgressBar.tsx
624056
624171
  function ProgressBar(t0) {
@@ -624719,7 +624834,7 @@ var init_MCPTool = __esm(() => {
624719
624834
  name: "mcp",
624720
624835
  maxResultSizeChars: 1e5,
624721
624836
  async description() {
624722
- return DESCRIPTION24;
624837
+ return DESCRIPTION23;
624723
624838
  },
624724
624839
  async prompt() {
624725
624840
  return PROMPT10;
@@ -709090,7 +709205,7 @@ function _temp148(s4) {
709090
709205
  }
709091
709206
  async function handleFastModeShortcut(enable2, getAppState, setAppState) {
709092
709207
  const unavailableReason = getFastModeUnavailableReason();
709093
- if (unavailableReason) {
709208
+ if (enable2 && unavailableReason) {
709094
709209
  return `Fast mode unavailable: ${unavailableReason}`;
709095
709210
  }
709096
709211
  if (enable2) {
@@ -710323,6 +710438,9 @@ function groupHooksByEventAndMatcher(appState, toolNames) {
710323
710438
  MessageDisplay: {},
710324
710439
  DirectoryAdded: {}
710325
710440
  };
710441
+ for (const event of Object.keys(grouped)) {
710442
+ grouped[event] = Object.create(null);
710443
+ }
710326
710444
  const metadata = getHookEventMetadata(toolNames);
710327
710445
  getAllHooks(appState).forEach((hook) => {
710328
710446
  const eventGroup = grouped[hook.event];
@@ -805938,6 +806056,7 @@ function REPL({
805938
806056
  const loadedNestedMemoryPathsRef = import_react321.useRef(new Set);
805939
806057
  const restoreReadFileState = import_react321.useCallback((messages2, cwd2) => {
805940
806058
  const extracted = extractReadFilesFromMessages(messages2, cwd2, READ_FILE_STATE_CACHE_SIZE);
806059
+ readFileState.current.clear();
805941
806060
  readFileState.current = mergeFileStateCaches(readFileState.current, extracted);
805942
806061
  for (const tool of extractBashToolsFromMessages(messages2)) {
805943
806062
  bashTools.current.add(tool);
@@ -816486,7 +816605,7 @@ var init_verifyContent = __esm(() => {
816486
816605
  function registerVerifySkill() {
816487
816606
  registerBundledSkill({
816488
816607
  name: "verify",
816489
- description: DESCRIPTION25,
816608
+ description: DESCRIPTION24,
816490
816609
  userInvocable: true,
816491
816610
  files: SKILL_FILES,
816492
816611
  async getPromptForCommand(args) {
@@ -816502,13 +816621,13 @@ ${args}`);
816502
816621
  }
816503
816622
  });
816504
816623
  }
816505
- var frontmatter, SKILL_BODY, DESCRIPTION25;
816624
+ var frontmatter, SKILL_BODY, DESCRIPTION24;
816506
816625
  var init_verify = __esm(() => {
816507
816626
  init_frontmatterParser();
816508
816627
  init_bundledSkills();
816509
816628
  init_verifyContent();
816510
816629
  ({ frontmatter, content: SKILL_BODY } = parseFrontmatter(SKILL_MD));
816511
- DESCRIPTION25 = typeof frontmatter.description === "string" ? frontmatter.description : "Verify a code change does what it should by running the app.";
816630
+ DESCRIPTION24 = typeof frontmatter.description === "string" ? frontmatter.description : "Verify a code change does what it should by running the app.";
816512
816631
  });
816513
816632
 
816514
816633
  // src/skills/bundled/dream.js
@@ -831494,7 +831613,7 @@ var _FEATURE_ALLOWLIST = new Set([
831494
831613
  var feature2 = (name3) => _FEATURE_ALLOWLIST.has(name3);
831495
831614
  if (typeof globalThis.MACRO === "undefined") {
831496
831615
  globalThis.MACRO = {
831497
- VERSION: "2.1.270",
831616
+ VERSION: "2.1.272",
831498
831617
  BINARY_NAME: "occ",
831499
831618
  BUILD_TIME: new Date().toISOString(),
831500
831619
  FEEDBACK_CHANNEL: "",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cnwenf/occ",
3
- "version": "2.1.335",
3
+ "version": "2.1.337",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "bin": {