@cnwenf/occ 2.1.336 → 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.336","BINARY_NAME":"occ","BUILD_TIME":"2026-09-15T19:40:03.023Z","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 {
@@ -584823,10 +584867,117 @@ ${output2.json}`
584823
584867
  var exports_MonitorTool = {};
584824
584868
  __export(exports_MonitorTool, {
584825
584869
  stopMonitor: () => stopMonitor,
584870
+ normalizeMonitorInput: () => normalizeMonitorInput,
584871
+ monitorExpiredNotice: () => monitorExpiredNotice,
584872
+ fireMonitorDeadline: () => fireMonitorDeadline,
584826
584873
  MonitorTool: () => MonitorTool,
584827
584874
  MONITOR_TOOL_NAME: () => MONITOR_TOOL_NAME
584828
584875
  });
584829
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
+ }
584830
584981
  function shellPath() {
584831
584982
  return process.env.SHELL || "/bin/sh";
584832
584983
  }
@@ -584919,77 +585070,13 @@ function stopMonitor(taskId) {
584919
585070
  activeMonitors.delete(taskId);
584920
585071
  return true;
584921
585072
  }
584922
- 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.
584923
-
584924
- Pick by how many notifications you need:
584925
- - **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.
584926
- - **One per occurrence, indefinitely** ("tell me every time an ERROR line appears") \u2192 Monitor with an unbounded command (\`tail -f\`, \`inotifywait -m\`, \`while true\`).
584927
- - **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.
584928
-
584929
- Your script's stdout is the event stream. Each line becomes a notification. Exit ends the watch.
584930
-
584931
- # Each matching log line is an event
584932
- tail -f /var/log/app.log | grep --line-buffered "ERROR"
584933
-
584934
- # Each file change is an event
584935
- inotifywait -m --format '%e %f' /watched/dir
584936
-
584937
- # Poll GitHub for new PR comments and emit one line per new comment
584938
- last=$(date -u +%Y-%m-%dT%H:%M:%SZ)
584939
- while true; do
584940
- now=$(date -u +%Y-%m-%dT%H:%M:%SZ)
584941
- gh api "repos/owner/repo/issues/123/comments?since=$last" --jq '.[] | "\\(.user.login): \\(.body)"'
584942
- last=$now; sleep 30
584943
- done
584944
-
584945
- # Node script that emits events as they arrive (e.g. WebSocket listener)
584946
- node watch-for-events.js
584947
-
584948
- # Per-occurrence with a natural end: emit each CI check as it lands, exit when the run completes
584949
- prev=""
584950
- while true; do
584951
- s=$(gh pr checks 123 --json name,bucket)
584952
- cur=$(jq -r '.[] | select(.bucket!="pending") | "\\(.name): \\(.bucket)"' <<<"$s" | sort)
584953
- comm -13 <(echo "$prev") <(echo "$cur")
584954
- prev=$cur
584955
- jq -e 'all(.bucket!="pending")' <<<"$s" >/dev/null && break
584956
- sleep 30
584957
- done
584958
-
584959
- **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.
584960
-
584961
- **Script quality:**
584962
- - 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.
584963
- - In poll loops, handle transient failures (\`curl ... || true\`) \u2014 one failed request shouldn't kill the monitor.
584964
- - Poll intervals: 30s+ for remote APIs (rate limits), 0.5-1s for local checks.
584965
- - Write a specific \`description\` \u2014 it appears in every notification ("errors in deploy.log" not "watching logs").
584966
- - 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.)
584967
-
584968
- **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.
584969
-
584970
- # Wrong \u2014 silent on crash, hang, or any non-success exit
584971
- tail -f run.log | grep --line-buffered "elapsed_steps="
584972
-
584973
- # Right \u2014 one alternation covering progress + the failure signatures you'd act on
584974
- tail -f run.log | grep -E --line-buffered "elapsed_steps=|Traceback|Error|FAILED|assert|Killed|OOM"
584975
-
584976
- 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.
584977
-
584978
- **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.
584979
-
584980
- Stdout lines within 200ms are batched into a single notification, so multiline output from a single event groups naturally.
584981
-
584982
- 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.
584983
- **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.
584984
- Monitor({
584985
- ws: {url: 'wss://events.example.com/stream', protocols: ['v1']},
584986
- description: 'deploy events',
584987
- })
584988
- 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.
584989
- 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;
584990
585074
  var init_MonitorTool = __esm(() => {
584991
585075
  init_v4();
584992
585076
  init_Tool();
585077
+ init_state();
585078
+ init_format();
585079
+ init_oauthLoginExpiry();
584993
585080
  inputSchema38 = lazySchema(() => exports_external.strictObject({
584994
585081
  command: exports_external.string().min(1).describe(COMMAND_DESC).optional(),
584995
585082
  ws: exports_external.object({
@@ -585013,10 +585100,10 @@ var init_MonitorTool = __esm(() => {
585013
585100
  maxResultSizeChars: 1e5,
585014
585101
  shouldDefer: true,
585015
585102
  async description() {
585016
- return DESCRIPTION19;
585103
+ return buildDescription2();
585017
585104
  },
585018
585105
  async prompt() {
585019
- return DESCRIPTION19;
585106
+ return buildDescription2();
585020
585107
  },
585021
585108
  get inputSchema() {
585022
585109
  return inputSchema38();
@@ -585038,8 +585125,7 @@ var init_MonitorTool = __esm(() => {
585038
585125
  },
585039
585126
  async call(input2, _context) {
585040
585127
  const taskId = `monitor-${randomUUID22()}`;
585041
- const persistent = input2.persistent ?? false;
585042
- const timeoutMs = persistent ? 0 : input2.timeout_ms ?? DEFAULT_TIMEOUT_MS2;
585128
+ const { timeoutMs, persistent } = normalizeMonitorInput(input2);
585043
585129
  const events2 = [];
585044
585130
  const emit2 = (line) => {
585045
585131
  events2.push(line);
@@ -585049,17 +585135,16 @@ var init_MonitorTool = __esm(() => {
585049
585135
  } else if (input2.ws) {
585050
585136
  streamWs(input2.ws.url, input2.ws.protocols, taskId, emit2).catch(() => {});
585051
585137
  }
585052
- if (timeoutMs > 0) {
585053
- const timer2 = setTimeout(() => {
585054
- const h5 = activeMonitors.get(taskId);
585055
- if (h5) {
585056
- h5.kill();
585057
- activeMonitors.delete(taskId);
585058
- }
585059
- }, timeoutMs);
585060
- if (typeof timer2 === "object" && timer2 && "unref" in timer2) {
585061
- timer2.unref();
585062
- }
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();
585063
585148
  }
585064
585149
  return {
585065
585150
  data: {
@@ -585099,7 +585184,7 @@ function isPushDisabled() {
585099
585184
  return true;
585100
585185
  }
585101
585186
  }
585102
- 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;
585103
585188
  var init_PushNotificationTool = __esm(() => {
585104
585189
  init_v4();
585105
585190
  init_Tool();
@@ -585127,10 +585212,10 @@ var init_PushNotificationTool = __esm(() => {
585127
585212
  maxResultSizeChars: 1000,
585128
585213
  shouldDefer: true,
585129
585214
  async description() {
585130
- return DESCRIPTION20;
585215
+ return DESCRIPTION19;
585131
585216
  },
585132
585217
  async prompt() {
585133
- return DESCRIPTION20;
585218
+ return DESCRIPTION19;
585134
585219
  },
585135
585220
  get inputSchema() {
585136
585221
  return inputSchema39();
@@ -585451,7 +585536,7 @@ If you receive a JSON message with \`type: "shutdown_request"\` or \`type: "plan
585451
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.
585452
585537
  `.trim();
585453
585538
  }
