{"_id":"@beremaran/opencode-subagent-throttle","_rev":"2-3435efdc3a023627b5e5ecbc8f34d3be","name":"@beremaran/opencode-subagent-throttle","dist-tags":{"latest":"0.2.1"},"versions":{"0.2.0":{"name":"@beremaran/opencode-subagent-throttle","version":"0.2.0","keywords":["opencode","opencode-plugin","subagent","throttle","queue","concurrency"],"author":{"name":"Berke Arslan","email":"berke@beremaran.com"},"license":"MIT","_id":"@beremaran/opencode-subagent-throttle@0.2.0","maintainers":[{"name":"beremaran","email":"beremaran@gmail.com"}],"homepage":"https://github.com/beremaran/opencode-subagent-throttle","bugs":{"url":"https://github.com/beremaran/opencode-subagent-throttle/issues"},"dist":{"shasum":"b65d21cc09d9a91fe884cee254077ee5f9925646","tarball":"https://registry.npmjs.org/@beremaran/opencode-subagent-throttle/-/opencode-subagent-throttle-0.2.0.tgz","fileCount":9,"integrity":"sha512-hTWAFVHCCMjqc0i9F4wK0OZv5JEoY66aQCLXgHaDX/qf5pzlPCI1KX9KudLSMoEFR1N8TArY8rIiWRySZdIWsQ==","signatures":[{"sig":"MEQCIGB7XbM5XhUCZYWN8PINZo9ICem+NP8Ys5Wbc295KN7+AiA0e2wU8n2hMZe2fX+ZVpg/NGwkpvg/NYEwdkUmn/kcwA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":30564},"main":"./src/v1.ts","type":"module","types":"./src/v2.ts","engines":{"node":">=22.6","opencode":">=1.18.11 <3"},"exports":{".":{"types":"./src/v2.ts","default":"./src/v2.ts"},"./server":{"types":"./src/index.ts","default":"./src/v1.ts"},"./package.json":"./package.json"},"funding":{"github":"beremaran"},"gitHead":"96e91121e5ea84aa6e879564ed39893e726f8ad6","scripts":{"lint":"biome check src test","test":"node --experimental-strip-types --test \"test/*.test.ts\"","check":"npm run typecheck && npm run lint && npm test","typecheck":"tsc --noEmit","prepublishOnly":"npm run check"},"_npmUser":{"name":"beremaran","email":"beremaran@gmail.com"},"repository":{"url":"git+https://github.com/beremaran/opencode-subagent-throttle.git","type":"git"},"_npmVersion":"11.19.0","description":"OpenCode plugin that throttles concurrent task/subagent tool calls by queueing them as pending (never rejecting).","directories":{},"sideEffects":false,"_nodeVersion":"26.7.0","dependencies":{"@opencode-ai/sdk":">=1.18.11 <2"},"publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"latest","typescript":"^5.5.0","@biomejs/biome":"^2.5.6","@opencode-ai/plugin":"1.18.15"},"peerDependencies":{"@opencode-ai/plugin":">=1.18.11 <2"},"_npmOperationalInternal":{"tmp":"tmp/opencode-subagent-throttle_0.2.0_1787397153461_0.5956720650798686","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"_id":"@beremaran/opencode-subagent-throttle@0.2.1","bugs":{"url":"https://github.com/beremaran/opencode-subagent-throttle/issues"},"dist":{"shasum":"11eeeff2c69a5a40809098edd14eb53225c233a1","tarball":"https://registry.npmjs.org/@beremaran/opencode-subagent-throttle/-/opencode-subagent-throttle-0.2.1.tgz","fileCount":10,"integrity":"sha512-WMgSeAbgOczY5qlSNEQThIpxqN2lMnM/hxllY1HJSywCD6ycEihlw0J97H5i5HE57BIVsPPEGifUTEwY3ZYNqQ==","signatures":[{"sig":"MEYCIQDNaLi8UQnj2H1ovDRtWlpGI35iqFVXB9lL4tIOTbTS+AIhAMulFHYCQgphc1K2J2xH3/Rv4mkWjRfKEkf5H71J8HQs","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIFVdtbtKyykPpg2P6vwAr750OPtu6pL9+onrhHG3R7spAiAic4hBBJQhtDiLFByUqWWPXKjSV+Co/FO+07uwUjuMuw=="}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@beremaran%2fopencode-subagent-throttle@0.2.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":30656},"main":"./index.ts","name":"@beremaran/opencode-subagent-throttle","type":"module","types":"./src/v2.ts","author":{"name":"Berke Arslan","email":"berke@beremaran.com"},"engines":{"node":">=22.6","opencode":">=1.18.11 <3"},"exports":{".":{"types":"./src/v2.ts","default":"./index.ts"},"./server":{"types":"./src/index.ts","default":"./src/v1.ts"},"./package.json":"./package.json"},"funding":{"github":"beremaran"},"gitHead":"8b9bee4c0290cf59864f6398225abc91001c545b","license":"MIT","scripts":{"lint":"biome check src test","test":"node --experimental-strip-types --test \"test/*.test.ts\"","check":"npm run typecheck && npm run lint && npm test","typecheck":"tsc --noEmit","prepublishOnly":"npm run check"},"version":"0.2.1","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:20f5e52d-9b24-4cee-b26b-69bd69e85945"}},"homepage":"https://github.com/beremaran/opencode-subagent-throttle","keywords":["opencode","opencode-plugin","task","subagent","concurrency","queue","throttle"],"repository":{"url":"git+https://github.com/beremaran/opencode-subagent-throttle.git","type":"git"},"_npmVersion":"11.19.0","description":"OpenCode plugin that limits concurrent task and subagent calls with FIFO queueing.","directories":{},"maintainers":[{"name":"beremaran","email":"beremaran@gmail.com"}],"sideEffects":false,"_nodeVersion":"24.20.0","dependencies":{"@opencode-ai/sdk":">=1.18.11 <2"},"publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"latest","typescript":"^5.5.0","@biomejs/biome":"^2.5.6","@opencode-ai/plugin":"1.18.15"},"peerDependencies":{"@opencode-ai/plugin":">=1.18.11 <2"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/opencode-subagent-throttle_0.2.1_1789459712170_0.5145083585036085"}}},"time":{"created":"2026-08-22T11:12:33.300Z","modified":"2026-09-15T08:08:32.640Z","0.2.0":"2026-08-22T11:12:33.612Z","0.2.1":"2026-09-15T08:08:32.299Z"},"bugs":{"url":"https://github.com/beremaran/opencode-subagent-throttle/issues"},"author":{"name":"Berke Arslan","email":"berke@beremaran.com"},"license":"MIT","homepage":"https://github.com/beremaran/opencode-subagent-throttle","keywords":["opencode","opencode-plugin","task","subagent","concurrency","queue","throttle"],"repository":{"url":"git+https://github.com/beremaran/opencode-subagent-throttle.git","type":"git"},"description":"OpenCode plugin that limits concurrent task and subagent calls with FIFO queueing.","maintainers":[{"name":"beremaran","email":"beremaran@gmail.com"}],"readme":"# opencode-subagent-throttle\n\n[![License](https://img.shields.io/npm/l/@beremaran/opencode-subagent-throttle.svg)](LICENSE)\n[![CI](https://github.com/beremaran/opencode-subagent-throttle/actions/workflows/ci.yml/badge.svg)](https://github.com/beremaran/opencode-subagent-throttle/actions/workflows/ci.yml)\n\nAn OpenCode plugin that limits concurrent `task` and `subagent` tool calls. Excess calls remain queued in FIFO order; they are never rejected or silently dropped.\n\n## Why Queue Instead of Reject\n\nQueuing preserves the parent agent's intent. Every requested task can still run when a slot becomes available, instead of failing because the concurrency limit was reached.\n\n## Installation\n\nOpenCode 2 can install the plugin directly from GitHub:\n\n```bash\nopencode plugin add github:beremaran/opencode-subagent-throttle\n```\n\nFor project-local configuration or options, add an object to `opencode.json` or\n`opencode.jsonc`:\n\n```json\n{\n  \"$schema\": \"https://opencode.ai/config.json\",\n  \"plugins\": [\n    {\n      \"package\": \"github:beremaran/opencode-subagent-throttle\",\n      \"options\": { \"maxParallel\": 2, \"mode\": \"session\" }\n    }\n  ]\n}\n```\n\nFor a local checkout, replace the GitHub spec with the checkout's absolute path,\nfor example `/absolute/path/to/opencode-subagent-throttle/index.ts`. The root\n`index.ts` loads the OpenCode 2 adapter. Relative paths resolve from the config\nfile. The legacy OpenCode 1 callable adapter remains available through the\npackage's `./server` export.\n\n`opencode plugin add` updates the global plugin configuration. Project-local\nentries live in the project's config. Restart OpenCode after changing an\nunwatched local dependency.\n\n## Configuration\n\nOptions are provided in the `options` object for the corresponding `plugins`\nentry.\n\n| Option | Type | Default | Description |\n| --- | --- | --- | --- |\n| `maxParallel` | number | `2` | Maximum number of task/subagent calls that may run at once. |\n| `mode` | string | `\"session\"` | `\"session\"` creates a separate throttle pool per session. `\"global\"` shares one pool within the plugin instance. |\n| `maxWaitMs` | number | `3600000` | Watchdog backstop in milliseconds. A call holding a slot longer than this is force-released with a warning log. The default is 60 minutes. |\n| `notifyQueue` | boolean | `false` | OpenCode 1 compatibility only: injects status lines when a task is queued or starts. OpenCode 2 skips transcript insertion and logs a warning. |\n\nThe common `\"session\"` mode is useful for one agent's fan-out. In `\"global\"` mode, all sessions share the same pool.\n\n## Usage\n\nThe OpenCode 2 adapter hooks `execute.before` and `execute.after` for the `task`\nand `subagent` tools. It awaits a semaphore slot before allowing a call to\nproceed. When all `maxParallel` slots are busy, additional calls wait in a FIFO\nqueue and start in order as slots become available. With `maxParallel: 2` and\nfive calls, two start immediately and three wait.\n\nForeground calls are the default, and release their slots when the tool\ncompletes. Background calls keep their slots until the child session emits an\nidle event. The watchdog releases a slot after `maxWaitMs` as a final backstop\nand logs a warning.\n\nIf your OpenCode build gates background subagents behind its experimental\nsetting, enable it before using `background: true`:\n\n```sh\nOPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=true opencode\n```\n\nTool errors release slots immediately. The legacy OpenCode 1 adapter uses the\nsame queue behavior for `task` calls through its `tool.execute.before` and\n`tool.execute.after` hooks.\n\n## Queue Notifications\n\n`notifyQueue` is supported only by the legacy OpenCode 1 adapter. Set it to\n`true` to add informational queued/started lines to the parent transcript.\nOpenCode 2 skips this option and logs a warning because its plugin API does not\nprovide the same transcript insertion.\n\nThese notes are sent with `noReply: true`, so the agent loop is not triggered; they are purely informational. They are also sent with `ignored: true`, so they show in the TUI but are excluded from the model's context and never consume tokens or influence the agent.\n\nEach queued task can add up to two transcript lines, so heavy fan-out produces transcript noise. The parent agent is typically blocked waiting on a foreground task while queued, so the notes are mainly for a human watching the TUI. A task aborted while still queued may leave its \"queued\" line behind without a \"started\" line.\n\n## Caveats\n\n- Queued calls appear as running tool calls in the UI while they wait. The tool output does not expose queue status.\n- With `notifyQueue: true` on OpenCode 1, queue status appears as\n  user-message-style lines in the transcript rather than inside the tool\n  call's own UI box. The plugin cannot repaint a running tool call's status;\n  see Queue Notifications above.\n- `\"session\"` mode gives each session its own pool. A parent agent and each subagent can therefore have separate pools.\n- `\"global\"` mode shares one pool within a plugin instance.\n- This throttles concurrency, not rate. It limits how many tasks run simultaneously, not how many tasks can be created over time.\n- The OpenCode 2 adapter throttles only `task` and `subagent`; other tools are unaffected.\n- If the watchdog fires, the slot is available again even if the underlying call is still running.\n\n## Runtime\n\nThe package root targets OpenCode 2.x and is loaded as raw TypeScript by\nOpenCode's Bun runtime. Node.js `22.6` or newer is required only for the local\ndevelopment checks, whose test command uses Node's native TypeScript stripping.\nThe legacy `./server` export is retained for compatible OpenCode 1 installs.\n\n## Project Structure\n\n- `index.ts` — OpenCode 2 package loader.\n- `src/index.ts` — OpenCode 1 plugin factory and hooks.\n- `src/v2.ts` — OpenCode 2 `{ id, setup }` adapter.\n- `src/v1.ts` — OpenCode 1 package entrypoint.\n- `src/queue.ts` — framework-independent FIFO semaphore.\n- `src/manager.ts` — slot manager for active slots, background idle watchers, error release, and the watchdog.\n- `test/` — Node test runner tests.\n\n## Development\n\n```sh\nnpm ci\nnpm run check\n```\n\n`npm run check` runs typecheck (`tsc --noEmit`), lint (Biome), and the tests.\nTests use Node's built-in test runner with native TypeScript type stripping.\nThere is no build step: OpenCode loads the TypeScript entrypoints directly.\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for getting started, manual testing,\nand test guidance. [RELEASING.md](RELEASING.md) documents the tag-triggered\nrelease flow, and [SECURITY.md](SECURITY.md) covers the security policy.\n\n## Related\n\n- [opencode-agent-tree](https://github.com/beremaran/opencode-agent-tree) —\n  force opencode to act as an orchestrator that delegates every task to\n  subagents. This throttle is a good companion: cap fan-out so orchestrator\n  delegation does not run away.\n","readmeFilename":"README.md"}