585454
- var DESCRIPTION21 = "Send a message to another agent";
585539
+ var DESCRIPTION20 = "Send a message to another agent";
585455
585540
  var init_prompt24 = __esm(() => {
585456
585541
  init_featureFlags();
585457
585542
  });
@@ -585972,7 +586057,7 @@ var init_SendMessageTool = __esm(() => {
585972
586057
  return { result: true };
585973
586058
  },
585974
586059
  async description() {
585975
- return DESCRIPTION21;
586060
+ return DESCRIPTION20;
585976
586061
  },
585977
586062
  async prompt() {
585978
586063
  return getPrompt6();
@@ -586220,7 +586305,7 @@ async function listCloudSessions() {
586220
586305
  async function listRemoteBridgeSessions() {
586221
586306
  return [];
586222
586307
  }
586223
- 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;
586224
586309
  var init_ListPeersTool = __esm(() => {
586225
586310
  init_v4();
586226
586311
  init_Tool();
@@ -586246,10 +586331,10 @@ var init_ListPeersTool = __esm(() => {
586246
586331
  maxResultSizeChars: 50000,
586247
586332
  shouldDefer: true,
586248
586333
  async description() {
586249
- return DESCRIPTION22;
586334
+ return DESCRIPTION21;
586250
586335
  },
586251
586336
  async prompt() {
586252
- return DESCRIPTION22;
586337
+ return DESCRIPTION21;
586253
586338
  },
586254
586339
  get inputSchema() {
586255
586340
  return inputSchema41();
@@ -588030,7 +588115,7 @@ function buildWorkflowProgressHandler(runId, seedPhases, emit2, onAgentEvent) {
588030
588115
  });
588031
588116
  };
588032
588117
  }
588033
- 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.
588034
588119
 
588035
588120
  - Ultracode is on for the session (a system-reminder confirms it) \u2014 see **Ultracode** below.
588036
588121
 
@@ -588089,10 +588174,10 @@ var init_WorkflowTool = __esm(() => {
588089
588174
  async description() {
588090
588175
  const size = getInitialSettings()?.dynamicWorkflowSize ?? "medium";
588091
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).";
588092
- 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.)`;
588093
588178
  },
588094
588179
  async prompt() {
588095
- return `${DESCRIPTION23}
588180
+ return `${DESCRIPTION22}
588096
588181
 
588097
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 }) => { ... }\`.`;
588098
588183
  },
@@ -624080,7 +624165,7 @@ var init_p_map = __esm(() => {
624080
624165
  });
624081
624166
 
624082
624167
  // src/tools/MCPTool/prompt.ts
624083
- var PROMPT10 = "", DESCRIPTION24 = "";
624168
+ var PROMPT10 = "", DESCRIPTION23 = "";
624084
624169
 
624085
624170
  // src/components/design-system/ProgressBar.tsx
624086
624171
  function ProgressBar(t0) {
@@ -624749,7 +624834,7 @@ var init_MCPTool = __esm(() => {
624749
624834
  name: "mcp",
624750
624835
  maxResultSizeChars: 1e5,
624751
624836
  async description() {
624752
- return DESCRIPTION24;
624837
+ return DESCRIPTION23;
624753
624838
  },
624754
624839
  async prompt() {
624755
624840
  return PROMPT10;
@@ -709120,7 +709205,7 @@ function _temp148(s4) {
709120
709205
  }
709121
709206
  async function handleFastModeShortcut(enable2, getAppState, setAppState) {
709122
709207
  const unavailableReason = getFastModeUnavailableReason();
709123
- if (unavailableReason) {
709208
+ if (enable2 && unavailableReason) {
709124
709209
  return `Fast mode unavailable: ${unavailableReason}`;
709125
709210
  }
709126
709211
  if (enable2) {
@@ -816520,7 +816605,7 @@ var init_verifyContent = __esm(() => {
816520
816605
  function registerVerifySkill() {
816521
816606
  registerBundledSkill({
816522
816607
  name: "verify",
816523
- description: DESCRIPTION25,
816608
+ description: DESCRIPTION24,
816524
816609
  userInvocable: true,
816525
816610
  files: SKILL_FILES,
816526
816611
  async getPromptForCommand(args) {
@@ -816536,13 +816621,13 @@ ${args}`);
816536
816621
  }
816537
816622
  });
816538
816623
  }
816539
- var frontmatter, SKILL_BODY, DESCRIPTION25;
816624
+ var frontmatter, SKILL_BODY, DESCRIPTION24;
816540
816625
  var init_verify = __esm(() => {
816541
816626
  init_frontmatterParser();
816542
816627
  init_bundledSkills();
816543
816628
  init_verifyContent();
816544
816629
  ({ frontmatter, content: SKILL_BODY } = parseFrontmatter(SKILL_MD));
816545
- 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.";
816546
816631
  });
816547
816632
 
816548
816633
  // src/skills/bundled/dream.js
@@ -831528,7 +831613,7 @@ var _FEATURE_ALLOWLIST = new Set([
831528
831613
  var feature2 = (name3) => _FEATURE_ALLOWLIST.has(name3);
831529
831614
  if (typeof globalThis.MACRO === "undefined") {
831530
831615
  globalThis.MACRO = {
831531
- VERSION: "2.1.270",
831616
+ VERSION: "2.1.272",
831532
831617
  BINARY_NAME: "occ",
831533
831618
  BUILD_TIME: new Date().toISOString(),
831534
831619
  FEEDBACK_CHANNEL: "",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cnwenf/occ",
3
- "version": "2.1.336",
3
+ "version": "2.1.337",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "bin": {